@oh-my-pi/pi-tui 18.13.3 → 18.14.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.
Files changed (226) hide show
  1. package/CHANGELOG.md +17 -41
  2. package/README.md +34 -34
  3. package/dist/types/app-keybindings.d.ts +15 -0
  4. package/dist/types/apps/session-picker.d.ts +1 -0
  5. package/dist/types/charts/chart-plan.d.ts +9 -7
  6. package/dist/types/chat/assistant-message.d.ts +14 -2
  7. package/dist/types/chat/extension-types.d.ts +31 -0
  8. package/dist/types/chat/reply-write.d.ts +48 -0
  9. package/dist/types/chat/table-chart.d.ts +4 -3
  10. package/dist/types/chat/tool-execution.d.ts +0 -1
  11. package/dist/types/chat/transcript-outline.d.ts +7 -0
  12. package/dist/types/chat/transcript-render-helpers.d.ts +2 -0
  13. package/dist/types/chrome/index.d.ts +1 -0
  14. package/dist/types/chrome/transcript-notice.d.ts +35 -0
  15. package/dist/types/chrome/transcript-status.d.ts +20 -8
  16. package/dist/types/components/editor.d.ts +6 -0
  17. package/dist/types/components/markdown.d.ts +7 -0
  18. package/dist/types/native/blobs.d.ts +2 -1
  19. package/dist/types/native/picker.d.ts +3 -3
  20. package/dist/types/overlays/login-dialog.d.ts +5 -1
  21. package/dist/types/overlays/model-browser.d.ts +10 -1
  22. package/dist/types/overlays/oauth-selector.d.ts +23 -0
  23. package/dist/types/overlays/rewind-selector.d.ts +1 -1
  24. package/dist/types/overlays/session-selector.d.ts +9 -0
  25. package/dist/types/prompt/composer.d.ts +41 -4
  26. package/dist/types/prompt/interactive-context-helpers.d.ts +10 -3
  27. package/dist/types/prompt/welcome.d.ts +6 -2
  28. package/dist/types/render/extension-links.d.ts +65 -0
  29. package/dist/types/render/hyperlink.d.ts +25 -7
  30. package/dist/types/render/index.d.ts +1 -0
  31. package/dist/types/setup/scenes/model.d.ts +1 -1
  32. package/dist/types/setup/scenes/outro.d.ts +5 -4
  33. package/dist/types/setup/scenes/sign-in.d.ts +13 -8
  34. package/dist/types/setup/scenes/splash.d.ts +4 -4
  35. package/dist/types/setup/scenes/types.d.ts +16 -1
  36. package/dist/types/setup/startup-splash.d.ts +1 -1
  37. package/dist/types/setup/wizard-overlay.d.ts +11 -7
  38. package/dist/types/setup/wizard.d.ts +5 -1
  39. package/dist/types/status-line/component.d.ts +1 -1
  40. package/dist/types/status-line/context-usage.d.ts +28 -6
  41. package/dist/types/status-line/host.d.ts +6 -2
  42. package/dist/types/tools/bash.d.ts +2 -0
  43. package/dist/types/tools/default-renderer.d.ts +6 -4
  44. package/dist/types/tools/irc.d.ts +6 -0
  45. package/dist/types/tools/json-tree.d.ts +23 -4
  46. package/dist/types/tools/lsp.d.ts +2 -0
  47. package/dist/types/tools/mcp.d.ts +6 -5
  48. package/dist/types/tools/native-view.d.ts +1 -1
  49. package/dist/types/tools/renderer.d.ts +2 -0
  50. package/dist/types/tools/streaming-output.d.ts +11 -0
  51. package/dist/types/tools/task.d.ts +9 -1
  52. package/dist/types/tools/url-scheme-host.d.ts +17 -0
  53. package/dist/types/tools/yield.d.ts +1 -1
  54. package/dist/types/tui.d.ts +3 -1
  55. package/package.json +9 -14
  56. package/src/app-keybindings.ts +15 -0
  57. package/src/apps/session-picker.ts +2 -0
  58. package/src/charts/chart-plan.ts +20 -50
  59. package/src/chat/assistant-message.ts +134 -18
  60. package/src/chat/background-tan-message.ts +4 -0
  61. package/src/chat/chat-transcript-builder.ts +58 -28
  62. package/src/chat/compaction-summary-message.ts +2 -1
  63. package/src/chat/extension-types.ts +34 -0
  64. package/src/chat/reply-write.ts +127 -0
  65. package/src/chat/table-chart.ts +10 -4
  66. package/src/chat/tool-execution.ts +13 -10
  67. package/src/chat/transcript-outline.ts +27 -0
  68. package/src/chat/transcript-render-helpers.ts +66 -24
  69. package/src/chrome/index.ts +1 -0
  70. package/src/chrome/transcript-notice.ts +83 -0
  71. package/src/chrome/transcript-status.ts +29 -29
  72. package/src/components/editor.ts +7 -0
  73. package/src/components/markdown.ts +116 -6
  74. package/src/hotkeys-markdown.ts +1 -0
  75. package/src/native/backend.ts +3 -2
  76. package/src/native/blobs.ts +3 -2
  77. package/src/native/picker.ts +3 -3
  78. package/src/overlays/advisor-config.ts +1 -10
  79. package/src/overlays/login-dialog.ts +31 -5
  80. package/src/overlays/model-browser.ts +37 -0
  81. package/src/overlays/model-hub.ts +1 -7
  82. package/src/overlays/model-picker.ts +1 -10
  83. package/src/overlays/oauth-selector.ts +44 -6
  84. package/src/overlays/rewind-selector.ts +29 -12
  85. package/src/overlays/session-selector.ts +113 -16
  86. package/src/prompt/composer.ts +213 -5
  87. package/src/prompt/emoji-autocomplete.ts +0 -2
  88. package/src/prompt/interactive-context-helpers.ts +29 -4
  89. package/src/prompt/welcome.ts +31 -45
  90. package/src/render/extension-links.ts +214 -0
  91. package/src/render/hyperlink.ts +65 -9
  92. package/src/render/index.ts +1 -0
  93. package/src/setup/scenes/composer.ts +2 -0
  94. package/src/setup/scenes/glyph.ts +2 -0
  95. package/src/setup/scenes/model.ts +192 -29
  96. package/src/setup/scenes/outro.ts +30 -17
  97. package/src/setup/scenes/sign-in.ts +196 -400
  98. package/src/setup/scenes/splash.ts +25 -21
  99. package/src/setup/scenes/theme.ts +2 -0
  100. package/src/setup/scenes/types.ts +18 -1
  101. package/src/setup/startup-splash.ts +8 -7
  102. package/src/setup/wizard-overlay.ts +164 -33
  103. package/src/setup/wizard.ts +11 -2
  104. package/src/status-line/component.ts +4 -10
  105. package/src/status-line/context-usage.ts +72 -21
  106. package/src/status-line/host.ts +6 -2
  107. package/src/theme/defaults.json +1 -0
  108. package/src/theme/loader.ts +1 -1
  109. package/src/theme/theme.ts +2 -10
  110. package/src/tools/bash.ts +2 -0
  111. package/src/tools/default-renderer.ts +9 -6
  112. package/src/tools/eval.ts +14 -4
  113. package/src/tools/irc.ts +6 -0
  114. package/src/tools/json-tree.ts +131 -41
  115. package/src/tools/lsp.ts +36 -15
  116. package/src/tools/mcp.ts +20 -12
  117. package/src/tools/native-view.ts +1 -1
  118. package/src/tools/renderer.ts +2 -0
  119. package/src/tools/streaming-output.ts +41 -0
  120. package/src/tools/task.ts +59 -17
  121. package/src/tools/url-scheme-host.ts +21 -0
  122. package/src/tools/yield.ts +18 -9
  123. package/src/tui.ts +36 -13
  124. package/THIRD-PARTY-NOTICES.txt +0 -22901
  125. package/dist/types/theme/defaults/index.d.ts +0 -10289
  126. package/src/theme/defaults/alabaster.json +0 -103
  127. package/src/theme/defaults/amethyst.json +0 -106
  128. package/src/theme/defaults/anthracite.json +0 -103
  129. package/src/theme/defaults/basalt.json +0 -101
  130. package/src/theme/defaults/birch.json +0 -105
  131. package/src/theme/defaults/dark-abyss.json +0 -101
  132. package/src/theme/defaults/dark-arctic.json +0 -114
  133. package/src/theme/defaults/dark-aurora.json +0 -105
  134. package/src/theme/defaults/dark-catppuccin.json +0 -117
  135. package/src/theme/defaults/dark-cavern.json +0 -101
  136. package/src/theme/defaults/dark-celestial.json +0 -116
  137. package/src/theme/defaults/dark-copper.json +0 -105
  138. package/src/theme/defaults/dark-cosmos.json +0 -100
  139. package/src/theme/defaults/dark-cyberpunk.json +0 -112
  140. package/src/theme/defaults/dark-dracula.json +0 -108
  141. package/src/theme/defaults/dark-eclipse.json +0 -101
  142. package/src/theme/defaults/dark-ember.json +0 -105
  143. package/src/theme/defaults/dark-equinox.json +0 -100
  144. package/src/theme/defaults/dark-forest.json +0 -106
  145. package/src/theme/defaults/dark-github.json +0 -115
  146. package/src/theme/defaults/dark-gruvbox.json +0 -122
  147. package/src/theme/defaults/dark-lavender.json +0 -105
  148. package/src/theme/defaults/dark-lunar.json +0 -99
  149. package/src/theme/defaults/dark-midnight.json +0 -105
  150. package/src/theme/defaults/dark-monochrome.json +0 -104
  151. package/src/theme/defaults/dark-monokai.json +0 -108
  152. package/src/theme/defaults/dark-nebula.json +0 -100
  153. package/src/theme/defaults/dark-neon-noir.json +0 -110
  154. package/src/theme/defaults/dark-nord.json +0 -108
  155. package/src/theme/defaults/dark-ocean.json +0 -111
  156. package/src/theme/defaults/dark-one.json +0 -110
  157. package/src/theme/defaults/dark-poimandres.json +0 -125
  158. package/src/theme/defaults/dark-rainforest.json +0 -101
  159. package/src/theme/defaults/dark-reef.json +0 -101
  160. package/src/theme/defaults/dark-retro.json +0 -102
  161. package/src/theme/defaults/dark-rose-pine.json +0 -106
  162. package/src/theme/defaults/dark-sakura.json +0 -105
  163. package/src/theme/defaults/dark-slate.json +0 -105
  164. package/src/theme/defaults/dark-solarized.json +0 -107
  165. package/src/theme/defaults/dark-solstice.json +0 -100
  166. package/src/theme/defaults/dark-starfall.json +0 -101
  167. package/src/theme/defaults/dark-sunset.json +0 -109
  168. package/src/theme/defaults/dark-swamp.json +0 -100
  169. package/src/theme/defaults/dark-synthwave.json +0 -113
  170. package/src/theme/defaults/dark-taiga.json +0 -101
  171. package/src/theme/defaults/dark-terminal.json +0 -105
  172. package/src/theme/defaults/dark-tokyo-night.json +0 -111
  173. package/src/theme/defaults/dark-tundra.json +0 -101
  174. package/src/theme/defaults/dark-twilight.json +0 -101
  175. package/src/theme/defaults/dark-volcanic.json +0 -101
  176. package/src/theme/defaults/graphite.json +0 -102
  177. package/src/theme/defaults/index.ts +0 -203
  178. package/src/theme/defaults/light-arctic.json +0 -117
  179. package/src/theme/defaults/light-aurora-day.json +0 -101
  180. package/src/theme/defaults/light-canyon.json +0 -101
  181. package/src/theme/defaults/light-catppuccin.json +0 -116
  182. package/src/theme/defaults/light-cirrus.json +0 -100
  183. package/src/theme/defaults/light-coral.json +0 -105
  184. package/src/theme/defaults/light-cyberpunk.json +0 -106
  185. package/src/theme/defaults/light-dawn.json +0 -100
  186. package/src/theme/defaults/light-dunes.json +0 -101
  187. package/src/theme/defaults/light-eucalyptus.json +0 -105
  188. package/src/theme/defaults/light-forest.json +0 -110
  189. package/src/theme/defaults/light-frost.json +0 -105
  190. package/src/theme/defaults/light-github.json +0 -125
  191. package/src/theme/defaults/light-glacier.json +0 -101
  192. package/src/theme/defaults/light-gruvbox.json +0 -118
  193. package/src/theme/defaults/light-haze.json +0 -100
  194. package/src/theme/defaults/light-honeycomb.json +0 -105
  195. package/src/theme/defaults/light-lagoon.json +0 -101
  196. package/src/theme/defaults/light-lavender.json +0 -105
  197. package/src/theme/defaults/light-meadow.json +0 -101
  198. package/src/theme/defaults/light-mint.json +0 -105
  199. package/src/theme/defaults/light-monochrome.json +0 -111
  200. package/src/theme/defaults/light-ocean.json +0 -109
  201. package/src/theme/defaults/light-one.json +0 -109
  202. package/src/theme/defaults/light-opal.json +0 -101
  203. package/src/theme/defaults/light-orchard.json +0 -101
  204. package/src/theme/defaults/light-paper.json +0 -105
  205. package/src/theme/defaults/light-poimandres.json +0 -125
  206. package/src/theme/defaults/light-prism.json +0 -100
  207. package/src/theme/defaults/light-retro.json +0 -108
  208. package/src/theme/defaults/light-sand.json +0 -105
  209. package/src/theme/defaults/light-savanna.json +0 -101
  210. package/src/theme/defaults/light-solarized.json +0 -112
  211. package/src/theme/defaults/light-soleil.json +0 -100
  212. package/src/theme/defaults/light-sunset.json +0 -109
  213. package/src/theme/defaults/light-synthwave.json +0 -108
  214. package/src/theme/defaults/light-tokyo-night.json +0 -121
  215. package/src/theme/defaults/light-wetland.json +0 -101
  216. package/src/theme/defaults/light-zenith.json +0 -99
  217. package/src/theme/defaults/limestone.json +0 -104
  218. package/src/theme/defaults/mahogany.json +0 -107
  219. package/src/theme/defaults/marble.json +0 -103
  220. package/src/theme/defaults/obsidian.json +0 -101
  221. package/src/theme/defaults/onyx.json +0 -101
  222. package/src/theme/defaults/pearl.json +0 -103
  223. package/src/theme/defaults/porcelain.json +0 -101
  224. package/src/theme/defaults/quartz.json +0 -106
  225. package/src/theme/defaults/sandstone.json +0 -105
  226. package/src/theme/defaults/titanium.json +0 -100
