@oh-my-pi/pi-tui 18.13.2 → 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.
- package/CHANGELOG.md +40 -54
- package/README.md +34 -34
- package/dist/types/app-keybindings.d.ts +15 -0
- package/dist/types/apps/session-picker.d.ts +5 -0
- package/dist/types/charts/chart-plan.d.ts +9 -7
- package/dist/types/chat/assistant-message.d.ts +15 -3
- package/dist/types/chat/bash-execution.d.ts +2 -0
- package/dist/types/chat/display-preferences.d.ts +2 -0
- package/dist/types/chat/extension-types.d.ts +31 -0
- package/dist/types/chat/reply-write.d.ts +48 -0
- package/dist/types/chat/table-chart.d.ts +4 -3
- package/dist/types/chat/tool-execution.d.ts +1 -2
- package/dist/types/chat/transcript-outline.d.ts +7 -0
- package/dist/types/chat/transcript-render-helpers.d.ts +2 -0
- package/dist/types/chrome/index.d.ts +1 -0
- package/dist/types/chrome/transcript-notice.d.ts +35 -0
- package/dist/types/chrome/transcript-status.d.ts +20 -8
- package/dist/types/components/editor.d.ts +8 -0
- package/dist/types/components/markdown.d.ts +7 -0
- package/dist/types/native/blobs.d.ts +2 -1
- package/dist/types/native/picker.d.ts +3 -3
- package/dist/types/overlays/annotation-overlay.d.ts +7 -1
- package/dist/types/overlays/annotation-types.d.ts +28 -0
- package/dist/types/overlays/login-dialog.d.ts +5 -1
- package/dist/types/overlays/model-browser.d.ts +10 -1
- package/dist/types/overlays/oauth-selector.d.ts +23 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +2 -0
- package/dist/types/overlays/rewind-selector.d.ts +1 -1
- package/dist/types/overlays/session-selector.d.ts +22 -2
- package/dist/types/prompt/composer.d.ts +41 -4
- package/dist/types/prompt/interactive-context-helpers.d.ts +10 -3
- package/dist/types/prompt/welcome.d.ts +6 -2
- package/dist/types/render/extension-links.d.ts +65 -0
- package/dist/types/render/hyperlink.d.ts +25 -7
- package/dist/types/render/index.d.ts +1 -0
- package/dist/types/setup/scenes/model.d.ts +1 -1
- package/dist/types/setup/scenes/outro.d.ts +5 -4
- package/dist/types/setup/scenes/sign-in.d.ts +13 -8
- package/dist/types/setup/scenes/splash.d.ts +4 -4
- package/dist/types/setup/scenes/types.d.ts +16 -1
- package/dist/types/setup/startup-splash.d.ts +1 -1
- package/dist/types/setup/wizard-overlay.d.ts +11 -7
- package/dist/types/setup/wizard.d.ts +5 -1
- package/dist/types/status-line/component.d.ts +1 -1
- package/dist/types/status-line/context-usage.d.ts +28 -6
- package/dist/types/status-line/host.d.ts +6 -2
- package/dist/types/theme/theme.d.ts +0 -23
- package/dist/types/tools/bash-interactive.d.ts +6 -0
- package/dist/types/tools/bash.d.ts +2 -0
- package/dist/types/tools/default-renderer.d.ts +6 -4
- package/dist/types/tools/irc.d.ts +6 -0
- package/dist/types/tools/json-tree.d.ts +23 -4
- package/dist/types/tools/lsp.d.ts +2 -0
- package/dist/types/tools/mcp.d.ts +6 -5
- package/dist/types/tools/native-view.d.ts +1 -1
- package/dist/types/tools/renderer.d.ts +2 -0
- package/dist/types/tools/streaming-output.d.ts +11 -0
- package/dist/types/tools/task.d.ts +9 -1
- package/dist/types/tools/url-scheme-host.d.ts +17 -0
- package/dist/types/tools/yield.d.ts +1 -1
- package/dist/types/tui.d.ts +7 -2
- package/package.json +10 -15
- package/src/app-keybindings.ts +15 -0
- package/src/apps/session-picker.ts +7 -0
- package/src/charts/chart-plan.ts +20 -50
- package/src/chat/advisor-message.ts +2 -0
- package/src/chat/assistant-message.ts +137 -19
- package/src/chat/background-tan-message.ts +4 -0
- package/src/chat/bash-execution.ts +6 -0
- package/src/chat/chat-transcript-builder.ts +58 -28
- package/src/chat/compaction-summary-message.ts +2 -1
- package/src/chat/display-preferences.ts +3 -0
- package/src/chat/extension-types.ts +34 -0
- package/src/chat/reply-write.ts +127 -0
- package/src/chat/table-chart.ts +10 -4
- package/src/chat/tool-execution.ts +20 -13
- package/src/chat/transcript-outline.ts +27 -0
- package/src/chat/transcript-render-helpers.ts +66 -24
- package/src/chrome/index.ts +1 -0
- package/src/chrome/transcript-notice.ts +83 -0
- package/src/chrome/transcript-status.ts +29 -29
- package/src/components/editor.ts +10 -1
- package/src/components/markdown.ts +116 -6
- package/src/hotkeys-markdown.ts +1 -0
- package/src/native/backend.ts +5 -66
- package/src/native/blobs.ts +3 -2
- package/src/native/picker.ts +3 -3
- package/src/overlays/advisor-config.ts +1 -10
- package/src/overlays/annotation-overlay.ts +125 -37
- package/src/overlays/annotation-types.ts +24 -0
- package/src/overlays/hook-selector.ts +2 -2
- package/src/overlays/login-dialog.ts +31 -5
- package/src/overlays/model-browser.ts +37 -0
- package/src/overlays/model-hub.ts +1 -7
- package/src/overlays/model-picker.ts +1 -10
- package/src/overlays/oauth-selector.ts +44 -6
- package/src/overlays/plan-review-overlay.ts +13 -2
- package/src/overlays/rewind-selector.ts +29 -12
- package/src/overlays/session-selector.ts +305 -39
- package/src/overlays/usage-dashboard.ts +5 -12
- package/src/prompt/composer.ts +213 -5
- package/src/prompt/custom-editor.ts +6 -1
- package/src/prompt/emoji-autocomplete.ts +0 -2
- package/src/prompt/interactive-context-helpers.ts +29 -4
- package/src/prompt/welcome.ts +31 -45
- package/src/render/extension-links.ts +214 -0
- package/src/render/hyperlink.ts +65 -9
- package/src/render/index.ts +1 -0
- package/src/setup/scenes/composer.ts +2 -0
- package/src/setup/scenes/glyph.ts +2 -0
- package/src/setup/scenes/model.ts +192 -29
- package/src/setup/scenes/outro.ts +30 -17
- package/src/setup/scenes/sign-in.ts +196 -400
- package/src/setup/scenes/splash.ts +25 -21
- package/src/setup/scenes/theme.ts +2 -0
- package/src/setup/scenes/types.ts +18 -1
- package/src/setup/startup-splash.ts +8 -7
- package/src/setup/wizard-overlay.ts +164 -33
- package/src/setup/wizard.ts +11 -2
- package/src/status-line/component.ts +4 -10
- package/src/status-line/context-usage.ts +72 -21
- package/src/status-line/host.ts +6 -2
- package/src/terminal.ts +24 -2
- package/src/theme/defaults.json +1 -0
- package/src/theme/loader.ts +1 -1
- package/src/theme/theme.ts +2 -75
- package/src/tools/bash-interactive.ts +6 -1
- package/src/tools/bash.ts +2 -0
- package/src/tools/default-renderer.ts +9 -6
- package/src/tools/eval.ts +14 -4
- package/src/tools/irc.ts +6 -0
- package/src/tools/job-widget.ts +13 -1
- package/src/tools/json-tree.ts +132 -42
- package/src/tools/lsp.ts +36 -15
- package/src/tools/mcp.ts +20 -12
- package/src/tools/native-view.ts +1 -1
- package/src/tools/renderer.ts +2 -0
- package/src/tools/streaming-output.ts +41 -0
- package/src/tools/task.ts +59 -17
- package/src/tools/url-scheme-host.ts +21 -0
- package/src/tools/yield.ts +18 -9
- package/src/tui.ts +43 -15
- package/THIRD-PARTY-NOTICES.txt +0 -22901
- package/dist/types/theme/defaults/index.d.ts +0 -10289
- package/src/theme/defaults/alabaster.json +0 -103
- package/src/theme/defaults/amethyst.json +0 -106
- package/src/theme/defaults/anthracite.json +0 -103
- package/src/theme/defaults/basalt.json +0 -101
- package/src/theme/defaults/birch.json +0 -105
- package/src/theme/defaults/dark-abyss.json +0 -101
- package/src/theme/defaults/dark-arctic.json +0 -114
- package/src/theme/defaults/dark-aurora.json +0 -105
- package/src/theme/defaults/dark-catppuccin.json +0 -117
- package/src/theme/defaults/dark-cavern.json +0 -101
- package/src/theme/defaults/dark-celestial.json +0 -116
- package/src/theme/defaults/dark-copper.json +0 -105
- package/src/theme/defaults/dark-cosmos.json +0 -100
- package/src/theme/defaults/dark-cyberpunk.json +0 -112
- package/src/theme/defaults/dark-dracula.json +0 -108
- package/src/theme/defaults/dark-eclipse.json +0 -101
- package/src/theme/defaults/dark-ember.json +0 -105
- package/src/theme/defaults/dark-equinox.json +0 -100
- package/src/theme/defaults/dark-forest.json +0 -106
- package/src/theme/defaults/dark-github.json +0 -115
- package/src/theme/defaults/dark-gruvbox.json +0 -122
- package/src/theme/defaults/dark-lavender.json +0 -105
- package/src/theme/defaults/dark-lunar.json +0 -99
- package/src/theme/defaults/dark-midnight.json +0 -105
- package/src/theme/defaults/dark-monochrome.json +0 -104
- package/src/theme/defaults/dark-monokai.json +0 -108
- package/src/theme/defaults/dark-nebula.json +0 -100
- package/src/theme/defaults/dark-neon-noir.json +0 -110
- package/src/theme/defaults/dark-nord.json +0 -108
- package/src/theme/defaults/dark-ocean.json +0 -111
- package/src/theme/defaults/dark-one.json +0 -110
- package/src/theme/defaults/dark-poimandres.json +0 -125
- package/src/theme/defaults/dark-rainforest.json +0 -101
- package/src/theme/defaults/dark-reef.json +0 -101
- package/src/theme/defaults/dark-retro.json +0 -102
- package/src/theme/defaults/dark-rose-pine.json +0 -106
- package/src/theme/defaults/dark-sakura.json +0 -105
- package/src/theme/defaults/dark-slate.json +0 -105
- package/src/theme/defaults/dark-solarized.json +0 -107
- package/src/theme/defaults/dark-solstice.json +0 -100
- package/src/theme/defaults/dark-starfall.json +0 -101
- package/src/theme/defaults/dark-sunset.json +0 -109
- package/src/theme/defaults/dark-swamp.json +0 -100
- package/src/theme/defaults/dark-synthwave.json +0 -113
- package/src/theme/defaults/dark-taiga.json +0 -101
- package/src/theme/defaults/dark-terminal.json +0 -105
- package/src/theme/defaults/dark-tokyo-night.json +0 -111
- package/src/theme/defaults/dark-tundra.json +0 -101
- package/src/theme/defaults/dark-twilight.json +0 -101
- package/src/theme/defaults/dark-volcanic.json +0 -101
- package/src/theme/defaults/graphite.json +0 -102
- package/src/theme/defaults/index.ts +0 -203
- package/src/theme/defaults/light-arctic.json +0 -117
- package/src/theme/defaults/light-aurora-day.json +0 -101
- package/src/theme/defaults/light-canyon.json +0 -101
- package/src/theme/defaults/light-catppuccin.json +0 -116
- package/src/theme/defaults/light-cirrus.json +0 -100
- package/src/theme/defaults/light-coral.json +0 -105
- package/src/theme/defaults/light-cyberpunk.json +0 -106
- package/src/theme/defaults/light-dawn.json +0 -100
- package/src/theme/defaults/light-dunes.json +0 -101
- package/src/theme/defaults/light-eucalyptus.json +0 -105
- package/src/theme/defaults/light-forest.json +0 -110
- package/src/theme/defaults/light-frost.json +0 -105
- package/src/theme/defaults/light-github.json +0 -125
- package/src/theme/defaults/light-glacier.json +0 -101
- package/src/theme/defaults/light-gruvbox.json +0 -118
- package/src/theme/defaults/light-haze.json +0 -100
- package/src/theme/defaults/light-honeycomb.json +0 -105
- package/src/theme/defaults/light-lagoon.json +0 -101
- package/src/theme/defaults/light-lavender.json +0 -105
- package/src/theme/defaults/light-meadow.json +0 -101
- package/src/theme/defaults/light-mint.json +0 -105
- package/src/theme/defaults/light-monochrome.json +0 -111
- package/src/theme/defaults/light-ocean.json +0 -109
- package/src/theme/defaults/light-one.json +0 -109
- package/src/theme/defaults/light-opal.json +0 -101
- package/src/theme/defaults/light-orchard.json +0 -101
- package/src/theme/defaults/light-paper.json +0 -105
- package/src/theme/defaults/light-poimandres.json +0 -125
- package/src/theme/defaults/light-prism.json +0 -100
- package/src/theme/defaults/light-retro.json +0 -108
- package/src/theme/defaults/light-sand.json +0 -105
- package/src/theme/defaults/light-savanna.json +0 -101
- package/src/theme/defaults/light-solarized.json +0 -112
- package/src/theme/defaults/light-soleil.json +0 -100
- package/src/theme/defaults/light-sunset.json +0 -109
- package/src/theme/defaults/light-synthwave.json +0 -108
- package/src/theme/defaults/light-tokyo-night.json +0 -121
- package/src/theme/defaults/light-wetland.json +0 -101
- package/src/theme/defaults/light-zenith.json +0 -99
- package/src/theme/defaults/limestone.json +0 -104
- package/src/theme/defaults/mahogany.json +0 -107
- package/src/theme/defaults/marble.json +0 -103
- package/src/theme/defaults/obsidian.json +0 -101
- package/src/theme/defaults/onyx.json +0 -101
- package/src/theme/defaults/pearl.json +0 -103
- package/src/theme/defaults/porcelain.json +0 -101
- package/src/theme/defaults/quartz.json +0 -106
- package/src/theme/defaults/sandstone.json +0 -105
- package/src/theme/defaults/titanium.json +0 -100
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.14.0] - 2026-10-29
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- Moved `PINNED_HUD_TOGGLE_ID` to the coding agent's task output manager so reserving subagent IDs no longer loads the interactive editor.
|
|
10
|
+
- Updated `StatusLineHost.resetExpiryNotice` to receive the session and manage warning deduplication; custom status-line components must use the new signature.
|
|
11
|
+
- Removed `ToolExecutionHandle.setToolActivityVisible`; tool-activity visibility is now controlled by transcript components, while reply blocks remain visible by default.
|
|
12
|
+
- Removed the `@oh-my-pi/pi-tui/theme/defaults` export. Bundled palettes are now available through `getBuiltinThemes()` from `theme/defaults.json`.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Fixed table-chart direction detection so measures are not incorrectly marked as better based on header words; single-measure tables are now sent for judging when local charting is appropriate.
|
|
17
|
+
- Fixed LSP diagnostics that incorrectly showed “No issues” before a language server had reported; such files are now shown as unverified. ([#17293](https://github.com/can1357/oh-my-pi/pull/17293) by [@JustasMasiulis](https://github.com/JustasMasiulis))
|
|
18
|
+
- Fixed Esc-Esc rewind in Tern selecting interrupted turns with no visible output instead of the last displayed turn.
|
|
19
|
+
- Fixed streamed code blocks losing lines that scrolled off screen before the closing fence arrived; completed lines now remain available in scrollback. ([#17333](https://github.com/can1357/oh-my-pi/pull/17333) by [@gzkGit777](https://github.com/gzkGit777))
|
|
20
|
+
|
|
21
|
+
## [18.13.3] - 2026-10-28
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- The resume picker renames the selected session in place: F2 opens a dialog prefilled with the current title, Enter commits, Esc cancels ([#17262](https://github.com/can1357/oh-my-pi/pull/17262) by [@Twilight0](https://github.com/Twilight0))
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Updated Bun engine requirement to ≥1.4.4
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Restored WebP and JPEG images stay visible in Kitty scrollback after resuming a session ([#17220](https://github.com/can1357/oh-my-pi/issues/17220)).
|
|
34
|
+
- Escape in an annotation note no longer discards it: the overlay closes and `getDraft()`/`restoreDraft()` let the host keep and reopen the note; **Discard notes and close** (confirmed by a second press) clears them instead, and code review's actions start on Paste so a stray Enter never sends the LLM review ([#17271](https://github.com/can1357/oh-my-pi/pull/17271) by [@H4vC](https://github.com/H4vC), based on [#17230](https://github.com/can1357/oh-my-pi/pull/17230) by [@Shadorain](https://github.com/Shadorain)).
|
|
35
|
+
- Fixed terminal replies such as Tern's `tsp;e;{"ev":"ack",…}` showing up in the shell prompt after quitting omp; the exit drain now waits for the terminal to answer a final DA1 sentinel
|
|
36
|
+
- Fixed the plan review sheet in Tern squeezing the "continue with" model tiers under a long plan, so the model name overlapped the tier buttons
|
|
37
|
+
- `/usage` in Tern shows when each quota resets as a countdown (`resets in 2h30m`) instead of a clock time; hovering shows the date and time
|
|
38
|
+
- Fixed extension `ui.select` dialogs treating unconfigured `j`/`k` keys as navigation, which could turn a default No into Yes when typing `ok` then Enter ([#17255](https://github.com/can1357/oh-my-pi/pull/17255) by [@SAKANA-MOONLIGHT](https://github.com/SAKANA-MOONLIGHT)).
|
|
39
|
+
|
|
40
|
+
### Removed
|
|
41
|
+
|
|
42
|
+
- Removed support for the TSP `t` (theme) verb, as surface theme synchronization is no longer required
|
|
43
|
+
|
|
5
44
|
## [18.13.2] - 2026-10-27
|
|
6
45
|
|
|
7
46
|
### Added
|
|
@@ -2435,57 +2474,4 @@
|
|
|
2435
2474
|
- 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.
|
|
2436
2475
|
- 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.
|
|
2437
2476
|
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
### Added
|
|
2441
|
-
|
|
2442
|
-
- Added `PI_NO_SYNC_OUTPUT=1` to disable DEC 2026 synchronized-output wrappers for terminals whose implementation is buggy or visually worse, while keeping the renderer's autowrap guards active during paints ([#1765](https://github.com/can1357/oh-my-pi/issues/1765)).
|
|
2443
|
-
|
|
2444
|
-
### Fixed
|
|
2445
|
-
|
|
2446
|
-
- Fixed terminal resizes that land in the same render frame as streamed output splicing a phantom blank row into native scrollback and offsetting every later row by one. A height shrink (or width change carrying an append) with content overflowing the viewport fell through to the differential emitter, whose scroll math is anchored to the pre-resize viewport top and hardware-cursor row — both invalidated by the terminal's own resize reflow. Geometry-changed frames now rebuild native history when the viewport is at (or possibly at) the bottom, and defer non-destructively for a reader confirmed scrolled into history.
|
|
2447
|
-
- Fixed Ghostty/kitty/Alacritty-style ED3-risk terminals freezing the prompt after a deferred shrink; focused keyboard input now uses the same explicit user-input viewport opt-in as autocomplete and can repaint immediately instead of waiting for a resize.
|
|
2448
|
-
- Deferred eager live scrollback rebuilds under WSL fronted by Windows Terminal (`WT_SESSION` present in a Linux environment) so foreground streaming no longer emits ED3 (`CSI 3 J`) and yanks a reader scrolled into Windows Terminal's host scrollback; deferred rewrites still reconcile at the next prompt-submit checkpoint ([#1610](https://github.com/can1357/oh-my-pi/issues/1610)).
|
|
2449
|
-
- Fixed tmux (and screen/zellij) pane history gaining a complete duplicate copy of the transcript every time a deferred offscreen edit was followed by another render. Multiplexer panes never receive a destructive scrollback clear, so the dirty-scrollback rebuild path only appended the full transcript on top of preserved pane history — repeatedly. Live frames inside multiplexers now keep repainting the viewport and leave history reconciliation to explicit checkpoints, which also removes the O(transcript) write amplification per frame.
|
|
2450
|
-
- Fixed tmux pane viewports corrupting and pane history duplicating when a resize coincides with rendering: a resize racing a streamed append reached the stale-anchor diff emitters (phantom rows in the pane), a forced render racing a resize replayed the whole transcript into preserved pane history, and the prompt-submit checkpoint did the same after any deferred offscreen edit. Geometry-changed frames inside multiplexers now repaint the viewport in place, and forced-render geometry replays plus checkpoint replays are disabled there — tmux reflows its own pane grid and its history cannot be cleared, only duplicated.
|
|
2451
|
-
- Fixed terminal resize events whose dimensions net out unchanged by render time (rapid SIGWINCH round trips during a window drag, coalesced into one 16ms frame) being invisible to the renderer. The terminal reflows its buffer on every resize event — rows move between the viewport and scrollback and can be evicted at the scrollback cap — so diffing against the pre-resize screen splices blank phantom rows into the viewport. The renderer now tracks the resize event itself, not just the dimension delta, and routes such frames through the geometry-change repaint/rebuild paths.
|
|
2452
|
-
- Fixed Termux terminal resizes (screen rotation or software-keyboard toggles) displacing or hiding output after the viewport height changed. Content-bearing resizes were routed to the differential emitter, whose scroll math is anchored to the pre-resize viewport, so appended rows landed too low; pure height changes were treated as no-ops, exposing blank rows that later appends could fill without growing native scrollback. Termux resizes now repaint or rebuild at the new geometry like every other non-multiplexer terminal.
|
|
2453
|
-
- Fixed the turn-end teardown frame freezing on ED3-risk terminals (Ghostty/kitty/Alacritty/iTerm2): disabling eager scrollback rebuild now takes effect only after the in-flight frame is classified, so the loader/status removal still paints instead of deferring and leaving a stale spinner until the next keystroke.
|
|
2454
|
-
- Fixed non-WT ConPTY terminals on Windows (Tabby, Hyper, VS Code, conhost) clearing scrollback and yanking the viewport to the top whenever streaming output or a prompt-submit rebuild arrived while the user was scrolled up. The kernel32 viewport probe describes the ConPTY pseudo-console buffer — which is pinned to the visible grid, invisible to host-UI scrollback — so it reported "at bottom" no matter where the user had scrolled, and the [#1635](https://github.com/can1357/oh-my-pi/issues/1635) fix only distrusted it under `WT_SESSION`, which Tabby and other ConPTY hosts never set. The probe is now removed entirely: every Windows host is treated as viewport-unobservable, live mutations defer destructive rebuilds (no `\x1b[3J`, no viewport movement), and native scrollback reconciles at the prompt-submit checkpoint where the Enter keystroke has already pinned the host viewport to the bottom ([#1746](https://github.com/can1357/oh-my-pi/issues/1746)).
|
|
2455
|
-
- Fixed emoji-presentation symbols (a default-text symbol followed by variation-selector-16 `U+FE0F`, e.g. `⚠️`, `ℹ️`, `❤️`, keycaps) measuring as 1 cell instead of 2 in the native width engine on macOS. The native scanner now keeps `UnicodeWidthStr` as the source of truth for multi-codepoint graphemes and applies only the local macOS Hangul Compatibility Jamo character-width delta, preserving VS16/keycap sequence widths without reintroducing jamo cursor drift.
|
|
2456
|
-
- Deferred eager live scrollback rebuilds on macOS Terminal.app and iTerm2 so assistant/tool streaming no longer emits ED3 (`CSI 3 J`) while their native viewport position is unobservable, preserving readers scrolled into terminal history ([#1300](https://github.com/can1357/oh-my-pi/issues/1300)).
|
|
2457
|
-
- Fixed width-shrink reflow leaving old-width rows in native history so later appends no longer undercount scrollback growth or duplicate wrapped content.
|
|
2458
|
-
- Fixed hiding overlays after terminal reflow so stale dialog rows are scrubbed from native scrollback on non-multiplexer terminals.
|
|
2459
|
-
|
|
2460
|
-
### Removed
|
|
2461
|
-
|
|
2462
|
-
- Removed `shouldTrustNativeViewportProbe` and `ProcessTerminal`'s kernel32 `GetConsoleScreenBufferInfo` viewport probe. No Windows environment can answer "is the user's viewport at the bottom" truthfully — under ConPTY (every modern host) the pseudo-console buffer is pinned to the visible grid so the probe always read "at bottom", and under legacy conhost the window tracks the output cursor rather than the buffer tail so it always read "scrolled up" — so the probe and its trust gate are gone; `ProcessTerminal` no longer implements the optional `Terminal.isNativeViewportAtBottom`.
|
|
2463
|
-
|
|
2464
|
-
## [15.8.1] - 2026-06-02
|
|
2465
|
-
|
|
2466
|
-
### Fixed
|
|
2467
|
-
|
|
2468
|
-
- Deferred eager live scrollback rebuilds on VTE terminals so GNOME-style Linux terminals do not flash or erase readable scrollback during streaming ([#1719](https://github.com/can1357/oh-my-pi/issues/1719)).
|
|
2469
|
-
|
|
2470
|
-
## [15.8.0] - 2026-06-02
|
|
2471
|
-
|
|
2472
|
-
### Fixed
|
|
2473
|
-
|
|
2474
|
-
- Deferred eager live scrollback rebuilds on POSIX terminals where xterm ED3 (`CSI 3 J`, erase saved lines) can disturb scrolled-up readers during streaming, while keeping direct user-input and checkpoint rebuilds explicit ([#1682](https://github.com/can1357/oh-my-pi/issues/1682)).
|
|
2475
|
-
- Fixed TUI shutdown placing the parent shell prompt one row below short rendered content instead of directly on the next line ([#1620](https://github.com/can1357/oh-my-pi/issues/1620)).
|
|
2476
|
-
- Stopped painting inline color swatches for 4-digit hex runs in Markdown rendering. The `#RGBA` CSS form collides with hashline `#TAG` snapshot tags (4 hex digits, e.g. `#6C5E`), which were sprouting spurious RGB swatches in prose and codespans. Only `#RGB`, `#RRGGBB`, and `#RRGGBBAA` qualify now.
|
|
2477
|
-
|
|
2478
|
-
## [15.7.6] - 2026-06-01
|
|
2479
|
-
|
|
2480
|
-
### Fixed
|
|
2481
|
-
|
|
2482
|
-
- Fixed native Windows + Windows Terminal freezing the editor on the wrap keystroke, on `/plan`/`/resume`/model-switch/status-line toggles, and on any other offscreen structural mutation until the next prompt submit. The `15.7.5` `#1635` fix routed every viewport-saturating pure-append and structural mutation through `deferredMutation` (a literal no-op) whenever `isNativeViewportAtBottom()` returned `undefined` — which it always does under `WT_SESSION` because the kernel32 probe can't see WT host scrollback. The deferral was only ever meant for the *confirmed-scrolled* case; an unknown viewport now falls back to a non-destructive `viewportRepaint` instead, so the live UI keeps updating without emitting `\x1b[3J` and without yanking a possibly-scrolled reader. Confirmed-scrolled frames (probe returns `false`) still defer.
|
|
2483
|
-
- Removed the hard-coded 20-result cap on `@`-prefixed fuzzy file completion in `CombinedAutocompleteProvider.#getFuzzyFileSuggestions`. The dropdown now honors the existing `maxResults: 100` ceiling already configured for `fuzzyFind`, so projects with many files sharing a common stem (e.g. `@controller`, `@test`) surface all relevant matches instead of being silently truncated. ([#1652](https://github.com/can1357/oh-my-pi/issues/1652))
|
|
2484
|
-
|
|
2485
|
-
## [15.7.5] - 2026-06-01
|
|
2486
|
-
|
|
2487
|
-
### Fixed
|
|
2488
|
-
|
|
2489
|
-
- Fixed native Windows + Windows Terminal scrollback being yanked to the top when a streaming response triggered a TUI full redraw. Under ConPTY the `kernel32` `GetConsoleScreenBufferInfo` probe answers about the pseudo-console (always at the buffer tail) and not about WT's host scrollback, so `isNativeViewportAtBottom()` falsely returned `true` while the user was scrolled up and the shrink-across-viewport branch issued a destructive `historyRebuild` (`\x1b[2J\x1b[H\x1b[3J`). The probe now short-circuits to `undefined` whenever `WT_SESSION` is set, letting the existing deferred-rebuild path keep streaming-time mutations non-destructive and reconcile native history at the next prompt-submit checkpoint. ([#1635](https://github.com/can1357/oh-my-pi/issues/1635))
|
|
2490
|
-
|
|
2491
|
-
Older entries are archived in [packages/tui/CHANGELOG.md@3d45d8557cd7](https://github.com/can1357/oh-my-pi/blob/3d45d8557cd7493221b69c7ed3c6b6a2307f46e7/packages/tui/CHANGELOG.md).
|
|
2477
|
+
Older entries are archived in [packages/tui/CHANGELOG.md@6693ddbfd58c](https://github.com/can1357/oh-my-pi/blob/6693ddbfd58ce9edcdc0dc3fe98a8882c9bae834/packages/tui/CHANGELOG.md).
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ const tui = new TUI(terminal);
|
|
|
28
28
|
tui.addChild(new Text("Welcome to my app!"));
|
|
29
29
|
|
|
30
30
|
const editor = new Editor(editorTheme);
|
|
31
|
-
editor.onSubmit =
|
|
31
|
+
editor.onSubmit = text => {
|
|
32
32
|
console.log("Submitted:", text);
|
|
33
33
|
tui.addChild(new Text(`You said: ${text}`));
|
|
34
34
|
};
|
|
@@ -106,12 +106,12 @@ interface Component {
|
|
|
106
106
|
}
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
| Method | Description
|
|
110
|
-
| ------------------------ |
|
|
109
|
+
| Method | Description |
|
|
110
|
+
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
111
111
|
| `render(width)` | Returns an array of strings, one per line. Each line **must not exceed `width`** or the TUI will error. Use `truncateToWidth()` or manual wrapping to ensure this. The result is component-owned and immutable to callers; return the same array reference when unchanged (enables renderer memoization) and a new array when content changed. |
|
|
112
|
-
| `handleInput?(data)` | Called when the component has focus and receives keyboard input. The `data` string contains raw terminal input (may include ANSI escape sequences).
|
|
113
|
-
| `invalidate?()` | Called to clear any cached render state. Components should re-render from scratch on the next `render()` call.
|
|
114
|
-
| `releaseRenderCaches?()` | Drops only derived render caches. The next `render()` must return the same rows without eager rebuilds, renderer callbacks, image conversions, or child replacement.
|
|
112
|
+
| `handleInput?(data)` | Called when the component has focus and receives keyboard input. The `data` string contains raw terminal input (may include ANSI escape sequences). |
|
|
113
|
+
| `invalidate?()` | Called to clear any cached render state. Components should re-render from scratch on the next `render()` call. |
|
|
114
|
+
| `releaseRenderCaches?()` | Drops only derived render caches. The next `render()` must return the same rows without eager rebuilds, renderer callbacks, image conversions, or child replacement. |
|
|
115
115
|
|
|
116
116
|
## Built-in Components
|
|
117
117
|
|
|
@@ -119,20 +119,20 @@ interface Component {
|
|
|
119
119
|
|
|
120
120
|
Build screens from persistent components and update their data, selection, expansion, or size through setters. Layouts own child bounds and mouse-coordinate translation; controllers retain domain workflows and asynchronous operations. Propagate `invalidate()` after theme changes and `dispose()` when removing an owned component tree.
|
|
121
121
|
|
|
122
|
-
| Family
|
|
123
|
-
|
|
|
124
|
-
| Layout
|
|
125
|
-
| Panels
|
|
126
|
-
| Menus
|
|
127
|
-
| Forms
|
|
128
|
-
| Wizard steps | `WizardStep`
|
|
129
|
-
| Viewports
|
|
130
|
-
| Trees
|
|
131
|
-
| Disclosure
|
|
132
|
-
| Messages
|
|
133
|
-
| Tool output
|
|
134
|
-
| Transcripts
|
|
135
|
-
| Data
|
|
122
|
+
| Family | Components | Import |
|
|
123
|
+
| ------------ | ------------------------------------------------------------------------------- | ------------ |
|
|
124
|
+
| Layout | `Stack`, `Row`, `SplitPane` | package root |
|
|
125
|
+
| Panels | `OverlayPanel`, `PanelRows`, `PanelDivider` | `/chrome` |
|
|
126
|
+
| Menus | `SelectList`, `MenuSelection` | package root |
|
|
127
|
+
| Forms | `Form`, `FormField`, `TextFormField`, `SelectFormField`, `SettingsFormField` | package root |
|
|
128
|
+
| Wizard steps | `WizardStep` | package root |
|
|
129
|
+
| Viewports | `ScrollView`, including child rendering, follow-tail, and keyed range anchoring | package root |
|
|
130
|
+
| Trees | `TreeView` | package root |
|
|
131
|
+
| Disclosure | `Disclosure`, with lazy summary/detail children | package root |
|
|
132
|
+
| Messages | `FramedMessageComponent`, `MessageNoticeComponent`, `MessageDividerComponent` | `/chrome` |
|
|
133
|
+
| Tool output | `ToolCard`, `framedToolCard`, `plainToolCard`, `OutputPane` | `/render` |
|
|
134
|
+
| Transcripts | `TranscriptBrowser` | package root |
|
|
135
|
+
| Data | `MetricRow`, `ProgressBar`, `Table`, `KeyValueList`, `Section` | package root |
|
|
136
136
|
|
|
137
137
|
```typescript
|
|
138
138
|
import { Disclosure, SplitPane, Text } from "@oh-my-pi/pi-tui";
|
|
@@ -176,10 +176,10 @@ Container that applies padding and background color to all children.
|
|
|
176
176
|
const box = new Box(
|
|
177
177
|
1, // paddingX (default: 1)
|
|
178
178
|
1, // paddingY (default: 1)
|
|
179
|
-
|
|
179
|
+
text => chalk.bgGray(text), // optional background function
|
|
180
180
|
);
|
|
181
181
|
box.addChild(new Text("Content"));
|
|
182
|
-
box.setBgFn(
|
|
182
|
+
box.setBgFn(text => chalk.bgBlue(text)); // Change background dynamically
|
|
183
183
|
```
|
|
184
184
|
|
|
185
185
|
### Text
|
|
@@ -191,10 +191,10 @@ const text = new Text(
|
|
|
191
191
|
"Hello World", // text content
|
|
192
192
|
1, // paddingX (default: 1)
|
|
193
193
|
1, // paddingY (default: 1)
|
|
194
|
-
|
|
194
|
+
text => chalk.bgGray(text), // optional background function
|
|
195
195
|
);
|
|
196
196
|
text.setText("Updated text");
|
|
197
|
-
text.setCustomBgFn(
|
|
197
|
+
text.setCustomBgFn(text => chalk.bgBlue(text));
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
### TruncatedText
|
|
@@ -215,7 +215,7 @@ Single-line text input with horizontal scrolling.
|
|
|
215
215
|
|
|
216
216
|
```typescript
|
|
217
217
|
const input = new Input();
|
|
218
|
-
input.onSubmit =
|
|
218
|
+
input.onSubmit = value => console.log(value);
|
|
219
219
|
input.setValue("initial");
|
|
220
220
|
input.getValue();
|
|
221
221
|
```
|
|
@@ -285,11 +285,11 @@ interface EditorTheme {
|
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
const editor = new Editor(theme);
|
|
288
|
-
editor.onSubmit =
|
|
289
|
-
editor.onChange =
|
|
288
|
+
editor.onSubmit = text => console.log(text);
|
|
289
|
+
editor.onChange = text => console.log("Changed:", text);
|
|
290
290
|
editor.disableSubmit = true; // Disable submit temporarily
|
|
291
291
|
editor.setAutocompleteProvider(provider);
|
|
292
|
-
editor.borderColor =
|
|
292
|
+
editor.borderColor = s => chalk.blue(s); // Change border dynamically
|
|
293
293
|
```
|
|
294
294
|
|
|
295
295
|
**Features:**
|
|
@@ -371,8 +371,8 @@ Animated loading spinner.
|
|
|
371
371
|
```typescript
|
|
372
372
|
const loader = new Loader(
|
|
373
373
|
tui, // TUI instance for render updates
|
|
374
|
-
|
|
375
|
-
|
|
374
|
+
s => chalk.cyan(s), // spinner color function
|
|
375
|
+
s => chalk.gray(s), // message color function
|
|
376
376
|
"Loading...", // message (default: "Loading...")
|
|
377
377
|
);
|
|
378
378
|
loader.start();
|
|
@@ -387,8 +387,8 @@ Extends Loader with Escape key handling and an AbortSignal for cancelling async
|
|
|
387
387
|
```typescript
|
|
388
388
|
const loader = new CancellableLoader(
|
|
389
389
|
tui, // TUI instance for render updates
|
|
390
|
-
|
|
391
|
-
|
|
390
|
+
s => chalk.cyan(s), // spinner color function
|
|
391
|
+
s => chalk.gray(s), // message color function
|
|
392
392
|
"Working...", // message
|
|
393
393
|
);
|
|
394
394
|
loader.onAbort = () => done(null); // Called when user presses Escape
|
|
@@ -430,9 +430,9 @@ const list = new SelectList(
|
|
|
430
430
|
theme, // SelectListTheme
|
|
431
431
|
);
|
|
432
432
|
|
|
433
|
-
list.onSelect =
|
|
433
|
+
list.onSelect = item => console.log("Selected:", item);
|
|
434
434
|
list.onCancel = () => console.log("Cancelled");
|
|
435
|
-
list.onSelectionChange =
|
|
435
|
+
list.onSelectionChange = item => console.log("Highlighted:", item);
|
|
436
436
|
list.setFilter("opt"); // Filter items
|
|
437
437
|
```
|
|
438
438
|
|
|
@@ -39,10 +39,13 @@ interface AppKeybindings {
|
|
|
39
39
|
"app.session.rename": true;
|
|
40
40
|
"app.session.delete": true;
|
|
41
41
|
"app.session.deleteNoninvasive": true;
|
|
42
|
+
"app.session.pin": true;
|
|
43
|
+
"app.session.unpin": true;
|
|
42
44
|
"app.tree.previousBranch": true;
|
|
43
45
|
"app.tree.nextBranch": true;
|
|
44
46
|
"app.plan.toggle": true;
|
|
45
47
|
"app.history.search": true;
|
|
48
|
+
"app.links.hint": true;
|
|
46
49
|
"app.stt.pushToTalk": true;
|
|
47
50
|
"app.stt.toggle": true;
|
|
48
51
|
"app.live.toggle": true;
|
|
@@ -329,6 +332,14 @@ export declare const KEYBINDINGS: {
|
|
|
329
332
|
readonly defaultKeys: "ctrl+backspace";
|
|
330
333
|
readonly description: "Delete session (non-invasive)";
|
|
331
334
|
};
|
|
335
|
+
readonly "app.session.pin": {
|
|
336
|
+
readonly defaultKeys: "alt+k";
|
|
337
|
+
readonly description: "Pin the selected session in the resume picker";
|
|
338
|
+
};
|
|
339
|
+
readonly "app.session.unpin": {
|
|
340
|
+
readonly defaultKeys: "alt+shift+k";
|
|
341
|
+
readonly description: "Unpin the selected session in the resume picker";
|
|
342
|
+
};
|
|
332
343
|
readonly "app.tree.previousBranch": {
|
|
333
344
|
readonly defaultKeys: [];
|
|
334
345
|
readonly description: "Jump to the previous branch in /tree";
|
|
@@ -345,6 +356,10 @@ export declare const KEYBINDINGS: {
|
|
|
345
356
|
readonly defaultKeys: "ctrl+r";
|
|
346
357
|
readonly description: "Search history";
|
|
347
358
|
};
|
|
359
|
+
readonly "app.links.hint": {
|
|
360
|
+
readonly defaultKeys: "alt+o";
|
|
361
|
+
readonly description: "Pick an extension link on screen by its hint tag";
|
|
362
|
+
};
|
|
348
363
|
readonly "app.stt.pushToTalk": {
|
|
349
364
|
readonly defaultKeys: "space";
|
|
350
365
|
readonly description: "Hold to record speech-to-text";
|
|
@@ -4,6 +4,9 @@ export interface SessionPickerHost<T extends SessionSelectorEntry = SessionSelec
|
|
|
4
4
|
loadPinnedIds?(): Promise<ReadonlySet<string>>;
|
|
5
5
|
loadHistoryMatcher?(): SessionHistoryMatcher;
|
|
6
6
|
deleteSession?(session: T): Promise<boolean>;
|
|
7
|
+
/** Rename the session and resolve with the title as stored, or null when it did not happen. */
|
|
8
|
+
renameSession?(session: T, title: string): Promise<string | null>;
|
|
9
|
+
setSessionPinned?(session: T, pinned: boolean): Promise<void>;
|
|
7
10
|
loadAllSessions?(): Promise<T[]>;
|
|
8
11
|
}
|
|
9
12
|
/** Presentation and capability controls for the standalone session picker. */
|
|
@@ -13,6 +16,8 @@ export interface SessionPickerOptions<T extends SessionSelectorEntry = SessionSe
|
|
|
13
16
|
scopeLabel?: string | false;
|
|
14
17
|
showCwd?: boolean;
|
|
15
18
|
allowDelete?: boolean;
|
|
19
|
+
/** Rename the selected session; resolve with the title as stored, or null when it did not happen. */
|
|
20
|
+
onRename?: (session: T, title: string) => Promise<string | null>;
|
|
16
21
|
allowGlobalScope?: boolean;
|
|
17
22
|
historySearch?: boolean;
|
|
18
23
|
pinnedIds?: ReadonlySet<string>;
|
|
@@ -419,9 +419,10 @@ export type ChartAnnotation = {
|
|
|
419
419
|
export declare function planChart(table: TableAnalysis): ChartPlan | undefined;
|
|
420
420
|
/**
|
|
421
421
|
* Whether a model should pick `table`'s chart (`tui.autoGraph: smart`):
|
|
422
|
-
* multi-series tables,
|
|
423
|
-
* `guess` plots (`Thread | State`, `Finding | Current`),
|
|
424
|
-
* tells a
|
|
422
|
+
* multi-series tables, tables whose rows may be named by a number the
|
|
423
|
+
* `guess` plots (`Thread | State`, `Finding | Current`), and any other chart
|
|
424
|
+
* the guess would draw — only meaning tells a measure from page references,
|
|
425
|
+
* step numbers or figures quoted in prose, which the judge charts as none.
|
|
425
426
|
*/
|
|
426
427
|
export declare function shouldJudge(table: TableAnalysis, guess: ChartPlan | undefined): boolean;
|
|
427
428
|
/** Measure columns before `guess`'s text label column: numbers that may only name their rows. */
|
|
@@ -446,10 +447,11 @@ export declare function tableTakeaways(table: TableAnalysis, plan: ChartPlan, co
|
|
|
446
447
|
*/
|
|
447
448
|
export declare function drawnNames(spec: ChartSpec): Set<string>;
|
|
448
449
|
/**
|
|
449
|
-
* The local guess at what `plan`'s rows and measures mean:
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
* `(current)` row names, and a status
|
|
450
|
+
* The local guess at what `plan`'s rows and measures mean: each measure's
|
|
451
|
+
* {@link Polarity} as far as its unit says ({@link dimPolarity}; what a name
|
|
452
|
+
* means — `Memory` as a capacity or a cost — is the judge's call), rivals from
|
|
453
|
+
* the label's header, focus from bolded or `(current)` row names, and a status
|
|
454
|
+
* column whose cells vary.
|
|
453
455
|
*/
|
|
454
456
|
export declare function guessMeaning(table: TableAnalysis, plan: ChartPlan): Pick<ChartPlan, "polarity" | "rowPolarity" | "rivals" | "focus" | "status">;
|
|
455
457
|
/** Whether `plan`'s rows may each be a metric of their own: a `change`, a transposed table, or mixed-unit columns. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AssistantMessage, ImageContent } from "@oh-my-pi/pi-ai";
|
|
2
2
|
import { type Component, Container } from "../tui.js";
|
|
3
3
|
import { type ImageBudget } from "../components/image.js";
|
|
4
|
-
import type { AssistantThinkingRenderer } from "./extension-types.js";
|
|
4
|
+
import type { AssistantTextRenderer, AssistantTextRendering, AssistantThinkingRenderer } from "./extension-types.js";
|
|
5
5
|
import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node.js";
|
|
6
6
|
import { type CacheInvalidation } from "./cache-invalidation-marker.js";
|
|
7
7
|
import { type ServedModelMismatch } from "./served-model-marker.js";
|
|
@@ -38,7 +38,7 @@ export declare class AssistantMessageComponent extends Container {
|
|
|
38
38
|
* for lack of a target is re-rendered with its reaction stripped.
|
|
39
39
|
*/
|
|
40
40
|
pickReactionTarget(transcript: readonly Component[]): void;
|
|
41
|
-
constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, onImageUpdate?: () => void, thinkingRenderers?: readonly AssistantThinkingRenderer[], imageBudget?: ImageBudget, proseOnlyThinking?: boolean, linkTargets?: ReadonlyMap<string, string>, expandThinkingBlocks?: boolean);
|
|
41
|
+
constructor(message?: AssistantMessage, hideThinkingBlock?: boolean, onImageUpdate?: () => void, thinkingRenderers?: readonly AssistantThinkingRenderer[], imageBudget?: ImageBudget, proseOnlyThinking?: boolean, linkTargets?: ReadonlyMap<string, string>, expandThinkingBlocks?: boolean, textRendering?: AssistantTextRendering);
|
|
42
42
|
/**
|
|
43
43
|
* Show or clear the trailing cache-invalidation divider. Set at `message_end`
|
|
44
44
|
* (live) or during rebuild, once the turn's usage is known and compared
|
|
@@ -87,7 +87,7 @@ export declare class AssistantMessageComponent extends Container {
|
|
|
87
87
|
*/
|
|
88
88
|
setExpanded(expanded: boolean): void;
|
|
89
89
|
isTranscriptBlockFinalized(): boolean;
|
|
90
|
-
/**
|
|
90
|
+
/** Hold image and figure rendering until the completed block can enter immutable scrollback. */
|
|
91
91
|
isTranscriptBlockPending(): boolean;
|
|
92
92
|
render(width: number): readonly string[];
|
|
93
93
|
/**
|
|
@@ -122,7 +122,19 @@ export declare class AssistantMessageComponent extends Container {
|
|
|
122
122
|
renderTranscriptBlockEmergencyRow(width: number): string | undefined;
|
|
123
123
|
getTranscriptBlockVersion(): number;
|
|
124
124
|
markTranscriptBlockFinalized(): void;
|
|
125
|
+
/**
|
|
126
|
+
* Swap the extension text renderers (the setting enabling them changed) and redraw with them.
|
|
127
|
+
* Enabling them also drops rows already published as stable, since a renderer may rewrite them;
|
|
128
|
+
* callers MUST pair this with a scrollback-clearing display reset, as for
|
|
129
|
+
* {@link resetTranscriptStableRows}.
|
|
130
|
+
*/
|
|
131
|
+
setTextRenderers(renderers: readonly AssistantTextRenderer[]): void;
|
|
125
132
|
applyRetryRecovery(retryRecovery: AssistantMessage["retryRecovery"]): void;
|
|
133
|
+
/**
|
|
134
|
+
* Draw the current message again when it is the reply sent at `timestamp`, re-running the
|
|
135
|
+
* extension text renderers; returns whether it was. The caller schedules the frame.
|
|
136
|
+
*/
|
|
137
|
+
rerenderMessage(timestamp: number): boolean;
|
|
126
138
|
messagePersistenceKey(): string | undefined;
|
|
127
139
|
/** Toggle rendering for assistant-native and tool-result images. */
|
|
128
140
|
setImagesVisible(visible: boolean): void;
|
|
@@ -37,6 +37,8 @@ export declare class BashExecutionComponent extends Container {
|
|
|
37
37
|
appendOutput(chunk: string): void;
|
|
38
38
|
/** Switch to PTY rendering and feed raw terminal bytes through the vterm replay. */
|
|
39
39
|
appendPtyChunk(chunk: string): void;
|
|
40
|
+
/** Bytes a terminal would send for a key event, honoring the command's cursor-key mode; "" for key releases. */
|
|
41
|
+
encodePtyInput(data: string): string;
|
|
40
42
|
setComplete(exitCode: number | undefined, cancelled: boolean, options?: {
|
|
41
43
|
output?: string;
|
|
42
44
|
truncation?: TruncationMeta;
|
|
@@ -6,6 +6,8 @@ export interface ChatTranscriptDisplayPreferences {
|
|
|
6
6
|
cacheMissMarker: boolean;
|
|
7
7
|
showTokenUsage: boolean;
|
|
8
8
|
showTurnTime: boolean;
|
|
9
|
+
/** Max rows a collapsed advisor card shows below its header; 0 = no cap. */
|
|
10
|
+
advisorCollapsedLines: number;
|
|
9
11
|
}
|
|
10
12
|
/** Current transcript display preferences. */
|
|
11
13
|
export declare const chatTranscriptDisplayPreferences: ChatTranscriptDisplayPreferences;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
1
2
|
import type { Component, TUI } from "../tui.js";
|
|
2
3
|
import type { Theme } from "../theme/theme.js";
|
|
3
4
|
import type { CustomMessage, HookMessage } from "./messages.js";
|
|
@@ -17,6 +18,36 @@ export interface AssistantThinkingRenderContext {
|
|
|
17
18
|
requestRender(): void;
|
|
18
19
|
}
|
|
19
20
|
export type AssistantThinkingRenderer = (context: AssistantThinkingRenderContext, theme: Theme) => Component | undefined;
|
|
21
|
+
export interface AssistantTextRenderContext {
|
|
22
|
+
/**
|
|
23
|
+
* The message being drawn; `message.timestamp` identifies the reply for `ctx.ui.rerenderMessage()`.
|
|
24
|
+
* After a tool call this is only the segment drawn there, so its `content` does not hold the whole reply.
|
|
25
|
+
* A deep copy: editing it, at any depth, cannot change the stored reply.
|
|
26
|
+
*/
|
|
27
|
+
message: AssistantMessage;
|
|
28
|
+
/**
|
|
29
|
+
* The text block's index in the full reply's `content`, also when the reply is drawn in segments
|
|
30
|
+
* around tool calls; not an index into `message.content` for a segment. It counts the content as
|
|
31
|
+
* currently stored: a transcript rebuild that drops tool calls left without a result shifts later
|
|
32
|
+
* blocks down, so do not persist it as a permanent key.
|
|
33
|
+
*/
|
|
34
|
+
contentIndex: number;
|
|
35
|
+
/** The block's markdown as drawn so far, after any earlier renderer. */
|
|
36
|
+
text: string;
|
|
37
|
+
/** True while the block may still grow; false for its final render, a block sealed at a tool call, and later redraws. */
|
|
38
|
+
streaming: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Display-only transform of one assistant text block: returns the markdown to draw, or `undefined`
|
|
42
|
+
* to draw `context.text` unchanged. The session, exports and model context keep the original text.
|
|
43
|
+
*/
|
|
44
|
+
export type AssistantTextRenderer = (context: AssistantTextRenderContext) => string | undefined;
|
|
45
|
+
/** Extension text renderers for one assistant component, and where its content starts in the full reply. */
|
|
46
|
+
export interface AssistantTextRendering {
|
|
47
|
+
renderers: readonly AssistantTextRenderer[];
|
|
48
|
+
/** Index in the full reply's `content` of this component's first block; a segment after a tool call starts past it. */
|
|
49
|
+
contentOffset: number;
|
|
50
|
+
}
|
|
20
51
|
export interface HookMessageRenderOptions {
|
|
21
52
|
/** Whether the view is expanded */
|
|
22
53
|
expanded: boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replies: text the agent sends to a scheme whose writes are `reply`-scoped (`out://`)
|
|
3
|
+
* is its mid-turn message to the user, drawn as assistant prose so it can answer
|
|
4
|
+
* without ending its turn.
|
|
5
|
+
* - A `write` call to a reply URL draws as {@link ReplyWriteComponent}, streaming as the
|
|
6
|
+
* call's arguments arrive, instead of a tool card.
|
|
7
|
+
* - Text a tool's commands write there (`printf … > out://` in bash) arrives in the
|
|
8
|
+
* tool's result `details.replies` ({@link toolResultReplies}); transcripts draw each
|
|
9
|
+
* one as a prose block after the call ({@link replyDisplayMessage}).
|
|
10
|
+
*/
|
|
11
|
+
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
12
|
+
import type { ImageBudget } from "../components/image.js";
|
|
13
|
+
import { AssistantMessageComponent } from "./assistant-message.js";
|
|
14
|
+
import type { ToolExecutionHandle, ToolResultFrame } from "./tool-execution.js";
|
|
15
|
+
/**
|
|
16
|
+
* Whether a `toolName` call writes to a reply URL. `undefined` while streamed args cannot tell yet:
|
|
17
|
+
* no path so far, or a path that could still grow into a reply URL (`ou`, `out:/`). Callers holding
|
|
18
|
+
* final args treat `undefined` as `false`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isReplyWrite(toolName: string, args: unknown): boolean | undefined;
|
|
21
|
+
/** Display options of a reply block; the rest of its presentation follows the assistant prose defaults. */
|
|
22
|
+
export interface ReplyWriteOptions {
|
|
23
|
+
/** Repaint request for figures and images that finish loading after a render. */
|
|
24
|
+
readonly requestRender?: () => void;
|
|
25
|
+
readonly imageBudget?: ImageBudget;
|
|
26
|
+
/** Resolved local destinations of Markdown links, as for assistant text. */
|
|
27
|
+
readonly linkTargets?: ReadonlyMap<string, string>;
|
|
28
|
+
}
|
|
29
|
+
/** Replies a tool result carries in `details.replies` (text its commands wrote to a reply URL), oldest first. */
|
|
30
|
+
export declare function toolResultReplies(details: unknown): readonly string[];
|
|
31
|
+
/** Assistant message drawing reply text. No provider turn backs it, so its identity fields stay empty. */
|
|
32
|
+
export declare function replyDisplayMessage(text: string, errorMessage?: string): AssistantMessage;
|
|
33
|
+
/**
|
|
34
|
+
* A reply write ({@link isReplyWrite}) drawn as assistant prose. The call's lifecycle arrives
|
|
35
|
+
* through {@link ToolExecutionHandle}: streamed args grow the text, final args settle it, and
|
|
36
|
+
* the result seals the block, a failure showing its error under the text. It is a reply, not
|
|
37
|
+
* tool activity, so hiding tool activity leaves it on screen.
|
|
38
|
+
*/
|
|
39
|
+
export declare class ReplyWriteComponent extends AssistantMessageComponent implements ToolExecutionHandle {
|
|
40
|
+
#private;
|
|
41
|
+
constructor(options?: ReplyWriteOptions);
|
|
42
|
+
updateArgs(args: unknown): void;
|
|
43
|
+
setArgsComplete(): void;
|
|
44
|
+
setExecutionStarted(): void;
|
|
45
|
+
updateResult(result: ToolResultFrame, isPartial?: boolean): void;
|
|
46
|
+
parkAsBackground(): void;
|
|
47
|
+
seal(): void;
|
|
48
|
+
}
|
|
@@ -19,10 +19,11 @@ export interface TableChartRequest {
|
|
|
19
19
|
readonly guess: ChartPlan;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* Picks the chart for a
|
|
23
|
-
*
|
|
22
|
+
* Picks the chart for a table under `smart`: a plan, or `null` for no chart.
|
|
23
|
+
* A rejection falls back to the local guess; `undefined` (no judge to ask
|
|
24
|
+
* right now) keeps the guess at once, exactly as `always` would draw it.
|
|
24
25
|
*/
|
|
25
|
-
export type TableChartPlanner = (request: TableChartRequest) => Promise<ChartPlan | null
|
|
26
|
+
export type TableChartPlanner = (request: TableChartRequest) => Promise<ChartPlan | null> | undefined;
|
|
26
27
|
/**
|
|
27
28
|
* The chart under a table: its SVG, colored with figure tokens (`var(--accent)`, …)
|
|
28
29
|
* still to resolve; none; or a smart pick on its way (the promise settles once the cache holds it).
|
|
@@ -35,7 +35,6 @@ export interface ToolExecutionHandle extends Component {
|
|
|
35
35
|
setArgsComplete(toolCallId?: string): void;
|
|
36
36
|
setExecutionStarted(toolCallId?: string): void;
|
|
37
37
|
setExpanded(expanded: boolean): void;
|
|
38
|
-
setToolActivityVisible(visible: boolean): void;
|
|
39
38
|
/** Mark the call parked: it returned, but stays tracked for async job frames. */
|
|
40
39
|
parkAsBackground(): void;
|
|
41
40
|
/** Seal the block as final history and stop its animations. */
|
|
@@ -102,7 +101,7 @@ export declare class ToolExecutionComponent extends Container {
|
|
|
102
101
|
* component-scoped so the TUI reuses every other root subtree (issue #4377).
|
|
103
102
|
*/
|
|
104
103
|
tickSpinner(frame: number): void;
|
|
105
|
-
/**
|
|
104
|
+
/** Hold visible results until their figures and Kitty images are ready for immutable scrollback. */
|
|
106
105
|
isTranscriptBlockPending(): boolean;
|
|
107
106
|
/**
|
|
108
107
|
* Whether this block is ready to retire as immutable history. Partial
|
|
@@ -9,6 +9,7 @@ import { type TranscriptEntryLike as TranscriptEntry } from "./transcript-entry.
|
|
|
9
9
|
import type { SessionMessageEntryLike as SessionMessageEntry } from "./transcript-entry.js";
|
|
10
10
|
import { type ThemeColor } from "../theme/index.js";
|
|
11
11
|
import type { ChatTranscriptBuilder } from "./chat-transcript-builder.js";
|
|
12
|
+
import type { DescribeContext } from "../native/node.js";
|
|
12
13
|
/** One selectable transcript item: a message entry plus its rendered block range. */
|
|
13
14
|
export interface OutlineTarget {
|
|
14
15
|
/** Entry the selection resolves to; extended over trailing componentless tool results. */
|
|
@@ -63,6 +64,12 @@ export declare class OutlineRowCache {
|
|
|
63
64
|
export declare function appendOutlineEntries(builder: ChatTranscriptBuilder, entries: TranscriptEntry[]): OutlineTarget[];
|
|
64
65
|
/** Per-target "renders at least one non-blank row" flags at the given rows. */
|
|
65
66
|
export declare function outlineVisibility(childRows: readonly (readonly string[])[], targets: readonly OutlineTarget[]): boolean[];
|
|
67
|
+
/**
|
|
68
|
+
* Per-target "describes something that shows" flags: {@link outlineVisibility}
|
|
69
|
+
* for a TSP page, where blocks describe nodes instead of rendering rows. An
|
|
70
|
+
* empty `col`/`row` (an interrupted turn with no output) shows nothing.
|
|
71
|
+
*/
|
|
72
|
+
export declare function describedVisibility(blocks: readonly Component[], targets: readonly OutlineTarget[], cx: DescribeContext): boolean[];
|
|
66
73
|
/** Dotted horizontal rule with rounded corners, spanning the outline width. */
|
|
67
74
|
export declare function outlineRule(left: string, right: string, innerWidth: number, color?: ThemeColor, caption?: string): string;
|
|
68
75
|
/** Wrap pre-rendered rows in the dotted outline (rules above/below, `┆` sides). */
|
|
@@ -55,6 +55,8 @@ export declare function assistantHasVisibleContent(message: AssistantAgentMessag
|
|
|
55
55
|
export declare function splitAssistantMessageToolTimeline(message: AssistantAgentMessage): {
|
|
56
56
|
beforeTools: AssistantAgentMessage;
|
|
57
57
|
afterToolCalls: ReadonlyMap<string, AssistantAgentMessage>;
|
|
58
|
+
/** Index in `message.content` of each after-tool segment's first block, by tool-call id. */
|
|
59
|
+
contentOffsets: ReadonlyMap<string, number>;
|
|
58
60
|
hasToolCalls: boolean;
|
|
59
61
|
lastToolCallId?: string;
|
|
60
62
|
};
|
|
@@ -16,5 +16,6 @@ export * from "./shared.js";
|
|
|
16
16
|
export * from "./streaming-panel.js";
|
|
17
17
|
export * from "./tool-activity.js";
|
|
18
18
|
export * from "./transcript-container.js";
|
|
19
|
+
export * from "./transcript-notice.js";
|
|
19
20
|
export * from "./transcript-status.js";
|
|
20
21
|
export * from "./visual-truncate.js";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { TspText } from "@oh-my-pi/pi-wire";
|
|
2
|
+
import type { NativeNode } from "../native/node.js";
|
|
3
|
+
import type { Component } from "../tui.js";
|
|
4
|
+
import { TranscriptBlock } from "./transcript-container.js";
|
|
5
|
+
/** How loud an inline transcript notice is; a native terminal styles it as `omp.notice.<tone>`. */
|
|
6
|
+
export type NoticeTone = "info" | "success" | "warning" | "error";
|
|
7
|
+
/** Optional parts of a {@link noticeRow}. */
|
|
8
|
+
export interface NoticeRowOptions {
|
|
9
|
+
/** Icon name in place of the tone's own (`read` for a file read, `download` for an update). */
|
|
10
|
+
readonly icon?: string;
|
|
11
|
+
readonly key?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* One inline transcript notice for a native terminal (`omp.notice.<tone>`): a
|
|
15
|
+
* leading icon beside the wrapped message. Warnings, errors, background-job
|
|
16
|
+
* completions and prompt file reads all draw as this row, so they read alike.
|
|
17
|
+
* The tone colors the icon (an info notice keeps it quiet); the message spans
|
|
18
|
+
* carry emphasis only (`path`, `mono`, `dim`), never the tone itself.
|
|
19
|
+
*/
|
|
20
|
+
export declare function noticeRow(tone: NoticeTone, message: TspText, options?: NoticeRowOptions): NativeNode;
|
|
21
|
+
/**
|
|
22
|
+
* A transcript block that a native terminal draws as one {@link noticeRow}
|
|
23
|
+
* while a text terminal draws `ansi`.
|
|
24
|
+
*/
|
|
25
|
+
export declare class TranscriptNotice extends TranscriptBlock {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(native: NativeNode, ansi: readonly Component[]);
|
|
28
|
+
/**
|
|
29
|
+
* `showWarning` / `showError`: a blank row and the `Warning: …` / `Error: …`
|
|
30
|
+
* line in its color in a text terminal; natively the tone's icon and the
|
|
31
|
+
* message, the label left to the icon.
|
|
32
|
+
*/
|
|
33
|
+
static line(tone: "warning" | "error", message: string): TranscriptNotice;
|
|
34
|
+
describe(): NativeNode;
|
|
35
|
+
}
|