@oh-my-pi/pi-tui 18.4.2 → 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 +56 -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/thinking-display.d.ts +2 -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 +42 -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/loop-watchdog.d.ts +9 -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 +9 -1
- 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 +16 -9
- package/dist/types/setup/scenes/splash.d.ts +8 -0
- package/dist/types/setup/scenes/types.d.ts +6 -27
- 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/stdin-buffer.d.ts +10 -7
- package/dist/types/terminal-capabilities.d.ts +1 -1
- package/dist/types/terminal.d.ts +36 -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-types.d.ts +90 -0
- package/dist/types/tools/web-search.d.ts +9 -168
- 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 +538 -51
- 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/thinking-display.ts +73 -11
- 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 +139 -17
- 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 +239 -36
- 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 +131 -56
- 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/loop-watchdog.ts +38 -10
- 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 +184 -7
- 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 +585 -33
- 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 +138 -24
- package/src/setup/scenes/splash.ts +28 -1
- package/src/setup/scenes/theme.ts +88 -3
- package/src/setup/scenes/types.ts +7 -28
- package/src/setup/startup-splash.ts +46 -9
- package/src/setup/wizard-overlay.ts +140 -23
- package/src/setup/wizard.ts +1 -1
- package/src/status-line/component.ts +414 -18
- 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/stdin-buffer.ts +27 -21
- package/src/terminal-capabilities.ts +7 -0
- package/src/terminal.ts +153 -11
- 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/mermaid-cache.ts +10 -1
- 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/theme/tui-adapters.ts +14 -1
- 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 +233 -62
- 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 +357 -31
- 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/streaming-output.ts +79 -16
- 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-types.ts +99 -0
- package/src/tools/web-search.ts +111 -170
- package/src/tools/write.ts +144 -5
- package/src/tools/xdev.ts +64 -1
- package/src/tui.ts +295 -4
- package/dist/types/setup/scenes/providers.d.ts +0 -3
- package/dist/types/setup/scenes/web-search.d.ts +0 -22
- package/src/setup/scenes/providers.ts +0 -110
- package/src/setup/scenes/web-search.ts +0 -165
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";
|
|
@@ -880,7 +883,10 @@ for (const table of [Lexer.rules.block.normal, Lexer.rules.block.gfm]) {
|
|
|
880
883
|
|
|
881
884
|
const RENDER_CACHE_MAX = 256; // sane cap: ~256 distinct message × width combos
|
|
882
885
|
const RENDER_CACHE_MAX_SIZE = 4 * 1024 * 1024;
|
|
883
|
-
|
|
886
|
+
// Entry size counts the key (it embeds the whole normalized source) plus the
|
|
887
|
+
// rendered rows, so this admits roughly the same documents a rows-only 256 KiB
|
|
888
|
+
// cap did while the aggregate bound covers everything the entry retains.
|
|
889
|
+
const RENDER_CACHE_MAX_ENTRY_SIZE = 512 * 1024;
|
|
884
890
|
const EMPTY_RENDER_LINES: readonly string[] = [];
|
|
885
891
|
|
|
886
892
|
interface RenderedLine {
|
|
@@ -900,7 +906,7 @@ const renderCache = new LRUCache<string, readonly string[]>({
|
|
|
900
906
|
max: RENDER_CACHE_MAX,
|
|
901
907
|
maxSize: RENDER_CACHE_MAX_SIZE,
|
|
902
908
|
maxEntrySize: RENDER_CACHE_MAX_ENTRY_SIZE,
|
|
903
|
-
sizeCalculation: renderedLinesCacheSize,
|
|
909
|
+
sizeCalculation: (lines, key) => renderedLinesCacheSize(lines) + key.length,
|
|
904
910
|
});
|
|
905
911
|
|
|
906
912
|
function renderedLinesCacheSize(lines: readonly string[]): number {
|
|
@@ -909,6 +915,15 @@ function renderedLinesCacheSize(lines: readonly string[]): number {
|
|
|
909
915
|
return Math.max(1, size);
|
|
910
916
|
}
|
|
911
917
|
|
|
918
|
+
/**
|
|
919
|
+
* Append `src` onto `dst` element-wise. `dst.push(...src)` passes every row as
|
|
920
|
+
* a call argument, which throws past the engine's argument limit on very long
|
|
921
|
+
* documents.
|
|
922
|
+
*/
|
|
923
|
+
function appendLines(dst: string[], src: readonly string[]): void {
|
|
924
|
+
for (let i = 0; i < src.length; i++) dst.push(src[i]!);
|
|
925
|
+
}
|
|
926
|
+
|
|
912
927
|
// ---------------------------------------------------------------------------
|
|
913
928
|
// Fast-tail (B+) hazard gates
|
|
914
929
|
// ---------------------------------------------------------------------------
|
|
@@ -1661,7 +1676,9 @@ interface RenderSignature {
|
|
|
1661
1676
|
interface StreamPrefixLineCache extends RenderSignature {
|
|
1662
1677
|
text: string;
|
|
1663
1678
|
tokenCount: number;
|
|
1664
|
-
|
|
1679
|
+
// Private to the cache and never handed to callers (each frame copies it
|
|
1680
|
+
// into a fresh output array), so an advancing prefix appends in place.
|
|
1681
|
+
lines: string[];
|
|
1665
1682
|
}
|
|
1666
1683
|
/**
|
|
1667
1684
|
* Per-token row cache for the *unfrozen tail* (PoC H). The tail re-lexes every
|
|
@@ -1717,7 +1734,9 @@ interface TailRenderRecorder {
|
|
|
1717
1734
|
interface StreamingHighlightCache extends RenderSignature {
|
|
1718
1735
|
lang: string | undefined;
|
|
1719
1736
|
text: string;
|
|
1720
|
-
|
|
1737
|
+
// Appended in place as the fence grows. Only ever returned to
|
|
1738
|
+
// #renderCodeBodyLines, which reads it synchronously and keeps no reference.
|
|
1739
|
+
lines: string[];
|
|
1721
1740
|
stream: HighlightStreamSession;
|
|
1722
1741
|
}
|
|
1723
1742
|
|
|
@@ -1801,6 +1820,7 @@ export class Markdown implements Component {
|
|
|
1801
1820
|
// B+ capture plumbing: #renderContentLines records the last rendered paragraph row.
|
|
1802
1821
|
#lastTailCapture?: { kind: "paragraph"; open: boolean; rowInput: string; rowRaw: string };
|
|
1803
1822
|
#ignoreTight = false;
|
|
1823
|
+
#native?: { text: string; stream: boolean; node: NativeNode };
|
|
1804
1824
|
setIgnoreTight(ignore: boolean): this {
|
|
1805
1825
|
this.#ignoreTight = ignore;
|
|
1806
1826
|
this.invalidate();
|
|
@@ -1882,10 +1902,7 @@ export class Markdown implements Component {
|
|
|
1882
1902
|
// Blank replacement: render() early-returns before #lexTokens can see
|
|
1883
1903
|
// the non-append edit, so drop the frozen stream state here or it
|
|
1884
1904
|
// outlives the content it indexed.
|
|
1885
|
-
this.#
|
|
1886
|
-
this.#streamPrefixTokens = undefined;
|
|
1887
|
-
this.#streamPrefixLineCache = undefined;
|
|
1888
|
-
this.#tailRowCache = undefined;
|
|
1905
|
+
this.#dropStreamPrefix();
|
|
1889
1906
|
// B+: the captured fast-path rows index the replaced content — drop
|
|
1890
1907
|
// the recipe so a fresh stream cannot splice onto stale rows.
|
|
1891
1908
|
this.#fastTail = undefined;
|
|
@@ -1900,6 +1917,23 @@ export class Markdown implements Component {
|
|
|
1900
1917
|
this.#cachedLines = undefined;
|
|
1901
1918
|
}
|
|
1902
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
|
+
|
|
1903
1937
|
/**
|
|
1904
1938
|
* Width-independent source prefix of the last render ending at a frozen
|
|
1905
1939
|
* Markdown block boundary. Only meaningful while streaming (transient
|
|
@@ -1927,6 +1961,17 @@ export class Markdown implements Component {
|
|
|
1927
1961
|
// source — drop the fast-path recipe so stale rows cannot be served
|
|
1928
1962
|
// across the transition.
|
|
1929
1963
|
this.#fastTail = undefined;
|
|
1964
|
+
if (!next) {
|
|
1965
|
+
// Finalize: the prefix row cache, tail row cache and open-fence
|
|
1966
|
+
// highlight stream are read only by transient renders, and each
|
|
1967
|
+
// rebuilds from scratch if the block ever streams again — release
|
|
1968
|
+
// them so settled blocks stop pinning rows and a native parser.
|
|
1969
|
+
// The frozen lex prefix survives only until the next final-mode
|
|
1970
|
+
// render consumes it (see #lexTokens / the L2 hit path).
|
|
1971
|
+
this.#streamPrefixLineCache = undefined;
|
|
1972
|
+
this.#tailRowCache = undefined;
|
|
1973
|
+
this.#streamingHighlightCache = undefined;
|
|
1974
|
+
}
|
|
1930
1975
|
this.invalidate();
|
|
1931
1976
|
}
|
|
1932
1977
|
|
|
@@ -1964,8 +2009,14 @@ export class Markdown implements Component {
|
|
|
1964
2009
|
// happens exactly when the CR/ref-def trigger behind a false verdict
|
|
1965
2010
|
// may have been deleted — never left stale, and never re-scanned on
|
|
1966
2011
|
// frames where the memo is sound.
|
|
2012
|
+
const appendGrowth = this.#lastScanValid && this.#appendOnlySinceLastScan && text.length > this.#lastScanLength;
|
|
2013
|
+
// Final mode keeps the frozen prefix only while the text keeps growing
|
|
2014
|
+
// by appends (a stream rendered without the transient flag). A one-shot
|
|
2015
|
+
// or just-finalized render still lexes against any existing prefix but
|
|
2016
|
+
// then drops it, so settled blocks do not pin a token tree.
|
|
2017
|
+
const retainPrefix = this.#transientRenderCache || appendGrowth;
|
|
1967
2018
|
let canStream: boolean;
|
|
1968
|
-
if (
|
|
2019
|
+
if (appendGrowth) {
|
|
1969
2020
|
const delta = text.slice(this.#lastScanLength);
|
|
1970
2021
|
if (
|
|
1971
2022
|
!delta.includes("[") &&
|
|
@@ -1990,21 +2041,27 @@ export class Markdown implements Component {
|
|
|
1990
2041
|
if (canStream && hasPrefix) {
|
|
1991
2042
|
const tailTokens = lexDocument(refDefText);
|
|
1992
2043
|
const tokens = [...prefixTokens, ...tailTokens];
|
|
1993
|
-
this.#freezeStablePrefix(text, tokens, { preserveExisting: true });
|
|
2044
|
+
if (retainPrefix) this.#freezeStablePrefix(text, tokens, { preserveExisting: true });
|
|
2045
|
+
else this.#dropStreamPrefix();
|
|
1994
2046
|
return tokens;
|
|
1995
2047
|
}
|
|
1996
2048
|
const tokens = lexDocument(text);
|
|
1997
|
-
if (canStream) {
|
|
2049
|
+
if (canStream && retainPrefix) {
|
|
1998
2050
|
this.#freezeStablePrefix(text, tokens, { preserveExisting: false });
|
|
1999
2051
|
} else {
|
|
2000
|
-
this.#
|
|
2001
|
-
this.#streamPrefixTokens = undefined;
|
|
2002
|
-
this.#streamPrefixLineCache = undefined;
|
|
2003
|
-
this.#tailRowCache = undefined;
|
|
2052
|
+
this.#dropStreamPrefix();
|
|
2004
2053
|
}
|
|
2005
2054
|
return tokens;
|
|
2006
2055
|
}
|
|
2007
2056
|
|
|
2057
|
+
/** Drop the frozen lex prefix and the transient row caches keyed on it. */
|
|
2058
|
+
#dropStreamPrefix(): void {
|
|
2059
|
+
this.#streamPrefixText = undefined;
|
|
2060
|
+
this.#streamPrefixTokens = undefined;
|
|
2061
|
+
this.#streamPrefixLineCache = undefined;
|
|
2062
|
+
this.#tailRowCache = undefined;
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2008
2065
|
// Freeze the largest run of leading blocks that end on a hard "\n\n" boundary
|
|
2009
2066
|
// (complete and immutable under append-only growth) so the next streaming
|
|
2010
2067
|
// render re-lexes only the unfrozen tail. Caller guarantees no CR / no
|
|
@@ -2032,12 +2089,7 @@ export class Markdown implements Component {
|
|
|
2032
2089
|
return;
|
|
2033
2090
|
}
|
|
2034
2091
|
|
|
2035
|
-
if (!opts.preserveExisting)
|
|
2036
|
-
this.#streamPrefixText = undefined;
|
|
2037
|
-
this.#streamPrefixTokens = undefined;
|
|
2038
|
-
this.#streamPrefixLineCache = undefined;
|
|
2039
|
-
this.#tailRowCache = undefined;
|
|
2040
|
-
}
|
|
2092
|
+
if (!opts.preserveExisting) this.#dropStreamPrefix();
|
|
2041
2093
|
}
|
|
2042
2094
|
|
|
2043
2095
|
render(width: number): readonly string[] {
|
|
@@ -2166,9 +2218,12 @@ export class Markdown implements Component {
|
|
|
2166
2218
|
);
|
|
2167
2219
|
}
|
|
2168
2220
|
// Splice onto the previous frame's rows (new array — parent may
|
|
2169
|
-
// hold the old one).
|
|
2221
|
+
// hold the old one). One copy of the head, then the few new and
|
|
2222
|
+
// trailing rows, instead of spreading two intermediate slices.
|
|
2170
2223
|
const prev = recipe.lines;
|
|
2171
|
-
const fastResult =
|
|
2224
|
+
const fastResult = prev.slice(0, recipe.rowStart);
|
|
2225
|
+
appendLines(fastResult, fastRows);
|
|
2226
|
+
for (let i = recipe.rowEnd; i < prev.length; i++) fastResult.push(prev[i]!);
|
|
2172
2227
|
this.#cachedText = this.#text;
|
|
2173
2228
|
this.#cachedWidth = width;
|
|
2174
2229
|
this.#cachedLines = fastResult;
|
|
@@ -2220,6 +2275,10 @@ export class Markdown implements Component {
|
|
|
2220
2275
|
cacheKey = this.#renderCacheKey(normalizedText, signature);
|
|
2221
2276
|
const cached = renderCache.get(cacheKey);
|
|
2222
2277
|
if (cached !== undefined) {
|
|
2278
|
+
// A final-mode hit right after finalize (or a non-append edit)
|
|
2279
|
+
// never reaches #lexTokens, which would otherwise consume and drop
|
|
2280
|
+
// the frozen lex prefix — release it here instead.
|
|
2281
|
+
if (!this.#appendOnlySinceLastScan) this.#dropStreamPrefix();
|
|
2223
2282
|
// Populate L1 so subsequent calls from this instance are O(1) map lookup.
|
|
2224
2283
|
this.#cachedText = this.#text;
|
|
2225
2284
|
this.#cachedWidth = width;
|
|
@@ -2241,8 +2300,10 @@ export class Markdown implements Component {
|
|
|
2241
2300
|
}
|
|
2242
2301
|
const emptyLines = this.#renderEmptyPaddingLines(signature);
|
|
2243
2302
|
|
|
2244
|
-
// Combine top padding, content, and bottom padding
|
|
2245
|
-
|
|
2303
|
+
// Combine top padding, content, and bottom padding. contentLines is a
|
|
2304
|
+
// fresh per-render array (never cache-owned), so without vertical
|
|
2305
|
+
// padding it is handed out as-is rather than copied again.
|
|
2306
|
+
const rawResult = emptyLines.length === 0 ? contentLines : [...emptyLines, ...contentLines, ...emptyLines];
|
|
2246
2307
|
const result = rawResult.length > 0 ? rawResult : [""];
|
|
2247
2308
|
|
|
2248
2309
|
// Update caches and hand the array out by reference. Callers must not
|
|
@@ -2329,11 +2390,15 @@ export class Markdown implements Component {
|
|
|
2329
2390
|
return this.#renderStreamingTail(tokens, 0, contentWidth, signature);
|
|
2330
2391
|
}
|
|
2331
2392
|
|
|
2332
|
-
|
|
2393
|
+
// Prefix rows live in #streamPrefixLineCache.lines, which is private to
|
|
2394
|
+
// the cache: an advancing prefix appends its newly frozen rows in place
|
|
2395
|
+
// instead of re-snapshotting, and each frame's output is one fresh copy
|
|
2396
|
+
// of prefix + tail, so no array handed to a caller is ever mutated.
|
|
2333
2397
|
const reusablePrefix = this.#matchingStreamPrefixLineCache(normalizedText, stableText, signature);
|
|
2398
|
+
let prefixLines: string[] = [];
|
|
2334
2399
|
let renderedUntil = 0;
|
|
2335
2400
|
if (reusablePrefix && reusablePrefix.tokenCount <= stableTokenCount) {
|
|
2336
|
-
|
|
2401
|
+
prefixLines = reusablePrefix.lines;
|
|
2337
2402
|
renderedUntil = reusablePrefix.tokenCount;
|
|
2338
2403
|
}
|
|
2339
2404
|
|
|
@@ -2341,13 +2406,14 @@ export class Markdown implements Component {
|
|
|
2341
2406
|
// Stable tokens render with full fidelity (syntax highlighting on)
|
|
2342
2407
|
// so these cached rows byte-match the finalized render.
|
|
2343
2408
|
this.#renderingStablePrefix = true;
|
|
2409
|
+
let frozenRows: string[];
|
|
2344
2410
|
try {
|
|
2345
|
-
|
|
2346
|
-
...this.#renderContentLines(tokens, renderedUntil, stableTokenCount, contentWidth, signature),
|
|
2347
|
-
);
|
|
2411
|
+
frozenRows = this.#renderContentLines(tokens, renderedUntil, stableTokenCount, contentWidth, signature);
|
|
2348
2412
|
} finally {
|
|
2349
2413
|
this.#renderingStablePrefix = false;
|
|
2350
2414
|
}
|
|
2415
|
+
if (prefixLines.length === 0) prefixLines = frozenRows;
|
|
2416
|
+
else appendLines(prefixLines, frozenRows);
|
|
2351
2417
|
renderedUntil = stableTokenCount;
|
|
2352
2418
|
}
|
|
2353
2419
|
|
|
@@ -2355,14 +2421,11 @@ export class Markdown implements Component {
|
|
|
2355
2421
|
...signature,
|
|
2356
2422
|
text: stableText,
|
|
2357
2423
|
tokenCount: stableTokenCount,
|
|
2358
|
-
lines:
|
|
2424
|
+
lines: prefixLines,
|
|
2359
2425
|
};
|
|
2360
2426
|
|
|
2361
|
-
if (renderedUntil
|
|
2362
|
-
|
|
2363
|
-
}
|
|
2364
|
-
|
|
2365
|
-
return contentLines;
|
|
2427
|
+
if (renderedUntil >= tokens.length) return prefixLines.slice();
|
|
2428
|
+
return prefixLines.concat(this.#renderStreamingTail(tokens, renderedUntil, contentWidth, signature));
|
|
2366
2429
|
}
|
|
2367
2430
|
|
|
2368
2431
|
#matchingStreamPrefixLineCache(
|
|
@@ -2403,7 +2466,7 @@ export class Markdown implements Component {
|
|
|
2403
2466
|
if (cache !== undefined) {
|
|
2404
2467
|
spliceEnd = this.#tailSpliceEnd(cache, start, signature, tokens);
|
|
2405
2468
|
for (let i = start; i < spliceEnd; i++) {
|
|
2406
|
-
out
|
|
2469
|
+
appendLines(out, cache.rows[i - start]!);
|
|
2407
2470
|
}
|
|
2408
2471
|
}
|
|
2409
2472
|
|
|
@@ -2416,7 +2479,7 @@ export class Markdown implements Component {
|
|
|
2416
2479
|
nextTypes: new Array(tokens.length - spliceEnd).fill(undefined),
|
|
2417
2480
|
};
|
|
2418
2481
|
const fresh = this.#renderContentLines(tokens, spliceEnd, tokens.length, contentWidth, signature, recorder);
|
|
2419
|
-
out.
|
|
2482
|
+
const result = out.length === 0 ? fresh : out.concat(fresh);
|
|
2420
2483
|
|
|
2421
2484
|
// Refresh the cache: keep entries for spliced tokens (their raws stay
|
|
2422
2485
|
// valid), overlay the fresh entries, and re-derive the contiguous
|
|
@@ -2453,7 +2516,7 @@ export class Markdown implements Component {
|
|
|
2453
2516
|
raws,
|
|
2454
2517
|
nextTypes,
|
|
2455
2518
|
};
|
|
2456
|
-
return
|
|
2519
|
+
return result;
|
|
2457
2520
|
}
|
|
2458
2521
|
|
|
2459
2522
|
// Longest cache-spliceable prefix: every cached row from `start` up to
|
|
@@ -2658,7 +2721,7 @@ export class Markdown implements Component {
|
|
|
2658
2721
|
// colors reach completed rows immediately; only the trailing partial
|
|
2659
2722
|
// line stays unhighlighted.
|
|
2660
2723
|
const lineEnd = tokenText.lastIndexOf("\n");
|
|
2661
|
-
const completedLines = lineEnd >= 0 ? this.#highlightStreamingLines(tokenText
|
|
2724
|
+
const completedLines = lineEnd >= 0 ? this.#highlightStreamingLines(tokenText, lineEnd, lang) : null;
|
|
2662
2725
|
if (completedLines) {
|
|
2663
2726
|
for (const hlLine of completedLines) {
|
|
2664
2727
|
addBodyLine(hlLine);
|
|
@@ -2708,21 +2771,28 @@ export class Markdown implements Component {
|
|
|
2708
2771
|
}
|
|
2709
2772
|
|
|
2710
2773
|
/**
|
|
2711
|
-
* Highlight the completed (newline-terminated) prefix
|
|
2712
|
-
* fence. Uses a stateful per-fence
|
|
2713
|
-
* only the newly completed lines,
|
|
2714
|
-
* whole-block `highlightCode` the
|
|
2715
|
-
* when no stream is available for
|
|
2716
|
-
* code-block styling).
|
|
2774
|
+
* Highlight the completed (newline-terminated) prefix `tokenText[0,
|
|
2775
|
+
* completedEnd)` of a streaming code fence. Uses a stateful per-fence
|
|
2776
|
+
* highlight stream so each render pushes only the newly completed lines,
|
|
2777
|
+
* with output byte-identical to the whole-block `highlightCode` the
|
|
2778
|
+
* finalized render performs. Returns null when no stream is available for
|
|
2779
|
+
* `lang` (caller falls back to plain code-block styling).
|
|
2717
2780
|
*/
|
|
2718
|
-
#highlightStreamingLines(
|
|
2781
|
+
#highlightStreamingLines(
|
|
2782
|
+
tokenText: string,
|
|
2783
|
+
completedEnd: number,
|
|
2784
|
+
lang: string | undefined,
|
|
2785
|
+
): readonly string[] | null {
|
|
2719
2786
|
const signature = this.#activeRenderSignature;
|
|
2720
2787
|
const cache = this.#streamingHighlightCache;
|
|
2788
|
+
// Cheap cursor/length and signature gates first; the prefix compare
|
|
2789
|
+
// (the only O(fence) check, needed because a different fence can reach
|
|
2790
|
+
// this cache) runs last.
|
|
2721
2791
|
if (
|
|
2722
2792
|
signature &&
|
|
2723
2793
|
cache &&
|
|
2724
|
-
|
|
2725
|
-
(cache.text.length ===
|
|
2794
|
+
cache.text.length <= completedEnd &&
|
|
2795
|
+
(cache.text.length === completedEnd || tokenText.charCodeAt(cache.text.length) === 0x0a) &&
|
|
2726
2796
|
cache.lang === lang &&
|
|
2727
2797
|
cache.width === signature.width &&
|
|
2728
2798
|
cache.paddingX === signature.paddingX &&
|
|
@@ -2734,18 +2804,23 @@ export class Markdown implements Component {
|
|
|
2734
2804
|
cache.hyperlinks === signature.hyperlinks &&
|
|
2735
2805
|
cache.textSizing === signature.textSizing &&
|
|
2736
2806
|
cache.bgColorProbe === signature.bgColorProbe &&
|
|
2737
|
-
cache.headingProbe === signature.headingProbe
|
|
2807
|
+
cache.headingProbe === signature.headingProbe &&
|
|
2808
|
+
tokenText.startsWith(cache.text)
|
|
2738
2809
|
) {
|
|
2739
|
-
|
|
2810
|
+
const cachedEnd = cache.text.length;
|
|
2811
|
+
if (cachedEnd === completedEnd) return cache.lines;
|
|
2740
2812
|
// Invariant: the stream has consumed `cache.text + "\n"`, so pushing
|
|
2741
2813
|
// the added lines with a trailing newline advances it to
|
|
2742
|
-
// `
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2814
|
+
// `completed + "\n"` — every fed line stays newline-terminated. The
|
|
2815
|
+
// signature gates above matched, so advancing the cache in place is
|
|
2816
|
+
// equivalent to rebuilding it, minus the whole-array copy per frame.
|
|
2817
|
+
const pushed = cache.stream.push(`${tokenText.slice(cachedEnd + 1, completedEnd)}\n`);
|
|
2818
|
+
appendLines(cache.lines, splitPushedHighlightLines(pushed));
|
|
2819
|
+
cache.text = tokenText.slice(0, completedEnd);
|
|
2820
|
+
return cache.lines;
|
|
2747
2821
|
}
|
|
2748
2822
|
|
|
2823
|
+
const completedText = tokenText.slice(0, completedEnd);
|
|
2749
2824
|
const stream = this.#createHighlightStream(lang);
|
|
2750
2825
|
if (!stream) return null;
|
|
2751
2826
|
const lines = splitPushedHighlightLines(stream.push(`${completedText}\n`));
|