@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/prompt/welcome.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { TERMINAL } from "../terminal-capabilities";
|
|
2
|
-
import type { Component } from "../tui";
|
|
3
|
-
import { padding, replaceTabs, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../utils";
|
|
4
1
|
import { APP_NAME } from "@oh-my-pi/pi-utils/dirs";
|
|
5
|
-
import {
|
|
2
|
+
import type { TspSpan } from "@oh-my-pi/pi-wire";
|
|
6
3
|
import { formatDoubleTap, formatKeyHint, formatKeyHints, type KeyName } from "../app-keybindings";
|
|
7
4
|
import { editorKey } from "../chrome/keybinding-hints";
|
|
8
5
|
import { getKeybindings, type Keybinding } from "../keybindings";
|
|
6
|
+
import { registerNativeBlob } from "../native/blobs";
|
|
7
|
+
import { card, col, kbd, keyed, node, row, span, text } from "../native/describe";
|
|
8
|
+
import type { DescribeContext, NativeChild, NativeNode, NativeUiEvent } from "../native/node";
|
|
9
|
+
import { runTranscriptAction } from "../chat/transcript-actions";
|
|
10
|
+
import { plainLine } from "../native/spans";
|
|
11
|
+
import { isNativeRendering } from "../native/state";
|
|
12
|
+
import { TERMINAL } from "../terminal-capabilities";
|
|
13
|
+
import { theme } from "../theme/theme";
|
|
14
|
+
import type { Component } from "../tui";
|
|
15
|
+
import { padding, replaceTabs, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "../utils";
|
|
9
16
|
import tipsText from "./tips.txt" with { type: "text" };
|
|
10
17
|
|
|
11
18
|
/** Tips embedded at build time, one per line; blanks dropped. Key placeholders
|
|
@@ -84,7 +91,12 @@ function renderNewTag(phase: number, encoding: ColorEncoding): string {
|
|
|
84
91
|
/** Key placeholders in tips.txt: `{key:shift+tab}`, `{keys:up,down}`, `{tap:left}`, `{action:tui.editor.undo}`. */
|
|
85
92
|
const TIP_KEY_PLACEHOLDER = /\{(key|keys|tap|action):([^}]+)\}/g;
|
|
86
93
|
|
|
87
|
-
const MODIFIER_NAMES: Record<string, true | undefined> = {
|
|
94
|
+
const MODIFIER_NAMES: Record<string, true | undefined> = {
|
|
95
|
+
ctrl: true,
|
|
96
|
+
shift: true,
|
|
97
|
+
alt: true,
|
|
98
|
+
super: true,
|
|
99
|
+
};
|
|
88
100
|
|
|
89
101
|
/** A `+`-joined chord whose leading parts are modifiers (`ctrl+o`, `shift`, `left`). */
|
|
90
102
|
function isKeyName(key: string): key is KeyName {
|
|
@@ -154,6 +166,8 @@ export function renderWelcomeTip(tip: string, boxWidth: number, phase = 0): stri
|
|
|
154
166
|
export interface RecentSession {
|
|
155
167
|
name: string;
|
|
156
168
|
timeAgo: string;
|
|
169
|
+
/** Session file; a native click on the row resumes it. */
|
|
170
|
+
path?: string;
|
|
157
171
|
}
|
|
158
172
|
|
|
159
173
|
export interface LspServerInfo {
|
|
@@ -180,6 +194,7 @@ export class WelcomeComponent implements Component {
|
|
|
180
194
|
// Bypassed while the intro animation runs (every frame differs).
|
|
181
195
|
#cachedWidth = -1;
|
|
182
196
|
#cachedLines: string[] | undefined;
|
|
197
|
+
#native: { tip: string | undefined; node: NativeNode } | undefined;
|
|
183
198
|
|
|
184
199
|
constructor(
|
|
185
200
|
private version: string,
|
|
@@ -201,7 +216,152 @@ export class WelcomeComponent implements Component {
|
|
|
201
216
|
invalidate(): void {
|
|
202
217
|
this.#cachedWidth = -1;
|
|
203
218
|
this.#cachedLines = undefined;
|
|
219
|
+
this.#native = undefined;
|
|
204
220
|
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* A `card` (`omp.welcome`) titled with the app version. The brand column
|
|
224
|
+
* (`omp.welcome.brand`: greeting, the animated SVG mark, model, provider) sits
|
|
225
|
+
* beside the info column (`omp.welcome.info`: prompt-sigil keycaps, LSP
|
|
226
|
+
* servers, recent sessions); the tip of the session closes the card. Roles
|
|
227
|
+
* carry the look (gradient logo, type scale, column hairline); a "[NEW]" tip
|
|
228
|
+
* carries a terminal-clocked shimmering tag.
|
|
229
|
+
*/
|
|
230
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
231
|
+
const tip = this.tip;
|
|
232
|
+
if (this.#native && this.#native.tip === tip) return this.#native.node;
|
|
233
|
+
const line = (spans: readonly TspSpan[], role?: string, key?: string): NativeNode =>
|
|
234
|
+
keyed(text(spans, { wrap: "none", truncate: "end", role }), key ?? role ?? "");
|
|
235
|
+
// Centered brand lines are short and fixed; the logo is multi-line art that must never truncate.
|
|
236
|
+
const art = (spans: readonly TspSpan[], role: string): NativeNode =>
|
|
237
|
+
keyed(text(spans, { wrap: "none", role }), role);
|
|
238
|
+
const brand = keyed(
|
|
239
|
+
col(
|
|
240
|
+
[
|
|
241
|
+
art([span("Welcome back!", "strong")], "omp.welcome.greeting"),
|
|
242
|
+
node(
|
|
243
|
+
"image",
|
|
244
|
+
{
|
|
245
|
+
blob: welcomeLogoBlob(),
|
|
246
|
+
alt: APP_NAME,
|
|
247
|
+
w: 128,
|
|
248
|
+
role: "omp.welcome.logo",
|
|
249
|
+
},
|
|
250
|
+
undefined,
|
|
251
|
+
"logo",
|
|
252
|
+
),
|
|
253
|
+
art([span(plainLine(this.modelName), "accent")], "omp.welcome.model"),
|
|
254
|
+
art([span(plainLine(this.providerName), "muted")], "omp.welcome.provider"),
|
|
255
|
+
],
|
|
256
|
+
{ align: "center", role: "omp.welcome.brand" },
|
|
257
|
+
),
|
|
258
|
+
"brand",
|
|
259
|
+
);
|
|
260
|
+
const section = (key: string, label: string, rows: readonly NativeChild[]): NativeNode =>
|
|
261
|
+
keyed(
|
|
262
|
+
col([line([span(label, "dim")], "omp.welcome.heading"), ...rows], {
|
|
263
|
+
gap: "xs",
|
|
264
|
+
role: `omp.welcome.${key}`,
|
|
265
|
+
}),
|
|
266
|
+
key,
|
|
267
|
+
);
|
|
268
|
+
const shortcut = (key: string, label: string): NativeNode =>
|
|
269
|
+
keyed(row([kbd(key), line([span(label, "muted")])], { gap: "sm" }), label);
|
|
270
|
+
const info: NativeChild[] = [
|
|
271
|
+
line([span(this.version, "dim mono")], "omp.welcome.version"),
|
|
272
|
+
section("tips", "Tips", [
|
|
273
|
+
shortcut("#", "prompt actions"),
|
|
274
|
+
shortcut("/", "commands"),
|
|
275
|
+
shortcut("!", "run bash"),
|
|
276
|
+
shortcut("$", "run python"),
|
|
277
|
+
]),
|
|
278
|
+
];
|
|
279
|
+
if (this.lspServers !== null) {
|
|
280
|
+
const lsp: NativeChild[] = [];
|
|
281
|
+
if (this.lspServers.length === 0) lsp.push(line([span("No LSP servers", "dim")], undefined, "none"));
|
|
282
|
+
for (const server of this.lspServers.slice(0, WELCOME_LSP_SLOTS)) {
|
|
283
|
+
const [symbol, token] =
|
|
284
|
+
server.status === "ready"
|
|
285
|
+
? (["status.enabled", "success"] as const)
|
|
286
|
+
: server.status === "available"
|
|
287
|
+
? (["status.enabled", "dim"] as const)
|
|
288
|
+
: server.status === "connecting"
|
|
289
|
+
? (["status.pending", "muted"] as const)
|
|
290
|
+
: (["status.error", "error"] as const);
|
|
291
|
+
lsp.push(
|
|
292
|
+
keyed(
|
|
293
|
+
row(
|
|
294
|
+
[
|
|
295
|
+
text([span("●", token)], { role: "omp.welcome.lsp-dot", title: server.status, aria: symbol }),
|
|
296
|
+
line([span(server.name)]),
|
|
297
|
+
...server.fileTypes
|
|
298
|
+
.slice(0, 3)
|
|
299
|
+
.map(type => node("badge", { text: type, role: "omp.welcome.lsp-type" }, undefined, type)),
|
|
300
|
+
],
|
|
301
|
+
{ gap: "sm", role: "omp.welcome.lsp-row" },
|
|
302
|
+
),
|
|
303
|
+
server.name,
|
|
304
|
+
),
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
info.push(section("lsp", "LSP servers", lsp));
|
|
308
|
+
}
|
|
309
|
+
const recents: NativeChild[] = [];
|
|
310
|
+
if (this.recentSessions.length === 0) recents.push(line([span("No recent sessions", "dim")], undefined, "none"));
|
|
311
|
+
for (const [index, session] of this.recentSessions.slice(0, WELCOME_SESSION_SLOTS).entries()) {
|
|
312
|
+
recents.push(
|
|
313
|
+
keyed(
|
|
314
|
+
row(
|
|
315
|
+
[
|
|
316
|
+
line([span(plainLine(session.name))], "omp.welcome.session"),
|
|
317
|
+
line([span(session.timeAgo, "dim")], "omp.welcome.age"),
|
|
318
|
+
],
|
|
319
|
+
{
|
|
320
|
+
gap: "md",
|
|
321
|
+
justify: "between",
|
|
322
|
+
role: "omp.welcome.recent",
|
|
323
|
+
actions: session.path ? { click: "resume" } : undefined,
|
|
324
|
+
title: session.path ? `Resume ${plainLine(session.name)}` : undefined,
|
|
325
|
+
},
|
|
326
|
+
),
|
|
327
|
+
`s${index}`,
|
|
328
|
+
),
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
info.push(section("recents", "Recent sessions", recents));
|
|
332
|
+
const body: NativeChild[] = [
|
|
333
|
+
keyed(
|
|
334
|
+
row([brand, keyed(col(info, { gap: "md", role: "omp.welcome.info" }), "info")], {
|
|
335
|
+
align: "start",
|
|
336
|
+
wrap: true,
|
|
337
|
+
role: "omp.welcome.grid",
|
|
338
|
+
}),
|
|
339
|
+
"grid",
|
|
340
|
+
),
|
|
341
|
+
];
|
|
342
|
+
if (tip) {
|
|
343
|
+
const isNew = NEW_TIP_MARKER.test(tip);
|
|
344
|
+
const tipText = plainLine(expandTipKeys(isNew ? tip.replace(NEW_TIP_MARKER, "") : tip));
|
|
345
|
+
const tipRow: NativeChild[] = [
|
|
346
|
+
node("icon", { name: "lightbulb", role: "omp.welcome.tip-icon" }),
|
|
347
|
+
text(tipText, { wrap: "word", role: "omp.welcome.tip-text" }),
|
|
348
|
+
];
|
|
349
|
+
if (isNew) tipRow.push(node("shimmer", { text: "New", role: "omp.welcome.new" }));
|
|
350
|
+
body.push(node("row", { gap: "sm", align: "start", role: "omp.welcome.tip" }, tipRow, "tip"));
|
|
351
|
+
}
|
|
352
|
+
// No head row or chevron: the card is the hero; the version sits in the info column.
|
|
353
|
+
const described = card({ role: "omp.welcome" }, body);
|
|
354
|
+
this.#native = { tip, node: described };
|
|
355
|
+
return described;
|
|
356
|
+
}
|
|
357
|
+
/** A click on a recent session resumes it. */
|
|
358
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
359
|
+
if (event.type !== "action" || event.act !== "resume") return;
|
|
360
|
+
const index = Number(/\/s(\d+)$/.exec(event.key)?.[1]);
|
|
361
|
+
const path = this.recentSessions[index]?.path;
|
|
362
|
+
if (path) runTranscriptAction({ act: "resume", path });
|
|
363
|
+
}
|
|
364
|
+
|
|
205
365
|
/** The intro keeps the welcome block mutable; settling lets it retire to history. */
|
|
206
366
|
isTranscriptBlockFinalized(): boolean {
|
|
207
367
|
return this.#animTimer == null;
|
|
@@ -214,6 +374,12 @@ export class WelcomeComponent implements Component {
|
|
|
214
374
|
*/
|
|
215
375
|
playIntro(requestRender: () => void): void {
|
|
216
376
|
this.#stopAnimation();
|
|
377
|
+
// The intro is a repaint-only gradient sweep; a TSP terminal shows the
|
|
378
|
+
// settled card right away.
|
|
379
|
+
if (isNativeRendering()) {
|
|
380
|
+
requestRender();
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
217
383
|
this.#requestRender = requestRender;
|
|
218
384
|
this.#animStart = performance.now();
|
|
219
385
|
this.#requestRender();
|
|
@@ -516,9 +682,47 @@ export class WelcomeComponent implements Component {
|
|
|
516
682
|
}
|
|
517
683
|
}
|
|
518
684
|
|
|
685
|
+
/**
|
|
686
|
+
* {@link PI_LOGO} as SVG for the native welcome, on the terminal's grid: a
|
|
687
|
+
* cell is 3×6 units, so the 12×5-cell art spans 36×30 from (14,16). The left
|
|
688
|
+
* leg's `▒▒` tail is a half-opacity cell; the gradient spans the whole art in
|
|
689
|
+
* user space (per-axis normalized, like {@link gradientLogo}) so the tail
|
|
690
|
+
* keeps its colour. Tern mounts SVG blobs as live DOM, so the classes are
|
|
691
|
+
* animation hooks: `trace` (the outline, `pathLength=1` for a draw-on), `mark`
|
|
692
|
+
* (the fills) and the gradient stops `s0`–`s2`.
|
|
693
|
+
*/
|
|
694
|
+
const WELCOME_LOGO_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="10 12 44 38">
|
|
695
|
+
<defs><linearGradient id="g" gradientUnits="userSpaceOnUse" gradientTransform="matrix(36 0 0 30 14 16)" x1="0" y1="0" x2="1" y2="1">
|
|
696
|
+
<stop class="s0" offset="0" stop-color="#ed4abf"/><stop class="s1" offset=".5" stop-color="#9b4dff"/><stop class="s2" offset="1" stop-color="#5ad8e6"/>
|
|
697
|
+
</linearGradient></defs>
|
|
698
|
+
<path class="mark" fill="url(#g)" d="M14 16h36v6h-9v24h-6V22h-6v12h-6V22h-9z"/>
|
|
699
|
+
<rect class="mark" fill="url(#g)" opacity=".5" x="23" y="34" width="6" height="6"/>
|
|
700
|
+
<path class="trace" fill="none" stroke="url(#g)" stroke-width="1" stroke-linejoin="round" pathLength="1" d="M14 16h36v6h-9v24h-6V22h-6v18h-6V22h-9z"/>
|
|
701
|
+
</svg>`;
|
|
702
|
+
|
|
703
|
+
let welcomeLogoId: string | undefined;
|
|
704
|
+
|
|
705
|
+
/** The registered blob id of {@link WELCOME_LOGO_SVG}. */
|
|
706
|
+
function welcomeLogoBlob(): string {
|
|
707
|
+
welcomeLogoId ??= registerNativeBlob(new TextEncoder().encode(WELCOME_LOGO_SVG), "image/svg+xml");
|
|
708
|
+
return welcomeLogoId;
|
|
709
|
+
}
|
|
710
|
+
|
|
519
711
|
/** Block-grid brand mark shared by the welcome and setup surfaces. */
|
|
520
712
|
export const PI_LOGO = ["████████████", " ██ ██ ", " ██ ██ ", " ▒▒ ██ ", " ██ "];
|
|
521
713
|
|
|
714
|
+
/** The block-grid brand mark as accent lines; `shimmer` declares the terminal-clocked shine sweep. */
|
|
715
|
+
export function logoNode(lines: readonly string[], shimmer: boolean): NativeNode {
|
|
716
|
+
return col(
|
|
717
|
+
lines.map(line =>
|
|
718
|
+
text([span(line, "accent", shimmer ? { fx: "shimmer" } : undefined)], {
|
|
719
|
+
wrap: "none",
|
|
720
|
+
}),
|
|
721
|
+
),
|
|
722
|
+
{ align: "center", role: "omp.setup.logo" },
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
|
|
522
726
|
/** Multi-stop palette for the diagonal gradient. */
|
|
523
727
|
const GRADIENT_STOPS: ReadonlyArray<readonly [number, number, number]> = [
|
|
524
728
|
[248, 79, 204], // oklch(0.7 0.24 340)
|
|
@@ -637,7 +841,10 @@ function introLogoFrame(progress: number): string[] {
|
|
|
637
841
|
const phase = ((((1 - eased) * INTRO_SWEEPS) % 1) + 1) % 1;
|
|
638
842
|
const shinePos = (((progress * INTRO_SHINE_TRAVERSALS) % 1) + 1) % 1;
|
|
639
843
|
const shineStrength = (1 - eased) ** 1.5;
|
|
640
|
-
return gradientLogo(PI_LOGO, phase, {
|
|
844
|
+
return gradientLogo(PI_LOGO, phase, {
|
|
845
|
+
strength: shineStrength,
|
|
846
|
+
pos: shinePos,
|
|
847
|
+
});
|
|
641
848
|
}
|
|
642
849
|
|
|
643
850
|
/** Resting gradient frame, cached for re-renders outside of the intro. */
|
package/src/render/code-cell.ts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Render a code or markdown cell with optional output section.
|
|
3
3
|
*/
|
|
4
|
+
import type { TspSpan } from "@oh-my-pi/pi-wire";
|
|
4
5
|
import { Markdown } from "../components/markdown";
|
|
6
|
+
import { styledSpans } from "../native/spans";
|
|
7
|
+
import { code, md, span } from "../native/describe";
|
|
8
|
+
import type { NativeNode } from "../native/node";
|
|
5
9
|
import { getMarkdownTheme, highlightCode, type Theme } from "../theme/theme";
|
|
6
10
|
import { formatDuration, formatExpandHint, formatMoreItems, formatStatusIcon, replaceTabs } from "./render-utils";
|
|
7
|
-
import {
|
|
8
|
-
|
|
11
|
+
import {
|
|
12
|
+
describeOutputBlock,
|
|
13
|
+
type NativeOutputBlockSection,
|
|
14
|
+
outputBlockContentWidth,
|
|
15
|
+
renderOutputBlock,
|
|
16
|
+
} from "./output-block";
|
|
17
|
+
import {
|
|
18
|
+
describeOutputLines,
|
|
19
|
+
formatOutputPaneLines,
|
|
20
|
+
splitTerminalOutputLines,
|
|
21
|
+
styleToolOutputLine,
|
|
22
|
+
} from "./output-pane";
|
|
9
23
|
import type { State } from "./types";
|
|
10
24
|
|
|
11
25
|
/** Content and display limits for a code preview with optional output. */
|
|
@@ -188,6 +202,93 @@ export function renderCodeCell(options: CodeCellOptions, theme: Theme): string[]
|
|
|
188
202
|
return renderOutputBlock({ header: title, headerMeta: meta, state, sections, width }, theme);
|
|
189
203
|
}
|
|
190
204
|
|
|
205
|
+
type CellHeaderOptions = Pick<CodeCellOptions, "index" | "total" | "title" | "duration" | "language" | "showLanguage">;
|
|
206
|
+
|
|
207
|
+
/** Header spans for a native cell: language icon, `[i/n]`, title. Status is the card's chip. */
|
|
208
|
+
function describeHeader(options: CellHeaderOptions, theme: Theme): { head: TspSpan[]; meta?: TspSpan[] } {
|
|
209
|
+
const head: TspSpan[] = [];
|
|
210
|
+
const push = (part: readonly TspSpan[]): void => {
|
|
211
|
+
if (head.length > 0) head.push(span(" "));
|
|
212
|
+
head.push(...part);
|
|
213
|
+
};
|
|
214
|
+
if (options.showLanguage && options.language) {
|
|
215
|
+
const icon = theme.getLangIconStyled(options.language);
|
|
216
|
+
if (icon) push(styledSpans(icon));
|
|
217
|
+
}
|
|
218
|
+
if (options.index !== undefined && options.total !== undefined && options.total > 1) {
|
|
219
|
+
push([span(`[${options.index + 1}/${options.total}]`, "accent")]);
|
|
220
|
+
}
|
|
221
|
+
if (options.title) push([span(options.title, "toolTitle")]);
|
|
222
|
+
if (head.length === 0) head.push(span("Code", "toolTitle"));
|
|
223
|
+
return {
|
|
224
|
+
head,
|
|
225
|
+
meta: options.duration === undefined ? undefined : [span(formatDuration(options.duration), "dim")],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function describeCellOutput(
|
|
230
|
+
output: string | undefined,
|
|
231
|
+
expanded: boolean,
|
|
232
|
+
outputMaxLines: number,
|
|
233
|
+
): NativeOutputBlockSection | undefined {
|
|
234
|
+
if (!output?.trim()) return undefined;
|
|
235
|
+
return {
|
|
236
|
+
label: [span("Output", "toolTitle")],
|
|
237
|
+
key: "output",
|
|
238
|
+
body: [describeOutputLines(splitTerminalOutputLines(output), { expanded, collapsedMaxLines: outputMaxLines })],
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* The native form of {@link renderCodeCell}: a collapsible `card` holding a
|
|
244
|
+
* `code` node (numbered from `codeStartLine`, or the first explicit line
|
|
245
|
+
* number) and an `ansi` output section. The collapsed code clamp is the
|
|
246
|
+
* card preview; highlighting and gutters are the terminal's.
|
|
247
|
+
*/
|
|
248
|
+
export function describeCodeCell(options: Omit<CodeCellOptions, "width">, theme: Theme): NativeNode {
|
|
249
|
+
const { expanded = false, outputMaxLines = 6, codeMaxLines = 12 } = options;
|
|
250
|
+
const { head, meta } = describeHeader(options, theme);
|
|
251
|
+
const start = options.codeStartLine ?? options.codeLineNumbers?.find((line): line is number => line != null);
|
|
252
|
+
const sections: NativeOutputBlockSection[] = [
|
|
253
|
+
{
|
|
254
|
+
key: "code",
|
|
255
|
+
body: [code(options.code ?? "", { lang: options.language, start, numbers: start !== undefined || undefined })],
|
|
256
|
+
},
|
|
257
|
+
];
|
|
258
|
+
const output = describeCellOutput(options.output, expanded, outputMaxLines);
|
|
259
|
+
if (output) sections.push(output);
|
|
260
|
+
return describeOutputBlock({
|
|
261
|
+
head,
|
|
262
|
+
meta,
|
|
263
|
+
state: getState(options.status),
|
|
264
|
+
role: "omp.cell.code",
|
|
265
|
+
sections,
|
|
266
|
+
collapsible: true,
|
|
267
|
+
collapsed: !expanded,
|
|
268
|
+
preview: { lines: codeMaxLines },
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** The native form of {@link renderMarkdownCell}: a collapsible `card` holding `md` source and optional output. */
|
|
273
|
+
export function describeMarkdownCell(options: Omit<MarkdownCellOptions, "width">, theme: Theme): NativeNode {
|
|
274
|
+
const { expanded = false, outputMaxLines = 6, contentMaxLines = 12 } = options;
|
|
275
|
+
const { head, meta } = describeHeader(options, theme);
|
|
276
|
+
const sections: NativeOutputBlockSection[] = [];
|
|
277
|
+
if (options.content.trim()) sections.push({ key: "content", body: [md(options.content)] });
|
|
278
|
+
const output = describeCellOutput(options.output, expanded, outputMaxLines);
|
|
279
|
+
if (output) sections.push(output);
|
|
280
|
+
return describeOutputBlock({
|
|
281
|
+
head,
|
|
282
|
+
meta,
|
|
283
|
+
state: getState(options.status),
|
|
284
|
+
role: "omp.cell.markdown",
|
|
285
|
+
sections,
|
|
286
|
+
collapsible: true,
|
|
287
|
+
collapsed: !expanded,
|
|
288
|
+
preview: { lines: contentMaxLines },
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
191
292
|
/** Content and display limits for a Markdown preview with optional output. */
|
|
192
293
|
export interface MarkdownCellOptions {
|
|
193
294
|
content: string;
|
package/src/render/file-list.ts
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Render file listings with optional icons and metadata.
|
|
3
3
|
*/
|
|
4
4
|
import { getLanguageFromPath } from "../lang-from-path";
|
|
5
|
+
import { node, span } from "../native/describe";
|
|
6
|
+
import type { NativeNode } from "../native/node";
|
|
5
7
|
import type { Theme } from "../theme/theme";
|
|
8
|
+
import { fileLinkSpan } from "./hyperlink";
|
|
6
9
|
import { renderTreeList } from "./tree-list";
|
|
7
10
|
|
|
8
11
|
/** A file-list item with optional display metadata. */
|
|
@@ -26,6 +29,32 @@ export interface FileListOptions {
|
|
|
26
29
|
hyperlinkFn?: (absPath: string, displayText: string) => string;
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
/**
|
|
33
|
+
* The native form of {@link renderFileList}: a `list` of path `item`s keyed
|
|
34
|
+
* by path, linked to their absolute path, with language/folder icons and the
|
|
35
|
+
* meta as detail. Collapsed, the list is clamped to `maxCollapsed` lines and
|
|
36
|
+
* the terminal scrolls the rest.
|
|
37
|
+
*/
|
|
38
|
+
export function describeFileList(options: Omit<FileListOptions, "hyperlinkFn">): NativeNode {
|
|
39
|
+
const { files, expanded = false, maxCollapsed = 8, showIcons = true } = options;
|
|
40
|
+
const items = files.map(entry => {
|
|
41
|
+
const isDirectory = entry.isDirectory ?? entry.path.endsWith("/");
|
|
42
|
+
const s = isDirectory ? "path accent" : "path";
|
|
43
|
+
const label = entry.absPath ? fileLinkSpan(entry.absPath, entry.path, s) : span(entry.path, s);
|
|
44
|
+
return node(
|
|
45
|
+
"item",
|
|
46
|
+
{
|
|
47
|
+
label: [label],
|
|
48
|
+
icon: showIcons ? (isDirectory ? "folder" : (getLanguageFromPath(entry.path) ?? "file")) : undefined,
|
|
49
|
+
detail: entry.meta ? [span(entry.meta, "dim")] : undefined,
|
|
50
|
+
},
|
|
51
|
+
undefined,
|
|
52
|
+
entry.path,
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
return node("list", { max: expanded ? undefined : { lines: maxCollapsed } }, items);
|
|
56
|
+
}
|
|
57
|
+
|
|
29
58
|
/** Render file entries as a themed tree listing. */
|
|
30
59
|
export function renderFileList(options: FileListOptions, theme: Theme): string[] {
|
|
31
60
|
const { files, expanded = false, maxCollapsed = 8, showIcons = true, hyperlinkFn } = options;
|
package/src/render/hyperlink.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* permits it. Falls back to plain text when disabled.
|
|
7
7
|
*/
|
|
8
8
|
import * as url from "node:url";
|
|
9
|
+
import type { TspSpan } from "@oh-my-pi/pi-wire";
|
|
10
|
+
import { span } from "../native/describe";
|
|
9
11
|
import { setTerminalHyperlinks, TERMINAL, type TerminalId } from "../terminal-capabilities";
|
|
10
12
|
|
|
11
13
|
const OSC = "\x1b]";
|
|
@@ -175,6 +177,36 @@ export function urlHyperlinkAlways(url: string, displayText: string): string {
|
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
|
|
180
|
+
/**
|
|
181
|
+
* A native link span to an HTTP(S) URL (`www.` inputs become `https://`).
|
|
182
|
+
* Unlike the OSC 8 wrappers this ignores terminal capability detection — a
|
|
183
|
+
* TSP terminal always handles `href` — but honours an explicit `off` policy.
|
|
184
|
+
* Non-HTTP(S) or unparsable URLs yield a plain span.
|
|
185
|
+
*/
|
|
186
|
+
export function urlLinkSpan(target: string, displayText: string, s = "link"): TspSpan {
|
|
187
|
+
if (hyperlinkMode === "off") return span(displayText, s);
|
|
188
|
+
const normalized = target.match(/^www\./i) ? `https://${target}` : target;
|
|
189
|
+
try {
|
|
190
|
+
const parsed = new URL(normalized);
|
|
191
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return span(displayText, s);
|
|
192
|
+
const href = safeHyperlinkUri(parsed.href);
|
|
193
|
+
return href ? span(displayText, s, { href }) : span(displayText, s);
|
|
194
|
+
} catch {
|
|
195
|
+
return span(displayText, s);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* A native link span to a filesystem path as a plain `file://` URI (the
|
|
201
|
+
* terminal opens it through the system; the location stays in the visible
|
|
202
|
+
* text). Honours an explicit `off` policy.
|
|
203
|
+
*/
|
|
204
|
+
export function fileLinkSpan(filePath: string, displayText: string, s = "path"): TspSpan {
|
|
205
|
+
if (hyperlinkMode === "off") return span(displayText, s);
|
|
206
|
+
const href = safeHyperlinkUri(url.pathToFileURL(filePath).href);
|
|
207
|
+
return href ? span(displayText, s, { href }) : span(displayText, s);
|
|
208
|
+
}
|
|
209
|
+
|
|
178
210
|
/**
|
|
179
211
|
* Wrap `displayText` in an OSC 8 hyperlink pointing at a filesystem path.
|
|
180
212
|
*
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Bordered output container with optional header and sections.
|
|
3
3
|
*/
|
|
4
|
+
import type { TspCardStatus, TspPreview, TspSpan, TspText, TspTone } from "@oh-my-pi/pi-wire";
|
|
5
|
+
import { node, span } from "../native/describe";
|
|
6
|
+
import type { NativeChild, NativeNode } from "../native/node";
|
|
4
7
|
import { ImageProtocol, TERMINAL } from "../terminal-capabilities";
|
|
5
8
|
import type { Theme, ThemeColor } from "../theme/theme";
|
|
6
9
|
import type { Component } from "../tui";
|
|
@@ -206,6 +209,113 @@ export function renderOutputBlock(options: OutputBlockOptions, theme: Theme): st
|
|
|
206
209
|
return lines;
|
|
207
210
|
}
|
|
208
211
|
|
|
212
|
+
/** Card tone for an output state. */
|
|
213
|
+
export function outputStateTone(state: State | undefined): TspTone {
|
|
214
|
+
switch (state) {
|
|
215
|
+
case "pending":
|
|
216
|
+
case "running":
|
|
217
|
+
return "pending";
|
|
218
|
+
case "success":
|
|
219
|
+
return "success";
|
|
220
|
+
case "error":
|
|
221
|
+
return "error";
|
|
222
|
+
case "warning":
|
|
223
|
+
return "warning";
|
|
224
|
+
default:
|
|
225
|
+
return "neutral";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Card status chip for an output state. */
|
|
230
|
+
export function outputStateStatus(state: State | undefined): TspCardStatus | undefined {
|
|
231
|
+
switch (state) {
|
|
232
|
+
case "pending":
|
|
233
|
+
return "pending";
|
|
234
|
+
case "running":
|
|
235
|
+
return "running";
|
|
236
|
+
case "success":
|
|
237
|
+
case "warning":
|
|
238
|
+
return "done";
|
|
239
|
+
case "error":
|
|
240
|
+
return "error";
|
|
241
|
+
default:
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** One body section of a native output block. */
|
|
247
|
+
export interface NativeOutputBlockSection {
|
|
248
|
+
/** Titled sub-section (the ANSI path's labelled separator bar). */
|
|
249
|
+
label?: TspText;
|
|
250
|
+
body: readonly NativeChild[];
|
|
251
|
+
/** Divide from the previous section with a rule. */
|
|
252
|
+
separator?: boolean;
|
|
253
|
+
/** Stable identity when sections come and go. */
|
|
254
|
+
key?: string;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Semantic inputs for {@link describeOutputBlock}. */
|
|
258
|
+
export interface NativeOutputBlockOptions {
|
|
259
|
+
head?: TspText;
|
|
260
|
+
meta?: TspText;
|
|
261
|
+
state?: State;
|
|
262
|
+
/** Card role (`omp.tool.bash`, `omp.eval.cell`, …). Defaults to `omp.output`. */
|
|
263
|
+
role?: string;
|
|
264
|
+
/** Override the state-derived tone (the ANSI path's `borderColor`). */
|
|
265
|
+
tone?: TspTone;
|
|
266
|
+
sections?: readonly NativeOutputBlockSection[];
|
|
267
|
+
collapsible?: boolean;
|
|
268
|
+
collapsed?: boolean;
|
|
269
|
+
preview?: TspPreview;
|
|
270
|
+
/** Flat card without a ring (inline/plain variants). */
|
|
271
|
+
inset?: boolean;
|
|
272
|
+
key?: string;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function asSpans(content: TspText): readonly TspSpan[] {
|
|
276
|
+
return typeof content === "string" ? [span(content)] : content;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* The native form of {@link renderOutputBlock}: a `card` whose tone and
|
|
281
|
+
* status chip come from the state, head from the header plus meta, and body
|
|
282
|
+
* from the sections (labelled ones as `section`s, separators as `rule`s).
|
|
283
|
+
* Borders, background fills and wrapping are the terminal's.
|
|
284
|
+
*/
|
|
285
|
+
export function describeOutputBlock(options: NativeOutputBlockOptions): NativeNode {
|
|
286
|
+
let head: TspText | undefined = options.head;
|
|
287
|
+
if (options.meta !== undefined && options.meta !== "") {
|
|
288
|
+
head = head === undefined ? options.meta : [...asSpans(head), span(" · ", "dim"), ...asSpans(options.meta)];
|
|
289
|
+
}
|
|
290
|
+
const children: NativeChild[] = [];
|
|
291
|
+
const sections = options.sections ?? [];
|
|
292
|
+
for (let index = 0; index < sections.length; index++) {
|
|
293
|
+
const section = sections[index]!;
|
|
294
|
+
const key = section.key ?? String(index);
|
|
295
|
+
if (section.label !== undefined) {
|
|
296
|
+
children.push(node("section", { head: section.label }, section.body, key));
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (section.separator && index > 0) children.push(node("rule", undefined, undefined, `${key}:rule`));
|
|
300
|
+
for (const child of section.body) children.push(child);
|
|
301
|
+
}
|
|
302
|
+
return node(
|
|
303
|
+
"card",
|
|
304
|
+
{
|
|
305
|
+
role: options.role ?? "omp.output",
|
|
306
|
+
tone: options.tone ?? outputStateTone(options.state),
|
|
307
|
+
status: outputStateStatus(options.state),
|
|
308
|
+
head,
|
|
309
|
+
collapsible: options.collapsible,
|
|
310
|
+
collapsed: options.collapsed,
|
|
311
|
+
preview: options.preview,
|
|
312
|
+
inset: options.inset,
|
|
313
|
+
},
|
|
314
|
+
children,
|
|
315
|
+
options.key,
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
209
319
|
/**
|
|
210
320
|
* Cached wrapper around `renderOutputBlock`.
|
|
211
321
|
*
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Text } from "../components/text";
|
|
2
|
+
import { ansi } from "../native/describe";
|
|
3
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
2
4
|
import { ImageProtocol, TERMINAL } from "../terminal-capabilities";
|
|
3
5
|
import type { Theme } from "../theme/theme";
|
|
4
6
|
import type { Component } from "../tui";
|
|
@@ -114,6 +116,28 @@ export function formatOutputPaneLines(options: OutputPaneFormatOptions, theme: T
|
|
|
114
116
|
return { lines, hiddenCount, hasSixel };
|
|
115
117
|
}
|
|
116
118
|
|
|
119
|
+
/** Display policy for {@link describeOutputLines}. */
|
|
120
|
+
export interface NativeOutputOptions {
|
|
121
|
+
expanded: boolean;
|
|
122
|
+
collapsedMaxLines: number;
|
|
123
|
+
expandedMaxLines?: number;
|
|
124
|
+
edge?: OutputPaneEdge;
|
|
125
|
+
key?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Raw output rows as a native `ansi` mini-terminal: the terminal wraps and
|
|
130
|
+
* styles them. The row cap becomes a `preview` clamp (with its own "N more"
|
|
131
|
+
* affordance); a tail edge follows the stream.
|
|
132
|
+
*/
|
|
133
|
+
export function describeOutputLines(lines: readonly string[], options: NativeOutputOptions): NativeNode {
|
|
134
|
+
const limit = options.expanded ? options.expandedMaxLines : options.collapsedMaxLines;
|
|
135
|
+
const preview =
|
|
136
|
+
limit !== undefined && Number.isFinite(limit) ? { lines: Math.max(0, Math.floor(limit)) } : undefined;
|
|
137
|
+
const described = ansi(lines.join("\n"), { follow: options.edge === "tail" ? true : undefined, preview });
|
|
138
|
+
return options.key === undefined ? described : { ...described, key: options.key };
|
|
139
|
+
}
|
|
140
|
+
|
|
117
141
|
/** Mutable options for a live {@link OutputPane}. */
|
|
118
142
|
export interface OutputPaneOptions extends Omit<OutputPaneFormatOptions, "lines"> {
|
|
119
143
|
paddingX?: number;
|
|
@@ -135,6 +159,7 @@ export class OutputPane implements Component {
|
|
|
135
159
|
#pendingCarriageReturn = false;
|
|
136
160
|
#text: Text;
|
|
137
161
|
#renderKey = "";
|
|
162
|
+
#native: NativeNode | undefined;
|
|
138
163
|
|
|
139
164
|
constructor(theme: Theme, options: OutputPaneOptions, text = "") {
|
|
140
165
|
this.#theme = theme;
|
|
@@ -240,6 +265,17 @@ export class OutputPane implements Component {
|
|
|
240
265
|
return this.#lines.join("\n");
|
|
241
266
|
}
|
|
242
267
|
|
|
268
|
+
/** The retained rows as an `ansi` node; streamed appends grow its text, so the reconciler sends `text append`. */
|
|
269
|
+
describe(_cx: DescribeContext): NativeNode {
|
|
270
|
+
this.#native ??= describeOutputLines(this.#lines, {
|
|
271
|
+
expanded: this.#options.expanded,
|
|
272
|
+
collapsedMaxLines: this.#options.collapsedMaxLines,
|
|
273
|
+
expandedMaxLines: this.#options.expandedMaxLines,
|
|
274
|
+
edge: this.#options.edge,
|
|
275
|
+
});
|
|
276
|
+
return this.#native;
|
|
277
|
+
}
|
|
278
|
+
|
|
243
279
|
render(width: number): readonly string[] {
|
|
244
280
|
const paddingX = getPaddingX(this.#options.paddingX ?? 0);
|
|
245
281
|
const contentWidth = Math.max(1, width - paddingX * 2);
|
|
@@ -262,6 +298,7 @@ export class OutputPane implements Component {
|
|
|
262
298
|
|
|
263
299
|
invalidate(): void {
|
|
264
300
|
this.#renderKey = "";
|
|
301
|
+
this.#native = undefined;
|
|
265
302
|
this.#text.invalidate();
|
|
266
303
|
}
|
|
267
304
|
|