@@ -16,14 +16,14 @@
16
16
  * the item id and `action` with an action id (plus `value` for
17
17
  * `scope`/`tab`/`strip`). {@link pickerEvent} folds them into one shape.
18
18
  */
19
- import type { TspPickerAction, TspPickerItem, TspPickerProps } from "@oh-my-pi/pi-wire";
19
+ import type { TspPickerAction, TspPickerItem, TspPickerProps, TspProps } from "@oh-my-pi/pi-wire";
20
20
  import type { KeyName } from "../key-hint-format.js";
21
21
  import { type Keybinding } from "../keybindings.js";
22
22
  import type { Input } from "../components/input.js";
23
23
  import type { SelectItem, SelectList } from "../components/select-list.js";
24
24
  import type { NativeChild, NativeNode, NativeUiEvent } from "./node.js";
25
25
  /** The picker sheet; `preview` children fill its preview pane. */
26
- export declare function picker(p: TspPickerProps, preview?: readonly NativeChild[]): NativeNode;
26
+ export declare function picker(p: TspProps<"picker">, preview?: readonly NativeChild[]): NativeNode;
27
27
  /**
28
28
  * A picker's search field from the {@link Input} that edits it: the text and
29
29
  * its caret. `null` hides the field. Memoized pickers MUST key on the caret
@@ -37,7 +37,7 @@ export declare const PICKER_KEY = "picker";
37
37
  * the picker as child {@link PICKER_KEY}, which the reconciler hoists into
38
38
  * `layer`. Route its events with `pickerEvent(event, PICKER_KEY)`.
39
39
  */
