@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
|
@@ -34,6 +34,10 @@ import { bottomBorder, row, topBorder } from "../chrome/overlay-box";
|
|
|
34
34
|
import { padToWidth } from "../render/utils";
|
|
35
35
|
import { SplitPane } from "../components/layout/split-pane";
|
|
36
36
|
import { clampSelection, contentRowWidth, padLinesToHeight, renderScrollableList } from "../chrome/selector-helpers";
|
|
37
|
+
import type { TspSpan } from "@oh-my-pi/pi-wire";
|
|
38
|
+
import type { NativeChild, NativeNode, NativeUiEvent } from "../native/node";
|
|
39
|
+
import { col, md, node, span, text } from "../native/describe";
|
|
40
|
+
import { actionHint, hintsRow, type NativeHint, statusHintsRow } from "../native/overlay";
|
|
37
41
|
|
|
38
42
|
interface BtwHistoryPanelOptions {
|
|
39
43
|
records: readonly BtwHistoryRecord[];
|
|
@@ -63,6 +67,20 @@ interface RenderedTurn {
|
|
|
63
67
|
width: number;
|
|
64
68
|
}
|
|
65
69
|
|
|
70
|
+
/** The visible inputs of the last native description; any change rebuilds it. */
|
|
71
|
+
interface BtwHistoryNativeMemo {
|
|
72
|
+
records: readonly BtwHistoryRecord[];
|
|
73
|
+
selectedId: string | undefined;
|
|
74
|
+
focus: "list" | "answer";
|
|
75
|
+
focused: boolean;
|
|
76
|
+
composer: FollowUpComposer | undefined;
|
|
77
|
+
notice: string | undefined;
|
|
78
|
+
followUpPending: boolean;
|
|
79
|
+
canFollowUp: boolean;
|
|
80
|
+
copied: boolean;
|
|
81
|
+
node: NativeNode;
|
|
82
|
+
}
|
|
83
|
+
|
|
66
84
|
const STATUS: Record<BtwHistoryRecord["status"], { label: string; color: ThemeColor }> = {
|
|
67
85
|
running: { label: "Running", color: "accent" },
|
|
68
86
|
complete: { label: "Complete", color: "success" },
|
|
@@ -89,6 +107,7 @@ export class BtwHistoryPanel implements Component, Focusable {
|
|
|
89
107
|
#detailDirty = true;
|
|
90
108
|
#lastCopiedId: string | undefined;
|
|
91
109
|
#lastCopiedText: string | undefined;
|
|
110
|
+
#native: BtwHistoryNativeMemo | undefined;
|
|
92
111
|
readonly #detail = new ScrollView([], {
|
|
93
112
|
height: 1,
|
|
94
113
|
scrollbar: "auto",
|
|
@@ -190,6 +209,7 @@ export class BtwHistoryPanel implements Component, Focusable {
|
|
|
190
209
|
this.#turns = [];
|
|
191
210
|
this.#composer?.input.invalidate();
|
|
192
211
|
this.#detailDirty = true;
|
|
212
|
+
this.#native = undefined;
|
|
193
213
|
this.#split.invalidate();
|
|
194
214
|
this.#labels.invalidate();
|
|
195
215
|
}
|
|
@@ -340,6 +360,168 @@ export class BtwHistoryPanel implements Component, Focusable {
|
|
|
340
360
|
this.#options.requestRender();
|
|
341
361
|
}
|
|
342
362
|
|
|
363
|
+
/** A large glass sheet titled "BTW history". */
|
|
364
|
+
readonly nativeOverlay = { role: "omp.overlay.btwHistory", size: "lg", head: "BTW history" } as const;
|
|
365
|
+
|
|
366
|
+
describe(): NativeNode {
|
|
367
|
+
const record = this.#selected();
|
|
368
|
+
const composer = this.#composer;
|
|
369
|
+
const canFollowUp = record !== undefined && this.#canFollowUp(record);
|
|
370
|
+
const copied = record !== undefined && this.#isCopied(record);
|
|
371
|
+
const memo = this.#native;
|
|
372
|
+
if (
|
|
373
|
+
memo?.records === this.#records &&
|
|
374
|
+
memo.selectedId === this.#selectedId &&
|
|
375
|
+
memo.focus === this.#focus &&
|
|
376
|
+
memo.focused === this.#focused &&
|
|
377
|
+
memo.composer === composer &&
|
|
378
|
+
memo.notice === composer?.notice &&
|
|
379
|
+
memo.followUpPending === this.#followUpPending &&
|
|
380
|
+
memo.canFollowUp === canFollowUp &&
|
|
381
|
+
memo.copied === copied
|
|
382
|
+
) {
|
|
383
|
+
return memo.node;
|
|
384
|
+
}
|
|
385
|
+
const children: NativeChild[] = [
|
|
386
|
+
node(
|
|
387
|
+
"row",
|
|
388
|
+
{ gap: "md", align: "start" },
|
|
389
|
+
[
|
|
390
|
+
node(
|
|
391
|
+
"section",
|
|
392
|
+
{ head: this.#describeFocusLabel("list"), basis: 0.42, max: { w: "46ch" } },
|
|
393
|
+
[this.#describeList()],
|
|
394
|
+
"history",
|
|
395
|
+
),
|
|
396
|
+
node(
|
|
397
|
+
"section",
|
|
398
|
+
{ head: this.#describeFocusLabel("answer"), grow: 1 },
|
|
399
|
+
[this.#describeDetail(record, copied)],
|
|
400
|
+
"details",
|
|
401
|
+
),
|
|
402
|
+
],
|
|
403
|
+
"body",
|
|
404
|
+
),
|
|
405
|
+
];
|
|
406
|
+
if (composer) {
|
|
407
|
+
composer.input.focused = this.#focused;
|
|
408
|
+
const lines: NativeChild[] = [
|
|
409
|
+
text([span(`Topic: ${sanitizeDisplayLine(record?.question ?? "")}`, "dim")], { truncate: "end" }),
|
|
410
|
+
];
|
|
411
|
+
if (composer.notice) {
|
|
412
|
+
lines.push(text([span(composer.notice, this.#followUpPending ? "dim" : "warning")], { wrap: "word" }));
|
|
413
|
+
}
|
|
414
|
+
lines.push(composer.input);
|
|
415
|
+
children.push(node("col", undefined, lines, "composer"));
|
|
416
|
+
}
|
|
417
|
+
children.push({ ...this.#describeFooter(record, canFollowUp, copied), key: "footer" });
|
|
418
|
+
// The sheet is the frame (`nativeOverlay`): a borderless column.
|
|
419
|
+
const described = col(children, { gap: "md" });
|
|
420
|
+
this.#native = {
|
|
421
|
+
records: this.#records,
|
|
422
|
+
selectedId: this.#selectedId,
|
|
423
|
+
focus: this.#focus,
|
|
424
|
+
focused: this.#focused,
|
|
425
|
+
composer,
|
|
426
|
+
notice: composer?.notice,
|
|
427
|
+
followUpPending: this.#followUpPending,
|
|
428
|
+
canFollowUp,
|
|
429
|
+
copied,
|
|
430
|
+
node: described,
|
|
431
|
+
};
|
|
432
|
+
return described;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
436
|
+
if ((event.type !== "select" && event.type !== "activate") || this.#composer) return;
|
|
437
|
+
const index = this.#records.findIndex(record => record.id === event.item);
|
|
438
|
+
if (index === -1) return;
|
|
439
|
+
this.#select(index);
|
|
440
|
+
this.#focus = "list";
|
|
441
|
+
// Enter on a history row opens the follow-up composer.
|
|
442
|
+
if (event.type === "activate") this.openFollowUp(event.item);
|
|
443
|
+
this.#options.requestRender();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
#describeFocusLabel(focus: "list" | "answer"): TspSpan[] {
|
|
447
|
+
const label = focus === "list" ? `History (${this.#records.length})` : "Details";
|
|
448
|
+
return this.#focus === focus ? [span(`${theme.nav.cursor} ${label}`, "accent strong")] : [span(label, "muted")];
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
#describeList(): NativeNode {
|
|
452
|
+
const items = this.#records.map(record => {
|
|
453
|
+
const status = STATUS[getBtwLatestTurn(record).status];
|
|
454
|
+
return node(
|
|
455
|
+
"item",
|
|
456
|
+
{
|
|
457
|
+
label: sanitizeDisplayLine(record.question),
|
|
458
|
+
detail: [span(this.#timeFormat.format(record.createdAt), "dim")],
|
|
459
|
+
value: [span(status.label, status.color)],
|
|
460
|
+
},
|
|
461
|
+
undefined,
|
|
462
|
+
record.id,
|
|
463
|
+
);
|
|
464
|
+
});
|
|
465
|
+
return node(
|
|
466
|
+
"list",
|
|
467
|
+
{
|
|
468
|
+
selected: this.#selectedId ?? null,
|
|
469
|
+
empty: [span("No side questions yet. Use /btw QUESTION to start one.", "muted")],
|
|
470
|
+
},
|
|
471
|
+
items,
|
|
472
|
+
"records",
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
#describeDetail(record: BtwHistoryRecord | undefined, copied: boolean): NativeNode {
|
|
477
|
+
if (!record)
|
|
478
|
+
return text([span("No side questions yet. Use /btw QUESTION to start one.", "muted")], { wrap: "word" });
|
|
479
|
+
const children: NativeChild[] = [];
|
|
480
|
+
if (copied)
|
|
481
|
+
children.push(node("text", { spans: [span("✓ Copied to clipboard", "success")] }, undefined, "copied"));
|
|
482
|
+
const turns = getBtwTurns(record);
|
|
483
|
+
for (let index = 0; index < turns.length; index++) {
|
|
484
|
+
if (index > 0) children.push(node("rule", undefined, undefined, `rule-${index}`));
|
|
485
|
+
children.push(this.#describeTurn(turns[index]!, `turn-${index}`));
|
|
486
|
+
}
|
|
487
|
+
return col(children, { gap: "md" });
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
#describeTurn(turn: BtwHistoryTurn, key: string): NativeNode {
|
|
491
|
+
const status = STATUS[turn.status];
|
|
492
|
+
const answer = turn.answer.trim()
|
|
493
|
+
? md(sanitizeDisplayText(turn.answer), { stream: turn.status === "running" })
|
|
494
|
+
: text([span(turn.status === "running" ? "Waiting for response…" : "No answer text.", "dim")]);
|
|
495
|
+
const children: NativeChild[] = [
|
|
496
|
+
text([span(`${status.label} · ${this.#dateFormat.format(turn.createdAt)}`, status.color)], { wrap: "word" }),
|
|
497
|
+
node("section", { head: [span("Question", "accent strong")] }, [md(sanitizeDisplayText(turn.question))]),
|
|
498
|
+
node("section", { head: [span("Answer", "accent strong")] }, [answer]),
|
|
499
|
+
];
|
|
500
|
+
if (turn.error) children.push(text([span(sanitizeErrorLine(turn.error), "error")], { wrap: "word" }));
|
|
501
|
+
if (turn.status === "interrupted") children.push(text([span("Not resumed in this view.", "muted")]));
|
|
502
|
+
return node("col", { gap: "sm" }, children, key);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
#describeFooter(record: BtwHistoryRecord | undefined, canFollowUp: boolean, copied: boolean): NativeNode {
|
|
506
|
+
if (this.#composer) {
|
|
507
|
+
return hintsRow([
|
|
508
|
+
actionHint("tui.input.submit", this.#followUpPending ? "starting…" : "send"),
|
|
509
|
+
actionHint("tui.select.cancel", "cancel"),
|
|
510
|
+
]);
|
|
511
|
+
}
|
|
512
|
+
const latest = record ? getBtwLatestTurn(record) : undefined;
|
|
513
|
+
const hints: (NativeHint | undefined)[] = [
|
|
514
|
+
actionHint("tui.select.cancel", latest?.status === "running" ? "cancel" : "close"),
|
|
515
|
+
{ keys: ["tab", "ctrl+/"], label: "switch pane" },
|
|
516
|
+
actionHint(["tui.select.up", "tui.select.down"], this.#focus === "list" ? "select" : "scroll"),
|
|
517
|
+
];
|
|
518
|
+
if (canFollowUp) hints.push({ keys: ["f", "enter"], label: "follow up" });
|
|
519
|
+
if (record && getBtwCopyText(record) !== undefined) {
|
|
520
|
+
hints.push({ keys: ["c"], label: copied ? "copy again" : "copy answer" });
|
|
521
|
+
}
|
|
522
|
+
return copied ? statusHintsRow([span("✓ copied", "success")], hints) : hintsRow(hints);
|
|
523
|
+
}
|
|
524
|
+
|
|
343
525
|
#renderList(width: number, height: number): readonly string[] {
|
|
344
526
|
const rowSpan = width < 36 && height >= 2 ? 2 : 1;
|
|
345
527
|
this.#listHeight = Math.max(1, Math.floor(height / rowSpan));
|
|
@@ -4,8 +4,11 @@ import { getMarkdownTheme, theme } from "../theme/theme";
|
|
|
4
4
|
import { sanitizeErrorLine } from "../chrome/error-block";
|
|
5
5
|
import { OverlayPanel } from "../chrome/overlay-box";
|
|
6
6
|
import { StreamingPanelContent } from "../chrome/streaming-panel";
|
|
7
|
-
import { interruptKey } from "../chrome/keybinding-hints";
|
|
7
|
+
import { boundKeys, interruptKey } from "../chrome/keybinding-hints";
|
|
8
8
|
import { formatKeyHint } from "../app-keybindings";
|
|
9
|
+
import type { NativeNode } from "../native/node";
|
|
10
|
+
import { col, md, node, span, text } from "../native/describe";
|
|
11
|
+
import { hintsRow, type NativeHint, statusHintsRow } from "../native/overlay";
|
|
9
12
|
|
|
10
13
|
type BtwPanelState = "running" | "complete" | "branching" | "aborted" | "error";
|
|
11
14
|
|
|
@@ -27,12 +30,15 @@ export class BtwPanelComponent extends OverlayPanel {
|
|
|
27
30
|
#closed = false;
|
|
28
31
|
#copied = false;
|
|
29
32
|
#baseTitle: string;
|
|
33
|
+
readonly #question: string;
|
|
30
34
|
readonly #content: StreamingPanelContent;
|
|
35
|
+
#native: { node: NativeNode; canFollowUp: boolean; canBranch: boolean } | undefined;
|
|
31
36
|
|
|
32
37
|
constructor(options: BtwPanelComponentOptions) {
|
|
33
38
|
const baseTitle = `/btw ${replaceTabs(options.question)}`;
|
|
34
|
-
super(baseTitle);
|
|
39
|
+
super(baseTitle, "omp.overlay.btw");
|
|
35
40
|
this.#baseTitle = baseTitle;
|
|
41
|
+
this.#question = replaceTabs(options.question);
|
|
36
42
|
this.#tui = options.tui;
|
|
37
43
|
this.#canBranch = options.canBranch;
|
|
38
44
|
this.#canFollowUp = options.canFollowUp;
|
|
@@ -121,7 +127,67 @@ export class BtwPanelComponent extends OverlayPanel {
|
|
|
121
127
|
this.#closed = true;
|
|
122
128
|
}
|
|
123
129
|
|
|
130
|
+
override invalidate(): void {
|
|
131
|
+
this.#native = undefined;
|
|
132
|
+
super.invalidate();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
override describe(): NativeNode {
|
|
136
|
+
const canFollowUp = this.#canFollowUp?.() ?? false;
|
|
137
|
+
const canBranch = this.#canBranch?.() ?? this.isBranchable();
|
|
138
|
+
const memo = this.#native;
|
|
139
|
+
if (memo && memo.canFollowUp === canFollowUp && memo.canBranch === canBranch) return memo.node;
|
|
140
|
+
// Inline in the dock, styled as a sheet by role: a borderless column headed by the question.
|
|
141
|
+
const title = text([span("/btw", "accent"), span(` ${this.#question}`)], { truncate: "end", lines: 1 });
|
|
142
|
+
const live = this.#state === "running" || this.#state === "branching";
|
|
143
|
+
const head = node("row", { role: "omp.sheet.head", gap: "sm", align: "center" }, [
|
|
144
|
+
...(live ? [node("spinner", {})] : []),
|
|
145
|
+
title,
|
|
146
|
+
]);
|
|
147
|
+
const described = col([head, this.#describeBody(), this.#describeFooter(canFollowUp, canBranch)], {
|
|
148
|
+
role: this.nativeRole,
|
|
149
|
+
gap: "sm",
|
|
150
|
+
tone: this.#state === "error" ? "error" : this.#state === "aborted" ? "warning" : undefined,
|
|
151
|
+
});
|
|
152
|
+
this.#native = { node: described, canFollowUp, canBranch };
|
|
153
|
+
return described;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#describeBody(): NativeNode {
|
|
157
|
+
if (this.#state === "error") {
|
|
158
|
+
return text([span(sanitizeErrorLine(this.#errorMessage ?? "Unknown error"), "error")], { wrap: "word" });
|
|
159
|
+
}
|
|
160
|
+
const answer = this.#visibleAnswer;
|
|
161
|
+
if (answer) return md(answer, { stream: this.#state === "running" });
|
|
162
|
+
const waiting = this.#state === "running" ? `${theme.status.pending} Waiting for response…` : "No text returned.";
|
|
163
|
+
return text([span(waiting, "dim")]);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
#describeFooter(canFollowUp: boolean, canBranch: boolean): NativeNode {
|
|
167
|
+
const esc: NativeHint = { keys: boundKeys("app.interrupt", ["escape"]).slice(0, 1), label: "to close" };
|
|
168
|
+
switch (this.#state) {
|
|
169
|
+
case "running":
|
|
170
|
+
return hintsRow([{ ...esc, label: "to cancel" }]);
|
|
171
|
+
case "complete": {
|
|
172
|
+
const hints: NativeHint[] = [];
|
|
173
|
+
if (this.isCopyable()) hints.push({ keys: ["c"], label: this.#copied ? "to copy again" : "to copy" });
|
|
174
|
+
if (canFollowUp) hints.push({ keys: ["f"], label: "to follow up" });
|
|
175
|
+
if (canBranch) hints.push({ keys: ["b"], label: "to branch" });
|
|
176
|
+
hints.push(esc);
|
|
177
|
+
if (!this.#copied) return hintsRow(hints);
|
|
178
|
+
return statusHintsRow([span("✓ Copied to clipboard", "success")], hints);
|
|
179
|
+
}
|
|
180
|
+
case "branching":
|
|
181
|
+
return text([span(`${theme.status.pending} Branching to chat…`, "muted")]);
|
|
182
|
+
case "aborted":
|
|
183
|
+
return statusHintsRow([span(`${theme.status.warning} Cancelled`, "warning")], [esc]);
|
|
184
|
+
case "error":
|
|
185
|
+
return statusHintsRow([span(`${theme.status.error} Error`, "error")], [esc]);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
124
189
|
#rebuild(): void {
|
|
190
|
+
this.#native = undefined;
|
|
125
191
|
this.#content.refresh();
|
|
126
192
|
// Component-scoped: a rebuild replaces only this panel's own children
|
|
127
193
|
// (streaming deltas arrive per token, and a full compose would re-walk
|
|
@@ -5,7 +5,13 @@ import { replaceTabs } from "../render/render-utils";
|
|
|
5
5
|
import { theme } from "../theme/theme";
|
|
6
6
|
import { OverlayPanel } from "../chrome/overlay-box";
|
|
7
7
|
import { StreamingPanelContent, type StreamingPanelPresentation } from "../chrome/streaming-panel";
|
|
8
|
-
import { interruptKey } from "../chrome/keybinding-hints";
|
|
8
|
+
import { boundKeys, interruptKey } from "../chrome/keybinding-hints";
|
|
9
|
+
import type { TspTone } from "@oh-my-pi/pi-wire";
|
|
10
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
11
|
+
import { col, node, span, text } from "../native/describe";
|
|
12
|
+
import { hintsRow, type NativeHint, statusHintsRow } from "../native/overlay";
|
|
13
|
+
import { plainText } from "../native/spans";
|
|
14
|
+
import { isNativeRendering } from "../native/state";
|
|
9
15
|
import type {
|
|
10
16
|
CleanseBoardModel,
|
|
11
17
|
CleanseCheckerDescriptor,
|
|
@@ -29,12 +35,26 @@ interface CleansePanelComponentOptions {
|
|
|
29
35
|
/** Terminal state of the run, mirrored into the footer once the core settles. */
|
|
30
36
|
type CleansePanelOutcome = CleansePanelRunStatus | "error";
|
|
31
37
|
|
|
38
|
+
/** Tone of the finished sheet per outcome. */
|
|
39
|
+
const OUTCOME_TONE: Record<CleansePanelOutcome, TspTone> = {
|
|
40
|
+
clean: "success",
|
|
41
|
+
unresolved: "warning",
|
|
42
|
+
unsupported: "warning",
|
|
43
|
+
cancelled: "warning",
|
|
44
|
+
error: "error",
|
|
45
|
+
};
|
|
46
|
+
|
|
32
47
|
export class CleansePanelComponent extends OverlayPanel {
|
|
33
48
|
readonly interactive = true;
|
|
34
49
|
|
|
35
50
|
readonly #tui: TUI;
|
|
36
51
|
readonly #model: CleanseBoardModel;
|
|
37
52
|
readonly #logLines: string[] = [];
|
|
53
|
+
/** Semantic twins of {@link #logLines}, keyed by a running sequence so scrolled-off entries keep their ids. */
|
|
54
|
+
readonly #nativeLog: NativeNode[] = [];
|
|
55
|
+
#logSeq = 0;
|
|
56
|
+
readonly #request: string | undefined;
|
|
57
|
+
#native: NativeNode | undefined;
|
|
38
58
|
#outcome: CleansePanelOutcome | undefined;
|
|
39
59
|
#errorMessage: string | undefined;
|
|
40
60
|
#frame = 0;
|
|
@@ -43,28 +63,39 @@ export class CleansePanelComponent extends OverlayPanel {
|
|
|
43
63
|
readonly #content: StreamingPanelContent;
|
|
44
64
|
|
|
45
65
|
constructor(options: CleansePanelComponentOptions) {
|
|
46
|
-
super(options.request ? `/cleanse ${replaceTabs(options.request)}` : "/cleanse");
|
|
66
|
+
super(options.request ? `/cleanse ${replaceTabs(options.request)}` : "/cleanse", "omp.overlay.cleanse");
|
|
47
67
|
this.#tui = options.tui;
|
|
48
68
|
this.#model = options.model;
|
|
69
|
+
this.#request = options.request === undefined ? undefined : replaceTabs(options.request);
|
|
49
70
|
this.#content = new StreamingPanelContent(() => this.#presentation());
|
|
50
71
|
this.addChild(this.#content);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this.#
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
// The spinner frame only repaints; a native terminal clocks the described spinners itself.
|
|
73
|
+
if (!isNativeRendering()) {
|
|
74
|
+
this.#timer = setInterval(() => {
|
|
75
|
+
this.#frame = (this.#frame + 1) % theme.getSpinnerFrames("activity").length;
|
|
76
|
+
this.#rebuild();
|
|
77
|
+
}, SPINNER_INTERVAL_MS);
|
|
78
|
+
this.#timer.unref?.();
|
|
79
|
+
}
|
|
56
80
|
this.#rebuild();
|
|
57
81
|
}
|
|
58
82
|
|
|
59
|
-
log(
|
|
60
|
-
this.#
|
|
61
|
-
if (this.#logLines.length > MAX_LOG_LINES) this.#logLines.splice(0, this.#logLines.length - MAX_LOG_LINES);
|
|
62
|
-
this.#rebuild();
|
|
83
|
+
log(line: string): void {
|
|
84
|
+
this.#pushLog(line, text(replaceTabs(line), { wrap: "word" }));
|
|
63
85
|
}
|
|
64
86
|
|
|
65
87
|
/** Permanent line styled as a failure (the core's stderr-equivalent). */
|
|
66
|
-
logError(
|
|
67
|
-
this
|
|
88
|
+
logError(line: string): void {
|
|
89
|
+
this.#pushLog(theme.fg("error", line), text([span(replaceTabs(line), "error")], { wrap: "word" }));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#pushLog(line: string, described: NativeNode | undefined): void {
|
|
93
|
+
this.#logLines.push(line);
|
|
94
|
+
if (this.#logLines.length > MAX_LOG_LINES) this.#logLines.splice(0, this.#logLines.length - MAX_LOG_LINES);
|
|
95
|
+
const entry = described ?? text(plainText(line), { wrap: "word" });
|
|
96
|
+
this.#nativeLog.push({ ...entry, key: `log-${this.#logSeq++}` });
|
|
97
|
+
if (this.#nativeLog.length > MAX_LOG_LINES) this.#nativeLog.splice(0, this.#nativeLog.length - MAX_LOG_LINES);
|
|
98
|
+
this.#rebuild();
|
|
68
99
|
}
|
|
69
100
|
|
|
70
101
|
phase(text: string | undefined): void {
|
|
@@ -78,7 +109,8 @@ export class CleansePanelComponent extends OverlayPanel {
|
|
|
78
109
|
}
|
|
79
110
|
|
|
80
111
|
checkerFinished(check: CleanseCheckResult, durationMs: number): void {
|
|
81
|
-
this
|
|
112
|
+
const line = this.#model.checkerFinished(check, durationMs);
|
|
113
|
+
this.#pushLog(line, this.#model.lastSettled);
|
|
82
114
|
}
|
|
83
115
|
|
|
84
116
|
repairFinished(): void {
|
|
@@ -93,10 +125,13 @@ export class CleansePanelComponent extends OverlayPanel {
|
|
|
93
125
|
|
|
94
126
|
agentProgress(name: string, progress: AgentProgress): void {
|
|
95
127
|
this.#model.agentProgress(name, progress);
|
|
128
|
+
// The ANSI view picks progress up on its next spinner repaint; natively nothing else repaints.
|
|
129
|
+
if (isNativeRendering()) this.#rebuild();
|
|
96
130
|
}
|
|
97
131
|
|
|
98
132
|
agentFinished(outcome: CleanseAgentOutcome, assignment: CleanseAssignment): void {
|
|
99
|
-
this
|
|
133
|
+
const line = this.#model.agentFinished(outcome, assignment);
|
|
134
|
+
this.#pushLog(line, this.#model.lastSettled);
|
|
100
135
|
}
|
|
101
136
|
|
|
102
137
|
/** Stop the live area; the panel stays mounted until the user dismisses it. */
|
|
@@ -144,7 +179,62 @@ export class CleansePanelComponent extends OverlayPanel {
|
|
|
144
179
|
};
|
|
145
180
|
}
|
|
146
181
|
|
|
182
|
+
override invalidate(): void {
|
|
183
|
+
this.#native = undefined;
|
|
184
|
+
super.invalidate();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
override describe(cx: DescribeContext): NativeNode {
|
|
188
|
+
if (this.#native) return this.#native;
|
|
189
|
+
// Inline in the dock, styled as a sheet by role: a borderless column headed by the request.
|
|
190
|
+
const title =
|
|
191
|
+
this.#request === undefined
|
|
192
|
+
? [span("/cleanse", "accent")]
|
|
193
|
+
: [span("/cleanse", "accent"), span(` ${this.#request}`)];
|
|
194
|
+
const head = node(
|
|
195
|
+
"row",
|
|
196
|
+
{ role: "omp.sheet.head", gap: "sm", align: "center" },
|
|
197
|
+
[...(this.#outcome === undefined ? [node("spinner", {})] : []), text(title, { truncate: "end", lines: 1 })],
|
|
198
|
+
"head",
|
|
199
|
+
);
|
|
200
|
+
const body: NativeNode[] = [head];
|
|
201
|
+
if (this.#nativeLog.length > 0) body.push(node("col", undefined, [...this.#nativeLog], "log"));
|
|
202
|
+
const live = this.#liveClosed ? undefined : this.#model.describeLive(cx);
|
|
203
|
+
if (live) body.push({ ...live, key: "live" });
|
|
204
|
+
if (this.#errorMessage) {
|
|
205
|
+
body.push(
|
|
206
|
+
node("text", { spans: [span(replaceTabs(this.#errorMessage), "error")], wrap: "word" }, undefined, "error"),
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
body.push({ ...this.#describeFooter(), key: "footer" });
|
|
210
|
+
this.#native = col(body, {
|
|
211
|
+
role: this.nativeRole,
|
|
212
|
+
gap: "sm",
|
|
213
|
+
tone: this.#outcome === undefined ? undefined : OUTCOME_TONE[this.#outcome],
|
|
214
|
+
});
|
|
215
|
+
return this.#native;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#describeFooter(): NativeNode {
|
|
219
|
+
const esc: NativeHint = { keys: boundKeys("app.interrupt", ["escape"]).slice(0, 1), label: "dismiss" };
|
|
220
|
+
switch (this.#outcome) {
|
|
221
|
+
case undefined:
|
|
222
|
+
return hintsRow([{ ...esc, label: "cancel /cleanse" }]);
|
|
223
|
+
case "clean":
|
|
224
|
+
return statusHintsRow([span(`${theme.status.success} Clean`, "success")], [esc]);
|
|
225
|
+
case "unresolved":
|
|
226
|
+
return statusHintsRow([span(`${theme.status.warning} Diagnostics remain`, "warning")], [esc]);
|
|
227
|
+
case "unsupported":
|
|
228
|
+
return statusHintsRow([span(`${theme.status.warning} No runnable checker`, "warning")], [esc]);
|
|
229
|
+
case "cancelled":
|
|
230
|
+
return statusHintsRow([span(`${theme.status.warning} Cancelled`, "warning")], [esc]);
|
|
231
|
+
case "error":
|
|
232
|
+
return statusHintsRow([span(`${theme.status.error} Error`, "error")], [esc]);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
147
236
|
#rebuild(): void {
|
|
237
|
+
this.#native = undefined;
|
|
148
238
|
this.#content.refresh();
|
|
149
239
|
this.#tui.requestRender();
|
|
150
240
|
}
|
|
@@ -9,6 +9,11 @@ import {
|
|
|
9
9
|
} from "../index";
|
|
10
10
|
import { type ThemeColor, theme } from "../theme/theme";
|
|
11
11
|
import { formatKeyHint } from "../app-keybindings";
|
|
12
|
+
import type { TspSpan } from "@oh-my-pi/pi-wire";
|
|
13
|
+
import type { NativeNode, NativeUiEvent } from "../native/node";
|
|
14
|
+
import { col, node, span, text } from "../native/describe";
|
|
15
|
+
import { actionBar, actionButton } from "../native/overlay";
|
|
16
|
+
import { isNativeRendering } from "../native/state";
|
|
12
17
|
|
|
13
18
|
const FRAME_INTERVAL_MS = 85;
|
|
14
19
|
const FRAME_COUNT = 34;
|
|
@@ -256,6 +261,40 @@ function drawBurst(
|
|
|
256
261
|
if (age <= 2) setCell(canvas, centerX, centerY, age === 0 ? "@" : "+", "white", 12);
|
|
257
262
|
}
|
|
258
263
|
|
|
264
|
+
/**
|
|
265
|
+
* The celebration for a TSP terminal: the banner's title as a terminal-clocked
|
|
266
|
+
* shimmer between pulsing sparks, over the event's subtitle. The particle sky
|
|
267
|
+
* is ANSI-only art.
|
|
268
|
+
*/
|
|
269
|
+
function describeCodexResetFireworks(event: CodexResetFireworksEvent): NativeNode {
|
|
270
|
+
const title = event.kind === "unscheduled-weekly-reset" ? "OpenAI reset" : "Saved reset";
|
|
271
|
+
const subtitle =
|
|
272
|
+
event.kind === "unscheduled-weekly-reset"
|
|
273
|
+
? "Weekly usage cleared early"
|
|
274
|
+
: event.added === 1
|
|
275
|
+
? `New reset banked · ${event.available} available`
|
|
276
|
+
: `${event.added} resets banked · ${event.available} available`;
|
|
277
|
+
const spark = (glyph: string, color: FireworkColor): TspSpan =>
|
|
278
|
+
span(glyph, FIREWORK_THEME_COLORS[color], { fx: "pulse" });
|
|
279
|
+
// The sheet is the frame (Tern bursts confetti from the pane's top edge for this role).
|
|
280
|
+
return col(
|
|
281
|
+
[
|
|
282
|
+
text([spark("✦ ", "pink"), spark("✧ ", "cyan"), spark("✦", "gold")]),
|
|
283
|
+
node("shimmer", {
|
|
284
|
+
text: title,
|
|
285
|
+
palette: {
|
|
286
|
+
low: FIREWORK_THEME_COLORS.violet,
|
|
287
|
+
mid: FIREWORK_THEME_COLORS.gold,
|
|
288
|
+
high: FIREWORK_THEME_COLORS.white,
|
|
289
|
+
},
|
|
290
|
+
}),
|
|
291
|
+
text([span(subtitle, FIREWORK_THEME_COLORS.cyan)]),
|
|
292
|
+
actionBar([null, actionButton("Close", "close", { keys: "escape" })]),
|
|
293
|
+
],
|
|
294
|
+
{ align: "center", gap: "sm" },
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
259
298
|
function renderCanvas(canvas: Array<Array<CanvasCell | undefined>>): string[] {
|
|
260
299
|
return canvas.map(row => {
|
|
261
300
|
let output = "";
|
|
@@ -300,6 +339,7 @@ class CodexResetFireworksComponent implements Component {
|
|
|
300
339
|
#done = Promise.withResolvers<void>();
|
|
301
340
|
#frame = 0;
|
|
302
341
|
#disposed = false;
|
|
342
|
+
#native: NativeNode | undefined;
|
|
303
343
|
|
|
304
344
|
constructor(
|
|
305
345
|
readonly host: CodexResetFireworksHost,
|
|
@@ -307,11 +347,14 @@ class CodexResetFireworksComponent implements Component {
|
|
|
307
347
|
) {}
|
|
308
348
|
|
|
309
349
|
run(): Promise<void> {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
this.#
|
|
313
|
-
|
|
314
|
-
|
|
350
|
+
// Frames only repaint the particle sky; a native terminal clocks the described shimmer.
|
|
351
|
+
if (!isNativeRendering()) {
|
|
352
|
+
this.#timer ??= setInterval(() => {
|
|
353
|
+
if (this.#disposed) return;
|
|
354
|
+
this.#frame = (this.#frame + 1) % FRAME_COUNT;
|
|
355
|
+
this.host.ui.requestRender();
|
|
356
|
+
}, FRAME_INTERVAL_MS);
|
|
357
|
+
}
|
|
315
358
|
this.host.ui.requestRender();
|
|
316
359
|
return this.#done.promise;
|
|
317
360
|
}
|
|
@@ -330,6 +373,23 @@ class CodexResetFireworksComponent implements Component {
|
|
|
330
373
|
if (matchesKey(data, "escape") || matchesKey(data, "esc")) this.#done.resolve();
|
|
331
374
|
}
|
|
332
375
|
|
|
376
|
+
/** Close runs what Esc runs. */
|
|
377
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
378
|
+
if (event.type === "action" && event.act === "close") this.#done.resolve();
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/** A glass sheet at the pane's top edge. */
|
|
382
|
+
readonly nativeOverlay = { role: "omp.overlay.fireworks", anchor: "top", size: "md" } as const;
|
|
383
|
+
|
|
384
|
+
invalidate(): void {
|
|
385
|
+
this.#native = undefined;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
describe(): NativeNode {
|
|
389
|
+
this.#native ??= describeCodexResetFireworks(this.event);
|
|
390
|
+
return this.#native;
|
|
391
|
+
}
|
|
392
|
+
|
|
333
393
|
render(width: number): readonly string[] {
|
|
334
394
|
const height = Math.max(1, Math.floor(this.host.ui.terminal.rows * 0.33));
|
|
335
395
|
return renderCodexResetFireworks(width, height, this.#frame, this.event);
|
|
@@ -17,8 +17,10 @@ import {
|
|
|
17
17
|
truncateToWidth,
|
|
18
18
|
visibleWidth,
|
|
19
19
|
} from "../index";
|
|
20
|
-
import type
|
|
20
|
+
import { type ComposerShape, getComposerShapeOptions } from "./composer-shape-registry";
|
|
21
21
|
import { theme } from "../theme/theme";
|
|
22
|
+
import type { NativeNode } from "../native/node";
|
|
23
|
+
import { col, node, span, text } from "../native/describe";
|
|
22
24
|
|
|
23
25
|
/**
|
|
24
26
|
* Real status renderer the preview borrows rows from — structurally satisfied
|
|
@@ -120,6 +122,7 @@ export function renderComposerShapePreview(
|
|
|
120
122
|
export class ComposerShapePreview implements Component {
|
|
121
123
|
#shape: ComposerShape;
|
|
122
124
|
#options: ComposerShapePreviewOptions;
|
|
125
|
+
#native: { shape: ComposerShape; node: NativeNode } | undefined;
|
|
123
126
|
|
|
124
127
|
constructor(initialValue: ComposerShape = "band", options: ComposerShapePreviewOptions = {}) {
|
|
125
128
|
this.#shape = initialValue;
|
|
@@ -132,6 +135,28 @@ export class ComposerShapePreview implements Component {
|
|
|
132
135
|
this.#options.requestRender?.();
|
|
133
136
|
}
|
|
134
137
|
|
|
138
|
+
/**
|
|
139
|
+
* A TSP terminal draws the composer itself, so the shape's glyph chrome has
|
|
140
|
+
* no native twin: the preview names the shape over a read-only prompt.
|
|
141
|
+
*/
|
|
142
|
+
describe(): NativeNode {
|
|
143
|
+
const memo = this.#native;
|
|
144
|
+
if (memo?.shape === this.#shape) return memo.node;
|
|
145
|
+
const option = getComposerShapeOptions().find(candidate => candidate.value === this.#shape);
|
|
146
|
+
const caption = [span(option?.label ?? this.#shape, "strong")];
|
|
147
|
+
if (option?.description) caption.push(span(` · ${option.description}`, "muted"));
|
|
148
|
+
const described = col(
|
|
149
|
+
[
|
|
150
|
+
text([span("Preview:", "muted")]),
|
|
151
|
+
node("editor", { placeholder: "Ask anything, edit files, run tools", readonly: true, maxLines: 1 }),
|
|
152
|
+
text(caption, { wrap: "word" }),
|
|
153
|
+
],
|
|
154
|
+
{ role: "omp.preview.composer-shape", gap: "xs" },
|
|
155
|
+
);
|
|
156
|
+
this.#native = { shape: this.#shape, node: described };
|
|
157
|
+
return described;
|
|
158
|
+
}
|
|
159
|
+
|
|
135
160
|
render(width: number): readonly string[] {
|
|
136
161
|
const lines = renderComposerShapePreview(this.#shape, width, this.#options.status);
|
|
137
162
|
return ["", theme.fg("muted", "Preview:"), ...lines];
|