@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
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import type { Model } from "@oh-my-pi/pi-ai";
|
|
14
|
+
import type { TspPickerAction, TspPickerColumn, TspPickerItem, TspPickerScope, TspSpan } from "@oh-my-pi/pi-wire";
|
|
14
15
|
import {
|
|
15
16
|
type Component,
|
|
16
17
|
Editor,
|
|
@@ -25,8 +26,13 @@ import {
|
|
|
25
26
|
visibleWidth,
|
|
26
27
|
wrapTextWithAnsi,
|
|
27
28
|
} from "../index";
|
|
29
|
+
import { code, col, md, node, row, span, text } from "../native/describe";
|
|
30
|
+
import type { DescribeContext, NativeChild, NativeNode, NativeUiEvent } from "../native/node";
|
|
31
|
+
import { actionHint, type NativeHint, hintsRow } from "../native/overlay";
|
|
32
|
+
import { CLOSE_ACTION, type PickerEvent, picker, pickerEvent, pickerQuery } from "../native/picker";
|
|
28
33
|
import type { AgentSource } from "../tools/task";
|
|
29
34
|
import { shortenPath } from "../render/render-utils";
|
|
35
|
+
import { sanitizeDisplaySingleLine } from "./extensions/display-text";
|
|
30
36
|
import { getEditorTheme, theme } from "../theme";
|
|
31
37
|
import { matchesAppFollowUp, matchesSelectCancel, matchesSelectDown, matchesSelectUp } from "../keybinding-matchers";
|
|
32
38
|
import { formatKeyHint, formatKeyHints } from "../app-keybindings";
|
|
@@ -39,6 +45,8 @@ import {
|
|
|
39
45
|
sortModelItems,
|
|
40
46
|
} from "./model-browser";
|
|
41
47
|
import {
|
|
48
|
+
describeHubFrame,
|
|
49
|
+
describeHubSidebar,
|
|
42
50
|
HubFrame,
|
|
43
51
|
moveStripSelection,
|
|
44
52
|
type SidebarEntry as HubSidebarEntry,
|
|
@@ -72,6 +80,14 @@ const SOURCE_LABEL: Record<AgentSource, string> = {
|
|
|
72
80
|
bundled: "Bundled",
|
|
73
81
|
};
|
|
74
82
|
const SOURCE_ORDER: Record<AgentSource, number> = { project: 0, user: 1, bundled: 2 };
|
|
83
|
+
const SOURCES = ["project", "user", "bundled"] as const satisfies readonly AgentSource[];
|
|
84
|
+
/** Per-agent override columns of the config picker; lower priorities hide first. */
|
|
85
|
+
const AGENT_COLUMNS: readonly TspPickerColumn[] = [
|
|
86
|
+
{ id: "model", head: "Model", format: "text", priority: 4, min: 8 },
|
|
87
|
+
{ id: "prewalk", head: "Prewalk", format: "text", priority: 2 },
|
|
88
|
+
{ id: "advisor", head: "Advisor", format: "text", priority: 3 },
|
|
89
|
+
];
|
|
90
|
+
const SOURCE_COLUMN: TspPickerColumn = { id: "source", head: "Source", format: "dim", priority: 1 };
|
|
75
91
|
|
|
76
92
|
interface SidebarEntry extends HubSidebarEntry<"all" | "source" | "new" | "separator"> {
|
|
77
93
|
source?: AgentSource;
|
|
@@ -160,6 +176,11 @@ function parseGeneratedAgentSpec(raw: string): GeneratedAgentSpec {
|
|
|
160
176
|
return { identifier, whenToUse, systemPrompt };
|
|
161
177
|
}
|
|
162
178
|
|
|
179
|
+
/** Stable native list-item id of an agent-list row. */
|
|
180
|
+
function listRowId(rowDef: ListRow): string {
|
|
181
|
+
return rowDef.kind === "new" ? "new" : `agent:${rowDef.agent.source}:${rowDef.agent.name}`;
|
|
182
|
+
}
|
|
183
|
+
|
|
163
184
|
function matchAgent(agent: HubAgent, query: string): boolean {
|
|
164
185
|
const text = `${agent.name} ${agent.description} ${SOURCE_LABEL[agent.source]} ${agent.overrideModel ?? ""}`;
|
|
165
186
|
return query
|
|
@@ -187,7 +208,8 @@ export class AgentsHubComponent implements Component {
|
|
|
187
208
|
#rowIndex = 0;
|
|
188
209
|
#rowHover: number | null = null;
|
|
189
210
|
#listScroll = 0;
|
|
190
|
-
|
|
211
|
+
/** Type-to-filter field for the agent list (chrome-less; the hub draws `search:`). */
|
|
212
|
+
readonly #search = Object.assign(new Input(), { prompt: "" });
|
|
191
213
|
#notice: string | null = null;
|
|
192
214
|
#loadError: string | null = null;
|
|
193
215
|
|
|
@@ -205,6 +227,12 @@ export class AgentsHubComponent implements Component {
|
|
|
205
227
|
#createError: string | null = null;
|
|
206
228
|
#createStreamingText = "";
|
|
207
229
|
|
|
230
|
+
/** Bumped on every visible-state change; the described node is rebuilt when it moves. */
|
|
231
|
+
#nativeVersion = 0;
|
|
232
|
+
#nativeCache: { version: number; sheet: boolean; node: NativeNode } | undefined;
|
|
233
|
+
/** Collapsed state of the generated system-prompt card (native only). */
|
|
234
|
+
#promptCollapsed = true;
|
|
235
|
+
|
|
208
236
|
#renderBodyPane = (width: number, height: number | undefined): readonly string[] => {
|
|
209
237
|
const rows = Math.max(1, Math.floor(height ?? 10));
|
|
210
238
|
const lines: string[] = [this.#statusRow(width)];
|
|
@@ -260,9 +288,16 @@ export class AgentsHubComponent implements Component {
|
|
|
260
288
|
|
|
261
289
|
dispose(): void {}
|
|
262
290
|
invalidate(): void {
|
|
291
|
+
this.#nativeVersion++;
|
|
263
292
|
this.#frame.invalidate();
|
|
264
293
|
}
|
|
265
294
|
|
|
295
|
+
/** Request a repaint after a state change, invalidating the described node. */
|
|
296
|
+
#requestRender(): void {
|
|
297
|
+
this.#nativeVersion++;
|
|
298
|
+
this.#tui.requestRender();
|
|
299
|
+
}
|
|
300
|
+
|
|
266
301
|
// ═══════════════════════════════════════════════════════════════════════
|
|
267
302
|
// Data pipeline
|
|
268
303
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -288,7 +323,7 @@ export class AgentsHubComponent implements Component {
|
|
|
288
323
|
this.#buildRows();
|
|
289
324
|
this.#loadError = error instanceof Error ? error.message : String(error);
|
|
290
325
|
}
|
|
291
|
-
this.#
|
|
326
|
+
this.#requestRender();
|
|
292
327
|
}
|
|
293
328
|
|
|
294
329
|
#buildSidebar(): void {
|
|
@@ -324,7 +359,8 @@ export class AgentsHubComponent implements Component {
|
|
|
324
359
|
const entry = this.#activeEntry();
|
|
325
360
|
const scoped =
|
|
326
361
|
entry.kind === "source" ? this.#allAgents.filter(agent => agent.source === entry.source) : this.#allAgents;
|
|
327
|
-
const
|
|
362
|
+
const query = this.#search.getValue();
|
|
363
|
+
const filtered = query ? scoped.filter(agent => matchAgent(agent, query)) : scoped;
|
|
328
364
|
this.#rows = [...filtered.map(agent => ({ kind: "agent", agent }) as ListRow), { kind: "new" }];
|
|
329
365
|
}
|
|
330
366
|
|
|
@@ -345,7 +381,7 @@ export class AgentsHubComponent implements Component {
|
|
|
345
381
|
agent.disabled = !agent.disabled;
|
|
346
382
|
this.#deps.setAgentDisabled(agent.name, { disabled: agent.disabled });
|
|
347
383
|
this.#notice = `${agent.name} ${agent.disabled ? "disabled" : "enabled"}`;
|
|
348
|
-
this.#
|
|
384
|
+
this.#requestRender();
|
|
349
385
|
}
|
|
350
386
|
|
|
351
387
|
#overrideFor(agent: HubAgent, property: PropertyKind): string | undefined {
|
|
@@ -374,7 +410,7 @@ export class AgentsHubComponent implements Component {
|
|
|
374
410
|
}
|
|
375
411
|
this.#deps.setAgentOverride(property, agent.name, trimmed);
|
|
376
412
|
this.#notice = this.#describeProperty(agent, property);
|
|
377
|
-
this.#
|
|
413
|
+
this.#requestRender();
|
|
378
414
|
}
|
|
379
415
|
|
|
380
416
|
/** One-line effective description used for notices and the status row. */
|
|
@@ -567,7 +603,7 @@ export class AgentsHubComponent implements Component {
|
|
|
567
603
|
#cancelAssign(): void {
|
|
568
604
|
this.#assigning = null;
|
|
569
605
|
this.#browser.setQuery("");
|
|
570
|
-
this.#
|
|
606
|
+
this.#requestRender();
|
|
571
607
|
}
|
|
572
608
|
|
|
573
609
|
// ═══════════════════════════════════════════════════════════════════════
|
|
@@ -592,7 +628,7 @@ export class AgentsHubComponent implements Component {
|
|
|
592
628
|
this.#createDescription = value;
|
|
593
629
|
};
|
|
594
630
|
this.#createInput = editor;
|
|
595
|
-
this.#
|
|
631
|
+
this.#requestRender();
|
|
596
632
|
}
|
|
597
633
|
|
|
598
634
|
#clearCreateFlow(): void {
|
|
@@ -609,14 +645,14 @@ export class AgentsHubComponent implements Component {
|
|
|
609
645
|
this.#createDescription = description;
|
|
610
646
|
if (!description) {
|
|
611
647
|
this.#createError = "Description is required.";
|
|
612
|
-
this.#
|
|
648
|
+
this.#requestRender();
|
|
613
649
|
return;
|
|
614
650
|
}
|
|
615
651
|
this.#createGenerating = true;
|
|
616
652
|
this.#createError = null;
|
|
617
653
|
this.#createSpec = null;
|
|
618
654
|
this.#createStreamingText = "";
|
|
619
|
-
this.#
|
|
655
|
+
this.#requestRender();
|
|
620
656
|
try {
|
|
621
657
|
const spec = await this.#runAgentCreationArchitect(description);
|
|
622
658
|
this.#createSpec = spec;
|
|
@@ -625,14 +661,14 @@ export class AgentsHubComponent implements Component {
|
|
|
625
661
|
this.#createError = error instanceof Error ? error.message : String(error);
|
|
626
662
|
} finally {
|
|
627
663
|
this.#createGenerating = false;
|
|
628
|
-
this.#
|
|
664
|
+
this.#requestRender();
|
|
629
665
|
}
|
|
630
666
|
}
|
|
631
667
|
|
|
632
668
|
async #runAgentCreationArchitect(description: string): Promise<GeneratedAgentSpec> {
|
|
633
669
|
const raw = await this.#deps.generateAgent(description, text => {
|
|
634
670
|
this.#createStreamingText += text;
|
|
635
|
-
this.#
|
|
671
|
+
this.#requestRender();
|
|
636
672
|
});
|
|
637
673
|
return parseGeneratedAgentSpec(raw);
|
|
638
674
|
}
|
|
@@ -651,21 +687,22 @@ export class AgentsHubComponent implements Component {
|
|
|
651
687
|
// ═══════════════════════════════════════════════════════════════════════
|
|
652
688
|
|
|
653
689
|
handleInput(data: string): void {
|
|
690
|
+
this.#nativeVersion++;
|
|
654
691
|
if (data.startsWith("\x1b[<")) {
|
|
655
692
|
routeSgrMouseInput(data, event => this.#routeMouseEvent(event));
|
|
656
|
-
this.#
|
|
693
|
+
this.#requestRender();
|
|
657
694
|
return;
|
|
658
695
|
}
|
|
659
696
|
|
|
660
697
|
if (this.#strip) {
|
|
661
698
|
this.#handleStripInput(data);
|
|
662
|
-
this.#
|
|
699
|
+
this.#requestRender();
|
|
663
700
|
return;
|
|
664
701
|
}
|
|
665
702
|
|
|
666
703
|
if (this.#createActive) {
|
|
667
704
|
this.#handleCreateInput(data);
|
|
668
|
-
this.#
|
|
705
|
+
this.#requestRender();
|
|
669
706
|
return;
|
|
670
707
|
}
|
|
671
708
|
|
|
@@ -674,11 +711,11 @@ export class AgentsHubComponent implements Component {
|
|
|
674
711
|
this.#cancelAssign();
|
|
675
712
|
return;
|
|
676
713
|
}
|
|
677
|
-
if (this.#
|
|
678
|
-
this.#
|
|
714
|
+
if (this.#search.getValue()) {
|
|
715
|
+
this.#search.setValue("");
|
|
679
716
|
this.#buildRows();
|
|
680
717
|
this.#clampRowIndex();
|
|
681
|
-
this.#
|
|
718
|
+
this.#requestRender();
|
|
682
719
|
return;
|
|
683
720
|
}
|
|
684
721
|
this.#callbacks.onCancel();
|
|
@@ -687,7 +724,7 @@ export class AgentsHubComponent implements Component {
|
|
|
687
724
|
|
|
688
725
|
if (this.#assigning) {
|
|
689
726
|
this.#browser.handleInput(data);
|
|
690
|
-
this.#
|
|
727
|
+
this.#requestRender();
|
|
691
728
|
return;
|
|
692
729
|
}
|
|
693
730
|
|
|
@@ -698,29 +735,29 @@ export class AgentsHubComponent implements Component {
|
|
|
698
735
|
|
|
699
736
|
if (matchesKey(data, "tab") || matchesKey(data, "shift+tab")) {
|
|
700
737
|
this.#focus = this.#focus === "scope" ? "list" : "scope";
|
|
701
|
-
this.#
|
|
738
|
+
this.#requestRender();
|
|
702
739
|
return;
|
|
703
740
|
}
|
|
704
741
|
if (matchesKey(data, "left")) {
|
|
705
742
|
this.#focus = "scope";
|
|
706
|
-
this.#
|
|
743
|
+
this.#requestRender();
|
|
707
744
|
return;
|
|
708
745
|
}
|
|
709
746
|
if (matchesKey(data, "right")) {
|
|
710
747
|
this.#focus = "list";
|
|
711
|
-
this.#
|
|
748
|
+
this.#requestRender();
|
|
712
749
|
return;
|
|
713
750
|
}
|
|
714
751
|
|
|
715
752
|
if (this.#focus === "scope") {
|
|
716
753
|
if (matchesSelectUp(data)) {
|
|
717
754
|
this.#moveSidebar(-1);
|
|
718
|
-
this.#
|
|
755
|
+
this.#requestRender();
|
|
719
756
|
return;
|
|
720
757
|
}
|
|
721
758
|
if (matchesSelectDown(data)) {
|
|
722
759
|
this.#moveSidebar(1);
|
|
723
|
-
this.#
|
|
760
|
+
this.#requestRender();
|
|
724
761
|
return;
|
|
725
762
|
}
|
|
726
763
|
if (matchesKey(data, "enter") || matchesKey(data, "return") || data === "\n") {
|
|
@@ -729,48 +766,47 @@ export class AgentsHubComponent implements Component {
|
|
|
729
766
|
} else {
|
|
730
767
|
this.#focus = "list";
|
|
731
768
|
}
|
|
732
|
-
this.#
|
|
769
|
+
this.#requestRender();
|
|
733
770
|
return;
|
|
734
771
|
}
|
|
735
772
|
}
|
|
736
773
|
|
|
737
774
|
if (matchesSelectUp(data)) {
|
|
738
775
|
this.#rowIndex = Math.max(0, this.#rowIndex - 1);
|
|
739
|
-
this.#
|
|
776
|
+
this.#requestRender();
|
|
740
777
|
return;
|
|
741
778
|
}
|
|
742
779
|
if (matchesSelectDown(data)) {
|
|
743
780
|
this.#rowIndex = Math.min(this.#rows.length - 1, this.#rowIndex + 1);
|
|
744
|
-
this.#
|
|
781
|
+
this.#requestRender();
|
|
745
782
|
return;
|
|
746
783
|
}
|
|
747
784
|
if (matchesKey(data, "enter") || matchesKey(data, "return") || data === "\n") {
|
|
748
785
|
this.#activateRow(this.#rows[this.#rowIndex]);
|
|
749
|
-
this.#
|
|
786
|
+
this.#requestRender();
|
|
750
787
|
return;
|
|
751
788
|
}
|
|
752
|
-
if (data === " " && this.#
|
|
789
|
+
if (data === " " && !this.#search.getValue()) {
|
|
753
790
|
const agent = this.#selectedAgent();
|
|
754
791
|
if (agent) this.#toggleAgent(agent);
|
|
755
792
|
return;
|
|
756
793
|
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
this.#searchQuery += data;
|
|
794
|
+
// Type-to-filter: every other key edits the search field.
|
|
795
|
+
const before = this.#search.getValue();
|
|
796
|
+
if (!this.#search.handleInput(data)) return;
|
|
797
|
+
const value = this.#search.getValue();
|
|
798
|
+
if (value === before) {
|
|
799
|
+
this.#requestRender();
|
|
800
|
+
} else if (value.length < before.length) {
|
|
801
|
+
this.#buildRows();
|
|
802
|
+
this.#clampRowIndex();
|
|
803
|
+
this.#requestRender();
|
|
804
|
+
} else {
|
|
769
805
|
this.#focus = "list";
|
|
770
806
|
this.#buildRows();
|
|
771
807
|
this.#rowIndex = 0;
|
|
772
808
|
this.#listScroll = 0;
|
|
773
|
-
this.#
|
|
809
|
+
this.#requestRender();
|
|
774
810
|
}
|
|
775
811
|
}
|
|
776
812
|
|
|
@@ -787,16 +823,7 @@ export class AgentsHubComponent implements Component {
|
|
|
787
823
|
const strip = this.#strip;
|
|
788
824
|
if (!strip) return;
|
|
789
825
|
if (matchesSelectCancel(data)) {
|
|
790
|
-
|
|
791
|
-
if (strip.kind === "chips" && strip.property) {
|
|
792
|
-
this.#openAgentStrip(strip.agent);
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
795
|
-
if (strip.kind === "pattern") {
|
|
796
|
-
this.#openPropertyStrip(strip.agent, strip.property);
|
|
797
|
-
return;
|
|
798
|
-
}
|
|
799
|
-
this.#closeStrip();
|
|
826
|
+
this.#stripBack(strip);
|
|
800
827
|
return;
|
|
801
828
|
}
|
|
802
829
|
if (strip.kind === "pattern") {
|
|
@@ -814,6 +841,19 @@ export class AgentsHubComponent implements Component {
|
|
|
814
841
|
}
|
|
815
842
|
}
|
|
816
843
|
|
|
844
|
+
/** Esc on a strip: a property strip steps back up to the agent strip, the agent strip closes. */
|
|
845
|
+
#stripBack(strip: StripState): void {
|
|
846
|
+
if (strip.kind === "chips" && strip.property) {
|
|
847
|
+
this.#openAgentStrip(strip.agent);
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
if (strip.kind === "pattern") {
|
|
851
|
+
this.#openPropertyStrip(strip.agent, strip.property);
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
this.#closeStrip();
|
|
855
|
+
}
|
|
856
|
+
|
|
817
857
|
#handleCreateInput(data: string): void {
|
|
818
858
|
if (this.#createSpec) {
|
|
819
859
|
if (matchesSelectCancel(data)) {
|
|
@@ -831,7 +871,7 @@ export class AgentsHubComponent implements Component {
|
|
|
831
871
|
if (matchesKey(data, "enter") || matchesKey(data, "return") || data === "\n") {
|
|
832
872
|
void this.#saveGeneratedAgent().catch(error => {
|
|
833
873
|
this.#createError = error instanceof Error ? error.message : String(error);
|
|
834
|
-
this.#
|
|
874
|
+
this.#requestRender();
|
|
835
875
|
});
|
|
836
876
|
}
|
|
837
877
|
return;
|
|
@@ -990,7 +1030,10 @@ export class AgentsHubComponent implements Component {
|
|
|
990
1030
|
|
|
991
1031
|
#renderList(width: number, rows: number): string[] {
|
|
992
1032
|
const lines: string[] = [];
|
|
993
|
-
const
|
|
1033
|
+
const query = this.#search.getValue();
|
|
1034
|
+
const searchText = query
|
|
1035
|
+
? theme.fg("accent", this.#search.render(visibleWidth(query) + 1)[0] ?? "")
|
|
1036
|
+
: theme.fg("dim", "type to filter");
|
|
994
1037
|
lines.push(truncateToWidth(` ${theme.fg("muted", "search:")} ${searchText}`, width));
|
|
995
1038
|
lines.push("");
|
|
996
1039
|
this.#listRowStart = lines.length;
|
|
@@ -1200,6 +1243,598 @@ export class AgentsHubComponent implements Component {
|
|
|
1200
1243
|
return this.#frame.renderChips(width, prefix, strip);
|
|
1201
1244
|
}
|
|
1202
1245
|
|
|
1246
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
1247
|
+
// Native (TSP) description
|
|
1248
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
1249
|
+
|
|
1250
|
+
/**
|
|
1251
|
+
* The agent list (and its chip strips) is a `picker` sheet. The pattern
|
|
1252
|
+
* input, the model browser and the create wizard stay the generic overlay.
|
|
1253
|
+
*/
|
|
1254
|
+
nativeSheet(cx: DescribeContext): boolean {
|
|
1255
|
+
return cx.supports("picker") && !this.#createActive && !this.#assigning && this.#strip?.kind !== "pattern";
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
describe(cx: DescribeContext): NativeNode {
|
|
1259
|
+
const sheet = this.nativeSheet(cx);
|
|
1260
|
+
const cached = this.#nativeCache;
|
|
1261
|
+
if (cached?.version === this.#nativeVersion && cached.sheet === sheet) return cached.node;
|
|
1262
|
+
if (sheet) {
|
|
1263
|
+
const described = this.#describePicker();
|
|
1264
|
+
this.#nativeCache = { version: this.#nativeVersion, sheet, node: described };
|
|
1265
|
+
return described;
|
|
1266
|
+
}
|
|
1267
|
+
const footer: NativeChild[] = [];
|
|
1268
|
+
const strip = this.#describeStrip();
|
|
1269
|
+
if (strip) footer.push(strip);
|
|
1270
|
+
footer.push(hintsRow(this.#footerHints()));
|
|
1271
|
+
const described = describeHubFrame(
|
|
1272
|
+
"omp.hub.agents",
|
|
1273
|
+
"Agents",
|
|
1274
|
+
describeHubSidebar(this.#entries, this.#activeEntryId, this.#sidebarStyle, "scopes"),
|
|
1275
|
+
this.#describeBody(),
|
|
1276
|
+
node("col", { gap: "xs" }, footer, "footer"),
|
|
1277
|
+
);
|
|
1278
|
+
this.#nativeCache = { version: this.#nativeVersion, sheet, node: described };
|
|
1279
|
+
return described;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
1283
|
+
const target = event.key.slice(event.key.lastIndexOf("/") + 1);
|
|
1284
|
+
const pick = pickerEvent(event);
|
|
1285
|
+
if (pick) {
|
|
1286
|
+
this.#handlePickerEvent(pick);
|
|
1287
|
+
this.#requestRender();
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
if (event.type === "toggle") {
|
|
1291
|
+
if (target !== "prompt") return;
|
|
1292
|
+
this.#promptCollapsed = event.collapsed;
|
|
1293
|
+
} else if (event.type === "select" || event.type === "activate") {
|
|
1294
|
+
const activate = event.type === "activate";
|
|
1295
|
+
if (target === "strip") {
|
|
1296
|
+
const strip = this.#strip;
|
|
1297
|
+
const index = Number(event.item);
|
|
1298
|
+
if (strip?.kind !== "chips" || !Number.isInteger(index) || !strip.chips[index]) return;
|
|
1299
|
+
strip.index = index;
|
|
1300
|
+
if (activate) this.#activateStripChip();
|
|
1301
|
+
} else if (target === "agents") {
|
|
1302
|
+
// Like the mouse path: the list is inert under a strip, the create flow, or the model browser.
|
|
1303
|
+
if (this.#strip || this.#createActive || this.#assigning) return;
|
|
1304
|
+
const index = this.#rows.findIndex(rowDef => listRowId(rowDef) === event.item);
|
|
1305
|
+
if (index < 0) return;
|
|
1306
|
+
this.#focus = "list";
|
|
1307
|
+
this.#rowIndex = index;
|
|
1308
|
+
if (activate) this.#activateRow(this.#rows[index]);
|
|
1309
|
+
} else if (target === "scopes") {
|
|
1310
|
+
if (this.#strip || this.#createActive || this.#assigning) return;
|
|
1311
|
+
const entry = this.#entries.find(candidate => candidate.id === event.item);
|
|
1312
|
+
if (!entry || entry.kind === "separator") return;
|
|
1313
|
+
if (entry.kind === "new") {
|
|
1314
|
+
this.#beginCreateFlow();
|
|
1315
|
+
} else {
|
|
1316
|
+
this.#activeEntryId = entry.id;
|
|
1317
|
+
this.#buildRows();
|
|
1318
|
+
this.#rowIndex = 0;
|
|
1319
|
+
this.#listScroll = 0;
|
|
1320
|
+
this.#focus = activate ? "list" : "scope";
|
|
1321
|
+
}
|
|
1322
|
+
} else {
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1325
|
+
} else {
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
this.#requestRender();
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
/** Picker pointer events: each runs the path of the key it stands for. */
|
|
1332
|
+
#handlePickerEvent(pick: PickerEvent): void {
|
|
1333
|
+
const strip = this.#strip;
|
|
1334
|
+
if (pick.kind !== "action") {
|
|
1335
|
+
if (strip) return; // the list is inert under a strip, like the mouse path
|
|
1336
|
+
const index = this.#rows.findIndex(rowDef => listRowId(rowDef) === pick.item);
|
|
1337
|
+
if (index < 0) return;
|
|
1338
|
+
this.#focus = "list";
|
|
1339
|
+
this.#rowIndex = index;
|
|
1340
|
+
if (pick.kind === "activate") this.#activateRow(this.#rows[index]);
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
if (pick.act === "close") {
|
|
1344
|
+
this.#callbacks.onCancel();
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
if (strip?.kind === "chips") {
|
|
1348
|
+
if (pick.act === "strip") {
|
|
1349
|
+
const index = Number(pick.value);
|
|
1350
|
+
if (!Number.isInteger(index) || !strip.chips[index]) return;
|
|
1351
|
+
strip.index = index;
|
|
1352
|
+
this.#activateStripChip();
|
|
1353
|
+
} else if (pick.act === "apply") {
|
|
1354
|
+
this.#activateStripChip();
|
|
1355
|
+
} else if (pick.act === "back") {
|
|
1356
|
+
this.#stripBack(strip);
|
|
1357
|
+
}
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
const agent = this.#selectedAgent();
|
|
1361
|
+
switch (pick.act) {
|
|
1362
|
+
case "scope": {
|
|
1363
|
+
const entry = this.#entries.find(candidate => candidate.id === pick.value);
|
|
1364
|
+
if (!entry || entry.kind === "separator" || entry.kind === "new") return;
|
|
1365
|
+
this.#activeEntryId = entry.id;
|
|
1366
|
+
this.#buildRows();
|
|
1367
|
+
this.#rowIndex = 0;
|
|
1368
|
+
this.#listScroll = 0;
|
|
1369
|
+
this.#focus = "scope";
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
case "configure":
|
|
1373
|
+
this.#activateRow(this.#rows[this.#rowIndex]);
|
|
1374
|
+
return;
|
|
1375
|
+
case "toggle":
|
|
1376
|
+
if (agent) this.#toggleAgent(agent);
|
|
1377
|
+
return;
|
|
1378
|
+
case "model":
|
|
1379
|
+
if (agent) this.#openPropertyStrip(agent, "model");
|
|
1380
|
+
return;
|
|
1381
|
+
case "new":
|
|
1382
|
+
this.#beginCreateFlow();
|
|
1383
|
+
return;
|
|
1384
|
+
case "reload":
|
|
1385
|
+
void this.#reload();
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
/** The config hub as a `picker` (§9.1): source scopes, override columns, prompt preview. */
|
|
1391
|
+
#describePicker(): NativeNode {
|
|
1392
|
+
const counts: Record<AgentSource, number> = { project: 0, user: 0, bundled: 0 };
|
|
1393
|
+
for (const agent of this.#allAgents) counts[agent.source]++;
|
|
1394
|
+
const scopes: TspPickerScope[] = [
|
|
1395
|
+
{ id: "all", label: "All agents", icon: "users", count: this.#allAgents.length },
|
|
1396
|
+
...SOURCES.map((source): TspPickerScope => ({
|
|
1397
|
+
id: `source:${source}`,
|
|
1398
|
+
label: SOURCE_LABEL[source],
|
|
1399
|
+
icon: source === "project" ? "folder" : source === "user" ? "user" : "box",
|
|
1400
|
+
count: counts[source],
|
|
1401
|
+
group: "Source",
|
|
1402
|
+
disabled: counts[source] === 0 ? `No ${source} agents` : undefined,
|
|
1403
|
+
})),
|
|
1404
|
+
];
|
|
1405
|
+
const entry = this.#activeEntry();
|
|
1406
|
+
const strip = this.#strip?.kind === "chips" ? this.#strip : null;
|
|
1407
|
+
const agent = this.#selectedAgent();
|
|
1408
|
+
let actions: TspPickerAction[];
|
|
1409
|
+
if (strip) {
|
|
1410
|
+
actions = [
|
|
1411
|
+
{ id: "apply", label: strip.property ? "Apply" : "Open", keys: ["enter"], primary: true },
|
|
1412
|
+
{ id: "back", label: strip.property ? "Back" : "Cancel", keys: ["esc"], end: true },
|
|
1413
|
+
];
|
|
1414
|
+
} else {
|
|
1415
|
+
const noAgent = agent ? undefined : "Select an agent";
|
|
1416
|
+
actions = [
|
|
1417
|
+
{ id: "configure", label: agent ? "Configure" : "Create", keys: ["enter"], primary: true },
|
|
1418
|
+
{
|
|
1419
|
+
id: "toggle",
|
|
1420
|
+
label: "Toggle",
|
|
1421
|
+
keys: ["space"],
|
|
1422
|
+
on: agent ? !agent.disabled : undefined,
|
|
1423
|
+
disabled: noAgent,
|
|
1424
|
+
},
|
|
1425
|
+
{ id: "model", label: "Model", disabled: noAgent },
|
|
1426
|
+
{ id: "new", label: "New agent" },
|
|
1427
|
+
{ id: "reload", label: "Reload", keys: ["ctrl", "r"] },
|
|
1428
|
+
CLOSE_ACTION,
|
|
1429
|
+
];
|
|
1430
|
+
}
|
|
1431
|
+
const selectedRow = this.#rows[this.#rowIndex];
|
|
1432
|
+
return picker(
|
|
1433
|
+
{
|
|
1434
|
+
title: "Agents",
|
|
1435
|
+
subtitle: this.#notice ?? undefined,
|
|
1436
|
+
icon: "users",
|
|
1437
|
+
noun: "agents",
|
|
1438
|
+
size: "lg",
|
|
1439
|
+
layout: "rows",
|
|
1440
|
+
preview: "side",
|
|
1441
|
+
...pickerQuery(this.#search),
|
|
1442
|
+
placeholder: "Search agents…",
|
|
1443
|
+
scopes,
|
|
1444
|
+
scope: entry.kind === "source" ? entry.id : "all",
|
|
1445
|
+
columns: entry.kind === "source" ? AGENT_COLUMNS : [...AGENT_COLUMNS, SOURCE_COLUMN],
|
|
1446
|
+
items: this.#rows.map(rowDef => this.#pickerItem(rowDef)),
|
|
1447
|
+
selected: selectedRow ? listRowId(selectedRow) : null,
|
|
1448
|
+
total: entry.kind === "source" && entry.source ? counts[entry.source] : this.#allAgents.length,
|
|
1449
|
+
state: this.#loadError ? "error" : "ready",
|
|
1450
|
+
message: this.#loadError ?? undefined,
|
|
1451
|
+
strip: strip
|
|
1452
|
+
? {
|
|
1453
|
+
label: strip.property ? `${strip.agent.name} · ${strip.property}` : strip.agent.name,
|
|
1454
|
+
items: strip.chips.map((chip, index) => ({
|
|
1455
|
+
id: String(index),
|
|
1456
|
+
label: this.#stripChipLabel(strip.agent, chip),
|
|
1457
|
+
on: this.#stripChipOn(strip.agent, strip.property, chip),
|
|
1458
|
+
})),
|
|
1459
|
+
selected: String(strip.index),
|
|
1460
|
+
}
|
|
1461
|
+
: null,
|
|
1462
|
+
actions,
|
|
1463
|
+
focus: strip ? "strip" : this.#focus === "scope" ? "scopes" : "list",
|
|
1464
|
+
},
|
|
1465
|
+
this.#describePreview(selectedRow),
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
#pickerItem(rowDef: ListRow): TspPickerItem {
|
|
1470
|
+
if (rowDef.kind === "new") {
|
|
1471
|
+
return { id: listRowId(rowDef), label: "New agent…", icon: "plus", tone: "muted" };
|
|
1472
|
+
}
|
|
1473
|
+
const agent = rowDef.agent;
|
|
1474
|
+
const prewalk = this.#deps.effectivePrewalkPattern(agent);
|
|
1475
|
+
const advisor = this.#deps.effectiveAdvisorPattern(agent);
|
|
1476
|
+
return {
|
|
1477
|
+
id: listRowId(rowDef),
|
|
1478
|
+
label: agent.name,
|
|
1479
|
+
mono: true,
|
|
1480
|
+
detail: sanitizeDisplaySingleLine(agent.description),
|
|
1481
|
+
dot: agent.disabled ? "muted" : "success",
|
|
1482
|
+
disabled: agent.disabled ? "Disabled · space to enable" : undefined,
|
|
1483
|
+
facts: {
|
|
1484
|
+
model: agent.overrideModel ? agent.overrideModel : [span("auto", "dim")],
|
|
1485
|
+
prewalk: prewalk ?? [span("off", "dim")],
|
|
1486
|
+
advisor: advisor ?? [span("off", "dim")],
|
|
1487
|
+
source: SOURCE_LABEL[agent.source],
|
|
1488
|
+
},
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
/** Chip text of a configuration strip, without the ANSI state glyphs (the chip's `on` carries state). */
|
|
1493
|
+
#stripChipLabel(agent: HubAgent, chip: StripChip): string {
|
|
1494
|
+
const action = chip.action;
|
|
1495
|
+
if (action.kind === "toggle") return agent.disabled ? "Enable" : "Disable";
|
|
1496
|
+
if (action.kind === "property") return `${action.property}: ${this.#propertySummary(agent, action.property)}`;
|
|
1497
|
+
return chip.label;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
#stripChipOn(agent: HubAgent, property: PropertyKind | undefined, chip: StripChip): boolean | undefined {
|
|
1501
|
+
const action = chip.action;
|
|
1502
|
+
if (action.kind !== "set" || action.property === "model" || !property) return undefined;
|
|
1503
|
+
return this.#overrideFor(agent, property)?.toLowerCase() === action.value;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
/** Preview of the selected agent: description, effective settings, system prompt. */
|
|
1507
|
+
#describePreview(rowDef: ListRow | undefined): NativeChild[] {
|
|
1508
|
+
if (!rowDef) return [];
|
|
1509
|
+
if (rowDef.kind === "new") {
|
|
1510
|
+
return [
|
|
1511
|
+
text("New agent", { role: "omp.picker.title" }),
|
|
1512
|
+
md(
|
|
1513
|
+
"Describe what the agent should do; the architect drafts its name, when to use it and its system prompt.",
|
|
1514
|
+
),
|
|
1515
|
+
];
|
|
1516
|
+
}
|
|
1517
|
+
const agent = rowDef.agent;
|
|
1518
|
+
const patterns = this.#deps.effectiveModelPatterns(agent);
|
|
1519
|
+
const resolved = this.#deps.resolvePatterns(patterns);
|
|
1520
|
+
const model: TspSpan[] = [patterns.length > 0 ? span(patterns.join(","), "mono") : span("session model", "dim")];
|
|
1521
|
+
if (resolved) model.push(span(" → ", "dim"), span(resolved, "mono success"));
|
|
1522
|
+
const prewalk = this.#deps.effectivePrewalkPattern(agent);
|
|
1523
|
+
const advisor = this.#deps.effectiveAdvisorPattern(agent);
|
|
1524
|
+
const facts: { k: string; v: TspSpan[] | string }[] = [
|
|
1525
|
+
{ k: "Model", v: model },
|
|
1526
|
+
{ k: "Prewalk", v: [prewalk ? span(prewalk, "mono") : span("off", "dim")] },
|
|
1527
|
+
{ k: "Advisor", v: [advisor ? span(advisor, "mono") : span("off", "dim")] },
|
|
1528
|
+
{ k: "Status", v: [agent.disabled ? span("Disabled", "warning") : span("Enabled", "success")] },
|
|
1529
|
+
{ k: "Source", v: SOURCE_LABEL[agent.source] },
|
|
1530
|
+
];
|
|
1531
|
+
if (agent.filePath) {
|
|
1532
|
+
// Bundled agents live in the binary (`embedded:…`): nothing to open.
|
|
1533
|
+
const href = agent.filePath.startsWith("/") ? { href: `file://${agent.filePath}` } : undefined;
|
|
1534
|
+
facts.push({ k: "File", v: [span(shortenPath(agent.filePath), "path", href)] });
|
|
1535
|
+
}
|
|
1536
|
+
const out: NativeChild[] = [
|
|
1537
|
+
node("text", { text: agent.name, role: "omp.picker.title" }, undefined, "title"),
|
|
1538
|
+
node("md", { text: agent.description }, undefined, "description"),
|
|
1539
|
+
node("kv", { items: facts, layout: "grid" }, undefined, "facts"),
|
|
1540
|
+
];
|
|
1541
|
+
if (agent.systemPrompt.trim()) {
|
|
1542
|
+
out.push(
|
|
1543
|
+
node(
|
|
1544
|
+
"section",
|
|
1545
|
+
{ head: "System prompt", role: "omp.agents.prompt" },
|
|
1546
|
+
[code(agent.systemPrompt, { lang: "md", wrap: true })],
|
|
1547
|
+
"prompt",
|
|
1548
|
+
),
|
|
1549
|
+
);
|
|
1550
|
+
}
|
|
1551
|
+
return out;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
#describeBody(): NativeNode {
|
|
1555
|
+
const children: NativeChild[] = [
|
|
1556
|
+
node("text", { spans: this.#statusSpans(), truncate: "end" }, undefined, "status"),
|
|
1557
|
+
];
|
|
1558
|
+
if (this.#createActive) {
|
|
1559
|
+
children.push(...this.#describeCreate());
|
|
1560
|
+
} else if (this.#assigning) {
|
|
1561
|
+
this.#browser.setFocused(true);
|
|
1562
|
+
children.push(this.#browser);
|
|
1563
|
+
} else {
|
|
1564
|
+
children.push(...this.#describeList());
|
|
1565
|
+
}
|
|
1566
|
+
return node("col", { gap: "sm", grow: 1 }, children, "body");
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
#statusSpans(): TspSpan[] {
|
|
1570
|
+
if (this.#loadError) return [span(this.#loadError, "error")];
|
|
1571
|
+
if (this.#assigning) {
|
|
1572
|
+
const { agent, property } = this.#assigning;
|
|
1573
|
+
const what = property === "model" ? "model override" : `${property} model`;
|
|
1574
|
+
return [span(`Picking ${what} for `, "accent"), span(agent.name, "accent strong")];
|
|
1575
|
+
}
|
|
1576
|
+
if (this.#createActive) return [span("New agent — describe it and let the architect draft it", "accent")];
|
|
1577
|
+
if (this.#notice) return [span(this.#notice, "success")];
|
|
1578
|
+
const entry = this.#activeEntry();
|
|
1579
|
+
const scopeLabel = entry.kind === "source" ? `${entry.label} agents` : "All agents";
|
|
1580
|
+
const count = this.#rows.filter(rowDef => rowDef.kind === "agent").length;
|
|
1581
|
+
return [span(`${scopeLabel} · ${count}`, "muted")];
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
#describeList(): NativeNode[] {
|
|
1585
|
+
const search = node(
|
|
1586
|
+
"text",
|
|
1587
|
+
{
|
|
1588
|
+
spans: [
|
|
1589
|
+
span("search: ", "muted"),
|
|
1590
|
+
this.#search.getValue() ? span(this.#search.getValue(), "accent") : span("type to filter", "dim"),
|
|
1591
|
+
],
|
|
1592
|
+
truncate: "end",
|
|
1593
|
+
},
|
|
1594
|
+
undefined,
|
|
1595
|
+
"search",
|
|
1596
|
+
);
|
|
1597
|
+
const items = this.#rows.map(rowDef =>
|
|
1598
|
+
rowDef.kind === "new"
|
|
1599
|
+
? node("item", { label: [span("+ New agent…", "dim")] }, undefined, listRowId(rowDef))
|
|
1600
|
+
: this.#describeAgentItem(rowDef.agent),
|
|
1601
|
+
);
|
|
1602
|
+
const selectedRow = this.#rows[this.#rowIndex];
|
|
1603
|
+
const list = node(
|
|
1604
|
+
"list",
|
|
1605
|
+
{
|
|
1606
|
+
selected: selectedRow ? listRowId(selectedRow) : null,
|
|
1607
|
+
filter: this.#search.getValue() || undefined,
|
|
1608
|
+
virtual: true,
|
|
1609
|
+
grow: 1,
|
|
1610
|
+
tone: this.#focus === "list" ? "accent" : undefined,
|
|
1611
|
+
aria: "Agents",
|
|
1612
|
+
},
|
|
1613
|
+
items,
|
|
1614
|
+
"agents",
|
|
1615
|
+
);
|
|
1616
|
+
return [search, list, this.#describeDetail()];
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
#describeAgentItem(agent: HubAgent): NativeNode {
|
|
1620
|
+
const value: TspSpan[] = [];
|
|
1621
|
+
const badge = (t: string, s: string): void => {
|
|
1622
|
+
if (value.length > 0) value.push(span(" "));
|
|
1623
|
+
value.push(span(t, s));
|
|
1624
|
+
};
|
|
1625
|
+
if (agent.overrideModel) badge(agent.overrideModel, "warning");
|
|
1626
|
+
const prewalk = this.#deps.effectivePrewalkPattern(agent);
|
|
1627
|
+
if (prewalk) badge(`pre:${prewalk}`, "dim");
|
|
1628
|
+
const advisor = this.#deps.effectiveAdvisorPattern(agent);
|
|
1629
|
+
if (advisor) badge(`adv:${advisor}`, "dim");
|
|
1630
|
+
return node(
|
|
1631
|
+
"item",
|
|
1632
|
+
{
|
|
1633
|
+
label: [
|
|
1634
|
+
agent.disabled ? span(`${theme.status.disabled} `, "dim") : span(`${theme.status.enabled} `, "success"),
|
|
1635
|
+
span(agent.name, agent.disabled ? "dim" : "strong"),
|
|
1636
|
+
],
|
|
1637
|
+
detail: [span(SOURCE_LABEL[agent.source].toLowerCase(), "dim")],
|
|
1638
|
+
value: value.length > 0 ? value : undefined,
|
|
1639
|
+
tone: agent.disabled ? "muted" : undefined,
|
|
1640
|
+
},
|
|
1641
|
+
undefined,
|
|
1642
|
+
listRowId({ kind: "agent", agent }),
|
|
1643
|
+
);
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
/** Selected-agent detail block under the list. */
|
|
1647
|
+
#describeDetail(): NativeNode {
|
|
1648
|
+
const agent = this.#selectedAgent();
|
|
1649
|
+
if (!agent) {
|
|
1650
|
+
return node("section", {}, [text([span("Select an agent to inspect", "dim")])], "detail");
|
|
1651
|
+
}
|
|
1652
|
+
const patterns = this.#deps.effectiveModelPatterns(agent);
|
|
1653
|
+
const resolved = this.#deps.resolvePatterns(patterns);
|
|
1654
|
+
const model: TspSpan[] = [patterns.length > 0 ? span(patterns.join(",")) : span("(session model)", "dim")];
|
|
1655
|
+
if (resolved) model.push(span(" → ", "dim"), span(resolved, "success"));
|
|
1656
|
+
const prewalk = this.#deps.effectivePrewalkPattern(agent);
|
|
1657
|
+
const advisor = this.#deps.effectiveAdvisorPattern(agent);
|
|
1658
|
+
const children: NativeChild[] = [
|
|
1659
|
+
text([span(agent.description, "dim")], { wrap: "word", lines: 2 }),
|
|
1660
|
+
node("kv", {
|
|
1661
|
+
items: [
|
|
1662
|
+
{ k: [span("model", "muted")], v: model },
|
|
1663
|
+
{ k: [span("prewalk", "muted")], v: [prewalk ? span(prewalk, "success") : span("off", "dim")] },
|
|
1664
|
+
{ k: [span("advisor", "muted")], v: [advisor ? span(advisor, "success") : span("off", "dim")] },
|
|
1665
|
+
],
|
|
1666
|
+
layout: "inline",
|
|
1667
|
+
}),
|
|
1668
|
+
];
|
|
1669
|
+
if (agent.filePath) children.push(text([span(shortenPath(agent.filePath), "path dim")], { truncate: "middle" }));
|
|
1670
|
+
return node("section", { head: [span(agent.name, "accent strong")] }, children, "detail");
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
#describeCreate(): NativeChild[] {
|
|
1674
|
+
const nodes: NativeChild[] = [];
|
|
1675
|
+
const spec = this.#createSpec;
|
|
1676
|
+
if (spec) {
|
|
1677
|
+
nodes.push(
|
|
1678
|
+
text([span("Review generated agent", "accent strong")]),
|
|
1679
|
+
node("kv", {
|
|
1680
|
+
items: [
|
|
1681
|
+
{ k: [span("Identifier", "muted")], v: [span(spec.identifier, "code")] },
|
|
1682
|
+
{ k: [span("Scope", "muted")], v: [span(this.#createScope, "accent")] },
|
|
1683
|
+
],
|
|
1684
|
+
}),
|
|
1685
|
+
node("section", { head: [span("whenToUse", "muted")] }, [text(spec.whenToUse, { wrap: "word", lines: 6 })]),
|
|
1686
|
+
node(
|
|
1687
|
+
"card",
|
|
1688
|
+
{
|
|
1689
|
+
head: [span("System prompt", "muted")],
|
|
1690
|
+
collapsible: true,
|
|
1691
|
+
collapsed: this.#promptCollapsed,
|
|
1692
|
+
preview: { lines: 8 },
|
|
1693
|
+
},
|
|
1694
|
+
[md(spec.systemPrompt)],
|
|
1695
|
+
"prompt",
|
|
1696
|
+
),
|
|
1697
|
+
);
|
|
1698
|
+
} else {
|
|
1699
|
+
nodes.push(
|
|
1700
|
+
text([span("Create new agent", "accent strong")]),
|
|
1701
|
+
text([span("Describe what the agent should do; scope: ", "muted"), span(this.#createScope, "accent")], {
|
|
1702
|
+
wrap: "word",
|
|
1703
|
+
}),
|
|
1704
|
+
);
|
|
1705
|
+
if (this.#createInput && !this.#createGenerating) {
|
|
1706
|
+
nodes.push(this.#createInput);
|
|
1707
|
+
}
|
|
1708
|
+
if (this.#createGenerating) {
|
|
1709
|
+
nodes.push(node("spinner", { label: "Generating…" }, undefined, "generating"));
|
|
1710
|
+
if (this.#createStreamingText) {
|
|
1711
|
+
nodes.push(
|
|
1712
|
+
node("code", { text: this.#createStreamingText, lang: "json", wrap: true }, undefined, "stream"),
|
|
1713
|
+
);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
if (this.#createError) {
|
|
1718
|
+
nodes.push(node("text", { text: this.#createError, tone: "error", wrap: "word" }, undefined, "error"));
|
|
1719
|
+
}
|
|
1720
|
+
return nodes;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
/** Styled spans of one footer chip, from its action rather than its ANSI label. */
|
|
1724
|
+
#chipSpans(agent: HubAgent, property: PropertyKind | undefined, chip: StripChip): TspSpan[] {
|
|
1725
|
+
const action = chip.action;
|
|
1726
|
+
switch (action.kind) {
|
|
1727
|
+
case "toggle":
|
|
1728
|
+
return chip.label === "enable"
|
|
1729
|
+
? [span(`${theme.status.enabled} enable`, "success")]
|
|
1730
|
+
: [span(`${theme.status.disabled} disable`, "dim")];
|
|
1731
|
+
case "property":
|
|
1732
|
+
return [span(action.property, "accent"), span(`: ${this.#propertySummary(agent, action.property)}`, "dim")];
|
|
1733
|
+
case "set": {
|
|
1734
|
+
if (action.property === "model") return [span(chip.label, "warning")];
|
|
1735
|
+
const current = property ? this.#overrideFor(agent, property)?.toLowerCase() : undefined;
|
|
1736
|
+
return current === action.value
|
|
1737
|
+
? [span(`${theme.status.enabled} ${chip.label}`, "accent")]
|
|
1738
|
+
: [span(chip.label, "muted")];
|
|
1739
|
+
}
|
|
1740
|
+
case "pick":
|
|
1741
|
+
return [span(chip.label, "accent")];
|
|
1742
|
+
case "pattern":
|
|
1743
|
+
return [span(chip.label, "muted")];
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
#describeStrip(): NativeNode | undefined {
|
|
1748
|
+
const strip = this.#strip;
|
|
1749
|
+
if (!strip) return undefined;
|
|
1750
|
+
if (strip.kind === "pattern") {
|
|
1751
|
+
return node(
|
|
1752
|
+
"row",
|
|
1753
|
+
{ gap: "sm", align: "center" },
|
|
1754
|
+
[text([span(`${strip.agent.name} ${strip.property} pattern:`, "accent")]), col([strip.input], { grow: 1 })],
|
|
1755
|
+
"pattern",
|
|
1756
|
+
);
|
|
1757
|
+
}
|
|
1758
|
+
const prefix: TspSpan[] = strip.property
|
|
1759
|
+
? [span(strip.agent.name, "accent"), span(` · ${strip.property} →`, "dim")]
|
|
1760
|
+
: [span(strip.agent.name, "accent"), span(" →", "dim")];
|
|
1761
|
+
return row(
|
|
1762
|
+
[
|
|
1763
|
+
text(prefix),
|
|
1764
|
+
node(
|
|
1765
|
+
"tabs",
|
|
1766
|
+
{
|
|
1767
|
+
items: strip.chips.map((chip, index) => ({
|
|
1768
|
+
id: String(index),
|
|
1769
|
+
label: this.#chipSpans(strip.agent, strip.property, chip),
|
|
1770
|
+
})),
|
|
1771
|
+
active: String(strip.index),
|
|
1772
|
+
actions: { click: "activate" },
|
|
1773
|
+
},
|
|
1774
|
+
undefined,
|
|
1775
|
+
"strip",
|
|
1776
|
+
),
|
|
1777
|
+
],
|
|
1778
|
+
{ gap: "sm", align: "center" },
|
|
1779
|
+
);
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
#footerHints(): (NativeHint | undefined)[] {
|
|
1783
|
+
const cancel = (label: string) => actionHint("tui.select.cancel", label);
|
|
1784
|
+
const upDown = (label: string) => actionHint(["tui.select.up", "tui.select.down"], label);
|
|
1785
|
+
const strip = this.#strip;
|
|
1786
|
+
if (strip) {
|
|
1787
|
+
if (strip.kind === "pattern") {
|
|
1788
|
+
const values = strip.property === "model" ? "a model pattern" : '"on", "off", or a model pattern';
|
|
1789
|
+
return [
|
|
1790
|
+
{ keys: ["enter"], label: `${values} (role aliases like @smol and :level suffixes work; empty clears)` },
|
|
1791
|
+
cancel("back"),
|
|
1792
|
+
];
|
|
1793
|
+
}
|
|
1794
|
+
return [
|
|
1795
|
+
{ keys: ["left", "right"], label: "choose" },
|
|
1796
|
+
{ keys: ["enter"], label: strip.property ? "apply" : "open" },
|
|
1797
|
+
cancel(strip.property ? "back" : "cancel"),
|
|
1798
|
+
];
|
|
1799
|
+
}
|
|
1800
|
+
if (this.#assigning) {
|
|
1801
|
+
return [
|
|
1802
|
+
{ keys: ["enter"], label: "pick" },
|
|
1803
|
+
upDown("models"),
|
|
1804
|
+
{ keys: [], label: "type to search" },
|
|
1805
|
+
cancel("cancel"),
|
|
1806
|
+
];
|
|
1807
|
+
}
|
|
1808
|
+
if (this.#createActive) {
|
|
1809
|
+
if (this.#createSpec) {
|
|
1810
|
+
return [
|
|
1811
|
+
{ keys: ["enter"], label: "save" },
|
|
1812
|
+
{ keys: ["tab"], label: "scope" },
|
|
1813
|
+
{ keys: ["r"], label: "regenerate" },
|
|
1814
|
+
cancel("cancel"),
|
|
1815
|
+
];
|
|
1816
|
+
}
|
|
1817
|
+
if (this.#createGenerating) return [];
|
|
1818
|
+
return [
|
|
1819
|
+
{ keys: boundKeys("app.message.followUp", ["ctrl+q", "ctrl+enter"]), label: "generate" },
|
|
1820
|
+
{ keys: ["enter"], label: "newline" },
|
|
1821
|
+
{ keys: ["tab"], label: "scope" },
|
|
1822
|
+
cancel("cancel"),
|
|
1823
|
+
];
|
|
1824
|
+
}
|
|
1825
|
+
if (this.#focus === "scope") {
|
|
1826
|
+
return [upDown("scopes"), { keys: ["right", "enter"], label: "agents" }, cancel("close")];
|
|
1827
|
+
}
|
|
1828
|
+
return [
|
|
1829
|
+
{ keys: ["enter"], label: "configure" },
|
|
1830
|
+
{ keys: ["space"], label: "enable/disable" },
|
|
1831
|
+
upDown("rows"),
|
|
1832
|
+
{ keys: [], label: "type to search" },
|
|
1833
|
+
{ keys: ["ctrl+r"], label: "reload" },
|
|
1834
|
+
cancel("close"),
|
|
1835
|
+
];
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1203
1838
|
render(width: number): readonly string[] {
|
|
1204
1839
|
return this.#frame.render(width, this.#terminalRows(), this.#entries, this.#renderFooter(width - 4));
|
|
1205
1840
|
}
|