@oh-my-pi/pi-tui 18.2.4 → 18.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +43 -0
- package/dist/types/app-keybindings.d.ts +395 -0
- package/dist/types/apps/autoresearch-dashboard.d.ts +43 -0
- package/dist/types/apps/autoresearch-data.d.ts +15 -0
- package/dist/types/apps/cleanse-board.d.ts +66 -0
- package/dist/types/apps/cleanse-picker.d.ts +23 -0
- package/dist/types/apps/debug/log-formatting.d.ts +6 -0
- package/dist/types/apps/debug/log-viewer.d.ts +81 -0
- package/dist/types/apps/debug/protocol-probe.d.ts +42 -0
- package/dist/types/apps/debug/raw-sse-buffer.d.ts +58 -0
- package/dist/types/apps/debug/raw-sse.d.ts +26 -0
- package/dist/types/apps/debug/terminal-info.d.ts +34 -0
- package/dist/types/apps/debug/viewer-frame.d.ts +52 -0
- package/dist/types/apps/git/avatar.d.ts +9 -0
- package/dist/types/apps/git/colors.d.ts +49 -0
- package/dist/types/apps/git/diff-pane.d.ts +188 -0
- package/dist/types/apps/git/git-tui.d.ts +66 -0
- package/dist/types/apps/git/sidebar.d.ts +149 -0
- package/dist/types/apps/git/state.d.ts +117 -0
- package/dist/types/apps/if-bench-board.d.ts +75 -0
- package/dist/types/apps/live-visualizer.d.ts +33 -0
- package/dist/types/apps/ps-data.d.ts +51 -0
- package/dist/types/apps/ps-top.d.ts +33 -0
- package/dist/types/apps/session-picker.d.ts +26 -0
- package/dist/types/apps/setup-model-picker.d.ts +13 -0
- package/dist/types/apps/standalone-picker.d.ts +42 -0
- package/dist/types/autocomplete.d.ts +4 -0
- package/dist/types/chat/advisor-message.d.ts +11 -0
- package/dist/types/chat/assistant-message.d.ts +106 -0
- package/dist/types/chat/background-tan-message.d.ts +9 -0
- package/dist/types/chat/bash-execution.d.ts +47 -0
- package/dist/types/chat/cache-invalidation-marker.d.ts +50 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +50 -0
- package/dist/types/chat/collab-prompt-message.d.ts +10 -0
- package/dist/types/chat/compaction-summary-message.d.ts +54 -0
- package/dist/types/chat/custom-message.d.ts +10 -0
- package/dist/types/chat/display-preferences.d.ts +13 -0
- package/dist/types/chat/eval-execution.d.ts +29 -0
- package/dist/types/chat/execution-shared.d.ts +51 -0
- package/dist/types/chat/extension-types.d.ts +28 -0
- package/dist/types/chat/hook-message.d.ts +10 -0
- package/dist/types/chat/image-loading.d.ts +46 -0
- package/dist/types/chat/late-diagnostics-message.d.ts +21 -0
- package/dist/types/chat/messages.d.ts +189 -0
- package/dist/types/chat/reaction.d.ts +30 -0
- package/dist/types/chat/read-target.d.ts +4 -0
- package/dist/types/chat/read-tool-group.d.ts +67 -0
- package/dist/types/chat/served-model-marker.d.ts +47 -0
- package/dist/types/chat/skill-message.d.ts +33 -0
- package/dist/types/chat/skill-title-input.d.ts +14 -0
- package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +12 -0
- package/dist/types/chat/thinking-display.d.ts +12 -0
- package/dist/types/chat/todo-reminder.d.ts +13 -0
- package/dist/types/chat/tool-execution.d.ts +138 -0
- package/dist/types/chat/transcript-browser.d.ts +93 -0
- package/dist/types/chat/transcript-entry.d.ts +45 -0
- package/dist/types/chat/transcript-outline.d.ts +86 -0
- package/dist/types/chat/transcript-render-helpers.d.ts +92 -0
- package/dist/types/chat/ttsr-notification.d.ts +23 -0
- package/dist/types/chat/user-message.d.ts +52 -0
- package/dist/types/chrome/chat-block.d.ts +64 -0
- package/dist/types/chrome/collab-qrcode.d.ts +28 -0
- package/dist/types/chrome/context-thresholds.d.ts +10 -0
- package/dist/types/chrome/countdown-timer.d.ts +14 -0
- package/dist/types/chrome/diff.d.ts +14 -0
- package/dist/types/chrome/dynamic-border.d.ts +16 -0
- package/dist/types/chrome/error-block.d.ts +17 -0
- package/dist/types/chrome/form-theme.d.ts +3 -0
- package/dist/types/chrome/format.d.ts +12 -0
- package/dist/types/chrome/index.d.ts +20 -0
- package/dist/types/chrome/keybinding-hints.d.ts +40 -0
- package/dist/types/chrome/live-board.d.ts +23 -0
- package/dist/types/chrome/local-date.d.ts +4 -0
- package/dist/types/chrome/message-divider.d.ts +22 -0
- package/dist/types/chrome/message-frame.d.ts +52 -0
- package/dist/types/chrome/message-notice.d.ts +35 -0
- package/dist/types/chrome/overlay-box.d.ts +74 -0
- package/dist/types/chrome/qrcode.d.ts +48 -0
- package/dist/types/chrome/segment-track.d.ts +27 -0
- package/dist/types/chrome/select-list-mouse-routing.d.ts +4 -0
- package/dist/types/chrome/selector-helpers.d.ts +52 -0
- package/dist/types/chrome/shared.d.ts +5 -0
- package/dist/types/chrome/streaming-panel.d.ts +19 -0
- package/dist/types/chrome/tool-activity.d.ts +17 -0
- package/dist/types/chrome/transcript-container.d.ts +129 -0
- package/dist/types/chrome/transcript-status.d.ts +12 -0
- package/dist/types/chrome/visual-truncate.d.ts +19 -0
- package/dist/types/components/disclosure.d.ts +42 -0
- package/dist/types/components/form.d.ts +130 -0
- package/dist/types/components/key-value-list.d.ts +24 -0
- package/dist/types/components/layout/geometry.d.ts +73 -0
- package/dist/types/components/layout/row.d.ts +55 -0
- package/dist/types/components/layout/split-pane.d.ts +80 -0
- package/dist/types/components/layout/stack.d.ts +50 -0
- package/dist/types/components/menu-selection.d.ts +71 -0
- package/dist/types/components/metric.d.ts +44 -0
- package/dist/types/components/progress-bar.d.ts +36 -0
- package/dist/types/components/scroll-view.d.ts +53 -19
- package/dist/types/components/scroll-viewport.d.ts +46 -0
- package/dist/types/components/section.d.ts +19 -0
- package/dist/types/components/select-list.d.ts +46 -2
- package/dist/types/components/settings-list.d.ts +20 -0
- package/dist/types/components/table.d.ts +32 -0
- package/dist/types/components/tree-view.d.ts +130 -0
- package/dist/types/components/wizard-step.d.ts +60 -0
- package/dist/types/hotkeys-markdown.d.ts +7 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/keybinding-matchers.d.ts +35 -0
- package/dist/types/keys.d.ts +2 -2
- package/dist/types/lang-from-path.d.ts +9 -0
- package/dist/types/overlays/advisor-config.d.ts +114 -0
- package/dist/types/overlays/agent-activity.d.ts +41 -0
- package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
- package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
- package/dist/types/overlays/agent-hub-types.d.ts +99 -0
- package/dist/types/overlays/agent-hub.d.ts +126 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
- package/dist/types/overlays/agents-hub.d.ts +72 -0
- package/dist/types/overlays/ask-dialog.d.ts +88 -0
- package/dist/types/overlays/bordered-loader.d.ts +11 -0
- package/dist/types/overlays/btw-history-panel.d.ts +29 -0
- package/dist/types/overlays/btw-history.d.ts +17 -0
- package/dist/types/overlays/btw-panel.d.ts +26 -0
- package/dist/types/overlays/cleanse-panel.d.ts +36 -0
- package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
- package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
- package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
- package/dist/types/overlays/copy-selector.d.ts +48 -0
- package/dist/types/overlays/copy-targets.d.ts +63 -0
- package/dist/types/overlays/error-banner.d.ts +13 -0
- package/dist/types/overlays/extensions/display-text.d.ts +10 -0
- package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
- package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
- package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
- package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
- package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
- package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
- package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
- package/dist/types/overlays/extensions/types.d.ts +165 -0
- package/dist/types/overlays/history-search.d.ts +16 -0
- package/dist/types/overlays/hook-editor.d.ts +44 -0
- package/dist/types/overlays/hook-input.d.ts +20 -0
- package/dist/types/overlays/hook-selector.d.ts +71 -0
- package/dist/types/overlays/hub-frame.d.ts +77 -0
- package/dist/types/overlays/login-dialog.d.ts +43 -0
- package/dist/types/overlays/logout-account-selector.d.ts +15 -0
- package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
- package/dist/types/overlays/model-browser.d.ts +213 -0
- package/dist/types/overlays/model-hub.d.ts +72 -0
- package/dist/types/overlays/model-picker.d.ts +74 -0
- package/dist/types/overlays/model-selector.d.ts +52 -0
- package/dist/types/overlays/move-overlay.d.ts +39 -0
- package/dist/types/overlays/oauth-selector.d.ts +41 -0
- package/dist/types/overlays/omfg-panel.d.ts +20 -0
- package/dist/types/overlays/pause-screen.d.ts +43 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
- package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
- package/dist/types/overlays/plan-toc.d.ts +41 -0
- package/dist/types/overlays/plugin-selector.d.ts +28 -0
- package/dist/types/overlays/plugin-settings.d.ts +180 -0
- package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
- package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
- package/dist/types/overlays/rewind-selector.d.ts +61 -0
- package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
- package/dist/types/overlays/session-account-selector.d.ts +24 -0
- package/dist/types/overlays/session-info-overlay.d.ts +17 -0
- package/dist/types/overlays/session-observer-registry.d.ts +77 -0
- package/dist/types/overlays/session-selector.d.ts +131 -0
- package/dist/types/overlays/settings-defs.d.ts +119 -0
- package/dist/types/overlays/settings-selector.d.ts +73 -0
- package/dist/types/overlays/show-images-selector.d.ts +11 -0
- package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
- package/dist/types/overlays/theme-selector.d.ts +12 -0
- package/dist/types/overlays/thinking-selector.d.ts +12 -0
- package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
- package/dist/types/overlays/tree-selector.d.ts +92 -0
- package/dist/types/overlays/usage-dashboard.d.ts +94 -0
- package/dist/types/overlays/usage-display.d.ts +5 -0
- package/dist/types/overlays/usage-row.d.ts +17 -0
- package/dist/types/prompt/attachment-chips.d.ts +19 -0
- package/dist/types/prompt/composer-attachments.d.ts +71 -0
- package/dist/types/prompt/composer-cache.d.ts +37 -0
- package/dist/types/prompt/composer.d.ts +159 -0
- package/dist/types/prompt/custom-editor.d.ts +261 -0
- package/dist/types/prompt/editor-top-gap.d.ts +18 -0
- package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
- package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
- package/dist/types/prompt/gradient-highlight.d.ts +32 -0
- package/dist/types/prompt/image-format.d.ts +4 -0
- package/dist/types/prompt/image-references.d.ts +26 -0
- package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
- package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
- package/dist/types/prompt/macos-spelling.d.ts +44 -0
- package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
- package/dist/types/prompt/magic-keywords.d.ts +26 -0
- package/dist/types/prompt/markdown-prose.d.ts +15 -0
- package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
- package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
- package/dist/types/prompt/orchestrate.d.ts +13 -0
- package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
- package/dist/types/prompt/queue-input.d.ts +8 -0
- package/dist/types/prompt/skill-tokens.d.ts +13 -0
- package/dist/types/prompt/tools-markdown.d.ts +12 -0
- package/dist/types/prompt/ultrathink.d.ts +13 -0
- package/dist/types/prompt/usage-amounts.d.ts +26 -0
- package/dist/types/prompt/video.d.ts +18 -0
- package/dist/types/prompt/welcome.d.ts +83 -0
- package/dist/types/prompt/workflow.d.ts +13 -0
- package/dist/types/render/code-cell.d.ts +51 -0
- package/dist/types/render/file-list.d.ts +22 -0
- package/dist/types/render/hyperlink.d.ts +80 -0
- package/dist/types/render/index.d.ts +16 -0
- package/dist/types/render/output-block.d.ts +54 -0
- package/dist/types/render/output-pane.d.ts +80 -0
- package/dist/types/render/render-utils.d.ts +312 -0
- package/dist/types/render/sixel.d.ts +21 -0
- package/dist/types/render/status-line.d.ts +23 -0
- package/dist/types/render/tool-card.d.ts +71 -0
- package/dist/types/render/tree-list.d.ts +29 -0
- package/dist/types/render/types.d.ts +17 -0
- package/dist/types/render/utils.d.ts +43 -0
- package/dist/types/render/width-aware-text.d.ts +23 -0
- package/dist/types/setup/lazy.d.ts +3 -0
- package/dist/types/setup/scenes/composer.d.ts +3 -0
- package/dist/types/setup/scenes/glyph.d.ts +3 -0
- package/dist/types/setup/scenes/model.d.ts +3 -0
- package/dist/types/setup/scenes/outro.d.ts +2 -0
- package/dist/types/setup/scenes/providers.d.ts +3 -0
- package/dist/types/setup/scenes/sign-in.d.ts +21 -0
- package/dist/types/setup/scenes/splash.d.ts +11 -0
- package/dist/types/setup/scenes/theme.d.ts +3 -0
- package/dist/types/setup/scenes/types.d.ts +110 -0
- package/dist/types/setup/scenes/web-search.d.ts +22 -0
- package/dist/types/setup/setup-version.d.ts +11 -0
- package/dist/types/setup/startup-splash.d.ts +9 -0
- package/dist/types/setup/wizard-overlay.d.ts +16 -0
- package/dist/types/setup/wizard.d.ts +25 -0
- package/dist/types/status-line/component.d.ts +182 -0
- package/dist/types/status-line/context-usage.d.ts +156 -0
- package/dist/types/status-line/footer.d.ts +30 -0
- package/dist/types/status-line/git-utils.d.ts +22 -0
- package/dist/types/status-line/host.d.ts +129 -0
- package/dist/types/status-line/index.d.ts +6 -0
- package/dist/types/status-line/loop.d.ts +18 -0
- package/dist/types/status-line/metrics.d.ts +21 -0
- package/dist/types/status-line/presets.d.ts +3 -0
- package/dist/types/status-line/schema.d.ts +15 -0
- package/dist/types/status-line/segments.d.ts +5 -0
- package/dist/types/status-line/separators.d.ts +3 -0
- package/dist/types/status-line/types.d.ts +236 -0
- package/dist/types/stdin-buffer.d.ts +4 -0
- package/dist/types/theme/color.d.ts +24 -0
- package/dist/types/theme/defaults/index.d.ts +9489 -0
- package/dist/types/theme/index.d.ts +4 -0
- package/dist/types/theme/loader.d.ts +23 -0
- package/dist/types/theme/mermaid-cache.d.ts +26 -0
- package/dist/types/theme/schema-validation.d.ts +3 -0
- package/dist/types/theme/schema.d.ts +25 -0
- package/dist/types/theme/session-color.d.ts +43 -0
- package/dist/types/theme/shimmer.d.ts +44 -0
- package/dist/types/theme/symbols.d.ts +34 -0
- package/dist/types/theme/theme-class.d.ts +299 -0
- package/dist/types/theme/theme.d.ts +111 -0
- package/dist/types/theme/tui-adapters.d.ts +30 -0
- package/dist/types/thinking.d.ts +165 -0
- package/dist/types/tools/agent-tree.d.ts +36 -0
- package/dist/types/tools/ask.d.ts +67 -0
- package/dist/types/tools/ast-edit.d.ts +53 -0
- package/dist/types/tools/ast-grep.d.ts +52 -0
- package/dist/types/tools/autoresearch.d.ts +156 -0
- package/dist/types/tools/bash-interactive.d.ts +28 -0
- package/dist/types/tools/bash.d.ts +103 -0
- package/dist/types/tools/conflict-detect.d.ts +43 -0
- package/dist/types/tools/debug.d.ts +60 -0
- package/dist/types/tools/default-renderer.d.ts +24 -0
- package/dist/types/tools/edit.d.ts +158 -0
- package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
- package/dist/types/tools/eval-format/index.d.ts +5 -0
- package/dist/types/tools/eval-format/javascript.d.ts +2 -0
- package/dist/types/tools/eval-format/python.d.ts +2 -0
- package/dist/types/tools/eval.d.ts +94 -0
- package/dist/types/tools/fetch.d.ts +42 -0
- package/dist/types/tools/gh-format.d.ts +8 -0
- package/dist/types/tools/github.d.ts +144 -0
- package/dist/types/tools/glob.d.ts +44 -0
- package/dist/types/tools/goal.d.ts +42 -0
- package/dist/types/tools/grep.d.ts +64 -0
- package/dist/types/tools/grouped-file-output.d.ts +71 -0
- package/dist/types/tools/hashline-format.d.ts +28 -0
- package/dist/types/tools/hub.d.ts +340 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/json-tree.d.ts +59 -0
- package/dist/types/tools/line-ranges.d.ts +29 -0
- package/dist/types/tools/list-limit.d.ts +15 -0
- package/dist/types/tools/lsp.d.ts +72 -0
- package/dist/types/tools/match-line-format.d.ts +11 -0
- package/dist/types/tools/mcp.d.ts +81 -0
- package/dist/types/tools/memory.d.ts +67 -0
- package/dist/types/tools/output-meta.d.ts +151 -0
- package/dist/types/tools/read.d.ts +139 -0
- package/dist/types/tools/renderer.d.ts +98 -0
- package/dist/types/tools/report-tool-issue.d.ts +8 -0
- package/dist/types/tools/resolve.d.ts +47 -0
- package/dist/types/tools/streaming-output.d.ts +282 -0
- package/dist/types/tools/subprocess.d.ts +24 -0
- package/dist/types/tools/task-repair-args.d.ts +53 -0
- package/dist/types/tools/task-yield-assembly.d.ts +20 -0
- package/dist/types/tools/task.d.ts +425 -0
- package/dist/types/tools/terminal-output.d.ts +8 -0
- package/dist/types/tools/think.d.ts +13 -0
- package/dist/types/tools/todo.d.ts +118 -0
- package/dist/types/tools/tool-errors.d.ts +7 -0
- package/dist/types/tools/vibe.d.ts +120 -0
- package/dist/types/tools/web-search.d.ts +195 -0
- package/dist/types/tools/write.d.ts +76 -0
- package/dist/types/tools/xd-url.d.ts +13 -0
- package/dist/types/tools/xdev.d.ts +52 -0
- package/dist/types/tui.d.ts +18 -0
- package/dist/types/utils.d.ts +2 -0
- package/package.json +37 -3
- package/src/app-keybindings.ts +760 -0
- package/src/apps/autoresearch-dashboard.ts +500 -0
- package/src/apps/autoresearch-data.ts +64 -0
- package/src/apps/cleanse-board.ts +341 -0
- package/src/apps/cleanse-picker.ts +57 -0
- package/src/apps/debug/log-formatting.ts +53 -0
- package/src/apps/debug/log-viewer.ts +868 -0
- package/src/apps/debug/protocol-probe.ts +267 -0
- package/src/apps/debug/raw-sse-buffer.ts +449 -0
- package/src/apps/debug/raw-sse.ts +282 -0
- package/src/apps/debug/terminal-info.ts +115 -0
- package/src/apps/debug/viewer-frame.ts +174 -0
- package/src/apps/git/avatar.ts +52 -0
- package/src/apps/git/colors.ts +109 -0
- package/src/apps/git/diff-pane.ts +1512 -0
- package/src/apps/git/git-tui.ts +889 -0
- package/src/apps/git/sidebar.ts +1204 -0
- package/src/apps/git/state.ts +113 -0
- package/src/apps/if-bench-board.ts +324 -0
- package/src/apps/live-visualizer.ts +238 -0
- package/src/apps/ps-data.ts +116 -0
- package/src/apps/ps-top.ts +422 -0
- package/src/apps/session-picker.ts +95 -0
- package/src/apps/setup-model-picker.ts +21 -0
- package/src/apps/standalone-picker.ts +111 -0
- package/src/autocomplete.ts +9 -13
- package/src/chat/advisor-message.ts +175 -0
- package/src/chat/assistant-message.ts +1214 -0
- package/src/chat/background-tan-message.ts +35 -0
- package/src/chat/bash-execution.ts +394 -0
- package/src/chat/cache-invalidation-marker.ts +94 -0
- package/src/chat/chat-transcript-builder.ts +593 -0
- package/src/chat/collab-prompt-message.ts +34 -0
- package/src/chat/compaction-summary-message.ts +261 -0
- package/src/chat/custom-message.ts +23 -0
- package/src/chat/display-preferences.ts +24 -0
- package/src/chat/eval-execution.ts +172 -0
- package/src/chat/execution-shared.ts +113 -0
- package/src/chat/extension-types.ts +46 -0
- package/src/chat/hook-message.ts +20 -0
- package/src/chat/image-loading.ts +122 -0
- package/src/chat/late-diagnostics-message.ts +92 -0
- package/src/chat/messages.ts +305 -0
- package/src/chat/reaction.ts +65 -0
- package/src/chat/read-target.ts +7 -0
- package/src/chat/read-tool-group.ts +873 -0
- package/src/chat/served-model-marker.ts +91 -0
- package/src/chat/skill-message.ts +220 -0
- package/src/chat/skill-title-input.ts +41 -0
- package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
- package/src/chat/thinking-display.ts +312 -0
- package/src/chat/todo-reminder.ts +33 -0
- package/src/chat/tool-execution.ts +1395 -0
- package/src/chat/transcript-browser.ts +268 -0
- package/src/chat/transcript-entry.ts +96 -0
- package/src/chat/transcript-outline.ts +260 -0
- package/src/chat/transcript-render-helpers.ts +315 -0
- package/src/chat/ttsr-notification.ts +123 -0
- package/src/chat/user-message.ts +287 -0
- package/src/chrome/chat-block.ts +110 -0
- package/src/chrome/collab-qrcode.ts +74 -0
- package/src/chrome/context-thresholds.ts +85 -0
- package/src/chrome/countdown-timer.ts +74 -0
- package/src/chrome/diff.ts +266 -0
- package/src/chrome/dynamic-border.ts +36 -0
- package/src/chrome/error-block.ts +63 -0
- package/src/chrome/form-theme.ts +10 -0
- package/src/chrome/format.ts +66 -0
- package/src/chrome/index.ts +21 -0
- package/src/chrome/keybinding-hints.ts +55 -0
- package/src/chrome/live-board.ts +123 -0
- package/src/chrome/local-date.ts +20 -0
- package/src/chrome/message-divider.ts +51 -0
- package/src/chrome/message-frame.ts +164 -0
- package/src/chrome/message-notice.ts +103 -0
- package/src/chrome/overlay-box.ts +301 -0
- package/src/chrome/qrcode.ts +539 -0
- package/src/chrome/segment-track.ts +86 -0
- package/src/chrome/select-list-mouse-routing.ts +11 -0
- package/src/chrome/selector-helpers.ts +119 -0
- package/src/chrome/shared.ts +27 -0
- package/src/chrome/streaming-panel.ts +72 -0
- package/src/chrome/tool-activity.ts +44 -0
- package/src/chrome/transcript-container.ts +902 -0
- package/src/chrome/transcript-status.ts +27 -0
- package/src/chrome/visual-truncate.ts +70 -0
- package/src/components/disclosure.ts +235 -0
- package/src/components/editor.ts +10 -12
- package/src/components/form.ts +566 -0
- package/src/components/input.ts +6 -27
- package/src/components/key-value-list.ts +88 -0
- package/src/components/layout/geometry.ts +202 -0
- package/src/components/layout/row.ts +283 -0
- package/src/components/layout/split-pane.ts +349 -0
- package/src/components/layout/stack.ts +261 -0
- package/src/components/markdown.ts +16 -12
- package/src/components/menu-selection.ts +248 -0
- package/src/components/metric.ts +132 -0
- package/src/components/progress-bar.ts +140 -0
- package/src/components/scroll-view.ts +372 -70
- package/src/components/scroll-viewport.ts +154 -0
- package/src/components/section.ts +77 -0
- package/src/components/select-list.ts +238 -159
- package/src/components/settings-list.ts +103 -80
- package/src/components/table.ts +127 -0
- package/src/components/tree-view.ts +481 -0
- package/src/components/wizard-step.ts +229 -0
- package/src/deccara.ts +1 -3
- package/src/hotkeys-markdown.ts +100 -0
- package/src/index.ts +18 -0
- package/src/keybinding-matchers.ts +99 -0
- package/src/keys.ts +2 -2
- package/src/lang-from-path.ts +252 -0
- package/src/overlays/advisor-config.ts +761 -0
- package/src/overlays/agent-activity.ts +113 -0
- package/src/overlays/agent-hub-projection.ts +250 -0
- package/src/overlays/agent-hub-renderer.ts +281 -0
- package/src/overlays/agent-hub-types.ts +74 -0
- package/src/overlays/agent-hub.ts +1562 -0
- package/src/overlays/agent-transcript-viewer.ts +669 -0
- package/src/overlays/agents-hub.ts +1203 -0
- package/src/overlays/ask-dialog.ts +1202 -0
- package/src/overlays/bordered-loader.ts +41 -0
- package/src/overlays/btw-history-panel.ts +591 -0
- package/src/overlays/btw-history.ts +33 -0
- package/src/overlays/btw-panel.ts +167 -0
- package/src/overlays/cleanse-panel.ts +167 -0
- package/src/overlays/codex-reset-fireworks.ts +375 -0
- package/src/overlays/composer-shape-preview.ts +137 -0
- package/src/overlays/composer-shape-registry.ts +82 -0
- package/src/overlays/copy-selector.ts +618 -0
- package/src/overlays/copy-targets.ts +210 -0
- package/src/overlays/error-banner.ts +39 -0
- package/src/overlays/extensions/display-text.ts +39 -0
- package/src/overlays/extensions/extension-dashboard.ts +645 -0
- package/src/overlays/extensions/extension-list.ts +667 -0
- package/src/overlays/extensions/inspector-model.ts +484 -0
- package/src/overlays/extensions/inspector-panel.ts +669 -0
- package/src/overlays/extensions/live-tool-session.ts +67 -0
- package/src/overlays/extensions/mcp-runtime.ts +289 -0
- package/src/overlays/extensions/state-manager.ts +337 -0
- package/src/overlays/extensions/types.ts +208 -0
- package/src/overlays/history-search.ts +268 -0
- package/src/overlays/hook-editor.ts +272 -0
- package/src/overlays/hook-input.ts +84 -0
- package/src/overlays/hook-selector.ts +635 -0
- package/src/overlays/hub-frame.ts +262 -0
- package/src/overlays/login-dialog.ts +231 -0
- package/src/overlays/logout-account-selector.ts +115 -0
- package/src/overlays/mcp-add-wizard.ts +1436 -0
- package/src/overlays/model-browser.ts +1176 -0
- package/src/overlays/model-hub.ts +2279 -0
- package/src/overlays/model-picker.ts +285 -0
- package/src/overlays/model-selector.ts +107 -0
- package/src/overlays/move-overlay.ts +197 -0
- package/src/overlays/oauth-selector.ts +446 -0
- package/src/overlays/omfg-panel.ts +136 -0
- package/src/overlays/pause-screen.ts +198 -0
- package/src/overlays/plan-review-overlay.ts +1227 -0
- package/src/overlays/plan-save-overlay.ts +74 -0
- package/src/overlays/plan-toc.ts +139 -0
- package/src/overlays/plugin-selector.ts +97 -0
- package/src/overlays/plugin-settings.ts +839 -0
- package/src/overlays/queue-mode-selector.ts +55 -0
- package/src/overlays/reset-usage-selector.ts +170 -0
- package/src/overlays/rewind-selector.ts +499 -0
- package/src/overlays/running-subagent-badge.ts +19 -0
- package/src/overlays/session-account-selector.ts +68 -0
- package/src/overlays/session-info-overlay.ts +96 -0
- package/src/overlays/session-observer-registry.ts +289 -0
- package/src/overlays/session-selector.ts +1137 -0
- package/src/overlays/settings-defs.ts +315 -0
- package/src/overlays/settings-selector.ts +1415 -0
- package/src/overlays/show-images-selector.ts +44 -0
- package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
- package/src/overlays/snapcompact-shape-preview.ts +192 -0
- package/src/overlays/theme-selector.ts +62 -0
- package/src/overlays/thinking-selector.ts +51 -0
- package/src/overlays/tiny-title-download-progress.ts +102 -0
- package/src/overlays/tree-selector.ts +1121 -0
- package/src/overlays/usage-dashboard.ts +629 -0
- package/src/overlays/usage-display.ts +45 -0
- package/src/overlays/usage-row.ts +118 -0
- package/src/prompt/attachment-chips.ts +201 -0
- package/src/prompt/composer-attachments.ts +280 -0
- package/src/prompt/composer-cache.ts +304 -0
- package/src/prompt/composer.ts +934 -0
- package/src/prompt/custom-editor.ts +1392 -0
- package/src/prompt/data/emojis.json +1 -0
- package/src/prompt/editor-top-gap.ts +28 -0
- package/src/prompt/emoji-autocomplete.ts +285 -0
- package/src/prompt/github-ref-autocomplete.ts +75 -0
- package/src/prompt/gradient-highlight.ts +101 -0
- package/src/prompt/image-format.ts +28 -0
- package/src/prompt/image-references.ts +102 -0
- package/src/prompt/interactive-context-helpers.ts +126 -0
- package/src/prompt/internal-url-autocomplete.ts +155 -0
- package/src/prompt/macos-spelling.ts +456 -0
- package/src/prompt/magic-keyword-boundary.ts +23 -0
- package/src/prompt/magic-keywords.ts +42 -0
- package/src/prompt/markdown-prose.ts +245 -0
- package/src/prompt/model-mention-autocomplete.ts +94 -0
- package/src/prompt/model-mention-syntax.ts +41 -0
- package/src/prompt/orchestrate.ts +26 -0
- package/src/prompt/prompt-action-autocomplete.ts +337 -0
- package/src/prompt/queue-input.ts +132 -0
- package/src/prompt/skill-tokens.ts +36 -0
- package/src/prompt/tips.txt +27 -0
- package/src/prompt/tools-markdown.ts +29 -0
- package/src/prompt/ultrathink.ts +26 -0
- package/src/prompt/usage-amounts.ts +99 -0
- package/src/prompt/video.ts +47 -0
- package/src/prompt/welcome.ts +605 -0
- package/src/prompt/workflow.ts +26 -0
- package/src/render/code-cell.ts +244 -0
- package/src/render/file-list.ts +58 -0
- package/src/render/hyperlink.ts +192 -0
- package/src/render/index.ts +17 -0
- package/src/render/output-block.ts +267 -0
- package/src/render/output-pane.ts +299 -0
- package/src/render/render-utils.ts +1182 -0
- package/src/render/sixel.ts +69 -0
- package/src/render/status-line.ts +55 -0
- package/src/render/tool-card.ts +272 -0
- package/src/render/tree-list.ts +188 -0
- package/src/render/types.ts +19 -0
- package/src/render/utils.ts +109 -0
- package/src/render/width-aware-text.ts +60 -0
- package/src/setup/lazy.ts +17 -0
- package/src/setup/scenes/composer.ts +127 -0
- package/src/setup/scenes/glyph.ts +120 -0
- package/src/setup/scenes/model.ts +138 -0
- package/src/setup/scenes/outro.ts +24 -0
- package/src/setup/scenes/providers.ts +107 -0
- package/src/setup/scenes/sign-in.ts +373 -0
- package/src/setup/scenes/splash.ts +192 -0
- package/src/setup/scenes/theme.ts +343 -0
- package/src/setup/scenes/types.ts +111 -0
- package/src/setup/scenes/web-search.ts +165 -0
- package/src/setup/setup-version.ts +11 -0
- package/src/setup/startup-splash.ts +107 -0
- package/src/setup/wizard-overlay.ts +319 -0
- package/src/setup/wizard.ts +101 -0
- package/src/status-line/component.ts +3003 -0
- package/src/status-line/context-usage.ts +688 -0
- package/src/status-line/footer.ts +323 -0
- package/src/status-line/git-utils.ts +42 -0
- package/src/status-line/host.ts +97 -0
- package/src/status-line/index.ts +6 -0
- package/src/status-line/loop.ts +28 -0
- package/src/status-line/metrics.ts +94 -0
- package/src/status-line/presets.ts +107 -0
- package/src/status-line/schema.ts +57 -0
- package/src/status-line/segments.ts +934 -0
- package/src/status-line/separators.ts +55 -0
- package/src/status-line/types.ts +227 -0
- package/src/stdin-buffer.ts +4 -2
- package/src/theme/color.ts +95 -0
- package/src/theme/dark.json +95 -0
- package/src/theme/defaults/alabaster.json +93 -0
- package/src/theme/defaults/amethyst.json +96 -0
- package/src/theme/defaults/anthracite.json +93 -0
- package/src/theme/defaults/basalt.json +91 -0
- package/src/theme/defaults/birch.json +95 -0
- package/src/theme/defaults/dark-abyss.json +91 -0
- package/src/theme/defaults/dark-arctic.json +104 -0
- package/src/theme/defaults/dark-aurora.json +95 -0
- package/src/theme/defaults/dark-catppuccin.json +107 -0
- package/src/theme/defaults/dark-cavern.json +91 -0
- package/src/theme/defaults/dark-celestial.json +106 -0
- package/src/theme/defaults/dark-copper.json +95 -0
- package/src/theme/defaults/dark-cosmos.json +90 -0
- package/src/theme/defaults/dark-cyberpunk.json +102 -0
- package/src/theme/defaults/dark-dracula.json +98 -0
- package/src/theme/defaults/dark-eclipse.json +91 -0
- package/src/theme/defaults/dark-ember.json +95 -0
- package/src/theme/defaults/dark-equinox.json +90 -0
- package/src/theme/defaults/dark-forest.json +96 -0
- package/src/theme/defaults/dark-github.json +105 -0
- package/src/theme/defaults/dark-gruvbox.json +112 -0
- package/src/theme/defaults/dark-lavender.json +95 -0
- package/src/theme/defaults/dark-lunar.json +89 -0
- package/src/theme/defaults/dark-midnight.json +95 -0
- package/src/theme/defaults/dark-monochrome.json +94 -0
- package/src/theme/defaults/dark-monokai.json +98 -0
- package/src/theme/defaults/dark-nebula.json +90 -0
- package/src/theme/defaults/dark-nord.json +98 -0
- package/src/theme/defaults/dark-ocean.json +101 -0
- package/src/theme/defaults/dark-one.json +100 -0
- package/src/theme/defaults/dark-poimandres.json +115 -0
- package/src/theme/defaults/dark-rainforest.json +91 -0
- package/src/theme/defaults/dark-reef.json +91 -0
- package/src/theme/defaults/dark-retro.json +92 -0
- package/src/theme/defaults/dark-rose-pine.json +96 -0
- package/src/theme/defaults/dark-sakura.json +95 -0
- package/src/theme/defaults/dark-slate.json +95 -0
- package/src/theme/defaults/dark-solarized.json +97 -0
- package/src/theme/defaults/dark-solstice.json +90 -0
- package/src/theme/defaults/dark-starfall.json +91 -0
- package/src/theme/defaults/dark-sunset.json +99 -0
- package/src/theme/defaults/dark-swamp.json +90 -0
- package/src/theme/defaults/dark-synthwave.json +103 -0
- package/src/theme/defaults/dark-taiga.json +91 -0
- package/src/theme/defaults/dark-terminal.json +95 -0
- package/src/theme/defaults/dark-tokyo-night.json +101 -0
- package/src/theme/defaults/dark-tundra.json +91 -0
- package/src/theme/defaults/dark-twilight.json +91 -0
- package/src/theme/defaults/dark-volcanic.json +91 -0
- package/src/theme/defaults/graphite.json +92 -0
- package/src/theme/defaults/index.ts +201 -0
- package/src/theme/defaults/light-arctic.json +107 -0
- package/src/theme/defaults/light-aurora-day.json +91 -0
- package/src/theme/defaults/light-canyon.json +91 -0
- package/src/theme/defaults/light-catppuccin.json +106 -0
- package/src/theme/defaults/light-cirrus.json +90 -0
- package/src/theme/defaults/light-coral.json +95 -0
- package/src/theme/defaults/light-cyberpunk.json +96 -0
- package/src/theme/defaults/light-dawn.json +90 -0
- package/src/theme/defaults/light-dunes.json +91 -0
- package/src/theme/defaults/light-eucalyptus.json +95 -0
- package/src/theme/defaults/light-forest.json +100 -0
- package/src/theme/defaults/light-frost.json +95 -0
- package/src/theme/defaults/light-github.json +115 -0
- package/src/theme/defaults/light-glacier.json +91 -0
- package/src/theme/defaults/light-gruvbox.json +108 -0
- package/src/theme/defaults/light-haze.json +90 -0
- package/src/theme/defaults/light-honeycomb.json +95 -0
- package/src/theme/defaults/light-lagoon.json +91 -0
- package/src/theme/defaults/light-lavender.json +95 -0
- package/src/theme/defaults/light-meadow.json +91 -0
- package/src/theme/defaults/light-mint.json +95 -0
- package/src/theme/defaults/light-monochrome.json +101 -0
- package/src/theme/defaults/light-ocean.json +99 -0
- package/src/theme/defaults/light-one.json +99 -0
- package/src/theme/defaults/light-opal.json +91 -0
- package/src/theme/defaults/light-orchard.json +91 -0
- package/src/theme/defaults/light-paper.json +95 -0
- package/src/theme/defaults/light-poimandres.json +115 -0
- package/src/theme/defaults/light-prism.json +90 -0
- package/src/theme/defaults/light-retro.json +98 -0
- package/src/theme/defaults/light-sand.json +95 -0
- package/src/theme/defaults/light-savanna.json +91 -0
- package/src/theme/defaults/light-solarized.json +102 -0
- package/src/theme/defaults/light-soleil.json +90 -0
- package/src/theme/defaults/light-sunset.json +99 -0
- package/src/theme/defaults/light-synthwave.json +98 -0
- package/src/theme/defaults/light-tokyo-night.json +111 -0
- package/src/theme/defaults/light-wetland.json +91 -0
- package/src/theme/defaults/light-zenith.json +89 -0
- package/src/theme/defaults/limestone.json +94 -0
- package/src/theme/defaults/mahogany.json +97 -0
- package/src/theme/defaults/marble.json +93 -0
- package/src/theme/defaults/obsidian.json +91 -0
- package/src/theme/defaults/onyx.json +91 -0
- package/src/theme/defaults/pearl.json +93 -0
- package/src/theme/defaults/porcelain.json +91 -0
- package/src/theme/defaults/quartz.json +96 -0
- package/src/theme/defaults/sandstone.json +95 -0
- package/src/theme/defaults/titanium.json +90 -0
- package/src/theme/index.ts +5 -0
- package/src/theme/light.json +93 -0
- package/src/theme/loader.ts +200 -0
- package/src/theme/mermaid-cache.ts +92 -0
- package/src/theme/schema-validation.ts +119 -0
- package/src/theme/schema.ts +168 -0
- package/src/theme/session-color.ts +253 -0
- package/src/theme/shimmer.ts +307 -0
- package/src/theme/symbols.ts +1433 -0
- package/src/theme/theme-class.ts +787 -0
- package/src/theme/theme-schema.json +463 -0
- package/src/theme/theme.ts +810 -0
- package/src/theme/tui-adapters.ts +339 -0
- package/src/thinking.ts +380 -0
- package/src/tools/agent-tree.ts +128 -0
- package/src/tools/ask.ts +482 -0
- package/src/tools/ast-edit.ts +210 -0
- package/src/tools/ast-grep.ts +171 -0
- package/src/tools/autoresearch.ts +287 -0
- package/src/tools/bash-interactive.ts +295 -0
- package/src/tools/bash.ts +468 -0
- package/src/tools/conflict-detect.ts +77 -0
- package/src/tools/debug.ts +167 -0
- package/src/tools/default-renderer.ts +172 -0
- package/src/tools/edit.ts +1258 -0
- package/src/tools/eval-format/code-mode-declarations.ts +61 -0
- package/src/tools/eval-format/index.ts +16 -0
- package/src/tools/eval-format/javascript.ts +952 -0
- package/src/tools/eval-format/python.ts +544 -0
- package/src/tools/eval.ts +835 -0
- package/src/tools/fetch.ts +226 -0
- package/src/tools/gh-format.ts +18 -0
- package/src/tools/github.ts +686 -0
- package/src/tools/glob.ts +213 -0
- package/src/tools/goal.ts +153 -0
- package/src/tools/grep.ts +385 -0
- package/src/tools/grouped-file-output.ts +211 -0
- package/src/tools/hashline-format.ts +59 -0
- package/src/tools/hub.ts +1488 -0
- package/src/tools/index.ts +71 -0
- package/src/tools/json-tree.ts +388 -0
- package/src/tools/line-ranges.ts +98 -0
- package/src/tools/list-limit.ts +43 -0
- package/src/tools/lsp.ts +702 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/mcp.ts +309 -0
- package/src/tools/memory.ts +220 -0
- package/src/tools/output-meta.ts +367 -0
- package/src/tools/read.ts +628 -0
- package/src/tools/renderer.ts +107 -0
- package/src/tools/report-tool-issue.ts +13 -0
- package/src/tools/resolve.ts +139 -0
- package/src/tools/streaming-output.ts +1576 -0
- package/src/tools/subprocess.ts +39 -0
- package/src/tools/task-repair-args.ts +118 -0
- package/src/tools/task-yield-assembly.ts +147 -0
- package/src/tools/task.ts +2110 -0
- package/src/tools/terminal-output.ts +153 -0
- package/src/tools/think.ts +28 -0
- package/src/tools/todo.ts +580 -0
- package/src/tools/tool-errors.ts +15 -0
- package/src/tools/vibe.ts +420 -0
- package/src/tools/web-search.ts +409 -0
- package/src/tools/write.ts +511 -0
- package/src/tools/xd-url.ts +28 -0
- package/src/tools/xdev.ts +201 -0
- package/src/tui.ts +57 -4
- package/src/utils.ts +8 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import type { Component } from "../tui";
|
|
2
|
+
import { Text } from "../components/text";
|
|
3
|
+
import type { RenderResultOptions, ToolRenderer } from "./renderer";
|
|
4
|
+
import { type Theme } from "../theme/theme";
|
|
5
|
+
import type { OutputMeta } from "./output-meta";
|
|
6
|
+
import type { TruncationResult } from "./streaming-output";
|
|
7
|
+
import { toPathList } from "../render/render-utils";
|
|
8
|
+
import {
|
|
9
|
+
Ellipsis,
|
|
10
|
+
fileHyperlink,
|
|
11
|
+
getTreeBranch,
|
|
12
|
+
getTreeContinuePrefix,
|
|
13
|
+
renderStatusLine,
|
|
14
|
+
renderTreeList,
|
|
15
|
+
truncateToWidth,
|
|
16
|
+
uriHyperlink,
|
|
17
|
+
} from "../render";
|
|
18
|
+
import {
|
|
19
|
+
createCachedComponent,
|
|
20
|
+
formatCount,
|
|
21
|
+
formatEmptyMessage,
|
|
22
|
+
formatErrorMessage,
|
|
23
|
+
formatMoreItems,
|
|
24
|
+
PREVIEW_LIMITS,
|
|
25
|
+
replaceTabs,
|
|
26
|
+
} from "../render/render-utils";
|
|
27
|
+
import { classifyGroupedLines, groupLineIndicesByBlank } from "./grouped-file-output";
|
|
28
|
+
|
|
29
|
+
/** Display metadata for grep tool results. */
|
|
30
|
+
export interface GrepToolDetails {
|
|
31
|
+
truncation?: TruncationResult;
|
|
32
|
+
fileLimitReached?: number;
|
|
33
|
+
perFileLimitReached?: number;
|
|
34
|
+
linesTruncated?: boolean;
|
|
35
|
+
meta?: OutputMeta;
|
|
36
|
+
scopePath?: string;
|
|
37
|
+
matchCount?: number;
|
|
38
|
+
fileCount?: number;
|
|
39
|
+
files?: string[];
|
|
40
|
+
fileMatches?: Array<{ path: string; count: number }>;
|
|
41
|
+
truncated?: boolean;
|
|
42
|
+
error?: string;
|
|
43
|
+
/** Pre-formatted text for the user-visible TUI render. Mirrors the model-facing
|
|
44
|
+
* `result.text` lines but uses a `│` gutter and `*` to mark match lines (vs space for
|
|
45
|
+
* context). The TUI uses this directly so it never parses model-facing hashline anchors. */
|
|
46
|
+
displayContent?: string;
|
|
47
|
+
/** Filesystem hyperlink targets resolved for internal URL headers at execution time. */
|
|
48
|
+
displayTargets?: Record<string, string>;
|
|
49
|
+
/** Absolute base directory used during search. Used by the renderer to resolve
|
|
50
|
+
* display-relative paths to absolute paths for OSC 8 hyperlinks. */
|
|
51
|
+
searchPath?: string;
|
|
52
|
+
/** Session cwd at search time. The renderer resolves the display-relative
|
|
53
|
+
* (cwd-relative) header/match paths against this for OSC 8 hyperlinks;
|
|
54
|
+
* `searchPath` is the scope label target, not the display-path base. */
|
|
55
|
+
cwd?: string;
|
|
56
|
+
/** User-supplied paths whose base directory was missing on disk. The tool
|
|
57
|
+
* skipped these and continued with the surviving entries; surfaced as a
|
|
58
|
+
* non-fatal warning in the renderer and in the model-facing text. */
|
|
59
|
+
missingPaths?: string[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// =============================================================================
|
|
63
|
+
// TUI Renderer
|
|
64
|
+
// =============================================================================
|
|
65
|
+
|
|
66
|
+
interface GrepRenderArgs {
|
|
67
|
+
pattern: string;
|
|
68
|
+
path?: string | string[];
|
|
69
|
+
/** Legacy pre-`path` argument name; kept so historical transcripts still render a scope. */
|
|
70
|
+
paths?: string | string[];
|
|
71
|
+
case?: boolean;
|
|
72
|
+
gitignore?: boolean;
|
|
73
|
+
skip?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const COLLAPSED_TEXT_LIMIT = PREVIEW_LIMITS.COLLAPSED_LINES * 2;
|
|
77
|
+
/** Line budget for the expanded view. Larger than collapsed so expanding
|
|
78
|
+
* reveals more matches with context, but still bounded so a single hot file
|
|
79
|
+
* whose matches span the whole file can't dump its entire length. */
|
|
80
|
+
const EXPANDED_TEXT_LIMIT = PREVIEW_LIMITS.EXPANDED_LINES * 2;
|
|
81
|
+
|
|
82
|
+
const SEARCH_CODE_FRAME_LINE_RE = /^\s*\*?(\d+)│/;
|
|
83
|
+
|
|
84
|
+
function searchScopeMeta(details: GrepToolDetails | undefined): string | undefined {
|
|
85
|
+
if (!details?.scopePath) return undefined;
|
|
86
|
+
const label = details.searchPath ? fileHyperlink(details.searchPath, details.scopePath) : details.scopePath;
|
|
87
|
+
return `in ${label}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function linkUrlLikeSearchHeader(
|
|
91
|
+
raw: string,
|
|
92
|
+
styled: string,
|
|
93
|
+
resolvedPath?: string,
|
|
94
|
+
): { line: string; absPath?: string } {
|
|
95
|
+
if (resolvedPath) return { line: fileHyperlink(resolvedPath, styled), absPath: resolvedPath };
|
|
96
|
+
return { line: uriHyperlink(raw, styled) };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function parseSearchDisplayLineNumber(line: string): number | undefined {
|
|
100
|
+
const match = SEARCH_CODE_FRAME_LINE_RE.exec(line);
|
|
101
|
+
if (!match) return undefined;
|
|
102
|
+
return Number.parseInt(match[1]!, 10);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const SEARCH_MATCH_LINE_RE = /^\s*\*\d+(?:│|[:|])/;
|
|
106
|
+
|
|
107
|
+
interface RenderedSearchLine {
|
|
108
|
+
raw: string;
|
|
109
|
+
styled: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function isSearchMatchLine(line: string): boolean {
|
|
113
|
+
return SEARCH_MATCH_LINE_RE.test(line);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function isSearchHeaderLine(line: string): boolean {
|
|
117
|
+
return /^#+ /.test(line);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const URL_HEADER_PREFIX_RE = /^#+\s+/;
|
|
121
|
+
|
|
122
|
+
function renderSearchDisplayLines(
|
|
123
|
+
lines: readonly string[],
|
|
124
|
+
headerBase: string | undefined,
|
|
125
|
+
fileScope: string | undefined,
|
|
126
|
+
uiTheme: Theme,
|
|
127
|
+
displayTargets: Record<string, string> | undefined,
|
|
128
|
+
): RenderedSearchLine[] {
|
|
129
|
+
const contexts = classifyGroupedLines(lines, headerBase, fileScope);
|
|
130
|
+
// `classifyGroupedLines` can't resolve internal URLs (TUI-only), so track the
|
|
131
|
+
// resolved URL target here and use it for the body lines that follow.
|
|
132
|
+
let urlFile: string | undefined;
|
|
133
|
+
return lines.map((line, index) => {
|
|
134
|
+
const ctx = contexts[index]!;
|
|
135
|
+
if (ctx.kind === "dir") {
|
|
136
|
+
urlFile = undefined;
|
|
137
|
+
const styled = uiTheme.fg("accent", line);
|
|
138
|
+
return { raw: line, styled: ctx.headerPath ? fileHyperlink(ctx.headerPath, styled) : styled };
|
|
139
|
+
}
|
|
140
|
+
if (ctx.kind === "file") {
|
|
141
|
+
if (ctx.isUrl) {
|
|
142
|
+
const raw = line
|
|
143
|
+
.replace(URL_HEADER_PREFIX_RE, "")
|
|
144
|
+
.trimEnd()
|
|
145
|
+
.replace(/\s+\([^)]*\)\s*$/, "");
|
|
146
|
+
const linked = linkUrlLikeSearchHeader(raw, uiTheme.fg("accent", line), displayTargets?.[raw]);
|
|
147
|
+
urlFile = linked.absPath;
|
|
148
|
+
return { raw: line, styled: linked.line };
|
|
149
|
+
}
|
|
150
|
+
urlFile = undefined;
|
|
151
|
+
// Root-level files keep the bright accent; nested file headers are dimmed.
|
|
152
|
+
const styled = uiTheme.fg(ctx.depth === 1 ? "accent" : "dim", line);
|
|
153
|
+
return { raw: line, styled: ctx.headerPath ? fileHyperlink(ctx.headerPath, styled) : styled };
|
|
154
|
+
}
|
|
155
|
+
const styled = uiTheme.fg("toolOutput", line);
|
|
156
|
+
const lineNumber = parseSearchDisplayLineNumber(line);
|
|
157
|
+
const filePath = ctx.filePath ?? urlFile;
|
|
158
|
+
return {
|
|
159
|
+
raw: line,
|
|
160
|
+
styled: filePath && lineNumber !== undefined ? fileHyperlink(filePath, styled, { line: lineNumber }) : styled,
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function compactSearchPreviewGroup(group: RenderedSearchLine[]): RenderedSearchLine[] {
|
|
166
|
+
const compact = group.filter(line => isSearchHeaderLine(line.raw) || isSearchMatchLine(line.raw));
|
|
167
|
+
return compact.length > 0 ? compact : group;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function countPreviewMatches(lines: readonly RenderedSearchLine[], hasMarkedMatches: boolean): number {
|
|
171
|
+
if (hasMarkedMatches) return lines.reduce((count, line) => count + (isSearchMatchLine(line.raw) ? 1 : 0), 0);
|
|
172
|
+
return lines.reduce((count, line) => count + (!isSearchHeaderLine(line.raw) && line.raw.length > 0 ? 1 : 0), 0);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function renderBudgetedSearchGroups(
|
|
176
|
+
groups: RenderedSearchLine[][],
|
|
177
|
+
maxLines: number,
|
|
178
|
+
matchCount: number,
|
|
179
|
+
uiTheme: Theme,
|
|
180
|
+
compact: boolean,
|
|
181
|
+
): string[] {
|
|
182
|
+
if (maxLines <= 0) return [];
|
|
183
|
+
const renderedGroups = groups
|
|
184
|
+
.map(group => (compact ? compactSearchPreviewGroup(group) : group))
|
|
185
|
+
.filter(group => group.length > 0);
|
|
186
|
+
if (renderedGroups.length === 0) return [];
|
|
187
|
+
|
|
188
|
+
let totalLines = 0;
|
|
189
|
+
let totalMarkedMatches = 0;
|
|
190
|
+
let totalFallbackMatches = 0;
|
|
191
|
+
for (const group of renderedGroups) {
|
|
192
|
+
totalLines += group.length;
|
|
193
|
+
totalMarkedMatches += countPreviewMatches(group, true);
|
|
194
|
+
totalFallbackMatches += countPreviewMatches(group, false);
|
|
195
|
+
}
|
|
196
|
+
const hasMarkedMatches = totalMarkedMatches > 0;
|
|
197
|
+
const needsSummary = totalLines > maxLines;
|
|
198
|
+
const contentBudget = needsSummary ? Math.max(maxLines - 1, 0) : maxLines;
|
|
199
|
+
const visibleGroups: RenderedSearchLine[][] = [];
|
|
200
|
+
let visibleLineCount = 0;
|
|
201
|
+
let visibleMatches = 0;
|
|
202
|
+
for (const group of renderedGroups) {
|
|
203
|
+
if (visibleLineCount >= contentBudget) break;
|
|
204
|
+
const available = contentBudget - visibleLineCount;
|
|
205
|
+
const take = Math.min(group.length, available);
|
|
206
|
+
if (take <= 0) break;
|
|
207
|
+
const visibleGroup = group.slice(0, take);
|
|
208
|
+
visibleGroups.push(visibleGroup);
|
|
209
|
+
visibleLineCount += visibleGroup.length;
|
|
210
|
+
visibleMatches += countPreviewMatches(visibleGroup, hasMarkedMatches);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const totalMatches = hasMarkedMatches ? totalMarkedMatches : Math.max(matchCount, totalFallbackMatches);
|
|
214
|
+
const hiddenMatches = Math.max(totalMatches - visibleMatches, 0);
|
|
215
|
+
const hiddenLines = Math.max(totalLines - visibleLineCount, 0);
|
|
216
|
+
const hasSummary = needsSummary && (hiddenMatches > 0 || hiddenLines > 0);
|
|
217
|
+
const lines: string[] = [];
|
|
218
|
+
for (let i = 0; i < visibleGroups.length; i++) {
|
|
219
|
+
const group = visibleGroups[i]!;
|
|
220
|
+
const isLast = !hasSummary && i === visibleGroups.length - 1;
|
|
221
|
+
const prefix = `${uiTheme.fg("dim", getTreeBranch(isLast, uiTheme))} `;
|
|
222
|
+
const continuePrefix = uiTheme.fg("dim", getTreeContinuePrefix(isLast, uiTheme));
|
|
223
|
+
lines.push(`${prefix}${replaceTabs(group[0]!.styled)}`);
|
|
224
|
+
for (let j = 1; j < group.length; j++) {
|
|
225
|
+
lines.push(`${continuePrefix}${replaceTabs(group[j]!.styled)}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (hasSummary) {
|
|
229
|
+
const hiddenLabel =
|
|
230
|
+
hiddenMatches > 0 ? formatMoreItems(hiddenMatches, "match") : formatMoreItems(hiddenLines, "line");
|
|
231
|
+
lines.push(`${uiTheme.fg("dim", uiTheme.tree.last)} ${uiTheme.fg("muted", hiddenLabel)}`);
|
|
232
|
+
}
|
|
233
|
+
return lines;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function grepStatusIcon(uiTheme: Theme): string {
|
|
237
|
+
return uiTheme.fg("toolTitle", uiTheme.symbol("icon.search"));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Render grep calls and results in the transcript. */
|
|
241
|
+
export const grepToolRenderer = {
|
|
242
|
+
inline: true,
|
|
243
|
+
renderCall(args: GrepRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
|
|
244
|
+
const paths = toPathList(args.path ?? args.paths);
|
|
245
|
+
const meta: string[] = [];
|
|
246
|
+
if (paths.length) meta.push(`in ${paths.join(", ")}`);
|
|
247
|
+
if (args.case === false) meta.push("case:insensitive");
|
|
248
|
+
if (args.gitignore === false) meta.push("gitignore:false");
|
|
249
|
+
if (args.skip !== undefined && args.skip > 0) meta.push(`skip:${args.skip}`);
|
|
250
|
+
|
|
251
|
+
const text = renderStatusLine(
|
|
252
|
+
{ icon: "pending", title: "Grep", titleColor: "toolTitle", description: args.pattern || "?", meta },
|
|
253
|
+
uiTheme,
|
|
254
|
+
);
|
|
255
|
+
return new Text(text, 1, 0);
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
renderResult(
|
|
259
|
+
result: { content: Array<{ type: string; text?: string }>; details?: GrepToolDetails; isError?: boolean },
|
|
260
|
+
options: RenderResultOptions,
|
|
261
|
+
uiTheme: Theme,
|
|
262
|
+
args?: GrepRenderArgs,
|
|
263
|
+
): Component {
|
|
264
|
+
const details = result.details;
|
|
265
|
+
|
|
266
|
+
if (result.isError || details?.error) {
|
|
267
|
+
const errorText = details?.error || result.content?.find(c => c.type === "text")?.text || "Unknown error";
|
|
268
|
+
return new Text(formatErrorMessage(errorText, uiTheme), 1, 0);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const hasDetailedData = details?.matchCount !== undefined || details?.fileCount !== undefined;
|
|
272
|
+
|
|
273
|
+
if (!hasDetailedData) {
|
|
274
|
+
const textContent = result.details?.displayContent ?? result.content?.find(c => c.type === "text")?.text;
|
|
275
|
+
if (!textContent || textContent === "No matches found") {
|
|
276
|
+
return new Text(formatEmptyMessage("No matches found", uiTheme), 1, 0);
|
|
277
|
+
}
|
|
278
|
+
const lines = textContent.split("\n").filter(line => line.trim() !== "");
|
|
279
|
+
const description = args?.pattern ?? undefined;
|
|
280
|
+
const header = renderStatusLine(
|
|
281
|
+
{
|
|
282
|
+
iconOverride: grepStatusIcon(uiTheme),
|
|
283
|
+
title: "Grep",
|
|
284
|
+
titleColor: "toolTitle",
|
|
285
|
+
description,
|
|
286
|
+
meta: [formatCount("item", lines.length)],
|
|
287
|
+
},
|
|
288
|
+
uiTheme,
|
|
289
|
+
);
|
|
290
|
+
return createCachedComponent(
|
|
291
|
+
() => options.expanded,
|
|
292
|
+
width => {
|
|
293
|
+
const listLines = renderTreeList(
|
|
294
|
+
{
|
|
295
|
+
items: lines,
|
|
296
|
+
expanded: options.expanded,
|
|
297
|
+
maxCollapsed: COLLAPSED_TEXT_LIMIT,
|
|
298
|
+
maxCollapsedLines: COLLAPSED_TEXT_LIMIT,
|
|
299
|
+
itemType: "item",
|
|
300
|
+
renderItem: line => uiTheme.fg("toolOutput", line),
|
|
301
|
+
},
|
|
302
|
+
uiTheme,
|
|
303
|
+
);
|
|
304
|
+
return [header, ...listLines].map(l => truncateToWidth(l, width, Ellipsis.Omit));
|
|
305
|
+
},
|
|
306
|
+
{ paddingX: 1 },
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const matchCount = details?.matchCount ?? 0;
|
|
311
|
+
const fileCount = details?.fileCount ?? 0;
|
|
312
|
+
const truncation = details?.meta?.truncation;
|
|
313
|
+
const limits = details?.meta?.limits;
|
|
314
|
+
const truncated = Boolean(details?.truncated || truncation || limits?.columnTruncated);
|
|
315
|
+
|
|
316
|
+
const missingPathsList = details?.missingPaths ?? [];
|
|
317
|
+
const missingNote =
|
|
318
|
+
missingPathsList.length > 0
|
|
319
|
+
? uiTheme.fg("warning", `skipped missing: ${missingPathsList.join(", ")}`)
|
|
320
|
+
: undefined;
|
|
321
|
+
|
|
322
|
+
if (matchCount === 0) {
|
|
323
|
+
const meta = ["0 matches"];
|
|
324
|
+
const scopeMeta = searchScopeMeta(details);
|
|
325
|
+
if (scopeMeta) meta.push(scopeMeta);
|
|
326
|
+
const header = renderStatusLine(
|
|
327
|
+
{ icon: "warning", title: "Grep", titleColor: "toolTitle", description: args?.pattern, meta },
|
|
328
|
+
uiTheme,
|
|
329
|
+
);
|
|
330
|
+
const lines = [header, formatEmptyMessage("No matches found", uiTheme)];
|
|
331
|
+
if (missingNote) lines.push(missingNote);
|
|
332
|
+
return new Text(lines.join("\n"), 1, 0);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const summaryParts = [formatCount("match", matchCount), formatCount("file", fileCount)];
|
|
336
|
+
const meta = [...summaryParts];
|
|
337
|
+
const scopeMeta = searchScopeMeta(details);
|
|
338
|
+
if (scopeMeta) meta.push(scopeMeta);
|
|
339
|
+
if (truncated) meta.push(uiTheme.fg("warning", "truncated"));
|
|
340
|
+
const description = args?.pattern ?? undefined;
|
|
341
|
+
const header = renderStatusLine(
|
|
342
|
+
{
|
|
343
|
+
...(truncated ? { icon: "warning" as const } : { iconOverride: grepStatusIcon(uiTheme) }),
|
|
344
|
+
title: "Grep",
|
|
345
|
+
titleColor: "toolTitle",
|
|
346
|
+
description,
|
|
347
|
+
meta,
|
|
348
|
+
},
|
|
349
|
+
uiTheme,
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
const textContent = result.details?.displayContent ?? result.content?.find(c => c.type === "text")?.text ?? "";
|
|
353
|
+
const allLines = textContent.split("\n");
|
|
354
|
+
// Resolve hyperlinks once over the whole output so a nested directory stack
|
|
355
|
+
// reconstructs correctly across blank-line group boundaries.
|
|
356
|
+
// Header/match display paths are cwd-relative, so resolve them against cwd
|
|
357
|
+
// (falling back to searchPath for legacy results that predate `cwd`); the
|
|
358
|
+
// scoped file's absolute path seeds body lines in single-file searches.
|
|
359
|
+
const renderedLines = renderSearchDisplayLines(
|
|
360
|
+
allLines,
|
|
361
|
+
details?.cwd ?? details?.searchPath,
|
|
362
|
+
details?.searchPath,
|
|
363
|
+
uiTheme,
|
|
364
|
+
details?.displayTargets,
|
|
365
|
+
);
|
|
366
|
+
const matchGroups = groupLineIndicesByBlank(allLines).map(indices => indices.map(i => renderedLines[i]!));
|
|
367
|
+
|
|
368
|
+
const extraLines: string[] = [];
|
|
369
|
+
if (missingNote) extraLines.push(missingNote);
|
|
370
|
+
|
|
371
|
+
return createCachedComponent(
|
|
372
|
+
() => options.expanded,
|
|
373
|
+
width => {
|
|
374
|
+
const budget = Math.max(
|
|
375
|
+
(options.expanded ? EXPANDED_TEXT_LIMIT : COLLAPSED_TEXT_LIMIT) - extraLines.length,
|
|
376
|
+
0,
|
|
377
|
+
);
|
|
378
|
+
const matchLines = renderBudgetedSearchGroups(matchGroups, budget, matchCount, uiTheme, !options.expanded);
|
|
379
|
+
return [header, ...matchLines, ...extraLines].map(l => truncateToWidth(l, width, Ellipsis.Omit));
|
|
380
|
+
},
|
|
381
|
+
{ paddingX: 1 },
|
|
382
|
+
);
|
|
383
|
+
},
|
|
384
|
+
mergeCallAndResult: true,
|
|
385
|
+
} satisfies ToolRenderer<GrepRenderArgs, GrepToolDetails>;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
|
|
3
|
+
import { buildPathTree, isUrlLikePath, type PathTreeInput, walkPathTree } from "@oh-my-pi/pi-utils";
|
|
4
|
+
|
|
5
|
+
// =============================================================================
|
|
6
|
+
// Grouped file output (grep / ast-grep / ast-edit / lsp diagnostics)
|
|
7
|
+
// =============================================================================
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* One file's contribution to a grouped file output. The header itself is generated
|
|
11
|
+
* by `formatGroupedFiles` (one `#` per nesting level); use `headerSuffix` to tack
|
|
12
|
+
* on extras like ` (1 replacement)`.
|
|
13
|
+
*/
|
|
14
|
+
export interface GroupedFileSection {
|
|
15
|
+
/** Optional suffix appended to the file header. */
|
|
16
|
+
headerSuffix?: string;
|
|
17
|
+
/** Body lines emitted into the textual model output. */
|
|
18
|
+
modelLines: string[];
|
|
19
|
+
/** Body lines emitted into the display output. Defaults to `modelLines`. */
|
|
20
|
+
displayLines?: string[];
|
|
21
|
+
/** When true, the file (and its header) is omitted entirely. */
|
|
22
|
+
skip?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Parallel model-facing and display-facing lines for grouped files. */
|
|
26
|
+
export interface GroupedFilesOutput {
|
|
27
|
+
model: string[];
|
|
28
|
+
display: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Render a list of files as a multi-level, prefix-folded directory tree shared by
|
|
33
|
+
* grep, ast-grep, ast-edit, and the LSP diagnostic formatter.
|
|
34
|
+
*
|
|
35
|
+
* Layout (one `#` per level; the shared prefix folds into the top header):
|
|
36
|
+
* # packages/pkg/src/
|
|
37
|
+
* ## root.ts
|
|
38
|
+
* …body…
|
|
39
|
+
* ## nested/
|
|
40
|
+
* ### child.ts
|
|
41
|
+
* …body…
|
|
42
|
+
*
|
|
43
|
+
* Files in the (folded) project root become single-`#` headers with no parent
|
|
44
|
+
* directory line. A blank line precedes every directory header and every
|
|
45
|
+
* root-level file so the renderers can split the output into collapsible groups.
|
|
46
|
+
*/
|
|
47
|
+
export function formatGroupedFiles(
|
|
48
|
+
files: string[],
|
|
49
|
+
renderFile: (filePath: string) => GroupedFileSection,
|
|
50
|
+
): GroupedFilesOutput {
|
|
51
|
+
const sections = new Map<string, GroupedFileSection>();
|
|
52
|
+
const inputs: PathTreeInput[] = [];
|
|
53
|
+
for (const filePath of files) {
|
|
54
|
+
if (sections.has(filePath)) continue;
|
|
55
|
+
const section = renderFile(filePath);
|
|
56
|
+
if (section.skip) continue;
|
|
57
|
+
sections.set(filePath, section);
|
|
58
|
+
inputs.push({ path: filePath, isDir: false, key: filePath });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const tree = buildPathTree(inputs);
|
|
62
|
+
const model: string[] = [];
|
|
63
|
+
const display: string[] = [];
|
|
64
|
+
let emitted = false;
|
|
65
|
+
|
|
66
|
+
for (const event of walkPathTree(tree)) {
|
|
67
|
+
const hashes = "#".repeat(event.depth + 1);
|
|
68
|
+
const needsSeparator = emitted && (event.depth === 0 || event.kind === "dir");
|
|
69
|
+
if (needsSeparator) {
|
|
70
|
+
model.push("");
|
|
71
|
+
display.push("");
|
|
72
|
+
}
|
|
73
|
+
emitted = true;
|
|
74
|
+
if (event.kind === "dir") {
|
|
75
|
+
const header = `${hashes} ${event.name}/`;
|
|
76
|
+
model.push(header);
|
|
77
|
+
display.push(header);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const section = sections.get(event.key)!;
|
|
81
|
+
const header = `${hashes} ${event.name}${section.headerSuffix ?? ""}`;
|
|
82
|
+
model.push(header, ...section.modelLines);
|
|
83
|
+
display.push(header, ...(section.displayLines ?? section.modelLines));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return { model, display };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// =============================================================================
|
|
90
|
+
// Parsing grouped output back into per-line context (TUI renderers)
|
|
91
|
+
// =============================================================================
|
|
92
|
+
|
|
93
|
+
const GROUPED_HEADER_RE = /^(#+)\s+(.*)$/;
|
|
94
|
+
const HEADER_SUFFIX_RE = /\s+\([^)]*\)\s*$/;
|
|
95
|
+
const HEADER_HASH_TAG_RE = /#[0-9a-f]+$/i;
|
|
96
|
+
|
|
97
|
+
/** Per-line classification of grouped output, used by renderers for hyperlinks. */
|
|
98
|
+
export interface GroupedLineContext {
|
|
99
|
+
/** Directory header, file header, or any non-header body/content line. */
|
|
100
|
+
kind: "dir" | "file" | "content";
|
|
101
|
+
/** Number of leading `#` for headers; 0 for content lines. */
|
|
102
|
+
depth: number;
|
|
103
|
+
/** Resolved absolute path of the dir/file a header points at (when resolvable). */
|
|
104
|
+
headerPath?: string;
|
|
105
|
+
/** For content lines, the absolute path of the owning file (line hyperlinks). */
|
|
106
|
+
filePath?: string;
|
|
107
|
+
/** Header is an internal/url-like target the caller resolves itself. */
|
|
108
|
+
isUrl?: boolean;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function resolveGroupedPath(parent: string | undefined, name: string): string | undefined {
|
|
112
|
+
if (parent === undefined) return undefined;
|
|
113
|
+
if (name === "" || name === ".") return parent;
|
|
114
|
+
// `path.resolve` keeps an absolute `name` intact (out-of-cwd results) while
|
|
115
|
+
// joining a relative folded chain (`packages/pkg/src`) onto the parent.
|
|
116
|
+
return path.resolve(parent, name);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Walk grouped output lines, tracking a directory stack keyed by header depth, so
|
|
121
|
+
* each header and body line can be linked back to its absolute filesystem path.
|
|
122
|
+
* Reconstruction is stack-based (not per-blank-group) so nested directory headers
|
|
123
|
+
* resolve correctly across the whole output.
|
|
124
|
+
*
|
|
125
|
+
* `headerBase` is the directory the displayed (folded) header paths are relative
|
|
126
|
+
* to — for grep/ast tools that is the session cwd, since display paths are
|
|
127
|
+
* formatted relative to cwd regardless of the (sub)directory the search was
|
|
128
|
+
* scoped to. `fileScope` is the initial owning file for body lines that appear
|
|
129
|
+
* before any header (single-file scopes have no `#` headers); it defaults to
|
|
130
|
+
* `headerBase` and should be passed the scoped file's absolute path.
|
|
131
|
+
*/
|
|
132
|
+
export function classifyGroupedLines(
|
|
133
|
+
lines: readonly string[],
|
|
134
|
+
headerBase: string | undefined,
|
|
135
|
+
fileScope: string | undefined = headerBase,
|
|
136
|
+
): GroupedLineContext[] {
|
|
137
|
+
const result: GroupedLineContext[] = [];
|
|
138
|
+
const dirAtDepth = new Map<number, string>();
|
|
139
|
+
// Body lines before any header (single-file scopes) link to the scoped file.
|
|
140
|
+
let currentFile = fileScope;
|
|
141
|
+
|
|
142
|
+
const clearDeeper = (depth: number) => {
|
|
143
|
+
for (const key of dirAtDepth.keys()) {
|
|
144
|
+
if (key >= depth) dirAtDepth.delete(key);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
for (const line of lines) {
|
|
149
|
+
const match = GROUPED_HEADER_RE.exec(line);
|
|
150
|
+
if (!match) {
|
|
151
|
+
result.push({ kind: "content", depth: 0, filePath: currentFile });
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const depth = match[1]!.length;
|
|
155
|
+
const rest = match[2]!.trimEnd();
|
|
156
|
+
if (isUrlLikePath(rest)) {
|
|
157
|
+
clearDeeper(depth);
|
|
158
|
+
currentFile = undefined;
|
|
159
|
+
result.push({ kind: "file", depth, isUrl: true });
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const parent = depth > 1 ? dirAtDepth.get(depth - 1) : headerBase;
|
|
163
|
+
if (rest.endsWith("/")) {
|
|
164
|
+
const name = rest.slice(0, -1).replace(HEADER_SUFFIX_RE, "");
|
|
165
|
+
const abs = resolveGroupedPath(parent, name);
|
|
166
|
+
clearDeeper(depth);
|
|
167
|
+
if (abs !== undefined) dirAtDepth.set(depth, abs);
|
|
168
|
+
currentFile = undefined;
|
|
169
|
+
result.push({ kind: "dir", depth, headerPath: abs });
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const name = rest.replace(HEADER_SUFFIX_RE, "").replace(HEADER_HASH_TAG_RE, "");
|
|
173
|
+
const abs = name ? resolveGroupedPath(parent, name) : undefined;
|
|
174
|
+
currentFile = abs;
|
|
175
|
+
result.push({ kind: "file", depth, headerPath: abs });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Split line indices into blank-line-separated groups, mirroring
|
|
183
|
+
* `splitGroupsByBlankLine`: when any blank line is present, break on runs of
|
|
184
|
+
* blanks; otherwise return a single group of the non-empty lines. Returning
|
|
185
|
+
* indices lets callers slice parallel arrays (raw lines, styled lines, contexts).
|
|
186
|
+
*/
|
|
187
|
+
export function groupLineIndicesByBlank(rawLines: readonly string[]): number[][] {
|
|
188
|
+
const hasSeparators = rawLines.some(line => line.trim().length === 0);
|
|
189
|
+
const groups: number[][] = [];
|
|
190
|
+
if (hasSeparators) {
|
|
191
|
+
let current: number[] = [];
|
|
192
|
+
for (let i = 0; i < rawLines.length; i++) {
|
|
193
|
+
if (rawLines[i]!.trim().length === 0) {
|
|
194
|
+
if (current.length > 0) {
|
|
195
|
+
groups.push(current);
|
|
196
|
+
current = [];
|
|
197
|
+
}
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
current.push(i);
|
|
201
|
+
}
|
|
202
|
+
if (current.length > 0) groups.push(current);
|
|
203
|
+
} else {
|
|
204
|
+
const current: number[] = [];
|
|
205
|
+
for (let i = 0; i < rawLines.length; i++) {
|
|
206
|
+
if (rawLines[i]!.trim().length > 0) current.push(i);
|
|
207
|
+
}
|
|
208
|
+
if (current.length > 0) groups.push(current);
|
|
209
|
+
}
|
|
210
|
+
return groups;
|
|
211
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hashlineFileHash,
|
|
3
|
+
hashlineFormatHeader,
|
|
4
|
+
hashlineFormatNumberedLines,
|
|
5
|
+
hashlineIsReadTruncationNotice,
|
|
6
|
+
hashlineStripPrefixes,
|
|
7
|
+
} from "@oh-my-pi/pi-natives";
|
|
8
|
+
|
|
9
|
+
/** Opening delimiter of a hashline file header. */
|
|
10
|
+
export const HL_FILE_PREFIX = "[";
|
|
11
|
+
/** Closing delimiter of a hashline file header. */
|
|
12
|
+
export const HL_FILE_SUFFIX = "]";
|
|
13
|
+
/** Separator between the file path and content hash. */
|
|
14
|
+
export const HL_FILE_HASH_SEP = "#";
|
|
15
|
+
/** Number of characters in a displayed file hash. */
|
|
16
|
+
export const HL_FILE_HASH_LENGTH = 4;
|
|
17
|
+
/** Keyword identifying a file move operation. */
|
|
18
|
+
export const HL_MOVE_KEYWORD = "MV";
|
|
19
|
+
/** Keyword identifying a file removal operation. */
|
|
20
|
+
export const HL_REM_KEYWORD = "REM";
|
|
21
|
+
/** Separator between a line number and its body. */
|
|
22
|
+
export const HL_LINE_BODY_SEP = ":";
|
|
23
|
+
|
|
24
|
+
/** Format a file path and content hash as a hashline header. */
|
|
25
|
+
export function formatHashlineHeader(path: string, tag: string): string {
|
|
26
|
+
return hashlineFormatHeader(path, tag);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Prefix each addressable line with its file line number. */
|
|
30
|
+
export function formatNumberedLines(text: string, startLine?: number): string {
|
|
31
|
+
return hashlineFormatNumberedLines(text, startLine);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Prefix one line with its file line number. */
|
|
35
|
+
export function formatNumberedLine(lineNumber: number, line: string): string {
|
|
36
|
+
return `${lineNumber}:${line}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Split file lines without treating a trailing newline as an empty address. */
|
|
40
|
+
export function splitAddressableFileLines(text: string): string[] {
|
|
41
|
+
const lines = text.split("\n");
|
|
42
|
+
if (lines.at(-1) === "") lines.pop();
|
|
43
|
+
return lines;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Remove model-facing hashline anchors from copied file content. */
|
|
47
|
+
export function stripHashlinePrefixes(lines: string[]): string[] {
|
|
48
|
+
return hashlineStripPrefixes(lines);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Whether a row is a truncation notice emitted by `read`. */
|
|
52
|
+
export function isReadTruncationNotice(line: string): boolean {
|
|
53
|
+
return hashlineIsReadTruncationNotice(line);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Compute the native hashline content fingerprint. */
|
|
57
|
+
export function computeFileHash(text: string): string {
|
|
58
|
+
return hashlineFileHash(text);
|
|
59
|
+
}
|