@oh-my-pi/pi-tui 18.2.4 → 18.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +43 -0
- package/dist/types/app-keybindings.d.ts +395 -0
- package/dist/types/apps/autoresearch-dashboard.d.ts +43 -0
- package/dist/types/apps/autoresearch-data.d.ts +15 -0
- package/dist/types/apps/cleanse-board.d.ts +66 -0
- package/dist/types/apps/cleanse-picker.d.ts +23 -0
- package/dist/types/apps/debug/log-formatting.d.ts +6 -0
- package/dist/types/apps/debug/log-viewer.d.ts +81 -0
- package/dist/types/apps/debug/protocol-probe.d.ts +42 -0
- package/dist/types/apps/debug/raw-sse-buffer.d.ts +58 -0
- package/dist/types/apps/debug/raw-sse.d.ts +26 -0
- package/dist/types/apps/debug/terminal-info.d.ts +34 -0
- package/dist/types/apps/debug/viewer-frame.d.ts +52 -0
- package/dist/types/apps/git/avatar.d.ts +9 -0
- package/dist/types/apps/git/colors.d.ts +49 -0
- package/dist/types/apps/git/diff-pane.d.ts +188 -0
- package/dist/types/apps/git/git-tui.d.ts +66 -0
- package/dist/types/apps/git/sidebar.d.ts +149 -0
- package/dist/types/apps/git/state.d.ts +117 -0
- package/dist/types/apps/if-bench-board.d.ts +75 -0
- package/dist/types/apps/live-visualizer.d.ts +33 -0
- package/dist/types/apps/ps-data.d.ts +51 -0
- package/dist/types/apps/ps-top.d.ts +33 -0
- package/dist/types/apps/session-picker.d.ts +26 -0
- package/dist/types/apps/setup-model-picker.d.ts +13 -0
- package/dist/types/apps/standalone-picker.d.ts +42 -0
- package/dist/types/autocomplete.d.ts +4 -0
- package/dist/types/chat/advisor-message.d.ts +11 -0
- package/dist/types/chat/assistant-message.d.ts +106 -0
- package/dist/types/chat/background-tan-message.d.ts +9 -0
- package/dist/types/chat/bash-execution.d.ts +47 -0
- package/dist/types/chat/cache-invalidation-marker.d.ts +50 -0
- package/dist/types/chat/chat-transcript-builder.d.ts +50 -0
- package/dist/types/chat/collab-prompt-message.d.ts +10 -0
- package/dist/types/chat/compaction-summary-message.d.ts +54 -0
- package/dist/types/chat/custom-message.d.ts +10 -0
- package/dist/types/chat/display-preferences.d.ts +13 -0
- package/dist/types/chat/eval-execution.d.ts +29 -0
- package/dist/types/chat/execution-shared.d.ts +51 -0
- package/dist/types/chat/extension-types.d.ts +28 -0
- package/dist/types/chat/hook-message.d.ts +10 -0
- package/dist/types/chat/image-loading.d.ts +46 -0
- package/dist/types/chat/late-diagnostics-message.d.ts +21 -0
- package/dist/types/chat/messages.d.ts +189 -0
- package/dist/types/chat/reaction.d.ts +30 -0
- package/dist/types/chat/read-target.d.ts +4 -0
- package/dist/types/chat/read-tool-group.d.ts +67 -0
- package/dist/types/chat/served-model-marker.d.ts +47 -0
- package/dist/types/chat/skill-message.d.ts +33 -0
- package/dist/types/chat/skill-title-input.d.ts +14 -0
- package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +12 -0
- package/dist/types/chat/thinking-display.d.ts +12 -0
- package/dist/types/chat/todo-reminder.d.ts +13 -0
- package/dist/types/chat/tool-execution.d.ts +138 -0
- package/dist/types/chat/transcript-browser.d.ts +93 -0
- package/dist/types/chat/transcript-entry.d.ts +45 -0
- package/dist/types/chat/transcript-outline.d.ts +86 -0
- package/dist/types/chat/transcript-render-helpers.d.ts +92 -0
- package/dist/types/chat/ttsr-notification.d.ts +23 -0
- package/dist/types/chat/user-message.d.ts +52 -0
- package/dist/types/chrome/chat-block.d.ts +64 -0
- package/dist/types/chrome/collab-qrcode.d.ts +28 -0
- package/dist/types/chrome/context-thresholds.d.ts +10 -0
- package/dist/types/chrome/countdown-timer.d.ts +14 -0
- package/dist/types/chrome/diff.d.ts +14 -0
- package/dist/types/chrome/dynamic-border.d.ts +16 -0
- package/dist/types/chrome/error-block.d.ts +17 -0
- package/dist/types/chrome/form-theme.d.ts +3 -0
- package/dist/types/chrome/format.d.ts +12 -0
- package/dist/types/chrome/index.d.ts +20 -0
- package/dist/types/chrome/keybinding-hints.d.ts +40 -0
- package/dist/types/chrome/live-board.d.ts +23 -0
- package/dist/types/chrome/local-date.d.ts +4 -0
- package/dist/types/chrome/message-divider.d.ts +22 -0
- package/dist/types/chrome/message-frame.d.ts +52 -0
- package/dist/types/chrome/message-notice.d.ts +35 -0
- package/dist/types/chrome/overlay-box.d.ts +74 -0
- package/dist/types/chrome/qrcode.d.ts +48 -0
- package/dist/types/chrome/segment-track.d.ts +27 -0
- package/dist/types/chrome/select-list-mouse-routing.d.ts +4 -0
- package/dist/types/chrome/selector-helpers.d.ts +52 -0
- package/dist/types/chrome/shared.d.ts +5 -0
- package/dist/types/chrome/streaming-panel.d.ts +19 -0
- package/dist/types/chrome/tool-activity.d.ts +17 -0
- package/dist/types/chrome/transcript-container.d.ts +129 -0
- package/dist/types/chrome/transcript-status.d.ts +12 -0
- package/dist/types/chrome/visual-truncate.d.ts +19 -0
- package/dist/types/components/disclosure.d.ts +42 -0
- package/dist/types/components/form.d.ts +130 -0
- package/dist/types/components/key-value-list.d.ts +24 -0
- package/dist/types/components/layout/geometry.d.ts +73 -0
- package/dist/types/components/layout/row.d.ts +55 -0
- package/dist/types/components/layout/split-pane.d.ts +80 -0
- package/dist/types/components/layout/stack.d.ts +50 -0
- package/dist/types/components/menu-selection.d.ts +71 -0
- package/dist/types/components/metric.d.ts +44 -0
- package/dist/types/components/progress-bar.d.ts +36 -0
- package/dist/types/components/scroll-view.d.ts +53 -19
- package/dist/types/components/scroll-viewport.d.ts +46 -0
- package/dist/types/components/section.d.ts +19 -0
- package/dist/types/components/select-list.d.ts +46 -2
- package/dist/types/components/settings-list.d.ts +20 -0
- package/dist/types/components/table.d.ts +32 -0
- package/dist/types/components/tree-view.d.ts +130 -0
- package/dist/types/components/wizard-step.d.ts +60 -0
- package/dist/types/hotkeys-markdown.d.ts +7 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/keybinding-matchers.d.ts +35 -0
- package/dist/types/keys.d.ts +2 -2
- package/dist/types/lang-from-path.d.ts +9 -0
- package/dist/types/overlays/advisor-config.d.ts +114 -0
- package/dist/types/overlays/agent-activity.d.ts +41 -0
- package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
- package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
- package/dist/types/overlays/agent-hub-types.d.ts +99 -0
- package/dist/types/overlays/agent-hub.d.ts +126 -0
- package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
- package/dist/types/overlays/agents-hub.d.ts +72 -0
- package/dist/types/overlays/ask-dialog.d.ts +88 -0
- package/dist/types/overlays/bordered-loader.d.ts +11 -0
- package/dist/types/overlays/btw-history-panel.d.ts +29 -0
- package/dist/types/overlays/btw-history.d.ts +17 -0
- package/dist/types/overlays/btw-panel.d.ts +26 -0
- package/dist/types/overlays/cleanse-panel.d.ts +36 -0
- package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
- package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
- package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
- package/dist/types/overlays/copy-selector.d.ts +48 -0
- package/dist/types/overlays/copy-targets.d.ts +63 -0
- package/dist/types/overlays/error-banner.d.ts +13 -0
- package/dist/types/overlays/extensions/display-text.d.ts +10 -0
- package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
- package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
- package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
- package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
- package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
- package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
- package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
- package/dist/types/overlays/extensions/types.d.ts +165 -0
- package/dist/types/overlays/history-search.d.ts +16 -0
- package/dist/types/overlays/hook-editor.d.ts +44 -0
- package/dist/types/overlays/hook-input.d.ts +20 -0
- package/dist/types/overlays/hook-selector.d.ts +71 -0
- package/dist/types/overlays/hub-frame.d.ts +77 -0
- package/dist/types/overlays/login-dialog.d.ts +43 -0
- package/dist/types/overlays/logout-account-selector.d.ts +15 -0
- package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
- package/dist/types/overlays/model-browser.d.ts +213 -0
- package/dist/types/overlays/model-hub.d.ts +72 -0
- package/dist/types/overlays/model-picker.d.ts +74 -0
- package/dist/types/overlays/model-selector.d.ts +52 -0
- package/dist/types/overlays/move-overlay.d.ts +39 -0
- package/dist/types/overlays/oauth-selector.d.ts +41 -0
- package/dist/types/overlays/omfg-panel.d.ts +20 -0
- package/dist/types/overlays/pause-screen.d.ts +43 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
- package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
- package/dist/types/overlays/plan-toc.d.ts +41 -0
- package/dist/types/overlays/plugin-selector.d.ts +28 -0
- package/dist/types/overlays/plugin-settings.d.ts +180 -0
- package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
- package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
- package/dist/types/overlays/rewind-selector.d.ts +61 -0
- package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
- package/dist/types/overlays/session-account-selector.d.ts +24 -0
- package/dist/types/overlays/session-info-overlay.d.ts +17 -0
- package/dist/types/overlays/session-observer-registry.d.ts +77 -0
- package/dist/types/overlays/session-selector.d.ts +131 -0
- package/dist/types/overlays/settings-defs.d.ts +119 -0
- package/dist/types/overlays/settings-selector.d.ts +73 -0
- package/dist/types/overlays/show-images-selector.d.ts +11 -0
- package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
- package/dist/types/overlays/theme-selector.d.ts +12 -0
- package/dist/types/overlays/thinking-selector.d.ts +12 -0
- package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
- package/dist/types/overlays/tree-selector.d.ts +92 -0
- package/dist/types/overlays/usage-dashboard.d.ts +94 -0
- package/dist/types/overlays/usage-display.d.ts +5 -0
- package/dist/types/overlays/usage-row.d.ts +17 -0
- package/dist/types/prompt/attachment-chips.d.ts +19 -0
- package/dist/types/prompt/composer-attachments.d.ts +71 -0
- package/dist/types/prompt/composer-cache.d.ts +37 -0
- package/dist/types/prompt/composer.d.ts +159 -0
- package/dist/types/prompt/custom-editor.d.ts +261 -0
- package/dist/types/prompt/editor-top-gap.d.ts +18 -0
- package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
- package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
- package/dist/types/prompt/gradient-highlight.d.ts +32 -0
- package/dist/types/prompt/image-format.d.ts +4 -0
- package/dist/types/prompt/image-references.d.ts +26 -0
- package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
- package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
- package/dist/types/prompt/macos-spelling.d.ts +44 -0
- package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
- package/dist/types/prompt/magic-keywords.d.ts +26 -0
- package/dist/types/prompt/markdown-prose.d.ts +15 -0
- package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
- package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
- package/dist/types/prompt/orchestrate.d.ts +13 -0
- package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
- package/dist/types/prompt/queue-input.d.ts +8 -0
- package/dist/types/prompt/skill-tokens.d.ts +13 -0
- package/dist/types/prompt/tools-markdown.d.ts +12 -0
- package/dist/types/prompt/ultrathink.d.ts +13 -0
- package/dist/types/prompt/usage-amounts.d.ts +26 -0
- package/dist/types/prompt/video.d.ts +18 -0
- package/dist/types/prompt/welcome.d.ts +83 -0
- package/dist/types/prompt/workflow.d.ts +13 -0
- package/dist/types/render/code-cell.d.ts +51 -0
- package/dist/types/render/file-list.d.ts +22 -0
- package/dist/types/render/hyperlink.d.ts +80 -0
- package/dist/types/render/index.d.ts +16 -0
- package/dist/types/render/output-block.d.ts +54 -0
- package/dist/types/render/output-pane.d.ts +80 -0
- package/dist/types/render/render-utils.d.ts +312 -0
- package/dist/types/render/sixel.d.ts +21 -0
- package/dist/types/render/status-line.d.ts +23 -0
- package/dist/types/render/tool-card.d.ts +71 -0
- package/dist/types/render/tree-list.d.ts +29 -0
- package/dist/types/render/types.d.ts +17 -0
- package/dist/types/render/utils.d.ts +43 -0
- package/dist/types/render/width-aware-text.d.ts +23 -0
- package/dist/types/setup/lazy.d.ts +3 -0
- package/dist/types/setup/scenes/composer.d.ts +3 -0
- package/dist/types/setup/scenes/glyph.d.ts +3 -0
- package/dist/types/setup/scenes/model.d.ts +3 -0
- package/dist/types/setup/scenes/outro.d.ts +2 -0
- package/dist/types/setup/scenes/providers.d.ts +3 -0
- package/dist/types/setup/scenes/sign-in.d.ts +21 -0
- package/dist/types/setup/scenes/splash.d.ts +11 -0
- package/dist/types/setup/scenes/theme.d.ts +3 -0
- package/dist/types/setup/scenes/types.d.ts +110 -0
- package/dist/types/setup/scenes/web-search.d.ts +22 -0
- package/dist/types/setup/setup-version.d.ts +11 -0
- package/dist/types/setup/startup-splash.d.ts +9 -0
- package/dist/types/setup/wizard-overlay.d.ts +16 -0
- package/dist/types/setup/wizard.d.ts +25 -0
- package/dist/types/status-line/component.d.ts +182 -0
- package/dist/types/status-line/context-usage.d.ts +156 -0
- package/dist/types/status-line/footer.d.ts +30 -0
- package/dist/types/status-line/git-utils.d.ts +22 -0
- package/dist/types/status-line/host.d.ts +129 -0
- package/dist/types/status-line/index.d.ts +6 -0
- package/dist/types/status-line/loop.d.ts +18 -0
- package/dist/types/status-line/metrics.d.ts +21 -0
- package/dist/types/status-line/presets.d.ts +3 -0
- package/dist/types/status-line/schema.d.ts +15 -0
- package/dist/types/status-line/segments.d.ts +5 -0
- package/dist/types/status-line/separators.d.ts +3 -0
- package/dist/types/status-line/types.d.ts +236 -0
- package/dist/types/stdin-buffer.d.ts +4 -0
- package/dist/types/theme/color.d.ts +24 -0
- package/dist/types/theme/defaults/index.d.ts +9489 -0
- package/dist/types/theme/index.d.ts +4 -0
- package/dist/types/theme/loader.d.ts +23 -0
- package/dist/types/theme/mermaid-cache.d.ts +26 -0
- package/dist/types/theme/schema-validation.d.ts +3 -0
- package/dist/types/theme/schema.d.ts +25 -0
- package/dist/types/theme/session-color.d.ts +43 -0
- package/dist/types/theme/shimmer.d.ts +44 -0
- package/dist/types/theme/symbols.d.ts +34 -0
- package/dist/types/theme/theme-class.d.ts +299 -0
- package/dist/types/theme/theme.d.ts +111 -0
- package/dist/types/theme/tui-adapters.d.ts +30 -0
- package/dist/types/thinking.d.ts +165 -0
- package/dist/types/tools/agent-tree.d.ts +36 -0
- package/dist/types/tools/ask.d.ts +67 -0
- package/dist/types/tools/ast-edit.d.ts +53 -0
- package/dist/types/tools/ast-grep.d.ts +52 -0
- package/dist/types/tools/autoresearch.d.ts +156 -0
- package/dist/types/tools/bash-interactive.d.ts +28 -0
- package/dist/types/tools/bash.d.ts +103 -0
- package/dist/types/tools/conflict-detect.d.ts +43 -0
- package/dist/types/tools/debug.d.ts +60 -0
- package/dist/types/tools/default-renderer.d.ts +24 -0
- package/dist/types/tools/edit.d.ts +158 -0
- package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
- package/dist/types/tools/eval-format/index.d.ts +5 -0
- package/dist/types/tools/eval-format/javascript.d.ts +2 -0
- package/dist/types/tools/eval-format/python.d.ts +2 -0
- package/dist/types/tools/eval.d.ts +94 -0
- package/dist/types/tools/fetch.d.ts +42 -0
- package/dist/types/tools/gh-format.d.ts +8 -0
- package/dist/types/tools/github.d.ts +144 -0
- package/dist/types/tools/glob.d.ts +44 -0
- package/dist/types/tools/goal.d.ts +42 -0
- package/dist/types/tools/grep.d.ts +64 -0
- package/dist/types/tools/grouped-file-output.d.ts +71 -0
- package/dist/types/tools/hashline-format.d.ts +28 -0
- package/dist/types/tools/hub.d.ts +340 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/json-tree.d.ts +59 -0
- package/dist/types/tools/line-ranges.d.ts +29 -0
- package/dist/types/tools/list-limit.d.ts +15 -0
- package/dist/types/tools/lsp.d.ts +72 -0
- package/dist/types/tools/match-line-format.d.ts +11 -0
- package/dist/types/tools/mcp.d.ts +81 -0
- package/dist/types/tools/memory.d.ts +67 -0
- package/dist/types/tools/output-meta.d.ts +151 -0
- package/dist/types/tools/read.d.ts +139 -0
- package/dist/types/tools/renderer.d.ts +98 -0
- package/dist/types/tools/report-tool-issue.d.ts +8 -0
- package/dist/types/tools/resolve.d.ts +47 -0
- package/dist/types/tools/streaming-output.d.ts +282 -0
- package/dist/types/tools/subprocess.d.ts +24 -0
- package/dist/types/tools/task-repair-args.d.ts +53 -0
- package/dist/types/tools/task-yield-assembly.d.ts +20 -0
- package/dist/types/tools/task.d.ts +425 -0
- package/dist/types/tools/terminal-output.d.ts +8 -0
- package/dist/types/tools/think.d.ts +13 -0
- package/dist/types/tools/todo.d.ts +118 -0
- package/dist/types/tools/tool-errors.d.ts +7 -0
- package/dist/types/tools/vibe.d.ts +120 -0
- package/dist/types/tools/web-search.d.ts +195 -0
- package/dist/types/tools/write.d.ts +76 -0
- package/dist/types/tools/xd-url.d.ts +13 -0
- package/dist/types/tools/xdev.d.ts +52 -0
- package/dist/types/tui.d.ts +18 -0
- package/dist/types/utils.d.ts +2 -0
- package/package.json +37 -3
- package/src/app-keybindings.ts +760 -0
- package/src/apps/autoresearch-dashboard.ts +500 -0
- package/src/apps/autoresearch-data.ts +64 -0
- package/src/apps/cleanse-board.ts +341 -0
- package/src/apps/cleanse-picker.ts +57 -0
- package/src/apps/debug/log-formatting.ts +53 -0
- package/src/apps/debug/log-viewer.ts +868 -0
- package/src/apps/debug/protocol-probe.ts +267 -0
- package/src/apps/debug/raw-sse-buffer.ts +449 -0
- package/src/apps/debug/raw-sse.ts +282 -0
- package/src/apps/debug/terminal-info.ts +115 -0
- package/src/apps/debug/viewer-frame.ts +174 -0
- package/src/apps/git/avatar.ts +52 -0
- package/src/apps/git/colors.ts +109 -0
- package/src/apps/git/diff-pane.ts +1512 -0
- package/src/apps/git/git-tui.ts +889 -0
- package/src/apps/git/sidebar.ts +1204 -0
- package/src/apps/git/state.ts +113 -0
- package/src/apps/if-bench-board.ts +324 -0
- package/src/apps/live-visualizer.ts +238 -0
- package/src/apps/ps-data.ts +116 -0
- package/src/apps/ps-top.ts +422 -0
- package/src/apps/session-picker.ts +95 -0
- package/src/apps/setup-model-picker.ts +21 -0
- package/src/apps/standalone-picker.ts +111 -0
- package/src/autocomplete.ts +9 -13
- package/src/chat/advisor-message.ts +175 -0
- package/src/chat/assistant-message.ts +1214 -0
- package/src/chat/background-tan-message.ts +35 -0
- package/src/chat/bash-execution.ts +394 -0
- package/src/chat/cache-invalidation-marker.ts +94 -0
- package/src/chat/chat-transcript-builder.ts +593 -0
- package/src/chat/collab-prompt-message.ts +34 -0
- package/src/chat/compaction-summary-message.ts +261 -0
- package/src/chat/custom-message.ts +23 -0
- package/src/chat/display-preferences.ts +24 -0
- package/src/chat/eval-execution.ts +172 -0
- package/src/chat/execution-shared.ts +113 -0
- package/src/chat/extension-types.ts +46 -0
- package/src/chat/hook-message.ts +20 -0
- package/src/chat/image-loading.ts +122 -0
- package/src/chat/late-diagnostics-message.ts +92 -0
- package/src/chat/messages.ts +305 -0
- package/src/chat/reaction.ts +65 -0
- package/src/chat/read-target.ts +7 -0
- package/src/chat/read-tool-group.ts +873 -0
- package/src/chat/served-model-marker.ts +91 -0
- package/src/chat/skill-message.ts +220 -0
- package/src/chat/skill-title-input.ts +41 -0
- package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
- package/src/chat/thinking-display.ts +312 -0
- package/src/chat/todo-reminder.ts +33 -0
- package/src/chat/tool-execution.ts +1395 -0
- package/src/chat/transcript-browser.ts +268 -0
- package/src/chat/transcript-entry.ts +96 -0
- package/src/chat/transcript-outline.ts +260 -0
- package/src/chat/transcript-render-helpers.ts +315 -0
- package/src/chat/ttsr-notification.ts +123 -0
- package/src/chat/user-message.ts +287 -0
- package/src/chrome/chat-block.ts +110 -0
- package/src/chrome/collab-qrcode.ts +74 -0
- package/src/chrome/context-thresholds.ts +85 -0
- package/src/chrome/countdown-timer.ts +74 -0
- package/src/chrome/diff.ts +266 -0
- package/src/chrome/dynamic-border.ts +36 -0
- package/src/chrome/error-block.ts +63 -0
- package/src/chrome/form-theme.ts +10 -0
- package/src/chrome/format.ts +66 -0
- package/src/chrome/index.ts +21 -0
- package/src/chrome/keybinding-hints.ts +55 -0
- package/src/chrome/live-board.ts +123 -0
- package/src/chrome/local-date.ts +20 -0
- package/src/chrome/message-divider.ts +51 -0
- package/src/chrome/message-frame.ts +164 -0
- package/src/chrome/message-notice.ts +103 -0
- package/src/chrome/overlay-box.ts +301 -0
- package/src/chrome/qrcode.ts +539 -0
- package/src/chrome/segment-track.ts +86 -0
- package/src/chrome/select-list-mouse-routing.ts +11 -0
- package/src/chrome/selector-helpers.ts +119 -0
- package/src/chrome/shared.ts +27 -0
- package/src/chrome/streaming-panel.ts +72 -0
- package/src/chrome/tool-activity.ts +44 -0
- package/src/chrome/transcript-container.ts +902 -0
- package/src/chrome/transcript-status.ts +27 -0
- package/src/chrome/visual-truncate.ts +70 -0
- package/src/components/disclosure.ts +235 -0
- package/src/components/editor.ts +10 -12
- package/src/components/form.ts +566 -0
- package/src/components/input.ts +6 -27
- package/src/components/key-value-list.ts +88 -0
- package/src/components/layout/geometry.ts +202 -0
- package/src/components/layout/row.ts +283 -0
- package/src/components/layout/split-pane.ts +349 -0
- package/src/components/layout/stack.ts +261 -0
- package/src/components/markdown.ts +16 -12
- package/src/components/menu-selection.ts +248 -0
- package/src/components/metric.ts +132 -0
- package/src/components/progress-bar.ts +140 -0
- package/src/components/scroll-view.ts +372 -70
- package/src/components/scroll-viewport.ts +154 -0
- package/src/components/section.ts +77 -0
- package/src/components/select-list.ts +238 -159
- package/src/components/settings-list.ts +103 -80
- package/src/components/table.ts +127 -0
- package/src/components/tree-view.ts +481 -0
- package/src/components/wizard-step.ts +229 -0
- package/src/deccara.ts +1 -3
- package/src/hotkeys-markdown.ts +100 -0
- package/src/index.ts +18 -0
- package/src/keybinding-matchers.ts +99 -0
- package/src/keys.ts +2 -2
- package/src/lang-from-path.ts +252 -0
- package/src/overlays/advisor-config.ts +761 -0
- package/src/overlays/agent-activity.ts +113 -0
- package/src/overlays/agent-hub-projection.ts +250 -0
- package/src/overlays/agent-hub-renderer.ts +281 -0
- package/src/overlays/agent-hub-types.ts +74 -0
- package/src/overlays/agent-hub.ts +1562 -0
- package/src/overlays/agent-transcript-viewer.ts +669 -0
- package/src/overlays/agents-hub.ts +1203 -0
- package/src/overlays/ask-dialog.ts +1202 -0
- package/src/overlays/bordered-loader.ts +41 -0
- package/src/overlays/btw-history-panel.ts +591 -0
- package/src/overlays/btw-history.ts +33 -0
- package/src/overlays/btw-panel.ts +167 -0
- package/src/overlays/cleanse-panel.ts +167 -0
- package/src/overlays/codex-reset-fireworks.ts +375 -0
- package/src/overlays/composer-shape-preview.ts +137 -0
- package/src/overlays/composer-shape-registry.ts +82 -0
- package/src/overlays/copy-selector.ts +618 -0
- package/src/overlays/copy-targets.ts +210 -0
- package/src/overlays/error-banner.ts +39 -0
- package/src/overlays/extensions/display-text.ts +39 -0
- package/src/overlays/extensions/extension-dashboard.ts +645 -0
- package/src/overlays/extensions/extension-list.ts +667 -0
- package/src/overlays/extensions/inspector-model.ts +484 -0
- package/src/overlays/extensions/inspector-panel.ts +669 -0
- package/src/overlays/extensions/live-tool-session.ts +67 -0
- package/src/overlays/extensions/mcp-runtime.ts +289 -0
- package/src/overlays/extensions/state-manager.ts +337 -0
- package/src/overlays/extensions/types.ts +208 -0
- package/src/overlays/history-search.ts +268 -0
- package/src/overlays/hook-editor.ts +272 -0
- package/src/overlays/hook-input.ts +84 -0
- package/src/overlays/hook-selector.ts +635 -0
- package/src/overlays/hub-frame.ts +262 -0
- package/src/overlays/login-dialog.ts +231 -0
- package/src/overlays/logout-account-selector.ts +115 -0
- package/src/overlays/mcp-add-wizard.ts +1436 -0
- package/src/overlays/model-browser.ts +1176 -0
- package/src/overlays/model-hub.ts +2279 -0
- package/src/overlays/model-picker.ts +285 -0
- package/src/overlays/model-selector.ts +107 -0
- package/src/overlays/move-overlay.ts +197 -0
- package/src/overlays/oauth-selector.ts +446 -0
- package/src/overlays/omfg-panel.ts +136 -0
- package/src/overlays/pause-screen.ts +198 -0
- package/src/overlays/plan-review-overlay.ts +1227 -0
- package/src/overlays/plan-save-overlay.ts +74 -0
- package/src/overlays/plan-toc.ts +139 -0
- package/src/overlays/plugin-selector.ts +97 -0
- package/src/overlays/plugin-settings.ts +839 -0
- package/src/overlays/queue-mode-selector.ts +55 -0
- package/src/overlays/reset-usage-selector.ts +170 -0
- package/src/overlays/rewind-selector.ts +499 -0
- package/src/overlays/running-subagent-badge.ts +19 -0
- package/src/overlays/session-account-selector.ts +68 -0
- package/src/overlays/session-info-overlay.ts +96 -0
- package/src/overlays/session-observer-registry.ts +289 -0
- package/src/overlays/session-selector.ts +1137 -0
- package/src/overlays/settings-defs.ts +315 -0
- package/src/overlays/settings-selector.ts +1415 -0
- package/src/overlays/show-images-selector.ts +44 -0
- package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
- package/src/overlays/snapcompact-shape-preview.ts +192 -0
- package/src/overlays/theme-selector.ts +62 -0
- package/src/overlays/thinking-selector.ts +51 -0
- package/src/overlays/tiny-title-download-progress.ts +102 -0
- package/src/overlays/tree-selector.ts +1121 -0
- package/src/overlays/usage-dashboard.ts +629 -0
- package/src/overlays/usage-display.ts +45 -0
- package/src/overlays/usage-row.ts +118 -0
- package/src/prompt/attachment-chips.ts +201 -0
- package/src/prompt/composer-attachments.ts +280 -0
- package/src/prompt/composer-cache.ts +304 -0
- package/src/prompt/composer.ts +934 -0
- package/src/prompt/custom-editor.ts +1392 -0
- package/src/prompt/data/emojis.json +1 -0
- package/src/prompt/editor-top-gap.ts +28 -0
- package/src/prompt/emoji-autocomplete.ts +285 -0
- package/src/prompt/github-ref-autocomplete.ts +75 -0
- package/src/prompt/gradient-highlight.ts +101 -0
- package/src/prompt/image-format.ts +28 -0
- package/src/prompt/image-references.ts +102 -0
- package/src/prompt/interactive-context-helpers.ts +126 -0
- package/src/prompt/internal-url-autocomplete.ts +155 -0
- package/src/prompt/macos-spelling.ts +456 -0
- package/src/prompt/magic-keyword-boundary.ts +23 -0
- package/src/prompt/magic-keywords.ts +42 -0
- package/src/prompt/markdown-prose.ts +245 -0
- package/src/prompt/model-mention-autocomplete.ts +94 -0
- package/src/prompt/model-mention-syntax.ts +41 -0
- package/src/prompt/orchestrate.ts +26 -0
- package/src/prompt/prompt-action-autocomplete.ts +337 -0
- package/src/prompt/queue-input.ts +132 -0
- package/src/prompt/skill-tokens.ts +36 -0
- package/src/prompt/tips.txt +27 -0
- package/src/prompt/tools-markdown.ts +29 -0
- package/src/prompt/ultrathink.ts +26 -0
- package/src/prompt/usage-amounts.ts +99 -0
- package/src/prompt/video.ts +47 -0
- package/src/prompt/welcome.ts +605 -0
- package/src/prompt/workflow.ts +26 -0
- package/src/render/code-cell.ts +244 -0
- package/src/render/file-list.ts +58 -0
- package/src/render/hyperlink.ts +192 -0
- package/src/render/index.ts +17 -0
- package/src/render/output-block.ts +267 -0
- package/src/render/output-pane.ts +299 -0
- package/src/render/render-utils.ts +1182 -0
- package/src/render/sixel.ts +69 -0
- package/src/render/status-line.ts +55 -0
- package/src/render/tool-card.ts +272 -0
- package/src/render/tree-list.ts +188 -0
- package/src/render/types.ts +19 -0
- package/src/render/utils.ts +109 -0
- package/src/render/width-aware-text.ts +60 -0
- package/src/setup/lazy.ts +17 -0
- package/src/setup/scenes/composer.ts +127 -0
- package/src/setup/scenes/glyph.ts +120 -0
- package/src/setup/scenes/model.ts +138 -0
- package/src/setup/scenes/outro.ts +24 -0
- package/src/setup/scenes/providers.ts +107 -0
- package/src/setup/scenes/sign-in.ts +373 -0
- package/src/setup/scenes/splash.ts +192 -0
- package/src/setup/scenes/theme.ts +343 -0
- package/src/setup/scenes/types.ts +111 -0
- package/src/setup/scenes/web-search.ts +165 -0
- package/src/setup/setup-version.ts +11 -0
- package/src/setup/startup-splash.ts +107 -0
- package/src/setup/wizard-overlay.ts +319 -0
- package/src/setup/wizard.ts +101 -0
- package/src/status-line/component.ts +3003 -0
- package/src/status-line/context-usage.ts +688 -0
- package/src/status-line/footer.ts +323 -0
- package/src/status-line/git-utils.ts +42 -0
- package/src/status-line/host.ts +97 -0
- package/src/status-line/index.ts +6 -0
- package/src/status-line/loop.ts +28 -0
- package/src/status-line/metrics.ts +94 -0
- package/src/status-line/presets.ts +107 -0
- package/src/status-line/schema.ts +57 -0
- package/src/status-line/segments.ts +934 -0
- package/src/status-line/separators.ts +55 -0
- package/src/status-line/types.ts +227 -0
- package/src/stdin-buffer.ts +4 -2
- package/src/theme/color.ts +95 -0
- package/src/theme/dark.json +95 -0
- package/src/theme/defaults/alabaster.json +93 -0
- package/src/theme/defaults/amethyst.json +96 -0
- package/src/theme/defaults/anthracite.json +93 -0
- package/src/theme/defaults/basalt.json +91 -0
- package/src/theme/defaults/birch.json +95 -0
- package/src/theme/defaults/dark-abyss.json +91 -0
- package/src/theme/defaults/dark-arctic.json +104 -0
- package/src/theme/defaults/dark-aurora.json +95 -0
- package/src/theme/defaults/dark-catppuccin.json +107 -0
- package/src/theme/defaults/dark-cavern.json +91 -0
- package/src/theme/defaults/dark-celestial.json +106 -0
- package/src/theme/defaults/dark-copper.json +95 -0
- package/src/theme/defaults/dark-cosmos.json +90 -0
- package/src/theme/defaults/dark-cyberpunk.json +102 -0
- package/src/theme/defaults/dark-dracula.json +98 -0
- package/src/theme/defaults/dark-eclipse.json +91 -0
- package/src/theme/defaults/dark-ember.json +95 -0
- package/src/theme/defaults/dark-equinox.json +90 -0
- package/src/theme/defaults/dark-forest.json +96 -0
- package/src/theme/defaults/dark-github.json +105 -0
- package/src/theme/defaults/dark-gruvbox.json +112 -0
- package/src/theme/defaults/dark-lavender.json +95 -0
- package/src/theme/defaults/dark-lunar.json +89 -0
- package/src/theme/defaults/dark-midnight.json +95 -0
- package/src/theme/defaults/dark-monochrome.json +94 -0
- package/src/theme/defaults/dark-monokai.json +98 -0
- package/src/theme/defaults/dark-nebula.json +90 -0
- package/src/theme/defaults/dark-nord.json +98 -0
- package/src/theme/defaults/dark-ocean.json +101 -0
- package/src/theme/defaults/dark-one.json +100 -0
- package/src/theme/defaults/dark-poimandres.json +115 -0
- package/src/theme/defaults/dark-rainforest.json +91 -0
- package/src/theme/defaults/dark-reef.json +91 -0
- package/src/theme/defaults/dark-retro.json +92 -0
- package/src/theme/defaults/dark-rose-pine.json +96 -0
- package/src/theme/defaults/dark-sakura.json +95 -0
- package/src/theme/defaults/dark-slate.json +95 -0
- package/src/theme/defaults/dark-solarized.json +97 -0
- package/src/theme/defaults/dark-solstice.json +90 -0
- package/src/theme/defaults/dark-starfall.json +91 -0
- package/src/theme/defaults/dark-sunset.json +99 -0
- package/src/theme/defaults/dark-swamp.json +90 -0
- package/src/theme/defaults/dark-synthwave.json +103 -0
- package/src/theme/defaults/dark-taiga.json +91 -0
- package/src/theme/defaults/dark-terminal.json +95 -0
- package/src/theme/defaults/dark-tokyo-night.json +101 -0
- package/src/theme/defaults/dark-tundra.json +91 -0
- package/src/theme/defaults/dark-twilight.json +91 -0
- package/src/theme/defaults/dark-volcanic.json +91 -0
- package/src/theme/defaults/graphite.json +92 -0
- package/src/theme/defaults/index.ts +201 -0
- package/src/theme/defaults/light-arctic.json +107 -0
- package/src/theme/defaults/light-aurora-day.json +91 -0
- package/src/theme/defaults/light-canyon.json +91 -0
- package/src/theme/defaults/light-catppuccin.json +106 -0
- package/src/theme/defaults/light-cirrus.json +90 -0
- package/src/theme/defaults/light-coral.json +95 -0
- package/src/theme/defaults/light-cyberpunk.json +96 -0
- package/src/theme/defaults/light-dawn.json +90 -0
- package/src/theme/defaults/light-dunes.json +91 -0
- package/src/theme/defaults/light-eucalyptus.json +95 -0
- package/src/theme/defaults/light-forest.json +100 -0
- package/src/theme/defaults/light-frost.json +95 -0
- package/src/theme/defaults/light-github.json +115 -0
- package/src/theme/defaults/light-glacier.json +91 -0
- package/src/theme/defaults/light-gruvbox.json +108 -0
- package/src/theme/defaults/light-haze.json +90 -0
- package/src/theme/defaults/light-honeycomb.json +95 -0
- package/src/theme/defaults/light-lagoon.json +91 -0
- package/src/theme/defaults/light-lavender.json +95 -0
- package/src/theme/defaults/light-meadow.json +91 -0
- package/src/theme/defaults/light-mint.json +95 -0
- package/src/theme/defaults/light-monochrome.json +101 -0
- package/src/theme/defaults/light-ocean.json +99 -0
- package/src/theme/defaults/light-one.json +99 -0
- package/src/theme/defaults/light-opal.json +91 -0
- package/src/theme/defaults/light-orchard.json +91 -0
- package/src/theme/defaults/light-paper.json +95 -0
- package/src/theme/defaults/light-poimandres.json +115 -0
- package/src/theme/defaults/light-prism.json +90 -0
- package/src/theme/defaults/light-retro.json +98 -0
- package/src/theme/defaults/light-sand.json +95 -0
- package/src/theme/defaults/light-savanna.json +91 -0
- package/src/theme/defaults/light-solarized.json +102 -0
- package/src/theme/defaults/light-soleil.json +90 -0
- package/src/theme/defaults/light-sunset.json +99 -0
- package/src/theme/defaults/light-synthwave.json +98 -0
- package/src/theme/defaults/light-tokyo-night.json +111 -0
- package/src/theme/defaults/light-wetland.json +91 -0
- package/src/theme/defaults/light-zenith.json +89 -0
- package/src/theme/defaults/limestone.json +94 -0
- package/src/theme/defaults/mahogany.json +97 -0
- package/src/theme/defaults/marble.json +93 -0
- package/src/theme/defaults/obsidian.json +91 -0
- package/src/theme/defaults/onyx.json +91 -0
- package/src/theme/defaults/pearl.json +93 -0
- package/src/theme/defaults/porcelain.json +91 -0
- package/src/theme/defaults/quartz.json +96 -0
- package/src/theme/defaults/sandstone.json +95 -0
- package/src/theme/defaults/titanium.json +90 -0
- package/src/theme/index.ts +5 -0
- package/src/theme/light.json +93 -0
- package/src/theme/loader.ts +200 -0
- package/src/theme/mermaid-cache.ts +92 -0
- package/src/theme/schema-validation.ts +119 -0
- package/src/theme/schema.ts +168 -0
- package/src/theme/session-color.ts +253 -0
- package/src/theme/shimmer.ts +307 -0
- package/src/theme/symbols.ts +1433 -0
- package/src/theme/theme-class.ts +787 -0
- package/src/theme/theme-schema.json +463 -0
- package/src/theme/theme.ts +810 -0
- package/src/theme/tui-adapters.ts +339 -0
- package/src/thinking.ts +380 -0
- package/src/tools/agent-tree.ts +128 -0
- package/src/tools/ask.ts +482 -0
- package/src/tools/ast-edit.ts +210 -0
- package/src/tools/ast-grep.ts +171 -0
- package/src/tools/autoresearch.ts +287 -0
- package/src/tools/bash-interactive.ts +295 -0
- package/src/tools/bash.ts +468 -0
- package/src/tools/conflict-detect.ts +77 -0
- package/src/tools/debug.ts +167 -0
- package/src/tools/default-renderer.ts +172 -0
- package/src/tools/edit.ts +1258 -0
- package/src/tools/eval-format/code-mode-declarations.ts +61 -0
- package/src/tools/eval-format/index.ts +16 -0
- package/src/tools/eval-format/javascript.ts +952 -0
- package/src/tools/eval-format/python.ts +544 -0
- package/src/tools/eval.ts +835 -0
- package/src/tools/fetch.ts +226 -0
- package/src/tools/gh-format.ts +18 -0
- package/src/tools/github.ts +686 -0
- package/src/tools/glob.ts +213 -0
- package/src/tools/goal.ts +153 -0
- package/src/tools/grep.ts +385 -0
- package/src/tools/grouped-file-output.ts +211 -0
- package/src/tools/hashline-format.ts +59 -0
- package/src/tools/hub.ts +1488 -0
- package/src/tools/index.ts +71 -0
- package/src/tools/json-tree.ts +388 -0
- package/src/tools/line-ranges.ts +98 -0
- package/src/tools/list-limit.ts +43 -0
- package/src/tools/lsp.ts +702 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/mcp.ts +309 -0
- package/src/tools/memory.ts +220 -0
- package/src/tools/output-meta.ts +367 -0
- package/src/tools/read.ts +628 -0
- package/src/tools/renderer.ts +107 -0
- package/src/tools/report-tool-issue.ts +13 -0
- package/src/tools/resolve.ts +139 -0
- package/src/tools/streaming-output.ts +1576 -0
- package/src/tools/subprocess.ts +39 -0
- package/src/tools/task-repair-args.ts +118 -0
- package/src/tools/task-yield-assembly.ts +147 -0
- package/src/tools/task.ts +2110 -0
- package/src/tools/terminal-output.ts +153 -0
- package/src/tools/think.ts +28 -0
- package/src/tools/todo.ts +580 -0
- package/src/tools/tool-errors.ts +15 -0
- package/src/tools/vibe.ts +420 -0
- package/src/tools/web-search.ts +409 -0
- package/src/tools/write.ts +511 -0
- package/src/tools/xd-url.ts +28 -0
- package/src/tools/xdev.ts +201 -0
- package/src/tui.ts +57 -4
- package/src/utils.ts +8 -0
|
@@ -0,0 +1,688 @@
|
|
|
1
|
+
import type { AgentMessage, Tokenizer } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import type { CompactionSettings } from "@oh-my-pi/pi-agent-core/compaction";
|
|
3
|
+
import { effectiveReserveTokens, resolveThresholdTokens } from "@oh-my-pi/pi-agent-core/compaction";
|
|
4
|
+
import type { Tool as AiTool, Model } from "@oh-my-pi/pi-ai";
|
|
5
|
+
import { toolWireSchema } from "@oh-my-pi/pi-ai/utils/schema";
|
|
6
|
+
import { formatNumber } from "@oh-my-pi/pi-utils";
|
|
7
|
+
import type { Theme } from "../theme";
|
|
8
|
+
|
|
9
|
+
interface ContextSkill {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly description?: string;
|
|
12
|
+
readonly hide?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type ContextTool = Pick<AiTool, "name" | "description" | "parameters">;
|
|
16
|
+
|
|
17
|
+
/** Savings computed by the host's inline-image planner, not by the renderer. */
|
|
18
|
+
export interface ContextSavingsEstimate {
|
|
19
|
+
visionCapable: boolean;
|
|
20
|
+
systemPrompt?: {
|
|
21
|
+
applied: boolean;
|
|
22
|
+
reason?: "empty" | "margin" | "budget";
|
|
23
|
+
textTokens: number;
|
|
24
|
+
frames: number;
|
|
25
|
+
imageTokens: number;
|
|
26
|
+
savedTokens: number;
|
|
27
|
+
scope: "agents-md" | "all";
|
|
28
|
+
};
|
|
29
|
+
toolResults?: {
|
|
30
|
+
total: number;
|
|
31
|
+
swapped: number;
|
|
32
|
+
textTokens: number;
|
|
33
|
+
frames: number;
|
|
34
|
+
imageTokens: number;
|
|
35
|
+
savedTokens: number;
|
|
36
|
+
};
|
|
37
|
+
savedTokens: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Real sessions satisfy this view without wrapping or copying their state. */
|
|
41
|
+
export interface ContextUsageSession extends NonMessageTokenSource {
|
|
42
|
+
readonly model: Model | undefined;
|
|
43
|
+
readonly agent: {
|
|
44
|
+
readonly tokenizer: Tokenizer;
|
|
45
|
+
readonly state?: { readonly tools?: readonly ContextTool[] };
|
|
46
|
+
};
|
|
47
|
+
readonly messages?: AgentMessage[];
|
|
48
|
+
getContextBreakdown?():
|
|
49
|
+
| {
|
|
50
|
+
messagesTokens: number;
|
|
51
|
+
skillsTokens: number;
|
|
52
|
+
systemToolsTokens: number;
|
|
53
|
+
systemContextTokens: number;
|
|
54
|
+
systemPromptTokens: number;
|
|
55
|
+
usedTokens: number;
|
|
56
|
+
}
|
|
57
|
+
| undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface ContextUsageOptions {
|
|
61
|
+
compaction: CompactionSettings;
|
|
62
|
+
sourceRevision?: number;
|
|
63
|
+
skillful?: boolean;
|
|
64
|
+
snapcompact?: ContextSavingsEstimate;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const GRID_COLS = 20;
|
|
68
|
+
const GRID_ROWS = 10;
|
|
69
|
+
const GRID_CELLS = GRID_COLS * GRID_ROWS;
|
|
70
|
+
const GRID_GUTTER = " ";
|
|
71
|
+
|
|
72
|
+
const CELL_FILLED = "⛁";
|
|
73
|
+
const CELL_FILLED_MESSAGES = "⛃";
|
|
74
|
+
const CELL_FREE = "⛶";
|
|
75
|
+
const CELL_BUFFER = "⛝";
|
|
76
|
+
|
|
77
|
+
type CategoryId = "systemPrompt" | "systemContext" | "systemTools" | "skills" | "messages";
|
|
78
|
+
|
|
79
|
+
interface CategoryInfo {
|
|
80
|
+
id: CategoryId;
|
|
81
|
+
label: string;
|
|
82
|
+
tokens: number;
|
|
83
|
+
color: "accent" | "warning" | "success" | "userMessageText" | "customMessageLabel";
|
|
84
|
+
glyph: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ContextBreakdown {
|
|
88
|
+
model: Model | undefined;
|
|
89
|
+
contextWindow: number;
|
|
90
|
+
categories: CategoryInfo[];
|
|
91
|
+
usedTokens: number;
|
|
92
|
+
autoCompactBufferTokens: number;
|
|
93
|
+
freeTokens: number;
|
|
94
|
+
/** Estimated snapcompact wire savings; set when requested and a snapcompact.* setting is enabled. */
|
|
95
|
+
snapcompact?: ContextSavingsEstimate;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Percent positions (0–100 of the context window) for the auto-compaction boundaries. */
|
|
99
|
+
export interface CompactionBoundaries {
|
|
100
|
+
/** Where auto-compaction fires. */
|
|
101
|
+
thresholdPercent: number;
|
|
102
|
+
/**
|
|
103
|
+
* Where the background speculative summarizer starts (threshold − lead), or
|
|
104
|
+
* `null` when no speculation will run (async compaction disabled, or the
|
|
105
|
+
* first available method is local — snapcompact/shake — and thus instant).
|
|
106
|
+
*/
|
|
107
|
+
speculationPercent: number | null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Boundary positions for the status line's annotated context gauge. `null`
|
|
112
|
+
* when compaction is disabled/off or the window is unknown — the gauge then
|
|
113
|
+
* renders without markers. The host supplies a lead only when its configured
|
|
114
|
+
* method and async policy allow speculative compaction.
|
|
115
|
+
*/
|
|
116
|
+
export function computeCompactionBoundaries(
|
|
117
|
+
compactionSettings: CompactionSettings,
|
|
118
|
+
contextWindow: number,
|
|
119
|
+
speculationLeadTokens?: number,
|
|
120
|
+
): CompactionBoundaries | null {
|
|
121
|
+
if (!(contextWindow > 0)) return null;
|
|
122
|
+
if (!compactionSettings.enabled || compactionSettings.strategy === "off") return null;
|
|
123
|
+
const thresholdTokens = resolveThresholdTokens(contextWindow, compactionSettings);
|
|
124
|
+
if (!(thresholdTokens > 0) || thresholdTokens > contextWindow) return null;
|
|
125
|
+
return {
|
|
126
|
+
thresholdPercent: (thresholdTokens / contextWindow) * 100,
|
|
127
|
+
speculationPercent:
|
|
128
|
+
speculationLeadTokens === undefined
|
|
129
|
+
? null
|
|
130
|
+
: (Math.max(0, thresholdTokens - speculationLeadTokens) / contextWindow) * 100,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Stable inputs used to cache non-message token estimates. */
|
|
135
|
+
export interface NonMessageTokenSource {
|
|
136
|
+
readonly systemPrompt?: readonly string[];
|
|
137
|
+
readonly agent?: {
|
|
138
|
+
readonly state?: {
|
|
139
|
+
readonly tools?: readonly ContextTool[];
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
readonly skills?: readonly ContextSkill[];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Shared empty system-prompt part list, avoiding an allocation per render. */
|
|
146
|
+
export const EMPTY_STRING_PARTS: string[] = [];
|
|
147
|
+
const EMPTY_TOOLS: readonly ContextTool[] = [];
|
|
148
|
+
const EMPTY_SKILLS: readonly ContextSkill[] = [];
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Skills actually rendered into the system prompt, mirroring the filter in
|
|
152
|
+
* `buildSystemPrompt` (`system-prompt.ts`): the `read` tool must be present so
|
|
153
|
+
* the model can fetch skill content, and skills with frontmatter `hide: true`
|
|
154
|
+
* (or `disable-model-invocation`, normalized onto `hide`) are excluded.
|
|
155
|
+
* Accounting must count only these so the Skills category and the System-prompt
|
|
156
|
+
* subtraction stay aligned with the provider-facing prompt.
|
|
157
|
+
*/
|
|
158
|
+
function renderedSkills(skills: readonly ContextSkill[], tools: readonly ContextTool[]): readonly ContextSkill[] {
|
|
159
|
+
if (!tools.some(tool => tool.name === "read")) return EMPTY_SKILLS;
|
|
160
|
+
return skills.filter(skill => skill.hide !== true);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function estimateSkillsTokens(skills: readonly ContextSkill[], tokenizer: Tokenizer): number {
|
|
164
|
+
const fragments: string[] = [];
|
|
165
|
+
for (const skill of skills) {
|
|
166
|
+
// "- name: description\n" wire framing tokenizes ~identically to the
|
|
167
|
+
// concatenated form, so encode each piece separately and sum.
|
|
168
|
+
fragments.push(skill.name, skill.description ?? "");
|
|
169
|
+
}
|
|
170
|
+
return tokenizer.countTokens(fragments);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
type ToolSchemaSource = readonly ContextTool[];
|
|
174
|
+
|
|
175
|
+
interface ToolSchemaTokenCache {
|
|
176
|
+
revision: number;
|
|
177
|
+
byTokenizer: WeakMap<Tokenizer, { revision: number; sourceRevision: number; tokens: number }>;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Per-roster metadata revisions and token estimates. Tool arrays are
|
|
182
|
+
* caller-owned and may be frozen, so a WeakMap is the only safe place to keep
|
|
183
|
+
* cache state without changing their observable shape.
|
|
184
|
+
*/
|
|
185
|
+
const TOOL_SCHEMA_TOKEN_CACHE = new WeakMap<ToolSchemaSource, ToolSchemaTokenCache>();
|
|
186
|
+
|
|
187
|
+
function toolSchemaTokenCache(tools: ToolSchemaSource): ToolSchemaTokenCache {
|
|
188
|
+
let cache = TOOL_SCHEMA_TOKEN_CACHE.get(tools);
|
|
189
|
+
if (!cache) {
|
|
190
|
+
cache = { revision: 0, byTokenizer: new WeakMap() };
|
|
191
|
+
TOOL_SCHEMA_TOKEN_CACHE.set(tools, cache);
|
|
192
|
+
}
|
|
193
|
+
return cache;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Current dynamic metadata revision for one tool roster.
|
|
198
|
+
*
|
|
199
|
+
* Consumers caching a larger context breakdown must key on both the tools
|
|
200
|
+
* array identity and this revision. Array replacement covers roster changes;
|
|
201
|
+
* {@link invalidateToolSchemaMetadata} covers live description/schema changes
|
|
202
|
+
* while the roster object remains stable.
|
|
203
|
+
*/
|
|
204
|
+
export function getToolSchemaMetadataRevision(tools: ToolSchemaSource): number {
|
|
205
|
+
return TOOL_SCHEMA_TOKEN_CACHE.get(tools)?.revision ?? 0;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Invalidate token estimates after a live tool description or parameter schema
|
|
210
|
+
* can change without replacing the tools array (settings, model, policy, or
|
|
211
|
+
* discovered-agent metadata changes).
|
|
212
|
+
*/
|
|
213
|
+
export function invalidateToolSchemaMetadata(tools: ToolSchemaSource): void {
|
|
214
|
+
toolSchemaTokenCache(tools).revision++;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Estimate provider-visible tool-schema tokens.
|
|
219
|
+
*
|
|
220
|
+
* Results are cached by roster-array identity, tokenizer identity, the
|
|
221
|
+
* caller-supplied settings/source revision, and the roster's explicit dynamic
|
|
222
|
+
* metadata revision. Callers whose descriptions or schemas are live getters
|
|
223
|
+
* must either advance `sourceRevision` or call
|
|
224
|
+
* {@link invalidateToolSchemaMetadata} when those inputs change.
|
|
225
|
+
*/
|
|
226
|
+
export function estimateToolSchemaTokens(tools: ToolSchemaSource, tokenizer: Tokenizer, sourceRevision = 0): number {
|
|
227
|
+
const cache = toolSchemaTokenCache(tools);
|
|
228
|
+
const cached = cache.byTokenizer.get(tokenizer);
|
|
229
|
+
if (cached?.revision === cache.revision && cached.sourceRevision === sourceRevision) return cached.tokens;
|
|
230
|
+
|
|
231
|
+
const fragments: string[] = [];
|
|
232
|
+
for (const tool of tools) {
|
|
233
|
+
// Extension-supplied tools may carry a non-string name/description or a
|
|
234
|
+
// parameters value whose wire schema stringifies to `undefined` (e.g. a
|
|
235
|
+
// callable schema that escaped normalization). A non-string fragment is
|
|
236
|
+
// fatal inside the native tokenizer, so only real strings are counted.
|
|
237
|
+
const name = tool.name;
|
|
238
|
+
const description = tool.description;
|
|
239
|
+
const parameters = tool.parameters;
|
|
240
|
+
if (typeof name === "string") fragments.push(name);
|
|
241
|
+
if (typeof description === "string") fragments.push(description);
|
|
242
|
+
try {
|
|
243
|
+
const wireTool: AiTool = {
|
|
244
|
+
name,
|
|
245
|
+
description,
|
|
246
|
+
parameters: parameters as AiTool["parameters"],
|
|
247
|
+
};
|
|
248
|
+
const wireJson = JSON.stringify(toolWireSchema(wireTool) ?? {});
|
|
249
|
+
if (typeof wireJson === "string") fragments.push(wireJson);
|
|
250
|
+
} catch {
|
|
251
|
+
// Schema may contain functions or cycles; ignore.
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const tokens = tokenizer.countTokens(fragments);
|
|
255
|
+
cache.byTokenizer.set(tokenizer, { revision: cache.revision, sourceRevision, tokens });
|
|
256
|
+
return tokens;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Compute just the NON-MESSAGE token total: system prompt (with its skills
|
|
261
|
+
* section subtracted, since skills are tokenized separately) + system context
|
|
262
|
+
* (the rest of the system-prompt array) + tools + skills.
|
|
263
|
+
*
|
|
264
|
+
* Exposed so callers like `StatusLineComponent` can cache the non-message
|
|
265
|
+
* total separately from the message total. Non-message inputs (skills,
|
|
266
|
+
* tools, system prompt) change rarely; the message list grows on every
|
|
267
|
+
* streaming turn. Splitting the two lets the caller refresh each on its own
|
|
268
|
+
* cadence — non-message recomputed only when the inputs identity changes,
|
|
269
|
+
* messages walked incrementally as new entries append.
|
|
270
|
+
*/
|
|
271
|
+
// Non-message inputs (system prompt, tools, skills) change rarely — at most
|
|
272
|
+
// once per turn via setSystemPrompt/setTools — but the per-turn compaction and
|
|
273
|
+
// threshold paths call these helpers several times: getContextBreakdown calls
|
|
274
|
+
// both, and #estimateStoredContextTokens adds a third. Memoize on the identity
|
|
275
|
+
// of the three input arrays so the expensive parts (system-prompt tokenization
|
|
276
|
+
// and the per-tool JSON.stringify(toolWireSchema) inside estimateToolSchemaTokens)
|
|
277
|
+
// run at most once per input change rather than per call. The identity keys are
|
|
278
|
+
// the same stable references the StatusLineComponent cache already trusts
|
|
279
|
+
// (setSystemPrompt/setTools replace the array reference rather than mutating it).
|
|
280
|
+
interface NonMessageTokenCache {
|
|
281
|
+
systemPromptRef: readonly string[];
|
|
282
|
+
toolsRef: ToolSchemaSource;
|
|
283
|
+
toolsRevision: number;
|
|
284
|
+
sourceRevision: number;
|
|
285
|
+
skillful: boolean;
|
|
286
|
+
skillsRef: readonly ContextSkill[];
|
|
287
|
+
// The Agent swaps its Tokenizer instance when the model's encoding changes,
|
|
288
|
+
// so instance identity doubles as the encoding key.
|
|
289
|
+
tokenizerRef: Tokenizer;
|
|
290
|
+
tokens: number | undefined;
|
|
291
|
+
breakdown:
|
|
292
|
+
| {
|
|
293
|
+
skillsTokens: number;
|
|
294
|
+
toolsTokens: number;
|
|
295
|
+
systemContextTokens: number;
|
|
296
|
+
systemPromptTokens: number;
|
|
297
|
+
}
|
|
298
|
+
| undefined;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const NON_MESSAGE_TOKEN_CACHE = Symbol("non-message-token-cache");
|
|
302
|
+
|
|
303
|
+
interface CachedNonMessageTokenSource extends NonMessageTokenSource {
|
|
304
|
+
[NON_MESSAGE_TOKEN_CACHE]?: NonMessageTokenCache;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function nonMessageTokenCacheEntry(
|
|
308
|
+
session: NonMessageTokenSource,
|
|
309
|
+
tokenizer: Tokenizer,
|
|
310
|
+
sourceRevision: number,
|
|
311
|
+
): NonMessageTokenCache {
|
|
312
|
+
const cachedSession: CachedNonMessageTokenSource = session;
|
|
313
|
+
const systemPromptRef = session.systemPrompt ?? EMPTY_STRING_PARTS;
|
|
314
|
+
const toolsRef = session.agent?.state?.tools ?? EMPTY_TOOLS;
|
|
315
|
+
const toolsRevision = getToolSchemaMetadataRevision(toolsRef);
|
|
316
|
+
const skillsRef = session.skills ?? EMPTY_SKILLS;
|
|
317
|
+
let entry = cachedSession[NON_MESSAGE_TOKEN_CACHE];
|
|
318
|
+
if (
|
|
319
|
+
entry &&
|
|
320
|
+
entry.systemPromptRef === systemPromptRef &&
|
|
321
|
+
entry.toolsRef === toolsRef &&
|
|
322
|
+
entry.toolsRevision === toolsRevision &&
|
|
323
|
+
entry.sourceRevision === sourceRevision &&
|
|
324
|
+
entry.skillsRef === skillsRef &&
|
|
325
|
+
entry.tokenizerRef === tokenizer
|
|
326
|
+
) {
|
|
327
|
+
return entry;
|
|
328
|
+
}
|
|
329
|
+
entry = {
|
|
330
|
+
systemPromptRef,
|
|
331
|
+
toolsRef,
|
|
332
|
+
toolsRevision,
|
|
333
|
+
sourceRevision,
|
|
334
|
+
skillful: true,
|
|
335
|
+
skillsRef,
|
|
336
|
+
tokenizerRef: tokenizer,
|
|
337
|
+
tokens: undefined,
|
|
338
|
+
breakdown: undefined,
|
|
339
|
+
};
|
|
340
|
+
cachedSession[NON_MESSAGE_TOKEN_CACHE] = entry;
|
|
341
|
+
return entry;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export function computeNonMessageTokens(
|
|
345
|
+
session: NonMessageTokenSource,
|
|
346
|
+
tokenizer: Tokenizer,
|
|
347
|
+
sourceRevision = 0,
|
|
348
|
+
): number {
|
|
349
|
+
const entry = nonMessageTokenCacheEntry(session, tokenizer, sourceRevision);
|
|
350
|
+
if (entry.tokens !== undefined) return entry.tokens;
|
|
351
|
+
const systemPromptParts = session.systemPrompt ?? EMPTY_STRING_PARTS;
|
|
352
|
+
const tools = session.agent?.state?.tools ?? EMPTY_TOOLS;
|
|
353
|
+
const tokens =
|
|
354
|
+
tokenizer.countTokens(Array.from(systemPromptParts, part => part ?? "")) +
|
|
355
|
+
estimateToolSchemaTokens(tools, tokenizer, sourceRevision);
|
|
356
|
+
entry.tokens = tokens;
|
|
357
|
+
return tokens;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Shared helper for the four non-message token totals used by
|
|
362
|
+
* `computeContextBreakdown` (/context panel). Keep this category split stable:
|
|
363
|
+
* the status-line fast path intentionally uses the equivalent collapsed total
|
|
364
|
+
* in `computeNonMessageTokens`.
|
|
365
|
+
*/
|
|
366
|
+
export function computeNonMessageBreakdown(
|
|
367
|
+
session: NonMessageTokenSource,
|
|
368
|
+
tokenizer: Tokenizer,
|
|
369
|
+
sourceRevision = 0,
|
|
370
|
+
skillful = true,
|
|
371
|
+
): {
|
|
372
|
+
skillsTokens: number;
|
|
373
|
+
toolsTokens: number;
|
|
374
|
+
systemContextTokens: number;
|
|
375
|
+
systemPromptTokens: number;
|
|
376
|
+
} {
|
|
377
|
+
const entry = nonMessageTokenCacheEntry(session, tokenizer, sourceRevision);
|
|
378
|
+
if (entry.breakdown && entry.skillful === skillful) return entry.breakdown;
|
|
379
|
+
const tools = session.agent?.state?.tools ?? EMPTY_TOOLS;
|
|
380
|
+
const skillsTokens =
|
|
381
|
+
skillful === false ? 0 : estimateSkillsTokens(renderedSkills(session.skills ?? EMPTY_SKILLS, tools), tokenizer);
|
|
382
|
+
const toolsTokens = estimateToolSchemaTokens(tools, tokenizer, sourceRevision);
|
|
383
|
+
const systemPromptParts = session.systemPrompt ?? EMPTY_STRING_PARTS;
|
|
384
|
+
const systemContextTokens = tokenizer.countTokens(Array.from(systemPromptParts.slice(1), part => part ?? ""));
|
|
385
|
+
const systemPromptTokens = Math.max(0, tokenizer.countTokens(systemPromptParts[0] ?? "") - skillsTokens);
|
|
386
|
+
const breakdown = { skillsTokens, toolsTokens, systemContextTokens, systemPromptTokens };
|
|
387
|
+
entry.skillful = skillful;
|
|
388
|
+
entry.breakdown = breakdown;
|
|
389
|
+
return breakdown;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Compute a breakdown of estimated context usage by category for the active
|
|
394
|
+
* session and model.
|
|
395
|
+
*/
|
|
396
|
+
export function computeContextBreakdown(session: ContextUsageSession, options: ContextUsageOptions): ContextBreakdown {
|
|
397
|
+
const model = session.model;
|
|
398
|
+
const tokenizer = session.agent.tokenizer;
|
|
399
|
+
const contextWindow = model?.contextWindow ?? 0;
|
|
400
|
+
|
|
401
|
+
const breakdown = typeof session.getContextBreakdown === "function" ? session.getContextBreakdown() : undefined;
|
|
402
|
+
|
|
403
|
+
let messagesTokens = 0;
|
|
404
|
+
let skillsTokens = 0;
|
|
405
|
+
let toolsTokens = 0;
|
|
406
|
+
let systemContextTokens = 0;
|
|
407
|
+
let systemPromptTokens = 0;
|
|
408
|
+
let usedTokens = 0;
|
|
409
|
+
|
|
410
|
+
if (breakdown) {
|
|
411
|
+
messagesTokens = breakdown.messagesTokens;
|
|
412
|
+
skillsTokens = breakdown.skillsTokens;
|
|
413
|
+
toolsTokens = breakdown.systemToolsTokens;
|
|
414
|
+
systemContextTokens = breakdown.systemContextTokens;
|
|
415
|
+
systemPromptTokens = breakdown.systemPromptTokens;
|
|
416
|
+
usedTokens = breakdown.usedTokens;
|
|
417
|
+
} else {
|
|
418
|
+
// Category split needs a messages-only number, so this walk stays local:
|
|
419
|
+
// an anchored total folds the system prompt and tool schemas into it.
|
|
420
|
+
messagesTokens = tokenizer.countMessages(session.messages ?? []);
|
|
421
|
+
const nonMessage = computeNonMessageBreakdown(session, tokenizer, options.sourceRevision, options.skillful);
|
|
422
|
+
skillsTokens = nonMessage.skillsTokens;
|
|
423
|
+
toolsTokens = nonMessage.toolsTokens;
|
|
424
|
+
systemContextTokens = nonMessage.systemContextTokens;
|
|
425
|
+
systemPromptTokens = nonMessage.systemPromptTokens;
|
|
426
|
+
usedTokens = skillsTokens + toolsTokens + systemContextTokens + systemPromptTokens + messagesTokens;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const categories: CategoryInfo[] = [
|
|
430
|
+
{ id: "systemPrompt", label: "System prompt", tokens: systemPromptTokens, color: "accent", glyph: CELL_FILLED },
|
|
431
|
+
{ id: "systemTools", label: "System tools", tokens: toolsTokens, color: "warning", glyph: CELL_FILLED },
|
|
432
|
+
{
|
|
433
|
+
id: "systemContext",
|
|
434
|
+
label: "System context",
|
|
435
|
+
tokens: systemContextTokens,
|
|
436
|
+
color: "customMessageLabel",
|
|
437
|
+
glyph: CELL_FILLED,
|
|
438
|
+
},
|
|
439
|
+
{ id: "skills", label: "Skills", tokens: skillsTokens, color: "success", glyph: CELL_FILLED },
|
|
440
|
+
{
|
|
441
|
+
id: "messages",
|
|
442
|
+
label: "Messages",
|
|
443
|
+
tokens: messagesTokens,
|
|
444
|
+
color: "userMessageText",
|
|
445
|
+
glyph: CELL_FILLED_MESSAGES,
|
|
446
|
+
},
|
|
447
|
+
];
|
|
448
|
+
|
|
449
|
+
let autoCompactBufferTokens = 0;
|
|
450
|
+
if (contextWindow > 0) {
|
|
451
|
+
const compactionSettings = options.compaction;
|
|
452
|
+
if (compactionSettings.enabled && compactionSettings.strategy !== "off") {
|
|
453
|
+
const threshold = resolveThresholdTokens(contextWindow, compactionSettings);
|
|
454
|
+
autoCompactBufferTokens = Math.max(0, contextWindow - threshold);
|
|
455
|
+
} else {
|
|
456
|
+
autoCompactBufferTokens = 0;
|
|
457
|
+
}
|
|
458
|
+
// Even when fully disabled, fall back to a sensible reserve floor for display.
|
|
459
|
+
if (autoCompactBufferTokens === 0 && compactionSettings.enabled) {
|
|
460
|
+
autoCompactBufferTokens = effectiveReserveTokens(contextWindow, compactionSettings);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
autoCompactBufferTokens = Math.min(autoCompactBufferTokens, Math.max(0, contextWindow - usedTokens));
|
|
464
|
+
|
|
465
|
+
const freeTokens = Math.max(0, contextWindow - usedTokens - autoCompactBufferTokens);
|
|
466
|
+
|
|
467
|
+
return {
|
|
468
|
+
model,
|
|
469
|
+
contextWindow,
|
|
470
|
+
categories,
|
|
471
|
+
usedTokens,
|
|
472
|
+
autoCompactBufferTokens,
|
|
473
|
+
freeTokens,
|
|
474
|
+
snapcompact: options.snapcompact,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
interface CellSpec {
|
|
479
|
+
glyph: string;
|
|
480
|
+
color: "accent" | "warning" | "success" | "userMessageText" | "customMessageLabel" | "muted" | "dim";
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function planCells(breakdown: ContextBreakdown): CellSpec[] {
|
|
484
|
+
const cells: CellSpec[] = [];
|
|
485
|
+
const window = breakdown.contextWindow;
|
|
486
|
+
|
|
487
|
+
if (window <= 0) {
|
|
488
|
+
for (let i = 0; i < GRID_CELLS; i++) {
|
|
489
|
+
cells.push({ glyph: CELL_FREE, color: "dim" });
|
|
490
|
+
}
|
|
491
|
+
return cells;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const tokensPerCell = window / GRID_CELLS;
|
|
495
|
+
|
|
496
|
+
const ratioCells = (tokens: number): number => {
|
|
497
|
+
if (tokens <= 0) return 0;
|
|
498
|
+
return Math.max(1, Math.round(tokens / tokensPerCell));
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
const categoryCounts = breakdown.categories.map(category => ({
|
|
502
|
+
category,
|
|
503
|
+
count: ratioCells(category.tokens),
|
|
504
|
+
}));
|
|
505
|
+
|
|
506
|
+
let bufferCount = ratioCells(breakdown.autoCompactBufferTokens);
|
|
507
|
+
|
|
508
|
+
let usedCount = categoryCounts.reduce((sum, c) => sum + c.count, 0);
|
|
509
|
+
|
|
510
|
+
// Prevent the visualization from over-running the grid.
|
|
511
|
+
const maxUsable = GRID_CELLS - bufferCount;
|
|
512
|
+
if (usedCount > maxUsable) {
|
|
513
|
+
// Scale categories proportionally down to fit.
|
|
514
|
+
let overflow = usedCount - maxUsable;
|
|
515
|
+
// Trim from the largest categories first to preserve visibility for small ones.
|
|
516
|
+
const order = [...categoryCounts].sort((a, b) => b.count - a.count);
|
|
517
|
+
for (const entry of order) {
|
|
518
|
+
while (overflow > 0 && entry.count > 1) {
|
|
519
|
+
entry.count -= 1;
|
|
520
|
+
overflow -= 1;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
usedCount = categoryCounts.reduce((sum, c) => sum + c.count, 0);
|
|
524
|
+
if (usedCount + bufferCount > GRID_CELLS) {
|
|
525
|
+
bufferCount = Math.max(0, GRID_CELLS - usedCount);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
for (const { category, count } of categoryCounts) {
|
|
530
|
+
for (let i = 0; i < count; i++) {
|
|
531
|
+
cells.push({ glyph: category.glyph, color: category.color });
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const freeCount = Math.max(0, GRID_CELLS - cells.length - bufferCount);
|
|
536
|
+
for (let i = 0; i < freeCount; i++) {
|
|
537
|
+
cells.push({ glyph: CELL_FREE, color: "dim" });
|
|
538
|
+
}
|
|
539
|
+
for (let i = 0; i < bufferCount; i++) {
|
|
540
|
+
cells.push({ glyph: CELL_BUFFER, color: "warning" });
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Pad to exactly GRID_CELLS in case rounding undershot.
|
|
544
|
+
while (cells.length < GRID_CELLS) {
|
|
545
|
+
cells.push({ glyph: CELL_FREE, color: "dim" });
|
|
546
|
+
}
|
|
547
|
+
return cells.slice(0, GRID_CELLS);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
function percentString(part: number, whole: number, fractionDigits = 1): string {
|
|
551
|
+
if (whole <= 0) return "0%";
|
|
552
|
+
const pct = (part / whole) * 100;
|
|
553
|
+
if (pct > 0 && pct < 0.05) return "<0.1%";
|
|
554
|
+
return `${pct.toFixed(fractionDigits)}%`;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function buildLegendLines(breakdown: ContextBreakdown, theme: Theme): string[] {
|
|
558
|
+
const lines: string[] = [];
|
|
559
|
+
const { model, contextWindow, categories, usedTokens, autoCompactBufferTokens, freeTokens } = breakdown;
|
|
560
|
+
|
|
561
|
+
const modelName = model?.name ?? model?.id ?? "no model";
|
|
562
|
+
const modelId = model?.id ?? "unknown";
|
|
563
|
+
const windowLabel = formatNumber(contextWindow).toLowerCase();
|
|
564
|
+
|
|
565
|
+
lines.push(theme.bold(`${modelName}`) + theme.fg("dim", ` (${windowLabel} context)`));
|
|
566
|
+
lines.push(theme.fg("muted", `${modelId}[${windowLabel}]`));
|
|
567
|
+
lines.push(
|
|
568
|
+
`${theme.bold(formatNumber(usedTokens))}${theme.fg("dim", `/${windowLabel} tokens`)}` +
|
|
569
|
+
theme.fg("muted", ` (${percentString(usedTokens, contextWindow)})`),
|
|
570
|
+
);
|
|
571
|
+
lines.push("");
|
|
572
|
+
lines.push(theme.fg("muted", "Estimated usage by category"));
|
|
573
|
+
|
|
574
|
+
for (const category of categories) {
|
|
575
|
+
const dot = theme.fg(category.color, category.glyph);
|
|
576
|
+
const label = category.label;
|
|
577
|
+
const tokens = formatNumber(category.tokens);
|
|
578
|
+
const pct = percentString(category.tokens, contextWindow);
|
|
579
|
+
lines.push(`${dot} ${label}: ${theme.bold(tokens)} ${theme.fg("dim", `tokens (${pct})`)}`);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const freeDot = theme.fg("dim", CELL_FREE);
|
|
583
|
+
lines.push(
|
|
584
|
+
`${freeDot} Free space: ${theme.bold(formatNumber(freeTokens))} ${theme.fg("dim", `(${percentString(freeTokens, contextWindow)})`)}`,
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
if (autoCompactBufferTokens > 0) {
|
|
588
|
+
const bufferDot = theme.fg("warning", CELL_BUFFER);
|
|
589
|
+
lines.push(
|
|
590
|
+
`${bufferDot} Autocompact buffer: ${theme.bold(formatNumber(autoCompactBufferTokens))} ${theme.fg(
|
|
591
|
+
"dim",
|
|
592
|
+
`tokens (${percentString(autoCompactBufferTokens, contextWindow)})`,
|
|
593
|
+
)}`,
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
const snap = breakdown.snapcompact;
|
|
598
|
+
if (snap) {
|
|
599
|
+
lines.push("");
|
|
600
|
+
if (!snap.visionCapable) {
|
|
601
|
+
lines.push(theme.fg("muted", "Snapcompact: inactive (model has no image input)"));
|
|
602
|
+
} else {
|
|
603
|
+
lines.push(theme.fg("muted", "Snapcompact (estimated wire savings)"));
|
|
604
|
+
if (snap.systemPrompt) {
|
|
605
|
+
const sp = snap.systemPrompt;
|
|
606
|
+
if (sp.applied) {
|
|
607
|
+
lines.push(
|
|
608
|
+
` System prompt (${sp.scope === "agents-md" ? "AGENTS.md" : "all"}): saves ${theme.bold(`~${formatNumber(sp.savedTokens)}`)} ` +
|
|
609
|
+
theme.fg(
|
|
610
|
+
"dim",
|
|
611
|
+
`(${formatNumber(sp.textTokens)} text → ${sp.frames} frame${sp.frames === 1 ? "" : "s"} ≈ ${formatNumber(sp.imageTokens)})`,
|
|
612
|
+
),
|
|
613
|
+
);
|
|
614
|
+
} else {
|
|
615
|
+
const reason =
|
|
616
|
+
sp.reason === "budget"
|
|
617
|
+
? "image budget exhausted"
|
|
618
|
+
: sp.reason === "empty"
|
|
619
|
+
? "nothing to image"
|
|
620
|
+
: "frames would not save tokens";
|
|
621
|
+
lines.push(
|
|
622
|
+
` System prompt (${sp.scope === "agents-md" ? "AGENTS.md" : "all"}): ${theme.fg("dim", `stays text (${reason})`)}`,
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (snap.toolResults) {
|
|
627
|
+
const tr = snap.toolResults;
|
|
628
|
+
if (tr.swapped > 0) {
|
|
629
|
+
lines.push(
|
|
630
|
+
` Tool results: saves ${theme.bold(`~${formatNumber(tr.savedTokens)}`)} ` +
|
|
631
|
+
theme.fg(
|
|
632
|
+
"dim",
|
|
633
|
+
`(${tr.swapped}/${tr.total} imaged, ${formatNumber(tr.textTokens)} text → ${tr.frames} frames ≈ ${formatNumber(tr.imageTokens)})`,
|
|
634
|
+
),
|
|
635
|
+
);
|
|
636
|
+
} else {
|
|
637
|
+
lines.push(` Tool results: ${theme.fg("dim", `none imaged (${tr.total} in history)`)}`);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
if (snap.savedTokens > 0) {
|
|
641
|
+
lines.push(
|
|
642
|
+
` Next request: ${theme.bold(`~${formatNumber(Math.max(0, usedTokens - snap.savedTokens))}`)} ${theme.fg("dim", "tokens on the wire")}`,
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
return lines;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Render a colorful context-usage panel as ANSI text. Output is a series of
|
|
653
|
+
* lines pairing the grid (left) with the legend (right).
|
|
654
|
+
*/
|
|
655
|
+
export function renderContextUsage(breakdown: ContextBreakdown, theme: Theme): string {
|
|
656
|
+
if (breakdown.contextWindow <= 0) {
|
|
657
|
+
return theme.fg("muted", "Context usage is unavailable: no model is selected for this session.");
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
const cells = planCells(breakdown);
|
|
661
|
+
const legend = buildLegendLines(breakdown, theme);
|
|
662
|
+
|
|
663
|
+
const totalLines = Math.max(GRID_ROWS, legend.length);
|
|
664
|
+
const lines: string[] = [];
|
|
665
|
+
|
|
666
|
+
for (let row = 0; row < totalLines; row++) {
|
|
667
|
+
let gridSegment = "";
|
|
668
|
+
if (row < GRID_ROWS) {
|
|
669
|
+
const rowCells: string[] = [];
|
|
670
|
+
for (let col = 0; col < GRID_COLS; col++) {
|
|
671
|
+
const cell = cells[row * GRID_COLS + col];
|
|
672
|
+
rowCells.push(theme.fg(cell.color, cell.glyph));
|
|
673
|
+
}
|
|
674
|
+
gridSegment = rowCells.join(" ");
|
|
675
|
+
} else {
|
|
676
|
+
// Pad with blanks the same visible width as a grid row so legend lines
|
|
677
|
+
// past the grid stay aligned with their column.
|
|
678
|
+
const blank = " ".repeat(GRID_COLS * 2 - 1);
|
|
679
|
+
gridSegment = blank;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const legendSegment = legend[row] ?? "";
|
|
683
|
+
const line = legendSegment.length > 0 ? `${gridSegment}${GRID_GUTTER}${legendSegment}` : gridSegment;
|
|
684
|
+
lines.push(line);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
return lines.join("\n");
|
|
688
|
+
}
|