@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
|
@@ -14,7 +14,10 @@ import { wrapTextWithAnsi } from "../../utils";
|
|
|
14
14
|
import { getAgentDbPath } from "@oh-my-pi/pi-utils";
|
|
15
15
|
import { OAuthSelectorComponent } from "../../overlays/oauth-selector";
|
|
16
16
|
import { theme } from "../../theme/theme";
|
|
17
|
-
import
|
|
17
|
+
import { col, node, span, text } from "../../native/describe";
|
|
18
|
+
import type { NativeChild, NativeNode } from "../../native/node";
|
|
19
|
+
import { Memo } from "../../native/memo";
|
|
20
|
+
import type { SetupScene, SetupSceneController, SetupSceneHost, StyledLine } from "./types";
|
|
18
21
|
|
|
19
22
|
function loginUrlLink(url: string): string {
|
|
20
23
|
return `\x1b]8;;${url}\x07Open login URL\x1b]8;;\x07`;
|
|
@@ -27,10 +30,12 @@ function loginCopyHint(): string {
|
|
|
27
30
|
class CopyablePromptInput implements Component, Focusable {
|
|
28
31
|
#input: Input;
|
|
29
32
|
#onCopy: () => void;
|
|
33
|
+
readonly #native: NativeNode;
|
|
30
34
|
|
|
31
35
|
constructor(input: Input, onCopy: () => void) {
|
|
32
36
|
this.#input = input;
|
|
33
37
|
this.#onCopy = onCopy;
|
|
38
|
+
this.#native = col([input]);
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
get focused(): boolean {
|
|
@@ -49,6 +54,11 @@ class CopyablePromptInput implements Component, Focusable {
|
|
|
49
54
|
return this.#input.render(width);
|
|
50
55
|
}
|
|
51
56
|
|
|
57
|
+
/** The wrapped field describes itself (`input`, caret while focused); alt+c stays a key here. */
|
|
58
|
+
describe(): NativeNode {
|
|
59
|
+
return this.#native;
|
|
60
|
+
}
|
|
61
|
+
|
|
52
62
|
handleInput(data: string): void {
|
|
53
63
|
if (matchesKey(data, "alt+c")) {
|
|
54
64
|
this.#onCopy();
|
|
@@ -69,17 +79,20 @@ interface PromptState {
|
|
|
69
79
|
}
|
|
70
80
|
|
|
71
81
|
/**
|
|
72
|
-
* "Sign in"
|
|
73
|
-
* OAuth.
|
|
74
|
-
*
|
|
82
|
+
* "Sign in" scene: lets the user authenticate one or more model providers via
|
|
83
|
+
* OAuth. It never auto-advances the wizard — the user may sign in to several
|
|
84
|
+
* providers and then continue with Esc.
|
|
75
85
|
*/
|
|
76
|
-
export class
|
|
77
|
-
readonly
|
|
78
|
-
|
|
86
|
+
export class SignInScene implements SetupSceneController {
|
|
87
|
+
readonly title = "Sign in to your providers";
|
|
88
|
+
get subtitle(): string {
|
|
89
|
+
return `Sign in to one or more providers. Press ${editorKey("tui.select.cancel")} when you're done.`;
|
|
90
|
+
}
|
|
79
91
|
|
|
80
92
|
#authStorage: AuthStorage;
|
|
81
93
|
#selector: OAuthSelectorComponent;
|
|
82
|
-
|
|
94
|
+
/** Status copy under the selector or login flow; replaced (never mutated) on change. */
|
|
95
|
+
#statusLines: readonly StyledLine[] = [];
|
|
83
96
|
#authUrl: string | undefined;
|
|
84
97
|
#authLaunchUrl: string | undefined;
|
|
85
98
|
#prompt: PromptState | undefined;
|
|
@@ -90,6 +103,7 @@ export class SignInTab implements SetupTab {
|
|
|
90
103
|
#loggingInProvider: string | undefined;
|
|
91
104
|
#disposed = false;
|
|
92
105
|
#step: WizardStep | undefined;
|
|
106
|
+
#native = new Memo();
|
|
93
107
|
|
|
94
108
|
readonly #host: SetupSceneHost;
|
|
95
109
|
|
|
@@ -99,11 +113,6 @@ export class SignInTab implements SetupTab {
|
|
|
99
113
|
this.#selector = this.#createSelector();
|
|
100
114
|
}
|
|
101
115
|
|
|
102
|
-
/** Modal while an OAuth flow is running so the scene won't switch tabs or finish. */
|
|
103
|
-
get modal(): boolean {
|
|
104
|
-
return this.#loggingInProvider !== undefined;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
116
|
dispose(): void {
|
|
108
117
|
this.#disposed = true;
|
|
109
118
|
this.#selector.stopValidation();
|
|
@@ -112,6 +121,7 @@ export class SignInTab implements SetupTab {
|
|
|
112
121
|
}
|
|
113
122
|
|
|
114
123
|
invalidate(): void {
|
|
124
|
+
this.#native.clear();
|
|
115
125
|
this.#step?.invalidate();
|
|
116
126
|
this.#selector.invalidate();
|
|
117
127
|
this.#prompt?.input.invalidate();
|
|
@@ -177,7 +187,7 @@ export class SignInTab implements SetupTab {
|
|
|
177
187
|
}
|
|
178
188
|
}
|
|
179
189
|
for (const line of this.#statusLines) {
|
|
180
|
-
for (const wrapped of wrapTextWithAnsi(line, width)) {
|
|
190
|
+
for (const wrapped of wrapTextWithAnsi(theme.fg(line.color, line.text), width)) {
|
|
181
191
|
tail.addChild(new Text(wrapped, 0, 0));
|
|
182
192
|
}
|
|
183
193
|
}
|
|
@@ -208,6 +218,98 @@ export class SignInTab implements SetupTab {
|
|
|
208
218
|
return this.#step.render(width);
|
|
209
219
|
}
|
|
210
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Picking: intro, the provider selector (describes itself) and the last
|
|
223
|
+
* outcome. Signing in: a spinner heading, the login link (with the full
|
|
224
|
+
* URL once, char-wrapped), any code prompt and the flow's progress lines.
|
|
225
|
+
*/
|
|
226
|
+
describe(): NativeNode {
|
|
227
|
+
const provider = this.#loggingInProvider;
|
|
228
|
+
const authUrl = this.#authUrl;
|
|
229
|
+
const launchUrl = this.#authLaunchUrl;
|
|
230
|
+
const prompt = this.#prompt;
|
|
231
|
+
const statusLines = this.#statusLines;
|
|
232
|
+
const copyKey = formatKeyHint("alt+c");
|
|
233
|
+
return this.#native.get([provider, authUrl, launchUrl, prompt, statusLines, this.#selector, copyKey], () => {
|
|
234
|
+
const tail: NativeChild[] = [];
|
|
235
|
+
if (authUrl) {
|
|
236
|
+
tail.push(
|
|
237
|
+
node(
|
|
238
|
+
"text",
|
|
239
|
+
{
|
|
240
|
+
spans: [
|
|
241
|
+
span("Browser login: ", "accent"),
|
|
242
|
+
span("Open login URL", "accent link", { href: authUrl }),
|
|
243
|
+
span(` (clipboard copy attempted; ${copyKey} retries)`, "dim"),
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
undefined,
|
|
247
|
+
"login",
|
|
248
|
+
),
|
|
249
|
+
node(
|
|
250
|
+
"text",
|
|
251
|
+
{ spans: [span(authUrl, "dim link", { href: authUrl })], wrap: "char", actions: { menu: ["copy"] } },
|
|
252
|
+
undefined,
|
|
253
|
+
"url",
|
|
254
|
+
),
|
|
255
|
+
);
|
|
256
|
+
if (launchUrl) {
|
|
257
|
+
tail.push(
|
|
258
|
+
node(
|
|
259
|
+
"text",
|
|
260
|
+
{
|
|
261
|
+
spans: [
|
|
262
|
+
span("Local shortcut (this machine only): ", "dim"),
|
|
263
|
+
span(launchUrl, "dim link", { href: launchUrl }),
|
|
264
|
+
],
|
|
265
|
+
wrap: "char",
|
|
266
|
+
},
|
|
267
|
+
undefined,
|
|
268
|
+
"launch",
|
|
269
|
+
),
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (prompt) {
|
|
274
|
+
const promptChildren: NativeChild[] = [text([span(prompt.message, "warning")])];
|
|
275
|
+
if (prompt.placeholder) promptChildren.push(text([span(prompt.placeholder, "dim")]));
|
|
276
|
+
promptChildren.push(prompt.input);
|
|
277
|
+
tail.push(node("col", {}, promptChildren, "prompt"));
|
|
278
|
+
}
|
|
279
|
+
statusLines.forEach((line, index) => {
|
|
280
|
+
tail.push(node("text", { spans: [span(line.text, line.color)] }, undefined, `status:${index}`));
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
if (provider) {
|
|
284
|
+
return col(
|
|
285
|
+
[
|
|
286
|
+
node(
|
|
287
|
+
"row",
|
|
288
|
+
{ gap: "sm", align: "center" },
|
|
289
|
+
[node("spinner", {}), text([span(`Signing in to ${provider}`, "strong")])],
|
|
290
|
+
"heading",
|
|
291
|
+
),
|
|
292
|
+
...tail,
|
|
293
|
+
],
|
|
294
|
+
{ gap: "sm", role: "omp.setup.sign-in", tone: "pending" },
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
return col(
|
|
298
|
+
[
|
|
299
|
+
node(
|
|
300
|
+
"text",
|
|
301
|
+
{ spans: [span("Pick a provider to sign in — you can connect more than one.", "muted")] },
|
|
302
|
+
undefined,
|
|
303
|
+
"intro",
|
|
304
|
+
),
|
|
305
|
+
this.#selector,
|
|
306
|
+
...tail,
|
|
307
|
+
],
|
|
308
|
+
{ gap: "sm", role: "omp.setup.sign-in" },
|
|
309
|
+
);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
211
313
|
#createSelector(): OAuthSelectorComponent {
|
|
212
314
|
return new OAuthSelectorComponent(
|
|
213
315
|
"login",
|
|
@@ -225,7 +327,7 @@ export class SignInTab implements SetupTab {
|
|
|
225
327
|
const useManualInput = PASTE_CODE_LOGIN_PROVIDERS.has(providerId);
|
|
226
328
|
this.#selector.stopValidation();
|
|
227
329
|
this.#loggingInProvider = providerId;
|
|
228
|
-
this.#statusLines = [
|
|
330
|
+
this.#statusLines = [{ text: "Starting OAuth flow…", color: "dim" }];
|
|
229
331
|
this.#authUrl = undefined;
|
|
230
332
|
this.#authLaunchUrl = undefined;
|
|
231
333
|
this.#loginAbort = new AbortController();
|
|
@@ -247,20 +349,21 @@ export class SignInTab implements SetupTab {
|
|
|
247
349
|
// shortcut for wide-terminal local users.
|
|
248
350
|
this.#authUrl = info.url;
|
|
249
351
|
this.#authLaunchUrl = info.launchUrl && info.launchUrl !== info.url ? info.launchUrl : undefined;
|
|
250
|
-
|
|
352
|
+
const statusLines: StyledLine[] = [];
|
|
251
353
|
if (info.instructions) {
|
|
252
|
-
|
|
354
|
+
statusLines.push({ text: info.instructions, color: "warning" });
|
|
253
355
|
}
|
|
254
356
|
if (useManualInput) {
|
|
255
|
-
|
|
357
|
+
statusLines.push({ text: "Paste the returned code or redirect URL when prompted.", color: "dim" });
|
|
256
358
|
}
|
|
359
|
+
this.#statusLines = statusLines;
|
|
257
360
|
void this.#copyAuthUrl();
|
|
258
361
|
this.#host.ctx.openInBrowser(info.url);
|
|
259
362
|
this.#host.requestRender();
|
|
260
363
|
},
|
|
261
364
|
onPrompt: prompt => this.#showPrompt(prompt),
|
|
262
365
|
onProgress: message => {
|
|
263
|
-
this.#statusLines
|
|
366
|
+
this.#statusLines = [...this.#statusLines, { text: message, color: "dim" }];
|
|
264
367
|
this.#host.requestRender();
|
|
265
368
|
},
|
|
266
369
|
onManualCodeInput: signal =>
|
|
@@ -271,8 +374,8 @@ export class SignInTab implements SetupTab {
|
|
|
271
374
|
await this.#host.ctx.refreshProvider(providerId);
|
|
272
375
|
if (this.#disposed) return;
|
|
273
376
|
this.#statusLines = [
|
|
274
|
-
|
|
275
|
-
|
|
377
|
+
{ text: `${theme.status.success} Signed in to ${providerId}`, color: "success" },
|
|
378
|
+
{ text: `Credentials saved to ${getAgentDbPath()}`, color: "dim" },
|
|
276
379
|
];
|
|
277
380
|
this.#authUrl = undefined;
|
|
278
381
|
this.#authLaunchUrl = undefined;
|
|
@@ -285,14 +388,17 @@ export class SignInTab implements SetupTab {
|
|
|
285
388
|
} catch (error) {
|
|
286
389
|
if (this.#disposed) return;
|
|
287
390
|
if (this.#loginAbort?.signal.aborted) {
|
|
288
|
-
this.#statusLines = [
|
|
391
|
+
this.#statusLines = [{ text: "Login cancelled.", color: "dim" }];
|
|
289
392
|
this.#authUrl = undefined;
|
|
290
393
|
this.#authLaunchUrl = undefined;
|
|
291
394
|
} else {
|
|
292
395
|
const message = error instanceof Error ? error.message : String(error);
|
|
293
396
|
this.#statusLines = [
|
|
294
|
-
|
|
295
|
-
|
|
397
|
+
{ text: `Login failed: ${message}`, color: "error" },
|
|
398
|
+
{
|
|
399
|
+
text: `Choose another provider or press ${editorKey("tui.select.cancel")} to continue.`,
|
|
400
|
+
color: "dim",
|
|
401
|
+
},
|
|
296
402
|
];
|
|
297
403
|
this.#authUrl = undefined;
|
|
298
404
|
this.#authLaunchUrl = undefined;
|
|
@@ -373,3 +479,11 @@ export class SignInTab implements SetupTab {
|
|
|
373
479
|
this.#host.requestRender();
|
|
374
480
|
}
|
|
375
481
|
}
|
|
482
|
+
|
|
483
|
+
/** Onboarding scene for provider sign-in. */
|
|
484
|
+
export const providersSetupScene: SetupScene = {
|
|
485
|
+
id: "providers",
|
|
486
|
+
title: "Sign in to your providers",
|
|
487
|
+
minVersion: 1,
|
|
488
|
+
mount: host => new SignInScene(host),
|
|
489
|
+
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { centerLine, visibleWidth } from "../../utils";
|
|
2
2
|
import { padToWidth } from "../../render/utils";
|
|
3
|
-
import { gradientEscape, gradientLogo, PI_LOGO, type ShineConfig } from "../../prompt/welcome";
|
|
3
|
+
import { gradientEscape, gradientLogo, logoNode, PI_LOGO, type ShineConfig } from "../../prompt/welcome";
|
|
4
4
|
import { theme } from "../../theme/theme";
|
|
5
5
|
import { formatKeyHint } from "../../app-keybindings";
|
|
6
|
+
import { col, node, span, text } from "../../native/describe";
|
|
7
|
+
import type { NativeNode } from "../../native/node";
|
|
8
|
+
import { Memo } from "../../native/memo";
|
|
6
9
|
|
|
7
10
|
export const SETUP_SPLASH_MS = 2600;
|
|
8
11
|
export const SETUP_TICK_MS = 33;
|
|
@@ -181,6 +184,30 @@ export function renderSetupSplash(width: number, height: number, elapsedMs: numb
|
|
|
181
184
|
return cells.map(row => row.join(""));
|
|
182
185
|
}
|
|
183
186
|
|
|
187
|
+
const splashMemo = new Memo();
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Native splash: the 2x brand mark with a terminal-clocked shimmer, the
|
|
191
|
+
* wordmark, and the skip hint pinned to the bottom. The water and starfield
|
|
192
|
+
* are cell paintings with no semantic counterpart. A click on the splash
|
|
193
|
+
* sends the `skip` action.
|
|
194
|
+
*/
|
|
195
|
+
export function describeSetupSplash(): NativeNode {
|
|
196
|
+
const hint = skipHint();
|
|
197
|
+
return splashMemo.get([hint], () =>
|
|
198
|
+
col(
|
|
199
|
+
[
|
|
200
|
+
node("spacer", { grow: 1 }),
|
|
201
|
+
logoNode(LARGE_LOGO, true),
|
|
202
|
+
text([span("O h M y P i", "strong")], { wrap: "none" }),
|
|
203
|
+
node("spacer", { grow: 1 }),
|
|
204
|
+
text([span(hint, "dim")], { wrap: "none" }),
|
|
205
|
+
],
|
|
206
|
+
{ align: "center", gap: "md", grow: 1, role: "omp.setup.splash", actions: { click: "skip" } },
|
|
207
|
+
),
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
184
211
|
/** Centered fallback for windows too small to hold the full scene. */
|
|
185
212
|
function renderCompactSplash(width: number, height: number, phase: number, shine: ShineConfig): string[] {
|
|
186
213
|
const art = height >= 14 ? LARGE_LOGO : PI_LOGO;
|
|
@@ -18,6 +18,9 @@ import {
|
|
|
18
18
|
setSymbolPreset,
|
|
19
19
|
theme,
|
|
20
20
|
} from "../../theme/theme";
|
|
21
|
+
import { col, node, span, text } from "../../native/describe";
|
|
22
|
+
import type { NativeChild, NativeNode } from "../../native/node";
|
|
23
|
+
import { Memo } from "../../native/memo";
|
|
21
24
|
import type { SetupScene, SetupSceneController, SetupSceneHost } from "./types";
|
|
22
25
|
|
|
23
26
|
type ThemeMode = "curated" | "all";
|
|
@@ -85,6 +88,50 @@ function renderThemePreview(width: number): string[] {
|
|
|
85
88
|
];
|
|
86
89
|
}
|
|
87
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Native theme preview: status samples, a status bar and a read-only editor
|
|
93
|
+
* in the highlighted theme's tokens. The terminal draws the bar and editor
|
|
94
|
+
* chrome, so none of the ANSI mock's box or fill math applies.
|
|
95
|
+
*/
|
|
96
|
+
function describeThemePreview(): NativeNode {
|
|
97
|
+
return col(
|
|
98
|
+
[
|
|
99
|
+
text([span("Preview", "strong")]),
|
|
100
|
+
text([
|
|
101
|
+
span(`${theme.status.success} success`, "success"),
|
|
102
|
+
span(" "),
|
|
103
|
+
span(`${theme.status.warning} warning`, "warning"),
|
|
104
|
+
span(" "),
|
|
105
|
+
span(`${theme.status.error} error`, "error"),
|
|
106
|
+
span(" "),
|
|
107
|
+
span("accent", "accent"),
|
|
108
|
+
]),
|
|
109
|
+
text([span("Status line", "muted")]),
|
|
110
|
+
node("status", {}, [
|
|
111
|
+
node("seg", { spans: [span(`${theme.icon.model} sonnet`, "statusLineModel")], side: "left" }),
|
|
112
|
+
node("seg", { spans: [span("~/project", "statusLinePath")], side: "left" }),
|
|
113
|
+
node("seg", { spans: [span(`${theme.icon.git} main +2`, "statusLineGitDirty")], side: "left" }),
|
|
114
|
+
node("seg", { spans: [span(`${theme.icon.context} 42%`, "statusLineContext")], side: "right" }),
|
|
115
|
+
node("seg", { spans: [span(`${theme.icon.cost} 0.18`, "statusLineCost")], side: "right" }),
|
|
116
|
+
]),
|
|
117
|
+
text([span("Editor", "muted")]),
|
|
118
|
+
node("input", {
|
|
119
|
+
text: "Ask anything, edit files, run tools",
|
|
120
|
+
cursor: "Ask anything, edit files, run tools".length,
|
|
121
|
+
prompt: [span(">", "accent")],
|
|
122
|
+
readonly: true,
|
|
123
|
+
}),
|
|
124
|
+
text([
|
|
125
|
+
span(
|
|
126
|
+
`${editorKey("tui.input.submit")} send · ${editorKey("tui.input.newLine")} newline · / commands`,
|
|
127
|
+
"dim",
|
|
128
|
+
),
|
|
129
|
+
]),
|
|
130
|
+
],
|
|
131
|
+
{ role: "omp.setup.theme.preview" },
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
88
135
|
class ThemeSceneController implements SetupSceneController {
|
|
89
136
|
title = "Pick a theme";
|
|
90
137
|
get subtitle(): string {
|
|
@@ -93,10 +140,12 @@ class ThemeSceneController implements SetupSceneController {
|
|
|
93
140
|
#mode: ThemeMode = "curated";
|
|
94
141
|
#selectList: SelectList;
|
|
95
142
|
#loadingAllThemes = false;
|
|
143
|
+
/** Error copy shown under the list (raw text; styled at render/describe time). */
|
|
96
144
|
#message: string | undefined;
|
|
97
145
|
#previewRequest = 0;
|
|
98
146
|
#disposed = false;
|
|
99
147
|
#step: WizardStep | undefined;
|
|
148
|
+
#native = new Memo();
|
|
100
149
|
readonly #originalTheme = getCurrentThemeName();
|
|
101
150
|
readonly #originalSymbolPreset: SymbolPreset;
|
|
102
151
|
readonly #originalColorBlindMode: boolean;
|
|
@@ -115,6 +164,7 @@ class ThemeSceneController implements SetupSceneController {
|
|
|
115
164
|
}
|
|
116
165
|
|
|
117
166
|
invalidate(): void {
|
|
167
|
+
this.#native.clear();
|
|
118
168
|
this.#step?.invalidate();
|
|
119
169
|
this.#selectList.invalidate();
|
|
120
170
|
}
|
|
@@ -168,7 +218,7 @@ class ThemeSceneController implements SetupSceneController {
|
|
|
168
218
|
preview.addChild(new Text(line, 0, 0));
|
|
169
219
|
}
|
|
170
220
|
const loading = this.#loadingAllThemes ? new Text(theme.fg("dim", "Loading themes…"), 0, 0) : undefined;
|
|
171
|
-
const status = this.#message ? new Text(this.#message, 0, 0) : undefined;
|
|
221
|
+
const status = this.#message ? new Text(theme.fg("error", this.#message), 0, 0) : undefined;
|
|
172
222
|
if (!this.#step) {
|
|
173
223
|
this.#step = new WizardStep({
|
|
174
224
|
kind: loading ? "async" : "choice",
|
|
@@ -194,6 +244,41 @@ class ThemeSceneController implements SetupSceneController {
|
|
|
194
244
|
return this.#step.render(width);
|
|
195
245
|
}
|
|
196
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Intro hints, the live preview, the theme list (a spinner while every
|
|
249
|
+
* theme loads) and any preview error. Theme switches re-describe through
|
|
250
|
+
* `invalidate()`, so the preview's tokens follow the highlighted theme.
|
|
251
|
+
*/
|
|
252
|
+
describe(): NativeNode {
|
|
253
|
+
const confirm = editorKey("tui.select.confirm");
|
|
254
|
+
const cancel = editorKey("tui.select.cancel");
|
|
255
|
+
return this.#native.get(
|
|
256
|
+
[this.#mode, this.#loadingAllThemes, this.#selectList, this.#message, confirm, cancel],
|
|
257
|
+
() => {
|
|
258
|
+
const children: NativeChild[] = [
|
|
259
|
+
col([
|
|
260
|
+
text([span(`Theme changes preview live. Nothing is saved until you press ${confirm}.`, "muted")]),
|
|
261
|
+
text([
|
|
262
|
+
span(
|
|
263
|
+
this.#mode === "all"
|
|
264
|
+
? `Browsing all themes · ${cancel} returns to curated choices`
|
|
265
|
+
: `${cancel} skips this step`,
|
|
266
|
+
"dim",
|
|
267
|
+
),
|
|
268
|
+
]),
|
|
269
|
+
]),
|
|
270
|
+
describeThemePreview(),
|
|
271
|
+
this.#loadingAllThemes
|
|
272
|
+
? node("spinner", { label: [span("Loading themes…", "dim")] }, undefined, "loading")
|
|
273
|
+
: this.#selectList,
|
|
274
|
+
];
|
|
275
|
+
if (this.#message)
|
|
276
|
+
children.push(node("text", { spans: [span(this.#message, "error")] }, undefined, "status"));
|
|
277
|
+
return col(children, { gap: "sm", role: "omp.setup.theme" });
|
|
278
|
+
},
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
197
282
|
#createSelectList(items: readonly SelectItem[], selectedIndex: number): SelectList {
|
|
198
283
|
const list = new SelectList(items, Math.min(10, Math.max(1, items.length)), getSelectListTheme());
|
|
199
284
|
list.setSelectedIndex(selectedIndex);
|
|
@@ -256,7 +341,7 @@ class ThemeSceneController implements SetupSceneController {
|
|
|
256
341
|
this.#selectList = this.#createSelectList(items, selectedIndex);
|
|
257
342
|
} catch (error) {
|
|
258
343
|
const message = error instanceof Error ? error.message : String(error);
|
|
259
|
-
this.#message =
|
|
344
|
+
this.#message = `Failed to load themes: ${message}`;
|
|
260
345
|
} finally {
|
|
261
346
|
this.#loadingAllThemes = false;
|
|
262
347
|
this.#host.requestRender();
|
|
@@ -320,7 +405,7 @@ class ThemeSceneController implements SetupSceneController {
|
|
|
320
405
|
}
|
|
321
406
|
if (request !== this.#previewRequest || this.#disposed) return;
|
|
322
407
|
if (!result.success) {
|
|
323
|
-
this.#message =
|
|
408
|
+
this.#message = result.error ?? "Theme preview failed";
|
|
324
409
|
}
|
|
325
410
|
this.#host.ctx.ui.invalidate();
|
|
326
411
|
this.#host.requestRender();
|
|
@@ -4,10 +4,15 @@ import type { SgrMouseEvent } from "../../mouse";
|
|
|
4
4
|
import type { ComposerPreviewStatusSource } from "../../overlays/composer-shape-preview";
|
|
5
5
|
import type { ComposerShape } from "../../overlays/composer-shape-registry";
|
|
6
6
|
import type { ModelBrowserSource } from "../../overlays/model-browser";
|
|
7
|
-
import type { SymbolPreset } from "../../theme/theme";
|
|
8
|
-
import type { SearchProviderId } from "../../tools/web-search";
|
|
7
|
+
import type { SymbolPreset, ThemeColor } from "../../theme/theme";
|
|
9
8
|
import type { Component, TUI } from "../../tui";
|
|
10
9
|
|
|
10
|
+
/** One line of status copy kept as raw text plus its theme colour, never as pre-styled ANSI. */
|
|
11
|
+
export interface StyledLine {
|
|
12
|
+
readonly text: string;
|
|
13
|
+
readonly color: ThemeColor;
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
/** Terminal capabilities used by setup overlays and the startup splash. */
|
|
12
17
|
export interface SetupUiHost {
|
|
13
18
|
readonly ui: Pick<TUI, "showOverlay" | "setFocus" | "requestRender" | "invalidate"> & {
|
|
@@ -21,7 +26,6 @@ export interface SetupHost extends SetupUiHost {
|
|
|
21
26
|
readonly composerShape: ComposerShape;
|
|
22
27
|
readonly symbolPreset: SymbolPreset;
|
|
23
28
|
readonly colorBlindMode: boolean;
|
|
24
|
-
readonly webSearchOrder: readonly string[];
|
|
25
29
|
readonly disabledProviders: readonly string[];
|
|
26
30
|
readonly authStorage: AuthStorage;
|
|
27
31
|
readonly modelSource: ModelBrowserSource;
|
|
@@ -33,8 +37,6 @@ export interface SetupHost extends SetupUiHost {
|
|
|
33
37
|
saveSymbolPreset(preset: SymbolPreset): void;
|
|
34
38
|
saveColorBlindMode(enabled: boolean): void;
|
|
35
39
|
saveTheme(mode: "dark" | "light", name: string): void;
|
|
36
|
-
isSearchProviderAvailable(id: SearchProviderId): Promise<boolean>;
|
|
37
|
-
saveSearchProvider(id: SearchProviderId | "auto"): void;
|
|
38
40
|
captureBrowserSession(request: OAuthBrowserSessionRequest, signal?: AbortSignal): Promise<string>;
|
|
39
41
|
copyToClipboard(text: string): Promise<void>;
|
|
40
42
|
openInBrowser(url: string): void;
|
|
@@ -78,29 +80,6 @@ export interface SetupSceneController extends Component {
|
|
|
78
80
|
routeMouse?(event: SgrMouseEvent, line: number, col: number): void;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
/**
|
|
82
|
-
* A single panel inside a tabbed setup scene. The host scene owns the tab bar
|
|
83
|
-
* and forwards rendering/input to the active tab.
|
|
84
|
-
*/
|
|
85
|
-
export interface SetupTab {
|
|
86
|
-
readonly id: string;
|
|
87
|
-
readonly label: string;
|
|
88
|
-
/**
|
|
89
|
-
* While `true` the tab owns all keyboard input (e.g. an in-progress OAuth
|
|
90
|
-
* login). The parent scene MUST NOT switch tabs or finish while modal.
|
|
91
|
-
*/
|
|
92
|
-
readonly modal: boolean;
|
|
93
|
-
/** See {@link SetupSceneController.render}: `maxLines` is the tab-local row budget. */
|
|
94
|
-
render(width: number, maxLines?: number): readonly string[];
|
|
95
|
-
handleInput(data: string): void;
|
|
96
|
-
invalidate(): void;
|
|
97
|
-
/** Called when the tab becomes active (including initial mount). */
|
|
98
|
-
onActivate?(): void;
|
|
99
|
-
/** Mouse routing at tab-local coordinates; see {@link SetupSceneController.routeMouse}. */
|
|
100
|
-
routeMouse?(event: SgrMouseEvent, line: number, col: number): void;
|
|
101
|
-
dispose(): void;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
83
|
/** Versioned onboarding scene definition. */
|
|
105
84
|
export interface SetupScene {
|
|
106
85
|
id: string;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { type Component, type OverlayFocusOwner } from "../tui";
|
|
2
2
|
import { matchesKey } from "../keys";
|
|
3
|
+
import { col } from "../native/describe";
|
|
4
|
+
import type { NativeNode, NativeUiEvent } from "../native/node";
|
|
5
|
+
import { Memo } from "../native/memo";
|
|
6
|
+
import { isNativeRendering } from "../native/state";
|
|
3
7
|
import type { SetupUiHost } from "./scenes/types";
|
|
4
|
-
import { renderSetupSplash, SETUP_SPLASH_MS, SETUP_TICK_MS } from "./scenes/splash";
|
|
8
|
+
import { describeSetupSplash, renderSetupSplash, SETUP_SPLASH_MS, SETUP_TICK_MS } from "./scenes/splash";
|
|
5
9
|
|
|
6
10
|
/** Timing controls for the standalone startup animation. */
|
|
7
11
|
export interface RunStartupSplashOptions {
|
|
@@ -13,6 +17,9 @@ export interface RunStartupSplashOptions {
|
|
|
13
17
|
class StartupSplashComponent implements Component, OverlayFocusOwner {
|
|
14
18
|
#phaseStartedAt = 0;
|
|
15
19
|
#timer: NodeJS.Timeout | undefined;
|
|
20
|
+
/** Native path: one-shot at the end of the splash; the terminal clocks the motion. */
|
|
21
|
+
#deadline: NodeJS.Timeout | undefined;
|
|
22
|
+
#native = new Memo();
|
|
16
23
|
#done = Promise.withResolvers<void>();
|
|
17
24
|
#disposed = false;
|
|
18
25
|
readonly #durationMs: number;
|
|
@@ -60,20 +67,50 @@ class StartupSplashComponent implements Component, OverlayFocusOwner {
|
|
|
60
67
|
return renderSetupSplash(Math.max(1, width), Math.max(1, this.ctx.ui.terminal.rows), elapsedMs);
|
|
61
68
|
}
|
|
62
69
|
|
|
70
|
+
describe(): NativeNode {
|
|
71
|
+
const splash = describeSetupSplash();
|
|
72
|
+
return this.#native.get([splash], () => col([splash], { grow: 1, role: "omp.app.startup-splash" }));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
76
|
+
if (event.type === "action" && event.act === "skip") this.#complete();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* ANSI: repaint every tick. Native: no repaint loop, only a one-shot at
|
|
81
|
+
* the end of the splash (re-armed if it fires early).
|
|
82
|
+
*/
|
|
63
83
|
#startTimer(): void {
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (elapsed >= this.#durationMs) {
|
|
69
|
-
this.#complete();
|
|
70
|
-
return;
|
|
84
|
+
if (isNativeRendering()) {
|
|
85
|
+
if (this.#timer) {
|
|
86
|
+
clearInterval(this.#timer);
|
|
87
|
+
this.#timer = undefined;
|
|
71
88
|
}
|
|
89
|
+
clearTimeout(this.#deadline);
|
|
90
|
+
const remaining = this.#durationMs - (this.#now() - this.#phaseStartedAt);
|
|
91
|
+
this.#deadline = setTimeout(() => this.#tick(), Math.max(0, remaining));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (this.#timer) return;
|
|
95
|
+
this.#timer = setInterval(() => this.#tick(), this.#tickMs);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#tick(): void {
|
|
99
|
+
if (this.#disposed) return;
|
|
100
|
+
const elapsed = this.#now() - this.#phaseStartedAt;
|
|
101
|
+
if (elapsed >= this.#durationMs) {
|
|
102
|
+
this.#complete();
|
|
103
|
+
} else if (isNativeRendering() || !this.#timer) {
|
|
104
|
+
// Re-arm the deadline, or switch loops when the native surface opened/closed.
|
|
105
|
+
this.#startTimer();
|
|
106
|
+
} else {
|
|
72
107
|
this.ctx.ui.requestRender();
|
|
73
|
-
}
|
|
108
|
+
}
|
|
74
109
|
}
|
|
75
110
|
|
|
76
111
|
#stopTimer(): void {
|
|
112
|
+
clearTimeout(this.#deadline);
|
|
113
|
+
this.#deadline = undefined;
|
|
77
114
|
if (!this.#timer) return;
|
|
78
115
|
clearInterval(this.#timer);
|
|
79
116
|
this.#timer = undefined;
|