@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
|
@@ -2,12 +2,21 @@ import * as url from "node:url";
|
|
|
2
2
|
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import { BracketedPasteHandler } from "../bracketed-paste";
|
|
4
4
|
import { BRACKETED_PASTE_END, BRACKETED_PASTE_START } from "../stdin-buffer";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
Editor,
|
|
7
|
+
type EditorTextDecorationContext,
|
|
8
|
+
type EditorTheme,
|
|
9
|
+
type NativeEditorLayout,
|
|
10
|
+
} from "../components/editor";
|
|
6
11
|
import { addKeyAliases, canonicalKeyId, getKeybindings } from "../keybindings";
|
|
7
12
|
import { type KeyId, parseKey, parseKittySequence } from "../keys";
|
|
8
13
|
import { SpaceHoldGesture } from "../space-hold";
|
|
9
|
-
import { TUI } from "../tui";
|
|
14
|
+
import { type Component, TUI } from "../tui";
|
|
10
15
|
import type { AppKeybinding } from "../app-keybindings";
|
|
16
|
+
import { formatKeyHint } from "../key-hint-format";
|
|
17
|
+
import { compact, keyed, node, row, span } from "../native/describe";
|
|
18
|
+
import type { DescribeContext, NativeNode, NativeUiEvent } from "../native/node";
|
|
19
|
+
import type { ComposerFacts, ComposerFactsSource } from "../status-line/types";
|
|
11
20
|
import { allowsModelMentions, allowsSkillTokens, SKILL_TOKEN_RE } from "./skill-tokens";
|
|
12
21
|
import { expandModelMentionTags, MODEL_MENTION_RE, modelMentionToken } from "./model-mention-syntax";
|
|
13
22
|
import { imageAttachmentSource } from "./image-source";
|
|
@@ -30,11 +39,42 @@ import {
|
|
|
30
39
|
skillToken,
|
|
31
40
|
} from "./composer-attachments";
|
|
32
41
|
import { type MacOSSpellingFeatures, MacOSSpellingProvider } from "./macos-spelling";
|
|
33
|
-
import { hasMagicKeyword, highlightMagicKeywords } from "./magic-keywords";
|
|
42
|
+
import { hasMagicKeyword, highlightMagicKeywords, magicKeywordRanges } from "./magic-keywords";
|
|
43
|
+
import type { TspEditorDecoration } from "@oh-my-pi/pi-wire";
|
|
44
|
+
import { isNativeRendering } from "../native/state";
|
|
34
45
|
import { isQueuedMessageList, parseQueueShorthand, QUEUE_LIST_MARKER_RE } from "./queue-input";
|
|
35
46
|
import { type WordCompletionMethod, WordCompletionProvider } from "./word-completion";
|
|
36
47
|
import { fgOrPlain, theme } from "../theme/theme";
|
|
37
48
|
|
|
49
|
+
/** A shell-mode draft's sigil (`!`, `!!`, `$`, `$$`) with its surrounding blanks; the mode chip stands in for it natively. */
|
|
50
|
+
const SHELL_SIGIL_RE = /^\s*(?:!!?|\$\$?)[ \t]?/;
|
|
51
|
+
|
|
52
|
+
/** The composer's TSP placeholder; the rotating ANSI hints (thinking effort, …) move into control tooltips. */
|
|
53
|
+
const NATIVE_COMPOSER_PLACEHOLDER = "Ask omp — / commands · @ files · ! bash";
|
|
54
|
+
|
|
55
|
+
/** Live composer state the TSP layout shows; the interactive host wires {@link CustomEditor.composerState}. */
|
|
56
|
+
export interface ComposerNativeState {
|
|
57
|
+
/** The draft runs as a shell command (`!`, `!!`) or Python (`$`, `$$`); `excluded` keeps it from the model. */
|
|
58
|
+
readonly shell?: { readonly kind: "bash" | "python"; readonly excluded: boolean };
|
|
59
|
+
/** Thinking effort word (`high`, `off`, `auto`); undefined when the model has no thinking. */
|
|
60
|
+
readonly thinking?: string;
|
|
61
|
+
/** A turn is running: the send keycap becomes a Stop button. */
|
|
62
|
+
readonly running: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const IDLE_COMPOSER: ComposerNativeState = { running: false };
|
|
66
|
+
|
|
67
|
+
/** Filled steps (of four) of the effort chip's meter per thinking level; `auto` before it resolves has none known. */
|
|
68
|
+
const EFFORT_STEPS: Partial<Record<string, number>> = {
|
|
69
|
+
off: 0,
|
|
70
|
+
minimal: 1,
|
|
71
|
+
low: 1,
|
|
72
|
+
medium: 2,
|
|
73
|
+
high: 3,
|
|
74
|
+
xhigh: 4,
|
|
75
|
+
max: 4,
|
|
76
|
+
};
|
|
77
|
+
|
|
38
78
|
/** Independently switchable prose-assistance features of the composer. */
|
|
39
79
|
export interface SpellingFeatures extends MacOSSpellingFeatures {
|
|
40
80
|
/** Word-completion engine; `off` disables ghost text. */
|
|
@@ -838,6 +878,67 @@ export class CustomEditor extends Editor {
|
|
|
838
878
|
);
|
|
839
879
|
};
|
|
840
880
|
|
|
881
|
+
/**
|
|
882
|
+
* TSP decorations: magic keywords shimmer (terminal-clocked) in the accent
|
|
883
|
+
* color, chips and markers take their token colors, misspellings are marked,
|
|
884
|
+
* and queue-composer markers are dimmed/accented, all as ranges over the raw
|
|
885
|
+
* buffer instead of painted text. A shell-mode draft is code: only its sigil
|
|
886
|
+
* is decorated, hidden behind the mode chip.
|
|
887
|
+
*/
|
|
888
|
+
override describeDecorations = (lines: readonly string[]): readonly TspEditorDecoration[] => {
|
|
889
|
+
const text = lines.join("\n");
|
|
890
|
+
if (this.composerState().shell) {
|
|
891
|
+
const sigil = SHELL_SIGIL_RE.exec(text)?.[0].length ?? 0;
|
|
892
|
+
return sigil > 0 ? [{ from: 0, to: sigil, s: "hide" }] : [];
|
|
893
|
+
}
|
|
894
|
+
this.#syncComposerTokenPattern();
|
|
895
|
+
const decor: TspEditorDecoration[] = [];
|
|
896
|
+
let offset = 0;
|
|
897
|
+
const mark = (length: number, s: string): string => {
|
|
898
|
+
decor.push({ from: offset, to: offset + length, s });
|
|
899
|
+
offset += length;
|
|
900
|
+
return "";
|
|
901
|
+
};
|
|
902
|
+
renderPlaceholders(
|
|
903
|
+
text,
|
|
904
|
+
{
|
|
905
|
+
renderText: value => {
|
|
906
|
+
offset += value.length;
|
|
907
|
+
return "";
|
|
908
|
+
},
|
|
909
|
+
renderSkill: label => mark(label.length, "customMessageLabel strong"),
|
|
910
|
+
renderMention: label => mark(label.length, "statusLineModel strong"),
|
|
911
|
+
renderReference: value => mark(value.length, "accent strong"),
|
|
912
|
+
},
|
|
913
|
+
this.atomicTokenPattern,
|
|
914
|
+
);
|
|
915
|
+
|
|
916
|
+
const fx = this.#shimmerEnabled() ? "shimmer" : undefined;
|
|
917
|
+
for (const range of magicKeywordRanges(text)) decor.push({ ...range, s: "accent", fx });
|
|
918
|
+
|
|
919
|
+
const queueBody = parseQueueShorthand(text);
|
|
920
|
+
const queueList = queueBody !== undefined && isQueuedMessageList(queueBody);
|
|
921
|
+
let lineStart = 0;
|
|
922
|
+
for (let line = 0; line < lines.length; line++) {
|
|
923
|
+
const value = lines[line] ?? "";
|
|
924
|
+
if (queueBody !== undefined && (value.startsWith("->") || value.startsWith("=>"))) {
|
|
925
|
+
decor.push({ from: lineStart, to: lineStart + 2, s: "dim" });
|
|
926
|
+
}
|
|
927
|
+
if (queueList) {
|
|
928
|
+
const marker = QUEUE_LIST_MARKER_RE.exec(value);
|
|
929
|
+
if (marker) {
|
|
930
|
+
const indent = marker[1]?.length ?? 0;
|
|
931
|
+
decor.push({ from: lineStart + indent, to: lineStart + marker[0].length, s: "accent" });
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
for (const typo of this.#spelling.typoRanges(value, { editorText: text, lines, line, startCol: 0 })) {
|
|
935
|
+
decor.push({ from: lineStart + typo.start, to: lineStart + typo.start + typo.length, s: "mark" });
|
|
936
|
+
}
|
|
937
|
+
lineStart += value.length + 1;
|
|
938
|
+
}
|
|
939
|
+
return decor.sort((a, b) => a.from - b.from);
|
|
940
|
+
};
|
|
941
|
+
|
|
841
942
|
/** Optional test override for the magic-keyword shimmer gate. */
|
|
842
943
|
magicKeywordsEnabledOverride: boolean | undefined;
|
|
843
944
|
|
|
@@ -877,13 +978,210 @@ export class CustomEditor extends Editor {
|
|
|
877
978
|
* decides whether to schedule another, so the chain stops by itself when
|
|
878
979
|
* `focused` flips off or the keyword leaves the buffer. */
|
|
879
980
|
#scheduleShimmerFrame(): void {
|
|
880
|
-
|
|
981
|
+
// A TSP terminal animates the keyword shimmer from `describeDecorations`.
|
|
982
|
+
if (this.#shimmerTimer || !this.#requestShimmerRepaint || isNativeRendering()) return;
|
|
881
983
|
this.#shimmerTimer = setTimeout(() => {
|
|
882
984
|
this.#shimmerTimer = undefined;
|
|
883
985
|
this.#requestShimmerRepaint?.();
|
|
884
986
|
}, CustomEditor.SHIMMER_FRAME_MS);
|
|
885
987
|
this.#shimmerTimer.unref?.();
|
|
886
988
|
}
|
|
989
|
+
override nativePlaceholder: string | undefined = NATIVE_COMPOSER_PLACEHOLDER;
|
|
990
|
+
/** A shell-mode draft highlights as its language. */
|
|
991
|
+
override describeLanguage = (): string | undefined => this.composerState().shell?.kind;
|
|
992
|
+
/** Host-owned live state for the TSP composer (shell mode, effort chip, send/stop). */
|
|
993
|
+
composerState: () => ComposerNativeState = () => IDLE_COMPOSER;
|
|
994
|
+
/** The attachment band, described inside the composer on a TSP terminal (ANSI renders it above). */
|
|
995
|
+
attachmentChips: Component | undefined;
|
|
996
|
+
/** The status line's facts the TSP composer carries (context, model, usage, the other segments). */
|
|
997
|
+
composerFacts: ComposerFactsSource | undefined;
|
|
998
|
+
#nativeComposer:
|
|
999
|
+
| {
|
|
1000
|
+
key: string;
|
|
1001
|
+
facts: ComposerFacts | undefined;
|
|
1002
|
+
chips: Component | undefined;
|
|
1003
|
+
input: NativeNode;
|
|
1004
|
+
mode: NativeNode | undefined;
|
|
1005
|
+
bar: NativeNode;
|
|
1006
|
+
layout: NativeEditorLayout;
|
|
1007
|
+
}
|
|
1008
|
+
| undefined;
|
|
1009
|
+
|
|
1010
|
+
/**
|
|
1011
|
+
* The TSP composer: role `omp.editor[.bash|.python]` (tone `pending` while
|
|
1012
|
+
* a turn runs) over the context hairline, the attachment chips, a `line`
|
|
1013
|
+
* row of the shell-mode chip and the input, and the `bar`: model chip,
|
|
1014
|
+
* effort chip, the other status facts, usage, then send (Stop while a turn
|
|
1015
|
+
* runs). Clicks come back as `status.model`, `thinking.cycle`, `submit`
|
|
1016
|
+
* and `interrupt` actions.
|
|
1017
|
+
*/
|
|
1018
|
+
override describeLayout = (input: NativeNode, _cx: DescribeContext): NativeEditorLayout => {
|
|
1019
|
+
const state = this.composerState();
|
|
1020
|
+
const shell = state.shell;
|
|
1021
|
+
const facts = this.composerFacts?.describeComposerFacts();
|
|
1022
|
+
const thinkingKey = this.#actionKeys.get("app.thinking.cycle")?.[0];
|
|
1023
|
+
const modelKey = this.#actionKeys.get("app.model.selectTemporary")?.[0];
|
|
1024
|
+
const interruptKey = this.#actionKeys.get("app.interrupt")?.[0] ?? "escape";
|
|
1025
|
+
const key = [
|
|
1026
|
+
shell?.kind,
|
|
1027
|
+
shell?.excluded,
|
|
1028
|
+
state.thinking,
|
|
1029
|
+
state.running,
|
|
1030
|
+
thinkingKey,
|
|
1031
|
+
modelKey,
|
|
1032
|
+
interruptKey,
|
|
1033
|
+
].join("\0");
|
|
1034
|
+
const chips = this.attachmentChips;
|
|
1035
|
+
const memo = this.#nativeComposer;
|
|
1036
|
+
if (memo && memo.key === key && memo.facts === facts && memo.input === input && memo.chips === chips) {
|
|
1037
|
+
return memo.layout;
|
|
1038
|
+
}
|
|
1039
|
+
const { mode, bar } =
|
|
1040
|
+
memo?.key === key && memo.facts === facts
|
|
1041
|
+
? memo
|
|
1042
|
+
: this.#describeComposerControls(state, facts, thinkingKey, modelKey, interruptKey);
|
|
1043
|
+
const line = keyed(row(compact([mode, input]), { role: "omp.composer.line", align: "start", gap: "sm" }), "line");
|
|
1044
|
+
const layout: NativeEditorLayout = {
|
|
1045
|
+
role: shell ? `omp.editor.${shell.kind}` : "omp.editor",
|
|
1046
|
+
tone: state.running ? "pending" : undefined,
|
|
1047
|
+
children: compact([facts?.context, chips, line, bar]),
|
|
1048
|
+
caret: "line/input",
|
|
1049
|
+
};
|
|
1050
|
+
this.#nativeComposer = { key, facts, chips, input, mode, bar, layout };
|
|
1051
|
+
return layout;
|
|
1052
|
+
};
|
|
1053
|
+
|
|
1054
|
+
/** The shell-mode chip before the input, and the bar under it. */
|
|
1055
|
+
#describeComposerControls(
|
|
1056
|
+
state: ComposerNativeState,
|
|
1057
|
+
facts: ComposerFacts | undefined,
|
|
1058
|
+
thinkingKey: KeyId | undefined,
|
|
1059
|
+
modelKey: KeyId | undefined,
|
|
1060
|
+
interruptKey: KeyId,
|
|
1061
|
+
): { mode: NativeNode | undefined; bar: NativeNode } {
|
|
1062
|
+
const shell = state.shell;
|
|
1063
|
+
const model =
|
|
1064
|
+
facts &&
|
|
1065
|
+
node(
|
|
1066
|
+
"row",
|
|
1067
|
+
{
|
|
1068
|
+
role: "omp.composer.model",
|
|
1069
|
+
gap: "xs",
|
|
1070
|
+
align: "center",
|
|
1071
|
+
tone: facts.model.tone,
|
|
1072
|
+
title: modelKey ? `Switch model ${formatKeyHint(modelKey)}` : "Switch model",
|
|
1073
|
+
actions: { click: "status.model" },
|
|
1074
|
+
},
|
|
1075
|
+
[
|
|
1076
|
+
node("icon", { name: "model" }, undefined, "icon"),
|
|
1077
|
+
node("text", { spans: facts.model.spans, wrap: "none" }, undefined, "name"),
|
|
1078
|
+
node("icon", { name: "chev" }, undefined, "chev"),
|
|
1079
|
+
],
|
|
1080
|
+
"model",
|
|
1081
|
+
);
|
|
1082
|
+
const effortSteps = state.thinking === undefined ? undefined : EFFORT_STEPS[state.thinking];
|
|
1083
|
+
const effort =
|
|
1084
|
+
state.thinking !== undefined &&
|
|
1085
|
+
node(
|
|
1086
|
+
"row",
|
|
1087
|
+
{
|
|
1088
|
+
role: "omp.composer.effort",
|
|
1089
|
+
gap: "xs",
|
|
1090
|
+
align: "center",
|
|
1091
|
+
title: thinkingKey ? `Thinking effort ${formatKeyHint(thinkingKey)}` : "Thinking effort",
|
|
1092
|
+
actions: { click: "thinking.cycle" },
|
|
1093
|
+
},
|
|
1094
|
+
[
|
|
1095
|
+
node(
|
|
1096
|
+
"meter",
|
|
1097
|
+
{ value: effortSteps === undefined ? null : effortSteps / 4, style: "blocks", steps: 4 },
|
|
1098
|
+
undefined,
|
|
1099
|
+
"meter",
|
|
1100
|
+
),
|
|
1101
|
+
node("text", { text: state.thinking, wrap: "none" }, undefined, "level"),
|
|
1102
|
+
],
|
|
1103
|
+
"effort",
|
|
1104
|
+
);
|
|
1105
|
+
const submit = state.running
|
|
1106
|
+
? node(
|
|
1107
|
+
"text",
|
|
1108
|
+
{
|
|
1109
|
+
role: "omp.composer.stop",
|
|
1110
|
+
text: "Stop",
|
|
1111
|
+
tone: "error",
|
|
1112
|
+
title: `Stop ${interruptKey === "escape" ? "esc" : formatKeyHint(interruptKey)}`,
|
|
1113
|
+
actions: { click: "interrupt" },
|
|
1114
|
+
},
|
|
1115
|
+
undefined,
|
|
1116
|
+
"stop",
|
|
1117
|
+
)
|
|
1118
|
+
: node(
|
|
1119
|
+
"kbd",
|
|
1120
|
+
{
|
|
1121
|
+
role: "omp.composer.send",
|
|
1122
|
+
keys: ["enter"],
|
|
1123
|
+
title: `Send ${formatKeyHint("enter")}`,
|
|
1124
|
+
actions: { click: "submit" },
|
|
1125
|
+
},
|
|
1126
|
+
undefined,
|
|
1127
|
+
"send",
|
|
1128
|
+
);
|
|
1129
|
+
// The status facts are the bar's flexible space; without them a spacer keeps send at the end.
|
|
1130
|
+
const bar = keyed(
|
|
1131
|
+
row(compact([model, effort, facts?.extras ?? node("row", { grow: 1 }, [], "gap"), facts?.usage, submit]), {
|
|
1132
|
+
role: "omp.composer.bar",
|
|
1133
|
+
gap: "sm",
|
|
1134
|
+
align: "center",
|
|
1135
|
+
}),
|
|
1136
|
+
"bar",
|
|
1137
|
+
);
|
|
1138
|
+
if (!shell) return { mode: undefined, bar };
|
|
1139
|
+
const runs = shell.kind === "bash" ? "Runs in your shell" : "Runs in Python";
|
|
1140
|
+
const mode = keyed(
|
|
1141
|
+
row(
|
|
1142
|
+
compact([
|
|
1143
|
+
shell.excluded &&
|
|
1144
|
+
node("icon", { name: "eye-off", title: "Not sent to the model" }, undefined, "excluded"),
|
|
1145
|
+
node(
|
|
1146
|
+
"text",
|
|
1147
|
+
{ spans: [span(shell.kind, shell.kind === "bash" ? "bashMode" : "pythonMode")], wrap: "none" },
|
|
1148
|
+
undefined,
|
|
1149
|
+
"label",
|
|
1150
|
+
),
|
|
1151
|
+
]),
|
|
1152
|
+
{
|
|
1153
|
+
role: "omp.composer.mode",
|
|
1154
|
+
gap: "xs",
|
|
1155
|
+
align: "center",
|
|
1156
|
+
title: shell.excluded ? `${runs} · not sent to the model` : runs,
|
|
1157
|
+
},
|
|
1158
|
+
),
|
|
1159
|
+
"mode",
|
|
1160
|
+
);
|
|
1161
|
+
return { mode, bar };
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
/**
|
|
1165
|
+
* Clicks on the composer's controls take the same paths as their keys: ⇧⇥,
|
|
1166
|
+
* ⏎ and Esc; the status facts' clicks (`status.*`) go to their source.
|
|
1167
|
+
*/
|
|
1168
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
1169
|
+
if (event.type !== "action") return;
|
|
1170
|
+
switch (event.act) {
|
|
1171
|
+
case "thinking.cycle":
|
|
1172
|
+
this.onCycleThinkingLevel?.();
|
|
1173
|
+
return;
|
|
1174
|
+
case "submit":
|
|
1175
|
+
this.submit();
|
|
1176
|
+
return;
|
|
1177
|
+
case "interrupt":
|
|
1178
|
+
this.onEscape?.();
|
|
1179
|
+
return;
|
|
1180
|
+
default:
|
|
1181
|
+
this.composerFacts?.handleNativeEvent(event);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
|
|
887
1185
|
onEscape?: () => void;
|
|
888
1186
|
onClear?: () => void;
|
|
889
1187
|
onExit?: () => void;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Component } from "../index";
|
|
2
|
+
import type { NativeNode } from "../native/node";
|
|
3
|
+
import { col } from "../native/describe";
|
|
2
4
|
let composerShape = "box";
|
|
3
5
|
|
|
4
6
|
/** Set the process-wide editor gap layout. */
|
|
@@ -8,6 +10,8 @@ export function setEditorGapComposerShape(shape: string): void {
|
|
|
8
10
|
|
|
9
11
|
const GAP: readonly string[] = [""];
|
|
10
12
|
const FLUSH: readonly string[] = [];
|
|
13
|
+
/** A TSP terminal spaces the dock itself; the gap describes nothing. */
|
|
14
|
+
const NATIVE_GAP: NativeNode = col([]);
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
17
|
* One-line top margin between the working/status HUD row and the editor.
|
|
@@ -25,4 +29,8 @@ export class EditorTopGap implements Component {
|
|
|
25
29
|
render(_width: number): readonly string[] {
|
|
26
30
|
return composerShape === "band" && this.statusRowOccupied() ? FLUSH : GAP;
|
|
27
31
|
}
|
|
32
|
+
|
|
33
|
+
describe(): NativeNode {
|
|
34
|
+
return NATIVE_GAP;
|
|
35
|
+
}
|
|
28
36
|
}
|
|
@@ -96,10 +96,27 @@ export class MacOSSpellingProvider implements EditorTextAssistProvider {
|
|
|
96
96
|
context: SpellingDecorationContext,
|
|
97
97
|
decorate: (span: string) => string = value => value,
|
|
98
98
|
): string {
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
|
|
99
|
+
const ranges = this.typoRanges(text, context);
|
|
100
|
+
if (ranges.length === 0) return decorate(text);
|
|
101
|
+
let rendered = "";
|
|
102
|
+
let cursor = 0;
|
|
103
|
+
for (const range of ranges) {
|
|
104
|
+
const end = range.start + range.length;
|
|
105
|
+
rendered += decorate(text.slice(cursor, range.start));
|
|
106
|
+
rendered += this.#marks.start + decorate(text.slice(range.start, end)) + this.#marks.end;
|
|
107
|
+
cursor = end;
|
|
102
108
|
}
|
|
109
|
+
return rendered + decorate(text.slice(cursor));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Misspelled prose ranges in `text` (offsets into it), in order and
|
|
114
|
+
* non-overlapping. Schedules the verification check for uncached text; its
|
|
115
|
+
* result arrives through {@link onUpdate}.
|
|
116
|
+
*/
|
|
117
|
+
typoRanges(text: string, context: SpellingDecorationContext): readonly native.SpellingRange[] {
|
|
118
|
+
if (!this.#available || !this.#features.typoDetection || text.length === 0) return [];
|
|
119
|
+
if (!this.#prose.isProse(context, context.startCol, context.startCol + text.length)) return [];
|
|
103
120
|
const lane = `${context.line}:${context.startCol}`;
|
|
104
121
|
const cached = this.#typoCache.get(text);
|
|
105
122
|
// A cache hit obsoletes any older text queued for this lane. A miss must
|
|
@@ -110,9 +127,8 @@ export class MacOSSpellingProvider implements EditorTextAssistProvider {
|
|
|
110
127
|
if (cached === undefined) this.#scheduleTypoRanges(text, lane);
|
|
111
128
|
else this.#automaticTypoQueue.delete(lane);
|
|
112
129
|
const ranges = cached ?? this.#projectTypoRanges(text);
|
|
113
|
-
if (!ranges) return
|
|
114
|
-
|
|
115
|
-
let rendered = "";
|
|
130
|
+
if (!ranges || ranges.length === 0) return [];
|
|
131
|
+
const kept: native.SpellingRange[] = [];
|
|
116
132
|
let cursor = 0;
|
|
117
133
|
for (const range of ranges) {
|
|
118
134
|
const end = range.start + range.length;
|
|
@@ -123,11 +139,10 @@ export class MacOSSpellingProvider implements EditorTextAssistProvider {
|
|
|
123
139
|
if (!this.#prose.isProse(context, context.startCol + range.start, context.startCol + end)) {
|
|
124
140
|
continue;
|
|
125
141
|
}
|
|
126
|
-
|
|
127
|
-
rendered += this.#marks.start + decorate(text.slice(range.start, end)) + this.#marks.end;
|
|
142
|
+
kept.push(range);
|
|
128
143
|
cursor = end;
|
|
129
144
|
}
|
|
130
|
-
return
|
|
145
|
+
return kept;
|
|
131
146
|
}
|
|
132
147
|
|
|
133
148
|
/** Return the confident macOS correction after a completed prose word. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createGradientHighlighter, type KeywordHighlighter } from "./gradient-highlight";
|
|
2
|
-
import { keywordInProse } from "./markdown-prose";
|
|
2
|
+
import { keywordInProse, maskNonProse } from "./markdown-prose";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Magic-keyword engine: standalone prose words the host registers via
|
|
@@ -39,6 +39,8 @@ function magicKeywordRegex(word: string, flags = ""): RegExp {
|
|
|
39
39
|
interface RegisteredKeyword {
|
|
40
40
|
readonly word: string;
|
|
41
41
|
readonly highlight: KeywordHighlighter;
|
|
42
|
+
/** Global standalone-prose matcher, walked over masked text. */
|
|
43
|
+
readonly pattern: RegExp;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
let registry: readonly RegisteredKeyword[] = [];
|
|
@@ -62,6 +64,7 @@ function matcherFor(word: string): RegExp {
|
|
|
62
64
|
export function setMagicKeywords(specs: readonly MagicKeywordSpec[]): void {
|
|
63
65
|
registry = specs.map(({ word, hue: [from, to] }) => ({
|
|
64
66
|
word,
|
|
67
|
+
pattern: magicKeywordRegex(word, "g"),
|
|
65
68
|
highlight: createGradientHighlighter({
|
|
66
69
|
probe: word,
|
|
67
70
|
highlight: magicKeywordRegex(word, "g"),
|
|
@@ -110,6 +113,24 @@ export function highlightMagicKeywords(text: string, resetTo?: string, phase?: n
|
|
|
110
113
|
return out;
|
|
111
114
|
}
|
|
112
115
|
|
|
116
|
+
/**
|
|
117
|
+
* UTF-16 ranges of every registered keyword standing as prose in `text`
|
|
118
|
+
* (never inside code or XML/HTML sections), for decorating the keywords
|
|
119
|
+
* without painting them: a TSP terminal draws the gradient sweep itself.
|
|
120
|
+
*/
|
|
121
|
+
export function magicKeywordRanges(text: string): { from: number; to: number }[] {
|
|
122
|
+
const ranges: { from: number; to: number }[] = [];
|
|
123
|
+
let masked: string | undefined;
|
|
124
|
+
for (const keyword of registry) {
|
|
125
|
+
if (!text.includes(keyword.word)) continue;
|
|
126
|
+
masked ??= maskNonProse(text);
|
|
127
|
+
for (const match of masked.matchAll(keyword.pattern)) {
|
|
128
|
+
ranges.push({ from: match.index, to: match.index + match[0].length });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return ranges.sort((a, b) => a.from - b.from);
|
|
132
|
+
}
|
|
133
|
+
|
|
113
134
|
/**
|
|
114
135
|
* Cheap test for "does this text contain any registered keyword as standalone
|
|
115
136
|
* prose?". Short-circuits on a substring probe before paying for the
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Container } from "../tui";
|
|
2
|
+
import { Spacer } from "../components/spacer";
|
|
3
|
+
import { TruncatedText } from "../components/truncated-text";
|
|
4
|
+
import { formatKeyHint } from "../key-hint-format";
|
|
5
|
+
import type { KeyId } from "../keys";
|
|
6
|
+
import { kbd, node, text } from "../native/describe";
|
|
7
|
+
import type { NativeNode, NativeUiEvent } from "../native/node";
|
|
8
|
+
import { replaceTabs } from "../utils";
|
|
9
|
+
import { theme } from "../theme/theme";
|
|
10
|
+
|
|
11
|
+
/** Queued messages under one heading ("Steering", "After yield"). */
|
|
12
|
+
export interface QueuedMessageGroup {
|
|
13
|
+
readonly label: string;
|
|
14
|
+
readonly messages: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Messages queued while the agent works, above the editor. ANSI: a heading
|
|
19
|
+
* per group, numbered dim rows and the dequeue hint. Natively (§8.1): a
|
|
20
|
+
* stack of pills, each `corner-down-right` · the text · `⌥↑ Edit`, the total
|
|
21
|
+
* count in the first pill when more than one waits; the edit control sends
|
|
22
|
+
* `queue.edit`, answered like the dequeue key.
|
|
23
|
+
*/
|
|
24
|
+
export class QueuedMessagesBand extends Container {
|
|
25
|
+
readonly #native: NativeNode;
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
groups: readonly QueuedMessageGroup[],
|
|
29
|
+
dequeueKey: KeyId,
|
|
30
|
+
private readonly onEdit: () => void,
|
|
31
|
+
) {
|
|
32
|
+
super();
|
|
33
|
+
this.addChild(new Spacer(1));
|
|
34
|
+
for (const group of groups) {
|
|
35
|
+
const heading = theme.fg("muted", `${group.label}${theme.sep.dot}${group.messages.length}`);
|
|
36
|
+
this.addChild(new TruncatedText(heading, 1, 0));
|
|
37
|
+
for (let index = 0; index < group.messages.length; index++) {
|
|
38
|
+
const message = replaceTabs(group.messages[index] ?? "").replace(/\r?\n/g, " ↵ ");
|
|
39
|
+
this.addChild(new TruncatedText(theme.fg("dim", ` ${index + 1}. ${message}`), 1, 0));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const editKey = formatKeyHint(dequeueKey);
|
|
43
|
+
this.addChild(new TruncatedText(theme.fg("dim", ` ${theme.tree.hook} ${editKey} to edit`), 1, 0));
|
|
44
|
+
|
|
45
|
+
const count = groups.reduce((sum, group) => sum + group.messages.length, 0);
|
|
46
|
+
const pills: NativeNode[] = [];
|
|
47
|
+
for (const group of groups) {
|
|
48
|
+
group.messages.forEach((message, index) => {
|
|
49
|
+
const children: NativeNode[] = [
|
|
50
|
+
node("icon", { name: "corner-down-right" }, undefined, "icon"),
|
|
51
|
+
node(
|
|
52
|
+
"text",
|
|
53
|
+
{
|
|
54
|
+
text: replaceTabs(message).replace(/\s*\r?\n\s*/g, " ↵ "),
|
|
55
|
+
wrap: "none",
|
|
56
|
+
truncate: "end",
|
|
57
|
+
grow: 1,
|
|
58
|
+
},
|
|
59
|
+
undefined,
|
|
60
|
+
"text",
|
|
61
|
+
),
|
|
62
|
+
];
|
|
63
|
+
if (pills.length === 0 && count > 1) {
|
|
64
|
+
children.push(node("badge", { text: `${count}`, role: "omp.queue.count" }, undefined, "count"));
|
|
65
|
+
}
|
|
66
|
+
children.push(
|
|
67
|
+
node(
|
|
68
|
+
"row",
|
|
69
|
+
{
|
|
70
|
+
role: "omp.queue.edit",
|
|
71
|
+
gap: "xs",
|
|
72
|
+
align: "center",
|
|
73
|
+
title: `Edit ${editKey}`,
|
|
74
|
+
actions: { click: "queue.edit" },
|
|
75
|
+
},
|
|
76
|
+
[kbd(dequeueKey), text("Edit")],
|
|
77
|
+
"edit",
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
pills.push(
|
|
81
|
+
node(
|
|
82
|
+
"row",
|
|
83
|
+
{ role: "omp.queue.item", align: "center", gap: "sm", title: group.label },
|
|
84
|
+
children,
|
|
85
|
+
`${group.label}/${index}`,
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
this.#native = node("col", { role: "omp.queue", gap: "xs" }, pills);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
override describe(): NativeNode {
|
|
94
|
+
return this.#native;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** The pills' Edit control: the dequeue key's path (queued messages back into the editor). */
|
|
98
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
99
|
+
if (event.type === "action" && event.act === "queue.edit") this.onEdit();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* One `/skill:<name>` token delimited by whitespace or line edges. Group 1 is
|
|
3
|
-
* the leading delimiter (empty at line start), group 2 the
|
|
4
|
-
*
|
|
3
|
+
* the leading delimiter (empty at line start), group 2 the skill name: a bare
|
|
4
|
+
* name or a collision-namespaced `<namespace>/<name>` (exactly one `/`; deeper
|
|
5
|
+
* paths never match). Global so callers can walk every token; reset
|
|
6
|
+
* `lastIndex` before reuse.
|
|
5
7
|
*/
|
|
6
|
-
export const SKILL_TOKEN_RE = /(^|\s)\/skill:([^\s/]+)(?=\s|$)/g;
|
|
8
|
+
export const SKILL_TOKEN_RE = /(^|\s)\/skill:([^\s/]+(?:\/[^\s/]+)?)(?=\s|$)/g;
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Whether the (already left-trimmed) draft begins with a TUI local-execution
|