@oh-my-pi/pi-tui 18.6.1 → 18.7.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 +50 -58
- package/README.md +6 -2
- package/dist/types/app-keybindings.d.ts +7 -2
- package/dist/types/autocomplete.d.ts +5 -2
- package/dist/types/charts/chart-plan.d.ts +92 -0
- package/dist/types/charts/chart-svg.d.ts +30 -0
- package/dist/types/charts/table-data.d.ts +107 -0
- package/dist/types/chat/assistant-message.d.ts +10 -1
- package/dist/types/chat/chat-transcript-builder.d.ts +3 -0
- package/dist/types/chat/figure-markdown.d.ts +42 -0
- package/dist/types/chat/svg-figure.d.ts +33 -0
- package/dist/types/chat/svg-source.d.ts +49 -0
- package/dist/types/chat/table-chart.d.ts +88 -0
- package/dist/types/chat/user-message.d.ts +2 -2
- package/dist/types/chrome/status-notice.d.ts +15 -3
- package/dist/types/components/editor.d.ts +5 -1
- package/dist/types/components/image.d.ts +23 -0
- package/dist/types/components/input.d.ts +1 -0
- package/dist/types/components/loader.d.ts +5 -6
- package/dist/types/components/markdown.d.ts +9 -0
- package/dist/types/fuzzy.d.ts +14 -0
- package/dist/types/key-hint-format.d.ts +8 -0
- package/dist/types/keybindings.d.ts +1 -1
- package/dist/types/native/backend.d.ts +2 -2
- package/dist/types/native/node.d.ts +6 -0
- package/dist/types/native/overlay.d.ts +3 -3
- package/dist/types/overlays/agent-hub.d.ts +1 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +1 -0
- package/dist/types/overlays/agents-hub.d.ts +9 -0
- package/dist/types/overlays/annotation-overlay.d.ts +5 -2
- package/dist/types/overlays/btw-history-panel.d.ts +5 -1
- package/dist/types/overlays/copy-selector.d.ts +1 -0
- package/dist/types/overlays/model-browser.d.ts +25 -3
- package/dist/types/overlays/plan-review-overlay.d.ts +3 -2
- package/dist/types/overlays/rewind-selector.d.ts +1 -0
- package/dist/types/overlays/usage-dashboard.d.ts +4 -4
- package/dist/types/prompt/custom-editor.d.ts +10 -4
- package/dist/types/prompt/interactive-context-helpers.d.ts +3 -0
- package/dist/types/prompt/model-mention-autocomplete.d.ts +1 -1
- package/dist/types/render/composite.d.ts +2 -0
- package/dist/types/space-hold.d.ts +40 -25
- package/dist/types/terminal-capabilities.d.ts +13 -0
- package/dist/types/tools/glob.d.ts +4 -0
- package/dist/types/tui.d.ts +5 -0
- package/dist/types/utils.d.ts +6 -0
- package/package.json +9 -9
- package/src/app-keybindings.ts +6 -1
- package/src/apps/git/diff-pane.ts +42 -16
- package/src/apps/git/git-tui.ts +9 -9
- package/src/apps/git/sidebar.ts +6 -1
- package/src/autocomplete.ts +8 -10
- package/src/charts/chart-plan.ts +367 -0
- package/src/charts/chart-svg.ts +693 -0
- package/src/charts/table-data.ts +436 -0
- package/src/chat/assistant-message.ts +165 -25
- package/src/chat/chat-transcript-builder.ts +8 -0
- package/src/chat/figure-markdown.ts +174 -0
- package/src/chat/svg-figure.ts +364 -0
- package/src/chat/svg-source.ts +188 -0
- package/src/chat/table-chart.ts +301 -0
- package/src/chat/tool-execution.ts +6 -1
- package/src/chat/user-message.ts +16 -5
- package/src/chrome/status-notice.ts +25 -7
- package/src/chrome/transcript-container.ts +13 -4
- package/src/components/editor.ts +66 -30
- package/src/components/image.ts +95 -2
- package/src/components/input.ts +14 -6
- package/src/components/loader.ts +10 -17
- package/src/components/markdown.ts +6 -3
- package/src/fuzzy.ts +59 -19
- package/src/hotkeys-markdown.ts +9 -2
- package/src/key-hint-format.ts +25 -10
- package/src/keybindings.ts +1 -1
- package/src/native/backend.ts +10 -3
- package/src/native/node.ts +6 -0
- package/src/native/overlay.ts +4 -4
- package/src/overlays/agent-hub.ts +4 -0
- package/src/overlays/agent-transcript-viewer.ts +4 -0
- package/src/overlays/agents-hub.ts +14 -1
- package/src/overlays/annotation-overlay.ts +179 -80
- package/src/overlays/ask-dialog.ts +1 -1
- package/src/overlays/btw-history-panel.ts +9 -2
- package/src/overlays/copy-selector.ts +2 -0
- package/src/overlays/extensions/extension-dashboard.ts +4 -4
- package/src/overlays/model-browser.ts +169 -76
- package/src/overlays/pause-screen.ts +2 -2
- package/src/overlays/plan-review-overlay.ts +41 -4
- package/src/overlays/rewind-selector.ts +2 -0
- package/src/overlays/usage-dashboard.ts +17 -8
- package/src/overlays/usage-row.ts +22 -8
- package/src/prompt/composer.ts +2 -14
- package/src/prompt/custom-editor.ts +188 -67
- package/src/prompt/interactive-context-helpers.ts +5 -0
- package/src/prompt/model-mention-autocomplete.ts +14 -14
- package/src/prompt/queued-messages.ts +6 -4
- package/src/render/composite.ts +62 -0
- package/src/space-hold.ts +156 -52
- package/src/status-line/segments.ts +3 -1
- package/src/terminal-capabilities.ts +42 -23
- package/src/tools/glob.ts +23 -6
- package/src/tui.ts +154 -119
- package/src/utils.ts +19 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Tokens } from "@oh-my-pi/pi-utils/marked";
|
|
2
|
+
import { type ChartPlan } from "../charts/chart-plan.js";
|
|
3
|
+
import { type TableAnalysis } from "../charts/table-data.js";
|
|
4
|
+
import type { ImageBudget } from "../components/image.js";
|
|
5
|
+
import type { NativeNode } from "../native/node.js";
|
|
6
|
+
import type { Component } from "../tui.js";
|
|
7
|
+
/**
|
|
8
|
+
* `smart`: a model picks the kind and columns of multi-series tables;
|
|
9
|
+
* `always`: the local best guess charts every table it reads as numeric;
|
|
10
|
+
* `off`: tables stay tables.
|
|
11
|
+
*/
|
|
12
|
+
export type TableChartMode = "smart" | "always" | "off";
|
|
13
|
+
/** A multi-series table the host's planner picks a chart for. */
|
|
14
|
+
export interface TableChartRequest {
|
|
15
|
+
/** The table's Markdown source. */
|
|
16
|
+
readonly markdown: string;
|
|
17
|
+
readonly table: TableAnalysis;
|
|
18
|
+
/** The local best guess; the planner may keep it. */
|
|
19
|
+
readonly guess: ChartPlan;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Picks the chart for a multi-series table under `smart`: a plan, or `null`
|
|
23
|
+
* for no chart. A rejection falls back to the local guess.
|
|
24
|
+
*/
|
|
25
|
+
export type TableChartPlanner = (request: TableChartRequest) => Promise<ChartPlan | null>;
|
|
26
|
+
/** A drawn chart, ready to resolve against the theme. */
|
|
27
|
+
export interface TableChart {
|
|
28
|
+
/** SVG colored with figure tokens (`var(--accent)`, …). */
|
|
29
|
+
readonly svg: string;
|
|
30
|
+
readonly alt: string;
|
|
31
|
+
/** Size in SVG user units. */
|
|
32
|
+
readonly width: number;
|
|
33
|
+
readonly height: number;
|
|
34
|
+
}
|
|
35
|
+
/** The chart under a table: drawn, none, or a smart pick on its way (the promise settles once the cache holds it). */
|
|
36
|
+
export type ChartLookup = TableChart | null | Promise<void>;
|
|
37
|
+
/** One run of a Markdown block: prose (ending at a charted table), or the chart drawn after that table. */
|
|
38
|
+
export type ChartSegment = {
|
|
39
|
+
readonly kind: "markdown";
|
|
40
|
+
readonly text: string;
|
|
41
|
+
} | {
|
|
42
|
+
readonly kind: "chart";
|
|
43
|
+
readonly table: Tokens.Table;
|
|
44
|
+
};
|
|
45
|
+
/** Set how tables become charts (the host's `tui.autoGraph`) and its `smart` planner; the host rebuilds the transcript after. */
|
|
46
|
+
export declare function setTableCharts(mode: TableChartMode, planner?: TableChartPlanner): void;
|
|
47
|
+
/** How assistant tables currently become charts. */
|
|
48
|
+
export declare function tableChartMode(): TableChartMode;
|
|
49
|
+
/** Whether `markdown` may hold a table {@link splitTableCharts} would chart. */
|
|
50
|
+
export declare function hasChartTable(markdown: string): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Split `markdown` after each top-level table that has (or may get) a chart.
|
|
53
|
+
* A table still streaming at the block's tail is left whole: rows may follow.
|
|
54
|
+
*/
|
|
55
|
+
export declare function splitTableCharts(markdown: string, streaming: boolean): ChartSegment[];
|
|
56
|
+
/**
|
|
57
|
+
* The chart for `table` under the current mode, read once per table source.
|
|
58
|
+
* Under `smart` the first lookup of a multi-series table asks the planner.
|
|
59
|
+
*/
|
|
60
|
+
export declare function lookupTableChart(table: Tokens.Table): ChartLookup;
|
|
61
|
+
/**
|
|
62
|
+
* A native `image` node drawing `chart` from its SVG — no raster — resolved
|
|
63
|
+
* against the active theme; rebuilt when the theme changes.
|
|
64
|
+
*/
|
|
65
|
+
export declare function describeTableChart(chart: TableChart, key: string): NativeNode;
|
|
66
|
+
export interface TableChartFigureOptions {
|
|
67
|
+
/** Shared inline-image budget. */
|
|
68
|
+
budget?: ImageBudget;
|
|
69
|
+
/** The chart's rows changed outside a text update: its pick or raster landed. */
|
|
70
|
+
onChange: () => void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The chart under one table, as a terminal image a blank row below it. Looks
|
|
74
|
+
* the chart up on first render — a block rebuilt mid-stream never asks for a
|
|
75
|
+
* pick it drops — and renders nothing until it is drawn, or when the table
|
|
76
|
+
* gets no chart.
|
|
77
|
+
*/
|
|
78
|
+
export declare class TableChartFigure implements Component {
|
|
79
|
+
#private;
|
|
80
|
+
constructor(options: TableChartFigureOptions);
|
|
81
|
+
/** Point the figure at `table`. */
|
|
82
|
+
update(table: Tokens.Table): void;
|
|
83
|
+
/** Whether the chart is still being looked up, picked or drawn. */
|
|
84
|
+
get pending(): boolean;
|
|
85
|
+
render(width: number): readonly string[];
|
|
86
|
+
invalidate(): void;
|
|
87
|
+
dispose(): void;
|
|
88
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Component, Container } from "../tui.js";
|
|
2
2
|
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import type { ReactionTarget } from "./reaction.js";
|
|
4
|
-
import { type NativeNode, type NativeUiEvent } from "../native/node.js";
|
|
4
|
+
import { type DescribeContext, type NativeNode, type NativeUiEvent } from "../native/node.js";
|
|
5
5
|
/** How a user bubble styles its prose and chips (see {@link userBubbleColor}). */
|
|
6
6
|
export interface UserBubbleOptions {
|
|
7
7
|
/** Materialized `file://` targets per attached image, indexed by chip number. */
|
|
@@ -42,7 +42,7 @@ export declare class UserMessageComponent extends Container implements ReactionT
|
|
|
42
42
|
* agent's reaction are chips at the bottom-right, so a reaction landing
|
|
43
43
|
* later updates the frame in place, even deep in scrollback.
|
|
44
44
|
*/
|
|
45
|
-
describe(): NativeNode;
|
|
45
|
+
describe(cx?: DescribeContext): NativeNode;
|
|
46
46
|
/** Hover toolbar clicks: omp's own copy and rewind commands. */
|
|
47
47
|
handleNativeEvent(event: NativeUiEvent): void;
|
|
48
48
|
render(width: number): readonly string[];
|
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
import type { NativeNode } from "../native/node.js";
|
|
2
2
|
import { Container } from "../tui.js";
|
|
3
|
+
/** How a {@link StatusNotice} shows. */
|
|
4
|
+
export interface StatusNoticeOptions {
|
|
5
|
+
/** Styles the ANSI line; resolved at render so a theme change re-shapes it. */
|
|
6
|
+
styleFn?: (text: string) => string;
|
|
7
|
+
/**
|
|
8
|
+
* Whether a native terminal toasts it (default). False keeps the notice to
|
|
9
|
+
* the ANSI transcript: background chatter such as MCP connection progress,
|
|
10
|
+
* which would otherwise re-toast on every server that connects or fails.
|
|
11
|
+
*/
|
|
12
|
+
toast?: boolean;
|
|
13
|
+
}
|
|
3
14
|
/**
|
|
4
15
|
* A transient status notice (`showStatus`: "Thinking blocks: hidden", "Copied
|
|
5
16
|
* to clipboard"). The ANSI render appends a blank row and the dim line to the
|
|
6
17
|
* transcript; a native terminal shows it as a toast instead, so notices never
|
|
7
|
-
* pile up in the history. Updating the text re-shows the toast
|
|
18
|
+
* pile up in the history. Updating the text re-shows the toast; a notice
|
|
19
|
+
* with `toast: false` describes nothing natively.
|
|
8
20
|
*/
|
|
9
21
|
export declare class StatusNotice extends Container {
|
|
10
22
|
#private;
|
|
11
|
-
constructor(message: string,
|
|
12
|
-
setMessage(message: string,
|
|
23
|
+
constructor(message: string, options?: StatusNoticeOptions);
|
|
24
|
+
setMessage(message: string, options?: StatusNoticeOptions): void;
|
|
13
25
|
describe(): NativeNode;
|
|
14
26
|
}
|
|
@@ -285,7 +285,7 @@ export declare class Editor implements Component, Focusable {
|
|
|
285
285
|
* Mirrors the transient state the key dispatch tears down before this action so the two
|
|
286
286
|
* cannot diverge: a pending character jump is cancelled by any other key, and an open
|
|
287
287
|
* spelling-assist popup is dismissed by anything that is not one of its accept keys (its
|
|
288
|
-
*
|
|
288
|
+
* refresh skips assist mode, so a surviving list would hang around forever).
|
|
289
289
|
* While Vim owns the buffer (Normal or Visual) the operation is Vim's `x` — deleting the
|
|
290
290
|
* selection and returning to Normal in Visual mode, the grapheme under the cursor
|
|
291
291
|
* otherwise. Only Insert mode and Vim-off editors delete straight through. */
|
|
@@ -330,6 +330,10 @@ export declare class Editor implements Component, Focusable {
|
|
|
330
330
|
* {@link getExpandedText}). Hosts that intercept large pastes through {@link onLargePaste} use
|
|
331
331
|
* this to re-insert a (possibly transformed) paste without re-triggering the interception hook. */
|
|
332
332
|
insertPaste(content: string): void;
|
|
333
|
+
/** Whether a character-jump hotkey is waiting for its target character. */
|
|
334
|
+
get isJumpPending(): boolean;
|
|
335
|
+
/** Type literal text through the character-editing pipeline without keybinding dispatch. */
|
|
336
|
+
typeCharacter(text: string): void;
|
|
333
337
|
/**
|
|
334
338
|
* Whether an autocomplete popup is on screen. An `@` list narrowed to no match
|
|
335
339
|
* while its refresh is pending stays open internally but is hidden, so it does
|
|
@@ -16,7 +16,21 @@ export interface ImageOptions {
|
|
|
16
16
|
* repaint replaces the placement instead of stacking a duplicate.
|
|
17
17
|
*/
|
|
18
18
|
imageKey?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Schedules a repaint once this image's off-thread SIXEL encode lands.
|
|
21
|
+
* Defaults to the budget's repaint; a host without a budget must pass one,
|
|
22
|
+
* or the image's reserved rows stay blank until an unrelated repaint.
|
|
23
|
+
*/
|
|
24
|
+
requestRender?: () => void;
|
|
19
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Run `render` for rows bound for native scrollback. Those rows are never
|
|
28
|
+
* repainted, so an image whose off-thread SIXEL encode has not landed encodes
|
|
29
|
+
* synchronously instead of committing its reserved blank rows.
|
|
30
|
+
*/
|
|
31
|
+
export declare function renderForScrollback<T>(render: () => T): T;
|
|
32
|
+
/** Widest an {@link Image} rendered at `width` columns draws; callers sizing a raster for it (`SvgFigure`) match it. */
|
|
33
|
+
export declare function imageMaxColumns(width: number): number;
|
|
20
34
|
/** Default count of inline images kept as live graphics before older ones fall back to text. */
|
|
21
35
|
export declare const DEFAULT_MAX_INLINE_IMAGES = 8;
|
|
22
36
|
/**
|
|
@@ -52,6 +66,8 @@ export declare class ImageBudget {
|
|
|
52
66
|
get cap(): number;
|
|
53
67
|
get enabled(): boolean;
|
|
54
68
|
setRequestRender(requestRender: () => void): void;
|
|
69
|
+
/** Ask for a repaint, e.g. once an image's off-thread encode settles. */
|
|
70
|
+
requestRender(): void;
|
|
55
71
|
setCap(cap: number): void;
|
|
56
72
|
/**
|
|
57
73
|
* Stable graphics id for a logical image. A non-empty `key` maps to the same
|
|
@@ -59,6 +75,13 @@ export declare class ImageBudget {
|
|
|
59
75
|
* gets a fresh id every call.
|
|
60
76
|
*/
|
|
61
77
|
acquireId(key?: string): number;
|
|
78
|
+
/**
|
|
79
|
+
* Retire the graphic held under `key` as soon as no frame shows it, instead
|
|
80
|
+
* of when the residency sweep reaches it. For an owner that replaced the
|
|
81
|
+
* image for good — a streaming SVG figure's earlier raster — so superseded
|
|
82
|
+
* revisions never push older images (scrollback included) out of the store.
|
|
83
|
+
*/
|
|
84
|
+
release(key: string): void;
|
|
62
85
|
/**
|
|
63
86
|
* Start an alternate-buffer lifecycle. Call once per `?1049h`, before the
|
|
64
87
|
* first pass of the fullscreen overlay or resize borrow that owns the buffer.
|
|
@@ -28,6 +28,7 @@ export declare class Input implements Component, Focusable {
|
|
|
28
28
|
setValue(value: string): void;
|
|
29
29
|
setUseTerminalCursor(useTerminalCursor: boolean): void;
|
|
30
30
|
getUseTerminalCursor(): boolean;
|
|
31
|
+
capturesInput(data: string): boolean;
|
|
31
32
|
/**
|
|
32
33
|
* Apply one key: the editor's text bindings (motion, deletion, kill ring,
|
|
33
34
|
* undo), pastes and printable text. Returns whether the key was the
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { KeyId } from "../keys.js";
|
|
1
2
|
import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
|
|
2
3
|
import { type ShimmerPalette } from "../theme/shimmer.js";
|
|
3
4
|
import type { TUI } from "../tui.js";
|
|
@@ -23,16 +24,14 @@ export interface WorkingRowSpec {
|
|
|
23
24
|
readonly variant?: WorkingRowVariant;
|
|
24
25
|
/** Shimmer palette of the label (a session-accented intent). */
|
|
25
26
|
readonly palette?: ShimmerPalette;
|
|
26
|
-
/** Live tok/s, docked before the stop control. */
|
|
27
|
-
readonly rate?: number;
|
|
28
27
|
/** Key id that interrupts (`escape`); undefined hides the stop control (Esc would not cancel). */
|
|
29
|
-
readonly interruptKey?:
|
|
28
|
+
readonly interruptKey?: KeyId;
|
|
30
29
|
}
|
|
31
30
|
/**
|
|
32
31
|
* The dock's working row: `starburst` spinner (or a retry countdown ring),
|
|
33
|
-
* the
|
|
34
|
-
* control whose click sends `interrupt`. Compaction adds an
|
|
35
|
-
* `progress` before the stop control; a retry says "Cancel".
|
|
32
|
+
* the elapsed time, the `·` divider, the intent shimmering, a grow spacer,
|
|
33
|
+
* then the stop control whose click sends `interrupt`. Compaction adds an
|
|
34
|
+
* indeterminate `progress` before the stop control; a retry says "Cancel".
|
|
36
35
|
*/
|
|
37
36
|
export declare function describeWorkingRow(spec: WorkingRowSpec, cx: DescribeContext, now?: number): NativeNode;
|
|
38
37
|
type ColorFn = (str: string) => string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type TokensList } from "@oh-my-pi/pi-utils/marked";
|
|
1
2
|
import type { DescribeContext, NativeNode } from "../native/node.js";
|
|
2
3
|
import type { SymbolTheme } from "../symbols.js";
|
|
3
4
|
import type { Component } from "../tui.js";
|
|
@@ -5,6 +6,14 @@ import type { Component } from "../tui.js";
|
|
|
5
6
|
export declare function fastLineStartHazard(grownLine: string): boolean;
|
|
6
7
|
/** @internal exported for tests — the windowed lexer's first-probe window size. */
|
|
7
8
|
export declare const LEX_WINDOW_BYTES: number;
|
|
9
|
+
/**
|
|
10
|
+
* Lex a whole document with the renderer's rules (math, custom rules,
|
|
11
|
+
* strikethrough), windowing anything large enough for the quadratic scan to
|
|
12
|
+
* bite. `links` holds every reference definition, at any nesting depth. Callers
|
|
13
|
+
* that split a document along its blocks (table charts) lex through this so
|
|
14
|
+
* they see the blocks Markdown renders.
|
|
15
|
+
*/
|
|
16
|
+
export declare function lexDocument(text: string): TokensList;
|
|
8
17
|
/** A hyperlink as the renderer sees it: inline `[text](href)`, `<autolink>`, bare GFM URL, or reference link. */
|
|
9
18
|
export interface MarkdownLink {
|
|
10
19
|
/** Flattened visible label with whitespace collapsed to one row; falls back to `href` when empty. */
|
package/dist/types/fuzzy.d.ts
CHANGED
|
@@ -32,6 +32,20 @@ export declare class FuzzyText {
|
|
|
32
32
|
/** Match `query` (space-separated tokens; all must match) against the prepared text. */
|
|
33
33
|
match(query: string): FuzzyMatch;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Items prepared once for repeated {@link fuzzyRank}-equivalent ranking.
|
|
37
|
+
*
|
|
38
|
+
* `fuzzyRank` resolves each candidate's search index through the module cache,
|
|
39
|
+
* which stops admitting entries at {@link INDEX_CACHE_MAX}; larger candidate
|
|
40
|
+
* lists (the full model catalog) rebuild the overflow on every query. Hold one
|
|
41
|
+
* corpus per stable candidate list and call {@link rank} per keystroke instead.
|
|
42
|
+
*/
|
|
43
|
+
export declare class FuzzyCorpus<T> {
|
|
44
|
+
#private;
|
|
45
|
+
constructor(items: readonly T[], getText: (item: T) => string);
|
|
46
|
+
/** Same results as `fuzzyRank(items, query, getText)` for the prepared items. */
|
|
47
|
+
rank(query: string): FuzzyFilterResult<T>[];
|
|
48
|
+
}
|
|
35
49
|
/**
|
|
36
50
|
* Filter and sort items by fuzzy match quality (best matches first).
|
|
37
51
|
* Supports space-separated tokens: all tokens must match.
|
|
@@ -23,6 +23,14 @@ export type KeyName = KeyId | ModifierName;
|
|
|
23
23
|
* is capitalized. Other keys are capitalized (`f5` → `F5`).
|
|
24
24
|
*/
|
|
25
25
|
export declare function formatKeyHint(key: KeyName): string;
|
|
26
|
+
/**
|
|
27
|
+
* Format one key for a native tooltip (a TSP `title`): unicode keycap glyphs
|
|
28
|
+
* whatever the theme's symbol preset (`shift+tab` → `⇧⇥`), which Tern's
|
|
29
|
+
* tooltip splits into keycaps, and `esc` as Tern's own keycaps read. The nerd
|
|
30
|
+
* preset's icons are missing from Tern's UI font, and its spaced chords would
|
|
31
|
+
* not parse as keys.
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatTooltipKey(key: KeyName): string;
|
|
26
34
|
/** Format alternative keys as a slash-separated hint (`["f5", "alt+r"]` → `F5/⌥R`). */
|
|
27
35
|
export declare function formatKeyHints(keys: KeyName | readonly KeyName[]): string;
|
|
28
36
|
/** Format a double-tap gesture: `←←` with glyphs, `Left Left` with words. */
|
|
@@ -107,7 +107,7 @@ export declare const TUI_KEYBINDINGS: {
|
|
|
107
107
|
readonly description: "Delete word backward";
|
|
108
108
|
};
|
|
109
109
|
readonly "tui.editor.deleteWordForward": {
|
|
110
|
-
readonly defaultKeys: ["alt+delete", "alt+d", "super+alt+delete", "super+alt+d"];
|
|
110
|
+
readonly defaultKeys: ["alt+delete", "alt+d", "ctrl+delete", "super+alt+delete", "super+alt+d"];
|
|
111
111
|
readonly description: "Delete word forward";
|
|
112
112
|
};
|
|
113
113
|
readonly "tui.editor.deleteToLineStart": {
|
|
@@ -83,8 +83,8 @@ export declare class NativeBackend {
|
|
|
83
83
|
* The terminal's real `hello` reply after an optimistic start: adopt its
|
|
84
84
|
* APC limit, credits, cell size, kinds, appearance and motion preference.
|
|
85
85
|
* A width the terminal already reported in a `resize` event wins over the
|
|
86
|
-
* reply's. A different vocabulary
|
|
87
|
-
* component, so kinds the terminal lacks fall back.
|
|
86
|
+
* reply's. A different vocabulary, motion preference or clock re-describes
|
|
87
|
+
* every component, so kinds the terminal lacks fall back.
|
|
88
88
|
*/
|
|
89
89
|
confirm(hello: TspHello): void;
|
|
90
90
|
/** SIGWINCH: refresh the width used for `rows` fallback until the terminal reports one. */
|
|
@@ -71,6 +71,12 @@ export interface DescribeContext {
|
|
|
71
71
|
readonly reduceMotion: boolean;
|
|
72
72
|
/** The terminal's appearance is dark. */
|
|
73
73
|
readonly dark: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* The user's system reads a 12-hour clock (`false`: 24-hour); `undefined`
|
|
76
|
+
* when the terminal doesn't say. Pass it as `hour12` when formatting times:
|
|
77
|
+
* the process's own default locale may not know.
|
|
78
|
+
*/
|
|
79
|
+
readonly hour12?: boolean;
|
|
74
80
|
/** Whether the terminal renders `kind` natively (else describe something simpler or let it fall back). */
|
|
75
81
|
supports(kind: TspKind): boolean;
|
|
76
82
|
/**
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* component's root is a `card` whose `head` carries the title.
|
|
8
8
|
*/
|
|
9
9
|
import type { TspProps, TspSpan, TspText } from "@oh-my-pi/pi-wire";
|
|
10
|
-
import type
|
|
10
|
+
import { type KeyName } from "../key-hint-format.js";
|
|
11
11
|
import { type Keybinding } from "../keybindings.js";
|
|
12
12
|
import type { NativeChild, NativeNode } from "./node.js";
|
|
13
13
|
/** One footer hint: the keys that trigger it and what it does. */
|
|
@@ -44,10 +44,10 @@ export interface ActionButtonOptions {
|
|
|
44
44
|
/** Sibling identity key (defaults to the action id); `leafKey(event.key)` reports it back. */
|
|
45
45
|
readonly key?: string;
|
|
46
46
|
/** Key id of the keyboard path the button mirrors, drawn as a keycap inside it (`"r"`, `"ctrl+g"`). */
|
|
47
|
-
readonly keys?:
|
|
47
|
+
readonly keys?: KeyName;
|
|
48
48
|
/** `accent` = the view's hero action, `error` = destructive. */
|
|
49
49
|
readonly tone?: "accent" | "error";
|
|
50
|
-
/** Tooltip; defaults to the label plus the keycap (`"Refresh r"
|
|
50
|
+
/** Tooltip; defaults to the label plus the keycap (`"Refresh r"`, see {@link formatTooltipKey}). */
|
|
51
51
|
readonly title?: string;
|
|
52
52
|
/** Target of an `open` action (URL or `file://` path). */
|
|
53
53
|
readonly href?: string;
|
|
@@ -73,6 +73,7 @@ export interface AgentHubDeps<TRecord extends AgentRecordLike = AgentRecordLike>
|
|
|
73
73
|
/** Mirrors the main transcript's thinking-block visibility. */
|
|
74
74
|
hideThinkingBlock?: () => boolean;
|
|
75
75
|
proseOnlyThinking?: () => boolean;
|
|
76
|
+
expandThinkingBlocks?: () => boolean;
|
|
76
77
|
/** Keys toggling tool output expansion (app.tools.expand). */
|
|
77
78
|
expandKeys?: KeyId[];
|
|
78
79
|
/** Focus the main view on this agent's live session (ctx.focusAgentSession). When absent (collab guest, tests), Enter opens the in-hub chat view instead. */
|
|
@@ -54,6 +54,7 @@ export interface AgentTranscriptViewerDeps {
|
|
|
54
54
|
cwd: string;
|
|
55
55
|
hideThinkingBlock?: () => boolean;
|
|
56
56
|
proseOnlyThinking?: () => boolean;
|
|
57
|
+
expandThinkingBlocks?: () => boolean;
|
|
57
58
|
expandKeys: KeyId[];
|
|
58
59
|
/** Keys that toggle the whole hub closed (app.agents.hub + app.session.observe). */
|
|
59
60
|
hubKeys: KeyId[];
|
|
@@ -60,6 +60,15 @@ export interface AgentsHubDeps {
|
|
|
60
60
|
export interface AgentsHubCallbacks {
|
|
61
61
|
onCancel: () => void;
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Parse model output into a {@link GeneratedAgentSpec}. Accepts a bare JSON object
|
|
65
|
+
* (tried first) or one wrapped in a code fence. Returns the spec with trimmed fields.
|
|
66
|
+
* Throws if the output is not valid JSON or not an object, if `identifier`, `whenToUse`
|
|
67
|
+
* or `systemPrompt` is missing or not a string, if the identifier is not lowercase
|
|
68
|
+
* kebab-case with 2+ words, if `whenToUse` does not start with "Use this agent when",
|
|
69
|
+
* or if `systemPrompt` is empty.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseGeneratedAgentSpec(raw: string): GeneratedAgentSpec;
|
|
63
72
|
/**
|
|
64
73
|
* The fullscreen agents hub component. Hosted via
|
|
65
74
|
* `ui.showOverlay(..., { fullscreen: true })`; the host must call
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Focusable, type TUI } from "../index.js";
|
|
2
2
|
import { type KeybindingsManager } from "../app-keybindings.js";
|
|
3
3
|
import { type Theme } from "../theme/theme.js";
|
|
4
4
|
import type { CodeReviewAnnotation, CodeReviewOverlayResult, ReviewDiffFile, TextReviewAnnotation, TextReviewOverlayResult, TextReviewSource } from "./annotation-types.js";
|
|
@@ -18,10 +18,13 @@ export interface TextReviewOverlayCallbacks extends AnnotationOverlayCallbacks {
|
|
|
18
18
|
onComplete(result: TextReviewOverlayResult | undefined): void;
|
|
19
19
|
}
|
|
20
20
|
/** A fullscreen, annotated diff picker that only relies on public OMP APIs. */
|
|
21
|
-
export declare class AnnotationOverlay implements
|
|
21
|
+
export declare class AnnotationOverlay implements Focusable {
|
|
22
22
|
#private;
|
|
23
|
+
focused: boolean;
|
|
23
24
|
constructor(tui: TUI, theme: Theme, keybindings: KeybindingsManager, files: readonly ReviewDiffFile[], mode: string, callbacks: CodeReviewOverlayCallbacks);
|
|
24
25
|
constructor(tui: TUI, theme: Theme, keybindings: KeybindingsManager, source: TextReviewSource, callbacks: TextReviewOverlayCallbacks);
|
|
26
|
+
/** Keep the nested editor's cursor mode aligned with the overlay focus target. */
|
|
27
|
+
setUseTerminalCursor(useTerminalCursor: boolean): void;
|
|
25
28
|
invalidate(): void;
|
|
26
29
|
dispose(): void;
|
|
27
30
|
getAnnotations(): CodeReviewAnnotation[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Component, type Focusable, Input } from "../index.js";
|
|
2
2
|
import { type BtwHistoryRecord } from "./btw-history.js";
|
|
3
3
|
import type { SpaceHoldHandler } from "../space-hold.js";
|
|
4
|
+
import { type KeyId } from "../app-keybindings.js";
|
|
4
5
|
import type { NativeNode, NativeUiEvent } from "../native/node.js";
|
|
5
6
|
interface BtwHistoryPanelOptions {
|
|
6
7
|
records: readonly BtwHistoryRecord[];
|
|
@@ -9,7 +10,8 @@ interface BtwHistoryPanelOptions {
|
|
|
9
10
|
onCancel: (record: BtwHistoryRecord) => void;
|
|
10
11
|
canFollowUp?: (record: BtwHistoryRecord) => boolean;
|
|
11
12
|
onFollowUp?: (record: BtwHistoryRecord, question: string, signal: AbortSignal) => Promise<boolean>;
|
|
12
|
-
/**
|
|
13
|
+
/** Configured push-to-talk keys for a follow-up composer. */
|
|
14
|
+
spaceHoldKeys?: readonly KeyId[];
|
|
13
15
|
spaceHold?: (input: Input) => SpaceHoldHandler;
|
|
14
16
|
requestRender: () => void;
|
|
15
17
|
getHeight: () => number;
|
|
@@ -33,6 +35,8 @@ export declare class BtwHistoryPanel implements Component, Focusable {
|
|
|
33
35
|
openFollowUp(recordId: string): boolean;
|
|
34
36
|
/** Select a record with its answer pane focused, read from the top (a just-asked /btw). */
|
|
35
37
|
showRecord(recordId: string): void;
|
|
38
|
+
/** Only an active follow-up composer can claim its configured push-to-talk keys. */
|
|
39
|
+
capturesInput(data: string): boolean;
|
|
36
40
|
/** Enhanced clipboard pastes belong only to the active composer. */
|
|
37
41
|
pasteText(text: string): void;
|
|
38
42
|
handleInput(data: string): void;
|
|
@@ -31,6 +31,7 @@ export interface CopySelectorDeps {
|
|
|
31
31
|
cwd: string;
|
|
32
32
|
hideThinkingBlock?: () => boolean;
|
|
33
33
|
proseOnlyThinking?: () => boolean;
|
|
34
|
+
expandThinkingBlocks?: () => boolean;
|
|
34
35
|
linkTargets?: ReadonlyMap<string, string>;
|
|
35
36
|
requestRender: () => void;
|
|
36
37
|
/** Replaces the "Copy" header when the picker is reused for another purpose. */
|
|
@@ -49,6 +49,12 @@ export interface ModelBrowserSource extends ModelRoleLookup {
|
|
|
49
49
|
readonly knownRoleIds: readonly string[];
|
|
50
50
|
readonly mruOrder: readonly string[];
|
|
51
51
|
readonly modelPerf: ReadonlyMap<string, ModelBrowserPerf>;
|
|
52
|
+
/**
|
|
53
|
+
* Service tier the host would send for `model`, when it runs one. Rows with a
|
|
54
|
+
* measured tier aggregate (`selector@tier`) then display that tier's numbers
|
|
55
|
+
* instead of the standard aggregate.
|
|
56
|
+
*/
|
|
57
|
+
serviceTierFor?(model: Model): string | undefined;
|
|
52
58
|
getRoleInfo(role: string): ModelBrowserRoleInfo;
|
|
53
59
|
defaultRoleChain(role: string): string[];
|
|
54
60
|
resolveRoleValue(value: string | undefined, models: Model[], roleLookup?: ModelRoleLookup): ResolvedModelRoleValue;
|
|
@@ -134,12 +140,28 @@ export interface SearchAffinity {
|
|
|
134
140
|
* policy, not evidence of user preference.
|
|
135
141
|
*/
|
|
136
142
|
export declare function buildSearchAffinity(providerOrder: ReadonlyArray<string>, roles: RoleAssignments, mruOrder: ReadonlyArray<string>): SearchAffinity;
|
|
137
|
-
/**
|
|
138
|
-
export
|
|
143
|
+
/** Inputs to {@link rankModelItems} / {@link ModelItemRanker}. */
|
|
144
|
+
export interface ModelRankOptions {
|
|
139
145
|
roles: RoleAssignments;
|
|
140
146
|
mruOrder: ReadonlyArray<string>;
|
|
141
147
|
affinity: SearchAffinity;
|
|
142
|
-
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* {@link rankModelItems} prepared for one candidate list: the fuzzy index, the
|
|
151
|
+
* MRU/version order, and the affinity ranks depend only on the items and options,
|
|
152
|
+
* so per-keystroke callers (composer mentions, `/switch` arguments, the picker)
|
|
153
|
+
* hold one ranker and pay only the per-query fuzzy scan.
|
|
154
|
+
*/
|
|
155
|
+
export declare class ModelItemRanker {
|
|
156
|
+
#private;
|
|
157
|
+
readonly items: ReadonlyArray<ModelBrowserItem>;
|
|
158
|
+
readonly options: ModelRankOptions;
|
|
159
|
+
constructor(items: ReadonlyArray<ModelBrowserItem>, options: ModelRankOptions);
|
|
160
|
+
/** Rank by text relevance, user affinity, and MRU/version order. */
|
|
161
|
+
rank(query: string): ModelBrowserItem[];
|
|
162
|
+
}
|
|
163
|
+
/** Rank picker and mention candidates by text relevance, user affinity, and MRU/version order. */
|
|
164
|
+
export declare function rankModelItems(query: string, items: ReadonlyArray<ModelBrowserItem>, options: ModelRankOptions): ModelBrowserItem[];
|
|
143
165
|
/**
|
|
144
166
|
* A slim role chip: `● default ◉` — solid dot for configured assignments,
|
|
145
167
|
* hollow for auto-selected fallbacks, thinking glyph attached when set.
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
* Focus regions (`toc`/`body`/`actions`) cycle with Tab/Shift+Tab; arrows move
|
|
14
14
|
* within the focused region and step left into the sidebar. The default focus is
|
|
15
15
|
* `actions`, so the muscle memory of the old single-target overlay carries over:
|
|
16
|
-
* ↑/↓ select options, Enter confirms, ←/→ drives the slider
|
|
17
|
-
*
|
|
16
|
+
* ↑/↓ select options, Enter confirms, ←/→ drives the slider, g/G + PgUp/PgDn
|
|
17
|
+
* scroll, and the external-editor key opens the plan. Under Tern the options
|
|
18
|
+
* are a horizontal bar, so ←/→ select options and Shift+←/→ drive the slider.
|
|
18
19
|
*/
|
|
19
20
|
import { type Component } from "../index.js";
|
|
20
21
|
import type { HookSelectorSlider } from "./hook-selector.js";
|
|
@@ -48,6 +48,7 @@ export interface RewindSelectorDeps {
|
|
|
48
48
|
cwd: string;
|
|
49
49
|
hideThinkingBlock?: () => boolean;
|
|
50
50
|
proseOnlyThinking?: () => boolean;
|
|
51
|
+
expandThinkingBlocks?: () => boolean;
|
|
51
52
|
linkTargets?: ReadonlyMap<string, string>;
|
|
52
53
|
requestRender: () => void;
|
|
53
54
|
/** Sibling branch paths of `entryId`'s turn (excluding the turn itself). */
|
|
@@ -121,12 +121,12 @@ export declare class UsageDashboardComponent implements Component {
|
|
|
121
121
|
* The sheet body (the terminal's `lg` overlay is the frame): a head row
|
|
122
122
|
* (checked ago, Overview/Details tabs, Refresh), then either the provider
|
|
123
123
|
* grid of frames with window meters and the activity heatmap, or the
|
|
124
|
-
* per-provider detail tables
|
|
125
|
-
* `progress`/`table` on terminals without
|
|
126
|
-
* inputs change.
|
|
124
|
+
* per-provider detail tables, then Close like the other report sheets.
|
|
125
|
+
* `meter`/`chart` fall back to `progress`/`table` on terminals without
|
|
126
|
+
* them. Rebuilt only when its inputs change.
|
|
127
127
|
*/
|
|
128
128
|
describe(cx: DescribeContext): NativeNode;
|
|
129
|
-
/** Tab clicks switch views like Enter/Esc; the Refresh button runs `r
|
|
129
|
+
/** Tab clicks switch views like Enter/Esc; the Refresh button runs `r`; Close closes from either view. */
|
|
130
130
|
handleNativeEvent(event: NativeUiEvent): void;
|
|
131
131
|
handleInput(data: string): void;
|
|
132
132
|
}
|
|
@@ -18,6 +18,10 @@ export interface ComposerNativeState {
|
|
|
18
18
|
};
|
|
19
19
|
/** Thinking effort word (`high`, `off`, `auto`); undefined when the model has no thinking. */
|
|
20
20
|
readonly thinking?: string;
|
|
21
|
+
/** The thinking level draws as the model chip's icon instead of its own chip (where the terminal has `effort`). */
|
|
22
|
+
readonly thinkingInModel?: boolean;
|
|
23
|
+
/** Generation tok/s after the thinking level (live while running, else the last reading); undefined hides it. */
|
|
24
|
+
readonly rate?: number;
|
|
21
25
|
/** A turn is running: the send keycap becomes a Stop button. */
|
|
22
26
|
readonly running: boolean;
|
|
23
27
|
/** The viewed subagent's lineage, outermost first and the viewed agent last; undefined on the main session. */
|
|
@@ -229,7 +233,8 @@ export declare class CustomEditor extends Editor {
|
|
|
229
233
|
* The TSP composer: role `omp.editor[.bash|.python]` (tone `pending` while
|
|
230
234
|
* a turn runs) over the context hairline, the viewing header while a
|
|
231
235
|
* subagent is focused, the attachment chips, a `line` row of the
|
|
232
|
-
* shell-mode chip and the input, and the `bar`: model chip, effort chip
|
|
236
|
+
* shell-mode chip and the input, and the `bar`: model chip, effort chip
|
|
237
|
+
* (or the effort glyph as the model chip's icon), the generation rate,
|
|
233
238
|
* the other status facts, usage, then send (Stop while a turn runs).
|
|
234
239
|
* Clicks come back as `status.model`, `thinking.cycle`, `submit`,
|
|
235
240
|
* `interrupt` and `focus:<id>` actions.
|
|
@@ -271,9 +276,9 @@ export declare class CustomEditor extends Editor {
|
|
|
271
276
|
onLeftAtStart?: () => void;
|
|
272
277
|
/** Called when the viewing header asks to view agent `id` ({@link MAIN_AGENT_ID}: the main session). */
|
|
273
278
|
onFocusAgent?: (id: string) => void;
|
|
274
|
-
/**
|
|
275
|
-
* stays out of Vim's Normal/Visual modes (where the space bar is the `l` motion)
|
|
276
|
-
* open autocomplete menu. */
|
|
279
|
+
/** Configurable push-to-talk; set its `handler` to enable it. It is a text-composition gesture, so
|
|
280
|
+
* it stays out of Vim's Normal/Visual modes (where the space bar is the `l` motion), away from an
|
|
281
|
+
* open autocomplete menu, and out of a pending character jump (whose target may be the key). */
|
|
277
282
|
readonly spaceHold: SpaceHoldGesture;
|
|
278
283
|
setActionKeys(action: ConfigurableEditorAction, keys: KeyId[]): void;
|
|
279
284
|
/**
|
|
@@ -288,6 +293,7 @@ export declare class CustomEditor extends Editor {
|
|
|
288
293
|
* Clear all custom key handlers.
|
|
289
294
|
*/
|
|
290
295
|
clearCustomKeyHandlers(): void;
|
|
296
|
+
capturesInput(data: string): boolean;
|
|
291
297
|
handleInput(data: string): void;
|
|
292
298
|
/**
|
|
293
299
|
* Route a keystroke through the base text-editor pipeline only, skipping the
|
|
@@ -15,7 +15,10 @@ export interface AssistantMessageHost {
|
|
|
15
15
|
readonly viewSession: AssistantMessageSession;
|
|
16
16
|
readonly effectiveHideThinkingBlock: boolean;
|
|
17
17
|
readonly proseOnlyThinking: boolean;
|
|
18
|
+
readonly expandThinkingBlocks: boolean;
|
|
18
19
|
readonly assistantImagesVisible: boolean;
|
|
20
|
+
/** Whether the viewed session's tables get charts: the main session's do, a focused subagent's do not. */
|
|
21
|
+
readonly tableChartsVisible: boolean;
|
|
19
22
|
readonly hideToolActivity: boolean;
|
|
20
23
|
readonly toolOutputExpanded: boolean;
|
|
21
24
|
readonly ui: {
|
|
@@ -19,7 +19,7 @@ export declare function applyModelMentionCompletion(lines: string[], cursorLine:
|
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
21
|
* Create a session-scoped model candidate lookup using picker ordering. The
|
|
22
|
-
* scope and
|
|
22
|
+
* scope and its prepared ranker are reused across queries until their inputs change.
|
|
23
23
|
*/
|
|
24
24
|
export declare function createModelMentionSource(host: {
|
|
25
25
|
source: ModelBrowserSource;
|