@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
|
@@ -30,7 +30,15 @@ import { editorKey, editorKeys } from "../chrome/keybinding-hints";
|
|
|
30
30
|
import { formatKeyHint } from "../app-keybindings";
|
|
31
31
|
import { OverlayPanel } from "../chrome/overlay-box";
|
|
32
32
|
import { renderSegmentTrack } from "../chrome/segment-track";
|
|
33
|
+
import { Input } from "../components/input";
|
|
33
34
|
import { MenuSelection, getMenuWindow } from "../components/menu-selection";
|
|
35
|
+
import type { KeyName } from "../key-hint-format";
|
|
36
|
+
import { node, span } from "../native/describe";
|
|
37
|
+
import type { DescribeContext, NativeChild, NativeNode, NativeUiEvent } from "../native/node";
|
|
38
|
+
import { actionHint, hintsRow, overlayCard } from "../native/overlay";
|
|
39
|
+
import { plainText } from "../native/spans";
|
|
40
|
+
import { CLOSE_ACTION, dockedPicker, PICKER_KEY, pickerAction, pickerEvent, pickerQuery } from "../native/picker";
|
|
41
|
+
import type { TspPickerItem } from "@oh-my-pi/pi-wire";
|
|
34
42
|
|
|
35
43
|
/** One segment of a {@link HookSelectorSlider} — a label and an optional
|
|
36
44
|
* detail line (e.g. the resolved model name) shown beneath the track while
|
|
@@ -161,9 +169,27 @@ class OutlinedList extends Container {
|
|
|
161
169
|
* disabled-index lookups survive fuzzy filtering and reordering. */
|
|
162
170
|
type FilteredOption = { option: HookSelectorOption; index: number };
|
|
163
171
|
|
|
172
|
+
/** Plain text of an extension-supplied inline-markdown string: markers rendered away, no ANSI. */
|
|
173
|
+
function plainInline(source: string, mdTheme: MarkdownTheme): string {
|
|
174
|
+
return plainText(renderInlineMarkdown(source, mdTheme));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const ENTER_KEYS: readonly KeyName[] = ["enter"];
|
|
178
|
+
|
|
179
|
+
interface HookSelectorNativeMemo {
|
|
180
|
+
items: readonly FilteredOption[];
|
|
181
|
+
selected: string | undefined;
|
|
182
|
+
query: string;
|
|
183
|
+
slider: number;
|
|
184
|
+
countdown: NativeNode | undefined;
|
|
185
|
+
node: NativeNode;
|
|
186
|
+
}
|
|
187
|
+
|
|
164
188
|
export class HookSelectorComponent extends OverlayPanel {
|
|
165
189
|
#options: HookSelectorOption[];
|
|
166
190
|
#menu: MenuSelection<FilteredOption>;
|
|
191
|
+
/** The type-to-search field; its value drives `#menu`'s query. */
|
|
192
|
+
#search = Object.assign(new Input(), { prompt: "" });
|
|
167
193
|
#disabledIndices: Set<number>;
|
|
168
194
|
#selectionMarker: "radio" | "checkbox" | undefined;
|
|
169
195
|
#checkedIndices: Set<number>;
|
|
@@ -183,6 +209,24 @@ export class HookSelectorComponent extends OverlayPanel {
|
|
|
183
209
|
#sliderIndex: number = 0;
|
|
184
210
|
#sliderComponent: Text | undefined;
|
|
185
211
|
#lastRenderWidth: number | undefined;
|
|
212
|
+
readonly #detailLines: readonly string[];
|
|
213
|
+
readonly #helpText: string | undefined;
|
|
214
|
+
/** Described option rows by original index; `marker` is the radio state baked into the label. */
|
|
215
|
+
readonly #nativeItems = new Map<number, { marker: boolean; node: NativeNode }>();
|
|
216
|
+
/** Title/detail/hint nodes, fixed for the dialog's lifetime. */
|
|
217
|
+
#nativeStatic: { title: string; detail: NativeNode | undefined; hints: NativeNode } | undefined;
|
|
218
|
+
#nativeMemo: HookSelectorNativeMemo | undefined;
|
|
219
|
+
/** Every option as a picker row, by original index (built once; filtering only changes `order`). */
|
|
220
|
+
#pickerItems: readonly TspPickerItem[] | undefined;
|
|
221
|
+
#pickerMemo:
|
|
222
|
+
| {
|
|
223
|
+
items: readonly FilteredOption[];
|
|
224
|
+
selected: string | undefined;
|
|
225
|
+
query: string;
|
|
226
|
+
cursor: number;
|
|
227
|
+
node: NativeNode;
|
|
228
|
+
}
|
|
229
|
+
| undefined;
|
|
186
230
|
constructor(
|
|
187
231
|
title: string,
|
|
188
232
|
options: HookSelectorOptionInput[],
|
|
@@ -190,7 +234,7 @@ export class HookSelectorComponent extends OverlayPanel {
|
|
|
190
234
|
onCancel: () => void,
|
|
191
235
|
opts?: HookSelectorOptions,
|
|
192
236
|
) {
|
|
193
|
-
super(title.split(/\r?\n/, 1)[0] ?? "");
|
|
237
|
+
super(title.split(/\r?\n/, 1)[0] ?? "", "omp.overlay.hook-select");
|
|
194
238
|
|
|
195
239
|
this.#options = options.map(normalizeHookSelectorOption);
|
|
196
240
|
this.#disabledIndices = new Set(
|
|
@@ -218,6 +262,8 @@ export class HookSelectorComponent extends OverlayPanel {
|
|
|
218
262
|
this.#onSelectCallback = onSelect;
|
|
219
263
|
this.#onCancelCallback = onCancel;
|
|
220
264
|
this.#baseTitle = this.title;
|
|
265
|
+
this.#detailLines = title.split(/\r?\n/).slice(1);
|
|
266
|
+
this.#helpText = opts?.helpText;
|
|
221
267
|
this.#onLeftCallback = opts?.onLeft;
|
|
222
268
|
this.#onRightCallback = opts?.onRight;
|
|
223
269
|
this.#onExternalEditorCallback = opts?.onExternalEditor;
|
|
@@ -536,31 +582,30 @@ export class HookSelectorComponent extends OverlayPanel {
|
|
|
536
582
|
this.#menu.query.trim() && total !== this.#options.length
|
|
537
583
|
? `${selectedCount}/${total} of ${this.#options.length}`
|
|
538
584
|
: `${selectedCount}/${total}`;
|
|
539
|
-
|
|
540
|
-
|
|
585
|
+
if (!this.#menu.query.trim()) return theme.fg("dim", ` (${count}) Type to search`);
|
|
586
|
+
const field = this.#search.render(visibleWidth(this.#search.getValue()) + 1)[0] ?? "";
|
|
587
|
+
return `${theme.fg("dim", ` (${count}) Search: `)}${field}`;
|
|
541
588
|
}
|
|
542
589
|
|
|
543
|
-
|
|
544
|
-
|
|
590
|
+
/** Applies the search field's value to the filter. */
|
|
591
|
+
#syncSearchQuery(): void {
|
|
592
|
+
this.#menu.setQuery(this.#search.getValue(), false);
|
|
545
593
|
this.#updateList();
|
|
546
594
|
}
|
|
547
595
|
|
|
596
|
+
/** Feeds keys the selector does not bind to the search field. Backspace on an empty query and a leading space bubble. */
|
|
548
597
|
#handleSearchInput(keyData: string): boolean {
|
|
549
598
|
if (!this.#isSearchEnabled()) return false;
|
|
550
|
-
|
|
551
|
-
if (
|
|
552
|
-
if (
|
|
553
|
-
const
|
|
554
|
-
|
|
555
|
-
this.#setSearchQuery(chars.join(""));
|
|
556
|
-
return true;
|
|
599
|
+
const before = this.#search.getValue();
|
|
600
|
+
if (before.length === 0) {
|
|
601
|
+
if (matchesKey(keyData, "backspace")) return false;
|
|
602
|
+
const printableText = extractPrintableText(keyData);
|
|
603
|
+
if (printableText !== undefined && printableText.trim().length === 0) return false;
|
|
557
604
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
if (
|
|
561
|
-
if (this.#
|
|
562
|
-
|
|
563
|
-
this.#setSearchQuery(this.#menu.query + printableText);
|
|
605
|
+
const cursorBefore = this.#search.getCursor();
|
|
606
|
+
if (!this.#search.handleInput(keyData)) return false;
|
|
607
|
+
if (this.#search.getValue() !== before) this.#syncSearchQuery();
|
|
608
|
+
else if (this.#search.getCursor() !== cursorBefore) this.#updateList();
|
|
564
609
|
return true;
|
|
565
610
|
}
|
|
566
611
|
|
|
@@ -596,10 +641,6 @@ export class HookSelectorComponent extends OverlayPanel {
|
|
|
596
641
|
return;
|
|
597
642
|
}
|
|
598
643
|
|
|
599
|
-
if (this.#handleSearchInput(keyData)) {
|
|
600
|
-
return;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
644
|
if (matchesSelectUp(keyData) || (!this.#isSearchEnabled() && matchesKey(keyData, "k"))) {
|
|
604
645
|
this.#moveSelection(-1);
|
|
605
646
|
} else if (matchesSelectDown(keyData) || (!this.#isSearchEnabled() && matchesKey(keyData, "j"))) {
|
|
@@ -621,6 +662,8 @@ export class HookSelectorComponent extends OverlayPanel {
|
|
|
621
662
|
else this.#onRightCallback?.();
|
|
622
663
|
} else if (this.#onExternalEditorCallback && matchesAppExternalEditor(keyData)) {
|
|
623
664
|
this.#onExternalEditorCallback();
|
|
665
|
+
} else {
|
|
666
|
+
this.#handleSearchInput(keyData);
|
|
624
667
|
}
|
|
625
668
|
}
|
|
626
669
|
|
|
@@ -636,4 +679,250 @@ export class HookSelectorComponent extends OverlayPanel {
|
|
|
636
679
|
override dispose(): void {
|
|
637
680
|
this.#countdown?.dispose();
|
|
638
681
|
}
|
|
682
|
+
|
|
683
|
+
/** The options as a `picker md` sheet: every option by original index, filtering sends only `order`. */
|
|
684
|
+
#describePicker(): NativeNode {
|
|
685
|
+
const items = this.#menu.visibleItems;
|
|
686
|
+
const selected = this.#menu.selectedKey;
|
|
687
|
+
const query = this.#menu.query;
|
|
688
|
+
const cursor = this.#search.getCursor();
|
|
689
|
+
const memo = this.#pickerMemo;
|
|
690
|
+
if (
|
|
691
|
+
memo &&
|
|
692
|
+
memo.items === items &&
|
|
693
|
+
memo.selected === selected &&
|
|
694
|
+
memo.query === query &&
|
|
695
|
+
memo.cursor === cursor
|
|
696
|
+
) {
|
|
697
|
+
return memo.node;
|
|
698
|
+
}
|
|
699
|
+
const mdTheme = getMarkdownTheme();
|
|
700
|
+
const fixed = this.#describeStatic(mdTheme);
|
|
701
|
+
this.#pickerItems ??= this.#options.map((option, index) => ({
|
|
702
|
+
id: String(index),
|
|
703
|
+
label: plainInline(option.label, mdTheme),
|
|
704
|
+
...(option.description ? { detail: plainInline(option.description, mdTheme) } : {}),
|
|
705
|
+
...(this.#isDisabled(index) ? { disabled: true as const } : {}),
|
|
706
|
+
}));
|
|
707
|
+
const checkbox = this.#selectionMarker === "checkbox";
|
|
708
|
+
const result = dockedPicker({
|
|
709
|
+
title: fixed.title,
|
|
710
|
+
...(this.#detailLines.length > 0 ? { subtitle: plainText(this.#detailLines.join(" ")) } : {}),
|
|
711
|
+
noun: "options",
|
|
712
|
+
size: "md",
|
|
713
|
+
layout: "rows",
|
|
714
|
+
preview: "none",
|
|
715
|
+
...pickerQuery(this.#isSearchEnabled() || query.length > 0 ? this.#search : null),
|
|
716
|
+
items: this.#pickerItems,
|
|
717
|
+
...(query.length > 0 ? { order: items.map(filtered => String(filtered.index)) } : {}),
|
|
718
|
+
selected: selected ?? null,
|
|
719
|
+
...(checkbox ? { current: [...this.#checkedIndices].map(String) } : {}),
|
|
720
|
+
total: this.#options.length,
|
|
721
|
+
empty: "No matching options",
|
|
722
|
+
actions: [pickerAction("confirm", "Select", "enter", { primary: true }), CLOSE_ACTION],
|
|
723
|
+
});
|
|
724
|
+
this.#pickerMemo = { items, selected, query, cursor, node: result };
|
|
725
|
+
return result;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* A plain option list is a picker sheet. Otherwise a card headed by the
|
|
730
|
+
* title (plus the countdown `elapsed` when a timeout runs), the extra title
|
|
731
|
+
* lines, the slider as `tabs`, the options as a `list` keyed by original
|
|
732
|
+
* option index, the search query while typing, and the key hints.
|
|
733
|
+
*/
|
|
734
|
+
override describe(cx: DescribeContext): NativeNode {
|
|
735
|
+
if (cx.supports("picker") && !this.#slider && !this.#countdown) return this.#describePicker();
|
|
736
|
+
const items = this.#menu.visibleItems;
|
|
737
|
+
const selected = this.#menu.selectedKey;
|
|
738
|
+
const query = this.#menu.query;
|
|
739
|
+
const countdown = this.#countdown?.describe();
|
|
740
|
+
const memo = this.#nativeMemo;
|
|
741
|
+
if (
|
|
742
|
+
memo &&
|
|
743
|
+
memo.items === items &&
|
|
744
|
+
memo.selected === selected &&
|
|
745
|
+
memo.query === query &&
|
|
746
|
+
memo.slider === this.#sliderIndex &&
|
|
747
|
+
memo.countdown === countdown
|
|
748
|
+
) {
|
|
749
|
+
return memo.node;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
const mdTheme = getMarkdownTheme();
|
|
753
|
+
const fixed = this.#describeStatic(mdTheme);
|
|
754
|
+
const children: NativeChild[] = [];
|
|
755
|
+
if (countdown) {
|
|
756
|
+
children.push(
|
|
757
|
+
node("row", { gap: "sm", align: "baseline" }, [node("text", { text: fixed.title }), countdown], "head"),
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
if (fixed.detail) children.push(fixed.detail);
|
|
761
|
+
if (this.#slider) children.push(...this.#describeSlider(this.#slider));
|
|
762
|
+
|
|
763
|
+
const selectedItem = this.#menu.selectedItem;
|
|
764
|
+
const rows: NativeNode[] = [];
|
|
765
|
+
for (const filtered of items) {
|
|
766
|
+
rows.push(this.#describeOption(filtered, filtered === selectedItem, mdTheme));
|
|
767
|
+
}
|
|
768
|
+
children.push(
|
|
769
|
+
node(
|
|
770
|
+
"list",
|
|
771
|
+
{
|
|
772
|
+
selected: selectedItem && !this.#menu.isDisabled(selectedItem) ? (selected ?? null) : null,
|
|
773
|
+
filter: query.trim() || undefined,
|
|
774
|
+
empty: "No matching options",
|
|
775
|
+
max: { lines: this.#maxVisible },
|
|
776
|
+
},
|
|
777
|
+
rows,
|
|
778
|
+
"list",
|
|
779
|
+
),
|
|
780
|
+
);
|
|
781
|
+
if (query) {
|
|
782
|
+
children.push(
|
|
783
|
+
node("text", { spans: [span("Search: ", "dim"), span(query)], wrap: "none" }, undefined, "search"),
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
children.push(fixed.hints);
|
|
787
|
+
|
|
788
|
+
const root = overlayCard(this.nativeRole, countdown ? undefined : fixed.title, children);
|
|
789
|
+
this.#nativeMemo = { items, selected, query, slider: this.#sliderIndex, countdown, node: root };
|
|
790
|
+
return root;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
/** Pointer pick of an option does what highlighting it and pressing Enter does; a tab pick moves the slider. */
|
|
794
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
795
|
+
const ev = pickerEvent(event, PICKER_KEY);
|
|
796
|
+
if (ev?.kind === "action") {
|
|
797
|
+
this.#resetCountdown();
|
|
798
|
+
if (ev.act === "close" || ev.act === "cancel") this.#onCancelCallback();
|
|
799
|
+
else if (ev.act === "clear") {
|
|
800
|
+
this.#search.setValue("");
|
|
801
|
+
this.#syncSearchQuery();
|
|
802
|
+
} else if (ev.act === "confirm") {
|
|
803
|
+
const selected = this.#menu.selectedItem;
|
|
804
|
+
if (selected && !this.#menu.isDisabled(selected)) this.#onSelectCallback(selected.option.label);
|
|
805
|
+
}
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
if (ev?.kind === "select") {
|
|
809
|
+
const index = this.#menu.visibleItems.findIndex(filtered => String(filtered.index) === ev.item);
|
|
810
|
+
const target = this.#menu.visibleItems[index];
|
|
811
|
+
if (!target || this.#menu.isDisabled(target)) return;
|
|
812
|
+
this.#resetCountdown();
|
|
813
|
+
this.#menu.setSelectedIndex(index);
|
|
814
|
+
this.#updateList();
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
if (event.type !== "select" && event.type !== "activate") return;
|
|
818
|
+
if (event.key === "slider") {
|
|
819
|
+
const target = Number(event.item);
|
|
820
|
+
if (!Number.isInteger(target)) return;
|
|
821
|
+
this.#resetCountdown();
|
|
822
|
+
this.#moveSlider(target - this.#sliderIndex);
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
if (event.key !== "list" && ev?.kind !== "activate") return;
|
|
826
|
+
const index = this.#menu.visibleItems.findIndex(filtered => String(filtered.index) === event.item);
|
|
827
|
+
const target = this.#menu.visibleItems[index];
|
|
828
|
+
if (!target || this.#menu.isDisabled(target)) return;
|
|
829
|
+
this.#resetCountdown();
|
|
830
|
+
this.#menu.setSelectedIndex(index);
|
|
831
|
+
this.#updateList();
|
|
832
|
+
this.#onSelectCallback(target.option.label);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
#resetCountdown(): void {
|
|
836
|
+
if (!this.#countdown) return;
|
|
837
|
+
this.#countdown.reset();
|
|
838
|
+
this.#onTimeoutResetCallback?.();
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
#describeStatic(mdTheme: MarkdownTheme): { title: string; detail: NativeNode | undefined; hints: NativeNode } {
|
|
842
|
+
if (this.#nativeStatic) return this.#nativeStatic;
|
|
843
|
+
const detail =
|
|
844
|
+
this.#detailLines.length > 0
|
|
845
|
+
? node(
|
|
846
|
+
"text",
|
|
847
|
+
{ spans: [span(plainText(this.#detailLines.join("\n")), "accent")], wrap: "word" },
|
|
848
|
+
undefined,
|
|
849
|
+
"detail",
|
|
850
|
+
)
|
|
851
|
+
: undefined;
|
|
852
|
+
const hints =
|
|
853
|
+
this.#helpText !== undefined
|
|
854
|
+
? node("text", { spans: [span(plainText(this.#helpText), "dim")], wrap: "word" }, undefined, "hints")
|
|
855
|
+
: hintsRow([
|
|
856
|
+
actionHint(["tui.select.up", "tui.select.down"], "navigate"),
|
|
857
|
+
{ keys: ENTER_KEYS, label: "select" },
|
|
858
|
+
actionHint("tui.select.cancel", "cancel"),
|
|
859
|
+
]);
|
|
860
|
+
this.#nativeStatic = { title: plainInline(this.#baseTitle, mdTheme), detail, hints };
|
|
861
|
+
return this.#nativeStatic;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/** Caption, a `tabs` strip of the segments (active = slider index), and the active segment's detail. */
|
|
865
|
+
#describeSlider(slider: HookSelectorSlider): NativeNode[] {
|
|
866
|
+
const out: NativeNode[] = [];
|
|
867
|
+
if (slider.caption) {
|
|
868
|
+
out.push(node("text", { spans: [span(plainText(slider.caption), "dim")] }, undefined, "slider-caption"));
|
|
869
|
+
}
|
|
870
|
+
out.push(
|
|
871
|
+
node(
|
|
872
|
+
"tabs",
|
|
873
|
+
{
|
|
874
|
+
items: slider.segments.map((segment, i) => ({ id: String(i), label: plainText(segment.label) })),
|
|
875
|
+
active: String(this.#sliderIndex),
|
|
876
|
+
},
|
|
877
|
+
undefined,
|
|
878
|
+
"slider",
|
|
879
|
+
),
|
|
880
|
+
);
|
|
881
|
+
const detail = slider.segments[this.#sliderIndex]?.detail;
|
|
882
|
+
if (detail) {
|
|
883
|
+
out.push(
|
|
884
|
+
node(
|
|
885
|
+
"text",
|
|
886
|
+
{ spans: [span("↳ ", "dim"), span(plainText(detail), "muted")], wrap: "word" },
|
|
887
|
+
undefined,
|
|
888
|
+
"slider-detail",
|
|
889
|
+
),
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
return out;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/** One option `item`; radio rows re-describe only when their filled state flips. */
|
|
896
|
+
#describeOption(filtered: FilteredOption, isSelected: boolean, mdTheme: MarkdownTheme): NativeNode {
|
|
897
|
+
const { option, index } = filtered;
|
|
898
|
+
const radio = this.#selectionMarker === "radio" && index < this.#markableCount;
|
|
899
|
+
const marker = radio && isSelected;
|
|
900
|
+
const cached = this.#nativeItems.get(index);
|
|
901
|
+
if (cached && cached.marker === marker) return cached.node;
|
|
902
|
+
|
|
903
|
+
const disabled = this.#isDisabled(index);
|
|
904
|
+
const label = plainInline(option.label, mdTheme);
|
|
905
|
+
let glyph: string | undefined;
|
|
906
|
+
let glyphColor = "dim";
|
|
907
|
+
if (radio) {
|
|
908
|
+
glyph = marker ? theme.radio.selected : theme.radio.unselected;
|
|
909
|
+
if (marker && !disabled) glyphColor = "accent";
|
|
910
|
+
} else if (this.#selectionMarker === "checkbox" && index < this.#markableCount) {
|
|
911
|
+
const checked = this.#checkedIndices.has(index);
|
|
912
|
+
glyph = checked ? theme.checkbox.checked : theme.checkbox.unchecked;
|
|
913
|
+
if (checked && !disabled) glyphColor = "success";
|
|
914
|
+
}
|
|
915
|
+
const described = node(
|
|
916
|
+
"item",
|
|
917
|
+
{
|
|
918
|
+
label: glyph ? [span(`${glyph} `, glyphColor), span(label)] : [span(label)],
|
|
919
|
+
detail: option.description ? [span(plainInline(option.description, mdTheme), "muted")] : undefined,
|
|
920
|
+
disabled: disabled || undefined,
|
|
921
|
+
},
|
|
922
|
+
undefined,
|
|
923
|
+
String(index),
|
|
924
|
+
);
|
|
925
|
+
this.#nativeItems.set(index, { marker, node: described });
|
|
926
|
+
return described;
|
|
927
|
+
}
|
|
639
928
|
}
|
|
@@ -4,6 +4,11 @@ import { Stack } from "../components/layout/stack";
|
|
|
4
4
|
import { matchesKey } from "../keys";
|
|
5
5
|
import { theme } from "../theme/theme";
|
|
6
6
|
import { truncateToWidth, visibleWidth } from "../utils";
|
|
7
|
+
import type { TspText } from "@oh-my-pi/pi-wire";
|
|
8
|
+
import { node, span, text } from "../native/describe";
|
|
9
|
+
import type { NativeChild, NativeNode } from "../native/node";
|
|
10
|
+
import { overlayCard } from "../native/overlay";
|
|
11
|
+
import { plainText } from "../native/spans";
|
|
7
12
|
|
|
8
13
|
/** A scope row shared by fullscreen hubs, with hub-specific kinds and metadata. */
|
|
9
14
|
export interface SidebarEntry<TKind extends string> {
|
|
@@ -55,6 +60,81 @@ export function moveStripSelection(strip: StripState<StripChip<unknown>>, data:
|
|
|
55
60
|
return false;
|
|
56
61
|
}
|
|
57
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Native sidebar: a `list` whose `item`s are keyed by entry id (the `item` of
|
|
65
|
+
* `select`/`activate` events), separators as `rule`s. Scrolling and clipping
|
|
66
|
+
* are the terminal's; `style` supplies icon, annotation and muting.
|
|
67
|
+
*/
|
|
68
|
+
export function describeHubSidebar<TEntry extends SidebarEntry<string>>(
|
|
69
|
+
entries: readonly TEntry[],
|
|
70
|
+
selectedId: string,
|
|
71
|
+
style: (entry: TEntry, index: number) => Pick<SidebarStyle, "icon" | "annotation" | "muted">,
|
|
72
|
+
key = "sidebar",
|
|
73
|
+
): NativeNode {
|
|
74
|
+
const items: NativeNode[] = [];
|
|
75
|
+
for (let i = 0; i < entries.length; i++) {
|
|
76
|
+
const entry = entries[i]!;
|
|
77
|
+
if (entry.kind === "separator") {
|
|
78
|
+
items.push(node("rule", undefined, undefined, entry.id));
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const decoration = style(entry, i);
|
|
82
|
+
items.push(
|
|
83
|
+
node(
|
|
84
|
+
"item",
|
|
85
|
+
{
|
|
86
|
+
label: decoration.icon
|
|
87
|
+
? [
|
|
88
|
+
span(`${plainText(decoration.icon)} `, "muted"),
|
|
89
|
+
span(entry.label, decoration.muted ? "dim" : undefined),
|
|
90
|
+
]
|
|
91
|
+
: [span(entry.label, decoration.muted ? "dim" : undefined)],
|
|
92
|
+
value: decoration.annotation ? plainText(decoration.annotation) : undefined,
|
|
93
|
+
},
|
|
94
|
+
undefined,
|
|
95
|
+
entry.id,
|
|
96
|
+
),
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
return node("list", { selected: selectedId }, items, key);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Native footer chip strip: a `tabs` node whose tab ids are the chip indices
|
|
104
|
+
* (`select` events carry the index as `item`), with an optional prefix label.
|
|
105
|
+
*/
|
|
106
|
+
export function describeHubChips(strip: StripState<StripChip<unknown>>, prefix?: TspText, key = "chips"): NativeNode {
|
|
107
|
+
const tabs = node(
|
|
108
|
+
"tabs",
|
|
109
|
+
{
|
|
110
|
+
items: strip.chips.map((chip, index) => ({ id: String(index), label: chip.label })),
|
|
111
|
+
active: String(strip.index),
|
|
112
|
+
},
|
|
113
|
+
undefined,
|
|
114
|
+
"tabs",
|
|
115
|
+
);
|
|
116
|
+
const children: NativeChild[] = prefix === undefined ? [tabs] : [text(prefix), tabs];
|
|
117
|
+
return node("row", { gap: "sm", align: "center" }, children, key);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Native fullscreen hub: a root card titled `title` over a sidebar/body row and
|
|
122
|
+
* a footer. The split geometry, ring and dividers are the terminal's.
|
|
123
|
+
*/
|
|
124
|
+
export function describeHubFrame(
|
|
125
|
+
role: string,
|
|
126
|
+
title: TspText,
|
|
127
|
+
sidebar: NativeChild,
|
|
128
|
+
body: NativeChild,
|
|
129
|
+
footer: NativeChild,
|
|
130
|
+
): NativeNode {
|
|
131
|
+
return overlayCard(role, title, [
|
|
132
|
+
node("row", { gap: "md", align: "start", grow: 1 }, [sidebar, body], "split"),
|
|
133
|
+
node("rule", undefined, undefined, "divider"),
|
|
134
|
+
footer,
|
|
135
|
+
]);
|
|
136
|
+
}
|
|
137
|
+
|
|
58
138
|
/** Persistent fullscreen split frame, sidebar viewport, and footer chip renderer. */
|
|
59
139
|
export class HubFrame {
|
|
60
140
|
/** Current sidebar viewport offset, shared with the hub's navigation. */
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/jobs` output: the async background jobs of a session. ANSI keeps the
|
|
3
|
+
* caller's text report; natively it is one frame whose rows are `agent`
|
|
4
|
+
* nodes for task jobs and a status dot, the label and a live `elapsed` for
|
|
5
|
+
* the others (running first, recent below a hairline).
|
|
6
|
+
*/
|
|
7
|
+
import type { TspAgentProps, TspSpan } from "@oh-my-pi/pi-wire";
|
|
8
|
+
import { type Component, Container } from "../tui";
|
|
9
|
+
import { card, elapsed, node, span, text } from "../native/describe";
|
|
10
|
+
import type { DescribeContext, NativeChild, NativeNode } from "../native/node";
|
|
11
|
+
|
|
12
|
+
/** One async job as the session snapshots it. */
|
|
13
|
+
export interface JobsPanelJob {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly type: string;
|
|
16
|
+
readonly status: "running" | "completed" | "failed" | "cancelled";
|
|
17
|
+
readonly label: string;
|
|
18
|
+
readonly startTime: number;
|
|
19
|
+
readonly endTime?: number;
|
|
20
|
+
/** Registry id of the subagent a task job runs. */
|
|
21
|
+
readonly agentId?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Running and recently settled jobs. */
|
|
25
|
+
export interface JobsPanelSnapshot {
|
|
26
|
+
readonly running: readonly JobsPanelJob[];
|
|
27
|
+
readonly recent: readonly JobsPanelJob[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const AGENT_STATUS: Record<JobsPanelJob["status"], TspAgentProps["status"]> = {
|
|
31
|
+
running: "running",
|
|
32
|
+
completed: "done",
|
|
33
|
+
failed: "failed",
|
|
34
|
+
cancelled: "aborted",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const DOT: Record<JobsPanelJob["status"], TspSpan> = {
|
|
38
|
+
running: { t: "●", s: "accent", fx: "pulse" },
|
|
39
|
+
completed: { t: "●", s: "success" },
|
|
40
|
+
failed: { t: "●", s: "error" },
|
|
41
|
+
cancelled: { t: "●", s: "dim" },
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** The `/jobs` block: `ansi` renders in the terminal, the snapshot describes the native frame. */
|
|
45
|
+
export class JobsPanel extends Container {
|
|
46
|
+
readonly #snapshot: JobsPanelSnapshot;
|
|
47
|
+
readonly #nowMs: number;
|
|
48
|
+
#native: { agent: boolean; node: NativeNode } | undefined;
|
|
49
|
+
|
|
50
|
+
constructor(snapshot: JobsPanelSnapshot, nowMs: number, ansi: readonly Component[]) {
|
|
51
|
+
super();
|
|
52
|
+
this.#snapshot = snapshot;
|
|
53
|
+
this.#nowMs = nowMs;
|
|
54
|
+
for (const child of ansi) this.addChild(child);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
override describe(cx: DescribeContext): NativeNode {
|
|
58
|
+
const agent = cx.supports("agent");
|
|
59
|
+
if (this.#native?.agent === agent) return this.#native.node;
|
|
60
|
+
const { running, recent } = this.#snapshot;
|
|
61
|
+
const children: NativeChild[] = [];
|
|
62
|
+
if (running.length === 0 && recent.length === 0) {
|
|
63
|
+
children.push(node("text", { text: "No background jobs", role: "omp.jobs.empty" }, undefined, "empty"));
|
|
64
|
+
}
|
|
65
|
+
for (const job of running) children.push(this.#describeJob(job, agent));
|
|
66
|
+
if (recent.length > 0) {
|
|
67
|
+
children.push(
|
|
68
|
+
node(
|
|
69
|
+
"section",
|
|
70
|
+
{ head: [span("Recent", "muted")] },
|
|
71
|
+
recent.map(job => this.#describeJob(job, agent)),
|
|
72
|
+
"recent",
|
|
73
|
+
),
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
const head: TspSpan[] = [span("Background jobs", "strong")];
|
|
77
|
+
if (running.length > 0) head.push(span(` · ${running.length} running`, "muted"));
|
|
78
|
+
const described = card({ role: "omp.jobs", head }, children);
|
|
79
|
+
this.#native = { agent, node: described };
|
|
80
|
+
return described;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#describeJob(job: JobsPanelJob, agent: boolean): NativeNode {
|
|
84
|
+
const settled = job.status !== "running";
|
|
85
|
+
const age = Math.max(0, (job.endTime ?? this.#nowMs) - job.startTime);
|
|
86
|
+
if (agent && job.type === "task") {
|
|
87
|
+
return node(
|
|
88
|
+
"agent",
|
|
89
|
+
{
|
|
90
|
+
name: job.agentId ?? job.id,
|
|
91
|
+
agent: "task",
|
|
92
|
+
task: job.label,
|
|
93
|
+
status: AGENT_STATUS[job.status],
|
|
94
|
+
stats: settled ? { took: age } : { age },
|
|
95
|
+
},
|
|
96
|
+
undefined,
|
|
97
|
+
job.id,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return node(
|
|
101
|
+
"row",
|
|
102
|
+
{ role: "omp.jobs.row", gap: "sm", align: "center", title: `${job.id} · ${job.type} · ${job.status}` },
|
|
103
|
+
[
|
|
104
|
+
text([DOT[job.status]], { aria: job.status }),
|
|
105
|
+
text([span(job.label)], { truncate: "end", grow: 1 }),
|
|
106
|
+
text([span(job.type, "dim")]),
|
|
107
|
+
elapsed(age, settled),
|
|
108
|
+
],
|
|
109
|
+
job.id,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|