40
- export declare function dockedPicker(p: TspPickerProps, preview?: readonly NativeChild[]): NativeNode;
40
+ export declare function dockedPicker(p: TspProps<"picker">, preview?: readonly NativeChild[]): NativeNode;
41
41
  /** Keycap names for one key id (`"alt+enter"` → `["alt", "enter"]`, `"escape"` → `["esc"]`). */
42
42
  export declare function pickerKeys(key: KeyName | string): string[];
43
43
  /** The keycaps of a keybinding's primary key, empty when unbound. */
@@ -7,7 +7,11 @@ import type { NativeNode, NativeUiEvent } from "../native/node.js";
7
7
  */
8
8
  export declare class LoginDialogComponent extends OverlayPanel {
9
9
  #private;
10
- constructor(tui: TUI, providerId: string, onComplete: (success: boolean, message?: string) => void, openUrl: (url: string) => void);
10
+ constructor(tui: Pick<TUI, "requestRender">, providerId: string, onComplete: (success: boolean, message?: string) => void, openUrl: (url: string) => void);
11
+ /** Focus reaches the live field: it draws the caret (the hardware cursor when the terminal's is on). */
12
+ get focused(): boolean;
13
+ set focused(value: boolean);
14
+ setUseTerminalCursor(useTerminalCursor: boolean): void;
11
15
  get signal(): AbortSignal;
12
16
  /**
13
17
  * Called by the OAuth `onAuth` callback. Renders the full authorization URL
@@ -4,7 +4,7 @@ import type { Component } from "../tui.js";
4
4
  import type { SgrMouseEvent } from "../mouse.js";
5
5
  import { type ConfiguredThinkingLevel } from "../thinking.js";
6
6
  import { type ThemeColor } from "../theme/theme.js";
7
- import type { TspPickerColumn, TspPickerGroup, TspPickerItem, TspPickerMark } from "@oh-my-pi/pi-wire";
7
+ import type { TspPickerColumn, TspPickerGroup, TspPickerItem, TspPickerMark, TspPickerProps } from "@oh-my-pi/pi-wire";
8
8
  import type { NativeChild, NativeNode, NativeUiEvent } from "../native/node.js";
9
9
  /** Canonical display ordering of built-in model roles. */
10
10
  export type ModelRole = "default" | "smol" | "slow" | "vision" | "plan" | "commit" | "tiny" | "memory" | "task" | "advisor" | "widget" | "image" | "web" | "speech" | "dictation" | "judge";
@@ -232,6 +232,8 @@ export interface ModelPickerCatalogue {
232
232
  readonly itemsAdd?: readonly TspPickerItem[];
233
233
  readonly itemsDel?: readonly string[];
234
234
  }
235
+ /** The search, fact-column and row props every model `picker` sheet sends ({@link ModelBrowser.pickerRows}). */
236
+ export type ModelPickerRows = Pick<TspPickerProps, "query" | "cursor" | "columns" | "items" | "itemsAdd" | "itemsDel" | "order" | "hits" | "selected" | "current" | "total">;
235
237
  /** How {@link ModelBrowser.pickerOrder} heads its rows. */
236
238
  export interface ModelPickerGrouping {
237
239
  /** One group per provider after the Recent block (the unfiltered All models view). */
@@ -329,6 +331,13 @@ export declare class ModelBrowser implements Component {
329
331
  get baseCount(): number;
330
332
  /** The selected row's selector, null when nothing selectable is selected. */
331
333
  get pickerSelected(): string | null;
334
+ /**
335
+ * A model picker's search field, fact columns and rows: `catalogue` (from
336
+ * {@link pickerItems}) in `view` order (from {@link pickerOrder}), the
337
+ * selection, and `current` checked. Memoize hosts on its inputs plus
338
+ * {@link query}, {@link cursor} and {@link pickerSelected}.
339
+ */
340
+ pickerRows(catalogue: ModelPickerCatalogue, view: ModelPickerOrder, current: string | undefined): ModelPickerRows;
332
341
  /**
333
342
  * Picker rows for `catalogue`: the same object while the catalogue, roles
334
343
  * and row inputs are unchanged, so typing and scope hops never resend it.
@@ -1,12 +1,30 @@
1
1
  import type { CredentialsApi, KeysApi } from "@oh-my-pi/pi-ai";
2
2
  import { type SgrMouseEvent } from "../index.js";
3
3
  import { OverlayPanel } from "../chrome/overlay-box.js";
4
+ import type { TspText } from "@oh-my-pi/pi-wire";
4
5
  import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
5
6
  /** Credential presence and provenance needed by the provider picker. */
6
7
  export interface OAuthSelectorAuthSource {
7
8
  readonly credentials: Pick<CredentialsApi, "has">;
8
9
  readonly keys: Pick<KeysApi, "source">;
9
10
  }
11
+ /**
12
+ * How a host other than `/login` presents the native provider sheet (the
13
+ * setup wizard): its heading, `role` and size, a status line docked above the
14
+ * action bar, and the Esc action that leaves in place of Close (the action's
15
+ * `id` cancels like Esc).
16
+ */
17
+ export interface OAuthSelectorSheet {
18
+ readonly title: string;
19
+ readonly subtitle: TspText;
20
+ readonly role: string;
21
+ readonly size: "md" | "lg";
22
+ readonly status?: TspText;
23
+ readonly leave: {
24
+ readonly id: string;
25
+ readonly label: string;
26
+ };
27
+ }
10
28
  /**
11
29
  * Component that renders an OAuth provider selector.
12
30
  */
@@ -16,8 +34,13 @@ export declare class OAuthSelectorComponent extends OverlayPanel {
16
34
  disabledProviders?: readonly string[];
17
35
  validateAuth?: (providerId: string) => Promise<boolean>;
18
36
  requestRender?: () => void;
37
+ sheet?: OAuthSelectorSheet;
19
38
  });
20
39
  stopValidation(): void;
40
+ /** Replace the native sheet's presentation (a new outcome line, a relabelled leave action). */
41
+ setSheet(sheet: OAuthSelectorSheet): void;
42
+ /** Re-read credential state after a sign-in stored one, keeping the query and selection. */
43
+ refreshAuth(): void;
21
44
  /**
22
45
  * Fit the selector into `lines` rendered rows by shrinking the visible list
23
46
  * window (the window is centered on the selection, so the selected row is
@@ -74,7 +74,7 @@ export declare class RewindSelectorComponent implements Component {
74
74
  * of branch columns, the current path first. The bar is this component's
75
75
  * own node, docked under the page, so the filter field keeps the caret.
76
76
  */
77
- describeScreen(_cx: DescribeContext): NativeScreen;
77
+ describeScreen(cx: DescribeContext): NativeScreen;
78
78
  /** The bar docked under the page: position, key hints, Cancel and Rewind; the filter field while filtering. */
79
79
  describe(_cx: DescribeContext): NativeNode;
80
80
  /** The bar's buttons run their keys' paths; everything else belongs to the blocks. */
@@ -72,6 +72,7 @@ declare class SessionList<T extends SessionSelectorEntry> implements Component {
72
72
  onToggleScope?: () => void;
73
73
  onDeleteRequest?: (session: T) => void;
74
74
  onRenameRequest?: (session: T) => void;
75
+ onPinRequest?: (session: T, pinned: boolean) => void;
75
76
  /** Re-render hook for async list updates (fuzzy scan completion, history merge). */
76
77
  onRequestRender?: () => void;
77
78
  constructor(sessions: T[], showCwd?: boolean, historyMatcher?: SessionHistoryMatcher, getTerminalRows?: () => number, pinnedIds?: ReadonlySet<string>, currentSessionPath?: string | (() => string | undefined));
@@ -98,6 +99,12 @@ declare class SessionList<T extends SessionSelectorEntry> implements Component {
98
99
  requestDelete(): void;
99
100
  /** F2: ask the parent to rename the selected session. */
100
101
  requestRename(): void;
102
+ /** Pin keys: ask the parent to pin or unpin the selected session (default: flip it); no-op when already there. */
103
+ requestPin(pinned?: boolean): void;
104
+ /** Apply a persisted pin change; the list re-partitions and the cursor follows the session. */
105
+ setPinned(sessionId: string, pinned: boolean): void;
106
+ /** Whether the selected session is pinned (picks the pin action's direction). */
107
+ get selectedPinned(): boolean;
101
108
  /** Empty the search query (the empty state's "Clear search"). */
102
109
  clearSearch(): void;
103
110
  get selectedSession(): T | undefined;
@@ -131,6 +138,8 @@ export interface SessionSelectorOptions<T extends SessionSelectorEntry = Session
131
138
  * did not happen.
132
139
  */
133
140
  onRename?: (session: T, title: string) => Promise<string | null>;
141
+ /** Persist the selected session's pin state (pin keys / the picker's Pin action). */
142
+ onSetPinned?: (session: T, pinned: boolean) => Promise<void>;
134
143
  historyMatcher?: SessionHistoryMatcher;
135
144
  /** Loads sessions across all projects for the all-projects scope toggle (Tab). */
136
145
  loadAllSessions?: () => Promise<T[]>;
@@ -108,12 +108,19 @@ export interface ViewportClickRowTarget {
108
108
  * decides focusability and recency.
109
109
  */
110
110
  export declare function routeViewportClick(spans: readonly ViewportClickSpan[], index: number): string[];
111
+ /** An extension link label drawn on a mutable-viewport line: what a click or hint tag lands on. */
112
+ export interface ViewportLink {
113
+ readonly url: string;
114
+ /** Mutable-viewport line the label is drawn on. */
115
+ readonly row: number;
116
+ /** First cell of the label's part on that line. */
117
+ readonly start: number;
118
+ }
111
119
  /**
112
- * Reserved click-candidate id for the pinned HUD expander row. Checked before
113
- * any registry lookup: its `@…:…` charset cannot collide with generated agent
114
- * ids (word names, numeric and `-N` suffixes, dotted nesting).
120
+ * Called once when link-hint mode ends; `reason` is `"crowded"` when a row held more links than
121
+ * their tags could fit side by side, so no tags were drawn.
115
122
  */
116
- export declare const PINNED_HUD_TOGGLE_ID = "@omp:toggle-pinned-hud";
123
+ export type LinkHintsEnd = (reason?: "crowded") => void;
117
124
  /**
118
125
  * Canonical interactive composer, usable before session/settings exist and updatable in place.
119
126
  * It owns the terminal, welcome header, and editor; InteractiveMode later supplies authoritative
@@ -146,11 +153,35 @@ export declare class Composer implements TerminalFrameProvider, NativeSurfacePro
146
153
  * are never in the viewport). Callers intersect with the live registry.
147
154
  */
148
155
  viewportClickCandidates(index: number): string[];
156
+ /**
157
+ * The extension-owned link label drawn at cell `col` of a mutable-viewport line, or `undefined`.
158
+ * Only links whose scheme an extension registered match; see `extensionLinkLabels`.
159
+ */
160
+ viewportLinkAt(index: number, col: number): ViewportLink | undefined;
149
161
  /**
150
162
  * Point the hover band at a click-candidate id (or clear it). Takes effect
151
163
  * on the next frame; callers repaint only when the target actually changes.
152
164
  */
153
165
  setHoveredClickId(id: string | undefined): void;
166
+ /** How many extension link labels the last frame drew; a label wrapped across rows counts once. */
167
+ viewportLinkCount(): number;
168
+ /**
169
+ * Enter keyboard link-hint mode: the next frame draws a tag over each extension link label it
170
+ * shows. `onEnd` runs once when the mode ends: a pick, a cancel, a key no tag starts with, a
171
+ * repaint that no longer draws the tagged labels where they were, or (`"crowded"`) a row with
172
+ * too many links for their tags to fit side by side.
173
+ */
174
+ startLinkHints(onEnd: LinkHintsEnd): void;
175
+ /** Whether link-hint mode is on. */
176
+ get linkHintsActive(): boolean;
177
+ /**
178
+ * Type one letter of a tag. Returns the link whose whole tag is now typed, `true` while the
179
+ * letters still lead to several tags, and `false` when none starts with them. The mode ends on
180
+ * a pick or a miss.
181
+ */
182
+ typeLinkHint(letter: string): ViewportLink | boolean;
183
+ /** Leave link-hint mode without picking a link. */
184
+ cancelLinkHints(): void;
154
185
  /** Acknowledges one accepted header, replay, or transcript batch. */
155
186
  acknowledgeHistory(id: number): void;
156
187
  /** Render the semantic transcript tail while the terminal borrows its resize buffer. */
@@ -183,6 +214,12 @@ export declare class Composer implements TerminalFrameProvider, NativeSurfacePro
183
214
  setHeaderExtras(before: readonly Component[], after: readonly Component[]): void;
184
215
  /** Update the canonical editor reference after InteractiveMode remounts a custom editor. */
185
216
  setEditor(editor: CustomEditor): void;
217
+ /**
218
+ * End the startup input hold once the app's handlers are wired: the TSP
219
+ * terminal sends the typing it kept, and the keys the TUI held replay
220
+ * ({@link TUI.releaseHeldInput}). Idempotent.
221
+ */
222
+ releaseHeldInput(): void;
186
223
  /**
187
224
  * Mount the session-aware status component into the slot below the editor,
188
225
  * retiring the startup status line; the caller installs the real top-border
@@ -1,13 +1,16 @@
1
1
  /** Shared assistant transcript construction and model-authored link caching. */
2
2
  import type { AssistantMessage, Model } from "@oh-my-pi/pi-ai";
3
3
  import type { ImageBudget } from "../components/image.js";
4
- import type { AssistantThinkingRenderer } from "../chat/extension-types.js";
4
+ import type { AssistantTextRenderer, AssistantThinkingRenderer } from "../chat/extension-types.js";
5
5
  import { AssistantMessageComponent } from "../chat/assistant-message.js";
6
+ import { ReplyWriteComponent } from "../chat/reply-write.js";
6
7
  /** Session display capabilities supplied unchanged by the interactive host. */
7
8
  export interface AssistantMessageSession {
8
9
  readonly model?: Model;
9
10
  readonly extensionRunner?: {
10
11
  getAssistantThinkingRenderers(): readonly AssistantThinkingRenderer[];
12
+ /** Empty while the setting that enables them is off; hosts predating it may omit it. */
13
+ getAssistantTextRenderers?(): readonly AssistantTextRenderer[];
11
14
  };
12
15
  }
13
16
  /** Host state required to construct and refresh assistant transcript segments. */
@@ -42,6 +45,10 @@ export declare function assistantMessageLinkTargets(message: AssistantMessage, t
42
45
  /**
43
46
  * Construct an {@link AssistantMessageComponent} wired to the live context's
44
47
  * thinking/image settings. `message` is omitted for the streaming placeholder
45
- * component and supplied when rendering a persisted turn.
48
+ * component and supplied when rendering a persisted turn. `contentOffset` is
49
+ * the index in the full reply of the first block of a segment drawn after a
50
+ * tool call, so extension text renderers see the reply's own block indexes.
46
51
  */
47
- export declare function createAssistantMessageComponent(ctx: AssistantMessageHost, message?: AssistantMessage, linkTargets?: ReadonlyMap<string, string>): AssistantMessageComponent;
52
+ export declare function createAssistantMessageComponent(ctx: AssistantMessageHost, message?: AssistantMessage, linkTargets?: ReadonlyMap<string, string>, contentOffset?: number): AssistantMessageComponent;
53
+ /** Construct a {@link ReplyWriteComponent} (an `out://` write) drawn like the context's assistant prose. */
54
+ export declare function createReplyWriteComponent(ctx: AssistantMessageHost): ReplyWriteComponent;
@@ -51,10 +51,14 @@ export declare class WelcomeComponent implements Component {
51
51
  setVersion(version: string): void;
52
52
  render(termWidth: number): readonly string[];
53
53
  }
54
+ /**
55
+ * omp's native lockup (`omp.welcome.lockup`, keyed `lockup`): the terminal's
56
+ * builtin `omp` mark, which it draws on, beside the `omp` wordmark with
57
+ * `v<version>` under it. The welcome card and the setup splash show it.
58
+ */
59
+ export declare function lockupNode(version: string): NativeNode;
54
60
  /** Block-grid brand mark shared by the welcome and setup surfaces. */
55
61
  export declare const PI_LOGO: string[];
56
- /** The block-grid brand mark as accent lines; `shimmer` declares the terminal-clocked shine sweep. */
57
- export declare function logoNode(lines: readonly string[], shimmer: boolean): NativeNode;
58
62
  export interface ShineConfig {
59
63
  /** Overall opacity of the shine overlay, in [0, 1]. */
60
64
  strength: number;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Set the registered schemes (lowercase, without `:`). Bumps {@link extensionLinksVersion} on any
3
+ * change so cached markdown renders are redrawn.
4
+ */
5
+ export declare function setExtensionLinks(next: Iterable<string>): void;
6
+ /** Changes whenever the scheme set changes; part of the markdown render cache key. */
7
+ export declare function extensionLinksVersion(): number;
8
+ /**
9
+ * Whether activating a registered-scheme link (a click or a hint tag) reaches its extension: a
10
+ * scheme is registered and the terminal is plain.
11
+ */
12
+ export declare function extensionLinksRouted(): boolean;
13
+ /**
14
+ * Set by the interactive product: whether the user has a way to pick a link drawn now (a bound
15
+ * hint key, mouse clicks). `undefined` when nothing in this process can pick one.
16
+ */
17
+ export declare function setExtensionLinkPicking(provider: (() => boolean) | undefined): void;
18
+ /**
19
+ * Whether a registered-scheme link drawn now can be activated: links are routed and the product
20
+ * offers a way to pick them. Process-wide, so a UI-less extension runner (a subagent's, whose
21
+ * transcript the user may focus) answers like the interactive one.
22
+ */
23
+ export declare function extensionLinkClicksAvailable(): boolean;
24
+ /** The registered scheme `href` uses, or `undefined` for every other link. */
25
+ export declare function extensionLinkScheme(href: string): string | undefined;
26
+ /**
27
+ * Draw an extension link's label: dotted-underlined (plain underline where the terminal has no
28
+ * styled underlines, re-applied after any style reset inside it) and wrapped in the OSC 8 marker
29
+ * {@link extensionLinkLabels} reads back in a plain terminal; as given in Tern's native view. Never
30
+ * followed by a ` (url)` suffix. `key` tells apart links of one URL drawn near each other; it must
31
+ * not change between renders of the same text, or rows rendered twice stop matching.
32
+ */
33
+ export declare function formatExtensionLink(label: string, href: string, key: string): string;
34
+ /**
35
+ * Tags for `count` links in keyboard link-hint mode: single letters while they suffice, otherwise
36
+ * two letters each, so no tag is a prefix of another. At most the alphabet squared (676) are made;
37
+ * links past that stay untagged.
38
+ */
39
+ export declare function linkHintTags(count: number): string[];
40
+ /**
41
+ * `line` without omp's extension-link markers (the OSC 8 open and close around each label), for
42
+ * terminal output. Every other hyperlink is kept as is.
43
+ */
44
+ export declare function stripExtensionLinkMarkers(line: string): string;
45
+ /** One extension link label drawn on a rendered row (before {@link stripExtensionLinkMarkers}). */
46
+ export interface ExtensionLinkLabel {
47
+ readonly url: string;
48
+ /**
49
+ * The marker's params, unique to each drawn link and repeated on every row a wrapped label
50
+ * spans, so a row's parts of one label can be told from an adjacent label of the same URL.
51
+ */
52
+ readonly id: string;
53
+ /** First 0-based cell the label covers. */
54
+ readonly start: number;
55
+ /** Cell just past the label. */
56
+ readonly end: number;
57
+ /** Whether only blank cells follow the label on its row, so a wrapped label may go on below. */
58
+ readonly endsRow: boolean;
59
+ }
60
+ /**
61
+ * The extension link labels drawn on a rendered row, left to right. Only omp's own markers with a
62
+ * registered scheme match, so ordinary hyperlinks (even of a registered scheme) and rows drawn for
63
+ * a scheme that is no longer registered never do.
64
+ */
65
+ export declare function extensionLinkLabels(line: string): ExtensionLinkLabel[];
@@ -1,14 +1,31 @@
1
1
  import type { TspSpan } from "@oh-my-pi/pi-wire";
2
2
  import { type TerminalId } from "../terminal-capabilities.js";
3
+ export interface FileLinkConfig {
4
+ scheme?: string;
5
+ host?: string;
6
+ }
7
+ interface FileUriOptions {
8
+ line?: number;
9
+ col?: number;
10
+ /** Native image open actions need a local file URL rather than a desktop handler. */
11
+ local?: boolean;
12
+ }
13
+ /**
14
+ * Resolve the remote file-link configuration once at host startup. Passing an
15
+ * explicit object lets SDK hosts and tests configure links without changing the
16
+ * process environment; an empty object restores ordinary file links. An invalid
17
+ * scheme or host logs a warning and keeps ordinary links.
18
+ */
19
+ export declare function applyFileLinkSetting(config?: FileLinkConfig): void;
3
20
  /**
4
- * A `file:` URL for `filePath`, or `undefined` when Node cannot encode it.
21
+ * A file-link target for `filePath`, or `undefined` when Node cannot encode it.
5
22
  *
6
23
  * Node rejects a malformed UNC target (a UNC path escaped twice by its author,
7
24
  * e.g. `\\\wsl.localhost\…`) with `ERR_INVALID_ARG_VALUE: Empty UNC servername`.
8
25
  * A stored session keeps whatever a tool call recorded, so a transcript must
9
26
  * render such a path without a link rather than throw while it rebuilds.
10
27
  */
11
- export declare function tryFileUri(filePath: string): string | undefined;
28
+ export declare function tryFileUri(filePath: string, opts?: FileUriOptions): string | undefined;
12
29
  /**
13
30
  * Build the OSC 8 target for a file path on `terminalId`.
14
31
  *
@@ -23,7 +40,8 @@ export declare function tryFileUri(filePath: string): string | undefined;
23
40
  * The VS Code family instead navigates the documented
24
41
  * `vscode://file/<path>:<line>:<col>` form. Everywhere else the plain `file:`
25
42
  * URI is right, with the location left in the visible text — terminals that
26
- * parse a `path:line:col` suffix resolve that on their own.
43
+ * parse a `path:line:col` suffix resolve that on their own. A configured custom
44
+ * handler takes precedence and receives optional `line`/`col` query parameters.
27
45
  *
28
46
  * Returns `undefined` when `filePath` cannot be encoded — a malformed UNC
29
47
  * target on the `file:` branch, or a lone surrogate on the `vscode://` branch.
@@ -85,9 +103,8 @@ export declare function urlLinkSpan(target: string, displayText: string, s?: str
85
103
  /** Whether native link spans and nodes may carry an `href`: everything but an explicit `off` policy. */
86
104
  export declare function isNativeLinkEnabled(): boolean;
87
105
  /**
88
- * A native link span to a filesystem path as a plain `file://` URI (the
89
- * terminal opens it through the system; the location stays in the visible
90
- * text). Honours an explicit `off` policy.
106
+ * A native link span to a filesystem path using the configured file-link
107
+ * target. Honours an explicit `off` policy.
91
108
  */
92
109
  export declare function fileLinkSpan(filePath: string, displayText: string, s?: string): TspSpan;
93
110
  /**
@@ -101,9 +118,10 @@ export declare function fileLinkSpan(filePath: string, displayText: string, s?:
101
118
  *
102
119
  * @param filePath - Filesystem path
103
120
  * @param displayText - Text to render as the hyperlink anchor (may contain ANSI codes)
104
- * @param opts - Optional line/col position appended as `?line=N&col=M` query params
121
+ * @param opts - Optional line/col position (custom handlers use query params; VS Code uses a path suffix)
105
122
  */
106
123
  export declare function fileHyperlink(filePath: string, displayText: string, opts?: {
107
124
  line?: number;
108
125
  col?: number;
109
126
  }): string;
127
+ export {};
@@ -2,6 +2,7 @@
2
2
  * Public exports for shared TUI components.
3
3
  */
4
4
  export * from "./code-cell.js";
5
+ export * from "./extension-links.js";
5
6
  export * from "./file-list.js";
6
7
  export * from "./hyperlink.js";
7
8
  export * from "./output-block.js";
@@ -1,3 +1,3 @@
1
- import type { SetupScene } from "./types.js";
1
+ import { type SetupScene } from "./types.js";
2
2
  /** Setup step that assigns one available model to the persisted default role. */
3
3
  export declare const modelSetupScene: SetupScene;
@@ -1,9 +1,10 @@
1
1
  import type { NativeNode } from "../../native/node.js";
2
2
  export declare const SETUP_OUTRO_MS = 1200;
3
3
  /**
4
- * Native outro: the shimmering mark, the saved confirmation, and an
5
- * indeterminate progress bar standing in for the timed sweep. A click sends
6
- * the `continue` action.
4
+ * Native outro, centered: the builtin `omp` mark, "You're all set", the
5
+ * default model now in effect (`model`, its display name, when there is
6
+ * one), and an indeterminate progress bar standing in for the timed sweep.
7
+ * A click sends the `continue` action.
7
8
  */
8
- export declare function describeSetupOutro(): NativeNode;
9
+ export declare function describeSetupOutro(model: string | undefined): NativeNode;
9
10
  export declare function renderSetupOutro(width: number, height: number, elapsedMs: number): string[];
@@ -1,10 +1,15 @@
1
1
  import { type SgrMouseEvent } from "../../mouse.js";
2
- import type { NativeNode } from "../../native/node.js";
3
- import type { SetupScene, SetupSceneController, SetupSceneHost } from "./types.js";
2
+ import type { DescribeContext, NativeNode } from "../../native/node.js";
3
+ import { type SetupScene, type SetupSceneController, type SetupSceneHost } from "./types.js";
4
4
  /**
5
5
  * "Sign in" scene: lets the user authenticate one or more model providers via
6
6
  * OAuth. It never auto-advances the wizard — the user may sign in to several
7
- * providers and then continue with Esc.
7
+ * providers and then leave the step with Esc.
8
+ *
9
+ * Picking is the provider selector (natively a setup sheet: Skip/Continue on
10
+ * Esc, Sign in on Enter); signing in is the app's {@link LoginDialogComponent},
11
+ * driven like `/login` drives it: natively its own sheet over the setup page,
12
+ * in the cell grid drawn in the wizard body in place of the selector.
8
13
  */
9
14
  export declare class SignInScene implements SetupSceneController {
10
15
  #private;
@@ -14,15 +19,15 @@ export declare class SignInScene implements SetupSceneController {
14
19
  dispose(): void;
15
20
  invalidate(): void;
16
21
  handleInput(data: string): void;
17
- /** Forward mouse to the provider selector; pointer is inert during an active login or code prompt. */
22
+ /** Forward mouse to the provider selector; the login dialog takes keys only. */
18
23
  routeMouse(event: SgrMouseEvent, line: number, col: number): void;
19
24
  render(width: number, maxLines?: number): readonly string[];
20
25
  /**
21
- * Picking: intro, the provider selector (describes itself) and the last
22
- * outcome. Signing in: a spinner heading, the login link (with the full
23
- * URL once, char-wrapped), any code prompt and the flow's progress lines.
26
+ * Signing in: the login dialog (its own sheet). Picking: the provider
27
+ * selector, which presents the setup sheet where the terminal draws
28
+ * pickers; elsewhere it is an inline card under the lead and the outcome.
24
29
  */
25
- describe(): NativeNode;
30
+ describe(cx: DescribeContext): NativeNode;
26
31
  }
27
32
  /** Onboarding scene for provider sign-in. */
28
33
  export declare const providersSetupScene: SetupScene;
@@ -11,9 +11,9 @@ export declare function renderStarfield(width: number, height: number, frame: nu
11
11
  */
12
12
  export declare function renderSetupSplash(width: number, height: number, elapsedMs: number): string[];
13
13
  /**
14
- * Native splash: the 2x brand mark with a terminal-clocked shimmer, the
15
- * wordmark, and the skip hint pinned to the bottom. The water and starfield
16
- * are cell paintings with no semantic counterpart. A click on the splash
17
- * sends the `skip` action.
14
+ * Native splash: omp's lockup as the welcome draws it (the builtin mark
15
+ * drawing on beside the wordmark and version), centered, and a quiet Enter
16
+ * hint pinned to the bottom. The water and starfield are cell paintings with
17
+ * no semantic counterpart. A click anywhere sends `skip`.
18
18
  */
19
19
  export declare function describeSetupSplash(): NativeNode;
@@ -42,7 +42,6 @@ export interface SetupHost extends SetupUiHost {
42
42
  saveColorBlindMode(enabled: boolean): void;
43
43
  saveTheme(mode: "dark" | "light", name: string): void;
44
44
  captureBrowserSession(request: OAuthBrowserSessionRequest, signal?: AbortSignal): Promise<string>;
45
- copyToClipboard(text: string): Promise<void>;
46
45
  openInBrowser(url: string): void;
47
46
  markComplete(version: number): Promise<void>;
48
47
  playWelcomeIntro(): void;
@@ -80,11 +79,27 @@ export interface SetupSceneController extends Component {
80
79
  */
81
80
  routeMouse?(event: SgrMouseEvent, line: number, col: number): void;
82
81
  }
82
+ /**
83
+ * Role of the sheet (`picker` or `overlay`) an interactive scene presents in a
84
+ * TSP terminal. The terminal's setup stylesheet seats it under the wizard's
85
+ * brand and stepper instead of floating it over a dimmed page.
86
+ */
87
+ export declare const SETUP_SHEET_ROLE = "omp.setup.sheet";
88
+ /** Surface role of the setup page (wizard and startup splash) in a TSP terminal. */
89
+ export declare const SETUP_SURFACE_ROLE = "omp.app.setup";
83
90
  /** Versioned onboarding scene definition. */
84
91
  export interface SetupScene {
85
92
  id: string;
86
93
  title: string;
94
+ /** Short label for the wizard's stepper (`Sign in`, `Model`). */
95
+ step: string;
87
96
  minVersion: number;
97
+ /**
98
+ * Configures something only the cell-grid renderer draws (glyphs, composer
99
+ * shape, theme). A TSP terminal draws those itself, so the wizard skips the
100
+ * scene while a native surface is live.
101
+ */
102
+ ansiOnly?: boolean;
88
103
  shouldRun?(ctx: SetupHost): boolean | Promise<boolean>;
89
104
  mount(host: SetupSceneHost): SetupSceneController;
90
105
  }
@@ -1,4 +1,4 @@
1
- import type { SetupUiHost } from "./scenes/types.js";
1
+ import { type SetupUiHost } from "./scenes/types.js";
2
2
  /** Timing controls for the standalone startup animation. */
3
3
  export interface RunStartupSplashOptions {
4
4
  readonly durationMs?: number;
@@ -1,7 +1,9 @@
1
1
  import { type Component, type OverlayFocusOwner } from "../tui.js";
2
- import type { NativeNode, NativeUiEvent } from "../native/node.js";
2
+ import type { DescribeContext, NativeNode, NativeScreen, NativeUiEvent } from "../native/node.js";
3
3
  import type { SetupHost } from "./scenes/types.js";
4
- import type { SetupScene } from "./scenes/types.js";
4
+ import { type SetupScene } from "./scenes/types.js";
5
+ /** Whether `scene` is asked under the current renderer: a TSP surface draws `ansiOnly` settings itself. */
6
+ export declare function setupSceneApplies(scene: SetupScene): boolean;
5
7
  /** Fullscreen onboarding presentation with scene focus and mouse routing. */
6
8
  export declare class SetupWizardComponent implements Component, OverlayFocusOwner {
7
9
  #private;
@@ -14,12 +16,14 @@ export declare class SetupWizardComponent implements Component, OverlayFocusOwne
14
16
  ownsOverlayFocusTarget(component: Component): boolean;
15
17
  handleInput(data: string): void;
16
18
  render(width: number): readonly string[];
19
+ /** The wizard is a page of its own: a screen surface styled by {@link SETUP_SURFACE_ROLE}. */
20
+ describeScreen(_cx: DescribeContext): NativeScreen;
17
21
  /**
18
- * Fullscreen description: splash, the active scene inside the wizard
19
- * frame (brand header, step counter, title, footer hints), or the outro.
20
- * The splash→scene dissolve is a row effect with no native counterpart, so
21
- * a transition describes as the scene.
22
+ * Fullscreen description: splash, the active scene under the setup
23
+ * header (brand, stepper, Exit setup), or the outro. The splash→scene
24
+ * dissolve is a row effect with no native counterpart, so a transition
25
+ * describes as the scene.
22
26
  */
23
- describe(): NativeNode;
27
+ describe(cx: DescribeContext): NativeNode;
24
28
  handleNativeEvent(event: NativeUiEvent): void;
25
29
  }
@@ -21,5 +21,9 @@ export interface RunSetupWizardOptions {
21
21
  markComplete?: boolean;
22
22
  playWelcomeIntro?: boolean;
23
23
  }
24
- /** Own the fullscreen setup overlay until its scenes and outro finish. */
24
+ /**
25
+ * Own the fullscreen setup overlay until its scenes and outro finish. When
26
+ * none of `scenes` applies to the current renderer (a TSP surface skips
27
+ * `ansiOnly` ones) nothing is shown, but completion is still persisted.
28
+ */
25
29
  export declare function runSetupWizard(ctx: SetupHost, scenes?: readonly SetupScene[], options?: RunSetupWizardOptions): Promise<void>;
@@ -111,7 +111,7 @@ export declare class StatusLineComponent<TSession extends StatusLineSession = St
111
111
  setRecording(recording: boolean): void;
112
112
  /** Set the callback that presents detected Codex reset celebrations, or clear it with `undefined`. */
113
113
  setCodexResetFireworksHandler(handler: ((event: CodexResetFireworksEvent) => void) | undefined): void;
114
- /** Set the callback that presents the first pool-wide saved-reset expiry warning, or clear it with `undefined`. */
114
+ /** Set the callback that presents pool-wide saved-reset expiry warnings, or clear it with `undefined`. */
115
115
  setResetExpiryNoticeHandler(handler: ((notice: string) => void) | undefined): void;
116
116
  setHookStatus(key: string, text: string | undefined): void;
117
117
  watchBranch(onBranchChange: () => void): void;