@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,628 @@
|
|
|
1
|
+
import type { SummaryResult } from "@oh-my-pi/pi-natives";
|
|
2
|
+
import { formatNumberedLine } from "./hashline-format";
|
|
3
|
+
import { LINE_RANGE_CHUNK_SOURCE, parseLineRanges } from "./line-ranges";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import type { Component } from "../tui";
|
|
6
|
+
import { Text } from "../components/text";
|
|
7
|
+
import type { RenderResultOptions, ToolRenderer } from "./renderer";
|
|
8
|
+
import { getLanguageFromPath } from "../lang-from-path";
|
|
9
|
+
import type { Theme } from "../theme/theme";
|
|
10
|
+
import { fileHyperlink, renderCodeCell, renderMarkdownCell, renderStatusLine } from "../render";
|
|
11
|
+
import { markFramedBlockComponent } from "../render/output-block";
|
|
12
|
+
import { framedToolCard } from "../render/tool-card";
|
|
13
|
+
import { type ReadUrlToolDetails, renderReadUrlCall, renderReadUrlResult } from "./fetch";
|
|
14
|
+
import { formatFullOutputReference, formatStyledTruncationWarning, stripOutputNotice } from "./output-meta";
|
|
15
|
+
import { formatBytes, sanitizeDisplayLines, shortenPath, wrapBrackets } from "../render/render-utils";
|
|
16
|
+
|
|
17
|
+
import type { OutputMeta } from "./output-meta";
|
|
18
|
+
import type { TruncationResult } from "./streaming-output";
|
|
19
|
+
|
|
20
|
+
/** Read result metadata retains truncation statistics, not a second copy of the body. */
|
|
21
|
+
export type ReadTruncationStats = Omit<TruncationResult, "content">;
|
|
22
|
+
|
|
23
|
+
/** Display metadata for file and URL reads. */
|
|
24
|
+
export interface ReadToolDetails {
|
|
25
|
+
kind?: "file" | "url";
|
|
26
|
+
/** Filesystem hyperlink target resolved by the executing tool. */
|
|
27
|
+
displayTarget?: string;
|
|
28
|
+
truncation?: ReadTruncationStats;
|
|
29
|
+
isDirectory?: boolean;
|
|
30
|
+
resolvedPath?: string;
|
|
31
|
+
suffixResolution?: { from: string; to: string };
|
|
32
|
+
url?: string;
|
|
33
|
+
finalUrl?: string;
|
|
34
|
+
contentType?: string;
|
|
35
|
+
method?: string;
|
|
36
|
+
notes?: string[];
|
|
37
|
+
meta?: OutputMeta;
|
|
38
|
+
/** Full on-disk byte size recorded before applying a file range. */
|
|
39
|
+
fileSize?: number;
|
|
40
|
+
/** Full source line count when the read reached EOF and the count is exact. */
|
|
41
|
+
totalLines?: number;
|
|
42
|
+
/** Raw text + start line for user-visible TUI rendering, set when content is text-like.
|
|
43
|
+
* Mirrors the same lines the model receives but without hashline/line-number prefixes,
|
|
44
|
+
* so the TUI can render the file content with its own gutter without re-parsing the formatted text. */
|
|
45
|
+
displayContent?: {
|
|
46
|
+
text: string;
|
|
47
|
+
startLine: number;
|
|
48
|
+
lineNumbers?: Array<number | null>;
|
|
49
|
+
};
|
|
50
|
+
summary?: { lines: number; elidedSpans: number; elidedLines: number };
|
|
51
|
+
/** Number of unresolved git conflicts surfaced by this read (TUI uses for inline `⚠ N` badge). */
|
|
52
|
+
conflictCount?: number;
|
|
53
|
+
/** Paths recovered from a delimited read argument; used only by the TUI to render one call as multiple read rows. */
|
|
54
|
+
displayReadTargets?: string[];
|
|
55
|
+
/**
|
|
56
|
+
* Resolved filesystem link target for each {@link displayReadTargets} entry, aligned by index; `null` when a
|
|
57
|
+
* delimited part has no linkable fs path. Lets the TUI hyperlink each grouped row the same way a standalone read row is.
|
|
58
|
+
*/
|
|
59
|
+
displayReadTargetLinks?: Array<string | null>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Parsing also recognizes incomplete counts to explain their errors; path splitting
|
|
63
|
+
// only peels complete selectors (not a trailing `+` or `L`).
|
|
64
|
+
const RANGE_SELECTOR_CHUNK = `${LINE_RANGE_CHUNK_SOURCE}(?<=[\\d.-])`;
|
|
65
|
+
const RANGE_LIST_SRC = `${RANGE_SELECTOR_CHUNK}(?:,${RANGE_SELECTOR_CHUNK})*`;
|
|
66
|
+
// A tail selector: `-N` reads the last N lines. Keep in sync with TAIL_SELECTOR_RE.
|
|
67
|
+
const TAIL_CHUNK_SRC = String.raw`-\d+`;
|
|
68
|
+
const FILE_LINE_RANGE_RE = new RegExp(`^(?:${RANGE_LIST_SRC}|${TAIL_CHUNK_SRC}|raw|conflicts|img)$`, "i");
|
|
69
|
+
const FILE_LINE_RANGE_ONLY_RE = new RegExp(`^(?:${RANGE_LIST_SRC}|${TAIL_CHUNK_SRC})$`, "i");
|
|
70
|
+
const FILE_RAW_ONLY_RE = /^raw$/i;
|
|
71
|
+
// Permissive selector chunk for internal URLs — accepts well-formed selectors
|
|
72
|
+
// plus common malformed shapes (e.g. `:-N-M`) so the read tool peels the entire
|
|
73
|
+
// selector chain off before dispatching to a protocol handler.
|
|
74
|
+
const INTERNAL_URL_SELECTOR_PART_RE = new RegExp(
|
|
75
|
+
String.raw`^(?:raw|conflicts|img|${RANGE_LIST_SRC}|-\d+(?:[-+]\d+)?)$`,
|
|
76
|
+
"i",
|
|
77
|
+
);
|
|
78
|
+
// Schemes whose host grammar is identifier-shaped, so any trailing
|
|
79
|
+
// `:<selector-chunk>` is unambiguously a read-tool selector. `mcp://` is
|
|
80
|
+
// excluded because mcp resource URIs may legitimately contain colons. `ssh://`
|
|
81
|
+
// is included despite an optional `:port`; `splitInternalUrlSel` skips the peel
|
|
82
|
+
// for an `ssh://host:port` that has no `/path`, so the port colon is never
|
|
83
|
+
// mistaken for a selector (a real ssh selector trails the `/path`, e.g.
|
|
84
|
+
// `ssh://h/f:1-5`).
|
|
85
|
+
const INTERNAL_SCHEMES_WITH_SELECTORS: Record<string, true> = {
|
|
86
|
+
agent: true,
|
|
87
|
+
artifact: true,
|
|
88
|
+
issue: true,
|
|
89
|
+
history: true,
|
|
90
|
+
local: true,
|
|
91
|
+
memory: true,
|
|
92
|
+
omp: true,
|
|
93
|
+
pr: true,
|
|
94
|
+
rule: true,
|
|
95
|
+
security: true,
|
|
96
|
+
skill: true,
|
|
97
|
+
ssh: true,
|
|
98
|
+
vault: true,
|
|
99
|
+
};
|
|
100
|
+
// Schemes whose resource URIs are server-defined and may legitimately end
|
|
101
|
+
// with selector-shaped tails (e.g. `:raw`, `:conflicts`, `:1-50`, `/:raw`).
|
|
102
|
+
// `McpProtocolHandler` resolves by exact URI match (`r.uri === uri`), so
|
|
103
|
+
// peeling syntactically can make valid resources unreachable. Keep these
|
|
104
|
+
// schemes opaque; selector support for them needs a resolver-aware path that
|
|
105
|
+
// tries the exact URI before interpreting any suffix as a read selector.
|
|
106
|
+
const OPAQUE_RESOURCE_SCHEMES: ReadonlySet<string> = new Set(["mcp"]);
|
|
107
|
+
const INTERNAL_URL_SCHEME_RE = /^([a-z][a-z0-9+.-]*):\/\//i;
|
|
108
|
+
/** Split a filesystem path from its trailing read selector. */
|
|
109
|
+
export function splitPathAndSel(rawPath: string): { path: string; sel?: string } {
|
|
110
|
+
const colon = rawPath.lastIndexOf(":");
|
|
111
|
+
if (colon <= 0) return { path: rawPath };
|
|
112
|
+
|
|
113
|
+
const candidate = rawPath.slice(colon + 1);
|
|
114
|
+
if (!FILE_LINE_RANGE_RE.test(candidate)) return { path: rawPath };
|
|
115
|
+
|
|
116
|
+
let basePath = rawPath.slice(0, colon);
|
|
117
|
+
let sel = candidate;
|
|
118
|
+
|
|
119
|
+
// Allow a compound trailing selector: `path:1-50:raw`, `path:raw:1-50`, or
|
|
120
|
+
// `path:raw:-60`. The two chunks must be one line-range (or tail) plus one
|
|
121
|
+
// `raw`, in either order.
|
|
122
|
+
const innerColon = basePath.lastIndexOf(":");
|
|
123
|
+
if (innerColon > 0) {
|
|
124
|
+
const innerCandidate = basePath.slice(innerColon + 1);
|
|
125
|
+
const innerIsRaw = FILE_RAW_ONLY_RE.test(innerCandidate);
|
|
126
|
+
const outerIsRaw = FILE_RAW_ONLY_RE.test(candidate);
|
|
127
|
+
const innerIsRange = FILE_LINE_RANGE_ONLY_RE.test(innerCandidate);
|
|
128
|
+
const outerIsRange = FILE_LINE_RANGE_ONLY_RE.test(candidate);
|
|
129
|
+
if ((innerIsRaw && outerIsRange) || (innerIsRange && outerIsRaw)) {
|
|
130
|
+
sel = `${innerCandidate}:${candidate}`;
|
|
131
|
+
basePath = basePath.slice(0, innerColon);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { path: basePath, sel };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Variant of {@link splitPathAndSel} for internal URLs (`scheme://...`).
|
|
140
|
+
*
|
|
141
|
+
* The filesystem-path splitter is intentionally conservative: it refuses to
|
|
142
|
+
* peel a trailing `:<chunk>` unless that chunk matches the strict selector
|
|
143
|
+
* grammar. That rule is right for filesystem paths (a file named `a:1-50` is
|
|
144
|
+
* legal) but wrong for internal URLs, where any trailing `:<chunk>` after the
|
|
145
|
+
* scheme is unambiguously a read-tool selector — even if malformed (e.g.
|
|
146
|
+
* `artifact://3:raw:-100-5`).
|
|
147
|
+
*
|
|
148
|
+
* This function iteratively peels selector-shaped chunks (well-formed plus
|
|
149
|
+
* common malformed shapes like `:-N-M`) so the rest of the read tool can pass a
|
|
150
|
+
* clean URL to the protocol handler and surface selector errors via parseSel
|
|
151
|
+
* instead of as misleading "host invalid" errors from the handler. Schemes
|
|
152
|
+
* whose resource URIs may legitimately contain colons (`mcp://`) are skipped.
|
|
153
|
+
*
|
|
154
|
+
* Falls back to the input unchanged when nothing matches.
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
export function splitInternalUrlSel(rawPath: string): { path: string; sel?: string } {
|
|
158
|
+
const schemeMatch = rawPath.match(INTERNAL_URL_SCHEME_RE);
|
|
159
|
+
if (!schemeMatch) return { path: rawPath };
|
|
160
|
+
const scheme = schemeMatch[1].toLowerCase();
|
|
161
|
+
// Opaque schemes (mcp://, etc.) carry server-defined resource URIs that may
|
|
162
|
+
// legitimately end in selector-shaped tails. Forward verbatim — see
|
|
163
|
+
// OPAQUE_RESOURCE_SCHEMES.
|
|
164
|
+
if (OPAQUE_RESOURCE_SCHEMES.has(scheme)) return { path: rawPath };
|
|
165
|
+
if (!INTERNAL_SCHEMES_WITH_SELECTORS[scheme]) return { path: rawPath };
|
|
166
|
+
|
|
167
|
+
const schemeEnd = schemeMatch[0].length;
|
|
168
|
+
// ssh:// authority carries an optional `:port`; with no `/path` after the
|
|
169
|
+
// authority, a trailing `:NNNN` is the port, not a read selector
|
|
170
|
+
// (e.g. ssh://host:2222). Other schemes' authority-trailing selectors
|
|
171
|
+
// (artifact://5:1-50) still peel, so this guard is ssh-specific.
|
|
172
|
+
if (scheme === "ssh" && rawPath.indexOf("/", schemeEnd) === -1) {
|
|
173
|
+
return { path: rawPath };
|
|
174
|
+
}
|
|
175
|
+
let path = rawPath;
|
|
176
|
+
const chunks: string[] = [];
|
|
177
|
+
while (true) {
|
|
178
|
+
const colon = path.lastIndexOf(":");
|
|
179
|
+
// Stop before crossing into the scheme separator `://`.
|
|
180
|
+
if (colon < schemeEnd) break;
|
|
181
|
+
const tail = path.slice(colon + 1);
|
|
182
|
+
if (!INTERNAL_URL_SELECTOR_PART_RE.test(tail)) break;
|
|
183
|
+
chunks.unshift(tail);
|
|
184
|
+
path = path.slice(0, colon);
|
|
185
|
+
}
|
|
186
|
+
if (chunks.length === 0) return { path: rawPath };
|
|
187
|
+
return { path, sel: chunks.join(":") };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Recognize HTTP URLs and www-prefixed external read targets. */
|
|
191
|
+
export function isReadableUrlPath(value: string): boolean {
|
|
192
|
+
return /^https?:\/\/?/i.test(value) || /^www\./i.test(value);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Return the first selected line when every range has valid one-based bounds. */
|
|
196
|
+
export function readSelectorRangeStart(selector: string): number | undefined {
|
|
197
|
+
try {
|
|
198
|
+
const start = parseLineRanges(selector)?.[0].startLine;
|
|
199
|
+
return start !== undefined && Number.isFinite(start) ? start : undefined;
|
|
200
|
+
} catch {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// =============================================================================
|
|
206
|
+
// TUI Renderer
|
|
207
|
+
// =============================================================================
|
|
208
|
+
|
|
209
|
+
export interface ReadRenderArgs {
|
|
210
|
+
path?: unknown;
|
|
211
|
+
file_path?: unknown;
|
|
212
|
+
// Legacy fields from old schema — tolerated for in-flight tool calls during transition
|
|
213
|
+
offset?: number;
|
|
214
|
+
limit?: number;
|
|
215
|
+
raw?: boolean;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const INTERNAL_URL_LIKE_RE = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
219
|
+
|
|
220
|
+
function splitReadRenderPath(rawPath: string): { path: string; sel?: string } {
|
|
221
|
+
if (INTERNAL_URL_LIKE_RE.test(rawPath)) {
|
|
222
|
+
const internal = splitInternalUrlSel(rawPath);
|
|
223
|
+
if (internal.sel) return internal;
|
|
224
|
+
}
|
|
225
|
+
return splitPathAndSel(rawPath);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function firstReadSelectorLine(sel: string | undefined): number | undefined {
|
|
229
|
+
if (!sel) return undefined;
|
|
230
|
+
const range = sel.split(":").find(chunk => chunk.toLowerCase() !== "raw");
|
|
231
|
+
return range ? readSelectorRangeStart(range) : undefined;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Absolute fs path the read result actually resolved to, used as the OSC 8 link
|
|
235
|
+
* target when the structured `resolvedPath` isn't set (the common plain-file and
|
|
236
|
+
* image reads only record the path in `meta.source`). URL/internal sources are
|
|
237
|
+
* not fs paths, so only `type: "path"` qualifies. */
|
|
238
|
+
export function readSourceFsPath(details: ReadToolDetails | undefined): string | undefined {
|
|
239
|
+
const source = details?.meta?.source;
|
|
240
|
+
return source?.type === "path" && typeof source.value === "string" ? source.value : undefined;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function formatReadPathLink(
|
|
244
|
+
rawPath: string,
|
|
245
|
+
options: {
|
|
246
|
+
resolvedPath?: string;
|
|
247
|
+
sourcePath?: string;
|
|
248
|
+
suffixResolution?: { from: string; to: string };
|
|
249
|
+
offset?: number;
|
|
250
|
+
fallbackLabel?: string;
|
|
251
|
+
},
|
|
252
|
+
): string {
|
|
253
|
+
const split = splitReadRenderPath(rawPath);
|
|
254
|
+
const basePath = split.path || rawPath;
|
|
255
|
+
const selectorSuffix = split.sel ? `:${split.sel}` : "";
|
|
256
|
+
const plainDisplayPath = options.suffixResolution
|
|
257
|
+
? shortenPath(options.suffixResolution.to)
|
|
258
|
+
: shortenPath(basePath || options.resolvedPath || options.fallbackLabel || rawPath);
|
|
259
|
+
const absoluteInputPath = path.isAbsolute(basePath) ? basePath : undefined;
|
|
260
|
+
const target = options.resolvedPath ?? options.sourcePath ?? absoluteInputPath;
|
|
261
|
+
const line = firstReadSelectorLine(split.sel) ?? options.offset;
|
|
262
|
+
const linkOptions = line !== undefined ? { line } : undefined;
|
|
263
|
+
const linkedPath = target ? fileHyperlink(target, plainDisplayPath, linkOptions) : plainDisplayPath;
|
|
264
|
+
return `${linkedPath}${selectorSuffix}`;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Render file, image, and URL reads in the transcript. */
|
|
268
|
+
export const readToolRenderer = {
|
|
269
|
+
renderCall(args: ReadRenderArgs, _options: RenderResultOptions, uiTheme: Theme): Component {
|
|
270
|
+
const rawPath =
|
|
271
|
+
typeof args.file_path === "string" ? args.file_path : typeof args.path === "string" ? args.path : "";
|
|
272
|
+
if (isReadableUrlPath(rawPath)) {
|
|
273
|
+
return renderReadUrlCall({ path: rawPath, raw: args.raw }, _options, uiTheme);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const offset = args.offset;
|
|
277
|
+
const limit = args.limit;
|
|
278
|
+
|
|
279
|
+
let pathDisplay = formatReadPathLink(rawPath, { offset, fallbackLabel: "…" }) || "…";
|
|
280
|
+
if (offset !== undefined || limit !== undefined) {
|
|
281
|
+
const startLine = offset ?? 1;
|
|
282
|
+
const endLine = limit !== undefined ? startLine + limit - 1 : "";
|
|
283
|
+
pathDisplay += `:${startLine}${endLine ? `-${endLine}` : ""}`;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const text = renderStatusLine({ icon: "pending", title: "Read", description: pathDisplay }, uiTheme);
|
|
287
|
+
return new Text(text, 0, 0);
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
renderResult(
|
|
291
|
+
result: { content: Array<{ type: string; text?: string }>; details?: ReadToolDetails; isError?: boolean },
|
|
292
|
+
options: RenderResultOptions,
|
|
293
|
+
uiTheme: Theme,
|
|
294
|
+
args?: ReadRenderArgs,
|
|
295
|
+
): Component {
|
|
296
|
+
const urlDetails = result.details as ReadUrlToolDetails | undefined;
|
|
297
|
+
const baseRawPathForKind =
|
|
298
|
+
typeof args?.file_path === "string" ? args.file_path : typeof args?.path === "string" ? args.path : "";
|
|
299
|
+
if (urlDetails?.kind === "url" || isReadableUrlPath(baseRawPathForKind)) {
|
|
300
|
+
return renderReadUrlResult(
|
|
301
|
+
result as {
|
|
302
|
+
content: Array<{ type: string; text?: string }>;
|
|
303
|
+
details?: ReadUrlToolDetails;
|
|
304
|
+
isError?: boolean;
|
|
305
|
+
},
|
|
306
|
+
options,
|
|
307
|
+
uiTheme,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (result.isError) {
|
|
312
|
+
const rawErrorText = result.content?.find(c => c.type === "text")?.text ?? "";
|
|
313
|
+
const errorText = (rawErrorText || "Unknown error").replace(/^Error:\s*/, "");
|
|
314
|
+
const rawPath =
|
|
315
|
+
typeof args?.file_path === "string" ? args.file_path : typeof args?.path === "string" ? args.path : "";
|
|
316
|
+
const filePath =
|
|
317
|
+
formatReadPathLink(rawPath, {
|
|
318
|
+
offset: args?.offset,
|
|
319
|
+
sourcePath: result.details?.displayTarget ?? readSourceFsPath(result.details),
|
|
320
|
+
}) || shortenPath(rawPath);
|
|
321
|
+
let title = filePath ? `Read ${filePath}` : "Read";
|
|
322
|
+
if (args?.offset !== undefined || args?.limit !== undefined) {
|
|
323
|
+
const startLine = args.offset ?? 1;
|
|
324
|
+
const endLine = args.limit !== undefined ? startLine + args.limit - 1 : "";
|
|
325
|
+
title += `:${startLine}${endLine ? `-${endLine}` : ""}`;
|
|
326
|
+
}
|
|
327
|
+
const header = renderStatusLine({ icon: "error", title }, uiTheme);
|
|
328
|
+
const errorLines = sanitizeDisplayLines(errorText).map(line => uiTheme.fg("error", line));
|
|
329
|
+
return framedToolCard(uiTheme, () => ({
|
|
330
|
+
header,
|
|
331
|
+
phase: "error",
|
|
332
|
+
sections: [{ content: errorLines }],
|
|
333
|
+
}));
|
|
334
|
+
}
|
|
335
|
+
const details = result.details;
|
|
336
|
+
const rawText = result.content?.find(c => c.type === "text")?.text ?? "";
|
|
337
|
+
// Prefer structured `displayContent` from details when available so the TUI
|
|
338
|
+
// shows clean file content (no model-only hashline anchors) without parsing the formatted text.
|
|
339
|
+
// Fall back to the raw text, but strip the LLM-facing notice so it doesn't
|
|
340
|
+
// echo next to the styled warning line below.
|
|
341
|
+
const contentText = details?.displayContent?.text ?? stripOutputNotice(rawText, details?.meta);
|
|
342
|
+
const imageContent = result.content?.find(c => c.type === "image");
|
|
343
|
+
const rawPath =
|
|
344
|
+
typeof args?.file_path === "string" ? args.file_path : typeof args?.path === "string" ? args.path : "";
|
|
345
|
+
const renderPath = splitReadRenderPath(rawPath);
|
|
346
|
+
const lang = getLanguageFromPath(renderPath.path);
|
|
347
|
+
|
|
348
|
+
const warningLines: string[] = [];
|
|
349
|
+
const truncation = details?.meta?.truncation;
|
|
350
|
+
const fallback = details?.truncation;
|
|
351
|
+
if (details?.resolvedPath) {
|
|
352
|
+
warningLines.push(uiTheme.fg("dim", wrapBrackets(`Resolved path: ${details.resolvedPath}`, uiTheme)));
|
|
353
|
+
}
|
|
354
|
+
if (truncation) {
|
|
355
|
+
if (fallback?.firstLineExceedsLimit) {
|
|
356
|
+
let warning = `First line exceeds ${formatBytes(fallback.outputBytes ?? fallback.totalBytes)} limit`;
|
|
357
|
+
if (truncation.artifactId) {
|
|
358
|
+
warning += `. ${formatFullOutputReference(truncation.artifactId)}`;
|
|
359
|
+
}
|
|
360
|
+
warningLines.push(uiTheme.fg("warning", wrapBrackets(warning, uiTheme)));
|
|
361
|
+
} else {
|
|
362
|
+
const warning = formatStyledTruncationWarning(details?.meta, uiTheme);
|
|
363
|
+
if (warning) warningLines.push(warning);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (imageContent) {
|
|
368
|
+
const suffix = details?.suffixResolution;
|
|
369
|
+
const displayPath = formatReadPathLink(rawPath, {
|
|
370
|
+
resolvedPath: details?.resolvedPath,
|
|
371
|
+
sourcePath: details?.displayTarget ?? readSourceFsPath(details),
|
|
372
|
+
suffixResolution: suffix,
|
|
373
|
+
fallbackLabel: "image",
|
|
374
|
+
});
|
|
375
|
+
const correction = suffix ? ` ${uiTheme.fg("dim", `(corrected from ${shortenPath(suffix.from)})`)}` : "";
|
|
376
|
+
const header = renderStatusLine(
|
|
377
|
+
{ icon: suffix ? "warning" : "success", title: "Read", description: `${displayPath}${correction}` },
|
|
378
|
+
uiTheme,
|
|
379
|
+
);
|
|
380
|
+
const detailLines = contentText
|
|
381
|
+
? sanitizeDisplayLines(contentText).map(line => uiTheme.fg("toolOutput", line))
|
|
382
|
+
: [];
|
|
383
|
+
const lines = [...detailLines, ...warningLines];
|
|
384
|
+
return framedToolCard(uiTheme, () => ({
|
|
385
|
+
header,
|
|
386
|
+
phase: "success",
|
|
387
|
+
sections: [
|
|
388
|
+
{
|
|
389
|
+
label: uiTheme.fg("toolTitle", "Details"),
|
|
390
|
+
content: lines.length > 0 ? lines : [uiTheme.fg("dim", "(image)")],
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
}));
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const suffix = details?.suffixResolution;
|
|
397
|
+
// resolvedPath is the absolute fs path when a read resolved/corrected the
|
|
398
|
+
// input (suffix match, internal URL, archive/sqlite/notebook); plain file
|
|
399
|
+
// reads only record the absolute path in meta.source, so fall back to that
|
|
400
|
+
// to keep the title clickable.
|
|
401
|
+
const displayPath = formatReadPathLink(rawPath, {
|
|
402
|
+
resolvedPath: details?.resolvedPath,
|
|
403
|
+
sourcePath: details?.displayTarget ?? readSourceFsPath(details),
|
|
404
|
+
suffixResolution: suffix,
|
|
405
|
+
offset: args?.offset,
|
|
406
|
+
});
|
|
407
|
+
const correction = suffix ? ` ${uiTheme.fg("dim", `(corrected from ${shortenPath(suffix.from)})`)}` : "";
|
|
408
|
+
let title = displayPath ? `Read ${displayPath}${correction}` : "Read";
|
|
409
|
+
if (args?.offset !== undefined || args?.limit !== undefined) {
|
|
410
|
+
const startLine = args.offset ?? 1;
|
|
411
|
+
const endLine = args.limit !== undefined ? startLine + args.limit - 1 : "";
|
|
412
|
+
title += `:${startLine}${endLine ? `-${endLine}` : ""}`;
|
|
413
|
+
}
|
|
414
|
+
if (details?.summary) {
|
|
415
|
+
title += ` (summary: ${details.summary.elidedSpans} elided span${details.summary.elidedSpans === 1 ? "" : "s"})`;
|
|
416
|
+
}
|
|
417
|
+
if (details?.conflictCount && details.conflictCount > 0) {
|
|
418
|
+
const n = details.conflictCount;
|
|
419
|
+
title += ` ${uiTheme.fg("warning", `(⚠ ${n} conflict${n === 1 ? "" : "s"})`)}`;
|
|
420
|
+
}
|
|
421
|
+
const rawRequested =
|
|
422
|
+
args?.raw === true || renderPath.sel?.split(":").some(chunk => chunk.toLowerCase() === "raw") === true;
|
|
423
|
+
const isMarkdown = details?.contentType === "text/markdown" && !rawRequested;
|
|
424
|
+
let cachedWidth: number | undefined;
|
|
425
|
+
let cachedExpanded: boolean | undefined;
|
|
426
|
+
let cachedLines: string[] | undefined;
|
|
427
|
+
return markFramedBlockComponent({
|
|
428
|
+
render: (width: number) => {
|
|
429
|
+
const expanded = options.expanded;
|
|
430
|
+
if (cachedLines && cachedWidth === width && cachedExpanded === expanded) return cachedLines;
|
|
431
|
+
cachedLines = isMarkdown
|
|
432
|
+
? renderMarkdownCell(
|
|
433
|
+
{
|
|
434
|
+
content: contentText,
|
|
435
|
+
title,
|
|
436
|
+
status: "complete",
|
|
437
|
+
output: warningLines.length > 0 ? warningLines.join("\n") : undefined,
|
|
438
|
+
expanded,
|
|
439
|
+
width,
|
|
440
|
+
},
|
|
441
|
+
uiTheme,
|
|
442
|
+
)
|
|
443
|
+
: renderCodeCell(
|
|
444
|
+
{
|
|
445
|
+
code: contentText,
|
|
446
|
+
language: lang,
|
|
447
|
+
title,
|
|
448
|
+
status: "complete",
|
|
449
|
+
output: warningLines.length > 0 ? warningLines.join("\n") : undefined,
|
|
450
|
+
expanded,
|
|
451
|
+
codeStartLine: details?.displayContent?.startLine,
|
|
452
|
+
codeLineNumbers: details?.displayContent?.lineNumbers,
|
|
453
|
+
width,
|
|
454
|
+
},
|
|
455
|
+
uiTheme,
|
|
456
|
+
);
|
|
457
|
+
cachedWidth = width;
|
|
458
|
+
cachedExpanded = expanded;
|
|
459
|
+
return cachedLines;
|
|
460
|
+
},
|
|
461
|
+
invalidate: () => {
|
|
462
|
+
cachedWidth = undefined;
|
|
463
|
+
cachedExpanded = undefined;
|
|
464
|
+
cachedLines = undefined;
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
},
|
|
468
|
+
mergeCallAndResult: true,
|
|
469
|
+
} satisfies ToolRenderer<ReadRenderArgs, ReadToolDetails>;
|
|
470
|
+
|
|
471
|
+
/** Inclusive line range describing one elided span in a structural summary. */
|
|
472
|
+
export interface ElidedRange {
|
|
473
|
+
start: number;
|
|
474
|
+
end: number;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const BRACE_PAIRS: Record<string, string> = { "{": "}", "(": ")", "[": "]" };
|
|
478
|
+
const BRACE_TAIL_TRAILING_RE = /^[;,)\]}]*$/;
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Decide whether the kept lines surrounding an elided range collapse to a
|
|
482
|
+
* single brace-pair line in the rendered summary. Returns true when the head
|
|
483
|
+
* line ends with `{` / `(` / `[` and the tail line is the matching closer
|
|
484
|
+
* (optionally followed by terminating punctuation like `;`, `,`, or further
|
|
485
|
+
* closers — e.g. `};`, `})`, `]);`).
|
|
486
|
+
*/
|
|
487
|
+
export function canMergeBracePair(headLine: string, tailLine: string): boolean {
|
|
488
|
+
const head = headLine.trimEnd();
|
|
489
|
+
const tail = tailLine.trim();
|
|
490
|
+
const opener = head.slice(-1);
|
|
491
|
+
const closer = BRACE_PAIRS[opener];
|
|
492
|
+
if (!closer) return false;
|
|
493
|
+
if (!tail.startsWith(closer)) return false;
|
|
494
|
+
return BRACE_TAIL_TRAILING_RE.test(tail.slice(closer.length));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/** Format one summary line with the selected line-prefix mode. */
|
|
498
|
+
export function formatSingleLine(
|
|
499
|
+
line: number,
|
|
500
|
+
text: string,
|
|
501
|
+
shouldAddHashLines: boolean,
|
|
502
|
+
shouldAddLineNumbers: boolean,
|
|
503
|
+
): string {
|
|
504
|
+
if (shouldAddHashLines) return formatNumberedLine(line, text);
|
|
505
|
+
if (shouldAddLineNumbers) return `${line}|${text}`;
|
|
506
|
+
return text;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/** Format the boundary lines around an elided brace-pair body. */
|
|
510
|
+
export function formatMergedBraceLine(
|
|
511
|
+
startLine: number,
|
|
512
|
+
endLine: number,
|
|
513
|
+
headText: string,
|
|
514
|
+
tailText: string,
|
|
515
|
+
shouldAddHashLines: boolean,
|
|
516
|
+
shouldAddLineNumbers: boolean,
|
|
517
|
+
): { model: string; display: string } {
|
|
518
|
+
const merged = `${headText.trimEnd()} … ${tailText.trim()}`;
|
|
519
|
+
if (shouldAddHashLines) {
|
|
520
|
+
return { model: `${startLine}-${endLine}:${merged}`, display: merged };
|
|
521
|
+
}
|
|
522
|
+
if (shouldAddLineNumbers) {
|
|
523
|
+
return { model: `${startLine}-${endLine}|${merged}`, display: merged };
|
|
524
|
+
}
|
|
525
|
+
return { model: merged, display: merged };
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/** Format a structural summary using the supplied file-display preferences. */
|
|
529
|
+
export function formatReadSummary(
|
|
530
|
+
displayMode: { hashLines: boolean; lineNumbers: boolean },
|
|
531
|
+
summary: SummaryResult,
|
|
532
|
+
): {
|
|
533
|
+
text: string;
|
|
534
|
+
displayText: string;
|
|
535
|
+
elidedRanges: ElidedRange[];
|
|
536
|
+
elidedLines: number;
|
|
537
|
+
} {
|
|
538
|
+
const shouldAddHashLines = displayMode.hashLines;
|
|
539
|
+
const shouldAddLineNumbers = shouldAddHashLines ? false : displayMode.lineNumbers;
|
|
540
|
+
|
|
541
|
+
// Flatten segments into per-line units so we can merge a kept-head /
|
|
542
|
+
// elided / kept-tail sandwich into a single brace-pair line when the
|
|
543
|
+
// boundary lines look like `… {` and `}` (or matching variants).
|
|
544
|
+
type Unit =
|
|
545
|
+
| { kind: "line"; line: number; text: string }
|
|
546
|
+
| { kind: "elided"; startLine: number; endLine: number }
|
|
547
|
+
| {
|
|
548
|
+
kind: "merged";
|
|
549
|
+
startLine: number;
|
|
550
|
+
endLine: number;
|
|
551
|
+
headText: string;
|
|
552
|
+
tailText: string;
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
const raw: Unit[] = [];
|
|
556
|
+
for (const segment of summary.segments) {
|
|
557
|
+
if (segment.kind === "elided") {
|
|
558
|
+
raw.push({ kind: "elided", startLine: segment.startLine, endLine: segment.endLine });
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
const text = segment.text ?? "";
|
|
562
|
+
if (text.length === 0) continue;
|
|
563
|
+
const lines = text.split("\n");
|
|
564
|
+
for (let i = 0; i < lines.length; i++) {
|
|
565
|
+
raw.push({ kind: "line", line: segment.startLine + i, text: lines[i] });
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const units: Unit[] = [];
|
|
570
|
+
let i = 0;
|
|
571
|
+
while (i < raw.length) {
|
|
572
|
+
const cur = raw[i];
|
|
573
|
+
if (cur.kind === "elided") {
|
|
574
|
+
const prev = units.length > 0 ? units[units.length - 1] : null;
|
|
575
|
+
const next = i + 1 < raw.length ? raw[i + 1] : null;
|
|
576
|
+
if (prev?.kind === "line" && next?.kind === "line" && canMergeBracePair(prev.text, next.text)) {
|
|
577
|
+
units.pop();
|
|
578
|
+
units.push({
|
|
579
|
+
kind: "merged",
|
|
580
|
+
startLine: prev.line,
|
|
581
|
+
endLine: next.line,
|
|
582
|
+
headText: prev.text,
|
|
583
|
+
tailText: next.text,
|
|
584
|
+
});
|
|
585
|
+
i += 2;
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
units.push(cur);
|
|
590
|
+
i++;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const modelParts: string[] = [];
|
|
594
|
+
const displayParts: string[] = [];
|
|
595
|
+
const elidedRanges: ElidedRange[] = [];
|
|
596
|
+
let elidedLines = 0;
|
|
597
|
+
for (const unit of units) {
|
|
598
|
+
if (unit.kind === "elided") {
|
|
599
|
+
modelParts.push("…");
|
|
600
|
+
displayParts.push("…");
|
|
601
|
+
elidedRanges.push({ start: unit.startLine, end: unit.endLine });
|
|
602
|
+
elidedLines += unit.endLine - unit.startLine + 1;
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
if (unit.kind === "merged") {
|
|
606
|
+
const formatted = formatMergedBraceLine(
|
|
607
|
+
unit.startLine,
|
|
608
|
+
unit.endLine,
|
|
609
|
+
unit.headText,
|
|
610
|
+
unit.tailText,
|
|
611
|
+
shouldAddHashLines,
|
|
612
|
+
shouldAddLineNumbers,
|
|
613
|
+
);
|
|
614
|
+
modelParts.push(formatted.model);
|
|
615
|
+
displayParts.push(formatted.display);
|
|
616
|
+
// Suggest the full brace range so re-reading shows both braces
|
|
617
|
+
// plus the elided body in one shot.
|
|
618
|
+
elidedRanges.push({ start: unit.startLine, end: unit.endLine });
|
|
619
|
+
// Merged brace pair encloses (start+1)..(end-1) as elided.
|
|
620
|
+
elidedLines += Math.max(0, unit.endLine - unit.startLine - 1);
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
modelParts.push(formatSingleLine(unit.line, unit.text, shouldAddHashLines, shouldAddLineNumbers));
|
|
624
|
+
displayParts.push(unit.text);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
return { text: modelParts.join("\n"), displayText: displayParts.join("\n"), elidedRanges, elidedLines };
|
|
628
|
+
}
|