@linxiraos/pi-tui 1.1.26 → 1.1.27

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.
Files changed (137) hide show
  1. package/CHANGELOG.md +9 -33
  2. package/README.md +6 -2
  3. package/dist/types/active-terminal.d.ts +30 -0
  4. package/dist/types/app-keybindings.d.ts +6 -1
  5. package/dist/types/apps/git/git-tui.d.ts +3 -2
  6. package/dist/types/chat/assistant-message.d.ts +6 -1
  7. package/dist/types/chat/chat-transcript-builder.d.ts +1 -0
  8. package/dist/types/chat/user-message.d.ts +2 -2
  9. package/dist/types/chrome/status-notice.d.ts +15 -3
  10. package/dist/types/components/editor.d.ts +8 -1
  11. package/dist/types/components/image.d.ts +14 -0
  12. package/dist/types/components/input.d.ts +2 -1
  13. package/dist/types/components/loader.d.ts +5 -6
  14. package/dist/types/components/markdown.d.ts +13 -4
  15. package/dist/types/key-hint-format.d.ts +8 -0
  16. package/dist/types/native/apply.d.ts +4 -3
  17. package/dist/types/native/backend.d.ts +2 -2
  18. package/dist/types/native/encode.d.ts +5 -2
  19. package/dist/types/native/node.d.ts +36 -5
  20. package/dist/types/native/overlay.d.ts +3 -3
  21. package/dist/types/native/settle.d.ts +4 -3
  22. package/dist/types/overlays/agent-hub.d.ts +1 -0
  23. package/dist/types/overlays/agent-transcript-viewer.d.ts +1 -0
  24. package/dist/types/overlays/btw-history-panel.d.ts +13 -1
  25. package/dist/types/overlays/copy-selector.d.ts +1 -0
  26. package/dist/types/overlays/hub-frame.d.ts +4 -1
  27. package/dist/types/overlays/model-hub.d.ts +14 -0
  28. package/dist/types/overlays/report-panel.d.ts +68 -0
  29. package/dist/types/overlays/rewind-selector.d.ts +1 -0
  30. package/dist/types/overlays/thinking-selector.d.ts +2 -2
  31. package/dist/types/overlays/usage-dashboard.d.ts +4 -4
  32. package/dist/types/prompt/composer-cache.d.ts +0 -16
  33. package/dist/types/prompt/composer.d.ts +17 -2
  34. package/dist/types/prompt/custom-editor.d.ts +14 -5
  35. package/dist/types/prompt/interactive-context-helpers.d.ts +1 -0
  36. package/dist/types/prompt/welcome.d.ts +1 -1
  37. package/dist/types/space-hold.d.ts +40 -25
  38. package/dist/types/status-line/context-usage.d.ts +7 -5
  39. package/dist/types/terminal-capabilities.d.ts +14 -1
  40. package/dist/types/terminal.d.ts +1 -10
  41. package/dist/types/thinking.d.ts +1 -1
  42. package/dist/types/tools/bash.d.ts +7 -2
  43. package/dist/types/tools/task.d.ts +6 -3
  44. package/dist/types/tui.d.ts +5 -0
  45. package/dist/types/windows-input-mode.d.ts +33 -1
  46. package/package.json +9 -9
  47. package/src/active-terminal.d.ts +30 -0
  48. package/src/active-terminal.ts +80 -0
  49. package/src/app-keybindings.d.ts +6 -1
  50. package/src/app-keybindings.ts +6 -1
  51. package/src/apps/git/diff-pane.ts +70 -18
  52. package/src/apps/git/git-tui.ts +21 -14
  53. package/src/apps/git/sidebar.ts +8 -3
  54. package/src/bracketed-paste.ts +10 -3
  55. package/src/chat/assistant-message.d.ts +6 -1
  56. package/src/chat/assistant-message.ts +26 -4
  57. package/src/chat/chat-transcript-builder.d.ts +1 -0
  58. package/src/chat/chat-transcript-builder.ts +4 -0
  59. package/src/chat/tool-execution.ts +6 -1
  60. package/src/chat/user-message.d.ts +2 -2
  61. package/src/chat/user-message.ts +16 -5
  62. package/src/chrome/status-notice.ts +25 -7
  63. package/src/chrome/transcript-container.ts +69 -6
  64. package/src/components/editor.d.ts +8 -1
  65. package/src/components/editor.ts +22 -1
  66. package/src/components/image.d.ts +14 -0
  67. package/src/components/image.ts +68 -1
  68. package/src/components/input.d.ts +2 -1
  69. package/src/components/input.ts +17 -7
  70. package/src/components/loader.d.ts +5 -6
  71. package/src/components/loader.ts +10 -17
  72. package/src/components/markdown.d.ts +13 -4
  73. package/src/components/markdown.ts +473 -105
  74. package/src/desktop-notify.ts +2 -1
  75. package/src/hotkeys-markdown.ts +9 -2
  76. package/src/key-hint-format.d.ts +8 -0
  77. package/src/key-hint-format.ts +25 -10
  78. package/src/kitty-graphics.ts +7 -1
  79. package/src/native/apply.d.ts +4 -3
  80. package/src/native/apply.ts +4 -3
  81. package/src/native/backend.d.ts +2 -2
  82. package/src/native/backend.ts +25 -4
  83. package/src/native/encode.d.ts +5 -2
  84. package/src/native/encode.ts +18 -3
  85. package/src/native/node.d.ts +36 -5
  86. package/src/native/node.ts +31 -5
  87. package/src/native/overlay.d.ts +3 -3
  88. package/src/native/overlay.ts +4 -4
  89. package/src/native/reconcile.ts +12 -4
  90. package/src/native/settle.d.ts +4 -3
  91. package/src/native/settle.ts +4 -3
  92. package/src/overlays/agent-hub.ts +4 -0
  93. package/src/overlays/agent-transcript-viewer.ts +2 -0
  94. package/src/overlays/ask-dialog.ts +3 -7
  95. package/src/overlays/btw-history-panel.ts +124 -38
  96. package/src/overlays/copy-selector.d.ts +1 -0
  97. package/src/overlays/copy-selector.ts +2 -0
  98. package/src/overlays/extensions/extension-dashboard.ts +4 -4
  99. package/src/overlays/hub-frame.ts +19 -1
  100. package/src/overlays/jobs-panel.ts +5 -6
  101. package/src/overlays/model-browser.ts +30 -16
  102. package/src/overlays/model-hub.ts +137 -12
  103. package/src/overlays/pause-screen.ts +2 -2
  104. package/src/overlays/plan-review-overlay.ts +14 -0
  105. package/src/overlays/report-panel.ts +191 -0
  106. package/src/overlays/rewind-selector.ts +2 -0
  107. package/src/overlays/settings-defs.ts +1 -1
  108. package/src/overlays/thinking-selector.ts +11 -10
  109. package/src/overlays/usage-dashboard.ts +17 -8
  110. package/src/overlays/usage-row.ts +22 -8
  111. package/src/prompt/composer-cache.ts +7 -86
  112. package/src/prompt/composer.ts +33 -11
  113. package/src/prompt/custom-editor.ts +228 -79
  114. package/src/prompt/interactive-context-helpers.ts +2 -0
  115. package/src/prompt/queued-messages.ts +6 -4
  116. package/src/prompt/tips.txt +12 -9
  117. package/src/prompt/welcome.ts +10 -35
  118. package/src/render/render-utils.ts +5 -1
  119. package/src/space-hold.d.ts +40 -25
  120. package/src/space-hold.ts +156 -52
  121. package/src/status-line/context-usage.ts +21 -46
  122. package/src/terminal-capabilities.d.ts +14 -1
  123. package/src/terminal-capabilities.ts +64 -26
  124. package/src/terminal.d.ts +1 -10
  125. package/src/terminal.ts +64 -62
  126. package/src/theme/symbols.ts +5 -3
  127. package/src/thinking.d.ts +1 -1
  128. package/src/thinking.ts +1 -1
  129. package/src/tools/bash.d.ts +7 -2
  130. package/src/tools/bash.ts +24 -5
  131. package/src/tools/streaming-output.ts +5 -0
  132. package/src/tools/task.d.ts +6 -3
  133. package/src/tools/task.ts +9 -9
  134. package/src/tui.d.ts +5 -0
  135. package/src/tui.ts +370 -70
  136. package/src/windows-input-mode.d.ts +33 -1
  137. package/src/windows-input-mode.ts +204 -6
