@oh-my-pi/pi-tui 18.4.2 → 18.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/dist/types/apps/cleanse-board.d.ts +17 -0
- package/dist/types/apps/git/help.d.ts +16 -0
- package/dist/types/apps/git/sidebar.d.ts +18 -0
- package/dist/types/apps/live-visualizer.d.ts +10 -0
- package/dist/types/apps/ps-top.d.ts +15 -0
- package/dist/types/apps/standalone-picker.d.ts +3 -0
- package/dist/types/autocomplete.d.ts +8 -0
- package/dist/types/chat/advisor-message.d.ts +12 -2
- package/dist/types/chat/assistant-message.d.ts +20 -0
- package/dist/types/chat/bash-execution.d.ts +9 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +6 -1
- package/dist/types/chat/collab-prompt-message.d.ts +4 -0
- package/dist/types/chat/compaction-summary-message.d.ts +15 -0
- package/dist/types/chat/eval-execution.d.ts +8 -0
- package/dist/types/chat/execution-shared.d.ts +58 -0
- package/dist/types/chat/late-diagnostics-message.d.ts +15 -1
- package/dist/types/chat/read-tool-group.d.ts +15 -0
- package/dist/types/chat/skill-message.d.ts +9 -0
- package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +3 -0
- package/dist/types/chat/thinking-display.d.ts +2 -0
- package/dist/types/chat/todo-reminder.d.ts +4 -1
- package/dist/types/chat/tool-execution.d.ts +25 -1
- package/dist/types/chat/transcript-actions.d.ts +37 -0
- package/dist/types/chat/transcript-entry.d.ts +3 -1
- package/dist/types/chat/user-message.d.ts +25 -0
- package/dist/types/chrome/collab-qrcode.d.ts +7 -0
- package/dist/types/chrome/context-thresholds.d.ts +11 -0
- package/dist/types/chrome/countdown-timer.d.ts +9 -3
- package/dist/types/chrome/diff.d.ts +12 -0
- package/dist/types/chrome/dynamic-border.d.ts +3 -0
- package/dist/types/chrome/format.d.ts +6 -0
- package/dist/types/chrome/message-divider.d.ts +13 -0
- package/dist/types/chrome/message-frame.d.ts +10 -0
- package/dist/types/chrome/message-notice.d.ts +23 -0
- package/dist/types/chrome/overlay-box.d.ts +11 -2
- package/dist/types/chrome/qrcode.d.ts +7 -0
- package/dist/types/chrome/segment-track.d.ts +7 -0
- package/dist/types/chrome/selector-helpers.d.ts +0 -6
- package/dist/types/chrome/status-notice.d.ts +14 -0
- package/dist/types/chrome/streaming-panel.d.ts +3 -0
- package/dist/types/chrome/tool-activity.d.ts +3 -0
- package/dist/types/chrome/transcript-container.d.ts +13 -0
- package/dist/types/chrome/transcript-status.d.ts +15 -3
- package/dist/types/components/box.d.ts +7 -0
- package/dist/types/components/disclosure.d.ts +9 -0
- package/dist/types/components/editor.d.ts +42 -0
- package/dist/types/components/form.d.ts +14 -0
- package/dist/types/components/image.d.ts +7 -0
- package/dist/types/components/input.d.ts +20 -1
- package/dist/types/components/key-value-list.d.ts +3 -0
- package/dist/types/components/layout/geometry.d.ts +16 -0
- package/dist/types/components/layout/row.d.ts +7 -0
- package/dist/types/components/layout/split-pane.d.ts +8 -0
- package/dist/types/components/layout/stack.d.ts +6 -0
- package/dist/types/components/loader.d.ts +48 -0
- package/dist/types/components/markdown.d.ts +8 -0
- package/dist/types/components/metric.d.ts +7 -0
- package/dist/types/components/progress-bar.d.ts +3 -0
- package/dist/types/components/scroll-view.d.ts +6 -0
- package/dist/types/components/section.d.ts +3 -0
- package/dist/types/components/select-list.d.ts +33 -0
- package/dist/types/components/settings-list.d.ts +68 -0
- package/dist/types/components/spacer.d.ts +4 -0
- package/dist/types/components/tab-bar.d.ts +9 -0
- package/dist/types/components/table.d.ts +7 -0
- package/dist/types/components/text.d.ts +6 -0
- package/dist/types/components/tree-view.d.ts +9 -0
- package/dist/types/components/truncated-text.d.ts +3 -0
- package/dist/types/components/wizard-step.d.ts +6 -0
- package/dist/types/hotkeys-markdown.d.ts +24 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/latex-block.d.ts +7 -0
- package/dist/types/loop-watchdog.d.ts +9 -0
- package/dist/types/native/apply.d.ts +39 -0
- package/dist/types/native/backend.d.ts +94 -0
- package/dist/types/native/blobs.d.ts +29 -0
- package/dist/types/native/describe.d.ts +56 -0
- package/dist/types/native/encode.d.ts +50 -0
- package/dist/types/native/icons.d.ts +18 -0
- package/dist/types/native/memo.d.ts +27 -0
- package/dist/types/native/node.d.ts +107 -0
- package/dist/types/native/overlay.d.ts +64 -0
- package/dist/types/native/picker.d.ts +124 -0
- package/dist/types/native/reconcile.d.ts +41 -0
- package/dist/types/native/settle.d.ts +11 -0
- package/dist/types/native/spans.d.ts +21 -0
- package/dist/types/native/state.d.ts +6 -0
- package/dist/types/native/tone.d.ts +24 -0
- package/dist/types/overlays/advisor-config.d.ts +20 -0
- package/dist/types/overlays/agent-hub-renderer.d.ts +27 -11
- package/dist/types/overlays/agent-hub.d.ts +10 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +7 -0
- package/dist/types/overlays/agents-hub.d.ts +8 -0
- package/dist/types/overlays/annotation-overlay.d.ts +3 -0
- package/dist/types/overlays/ask-dialog.d.ts +23 -0
- package/dist/types/overlays/bordered-loader.d.ts +3 -0
- package/dist/types/overlays/btw-history-panel.d.ts +9 -0
- package/dist/types/overlays/btw-panel.d.ts +3 -0
- package/dist/types/overlays/cleanse-panel.d.ts +5 -2
- package/dist/types/overlays/composer-shape-preview.d.ts +7 -1
- package/dist/types/overlays/copy-selector.d.ts +38 -0
- package/dist/types/overlays/error-banner.d.ts +9 -0
- package/dist/types/overlays/extensions/extension-list.d.ts +1 -0
- package/dist/types/overlays/history-search.d.ts +18 -0
- package/dist/types/overlays/hook-editor.d.ts +28 -1
- package/dist/types/overlays/hook-input.d.ts +3 -0
- package/dist/types/overlays/hook-selector.d.ts +10 -0
- package/dist/types/overlays/hub-frame.d.ts +18 -0
- package/dist/types/overlays/jobs-panel.d.ts +24 -0
- package/dist/types/overlays/login-dialog.d.ts +10 -0
- package/dist/types/overlays/logout-account-selector.d.ts +4 -0
- package/dist/types/overlays/mcp-add-wizard.d.ts +4 -0
- package/dist/types/overlays/model-browser.d.ts +69 -0
- package/dist/types/overlays/model-hub.d.ts +7 -0
- package/dist/types/overlays/model-picker.d.ts +9 -1
- package/dist/types/overlays/move-overlay.d.ts +3 -0
- package/dist/types/overlays/oauth-selector.d.ts +4 -0
- package/dist/types/overlays/omfg-panel.d.ts +3 -0
- package/dist/types/overlays/pause-screen.d.ts +12 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +5 -0
- package/dist/types/overlays/plan-save-overlay.d.ts +10 -0
- package/dist/types/overlays/plugin-selector.d.ts +4 -0
- package/dist/types/overlays/plugin-settings.d.ts +30 -0
- package/dist/types/overlays/queue-mode-selector.d.ts +4 -0
- package/dist/types/overlays/reset-usage-selector.d.ts +8 -0
- package/dist/types/overlays/rewind-selector.d.ts +5 -0
- package/dist/types/overlays/session-info-overlay.d.ts +19 -1
- package/dist/types/overlays/session-selector.d.ts +64 -1
- package/dist/types/overlays/settings-defs.d.ts +14 -0
- package/dist/types/overlays/settings-selector.d.ts +21 -0
- package/dist/types/overlays/show-images-selector.d.ts +4 -0
- package/dist/types/overlays/snapcompact-shape-preview.d.ts +2 -0
- package/dist/types/overlays/stats-notice.d.ts +8 -0
- package/dist/types/overlays/theme-selector.d.ts +11 -0
- package/dist/types/overlays/thinking-selector.d.ts +4 -0
- package/dist/types/overlays/tree-selector.d.ts +60 -2
- package/dist/types/overlays/usage-dashboard.d.ts +26 -3
- package/dist/types/overlays/usage-row.d.ts +36 -2
- package/dist/types/prompt/attachment-chips.d.ts +8 -0
- package/dist/types/prompt/composer-attachments.d.ts +15 -3
- package/dist/types/prompt/composer.d.ts +18 -1
- package/dist/types/prompt/custom-editor.d.ts +48 -2
- package/dist/types/prompt/editor-top-gap.d.ts +2 -0
- package/dist/types/prompt/macos-spelling.d.ts +6 -0
- package/dist/types/prompt/magic-keywords.d.ts +9 -0
- package/dist/types/prompt/queued-messages.d.ts +23 -0
- package/dist/types/prompt/skill-tokens.d.ts +4 -2
- package/dist/types/prompt/welcome.d.ts +16 -0
- package/dist/types/render/code-cell.d.ts +10 -0
- package/dist/types/render/file-list.d.ts +8 -0
- package/dist/types/render/hyperlink.d.ts +14 -0
- package/dist/types/render/output-block.d.ts +43 -0
- package/dist/types/render/output-pane.d.ts +17 -0
- package/dist/types/render/tool-card.d.ts +8 -0
- package/dist/types/render/tree-list.d.ts +8 -0
- package/dist/types/render/width-aware-text.d.ts +7 -0
- package/dist/types/setup/scenes/outro.d.ts +7 -0
- package/dist/types/setup/scenes/sign-in.d.ts +16 -9
- package/dist/types/setup/scenes/splash.d.ts +8 -0
- package/dist/types/setup/scenes/types.d.ts +6 -27
- package/dist/types/setup/wizard-overlay.d.ts +9 -0
- package/dist/types/status-line/component.d.ts +49 -5
- package/dist/types/status-line/context-usage.d.ts +20 -0
- package/dist/types/status-line/footer.d.ts +8 -0
- package/dist/types/status-line/metrics.d.ts +1 -2
- package/dist/types/status-line/segments.d.ts +10 -1
- package/dist/types/status-line/types.d.ts +40 -1
- package/dist/types/stdin-buffer.d.ts +10 -7
- package/dist/types/terminal-capabilities.d.ts +1 -1
- package/dist/types/terminal.d.ts +36 -0
- package/dist/types/theme/defaults/index.d.ts +100 -0
- package/dist/types/theme/schema.d.ts +2 -0
- package/dist/types/theme/shimmer.d.ts +8 -0
- package/dist/types/theme/theme-class.d.ts +2 -0
- package/dist/types/theme/theme.d.ts +33 -1
- package/dist/types/tools/ask.d.ts +3 -0
- package/dist/types/tools/ast-edit.d.ts +10 -1
- package/dist/types/tools/ast-grep.d.ts +10 -1
- package/dist/types/tools/autoresearch.d.ts +21 -4
- package/dist/types/tools/bash.d.ts +30 -1
- package/dist/types/tools/cfg-render.d.ts +5 -1
- package/dist/types/tools/debug.d.ts +3 -1
- package/dist/types/tools/default-renderer.d.ts +6 -1
- package/dist/types/tools/edit.d.ts +14 -1
- package/dist/types/tools/eval.d.ts +12 -1
- package/dist/types/tools/fetch.d.ts +16 -1
- package/dist/types/tools/find.d.ts +15 -1
- package/dist/types/tools/github.d.ts +3 -0
- package/dist/types/tools/glob.d.ts +14 -1
- package/dist/types/tools/goal.d.ts +3 -1
- package/dist/types/tools/grep.d.ts +14 -1
- package/dist/types/tools/grouped-file-output.d.ts +58 -0
- package/dist/types/tools/json-tree.d.ts +20 -0
- package/dist/types/tools/lsp.d.ts +3 -10
- package/dist/types/tools/mcp.d.ts +16 -1
- package/dist/types/tools/memory.d.ts +26 -0
- package/dist/types/tools/native-view.d.ts +90 -0
- package/dist/types/tools/proc-render.d.ts +7 -1
- package/dist/types/tools/read.d.ts +23 -1
- package/dist/types/tools/renderer.d.ts +57 -0
- package/dist/types/tools/report-tool-issue.d.ts +3 -0
- package/dist/types/tools/resolve.d.ts +14 -1
- package/dist/types/tools/task.d.ts +3 -0
- package/dist/types/tools/think.d.ts +3 -0
- package/dist/types/tools/todo.d.ts +12 -0
- package/dist/types/tools/vibe.d.ts +3 -1
- package/dist/types/tools/wait.d.ts +3 -0
- package/dist/types/tools/web-search-types.d.ts +90 -0
- package/dist/types/tools/web-search.d.ts +9 -168
- package/dist/types/tools/write.d.ts +14 -1
- package/dist/types/tools/xdev.d.ts +13 -0
- package/dist/types/tui.d.ts +49 -0
- package/package.json +9 -9
- package/src/apps/autoresearch-dashboard.ts +362 -4
- package/src/apps/cleanse-board.ts +219 -1
- package/src/apps/cleanse-picker.ts +9 -1
- package/src/apps/debug/log-viewer.ts +15 -15
- package/src/apps/debug/protocol-probe.ts +2 -20
- package/src/apps/git/avatar.ts +2 -22
- package/src/apps/git/git-tui.ts +406 -59
- package/src/apps/git/help.ts +130 -0
- package/src/apps/git/sidebar.ts +491 -0
- package/src/apps/live-visualizer.ts +65 -0
- package/src/apps/ps-top.ts +448 -17
- package/src/apps/session-picker.ts +1 -0
- package/src/apps/setup-model-picker.ts +5 -1
- package/src/apps/standalone-picker.ts +55 -1
- package/src/autocomplete.ts +44 -1
- package/src/chat/advisor-message.ts +72 -3
- package/src/chat/assistant-message.ts +538 -51
- package/src/chat/background-tan-message.ts +4 -4
- package/src/chat/bash-execution.ts +81 -0
- package/src/chat/cache-invalidation-marker.ts +8 -0
- package/src/chat/chat-transcript-builder.ts +37 -6
- package/src/chat/collab-prompt-message.ts +15 -3
- package/src/chat/compaction-summary-message.ts +74 -1
- package/src/chat/custom-message.ts +3 -1
- package/src/chat/eval-execution.ts +57 -0
- package/src/chat/execution-shared.ts +153 -1
- package/src/chat/hook-message.ts +1 -0
- package/src/chat/late-diagnostics-message.ts +85 -2
- package/src/chat/read-tool-group.ts +341 -1
- package/src/chat/served-model-marker.ts +8 -0
- package/src/chat/skill-message.ts +63 -0
- package/src/chat/stripped-tool-calls-placeholder.ts +18 -10
- package/src/chat/thinking-display.ts +73 -11
- package/src/chat/todo-reminder.ts +34 -4
- package/src/chat/tool-execution.ts +385 -10
- package/src/chat/transcript-actions.ts +38 -0
- package/src/chat/transcript-browser.ts +2 -9
- package/src/chat/transcript-entry.ts +10 -1
- package/src/chat/transcript-render-helpers.ts +16 -15
- package/src/chat/ttsr-notification.ts +38 -1
- package/src/chat/user-message.ts +167 -4
- package/src/chrome/collab-qrcode.ts +27 -2
- package/src/chrome/context-thresholds.ts +34 -0
- package/src/chrome/countdown-timer.ts +24 -1
- package/src/chrome/diff.ts +60 -1
- package/src/chrome/dynamic-border.ts +7 -0
- package/src/chrome/format.ts +12 -0
- package/src/chrome/message-divider.ts +33 -1
- package/src/chrome/message-frame.ts +53 -10
- package/src/chrome/message-notice.ts +71 -0
- package/src/chrome/overlay-box.ts +45 -2
- package/src/chrome/qrcode.ts +28 -0
- package/src/chrome/segment-track.ts +26 -0
- package/src/chrome/selector-helpers.ts +1 -17
- package/src/chrome/status-notice.ts +46 -0
- package/src/chrome/streaming-panel.ts +25 -1
- package/src/chrome/tool-activity.ts +20 -0
- package/src/chrome/transcript-container.ts +139 -17
- package/src/chrome/transcript-status.ts +40 -11
- package/src/components/box.ts +51 -0
- package/src/components/disclosure.ts +33 -0
- package/src/components/editor.ts +239 -36
- package/src/components/form.ts +93 -9
- package/src/components/image.ts +30 -0
- package/src/components/input.ts +77 -26
- package/src/components/key-value-list.ts +18 -0
- package/src/components/layout/geometry.ts +44 -0
- package/src/components/layout/row.ts +30 -0
- package/src/components/layout/split-pane.ts +65 -0
- package/src/components/layout/stack.ts +27 -0
- package/src/components/loader.ts +183 -1
- package/src/components/markdown.ts +131 -56
- package/src/components/metric.ts +39 -0
- package/src/components/progress-bar.ts +28 -0
- package/src/components/scroll-view.ts +23 -0
- package/src/components/section.ts +16 -0
- package/src/components/select-list.ts +174 -25
- package/src/components/settings-list.ts +264 -7
- package/src/components/spacer.ts +17 -0
- package/src/components/tab-bar.ts +42 -0
- package/src/components/table.ts +34 -0
- package/src/components/text.ts +23 -0
- package/src/components/tree-view.ts +65 -0
- package/src/components/truncated-text.ts +14 -0
- package/src/components/wizard-step.ts +18 -9
- package/src/debug-server.ts +14 -7
- package/src/hotkeys-markdown.ts +251 -69
- package/src/index.ts +6 -0
- package/src/latex-block.ts +11 -0
- package/src/loop-watchdog.ts +38 -10
- package/src/native/apply.ts +275 -0
- package/src/native/backend.ts +682 -0
- package/src/native/blobs.ts +70 -0
- package/src/native/describe.ts +124 -0
- package/src/native/encode.ts +233 -0
- package/src/native/icons.ts +184 -0
- package/src/native/memo.ts +64 -0
- package/src/native/node.ts +112 -0
- package/src/native/overlay.ts +131 -0
- package/src/native/picker.ts +333 -0
- package/src/native/reconcile.ts +1063 -0
- package/src/native/settle.ts +23 -0
- package/src/native/spans.ts +308 -0
- package/src/native/state.ts +28 -0
- package/src/native/tone.ts +79 -0
- package/src/overlays/advisor-config.ts +420 -0
- package/src/overlays/agent-hub-renderer.ts +155 -18
- package/src/overlays/agent-hub.ts +1037 -44
- package/src/overlays/agent-transcript-viewer.ts +129 -0
- package/src/overlays/agents-hub.ts +688 -53
- package/src/overlays/annotation-overlay.ts +391 -52
- package/src/overlays/ask-dialog.ts +435 -24
- package/src/overlays/bordered-loader.ts +17 -0
- package/src/overlays/btw-history-panel.ts +182 -0
- package/src/overlays/btw-panel.ts +68 -2
- package/src/overlays/cleanse-panel.ts +105 -15
- package/src/overlays/codex-reset-fireworks.ts +65 -5
- package/src/overlays/composer-shape-preview.ts +26 -1
- package/src/overlays/copy-selector.ts +545 -23
- package/src/overlays/error-banner.ts +44 -0
- package/src/overlays/extensions/extension-list.ts +23 -17
- package/src/overlays/history-search.ts +175 -33
- package/src/overlays/hook-editor.ts +113 -6
- package/src/overlays/hook-input.ts +22 -1
- package/src/overlays/hook-selector.ts +311 -22
- package/src/overlays/hub-frame.ts +80 -0
- package/src/overlays/jobs-panel.ts +112 -0
- package/src/overlays/login-dialog.ts +183 -1
- package/src/overlays/logout-account-selector.ts +102 -4
- package/src/overlays/mcp-add-wizard.ts +232 -53
- package/src/overlays/model-browser.ts +681 -22
- package/src/overlays/model-hub.ts +1402 -78
- package/src/overlays/model-picker.ts +184 -7
- package/src/overlays/move-overlay.ts +45 -0
- package/src/overlays/oauth-selector.ts +227 -23
- package/src/overlays/omfg-panel.ts +86 -2
- package/src/overlays/pause-screen.ts +55 -4
- package/src/overlays/plan-review-overlay.ts +352 -0
- package/src/overlays/plan-save-overlay.ts +45 -0
- package/src/overlays/plugin-selector.ts +21 -1
- package/src/overlays/plugin-settings.ts +195 -5
- package/src/overlays/queue-mode-selector.ts +19 -1
- package/src/overlays/reset-usage-selector.ts +110 -40
- package/src/overlays/rewind-selector.ts +458 -44
- package/src/overlays/session-account-selector.ts +1 -1
- package/src/overlays/session-info-overlay.ts +137 -1
- package/src/overlays/session-selector.ts +807 -46
- package/src/overlays/settings-defs.ts +41 -0
- package/src/overlays/settings-selector.ts +585 -33
- package/src/overlays/show-images-selector.ts +18 -1
- package/src/overlays/snapcompact-shape-preview.ts +48 -3
- package/src/overlays/stats-notice.ts +31 -0
- package/src/overlays/theme-selector.ts +31 -1
- package/src/overlays/thinking-selector.ts +22 -1
- package/src/overlays/tree-selector.ts +570 -110
- package/src/overlays/usage-dashboard.ts +587 -12
- package/src/overlays/usage-row.ts +161 -25
- package/src/prompt/attachment-chips.ts +60 -0
- package/src/prompt/composer-attachments.ts +31 -9
- package/src/prompt/composer.ts +55 -2
- package/src/prompt/custom-editor.ts +302 -4
- package/src/prompt/editor-top-gap.ts +8 -0
- package/src/prompt/macos-spelling.ts +24 -9
- package/src/prompt/magic-keywords.ts +22 -1
- package/src/prompt/model-mention-autocomplete.ts +1 -0
- package/src/prompt/queued-messages.ts +101 -0
- package/src/prompt/skill-tokens.ts +5 -3
- package/src/prompt/welcome.ts +213 -6
- package/src/render/code-cell.ts +103 -2
- package/src/render/file-list.ts +29 -0
- package/src/render/hyperlink.ts +32 -0
- package/src/render/output-block.ts +110 -0
- package/src/render/output-pane.ts +37 -0
- package/src/render/tool-card.ts +137 -0
- package/src/render/tree-list.ts +39 -0
- package/src/render/width-aware-text.ts +20 -0
- package/src/setup/scenes/composer.ts +29 -0
- package/src/setup/scenes/glyph.ts +15 -0
- package/src/setup/scenes/model.ts +36 -8
- package/src/setup/scenes/outro.ts +28 -1
- package/src/setup/scenes/sign-in.ts +138 -24
- package/src/setup/scenes/splash.ts +28 -1
- package/src/setup/scenes/theme.ts +88 -3
- package/src/setup/scenes/types.ts +7 -28
- package/src/setup/startup-splash.ts +46 -9
- package/src/setup/wizard-overlay.ts +140 -23
- package/src/setup/wizard.ts +1 -1
- package/src/status-line/component.ts +414 -18
- package/src/status-line/context-usage.ts +279 -50
- package/src/status-line/footer.ts +94 -1
- package/src/status-line/metrics.ts +3 -6
- package/src/status-line/segments.ts +463 -97
- package/src/status-line/separators.ts +3 -16
- package/src/status-line/types.ts +43 -1
- package/src/stdin-buffer.ts +27 -21
- package/src/terminal-capabilities.ts +7 -0
- package/src/terminal.ts +153 -11
- package/src/theme/defaults/dark-neon-noir.json +100 -0
- package/src/theme/defaults/index.ts +2 -0
- package/src/theme/defaults/light-prism.json +5 -5
- package/src/theme/defaults/onyx.json +62 -62
- package/src/theme/mermaid-cache.ts +10 -1
- package/src/theme/schema.ts +15 -0
- package/src/theme/shimmer.ts +33 -0
- package/src/theme/theme-class.ts +24 -19
- package/src/theme/theme.ts +111 -9
- package/src/theme/tui-adapters.ts +14 -1
- package/src/tools/ask.ts +157 -1
- package/src/tools/ast-edit.ts +174 -1
- package/src/tools/ast-grep.ts +82 -2
- package/src/tools/autoresearch.ts +149 -1
- package/src/tools/bash.ts +233 -62
- package/src/tools/cfg-render.ts +66 -1
- package/src/tools/debug.ts +78 -1
- package/src/tools/default-renderer.ts +35 -1
- package/src/tools/edit.ts +357 -31
- package/src/tools/eval.ts +257 -1
- package/src/tools/fetch.ts +102 -3
- package/src/tools/find.ts +127 -1
- package/src/tools/github.ts +119 -10
- package/src/tools/glob.ts +116 -1
- package/src/tools/goal.ts +56 -1
- package/src/tools/grep.ts +83 -2
- package/src/tools/grouped-file-output.ts +205 -0
- package/src/tools/json-tree.ts +116 -1
- package/src/tools/lsp.ts +318 -1
- package/src/tools/mcp.ts +80 -1
- package/src/tools/memory.ts +93 -11
- package/src/tools/native-view.ts +292 -0
- package/src/tools/proc-render.ts +221 -1
- package/src/tools/read.ts +199 -4
- package/src/tools/renderer.ts +61 -0
- package/src/tools/report-tool-issue.ts +7 -1
- package/src/tools/resolve.ts +63 -1
- package/src/tools/streaming-output.ts +79 -16
- package/src/tools/task.ts +406 -4
- package/src/tools/think.ts +19 -1
- package/src/tools/todo.ts +89 -0
- package/src/tools/vibe.ts +230 -2
- package/src/tools/wait.ts +181 -1
- package/src/tools/web-search-types.ts +99 -0
- package/src/tools/web-search.ts +111 -170
- package/src/tools/write.ts +144 -5
- package/src/tools/xdev.ts +64 -1
- package/src/tui.ts +295 -4
- package/dist/types/setup/scenes/providers.d.ts +0 -3
- package/dist/types/setup/scenes/web-search.d.ts +0 -22
- package/src/setup/scenes/providers.ts +0 -110
- package/src/setup/scenes/web-search.ts +0 -165
package/src/tools/read.ts
CHANGED
|
@@ -6,20 +6,38 @@ import * as path from "node:path";
|
|
|
6
6
|
import { parseArchivePathCandidates } from "@oh-my-pi/pi-utils/ar";
|
|
7
7
|
import type { Component } from "../tui";
|
|
8
8
|
import { Text } from "../components/text";
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
NativeToolHead,
|
|
11
|
+
NativeToolView,
|
|
12
|
+
RenderResultOptions,
|
|
13
|
+
ToolActivityContext,
|
|
14
|
+
ToolActivitySummary,
|
|
15
|
+
ToolRenderer,
|
|
16
|
+
} from "./renderer";
|
|
17
|
+
import { ansi, compact, md } from "../native/describe";
|
|
18
|
+
import { base64ImageNode } from "../native/blobs";
|
|
19
|
+
import type { NativeChild, NativeNode } from "../native/node";
|
|
20
|
+
import { fileHref, footnoteText, inlineErrorView, resultText } from "./native-view";
|
|
21
|
+
import { numberedCode } from "./grouped-file-output";
|
|
10
22
|
import { getLanguageFromPath } from "../lang-from-path";
|
|
11
23
|
import type { Theme } from "../theme/theme";
|
|
12
24
|
import { fileHyperlink, renderCodeCell, renderMarkdownCell, renderStatusLine } from "../render";
|
|
13
25
|
import { markFramedBlockComponent } from "../render/output-block";
|
|
14
26
|
import { framedToolCard } from "../render/tool-card";
|
|
15
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
describeReadUrlCall,
|
|
29
|
+
describeReadUrlResult,
|
|
30
|
+
type ReadUrlToolDetails,
|
|
31
|
+
renderReadUrlCall,
|
|
32
|
+
renderReadUrlResult,
|
|
33
|
+
} from "./fetch";
|
|
16
34
|
import { formatFullOutputReference, formatStyledTruncationWarning, stripOutputNotice } from "./output-meta";
|
|
17
35
|
import { formatBytes, sanitizeDisplayLines, shortenPath, wrapBrackets } from "../render/render-utils";
|
|
18
36
|
|
|
19
37
|
import type { OutputMeta } from "./output-meta";
|
|
20
38
|
import type { TruncationResult } from "./streaming-output";
|
|
21
|
-
import { renderProcRead, type ProcReadDetails } from "./proc-render";
|
|
22
|
-
import { renderCfgRead, type CfgReadDetails } from "./cfg-render";
|
|
39
|
+
import { describeProcRead, renderProcRead, type ProcReadDetails } from "./proc-render";
|
|
40
|
+
import { describeCfgRead, renderCfgRead, type CfgReadDetails } from "./cfg-render";
|
|
23
41
|
import type { CardToolResult } from "./result-card";
|
|
24
42
|
import { type InternalUrlSchemeSpec, internalUrlSchemeSpec, splitUrlScheme } from "./url-scheme-host";
|
|
25
43
|
|
|
@@ -313,6 +331,102 @@ function formatReadPathLink(
|
|
|
313
331
|
return `${linkedPath}${selectorSuffix}`;
|
|
314
332
|
}
|
|
315
333
|
|
|
334
|
+
function readRawPath(args: ReadRenderArgs | undefined): string {
|
|
335
|
+
return typeof args?.file_path === "string" ? args.file_path : typeof args?.path === "string" ? args.path : "";
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Native read head (§7.3 read): `Read path:13-36` with the path as the
|
|
340
|
+
* target (shortened, plus the selector / legacy offset range), a `file://`
|
|
341
|
+
* link when the fs path is known, and a suffix correction as meta.
|
|
342
|
+
*/
|
|
343
|
+
function readNativeHead(rawPath: string, args: ReadRenderArgs | undefined, details?: ReadToolDetails): NativeToolHead {
|
|
344
|
+
const split = splitReadRenderPath(rawPath);
|
|
345
|
+
const suffix = details?.suffixResolution;
|
|
346
|
+
let target = suffix ? shortenPath(suffix.to) : shortenPath(split.path || rawPath);
|
|
347
|
+
if (split.sel) target += `:${split.sel}`;
|
|
348
|
+
if (args?.offset !== undefined || args?.limit !== undefined) {
|
|
349
|
+
const startLine = args.offset ?? 1;
|
|
350
|
+
const endLine = args.limit !== undefined ? startLine + args.limit - 1 : "";
|
|
351
|
+
target += `:${startLine}${endLine ? `-${endLine}` : ""}`;
|
|
352
|
+
}
|
|
353
|
+
const meta: string[] = [];
|
|
354
|
+
if (suffix) meta.push(`corrected from ${shortenPath(suffix.from)}`);
|
|
355
|
+
if (details?.summary) {
|
|
356
|
+
const n = details.summary.elidedSpans;
|
|
357
|
+
meta.push(`summary: ${n} elided span${n === 1 ? "" : "s"}`);
|
|
358
|
+
}
|
|
359
|
+
const conflicts = details?.conflictCount ?? 0;
|
|
360
|
+
return {
|
|
361
|
+
title: "Read",
|
|
362
|
+
target: target || "…",
|
|
363
|
+
targetKind: "path",
|
|
364
|
+
href: fileHref(details?.resolvedPath ?? details?.displayTarget ?? readSourceFsPath(details)),
|
|
365
|
+
meta,
|
|
366
|
+
badges:
|
|
367
|
+
conflicts > 0 ? [{ text: `${conflicts} conflict${conflicts === 1 ? "" : "s"}`, tone: "warning" }] : undefined,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* The first line a read shows: the selector's (or legacy `offset`'s) range
|
|
373
|
+
* start, so legacy results without `displayContent` still number from there.
|
|
374
|
+
*/
|
|
375
|
+
function readRangeStart(rawPath: string, args: ReadRenderArgs | undefined): number {
|
|
376
|
+
const sel = splitReadRenderPath(rawPath).sel;
|
|
377
|
+
return firstReadSelectorLine(sel) ?? args?.offset ?? 1;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Read content as numbered `code` (no path header: the head names the file).
|
|
382
|
+
* Numbers come from `lineNumbers` (`displayContent`'s per-line numbers,
|
|
383
|
+
* `null` for an elided block; runs split with `…` between) when they cover
|
|
384
|
+
* every line, else count up from `start`.
|
|
385
|
+
*/
|
|
386
|
+
export function readContentCode(
|
|
387
|
+
content: string,
|
|
388
|
+
start: number,
|
|
389
|
+
numbers: readonly (number | null)[] | undefined,
|
|
390
|
+
lang: string | undefined,
|
|
391
|
+
): NativeNode[] {
|
|
392
|
+
const lines = content.split("\n");
|
|
393
|
+
return numberedCode(
|
|
394
|
+
lines.map((text, i) => ({ n: numbers && numbers.length === lines.length ? numbers[i]! : start + i, text })),
|
|
395
|
+
{ lang },
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/** An image content block as the read tool emits it (base64 data + mime type). */
|
|
400
|
+
interface ReadImageBlock {
|
|
401
|
+
type: "image";
|
|
402
|
+
data: string;
|
|
403
|
+
mimeType: string;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function isImageBlock(block: { type: string }): block is ReadImageBlock {
|
|
407
|
+
return (
|
|
408
|
+
block.type === "image" &&
|
|
409
|
+
typeof (block as Partial<ReadImageBlock>).data === "string" &&
|
|
410
|
+
typeof (block as Partial<ReadImageBlock>).mimeType === "string"
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** Cached `image` node on its content block, so decoding and hashing happen once per block. */
|
|
415
|
+
const kReadImageNode = Symbol("read.imageNode");
|
|
416
|
+
|
|
417
|
+
interface TaggedReadImageBlock extends ReadImageBlock {
|
|
418
|
+
[kReadImageNode]?: NativeNode;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/** Native `image` node for a read image: registered blob, alt = displayed path, source pixel size when parseable. */
|
|
422
|
+
function describeReadImage(block: TaggedReadImageBlock, alt: string): NativeNode {
|
|
423
|
+
const cached = block[kReadImageNode];
|
|
424
|
+
if (cached) return cached;
|
|
425
|
+
const described = base64ImageNode(block.data, block.mimeType, { alt: alt || "image", role: "omp.tool.read.image" });
|
|
426
|
+
block[kReadImageNode] = described;
|
|
427
|
+
return described;
|
|
428
|
+
}
|
|
429
|
+
|
|
316
430
|
/** Render file, image, and URL reads in the transcript. */
|
|
317
431
|
export const readToolRenderer = {
|
|
318
432
|
activitySummary(args: unknown, _context: ToolActivityContext): ToolActivitySummary {
|
|
@@ -527,6 +641,87 @@ export const readToolRenderer = {
|
|
|
527
641
|
},
|
|
528
642
|
});
|
|
529
643
|
},
|
|
644
|
+
describeCall(args: ReadRenderArgs): NativeToolView {
|
|
645
|
+
const rawPath = readRawPath(args);
|
|
646
|
+
const routed = readUrlCard(rawPath);
|
|
647
|
+
if (routed?.card.detailsKey === "proc") return describeProcRead(routed.target, undefined, undefined);
|
|
648
|
+
if (routed) return describeCfgRead(splitInternalUrlSel(rawPath).path, undefined, undefined);
|
|
649
|
+
if (isReadableUrlPath(rawPath)) return describeReadUrlCall({ path: rawPath, raw: args.raw });
|
|
650
|
+
return { tool: readNativeHead(rawPath, args), inline: true };
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Inline (§7.3 read): the head names the file and range; the content
|
|
655
|
+
* (numbered from the range start, no path header) is the disclosed body.
|
|
656
|
+
* An error shows its message in the head, never behind the disclosure.
|
|
657
|
+
*/
|
|
658
|
+
describeResult(
|
|
659
|
+
result: { content: Array<{ type: string; text?: string }>; details?: ReadToolDetails; isError?: boolean },
|
|
660
|
+
_options: RenderResultOptions,
|
|
661
|
+
args?: ReadRenderArgs,
|
|
662
|
+
): NativeToolView {
|
|
663
|
+
const details = result.details;
|
|
664
|
+
const rawPath = readRawPath(args);
|
|
665
|
+
const routed = readUrlCard(rawPath, details);
|
|
666
|
+
if (routed?.card.detailsKey === "proc") return describeProcRead(routed.target, result, details?.proc);
|
|
667
|
+
if (routed) return describeCfgRead(splitInternalUrlSel(rawPath).path, result, details?.cfg);
|
|
668
|
+
if (details?.kind === "url" || isReadableUrlPath(rawPath)) {
|
|
669
|
+
return describeReadUrlResult({
|
|
670
|
+
content: result.content,
|
|
671
|
+
details: result.details as ReadUrlToolDetails | undefined,
|
|
672
|
+
isError: result.isError,
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
if (result.isError) {
|
|
677
|
+
const message = (resultText(result) || "Unknown error").replace(/^Error:\s*/, "");
|
|
678
|
+
return inlineErrorView(readNativeHead(rawPath, args, details), message);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const suffix = details?.suffixResolution;
|
|
682
|
+
const head = readNativeHead(rawPath, args, details);
|
|
683
|
+
const truncation = details?.meta?.truncation;
|
|
684
|
+
const fallback = details?.truncation;
|
|
685
|
+
const firstLineTooLong = truncation !== undefined && fallback?.firstLineExceedsLimit === true;
|
|
686
|
+
const foot = footnoteText(
|
|
687
|
+
compact([
|
|
688
|
+
details?.resolvedPath !== undefined && `resolved ${shortenPath(details.resolvedPath)}`,
|
|
689
|
+
firstLineTooLong &&
|
|
690
|
+
`First line exceeds ${formatBytes(fallback.outputBytes ?? fallback.totalBytes)} limit${truncation.artifactId ? `. ${formatFullOutputReference(truncation.artifactId)}` : ""}`,
|
|
691
|
+
]),
|
|
692
|
+
firstLineTooLong ? { artifactError: details?.meta?.artifactError } : details?.meta,
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
const contentText = details?.displayContent?.text ?? stripOutputNotice(resultText(result), details?.meta);
|
|
696
|
+
const imageBlock = result.content?.find(isImageBlock);
|
|
697
|
+
if (imageBlock) {
|
|
698
|
+
const detailText = contentText.trim();
|
|
699
|
+
return {
|
|
700
|
+
tool: head,
|
|
701
|
+
tone: suffix ? "warning" : undefined,
|
|
702
|
+
inline: true,
|
|
703
|
+
body: compact<NativeChild>([
|
|
704
|
+
describeReadImage(imageBlock, shortenPath(suffix?.to ?? splitReadRenderPath(rawPath).path)),
|
|
705
|
+
detailText.length > 0 && ansi(detailText),
|
|
706
|
+
foot,
|
|
707
|
+
]),
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
const renderPath = splitReadRenderPath(rawPath);
|
|
712
|
+
const rawRequested =
|
|
713
|
+
args?.raw === true || renderPath.sel?.split(":").some(chunk => chunk.toLowerCase() === "raw") === true;
|
|
714
|
+
const content: NativeChild[] =
|
|
715
|
+
details?.contentType === "text/markdown" && !rawRequested
|
|
716
|
+
? [md(contentText)]
|
|
717
|
+
: readContentCode(
|
|
718
|
+
contentText,
|
|
719
|
+
details?.displayContent?.startLine ?? readRangeStart(rawPath, args),
|
|
720
|
+
details?.displayContent?.lineNumbers,
|
|
721
|
+
getLanguageFromPath(renderPath.path),
|
|
722
|
+
);
|
|
723
|
+
return { tool: head, inline: true, body: compact<NativeChild>([...content, foot]) };
|
|
724
|
+
},
|
|
530
725
|
mergeCallAndResult: true,
|
|
531
726
|
} satisfies ToolRenderer<ReadRenderArgs, ReadToolDetails>;
|
|
532
727
|
|
package/src/tools/renderer.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* transcript components. Built-in renderers live beside this file; the
|
|
4
4
|
* coding-agent tools implement the matching `*Details` payloads.
|
|
5
5
|
*/
|
|
6
|
+
import type { TspPreview, TspText, TspTone, TspToolProps } from "@oh-my-pi/pi-wire";
|
|
7
|
+
import type { NativeChild } from "../native/node";
|
|
6
8
|
import type { Component } from "../tui";
|
|
7
9
|
import type { Theme } from "../theme/theme";
|
|
8
10
|
|
|
@@ -62,6 +64,54 @@ export interface ToolActivityContext {
|
|
|
62
64
|
readonly renderContext?: Record<string, unknown>;
|
|
63
65
|
}
|
|
64
66
|
|
|
67
|
+
/**
|
|
68
|
+
* The data head of a tool call (NATIVE_REDESIGN §7.2): what the terminal
|
|
69
|
+
* draws in the `tool` kind's head. Each fact appears once — a target named
|
|
70
|
+
* here is never repeated in the body.
|
|
71
|
+
*/
|
|
72
|
+
export interface NativeToolHead {
|
|
73
|
+
/** The verb ("Bash", "Edit"); defaults to the tool's label. */
|
|
74
|
+
readonly title?: TspText;
|
|
75
|
+
/** The primary argument, shown once: command, path, pattern, query. */
|
|
76
|
+
readonly target?: TspText;
|
|
77
|
+
readonly targetKind?: TspToolProps["targetKind"];
|
|
78
|
+
/** Language for `command` targets. */
|
|
79
|
+
readonly lang?: string;
|
|
80
|
+
/** `file://` link for path targets. */
|
|
81
|
+
readonly href?: string;
|
|
82
|
+
/** Short facts after the target (`+8 −1`, `5 matches · 2 files`). */
|
|
83
|
+
readonly meta?: readonly TspText[];
|
|
84
|
+
readonly badges?: TspToolProps["badges"];
|
|
85
|
+
/** A one-word state note ("timed out", "partial"). */
|
|
86
|
+
readonly note?: TspText;
|
|
87
|
+
/** A non-zero exit code (error chip). */
|
|
88
|
+
readonly exit?: number | null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A tool's semantic presentation for Tern Surface Protocol terminals.
|
|
93
|
+
* `ToolExecutionComponent` wraps it in a `tool` node (terminals that list
|
|
94
|
+
* the kind) or, as the fallback, a `card` (role `omp.tool.<name>`, status,
|
|
95
|
+
* elapsed timer, collapse): the renderer supplies only the head data and the
|
|
96
|
+
* body nodes, never frames, padding or width math.
|
|
97
|
+
*/
|
|
98
|
+
export interface NativeToolView {
|
|
99
|
+
/** The data head; the fallback card's head spans derive from it when {@link head} is absent. */
|
|
100
|
+
readonly tool?: NativeToolHead;
|
|
101
|
+
/** Header spans for the fallback card (and the `tool` title when {@link tool} is absent). */
|
|
102
|
+
readonly head?: TspText;
|
|
103
|
+
/** Body: sections, never frames. */
|
|
104
|
+
readonly body?: readonly NativeChild[];
|
|
105
|
+
/** Tone override; the frame otherwise derives it from the call status. */
|
|
106
|
+
readonly tone?: TspTone;
|
|
107
|
+
/** Body clamp while collapsed; `{tail}` keeps the end (terminal output). Defaults to the transcript's preview size. */
|
|
108
|
+
readonly preview?: TspPreview | { readonly tail: number } | "none";
|
|
109
|
+
/** Render frameless (`frame:"inline"`): a head line plus a disclosed body. */
|
|
110
|
+
readonly inline?: boolean;
|
|
111
|
+
/** Head actions offered on hover (`copy`, `retry`). */
|
|
112
|
+
readonly tools?: TspToolProps["tools"];
|
|
113
|
+
}
|
|
114
|
+
|
|
65
115
|
/**
|
|
66
116
|
* A tool's transcript presentation: call preview, result view, and repaint/animation hints.
|
|
67
117
|
* Method signatures are intentionally bivariant so a renderer typed over its own
|
|
@@ -76,6 +126,17 @@ export interface ToolRenderer<TArgs = unknown, TDetails = unknown> {
|
|
|
76
126
|
theme: Theme,
|
|
77
127
|
args?: TArgs,
|
|
78
128
|
): Component | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* Semantic call preview for TSP terminals. When a renderer implements the
|
|
131
|
+
* describe hooks, the native backend never calls `renderCall`/`renderResult`.
|
|
132
|
+
*/
|
|
133
|
+
describeCall?(args: TArgs, options: RenderResultOptions): NativeToolView | undefined;
|
|
134
|
+
/** Semantic result view for TSP terminals; merged with the call view when {@link mergeCallAndResult}. */
|
|
135
|
+
describeResult?(
|
|
136
|
+
result: ToolRenderResult<TDetails>,
|
|
137
|
+
options: RenderResultContextOptions,
|
|
138
|
+
args?: TArgs,
|
|
139
|
+
): NativeToolView | undefined;
|
|
79
140
|
mergeCallAndResult?: boolean;
|
|
80
141
|
/** Describes current activity without coupling a renderer to terminal layout. */
|
|
81
142
|
activitySummary?(args: TArgs, context: ToolActivityContext): ToolActivitySummary;
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { Component } from "../index";
|
|
2
2
|
import type { Theme } from "../theme/theme";
|
|
3
|
-
import {
|
|
3
|
+
import type { NativeToolView } from "./renderer";
|
|
4
|
+
import { describeDeviceCallPreview, renderDeviceCallPreview } from "./resolve";
|
|
4
5
|
|
|
5
6
|
/** Call preview for an `xd://report_issue` write. */
|
|
6
7
|
export function renderReportIssueDeviceCall(content: unknown, uiTheme: Theme): Component {
|
|
7
8
|
return renderDeviceCallPreview("Report Tool Issue", content, uiTheme);
|
|
8
9
|
}
|
|
9
10
|
|
|
11
|
+
/** Native call preview for an `xd://report_issue` write. */
|
|
12
|
+
export function describeReportIssueDeviceCall(content: unknown): NativeToolView {
|
|
13
|
+
return describeDeviceCallPreview("Report Tool Issue", content);
|
|
14
|
+
}
|
|
15
|
+
|
|
10
16
|
/** Device name for automatic tool issue reports. */
|
|
11
17
|
export const REPORT_ISSUE_DEVICE_NAME = "report_issue";
|
|
12
18
|
/** Internal device URL for automatic tool issue reports. */
|
package/src/tools/resolve.ts
CHANGED
|
@@ -3,7 +3,13 @@ import type { ToolRenderer } from "./renderer";
|
|
|
3
3
|
import type { Component } from "../index";
|
|
4
4
|
import { Text } from "../index";
|
|
5
5
|
|
|
6
|
-
import type { RenderResultOptions } from "./renderer";
|
|
6
|
+
import type { NativeToolView, RenderResultOptions } from "./renderer";
|
|
7
|
+
|
|
8
|
+
import type { TspSpan } from "@oh-my-pi/pi-wire";
|
|
9
|
+
import { span, text } from "../native/describe";
|
|
10
|
+
import { OwnerMemo } from "../native/memo";
|
|
11
|
+
import { plainText } from "../native/spans";
|
|
12
|
+
import { noteText, toolHead } from "./native-view";
|
|
7
13
|
|
|
8
14
|
import type { Theme } from "../theme/theme";
|
|
9
15
|
|
|
@@ -47,6 +53,20 @@ export function renderResolutionDeviceCall(device: ResolutionDeviceName, content
|
|
|
47
53
|
return renderDeviceCallPreview(title, content, uiTheme, Ellipsis.Omit);
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
/** Native form of {@link renderResolutionDeviceCall}: `Resolve/Reject/Propose` head with the first content line. */
|
|
57
|
+
export function describeResolutionDeviceCall(device: ResolutionDeviceName, content: unknown): NativeToolView {
|
|
58
|
+
const title = device === PROPOSE_DEVICE_NAME ? "Propose" : device === REJECT_DEVICE_NAME ? "Reject" : "Resolve";
|
|
59
|
+
return describeDeviceCallPreview(title, content);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Native form of {@link renderDeviceCallPreview}: title head plus the first content line of a pending device write. */
|
|
63
|
+
export function describeDeviceCallPreview(title: string, content: unknown): NativeToolView {
|
|
64
|
+
const body = typeof content === "string" ? (plainText(content).trim().split("\n")[0] ?? "") : "";
|
|
65
|
+
return { head: toolHead(title, body || undefined) };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const resolveResultMemo = new OwnerMemo<NativeToolView | undefined>();
|
|
69
|
+
|
|
50
70
|
/** Render the first content line of a pending device write. */
|
|
51
71
|
export function renderDeviceCallPreview(
|
|
52
72
|
title: string,
|
|
@@ -129,6 +149,48 @@ export const resolveRenderer = {
|
|
|
129
149
|
};
|
|
130
150
|
},
|
|
131
151
|
|
|
152
|
+
describeCall(args: Partial<ResolveInvocation>): NativeToolView {
|
|
153
|
+
const head: TspSpan[] = toolHead("Resolve", args.action);
|
|
154
|
+
if (args.action) {
|
|
155
|
+
head.push(
|
|
156
|
+
span(" "),
|
|
157
|
+
span(
|
|
158
|
+
args.action === "apply" ? "proposed → resolved" : "proposed → rejected",
|
|
159
|
+
args.action === "apply" ? "success" : "warning",
|
|
160
|
+
),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
const reason = args.reason?.trim();
|
|
164
|
+
return { head, inline: true, body: reason ? [noteText(reason, "muted", 1)] : undefined };
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
describeResult(result: {
|
|
168
|
+
content: Array<{ type: string; text?: string }>;
|
|
169
|
+
details?: ResolveDetails;
|
|
170
|
+
isError?: boolean;
|
|
171
|
+
}): NativeToolView | undefined {
|
|
172
|
+
return resolveResultMemo.get(result, [], () => {
|
|
173
|
+
const details = result.details;
|
|
174
|
+
const label = plainText(details?.label ?? "pending action");
|
|
175
|
+
const reason = plainText(details?.reason?.trim() || "No reason provided");
|
|
176
|
+
const action = details?.action ?? "apply";
|
|
177
|
+
const isApply = action === "apply" && !result.isError;
|
|
178
|
+
const verb = isApply ? "Accept" : action === "apply" ? "Failed" : "Discard";
|
|
179
|
+
const tone = result.isError ? "error" : isApply ? "success" : "warning";
|
|
180
|
+
const separatorIndex = label.indexOf(": ");
|
|
181
|
+
const sourceLabel = separatorIndex > 0 ? label.slice(0, separatorIndex).trim() : undefined;
|
|
182
|
+
const summaryLabel = separatorIndex > 0 ? label.slice(separatorIndex + 2).trim() : label;
|
|
183
|
+
const head: TspSpan[] = [span(`${verb}:`, `strong ${tone}`), span(" "), span(summaryLabel)];
|
|
184
|
+
if (sourceLabel) head.push(span(" "), span(`[${sourceLabel}]`, "strong muted"));
|
|
185
|
+
return {
|
|
186
|
+
head,
|
|
187
|
+
tone,
|
|
188
|
+
inline: true,
|
|
189
|
+
body: [text([span(reason, "muted")], { wrap: "word" })],
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
},
|
|
193
|
+
|
|
132
194
|
inline: true,
|
|
133
195
|
mergeCallAndResult: true,
|
|
134
196
|
} satisfies ToolRenderer<Partial<ResolveInvocation>, ResolveDetails>;
|
|
@@ -718,6 +718,12 @@ const MAX_PENDING = 10;
|
|
|
718
718
|
export class TailBuffer {
|
|
719
719
|
#pending: string[] = [];
|
|
720
720
|
#pos = 0; // byte count of the currently-held tail (after trims)
|
|
721
|
+
// `#pending[0]` and its byte count. Clean = well-formed and `#headBytes` is its exact
|
|
722
|
+
// UTF-8 length (a head compacted from chunks that split a surrogate pair is neither).
|
|
723
|
+
#headBytes = 0;
|
|
724
|
+
#headClean = true;
|
|
725
|
+
// Every chunk after `#pending[0]` is well-formed (no lone surrogates).
|
|
726
|
+
#restWellFormed = true;
|
|
721
727
|
|
|
722
728
|
constructor(readonly maxBytes: number) {}
|
|
723
729
|
|
|
@@ -726,8 +732,7 @@ export class TailBuffer {
|
|
|
726
732
|
|
|
727
733
|
const max = this.maxBytes;
|
|
728
734
|
if (max === 0) {
|
|
729
|
-
this.#
|
|
730
|
-
this.#pos = 0;
|
|
735
|
+
this.#setHead("", 0, true);
|
|
731
736
|
return;
|
|
732
737
|
}
|
|
733
738
|
|
|
@@ -736,19 +741,17 @@ export class TailBuffer {
|
|
|
736
741
|
// If the incoming chunk alone is >= budget, it fully dominates the tail.
|
|
737
742
|
if (n >= max) {
|
|
738
743
|
const { text: t, bytes } = truncateTailBytes(text, max);
|
|
739
|
-
|
|
740
|
-
this.#
|
|
741
|
-
this.#pos = bytes;
|
|
744
|
+
// A chunk of exactly `max` bytes comes back verbatim, lone surrogates included.
|
|
745
|
+
this.#setHead(t, bytes, t.isWellFormed());
|
|
742
746
|
return;
|
|
743
747
|
}
|
|
744
748
|
|
|
745
|
-
this.#pos += n;
|
|
746
|
-
|
|
747
749
|
if (this.#pending.length === 0) {
|
|
748
|
-
this.#
|
|
749
|
-
this.#pending.length = 1;
|
|
750
|
+
this.#setHead(text, n, text.isWellFormed());
|
|
750
751
|
} else {
|
|
752
|
+
this.#pos += n;
|
|
751
753
|
this.#pending.push(text);
|
|
754
|
+
if (this.#restWellFormed && !text.isWellFormed()) this.#restWellFormed = false;
|
|
752
755
|
if (this.#pending.length > MAX_PENDING) this.#compact();
|
|
753
756
|
}
|
|
754
757
|
|
|
@@ -770,9 +773,22 @@ export class TailBuffer {
|
|
|
770
773
|
|
|
771
774
|
// -- private ---------------------------------------------------------------
|
|
772
775
|
|
|
776
|
+
/** Replace the whole buffer with a single chunk. */
|
|
777
|
+
#setHead(text: string, bytes: number, clean: boolean): void {
|
|
778
|
+
this.#pending[0] = text;
|
|
779
|
+
this.#pending.length = 1;
|
|
780
|
+
this.#pos = bytes;
|
|
781
|
+
this.#headBytes = bytes;
|
|
782
|
+
this.#headClean = clean;
|
|
783
|
+
this.#restWellFormed = true;
|
|
784
|
+
}
|
|
785
|
+
|
|
773
786
|
#compact(): void {
|
|
774
787
|
this.#pending[0] = this.#pending.join("");
|
|
775
788
|
this.#pending.length = 1;
|
|
789
|
+
this.#headBytes = this.#pos;
|
|
790
|
+
this.#headClean = this.#headClean && this.#restWellFormed;
|
|
791
|
+
this.#restWellFormed = true;
|
|
776
792
|
}
|
|
777
793
|
|
|
778
794
|
#flush(): string {
|
|
@@ -783,17 +799,64 @@ export class TailBuffer {
|
|
|
783
799
|
|
|
784
800
|
#trimTo(max: number): void {
|
|
785
801
|
if (max === 0) {
|
|
786
|
-
this.#
|
|
787
|
-
this.#pos = 0;
|
|
802
|
+
this.#setHead("", 0, true);
|
|
788
803
|
return;
|
|
789
804
|
}
|
|
790
805
|
if (this.#pos <= max) return;
|
|
791
806
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
807
|
+
// Steady state (one `text()` per appended chunk): the overflow lies inside the
|
|
808
|
+
// already-trimmed head, so only the head's front is cut and the chunks after it
|
|
809
|
+
// are kept verbatim instead of re-encoding the whole window. Those chunks must be
|
|
810
|
+
// well-formed: the full path round-trips them through UTF-8, which rewrites lone
|
|
811
|
+
// surrogates (and heals pairs split across chunk boundaries).
|
|
812
|
+
const restBytes = this.#pos - this.#headBytes;
|
|
813
|
+
if (restBytes < max && this.#restWellFormed) {
|
|
814
|
+
const head = this.#pending[0];
|
|
815
|
+
const keep = max - restBytes;
|
|
816
|
+
const drop = this.#headBytes - keep;
|
|
817
|
+
if (head.length === this.#headBytes) {
|
|
818
|
+
// All-ASCII head: byte offsets are char offsets and every byte is a boundary.
|
|
819
|
+
this.#pending[0] = head.slice(drop);
|
|
820
|
+
this.#headBytes = keep;
|
|
821
|
+
} else if (this.#headClean && drop <= keep) {
|
|
822
|
+
// Walk code points to the first boundary at or after `drop` bytes.
|
|
823
|
+
let dropped = 0;
|
|
824
|
+
let index = 0;
|
|
825
|
+
while (dropped < drop) {
|
|
826
|
+
const code = head.charCodeAt(index);
|
|
827
|
+
if (code < 0x80) {
|
|
828
|
+
dropped += 1;
|
|
829
|
+
index += 1;
|
|
830
|
+
} else if (code < 0x800) {
|
|
831
|
+
dropped += 2;
|
|
832
|
+
index += 1;
|
|
833
|
+
} else if (code >= 0xd800 && code <= 0xdbff) {
|
|
834
|
+
// Well-formed, so a high surrogate always starts a pair.
|
|
835
|
+
dropped += 4;
|
|
836
|
+
index += 2;
|
|
837
|
+
} else {
|
|
838
|
+
dropped += 3;
|
|
839
|
+
index += 1;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
this.#pending[0] = head.slice(index);
|
|
843
|
+
this.#headBytes -= dropped;
|
|
844
|
+
} else {
|
|
845
|
+
// A head that already fits comes back verbatim, lone surrogates included.
|
|
846
|
+
const { text, bytes } = truncateTailBytes(head, keep);
|
|
847
|
+
this.#pending[0] = text;
|
|
848
|
+
this.#headBytes = bytes;
|
|
849
|
+
this.#headClean = text.isWellFormed();
|
|
850
|
+
this.#pos = this.#headBytes + restBytes;
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
this.#headClean = true;
|
|
854
|
+
this.#pos = this.#headBytes + restBytes;
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
const { text, bytes } = truncateTailBytes(this.#flush(), max);
|
|
859
|
+
this.#setHead(text, bytes, text.isWellFormed());
|
|
797
860
|
}
|
|
798
861
|
}
|
|
799
862
|
|