@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.
Files changed (748) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +43 -0
  3. package/dist/types/app-keybindings.d.ts +395 -0
  4. package/dist/types/apps/autoresearch-dashboard.d.ts +43 -0
  5. package/dist/types/apps/autoresearch-data.d.ts +15 -0
  6. package/dist/types/apps/cleanse-board.d.ts +66 -0
  7. package/dist/types/apps/cleanse-picker.d.ts +23 -0
  8. package/dist/types/apps/debug/log-formatting.d.ts +6 -0
  9. package/dist/types/apps/debug/log-viewer.d.ts +81 -0
  10. package/dist/types/apps/debug/protocol-probe.d.ts +42 -0
  11. package/dist/types/apps/debug/raw-sse-buffer.d.ts +58 -0
  12. package/dist/types/apps/debug/raw-sse.d.ts +26 -0
  13. package/dist/types/apps/debug/terminal-info.d.ts +34 -0
  14. package/dist/types/apps/debug/viewer-frame.d.ts +52 -0
  15. package/dist/types/apps/git/avatar.d.ts +9 -0
  16. package/dist/types/apps/git/colors.d.ts +49 -0
  17. package/dist/types/apps/git/diff-pane.d.ts +188 -0
  18. package/dist/types/apps/git/git-tui.d.ts +66 -0
  19. package/dist/types/apps/git/sidebar.d.ts +149 -0
  20. package/dist/types/apps/git/state.d.ts +117 -0
  21. package/dist/types/apps/if-bench-board.d.ts +75 -0
  22. package/dist/types/apps/live-visualizer.d.ts +33 -0
  23. package/dist/types/apps/ps-data.d.ts +51 -0
  24. package/dist/types/apps/ps-top.d.ts +33 -0
  25. package/dist/types/apps/session-picker.d.ts +26 -0
  26. package/dist/types/apps/setup-model-picker.d.ts +13 -0
  27. package/dist/types/apps/standalone-picker.d.ts +42 -0
  28. package/dist/types/autocomplete.d.ts +4 -0
  29. package/dist/types/chat/advisor-message.d.ts +11 -0
  30. package/dist/types/chat/assistant-message.d.ts +106 -0
  31. package/dist/types/chat/background-tan-message.d.ts +9 -0
  32. package/dist/types/chat/bash-execution.d.ts +47 -0
  33. package/dist/types/chat/cache-invalidation-marker.d.ts +50 -0
  34. package/dist/types/chat/chat-transcript-builder.d.ts +50 -0
  35. package/dist/types/chat/collab-prompt-message.d.ts +10 -0
  36. package/dist/types/chat/compaction-summary-message.d.ts +54 -0
  37. package/dist/types/chat/custom-message.d.ts +10 -0
  38. package/dist/types/chat/display-preferences.d.ts +13 -0
  39. package/dist/types/chat/eval-execution.d.ts +29 -0
  40. package/dist/types/chat/execution-shared.d.ts +51 -0
  41. package/dist/types/chat/extension-types.d.ts +28 -0
  42. package/dist/types/chat/hook-message.d.ts +10 -0
  43. package/dist/types/chat/image-loading.d.ts +46 -0
  44. package/dist/types/chat/late-diagnostics-message.d.ts +21 -0
  45. package/dist/types/chat/messages.d.ts +189 -0
  46. package/dist/types/chat/reaction.d.ts +30 -0
  47. package/dist/types/chat/read-target.d.ts +4 -0
  48. package/dist/types/chat/read-tool-group.d.ts +67 -0
  49. package/dist/types/chat/served-model-marker.d.ts +47 -0
  50. package/dist/types/chat/skill-message.d.ts +33 -0
  51. package/dist/types/chat/skill-title-input.d.ts +14 -0
  52. package/dist/types/chat/stripped-tool-calls-placeholder.d.ts +12 -0
  53. package/dist/types/chat/thinking-display.d.ts +12 -0
  54. package/dist/types/chat/todo-reminder.d.ts +13 -0
  55. package/dist/types/chat/tool-execution.d.ts +138 -0
  56. package/dist/types/chat/transcript-browser.d.ts +93 -0
  57. package/dist/types/chat/transcript-entry.d.ts +45 -0
  58. package/dist/types/chat/transcript-outline.d.ts +86 -0
  59. package/dist/types/chat/transcript-render-helpers.d.ts +92 -0
  60. package/dist/types/chat/ttsr-notification.d.ts +23 -0
  61. package/dist/types/chat/user-message.d.ts +52 -0
  62. package/dist/types/chrome/chat-block.d.ts +64 -0
  63. package/dist/types/chrome/collab-qrcode.d.ts +28 -0
  64. package/dist/types/chrome/context-thresholds.d.ts +10 -0
  65. package/dist/types/chrome/countdown-timer.d.ts +14 -0
  66. package/dist/types/chrome/diff.d.ts +14 -0
  67. package/dist/types/chrome/dynamic-border.d.ts +16 -0
  68. package/dist/types/chrome/error-block.d.ts +17 -0
  69. package/dist/types/chrome/form-theme.d.ts +3 -0
  70. package/dist/types/chrome/format.d.ts +12 -0
  71. package/dist/types/chrome/index.d.ts +20 -0
  72. package/dist/types/chrome/keybinding-hints.d.ts +40 -0
  73. package/dist/types/chrome/live-board.d.ts +23 -0
  74. package/dist/types/chrome/local-date.d.ts +4 -0
  75. package/dist/types/chrome/message-divider.d.ts +22 -0
  76. package/dist/types/chrome/message-frame.d.ts +52 -0
  77. package/dist/types/chrome/message-notice.d.ts +35 -0
  78. package/dist/types/chrome/overlay-box.d.ts +74 -0
  79. package/dist/types/chrome/qrcode.d.ts +48 -0
  80. package/dist/types/chrome/segment-track.d.ts +27 -0
  81. package/dist/types/chrome/select-list-mouse-routing.d.ts +4 -0
  82. package/dist/types/chrome/selector-helpers.d.ts +52 -0
  83. package/dist/types/chrome/shared.d.ts +5 -0
  84. package/dist/types/chrome/streaming-panel.d.ts +19 -0
  85. package/dist/types/chrome/tool-activity.d.ts +17 -0
  86. package/dist/types/chrome/transcript-container.d.ts +129 -0
  87. package/dist/types/chrome/transcript-status.d.ts +12 -0
  88. package/dist/types/chrome/visual-truncate.d.ts +19 -0
  89. package/dist/types/components/disclosure.d.ts +42 -0
  90. package/dist/types/components/form.d.ts +130 -0
  91. package/dist/types/components/key-value-list.d.ts +24 -0
  92. package/dist/types/components/layout/geometry.d.ts +73 -0
  93. package/dist/types/components/layout/row.d.ts +55 -0
  94. package/dist/types/components/layout/split-pane.d.ts +80 -0
  95. package/dist/types/components/layout/stack.d.ts +50 -0
  96. package/dist/types/components/menu-selection.d.ts +71 -0
  97. package/dist/types/components/metric.d.ts +44 -0
  98. package/dist/types/components/progress-bar.d.ts +36 -0
  99. package/dist/types/components/scroll-view.d.ts +53 -19
  100. package/dist/types/components/scroll-viewport.d.ts +46 -0
  101. package/dist/types/components/section.d.ts +19 -0
  102. package/dist/types/components/select-list.d.ts +46 -2
  103. package/dist/types/components/settings-list.d.ts +20 -0
  104. package/dist/types/components/table.d.ts +32 -0
  105. package/dist/types/components/tree-view.d.ts +130 -0
  106. package/dist/types/components/wizard-step.d.ts +60 -0
  107. package/dist/types/hotkeys-markdown.d.ts +7 -0
  108. package/dist/types/index.d.ts +17 -0
  109. package/dist/types/keybinding-matchers.d.ts +35 -0
  110. package/dist/types/keys.d.ts +2 -2
  111. package/dist/types/lang-from-path.d.ts +9 -0
  112. package/dist/types/overlays/advisor-config.d.ts +114 -0
  113. package/dist/types/overlays/agent-activity.d.ts +41 -0
  114. package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
  115. package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
  116. package/dist/types/overlays/agent-hub-types.d.ts +99 -0
  117. package/dist/types/overlays/agent-hub.d.ts +126 -0
  118. package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
  119. package/dist/types/overlays/agents-hub.d.ts +72 -0
  120. package/dist/types/overlays/ask-dialog.d.ts +88 -0
  121. package/dist/types/overlays/bordered-loader.d.ts +11 -0
  122. package/dist/types/overlays/btw-history-panel.d.ts +29 -0
  123. package/dist/types/overlays/btw-history.d.ts +17 -0
  124. package/dist/types/overlays/btw-panel.d.ts +26 -0
  125. package/dist/types/overlays/cleanse-panel.d.ts +36 -0
  126. package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
  127. package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
  128. package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
  129. package/dist/types/overlays/copy-selector.d.ts +48 -0
  130. package/dist/types/overlays/copy-targets.d.ts +63 -0
  131. package/dist/types/overlays/error-banner.d.ts +13 -0
  132. package/dist/types/overlays/extensions/display-text.d.ts +10 -0
  133. package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
  134. package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
  135. package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
  136. package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
  137. package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
  138. package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
  139. package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
  140. package/dist/types/overlays/extensions/types.d.ts +165 -0
  141. package/dist/types/overlays/history-search.d.ts +16 -0
  142. package/dist/types/overlays/hook-editor.d.ts +44 -0
  143. package/dist/types/overlays/hook-input.d.ts +20 -0
  144. package/dist/types/overlays/hook-selector.d.ts +71 -0
  145. package/dist/types/overlays/hub-frame.d.ts +77 -0
  146. package/dist/types/overlays/login-dialog.d.ts +43 -0
  147. package/dist/types/overlays/logout-account-selector.d.ts +15 -0
  148. package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
  149. package/dist/types/overlays/model-browser.d.ts +213 -0
  150. package/dist/types/overlays/model-hub.d.ts +72 -0
  151. package/dist/types/overlays/model-picker.d.ts +74 -0
  152. package/dist/types/overlays/model-selector.d.ts +52 -0
  153. package/dist/types/overlays/move-overlay.d.ts +39 -0
  154. package/dist/types/overlays/oauth-selector.d.ts +41 -0
  155. package/dist/types/overlays/omfg-panel.d.ts +20 -0
  156. package/dist/types/overlays/pause-screen.d.ts +43 -0
  157. package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
  158. package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
  159. package/dist/types/overlays/plan-toc.d.ts +41 -0
  160. package/dist/types/overlays/plugin-selector.d.ts +28 -0
  161. package/dist/types/overlays/plugin-settings.d.ts +180 -0
  162. package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
  163. package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
  164. package/dist/types/overlays/rewind-selector.d.ts +61 -0
  165. package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
  166. package/dist/types/overlays/session-account-selector.d.ts +24 -0
  167. package/dist/types/overlays/session-info-overlay.d.ts +17 -0
  168. package/dist/types/overlays/session-observer-registry.d.ts +77 -0
  169. package/dist/types/overlays/session-selector.d.ts +131 -0
  170. package/dist/types/overlays/settings-defs.d.ts +119 -0
  171. package/dist/types/overlays/settings-selector.d.ts +73 -0
  172. package/dist/types/overlays/show-images-selector.d.ts +11 -0
  173. package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
  174. package/dist/types/overlays/theme-selector.d.ts +12 -0
  175. package/dist/types/overlays/thinking-selector.d.ts +12 -0
  176. package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
  177. package/dist/types/overlays/tree-selector.d.ts +92 -0
  178. package/dist/types/overlays/usage-dashboard.d.ts +94 -0
  179. package/dist/types/overlays/usage-display.d.ts +5 -0
  180. package/dist/types/overlays/usage-row.d.ts +17 -0
  181. package/dist/types/prompt/attachment-chips.d.ts +19 -0
  182. package/dist/types/prompt/composer-attachments.d.ts +71 -0
  183. package/dist/types/prompt/composer-cache.d.ts +37 -0
  184. package/dist/types/prompt/composer.d.ts +159 -0
  185. package/dist/types/prompt/custom-editor.d.ts +261 -0
  186. package/dist/types/prompt/editor-top-gap.d.ts +18 -0
  187. package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
  188. package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
  189. package/dist/types/prompt/gradient-highlight.d.ts +32 -0
  190. package/dist/types/prompt/image-format.d.ts +4 -0
  191. package/dist/types/prompt/image-references.d.ts +26 -0
  192. package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
  193. package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
  194. package/dist/types/prompt/macos-spelling.d.ts +44 -0
  195. package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
  196. package/dist/types/prompt/magic-keywords.d.ts +26 -0
  197. package/dist/types/prompt/markdown-prose.d.ts +15 -0
  198. package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
  199. package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
  200. package/dist/types/prompt/orchestrate.d.ts +13 -0
  201. package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
  202. package/dist/types/prompt/queue-input.d.ts +8 -0
  203. package/dist/types/prompt/skill-tokens.d.ts +13 -0
  204. package/dist/types/prompt/tools-markdown.d.ts +12 -0
  205. package/dist/types/prompt/ultrathink.d.ts +13 -0
  206. package/dist/types/prompt/usage-amounts.d.ts +26 -0
  207. package/dist/types/prompt/video.d.ts +18 -0
  208. package/dist/types/prompt/welcome.d.ts +83 -0
  209. package/dist/types/prompt/workflow.d.ts +13 -0
  210. package/dist/types/render/code-cell.d.ts +51 -0
  211. package/dist/types/render/file-list.d.ts +22 -0
  212. package/dist/types/render/hyperlink.d.ts +80 -0
  213. package/dist/types/render/index.d.ts +16 -0
  214. package/dist/types/render/output-block.d.ts +54 -0
  215. package/dist/types/render/output-pane.d.ts +80 -0
  216. package/dist/types/render/render-utils.d.ts +312 -0
  217. package/dist/types/render/sixel.d.ts +21 -0
  218. package/dist/types/render/status-line.d.ts +23 -0
  219. package/dist/types/render/tool-card.d.ts +71 -0
  220. package/dist/types/render/tree-list.d.ts +29 -0
  221. package/dist/types/render/types.d.ts +17 -0
  222. package/dist/types/render/utils.d.ts +43 -0
  223. package/dist/types/render/width-aware-text.d.ts +23 -0
  224. package/dist/types/setup/lazy.d.ts +3 -0
  225. package/dist/types/setup/scenes/composer.d.ts +3 -0
  226. package/dist/types/setup/scenes/glyph.d.ts +3 -0
  227. package/dist/types/setup/scenes/model.d.ts +3 -0
  228. package/dist/types/setup/scenes/outro.d.ts +2 -0
  229. package/dist/types/setup/scenes/providers.d.ts +3 -0
  230. package/dist/types/setup/scenes/sign-in.d.ts +21 -0
  231. package/dist/types/setup/scenes/splash.d.ts +11 -0
  232. package/dist/types/setup/scenes/theme.d.ts +3 -0
  233. package/dist/types/setup/scenes/types.d.ts +110 -0
  234. package/dist/types/setup/scenes/web-search.d.ts +22 -0
  235. package/dist/types/setup/setup-version.d.ts +11 -0
  236. package/dist/types/setup/startup-splash.d.ts +9 -0
  237. package/dist/types/setup/wizard-overlay.d.ts +16 -0
  238. package/dist/types/setup/wizard.d.ts +25 -0
  239. package/dist/types/status-line/component.d.ts +182 -0
  240. package/dist/types/status-line/context-usage.d.ts +156 -0
  241. package/dist/types/status-line/footer.d.ts +30 -0
  242. package/dist/types/status-line/git-utils.d.ts +22 -0
  243. package/dist/types/status-line/host.d.ts +129 -0
  244. package/dist/types/status-line/index.d.ts +6 -0
  245. package/dist/types/status-line/loop.d.ts +18 -0
  246. package/dist/types/status-line/metrics.d.ts +21 -0
  247. package/dist/types/status-line/presets.d.ts +3 -0
  248. package/dist/types/status-line/schema.d.ts +15 -0
  249. package/dist/types/status-line/segments.d.ts +5 -0
  250. package/dist/types/status-line/separators.d.ts +3 -0
  251. package/dist/types/status-line/types.d.ts +236 -0
  252. package/dist/types/stdin-buffer.d.ts +4 -0
  253. package/dist/types/theme/color.d.ts +24 -0
  254. package/dist/types/theme/defaults/index.d.ts +9489 -0
  255. package/dist/types/theme/index.d.ts +4 -0
  256. package/dist/types/theme/loader.d.ts +23 -0
  257. package/dist/types/theme/mermaid-cache.d.ts +26 -0
  258. package/dist/types/theme/schema-validation.d.ts +3 -0
  259. package/dist/types/theme/schema.d.ts +25 -0
  260. package/dist/types/theme/session-color.d.ts +43 -0
  261. package/dist/types/theme/shimmer.d.ts +44 -0
  262. package/dist/types/theme/symbols.d.ts +34 -0
  263. package/dist/types/theme/theme-class.d.ts +299 -0
  264. package/dist/types/theme/theme.d.ts +111 -0
  265. package/dist/types/theme/tui-adapters.d.ts +30 -0
  266. package/dist/types/thinking.d.ts +165 -0
  267. package/dist/types/tools/agent-tree.d.ts +36 -0
  268. package/dist/types/tools/ask.d.ts +67 -0
  269. package/dist/types/tools/ast-edit.d.ts +53 -0
  270. package/dist/types/tools/ast-grep.d.ts +52 -0
  271. package/dist/types/tools/autoresearch.d.ts +156 -0
  272. package/dist/types/tools/bash-interactive.d.ts +28 -0
  273. package/dist/types/tools/bash.d.ts +103 -0
  274. package/dist/types/tools/conflict-detect.d.ts +43 -0
  275. package/dist/types/tools/debug.d.ts +60 -0
  276. package/dist/types/tools/default-renderer.d.ts +24 -0
  277. package/dist/types/tools/edit.d.ts +158 -0
  278. package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
  279. package/dist/types/tools/eval-format/index.d.ts +5 -0
  280. package/dist/types/tools/eval-format/javascript.d.ts +2 -0
  281. package/dist/types/tools/eval-format/python.d.ts +2 -0
  282. package/dist/types/tools/eval.d.ts +94 -0
  283. package/dist/types/tools/fetch.d.ts +42 -0
  284. package/dist/types/tools/gh-format.d.ts +8 -0
  285. package/dist/types/tools/github.d.ts +144 -0
  286. package/dist/types/tools/glob.d.ts +44 -0
  287. package/dist/types/tools/goal.d.ts +42 -0
  288. package/dist/types/tools/grep.d.ts +64 -0
  289. package/dist/types/tools/grouped-file-output.d.ts +71 -0
  290. package/dist/types/tools/hashline-format.d.ts +28 -0
  291. package/dist/types/tools/hub.d.ts +340 -0
  292. package/dist/types/tools/index.d.ts +4 -0
  293. package/dist/types/tools/json-tree.d.ts +59 -0
  294. package/dist/types/tools/line-ranges.d.ts +29 -0
  295. package/dist/types/tools/list-limit.d.ts +15 -0
  296. package/dist/types/tools/lsp.d.ts +72 -0
  297. package/dist/types/tools/match-line-format.d.ts +11 -0
  298. package/dist/types/tools/mcp.d.ts +81 -0
  299. package/dist/types/tools/memory.d.ts +67 -0
  300. package/dist/types/tools/output-meta.d.ts +151 -0
  301. package/dist/types/tools/read.d.ts +139 -0
  302. package/dist/types/tools/renderer.d.ts +98 -0
  303. package/dist/types/tools/report-tool-issue.d.ts +8 -0
  304. package/dist/types/tools/resolve.d.ts +47 -0
  305. package/dist/types/tools/streaming-output.d.ts +282 -0
  306. package/dist/types/tools/subprocess.d.ts +24 -0
  307. package/dist/types/tools/task-repair-args.d.ts +53 -0
  308. package/dist/types/tools/task-yield-assembly.d.ts +20 -0
  309. package/dist/types/tools/task.d.ts +425 -0
  310. package/dist/types/tools/terminal-output.d.ts +8 -0
  311. package/dist/types/tools/think.d.ts +13 -0
  312. package/dist/types/tools/todo.d.ts +118 -0
  313. package/dist/types/tools/tool-errors.d.ts +7 -0
  314. package/dist/types/tools/vibe.d.ts +120 -0
  315. package/dist/types/tools/web-search.d.ts +195 -0
  316. package/dist/types/tools/write.d.ts +76 -0
  317. package/dist/types/tools/xd-url.d.ts +13 -0
  318. package/dist/types/tools/xdev.d.ts +52 -0
  319. package/dist/types/tui.d.ts +18 -0
  320. package/dist/types/utils.d.ts +2 -0
  321. package/package.json +37 -3
  322. package/src/app-keybindings.ts +760 -0
  323. package/src/apps/autoresearch-dashboard.ts +500 -0
  324. package/src/apps/autoresearch-data.ts +64 -0
  325. package/src/apps/cleanse-board.ts +341 -0
  326. package/src/apps/cleanse-picker.ts +57 -0
  327. package/src/apps/debug/log-formatting.ts +53 -0
  328. package/src/apps/debug/log-viewer.ts +868 -0
  329. package/src/apps/debug/protocol-probe.ts +267 -0
  330. package/src/apps/debug/raw-sse-buffer.ts +449 -0
  331. package/src/apps/debug/raw-sse.ts +282 -0
  332. package/src/apps/debug/terminal-info.ts +115 -0
  333. package/src/apps/debug/viewer-frame.ts +174 -0
  334. package/src/apps/git/avatar.ts +52 -0
  335. package/src/apps/git/colors.ts +109 -0
  336. package/src/apps/git/diff-pane.ts +1512 -0
  337. package/src/apps/git/git-tui.ts +889 -0
  338. package/src/apps/git/sidebar.ts +1204 -0
  339. package/src/apps/git/state.ts +113 -0
  340. package/src/apps/if-bench-board.ts +324 -0
  341. package/src/apps/live-visualizer.ts +238 -0
  342. package/src/apps/ps-data.ts +116 -0
  343. package/src/apps/ps-top.ts +422 -0
  344. package/src/apps/session-picker.ts +95 -0
  345. package/src/apps/setup-model-picker.ts +21 -0
  346. package/src/apps/standalone-picker.ts +111 -0
  347. package/src/autocomplete.ts +9 -13
  348. package/src/chat/advisor-message.ts +175 -0
  349. package/src/chat/assistant-message.ts +1214 -0
  350. package/src/chat/background-tan-message.ts +35 -0
  351. package/src/chat/bash-execution.ts +394 -0
  352. package/src/chat/cache-invalidation-marker.ts +94 -0
  353. package/src/chat/chat-transcript-builder.ts +593 -0
  354. package/src/chat/collab-prompt-message.ts +34 -0
  355. package/src/chat/compaction-summary-message.ts +261 -0
  356. package/src/chat/custom-message.ts +23 -0
  357. package/src/chat/display-preferences.ts +24 -0
  358. package/src/chat/eval-execution.ts +172 -0
  359. package/src/chat/execution-shared.ts +113 -0
  360. package/src/chat/extension-types.ts +46 -0
  361. package/src/chat/hook-message.ts +20 -0
  362. package/src/chat/image-loading.ts +122 -0
  363. package/src/chat/late-diagnostics-message.ts +92 -0
  364. package/src/chat/messages.ts +305 -0
  365. package/src/chat/reaction.ts +65 -0
  366. package/src/chat/read-target.ts +7 -0
  367. package/src/chat/read-tool-group.ts +873 -0
  368. package/src/chat/served-model-marker.ts +91 -0
  369. package/src/chat/skill-message.ts +220 -0
  370. package/src/chat/skill-title-input.ts +41 -0
  371. package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
  372. package/src/chat/thinking-display.ts +312 -0
  373. package/src/chat/todo-reminder.ts +33 -0
  374. package/src/chat/tool-execution.ts +1395 -0
  375. package/src/chat/transcript-browser.ts +268 -0
  376. package/src/chat/transcript-entry.ts +96 -0
  377. package/src/chat/transcript-outline.ts +260 -0
  378. package/src/chat/transcript-render-helpers.ts +315 -0
  379. package/src/chat/ttsr-notification.ts +123 -0
  380. package/src/chat/user-message.ts +287 -0
  381. package/src/chrome/chat-block.ts +110 -0
  382. package/src/chrome/collab-qrcode.ts +74 -0
  383. package/src/chrome/context-thresholds.ts +85 -0
  384. package/src/chrome/countdown-timer.ts +74 -0
  385. package/src/chrome/diff.ts +266 -0
  386. package/src/chrome/dynamic-border.ts +36 -0
  387. package/src/chrome/error-block.ts +63 -0
  388. package/src/chrome/form-theme.ts +10 -0
  389. package/src/chrome/format.ts +66 -0
  390. package/src/chrome/index.ts +21 -0
  391. package/src/chrome/keybinding-hints.ts +55 -0
  392. package/src/chrome/live-board.ts +123 -0
  393. package/src/chrome/local-date.ts +20 -0
  394. package/src/chrome/message-divider.ts +51 -0
  395. package/src/chrome/message-frame.ts +164 -0
  396. package/src/chrome/message-notice.ts +103 -0
  397. package/src/chrome/overlay-box.ts +301 -0
  398. package/src/chrome/qrcode.ts +539 -0
  399. package/src/chrome/segment-track.ts +86 -0
  400. package/src/chrome/select-list-mouse-routing.ts +11 -0
  401. package/src/chrome/selector-helpers.ts +119 -0
  402. package/src/chrome/shared.ts +27 -0
  403. package/src/chrome/streaming-panel.ts +72 -0
  404. package/src/chrome/tool-activity.ts +44 -0
  405. package/src/chrome/transcript-container.ts +902 -0
  406. package/src/chrome/transcript-status.ts +27 -0
  407. package/src/chrome/visual-truncate.ts +70 -0
  408. package/src/components/disclosure.ts +235 -0
  409. package/src/components/editor.ts +10 -12
  410. package/src/components/form.ts +566 -0
  411. package/src/components/input.ts +6 -27
  412. package/src/components/key-value-list.ts +88 -0
  413. package/src/components/layout/geometry.ts +202 -0
  414. package/src/components/layout/row.ts +283 -0
  415. package/src/components/layout/split-pane.ts +349 -0
  416. package/src/components/layout/stack.ts +261 -0
  417. package/src/components/markdown.ts +16 -12
  418. package/src/components/menu-selection.ts +248 -0
  419. package/src/components/metric.ts +132 -0
  420. package/src/components/progress-bar.ts +140 -0
  421. package/src/components/scroll-view.ts +372 -70
  422. package/src/components/scroll-viewport.ts +154 -0
  423. package/src/components/section.ts +77 -0
  424. package/src/components/select-list.ts +238 -159
  425. package/src/components/settings-list.ts +103 -80
  426. package/src/components/table.ts +127 -0
  427. package/src/components/tree-view.ts +481 -0
  428. package/src/components/wizard-step.ts +229 -0
  429. package/src/deccara.ts +1 -3
  430. package/src/hotkeys-markdown.ts +100 -0
  431. package/src/index.ts +18 -0
  432. package/src/keybinding-matchers.ts +99 -0
  433. package/src/keys.ts +2 -2
  434. package/src/lang-from-path.ts +252 -0
  435. package/src/overlays/advisor-config.ts +761 -0
  436. package/src/overlays/agent-activity.ts +113 -0
  437. package/src/overlays/agent-hub-projection.ts +250 -0
  438. package/src/overlays/agent-hub-renderer.ts +281 -0
  439. package/src/overlays/agent-hub-types.ts +74 -0
  440. package/src/overlays/agent-hub.ts +1562 -0
  441. package/src/overlays/agent-transcript-viewer.ts +669 -0
  442. package/src/overlays/agents-hub.ts +1203 -0
  443. package/src/overlays/ask-dialog.ts +1202 -0
  444. package/src/overlays/bordered-loader.ts +41 -0
  445. package/src/overlays/btw-history-panel.ts +591 -0
  446. package/src/overlays/btw-history.ts +33 -0
  447. package/src/overlays/btw-panel.ts +167 -0
  448. package/src/overlays/cleanse-panel.ts +167 -0
  449. package/src/overlays/codex-reset-fireworks.ts +375 -0
  450. package/src/overlays/composer-shape-preview.ts +137 -0
  451. package/src/overlays/composer-shape-registry.ts +82 -0
  452. package/src/overlays/copy-selector.ts +618 -0
  453. package/src/overlays/copy-targets.ts +210 -0
  454. package/src/overlays/error-banner.ts +39 -0
  455. package/src/overlays/extensions/display-text.ts +39 -0
  456. package/src/overlays/extensions/extension-dashboard.ts +645 -0
  457. package/src/overlays/extensions/extension-list.ts +667 -0
  458. package/src/overlays/extensions/inspector-model.ts +484 -0
  459. package/src/overlays/extensions/inspector-panel.ts +669 -0
  460. package/src/overlays/extensions/live-tool-session.ts +67 -0
  461. package/src/overlays/extensions/mcp-runtime.ts +289 -0
  462. package/src/overlays/extensions/state-manager.ts +337 -0
  463. package/src/overlays/extensions/types.ts +208 -0
  464. package/src/overlays/history-search.ts +268 -0
  465. package/src/overlays/hook-editor.ts +272 -0
  466. package/src/overlays/hook-input.ts +84 -0
  467. package/src/overlays/hook-selector.ts +635 -0
  468. package/src/overlays/hub-frame.ts +262 -0
  469. package/src/overlays/login-dialog.ts +231 -0
  470. package/src/overlays/logout-account-selector.ts +115 -0
  471. package/src/overlays/mcp-add-wizard.ts +1436 -0
  472. package/src/overlays/model-browser.ts +1176 -0
  473. package/src/overlays/model-hub.ts +2279 -0
  474. package/src/overlays/model-picker.ts +285 -0
  475. package/src/overlays/model-selector.ts +107 -0
  476. package/src/overlays/move-overlay.ts +197 -0
  477. package/src/overlays/oauth-selector.ts +446 -0
  478. package/src/overlays/omfg-panel.ts +136 -0
  479. package/src/overlays/pause-screen.ts +198 -0
  480. package/src/overlays/plan-review-overlay.ts +1227 -0
  481. package/src/overlays/plan-save-overlay.ts +74 -0
  482. package/src/overlays/plan-toc.ts +139 -0
  483. package/src/overlays/plugin-selector.ts +97 -0
  484. package/src/overlays/plugin-settings.ts +839 -0
  485. package/src/overlays/queue-mode-selector.ts +55 -0
  486. package/src/overlays/reset-usage-selector.ts +170 -0
  487. package/src/overlays/rewind-selector.ts +499 -0
  488. package/src/overlays/running-subagent-badge.ts +19 -0
  489. package/src/overlays/session-account-selector.ts +68 -0
  490. package/src/overlays/session-info-overlay.ts +96 -0
  491. package/src/overlays/session-observer-registry.ts +289 -0
  492. package/src/overlays/session-selector.ts +1137 -0
  493. package/src/overlays/settings-defs.ts +315 -0
  494. package/src/overlays/settings-selector.ts +1415 -0
  495. package/src/overlays/show-images-selector.ts +44 -0
  496. package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
  497. package/src/overlays/snapcompact-shape-preview.ts +192 -0
  498. package/src/overlays/theme-selector.ts +62 -0
  499. package/src/overlays/thinking-selector.ts +51 -0
  500. package/src/overlays/tiny-title-download-progress.ts +102 -0
  501. package/src/overlays/tree-selector.ts +1121 -0
  502. package/src/overlays/usage-dashboard.ts +629 -0
  503. package/src/overlays/usage-display.ts +45 -0
  504. package/src/overlays/usage-row.ts +118 -0
  505. package/src/prompt/attachment-chips.ts +201 -0
  506. package/src/prompt/composer-attachments.ts +280 -0
  507. package/src/prompt/composer-cache.ts +304 -0
  508. package/src/prompt/composer.ts +934 -0
  509. package/src/prompt/custom-editor.ts +1392 -0
  510. package/src/prompt/data/emojis.json +1 -0
  511. package/src/prompt/editor-top-gap.ts +28 -0
  512. package/src/prompt/emoji-autocomplete.ts +285 -0
  513. package/src/prompt/github-ref-autocomplete.ts +75 -0
  514. package/src/prompt/gradient-highlight.ts +101 -0
  515. package/src/prompt/image-format.ts +28 -0
  516. package/src/prompt/image-references.ts +102 -0
  517. package/src/prompt/interactive-context-helpers.ts +126 -0
  518. package/src/prompt/internal-url-autocomplete.ts +155 -0
  519. package/src/prompt/macos-spelling.ts +456 -0
  520. package/src/prompt/magic-keyword-boundary.ts +23 -0
  521. package/src/prompt/magic-keywords.ts +42 -0
  522. package/src/prompt/markdown-prose.ts +245 -0
  523. package/src/prompt/model-mention-autocomplete.ts +94 -0
  524. package/src/prompt/model-mention-syntax.ts +41 -0
  525. package/src/prompt/orchestrate.ts +26 -0
  526. package/src/prompt/prompt-action-autocomplete.ts +337 -0
  527. package/src/prompt/queue-input.ts +132 -0
  528. package/src/prompt/skill-tokens.ts +36 -0
  529. package/src/prompt/tips.txt +27 -0
  530. package/src/prompt/tools-markdown.ts +29 -0
  531. package/src/prompt/ultrathink.ts +26 -0
  532. package/src/prompt/usage-amounts.ts +99 -0
  533. package/src/prompt/video.ts +47 -0
  534. package/src/prompt/welcome.ts +605 -0
  535. package/src/prompt/workflow.ts +26 -0
  536. package/src/render/code-cell.ts +244 -0
  537. package/src/render/file-list.ts +58 -0
  538. package/src/render/hyperlink.ts +192 -0
  539. package/src/render/index.ts +17 -0
  540. package/src/render/output-block.ts +267 -0
  541. package/src/render/output-pane.ts +299 -0
  542. package/src/render/render-utils.ts +1182 -0
  543. package/src/render/sixel.ts +69 -0
  544. package/src/render/status-line.ts +55 -0
  545. package/src/render/tool-card.ts +272 -0
  546. package/src/render/tree-list.ts +188 -0
  547. package/src/render/types.ts +19 -0
  548. package/src/render/utils.ts +109 -0
  549. package/src/render/width-aware-text.ts +60 -0
  550. package/src/setup/lazy.ts +17 -0
  551. package/src/setup/scenes/composer.ts +127 -0
  552. package/src/setup/scenes/glyph.ts +120 -0
  553. package/src/setup/scenes/model.ts +138 -0
  554. package/src/setup/scenes/outro.ts +24 -0
  555. package/src/setup/scenes/providers.ts +107 -0
  556. package/src/setup/scenes/sign-in.ts +373 -0
  557. package/src/setup/scenes/splash.ts +192 -0
  558. package/src/setup/scenes/theme.ts +343 -0
  559. package/src/setup/scenes/types.ts +111 -0
  560. package/src/setup/scenes/web-search.ts +165 -0
  561. package/src/setup/setup-version.ts +11 -0
  562. package/src/setup/startup-splash.ts +107 -0
  563. package/src/setup/wizard-overlay.ts +319 -0
  564. package/src/setup/wizard.ts +101 -0
  565. package/src/status-line/component.ts +3003 -0
  566. package/src/status-line/context-usage.ts +688 -0
  567. package/src/status-line/footer.ts +323 -0
  568. package/src/status-line/git-utils.ts +42 -0
  569. package/src/status-line/host.ts +97 -0
  570. package/src/status-line/index.ts +6 -0
  571. package/src/status-line/loop.ts +28 -0
  572. package/src/status-line/metrics.ts +94 -0
  573. package/src/status-line/presets.ts +107 -0
  574. package/src/status-line/schema.ts +57 -0
  575. package/src/status-line/segments.ts +934 -0
  576. package/src/status-line/separators.ts +55 -0
  577. package/src/status-line/types.ts +227 -0
  578. package/src/stdin-buffer.ts +4 -2
  579. package/src/theme/color.ts +95 -0
  580. package/src/theme/dark.json +95 -0
  581. package/src/theme/defaults/alabaster.json +93 -0
  582. package/src/theme/defaults/amethyst.json +96 -0
  583. package/src/theme/defaults/anthracite.json +93 -0
  584. package/src/theme/defaults/basalt.json +91 -0
  585. package/src/theme/defaults/birch.json +95 -0
  586. package/src/theme/defaults/dark-abyss.json +91 -0
  587. package/src/theme/defaults/dark-arctic.json +104 -0
  588. package/src/theme/defaults/dark-aurora.json +95 -0
  589. package/src/theme/defaults/dark-catppuccin.json +107 -0
  590. package/src/theme/defaults/dark-cavern.json +91 -0
  591. package/src/theme/defaults/dark-celestial.json +106 -0
  592. package/src/theme/defaults/dark-copper.json +95 -0
  593. package/src/theme/defaults/dark-cosmos.json +90 -0
  594. package/src/theme/defaults/dark-cyberpunk.json +102 -0
  595. package/src/theme/defaults/dark-dracula.json +98 -0
  596. package/src/theme/defaults/dark-eclipse.json +91 -0
  597. package/src/theme/defaults/dark-ember.json +95 -0
  598. package/src/theme/defaults/dark-equinox.json +90 -0
  599. package/src/theme/defaults/dark-forest.json +96 -0
  600. package/src/theme/defaults/dark-github.json +105 -0
  601. package/src/theme/defaults/dark-gruvbox.json +112 -0
  602. package/src/theme/defaults/dark-lavender.json +95 -0
  603. package/src/theme/defaults/dark-lunar.json +89 -0
  604. package/src/theme/defaults/dark-midnight.json +95 -0
  605. package/src/theme/defaults/dark-monochrome.json +94 -0
  606. package/src/theme/defaults/dark-monokai.json +98 -0
  607. package/src/theme/defaults/dark-nebula.json +90 -0
  608. package/src/theme/defaults/dark-nord.json +98 -0
  609. package/src/theme/defaults/dark-ocean.json +101 -0
  610. package/src/theme/defaults/dark-one.json +100 -0
  611. package/src/theme/defaults/dark-poimandres.json +115 -0
  612. package/src/theme/defaults/dark-rainforest.json +91 -0
  613. package/src/theme/defaults/dark-reef.json +91 -0
  614. package/src/theme/defaults/dark-retro.json +92 -0
  615. package/src/theme/defaults/dark-rose-pine.json +96 -0
  616. package/src/theme/defaults/dark-sakura.json +95 -0
  617. package/src/theme/defaults/dark-slate.json +95 -0
  618. package/src/theme/defaults/dark-solarized.json +97 -0
  619. package/src/theme/defaults/dark-solstice.json +90 -0
  620. package/src/theme/defaults/dark-starfall.json +91 -0
  621. package/src/theme/defaults/dark-sunset.json +99 -0
  622. package/src/theme/defaults/dark-swamp.json +90 -0
  623. package/src/theme/defaults/dark-synthwave.json +103 -0
  624. package/src/theme/defaults/dark-taiga.json +91 -0
  625. package/src/theme/defaults/dark-terminal.json +95 -0
  626. package/src/theme/defaults/dark-tokyo-night.json +101 -0
  627. package/src/theme/defaults/dark-tundra.json +91 -0
  628. package/src/theme/defaults/dark-twilight.json +91 -0
  629. package/src/theme/defaults/dark-volcanic.json +91 -0
  630. package/src/theme/defaults/graphite.json +92 -0
  631. package/src/theme/defaults/index.ts +201 -0
  632. package/src/theme/defaults/light-arctic.json +107 -0
  633. package/src/theme/defaults/light-aurora-day.json +91 -0
  634. package/src/theme/defaults/light-canyon.json +91 -0
  635. package/src/theme/defaults/light-catppuccin.json +106 -0
  636. package/src/theme/defaults/light-cirrus.json +90 -0
  637. package/src/theme/defaults/light-coral.json +95 -0
  638. package/src/theme/defaults/light-cyberpunk.json +96 -0
  639. package/src/theme/defaults/light-dawn.json +90 -0
  640. package/src/theme/defaults/light-dunes.json +91 -0
  641. package/src/theme/defaults/light-eucalyptus.json +95 -0
  642. package/src/theme/defaults/light-forest.json +100 -0
  643. package/src/theme/defaults/light-frost.json +95 -0
  644. package/src/theme/defaults/light-github.json +115 -0
  645. package/src/theme/defaults/light-glacier.json +91 -0
  646. package/src/theme/defaults/light-gruvbox.json +108 -0
  647. package/src/theme/defaults/light-haze.json +90 -0
  648. package/src/theme/defaults/light-honeycomb.json +95 -0
  649. package/src/theme/defaults/light-lagoon.json +91 -0
  650. package/src/theme/defaults/light-lavender.json +95 -0
  651. package/src/theme/defaults/light-meadow.json +91 -0
  652. package/src/theme/defaults/light-mint.json +95 -0
  653. package/src/theme/defaults/light-monochrome.json +101 -0
  654. package/src/theme/defaults/light-ocean.json +99 -0
  655. package/src/theme/defaults/light-one.json +99 -0
  656. package/src/theme/defaults/light-opal.json +91 -0
  657. package/src/theme/defaults/light-orchard.json +91 -0
  658. package/src/theme/defaults/light-paper.json +95 -0
  659. package/src/theme/defaults/light-poimandres.json +115 -0
  660. package/src/theme/defaults/light-prism.json +90 -0
  661. package/src/theme/defaults/light-retro.json +98 -0
  662. package/src/theme/defaults/light-sand.json +95 -0
  663. package/src/theme/defaults/light-savanna.json +91 -0
  664. package/src/theme/defaults/light-solarized.json +102 -0
  665. package/src/theme/defaults/light-soleil.json +90 -0
  666. package/src/theme/defaults/light-sunset.json +99 -0
  667. package/src/theme/defaults/light-synthwave.json +98 -0
  668. package/src/theme/defaults/light-tokyo-night.json +111 -0
  669. package/src/theme/defaults/light-wetland.json +91 -0
  670. package/src/theme/defaults/light-zenith.json +89 -0
  671. package/src/theme/defaults/limestone.json +94 -0
  672. package/src/theme/defaults/mahogany.json +97 -0
  673. package/src/theme/defaults/marble.json +93 -0
  674. package/src/theme/defaults/obsidian.json +91 -0
  675. package/src/theme/defaults/onyx.json +91 -0
  676. package/src/theme/defaults/pearl.json +93 -0
  677. package/src/theme/defaults/porcelain.json +91 -0
  678. package/src/theme/defaults/quartz.json +96 -0
  679. package/src/theme/defaults/sandstone.json +95 -0
  680. package/src/theme/defaults/titanium.json +90 -0
  681. package/src/theme/index.ts +5 -0
  682. package/src/theme/light.json +93 -0
  683. package/src/theme/loader.ts +200 -0
  684. package/src/theme/mermaid-cache.ts +92 -0
  685. package/src/theme/schema-validation.ts +119 -0
  686. package/src/theme/schema.ts +168 -0
  687. package/src/theme/session-color.ts +253 -0
  688. package/src/theme/shimmer.ts +307 -0
  689. package/src/theme/symbols.ts +1433 -0
  690. package/src/theme/theme-class.ts +787 -0
  691. package/src/theme/theme-schema.json +463 -0
  692. package/src/theme/theme.ts +810 -0
  693. package/src/theme/tui-adapters.ts +339 -0
  694. package/src/thinking.ts +380 -0
  695. package/src/tools/agent-tree.ts +128 -0
  696. package/src/tools/ask.ts +482 -0
  697. package/src/tools/ast-edit.ts +210 -0
  698. package/src/tools/ast-grep.ts +171 -0
  699. package/src/tools/autoresearch.ts +287 -0
  700. package/src/tools/bash-interactive.ts +295 -0
  701. package/src/tools/bash.ts +468 -0
  702. package/src/tools/conflict-detect.ts +77 -0
  703. package/src/tools/debug.ts +167 -0
  704. package/src/tools/default-renderer.ts +172 -0
  705. package/src/tools/edit.ts +1258 -0
  706. package/src/tools/eval-format/code-mode-declarations.ts +61 -0
  707. package/src/tools/eval-format/index.ts +16 -0
  708. package/src/tools/eval-format/javascript.ts +952 -0
  709. package/src/tools/eval-format/python.ts +544 -0
  710. package/src/tools/eval.ts +835 -0
  711. package/src/tools/fetch.ts +226 -0
  712. package/src/tools/gh-format.ts +18 -0
  713. package/src/tools/github.ts +686 -0
  714. package/src/tools/glob.ts +213 -0
  715. package/src/tools/goal.ts +153 -0
  716. package/src/tools/grep.ts +385 -0
  717. package/src/tools/grouped-file-output.ts +211 -0
  718. package/src/tools/hashline-format.ts +59 -0
  719. package/src/tools/hub.ts +1488 -0
  720. package/src/tools/index.ts +71 -0
  721. package/src/tools/json-tree.ts +388 -0
  722. package/src/tools/line-ranges.ts +98 -0
  723. package/src/tools/list-limit.ts +43 -0
  724. package/src/tools/lsp.ts +702 -0
  725. package/src/tools/match-line-format.ts +20 -0
  726. package/src/tools/mcp.ts +309 -0
  727. package/src/tools/memory.ts +220 -0
  728. package/src/tools/output-meta.ts +367 -0
  729. package/src/tools/read.ts +628 -0
  730. package/src/tools/renderer.ts +107 -0
  731. package/src/tools/report-tool-issue.ts +13 -0
  732. package/src/tools/resolve.ts +139 -0
  733. package/src/tools/streaming-output.ts +1576 -0
  734. package/src/tools/subprocess.ts +39 -0
  735. package/src/tools/task-repair-args.ts +118 -0
  736. package/src/tools/task-yield-assembly.ts +147 -0
  737. package/src/tools/task.ts +2110 -0
  738. package/src/tools/terminal-output.ts +153 -0
  739. package/src/tools/think.ts +28 -0
  740. package/src/tools/todo.ts +580 -0
  741. package/src/tools/tool-errors.ts +15 -0
  742. package/src/tools/vibe.ts +420 -0
  743. package/src/tools/web-search.ts +409 -0
  744. package/src/tools/write.ts +511 -0
  745. package/src/tools/xd-url.ts +28 -0
  746. package/src/tools/xdev.ts +201 -0
  747. package/src/tui.ts +57 -4
  748. 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
+ }