@@ -12,6 +12,14 @@ export interface ModelHubSource extends ModelBrowserSource {
12
12
  getProjectModelRole(role: string): string | undefined;
13
13
  getGlobalModelRole(role: string): string | undefined;
14
14
  getModelRoleSource(role: string): "global" | "project" | "default";
15
+ /**
16
+ * Saved model presets (in switch order) and the one the current role setup
17
+ * matches, if any. Absent hosts have no presets to switch between.
18
+ */
19
+ getModelPresets?(): {
20
+ names: readonly string[];
21
+ active: string | undefined;
22
+ };
15
23
  }
16
24
  /** Catalog capabilities required by the model hub. */
17
25
  export interface ModelHubRegistry extends ModelBrowserRegistry {
@@ -48,6 +56,12 @@ export interface ModelHubCallbacks {
48
56
  onLoginRequest?: (providerId: string) => void;
49
57
  /** Save the current role assignments and default thinking level as a named model preset. */
50
58
  onSavePreset?: (name: string) => void;
59
+ /**
60
+ * Apply a saved model preset (ctrl+←/→ or p/⇧P in the Roles view) and report
61
+ * the outcome itself. A switch that writes nothing (a refused preset) still
62
+ * advances the hub's preset cursor, so the next press moves past it.
63
+ */
64
+ onSwitchPreset?: (name: string) => void | Promise<void>;
51
65
  /** Persist a new quick-switch cycle order (the ctrl+p role cycle). */
52
66
  onCycleOrderChange?: (order: string[]) => void;
53
67
  onCancel: () => void;
@@ -0,0 +1,68 @@
1
+ import type { TspText } from "@linxiraos/pi-wire";
2
+ import { OverlayPanel } from "../chrome/overlay-box.js";
3
+ import type { NativeNode, NativeUiEvent } from "../native/node.js";
4
+ import type { Component } from "../tui.js";
5
+ /** Options of a {@link ReportPanel}. */
6
+ export interface ReportPanelOptions {
7
+ /** Plain title: the text-mode border title, and the native sheet head unless {@link head} is given. */
8
+ readonly title: string;
9
+ /** Styled native sheet head. */
10
+ readonly head?: TspText;
11
+ /** The read-only report; it draws no frame or title of its own. */
12
+ readonly body: Component;
13
+ /**
14
+ * Display form of the key that dismisses the report while it sits above the
15
+ * editor (the editor's interrupt key, which routes to it). Once the panel
16
+ * holds focus ({@link ReportPanel.holdFocus}) the hint shows the key its own
17
+ * input closes on instead.
18
+ */
19
+ readonly closeKey: string;
20
+ /** The focused panel (native sheet, text-mode full-screen page) closes on Esc / its Close button: this runs. */
21
+ readonly onClose: () => void;
22
+ /**
23
+ * Most rows the text-mode panel may take, borders included (the screen rows
24
+ * left above the editor); a taller report scrolls inside it. `undefined`
25
+ * leaves it uncapped.
26
+ */
27
+ readonly maxRows?: () => number | undefined;
28
+ }
29
+ /**
30
+ * A read-only command report (`/changelog`, `/context`, `/tools`, …).
31
+ *
32
+ * Text mode draws a titled box with the body and an Esc hint: above the editor
33
+ * like the `/btw` panel while it fits there (the editor keeps focus and its
34
+ * Esc takes it away), or as a full-screen page on the alternate screen when it
35
+ * is taller, whose body scrolls on the arrow/page/Home/End keys and the wheel.
36
+ * Natively it is a sheet like `/usage`: a centred `lg` glass sheet titled by
37
+ * the report whose body the terminal scrolls (wheel, and the same keys
38
+ * forwarded as scroll requests), then a Close button; Esc closes it.
39
+ */
40
+ export declare class ReportPanel extends OverlayPanel {
41
+ #private;
42
+ readonly nativeOverlay: NonNullable<Component["nativeOverlay"]>;
43
+ constructor(options: ReportPanelOptions);
44
+ /**
45
+ * The panel is shown with focus (native sheet, text-mode full-screen page):
46
+ * its own {@link handleInput} closes it, so the hint names that key.
47
+ */
48
+ holdFocus(): void;
49
+ /**
50
+ * Text mode: cap the box to {@link ReportPanelOptions.maxRows}, scrolling a
51
+ * taller body. The cap is a hard limit: when a resize leaves fewer rows than
52
+ * the box's chrome needs, its bottom (the hint and closing border) is cut
53
+ * rather than spilling over the editor.
54
+ */
55
+ render(width: number): readonly string[];
56
+ /** Text mode: rows the whole box takes at `width` when nothing caps it. */
57
+ heightAt(width: number): number;
58
+ /** The sheet body (the overlay is the frame, and its body the scroller): the report, then Close (Esc). */
59
+ describe(): NativeNode;
60
+ invalidate(): void;
61
+ /**
62
+ * Focused (the native sheet, or the text-mode full-screen page): Esc closes;
63
+ * the arrow, page, Home and End keys and the wheel scroll the body.
64
+ */
65
+ handleInput(data: string): void;
66
+ /** Close runs what Esc runs. */
67
+ handleNativeEvent(event: NativeUiEvent): void;
68
+ }
@@ -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). */
@@ -1,4 +1,4 @@
1
- import type { Effort } from "@linxiraos/pi-ai";
1
+ import { type ConfiguredThinkingLevel } from "../thinking.js";
2
2
  import { SelectList, type SgrMouseEvent } from "../index.js";
3
3
  import { OverlayPanel } from "../chrome/overlay-box.js";
4
4
  import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
@@ -7,7 +7,7 @@ import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.
7
7
  */
8
8
  export declare class ThinkingSelectorComponent extends OverlayPanel {
9
9
  #private;
10
- constructor(currentLevel: Effort, availableLevels: Effort[], onSelect: (level: Effort) => void, onCancel: () => void);
10
+ constructor(currentLevel: ConfiguredThinkingLevel | undefined, availableLevels: ConfiguredThinkingLevel[], onSelect: (level: ConfiguredThinkingLevel) => void, onCancel: () => void);
11
11
  describe(cx: DescribeContext): NativeNode | null;
12
12
  /** Picker pointer events drive the list exactly as its keys do. */
13
13
  handleNativeEvent(event: NativeUiEvent): void;
@@ -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. `meter`/`chart` fall back to
125
- * `progress`/`table` on terminals without them. Rebuilt only when its
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
  }
@@ -1,4 +1,3 @@
1
- import type { LspServerInfo, RecentSession } from "./welcome.js";
2
1
  import type { ComposerPreferences, ComposerStatusCache } from "./composer.js";
3
2
  import type { SymbolPreset } from "../theme/theme.js";
4
3
  /** Theme inputs cached from the last resolved settings load for stable prepaint colors. */
@@ -8,19 +7,10 @@ export interface ComposerThemePreferences {
8
7
  readonly darkTheme?: string;
9
8
  readonly lightTheme?: string;
10
9
  }
11
- /** Last authoritative model labels shown in the welcome component. */
12
- export interface ComposerWelcomeCache {
13
- readonly modelName: string;
14
- readonly providerName: string;
15
- }
16
10
  /** Speculative composer state read before the settings/session graph is available. */
17
11
  export interface ComposerStartupCache {
18
12
  readonly preferences?: ComposerPreferences;
19
13
  readonly theme?: ComposerThemePreferences;
20
- readonly welcome?: ComposerWelcomeCache;
21
- readonly recentSessions: RecentSession[];
22
- /** `null` when the last run had LSP disabled. */
23
- readonly lspServers: LspServerInfo[] | null;
24
14
  readonly status?: ComposerStatusCache;
25
15
  }
26
16
  /**
@@ -43,12 +33,6 @@ export declare class ComposerCache {
43
33
  read(cwd: string): ComposerStartupCache;
44
34
  /** Resolved theme and composer settings for the next prepaint. */
45
35
  writeUi(cwd: string, preferences: ComposerPreferences, theme: ComposerThemePreferences): void;
46
- /** Authoritative model/provider labels for the next welcome prepaint. */
47
- writeWelcome(cwd: string, welcome: ComposerWelcomeCache): void;
48
- /** The latest recent-session rows (first four). */
49
- writeRecentSessions(cwd: string, sessions: readonly RecentSession[]): void;
50
- /** The latest detected project LSP rows; `null` records that LSP is disabled. */
51
- writeLspServers(cwd: string, servers: readonly LspServerInfo[] | null): void;
52
36
  /** Status-bar inputs for the next prepaint's startup status line. */
53
37
  writeStatus(cwd: string, status: ComposerStatusCache): void;
54
38
  close(): void;
@@ -6,7 +6,7 @@ import { type Component, type ResizeScrollbackMode, type TerminalFramePlan, type
6
6
  import type { NativeSurface, NativeSurfaceProvider } from "../native/node.js";
7
7
  import { CustomEditor } from "./custom-editor.js";
8
8
  import type { WordCompletionMethod } from "./word-completion.js";
9
- import { type LspServerInfo, type RecentSession, WelcomeComponent } from "./welcome.js";
9
+ import { WelcomeComponent, type RecentSession, type LspServerInfo } from "./welcome.js";
10
10
  /** Live settings that affect the composer before and after session adoption. */
11
11
  export interface ComposerPreferences {
12
12
  readonly quiet: boolean;
@@ -122,6 +122,21 @@ export declare class Composer implements TerminalFrameProvider, NativeSurfacePro
122
122
  #private;
123
123
  readonly ui: TUI;
124
124
  constructor(options?: ComposerOptions);
125
+ /**
126
+ * Rows the below-transcript chrome under `root` (editor, status line, …)
127
+ * took in the last frame, so a root that grows upward can cap itself to
128
+ * the screen rows left above them; `undefined` before `root` was laid out.
129
+ */
130
+ rowsBelow(root: Component): number | undefined;
131
+ /**
132
+ * Keep the input on the bottom row while the live rows cannot fill the
133
+ * screen, as after an inline decision panel closes. A tall block that just
134
+ * left the chrome above the editor (a command report) may have scrolled
135
+ * rows into native history that cannot be pulled back; without the pin the
136
+ * editor would jump up to where the shorter frame now ends. The pin lifts
137
+ * once live rows fill the screen again.
138
+ */
139
+ pinInputToBottom(): void;
125
140
  /** Compose the bounded mutable viewport and the next ordered history append. */
126
141
  renderFrame(viewport: ViewportSize): TerminalFramePlan;
127
142
  /**
@@ -164,7 +179,7 @@ export declare class Composer implements TerminalFrameProvider, NativeSurfacePro
164
179
  enableInput(): void;
165
180
  /** Apply settings changes without replacing the editor or welcome component. */
166
181
  setPreferences(update: Partial<ComposerPreferences>): void;
167
- /** Patch welcome data in place as model, session, and project discovery complete. */
182
+ /** Patch welcome data in place as version, session, and project discovery complete. */
168
183
  updateWelcome(update: ComposerWelcomeUpdate): void;
169
184
  /** Replace optional header content around the stable welcome scene. */
170
185
  setHeaderExtras(before: readonly Component[], after: readonly Component[]): void;
@@ -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. */
@@ -213,6 +217,8 @@ export declare class CustomEditor extends Editor {
213
217
  * once after construction (and again after `setEditorComponent` swaps the
214
218
  * editor). Passing `undefined` clears any pending frame. */
215
219
  setShimmerRepaintHandler(handler: (() => void) | undefined): void;
220
+ /** Editing is available during bootstrap; atomic sends wait until submission is wired and enabled. */
221
+ protected get nativeSendable(): boolean;
216
222
  /** Viewing a subagent, the draft goes to it: the placeholder names it. */
217
223
  describePlaceholder: () => string;
218
224
  /** A shell-mode draft highlights as its language. */
@@ -227,7 +233,8 @@ export declare class CustomEditor extends Editor {
227
233
  * The TSP composer: role `zeta.editor[.bash|.python]` (tone `pending` while
228
234
  * a turn runs) over the context hairline, the viewing header while a
229
235
  * subagent is focused, the attachment chips, a `line` row of the
230
- * 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,
231
238
  * the other status facts, usage, then send (Stop while a turn runs).
232
239
  * Clicks come back as `status.model`, `thinking.cycle`, `submit`,
233
240
  * `interrupt` and `focus:<id>` actions.
@@ -237,7 +244,8 @@ export declare class CustomEditor extends Editor {
237
244
  * Clicks on the composer's controls take the same paths as their keys: ⇧⇥,
238
245
  * ⏎ and Esc; the viewing header's links (`focus:<id>`) go to the host,
239
246
  * the status facts' clicks (`status.*`) to their source. Selection edits
240
- * go to the buffer.
247
+ * go to the buffer; `send` submits its own prompt after saving the old draft
248
+ * for recall and waiting for in-flight clipboard work.
241
249
  */
242
250
  handleNativeEvent(event: NativeUiEvent): void;
243
251
  onEscape?: () => void;
@@ -268,9 +276,9 @@ export declare class CustomEditor extends Editor {
268
276
  onLeftAtStart?: () => void;
269
277
  /** Called when the viewing header asks to view agent `id` ({@link MAIN_AGENT_ID}: the main session). */
270
278
  onFocusAgent?: (id: string) => void;
271
- /** Space-bar push-to-talk; set its `handler` to enable it. It is a text-composition gesture, so it
272
- * stays out of Vim's Normal/Visual modes (where the space bar is the `l` motion) and away from an
273
- * 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). */
274
282
  readonly spaceHold: SpaceHoldGesture;
275
283
  setActionKeys(action: ConfigurableEditorAction, keys: KeyId[]): void;
276
284
  /**
@@ -285,6 +293,7 @@ export declare class CustomEditor extends Editor {
285
293
  * Clear all custom key handlers.
286
294
  */
287
295
  clearCustomKeyHandlers(): void;
296
+ capturesInput(data: string): boolean;
288
297
  handleInput(data: string): void;
289
298
  /**
290
299
  * Route a keystroke through the base text-editor pipeline only, skipping the
@@ -15,6 +15,7 @@ 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;
19
20
  readonly hideToolActivity: boolean;
20
21
  readonly toolOutputExpanded: boolean;
@@ -37,7 +37,7 @@ export declare class WelcomeComponent implements Component {
37
37
  private recentSessions;
38
38
  /** Detected project servers; `null` means LSP is disabled and hides the section. */
39
39
  private lspServers;
40
- constructor(version: string, modelName: string, providerName: string, recentSessions?: RecentSession[],
40
+ constructor(version: string, modelName?: string, providerName?: string, recentSessions?: RecentSession[],
41
41
  /** Detected project servers; `null` means LSP is disabled and hides the section. */
42
42
  lspServers?: LspServerInfo[] | null);
43
43
  get tip(): string | undefined;
@@ -1,45 +1,60 @@
1
- /** Max gap (ms) between two spaces for the later one to count as OS key auto-repeat rather than a
2
- * deliberate press. OS auto-repeat is fast; a deliberate tap (even a fast one) is slower. */
1
+ import { type KeyId } from "./keys.js";
2
+ /** Printable text a push-to-talk candidate key types (plain or shifted single characters and Space),
3
+ * or undefined for non-printable keys and chords, which the gesture reserves instead of typing. */
4
+ export declare function getSpaceHoldText(data: string, canonical: string | undefined): string | undefined;
5
+ /** Max gap (ms) between two configured-key presses for a later one to count as OS key auto-repeat
6
+ * rather than a deliberate press. OS auto-repeat is fast; a deliberate tap (even a fast one) is slower. */
3
7
  export declare const SPACE_REPEAT_MAX_GAP_MS = 120;
4
- /** Two consecutive inter-space gaps are "mechanical" (machine-driven auto-repeat) when both are
8
+ /** Two consecutive inter-key gaps are "mechanical" (machine-driven auto-repeat) when both are
5
9
  * within {@link SPACE_REPEAT_MAX_GAP_MS} and differ by no more than this — an absolute jitter floor
6
10
  * or, for slower repeat rates, {@link SPACE_REPEAT_JITTER_RATIO} of the smaller gap. OS key-repeat
7
- * is metronomic; a human smashing the bar is fast but irregular, so its deltas never stay this
8
- * steady. */
11
+ * is metronomic; human typing is irregular, so its deltas do not stay this steady. */
9
12
  export declare const SPACE_REPEAT_JITTER_MS = 18;
10
13
  export declare const SPACE_REPEAT_JITTER_RATIO = 0.35;
11
- /** Consecutive mechanical (fast + steady) deltas that confirm the space bar is held and start
12
- * recording. Needs a sustained metronomic cadence, so jittery smashing and deliberate taps never
14
+ /** Consecutive mechanical (fast + steady) deltas that confirm a configured key is held and start
15
+ * recording. Needs a sustained metronomic cadence, so jittery typing and deliberate taps never
13
16
  * reach it. */
14
17
  export declare const SPACE_HOLD_MECHANICAL_RUN = 2;
15
- /** Idle gap (ms) after the last repeated space that counts as the space bar being released, ending
16
- * the push-to-talk recording. Must comfortably exceed the OS key-repeat interval. */
18
+ /** Idle gap (ms) after the last repeated configured-key press that counts as release and ends
19
+ * push-to-talk. Must comfortably exceed the OS key-repeat interval. */
17
20
  export declare const SPACE_HOLD_RELEASE_MS = 250;
18
- /** What a recognized space-bar hold drives — the push-to-talk start and stop. */
21
+ /** A release timer firing more than this (ms) past its deadline means the event loop stalled (a
22
+ * synchronous microphone open, GC, a heavy render) while the bar may still be held: the repeats
23
+ * emitted during the stall are queued but unread, so the stall must not read as a release. */
24
+ export declare const SPACE_HOLD_STALL_SLACK_MS = 100;
25
+ /** What a recognized push-to-talk hold drives — the start and stop callbacks. */
19
26
  export interface SpaceHoldHandler {
20
- /** Gate for the gesture. Returns false to keep the space bar inserting spaces normally, so
21
- * disabling push-to-talk restores plain space behavior. */
27
+ /** Gate for the gesture. Returns false to let matching keys behave normally. */
22
28
  enabled(): boolean;
23
- /** A sustained hold was recognized. The optimistically-typed spaces have already been deleted. */
29
+ /** A sustained hold was recognized; any safely typed candidate text has already been deleted. */
24
30
  onStart(): void;
25
- /** The held space bar was released (an idle gap with no further repeated spaces, or any other key). */
31
+ /** The held key was released (an idle gap with no further repeats, or any other key). */
26
32
  onEnd(): void;
27
33
  }
28
34
  /** What the host must do with a keypress after {@link SpaceHoldGesture.process} has seen it:
29
- * `"pass"` — handle it normally; `"type"` — insert the space now (it is tracked back out if the run
30
- * turns into a hold); `"swallow"` — drop it, the gesture consumed it. */
35
+ * `"pass"` — handle it normally; `"type"` — insert its safely decoded printable text now (it is
36
+ * tracked back out if the run turns into a hold); `"swallow"` — drop it, the gesture consumed it. */
31
37
  export type SpaceHoldStep = "pass" | "type" | "swallow";
32
- /** Space-hold push-to-talk state machine. A held space bar emits OS auto-repeat: a *steady* stream
33
- * of spaces at a fixed fast interval. We watch the inter-space deltas and only recognize a hold once
34
- * {@link SPACE_HOLD_MECHANICAL_RUN} consecutive deltas are "mechanical" — both auto-repeat-fast and
35
- * near-identical (see {@link gapsAreMechanical}). Smashing the bar is fast but jittery and deliberate
36
- * taps are too slow, so neither escalates and both keep typing real spaces; the few spaces typed
37
- * before a real hold is recognized are tracked back out of the host input. */
38
+ /** Push-to-talk key-hold state machine. A held key emits OS auto-repeat at a steady fast interval.
39
+ * We watch inter-key deltas and only recognize a hold once {@link SPACE_HOLD_MECHANICAL_RUN}
40
+ * consecutive deltas are mechanical (see {@link gapsAreMechanical}). Deliberate taps and jittery
41
+ * runs stay typed; only text typed during the current steady run is removed on recognition. */
38
42
  export declare class SpaceHoldGesture {
39
43
  #private;
40
- /** Unset (the default) keeps the space bar typing spaces. */
44
+ /** Configured alternative keys. Alternatives are tracked independently and never combine into one run. */
45
+ get keys(): readonly KeyId[];
46
+ set keys(keys: readonly KeyId[]);
47
+ /** Unset (the default) keeps configured keys behaving normally. */
41
48
  handler: SpaceHoldHandler | undefined;
42
49
  constructor(deleteTyped: (count: number) => void, allowed?: () => boolean);
43
- /** Feed one keypress, `isSpace` when it is a plain space bar press. */
44
- process(isSpace: boolean): SpaceHoldStep;
50
+ /** Pure focused-owner preflight on raw input: whether the key must reach the host before
51
+ * TUI-wide input listeners. Only non-printable bindings are claimed — they would otherwise
52
+ * trigger app shortcuts mid-hold; printable candidates keep the normal listener path so
53
+ * raw-input observers (e.g. extensions) still see typed text, as they did before remapping. */
54
+ shouldRoute(data: string): boolean;
55
+ /** Feed one canonical keypress and, when safely printable, its decoded text length. The host
56
+ * records the actual inserted length with {@link recordTyped} after applying normal typing. */
57
+ process(key: string | undefined, insertedCharacterLength?: number): SpaceHoldStep;
58
+ /** Account for text the host actually inserted for the preceding `"type"` step. */
59
+ recordTyped(insertedCharacterLength: number): void;
45
60
  }
@@ -3,6 +3,7 @@ import type { CompactionSettings } from "@linxiraos/pi-agent-core/compaction";
3
3
  import type { Tool as AiTool, Model } from "@linxiraos/pi-ai";
4
4
  import type { Theme } from "../theme/index.js";
5
5
  import { Container } from "../tui.js";
6
+ import type { TspText } from "@linxiraos/pi-wire";
6
7
  import type { DescribeContext, NativeNode } from "../native/node.js";
7
8
  interface ContextSkill {
8
9
  readonly name: string;
@@ -154,6 +155,8 @@ export declare function computeNonMessageBreakdown(session: NonMessageTokenSourc
154
155
  * session and model.
155
156
  */
156
157
  export declare function computeContextBreakdown(session: ContextUsageSession, options: ContextUsageOptions): ContextBreakdown;
158
+ /** The `/context` title: the model and its window once a model is selected. */
159
+ export declare function contextUsageHead(breakdown: ContextBreakdown): TspText;
157
160
  /**
158
161
  * Native context-usage panel for terminals without `meter`: the cell grid as
159
162
  * unwrapped styled rows beside the legend. The terminal places the legend
@@ -161,15 +164,14 @@ export declare function computeContextBreakdown(session: ContextUsageSession, op
161
164
  */
162
165
  export declare function describeContextUsage(breakdown: ContextBreakdown): NativeNode;
163
166
  /**
164
- * The `/context` transcript block: ANSI renders the titled cell grid between
165
- * rules; natively it is one frame, drawn with `meter`s where the terminal
166
- * has them and as the glyph grid otherwise.
167
+ * The `/context` report body, without a frame or title of its own (the panel
168
+ * showing it is titled {@link contextUsageHead}): ANSI renders the cell grid
169
+ * beside the legend; natively it is drawn with `meter`s where the terminal has
170
+ * them and as the glyph grid otherwise.
167
171
  */
168
172
  export declare class ContextUsageView extends Container {
169
173
  #private;
170
174
  constructor(breakdown: ContextBreakdown, theme: Theme);
171
- /** Replace the shown breakdown in place, refreshing both the ANSI and native views. */
172
- setBreakdown(breakdown: ContextBreakdown): void;
173
175
  describe(cx: DescribeContext): NativeNode;
174
176
  }
175
177
  /**
@@ -11,7 +11,7 @@ export declare enum NotifyProtocol {
11
11
  Osc99 = "\u001B]99;;",
12
12
  Osc9 = "\u001B]9;"
13
13
  }
14
- export type TerminalId = "kitty" | "ghostty" | "wezterm" | "iterm2" | "vscode" | "alacritty" | "warp" | "orca" | "otty" | "rio" | "tern" | "base" | "trueColor";
14
+ export type TerminalId = "kitty" | "ghostty" | "wezterm" | "iterm2" | "vscode" | "alacritty" | "warp" | "orca" | "otty" | "rio" | "tern" | "monstar" | "base" | "trueColor";
15
15
  /** Terminal capability details used for rendering and protocol selection. */
16
16
  export declare class TerminalInfo {
17
17
  readonly id: TerminalId;
@@ -296,6 +296,13 @@ export interface ImageRenderOptions {
296
296
  placementId?: number;
297
297
  /** When true (Kitty + {@link imageId}), also return the one-time transmit sequence. */
298
298
  includeTransmit?: boolean;
299
+ /**
300
+ * SIXEL sequence for the target pixel size renderImage computes, so the
301
+ * caller can encode off the JS thread: answer `undefined` while the encode
302
+ * is pending (the image's rows stay reserved) and `null` once it failed.
303
+ * Without a provider, renderImage encodes synchronously.
304
+ */
305
+ sixel?: (widthPx: number, heightPx: number) => string | null | undefined;
299
306
  }
300
307
  export declare function getCellDimensions(): CellDimensions;
301
308
  export declare function setCellDimensions(dims: CellDimensions): void;
@@ -393,6 +400,12 @@ export declare function getJpegDimensions(base64Data: string): ImageDimensions |
393
400
  export declare function getGifDimensions(base64Data: string): ImageDimensions | null;
394
401
  export declare function getWebpDimensions(base64Data: string): ImageDimensions | null;
395
402
  export declare function getImageDimensions(base64Data: string, mimeType: string): ImageDimensions | null;
403
+ /**
404
+ * SIXEL sequence for `base64Data` at the given pixel size, encoded on the JS
405
+ * thread; `null` when the encode fails. For output that cannot wait for an
406
+ * off-thread encode.
407
+ */
408
+ export declare function encodeSixelNow(base64Data: string, widthPx: number, heightPx: number): string | null;
396
409
  export declare function renderImage(base64Data: string, imageDimensions: ImageDimensions, options?: ImageRenderOptions): {
397
410
  sequence?: string;
398
411
  lines?: string[];
@@ -1,4 +1,5 @@
1
1
  import { type TspHello } from "./native/encode.js";
2
+ export { writeTerminalSequence, writeThroughActiveTerminal } from "./active-terminal.js";
2
3
  /**
3
4
  * Split `data` into chunks whose encoded UTF-8 byte length is no greater than
4
5
  * `maxChunkBytes`, preferring a line boundary (`\n`) as the cut point so
@@ -69,16 +70,6 @@ export declare class StdoutStallWatchdog {
69
70
  }
70
71
  /** Record alternate-screen state (called by the TUI on `?1049h`/`?1049l` writes). */
71
72
  export declare function setAltScreenActive(active: boolean): void;
72
- /**
73
- * Route an out-of-band escape sequence (e.g. an OSC title update) through the
74
- * active terminal's output path. While a TUI owns stdout, frame paints go
75
- * through the off-thread write pump and can split across multiple write(2)
76
- * calls; a direct main-thread `process.stdout.write` can land between two of
77
- * them — mid escape sequence — and the host terminal then prints the payload
78
- * as literal text at the cursor position. Returns false when no terminal has
79
- * started, in which case the caller owns stdout and may write directly.
80
- */
81
- export declare function writeThroughActiveTerminal(data: string): boolean;
82
73
  /**
83
74
  * Emergency terminal restore - call this from signal/crash handlers
84
75
  * Resets terminal state without requiring access to the ProcessTerminal instance
@@ -4,7 +4,7 @@ import { ThinkingLevel } from "@linxiraos/pi-agent-core/thinking";
4
4
  import { Effort } from "@linxiraos/pi-catalog/effort";
5
5
  import type { Model } from "@linxiraos/pi-catalog/types";
6
6
  /** Thinking selectors accepted by CLI inputs, in display order. */
7
- export declare const CLI_THINKING_LEVELS: readonly string[];
7
+ export declare const CLI_THINKING_LEVELS: readonly ConfiguredThinkingLevel[];
8
8
  /**
9
9
  * Metadata used to render thinking selector values in the coding-agent UI.
10
10
  */
@@ -4,8 +4,13 @@ import { type OutputMeta } from "./output-meta.js";
4
4
  import type { NativeToolView, RenderResultContextOptions, RenderResultOptions } from "./renderer.js";
5
5
  /** Default collapsed shell output preview height. */
6
6
  export declare const BASH_DEFAULT_PREVIEW_LINES = 10;
7
- /** LLM-facing footer appended when a tool call becomes a background job. */
8
- export declare function formatBackgroundNotice(jobId: string): string;
7
+ /**
8
+ * LLM-facing footer appended when a tool call becomes a background job. It states the job's kill
9
+ * deadline (`timeoutSec`, `undefined` when disabled) so the model knows the job will die at it before
10
+ * it waits on the result. The deadline counts the job's whole run time, not time left from now: an
11
+ * auto-backgrounded call has already spent its foreground wait.
12
+ */
13
+ export declare function formatBackgroundNotice(jobId: string, timeoutSec: number | undefined): string;
9
14
  /** Shell execution metadata used by transcript rendering. */
10
15
  export interface BashToolDetails {
11
16
  meta?: OutputMeta;
@@ -1,10 +1,9 @@
1
1
  import type { Usage } from "@linxiraos/pi-ai";
2
2
  import type { ThemeColor } from "../theme/theme.js";
3
3
  import type { ConfiguredThinkingLevel } from "../render/render-utils.js";
4
+ import type { RenderResultOptions, NativeToolView, ToolRenderResult } from "./renderer.js";
4
5
  import { type Component } from "../tui.js";
5
- import type { RenderResultOptions } from "./renderer.js";
6
6
  import { type Theme } from "../theme/theme.js";
7
- import type { NativeToolView, ToolRenderResult } from "./renderer.js";
8
7
  /** Render context threaded in from `ToolExecutionComponent.#buildRenderContext`. */
9
8
  interface TaskRenderContext {
10
9
  hasResult?: boolean;
@@ -108,6 +107,8 @@ export interface TaskItem {
108
107
  solutionSpace?: string;
109
108
  /** Per-spawn thinking effort: lowest/middle/highest level the resolved model supports. Overrides the agent's default selector (e.g. `auto`). */
110
109
  effort?: "lo" | "med" | "hi";
110
+ /** Per-spawn model selector or ordered selector array; overrides agent and settings preferences. */
111
+ model?: string | string[];
111
112
  /** Caller-provided output schema; its presence overrides the selected agent's schema. */
112
113
  outputSchema?: unknown;
113
114
  /** Validation behavior for a caller-provided or inherited output schema. */
@@ -134,6 +135,8 @@ export interface TaskParams {
134
135
  solutionSpace?: string;
135
136
  /** Per-spawn thinking effort (flat form): lowest/middle/highest level the resolved model supports. */
136
137
  effort?: "lo" | "med" | "hi";
138
+ /** Per-spawn model selector or ordered selector array; overrides agent and settings preferences. */
139
+ model?: string | string[];
137
140
  /** Caller-provided output schema; its presence overrides the selected agent's schema. */
138
141
  outputSchema?: unknown;
139
142
  /** Validation behavior for a caller-provided or inherited output schema. */
@@ -255,7 +258,7 @@ export interface AgentProgress {
255
258
  resolvedModelRoute?: string;
256
259
  /** True when a live advisor was attached to this run's session, not merely enabled in settings. */
257
260
  advisor?: boolean;
258
- /** The agent's latest self-estimate of task completion (0–100), from the periodic `task.completionProbeMs` side request. */
261
+ /** The agent's latest self-estimate of task completion (0–100), from the periodic `task.completionProbe` side request. */
259
262
  completionPercent?: number;
260
263
  /** Data extracted by registered subprocess tool handlers (keyed by tool name) */
261
264
  extractedToolData?: Record<string, unknown[]>;
@@ -150,6 +150,11 @@ export interface Component {
150
150
  describeScreen?(cx: DescribeContext): NativeScreen;
151
151
  /** User actions on nodes this component described (toggle, select, activate, custom). */
152
152
  handleNativeEvent?(event: NativeUiEvent): void;
153
+ /**
154
+ * Pure preflight for focused input that must precede TUI-wide input listeners
155
+ * and debug shortcuts. A true result routes the event to this component first.
156
+ */
157
+ capturesInput?(data: string): boolean;
153
158
  /**
154
159
  * Optional handler for keyboard input when component has focus
155
160
  */
@@ -16,10 +16,26 @@
16
16
  * terminal sends; chords legacy encoding loses (modified Enter/Tab/Escape,
17
17
  * Ctrl+Shift+letter, …) translate to kitty CSI-u, which key matching already
18
18
  * parses.
19
+ *
20
+ * A host terminal that writes VT instead of key records (any ConPTY host
21
+ * besides Windows Terminal's native path) reaches us as one `Vk = 0` text
22
+ * record per byte: Alt+Up arrives as `ESC`, `[`, `1`, `;`, `3`, `A`. Those
23
+ * bytes are reassembled into the escape sequence they spell; delivering them
24
+ * one at a time turns every such key into a bare Escape plus typed garbage.
25
+ */
26
+ /**
27
+ * Stateful decoder: joins UTF-16 surrogate halves that arrive as separate
28
+ * records, and reassembles VT escape sequences relayed as text records.
19
29
  */
20
- /** Stateful decoder: joins UTF-16 surrogate halves that arrive as separate records. */
21
30
  export declare class Win32InputModeDecoder {
22
31
  #private;
32
+ /** Whether relayed VT text is held waiting for the rest of its sequence. */
33
+ get hasPendingSequence(): boolean;
34
+ /**
35
+ * Release held VT text as-is. The caller invokes this once no further bytes
36
+ * arrived in time, so a lone relayed ESC still acts as the Escape key.
37
+ */
38
+ flushPendingSequence(): string[];
23
39
  /**
24
40
  * Translate one stdin sequence. Returns `undefined` when `data` is not a
25
41
  * win32-input-mode record (pass it through unchanged), otherwise the key
@@ -35,3 +51,19 @@ export declare class Win32InputModeDecoder {
35
51
  */
36
52
  decodePaste(content: string): string;
37
53
  }
54
+ /**
55
+ * Restores paste delimiters that a Windows console host emitted as individual
56
+ * win32-input-mode key records before StdinBuffer searches for the delimiters.
57
+ * Non-matching records remain untouched for normal key and paste decoding.
58
+ */
59
+ export declare class Win32PasteMarkerNormalizer {
60
+ #private;
61
+ /**
62
+ * `onExpired` runs after held records are released because their wait timed
63
+ * out, so a downstream holder can treat the same wait as already elapsed.
64
+ */
65
+ constructor(onInput: (data: string) => void, onExpired?: () => void);
66
+ process(data: string): void;
67
+ /** Release an incomplete marker as its original key records. */
68
+ flush(): void;
69
+ }