@oh-my-pi/pi-tui 18.13.3 → 18.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -41
- package/README.md +34 -34
- package/dist/types/app-keybindings.d.ts +15 -0
- package/dist/types/apps/session-picker.d.ts +1 -0
- package/dist/types/charts/chart-plan.d.ts +9 -7
- package/dist/types/chat/assistant-message.d.ts +14 -2
- 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 +0 -1
- 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 +6 -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/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/rewind-selector.d.ts +1 -1
- package/dist/types/overlays/session-selector.d.ts +9 -0
- 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/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 +3 -1
- package/package.json +9 -14
- package/src/app-keybindings.ts +15 -0
- package/src/apps/session-picker.ts +2 -0
- package/src/charts/chart-plan.ts +20 -50
- package/src/chat/assistant-message.ts +134 -18
- package/src/chat/background-tan-message.ts +4 -0
- package/src/chat/chat-transcript-builder.ts +58 -28
- package/src/chat/compaction-summary-message.ts +2 -1
- 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 +13 -10
- 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 +7 -0
- package/src/components/markdown.ts +116 -6
- package/src/hotkeys-markdown.ts +1 -0
- package/src/native/backend.ts +3 -2
- 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/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/rewind-selector.ts +29 -12
- package/src/overlays/session-selector.ts +113 -16
- package/src/prompt/composer.ts +213 -5
- 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/theme/defaults.json +1 -0
- package/src/theme/loader.ts +1 -1
- package/src/theme/theme.ts +2 -10
- 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/json-tree.ts +131 -41
- 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 +36 -13
- 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,22 @@
|
|
|
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
|
+
|
|
5
21
|
## [18.13.3] - 2026-10-28
|
|
6
22
|
|
|
7
23
|
### Added
|
|
@@ -2458,44 +2474,4 @@
|
|
|
2458
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.
|
|
2459
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.
|
|
2460
2476
|
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
### Added
|
|
2464
|
-
|
|
2465
|
-
- 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)).
|
|
2466
|
-
|
|
2467
|
-
### Fixed
|
|
2468
|
-
|
|
2469
|
-
- 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.
|
|
2470
|
-
- 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.
|
|
2471
|
-
- 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)).
|
|
2472
|
-
- 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.
|
|
2473
|
-
- 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.
|
|
2474
|
-
- 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.
|
|
2475
|
-
- 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.
|
|
2476
|
-
- 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.
|
|
2477
|
-
- 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)).
|
|
2478
|
-
- 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.
|
|
2479
|
-
- 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)).
|
|
2480
|
-
- Fixed width-shrink reflow leaving old-width rows in native history so later appends no longer undercount scrollback growth or duplicate wrapped content.
|
|
2481
|
-
- Fixed hiding overlays after terminal reflow so stale dialog rows are scrubbed from native scrollback on non-multiplexer terminals.
|
|
2482
|
-
|
|
2483
|
-
### Removed
|
|
2484
|
-
|
|
2485
|
-
- 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`.
|
|
2486
|
-
|
|
2487
|
-
## [15.8.1] - 2026-06-02
|
|
2488
|
-
|
|
2489
|
-
### Fixed
|
|
2490
|
-
|
|
2491
|
-
- 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)).
|
|
2492
|
-
|
|
2493
|
-
## [15.8.0] - 2026-06-02
|
|
2494
|
-
|
|
2495
|
-
### Fixed
|
|
2496
|
-
|
|
2497
|
-
- 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)).
|
|
2498
|
-
- 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)).
|
|
2499
|
-
- 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.
|
|
2500
|
-
|
|
2501
|
-
Older entries are archived in [packages/tui/CHANGELOG.md@3deb6751027b](https://github.com/can1357/oh-my-pi/blob/3deb6751027b11b10ac14b2a5c07303817276505/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";
|
|
@@ -6,6 +6,7 @@ export interface SessionPickerHost<T extends SessionSelectorEntry = SessionSelec
|
|
|
6
6
|
deleteSession?(session: T): Promise<boolean>;
|
|
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
|
+
setSessionPinned?(session: T, pinned: boolean): Promise<void>;
|
|
9
10
|
loadAllSessions?(): Promise<T[]>;
|
|
10
11
|
}
|
|
11
12
|
/** Presentation and capability controls for the standalone session picker. */
|
|
@@ -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
|
|
@@ -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;
|
|
@@ -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. */
|
|
@@ -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
|
+
}
|
|
@@ -1,24 +1,36 @@
|
|
|
1
|
+
import type { TspSpan } from "@oh-my-pi/pi-wire";
|
|
1
2
|
import type { NativeNode } from "../native/node.js";
|
|
2
3
|
import { type ThemeColor } from "../theme/index.js";
|
|
3
4
|
import { TranscriptBlock } from "./transcript-container.js";
|
|
4
|
-
|
|
5
|
+
import { type NoticeTone } from "./transcript-notice.js";
|
|
6
|
+
/** One themed run of a status row's terminal line. */
|
|
5
7
|
export interface TranscriptStatusPart {
|
|
6
8
|
readonly text: string;
|
|
7
9
|
readonly color: ThemeColor;
|
|
8
|
-
/** Glyph art (tree connectors) drawn only in rows; native terminals draw their own structure. */
|
|
9
|
-
readonly rowsOnly?: boolean;
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
11
|
+
/** A status row in a native terminal: its {@link noticeRow}'s tone, icon and message. */
|
|
12
|
+
export interface TranscriptStatusNative {
|
|
13
|
+
readonly tone: NoticeTone;
|
|
14
|
+
/** Icon name in place of the tone's own. */
|
|
15
|
+
readonly icon?: string;
|
|
16
|
+
readonly message: readonly TspSpan[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* One compact transcript status row: the terminal line's themed parts (joined
|
|
20
|
+
* by single spaces, glyphs and brackets included) and the same row natively.
|
|
21
|
+
*/
|
|
12
22
|
export interface TranscriptStatusRow {
|
|
13
23
|
readonly parts: readonly (TranscriptStatusPart | undefined)[];
|
|
14
24
|
readonly indent?: number;
|
|
25
|
+
readonly native: TranscriptStatusNative;
|
|
15
26
|
}
|
|
16
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Shared compact status block for background activity and prompt file reads:
|
|
29
|
+
* one themed line per row in a text terminal, one notice row per row natively
|
|
30
|
+
* (`omp.status-block`).
|
|
31
|
+
*/
|
|
17
32
|
export declare class TranscriptStatusBlock extends TranscriptBlock {
|
|
18
33
|
#private;
|
|
19
34
|
constructor(rows: readonly TranscriptStatusRow[]);
|
|
20
|
-
/** Append a supplemental line such as an artifact warning. */
|
|
21
|
-
addLine(parts: readonly (TranscriptStatusPart | undefined)[], indent?: number): void;
|
|
22
|
-
/** One wrapped text line per status row. */
|
|
23
35
|
describe(): NativeNode;
|
|
24
36
|
}
|
|
@@ -100,6 +100,12 @@ export declare class Editor implements Component, Focusable {
|
|
|
100
100
|
describeLanguage: (() => string | undefined) | undefined;
|
|
101
101
|
/** Label the TSP field to disable host-side editing while another input owner handles raw keys. */
|
|
102
102
|
nativeKeyPassthrough: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Ask the TSP terminal to keep what is typed into this field and draw it at
|
|
105
|
+
* the caret until this clears, then send it: set while startup cannot read
|
|
106
|
+
* input yet (the prompt composer's deferred-input start).
|
|
107
|
+
*/
|
|
108
|
+
nativeTypeahead: boolean;
|
|
103
109
|
/**
|
|
104
110
|
* TSP chrome around the `editor` node (the prompt composer's chips, mode
|
|
105
111
|
* chip, send/stop): the root role, the children with `input` placed where
|
|
@@ -10,6 +10,13 @@ import type { Component } from "../tui.js";
|
|
|
10
10
|
* byte-identical to rendering `text`.
|
|
11
11
|
*/
|
|
12
12
|
export declare function streamingMarkdownSource(text: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Whether `text` ends inside a code fence the source never closed. The
|
|
15
|
+
* renderer still draws such a fence's closing border, so a caller publishing a
|
|
16
|
+
* settled source prefix must drop that fabricated row: it is not a prefix of
|
|
17
|
+
* the live block, which reaches the border only once the closer arrives.
|
|
18
|
+
*/
|
|
19
|
+
export declare function endsInsideOpenFence(text: string): boolean;
|
|
13
20
|
/**
|
|
14
21
|
* Streaming `md` source for a native terminal, minus a still-growing table row:
|
|
15
22
|
* the unterminated last line when a GFM table (a run of pipe lines holding a
|
|
@@ -29,7 +29,8 @@ export declare function base64ImageNode(data: string, mimeType: string, p?: Omit
|
|
|
29
29
|
/**
|
|
30
30
|
* Props that make an `image` node open the file at `filePath` (as a `file://` URL, the TSP
|
|
31
31
|
* open-target form): a click zooms the image in the terminal, and the file opens from its
|
|
32
|
-
* context menu.
|
|
32
|
+
* context menu. Always uses a local file URL because the open action runs locally,
|
|
33
|
+
* even when remote file handlers are configured. Empty without a file.
|
|
33
34
|
*/
|
|
34
35
|
export declare function openableImageProps(filePath: string | undefined): Pick<TspProps<"image">, "href" | "actions">;
|
|
35
36
|
/**
|