@oh-my-pi/pi-tui 18.4.3 → 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 +36 -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/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 +37 -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/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 +7 -0
- 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 +7 -0
- package/dist/types/setup/scenes/splash.d.ts +8 -0
- package/dist/types/setup/scenes/types.d.ts +6 -1
- 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/terminal-capabilities.d.ts +1 -1
- package/dist/types/terminal.d.ts +27 -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.d.ts +8 -0
- 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 +346 -11
- 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/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 +37 -0
- 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 +216 -27
- 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 +21 -0
- 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/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 +175 -1
- 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 +583 -23
- 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 +122 -13
- package/src/setup/scenes/splash.ts +28 -1
- package/src/setup/scenes/theme.ts +88 -3
- package/src/setup/scenes/types.ts +7 -1
- package/src/setup/startup-splash.ts +46 -9
- package/src/setup/wizard-overlay.ts +140 -23
- package/src/status-line/component.ts +398 -16
- 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/terminal-capabilities.ts +7 -0
- package/src/terminal.ts +130 -2
- 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/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/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 +180 -49
- 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 +247 -2
- 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/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.ts +113 -1
- package/src/tools/write.ts +144 -5
- package/src/tools/xdev.ts +64 -1
- package/src/tui.ts +294 -3
|
@@ -5,11 +5,17 @@ import { ImageProtocol, TERMINAL } from "../terminal-capabilities";
|
|
|
5
5
|
import { Markdown, type MarkdownTheme } from "../components/markdown";
|
|
6
6
|
import { Spacer } from "../components/spacer";
|
|
7
7
|
import { Text } from "../components/text";
|
|
8
|
-
import { formatNumber } from "@oh-my-pi/pi-utils";
|
|
8
|
+
import { formatDuration, formatNumber } from "@oh-my-pi/pi-utils";
|
|
9
9
|
import chalk from "@oh-my-pi/pi-utils/chalk";
|
|
10
10
|
import { LRUCache } from "@oh-my-pi/pi-utils/lru";
|
|
11
11
|
import type { AssistantThinkingRenderer } from "./extension-types";
|
|
12
|
-
import { ensureThemeSync, getMarkdownTheme, theme } from "../theme";
|
|
12
|
+
import { ensureThemeSync, getMarkdownTheme, getThemeEpoch, theme } from "../theme";
|
|
13
|
+
import { card, col, elapsed, node, span, text } from "../native/describe";
|
|
14
|
+
import { hasTranscriptActions, runTranscriptAction } from "./transcript-actions";
|
|
15
|
+
import type { NativeChild, NativeNode, NativeUiEvent } from "../native/node";
|
|
16
|
+
import { isNativeRendering } from "../native/state";
|
|
17
|
+
import { NativeImageCache } from "../native/blobs";
|
|
18
|
+
import { Memo } from "../native/memo";
|
|
13
19
|
import { EMPTY_LINK_TARGETS, resolveImageOptions } from "../render/render-utils";
|
|
14
20
|
import { WidthAwareText } from "../render";
|
|
15
21
|
import { cachedPngConversion, convertImageToPngShared, imagePayloadKey } from "./image-loading";
|
|
@@ -20,6 +26,7 @@ import { formatErrorBlock } from "../chrome/error-block";
|
|
|
20
26
|
import { type ServedModelMismatch, ServedModelMarkerComponent } from "./served-model-marker";
|
|
21
27
|
import { isReactionTarget, type ReactionSplit, type ReactionTarget, splitReaction } from "./reaction";
|
|
22
28
|
import { isRowPrefix, type TranscriptStableRow, trimBlankEdges } from "../chrome/transcript-container";
|
|
29
|
+
import { formatTurnUsage, type TurnUsageSummary } from "../overlays/usage-row";
|
|
23
30
|
|
|
24
31
|
/**
|
|
25
32
|
* Max wrapped rows of a turn-ending provider error rendered inline in the
|
|
@@ -31,6 +38,13 @@ import { isRowPrefix, type TranscriptStableRow, trimBlankEdges } from "../chrome
|
|
|
31
38
|
const MAX_TRANSCRIPT_ERROR_ROWS = 8;
|
|
32
39
|
const EMPTY_STABLE_RENDER: readonly string[] = [];
|
|
33
40
|
|
|
41
|
+
/** The native head of a finished thinking block: "Thought for 12s", or "Thought" when it was never seen streaming. */
|
|
42
|
+
function thoughtLabel(clock: { start: number; end?: number } | undefined): string {
|
|
43
|
+
if (clock?.end === undefined) return "Thought";
|
|
44
|
+
const ms = clock.end - clock.start;
|
|
45
|
+
return `Thought for ${ms < 60_000 ? `${Math.max(1, Math.round(ms / 1000))}s` : formatDuration(ms)}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
34
48
|
type ThinkingContentBlock = Extract<AssistantMessage["content"][number], { type: "thinking" }>;
|
|
35
49
|
type DisplayThinkingContentBlock = ThinkingContentBlock & { rawThinking?: string };
|
|
36
50
|
type StablePartKind = "thinking" | "text";
|
|
@@ -251,6 +265,12 @@ export class AssistantMessageComponent extends Container {
|
|
|
251
265
|
* provider error whose tail would otherwise be unreachable in the live TUI.
|
|
252
266
|
*/
|
|
253
267
|
#errorExpanded = false;
|
|
268
|
+
/** The deduplicated message the native error frame shows (its "Copy error" copies it). */
|
|
269
|
+
#errorText: string | undefined;
|
|
270
|
+
/** A TTSR rule aborted this text; the turn re-streams below it. */
|
|
271
|
+
#rewound = false;
|
|
272
|
+
/** The turn's totals when this answer ends it; a TSP terminal shows them under the answer. */
|
|
273
|
+
#turnUsage: TurnUsageSummary | undefined;
|
|
254
274
|
/**
|
|
255
275
|
* True when the current {@link updateContent} message carries a truncatable
|
|
256
276
|
* inline provider error (the `#appendErrorBlock` path) — set whether or not
|
|
@@ -323,6 +343,19 @@ export class AssistantMessageComponent extends Container {
|
|
|
323
343
|
#reactionTarget: ReactionTarget | undefined;
|
|
324
344
|
/** Reaction lifted from the reply's opening emoji, once resolved. */
|
|
325
345
|
#reaction: string | undefined;
|
|
346
|
+
/** Display form of {@link #lastMessage} (reaction handled) the native description is built from. */
|
|
347
|
+
#displayedMessage: AssistantMessage | undefined;
|
|
348
|
+
/** Thinking-extension components per content index, recorded when the slow path mounts them. */
|
|
349
|
+
#thinkingExtensions = new Map<number, Component[]>();
|
|
350
|
+
/** Collapse state of thinking sections toggled in the terminal, by content index; cleared by {@link setHideThinkingBlock}. */
|
|
351
|
+
#thinkingCollapsed = new Map<number, boolean>();
|
|
352
|
+
/** When each thinking block was seen streaming and when it stopped (native "Thought for 12s"), by content index. */
|
|
353
|
+
#thinkingClock = new Map<number, { start: number; end?: number; tokens: number }>();
|
|
354
|
+
#nativeViewVersion = 0;
|
|
355
|
+
readonly #native = new Memo();
|
|
356
|
+
/** Markdown nodes by key, reused while their text and streaming flag are unchanged. */
|
|
357
|
+
#nativeParts = new Map<string, { text: string; stream: boolean; node: NativeNode }>();
|
|
358
|
+
readonly #nativeImages = new NativeImageCache();
|
|
326
359
|
|
|
327
360
|
setTextColorTransform(transform?: (text: string) => string): void {
|
|
328
361
|
this.#textColorTransform = transform;
|
|
@@ -469,6 +502,12 @@ export class AssistantMessageComponent extends Container {
|
|
|
469
502
|
this.#refreshMarkers();
|
|
470
503
|
}
|
|
471
504
|
|
|
505
|
+
/** Mark this answer as the end of a turn with the turn's totals (native only: ANSI keeps them in the status line). */
|
|
506
|
+
setTurnUsage(summary: TurnUsageSummary | undefined): void {
|
|
507
|
+
this.#turnUsage = summary;
|
|
508
|
+
this.#nativeViewVersion++;
|
|
509
|
+
}
|
|
510
|
+
|
|
472
511
|
/**
|
|
473
512
|
* Show or clear the trailing served-model divider. Set once the turn's
|
|
474
513
|
* signed thinking block (or router report) has named the model that actually
|
|
@@ -502,6 +541,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
502
541
|
|
|
503
542
|
setHideThinkingBlock(hide: boolean): void {
|
|
504
543
|
this.#hideThinkingBlock = hide;
|
|
544
|
+
this.#thinkingCollapsed.clear();
|
|
505
545
|
}
|
|
506
546
|
|
|
507
547
|
/**
|
|
@@ -534,14 +574,30 @@ export class AssistantMessageComponent extends Container {
|
|
|
534
574
|
* Once text starts, a tool call streams, or the block is sealed, the pulse ends.
|
|
535
575
|
*/
|
|
536
576
|
#shouldAnimateThinking(message: AssistantMessage): boolean {
|
|
537
|
-
|
|
577
|
+
return this.#hideThinkingBlock && this.#thinkingTailIndex(message) !== undefined;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Content index of the thinking block the model is producing right now:
|
|
582
|
+
* the block is still streaming (not finalized), no tool call has started,
|
|
583
|
+
* and the tail visible block is thinking. Undefined otherwise.
|
|
584
|
+
*/
|
|
585
|
+
#thinkingTailIndex(message: AssistantMessage): number | undefined {
|
|
586
|
+
if (this.#transcriptBlockFinalized) return undefined;
|
|
538
587
|
let tail: "text" | "thinking" | undefined;
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
588
|
+
let tailIndex = -1;
|
|
589
|
+
for (let index = 0; index < message.content.length; index++) {
|
|
590
|
+
const content = message.content[index]!;
|
|
591
|
+
if (content.type === "toolCall") return undefined;
|
|
592
|
+
if (content.type === "text" && canonicalizeMessage(content.text)) {
|
|
593
|
+
tail = "text";
|
|
594
|
+
tailIndex = index;
|
|
595
|
+
} else if (content.type === "thinking" && canonicalizeMessage(content.thinking)) {
|
|
596
|
+
tail = "thinking";
|
|
597
|
+
tailIndex = index;
|
|
598
|
+
}
|
|
543
599
|
}
|
|
544
|
-
return tail === "thinking";
|
|
600
|
+
return tail === "thinking" ? tailIndex : undefined;
|
|
545
601
|
}
|
|
546
602
|
|
|
547
603
|
#thinkingDotsLabel(): string {
|
|
@@ -571,7 +627,8 @@ export class AssistantMessageComponent extends Container {
|
|
|
571
627
|
}
|
|
572
628
|
|
|
573
629
|
#startThinkingAnimation(): void {
|
|
574
|
-
|
|
630
|
+
// A native terminal clocks the described starburst itself.
|
|
631
|
+
if (this.#thinkingDotsTimer || isNativeRendering()) return;
|
|
575
632
|
this.#scheduleThinkingFrame();
|
|
576
633
|
}
|
|
577
634
|
|
|
@@ -592,7 +649,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
592
649
|
|
|
593
650
|
#advanceThinkingDots(): void {
|
|
594
651
|
this.#thinkingDotsTimer = undefined;
|
|
595
|
-
if (!this.#thinkingDots) {
|
|
652
|
+
if (!this.#thinkingDots || isNativeRendering()) {
|
|
596
653
|
this.#stopThinkingAnimation();
|
|
597
654
|
return;
|
|
598
655
|
}
|
|
@@ -649,6 +706,276 @@ export class AssistantMessageComponent extends Container {
|
|
|
649
706
|
return rows;
|
|
650
707
|
}
|
|
651
708
|
|
|
709
|
+
/**
|
|
710
|
+
* A `col` (role `omp.assistant`) of `md` nodes keyed by content index, so
|
|
711
|
+
* streamed deltas reach the terminal as `text append` on the same node;
|
|
712
|
+
* the tail block carries `stream: true` until the message finalizes.
|
|
713
|
+
* Thinking blocks are quiet collapsible `section`s (collapsed per
|
|
714
|
+
* `hideThinkingBlock`): a muted "Thinking…" shimmer while live, then
|
|
715
|
+
* "Thought for 12s"; tokens and rate ride in the head's `title`.
|
|
716
|
+
*/
|
|
717
|
+
override describe(): NativeNode {
|
|
718
|
+
const tail = this.#displayedMessage ? this.#thinkingTailIndex(this.#displayedMessage) : undefined;
|
|
719
|
+
const rate =
|
|
720
|
+
tail !== undefined && this.#lastUpdateTransient && this.#thinkingRateLive
|
|
721
|
+
? Math.round(Math.min(SPEED_MAX, sharedSpeedTracker.getSpeed()) * 10) / 10
|
|
722
|
+
: 0;
|
|
723
|
+
const key = [
|
|
724
|
+
this.#blockVersion,
|
|
725
|
+
this.#transcriptBlockFinalized,
|
|
726
|
+
this.#hideThinkingBlock,
|
|
727
|
+
this.#showImages,
|
|
728
|
+
this.#showToolResultImages,
|
|
729
|
+
this.#errorExpanded,
|
|
730
|
+
this.#nativeViewVersion,
|
|
731
|
+
rate,
|
|
732
|
+
getThemeEpoch(),
|
|
733
|
+
];
|
|
734
|
+
return this.#native.get(key, () => this.#describeMessage(tail, rate));
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* A TTSR rule rewound this partial answer: a native terminal dims it and
|
|
739
|
+
* tags it `↺ rewound` (the ANSI render leaves it as it stopped).
|
|
740
|
+
*/
|
|
741
|
+
markRewound(): void {
|
|
742
|
+
if (this.#rewound) return;
|
|
743
|
+
this.#rewound = true;
|
|
744
|
+
this.#nativeViewVersion++;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/** Mirrors a thinking section collapsed or expanded in the terminal. */
|
|
748
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
749
|
+
if (event.type === "action") {
|
|
750
|
+
this.#handleErrorAction(event.act);
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
if (event.type !== "toggle" || !event.key.startsWith("k")) return;
|
|
754
|
+
const index = Number(event.key.slice(1));
|
|
755
|
+
if (!Number.isInteger(index)) return;
|
|
756
|
+
this.#thinkingCollapsed.set(index, event.collapsed);
|
|
757
|
+
this.#nativeViewVersion++;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
#describeMessage(thinkingTail: number | undefined, rate: number): NativeNode {
|
|
761
|
+
const message = this.#displayedMessage;
|
|
762
|
+
const previousParts = this.#nativeParts;
|
|
763
|
+
const parts = new Map<string, { text: string; stream: boolean; node: NativeNode }>();
|
|
764
|
+
// `slot` identifies the node across rebuilds; `key` is its sibling key inside its parent.
|
|
765
|
+
const markdown = (slot: string, key: string, source: string, stream: boolean): NativeNode => {
|
|
766
|
+
const cached = previousParts.get(slot);
|
|
767
|
+
const entry =
|
|
768
|
+
cached?.text === source && cached.stream === stream
|
|
769
|
+
? cached
|
|
770
|
+
: {
|
|
771
|
+
text: source,
|
|
772
|
+
stream,
|
|
773
|
+
node: node("md", stream ? { text: source, stream: true } : { text: source }, undefined, key),
|
|
774
|
+
};
|
|
775
|
+
parts.set(slot, entry);
|
|
776
|
+
return entry.node;
|
|
777
|
+
};
|
|
778
|
+
const children: NativeChild[] = [];
|
|
779
|
+
if (message) {
|
|
780
|
+
const live = !this.#transcriptBlockFinalized && this.#lastUpdateTransient;
|
|
781
|
+
let tailIndex = -1;
|
|
782
|
+
for (let index = 0; index < message.content.length; index++) {
|
|
783
|
+
const content = message.content[index]!;
|
|
784
|
+
if (
|
|
785
|
+
(content.type === "text" && canonicalizeMessage(content.text)) ||
|
|
786
|
+
(content.type === "thinking" && canonicalizeMessage(content.thinking))
|
|
787
|
+
) {
|
|
788
|
+
tailIndex = index;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
for (let index = 0; index < message.content.length; index++) {
|
|
792
|
+
const content = message.content[index]!;
|
|
793
|
+
const streaming = live && index === tailIndex;
|
|
794
|
+
if (content.type === "text" && canonicalizeMessage(content.text)) {
|
|
795
|
+
children.push(markdown(`t${index}`, `t${index}`, content.text.trim(), streaming));
|
|
796
|
+
} else if (content.type === "thinking") {
|
|
797
|
+
const display = resolveThinkingDisplay(content, this.#proseOnlyThinking);
|
|
798
|
+
if (!display.visible) continue;
|
|
799
|
+
const thinkingLive = streaming && thinkingTail === index;
|
|
800
|
+
const clock = this.#thinkingClock.get(index);
|
|
801
|
+
if (thinkingLive) {
|
|
802
|
+
if (clock) clock.tokens = this.#thinkingTokens || clock.tokens;
|
|
803
|
+
else this.#thinkingClock.set(index, { start: performance.now(), tokens: this.#thinkingTokens });
|
|
804
|
+
} else if (clock && clock.end === undefined) {
|
|
805
|
+
clock.end = performance.now();
|
|
806
|
+
}
|
|
807
|
+
const tokens = thinkingLive ? this.#thinkingTokens : (clock?.tokens ?? 0);
|
|
808
|
+
const title = tokens > 0 ? `${formatNumber(tokens)} tokens` : undefined;
|
|
809
|
+
// Live: starburst · "Thinking…" · ticking timer · tok/s. Done: "Thought for 12s".
|
|
810
|
+
const head = thinkingLive
|
|
811
|
+
? node(
|
|
812
|
+
"row",
|
|
813
|
+
{ gap: "sm", title },
|
|
814
|
+
[
|
|
815
|
+
node("spinner", { style: "starburst", role: "omp.thinking.spin" }),
|
|
816
|
+
text([span("Thinking…", "muted")]),
|
|
817
|
+
elapsed(performance.now() - (this.#thinkingClock.get(index)?.start ?? performance.now())),
|
|
818
|
+
...(rate >= 0.05 ? [node("rate", { value: rate, unit: "tok/s" })] : []),
|
|
819
|
+
],
|
|
820
|
+
"head",
|
|
821
|
+
)
|
|
822
|
+
: node("text", { spans: [span(thoughtLabel(clock), "muted")], title }, undefined, "head");
|
|
823
|
+
const body = markdown(`k${index}`, "body", display.text, streaming);
|
|
824
|
+
children.push(
|
|
825
|
+
node(
|
|
826
|
+
"section",
|
|
827
|
+
{
|
|
828
|
+
// `.live` while streaming: the body clamps to its tail under a fade.
|
|
829
|
+
// `.ghost` while thinking is hidden (Ctrl+T): only a faint "Thought for 12s" stays.
|
|
830
|
+
role: thinkingLive
|
|
831
|
+
? "omp.thinking.live"
|
|
832
|
+
: this.#hideThinkingBlock
|
|
833
|
+
? "omp.thinking.ghost"
|
|
834
|
+
: "omp.thinking",
|
|
835
|
+
collapsible: true,
|
|
836
|
+
// Open while it streams; a finished thought folds to its "Thought for 12s" line.
|
|
837
|
+
collapsed: this.#thinkingCollapsed.get(index) ?? (this.#hideThinkingBlock || !thinkingLive),
|
|
838
|
+
// Tern's fold head sums it into "Worked for 12s".
|
|
839
|
+
took: clock?.end === undefined ? undefined : Math.max(0, Math.round(clock.end - clock.start)),
|
|
840
|
+
},
|
|
841
|
+
[head, body],
|
|
842
|
+
`k${index}`,
|
|
843
|
+
),
|
|
844
|
+
);
|
|
845
|
+
if (!this.#hideThinkingBlock) children.push(...(this.#thinkingExtensions.get(index) ?? []));
|
|
846
|
+
} else if (content.type === "image" && content.data && content.mimeType && this.#showImages) {
|
|
847
|
+
children.push(this.#nativeImages.get(`i${index}`, content.data, content.mimeType));
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
if (this.#showImages && this.#showToolResultImages) {
|
|
851
|
+
for (const [toolCallId, images] of this.#toolImagesByCallId) {
|
|
852
|
+
images.forEach((image, index) => {
|
|
853
|
+
children.push(this.#nativeImages.get(`r${toolCallId}:${index}`, image.data, image.mimeType));
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
const errorNode = this.#describeError(message);
|
|
858
|
+
if (errorNode) children.push(errorNode);
|
|
859
|
+
}
|
|
860
|
+
this.#nativeParts = parts;
|
|
861
|
+
children.push(...this.#markerSlot.children);
|
|
862
|
+
if (this.#rewound) {
|
|
863
|
+
children.push(
|
|
864
|
+
node(
|
|
865
|
+
"badge",
|
|
866
|
+
{ text: "↺ rewound", tone: "muted", role: "omp.assistant.rewound-tag" },
|
|
867
|
+
undefined,
|
|
868
|
+
"rewound",
|
|
869
|
+
),
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
if (this.#turnUsage) {
|
|
873
|
+
const usage = formatTurnUsage(this.#turnUsage);
|
|
874
|
+
children.push(
|
|
875
|
+
node(
|
|
876
|
+
"row",
|
|
877
|
+
{ role: "omp.turn.usage", gap: "xs", align: "center", title: usage.title },
|
|
878
|
+
[
|
|
879
|
+
node("icon", { name: "time" }, undefined, "icon"),
|
|
880
|
+
node("text", { text: usage.text }, undefined, "text"),
|
|
881
|
+
],
|
|
882
|
+
"turn-usage",
|
|
883
|
+
),
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
return col(children, { role: this.#rewound ? "omp.assistant.rewound" : "omp.assistant" });
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* Turn-ending error, recovered-retry note or abort label. A failed request
|
|
891
|
+
* is one error frame (head: "Request failed" + the HTTP status chip; body:
|
|
892
|
+
* the message once; then Retry / Copy error / Switch model), and stays in
|
|
893
|
+
* the transcript: the pinned banner is ANSI-only. A recovered attempt is an
|
|
894
|
+
* inline row that discloses the original error.
|
|
895
|
+
*/
|
|
896
|
+
#describeError(message: AssistantMessage): NativeNode | undefined {
|
|
897
|
+
const presentation = resolveAssistantErrorPresentation(message);
|
|
898
|
+
if (presentation.kind === "compact-recovered") {
|
|
899
|
+
const attempt = message.retryRecovery?.attempt ?? 1;
|
|
900
|
+
const body = [message.errorMessage?.trim(), presentation.text].filter(
|
|
901
|
+
(line, index, all): line is string => !!line && all.indexOf(line) === index,
|
|
902
|
+
);
|
|
903
|
+
return node(
|
|
904
|
+
"section",
|
|
905
|
+
{
|
|
906
|
+
role: "omp.assistant.recovered",
|
|
907
|
+
head: [span(`↻ Recovered after ${attempt} ${attempt === 1 ? "retry" : "retries"}`, "muted")],
|
|
908
|
+
collapsible: true,
|
|
909
|
+
collapsed: true,
|
|
910
|
+
},
|
|
911
|
+
[text([span(body.join("\n"), "mono")], { wrap: "word" })],
|
|
912
|
+
"error",
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
if (presentation.kind !== "full" || message.content.some(content => content.type === "toolCall"))
|
|
916
|
+
return undefined;
|
|
917
|
+
if (message.stopReason === "aborted") {
|
|
918
|
+
return text([span(presentation.text, "error")], { wrap: "word", key: "error", role: "omp.assistant.abort" });
|
|
919
|
+
}
|
|
920
|
+
const lines = presentation.text
|
|
921
|
+
.split("\n")
|
|
922
|
+
.map(line => line.trim())
|
|
923
|
+
.filter(line => line.length > 0);
|
|
924
|
+
// "500 upstream overloaded" → chip "500", then the message once: a
|
|
925
|
+
// line the next one repeats with more detail is dropped.
|
|
926
|
+
const code = /^(\d{3})\s+/.exec(lines[0] ?? "");
|
|
927
|
+
if (code) lines[0] = lines[0]!.slice(code[0].length);
|
|
928
|
+
const detail = lines.filter((line, index) => !lines.slice(index + 1).some(next => next.startsWith(line)));
|
|
929
|
+
const errorText = detail.join("\n") || "Unknown error";
|
|
930
|
+
const children: NativeChild[] = [
|
|
931
|
+
node(
|
|
932
|
+
"row",
|
|
933
|
+
{ gap: "sm" },
|
|
934
|
+
[
|
|
935
|
+
text([span("Request failed", "error strong")]),
|
|
936
|
+
...(code ? [node("badge", { text: code[1]!, tone: "error", role: "omp.error.code" })] : []),
|
|
937
|
+
],
|
|
938
|
+
"head",
|
|
939
|
+
),
|
|
940
|
+
text([span(errorText, "mono")], {
|
|
941
|
+
wrap: "word",
|
|
942
|
+
lines: this.#errorExpanded ? undefined : MAX_TRANSCRIPT_ERROR_ROWS,
|
|
943
|
+
role: "omp.error.message",
|
|
944
|
+
key: "message",
|
|
945
|
+
}),
|
|
946
|
+
];
|
|
947
|
+
if (message.stopReason === "error" && hasTranscriptActions()) {
|
|
948
|
+
const button = (act: string, label: string, keys: readonly string[], title: string): NativeNode =>
|
|
949
|
+
node(
|
|
950
|
+
"row",
|
|
951
|
+
{ gap: "xs", role: "omp.error.action", actions: { click: act }, title },
|
|
952
|
+
keys.length > 0 ? [text(label), node("kbd", { keys })] : [text(label)],
|
|
953
|
+
act,
|
|
954
|
+
);
|
|
955
|
+
children.push(
|
|
956
|
+
node(
|
|
957
|
+
"row",
|
|
958
|
+
{ gap: "sm", role: "omp.error.actions" },
|
|
959
|
+
[
|
|
960
|
+
button("retry", "Retry", ["F5"], "Retry the failed turn"),
|
|
961
|
+
button("copy-error", "Copy error", [], "Copy the error message"),
|
|
962
|
+
button("switch-model", "Switch model", ["⌥P"], "Pick another model for this session"),
|
|
963
|
+
],
|
|
964
|
+
"actions",
|
|
965
|
+
),
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
this.#errorText = errorText;
|
|
969
|
+
return card({ role: "omp.error", tone: "error", key: "error" }, children);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/** Error frame action clicks: omp's own retry, clipboard and model-picker paths. */
|
|
973
|
+
#handleErrorAction(act: string): void {
|
|
974
|
+
if (act === "retry") runTranscriptAction({ act: "retry" });
|
|
975
|
+
else if (act === "switch-model") runTranscriptAction({ act: "switch-model" });
|
|
976
|
+
else if (act === "copy-error" && this.#errorText) runTranscriptAction({ act: "copy", text: this.#errorText });
|
|
977
|
+
}
|
|
978
|
+
|
|
652
979
|
/** Width-independent stable identities for the streamed leading thinking run. */
|
|
653
980
|
getTranscriptStableRows(): readonly TranscriptStableRow[] {
|
|
654
981
|
return this.#transcriptStableRows;
|
|
@@ -1066,6 +1393,8 @@ export class AssistantMessageComponent extends Container {
|
|
|
1066
1393
|
}
|
|
1067
1394
|
|
|
1068
1395
|
#appendThinkingExtensions(contentIndex: number, thinkingIndex: number, text: string): void {
|
|
1396
|
+
const mounted: Component[] = [];
|
|
1397
|
+
this.#thinkingExtensions.set(contentIndex, mounted);
|
|
1069
1398
|
for (const renderer of this.#thinkingRenderers) {
|
|
1070
1399
|
try {
|
|
1071
1400
|
const component = renderer(
|
|
@@ -1079,6 +1408,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
1079
1408
|
);
|
|
1080
1409
|
if (component) {
|
|
1081
1410
|
this.#contentContainer.addChild(component);
|
|
1411
|
+
mounted.push(component);
|
|
1082
1412
|
}
|
|
1083
1413
|
} catch {
|
|
1084
1414
|
// Ignore extension renderer failures and keep the original thinking block visible.
|
|
@@ -1198,6 +1528,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
1198
1528
|
// Everything below renders the display form; #lastMessage keeps the
|
|
1199
1529
|
// verbatim message so re-renders re-derive the reaction deterministically.
|
|
1200
1530
|
message = this.#displayMessage(message, this.#lastUpdateTransient);
|
|
1531
|
+
this.#displayedMessage = message;
|
|
1201
1532
|
|
|
1202
1533
|
// Streaming-speed gauge: only a live, in-flight render of the single
|
|
1203
1534
|
// animating hidden-thinking block feeds the shared session tracker. The
|
|
@@ -1211,7 +1542,10 @@ export class AssistantMessageComponent extends Container {
|
|
|
1211
1542
|
// the gauge and pollute the next block. Providers that report usage only at
|
|
1212
1543
|
// turn end leave the live count flat, so the rate stays 0 and the badge
|
|
1213
1544
|
// self-suppresses (see #thinkingDotsLabel).
|
|
1214
|
-
|
|
1545
|
+
// Native terminals show the live rate on visible thinking too, not only the hidden pulse.
|
|
1546
|
+
const isThinkingNow =
|
|
1547
|
+
this.#lastUpdateTransient &&
|
|
1548
|
+
(isNativeRendering() ? this.#thinkingTailIndex(message) !== undefined : this.#shouldAnimateThinking(message));
|
|
1215
1549
|
if (isThinkingNow) {
|
|
1216
1550
|
const currentTokens = message.usage.reasoningTokens ?? message.usage.output;
|
|
1217
1551
|
this.#thinkingTokens = currentTokens;
|
|
@@ -1240,6 +1574,7 @@ export class AssistantMessageComponent extends Container {
|
|
|
1240
1574
|
|
|
1241
1575
|
// Clear content container
|
|
1242
1576
|
this.#contentContainer.clear();
|
|
1577
|
+
this.#thinkingExtensions.clear();
|
|
1243
1578
|
this.#emergencyText = undefined;
|
|
1244
1579
|
this.#thinkingDots = undefined;
|
|
1245
1580
|
this.#hasTruncatableError = false;
|
|
@@ -25,10 +25,10 @@ export function createBackgroundTanDispatchBlock(message: CustomMessage<unknown>
|
|
|
25
25
|
return new TranscriptStatusBlock([
|
|
26
26
|
{
|
|
27
27
|
parts: [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
work ?
|
|
28
|
+
{ text: `${theme.icon.output} Tangent dispatched`, color: "muted" },
|
|
29
|
+
{ text: "[task]", color: "dim" },
|
|
30
|
+
{ text: jobId, color: "accent" },
|
|
31
|
+
work ? { text: `${theme.format.dash} ${work}`, color: "dim" } : undefined,
|
|
32
32
|
],
|
|
33
33
|
},
|
|
34
34
|
]);
|
|
@@ -21,10 +21,17 @@ import {
|
|
|
21
21
|
buildExecutionFrame,
|
|
22
22
|
buildStatusFooter,
|
|
23
23
|
clampDisplayLine,
|
|
24
|
+
describeExecutionCard,
|
|
25
|
+
describeExecutionTool,
|
|
26
|
+
type ExecutionColorKey,
|
|
24
27
|
type ExecutionStatus,
|
|
25
28
|
PREVIEW_LINES,
|
|
26
29
|
resolveExecutionStatus,
|
|
27
30
|
} from "./execution-shared";
|
|
31
|
+
import { span, text } from "../native/describe";
|
|
32
|
+
import { type DescribeContext, type NativeNode, type NativeUiEvent, rootToggleExpanded } from "../native/node";
|
|
33
|
+
import { NativeImageCache } from "../native/blobs";
|
|
34
|
+
import { Memo } from "../native/memo";
|
|
28
35
|
|
|
29
36
|
const STREAMING_LINE_CAP = PREVIEW_LINES * 5;
|
|
30
37
|
// Minimum interval between processing incoming chunks for display (ms).
|
|
@@ -78,6 +85,13 @@ export class BashExecutionComponent extends Container {
|
|
|
78
85
|
#showImages = true;
|
|
79
86
|
readonly #instanceId = nextBashExecutionId++;
|
|
80
87
|
readonly #command: string;
|
|
88
|
+
readonly #colorKey: ExecutionColorKey;
|
|
89
|
+
readonly #startedAt = performance.now();
|
|
90
|
+
#endedAt: number | undefined;
|
|
91
|
+
// Bumped whenever the displayed output lines change.
|
|
92
|
+
#outputVersion = 0;
|
|
93
|
+
readonly #native = new Memo();
|
|
94
|
+
readonly #nativeImages = new NativeImageCache();
|
|
81
95
|
|
|
82
96
|
constructor(command: string, ui: TUI, excludeFromContext = false) {
|
|
83
97
|
super();
|
|
@@ -86,6 +100,7 @@ export class BashExecutionComponent extends Container {
|
|
|
86
100
|
|
|
87
101
|
// Use dim border for excluded-from-context commands (!! prefix)
|
|
88
102
|
const colorKey = excludeFromContext ? "dim" : "bashMode";
|
|
103
|
+
this.#colorKey = colorKey;
|
|
89
104
|
const { contentContainer, loader } = buildExecutionFrame(this, ui, colorKey);
|
|
90
105
|
this.#contentContainer = contentContainer;
|
|
91
106
|
this.#loader = loader;
|
|
@@ -136,6 +151,68 @@ export class BashExecutionComponent extends Container {
|
|
|
136
151
|
this.#updateDisplay();
|
|
137
152
|
}
|
|
138
153
|
|
|
154
|
+
handleNativeEvent(event: NativeUiEvent): void {
|
|
155
|
+
const expanded = rootToggleExpanded(event);
|
|
156
|
+
if (expanded !== undefined) this.setExpanded(expanded);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The agent's bash `tool` frame (role `omp.bash`) with a `you` badge: the
|
|
161
|
+
* command in the head, the output as an `ansi` mini terminal following its
|
|
162
|
+
* tail. Terminals without the `tool` kind get a `card` headed by the
|
|
163
|
+
* command.
|
|
164
|
+
*/
|
|
165
|
+
override describe(cx?: DescribeContext): NativeNode {
|
|
166
|
+
const dataFirst = cx?.supports("tool") === true;
|
|
167
|
+
const key = [
|
|
168
|
+
dataFirst,
|
|
169
|
+
this.#outputVersion,
|
|
170
|
+
this.#blockVersion,
|
|
171
|
+
this.#status,
|
|
172
|
+
this.#expanded,
|
|
173
|
+
this.#showImages,
|
|
174
|
+
this.#images.length,
|
|
175
|
+
];
|
|
176
|
+
return this.#native.get(key, () => {
|
|
177
|
+
const images = this.#images.map((image, index) =>
|
|
178
|
+
this.#showImages
|
|
179
|
+
? this.#nativeImages.get(`img${index}`, image.data, image.mimeType)
|
|
180
|
+
: text([
|
|
181
|
+
span(
|
|
182
|
+
imageFallback(image.mimeType, getImageDimensions(image.data, image.mimeType) ?? undefined),
|
|
183
|
+
"muted",
|
|
184
|
+
),
|
|
185
|
+
]),
|
|
186
|
+
);
|
|
187
|
+
const common = {
|
|
188
|
+
role: "omp.bash",
|
|
189
|
+
status: this.#status,
|
|
190
|
+
startedAt: this.#startedAt,
|
|
191
|
+
expanded: this.#expanded,
|
|
192
|
+
output: this.#outputLines.join("\n"),
|
|
193
|
+
images,
|
|
194
|
+
exitCode: this.#exitCode,
|
|
195
|
+
truncation: this.#truncation,
|
|
196
|
+
artifactError: this.#artifactError,
|
|
197
|
+
};
|
|
198
|
+
return dataFirst
|
|
199
|
+
? describeExecutionTool({
|
|
200
|
+
...common,
|
|
201
|
+
name: "bash",
|
|
202
|
+
title: "Bash",
|
|
203
|
+
command: this.#command,
|
|
204
|
+
lang: "bash",
|
|
205
|
+
excluded: this.#colorKey === "dim",
|
|
206
|
+
endedAt: this.#endedAt,
|
|
207
|
+
})
|
|
208
|
+
: describeExecutionCard({
|
|
209
|
+
...common,
|
|
210
|
+
head: [span(`$ ${this.#command}`, `${this.#colorKey} strong`)],
|
|
211
|
+
muted: this.#colorKey === "dim",
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
139
216
|
appendOutput(chunk: string): void {
|
|
140
217
|
if (this.#ptyMode) return;
|
|
141
218
|
// During high-throughput output (e.g. seq 1 500M), processing every
|
|
@@ -165,6 +242,7 @@ export class BashExecutionComponent extends Container {
|
|
|
165
242
|
}
|
|
166
243
|
|
|
167
244
|
this.#displayDirty = true;
|
|
245
|
+
this.#outputVersion++;
|
|
168
246
|
}
|
|
169
247
|
|
|
170
248
|
/** Switch to PTY rendering and feed raw terminal bytes through the vterm replay. */
|
|
@@ -240,6 +318,7 @@ export class BashExecutionComponent extends Container {
|
|
|
240
318
|
const base = theme.getFgAnsi("muted");
|
|
241
319
|
this.#outputLines = rows.map(row => (row ? styleTerminalRow(row, base) : ""));
|
|
242
320
|
this.#displayDirty = true;
|
|
321
|
+
this.#outputVersion++;
|
|
243
322
|
}
|
|
244
323
|
|
|
245
324
|
/** Final full-scrollback read; the terminal is disposed once lines are snapshotted. */
|
|
@@ -268,6 +347,7 @@ export class BashExecutionComponent extends Container {
|
|
|
268
347
|
): void {
|
|
269
348
|
this.#exitCode = exitCode;
|
|
270
349
|
this.#status = resolveExecutionStatus(exitCode, cancelled);
|
|
350
|
+
this.#endedAt ??= performance.now();
|
|
271
351
|
this.#truncation = options?.truncation;
|
|
272
352
|
this.#artifactError = options?.artifactError;
|
|
273
353
|
this.#images = options?.images ?? [];
|
|
@@ -376,6 +456,7 @@ export class BashExecutionComponent extends Container {
|
|
|
376
456
|
#setOutput(output: string): void {
|
|
377
457
|
const clean = sanitizeWithOptionalSixelPassthrough(output, sanitizeText);
|
|
378
458
|
this.#outputLines = clean ? this.#clampLinesPreservingSixel(clean.split("\n")) : [];
|
|
459
|
+
this.#outputVersion++;
|
|
379
460
|
}
|
|
380
461
|
|
|
381
462
|
/**
|
|
@@ -87,6 +87,14 @@ export class CacheInvalidationMarkerComponent extends MessageDividerComponent {
|
|
|
87
87
|
labelColor: "muted",
|
|
88
88
|
ruleColor: "dim",
|
|
89
89
|
ruleWidth: 10,
|
|
90
|
+
role: "omp.marker.cache-miss",
|
|
91
|
+
native: {
|
|
92
|
+
icon: "database",
|
|
93
|
+
label: () =>
|
|
94
|
+
info.reprocessedTokens > 0
|
|
95
|
+
? `Cache miss · ${formatNumber(info.reprocessedTokens)} tokens`
|
|
96
|
+
: "Cache miss",
|
|
97
|
+
},
|
|
90
98
|
// Too narrow to frame — preserve the legacy bare label.
|
|
91
99
|
truncateWhenNarrow: false,
|
|
92
100
|
});
|