@oh-my-pi/pi-tui 18.14.2 → 18.16.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 +64 -50
- package/README.md +1 -1
- package/dist/types/app-keybindings.d.ts +5 -0
- package/dist/types/apps/session-picker.d.ts +5 -3
- package/dist/types/chat/bash-execution.d.ts +4 -1
- package/dist/types/chat/eval-execution.d.ts +2 -0
- package/dist/types/chat/execution-shared.d.ts +14 -8
- package/dist/types/chat/transcript-render-helpers.d.ts +8 -0
- package/dist/types/chrome/dynamic-border.d.ts +6 -0
- package/dist/types/chrome/transcript-status.d.ts +2 -2
- package/dist/types/components/editor.d.ts +15 -6
- package/dist/types/components/loader.d.ts +2 -0
- package/dist/types/keybinding-matchers.d.ts +7 -0
- package/dist/types/overlays/btw-history-panel.d.ts +13 -0
- package/dist/types/overlays/btw-history.d.ts +24 -0
- package/dist/types/overlays/btw-inject.d.ts +22 -0
- package/dist/types/overlays/btw-panel.d.ts +7 -0
- package/dist/types/overlays/hook-editor.d.ts +2 -0
- package/dist/types/overlays/jobs-panel.d.ts +4 -0
- package/dist/types/overlays/session-selector.d.ts +24 -3
- package/dist/types/render/render-utils.d.ts +21 -1
- package/dist/types/status-line/startup.d.ts +0 -15
- package/dist/types/terminal-capabilities.d.ts +1 -1
- package/dist/types/theme/symbols.d.ts +3 -1
- package/dist/types/theme/theme-class.d.ts +1 -0
- package/dist/types/tools/grouped-file-output.d.ts +76 -8
- package/dist/types/tools/hashline-format.d.ts +5 -0
- package/dist/types/tools/native-view.d.ts +2 -0
- package/dist/types/tools/output-meta.d.ts +27 -0
- package/dist/types/tools/read.d.ts +10 -0
- package/dist/types/tools/wait.d.ts +2 -0
- package/dist/types/utils.d.ts +4 -0
- package/package.json +9 -9
- package/src/app-keybindings.ts +5 -0
- package/src/apps/session-picker.ts +7 -3
- package/src/chat/bash-execution.ts +20 -9
- package/src/chat/chat-transcript-builder.ts +5 -2
- package/src/chat/eval-execution.ts +14 -7
- package/src/chat/execution-shared.ts +39 -18
- package/src/chat/read-tool-group.ts +56 -36
- package/src/chat/transcript-render-helpers.ts +52 -6
- package/src/chrome/dynamic-border.ts +28 -2
- package/src/chrome/transcript-status.ts +5 -3
- package/src/components/editor.ts +123 -24
- package/src/components/key-value-list.ts +9 -9
- package/src/components/loader.ts +7 -0
- package/src/components/section.ts +1 -9
- package/src/components/table.ts +1 -9
- package/src/keybinding-matchers.ts +13 -0
- package/src/overlays/btw-history-panel.ts +98 -14
- package/src/overlays/btw-history.ts +65 -0
- package/src/overlays/btw-inject.ts +91 -0
- package/src/overlays/btw-panel.ts +53 -12
- package/src/overlays/hook-editor.ts +6 -0
- package/src/overlays/jobs-panel.ts +45 -19
- package/src/overlays/model-browser.ts +65 -8
- package/src/overlays/session-selector.ts +131 -26
- package/src/overlays/usage-dashboard.ts +2 -2
- package/src/render/code-cell.ts +1 -1
- package/src/render/file-list.ts +4 -7
- package/src/render/render-utils.ts +36 -6
- package/src/setup/scenes/glyph.ts +1 -1
- package/src/status-line/startup.ts +36 -70
- package/src/terminal-capabilities.ts +5 -0
- package/src/theme/symbols.ts +16 -9
- package/src/theme/theme-class.ts +3 -0
- package/src/tmux.ts +1 -0
- package/src/tools/agent-tree.ts +13 -11
- package/src/tools/ask.ts +13 -6
- package/src/tools/ast-edit.ts +48 -93
- package/src/tools/ast-grep.ts +22 -66
- package/src/tools/bash.ts +7 -0
- package/src/tools/default-renderer.ts +1 -1
- package/src/tools/edit.ts +50 -43
- package/src/tools/fetch.ts +2 -1
- package/src/tools/find.ts +6 -3
- package/src/tools/github.ts +14 -46
- package/src/tools/glob.ts +2 -1
- package/src/tools/grep.ts +43 -287
- package/src/tools/grouped-file-output.ts +250 -64
- package/src/tools/hashline-format.ts +5 -0
- package/src/tools/json-tree.ts +1 -5
- package/src/tools/lsp.ts +53 -25
- package/src/tools/native-view.ts +11 -5
- package/src/tools/output-meta.ts +68 -4
- package/src/tools/proc-render.ts +3 -3
- package/src/tools/read.ts +14 -0
- package/src/tools/task.ts +34 -77
- package/src/tools/vibe.ts +4 -4
- package/src/tools/wait.ts +8 -5
- package/src/tools/write.ts +17 -27
- package/src/tools/yield.ts +1 -1
- package/src/utils.ts +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.16.0] - 2026-11-02
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- `buildExecutionFrame` sets its loader into the new `bottomBorder` itself, so callers no longer add it as a row and must dispose it; `buildStatusFooter` no longer takes `status` or `exitCode`, and `executionStatusLabel` returns a settled run's `exit N` / `cancelled` marker for that border ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
10
|
+
- `SessionSelectorOptions.loadAllSessions` and `SessionPickerHost.loadAllSessions` resolve to a `SessionListing`, and `allSessions` takes one, so the all-projects scope can show preliminary rows before its complete listing
|
|
11
|
+
- `Editor.prediction` is replaced by `Editor.predictions`, which returns every prediction for the next prompt, most likely first, and `Editor.onPredictionAccepted` receives the inserted prediction's index in that list ([#17796](https://github.com/can1357/oh-my-pi/pull/17796) by [@wolfiesch](https://github.com/wolfiesch))
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `SessionSelectorOptions.completeSessions` (and `SessionPickerOptions.completeSessions`) replaces the picker's preliminary rows with the complete listing once it settles, keeping the query, the selected session, and deletes/renames made meanwhile
|
|
16
|
+
- `/btw` answers can show a steering prompt as a block behind a pink rail (a toned card in Tern) that `Alt+I` (`app.btw.inject`, remappable) sends to the main session; once sent it turns green with `➤` on each line, without moving ([#17618](https://github.com/can1357/oh-my-pi/pull/17618) by [@apullin](https://github.com/apullin))
|
|
17
|
+
- Added `singleLine` and `finiteWidth` to `utils` for row-confined text and cell widths
|
|
18
|
+
- `Loader.inlineText()` returns the current spinner frame and message as one styled line, and `DynamicBorder.setLabel()` sets a label (or a function re-read every render) into the rule ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- The ASCII symbol preset's status glyphs are all three columns wide: success is `[+]`, error `[-]`, aborted `[#]` and pending `[ ]` (alongside `[~]` running, `[!]` warning and `[i]` info), and status spinners animate as `[|] [/] [-] [\]` ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
23
|
+
- Built-in renderers no longer use `status.done`, `theme.status.done` or the `done` value of `ToolUIStatus`; they remain as aliases of `status.success` / `success` (an explicit `symbols.overrides["status.done"]` still applies to `theme.status.done`) ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
24
|
+
- Every finished state shows the success glyph (`✔`, ASCII `[+]`). Task rows, verdicts and headers, background-job, launch and supervised-process rows, Eval cells, Vibe, Wait and process job rows, Yield and the generic tool card showed a separate `•` done dot, and a finished Read showed `●` (ASCII `[x]`). Live Task agent rows show the pending or running glyph, and a Task whose merge failed shows the warning glyph ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
25
|
+
- Edit and Write animate their streaming spinner in the card header, as Eval does, and show their `preview` / `streaming` label in the card's bottom border instead of on a row below the content; `streaming` ends once the content has fully arrived ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
26
|
+
- `!` shell and `$` Python runs show their spinner, and then `exit N` or `cancelled`, in the frame's bottom border instead of on rows of their own; the spinner is the status spinner tool headers use ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
27
|
+
- GitHub run-watch job rows use the shared status glyphs: a running job shows the running glyph instead of a warning-colored dot, a queued job the pending glyph instead of a hollow circle (a job in a state omp does not recognize keeps the circle), and a passed job's glyph is green like other success glyphs. Ask's multi-line custom answer lines up under its first line in every symbol preset ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- An LSP result other than diagnostics, such as a raw `request` response, that contains the error glyph (`✘`, ASCII `[-]`) is shown as a response instead of as diagnostics reading "No issues" with the rest of its lines dropped ([#17732](https://github.com/can1357/oh-my-pi/pull/17732) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
32
|
+
- `Editor.onPredictionAccepted` and `Editor.onPredictionShown` report when Tab or Right inserts the rest of the composer prediction and when a frame paints it (at least one cell in the terminal, or the ghost on a native editor node) ([#17739](https://github.com/can1357/oh-my-pi/pull/17739) by [@wolfiesch](https://github.com/wolfiesch))
|
|
33
|
+
- Added `OutputMeta.minimized` (bash minimizer filter, raw and minimized byte counts, raw-output artifact), shown as a `Minimized` fact on bash result cards ([#16586](https://github.com/can1357/oh-my-pi/pull/16586) by [@will-bogusz](https://github.com/will-bogusz))
|
|
34
|
+
- Added `isColumnTruncationNotice` and `hasColumnTruncationClause` to `tools/output-meta`, matching the `[Some lines truncated to …]` clause that `formatOutputNotice` emits alone or inside a longer notice, and `LimitsMeta.columnTruncated.rawByteCap`, which makes that notice name the byte cap a `:raw` read of the first cut line stops at ([#16595](https://github.com/can1357/oh-my-pi/pull/16595) by [@will-bogusz](https://github.com/will-bogusz))
|
|
35
|
+
- Fixed the model browser showing Factory Droid's undiscounted credit rate during a Factory promotion (2× instead of 1.6× for GPT-5.6 Sol); rows now show the rate in force and the model details show the next rate and its date ([#16309](https://github.com/can1357/oh-my-pi/pull/16309) by [@will-bogusz](https://github.com/will-bogusz))
|
|
36
|
+
- With two or more `Editor.predictions`, the ghost text follows the first one the draft is a prefix of; a typed draft that equals a shorter one keeps the ghost of a longer one. Once the buffer equals one of them with no ghost (always right after Tab, Right, or the list inserts one), a dim `⇥ N more` hint appears; press Tab to list them all, then Enter, Tab or Right to swap the whole line (never submitting) or Esc to keep it ([#17796](https://github.com/can1357/oh-my-pi/pull/17796) by [@wolfiesch](https://github.com/wolfiesch))
|
|
37
|
+
- F2 now opens the rename dialog in the resume picker in Ghostty, kitty and other terminals using the kitty keyboard protocol; F1 and F4 shortcuts work there too ([#17812](https://github.com/can1357/oh-my-pi/issues/17812)).
|
|
38
|
+
- Added `Component.nativeTrailers()`, which lets a transcript block add native blocks of its own directly after it. Trailing blocks stay visible while the block is collapsed.
|
|
39
|
+
|
|
40
|
+
## [18.15.0] - 2026-11-01
|
|
41
|
+
|
|
42
|
+
### Breaking Changes
|
|
43
|
+
|
|
44
|
+
- `GroupedLineContext.isUrl` is replaced by `url`, the internal URL a header names or a body row belongs to ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- Added `FILE_NAME_COLOR`, `formatStyledPath` and `pathNameStart` to `render/render-utils` for paths in tool bodies and Tern file rows; `createGroupedRowStyler`, `groupedLinkTargets`, `fitGroupsToBudget`, `groupsByFile` and `isMatchRow` to `tools/grouped-file-output`; `splitReadQuery` to `tools/read`; and `HASHLINE_TAG_SUFFIX_RE` to `tools/hashline-format`. `classifyGroupedLines` reports each file header's full `displayPath` and `suffix`, and a `TranscriptStatusPart` without `color` keeps its already-styled text ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
49
|
+
- `JobsPanelJob.caption`: the jobs sheet's detail pane shows it, muted, between the job's purpose and its command (`omp.jobs.caption`) ([#17649](https://github.com/can1357/oh-my-pi/pull/17649) by [@wolfiesch](https://github.com/wolfiesch))
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- The Background jobs sheet names each job by what it is for when the model said so, shows that above the full command in the detail pane, and no longer repeats the command in an empty widget box for jobs that print nothing ([#17649](https://github.com/can1357/oh-my-pi/pull/17649) by [@wolfiesch](https://github.com/wolfiesch))
|
|
54
|
+
- File paths in tool output share one style: a dim directory and the file name in the custom-message label color (bronze in titanium), with line locations and selectors (`:1-175`, `:42:14`, `?q=`) muted. This covers Grep, AST Grep, AST Edit, Glob, Find, LSP, diagnostics, grouped Reads and file mentions; Glob's folder icon is muted like the file-type icons, and paths in tool headers keep their color ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
55
|
+
- Grep, AST Grep and AST Edit results label each file with its full path instead of the model-facing `# dir/` and `## file#tag` headers, and each file gets its own tree branch. Their collapsed previews fit the same row budget the same way, cutting the last file short rather than overflowing, and end with `… N more matches` (`… N more files` for AST Edit) ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
56
|
+
- AST Grep match rows link to their line, as Grep's do ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
57
|
+
- LSP diagnostics carry their severity color on the `[error]`/`[warning]` tag instead of the location, and collapsed diagnostic rows now show that tag ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
- Rex sessions now render Kitty graphics without forcing the protocol, including when only `TERM=xterm-rex` identifies the client ([#17651](https://github.com/can1357/oh-my-pi/issues/17651)).
|
|
62
|
+
- Fixed collapsed AST Grep showing no matches when its first file or folder was taller than the preview, and its `… N more` row counting hidden folders instead of hidden matches ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
63
|
+
- Fixed collapsed AST Edit overflowing its preview when the first file's diff was long ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
64
|
+
- Fixed search and diagnostic file paths in Tern dropping the leading `/` of absolute paths and a folder's own `(…)` ending, and AST Edit diffs in Tern losing highlighting to the file's `#tag`; a file name ending in lowercase or other-length `#…` text keeps it ([#17608](https://github.com/can1357/oh-my-pi/pull/17608) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
65
|
+
- Fixed a read of a URL drawing as dead text in the folded read row: its target is not a file path, so no link was built for it, and clicking the URL did nothing. The row (and each row of a grouped read) now links to the URL itself, gaining an `https://` scheme for a bare `www.` host ([#17598](https://github.com/can1357/oh-my-pi/pull/17598) by [@iacore](https://github.com/iacore))
|
|
66
|
+
- Fixed replayed transcripts ignoring a registered `async-result` message renderer, so a replayed conversation rendered differently from the live one ([#17372](https://github.com/can1357/oh-my-pi/pull/17372) by [@AlexBrd999](https://github.com/AlexBrd999), from [#14484](https://github.com/can1357/oh-my-pi/pull/14484) by [@F0Rextasy](https://github.com/F0Rextasy); [#14131](https://github.com/can1357/oh-my-pi/issues/14131))
|
|
67
|
+
|
|
5
68
|
## [18.14.2] - 2026-10-31
|
|
6
69
|
|
|
7
70
|
### Added
|
|
@@ -2461,53 +2524,4 @@
|
|
|
2461
2524
|
- Fixed hiding overlays during ED3-risk foreground streaming on unknown-viewport terminals leaving the overlay's transient rows in native scrollback. Overlay visibility reductions now bypass the streaming deferral path and rebuild once, so hidden dialog/notification sentinels are scrubbed immediately.
|
|
2462
2525
|
- Fixed ED3-risk / unknown-viewport terminals (including WSL fronted by Windows Terminal) keeping the foreground-stream eager-rebuild mode active after the stream had already settled. A later scrolled content shrink or resize-with-append could then bypass the anti-yank deferral and repaint from stale geometry, jumping the viewport or replaying the wrong rows. The eager opt-in now drops immediately when no teardown render is pending, and the one-frame post-checkpoint suffix-suppression path no longer overrides geometry reflow handling.
|
|
2463
2526
|
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
### Changed
|
|
2467
|
-
|
|
2468
|
-
- Changed foreground-stream rendering on ED3-risk terminals (Ghostty/kitty/Alacritty/VTE/iTerm2 on POSIX) to defer native-scrollback commits for unpinned transient frames: while a turn streams, generic frames repaint only the viewport and suppress `\r\n` scroll growth, so transient output (spinner ticks, partial lines, status rows) never pollutes terminal history. Components that report a `NativeScrollbackLiveRegion` still commit newly sealed prefix rows while keeping the active suffix dirty for checkpoint replay. Native scrollback is reconciled in a single ED3 (`CSI 3 J`) + re-emit at the next checkpoint (prompt submit) or on an explicit user-input/IME opt-in; an erase is never emitted mid-stream under a possibly-scrolled reader. Non-ED3-risk terminals keep their eager live rebuild. ([#1895](https://github.com/can1357/oh-my-pi/pull/1895))
|
|
2469
|
-
|
|
2470
|
-
### Fixed
|
|
2471
|
-
|
|
2472
|
-
- Fixed ED3-risk foreground streaming dropping sealed transcript rows above the live block until the next prompt-submit checkpoint, which made scrollback beyond the viewport appear duplicated or out of order. The renderer restores native-scrollback live-region pinning so newly sealed rows are appended once while active live rows remain deferred.
|
|
2473
|
-
- Fixed inline images (added in 15.9) rendering as a wall of empty PUA box glyphs and producing laggy scrolling on Kitty-protocol terminals that do not implement Unicode placeholders — most notably WezTerm (per upstream wezterm/wezterm#986, placeholder support is still unchecked) and the tmux/screen `getFallbackImageProtocol` path that forces Kitty mode even on non-supporting outer terminals (Terminal.app, etc.). `unicodePlaceholders` now defaults on only for `kitty` and `ghostty`; everything else falls back to direct `a=p,i=…,p=…` placement, which those paths already render correctly. `PI_NO_KITTY_PLACEHOLDERS=1` is still honored as a hard opt-out, and a new `PI_KITTY_PLACEHOLDERS=1` opts in on otherwise-unsupported terminals (e.g. a wezterm nightly that has merged placeholder support) ([#1877](https://github.com/can1357/oh-my-pi/issues/1877)).
|
|
2474
|
-
|
|
2475
|
-
## [15.9.1] - 2026-06-04
|
|
2476
|
-
|
|
2477
|
-
### Fixed
|
|
2478
|
-
|
|
2479
|
-
- Fixed the OSC 11 appearance poll re-querying every 2s forever on terminals that support Mode 2031 but never change theme, whose repeated OSC 11/DA1 writes cleared the user's active text selection (breaking copy every 2 seconds). The poll now stops as soon as DECRQM confirms Mode 2031 support, since push notifications make polling redundant.
|
|
2480
|
-
|
|
2481
|
-
## [15.9.0] - 2026-06-04
|
|
2482
|
-
|
|
2483
|
-
### Added
|
|
2484
|
-
|
|
2485
|
-
- Added Kitty `CSI 22 J` screen-to-scrollback clears for non-destructive full paints, while keeping ED3 for destructive history/session rebuilds.
|
|
2486
|
-
- Added Kitty OSC 99 rich notification formatting and startup capability probing.
|
|
2487
|
-
- Added Kitty OSC 66 text-sized Markdown H1 headings (2x scale) plus native text-width support for OSC 66 spans. Off by default and gated to Kitty (the only terminal implementing OSC 66) via the `TERMINAL.textSizing` capability; hosts enable it through `setTextSizing`.
|
|
2488
|
-
- Added Kitty Unicode placeholder image rendering (`U=1` + U+10EEEE with explicit row/column diacritics): inline images are drawn as real text cells that carry the image id in their foreground color, so they survive horizontal slicing, reflow, and overlapping draws instead of relying on cursor-positioned `a=p` placements. Enabled by default on Kitty-family terminals; opt out with `PI_NO_KITTY_PLACEHOLDERS=1`, and falls back to direct placement when a grid exceeds the diacritic table's addressable range.
|
|
2489
|
-
- Added Kitty temp-file image transmission (`t=t`): on local sessions, decoded PNG bytes are written to a `tty-graphics-protocol` temp file and the path is sent instead of in-band base64, gated behind a startup `a=q,t=t` support probe. Controlled by `PI_KITTY_IMAGE_TRANSMISSION=direct|temp-file|auto`; disabled over SSH unless explicitly forced.
|
|
2490
|
-
- Added DECRQM capability detection for DEC private modes 2026 (synchronized output) and 2048 (in-band resize). Synchronized-output paint wrappers are dropped when the terminal reports 2026 unsupported (preserving the `PI_NO_SYNC_OUTPUT` override), and DEC 2048 in-band resize is enabled when supported — reported geometry and cell pixel size are updated from `CSI 48 ; rows ; cols ; yPx ; xPx t` reports, with SIGWINCH and `CSI 16 t` kept as fallbacks.
|
|
2491
|
-
- Added an injectable render scheduler for TUI tests, allowing deterministic render drains without patching global clocks or event-loop timing.
|
|
2492
|
-
- Added `ImageBudget`, an inline-image cap that keeps only the most recent N images as live terminal graphics and demotes older ones to their text fallback. Once a new image pushes the count past the cap, the renderer hides the oldest via a full redraw plus an explicit Kitty graphics purge (`a=d,d=I`) — text-clear escapes (`CSI 2 J`/`CSI 3 J`) do not remove Kitty images. Configure the cap via `TUI#setMaxInlineImages` (`0` disables it).
|
|
2493
|
-
- Changed Kitty inline images to a transmit-once + placement scheme: the base64 data is sent a single time (`a=t`) keyed by a stable image id, then every repaint emits only the tiny placement (`a=p,i=…,p=…`). Repaints — including full redraws — no longer re-send image data or stack duplicate placements, and the diff/line buffers and render caches hold short placement strings instead of multi-KB base64. The `ImageBudget` doubles as the transmit store (it tracks which ids are loaded and re-transmits after a purge frees the data). iTerm2/Sixel, which have no addressable image store, keep sending inline data as before.
|
|
2494
|
-
- Added a renderer-level DECCARA rectangular-SGR optimizer that paints solid background panels/rows (Box/Text/Markdown fills, status bars, any full-width `theme.bg` row) as a single coalesced rectangle escape (`CSI 2*x` / `CSI Pt;Pl;Pb;Pr;<sgr>$r` / `CSI *x`) instead of emitting a full-width run of background-styled spaces on every visible row. It operates at emit time on the final ANSI strings — components are unchanged — and strips only trailing padding it can prove sits under a single non-default background span, coalescing vertically adjacent identical fills into one rectangle and falling back to the original bytes whenever the rectangle would not save bytes. Enabled only on Kitty, which implements the SGR-background extension (`docs/deccara.rst`); **Ghostty is intentionally excluded** because its `CSI $r` is unimplemented (ghostty-org/ghostty#632) and would drop the background entirely. Scrollback-bound rows and the append/scroll paths always keep the padded representation so native history preserves colored cells, and the `PI_NO_DECCARA` kill switch (plus tmux/screen/zellij detection) forces the fallback.
|
|
2495
|
-
- Added `CMUX_SURFACE_ID` environment variable support to `getTerminalId()`, so cmux terminal surfaces get a stable identifier alongside kitty, tmux, macOS Terminal.app, and Windows Terminal — enabling per-surface session breadcrumbs for `omp -c` in cmux.
|
|
2496
|
-
|
|
2497
|
-
### Changed
|
|
2498
|
-
|
|
2499
|
-
- Changed TUI tests to use Ghostty's VT engine (`ghostty-web`) instead of `@xterm/headless`.
|
|
2500
|
-
- Changed the default inline-image live graphics budget from 3 to 8 images.
|
|
2501
|
-
|
|
2502
|
-
### Fixed
|
|
2503
|
-
|
|
2504
|
-
- Fixed the DECCARA background-fill optimizer rejecting or repainting the wrong cells when a trailing fill crossed from default-background spaces into colored spaces.
|
|
2505
|
-
- Fixed DEC private-mode reports with DECRPM status 3/4 being treated as unsupported, so permanent 2026/2048 reports stay recognized.
|
|
2506
|
-
- Fixed OSC 66 text-sizing width and slicing edge cases, including ZWJ emoji payloads and partial slices through scaled spans.
|
|
2507
|
-
- Fixed focused `Input` components following `TUI#setShowHardwareCursor`, so single-line prompts render either the terminal cursor or software cursor consistently with the editor.
|
|
2508
|
-
- Fixed the DECCARA background-fill optimizer painting fills on the wrong rows ("split into unaligned halves") in the differential repaint path. When a diff grew the transcript past the viewport, writing the rewritten rows scrolled the terminal, but the absolute DECCARA rectangle coordinates were derived from the pre-scroll viewport top, so every fill landed `scrollAmount` rows too low while the relatively-positioned text settled correctly; rows scrolled into history were also shortened, dropping their background padding from native scrollback. Rectangles now target the post-scroll rows and only rows remaining in the final viewport are optimized.
|
|
2509
|
-
- Fixed native scrollback desynchronization after terminal width or height changes reflowed overflowing content while the viewport was not at the bottom
|
|
2510
|
-
- Fixed a notification chip (or any injected block) rendering on top of an actively streaming tool render on ED3-risk terminals (Ghostty/kitty/Alacritty/iTerm2). While a foreground tool streams, its header's elapsed-time counter ticks every frame; once output scrolls the header above the viewport top, each tick is an offscreen edit that — because the eager scrollback-rebuild opt-in is gated off on these terminals — repaints the viewport in place and advances the rendered line count without committing the new overflow to native history. `#scrollbackHighWater` then lagged the logical viewport top, so a later content shrink whose changes landed in the visible region slipped past the shrink-across-boundary guard and reached the differential emitter, which is anchored to `#maxLinesRendered - height`: it rewrote only the suffix, dropped the newly exposed top row, and left a blank at the bottom, drifting every row below the edit one line up so it painted over the rows above. Such shrinks now re-anchor the bottom of the viewport with a non-destructive repaint, and the foreground-streaming shrink-across-boundary case repaints the live tail instead of padding and pinning the pre-shrink viewport.
|
|
2511
|
-
- Fixed a terminal resize during foreground-tool streaming on an unknown-viewport / ED3-risk host (Ghostty/kitty/Alacritty/iTerm2/WSL) leaving native scrollback permanently out of sync, so scrolling back after the turn showed missing rows. A pure geometry resize (no content change) takes the in-place viewport-repaint path, which — unlike a content-bearing resize that rebuilds via the geometry branch — never flagged native history. Because the prompt-submit checkpoint (`refreshNativeScrollbackIfDirty`) only rebuilds when scrollback is marked dirty on these hosts, the discrepancy was never reconciled. Overflowing geometry repaints whose viewport is not known to be at the bottom now mark scrollback dirty so the next checkpoint rebuilds an exact copy of the transcript.
|
|
2512
|
-
|
|
2513
|
-
Older entries are archived in [packages/tui/CHANGELOG.md@6693ddbfd58c](https://github.com/can1357/oh-my-pi/blob/6693ddbfd58ce9edcdc0dc3fe98a8882c9bae834/packages/tui/CHANGELOG.md).
|
|
2527
|
+
Older entries are archived in [packages/tui/CHANGELOG.md@9f40fb535f35](https://github.com/can1357/oh-my-pi/blob/9f40fb535f35f2b38336a4e694ff4c0dc91d4868/packages/tui/CHANGELOG.md).
|
package/README.md
CHANGED
|
@@ -493,7 +493,7 @@ const spacer = new Spacer(2); // 2 empty lines (default: 1)
|
|
|
493
493
|
|
|
494
494
|
### Image
|
|
495
495
|
|
|
496
|
-
Renders images inline for terminals that support the Kitty graphics protocol (Kitty, Ghostty, WezTerm, and Warp on macOS/Linux), iTerm2 inline images or SIXEL. Falls back to a text placeholder on unsupported terminals.
|
|
496
|
+
Renders images inline for terminals that support the Kitty graphics protocol (including Kitty, Ghostty, WezTerm, Rex, and Warp on macOS/Linux), iTerm2 inline images or SIXEL. Falls back to a text placeholder on unsupported terminals.
|
|
497
497
|
|
|
498
498
|
```typescript
|
|
499
499
|
interface ImageTheme {
|
|
@@ -24,6 +24,7 @@ interface AppKeybindings {
|
|
|
24
24
|
"app.message.followUp": true;
|
|
25
25
|
"app.retry": true;
|
|
26
26
|
"app.message.dequeue": true;
|
|
27
|
+
"app.btw.inject": true;
|
|
27
28
|
"app.clipboard.pasteImage": true;
|
|
28
29
|
"app.clipboard.pasteTextRaw": true;
|
|
29
30
|
"app.clipboard.copyLine": true;
|
|
@@ -272,6 +273,10 @@ export declare const KEYBINDINGS: {
|
|
|
272
273
|
readonly defaultKeys: ["alt+up", "shift+up"];
|
|
273
274
|
readonly description: "Dequeue message";
|
|
274
275
|
};
|
|
276
|
+
readonly "app.btw.inject": {
|
|
277
|
+
readonly defaultKeys: "alt+i";
|
|
278
|
+
readonly description: "Send a /btw answer's steering prompt to the main session";
|
|
279
|
+
};
|
|
275
280
|
readonly "app.clipboard.pasteImage": {
|
|
276
281
|
readonly defaultKeys: KeyId[];
|
|
277
282
|
readonly description: "Paste image or text from clipboard";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type SessionHistoryMatcher, type SessionListing, type SessionSelectorEntry } from "../overlays/session-selector.js";
|
|
2
2
|
/** Persistence and history capabilities supplied by the session-owning host. */
|
|
3
3
|
export interface SessionPickerHost<T extends SessionSelectorEntry = SessionSelectorEntry> {
|
|
4
4
|
loadPinnedIds?(): Promise<ReadonlySet<string>>;
|
|
@@ -7,11 +7,13 @@ export interface SessionPickerHost<T extends SessionSelectorEntry = SessionSelec
|
|
|
7
7
|
/** Rename the session and resolve with the title as stored, or null when it did not happen. */
|
|
8
8
|
renameSession?(session: T, title: string): Promise<string | null>;
|
|
9
9
|
setSessionPinned?(session: T, pinned: boolean): Promise<void>;
|
|
10
|
-
loadAllSessions?(): Promise<T
|
|
10
|
+
loadAllSessions?(): Promise<SessionListing<T>>;
|
|
11
11
|
}
|
|
12
12
|
/** Presentation and capability controls for the standalone session picker. */
|
|
13
13
|
export interface SessionPickerOptions<T extends SessionSelectorEntry = SessionSelectorEntry> {
|
|
14
|
-
|
|
14
|
+
/** Complete listing replacing the preliminary `sessions` once it settles. */
|
|
15
|
+
completeSessions?: Promise<T[]>;
|
|
16
|
+
allSessions?: SessionListing<T>;
|
|
15
17
|
title?: string;
|
|
16
18
|
scopeLabel?: string | false;
|
|
17
19
|
showCwd?: boolean;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
5
5
|
import { Container, type TUI } from "../tui.js";
|
|
6
6
|
import type { OutputArtifactError } from "../tools/streaming-output.js";
|
|
7
|
-
import type { TruncationMeta } from "../tools/output-meta.js";
|
|
7
|
+
import type { MinimizedMeta, TruncationMeta } from "../tools/output-meta.js";
|
|
8
8
|
import { type DescribeContext, type NativeNode, type NativeUiEvent } from "../native/node.js";
|
|
9
9
|
/** PTY size for `!` commands: the execution frame's inner content area. */
|
|
10
10
|
export declare function bashPtyViewport(ui: TUI): {
|
|
@@ -43,9 +43,12 @@ export declare class BashExecutionComponent extends Container {
|
|
|
43
43
|
output?: string;
|
|
44
44
|
truncation?: TruncationMeta;
|
|
45
45
|
artifactError?: OutputArtifactError;
|
|
46
|
+
minimized?: MinimizedMeta;
|
|
46
47
|
images?: readonly ImageContent[];
|
|
47
48
|
showImages?: boolean;
|
|
48
49
|
}): void;
|
|
50
|
+
/** The loader animates the bottom border from outside the child tree, so teardown stops it here. */
|
|
51
|
+
dispose(): void;
|
|
49
52
|
render(width: number): readonly string[];
|
|
50
53
|
/**
|
|
51
54
|
* Get the raw output for creating BashExecutionMessage.
|
|
@@ -32,6 +32,8 @@ export declare class EvalExecutionComponent extends Container {
|
|
|
32
32
|
truncation?: TruncationMeta;
|
|
33
33
|
artifactError?: OutputArtifactError;
|
|
34
34
|
}): void;
|
|
35
|
+
/** The loader animates the bottom border from outside the child tree, so teardown stops it here. */
|
|
36
|
+
dispose(): void;
|
|
35
37
|
getOutput(): string;
|
|
36
38
|
getCode(): string;
|
|
37
39
|
}
|
|
@@ -10,7 +10,8 @@ import { Loader } from "../components/loader.js";
|
|
|
10
10
|
import { Text } from "../components/text.js";
|
|
11
11
|
import { Container, type TUI } from "../tui.js";
|
|
12
12
|
import type { OutputArtifactError } from "../tools/streaming-output.js";
|
|
13
|
-
import { type TruncationMeta } from "../tools/output-meta.js";
|
|
13
|
+
import { type MinimizedMeta, type TruncationMeta } from "../tools/output-meta.js";
|
|
14
|
+
import { DynamicBorder } from "../chrome/dynamic-border.js";
|
|
14
15
|
import type { TspText } from "@oh-my-pi/pi-wire";
|
|
15
16
|
import type { NativeChild, NativeNode } from "../native/node.js";
|
|
16
17
|
/** Output rows shown while an execution is collapsed. */
|
|
@@ -25,23 +26,26 @@ export type ExecutionColorKey = "dim" | "bashMode" | "pythonMode";
|
|
|
25
26
|
/**
|
|
26
27
|
* Build the spacer + top border + content container + bottom border scaffold
|
|
27
28
|
* that bash and eval execution components share. The caller appends the
|
|
28
|
-
* header (command vs `>>>` prompt) and the
|
|
29
|
-
* `
|
|
29
|
+
* header (command vs `>>>` prompt) to `contentContainer` and keeps the run's
|
|
30
|
+
* state in `bottomBorder` ({@link executionStatusLabel}); the returned loader
|
|
31
|
+
* animates that label rather than taking a row of its own.
|
|
30
32
|
*/
|
|
31
33
|
export declare function buildExecutionFrame(parent: Container, ui: TUI, colorKey: ExecutionColorKey): {
|
|
32
34
|
contentContainer: Container;
|
|
33
35
|
loader: Loader;
|
|
36
|
+
bottomBorder: DynamicBorder;
|
|
34
37
|
};
|
|
38
|
+
/** The bottom-border marker of a settled run: `exit N` for a failure, `cancelled` for a cancel. */
|
|
39
|
+
export declare function executionStatusLabel(status: Exclude<ExecutionStatus, "running">, exitCode: number | undefined): string | undefined;
|
|
35
40
|
/**
|
|
36
|
-
* Build the post-run status block (hidden-line hint,
|
|
37
|
-
*
|
|
38
|
-
*
|
|
41
|
+
* Build the post-run status block (hidden-line hint, truncation notice).
|
|
42
|
+
* Returns undefined when there is nothing to display so callers can skip
|
|
43
|
+
* appending a stray Text child.
|
|
39
44
|
*/
|
|
40
45
|
export declare function buildStatusFooter(opts: {
|
|
41
|
-
status: ExecutionStatus;
|
|
42
|
-
exitCode: number | undefined;
|
|
43
46
|
truncation: TruncationMeta | undefined;
|
|
44
47
|
artifactError?: OutputArtifactError;
|
|
48
|
+
minimized?: MinimizedMeta;
|
|
45
49
|
hiddenLineCount: number;
|
|
46
50
|
/** Suppress the "… N more lines" hint (used when sixel passthrough renders the full output). */
|
|
47
51
|
suppressHiddenCount?: boolean;
|
|
@@ -64,6 +68,7 @@ export interface ExecutionCardInput {
|
|
|
64
68
|
readonly exitCode: number | undefined;
|
|
65
69
|
readonly truncation: TruncationMeta | undefined;
|
|
66
70
|
readonly artifactError?: OutputArtifactError;
|
|
71
|
+
readonly minimized?: MinimizedMeta;
|
|
67
72
|
}
|
|
68
73
|
/**
|
|
69
74
|
* Native card shared by user bash/eval runs: the head with a live `elapsed`
|
|
@@ -94,6 +99,7 @@ export interface ExecutionToolInput {
|
|
|
94
99
|
readonly exitCode: number | undefined;
|
|
95
100
|
readonly truncation: TruncationMeta | undefined;
|
|
96
101
|
readonly artifactError?: OutputArtifactError;
|
|
102
|
+
readonly minimized?: MinimizedMeta;
|
|
97
103
|
}
|
|
98
104
|
/**
|
|
99
105
|
* A user `!`/`$` run as the agent's `tool` frame (§6.6): a head with a `you`
|
|
@@ -8,6 +8,7 @@ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
|
8
8
|
import { type Component } from "../tui.js";
|
|
9
9
|
import { type FileMentionMessage } from "./messages.js";
|
|
10
10
|
import { ToolActivityContainer } from "../chrome/tool-activity.js";
|
|
11
|
+
import type { MessageRenderer } from "./extension-types.js";
|
|
11
12
|
import { type TranscriptBlock } from "../chrome/transcript-container.js";
|
|
12
13
|
type CustomOrHookMessage = Extract<AgentMessage, {
|
|
13
14
|
role: "custom" | "hookMessage";
|
|
@@ -21,6 +22,13 @@ type AssistantAgentMessage = Extract<AgentMessage, {
|
|
|
21
22
|
* row per job.
|
|
22
23
|
*/
|
|
23
24
|
export declare function buildAsyncResultBlock(message: CustomOrHookMessage): ToolActivityContainer;
|
|
25
|
+
/**
|
|
26
|
+
* The `async-result` card for both transcript surfaces: a registered renderer owns it (#14131);
|
|
27
|
+
* the built-in block covers no renderer, a declining renderer, and a throwing one.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildAsyncResultComponent(message: CustomOrHookMessage, renderer: MessageRenderer | undefined): Component & {
|
|
30
|
+
setExpanded(expanded: boolean): void;
|
|
31
|
+
};
|
|
24
32
|
/**
|
|
25
33
|
* Render a `launch-completion` custom message (terminal supervised-process
|
|
26
34
|
* exits from the launch broker) as a transcript block of one compact
|
|
@@ -13,6 +13,12 @@ export declare class DynamicBorder implements Component {
|
|
|
13
13
|
#private;
|
|
14
14
|
constructor(color?: (str: string) => string);
|
|
15
15
|
invalidate(): void;
|
|
16
|
+
/**
|
|
17
|
+
* Pre-styled text set into the rule after a short lead (`─── label ────`);
|
|
18
|
+
* undefined draws a plain rule. A function label is re-read every render,
|
|
19
|
+
* for live text such as a spinner.
|
|
20
|
+
*/
|
|
21
|
+
setLabel(label: string | (() => string) | undefined): void;
|
|
16
22
|
/** Native terminals draw their own chrome; a border rule describes nothing. */
|
|
17
23
|
describe(): NativeNode;
|
|
18
24
|
render(width: number): readonly string[];
|
|
@@ -3,10 +3,10 @@ import type { NativeNode } from "../native/node.js";
|
|
|
3
3
|
import { type ThemeColor } from "../theme/index.js";
|
|
4
4
|
import { TranscriptBlock } from "./transcript-container.js";
|
|
5
5
|
import { type NoticeTone } from "./transcript-notice.js";
|
|
6
|
-
/** One
|
|
6
|
+
/** One run of a status row's terminal line, in `color` unless the text is already styled. */
|
|
7
7
|
export interface TranscriptStatusPart {
|
|
8
8
|
readonly text: string;
|
|
9
|
-
readonly color
|
|
9
|
+
readonly color?: ThemeColor;
|
|
10
10
|
}
|
|
11
11
|
/** A status row in a native terminal: its {@link noticeRow}'s tone, icon and message. */
|
|
12
12
|
export interface TranscriptStatusNative {
|
|
@@ -157,12 +157,21 @@ export declare class Editor implements Component, Focusable {
|
|
|
157
157
|
* cursor. The host styles it (ANSI allowed). Re-evaluated on every render, so hosts can derive
|
|
158
158
|
* it from live state. */
|
|
159
159
|
placeholder?: () => string | undefined;
|
|
160
|
-
/** Whole-message
|
|
161
|
-
*
|
|
162
|
-
* autocomplete is open. A shown prediction replaces the {@link placeholder}; Tab or
|
|
163
|
-
* the rest without submitting.
|
|
164
|
-
*
|
|
165
|
-
|
|
160
|
+
/** Whole-message predictions for the next prompt, most likely first. The first one the single-line
|
|
161
|
+
* buffer is a strict prefix of is painted as ghost text after the cursor while the cursor sits at
|
|
162
|
+
* its end and no autocomplete is open. A shown prediction replaces the {@link placeholder}; Tab or
|
|
163
|
+
* Right inserts the rest without submitting. A buffer the user typed keeps the ghost even when it
|
|
164
|
+
* equals a shorter prediction; once Tab, Right, or the list has inserted one of two or more
|
|
165
|
+
* predictions, no ghost extends it to a longer one, and Tab instead opens a list of all of them
|
|
166
|
+
* that swaps the whole line, also without submitting. Each must be a single line. Re-evaluated on
|
|
167
|
+
* every render, so hosts can derive them from live state. */
|
|
168
|
+
predictions?: () => readonly string[] | undefined;
|
|
169
|
+
/** Called with the prediction's index in {@link predictions} after Tab or Right inserts the rest of
|
|
170
|
+
* a shown prediction, or the alternatives list swaps a different one into the buffer. */
|
|
171
|
+
onPredictionAccepted?: (index: number) => void;
|
|
172
|
+
/** Called for each frame that paints a prediction as ghost text: a terminal frame that draws at
|
|
173
|
+
* least one cell of it, or a native frame that carries it as the editor's ghost. */
|
|
174
|
+
onPredictionShown?: () => void;
|
|
166
175
|
constructor(theme: EditorTheme);
|
|
167
176
|
/** Return bounded editor content, cursor, and transient child state for debug inspection. */
|
|
168
177
|
debugState(): Record<string, unknown>;
|
|
@@ -71,6 +71,8 @@ export declare class Loader extends Text {
|
|
|
71
71
|
stop(): void;
|
|
72
72
|
/** Lifecycle teardown: stop the animation timer. Idempotent. */
|
|
73
73
|
dispose(): void;
|
|
74
|
+
/** The current spinner frame and message as one styled line, for hosts that set it into their own chrome. */
|
|
75
|
+
inlineText(): string;
|
|
74
76
|
/** Install a lazy right-docked suffix for the spinner row (e.g. a styled
|
|
75
77
|
* session title). Re-evaluated every paint; dropped when the row leaves
|
|
76
78
|
* less than a two-cell gap. */
|
|
@@ -42,3 +42,10 @@ export declare function matchesAppFollowUp(data: string): boolean;
|
|
|
42
42
|
export declare function appApproveKeys(): readonly KeyId[];
|
|
43
43
|
/** Match the tool-approval key, recognizing modifier-tagged LF as Ctrl+Enter like {@link matchesAppFollowUp}. */
|
|
44
44
|
export declare function matchesAppApprove(data: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Effective /btw inject key (Alt+I by default). No fallback: it sends text into the main
|
|
47
|
+
* session, so a user who unbinds it gets no key at all.
|
|
48
|
+
*/
|
|
49
|
+
export declare function appBtwInjectKey(): KeyId | undefined;
|
|
50
|
+
/** Match the key that sends a /btw answer's steering prompt to the main session. */
|
|
51
|
+
export declare function matchesAppBtwInject(data: string): boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
2
2
|
import { type Component, type Focusable, Input } from "../index.js";
|
|
3
3
|
import { type BtwHistoryRecord } from "./btw-history.js";
|
|
4
|
+
import { type BtwInjectState } from "./btw-inject.js";
|
|
4
5
|
import type { SpaceHoldHandler } from "../space-hold.js";
|
|
5
6
|
import { type KeyId } from "../app-keybindings.js";
|
|
6
7
|
import type { NativeNode, NativeUiEvent } from "../native/node.js";
|
|
@@ -26,6 +27,18 @@ interface BtwHistoryPanelOptions {
|
|
|
26
27
|
* first. For a host with no inline panel to fall back to (Tern).
|
|
27
28
|
*/
|
|
28
29
|
escapeHides?: boolean;
|
|
30
|
+
/** `btw.inject` hooks, given only while it is on for this view. */
|
|
31
|
+
inject?: BtwHistoryInject;
|
|
32
|
+
}
|
|
33
|
+
interface BtwHistoryInject {
|
|
34
|
+
/**
|
|
35
|
+
* How a finished turn's closed `<inject>` block shows: apart from its prose while pending or
|
|
36
|
+
* sent, plain text when `undefined`. A streaming turn always shows its block.
|
|
37
|
+
*/
|
|
38
|
+
state: (record: BtwHistoryRecord, turnIndex: number) => BtwInjectState | undefined;
|
|
39
|
+
/** Whether the inject key may send the record's latest block now. */
|
|
40
|
+
canSend: (record: BtwHistoryRecord) => boolean;
|
|
41
|
+
send: (record: BtwHistoryRecord) => void;
|
|
29
42
|
}
|
|
30
43
|
/** Session-local side questions. Selecting or copying never promotes them into chat. */
|
|
31
44
|
export declare class BtwHistoryPanel implements Component, Focusable {
|
|
@@ -20,5 +20,29 @@ export interface BtwHistoryRecord extends BtwHistoryTurn {
|
|
|
20
20
|
export declare function getBtwTopicLabel(record: BtwHistoryRecord): string;
|
|
21
21
|
export declare function getBtwLatestTurn(record: BtwHistoryRecord): BtwHistoryTurn;
|
|
22
22
|
export declare function getBtwTurns(record: BtwHistoryRecord): readonly BtwHistoryTurn[];
|
|
23
|
+
/** Identifies one turn of a topic, its latest by default: a follow-up gets a new key, so per-answer marks reset. */
|
|
24
|
+
export declare function getBtwTurnKey(record: BtwHistoryRecord, turnIndex?: number): string;
|
|
23
25
|
/** Copy the most recent nonblank answer, preserving its original whitespace. */
|
|
24
26
|
export declare function getBtwCopyText(record: BtwHistoryRecord): string | undefined;
|
|
27
|
+
/** An answer around its `<inject>` block: the steering prompt a side answer drafted for the main session. */
|
|
28
|
+
export interface BtwInjectParts {
|
|
29
|
+
before: string;
|
|
30
|
+
inject: string;
|
|
31
|
+
after: string;
|
|
32
|
+
/** False while no opener has a close: the block may still be streaming, so it runs to the end. */
|
|
33
|
+
closed: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Split an answer at its last closed `<inject>` block: the last opener that has a close
|
|
37
|
+
* after it, paired with the first close after it. A tag merely mentioned in prose,
|
|
38
|
+
* before or after the block, cannot capture it. Without a closed block, the last opener
|
|
39
|
+
* runs to the end (`closed: false`); display it only while the answer still streams.
|
|
40
|
+
* Linear: the last opener before the last close is the last one with any close after it.
|
|
41
|
+
*/
|
|
42
|
+
export declare function splitBtwInject(answer: string): BtwInjectParts | undefined;
|
|
43
|
+
/** A block's text as shown and as sent: control sequences stripped, tabs expanded, trimmed. */
|
|
44
|
+
export declare function formatBtwInjectText(inject: string): string;
|
|
45
|
+
/** The steering prompt to send, exactly as the block shows it; undefined while unclosed or blank. */
|
|
46
|
+
export declare function getBtwInject(answer: string): string | undefined;
|
|
47
|
+
/** A topic's steering prompt: only its latest turn's, once that turn completed. */
|
|
48
|
+
export declare function getBtwRecordInject(record: BtwHistoryRecord): string | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Component } from "../index.js";
|
|
2
|
+
import type { NativeNode } from "../native/node.js";
|
|
3
|
+
import { type BtwInjectParts } from "./btw-history.js";
|
|
4
|
+
/** Labels a steering prompt that has not been sent yet. */
|
|
5
|
+
export declare const BTW_INJECT_LABEL = "Inject into main session";
|
|
6
|
+
/** Labels a sent steering prompt. */
|
|
7
|
+
export declare const BTW_INJECTED_LABEL = "Injected into main session";
|
|
8
|
+
/** A displayed `<inject>` block: still sendable, or sent. Blocks in neither state render as plain text. */
|
|
9
|
+
export type BtwInjectState = "pending" | "sent";
|
|
10
|
+
/** Text-mode answer split around its `<inject>` block: prose, the railed block, prose, a blank row apart. */
|
|
11
|
+
export declare class BtwInjectAnswer implements Component {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(parts: BtwInjectParts, sent: boolean);
|
|
14
|
+
render(width: number): string[];
|
|
15
|
+
invalidate(): void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The same answer for native surfaces. They wrap text themselves, so a per-row gutter cannot
|
|
19
|
+
* follow wrapped lines: a card toned like the rail (`user` pending, `success` sent) marks the
|
|
20
|
+
* whole block instead, with the label as its last row.
|
|
21
|
+
*/
|
|
22
|
+
export declare function describeBtwInjectAnswer(parts: BtwInjectParts, sent: boolean, stream: boolean): NativeNode;
|
|
@@ -8,6 +8,11 @@ interface BtwPanelComponentOptions {
|
|
|
8
8
|
tui: TUI;
|
|
9
9
|
canBranch?: () => boolean;
|
|
10
10
|
canFollowUp?: () => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Given only while `btw.inject` is on: the answer's `<inject>` block shows apart from its
|
|
13
|
+
* prose, and the inject key (`app.btw.inject`) is offered while this returns true.
|
|
14
|
+
*/
|
|
15
|
+
canInject?: () => boolean;
|
|
11
16
|
}
|
|
12
17
|
export declare class BtwPanelComponent extends OverlayPanel {
|
|
13
18
|
#private;
|
|
@@ -17,6 +22,8 @@ export declare class BtwPanelComponent extends OverlayPanel {
|
|
|
17
22
|
markComplete(): void;
|
|
18
23
|
/** Visual confirmation that `c` copied the answer to the clipboard. */
|
|
19
24
|
markCopied(): void;
|
|
25
|
+
/** Shows the answer's steering prompt as sent (send arrows, green), or back to pending when a send failed. */
|
|
26
|
+
setInjected(injected: boolean): void;
|
|
20
27
|
/** Shows that the completed answer is being promoted into the chat session. */
|
|
21
28
|
markBranching(): void;
|
|
22
29
|
markAborted(): void;
|
|
@@ -85,4 +85,6 @@ export declare class HookEditorComponent extends OverlayPanel implements Focusab
|
|
|
85
85
|
* enhanced-paste routing falls back to the main prompt editor hidden behind the
|
|
86
86
|
* dialog (#2127 routing contract). */
|
|
87
87
|
pasteText(text: string): void;
|
|
88
|
+
/** Replace the draft, as Ctrl+R history search does for the main composer. */
|
|
89
|
+
setText(text: string): void;
|
|
88
90
|
}
|
|
@@ -8,6 +8,10 @@ export interface JobsPanelJob {
|
|
|
8
8
|
readonly type: string;
|
|
9
9
|
readonly status: "running" | "completed" | "failed" | "cancelled";
|
|
10
10
|
readonly label: string;
|
|
11
|
+
/** What the job is for, in the model's words; rows and the detail lead with it over a command `label`. */
|
|
12
|
+
readonly intent?: string;
|
|
13
|
+
/** One line on what a command does and when it ends, from the cheap model; the detail shows it under the intent. */
|
|
14
|
+
readonly caption?: string;
|
|
11
15
|
readonly startTime: number;
|
|
12
16
|
readonly endTime?: number;
|
|
13
17
|
/** Registry id of the agent that owns the job. */
|
|
@@ -18,6 +18,16 @@ export interface SessionSelectorEntry {
|
|
|
18
18
|
/** Path to the parent session when this one was forked. */
|
|
19
19
|
parentSessionPath?: string;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* One picker scope's rows, possibly in two passes: `sessions` show at once
|
|
23
|
+
* (e.g. rows built from a title index), and `complete` settles with the full
|
|
24
|
+
* listing that replaces them, keeping the query, the selected session, and
|
|
25
|
+
* deletes/renames made meanwhile.
|
|
26
|
+
*/
|
|
27
|
+
export interface SessionListing<T extends SessionSelectorEntry = SessionSelectorEntry> {
|
|
28
|
+
sessions: T[];
|
|
29
|
+
complete?: Promise<T[]>;
|
|
30
|
+
}
|
|
21
31
|
import { OverlayPanel } from "../chrome/overlay-box.js";
|
|
22
32
|
/** The session list's part of the picker props, plus the memo keys it was built from. */
|
|
23
33
|
interface SessionPickerView {
|
|
@@ -76,6 +86,12 @@ declare class SessionList<T extends SessionSelectorEntry> implements Component {
|
|
|
76
86
|
/** Re-render hook for async list updates (fuzzy scan completion, history merge). */
|
|
77
87
|
onRequestRender?: () => void;
|
|
78
88
|
constructor(sessions: T[], showCwd?: boolean, historyMatcher?: SessionHistoryMatcher, getTerminalRows?: () => number, pinnedIds?: ReadonlySet<string>, currentSessionPath?: string | (() => string | undefined));
|
|
89
|
+
/**
|
|
90
|
+
* Swap in the complete listing of the shown scope (a scan that finished
|
|
91
|
+
* after the picker opened), keeping the query and the selected session:
|
|
92
|
+
* rows arriving above the cursor never move it onto another session.
|
|
93
|
+
*/
|
|
94
|
+
refreshSessions(sessions: T[], showCwd: boolean): void;
|
|
79
95
|
/** Replace the visible dataset, e.g. when toggling folder/all-projects scope. */
|
|
80
96
|
setSessions(sessions: T[], showCwd: boolean, pinnedIds?: ReadonlySet<string>): void;
|
|
81
97
|
/** Cancel pending async search work; idempotent, called on every picker exit path. */
|
|
@@ -141,10 +157,15 @@ export interface SessionSelectorOptions<T extends SessionSelectorEntry = Session
|
|
|
141
157
|
/** Persist the selected session's pin state (pin keys / the picker's Pin action). */
|
|
142
158
|
onSetPinned?: (session: T, pinned: boolean) => Promise<void>;
|
|
143
159
|
historyMatcher?: SessionHistoryMatcher;
|
|
160
|
+
/**
|
|
161
|
+
* Complete folder listing when the constructor's `sessions` are a
|
|
162
|
+
* preliminary subset; replaces them once it settles (see {@link SessionListing}).
|
|
163
|
+
*/
|
|
164
|
+
completeSessions?: Promise<T[]>;
|
|
144
165
|
/** Loads sessions across all projects for the all-projects scope toggle (Tab). */
|
|
145
|
-
loadAllSessions?: () => Promise<T
|
|
146
|
-
/** Preloaded all-projects
|
|
147
|
-
allSessions?: T
|
|
166
|
+
loadAllSessions?: () => Promise<SessionListing<T>>;
|
|
167
|
+
/** Preloaded all-projects listing; cached so the first Tab toggle is instant. */
|
|
168
|
+
allSessions?: SessionListing<T>;
|
|
148
169
|
/** Picker heading; defaults to "Resume Session". */
|
|
149
170
|
title?: string;
|
|
150
171
|
/** Primary action label; defaults to "Resume" (ANSI footer defaults to "select"). */
|
|
@@ -190,11 +190,31 @@ export declare function formatErrorMessage(message: string | undefined, theme: T
|
|
|
190
190
|
export declare function formatErrorDetail(message: string | undefined, theme: Theme): string;
|
|
191
191
|
/** Render a muted empty-state message with a warning icon. */
|
|
192
192
|
export declare function formatEmptyMessage(message: string, theme: Theme): string;
|
|
193
|
+
/**
|
|
194
|
+
* Color of a file's name, or a whole URL, in tool bodies: it keeps paths apart
|
|
195
|
+
* from the tool titles above them (bronze in titanium).
|
|
196
|
+
*/
|
|
197
|
+
export declare const FILE_NAME_COLOR = "customMessageLabel";
|
|
198
|
+
/**
|
|
199
|
+
* Where a display path's final segment (file or folder name) starts, past its
|
|
200
|
+
* last `/` or `\` separator; a trailing-slash directory keeps its slash on the
|
|
201
|
+
* name. Shared by the terminal ({@link formatStyledPath}) and Tern file rows.
|
|
202
|
+
*/
|
|
203
|
+
export declare function pathNameStart(filePath: string): number;
|
|
204
|
+
/**
|
|
205
|
+
* A file path in a tool body: the directory (with its trailing separator) dim,
|
|
206
|
+
* the final segment in {@link FILE_NAME_COLOR}. Tool headers keep paths in
|
|
207
|
+
* their plain subject color instead.
|
|
208
|
+
*/
|
|
209
|
+
export declare function formatStyledPath(filePath: string, theme: Theme): string;
|
|
193
210
|
/** Marker displayed in the gutter of a code frame. */
|
|
194
211
|
export type CodeFrameMarker = "" | " " | "*" | "+" | "-" | ">";
|
|
195
212
|
/** Format a code-frame row with a padded line-number gutter. */
|
|
196
213
|
export declare function formatCodeFrameLine(marker: CodeFrameMarker, lineNumber: string | number, content: string, lineNumberWidth: number): string;
|
|
197
|
-
/**
|
|
214
|
+
/**
|
|
215
|
+
* Status states supported by shared tool renderer icons. `done` is a deprecated
|
|
216
|
+
* alias of `success`, kept for extension renderers.
|
|
217
|
+
*/
|
|
198
218
|
export type ToolUIStatus = "success" | "done" | "error" | "warning" | "info" | "pending" | "running" | "aborted";
|
|
199
219
|
/** Semantic foreground colors used by tool renderer labels. */
|
|
200
220
|
export type ToolUIColor = "success" | "error" | "warning" | "accent" | "muted";
|