@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
|
@@ -5,7 +5,14 @@ import type { Tool as AiTool, Model } from "@oh-my-pi/pi-ai";
|
|
|
5
5
|
import { renderToolExamples } from "@oh-my-pi/pi-ai/dialect";
|
|
6
6
|
import { toolWireSchema } from "@oh-my-pi/pi-ai/utils/schema";
|
|
7
7
|
import { formatNumber } from "@oh-my-pi/pi-utils";
|
|
8
|
-
import type { Theme } from "../theme";
|
|
8
|
+
import type { Theme, ThemeColor } from "../theme";
|
|
9
|
+
import { Container } from "../tui";
|
|
10
|
+
import { Text } from "../components/text";
|
|
11
|
+
import { Spacer } from "../components/spacer";
|
|
12
|
+
import { DynamicBorder } from "../chrome/dynamic-border";
|
|
13
|
+
import type { TspSpan, TspText } from "@oh-my-pi/pi-wire";
|
|
14
|
+
import type { DescribeContext, NativeNode } from "../native/node";
|
|
15
|
+
import { card, col, node, row, span, text } from "../native/describe";
|
|
9
16
|
|
|
10
17
|
interface ContextSkill {
|
|
11
18
|
readonly name: string;
|
|
@@ -92,6 +99,8 @@ export interface ContextBreakdown {
|
|
|
92
99
|
usedTokens: number;
|
|
93
100
|
autoCompactBufferTokens: number;
|
|
94
101
|
freeTokens: number;
|
|
102
|
+
/** Where auto-compaction fires, in tokens; undefined when compaction is off. */
|
|
103
|
+
thresholdTokens?: number;
|
|
95
104
|
/** Estimated snapcompact wire savings; set when requested and a snapcompact.* setting is enabled. */
|
|
96
105
|
snapcompact?: ContextSavingsEstimate;
|
|
97
106
|
}
|
|
@@ -459,10 +468,12 @@ export function computeContextBreakdown(session: ContextUsageSession, options: C
|
|
|
459
468
|
];
|
|
460
469
|
|
|
461
470
|
let autoCompactBufferTokens = 0;
|
|
471
|
+
let thresholdTokens: number | undefined;
|
|
462
472
|
if (contextWindow > 0) {
|
|
463
473
|
const compactionSettings = options.compaction;
|
|
464
474
|
if (compactionSettings.enabled && compactionSettings.strategy !== "off") {
|
|
465
475
|
const threshold = resolveThresholdTokens(contextWindow, compactionSettings);
|
|
476
|
+
if (threshold > 0 && threshold <= contextWindow) thresholdTokens = threshold;
|
|
466
477
|
autoCompactBufferTokens = Math.max(0, contextWindow - threshold);
|
|
467
478
|
} else {
|
|
468
479
|
autoCompactBufferTokens = 0;
|
|
@@ -483,6 +494,7 @@ export function computeContextBreakdown(session: ContextUsageSession, options: C
|
|
|
483
494
|
usedTokens,
|
|
484
495
|
autoCompactBufferTokens,
|
|
485
496
|
freeTokens,
|
|
497
|
+
thresholdTokens,
|
|
486
498
|
snapcompact: options.snapcompact,
|
|
487
499
|
};
|
|
488
500
|
}
|
|
@@ -566,63 +578,91 @@ function percentString(part: number, whole: number, fractionDigits = 1): string
|
|
|
566
578
|
return `${pct.toFixed(fractionDigits)}%`;
|
|
567
579
|
}
|
|
568
580
|
|
|
569
|
-
|
|
570
|
-
|
|
581
|
+
/** One styled run of a legend line: bold (`strong`), a theme color, or plain. */
|
|
582
|
+
interface LegendPart {
|
|
583
|
+
t: string;
|
|
584
|
+
s?: ThemeColor | "strong";
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/** Legend lines as styled runs, shared by the ANSI panel and the native description. */
|
|
588
|
+
function buildLegendParts(breakdown: ContextBreakdown): LegendPart[][] {
|
|
589
|
+
const lines: LegendPart[][] = [];
|
|
571
590
|
const { model, contextWindow, categories, usedTokens, autoCompactBufferTokens, freeTokens } = breakdown;
|
|
572
591
|
|
|
573
592
|
const modelName = model?.name ?? model?.id ?? "no model";
|
|
574
593
|
const modelId = model?.id ?? "unknown";
|
|
575
594
|
const windowLabel = formatNumber(contextWindow).toLowerCase();
|
|
576
595
|
|
|
577
|
-
lines.push(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
596
|
+
lines.push([
|
|
597
|
+
{ t: `${modelName}`, s: "strong" },
|
|
598
|
+
{ t: ` (${windowLabel} context)`, s: "dim" },
|
|
599
|
+
]);
|
|
600
|
+
lines.push([{ t: `${modelId}[${windowLabel}]`, s: "muted" }]);
|
|
601
|
+
lines.push([
|
|
602
|
+
{ t: formatNumber(usedTokens), s: "strong" },
|
|
603
|
+
{ t: `/${windowLabel} tokens`, s: "dim" },
|
|
604
|
+
{ t: ` (${percentString(usedTokens, contextWindow)})`, s: "muted" },
|
|
605
|
+
]);
|
|
606
|
+
lines.push([]);
|
|
607
|
+
lines.push([{ t: "Estimated usage by category", s: "muted" }]);
|
|
585
608
|
|
|
586
609
|
for (const category of categories) {
|
|
587
|
-
const dot = theme.fg(category.color, category.glyph);
|
|
588
|
-
const label = category.label;
|
|
589
|
-
const tokens = formatNumber(category.tokens);
|
|
590
610
|
const pct = percentString(category.tokens, contextWindow);
|
|
591
|
-
lines.push(
|
|
611
|
+
lines.push([
|
|
612
|
+
{ t: category.glyph, s: category.color },
|
|
613
|
+
{ t: ` ${category.label}: ` },
|
|
614
|
+
{ t: formatNumber(category.tokens), s: "strong" },
|
|
615
|
+
{ t: " " },
|
|
616
|
+
{ t: `tokens (${pct})`, s: "dim" },
|
|
617
|
+
]);
|
|
592
618
|
}
|
|
593
619
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
620
|
+
lines.push([
|
|
621
|
+
{ t: CELL_FREE, s: "dim" },
|
|
622
|
+
{ t: " Free space: " },
|
|
623
|
+
{ t: formatNumber(freeTokens), s: "strong" },
|
|
624
|
+
{ t: " " },
|
|
625
|
+
{ t: `(${percentString(freeTokens, contextWindow)})`, s: "dim" },
|
|
626
|
+
]);
|
|
598
627
|
|
|
599
628
|
if (autoCompactBufferTokens > 0) {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
)}`,
|
|
606
|
-
);
|
|
629
|
+
lines.push([
|
|
630
|
+
{ t: CELL_BUFFER, s: "warning" },
|
|
631
|
+
{ t: " Autocompact buffer: " },
|
|
632
|
+
{ t: formatNumber(autoCompactBufferTokens), s: "strong" },
|
|
633
|
+
{ t: " " },
|
|
634
|
+
{ t: `tokens (${percentString(autoCompactBufferTokens, contextWindow)})`, s: "dim" },
|
|
635
|
+
]);
|
|
607
636
|
}
|
|
608
637
|
|
|
638
|
+
const snap = buildSnapcompactParts(breakdown);
|
|
639
|
+
if (snap.length > 0) lines.push([], ...snap);
|
|
640
|
+
return lines;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/** Snapcompact savings lines of the legend; empty when no snapcompact setting is on. */
|
|
644
|
+
function buildSnapcompactParts(breakdown: ContextBreakdown): LegendPart[][] {
|
|
645
|
+
const lines: LegendPart[][] = [];
|
|
646
|
+
const { usedTokens } = breakdown;
|
|
609
647
|
const snap = breakdown.snapcompact;
|
|
610
648
|
if (snap) {
|
|
611
|
-
lines.push("");
|
|
612
649
|
if (!snap.visionCapable) {
|
|
613
|
-
lines.push(
|
|
650
|
+
lines.push([{ t: "Snapcompact: inactive (model has no image input)", s: "muted" }]);
|
|
614
651
|
} else {
|
|
615
|
-
lines.push(
|
|
652
|
+
lines.push([{ t: "Snapcompact (estimated wire savings)", s: "muted" }]);
|
|
616
653
|
if (snap.systemPrompt) {
|
|
617
654
|
const sp = snap.systemPrompt;
|
|
655
|
+
const scope = sp.scope === "agents-md" ? "AGENTS.md" : "all";
|
|
618
656
|
if (sp.applied) {
|
|
619
|
-
lines.push(
|
|
620
|
-
` System prompt (${
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
)
|
|
625
|
-
|
|
657
|
+
lines.push([
|
|
658
|
+
{ t: ` System prompt (${scope}): saves ` },
|
|
659
|
+
{ t: `~${formatNumber(sp.savedTokens)}`, s: "strong" },
|
|
660
|
+
{ t: " " },
|
|
661
|
+
{
|
|
662
|
+
t: `(${formatNumber(sp.textTokens)} text → ${sp.frames} frame${sp.frames === 1 ? "" : "s"} ≈ ${formatNumber(sp.imageTokens)})`,
|
|
663
|
+
s: "dim",
|
|
664
|
+
},
|
|
665
|
+
]);
|
|
626
666
|
} else {
|
|
627
667
|
const reason =
|
|
628
668
|
sp.reason === "budget"
|
|
@@ -630,29 +670,32 @@ function buildLegendLines(breakdown: ContextBreakdown, theme: Theme): string[] {
|
|
|
630
670
|
: sp.reason === "empty"
|
|
631
671
|
? "nothing to image"
|
|
632
672
|
: "frames would not save tokens";
|
|
633
|
-
lines.push(
|
|
634
|
-
` System prompt (${sp.scope === "agents-md" ? "AGENTS.md" : "all"}): ${theme.fg("dim", `stays text (${reason})`)}`,
|
|
635
|
-
);
|
|
673
|
+
lines.push([{ t: ` System prompt (${scope}): ` }, { t: `stays text (${reason})`, s: "dim" }]);
|
|
636
674
|
}
|
|
637
675
|
}
|
|
638
676
|
if (snap.toolResults) {
|
|
639
677
|
const tr = snap.toolResults;
|
|
640
678
|
if (tr.swapped > 0) {
|
|
641
|
-
lines.push(
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
)
|
|
647
|
-
|
|
679
|
+
lines.push([
|
|
680
|
+
{ t: " Tool results: saves " },
|
|
681
|
+
{ t: `~${formatNumber(tr.savedTokens)}`, s: "strong" },
|
|
682
|
+
{ t: " " },
|
|
683
|
+
{
|
|
684
|
+
t: `(${tr.swapped}/${tr.total} imaged, ${formatNumber(tr.textTokens)} text → ${tr.frames} frames ≈ ${formatNumber(tr.imageTokens)})`,
|
|
685
|
+
s: "dim",
|
|
686
|
+
},
|
|
687
|
+
]);
|
|
648
688
|
} else {
|
|
649
|
-
lines.push(
|
|
689
|
+
lines.push([{ t: " Tool results: " }, { t: `none imaged (${tr.total} in history)`, s: "dim" }]);
|
|
650
690
|
}
|
|
651
691
|
}
|
|
652
692
|
if (snap.savedTokens > 0) {
|
|
653
|
-
lines.push(
|
|
654
|
-
|
|
655
|
-
|
|
693
|
+
lines.push([
|
|
694
|
+
{ t: " Next request: " },
|
|
695
|
+
{ t: `~${formatNumber(Math.max(0, usedTokens - snap.savedTokens))}`, s: "strong" },
|
|
696
|
+
{ t: " " },
|
|
697
|
+
{ t: "tokens on the wire", s: "dim" },
|
|
698
|
+
]);
|
|
656
699
|
}
|
|
657
700
|
}
|
|
658
701
|
}
|
|
@@ -660,6 +703,192 @@ function buildLegendLines(breakdown: ContextBreakdown, theme: Theme): string[] {
|
|
|
660
703
|
return lines;
|
|
661
704
|
}
|
|
662
705
|
|
|
706
|
+
function buildLegendLines(breakdown: ContextBreakdown, theme: Theme): string[] {
|
|
707
|
+
return buildLegendParts(breakdown).map(line => {
|
|
708
|
+
let out = "";
|
|
709
|
+
for (const part of line) {
|
|
710
|
+
out += part.s === "strong" ? theme.bold(part.t) : part.s ? theme.fg(part.s, part.t) : part.t;
|
|
711
|
+
}
|
|
712
|
+
return out;
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/** Stacked meter parts in grid order: the categories, free space as the empty track, then the hatched buffer. */
|
|
717
|
+
function contextMeterParts(
|
|
718
|
+
breakdown: ContextBreakdown,
|
|
719
|
+
): { value: number; token?: string; label?: string; hatch?: boolean }[] {
|
|
720
|
+
const window = breakdown.contextWindow;
|
|
721
|
+
const parts: { value: number; token?: string; label?: string; hatch?: boolean }[] = breakdown.categories
|
|
722
|
+
.filter(category => category.tokens > 0)
|
|
723
|
+
.map(category => ({
|
|
724
|
+
value: category.tokens / window,
|
|
725
|
+
token: category.color,
|
|
726
|
+
label: `${category.label} · ${formatNumber(category.tokens)} tokens (${percentString(category.tokens, window)})`,
|
|
727
|
+
}));
|
|
728
|
+
parts.push({
|
|
729
|
+
value: breakdown.freeTokens / window,
|
|
730
|
+
token: "track",
|
|
731
|
+
label: `Free space · ${formatNumber(breakdown.freeTokens)} tokens (${percentString(breakdown.freeTokens, window)})`,
|
|
732
|
+
});
|
|
733
|
+
if (breakdown.autoCompactBufferTokens > 0) {
|
|
734
|
+
parts.push({
|
|
735
|
+
value: breakdown.autoCompactBufferTokens / window,
|
|
736
|
+
token: "warning",
|
|
737
|
+
hatch: true,
|
|
738
|
+
label: `Autocompact buffer · ${formatNumber(breakdown.autoCompactBufferTokens)} tokens (${percentString(breakdown.autoCompactBufferTokens, window)})`,
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
return parts;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* The `/context` frame for terminals that draw `meter`: a blocks meter
|
|
746
|
+
* beside a legend `kv` (swatch · label → tokens · %), then a full-width bar
|
|
747
|
+
* of the same parts marked where auto-compaction fires, then the snapcompact
|
|
748
|
+
* estimate when one is on. The head names the model and window once.
|
|
749
|
+
*/
|
|
750
|
+
function describeContextFrame(breakdown: ContextBreakdown): NativeNode {
|
|
751
|
+
const { contextWindow: window, usedTokens, freeTokens, autoCompactBufferTokens, thresholdTokens } = breakdown;
|
|
752
|
+
const parts = contextMeterParts(breakdown);
|
|
753
|
+
const used = Math.min(1, usedTokens / window);
|
|
754
|
+
const swatch = (token: string, glyph = "■"): TspSpan => span(glyph, token);
|
|
755
|
+
const figure = (tokens: number): TspText => [
|
|
756
|
+
span(formatNumber(tokens)),
|
|
757
|
+
span(` ${percentString(tokens, window)}`, "dim"),
|
|
758
|
+
];
|
|
759
|
+
const items: { k: TspText; v: TspText }[] = [
|
|
760
|
+
{
|
|
761
|
+
k: [span("Used", "strong")],
|
|
762
|
+
v: [
|
|
763
|
+
span(`${formatNumber(usedTokens)} / ${formatNumber(window).toLowerCase()}`),
|
|
764
|
+
span(` ${percentString(usedTokens, window)}`, "dim"),
|
|
765
|
+
],
|
|
766
|
+
},
|
|
767
|
+
];
|
|
768
|
+
for (const category of breakdown.categories) {
|
|
769
|
+
items.push({ k: [swatch(category.color), span(` ${category.label}`)], v: figure(category.tokens) });
|
|
770
|
+
}
|
|
771
|
+
items.push({ k: [swatch("dim", "□"), span(" Free space")], v: figure(freeTokens) });
|
|
772
|
+
if (autoCompactBufferTokens > 0) {
|
|
773
|
+
items.push({ k: [swatch("warning", "▨"), span(" Autocompact buffer")], v: figure(autoCompactBufferTokens) });
|
|
774
|
+
}
|
|
775
|
+
const marks =
|
|
776
|
+
thresholdTokens !== undefined
|
|
777
|
+
? [
|
|
778
|
+
{
|
|
779
|
+
at: thresholdTokens / window,
|
|
780
|
+
tone: "warning" as const,
|
|
781
|
+
title: `Auto-compaction at ${percentString(thresholdTokens, window, 0)} (${formatNumber(thresholdTokens)} tokens)`,
|
|
782
|
+
},
|
|
783
|
+
]
|
|
784
|
+
: undefined;
|
|
785
|
+
const children = [
|
|
786
|
+
node(
|
|
787
|
+
"row",
|
|
788
|
+
{ role: "omp.context.body" },
|
|
789
|
+
[
|
|
790
|
+
node("meter", { value: used, style: "blocks", size: "lg", parts, aria: "Context usage by category" }),
|
|
791
|
+
node("kv", { items, layout: "grid", role: "omp.context.legend" }),
|
|
792
|
+
],
|
|
793
|
+
"body",
|
|
794
|
+
),
|
|
795
|
+
node(
|
|
796
|
+
"meter",
|
|
797
|
+
{ value: used, style: "bar", size: "lg", parts, ...(marks ? { marks } : {}), grow: 1 },
|
|
798
|
+
undefined,
|
|
799
|
+
"bar",
|
|
800
|
+
),
|
|
801
|
+
];
|
|
802
|
+
const snap = buildSnapcompactParts(breakdown);
|
|
803
|
+
if (snap.length > 0) {
|
|
804
|
+
children.push(
|
|
805
|
+
node(
|
|
806
|
+
"section",
|
|
807
|
+
{},
|
|
808
|
+
snap.map((line, index) => node("text", { spans: line, wrap: "word" }, undefined, `snap-${index}`)),
|
|
809
|
+
"snapcompact",
|
|
810
|
+
),
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
const modelName = breakdown.model?.name ?? breakdown.model?.id ?? "no model";
|
|
814
|
+
return card(
|
|
815
|
+
{
|
|
816
|
+
role: "omp.context",
|
|
817
|
+
head: [
|
|
818
|
+
span("Context", "strong"),
|
|
819
|
+
span(` · ${modelName}`, "muted"),
|
|
820
|
+
span(` · ${formatNumber(window).toLowerCase()}`, "dim"),
|
|
821
|
+
],
|
|
822
|
+
},
|
|
823
|
+
children,
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Native context-usage panel for terminals without `meter`: the cell grid as
|
|
829
|
+
* unwrapped styled rows beside the legend. The terminal places the legend
|
|
830
|
+
* beside the grid, or below it when narrow.
|
|
831
|
+
*/
|
|
832
|
+
export function describeContextUsage(breakdown: ContextBreakdown): NativeNode {
|
|
833
|
+
if (breakdown.contextWindow <= 0) {
|
|
834
|
+
return text([{ t: "Context usage is unavailable: no model is selected for this session.", s: "muted" }]);
|
|
835
|
+
}
|
|
836
|
+
const cells = planCells(breakdown);
|
|
837
|
+
const grid: NativeNode[] = [];
|
|
838
|
+
for (let gridRow = 0; gridRow < GRID_ROWS; gridRow++) {
|
|
839
|
+
const spans: TspSpan[] = [];
|
|
840
|
+
for (let gridCol = 0; gridCol < GRID_COLS; gridCol++) {
|
|
841
|
+
const cell = cells[gridRow * GRID_COLS + gridCol]!;
|
|
842
|
+
spans.push({ t: gridCol === 0 ? cell.glyph : ` ${cell.glyph}`, s: cell.color });
|
|
843
|
+
}
|
|
844
|
+
grid.push(node("text", { spans, wrap: "none" }, undefined, `row-${gridRow}`));
|
|
845
|
+
}
|
|
846
|
+
const legend = buildLegendParts(breakdown).map((line, index) =>
|
|
847
|
+
node("text", { spans: line.length > 0 ? line : [{ t: " " }] }, undefined, `legend-${index}`),
|
|
848
|
+
);
|
|
849
|
+
return row([col(grid), col(legend)], {
|
|
850
|
+
gap: "lg",
|
|
851
|
+
wrap: true,
|
|
852
|
+
role: "omp.context.usage",
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* The `/context` transcript block: ANSI renders the titled cell grid between
|
|
858
|
+
* rules; natively it is one frame, drawn with `meter`s where the terminal
|
|
859
|
+
* has them and as the glyph grid otherwise.
|
|
860
|
+
*/
|
|
861
|
+
export class ContextUsageView extends Container {
|
|
862
|
+
readonly #breakdown: ContextBreakdown;
|
|
863
|
+
#native: { meter: boolean; node: NativeNode } | undefined;
|
|
864
|
+
|
|
865
|
+
constructor(breakdown: ContextBreakdown, theme: Theme) {
|
|
866
|
+
super();
|
|
867
|
+
this.#breakdown = breakdown;
|
|
868
|
+
this.addChild(new DynamicBorder());
|
|
869
|
+
this.addChild(new Text(theme.bold(theme.fg("accent", "Context Usage")), 1, 0));
|
|
870
|
+
this.addChild(new Spacer(1));
|
|
871
|
+
this.addChild(new Text(renderContextUsage(breakdown, theme), 1, 0));
|
|
872
|
+
this.addChild(new DynamicBorder());
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
override describe(cx: DescribeContext): NativeNode {
|
|
876
|
+
const meter = cx.supports("meter");
|
|
877
|
+
if (this.#native?.meter === meter) return this.#native.node;
|
|
878
|
+
const breakdown = this.#breakdown;
|
|
879
|
+
const described =
|
|
880
|
+
breakdown.contextWindow <= 0
|
|
881
|
+
? describeContextUsage(breakdown)
|
|
882
|
+
: meter
|
|
883
|
+
? describeContextFrame(breakdown)
|
|
884
|
+
: card({ role: "omp.context", head: [span("Context usage", "strong")] }, [
|
|
885
|
+
describeContextUsage(breakdown),
|
|
886
|
+
]);
|
|
887
|
+
this.#native = { meter, node: described };
|
|
888
|
+
return described;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
663
892
|
/**
|
|
664
893
|
* Render a colorful context-usage panel as ANSI text. Output is a series of
|
|
665
894
|
* lines pairing the grid (left) with the legend (right).
|
|
@@ -9,7 +9,15 @@ import { shortenPath } from "../render/render-utils";
|
|
|
9
9
|
import { sanitizeStatusText } from "../chrome/shared";
|
|
10
10
|
import { formatMetric } from "../components/metric";
|
|
11
11
|
import { formatBillingSummary } from "./metrics";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
formatContextUsage,
|
|
14
|
+
getContextUsageLevel,
|
|
15
|
+
getContextUsageThemeColor,
|
|
16
|
+
getContextUsageTone,
|
|
17
|
+
} from "../chrome/context-thresholds";
|
|
18
|
+
import type { TspProps, TspSpan } from "@oh-my-pi/pi-wire";
|
|
19
|
+
import type { NativeNode } from "../native/node";
|
|
20
|
+
import { col, node, span } from "../native/describe";
|
|
13
21
|
|
|
14
22
|
/**
|
|
15
23
|
* Footer component that shows pwd, token stats, and context usage
|
|
@@ -23,6 +31,7 @@ export class FooterComponent implements Component {
|
|
|
23
31
|
#disposed = false;
|
|
24
32
|
#autoCompactEnabled: boolean = true;
|
|
25
33
|
#extensionStatuses: Map<string, string> = new Map();
|
|
34
|
+
#nativeMemo: { node: NativeNode; fingerprint: string } | undefined;
|
|
26
35
|
|
|
27
36
|
constructor(
|
|
28
37
|
private readonly session: FooterSession,
|
|
@@ -159,6 +168,90 @@ export class FooterComponent implements Component {
|
|
|
159
168
|
return this.#cachedBranch;
|
|
160
169
|
}
|
|
161
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Native footer: a `status` bar (path and branch, usage counters, billing
|
|
173
|
+
* and context on the left, model on the right) plus the extension statuses.
|
|
174
|
+
* Rebuilt per call from cheap session reads; the node identity holds while
|
|
175
|
+
* the description is unchanged.
|
|
176
|
+
*/
|
|
177
|
+
describe(): NativeNode {
|
|
178
|
+
const state = this.session.state;
|
|
179
|
+
let input = 0;
|
|
180
|
+
let output = 0;
|
|
181
|
+
let cacheRead = 0;
|
|
182
|
+
let cacheWrite = 0;
|
|
183
|
+
let cost = 0;
|
|
184
|
+
let premiumRequests = 0;
|
|
185
|
+
for (const entry of this.session.sessionManager.getEntries()) {
|
|
186
|
+
if (entry.type === "message" && entry.message?.role === "assistant") {
|
|
187
|
+
input += entry.message.usage.input;
|
|
188
|
+
output += entry.message.usage.output;
|
|
189
|
+
cacheRead += entry.message.usage.cacheRead;
|
|
190
|
+
cacheWrite += entry.message.usage.cacheWrite;
|
|
191
|
+
cost += entry.message.usage.cost.total;
|
|
192
|
+
premiumRequests += entry.message.usage.premiumRequests ?? 0;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const segs: NativeNode[] = [];
|
|
196
|
+
const seg = (key: string, props: TspProps<"seg">): void => {
|
|
197
|
+
segs.push(node("seg", { role: `omp.footer.${key}`, ...props }, undefined, key));
|
|
198
|
+
};
|
|
199
|
+
const pathSpans: TspSpan[] = [span(shortenPath(getProjectDir()), "path dim")];
|
|
200
|
+
const branch = this.#getCurrentBranch();
|
|
201
|
+
if (branch) pathSpans.push(span(` (${branch})`, "dim"));
|
|
202
|
+
seg("path", { side: "left", priority: 6, icon: "folder", spans: pathSpans });
|
|
203
|
+
const counters: [string, string, number][] = [
|
|
204
|
+
["input", "↑", input],
|
|
205
|
+
["output", "↓", output],
|
|
206
|
+
["cache-read", "R", cacheRead],
|
|
207
|
+
["cache-write", "W", cacheWrite],
|
|
208
|
+
];
|
|
209
|
+
for (const [key, glyph, amount] of counters) {
|
|
210
|
+
if (amount) seg(key, { side: "left", priority: 1, spans: [span(`${glyph}${formatNumber(amount)}`, "dim")] });
|
|
211
|
+
}
|
|
212
|
+
const usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;
|
|
213
|
+
const billing = formatBillingSummary({ cost, usingSubscription, premiumRequests, fractionDigits: 3 }, theme);
|
|
214
|
+
if (billing) seg("cost", { side: "left", priority: 3, spans: [span(billing, "dim")] });
|
|
215
|
+
const contextUsage = this.session.getContextUsage();
|
|
216
|
+
const contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;
|
|
217
|
+
const contextPercent = contextWindow > 0 ? (contextUsage?.percent ?? 0) : null;
|
|
218
|
+
const level =
|
|
219
|
+
contextUsage && contextPercent !== null ? getContextUsageLevel(contextPercent, contextWindow) : "normal";
|
|
220
|
+
const contextSpans: TspSpan[] = [
|
|
221
|
+
span(
|
|
222
|
+
formatContextUsage(contextPercent, contextWindow, contextUsage?.tokens ?? 0),
|
|
223
|
+
getContextUsageThemeColor(level),
|
|
224
|
+
),
|
|
225
|
+
];
|
|
226
|
+
if (this.#autoCompactEnabled && theme.icon.auto) contextSpans.push(span(` ${theme.icon.auto}`, "dim"));
|
|
227
|
+
const contextProps: TspProps<"seg"> = { side: "left", priority: 4, icon: "context", spans: contextSpans };
|
|
228
|
+
const tone = getContextUsageTone(level);
|
|
229
|
+
if (tone) contextProps.tone = tone;
|
|
230
|
+
seg("context", contextProps);
|
|
231
|
+
let model = state.model?.id || "no-model";
|
|
232
|
+
if (state.model?.thinking) {
|
|
233
|
+
const level = this.session.isAutoThinking
|
|
234
|
+
? (this.session.autoResolvedThinkingLevel() ?? `${theme.thinking.autoPending} auto`)
|
|
235
|
+
: (state.thinkingLevel ?? ThinkingLevel.Off);
|
|
236
|
+
model += ` • ${level}`;
|
|
237
|
+
}
|
|
238
|
+
seg("model", { side: "right", priority: 5, icon: "model", spans: [span(model, "dim")] });
|
|
239
|
+
const bar = node("status", { role: "omp.footer" }, segs, "bar");
|
|
240
|
+
const children: NativeNode[] = [bar];
|
|
241
|
+
if (this.#extensionStatuses.size > 0) {
|
|
242
|
+
const statuses = Array.from(this.#extensionStatuses.entries())
|
|
243
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
244
|
+
.map(([, value]) => sanitizeStatusText(value))
|
|
245
|
+
.join(" ");
|
|
246
|
+
children.push(node("text", { text: statuses, wrap: "none", role: "omp.footer.extensions" }, undefined, "ext"));
|
|
247
|
+
}
|
|
248
|
+
const built = children.length === 1 ? bar : col(children, { role: "omp.footer.panel" });
|
|
249
|
+
const fingerprint = JSON.stringify(built);
|
|
250
|
+
if (this.#nativeMemo?.fingerprint === fingerprint) return this.#nativeMemo.node;
|
|
251
|
+
this.#nativeMemo = { node: built, fingerprint };
|
|
252
|
+
return built;
|
|
253
|
+
}
|
|
254
|
+
|
|
162
255
|
render(width: number): readonly string[] {
|
|
163
256
|
const state = this.session.state;
|
|
164
257
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { formatNumber } from "@oh-my-pi/pi-utils";
|
|
1
|
+
import { formatNumber, normalizePremiumRequests } from "@oh-my-pi/pi-utils";
|
|
2
2
|
import type { Theme } from "../theme";
|
|
3
3
|
|
|
4
|
+
export { normalizePremiumRequests } from "@oh-my-pi/pi-utils";
|
|
5
|
+
|
|
4
6
|
/** Inputs whose differences are intentionally preserved between current status segments and the legacy footer. */
|
|
5
7
|
export interface BillingSummaryOptions {
|
|
6
8
|
readonly cost: number;
|
|
@@ -14,11 +16,6 @@ export interface BillingSummaryOptions {
|
|
|
14
16
|
};
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
/** Round premium-request counters without losing legitimate fractional requests. */
|
|
18
|
-
export function normalizePremiumRequests(value: number): number {
|
|
19
|
-
return Math.round((value + Number.EPSILON) * 100) / 100;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
19
|
function formatSpend(amount: number, usingSubscription: boolean, fractionDigits: number, uiTheme: Theme): string {
|
|
23
20
|
const formatted = amount.toFixed(fractionDigits);
|
|
24
21
|
if (!usingSubscription) return `$${formatted}`;
|