@oh-my-pi/pi-tui 18.2.3 → 18.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -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/image.d.ts +18 -16
- 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/image.ts +80 -53
- 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 +70 -8
- package/src/utils.ts +8 -0
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import type { ToolRenderer } from "./renderer";
|
|
2
|
+
|
|
3
|
+
import type { Component } from "../index";
|
|
4
|
+
import { Text } from "../index";
|
|
5
|
+
import { sanitizeText } from "@oh-my-pi/pi-utils";
|
|
6
|
+
import chalk from "@oh-my-pi/pi-utils/chalk";
|
|
7
|
+
import type { RenderResultOptions } from "./renderer";
|
|
8
|
+
import type { Theme } from "../theme/theme";
|
|
9
|
+
|
|
10
|
+
import { renderStatusLine, renderTreeList } from "../render";
|
|
11
|
+
import { framedToolCard } from "../render/tool-card";
|
|
12
|
+
|
|
13
|
+
import { formatErrorDetail, formatMoreItems, PREVIEW_LIMITS, pluralize, replaceTabs } from "../render/render-utils";
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Types
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
/** Lifecycle state of a todo item. */
|
|
20
|
+
export type TodoStatus = "pending" | "in_progress" | "completed" | "abandoned" | "blocked";
|
|
21
|
+
|
|
22
|
+
/** Operation names accepted by the todo tool and echoed in successful result details. */
|
|
23
|
+
export type TodoOperation = "init" | "start" | "done" | "rm" | "drop" | "block" | "unblock" | "append" | "view";
|
|
24
|
+
|
|
25
|
+
/** A task displayed within a todo phase. */
|
|
26
|
+
export interface TodoItem {
|
|
27
|
+
content: string;
|
|
28
|
+
status: TodoStatus;
|
|
29
|
+
/** When `status === "blocked"`, an optional note on what the task is waiting for. */
|
|
30
|
+
blocker?: string;
|
|
31
|
+
details?: string;
|
|
32
|
+
notes?: string[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A named group of todo tasks. */
|
|
36
|
+
export interface TodoPhase {
|
|
37
|
+
name: string;
|
|
38
|
+
tasks: TodoItem[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** A task that became complete in the latest update. */
|
|
42
|
+
export interface TodoCompletionTransition {
|
|
43
|
+
phase: string;
|
|
44
|
+
content: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Todo snapshot and transitions displayed after an operation. */
|
|
48
|
+
export interface TodoToolDetails {
|
|
49
|
+
/** Operation that produced this snapshot; absent on legacy transcript entries. */
|
|
50
|
+
op?: TodoOperation;
|
|
51
|
+
phases: TodoPhase[];
|
|
52
|
+
storage: "session" | "memory";
|
|
53
|
+
completedTasks?: TodoCompletionTransition[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Minimum overlap (after normalization) required for a substring match.
|
|
57
|
+
* Picked at six chars to admit single-word identifiers like "review" /
|
|
58
|
+
* "Sonnet" without admitting tiny common substrings like "test" / "fix"
|
|
59
|
+
* that would collide across unrelated todos. */
|
|
60
|
+
const TODO_DESCRIPTION_MIN_OVERLAP = 6;
|
|
61
|
+
|
|
62
|
+
function normalizeForTodoMatch(value: string): string {
|
|
63
|
+
return value
|
|
64
|
+
.toLowerCase()
|
|
65
|
+
.replace(/[^\p{L}\p{N}]+/gu, " ")
|
|
66
|
+
.trim();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Report whether `content` likely names the same work as any entry in
|
|
71
|
+
* `descriptions`. Used by the sticky todo panel to light up a pending todo
|
|
72
|
+
* when an in-flight subagent is doing the work for it, without requiring
|
|
73
|
+
* the caller to flip the todo's status.
|
|
74
|
+
*
|
|
75
|
+
* Matching is normalize-then-equal first (lowercased; punctuation and
|
|
76
|
+
* whitespace runs both collapsed to a single space; trimmed), with a
|
|
77
|
+
* substring fallback in either direction so minor wording drift
|
|
78
|
+
* ("Sonnet #2: bug scan" vs "Sonnet #2") still links up. The substring
|
|
79
|
+
* fallback requires at least {@link TODO_DESCRIPTION_MIN_OVERLAP} chars on
|
|
80
|
+
* the contained side.
|
|
81
|
+
*/
|
|
82
|
+
export function todoMatchesAnyDescription(content: string, descriptions: readonly string[]): boolean {
|
|
83
|
+
const target = normalizeForTodoMatch(content);
|
|
84
|
+
if (!target) return false;
|
|
85
|
+
for (const desc of descriptions) {
|
|
86
|
+
const candidate = normalizeForTodoMatch(desc);
|
|
87
|
+
if (!candidate) continue;
|
|
88
|
+
if (target === candidate) return true;
|
|
89
|
+
if (target.length >= TODO_DESCRIPTION_MIN_OVERLAP && candidate.includes(target)) return true;
|
|
90
|
+
if (candidate.length >= TODO_DESCRIPTION_MIN_OVERLAP && target.includes(candidate)) return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Whether a todo is settled: completed or deliberately abandoned. Shared so
|
|
96
|
+
* the collapsed viewport, the HUD progress counters, and the HUD's closed-todo
|
|
97
|
+
* auto-clear can never disagree about what "done" hides. */
|
|
98
|
+
export function isClosedTodo<T extends { status: TodoStatus }>(task: T): boolean {
|
|
99
|
+
return task.status === "completed" || task.status === "abandoned";
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* A todo the collapsed viewport treats as current work: the literal
|
|
104
|
+
* `in_progress` task or a pending task a live subagent is executing. Both
|
|
105
|
+
* collapsed views (transient tool result + sticky HUD) run this same policy so
|
|
106
|
+
* they can never disagree about what the agent is doing (#5873).
|
|
107
|
+
*/
|
|
108
|
+
function isActiveTodo<T extends { status: TodoStatus }>(task: T, isMatched: (task: T) => boolean): boolean {
|
|
109
|
+
return task.status === "in_progress" || (task.status === "pending" && isMatched(task));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Result of {@link selectCollapsedTodos}: the rows to render plus an optional
|
|
113
|
+
* summary line (empty string ⇒ no summary row). */
|
|
114
|
+
export interface CollapsedTodoSelection<T> {
|
|
115
|
+
items: T[];
|
|
116
|
+
summary: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Closed rows kept directly above the open window so finishing a task is
|
|
121
|
+
* visible as it happens. Without this the collapsed viewport only ever renders
|
|
122
|
+
* unchecked boxes while a phase has open work: every completion silently
|
|
123
|
+
* removes a row, so a plan mid-flight looks untouched, and the card's
|
|
124
|
+
* completion strike animation (`completedTasks` → {@link TODO_STRIKE_TOTAL_FRAMES})
|
|
125
|
+
* animated a row that was never rendered.
|
|
126
|
+
*/
|
|
127
|
+
const COLLAPSED_CLOSED_CONTEXT = 1;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Rows to show for a display base already reduced to the relevant tasks.
|
|
131
|
+
*
|
|
132
|
+
* 1. Every active task (in-progress, or pending matched to a live subagent) is
|
|
133
|
+
* placed at the head in stable todo order — never dropped for lying outside
|
|
134
|
+
* an ordinary window.
|
|
135
|
+
* 2. Remaining rows up to `cap` are filled with the pending tasks that follow
|
|
136
|
+
* the first active one, in todo order (falling back to leading pending tasks
|
|
137
|
+
* when no active task exists), so a freshly-promoted task leads the preview.
|
|
138
|
+
* 3. When active tasks alone exceed `cap`, only the first `cap` active tasks are
|
|
139
|
+
* shown and the summary counts the hidden *active* todos, never replacing
|
|
140
|
+
* them with unrelated pending rows.
|
|
141
|
+
*/
|
|
142
|
+
function selectWithinCap<T extends { status: TodoStatus }>(
|
|
143
|
+
base: T[],
|
|
144
|
+
isMatched: (task: T) => boolean,
|
|
145
|
+
cap: number,
|
|
146
|
+
): CollapsedTodoSelection<T> {
|
|
147
|
+
if (base.length <= cap) return { items: base, summary: "" };
|
|
148
|
+
|
|
149
|
+
const active = base.filter(task => isActiveTodo(task, isMatched));
|
|
150
|
+
// Only when active work strictly exceeds the cap do we drop pending rows and
|
|
151
|
+
// count hidden *actives*. At exactly `cap` actives, fall through so the normal
|
|
152
|
+
// branch still surfaces any following pending work in the summary.
|
|
153
|
+
if (active.length > cap) {
|
|
154
|
+
const hiddenActive = active.length - cap;
|
|
155
|
+
return {
|
|
156
|
+
items: active.slice(0, cap),
|
|
157
|
+
summary: `… ${hiddenActive} more active ${pluralize("todo", hiddenActive)}`,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Fill trailing rows with tasks following the first active one, so the
|
|
162
|
+
// promoted/current task leads and its successors follow in todo order.
|
|
163
|
+
const firstActiveIdx = active.length > 0 ? base.indexOf(active[0]) : 0;
|
|
164
|
+
const fill: T[] = [];
|
|
165
|
+
for (let i = firstActiveIdx; i < base.length && active.length + fill.length < cap; i++) {
|
|
166
|
+
const task = base[i];
|
|
167
|
+
if (isActiveTodo(task, isMatched)) continue;
|
|
168
|
+
fill.push(task);
|
|
169
|
+
}
|
|
170
|
+
const items = [...active, ...fill];
|
|
171
|
+
const hidden = base.length - items.length;
|
|
172
|
+
return { items, summary: hidden > 0 ? formatMoreItems(hidden, "todo") : "" };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Walking-viewport selection for a phase's collapsed todo preview (#5873).
|
|
177
|
+
*
|
|
178
|
+
* Applied to `tasks` in todo order: the open tasks run through
|
|
179
|
+
* {@link selectWithinCap}, led by the last {@link COLLAPSED_CLOSED_CONTEXT}
|
|
180
|
+
* closed tasks in todo order so a checked row remains visible even when callers
|
|
181
|
+
* complete work out of sequence. The lead is additive — it never costs an open
|
|
182
|
+
* row — and a phase with no open work left falls back to its closed tasks so the
|
|
183
|
+
* sticky HUD's closed-todo persistence still has something to render.
|
|
184
|
+
*
|
|
185
|
+
* `summary` counts the open tasks that did not fit; the closed lead is context,
|
|
186
|
+
* not part of the budget.
|
|
187
|
+
*/
|
|
188
|
+
export function selectCollapsedTodos<T extends { status: TodoStatus }>(
|
|
189
|
+
tasks: T[],
|
|
190
|
+
isMatched: (task: T) => boolean,
|
|
191
|
+
cap: number,
|
|
192
|
+
): CollapsedTodoSelection<T> {
|
|
193
|
+
const open = tasks.filter(task => !isClosedTodo(task));
|
|
194
|
+
// Closed tasks are never active, so a settled phase selects over itself.
|
|
195
|
+
if (open.length === 0) return selectWithinCap(tasks, isMatched, cap);
|
|
196
|
+
// `done` accepts any named task, so closed tasks are not necessarily a prefix.
|
|
197
|
+
const lead = tasks.filter(isClosedTodo).slice(-COLLAPSED_CLOSED_CONTEXT);
|
|
198
|
+
const selected = selectWithinCap(open, isMatched, cap);
|
|
199
|
+
return { items: [...lead, ...selected.items], summary: selected.summary };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// =============================================================================
|
|
203
|
+
// TUI Renderer
|
|
204
|
+
// =============================================================================
|
|
205
|
+
|
|
206
|
+
type TodoRenderOp = {
|
|
207
|
+
op?: string;
|
|
208
|
+
task?: string;
|
|
209
|
+
phase?: string;
|
|
210
|
+
items?: string[];
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/** New single-op shape `{op,...}`; legacy `{ops:[...]}` still seen in old transcripts. */
|
|
214
|
+
type TodoRenderArgs = TodoRenderOp & {
|
|
215
|
+
ops?: TodoRenderOp[];
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Normalize streaming/legacy render args to a flat op list. Accepts the new
|
|
220
|
+
* top-level `{op,...}` shape (returned as a one-element list), the legacy
|
|
221
|
+
* `{ops:[...]}` batch from old transcripts/collab-web, and partially-parsed
|
|
222
|
+
* streaming deltas (non-array `ops`, non-object entries) without crashing.
|
|
223
|
+
*/
|
|
224
|
+
function normalizeTodoArg(args: TodoRenderArgs | undefined): TodoRenderOp[] {
|
|
225
|
+
if (!args || typeof args !== "object") return [];
|
|
226
|
+
if (Array.isArray(args.ops)) {
|
|
227
|
+
return args.ops.filter((entry): entry is TodoRenderOp => !!entry && typeof entry === "object");
|
|
228
|
+
}
|
|
229
|
+
return typeof args.op === "string" ? [args] : [];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// =============================================================================
|
|
233
|
+
// Phase numbering (display-only)
|
|
234
|
+
// =============================================================================
|
|
235
|
+
|
|
236
|
+
const ROMAN_PAIRS: Array<[number, string]> = [
|
|
237
|
+
[1000, "M"],
|
|
238
|
+
[900, "CM"],
|
|
239
|
+
[500, "D"],
|
|
240
|
+
[400, "CD"],
|
|
241
|
+
[100, "C"],
|
|
242
|
+
[90, "XC"],
|
|
243
|
+
[50, "L"],
|
|
244
|
+
[40, "XL"],
|
|
245
|
+
[10, "X"],
|
|
246
|
+
[9, "IX"],
|
|
247
|
+
[5, "V"],
|
|
248
|
+
[4, "IV"],
|
|
249
|
+
[1, "I"],
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
/** One-based ASCII roman numeral for display (I, II, III, IV, …). */
|
|
253
|
+
export function phaseRomanNumeral(oneBasedIndex: number): string {
|
|
254
|
+
if (oneBasedIndex <= 0) return "";
|
|
255
|
+
let out = "";
|
|
256
|
+
let rem = oneBasedIndex;
|
|
257
|
+
for (const [value, sym] of ROMAN_PAIRS) {
|
|
258
|
+
while (rem >= value) {
|
|
259
|
+
out += sym;
|
|
260
|
+
rem -= value;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return out;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Every render boundary in this file funnels display text through here.
|
|
268
|
+
*
|
|
269
|
+
* `sanitizeText` strips ANSI/C0 sequences but deliberately preserves tabs, and
|
|
270
|
+
* a raw tab punches holes in bordered TUI output, so both are needed. The raw
|
|
271
|
+
* value stays untouched everywhere else: task content and phase names are the
|
|
272
|
+
* identity keys the local list is looked up by, and what gets persisted.
|
|
273
|
+
*/
|
|
274
|
+
function forDisplay(text: string): string {
|
|
275
|
+
return replaceTabs(sanitizeText(text));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Display-only phase header: `I. Foundation`. State and prompts never see this.
|
|
280
|
+
*
|
|
281
|
+
* Sanitized for the same reason task labels are: this is a render boundary and
|
|
282
|
+
* the name may carry provider or session text holding control sequences. The
|
|
283
|
+
* raw `phase.name` stays the lookup key everywhere else.
|
|
284
|
+
*/
|
|
285
|
+
export function formatPhaseDisplayName(name: string, oneBasedIndex: number): string {
|
|
286
|
+
return `${phaseRomanNumeral(oneBasedIndex)}. ${forDisplay(name)}`;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** Frames held before revealing a completion strike. */
|
|
290
|
+
export const TODO_STRIKE_HOLD_FRAMES = 2;
|
|
291
|
+
|
|
292
|
+
/** Frames used to reveal a completion strike. */
|
|
293
|
+
export const TODO_STRIKE_REVEAL_FRAMES = 12;
|
|
294
|
+
|
|
295
|
+
/** Total frames in the completion strike animation. */
|
|
296
|
+
export const TODO_STRIKE_TOTAL_FRAMES = TODO_STRIKE_HOLD_FRAMES + TODO_STRIKE_REVEAL_FRAMES;
|
|
297
|
+
|
|
298
|
+
const EMPTY_COMPLETION_KEYS = new Set<string>();
|
|
299
|
+
|
|
300
|
+
const STRIKE_START = "\x1b[9m";
|
|
301
|
+
|
|
302
|
+
const STRIKE_END = "\x1b[29m";
|
|
303
|
+
|
|
304
|
+
function strikethroughText(text: string): string {
|
|
305
|
+
return `${STRIKE_START}${text}${STRIKE_END}`;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function partialStrikethrough(text: string, visibleChars: number): string {
|
|
309
|
+
if (visibleChars <= 0) return text;
|
|
310
|
+
const chars = [...text];
|
|
311
|
+
if (visibleChars >= chars.length) return strikethroughText(text);
|
|
312
|
+
return `${strikethroughText(chars.slice(0, visibleChars).join(""))}${chars.slice(visibleChars).join("")}`;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function strikeRevealCount(text: string, frame: number | undefined): number | undefined {
|
|
316
|
+
if (frame === undefined) return undefined;
|
|
317
|
+
if (frame <= TODO_STRIKE_HOLD_FRAMES) return 0;
|
|
318
|
+
const chars = [...text];
|
|
319
|
+
if (chars.length === 0) return undefined;
|
|
320
|
+
const revealFrame = Math.min(frame - TODO_STRIKE_HOLD_FRAMES, TODO_STRIKE_REVEAL_FRAMES);
|
|
321
|
+
return Math.ceil((chars.length * revealFrame) / TODO_STRIKE_REVEAL_FRAMES);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function formatTodoLine(
|
|
325
|
+
item: TodoItem,
|
|
326
|
+
uiTheme: Theme,
|
|
327
|
+
prefix: string,
|
|
328
|
+
completionKeys: Set<string>,
|
|
329
|
+
frame: number | undefined,
|
|
330
|
+
matched = false,
|
|
331
|
+
): string {
|
|
332
|
+
const checkbox = uiTheme.checkbox;
|
|
333
|
+
// Sanitize only for display. A mirrored Cursor snapshot carries provider text
|
|
334
|
+
// verbatim, and a label holding ANSI/C0 sequences would otherwise rewrite the
|
|
335
|
+
// terminal every time the list renders or replays. `item.content` stays raw
|
|
336
|
+
// everywhere else: it is the identity key the local list is looked up by
|
|
337
|
+
// (`findTaskByContent`) and what gets persisted.
|
|
338
|
+
const label = forDisplay(item.content);
|
|
339
|
+
switch (item.status) {
|
|
340
|
+
case "completed": {
|
|
341
|
+
const revealCount = completionKeys.has(item.content) ? strikeRevealCount(label, frame) : undefined;
|
|
342
|
+
const content =
|
|
343
|
+
revealCount === undefined ? strikethroughText(label) : partialStrikethrough(label, revealCount);
|
|
344
|
+
return uiTheme.fg("success", `${prefix}${checkbox.checked} ${content}`);
|
|
345
|
+
}
|
|
346
|
+
case "in_progress":
|
|
347
|
+
return uiTheme.fg("accent", `${prefix}${checkbox.unchecked} ${label}`);
|
|
348
|
+
case "abandoned":
|
|
349
|
+
return uiTheme.fg("error", `${prefix}${checkbox.unchecked} ${strikethroughText(label)}`);
|
|
350
|
+
case "blocked": {
|
|
351
|
+
const note = item.blocker ? `blocked: ${forDisplay(item.blocker)}` : "blocked";
|
|
352
|
+
return uiTheme.fg("warning", `${prefix}${checkbox.unchecked} ${label} (${note})`);
|
|
353
|
+
}
|
|
354
|
+
default:
|
|
355
|
+
// A pending todo lit by a live subagent match renders accent, matching
|
|
356
|
+
// the sticky HUD's convention (#5873).
|
|
357
|
+
return uiTheme.fg(matched ? "accent" : "dim", `${prefix}${checkbox.unchecked} ${label}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Phases the latest update touched, plus the active (in_progress) phase.
|
|
363
|
+
* Returns `null` when there is no usable signal, meaning "render every phase
|
|
364
|
+
* fully" — this preserves the legacy view and the manual-expand path.
|
|
365
|
+
*/
|
|
366
|
+
function computeTouchedPhases(
|
|
367
|
+
args: TodoRenderArgs | undefined,
|
|
368
|
+
phases: TodoPhase[],
|
|
369
|
+
completedTasks: TodoCompletionTransition[],
|
|
370
|
+
): Set<string> | null {
|
|
371
|
+
const touched = new Set<string>();
|
|
372
|
+
// The phase holding the in_progress task is where attention sits after the
|
|
373
|
+
// auto-promotion that follows every completion.
|
|
374
|
+
for (const phase of phases) {
|
|
375
|
+
if (phase.tasks.some(task => task.status === "in_progress")) touched.add(phase.name);
|
|
376
|
+
}
|
|
377
|
+
// Phases with a task that just transitioned to completed in this update.
|
|
378
|
+
for (const transition of completedTasks) touched.add(transition.phase);
|
|
379
|
+
// Phases explicitly named by the ops that ran. `init` replaces the whole
|
|
380
|
+
// list, so the entire plan is fresh and every phase counts as touched.
|
|
381
|
+
const ops = normalizeTodoArg(args);
|
|
382
|
+
for (const op of ops) {
|
|
383
|
+
if (!op || typeof op !== "object") continue;
|
|
384
|
+
if (op.op === "init") {
|
|
385
|
+
for (const phase of phases) touched.add(phase.name);
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
if (typeof op.phase === "string" && op.phase) {
|
|
389
|
+
const named = phases.find(phase => phase.name === op.phase);
|
|
390
|
+
if (named) touched.add(named.name);
|
|
391
|
+
}
|
|
392
|
+
if (typeof op.task === "string" && op.task) {
|
|
393
|
+
const phase = phases.find(phase => phase.tasks.some(task => task.content === op.task));
|
|
394
|
+
if (phase) touched.add(phase.name);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return touched.size > 0 ? touched : null;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Dim `closed/total` suffix for a phase header. Counts closed tasks, not just
|
|
402
|
+
* completed ones: the collapsed viewport hides both, so an abandoned task has to
|
|
403
|
+
* move the counter or its phase reads as permanently stuck.
|
|
404
|
+
*/
|
|
405
|
+
function formatPhaseProgress(phase: TodoPhase, uiTheme: Theme): string {
|
|
406
|
+
const done = phase.tasks.filter(isClosedTodo).length;
|
|
407
|
+
return uiTheme.fg("dim", ` ${done}/${phase.tasks.length}`);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/** One-line summary for a collapsed (untouched) phase: dim header + progress. */
|
|
411
|
+
function formatPhaseSummary(phase: TodoPhase, oneBasedIndex: number, uiTheme: Theme): string {
|
|
412
|
+
const name = uiTheme.fg("dim", chalk.bold(formatPhaseDisplayName(phase.name, oneBasedIndex)));
|
|
413
|
+
return `${name}${formatPhaseProgress(phase, uiTheme)}`;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Live subagent descriptions the transient tool result uses to detect
|
|
418
|
+
* pending todos being executed by an in-flight subagent, so its collapsed
|
|
419
|
+
* viewport surfaces the same active work the sticky HUD does (#5873). Wired
|
|
420
|
+
* once by interactive mode from its observer registry; returns `[]` outside an
|
|
421
|
+
* interactive session (tests, SDK, transcript rebuilds), where only literal
|
|
422
|
+
* `in_progress` counts as active.
|
|
423
|
+
*/
|
|
424
|
+
let activeTodoDescriptionsProvider: () => readonly string[] = () => [];
|
|
425
|
+
|
|
426
|
+
/** Wire the live-subagent description source for {@link todoToolRenderer}. */
|
|
427
|
+
export function setActiveTodoDescriptionsProvider(provider: () => readonly string[]): void {
|
|
428
|
+
activeTodoDescriptionsProvider = provider;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** Render todo operations and phased task snapshots. */
|
|
432
|
+
export const todoToolRenderer = {
|
|
433
|
+
renderCall(args: TodoRenderArgs, options: RenderResultOptions, uiTheme: Theme): Component {
|
|
434
|
+
// `args` is the raw partially-parsed JSON from the streaming tool-call
|
|
435
|
+
// delta and may not satisfy `TodoRenderArgs` at runtime:
|
|
436
|
+
// `parseStreamingJson` can hand back `{ op: 1 }` mid-delta, or a legacy
|
|
437
|
+
// `{ ops: "[" }` shape before fields stream. `normalizeTodoArg` guards
|
|
438
|
+
// both the new single-op and legacy batch shapes so a malformed delta
|
|
439
|
+
// never breaks the TUI render loop (#2005).
|
|
440
|
+
const opsList = normalizeTodoArg(args);
|
|
441
|
+
// Model-authored, partially-streamed strings going straight into a header:
|
|
442
|
+
// `renderStatusLine` only flattens CR/LF and leaves the rest to the caller.
|
|
443
|
+
const ops =
|
|
444
|
+
opsList.length === 0
|
|
445
|
+
? ["update"]
|
|
446
|
+
: opsList.map(e => {
|
|
447
|
+
const parts = [forDisplay(e.op ?? "update")];
|
|
448
|
+
if (e.task) parts.push(forDisplay(e.task));
|
|
449
|
+
if (e.phase) parts.push(forDisplay(e.phase));
|
|
450
|
+
if (Array.isArray(e.items) && e.items.length) {
|
|
451
|
+
parts.push(`${e.items.length} item${e.items.length === 1 ? "" : "s"}`);
|
|
452
|
+
}
|
|
453
|
+
return parts.join(" ");
|
|
454
|
+
});
|
|
455
|
+
// No body worth boxing while the call streams — a lone status line reads
|
|
456
|
+
// cleaner than an empty frame. The container renders it without chrome.
|
|
457
|
+
const header = renderStatusLine(
|
|
458
|
+
{ icon: "pending", spinnerFrame: options?.spinnerFrame, title: "Todo", meta: ops },
|
|
459
|
+
uiTheme,
|
|
460
|
+
);
|
|
461
|
+
return new Text(header, 0, 0);
|
|
462
|
+
},
|
|
463
|
+
|
|
464
|
+
renderResult(
|
|
465
|
+
result: { content: Array<{ type: string; text?: string }>; details?: TodoToolDetails; isError?: boolean },
|
|
466
|
+
options: RenderResultOptions,
|
|
467
|
+
uiTheme: Theme,
|
|
468
|
+
args?: TodoRenderArgs,
|
|
469
|
+
): Component {
|
|
470
|
+
if (result.isError) {
|
|
471
|
+
const errorText = result.content?.find(content => content.type === "text")?.text ?? "Todo operation failed";
|
|
472
|
+
const header = renderStatusLine({ icon: "error", title: "Todo" }, uiTheme);
|
|
473
|
+
return framedToolCard(uiTheme, () => ({
|
|
474
|
+
header,
|
|
475
|
+
sections: [{ content: formatErrorDetail(errorText, uiTheme).split("\n") }],
|
|
476
|
+
phase: "error",
|
|
477
|
+
borderColor: "error",
|
|
478
|
+
}));
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const phases = (result.details?.phases ?? []).filter(phase => phase.tasks.length > 0);
|
|
482
|
+
const completedTasks = result.details?.completedTasks ?? [];
|
|
483
|
+
const completionKeysByPhase = new Map<string, Set<string>>();
|
|
484
|
+
for (const task of completedTasks) {
|
|
485
|
+
let keys = completionKeysByPhase.get(task.phase);
|
|
486
|
+
if (!keys) {
|
|
487
|
+
keys = new Set<string>();
|
|
488
|
+
completionKeysByPhase.set(task.phase, keys);
|
|
489
|
+
}
|
|
490
|
+
keys.add(task.content);
|
|
491
|
+
}
|
|
492
|
+
const allTasks = phases.flatMap(phase => phase.tasks);
|
|
493
|
+
const header = renderStatusLine(
|
|
494
|
+
{
|
|
495
|
+
iconOverride: uiTheme.styledSymbol("tool.todo", "accent"),
|
|
496
|
+
title: "Todo",
|
|
497
|
+
meta: [`${allTasks.length} tasks`],
|
|
498
|
+
},
|
|
499
|
+
uiTheme,
|
|
500
|
+
);
|
|
501
|
+
if (allTasks.length === 0) {
|
|
502
|
+
// Provider text on the Cursor path (the todo summary or a refusal note),
|
|
503
|
+
// so sanitize like every other label. The error branch above already
|
|
504
|
+
// goes through `formatErrorDetail`.
|
|
505
|
+
const fallback = forDisplay(result.content?.find(content => content.type === "text")?.text ?? "No todos");
|
|
506
|
+
return new Text(`${header}\n ${uiTheme.fg("dim", fallback)}`, 0, 0);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return framedToolCard(uiTheme, () => {
|
|
510
|
+
const { expanded, spinnerFrame } = options;
|
|
511
|
+
const multiPhase = phases.length > 1;
|
|
512
|
+
const indent = multiPhase ? " " : "";
|
|
513
|
+
// Collapse phases this update didn't touch down to a one-line summary so
|
|
514
|
+
// a single task flip doesn't redraw every phase's full task list. The
|
|
515
|
+
// manual expand toggle (and the no-signal fallback) still shows all.
|
|
516
|
+
const touched = expanded || !multiPhase ? null : computeTouchedPhases(args, phases, completedTasks);
|
|
517
|
+
// A pending todo counts as active work when an in-flight subagent is
|
|
518
|
+
// executing it — the transient result surfaces the same active set the
|
|
519
|
+
// sticky HUD does (#5873). Empty outside an interactive session.
|
|
520
|
+
const activeDescs = expanded ? [] : activeTodoDescriptionsProvider();
|
|
521
|
+
const isMatched = (task: TodoItem): boolean =>
|
|
522
|
+
activeDescs.length > 0 && todoMatchesAnyDescription(task.content, activeDescs);
|
|
523
|
+
const bodyLines: string[] = [];
|
|
524
|
+
for (let p = 0; p < phases.length; p++) {
|
|
525
|
+
const phase = phases[p];
|
|
526
|
+
if (touched && !touched.has(phase.name)) {
|
|
527
|
+
bodyLines.push(formatPhaseSummary(phase, p + 1, uiTheme));
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
if (multiPhase) {
|
|
531
|
+
// Progress belongs on the expanded header too: the collapsed
|
|
532
|
+
// viewport below hides closed rows, so without it the phase the
|
|
533
|
+
// agent is actually working in is the one phase with no visible
|
|
534
|
+
// completion signal at all.
|
|
535
|
+
const name = uiTheme.fg("accent", chalk.bold(formatPhaseDisplayName(phase.name, p + 1)));
|
|
536
|
+
bodyLines.push(`${name}${formatPhaseProgress(phase, uiTheme)}`);
|
|
537
|
+
}
|
|
538
|
+
const completionKeys = completionKeysByPhase.get(phase.name) ?? EMPTY_COMPLETION_KEYS;
|
|
539
|
+
// Collapsed: walking viewport — the last closed task leads, then
|
|
540
|
+
// active work (in-progress / subagent-matched), then following
|
|
541
|
+
// pending tasks (#5873). Expanded: every task in order.
|
|
542
|
+
const treeLines = expanded
|
|
543
|
+
? renderTreeList(
|
|
544
|
+
{
|
|
545
|
+
items: phase.tasks,
|
|
546
|
+
expanded,
|
|
547
|
+
itemType: "todo",
|
|
548
|
+
renderItem: todo => formatTodoLine(todo, uiTheme, "", completionKeys, spinnerFrame),
|
|
549
|
+
},
|
|
550
|
+
uiTheme,
|
|
551
|
+
)
|
|
552
|
+
: (() => {
|
|
553
|
+
const selection = selectCollapsedTodos(phase.tasks, isMatched, PREVIEW_LIMITS.COLLAPSED_ITEMS);
|
|
554
|
+
return renderTreeList(
|
|
555
|
+
{
|
|
556
|
+
items: selection.items,
|
|
557
|
+
itemType: "todo",
|
|
558
|
+
trailingSummary: selection.summary,
|
|
559
|
+
renderItem: todo =>
|
|
560
|
+
formatTodoLine(todo, uiTheme, "", completionKeys, spinnerFrame, isMatched(todo)),
|
|
561
|
+
},
|
|
562
|
+
uiTheme,
|
|
563
|
+
);
|
|
564
|
+
})();
|
|
565
|
+
for (const line of treeLines) {
|
|
566
|
+
bodyLines.push(`${indent}${line}`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
while (bodyLines.length > 0 && bodyLines[0].trim() === "") bodyLines.shift();
|
|
570
|
+
return {
|
|
571
|
+
header,
|
|
572
|
+
sections: bodyLines.length > 0 ? [{ content: bodyLines }] : [],
|
|
573
|
+
phase: options.isPartial ? "partial" : "success",
|
|
574
|
+
borderColor: "borderMuted",
|
|
575
|
+
applyBg: false,
|
|
576
|
+
};
|
|
577
|
+
});
|
|
578
|
+
},
|
|
579
|
+
mergeCallAndResult: true,
|
|
580
|
+
} satisfies ToolRenderer<TodoRenderArgs, TodoToolDetails>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Structured tool failure shared by selector parsing and host tool execution. */
|
|
2
|
+
export class ToolError extends Error {
|
|
3
|
+
constructor(
|
|
4
|
+
message: string,
|
|
5
|
+
readonly context?: Record<string, unknown>,
|
|
6
|
+
) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "ToolError";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Render error for LLM consumption. Override for custom formatting. */
|
|
12
|
+
render(): string {
|
|
13
|
+
return this.message;
|
|
14
|
+
}
|
|
15
|
+
}
|