@oh-my-pi/pi-tui 18.4.3 → 18.4.4
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 +36 -0
- package/dist/types/apps/cleanse-board.d.ts +17 -0
- package/dist/types/apps/git/help.d.ts +16 -0
- package/dist/types/apps/git/sidebar.d.ts +18 -0
- package/dist/types/apps/live-visualizer.d.ts +10 -0
- package/dist/types/apps/ps-top.d.ts +15 -0
- package/dist/types/apps/standalone-picker.d.ts +3 -0
- package/dist/types/autocomplete.d.ts +8 -0
- package/dist/types/chat/advisor-message.d.ts +12 -2
- package/dist/types/chat/assistant-message.d.ts +20 -0
- package/dist/types/chat/bash-execution.d.ts +9 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +6 -1
- package/dist/types/chat/collab-prompt-message.d.ts +4 -0
- package/dist/types/chat/compaction-summary-message.d.ts +15 -0
- package/dist/types/chat/eval-execution.d.ts +8 -0
- package/dist/types/chat/execution-shared.d.ts +58 -0
- package/dist/types/chat/late-diagnostics-message.d.ts +15 -1
- package/dist/types/chat/read-tool-group.d.ts +15 -0
- package/dist/types/chat/skill-message.d.ts +9 -0
- package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +3 -0
- package/dist/types/chat/todo-reminder.d.ts +4 -1
- package/dist/types/chat/tool-execution.d.ts +25 -1
- package/dist/types/chat/transcript-actions.d.ts +37 -0
- package/dist/types/chat/transcript-entry.d.ts +3 -1
- package/dist/types/chat/user-message.d.ts +25 -0
- package/dist/types/chrome/collab-qrcode.d.ts +7 -0
- package/dist/types/chrome/context-thresholds.d.ts +11 -0
- package/dist/types/chrome/countdown-timer.d.ts +9 -3
- package/dist/types/chrome/diff.d.ts +12 -0
- package/dist/types/chrome/dynamic-border.d.ts +3 -0
- package/dist/types/chrome/format.d.ts +6 -0
- package/dist/types/chrome/message-divider.d.ts +13 -0
- package/dist/types/chrome/message-frame.d.ts +10 -0
- package/dist/types/chrome/message-notice.d.ts +23 -0
- package/dist/types/chrome/overlay-box.d.ts +11 -2
- package/dist/types/chrome/qrcode.d.ts +7 -0
- package/dist/types/chrome/segment-track.d.ts +7 -0
- package/dist/types/chrome/selector-helpers.d.ts +0 -6
- package/dist/types/chrome/status-notice.d.ts +14 -0
- package/dist/types/chrome/streaming-panel.d.ts +3 -0
- package/dist/types/chrome/tool-activity.d.ts +3 -0
- package/dist/types/chrome/transcript-container.d.ts +13 -0
- package/dist/types/chrome/transcript-status.d.ts +15 -3
- package/dist/types/components/box.d.ts +7 -0
- package/dist/types/components/disclosure.d.ts +9 -0
- package/dist/types/components/editor.d.ts +37 -0
- package/dist/types/components/form.d.ts +14 -0
- package/dist/types/components/image.d.ts +7 -0
- package/dist/types/components/input.d.ts +20 -1
- package/dist/types/components/key-value-list.d.ts +3 -0
- package/dist/types/components/layout/geometry.d.ts +16 -0
- package/dist/types/components/layout/row.d.ts +7 -0
- package/dist/types/components/layout/split-pane.d.ts +8 -0
- package/dist/types/components/layout/stack.d.ts +6 -0
- package/dist/types/components/loader.d.ts +48 -0
- package/dist/types/components/markdown.d.ts +8 -0
- package/dist/types/components/metric.d.ts +7 -0
- package/dist/types/components/progress-bar.d.ts +3 -0
- package/dist/types/components/scroll-view.d.ts +6 -0
- package/dist/types/components/section.d.ts +3 -0
- package/dist/types/components/select-list.d.ts +33 -0
- package/dist/types/components/settings-list.d.ts +68 -0
- package/dist/types/components/spacer.d.ts +4 -0
- package/dist/types/components/tab-bar.d.ts +9 -0
- package/dist/types/components/table.d.ts +7 -0
- package/dist/types/components/text.d.ts +6 -0
- package/dist/types/components/tree-view.d.ts +9 -0
- package/dist/types/components/truncated-text.d.ts +3 -0
- package/dist/types/components/wizard-step.d.ts +6 -0
- package/dist/types/hotkeys-markdown.d.ts +24 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/latex-block.d.ts +7 -0
- package/dist/types/native/apply.d.ts +39 -0
- package/dist/types/native/backend.d.ts +94 -0
- package/dist/types/native/blobs.d.ts +29 -0
- package/dist/types/native/describe.d.ts +56 -0
- package/dist/types/native/encode.d.ts +50 -0
- package/dist/types/native/icons.d.ts +18 -0
- package/dist/types/native/memo.d.ts +27 -0
- package/dist/types/native/node.d.ts +107 -0
- package/dist/types/native/overlay.d.ts +64 -0
- package/dist/types/native/picker.d.ts +124 -0
- package/dist/types/native/reconcile.d.ts +41 -0
- package/dist/types/native/settle.d.ts +11 -0
- package/dist/types/native/spans.d.ts +21 -0
- package/dist/types/native/state.d.ts +6 -0
- package/dist/types/native/tone.d.ts +24 -0
- package/dist/types/overlays/advisor-config.d.ts +20 -0
- package/dist/types/overlays/agent-hub-renderer.d.ts +27 -11
- package/dist/types/overlays/agent-hub.d.ts +10 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +7 -0
- package/dist/types/overlays/agents-hub.d.ts +8 -0
- package/dist/types/overlays/annotation-overlay.d.ts +3 -0
- package/dist/types/overlays/ask-dialog.d.ts +23 -0
- package/dist/types/overlays/bordered-loader.d.ts +3 -0
- package/dist/types/overlays/btw-history-panel.d.ts +9 -0
- package/dist/types/overlays/btw-panel.d.ts +3 -0
- package/dist/types/overlays/cleanse-panel.d.ts +5 -2
- package/dist/types/overlays/composer-shape-preview.d.ts +7 -1
- package/dist/types/overlays/copy-selector.d.ts +38 -0
- package/dist/types/overlays/error-banner.d.ts +9 -0
- package/dist/types/overlays/extensions/extension-list.d.ts +1 -0
- package/dist/types/overlays/history-search.d.ts +18 -0
- package/dist/types/overlays/hook-editor.d.ts +28 -1
- package/dist/types/overlays/hook-input.d.ts +3 -0
- package/dist/types/overlays/hook-selector.d.ts +10 -0
- package/dist/types/overlays/hub-frame.d.ts +18 -0
- package/dist/types/overlays/jobs-panel.d.ts +24 -0
- package/dist/types/overlays/login-dialog.d.ts +10 -0
- package/dist/types/overlays/logout-account-selector.d.ts +4 -0
- package/dist/types/overlays/mcp-add-wizard.d.ts +4 -0
- package/dist/types/overlays/model-browser.d.ts +69 -0
- package/dist/types/overlays/model-hub.d.ts +7 -0
- package/dist/types/overlays/model-picker.d.ts +7 -0
- package/dist/types/overlays/move-overlay.d.ts +3 -0
- package/dist/types/overlays/oauth-selector.d.ts +4 -0
- package/dist/types/overlays/omfg-panel.d.ts +3 -0
- package/dist/types/overlays/pause-screen.d.ts +12 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +5 -0
- package/dist/types/overlays/plan-save-overlay.d.ts +10 -0
- package/dist/types/overlays/plugin-selector.d.ts +4 -0
- package/dist/types/overlays/plugin-settings.d.ts +30 -0
- package/dist/types/overlays/queue-mode-selector.d.ts +4 -0
- package/dist/types/overlays/reset-usage-selector.d.ts +8 -0
- package/dist/types/overlays/rewind-selector.d.ts +5 -0
- package/dist/types/overlays/session-info-overlay.d.ts +19 -1
- package/dist/types/overlays/session-selector.d.ts +64 -1
- package/dist/types/overlays/settings-defs.d.ts +14 -0
- package/dist/types/overlays/settings-selector.d.ts +21 -0
- package/dist/types/overlays/show-images-selector.d.ts +4 -0
- package/dist/types/overlays/snapcompact-shape-preview.d.ts +2 -0
- package/dist/types/overlays/stats-notice.d.ts +8 -0
- package/dist/types/overlays/theme-selector.d.ts +11 -0
- package/dist/types/overlays/thinking-selector.d.ts +4 -0
- package/dist/types/overlays/tree-selector.d.ts +60 -2
- package/dist/types/overlays/usage-dashboard.d.ts +26 -3
- package/dist/types/overlays/usage-row.d.ts +36 -2
- package/dist/types/prompt/attachment-chips.d.ts +8 -0
- package/dist/types/prompt/composer-attachments.d.ts +15 -3
- package/dist/types/prompt/composer.d.ts +18 -1
- package/dist/types/prompt/custom-editor.d.ts +48 -2
- package/dist/types/prompt/editor-top-gap.d.ts +2 -0
- package/dist/types/prompt/macos-spelling.d.ts +6 -0
- package/dist/types/prompt/magic-keywords.d.ts +9 -0
- package/dist/types/prompt/queued-messages.d.ts +23 -0
- package/dist/types/prompt/skill-tokens.d.ts +4 -2
- package/dist/types/prompt/welcome.d.ts +16 -0
- package/dist/types/render/code-cell.d.ts +10 -0
- package/dist/types/render/file-list.d.ts +8 -0
- package/dist/types/render/hyperlink.d.ts +14 -0
- package/dist/types/render/output-block.d.ts +43 -0
- package/dist/types/render/output-pane.d.ts +17 -0
- package/dist/types/render/tool-card.d.ts +8 -0
- package/dist/types/render/tree-list.d.ts +8 -0
- package/dist/types/render/width-aware-text.d.ts +7 -0
- package/dist/types/setup/scenes/outro.d.ts +7 -0
- package/dist/types/setup/scenes/sign-in.d.ts +7 -0
- package/dist/types/setup/scenes/splash.d.ts +8 -0
- package/dist/types/setup/scenes/types.d.ts +6 -1
- package/dist/types/setup/wizard-overlay.d.ts +9 -0
- package/dist/types/status-line/component.d.ts +49 -5
- package/dist/types/status-line/context-usage.d.ts +20 -0
- package/dist/types/status-line/footer.d.ts +8 -0
- package/dist/types/status-line/metrics.d.ts +1 -2
- package/dist/types/status-line/segments.d.ts +10 -1
- package/dist/types/status-line/types.d.ts +40 -1
- package/dist/types/terminal-capabilities.d.ts +1 -1
- package/dist/types/terminal.d.ts +27 -0
- package/dist/types/theme/defaults/index.d.ts +100 -0
- package/dist/types/theme/schema.d.ts +2 -0
- package/dist/types/theme/shimmer.d.ts +8 -0
- package/dist/types/theme/theme-class.d.ts +2 -0
- package/dist/types/theme/theme.d.ts +33 -1
- package/dist/types/tools/ask.d.ts +3 -0
- package/dist/types/tools/ast-edit.d.ts +10 -1
- package/dist/types/tools/ast-grep.d.ts +10 -1
- package/dist/types/tools/autoresearch.d.ts +21 -4
- package/dist/types/tools/bash.d.ts +30 -1
- package/dist/types/tools/cfg-render.d.ts +5 -1
- package/dist/types/tools/debug.d.ts +3 -1
- package/dist/types/tools/default-renderer.d.ts +6 -1
- package/dist/types/tools/edit.d.ts +14 -1
- package/dist/types/tools/eval.d.ts +12 -1
- package/dist/types/tools/fetch.d.ts +16 -1
- package/dist/types/tools/find.d.ts +15 -1
- package/dist/types/tools/github.d.ts +3 -0
- package/dist/types/tools/glob.d.ts +14 -1
- package/dist/types/tools/goal.d.ts +3 -1
- package/dist/types/tools/grep.d.ts +14 -1
- package/dist/types/tools/grouped-file-output.d.ts +58 -0
- package/dist/types/tools/json-tree.d.ts +20 -0
- package/dist/types/tools/lsp.d.ts +3 -10
- package/dist/types/tools/mcp.d.ts +16 -1
- package/dist/types/tools/memory.d.ts +26 -0
- package/dist/types/tools/native-view.d.ts +90 -0
- package/dist/types/tools/proc-render.d.ts +7 -1
- package/dist/types/tools/read.d.ts +23 -1
- package/dist/types/tools/renderer.d.ts +57 -0
- package/dist/types/tools/report-tool-issue.d.ts +3 -0
- package/dist/types/tools/resolve.d.ts +14 -1
- package/dist/types/tools/task.d.ts +3 -0
- package/dist/types/tools/think.d.ts +3 -0
- package/dist/types/tools/todo.d.ts +12 -0
- package/dist/types/tools/vibe.d.ts +3 -1
- package/dist/types/tools/wait.d.ts +3 -0
- package/dist/types/tools/web-search.d.ts +8 -0
- package/dist/types/tools/write.d.ts +14 -1
- package/dist/types/tools/xdev.d.ts +13 -0
- package/dist/types/tui.d.ts +49 -0
- package/package.json +9 -9
- package/src/apps/autoresearch-dashboard.ts +362 -4
- package/src/apps/cleanse-board.ts +219 -1
- package/src/apps/cleanse-picker.ts +9 -1
- package/src/apps/debug/log-viewer.ts +15 -15
- package/src/apps/debug/protocol-probe.ts +2 -20
- package/src/apps/git/avatar.ts +2 -22
- package/src/apps/git/git-tui.ts +406 -59
- package/src/apps/git/help.ts +130 -0
- package/src/apps/git/sidebar.ts +491 -0
- package/src/apps/live-visualizer.ts +65 -0
- package/src/apps/ps-top.ts +448 -17
- package/src/apps/session-picker.ts +1 -0
- package/src/apps/setup-model-picker.ts +5 -1
- package/src/apps/standalone-picker.ts +55 -1
- package/src/autocomplete.ts +44 -1
- package/src/chat/advisor-message.ts +72 -3
- package/src/chat/assistant-message.ts +346 -11
- package/src/chat/background-tan-message.ts +4 -4
- package/src/chat/bash-execution.ts +81 -0
- package/src/chat/cache-invalidation-marker.ts +8 -0
- package/src/chat/chat-transcript-builder.ts +37 -6
- package/src/chat/collab-prompt-message.ts +15 -3
- package/src/chat/compaction-summary-message.ts +74 -1
- package/src/chat/custom-message.ts +3 -1
- package/src/chat/eval-execution.ts +57 -0
- package/src/chat/execution-shared.ts +153 -1
- package/src/chat/hook-message.ts +1 -0
- package/src/chat/late-diagnostics-message.ts +85 -2
- package/src/chat/read-tool-group.ts +341 -1
- package/src/chat/served-model-marker.ts +8 -0
- package/src/chat/skill-message.ts +63 -0
- package/src/chat/stripped-tool-calls-placeholder.ts +18 -10
- package/src/chat/todo-reminder.ts +34 -4
- package/src/chat/tool-execution.ts +385 -10
- package/src/chat/transcript-actions.ts +38 -0
- package/src/chat/transcript-browser.ts +2 -9
- package/src/chat/transcript-entry.ts +10 -1
- package/src/chat/transcript-render-helpers.ts +16 -15
- package/src/chat/ttsr-notification.ts +38 -1
- package/src/chat/user-message.ts +167 -4
- package/src/chrome/collab-qrcode.ts +27 -2
- package/src/chrome/context-thresholds.ts +34 -0
- package/src/chrome/countdown-timer.ts +24 -1
- package/src/chrome/diff.ts +60 -1
- package/src/chrome/dynamic-border.ts +7 -0
- package/src/chrome/format.ts +12 -0
- package/src/chrome/message-divider.ts +33 -1
- package/src/chrome/message-frame.ts +53 -10
- package/src/chrome/message-notice.ts +71 -0
- package/src/chrome/overlay-box.ts +45 -2
- package/src/chrome/qrcode.ts +28 -0
- package/src/chrome/segment-track.ts +26 -0
- package/src/chrome/selector-helpers.ts +1 -17
- package/src/chrome/status-notice.ts +46 -0
- package/src/chrome/streaming-panel.ts +25 -1
- package/src/chrome/tool-activity.ts +20 -0
- package/src/chrome/transcript-container.ts +37 -0
- package/src/chrome/transcript-status.ts +40 -11
- package/src/components/box.ts +51 -0
- package/src/components/disclosure.ts +33 -0
- package/src/components/editor.ts +216 -27
- package/src/components/form.ts +93 -9
- package/src/components/image.ts +30 -0
- package/src/components/input.ts +77 -26
- package/src/components/key-value-list.ts +18 -0
- package/src/components/layout/geometry.ts +44 -0
- package/src/components/layout/row.ts +30 -0
- package/src/components/layout/split-pane.ts +65 -0
- package/src/components/layout/stack.ts +27 -0
- package/src/components/loader.ts +183 -1
- package/src/components/markdown.ts +21 -0
- package/src/components/metric.ts +39 -0
- package/src/components/progress-bar.ts +28 -0
- package/src/components/scroll-view.ts +23 -0
- package/src/components/section.ts +16 -0
- package/src/components/select-list.ts +174 -25
- package/src/components/settings-list.ts +264 -7
- package/src/components/spacer.ts +17 -0
- package/src/components/tab-bar.ts +42 -0
- package/src/components/table.ts +34 -0
- package/src/components/text.ts +23 -0
- package/src/components/tree-view.ts +65 -0
- package/src/components/truncated-text.ts +14 -0
- package/src/components/wizard-step.ts +18 -9
- package/src/debug-server.ts +14 -7
- package/src/hotkeys-markdown.ts +251 -69
- package/src/index.ts +6 -0
- package/src/latex-block.ts +11 -0
- package/src/native/apply.ts +275 -0
- package/src/native/backend.ts +682 -0
- package/src/native/blobs.ts +70 -0
- package/src/native/describe.ts +124 -0
- package/src/native/encode.ts +233 -0
- package/src/native/icons.ts +184 -0
- package/src/native/memo.ts +64 -0
- package/src/native/node.ts +112 -0
- package/src/native/overlay.ts +131 -0
- package/src/native/picker.ts +333 -0
- package/src/native/reconcile.ts +1063 -0
- package/src/native/settle.ts +23 -0
- package/src/native/spans.ts +308 -0
- package/src/native/state.ts +28 -0
- package/src/native/tone.ts +79 -0
- package/src/overlays/advisor-config.ts +420 -0
- package/src/overlays/agent-hub-renderer.ts +155 -18
- package/src/overlays/agent-hub.ts +1037 -44
- package/src/overlays/agent-transcript-viewer.ts +129 -0
- package/src/overlays/agents-hub.ts +688 -53
- package/src/overlays/annotation-overlay.ts +391 -52
- package/src/overlays/ask-dialog.ts +435 -24
- package/src/overlays/bordered-loader.ts +17 -0
- package/src/overlays/btw-history-panel.ts +182 -0
- package/src/overlays/btw-panel.ts +68 -2
- package/src/overlays/cleanse-panel.ts +105 -15
- package/src/overlays/codex-reset-fireworks.ts +65 -5
- package/src/overlays/composer-shape-preview.ts +26 -1
- package/src/overlays/copy-selector.ts +545 -23
- package/src/overlays/error-banner.ts +44 -0
- package/src/overlays/extensions/extension-list.ts +23 -17
- package/src/overlays/history-search.ts +175 -33
- package/src/overlays/hook-editor.ts +113 -6
- package/src/overlays/hook-input.ts +22 -1
- package/src/overlays/hook-selector.ts +311 -22
- package/src/overlays/hub-frame.ts +80 -0
- package/src/overlays/jobs-panel.ts +112 -0
- package/src/overlays/login-dialog.ts +183 -1
- package/src/overlays/logout-account-selector.ts +102 -4
- package/src/overlays/mcp-add-wizard.ts +232 -53
- package/src/overlays/model-browser.ts +681 -22
- package/src/overlays/model-hub.ts +1402 -78
- package/src/overlays/model-picker.ts +175 -1
- package/src/overlays/move-overlay.ts +45 -0
- package/src/overlays/oauth-selector.ts +227 -23
- package/src/overlays/omfg-panel.ts +86 -2
- package/src/overlays/pause-screen.ts +55 -4
- package/src/overlays/plan-review-overlay.ts +352 -0
- package/src/overlays/plan-save-overlay.ts +45 -0
- package/src/overlays/plugin-selector.ts +21 -1
- package/src/overlays/plugin-settings.ts +195 -5
- package/src/overlays/queue-mode-selector.ts +19 -1
- package/src/overlays/reset-usage-selector.ts +110 -40
- package/src/overlays/rewind-selector.ts +458 -44
- package/src/overlays/session-account-selector.ts +1 -1
- package/src/overlays/session-info-overlay.ts +137 -1
- package/src/overlays/session-selector.ts +807 -46
- package/src/overlays/settings-defs.ts +41 -0
- package/src/overlays/settings-selector.ts +583 -23
- package/src/overlays/show-images-selector.ts +18 -1
- package/src/overlays/snapcompact-shape-preview.ts +48 -3
- package/src/overlays/stats-notice.ts +31 -0
- package/src/overlays/theme-selector.ts +31 -1
- package/src/overlays/thinking-selector.ts +22 -1
- package/src/overlays/tree-selector.ts +570 -110
- package/src/overlays/usage-dashboard.ts +587 -12
- package/src/overlays/usage-row.ts +161 -25
- package/src/prompt/attachment-chips.ts +60 -0
- package/src/prompt/composer-attachments.ts +31 -9
- package/src/prompt/composer.ts +55 -2
- package/src/prompt/custom-editor.ts +302 -4
- package/src/prompt/editor-top-gap.ts +8 -0
- package/src/prompt/macos-spelling.ts +24 -9
- package/src/prompt/magic-keywords.ts +22 -1
- package/src/prompt/model-mention-autocomplete.ts +1 -0
- package/src/prompt/queued-messages.ts +101 -0
- package/src/prompt/skill-tokens.ts +5 -3
- package/src/prompt/welcome.ts +213 -6
- package/src/render/code-cell.ts +103 -2
- package/src/render/file-list.ts +29 -0
- package/src/render/hyperlink.ts +32 -0
- package/src/render/output-block.ts +110 -0
- package/src/render/output-pane.ts +37 -0
- package/src/render/tool-card.ts +137 -0
- package/src/render/tree-list.ts +39 -0
- package/src/render/width-aware-text.ts +20 -0
- package/src/setup/scenes/composer.ts +29 -0
- package/src/setup/scenes/glyph.ts +15 -0
- package/src/setup/scenes/model.ts +36 -8
- package/src/setup/scenes/outro.ts +28 -1
- package/src/setup/scenes/sign-in.ts +122 -13
- package/src/setup/scenes/splash.ts +28 -1
- package/src/setup/scenes/theme.ts +88 -3
- package/src/setup/scenes/types.ts +7 -1
- package/src/setup/startup-splash.ts +46 -9
- package/src/setup/wizard-overlay.ts +140 -23
- package/src/status-line/component.ts +398 -16
- package/src/status-line/context-usage.ts +279 -50
- package/src/status-line/footer.ts +94 -1
- package/src/status-line/metrics.ts +3 -6
- package/src/status-line/segments.ts +463 -97
- package/src/status-line/separators.ts +3 -16
- package/src/status-line/types.ts +43 -1
- package/src/terminal-capabilities.ts +7 -0
- package/src/terminal.ts +130 -2
- package/src/theme/defaults/dark-neon-noir.json +100 -0
- package/src/theme/defaults/index.ts +2 -0
- package/src/theme/defaults/light-prism.json +5 -5
- package/src/theme/defaults/onyx.json +62 -62
- package/src/theme/schema.ts +15 -0
- package/src/theme/shimmer.ts +33 -0
- package/src/theme/theme-class.ts +24 -19
- package/src/theme/theme.ts +111 -9
- package/src/tools/ask.ts +157 -1
- package/src/tools/ast-edit.ts +174 -1
- package/src/tools/ast-grep.ts +82 -2
- package/src/tools/autoresearch.ts +149 -1
- package/src/tools/bash.ts +180 -49
- package/src/tools/cfg-render.ts +66 -1
- package/src/tools/debug.ts +78 -1
- package/src/tools/default-renderer.ts +35 -1
- package/src/tools/edit.ts +247 -2
- package/src/tools/eval.ts +257 -1
- package/src/tools/fetch.ts +102 -3
- package/src/tools/find.ts +127 -1
- package/src/tools/github.ts +119 -10
- package/src/tools/glob.ts +116 -1
- package/src/tools/goal.ts +56 -1
- package/src/tools/grep.ts +83 -2
- package/src/tools/grouped-file-output.ts +205 -0
- package/src/tools/json-tree.ts +116 -1
- package/src/tools/lsp.ts +318 -1
- package/src/tools/mcp.ts +80 -1
- package/src/tools/memory.ts +93 -11
- package/src/tools/native-view.ts +292 -0
- package/src/tools/proc-render.ts +221 -1
- package/src/tools/read.ts +199 -4
- package/src/tools/renderer.ts +61 -0
- package/src/tools/report-tool-issue.ts +7 -1
- package/src/tools/resolve.ts +63 -1
- package/src/tools/task.ts +406 -4
- package/src/tools/think.ts +19 -1
- package/src/tools/todo.ts +89 -0
- package/src/tools/vibe.ts +230 -2
- package/src/tools/wait.ts +181 -1
- package/src/tools/web-search.ts +113 -1
- package/src/tools/write.ts +144 -5
- package/src/tools/xdev.ts +64 -1
- package/src/tui.ts +294 -3
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { MouseRoutable, SgrMouseEvent } from "../../mouse";
|
|
2
|
+
import type { TspProps } from "@oh-my-pi/pi-wire";
|
|
3
|
+
import { col, node, row } from "../../native/describe";
|
|
4
|
+
import type { DescribeContext, NativeNode } from "../../native/node";
|
|
2
5
|
import type { Component } from "../../tui";
|
|
3
6
|
import { visibleWidth } from "../../utils";
|
|
4
7
|
import {
|
|
@@ -11,6 +14,9 @@ import {
|
|
|
11
14
|
type LayoutRect,
|
|
12
15
|
layoutRatio,
|
|
13
16
|
layoutSize,
|
|
17
|
+
nativeLayoutChild,
|
|
18
|
+
nativeLayoutGap,
|
|
19
|
+
nativeSlotProps,
|
|
14
20
|
optionalLayoutSize,
|
|
15
21
|
uniqueLayoutComponents,
|
|
16
22
|
} from "./geometry";
|
|
@@ -88,6 +94,16 @@ export class SplitPane implements Component, MouseRoutable {
|
|
|
88
94
|
#measureMemo: SplitMeasureMemo | undefined;
|
|
89
95
|
#rowMode: "split" | PaneSide = "split";
|
|
90
96
|
#rowLeftWidth = -1;
|
|
97
|
+
#native:
|
|
98
|
+
| {
|
|
99
|
+
leftSize: SplitPaneSize;
|
|
100
|
+
rightMinWidth: number;
|
|
101
|
+
narrowPane: PaneSide | undefined;
|
|
102
|
+
divider: LayoutDecoration | undefined;
|
|
103
|
+
height: number | undefined;
|
|
104
|
+
node: NativeNode;
|
|
105
|
+
}
|
|
106
|
+
| undefined;
|
|
91
107
|
|
|
92
108
|
constructor(options: SplitPaneOptions) {
|
|
93
109
|
this.#left = options.left;
|
|
@@ -268,6 +284,55 @@ export class SplitPane implements Component, MouseRoutable {
|
|
|
268
284
|
return geometry;
|
|
269
285
|
}
|
|
270
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Two flex slots in a `row`: the left pane fixed (`ch`) or a fraction of
|
|
289
|
+
* the width within its bounds, the right pane growing from its minimum.
|
|
290
|
+
* With a narrow pane configured the row may wrap, stacking the panes on
|
|
291
|
+
* narrow terminals instead of hiding one.
|
|
292
|
+
*/
|
|
293
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
294
|
+
const cached = this.#native;
|
|
295
|
+
if (
|
|
296
|
+
cached?.leftSize === this.#leftSize &&
|
|
297
|
+
cached.rightMinWidth === this.#rightMinWidth &&
|
|
298
|
+
cached.narrowPane === this.#narrowPane &&
|
|
299
|
+
cached.divider === this.#divider &&
|
|
300
|
+
cached.height === this.#height
|
|
301
|
+
) {
|
|
302
|
+
return cached.node;
|
|
303
|
+
}
|
|
304
|
+
const size = this.#leftSize;
|
|
305
|
+
const leftProps: TspProps<"col"> =
|
|
306
|
+
size.fixed !== undefined
|
|
307
|
+
? nativeSlotProps("w", { fixed: size.fixed })
|
|
308
|
+
: {
|
|
309
|
+
...nativeSlotProps("w", { grow: 0, min: size.min, max: size.max }),
|
|
310
|
+
basis: layoutRatio(size.ratio, 0.5),
|
|
311
|
+
};
|
|
312
|
+
const rightProps = nativeSlotProps("w", { grow: 1, min: this.#rightMinWidth });
|
|
313
|
+
const height = this.#height;
|
|
314
|
+
const described = row(
|
|
315
|
+
[
|
|
316
|
+
node("col", leftProps, [nativeLayoutChild(this.#left)], "left"),
|
|
317
|
+
node("col", rightProps, [nativeLayoutChild(this.#right)], "right"),
|
|
318
|
+
],
|
|
319
|
+
{ gap: nativeLayoutGap(this.#divider), align: this.#align, wrap: this.#narrowPane !== undefined },
|
|
320
|
+
);
|
|
321
|
+
const result =
|
|
322
|
+
height === undefined
|
|
323
|
+
? described
|
|
324
|
+
: col([described], { min: { h: `${height}lines` }, max: { h: `${height}lines` } });
|
|
325
|
+
this.#native = {
|
|
326
|
+
leftSize: size,
|
|
327
|
+
rightMinWidth: this.#rightMinWidth,
|
|
328
|
+
narrowPane: this.#narrowPane,
|
|
329
|
+
divider: this.#divider,
|
|
330
|
+
height,
|
|
331
|
+
node: result,
|
|
332
|
+
};
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
335
|
+
|
|
271
336
|
/** Translate a split-local point into pane-local coordinates. */
|
|
272
337
|
locate(line: number, col: number): SplitPaneHit | undefined {
|
|
273
338
|
const panes: readonly [PaneSide, LayoutContent, LayoutRect | undefined][] = [
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { MouseRoutable, SgrMouseEvent } from "../../mouse";
|
|
2
|
+
import { col } from "../../native/describe";
|
|
3
|
+
import type { DescribeContext, NativeNode } from "../../native/node";
|
|
2
4
|
import type { Component } from "../../tui";
|
|
3
5
|
import { padding } from "../../utils";
|
|
4
6
|
import {
|
|
@@ -13,6 +15,8 @@ import {
|
|
|
13
15
|
type LayoutInsets,
|
|
14
16
|
type LayoutRect,
|
|
15
17
|
layoutSize,
|
|
18
|
+
nativeLayoutChild,
|
|
19
|
+
nativeSlotProps,
|
|
16
20
|
optionalLayoutSize,
|
|
17
21
|
renderLayoutContent,
|
|
18
22
|
uniqueLayoutComponents,
|
|
@@ -76,6 +80,7 @@ export class Stack implements Component, MouseRoutable {
|
|
|
76
80
|
#frames: LayoutRect[] = [];
|
|
77
81
|
#memo: StackMemo | undefined;
|
|
78
82
|
#ignoreTight = false;
|
|
83
|
+
#native: { children: StackChild[]; height: number | undefined; node: NativeNode } | undefined;
|
|
79
84
|
|
|
80
85
|
constructor(options: StackOptions) {
|
|
81
86
|
this.#children = options.children.map(child => ({ ...child, padding: { ...child.padding } }));
|
|
@@ -141,6 +146,28 @@ export class Stack implements Component, MouseRoutable {
|
|
|
141
146
|
}
|
|
142
147
|
}
|
|
143
148
|
|
|
149
|
+
/**
|
|
150
|
+
* A `col` of slots carrying each child's height bounds (fixed → min = max
|
|
151
|
+
* `lines`, else grow/min/max); an exact stack height bounds the column.
|
|
152
|
+
*/
|
|
153
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
154
|
+
const cached = this.#native;
|
|
155
|
+
if (cached?.children === this.#children && cached.height === this.#height) return cached.node;
|
|
156
|
+
const slots = this.#children.map(child =>
|
|
157
|
+
col(
|
|
158
|
+
[nativeLayoutChild(child.content)],
|
|
159
|
+
nativeSlotProps("h", { fixed: child.height, grow: child.grow, min: child.minHeight, max: child.maxHeight }),
|
|
160
|
+
),
|
|
161
|
+
);
|
|
162
|
+
const height = this.#height;
|
|
163
|
+
const described = col(
|
|
164
|
+
slots,
|
|
165
|
+
height === undefined ? undefined : { min: { h: `${height}lines` }, max: { h: `${height}lines` } },
|
|
166
|
+
);
|
|
167
|
+
this.#native = { children: this.#children, height, node: described };
|
|
168
|
+
return described;
|
|
169
|
+
}
|
|
170
|
+
|
|
144
171
|
/** Translate a stack-local point into a child's local coordinates. */
|
|
145
172
|
locate(line: number, col: number): StackHit | undefined {
|
|
146
173
|
for (let index = 0; index < this.#frames.length; index++) {
|
package/src/components/loader.ts
CHANGED
|
@@ -1,13 +1,99 @@
|
|
|
1
|
+
import type { TspProps } from "@oh-my-pi/pi-wire";
|
|
2
|
+
import { elapsed, kbd, keyed, node, row, span, text } from "../native/describe";
|
|
3
|
+
import { plainText } from "../native/spans";
|
|
4
|
+
import type { DescribeContext, NativeChild, NativeNode, NativeUiEvent } from "../native/node";
|
|
5
|
+
import { isNativeRendering } from "../native/state";
|
|
6
|
+
import { describeShimmer, type ShimmerPalette, shimmerEnabled } from "../theme/shimmer";
|
|
1
7
|
import type { TUI } from "../tui";
|
|
2
8
|
import { getPaddingX, padding, sliceByColumn, visibleWidth } from "../utils";
|
|
3
9
|
import { Text } from "./text";
|
|
4
10
|
|
|
11
|
+
const DEFAULT_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
5
12
|
const RENDER_INTERVAL_MS = 1000 / 30;
|
|
6
13
|
/** Milliseconds between spinner-frame advances; exported so time-derived spinners elsewhere tick at the Loader cadence. */
|
|
7
14
|
export const SPINNER_ADVANCE_MS = 80;
|
|
8
15
|
const RENDER_BACKPRESSURE_MULTIPLIER = 9;
|
|
9
16
|
const MAX_BACKPRESSURE_FRAME_COST_MS = 200;
|
|
10
17
|
|
|
18
|
+
/** Native repaint cadence of a retry countdown ring (the terminal eases the ring between frames). */
|
|
19
|
+
const RETRY_METER_REPAINT_MS = 500;
|
|
20
|
+
|
|
21
|
+
/** A working-row variant (§6.5): a retry countdown, or context compaction. */
|
|
22
|
+
export type WorkingRowVariant =
|
|
23
|
+
| {
|
|
24
|
+
readonly kind: "retry";
|
|
25
|
+
readonly attempt: number;
|
|
26
|
+
readonly max: number;
|
|
27
|
+
/** The wait before the attempt, in ms, counted from the row's `startedAt`. */
|
|
28
|
+
readonly delayMs: number;
|
|
29
|
+
}
|
|
30
|
+
| { readonly kind: "compaction" };
|
|
31
|
+
|
|
32
|
+
/** What the dock's working row (§8.1, role `omp.working`) shows. */
|
|
33
|
+
export interface WorkingRowSpec {
|
|
34
|
+
/** The intent, or the variant's label ("Retrying · attempt 1 of 3", "Compacting context…"). */
|
|
35
|
+
readonly label: string;
|
|
36
|
+
/** Epoch ms the work started: the `elapsed` origin and the retry countdown start. */
|
|
37
|
+
readonly startedAt: number;
|
|
38
|
+
readonly variant?: WorkingRowVariant;
|
|
39
|
+
/** Shimmer palette of the label (a session-accented intent). */
|
|
40
|
+
readonly palette?: ShimmerPalette;
|
|
41
|
+
/** Live tok/s, docked before the stop control. */
|
|
42
|
+
readonly rate?: number;
|
|
43
|
+
/** Key id that interrupts (`escape`); undefined hides the stop control (Esc would not cancel). */
|
|
44
|
+
readonly interruptKey?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** A key id as tooltip keys: `escape` reads `esc`, the rest as bound. */
|
|
48
|
+
function titleKey(key: string): string {
|
|
49
|
+
return key === "escape" ? "esc" : key;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The dock's working row: `starburst` spinner (or a retry countdown ring),
|
|
54
|
+
* the intent shimmering, `·`, the elapsed time, a grow spacer, then the stop
|
|
55
|
+
* control whose click sends `interrupt`. Compaction adds an indeterminate
|
|
56
|
+
* `progress` before the stop control; a retry says "Cancel".
|
|
57
|
+
*/
|
|
58
|
+
export function describeWorkingRow(spec: WorkingRowSpec, cx: DescribeContext, now = Date.now()): NativeNode {
|
|
59
|
+
const variant = spec.variant;
|
|
60
|
+
const children: NativeChild[] = [];
|
|
61
|
+
if (variant?.kind === "retry" && cx.supports("meter")) {
|
|
62
|
+
const remaining = Math.max(0, variant.delayMs - (now - spec.startedAt));
|
|
63
|
+
const value = variant.delayMs > 0 ? Math.round((remaining / variant.delayMs) * 100) / 100 : 0;
|
|
64
|
+
children.push(node("meter", { value, style: "ring", size: "sm" }, undefined, "countdown"));
|
|
65
|
+
} else {
|
|
66
|
+
children.push(node("spinner", { style: "starburst", tone: "accent" }, undefined, "spinner"));
|
|
67
|
+
}
|
|
68
|
+
const label = describeShimmer([{ text: spec.label, palette: spec.palette }], "label");
|
|
69
|
+
children.push(
|
|
70
|
+
node(label.k, { ...label.p, role: "omp.working.label" } as TspProps, label.c, label.key),
|
|
71
|
+
node("text", { text: "·", role: "omp.working.sep" }, undefined, "sep"),
|
|
72
|
+
keyed(elapsed(now - spec.startedAt), "elapsed"),
|
|
73
|
+
node("row", { grow: 1 }, undefined, "fill"),
|
|
74
|
+
);
|
|
75
|
+
if (variant?.kind === "compaction") children.push(node("progress", { value: null }, undefined, "progress"));
|
|
76
|
+
if (spec.rate !== undefined) children.push(node("rate", { value: spec.rate, unit: "tok/s" }, undefined, "rate"));
|
|
77
|
+
if (spec.interruptKey !== undefined) {
|
|
78
|
+
const verb = variant?.kind === "retry" ? "Cancel" : "Stop";
|
|
79
|
+
children.push(
|
|
80
|
+
node(
|
|
81
|
+
"row",
|
|
82
|
+
{
|
|
83
|
+
role: "omp.working.stop",
|
|
84
|
+
gap: "xs",
|
|
85
|
+
align: "center",
|
|
86
|
+
title: `${verb} ${titleKey(spec.interruptKey)}`,
|
|
87
|
+
actions: { click: "interrupt" },
|
|
88
|
+
},
|
|
89
|
+
[kbd(titleKey(spec.interruptKey)), text(verb)],
|
|
90
|
+
"stop",
|
|
91
|
+
),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return row(children, { role: "omp.working", align: "center", gap: "sm" });
|
|
95
|
+
}
|
|
96
|
+
|
|
11
97
|
type ColorFn = (str: string) => string;
|
|
12
98
|
|
|
13
99
|
/**
|
|
@@ -20,7 +106,7 @@ export type LoaderMessageColorFn = ColorFn & {
|
|
|
20
106
|
|
|
21
107
|
/** Animates a spinner and colorized message while asynchronous work is pending. */
|
|
22
108
|
export class Loader extends Text {
|
|
23
|
-
#frames =
|
|
109
|
+
#frames = DEFAULT_SPINNER_FRAMES;
|
|
24
110
|
#currentFrame = 0;
|
|
25
111
|
#intervalId?: NodeJS.Timeout;
|
|
26
112
|
#ui: TUI | null = null;
|
|
@@ -37,6 +123,10 @@ export class Loader extends Text {
|
|
|
37
123
|
#layoutFrames: readonly string[];
|
|
38
124
|
#layoutFrame: string;
|
|
39
125
|
#trailer?: () => string | undefined;
|
|
126
|
+
#native?: { message: string; trailer: string; shimmer: boolean; node: NativeNode };
|
|
127
|
+
#working?: { spec: () => WorkingRowSpec; interrupt: () => void };
|
|
128
|
+
#workingNative?: { key: string; node: NativeNode };
|
|
129
|
+
#nativeTimer?: NodeJS.Timeout;
|
|
40
130
|
|
|
41
131
|
constructor(
|
|
42
132
|
ui: TUI,
|
|
@@ -136,10 +226,93 @@ export class Loader extends Text {
|
|
|
136
226
|
return lines;
|
|
137
227
|
}
|
|
138
228
|
|
|
229
|
+
/**
|
|
230
|
+
* A `spinner` (or the static glyph of a one-frame loader, e.g. an interrupt
|
|
231
|
+
* key hint) followed by the message, shimmering when the message colorizer
|
|
232
|
+
* animates, and the right-docked trailer. The terminal clocks the motion.
|
|
233
|
+
* Function messages are re-read whenever the engine revisits the loader.
|
|
234
|
+
*/
|
|
235
|
+
override describe(cx: DescribeContext): NativeNode {
|
|
236
|
+
if (this.#working) return this.#describeWorking(cx);
|
|
237
|
+
const message = plainText(this.#resolveMessage());
|
|
238
|
+
const trailer = plainText(this.#trailer?.() ?? "");
|
|
239
|
+
const shimmer = this.messageColorFn.animated === true && shimmerEnabled();
|
|
240
|
+
const cached = this.#native;
|
|
241
|
+
if (cached && cached.message === message && cached.trailer === trailer && cached.shimmer === shimmer) {
|
|
242
|
+
return cached.node;
|
|
243
|
+
}
|
|
244
|
+
const indicator =
|
|
245
|
+
this.#frames.length > 1
|
|
246
|
+
? node("spinner", this.#frames === DEFAULT_SPINNER_FRAMES ? { style: "braille" } : {})
|
|
247
|
+
: text([span(plainText(this.#frames[0] ?? "").trim(), "muted")], { wrap: "none" });
|
|
248
|
+
const label = shimmer
|
|
249
|
+
? describeShimmer([{ text: message }], "message")
|
|
250
|
+
: node("text", { spans: [span(message, "muted")] }, undefined, "message");
|
|
251
|
+
const children: NativeChild[] = [row([indicator, label], { gap: "sm", align: "baseline" })];
|
|
252
|
+
if (trailer) children.push(text(trailer, { wrap: "none", truncate: "end" }));
|
|
253
|
+
const described = row(children, { justify: "between", role: "omp.loader" });
|
|
254
|
+
this.#native = { message, trailer, shimmer, node: described };
|
|
255
|
+
return described;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Describe as the dock's working row ({@link describeWorkingRow}) instead
|
|
260
|
+
* of a spinner line; `spec` is re-read whenever the engine revisits the
|
|
261
|
+
* loader and `interrupt` answers a click on its stop control.
|
|
262
|
+
*/
|
|
263
|
+
setWorkingRow(spec: () => WorkingRowSpec, interrupt: () => void): void {
|
|
264
|
+
this.#working = { spec, interrupt };
|
|
265
|
+
this.#workingNative = undefined;
|
|
266
|
+
this.#startNativeCountdown();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** A click on the working row's stop control. */
|
|
270
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
271
|
+
if (event.type === "action" && event.act === "interrupt") this.#working?.interrupt();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
#describeWorking(cx: DescribeContext): NativeNode {
|
|
275
|
+
const spec = this.#working!.spec();
|
|
276
|
+
const now = Date.now();
|
|
277
|
+
const variant = spec.variant;
|
|
278
|
+
const countdown =
|
|
279
|
+
variant?.kind === "retry" && cx.supports("meter")
|
|
280
|
+
? Math.round((Math.max(0, variant.delayMs - (now - spec.startedAt)) / Math.max(1, variant.delayMs)) * 100)
|
|
281
|
+
: -1;
|
|
282
|
+
const key = [
|
|
283
|
+
spec.label,
|
|
284
|
+
spec.startedAt,
|
|
285
|
+
variant?.kind,
|
|
286
|
+
variant?.kind === "retry" ? `${variant.attempt}/${variant.max}` : "",
|
|
287
|
+
countdown,
|
|
288
|
+
spec.rate,
|
|
289
|
+
spec.interruptKey,
|
|
290
|
+
spec.palette?.mid,
|
|
291
|
+
shimmerEnabled(),
|
|
292
|
+
].join("\u0000");
|
|
293
|
+
const cached = this.#workingNative;
|
|
294
|
+
if (cached?.key === key) return cached.node;
|
|
295
|
+
const described = describeWorkingRow(spec, cx, now);
|
|
296
|
+
this.#workingNative = { key, node: described };
|
|
297
|
+
return described;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** A TSP terminal clocks the spinner and timer, but a retry ring's fill is omp's: repaint it while counting down. */
|
|
301
|
+
#startNativeCountdown(): void {
|
|
302
|
+
if (this.#nativeTimer || !isNativeRendering() || this.#working?.spec().variant?.kind !== "retry") return;
|
|
303
|
+
this.#nativeTimer = setInterval(() => this.#requestPaint(), RETRY_METER_REPAINT_MS);
|
|
304
|
+
this.#nativeTimer.unref?.();
|
|
305
|
+
}
|
|
306
|
+
|
|
139
307
|
start() {
|
|
140
308
|
this.#lastSpinnerTick = performance.now();
|
|
141
309
|
this.#syncText();
|
|
142
310
|
this.#requestPaint();
|
|
311
|
+
// The TSP terminal animates the described spinner; nothing to repaint.
|
|
312
|
+
if (isNativeRendering()) {
|
|
313
|
+
this.#startNativeCountdown();
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
143
316
|
const intervalMs = this.messageColorFn.animated === true ? RENDER_INTERVAL_MS : SPINNER_ADVANCE_MS;
|
|
144
317
|
this.#scheduleTick(intervalMs, intervalMs);
|
|
145
318
|
}
|
|
@@ -149,6 +322,10 @@ export class Loader extends Text {
|
|
|
149
322
|
clearTimeout(this.#intervalId);
|
|
150
323
|
this.#intervalId = undefined;
|
|
151
324
|
}
|
|
325
|
+
if (this.#nativeTimer) {
|
|
326
|
+
clearInterval(this.#nativeTimer);
|
|
327
|
+
this.#nativeTimer = undefined;
|
|
328
|
+
}
|
|
152
329
|
}
|
|
153
330
|
|
|
154
331
|
/** Lifecycle teardown: stop the animation timer. Idempotent. */
|
|
@@ -174,6 +351,11 @@ export class Loader extends Text {
|
|
|
174
351
|
#scheduleTick(intervalMs: number, delayMs: number): void {
|
|
175
352
|
const timer = setTimeout(() => {
|
|
176
353
|
if (this.#intervalId !== timer) return;
|
|
354
|
+
if (isNativeRendering()) {
|
|
355
|
+
// A TSP surface opened mid-animation: the terminal clocks it from here.
|
|
356
|
+
this.#intervalId = undefined;
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
177
359
|
const startedAt = performance.now();
|
|
178
360
|
const elapsed = startedAt - this.#lastSpinnerTick;
|
|
179
361
|
const shouldAdvanceSpinner = elapsed >= SPINNER_ADVANCE_MS;
|
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
import { mathBlockAt, mathSpanAt, mathStartIndex } from "@oh-my-pi/pi-utils/math-delimiters";
|
|
11
11
|
import { latexToBlock } from "../latex-block";
|
|
12
12
|
import { isBareMathEnvironment, latexToUnicode } from "../latex-to-unicode";
|
|
13
|
+
import { plainText } from "../native/spans";
|
|
14
|
+
import { md } from "../native/describe";
|
|
15
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
13
16
|
import type { SymbolTheme } from "../symbols";
|
|
14
17
|
import { TERMINAL } from "../terminal-capabilities";
|
|
15
18
|
import type { Component } from "../tui";
|
|
@@ -1817,6 +1820,7 @@ export class Markdown implements Component {
|
|
|
1817
1820
|
// B+ capture plumbing: #renderContentLines records the last rendered paragraph row.
|
|
1818
1821
|
#lastTailCapture?: { kind: "paragraph"; open: boolean; rowInput: string; rowRaw: string };
|
|
1819
1822
|
#ignoreTight = false;
|
|
1823
|
+
#native?: { text: string; stream: boolean; node: NativeNode };
|
|
1820
1824
|
setIgnoreTight(ignore: boolean): this {
|
|
1821
1825
|
this.#ignoreTight = ignore;
|
|
1822
1826
|
this.invalidate();
|
|
@@ -1913,6 +1917,23 @@ export class Markdown implements Component {
|
|
|
1913
1917
|
this.#cachedLines = undefined;
|
|
1914
1918
|
}
|
|
1915
1919
|
|
|
1920
|
+
/**
|
|
1921
|
+
* The unrendered source as an `md` node, `stream` while the streaming
|
|
1922
|
+
* (transient) cache is on. Append-only growth yields a fresh node of the
|
|
1923
|
+
* same kind and key whose text extends the previous one, which the
|
|
1924
|
+
* reconciler sends as `text append`.
|
|
1925
|
+
*/
|
|
1926
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
1927
|
+
const stream = this.#transientRenderCache;
|
|
1928
|
+
const cached = this.#native;
|
|
1929
|
+
if (cached?.text === this.#text && cached.stream === stream) return cached.node;
|
|
1930
|
+
// Sources are model text; OSC 8 / SGR bytes a caller spliced in are the terminal's to style, not ours.
|
|
1931
|
+
const source = this.#text.includes("\x1b") ? plainText(this.#text) : this.#text;
|
|
1932
|
+
const described = md(source, stream ? { stream: true } : undefined);
|
|
1933
|
+
this.#native = { text: this.#text, stream, node: described };
|
|
1934
|
+
return described;
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1916
1937
|
/**
|
|
1917
1938
|
* Width-independent source prefix of the last render ending at a frozen
|
|
1918
1939
|
* Markdown block boundary. Only meaningful while streaming (transient
|
package/src/components/metric.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { styleSpans } from "../native/spans";
|
|
2
|
+
import { node, text } from "../native/describe";
|
|
3
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
1
4
|
import type { Component } from "../tui";
|
|
2
5
|
import { Ellipsis, getWidthConfigEpoch, truncateToWidth, visibleWidth } from "../utils";
|
|
3
6
|
import { Text } from "./text";
|
|
@@ -85,6 +88,7 @@ export class MetricRow implements Component {
|
|
|
85
88
|
readonly #options: MetricRowOptions;
|
|
86
89
|
readonly #text: Text;
|
|
87
90
|
#cache: { width: number; epoch: number; source: readonly string[]; lines: readonly string[] } | undefined;
|
|
91
|
+
#native: NativeNode | undefined;
|
|
88
92
|
|
|
89
93
|
constructor(metrics: readonly MetricSpec[], options: MetricRowOptions = {}) {
|
|
90
94
|
this.#metrics = metrics;
|
|
@@ -96,12 +100,47 @@ export class MetricRow implements Component {
|
|
|
96
100
|
if (this.#metrics === metrics) return false;
|
|
97
101
|
this.#metrics = metrics;
|
|
98
102
|
this.#cache = undefined;
|
|
103
|
+
this.#native = undefined;
|
|
99
104
|
return true;
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
invalidate(): void {
|
|
103
108
|
this.#text.invalidate();
|
|
104
109
|
this.#cache = undefined;
|
|
110
|
+
this.#native = undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* `drop` overflow becomes a transparent `status` strip whose segments keep
|
|
115
|
+
* the metric priorities (the terminal drops the lowest first); the other
|
|
116
|
+
* modes are one text run that wraps or truncates.
|
|
117
|
+
*/
|
|
118
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
119
|
+
if (this.#native) return this.#native;
|
|
120
|
+
const options = this.#options;
|
|
121
|
+
if (options.overflow === "drop") {
|
|
122
|
+
const segs: NativeNode[] = [];
|
|
123
|
+
this.#metrics.forEach((metric, index) => {
|
|
124
|
+
const formatted = formatMetric(metric);
|
|
125
|
+
if (formatted === undefined) return;
|
|
126
|
+
segs.push(
|
|
127
|
+
node(
|
|
128
|
+
"seg",
|
|
129
|
+
{ side: "left", priority: metric.priority ?? 0, spans: styleSpans(formatted, options.style) },
|
|
130
|
+
undefined,
|
|
131
|
+
String(index),
|
|
132
|
+
),
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
this.#native = node("status", { transparent: true }, segs);
|
|
136
|
+
return this.#native;
|
|
137
|
+
}
|
|
138
|
+
const joined = formatMetricRow(this.#metrics, { separator: options.separator });
|
|
139
|
+
this.#native =
|
|
140
|
+
options.overflow === "wrap"
|
|
141
|
+
? text(styleSpans(joined, options.style), { wrap: "word" })
|
|
142
|
+
: text(styleSpans(joined, options.style), { wrap: "none", truncate: "end" });
|
|
143
|
+
return this.#native;
|
|
105
144
|
}
|
|
106
145
|
|
|
107
146
|
render(width: number): readonly string[] {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { compactText, styledSpans } from "../native/spans";
|
|
2
|
+
import { node } from "../native/describe";
|
|
3
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
1
4
|
import type { Component } from "../tui";
|
|
2
5
|
import { Ellipsis, getWidthConfigEpoch, truncateToWidth, visibleWidth } from "../utils";
|
|
3
6
|
|
|
@@ -87,6 +90,7 @@ export class ProgressBar implements Component {
|
|
|
87
90
|
#value: number | undefined;
|
|
88
91
|
readonly #options: ProgressBarOptions;
|
|
89
92
|
#cache: { width: number; epoch: number; value: number | undefined; lines: readonly string[] } | undefined;
|
|
93
|
+
#native: NativeNode | undefined;
|
|
90
94
|
|
|
91
95
|
constructor(value: number | undefined, options: ProgressBarOptions) {
|
|
92
96
|
this.#value = value;
|
|
@@ -97,11 +101,35 @@ export class ProgressBar implements Component {
|
|
|
97
101
|
if (Object.is(this.#value, value)) return false;
|
|
98
102
|
this.#value = value;
|
|
99
103
|
this.#cache = undefined;
|
|
104
|
+
this.#native = undefined;
|
|
100
105
|
return true;
|
|
101
106
|
}
|
|
102
107
|
|
|
103
108
|
invalidate(): void {
|
|
104
109
|
this.#cache = undefined;
|
|
110
|
+
this.#native = undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** A native `progress` bar (indeterminate when the value is unknown); prefix, suffix and percentage label it. */
|
|
114
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
115
|
+
if (this.#native) return this.#native;
|
|
116
|
+
const options = this.#options;
|
|
117
|
+
const fraction = progressFraction(this.#value, options.min, options.max);
|
|
118
|
+
const parts: string[] = [];
|
|
119
|
+
// Frame punctuation (`[`, `]`, `▕`) around the bar is the terminal's chrome now; only wording labels it.
|
|
120
|
+
const frame = /^[^\p{L}\p{N}]+|[^\p{L}\p{N}%)]+$/gu;
|
|
121
|
+
const prefix = singleLine(options.prefix ?? "").replace(frame, "");
|
|
122
|
+
const suffix = singleLine(options.suffix ?? "").replace(frame, "");
|
|
123
|
+
if (prefix) parts.push(prefix);
|
|
124
|
+
if (suffix) parts.push(suffix);
|
|
125
|
+
if (fraction !== undefined && options.showPercentage === true) {
|
|
126
|
+
parts.push(singleLine(options.formatPercentage?.(fraction) ?? `${Math.round(fraction * 100)}%`));
|
|
127
|
+
}
|
|
128
|
+
this.#native = node("progress", {
|
|
129
|
+
value: fraction ?? null,
|
|
130
|
+
label: parts.length > 0 ? compactText(styledSpans(parts.join(" "))) : undefined,
|
|
131
|
+
});
|
|
132
|
+
return this.#native;
|
|
105
133
|
}
|
|
106
134
|
|
|
107
135
|
render(width: number): readonly string[] {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { matchesKey } from "../keys";
|
|
2
|
+
import { rowsText } from "../native/spans";
|
|
3
|
+
import { col } from "../native/describe";
|
|
4
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
2
5
|
import type { Component } from "../tui";
|
|
3
6
|
import { Ellipsis, getWidthConfigEpoch, padding, replaceTabs, truncateToWidth, visibleWidth } from "../utils";
|
|
4
7
|
import {
|
|
@@ -126,6 +129,7 @@ export class ScrollView implements Component {
|
|
|
126
129
|
#rangeSnapshot: RangeSnapshot | undefined;
|
|
127
130
|
#cache: RenderCache | undefined;
|
|
128
131
|
#disposed = false;
|
|
132
|
+
#native: { content: readonly string[] | Component; height: number; node: NativeNode } | undefined;
|
|
129
133
|
|
|
130
134
|
constructor(content: readonly string[] | Component, options: ScrollViewOptions) {
|
|
131
135
|
this.#child = isComponent(content) ? content : undefined;
|
|
@@ -400,6 +404,7 @@ export class ScrollView implements Component {
|
|
|
400
404
|
invalidate(): void {
|
|
401
405
|
if (this.#disposed) return;
|
|
402
406
|
this.#cache = undefined;
|
|
407
|
+
this.#native = undefined;
|
|
403
408
|
this.#child?.invalidate?.();
|
|
404
409
|
}
|
|
405
410
|
|
|
@@ -415,6 +420,24 @@ export class ScrollView implements Component {
|
|
|
415
420
|
child?.dispose?.();
|
|
416
421
|
}
|
|
417
422
|
|
|
423
|
+
/**
|
|
424
|
+
* The whole content in a `col` capped at the viewport height: the
|
|
425
|
+
* terminal scrolls it natively and draws its own scrollbar.
|
|
426
|
+
*/
|
|
427
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
428
|
+
const content = this.#child ?? this.#lines;
|
|
429
|
+
const cached = this.#native;
|
|
430
|
+
if (cached?.content === content && cached.height === this.#height) return cached.node;
|
|
431
|
+
const described = this.#disposed
|
|
432
|
+
? col([], { hidden: true })
|
|
433
|
+
: col([this.#child ?? rowsText(this.#lines)], {
|
|
434
|
+
max: { h: `${this.#height}lines` },
|
|
435
|
+
hidden: this.#height === 0 ? true : undefined,
|
|
436
|
+
});
|
|
437
|
+
this.#native = { content, height: this.#height, node: described };
|
|
438
|
+
return described;
|
|
439
|
+
}
|
|
440
|
+
|
|
418
441
|
render(width: number): readonly string[] {
|
|
419
442
|
if (this.#disposed) return EMPTY_LINES;
|
|
420
443
|
const safeWidth = normalizedRows(width);
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { compactText, rowsText, styledSpans } from "../native/spans";
|
|
2
|
+
import { node } from "../native/describe";
|
|
3
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
1
4
|
import type { Component } from "../tui";
|
|
2
5
|
import { Ellipsis, getWidthConfigEpoch, replaceTabs, truncateToWidth, visibleWidth } from "../utils";
|
|
3
6
|
|
|
@@ -37,6 +40,7 @@ export class Section implements Component {
|
|
|
37
40
|
readonly #options: SectionOptions;
|
|
38
41
|
#cache: { width: number; epoch: number; child: readonly string[]; lines: readonly string[] } | undefined;
|
|
39
42
|
#disposed = false;
|
|
43
|
+
#native: { title: string; node: NativeNode } | undefined;
|
|
40
44
|
|
|
41
45
|
constructor(options: SectionOptions) {
|
|
42
46
|
this.#options = options;
|
|
@@ -53,6 +57,18 @@ export class Section implements Component {
|
|
|
53
57
|
if (isComponent(this.#options.body)) this.#options.body.dispose?.();
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
/** A `section` headed by the styled title; the rule is the terminal's. */
|
|
61
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
62
|
+
const options = this.#options;
|
|
63
|
+
const rawTitle = singleLine(options.title);
|
|
64
|
+
const title = options.titleStyle?.(rawTitle) ?? rawTitle;
|
|
65
|
+
if (this.#native?.title === title) return this.#native.node;
|
|
66
|
+
const body = isComponent(options.body) ? options.body : rowsText(options.body);
|
|
67
|
+
const described = node("section", { head: compactText(styledSpans(title)) }, [body]);
|
|
68
|
+
this.#native = { title, node: described };
|
|
69
|
+
return described;
|
|
70
|
+
}
|
|
71
|
+
|
|
56
72
|
render(width: number): readonly string[] {
|
|
57
73
|
const renderWidth = finiteWidth(width);
|
|
58
74
|
const epoch = getWidthConfigEpoch();
|