@oh-my-pi/pi-tui 18.2.4 → 18.2.5
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 +23 -0
- package/README.md +43 -0
- package/dist/types/app-keybindings.d.ts +395 -0
- package/dist/types/apps/autoresearch-dashboard.d.ts +43 -0
- package/dist/types/apps/autoresearch-data.d.ts +15 -0
- package/dist/types/apps/cleanse-board.d.ts +66 -0
- package/dist/types/apps/cleanse-picker.d.ts +23 -0
- package/dist/types/apps/debug/log-formatting.d.ts +6 -0
- package/dist/types/apps/debug/log-viewer.d.ts +81 -0
- package/dist/types/apps/debug/protocol-probe.d.ts +42 -0
- package/dist/types/apps/debug/raw-sse-buffer.d.ts +58 -0
- package/dist/types/apps/debug/raw-sse.d.ts +26 -0
- package/dist/types/apps/debug/terminal-info.d.ts +34 -0
- package/dist/types/apps/debug/viewer-frame.d.ts +52 -0
- package/dist/types/apps/git/avatar.d.ts +9 -0
- package/dist/types/apps/git/colors.d.ts +49 -0
- package/dist/types/apps/git/diff-pane.d.ts +188 -0
- package/dist/types/apps/git/git-tui.d.ts +66 -0
- package/dist/types/apps/git/sidebar.d.ts +149 -0
- package/dist/types/apps/git/state.d.ts +117 -0
- package/dist/types/apps/if-bench-board.d.ts +75 -0
- package/dist/types/apps/live-visualizer.d.ts +33 -0
- package/dist/types/apps/ps-data.d.ts +51 -0
- package/dist/types/apps/ps-top.d.ts +33 -0
- package/dist/types/apps/session-picker.d.ts +26 -0
- package/dist/types/apps/setup-model-picker.d.ts +13 -0
- package/dist/types/apps/standalone-picker.d.ts +42 -0
- package/dist/types/autocomplete.d.ts +4 -0
- package/dist/types/chat/advisor-message.d.ts +11 -0
- package/dist/types/chat/assistant-message.d.ts +106 -0
- package/dist/types/chat/background-tan-message.d.ts +9 -0
- package/dist/types/chat/bash-execution.d.ts +47 -0
- package/dist/types/chat/cache-invalidation-marker.d.ts +50 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +50 -0
- package/dist/types/chat/collab-prompt-message.d.ts +10 -0
- package/dist/types/chat/compaction-summary-message.d.ts +54 -0
- package/dist/types/chat/custom-message.d.ts +10 -0
- package/dist/types/chat/display-preferences.d.ts +13 -0
- package/dist/types/chat/eval-execution.d.ts +29 -0
- package/dist/types/chat/execution-shared.d.ts +51 -0
- package/dist/types/chat/extension-types.d.ts +28 -0
- package/dist/types/chat/hook-message.d.ts +10 -0
- package/dist/types/chat/image-loading.d.ts +46 -0
- package/dist/types/chat/late-diagnostics-message.d.ts +21 -0
- package/dist/types/chat/messages.d.ts +189 -0
- package/dist/types/chat/reaction.d.ts +30 -0
- package/dist/types/chat/read-target.d.ts +4 -0
- package/dist/types/chat/read-tool-group.d.ts +67 -0
- package/dist/types/chat/served-model-marker.d.ts +47 -0
- package/dist/types/chat/skill-message.d.ts +33 -0
- package/dist/types/chat/skill-title-input.d.ts +14 -0
- package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +12 -0
- package/dist/types/chat/thinking-display.d.ts +12 -0
- package/dist/types/chat/todo-reminder.d.ts +13 -0
- package/dist/types/chat/tool-execution.d.ts +138 -0
- package/dist/types/chat/transcript-browser.d.ts +93 -0
- package/dist/types/chat/transcript-entry.d.ts +45 -0
- package/dist/types/chat/transcript-outline.d.ts +86 -0
- package/dist/types/chat/transcript-render-helpers.d.ts +92 -0
- package/dist/types/chat/ttsr-notification.d.ts +23 -0
- package/dist/types/chat/user-message.d.ts +52 -0
- package/dist/types/chrome/chat-block.d.ts +64 -0
- package/dist/types/chrome/collab-qrcode.d.ts +28 -0
- package/dist/types/chrome/context-thresholds.d.ts +10 -0
- package/dist/types/chrome/countdown-timer.d.ts +14 -0
- package/dist/types/chrome/diff.d.ts +14 -0
- package/dist/types/chrome/dynamic-border.d.ts +16 -0
- package/dist/types/chrome/error-block.d.ts +17 -0
- package/dist/types/chrome/form-theme.d.ts +3 -0
- package/dist/types/chrome/format.d.ts +12 -0
- package/dist/types/chrome/index.d.ts +20 -0
- package/dist/types/chrome/keybinding-hints.d.ts +40 -0
- package/dist/types/chrome/live-board.d.ts +23 -0
- package/dist/types/chrome/local-date.d.ts +4 -0
- package/dist/types/chrome/message-divider.d.ts +22 -0
- package/dist/types/chrome/message-frame.d.ts +52 -0
- package/dist/types/chrome/message-notice.d.ts +35 -0
- package/dist/types/chrome/overlay-box.d.ts +74 -0
- package/dist/types/chrome/qrcode.d.ts +48 -0
- package/dist/types/chrome/segment-track.d.ts +27 -0
- package/dist/types/chrome/select-list-mouse-routing.d.ts +4 -0
- package/dist/types/chrome/selector-helpers.d.ts +52 -0
- package/dist/types/chrome/shared.d.ts +5 -0
- package/dist/types/chrome/streaming-panel.d.ts +19 -0
- package/dist/types/chrome/tool-activity.d.ts +17 -0
- package/dist/types/chrome/transcript-container.d.ts +129 -0
- package/dist/types/chrome/transcript-status.d.ts +12 -0
- package/dist/types/chrome/visual-truncate.d.ts +19 -0
- package/dist/types/components/disclosure.d.ts +42 -0
- package/dist/types/components/form.d.ts +130 -0
- package/dist/types/components/key-value-list.d.ts +24 -0
- package/dist/types/components/layout/geometry.d.ts +73 -0
- package/dist/types/components/layout/row.d.ts +55 -0
- package/dist/types/components/layout/split-pane.d.ts +80 -0
- package/dist/types/components/layout/stack.d.ts +50 -0
- package/dist/types/components/menu-selection.d.ts +71 -0
- package/dist/types/components/metric.d.ts +44 -0
- package/dist/types/components/progress-bar.d.ts +36 -0
- package/dist/types/components/scroll-view.d.ts +53 -19
- package/dist/types/components/scroll-viewport.d.ts +46 -0
- package/dist/types/components/section.d.ts +19 -0
- package/dist/types/components/select-list.d.ts +46 -2
- package/dist/types/components/settings-list.d.ts +20 -0
- package/dist/types/components/table.d.ts +32 -0
- package/dist/types/components/tree-view.d.ts +130 -0
- package/dist/types/components/wizard-step.d.ts +60 -0
- package/dist/types/hotkeys-markdown.d.ts +7 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/keybinding-matchers.d.ts +35 -0
- package/dist/types/keys.d.ts +2 -2
- package/dist/types/lang-from-path.d.ts +9 -0
- package/dist/types/overlays/advisor-config.d.ts +114 -0
- package/dist/types/overlays/agent-activity.d.ts +41 -0
- package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
- package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
- package/dist/types/overlays/agent-hub-types.d.ts +99 -0
- package/dist/types/overlays/agent-hub.d.ts +126 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
- package/dist/types/overlays/agents-hub.d.ts +72 -0
- package/dist/types/overlays/ask-dialog.d.ts +88 -0
- package/dist/types/overlays/bordered-loader.d.ts +11 -0
- package/dist/types/overlays/btw-history-panel.d.ts +29 -0
- package/dist/types/overlays/btw-history.d.ts +17 -0
- package/dist/types/overlays/btw-panel.d.ts +26 -0
- package/dist/types/overlays/cleanse-panel.d.ts +36 -0
- package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
- package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
- package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
- package/dist/types/overlays/copy-selector.d.ts +48 -0
- package/dist/types/overlays/copy-targets.d.ts +63 -0
- package/dist/types/overlays/error-banner.d.ts +13 -0
- package/dist/types/overlays/extensions/display-text.d.ts +10 -0
- package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
- package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
- package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
- package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
- package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
- package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
- package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
- package/dist/types/overlays/extensions/types.d.ts +165 -0
- package/dist/types/overlays/history-search.d.ts +16 -0
- package/dist/types/overlays/hook-editor.d.ts +44 -0
- package/dist/types/overlays/hook-input.d.ts +20 -0
- package/dist/types/overlays/hook-selector.d.ts +71 -0
- package/dist/types/overlays/hub-frame.d.ts +77 -0
- package/dist/types/overlays/login-dialog.d.ts +43 -0
- package/dist/types/overlays/logout-account-selector.d.ts +15 -0
- package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
- package/dist/types/overlays/model-browser.d.ts +213 -0
- package/dist/types/overlays/model-hub.d.ts +72 -0
- package/dist/types/overlays/model-picker.d.ts +74 -0
- package/dist/types/overlays/model-selector.d.ts +52 -0
- package/dist/types/overlays/move-overlay.d.ts +39 -0
- package/dist/types/overlays/oauth-selector.d.ts +41 -0
- package/dist/types/overlays/omfg-panel.d.ts +20 -0
- package/dist/types/overlays/pause-screen.d.ts +43 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
- package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
- package/dist/types/overlays/plan-toc.d.ts +41 -0
- package/dist/types/overlays/plugin-selector.d.ts +28 -0
- package/dist/types/overlays/plugin-settings.d.ts +180 -0
- package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
- package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
- package/dist/types/overlays/rewind-selector.d.ts +61 -0
- package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
- package/dist/types/overlays/session-account-selector.d.ts +24 -0
- package/dist/types/overlays/session-info-overlay.d.ts +17 -0
- package/dist/types/overlays/session-observer-registry.d.ts +77 -0
- package/dist/types/overlays/session-selector.d.ts +131 -0
- package/dist/types/overlays/settings-defs.d.ts +119 -0
- package/dist/types/overlays/settings-selector.d.ts +73 -0
- package/dist/types/overlays/show-images-selector.d.ts +11 -0
- package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
- package/dist/types/overlays/theme-selector.d.ts +12 -0
- package/dist/types/overlays/thinking-selector.d.ts +12 -0
- package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
- package/dist/types/overlays/tree-selector.d.ts +92 -0
- package/dist/types/overlays/usage-dashboard.d.ts +94 -0
- package/dist/types/overlays/usage-display.d.ts +5 -0
- package/dist/types/overlays/usage-row.d.ts +17 -0
- package/dist/types/prompt/attachment-chips.d.ts +19 -0
- package/dist/types/prompt/composer-attachments.d.ts +71 -0
- package/dist/types/prompt/composer-cache.d.ts +37 -0
- package/dist/types/prompt/composer.d.ts +159 -0
- package/dist/types/prompt/custom-editor.d.ts +261 -0
- package/dist/types/prompt/editor-top-gap.d.ts +18 -0
- package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
- package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
- package/dist/types/prompt/gradient-highlight.d.ts +32 -0
- package/dist/types/prompt/image-format.d.ts +4 -0
- package/dist/types/prompt/image-references.d.ts +26 -0
- package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
- package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
- package/dist/types/prompt/macos-spelling.d.ts +44 -0
- package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
- package/dist/types/prompt/magic-keywords.d.ts +26 -0
- package/dist/types/prompt/markdown-prose.d.ts +15 -0
- package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
- package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
- package/dist/types/prompt/orchestrate.d.ts +13 -0
- package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
- package/dist/types/prompt/queue-input.d.ts +8 -0
- package/dist/types/prompt/skill-tokens.d.ts +13 -0
- package/dist/types/prompt/tools-markdown.d.ts +12 -0
- package/dist/types/prompt/ultrathink.d.ts +13 -0
- package/dist/types/prompt/usage-amounts.d.ts +26 -0
- package/dist/types/prompt/video.d.ts +18 -0
- package/dist/types/prompt/welcome.d.ts +83 -0
- package/dist/types/prompt/workflow.d.ts +13 -0
- package/dist/types/render/code-cell.d.ts +51 -0
- package/dist/types/render/file-list.d.ts +22 -0
- package/dist/types/render/hyperlink.d.ts +80 -0
- package/dist/types/render/index.d.ts +16 -0
- package/dist/types/render/output-block.d.ts +54 -0
- package/dist/types/render/output-pane.d.ts +80 -0
- package/dist/types/render/render-utils.d.ts +312 -0
- package/dist/types/render/sixel.d.ts +21 -0
- package/dist/types/render/status-line.d.ts +23 -0
- package/dist/types/render/tool-card.d.ts +71 -0
- package/dist/types/render/tree-list.d.ts +29 -0
- package/dist/types/render/types.d.ts +17 -0
- package/dist/types/render/utils.d.ts +43 -0
- package/dist/types/render/width-aware-text.d.ts +23 -0
- package/dist/types/setup/lazy.d.ts +3 -0
- package/dist/types/setup/scenes/composer.d.ts +3 -0
- package/dist/types/setup/scenes/glyph.d.ts +3 -0
- package/dist/types/setup/scenes/model.d.ts +3 -0
- package/dist/types/setup/scenes/outro.d.ts +2 -0
- package/dist/types/setup/scenes/providers.d.ts +3 -0
- package/dist/types/setup/scenes/sign-in.d.ts +21 -0
- package/dist/types/setup/scenes/splash.d.ts +11 -0
- package/dist/types/setup/scenes/theme.d.ts +3 -0
- package/dist/types/setup/scenes/types.d.ts +110 -0
- package/dist/types/setup/scenes/web-search.d.ts +22 -0
- package/dist/types/setup/setup-version.d.ts +11 -0
- package/dist/types/setup/startup-splash.d.ts +9 -0
- package/dist/types/setup/wizard-overlay.d.ts +16 -0
- package/dist/types/setup/wizard.d.ts +25 -0
- package/dist/types/status-line/component.d.ts +182 -0
- package/dist/types/status-line/context-usage.d.ts +156 -0
- package/dist/types/status-line/footer.d.ts +30 -0
- package/dist/types/status-line/git-utils.d.ts +22 -0
- package/dist/types/status-line/host.d.ts +129 -0
- package/dist/types/status-line/index.d.ts +6 -0
- package/dist/types/status-line/loop.d.ts +18 -0
- package/dist/types/status-line/metrics.d.ts +21 -0
- package/dist/types/status-line/presets.d.ts +3 -0
- package/dist/types/status-line/schema.d.ts +15 -0
- package/dist/types/status-line/segments.d.ts +5 -0
- package/dist/types/status-line/separators.d.ts +3 -0
- package/dist/types/status-line/types.d.ts +236 -0
- package/dist/types/stdin-buffer.d.ts +4 -0
- package/dist/types/theme/color.d.ts +24 -0
- package/dist/types/theme/defaults/index.d.ts +9489 -0
- package/dist/types/theme/index.d.ts +4 -0
- package/dist/types/theme/loader.d.ts +23 -0
- package/dist/types/theme/mermaid-cache.d.ts +26 -0
- package/dist/types/theme/schema-validation.d.ts +3 -0
- package/dist/types/theme/schema.d.ts +25 -0
- package/dist/types/theme/session-color.d.ts +43 -0
- package/dist/types/theme/shimmer.d.ts +44 -0
- package/dist/types/theme/symbols.d.ts +34 -0
- package/dist/types/theme/theme-class.d.ts +299 -0
- package/dist/types/theme/theme.d.ts +111 -0
- package/dist/types/theme/tui-adapters.d.ts +30 -0
- package/dist/types/thinking.d.ts +165 -0
- package/dist/types/tools/agent-tree.d.ts +36 -0
- package/dist/types/tools/ask.d.ts +67 -0
- package/dist/types/tools/ast-edit.d.ts +53 -0
- package/dist/types/tools/ast-grep.d.ts +52 -0
- package/dist/types/tools/autoresearch.d.ts +156 -0
- package/dist/types/tools/bash-interactive.d.ts +28 -0
- package/dist/types/tools/bash.d.ts +103 -0
- package/dist/types/tools/conflict-detect.d.ts +43 -0
- package/dist/types/tools/debug.d.ts +60 -0
- package/dist/types/tools/default-renderer.d.ts +24 -0
- package/dist/types/tools/edit.d.ts +158 -0
- package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
- package/dist/types/tools/eval-format/index.d.ts +5 -0
- package/dist/types/tools/eval-format/javascript.d.ts +2 -0
- package/dist/types/tools/eval-format/python.d.ts +2 -0
- package/dist/types/tools/eval.d.ts +94 -0
- package/dist/types/tools/fetch.d.ts +42 -0
- package/dist/types/tools/gh-format.d.ts +8 -0
- package/dist/types/tools/github.d.ts +144 -0
- package/dist/types/tools/glob.d.ts +44 -0
- package/dist/types/tools/goal.d.ts +42 -0
- package/dist/types/tools/grep.d.ts +64 -0
- package/dist/types/tools/grouped-file-output.d.ts +71 -0
- package/dist/types/tools/hashline-format.d.ts +28 -0
- package/dist/types/tools/hub.d.ts +340 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/json-tree.d.ts +59 -0
- package/dist/types/tools/line-ranges.d.ts +29 -0
- package/dist/types/tools/list-limit.d.ts +15 -0
- package/dist/types/tools/lsp.d.ts +72 -0
- package/dist/types/tools/match-line-format.d.ts +11 -0
- package/dist/types/tools/mcp.d.ts +81 -0
- package/dist/types/tools/memory.d.ts +67 -0
- package/dist/types/tools/output-meta.d.ts +151 -0
- package/dist/types/tools/read.d.ts +139 -0
- package/dist/types/tools/renderer.d.ts +98 -0
- package/dist/types/tools/report-tool-issue.d.ts +8 -0
- package/dist/types/tools/resolve.d.ts +47 -0
- package/dist/types/tools/streaming-output.d.ts +282 -0
- package/dist/types/tools/subprocess.d.ts +24 -0
- package/dist/types/tools/task-repair-args.d.ts +53 -0
- package/dist/types/tools/task-yield-assembly.d.ts +20 -0
- package/dist/types/tools/task.d.ts +425 -0
- package/dist/types/tools/terminal-output.d.ts +8 -0
- package/dist/types/tools/think.d.ts +13 -0
- package/dist/types/tools/todo.d.ts +118 -0
- package/dist/types/tools/tool-errors.d.ts +7 -0
- package/dist/types/tools/vibe.d.ts +120 -0
- package/dist/types/tools/web-search.d.ts +195 -0
- package/dist/types/tools/write.d.ts +76 -0
- package/dist/types/tools/xd-url.d.ts +13 -0
- package/dist/types/tools/xdev.d.ts +52 -0
- package/dist/types/tui.d.ts +18 -0
- package/dist/types/utils.d.ts +2 -0
- package/package.json +37 -3
- package/src/app-keybindings.ts +760 -0
- package/src/apps/autoresearch-dashboard.ts +500 -0
- package/src/apps/autoresearch-data.ts +64 -0
- package/src/apps/cleanse-board.ts +341 -0
- package/src/apps/cleanse-picker.ts +57 -0
- package/src/apps/debug/log-formatting.ts +53 -0
- package/src/apps/debug/log-viewer.ts +868 -0
- package/src/apps/debug/protocol-probe.ts +267 -0
- package/src/apps/debug/raw-sse-buffer.ts +449 -0
- package/src/apps/debug/raw-sse.ts +282 -0
- package/src/apps/debug/terminal-info.ts +115 -0
- package/src/apps/debug/viewer-frame.ts +174 -0
- package/src/apps/git/avatar.ts +52 -0
- package/src/apps/git/colors.ts +109 -0
- package/src/apps/git/diff-pane.ts +1512 -0
- package/src/apps/git/git-tui.ts +889 -0
- package/src/apps/git/sidebar.ts +1204 -0
- package/src/apps/git/state.ts +113 -0
- package/src/apps/if-bench-board.ts +324 -0
- package/src/apps/live-visualizer.ts +238 -0
- package/src/apps/ps-data.ts +116 -0
- package/src/apps/ps-top.ts +422 -0
- package/src/apps/session-picker.ts +95 -0
- package/src/apps/setup-model-picker.ts +21 -0
- package/src/apps/standalone-picker.ts +111 -0
- package/src/autocomplete.ts +9 -13
- package/src/chat/advisor-message.ts +175 -0
- package/src/chat/assistant-message.ts +1214 -0
- package/src/chat/background-tan-message.ts +35 -0
- package/src/chat/bash-execution.ts +394 -0
- package/src/chat/cache-invalidation-marker.ts +94 -0
- package/src/chat/chat-transcript-builder.ts +593 -0
- package/src/chat/collab-prompt-message.ts +34 -0
- package/src/chat/compaction-summary-message.ts +261 -0
- package/src/chat/custom-message.ts +23 -0
- package/src/chat/display-preferences.ts +24 -0
- package/src/chat/eval-execution.ts +172 -0
- package/src/chat/execution-shared.ts +113 -0
- package/src/chat/extension-types.ts +46 -0
- package/src/chat/hook-message.ts +20 -0
- package/src/chat/image-loading.ts +122 -0
- package/src/chat/late-diagnostics-message.ts +92 -0
- package/src/chat/messages.ts +305 -0
- package/src/chat/reaction.ts +65 -0
- package/src/chat/read-target.ts +7 -0
- package/src/chat/read-tool-group.ts +873 -0
- package/src/chat/served-model-marker.ts +91 -0
- package/src/chat/skill-message.ts +220 -0
- package/src/chat/skill-title-input.ts +41 -0
- package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
- package/src/chat/thinking-display.ts +312 -0
- package/src/chat/todo-reminder.ts +33 -0
- package/src/chat/tool-execution.ts +1395 -0
- package/src/chat/transcript-browser.ts +268 -0
- package/src/chat/transcript-entry.ts +96 -0
- package/src/chat/transcript-outline.ts +260 -0
- package/src/chat/transcript-render-helpers.ts +315 -0
- package/src/chat/ttsr-notification.ts +123 -0
- package/src/chat/user-message.ts +287 -0
- package/src/chrome/chat-block.ts +110 -0
- package/src/chrome/collab-qrcode.ts +74 -0
- package/src/chrome/context-thresholds.ts +85 -0
- package/src/chrome/countdown-timer.ts +74 -0
- package/src/chrome/diff.ts +266 -0
- package/src/chrome/dynamic-border.ts +36 -0
- package/src/chrome/error-block.ts +63 -0
- package/src/chrome/form-theme.ts +10 -0
- package/src/chrome/format.ts +66 -0
- package/src/chrome/index.ts +21 -0
- package/src/chrome/keybinding-hints.ts +55 -0
- package/src/chrome/live-board.ts +123 -0
- package/src/chrome/local-date.ts +20 -0
- package/src/chrome/message-divider.ts +51 -0
- package/src/chrome/message-frame.ts +164 -0
- package/src/chrome/message-notice.ts +103 -0
- package/src/chrome/overlay-box.ts +301 -0
- package/src/chrome/qrcode.ts +539 -0
- package/src/chrome/segment-track.ts +86 -0
- package/src/chrome/select-list-mouse-routing.ts +11 -0
- package/src/chrome/selector-helpers.ts +119 -0
- package/src/chrome/shared.ts +27 -0
- package/src/chrome/streaming-panel.ts +72 -0
- package/src/chrome/tool-activity.ts +44 -0
- package/src/chrome/transcript-container.ts +902 -0
- package/src/chrome/transcript-status.ts +27 -0
- package/src/chrome/visual-truncate.ts +70 -0
- package/src/components/disclosure.ts +235 -0
- package/src/components/editor.ts +10 -12
- package/src/components/form.ts +566 -0
- package/src/components/input.ts +6 -27
- package/src/components/key-value-list.ts +88 -0
- package/src/components/layout/geometry.ts +202 -0
- package/src/components/layout/row.ts +283 -0
- package/src/components/layout/split-pane.ts +349 -0
- package/src/components/layout/stack.ts +261 -0
- package/src/components/markdown.ts +16 -12
- package/src/components/menu-selection.ts +248 -0
- package/src/components/metric.ts +132 -0
- package/src/components/progress-bar.ts +140 -0
- package/src/components/scroll-view.ts +372 -70
- package/src/components/scroll-viewport.ts +154 -0
- package/src/components/section.ts +77 -0
- package/src/components/select-list.ts +238 -159
- package/src/components/settings-list.ts +103 -80
- package/src/components/table.ts +127 -0
- package/src/components/tree-view.ts +481 -0
- package/src/components/wizard-step.ts +229 -0
- package/src/deccara.ts +1 -3
- package/src/hotkeys-markdown.ts +100 -0
- package/src/index.ts +18 -0
- package/src/keybinding-matchers.ts +99 -0
- package/src/keys.ts +2 -2
- package/src/lang-from-path.ts +252 -0
- package/src/overlays/advisor-config.ts +761 -0
- package/src/overlays/agent-activity.ts +113 -0
- package/src/overlays/agent-hub-projection.ts +250 -0
- package/src/overlays/agent-hub-renderer.ts +281 -0
- package/src/overlays/agent-hub-types.ts +74 -0
- package/src/overlays/agent-hub.ts +1562 -0
- package/src/overlays/agent-transcript-viewer.ts +669 -0
- package/src/overlays/agents-hub.ts +1203 -0
- package/src/overlays/ask-dialog.ts +1202 -0
- package/src/overlays/bordered-loader.ts +41 -0
- package/src/overlays/btw-history-panel.ts +591 -0
- package/src/overlays/btw-history.ts +33 -0
- package/src/overlays/btw-panel.ts +167 -0
- package/src/overlays/cleanse-panel.ts +167 -0
- package/src/overlays/codex-reset-fireworks.ts +375 -0
- package/src/overlays/composer-shape-preview.ts +137 -0
- package/src/overlays/composer-shape-registry.ts +82 -0
- package/src/overlays/copy-selector.ts +618 -0
- package/src/overlays/copy-targets.ts +210 -0
- package/src/overlays/error-banner.ts +39 -0
- package/src/overlays/extensions/display-text.ts +39 -0
- package/src/overlays/extensions/extension-dashboard.ts +645 -0
- package/src/overlays/extensions/extension-list.ts +667 -0
- package/src/overlays/extensions/inspector-model.ts +484 -0
- package/src/overlays/extensions/inspector-panel.ts +669 -0
- package/src/overlays/extensions/live-tool-session.ts +67 -0
- package/src/overlays/extensions/mcp-runtime.ts +289 -0
- package/src/overlays/extensions/state-manager.ts +337 -0
- package/src/overlays/extensions/types.ts +208 -0
- package/src/overlays/history-search.ts +268 -0
- package/src/overlays/hook-editor.ts +272 -0
- package/src/overlays/hook-input.ts +84 -0
- package/src/overlays/hook-selector.ts +635 -0
- package/src/overlays/hub-frame.ts +262 -0
- package/src/overlays/login-dialog.ts +231 -0
- package/src/overlays/logout-account-selector.ts +115 -0
- package/src/overlays/mcp-add-wizard.ts +1436 -0
- package/src/overlays/model-browser.ts +1176 -0
- package/src/overlays/model-hub.ts +2279 -0
- package/src/overlays/model-picker.ts +285 -0
- package/src/overlays/model-selector.ts +107 -0
- package/src/overlays/move-overlay.ts +197 -0
- package/src/overlays/oauth-selector.ts +446 -0
- package/src/overlays/omfg-panel.ts +136 -0
- package/src/overlays/pause-screen.ts +198 -0
- package/src/overlays/plan-review-overlay.ts +1227 -0
- package/src/overlays/plan-save-overlay.ts +74 -0
- package/src/overlays/plan-toc.ts +139 -0
- package/src/overlays/plugin-selector.ts +97 -0
- package/src/overlays/plugin-settings.ts +839 -0
- package/src/overlays/queue-mode-selector.ts +55 -0
- package/src/overlays/reset-usage-selector.ts +170 -0
- package/src/overlays/rewind-selector.ts +499 -0
- package/src/overlays/running-subagent-badge.ts +19 -0
- package/src/overlays/session-account-selector.ts +68 -0
- package/src/overlays/session-info-overlay.ts +96 -0
- package/src/overlays/session-observer-registry.ts +289 -0
- package/src/overlays/session-selector.ts +1137 -0
- package/src/overlays/settings-defs.ts +315 -0
- package/src/overlays/settings-selector.ts +1415 -0
- package/src/overlays/show-images-selector.ts +44 -0
- package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
- package/src/overlays/snapcompact-shape-preview.ts +192 -0
- package/src/overlays/theme-selector.ts +62 -0
- package/src/overlays/thinking-selector.ts +51 -0
- package/src/overlays/tiny-title-download-progress.ts +102 -0
- package/src/overlays/tree-selector.ts +1121 -0
- package/src/overlays/usage-dashboard.ts +629 -0
- package/src/overlays/usage-display.ts +45 -0
- package/src/overlays/usage-row.ts +118 -0
- package/src/prompt/attachment-chips.ts +201 -0
- package/src/prompt/composer-attachments.ts +280 -0
- package/src/prompt/composer-cache.ts +304 -0
- package/src/prompt/composer.ts +934 -0
- package/src/prompt/custom-editor.ts +1392 -0
- package/src/prompt/data/emojis.json +1 -0
- package/src/prompt/editor-top-gap.ts +28 -0
- package/src/prompt/emoji-autocomplete.ts +285 -0
- package/src/prompt/github-ref-autocomplete.ts +75 -0
- package/src/prompt/gradient-highlight.ts +101 -0
- package/src/prompt/image-format.ts +28 -0
- package/src/prompt/image-references.ts +102 -0
- package/src/prompt/interactive-context-helpers.ts +126 -0
- package/src/prompt/internal-url-autocomplete.ts +155 -0
- package/src/prompt/macos-spelling.ts +456 -0
- package/src/prompt/magic-keyword-boundary.ts +23 -0
- package/src/prompt/magic-keywords.ts +42 -0
- package/src/prompt/markdown-prose.ts +245 -0
- package/src/prompt/model-mention-autocomplete.ts +94 -0
- package/src/prompt/model-mention-syntax.ts +41 -0
- package/src/prompt/orchestrate.ts +26 -0
- package/src/prompt/prompt-action-autocomplete.ts +337 -0
- package/src/prompt/queue-input.ts +132 -0
- package/src/prompt/skill-tokens.ts +36 -0
- package/src/prompt/tips.txt +27 -0
- package/src/prompt/tools-markdown.ts +29 -0
- package/src/prompt/ultrathink.ts +26 -0
- package/src/prompt/usage-amounts.ts +99 -0
- package/src/prompt/video.ts +47 -0
- package/src/prompt/welcome.ts +605 -0
- package/src/prompt/workflow.ts +26 -0
- package/src/render/code-cell.ts +244 -0
- package/src/render/file-list.ts +58 -0
- package/src/render/hyperlink.ts +192 -0
- package/src/render/index.ts +17 -0
- package/src/render/output-block.ts +267 -0
- package/src/render/output-pane.ts +299 -0
- package/src/render/render-utils.ts +1182 -0
- package/src/render/sixel.ts +69 -0
- package/src/render/status-line.ts +55 -0
- package/src/render/tool-card.ts +272 -0
- package/src/render/tree-list.ts +188 -0
- package/src/render/types.ts +19 -0
- package/src/render/utils.ts +109 -0
- package/src/render/width-aware-text.ts +60 -0
- package/src/setup/lazy.ts +17 -0
- package/src/setup/scenes/composer.ts +127 -0
- package/src/setup/scenes/glyph.ts +120 -0
- package/src/setup/scenes/model.ts +138 -0
- package/src/setup/scenes/outro.ts +24 -0
- package/src/setup/scenes/providers.ts +107 -0
- package/src/setup/scenes/sign-in.ts +373 -0
- package/src/setup/scenes/splash.ts +192 -0
- package/src/setup/scenes/theme.ts +343 -0
- package/src/setup/scenes/types.ts +111 -0
- package/src/setup/scenes/web-search.ts +165 -0
- package/src/setup/setup-version.ts +11 -0
- package/src/setup/startup-splash.ts +107 -0
- package/src/setup/wizard-overlay.ts +319 -0
- package/src/setup/wizard.ts +101 -0
- package/src/status-line/component.ts +3003 -0
- package/src/status-line/context-usage.ts +688 -0
- package/src/status-line/footer.ts +323 -0
- package/src/status-line/git-utils.ts +42 -0
- package/src/status-line/host.ts +97 -0
- package/src/status-line/index.ts +6 -0
- package/src/status-line/loop.ts +28 -0
- package/src/status-line/metrics.ts +94 -0
- package/src/status-line/presets.ts +107 -0
- package/src/status-line/schema.ts +57 -0
- package/src/status-line/segments.ts +934 -0
- package/src/status-line/separators.ts +55 -0
- package/src/status-line/types.ts +227 -0
- package/src/stdin-buffer.ts +4 -2
- package/src/theme/color.ts +95 -0
- package/src/theme/dark.json +95 -0
- package/src/theme/defaults/alabaster.json +93 -0
- package/src/theme/defaults/amethyst.json +96 -0
- package/src/theme/defaults/anthracite.json +93 -0
- package/src/theme/defaults/basalt.json +91 -0
- package/src/theme/defaults/birch.json +95 -0
- package/src/theme/defaults/dark-abyss.json +91 -0
- package/src/theme/defaults/dark-arctic.json +104 -0
- package/src/theme/defaults/dark-aurora.json +95 -0
- package/src/theme/defaults/dark-catppuccin.json +107 -0
- package/src/theme/defaults/dark-cavern.json +91 -0
- package/src/theme/defaults/dark-celestial.json +106 -0
- package/src/theme/defaults/dark-copper.json +95 -0
- package/src/theme/defaults/dark-cosmos.json +90 -0
- package/src/theme/defaults/dark-cyberpunk.json +102 -0
- package/src/theme/defaults/dark-dracula.json +98 -0
- package/src/theme/defaults/dark-eclipse.json +91 -0
- package/src/theme/defaults/dark-ember.json +95 -0
- package/src/theme/defaults/dark-equinox.json +90 -0
- package/src/theme/defaults/dark-forest.json +96 -0
- package/src/theme/defaults/dark-github.json +105 -0
- package/src/theme/defaults/dark-gruvbox.json +112 -0
- package/src/theme/defaults/dark-lavender.json +95 -0
- package/src/theme/defaults/dark-lunar.json +89 -0
- package/src/theme/defaults/dark-midnight.json +95 -0
- package/src/theme/defaults/dark-monochrome.json +94 -0
- package/src/theme/defaults/dark-monokai.json +98 -0
- package/src/theme/defaults/dark-nebula.json +90 -0
- package/src/theme/defaults/dark-nord.json +98 -0
- package/src/theme/defaults/dark-ocean.json +101 -0
- package/src/theme/defaults/dark-one.json +100 -0
- package/src/theme/defaults/dark-poimandres.json +115 -0
- package/src/theme/defaults/dark-rainforest.json +91 -0
- package/src/theme/defaults/dark-reef.json +91 -0
- package/src/theme/defaults/dark-retro.json +92 -0
- package/src/theme/defaults/dark-rose-pine.json +96 -0
- package/src/theme/defaults/dark-sakura.json +95 -0
- package/src/theme/defaults/dark-slate.json +95 -0
- package/src/theme/defaults/dark-solarized.json +97 -0
- package/src/theme/defaults/dark-solstice.json +90 -0
- package/src/theme/defaults/dark-starfall.json +91 -0
- package/src/theme/defaults/dark-sunset.json +99 -0
- package/src/theme/defaults/dark-swamp.json +90 -0
- package/src/theme/defaults/dark-synthwave.json +103 -0
- package/src/theme/defaults/dark-taiga.json +91 -0
- package/src/theme/defaults/dark-terminal.json +95 -0
- package/src/theme/defaults/dark-tokyo-night.json +101 -0
- package/src/theme/defaults/dark-tundra.json +91 -0
- package/src/theme/defaults/dark-twilight.json +91 -0
- package/src/theme/defaults/dark-volcanic.json +91 -0
- package/src/theme/defaults/graphite.json +92 -0
- package/src/theme/defaults/index.ts +201 -0
- package/src/theme/defaults/light-arctic.json +107 -0
- package/src/theme/defaults/light-aurora-day.json +91 -0
- package/src/theme/defaults/light-canyon.json +91 -0
- package/src/theme/defaults/light-catppuccin.json +106 -0
- package/src/theme/defaults/light-cirrus.json +90 -0
- package/src/theme/defaults/light-coral.json +95 -0
- package/src/theme/defaults/light-cyberpunk.json +96 -0
- package/src/theme/defaults/light-dawn.json +90 -0
- package/src/theme/defaults/light-dunes.json +91 -0
- package/src/theme/defaults/light-eucalyptus.json +95 -0
- package/src/theme/defaults/light-forest.json +100 -0
- package/src/theme/defaults/light-frost.json +95 -0
- package/src/theme/defaults/light-github.json +115 -0
- package/src/theme/defaults/light-glacier.json +91 -0
- package/src/theme/defaults/light-gruvbox.json +108 -0
- package/src/theme/defaults/light-haze.json +90 -0
- package/src/theme/defaults/light-honeycomb.json +95 -0
- package/src/theme/defaults/light-lagoon.json +91 -0
- package/src/theme/defaults/light-lavender.json +95 -0
- package/src/theme/defaults/light-meadow.json +91 -0
- package/src/theme/defaults/light-mint.json +95 -0
- package/src/theme/defaults/light-monochrome.json +101 -0
- package/src/theme/defaults/light-ocean.json +99 -0
- package/src/theme/defaults/light-one.json +99 -0
- package/src/theme/defaults/light-opal.json +91 -0
- package/src/theme/defaults/light-orchard.json +91 -0
- package/src/theme/defaults/light-paper.json +95 -0
- package/src/theme/defaults/light-poimandres.json +115 -0
- package/src/theme/defaults/light-prism.json +90 -0
- package/src/theme/defaults/light-retro.json +98 -0
- package/src/theme/defaults/light-sand.json +95 -0
- package/src/theme/defaults/light-savanna.json +91 -0
- package/src/theme/defaults/light-solarized.json +102 -0
- package/src/theme/defaults/light-soleil.json +90 -0
- package/src/theme/defaults/light-sunset.json +99 -0
- package/src/theme/defaults/light-synthwave.json +98 -0
- package/src/theme/defaults/light-tokyo-night.json +111 -0
- package/src/theme/defaults/light-wetland.json +91 -0
- package/src/theme/defaults/light-zenith.json +89 -0
- package/src/theme/defaults/limestone.json +94 -0
- package/src/theme/defaults/mahogany.json +97 -0
- package/src/theme/defaults/marble.json +93 -0
- package/src/theme/defaults/obsidian.json +91 -0
- package/src/theme/defaults/onyx.json +91 -0
- package/src/theme/defaults/pearl.json +93 -0
- package/src/theme/defaults/porcelain.json +91 -0
- package/src/theme/defaults/quartz.json +96 -0
- package/src/theme/defaults/sandstone.json +95 -0
- package/src/theme/defaults/titanium.json +90 -0
- package/src/theme/index.ts +5 -0
- package/src/theme/light.json +93 -0
- package/src/theme/loader.ts +200 -0
- package/src/theme/mermaid-cache.ts +92 -0
- package/src/theme/schema-validation.ts +119 -0
- package/src/theme/schema.ts +168 -0
- package/src/theme/session-color.ts +253 -0
- package/src/theme/shimmer.ts +307 -0
- package/src/theme/symbols.ts +1433 -0
- package/src/theme/theme-class.ts +787 -0
- package/src/theme/theme-schema.json +463 -0
- package/src/theme/theme.ts +810 -0
- package/src/theme/tui-adapters.ts +339 -0
- package/src/thinking.ts +380 -0
- package/src/tools/agent-tree.ts +128 -0
- package/src/tools/ask.ts +482 -0
- package/src/tools/ast-edit.ts +210 -0
- package/src/tools/ast-grep.ts +171 -0
- package/src/tools/autoresearch.ts +287 -0
- package/src/tools/bash-interactive.ts +295 -0
- package/src/tools/bash.ts +468 -0
- package/src/tools/conflict-detect.ts +77 -0
- package/src/tools/debug.ts +167 -0
- package/src/tools/default-renderer.ts +172 -0
- package/src/tools/edit.ts +1258 -0
- package/src/tools/eval-format/code-mode-declarations.ts +61 -0
- package/src/tools/eval-format/index.ts +16 -0
- package/src/tools/eval-format/javascript.ts +952 -0
- package/src/tools/eval-format/python.ts +544 -0
- package/src/tools/eval.ts +835 -0
- package/src/tools/fetch.ts +226 -0
- package/src/tools/gh-format.ts +18 -0
- package/src/tools/github.ts +686 -0
- package/src/tools/glob.ts +213 -0
- package/src/tools/goal.ts +153 -0
- package/src/tools/grep.ts +385 -0
- package/src/tools/grouped-file-output.ts +211 -0
- package/src/tools/hashline-format.ts +59 -0
- package/src/tools/hub.ts +1488 -0
- package/src/tools/index.ts +71 -0
- package/src/tools/json-tree.ts +388 -0
- package/src/tools/line-ranges.ts +98 -0
- package/src/tools/list-limit.ts +43 -0
- package/src/tools/lsp.ts +702 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/mcp.ts +309 -0
- package/src/tools/memory.ts +220 -0
- package/src/tools/output-meta.ts +367 -0
- package/src/tools/read.ts +628 -0
- package/src/tools/renderer.ts +107 -0
- package/src/tools/report-tool-issue.ts +13 -0
- package/src/tools/resolve.ts +139 -0
- package/src/tools/streaming-output.ts +1576 -0
- package/src/tools/subprocess.ts +39 -0
- package/src/tools/task-repair-args.ts +118 -0
- package/src/tools/task-yield-assembly.ts +147 -0
- package/src/tools/task.ts +2110 -0
- package/src/tools/terminal-output.ts +153 -0
- package/src/tools/think.ts +28 -0
- package/src/tools/todo.ts +580 -0
- package/src/tools/tool-errors.ts +15 -0
- package/src/tools/vibe.ts +420 -0
- package/src/tools/web-search.ts +409 -0
- package/src/tools/write.ts +511 -0
- package/src/tools/xd-url.ts +28 -0
- package/src/tools/xdev.ts +201 -0
- package/src/tui.ts +57 -4
- package/src/utils.ts +8 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact session-model picker (alt+p / `/switch`): a bottom-anchored
|
|
3
|
+
* floating overlay hosting just a {@link ModelBrowser} — no provider sidebar.
|
|
4
|
+
* Model entries switch the current session only; a search beginning with `@`
|
|
5
|
+
* exposes the configured ctrl+p quick roles.
|
|
6
|
+
*/
|
|
7
|
+
import type { Model } from "@oh-my-pi/pi-ai";
|
|
8
|
+
import { addKeyAliases, canonicalKeyId } from "../keybindings";
|
|
9
|
+
import { type KeyId, parseKey } from "../keys";
|
|
10
|
+
import type { Component, TUI } from "../tui";
|
|
11
|
+
import { type ThemeColor, theme } from "../theme/theme";
|
|
12
|
+
import { buildSessionModelScope, ModelBrowser, type ModelBrowserItem } from "./model-browser";
|
|
13
|
+
import type { ModelBrowserRegistry, ModelBrowserSource } from "./model-browser";
|
|
14
|
+
import type { ConfiguredThinkingLevel } from "../thinking";
|
|
15
|
+
import type { ScopedModelItem } from "./model-hub";
|
|
16
|
+
import { bottomBorder, row, topBorder } from "../chrome/overlay-box";
|
|
17
|
+
import { resolveSegmentPalette } from "../chrome/segment-track";
|
|
18
|
+
|
|
19
|
+
/** Configured role resolved to a concrete model. */
|
|
20
|
+
export interface ResolvedRoleModel {
|
|
21
|
+
role: string;
|
|
22
|
+
model: Model;
|
|
23
|
+
thinkingLevel?: ConfiguredThinkingLevel;
|
|
24
|
+
explicitThinkingLevel: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Catalog refresh capability used by the session picker. */
|
|
28
|
+
export interface ModelPickerRegistry extends ModelBrowserRegistry {
|
|
29
|
+
refresh(strategy: "offline"): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ModelPickerCallbacks {
|
|
33
|
+
/**
|
|
34
|
+
* A model was chosen for a session-only switch. `selector` is `provider/id`.
|
|
35
|
+
* `overContext` is true when the session transcript exceeds the model's
|
|
36
|
+
* context window — the host must compact before switching.
|
|
37
|
+
*/
|
|
38
|
+
onPick: (model: Model, selector: string, meta: { overContext: boolean }) => void;
|
|
39
|
+
/** A configured ctrl+p quick role was chosen. */
|
|
40
|
+
onPickRole?: (entry: ResolvedRoleModel) => void;
|
|
41
|
+
/**
|
|
42
|
+
* A model was chosen for Task subagents (task mode, toggled by pressing the
|
|
43
|
+
* picker shortcut again). Session-only: the host applies a runtime override.
|
|
44
|
+
*/
|
|
45
|
+
onPickTask?: (model: Model, selector: string) => void;
|
|
46
|
+
/** The picker was dismissed. */
|
|
47
|
+
onCancel: () => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ModelPickerOptions {
|
|
51
|
+
/** Session token count; models with smaller context windows are grayed and compact-first on pick. */
|
|
52
|
+
currentContextTokens?: number;
|
|
53
|
+
/** `provider/id` of the session's active model; highlighted and preselected. */
|
|
54
|
+
currentSelector?: string;
|
|
55
|
+
/** Resolved role models in the same order used by the ctrl+p quick-role cycle. */
|
|
56
|
+
quickRoles?: ReadonlyArray<ResolvedRoleModel>;
|
|
57
|
+
/** Complete ctrl+p order, including unavailable roles, to preserve segment colors. */
|
|
58
|
+
quickRoleOrder?: ReadonlyArray<string>;
|
|
59
|
+
/** Active quick role, highlighted when the search begins with `@`. */
|
|
60
|
+
currentQuickRole?: string;
|
|
61
|
+
/** Keys that toggle task-subagent mode while the picker is open; typically the alt+p binding. */
|
|
62
|
+
taskModeKeys?: readonly KeyId[];
|
|
63
|
+
/** Human-readable label for the toggle key, shown in footer hints (e.g. "alt+p"). */
|
|
64
|
+
taskModeKeyLabel?: string;
|
|
65
|
+
/** `provider/id` highlighted and preselected in task mode (current Task subagent model). */
|
|
66
|
+
taskSelector?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Fixed chrome rows: top border, status row, footer, bottom border. */
|
|
70
|
+
const CHROME_ROWS = 4;
|
|
71
|
+
/** Rows the browser renders around its list window (search + blank, blank + two detail rows). */
|
|
72
|
+
export const BROWSER_FRAME_ROWS = 5;
|
|
73
|
+
/** Minimum rows for the browser list window on short terminals. */
|
|
74
|
+
const MIN_VISIBLE = 5;
|
|
75
|
+
/** Fraction of the terminal height the floating overlay occupies. */
|
|
76
|
+
const HEIGHT_FRACTION = 0.4;
|
|
77
|
+
|
|
78
|
+
const STATUS_HINT = "Session-only switch — role models stay unchanged";
|
|
79
|
+
const QUICK_ROLE_STATUS_HINT = "Quick role switch — applies its model and thinking for this session";
|
|
80
|
+
const TASK_STATUS_HINT = "Task subagent switch — spawned task agents use this model (session-only)";
|
|
81
|
+
const FOOTER_HINT = "↑/↓ models · Enter use for this session · type to search · @ quick roles · Esc close";
|
|
82
|
+
const QUICK_ROLE_FOOTER_HINT = "↑/↓ roles · Enter apply role model · type to search · Esc close";
|
|
83
|
+
const TASK_FOOTER_HINT = "↑/↓ models · Enter use for Task subagents · type to search · Esc close";
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The alt+p picker component. Hosted as a non-fullscreen bottom-anchored
|
|
87
|
+
* overlay (`ui.showOverlay(..., { anchor: "bottom-center" })`); keyboard-only,
|
|
88
|
+
* since mouse tracking is reserved for fullscreen overlays.
|
|
89
|
+
*/
|
|
90
|
+
export class ModelPickerComponent implements Component {
|
|
91
|
+
#tui: TUI;
|
|
92
|
+
#settings: ModelBrowserSource;
|
|
93
|
+
#registry: ModelPickerRegistry;
|
|
94
|
+
#scopedModels: ReadonlyArray<ScopedModelItem>;
|
|
95
|
+
#browser: ModelBrowser;
|
|
96
|
+
#configError: string | undefined;
|
|
97
|
+
#currentSelector: string | undefined;
|
|
98
|
+
#currentQuickRoleSelector: string | undefined;
|
|
99
|
+
#modelItems: ModelBrowserItem[] = [];
|
|
100
|
+
#quickRoleItems: ModelBrowserItem[] = [];
|
|
101
|
+
#quickRoles = new Map<string, ResolvedRoleModel>();
|
|
102
|
+
#roleMode = false;
|
|
103
|
+
#taskMode = false;
|
|
104
|
+
#taskMatchKeys = new Set<string>();
|
|
105
|
+
#taskModeKeyLabel: string;
|
|
106
|
+
#taskSelector: string | undefined;
|
|
107
|
+
|
|
108
|
+
constructor(
|
|
109
|
+
tui: TUI,
|
|
110
|
+
settings: ModelBrowserSource,
|
|
111
|
+
registry: ModelPickerRegistry,
|
|
112
|
+
scopedModels: ReadonlyArray<ScopedModelItem>,
|
|
113
|
+
callbacks: ModelPickerCallbacks,
|
|
114
|
+
options: ModelPickerOptions = {},
|
|
115
|
+
) {
|
|
116
|
+
this.#tui = tui;
|
|
117
|
+
this.#settings = settings;
|
|
118
|
+
this.#registry = registry;
|
|
119
|
+
this.#scopedModels = scopedModels;
|
|
120
|
+
this.#currentSelector = options.currentSelector;
|
|
121
|
+
this.#currentQuickRoleSelector = options.currentQuickRole ? `@${options.currentQuickRole}` : undefined;
|
|
122
|
+
this.#taskSelector = options.taskSelector;
|
|
123
|
+
this.#taskModeKeyLabel = options.taskModeKeyLabel ?? "alt+p";
|
|
124
|
+
if (callbacks.onPickTask) {
|
|
125
|
+
for (const key of options.taskModeKeys ?? []) addKeyAliases(this.#taskMatchKeys, key);
|
|
126
|
+
}
|
|
127
|
+
this.#quickRoleItems = this.#buildQuickRoleItems(
|
|
128
|
+
options.quickRoles ?? [],
|
|
129
|
+
options.quickRoleOrder ?? options.quickRoles?.map(entry => entry.role) ?? [],
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
this.#browser = new ModelBrowser(settings, {
|
|
133
|
+
currentContextTokens: options.currentContextTokens,
|
|
134
|
+
markOverContext: true,
|
|
135
|
+
emptyText: () => (this.#roleMode ? " No quick roles in the Ctrl+P cycle" : undefined),
|
|
136
|
+
});
|
|
137
|
+
this.#browser.onActivate = item => {
|
|
138
|
+
const quickRole = this.#quickRoles.get(item.selector);
|
|
139
|
+
if (quickRole) {
|
|
140
|
+
callbacks.onPickRole?.(quickRole);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (this.#taskMode) {
|
|
144
|
+
callbacks.onPickTask?.(item.model, item.selector);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
callbacks.onPick(item.model, item.selector, { overContext: this.#browser.isOverContext(item) });
|
|
148
|
+
};
|
|
149
|
+
this.#browser.onCancel = () => callbacks.onCancel();
|
|
150
|
+
this.#browser.onQueryChange = query => this.#syncItemsForQuery(query);
|
|
151
|
+
|
|
152
|
+
// Hydrate synchronously from the current registry snapshot so the first
|
|
153
|
+
// Enter after opening acts on cached models instead of being dropped
|
|
154
|
+
// while the offline refresh promise is still pending.
|
|
155
|
+
this.#syncFromRegistryState();
|
|
156
|
+
if (options.currentSelector) {
|
|
157
|
+
this.#browser.selectSelector(options.currentSelector);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Reconcile with cached discovery state in the background. A --models
|
|
161
|
+
// scope is registry-independent, so the offline reload would only repeat
|
|
162
|
+
// the synchronous hydration above.
|
|
163
|
+
if (this.#scopedModels.length === 0) {
|
|
164
|
+
this.#registry
|
|
165
|
+
.refresh("offline")
|
|
166
|
+
.then(() => this.#syncFromRegistryState())
|
|
167
|
+
.catch(error => {
|
|
168
|
+
this.#configError = error instanceof Error ? error.message : String(error);
|
|
169
|
+
})
|
|
170
|
+
.finally(() => this.#tui.requestRender());
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
invalidate(): void {}
|
|
175
|
+
|
|
176
|
+
/** Rebuild model items and role chips from the registry's in-memory state. */
|
|
177
|
+
#syncFromRegistryState(): void {
|
|
178
|
+
const scope = buildSessionModelScope(
|
|
179
|
+
this.#settings,
|
|
180
|
+
this.#registry,
|
|
181
|
+
this.#scopedModels.map(s => s.model),
|
|
182
|
+
);
|
|
183
|
+
this.#configError = scope.error;
|
|
184
|
+
this.#modelItems = scope.items;
|
|
185
|
+
this.#browser.setRoles(scope.roles);
|
|
186
|
+
this.#browser.setMruOrder(scope.mruOrder);
|
|
187
|
+
this.#browser.setPerfStats(this.#settings.modelPerf);
|
|
188
|
+
this.#syncItemsForQuery(this.#browser.query, true);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Build virtual `@role` rows, colored by their ctrl+p segment position. */
|
|
192
|
+
#buildQuickRoleItems(
|
|
193
|
+
quickRoles: ReadonlyArray<ResolvedRoleModel>,
|
|
194
|
+
quickRoleOrder: ReadonlyArray<string>,
|
|
195
|
+
): ModelBrowserItem[] {
|
|
196
|
+
const order = quickRoleOrder.length > 0 ? quickRoleOrder : quickRoles.map(entry => entry.role);
|
|
197
|
+
const palette = resolveSegmentPalette(order.length);
|
|
198
|
+
return quickRoles.map((entry, index) => {
|
|
199
|
+
const selector = `@${entry.role}`;
|
|
200
|
+
this.#quickRoles.set(selector, entry);
|
|
201
|
+
const orderIndex = order.indexOf(entry.role);
|
|
202
|
+
return {
|
|
203
|
+
provider: "",
|
|
204
|
+
id: selector,
|
|
205
|
+
model: entry.model,
|
|
206
|
+
selector,
|
|
207
|
+
labelColor: palette[(orderIndex >= 0 ? orderIndex : index) % palette.length],
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Switch browser content only when a leading `@` changes the search mode. */
|
|
213
|
+
#syncItemsForQuery(query: string, refresh = false): void {
|
|
214
|
+
const roleMode = query.startsWith("@") && !this.#taskMode;
|
|
215
|
+
const modeChanged = roleMode !== this.#roleMode;
|
|
216
|
+
if (!modeChanged && !refresh) return;
|
|
217
|
+
|
|
218
|
+
this.#roleMode = roleMode;
|
|
219
|
+
this.#browser.setShowProvider(!roleMode);
|
|
220
|
+
this.#browser.setMarkOverContext(!roleMode && !this.#taskMode);
|
|
221
|
+
this.#browser.setPreserveQueryOrder(roleMode);
|
|
222
|
+
const currentSelector = roleMode
|
|
223
|
+
? this.#currentQuickRoleSelector
|
|
224
|
+
: this.#taskMode
|
|
225
|
+
? this.#taskSelector
|
|
226
|
+
: this.#currentSelector;
|
|
227
|
+
this.#browser.setCurrentSelector(currentSelector);
|
|
228
|
+
this.#browser.setItems(roleMode ? this.#quickRoleItems : this.#modelItems);
|
|
229
|
+
if (modeChanged && currentSelector) {
|
|
230
|
+
this.#browser.selectSelector(currentSelector);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
handleInput(data: string): void {
|
|
235
|
+
// Mouse tracking is off outside fullscreen overlays; drop any stray SGR
|
|
236
|
+
// reports instead of feeding them to the search input.
|
|
237
|
+
if (data.startsWith("\x1b[<")) return;
|
|
238
|
+
if (this.#taskMatchKeys.size > 0) {
|
|
239
|
+
const parsed = parseKey(data);
|
|
240
|
+
const canonical = parsed !== undefined ? canonicalKeyId(parsed) : undefined;
|
|
241
|
+
if (canonical !== undefined && this.#taskMatchKeys.has(canonical)) {
|
|
242
|
+
this.#toggleTaskMode();
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
this.#browser.handleInput(data);
|
|
247
|
+
}
|
|
248
|
+
/** Flip between session-model and Task-subagent targets, repointing the highlight. */
|
|
249
|
+
#toggleTaskMode(): void {
|
|
250
|
+
this.#taskMode = !this.#taskMode;
|
|
251
|
+
this.#syncItemsForQuery(this.#browser.query, true);
|
|
252
|
+
const target = this.#taskMode ? this.#taskSelector : this.#currentSelector;
|
|
253
|
+
if (target) this.#browser.selectSelector(target);
|
|
254
|
+
this.#tui.requestRender();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
render(width: number): string[] {
|
|
258
|
+
const termRows = Math.max(16, this.#tui.terminal?.rows || process.stdout.rows || 40);
|
|
259
|
+
const listBudget = Math.floor(termRows * HEIGHT_FRACTION) - CHROME_ROWS - BROWSER_FRAME_ROWS;
|
|
260
|
+
this.#browser.setMaxVisible(Math.max(MIN_VISIBLE, listBudget));
|
|
261
|
+
|
|
262
|
+
const inner = Math.max(1, width - 4);
|
|
263
|
+
const status = this.#configError
|
|
264
|
+
? theme.fg("error", ` ${this.#configError}`)
|
|
265
|
+
: this.#taskMode
|
|
266
|
+
? theme.fg("error", ` ${TASK_STATUS_HINT}`)
|
|
267
|
+
: theme.fg("muted", ` ${this.#roleMode ? QUICK_ROLE_STATUS_HINT : STATUS_HINT}`);
|
|
268
|
+
|
|
269
|
+
const borderColor: ThemeColor | undefined = this.#taskMode ? "error" : undefined;
|
|
270
|
+
let footer = this.#taskMode ? TASK_FOOTER_HINT : this.#roleMode ? QUICK_ROLE_FOOTER_HINT : FOOTER_HINT;
|
|
271
|
+
if (this.#taskMatchKeys.size > 0 && !this.#roleMode) {
|
|
272
|
+
footer += ` · ${this.#taskModeKeyLabel} ${this.#taskMode ? "session model" : "task model"}`;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const out: string[] = [];
|
|
276
|
+
out.push(topBorder(width, this.#taskMode ? "Switch Task Model" : "Switch Model", borderColor));
|
|
277
|
+
out.push(row(status, width, borderColor));
|
|
278
|
+
for (const line of this.#browser.render(inner)) {
|
|
279
|
+
out.push(row(line, width, borderColor));
|
|
280
|
+
}
|
|
281
|
+
out.push(row(theme.fg("dim", footer), width, borderColor));
|
|
282
|
+
out.push(bottomBorder(width, borderColor));
|
|
283
|
+
return out;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { ThinkingLevel } from "@oh-my-pi/pi-agent-core/thinking";
|
|
2
|
+
import { AUTO_THINKING, type ConfiguredThinkingLevel, parseThinkingLevel } from "../thinking";
|
|
3
|
+
|
|
4
|
+
/** Opt-in selectors that can otherwise be literal model-id suffixes. */
|
|
5
|
+
export interface ThinkingSuffixOptions {
|
|
6
|
+
allowMaxSuffix?: boolean;
|
|
7
|
+
allowAutoAlias?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Selector parsing options with authoritative literal-model lookup. */
|
|
11
|
+
export interface ModelStringParseOptions extends ThinkingSuffixOptions {
|
|
12
|
+
isLiteralModelId?: (provider: string, id: string) => boolean;
|
|
13
|
+
}
|
|
14
|
+
// Suffix recognition for the model-pattern parser: `:max` is a real thinking
|
|
15
|
+
// level and `:auto` maps to the auto sentinel. Both are gated behind flags
|
|
16
|
+
// (and the literal-id / exact-match guards on the callers) because real model
|
|
17
|
+
// ids end in `:max` (e.g. `glm-4.7:max`) — an ungated split would silently
|
|
18
|
+
// reinterpret them as a thinking suffix.
|
|
19
|
+
/** Recognize all configured effort selectors after literal-id matching. */
|
|
20
|
+
export const MAX_THINKING_SUFFIX_OPTIONS: ThinkingSuffixOptions = { allowMaxSuffix: true, allowAutoAlias: true };
|
|
21
|
+
|
|
22
|
+
/** Parse a suffix while preserving selectors not explicitly enabled. */
|
|
23
|
+
export function parseThinkingSuffix(
|
|
24
|
+
value: string,
|
|
25
|
+
options?: ThinkingSuffixOptions,
|
|
26
|
+
): ConfiguredThinkingLevel | undefined {
|
|
27
|
+
const level = parseThinkingLevel(value);
|
|
28
|
+
if (level === ThinkingLevel.Max) return options?.allowMaxSuffix === true ? level : undefined;
|
|
29
|
+
if (level !== undefined) return level;
|
|
30
|
+
if (options?.allowAutoAlias === true && value === AUTO_THINKING) return AUTO_THINKING;
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Split a trailing `:<level>` thinking selector off a model pattern.
|
|
36
|
+
*
|
|
37
|
+
* `level` is set when the suffix parses as a concrete thinking level (or, when
|
|
38
|
+
* the caller opts in via `allowMaxSuffix`/`allowAutoAlias`, the guarded `:max`
|
|
39
|
+
* level / `:auto` sentinel); `base` then has the suffix stripped. Otherwise
|
|
40
|
+
* `base` is the input.
|
|
41
|
+
* `minColonIndex` requires the colon to appear strictly after that index —
|
|
42
|
+
* role-alias callers pass the matched alias prefix length.
|
|
43
|
+
*/
|
|
44
|
+
export function splitThinkingSuffix(
|
|
45
|
+
pattern: string,
|
|
46
|
+
minColonIndex = -1,
|
|
47
|
+
options?: ThinkingSuffixOptions,
|
|
48
|
+
): { base: string; level?: ConfiguredThinkingLevel } {
|
|
49
|
+
const colonIdx = pattern.lastIndexOf(":");
|
|
50
|
+
if (colonIdx <= minColonIndex) return { base: pattern };
|
|
51
|
+
const level = parseThinkingSuffix(pattern.slice(colonIdx + 1), options);
|
|
52
|
+
return level ? { base: pattern.slice(0, colonIdx), level } : { base: pattern };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Parse a model string in "provider/modelId" format.
|
|
57
|
+
* Returns undefined if the format is invalid.
|
|
58
|
+
*/
|
|
59
|
+
export function parseModelString(
|
|
60
|
+
modelStr: string,
|
|
61
|
+
options?: ModelStringParseOptions,
|
|
62
|
+
): { provider: string; id: string; thinkingLevel?: ConfiguredThinkingLevel } | undefined {
|
|
63
|
+
const slashIdx = modelStr.indexOf("/");
|
|
64
|
+
if (slashIdx <= 0) return undefined;
|
|
65
|
+
const id = modelStr.slice(slashIdx + 1);
|
|
66
|
+
const provider = modelStr.slice(0, slashIdx);
|
|
67
|
+
// Strip strict thinking level suffixes first (e.g. "claude-sonnet-4-6:high" -> id "claude-sonnet-4-6", thinkingLevel "high").
|
|
68
|
+
const strict = splitThinkingSuffix(id);
|
|
69
|
+
if (strict.level) return { provider, id: strict.base, thinkingLevel: strict.level };
|
|
70
|
+
// `max` is a real thinking level, but real model IDs can also end in
|
|
71
|
+
// `:max`. Context-aware callers pass a literal lookup so those models win.
|
|
72
|
+
const maxAlias = splitThinkingSuffix(id, -1, options);
|
|
73
|
+
if (maxAlias.level) {
|
|
74
|
+
return options?.isLiteralModelId?.(provider, id) === true
|
|
75
|
+
? { provider, id }
|
|
76
|
+
: { provider, id: maxAlias.base, thinkingLevel: maxAlias.level };
|
|
77
|
+
}
|
|
78
|
+
return { provider, id };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function formatModelSelectorValue(selector: string, thinkingLevel: ConfiguredThinkingLevel | undefined): string {
|
|
82
|
+
return thinkingLevel && thinkingLevel !== ThinkingLevel.Inherit ? `${selector}:${thinkingLevel}` : selector;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Bare slug (`cerebras`) or tiered/regional slug (`google-ai-studio/priority`, `google-vertex/global/flex`). */
|
|
86
|
+
const UPSTREAM_ROUTING_SLUG = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\/[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*$/i;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Split a trailing `@<upstream>` provider-routing selector off a model pattern.
|
|
90
|
+
*
|
|
91
|
+
* `openrouter/z-ai/glm-4.7@cerebras` -> base `openrouter/z-ai/glm-4.7`, upstream
|
|
92
|
+
* `cerebras`. Tiered upstreams keep their path (`...@google-ai-studio/priority`).
|
|
93
|
+
* A `:thinking` suffix after the slug is kept on the base
|
|
94
|
+
* (`...@cerebras:high` -> base `...:high`). Returns undefined when there is no
|
|
95
|
+
* `@` or the suffix is not a bare provider slug, so model ids that legitimately
|
|
96
|
+
* contain `@` (`claude-opus-4-8@default`, `workers-ai/@cf/...`) are never split.
|
|
97
|
+
*/
|
|
98
|
+
export function splitUpstreamRouting(pattern: string): { base: string; upstream: string } | undefined {
|
|
99
|
+
const at = pattern.lastIndexOf("@");
|
|
100
|
+
if (at <= 0) return undefined;
|
|
101
|
+
const rest = pattern.slice(at + 1);
|
|
102
|
+
const colon = rest.indexOf(":");
|
|
103
|
+
const upstream = colon === -1 ? rest : rest.slice(0, colon);
|
|
104
|
+
if (!UPSTREAM_ROUTING_SLUG.test(upstream)) return undefined;
|
|
105
|
+
const trailing = colon === -1 ? "" : rest.slice(colon);
|
|
106
|
+
return { base: pattern.slice(0, at) + trailing, upstream };
|
|
107
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/move` overlay: a path input with live directory autocomplete.
|
|
3
|
+
*
|
|
4
|
+
* Rendered as a centered modal via `showHookCustom(..., { overlay: true })`.
|
|
5
|
+
* The user types a path, Tab autocompletes the highlighted directory, and Enter
|
|
6
|
+
* confirms — yielding the resolved directory string (or `undefined` on cancel).
|
|
7
|
+
*/
|
|
8
|
+
import { type Component, type Focusable, Key, matchesKey } from "../index";
|
|
9
|
+
import { theme } from "../theme/theme";
|
|
10
|
+
import { matchesSelectCancel, matchesSelectDown, matchesSelectUp } from "../keybinding-matchers";
|
|
11
|
+
import { formTheme } from "../chrome/form-theme";
|
|
12
|
+
import { bottomBorder, row, topBorder } from "../chrome/overlay-box";
|
|
13
|
+
import { TextFormField } from "../components/form";
|
|
14
|
+
|
|
15
|
+
export interface MoveOverlayResult {
|
|
16
|
+
directory: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Directory suggestion displayed by the move dialog. */
|
|
20
|
+
export interface MoveDirectoryEntry {
|
|
21
|
+
/** Full absolute path. */
|
|
22
|
+
value: string;
|
|
23
|
+
/** Display label (basename + trailing slash). */
|
|
24
|
+
label: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Directory autocomplete supplied by the host. */
|
|
28
|
+
export interface MoveDirectorySource {
|
|
29
|
+
search(prefix: string, cwd: string, max: number): MoveDirectoryEntry[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const MAX_RESULTS = 15;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Overlay component for `/move`: a single-line path input with a live-filtered
|
|
36
|
+
* list of matching directories. Tab accepts the highlighted suggestion; Enter
|
|
37
|
+
* confirms the current input (or the highlighted suggestion if the input is
|
|
38
|
+
* empty); Escape cancels.
|
|
39
|
+
*/
|
|
40
|
+
export class MoveOverlay implements Component, Focusable {
|
|
41
|
+
#field: TextFormField;
|
|
42
|
+
#focused = false;
|
|
43
|
+
#selectedIndex = 0;
|
|
44
|
+
#results: MoveDirectoryEntry[] = [];
|
|
45
|
+
#cwd: string;
|
|
46
|
+
#source: MoveDirectorySource;
|
|
47
|
+
#done: (result: MoveOverlayResult | undefined) => void;
|
|
48
|
+
#revision = 0;
|
|
49
|
+
#renderMemo:
|
|
50
|
+
| { width: number; fieldLines: readonly string[]; revision: number; lines: readonly string[] }
|
|
51
|
+
| undefined;
|
|
52
|
+
|
|
53
|
+
constructor(cwd: string, done: (result: MoveOverlayResult | undefined) => void, source: MoveDirectorySource) {
|
|
54
|
+
this.#cwd = cwd;
|
|
55
|
+
this.#source = source;
|
|
56
|
+
this.#done = done;
|
|
57
|
+
this.#field = new TextFormField({
|
|
58
|
+
theme: formTheme,
|
|
59
|
+
prompt: theme.fg("dim", "Path: "),
|
|
60
|
+
empty: "submit",
|
|
61
|
+
spaceBeforeControl: false,
|
|
62
|
+
spaceAfterControl: false,
|
|
63
|
+
onSubmit: () => this.#confirm(),
|
|
64
|
+
onCancel: () => this.#done(undefined),
|
|
65
|
+
});
|
|
66
|
+
this.#field.focused = this.#focused;
|
|
67
|
+
this.#updateResults();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get focused(): boolean {
|
|
71
|
+
return this.#focused;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
set focused(value: boolean) {
|
|
75
|
+
this.#focused = value;
|
|
76
|
+
this.#field.focused = value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
setUseTerminalCursor(useTerminalCursor: boolean): void {
|
|
80
|
+
this.#field.setUseTerminalCursor(useTerminalCursor);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
pasteText(text: string): void {
|
|
84
|
+
this.#field.pasteText(text);
|
|
85
|
+
this.#selectedIndex = 0;
|
|
86
|
+
this.#updateResults();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
handleInput(data: string): void {
|
|
90
|
+
if (matchesSelectCancel(data) || matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl("c"))) {
|
|
91
|
+
this.#done(undefined);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (matchesKey(data, Key.enter) || matchesKey(data, Key.return)) {
|
|
95
|
+
this.#field.submit();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (matchesSelectUp(data) || matchesKey(data, Key.up)) {
|
|
99
|
+
if (this.#results.length > 0) {
|
|
100
|
+
const next = Math.max(0, this.#selectedIndex - 1);
|
|
101
|
+
if (next !== this.#selectedIndex) {
|
|
102
|
+
this.#selectedIndex = next;
|
|
103
|
+
this.#revision++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (matchesSelectDown(data) || matchesKey(data, Key.down)) {
|
|
109
|
+
if (this.#results.length > 0) {
|
|
110
|
+
const next = Math.min(this.#results.length - 1, this.#selectedIndex + 1);
|
|
111
|
+
if (next !== this.#selectedIndex) {
|
|
112
|
+
this.#selectedIndex = next;
|
|
113
|
+
this.#revision++;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (matchesKey(data, Key.tab)) {
|
|
119
|
+
const selected = this.#results[this.#selectedIndex];
|
|
120
|
+
if (selected) {
|
|
121
|
+
this.#field.setValue(selected.value);
|
|
122
|
+
this.#selectedIndex = 0;
|
|
123
|
+
this.#updateResults();
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const before = this.#field.getValue();
|
|
128
|
+
this.#field.handleInput(data);
|
|
129
|
+
if (this.#field.getValue() !== before) {
|
|
130
|
+
this.#selectedIndex = 0;
|
|
131
|
+
this.#updateResults();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
render(width: number): readonly string[] {
|
|
136
|
+
const w = width;
|
|
137
|
+
const innerWidth = Math.max(1, w - 4);
|
|
138
|
+
const fieldLines = this.#field.render(innerWidth);
|
|
139
|
+
const memo = this.#renderMemo;
|
|
140
|
+
if (memo?.width === w && memo.fieldLines === fieldLines && memo.revision === this.#revision) {
|
|
141
|
+
return memo.lines;
|
|
142
|
+
}
|
|
143
|
+
const lines: string[] = [];
|
|
144
|
+
|
|
145
|
+
lines.push(topBorder(w, "Move to directory"));
|
|
146
|
+
for (const fieldLine of fieldLines) {
|
|
147
|
+
lines.push(row(fieldLine, w));
|
|
148
|
+
}
|
|
149
|
+
lines.push(row("", w));
|
|
150
|
+
|
|
151
|
+
if (this.#results.length === 0 && this.#field.getValue().length > 0) {
|
|
152
|
+
lines.push(row(theme.fg("dim", "No matching directories"), w));
|
|
153
|
+
} else {
|
|
154
|
+
for (let i = 0; i < Math.min(this.#results.length, MAX_RESULTS); i++) {
|
|
155
|
+
const item = this.#results[i]!;
|
|
156
|
+
const selected = i === this.#selectedIndex;
|
|
157
|
+
const marker = selected ? theme.fg("accent", "▶ ") : " ";
|
|
158
|
+
const label = selected ? theme.fg("accent", item.label) : theme.fg("text", item.label);
|
|
159
|
+
lines.push(row(`${marker}${label}`, w));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
lines.push(row("", w));
|
|
164
|
+
lines.push(row(theme.fg("dim", "Type to filter · ↑↓ navigate · Tab accept · Enter confirm · Esc cancel"), w));
|
|
165
|
+
lines.push(bottomBorder(w));
|
|
166
|
+
this.#renderMemo = { width: w, fieldLines, revision: this.#revision, lines };
|
|
167
|
+
return lines;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
invalidate(): void {
|
|
171
|
+
this.#field.input.prompt = theme.fg("dim", "Path: ");
|
|
172
|
+
this.#field.invalidate();
|
|
173
|
+
this.#revision++;
|
|
174
|
+
this.#renderMemo = undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
#updateResults(): void {
|
|
178
|
+
this.#results = this.#source.search(this.#field.getValue(), this.#cwd, MAX_RESULTS + 5);
|
|
179
|
+
this.#revision++;
|
|
180
|
+
if (this.#selectedIndex >= this.#results.length) {
|
|
181
|
+
this.#selectedIndex = Math.max(0, this.#results.length - 1);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
#confirm(): void {
|
|
186
|
+
const selected = this.#results[this.#selectedIndex];
|
|
187
|
+
if (selected) {
|
|
188
|
+
this.#done({ directory: selected.value });
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (this.#field.getValue().trim().length > 0) {
|
|
192
|
+
this.#done({ directory: this.#field.getValue().trim() });
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
this.#done(undefined);
|
|
196
|
+
}
|
|
197
|
+
}
|