@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,285 @@
1
+ /**
2
+ * Compact session-model picker (alt+p / `/switch`): a bottom-anchored
3
+ * floating overlay hosting just a {@link ModelBrowser} — no provider sidebar.
4
+ * Model entries switch the current session only; a search beginning with `@`
5
+ * exposes the configured ctrl+p quick roles.
6
+ */
7
+ import type { Model } from "@oh-my-pi/pi-ai";
8
+ import { addKeyAliases, canonicalKeyId } from "../keybindings";
9
+ import { type KeyId, parseKey } from "../keys";
10
+ import type { Component, TUI } from "../tui";
11
+ import { type ThemeColor, theme } from "../theme/theme";
12
+ import { buildSessionModelScope, ModelBrowser, type ModelBrowserItem } from "./model-browser";
13
+ import type { ModelBrowserRegistry, ModelBrowserSource } from "./model-browser";
14
+ import type { ConfiguredThinkingLevel } from "../thinking";
15
+ import type { ScopedModelItem } from "./model-hub";
16
+ import { bottomBorder, row, topBorder } from "../chrome/overlay-box";
17
+ import { resolveSegmentPalette } from "../chrome/segment-track";
18
+
19
+ /** Configured role resolved to a concrete model. */
20
+ export interface ResolvedRoleModel {
21
+ role: string;
22
+ model: Model;
23
+ thinkingLevel?: ConfiguredThinkingLevel;
24
+ explicitThinkingLevel: boolean;
25
+ }
26
+
27
+ /** Catalog refresh capability used by the session picker. */
28
+ export interface ModelPickerRegistry extends ModelBrowserRegistry {
29
+ refresh(strategy: "offline"): Promise<void>;
30
+ }
31
+
32
+ export interface ModelPickerCallbacks {
33
+ /**
34
+ * A model was chosen for a session-only switch. `selector` is `provider/id`.
35
+ * `overContext` is true when the session transcript exceeds the model's
36
+ * context window — the host must compact before switching.
37
+ */
38
+ onPick: (model: Model, selector: string, meta: { overContext: boolean }) => void;
39
+ /** A configured ctrl+p quick role was chosen. */
40
+ onPickRole?: (entry: ResolvedRoleModel) => void;
41
+ /**
42
+ * A model was chosen for Task subagents (task mode, toggled by pressing the
43
+ * picker shortcut again). Session-only: the host applies a runtime override.
44
+ */
45
+ onPickTask?: (model: Model, selector: string) => void;
46
+ /** The picker was dismissed. */
47
+ onCancel: () => void;
48
+ }
49
+
50
+ export interface ModelPickerOptions {
51
+ /** Session token count; models with smaller context windows are grayed and compact-first on pick. */
52
+ currentContextTokens?: number;
53
+ /** `provider/id` of the session's active model; highlighted and preselected. */
54
+ currentSelector?: string;
55
+ /** Resolved role models in the same order used by the ctrl+p quick-role cycle. */
56
+ quickRoles?: ReadonlyArray<ResolvedRoleModel>;
57
+ /** Complete ctrl+p order, including unavailable roles, to preserve segment colors. */
58
+ quickRoleOrder?: ReadonlyArray<string>;
59
+ /** Active quick role, highlighted when the search begins with `@`. */
60
+ currentQuickRole?: string;
61
+ /** Keys that toggle task-subagent mode while the picker is open; typically the alt+p binding. */
62
+ taskModeKeys?: readonly KeyId[];
63
+ /** Human-readable label for the toggle key, shown in footer hints (e.g. "alt+p"). */
64
+ taskModeKeyLabel?: string;
65
+ /** `provider/id` highlighted and preselected in task mode (current Task subagent model). */
66
+ taskSelector?: string;
67
+ }
68
+
69
+ /** Fixed chrome rows: top border, status row, footer, bottom border. */
70
+ const CHROME_ROWS = 4;
71
+ /** Rows the browser renders around its list window (search + blank, blank + two detail rows). */
72
+ export const BROWSER_FRAME_ROWS = 5;
73
+ /** Minimum rows for the browser list window on short terminals. */
74
+ const MIN_VISIBLE = 5;
75
+ /** Fraction of the terminal height the floating overlay occupies. */
76
+ const HEIGHT_FRACTION = 0.4;
77
+
78
+ const STATUS_HINT = "Session-only switch — role models stay unchanged";
79
+ const QUICK_ROLE_STATUS_HINT = "Quick role switch — applies its model and thinking for this session";
80
+ const TASK_STATUS_HINT = "Task subagent switch — spawned task agents use this model (session-only)";
81
+ const FOOTER_HINT = "↑/↓ models · Enter use for this session · type to search · @ quick roles · Esc close";
82
+ const QUICK_ROLE_FOOTER_HINT = "↑/↓ roles · Enter apply role model · type to search · Esc close";
83
+ const TASK_FOOTER_HINT = "↑/↓ models · Enter use for Task subagents · type to search · Esc close";
84
+
85
+ /**
86
+ * The alt+p picker component. Hosted as a non-fullscreen bottom-anchored
87
+ * overlay (`ui.showOverlay(..., { anchor: "bottom-center" })`); keyboard-only,
88
+ * since mouse tracking is reserved for fullscreen overlays.
89
+ */
90
+ export class ModelPickerComponent implements Component {
91
+ #tui: TUI;
92
+ #settings: ModelBrowserSource;
93
+ #registry: ModelPickerRegistry;
94
+ #scopedModels: ReadonlyArray<ScopedModelItem>;
95
+ #browser: ModelBrowser;
96
+ #configError: string | undefined;
97
+ #currentSelector: string | undefined;
98
+ #currentQuickRoleSelector: string | undefined;
99
+ #modelItems: ModelBrowserItem[] = [];
100
+ #quickRoleItems: ModelBrowserItem[] = [];
101
+ #quickRoles = new Map<string, ResolvedRoleModel>();
102
+ #roleMode = false;
103
+ #taskMode = false;
104
+ #taskMatchKeys = new Set<string>();
105
+ #taskModeKeyLabel: string;
106
+ #taskSelector: string | undefined;
107
+
108
+ constructor(
109
+ tui: TUI,
110
+ settings: ModelBrowserSource,
111
+ registry: ModelPickerRegistry,
112
+ scopedModels: ReadonlyArray<ScopedModelItem>,
113
+ callbacks: ModelPickerCallbacks,
114
+ options: ModelPickerOptions = {},
115
+ ) {
116
+ this.#tui = tui;
117
+ this.#settings = settings;
118
+ this.#registry = registry;
119
+ this.#scopedModels = scopedModels;
120
+ this.#currentSelector = options.currentSelector;
121
+ this.#currentQuickRoleSelector = options.currentQuickRole ? `@${options.currentQuickRole}` : undefined;
122
+ this.#taskSelector = options.taskSelector;
123
+ this.#taskModeKeyLabel = options.taskModeKeyLabel ?? "alt+p";
124
+ if (callbacks.onPickTask) {
125
+ for (const key of options.taskModeKeys ?? []) addKeyAliases(this.#taskMatchKeys, key);
126
+ }
127
+ this.#quickRoleItems = this.#buildQuickRoleItems(
128
+ options.quickRoles ?? [],
129
+ options.quickRoleOrder ?? options.quickRoles?.map(entry => entry.role) ?? [],
130
+ );
131
+
132
+ this.#browser = new ModelBrowser(settings, {
133
+ currentContextTokens: options.currentContextTokens,
134
+ markOverContext: true,
135
+ emptyText: () => (this.#roleMode ? " No quick roles in the Ctrl+P cycle" : undefined),
136
+ });
137
+ this.#browser.onActivate = item => {
138
+ const quickRole = this.#quickRoles.get(item.selector);
139
+ if (quickRole) {
140
+ callbacks.onPickRole?.(quickRole);
141
+ return;
142
+ }
143
+ if (this.#taskMode) {
144
+ callbacks.onPickTask?.(item.model, item.selector);
145
+ return;
146
+ }
147
+ callbacks.onPick(item.model, item.selector, { overContext: this.#browser.isOverContext(item) });
148
+ };
149
+ this.#browser.onCancel = () => callbacks.onCancel();
150
+ this.#browser.onQueryChange = query => this.#syncItemsForQuery(query);
151
+
152
+ // Hydrate synchronously from the current registry snapshot so the first
153
+ // Enter after opening acts on cached models instead of being dropped
154
+ // while the offline refresh promise is still pending.
155
+ this.#syncFromRegistryState();
156
+ if (options.currentSelector) {
157
+ this.#browser.selectSelector(options.currentSelector);
158
+ }
159
+
160
+ // Reconcile with cached discovery state in the background. A --models
161
+ // scope is registry-independent, so the offline reload would only repeat
162
+ // the synchronous hydration above.
163
+ if (this.#scopedModels.length === 0) {
164
+ this.#registry
165
+ .refresh("offline")
166
+ .then(() => this.#syncFromRegistryState())
167
+ .catch(error => {
168
+ this.#configError = error instanceof Error ? error.message : String(error);
169
+ })
170
+ .finally(() => this.#tui.requestRender());
171
+ }
172
+ }
173
+
174
+ invalidate(): void {}
175
+
176
+ /** Rebuild model items and role chips from the registry's in-memory state. */
177
+ #syncFromRegistryState(): void {
178
+ const scope = buildSessionModelScope(
179
+ this.#settings,
180
+ this.#registry,
181
+ this.#scopedModels.map(s => s.model),
182
+ );
183
+ this.#configError = scope.error;
184
+ this.#modelItems = scope.items;
185
+ this.#browser.setRoles(scope.roles);
186
+ this.#browser.setMruOrder(scope.mruOrder);
187
+ this.#browser.setPerfStats(this.#settings.modelPerf);
188
+ this.#syncItemsForQuery(this.#browser.query, true);
189
+ }
190
+
191
+ /** Build virtual `@role` rows, colored by their ctrl+p segment position. */
192
+ #buildQuickRoleItems(
193
+ quickRoles: ReadonlyArray<ResolvedRoleModel>,
194
+ quickRoleOrder: ReadonlyArray<string>,
195
+ ): ModelBrowserItem[] {
196
+ const order = quickRoleOrder.length > 0 ? quickRoleOrder : quickRoles.map(entry => entry.role);
197
+ const palette = resolveSegmentPalette(order.length);
198
+ return quickRoles.map((entry, index) => {
199
+ const selector = `@${entry.role}`;
200
+ this.#quickRoles.set(selector, entry);
201
+ const orderIndex = order.indexOf(entry.role);
202
+ return {
203
+ provider: "",
204
+ id: selector,
205
+ model: entry.model,
206
+ selector,
207
+ labelColor: palette[(orderIndex >= 0 ? orderIndex : index) % palette.length],
208
+ };
209
+ });
210
+ }
211
+
212
+ /** Switch browser content only when a leading `@` changes the search mode. */
213
+ #syncItemsForQuery(query: string, refresh = false): void {
214
+ const roleMode = query.startsWith("@") && !this.#taskMode;
215
+ const modeChanged = roleMode !== this.#roleMode;
216
+ if (!modeChanged && !refresh) return;
217
+
218
+ this.#roleMode = roleMode;
219
+ this.#browser.setShowProvider(!roleMode);
220
+ this.#browser.setMarkOverContext(!roleMode && !this.#taskMode);
221
+ this.#browser.setPreserveQueryOrder(roleMode);
222
+ const currentSelector = roleMode
223
+ ? this.#currentQuickRoleSelector
224
+ : this.#taskMode
225
+ ? this.#taskSelector
226
+ : this.#currentSelector;
227
+ this.#browser.setCurrentSelector(currentSelector);
228
+ this.#browser.setItems(roleMode ? this.#quickRoleItems : this.#modelItems);
229
+ if (modeChanged && currentSelector) {
230
+ this.#browser.selectSelector(currentSelector);
231
+ }
232
+ }
233
+
234
+ handleInput(data: string): void {
235
+ // Mouse tracking is off outside fullscreen overlays; drop any stray SGR
236
+ // reports instead of feeding them to the search input.
237
+ if (data.startsWith("\x1b[<")) return;
238
+ if (this.#taskMatchKeys.size > 0) {
239
+ const parsed = parseKey(data);
240
+ const canonical = parsed !== undefined ? canonicalKeyId(parsed) : undefined;
241
+ if (canonical !== undefined && this.#taskMatchKeys.has(canonical)) {
242
+ this.#toggleTaskMode();
243
+ return;
244
+ }
245
+ }
246
+ this.#browser.handleInput(data);
247
+ }
248
+ /** Flip between session-model and Task-subagent targets, repointing the highlight. */
249
+ #toggleTaskMode(): void {
250
+ this.#taskMode = !this.#taskMode;
251
+ this.#syncItemsForQuery(this.#browser.query, true);
252
+ const target = this.#taskMode ? this.#taskSelector : this.#currentSelector;
253
+ if (target) this.#browser.selectSelector(target);
254
+ this.#tui.requestRender();
255
+ }
256
+
257
+ render(width: number): string[] {
258
+ const termRows = Math.max(16, this.#tui.terminal?.rows || process.stdout.rows || 40);
259
+ const listBudget = Math.floor(termRows * HEIGHT_FRACTION) - CHROME_ROWS - BROWSER_FRAME_ROWS;
260
+ this.#browser.setMaxVisible(Math.max(MIN_VISIBLE, listBudget));
261
+
262
+ const inner = Math.max(1, width - 4);
263
+ const status = this.#configError
264
+ ? theme.fg("error", ` ${this.#configError}`)
265
+ : this.#taskMode
266
+ ? theme.fg("error", ` ${TASK_STATUS_HINT}`)
267
+ : theme.fg("muted", ` ${this.#roleMode ? QUICK_ROLE_STATUS_HINT : STATUS_HINT}`);
268
+
269
+ const borderColor: ThemeColor | undefined = this.#taskMode ? "error" : undefined;
270
+ let footer = this.#taskMode ? TASK_FOOTER_HINT : this.#roleMode ? QUICK_ROLE_FOOTER_HINT : FOOTER_HINT;
271
+ if (this.#taskMatchKeys.size > 0 && !this.#roleMode) {
272
+ footer += ` · ${this.#taskModeKeyLabel} ${this.#taskMode ? "session model" : "task model"}`;
273
+ }
274
+
275
+ const out: string[] = [];
276
+ out.push(topBorder(width, this.#taskMode ? "Switch Task Model" : "Switch Model", borderColor));
277
+ out.push(row(status, width, borderColor));
278
+ for (const line of this.#browser.render(inner)) {
279
+ out.push(row(line, width, borderColor));
280
+ }
281
+ out.push(row(theme.fg("dim", footer), width, borderColor));
282
+ out.push(bottomBorder(width, borderColor));
283
+ return out;
284
+ }
285
+ }
@@ -0,0 +1,107 @@
1
+ import { ThinkingLevel } from "@oh-my-pi/pi-agent-core/thinking";
2
+ import { AUTO_THINKING, type ConfiguredThinkingLevel, parseThinkingLevel } from "../thinking";
3
+
4
+ /** Opt-in selectors that can otherwise be literal model-id suffixes. */
5
+ export interface ThinkingSuffixOptions {
6
+ allowMaxSuffix?: boolean;
7
+ allowAutoAlias?: boolean;
8
+ }
9
+
10
+ /** Selector parsing options with authoritative literal-model lookup. */
11
+ export interface ModelStringParseOptions extends ThinkingSuffixOptions {
12
+ isLiteralModelId?: (provider: string, id: string) => boolean;
13
+ }
14
+ // Suffix recognition for the model-pattern parser: `:max` is a real thinking
15
+ // level and `:auto` maps to the auto sentinel. Both are gated behind flags
16
+ // (and the literal-id / exact-match guards on the callers) because real model
17
+ // ids end in `:max` (e.g. `glm-4.7:max`) — an ungated split would silently
18
+ // reinterpret them as a thinking suffix.
19
+ /** Recognize all configured effort selectors after literal-id matching. */
20
+ export const MAX_THINKING_SUFFIX_OPTIONS: ThinkingSuffixOptions = { allowMaxSuffix: true, allowAutoAlias: true };
21
+
22
+ /** Parse a suffix while preserving selectors not explicitly enabled. */
23
+ export function parseThinkingSuffix(
24
+ value: string,
25
+ options?: ThinkingSuffixOptions,
26
+ ): ConfiguredThinkingLevel | undefined {
27
+ const level = parseThinkingLevel(value);
28
+ if (level === ThinkingLevel.Max) return options?.allowMaxSuffix === true ? level : undefined;
29
+ if (level !== undefined) return level;
30
+ if (options?.allowAutoAlias === true && value === AUTO_THINKING) return AUTO_THINKING;
31
+ return undefined;
32
+ }
33
+
34
+ /**
35
+ * Split a trailing `:<level>` thinking selector off a model pattern.
36
+ *
37
+ * `level` is set when the suffix parses as a concrete thinking level (or, when
38
+ * the caller opts in via `allowMaxSuffix`/`allowAutoAlias`, the guarded `:max`
39
+ * level / `:auto` sentinel); `base` then has the suffix stripped. Otherwise
40
+ * `base` is the input.
41
+ * `minColonIndex` requires the colon to appear strictly after that index —
42
+ * role-alias callers pass the matched alias prefix length.
43
+ */
44
+ export function splitThinkingSuffix(
45
+ pattern: string,
46
+ minColonIndex = -1,
47
+ options?: ThinkingSuffixOptions,
48
+ ): { base: string; level?: ConfiguredThinkingLevel } {
49
+ const colonIdx = pattern.lastIndexOf(":");
50
+ if (colonIdx <= minColonIndex) return { base: pattern };
51
+ const level = parseThinkingSuffix(pattern.slice(colonIdx + 1), options);
52
+ return level ? { base: pattern.slice(0, colonIdx), level } : { base: pattern };
53
+ }
54
+
55
+ /**
56
+ * Parse a model string in "provider/modelId" format.
57
+ * Returns undefined if the format is invalid.
58
+ */
59
+ export function parseModelString(
60
+ modelStr: string,
61
+ options?: ModelStringParseOptions,
62
+ ): { provider: string; id: string; thinkingLevel?: ConfiguredThinkingLevel } | undefined {
63
+ const slashIdx = modelStr.indexOf("/");
64
+ if (slashIdx <= 0) return undefined;
65
+ const id = modelStr.slice(slashIdx + 1);
66
+ const provider = modelStr.slice(0, slashIdx);
67
+ // Strip strict thinking level suffixes first (e.g. "claude-sonnet-4-6:high" -> id "claude-sonnet-4-6", thinkingLevel "high").
68
+ const strict = splitThinkingSuffix(id);
69
+ if (strict.level) return { provider, id: strict.base, thinkingLevel: strict.level };
70
+ // `max` is a real thinking level, but real model IDs can also end in
71
+ // `:max`. Context-aware callers pass a literal lookup so those models win.
72
+ const maxAlias = splitThinkingSuffix(id, -1, options);
73
+ if (maxAlias.level) {
74
+ return options?.isLiteralModelId?.(provider, id) === true
75
+ ? { provider, id }
76
+ : { provider, id: maxAlias.base, thinkingLevel: maxAlias.level };
77
+ }
78
+ return { provider, id };
79
+ }
80
+
81
+ export function formatModelSelectorValue(selector: string, thinkingLevel: ConfiguredThinkingLevel | undefined): string {
82
+ return thinkingLevel && thinkingLevel !== ThinkingLevel.Inherit ? `${selector}:${thinkingLevel}` : selector;
83
+ }
84
+
85
+ /** Bare slug (`cerebras`) or tiered/regional slug (`google-ai-studio/priority`, `google-vertex/global/flex`). */
86
+ const UPSTREAM_ROUTING_SLUG = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\/[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*$/i;
87
+
88
+ /**
89
+ * Split a trailing `@<upstream>` provider-routing selector off a model pattern.
90
+ *
91
+ * `openrouter/z-ai/glm-4.7@cerebras` -> base `openrouter/z-ai/glm-4.7`, upstream
92
+ * `cerebras`. Tiered upstreams keep their path (`...@google-ai-studio/priority`).
93
+ * A `:thinking` suffix after the slug is kept on the base
94
+ * (`...@cerebras:high` -> base `...:high`). Returns undefined when there is no
95
+ * `@` or the suffix is not a bare provider slug, so model ids that legitimately
96
+ * contain `@` (`claude-opus-4-8@default`, `workers-ai/@cf/...`) are never split.
97
+ */
98
+ export function splitUpstreamRouting(pattern: string): { base: string; upstream: string } | undefined {
99
+ const at = pattern.lastIndexOf("@");
100
+ if (at <= 0) return undefined;
101
+ const rest = pattern.slice(at + 1);
102
+ const colon = rest.indexOf(":");
103
+ const upstream = colon === -1 ? rest : rest.slice(0, colon);
104
+ if (!UPSTREAM_ROUTING_SLUG.test(upstream)) return undefined;
105
+ const trailing = colon === -1 ? "" : rest.slice(colon);
106
+ return { base: pattern.slice(0, at) + trailing, upstream };
107
+ }
@@ -0,0 +1,197 @@
1
+ /**
2
+ * `/move` overlay: a path input with live directory autocomplete.
3
+ *
4
+ * Rendered as a centered modal via `showHookCustom(..., { overlay: true })`.
5
+ * The user types a path, Tab autocompletes the highlighted directory, and Enter
6
+ * confirms — yielding the resolved directory string (or `undefined` on cancel).
7
+ */
8
+ import { type Component, type Focusable, Key, matchesKey } from "../index";
9
+ import { theme } from "../theme/theme";
10
+ import { matchesSelectCancel, matchesSelectDown, matchesSelectUp } from "../keybinding-matchers";
11
+ import { formTheme } from "../chrome/form-theme";
12
+ import { bottomBorder, row, topBorder } from "../chrome/overlay-box";
13
+ import { TextFormField } from "../components/form";
14
+
15
+ export interface MoveOverlayResult {
16
+ directory: string;
17
+ }
18
+
19
+ /** Directory suggestion displayed by the move dialog. */
20
+ export interface MoveDirectoryEntry {
21
+ /** Full absolute path. */
22
+ value: string;
23
+ /** Display label (basename + trailing slash). */
24
+ label: string;
25
+ }
26
+
27
+ /** Directory autocomplete supplied by the host. */
28
+ export interface MoveDirectorySource {
29
+ search(prefix: string, cwd: string, max: number): MoveDirectoryEntry[];
30
+ }
31
+
32
+ const MAX_RESULTS = 15;
33
+
34
+ /**
35
+ * Overlay component for `/move`: a single-line path input with a live-filtered
36
+ * list of matching directories. Tab accepts the highlighted suggestion; Enter
37
+ * confirms the current input (or the highlighted suggestion if the input is
38
+ * empty); Escape cancels.
39
+ */
40
+ export class MoveOverlay implements Component, Focusable {
41
+ #field: TextFormField;
42
+ #focused = false;
43
+ #selectedIndex = 0;
44
+ #results: MoveDirectoryEntry[] = [];
45
+ #cwd: string;
46
+ #source: MoveDirectorySource;
47
+ #done: (result: MoveOverlayResult | undefined) => void;
48
+ #revision = 0;
49
+ #renderMemo:
50
+ | { width: number; fieldLines: readonly string[]; revision: number; lines: readonly string[] }
51
+ | undefined;
52
+
53
+ constructor(cwd: string, done: (result: MoveOverlayResult | undefined) => void, source: MoveDirectorySource) {
54
+ this.#cwd = cwd;
55
+ this.#source = source;
56
+ this.#done = done;
57
+ this.#field = new TextFormField({
58
+ theme: formTheme,
59
+ prompt: theme.fg("dim", "Path: "),
60
+ empty: "submit",
61
+ spaceBeforeControl: false,
62
+ spaceAfterControl: false,
63
+ onSubmit: () => this.#confirm(),
64
+ onCancel: () => this.#done(undefined),
65
+ });
66
+ this.#field.focused = this.#focused;
67
+ this.#updateResults();
68
+ }
69
+
70
+ get focused(): boolean {
71
+ return this.#focused;
72
+ }
73
+
74
+ set focused(value: boolean) {
75
+ this.#focused = value;
76
+ this.#field.focused = value;
77
+ }
78
+
79
+ setUseTerminalCursor(useTerminalCursor: boolean): void {
80
+ this.#field.setUseTerminalCursor(useTerminalCursor);
81
+ }
82
+
83
+ pasteText(text: string): void {
84
+ this.#field.pasteText(text);
85
+ this.#selectedIndex = 0;
86
+ this.#updateResults();
87
+ }
88
+
89
+ handleInput(data: string): void {
90
+ if (matchesSelectCancel(data) || matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl("c"))) {
91
+ this.#done(undefined);
92
+ return;
93
+ }
94
+ if (matchesKey(data, Key.enter) || matchesKey(data, Key.return)) {
95
+ this.#field.submit();
96
+ return;
97
+ }
98
+ if (matchesSelectUp(data) || matchesKey(data, Key.up)) {
99
+ if (this.#results.length > 0) {
100
+ const next = Math.max(0, this.#selectedIndex - 1);
101
+ if (next !== this.#selectedIndex) {
102
+ this.#selectedIndex = next;
103
+ this.#revision++;
104
+ }
105
+ }
106
+ return;
107
+ }
108
+ if (matchesSelectDown(data) || matchesKey(data, Key.down)) {
109
+ if (this.#results.length > 0) {
110
+ const next = Math.min(this.#results.length - 1, this.#selectedIndex + 1);
111
+ if (next !== this.#selectedIndex) {
112
+ this.#selectedIndex = next;
113
+ this.#revision++;
114
+ }
115
+ }
116
+ return;
117
+ }
118
+ if (matchesKey(data, Key.tab)) {
119
+ const selected = this.#results[this.#selectedIndex];
120
+ if (selected) {
121
+ this.#field.setValue(selected.value);
122
+ this.#selectedIndex = 0;
123
+ this.#updateResults();
124
+ }
125
+ return;
126
+ }
127
+ const before = this.#field.getValue();
128
+ this.#field.handleInput(data);
129
+ if (this.#field.getValue() !== before) {
130
+ this.#selectedIndex = 0;
131
+ this.#updateResults();
132
+ }
133
+ }
134
+
135
+ render(width: number): readonly string[] {
136
+ const w = width;
137
+ const innerWidth = Math.max(1, w - 4);
138
+ const fieldLines = this.#field.render(innerWidth);
139
+ const memo = this.#renderMemo;
140
+ if (memo?.width === w && memo.fieldLines === fieldLines && memo.revision === this.#revision) {
141
+ return memo.lines;
142
+ }
143
+ const lines: string[] = [];
144
+
145
+ lines.push(topBorder(w, "Move to directory"));
146
+ for (const fieldLine of fieldLines) {
147
+ lines.push(row(fieldLine, w));
148
+ }
149
+ lines.push(row("", w));
150
+
151
+ if (this.#results.length === 0 && this.#field.getValue().length > 0) {
152
+ lines.push(row(theme.fg("dim", "No matching directories"), w));
153
+ } else {
154
+ for (let i = 0; i < Math.min(this.#results.length, MAX_RESULTS); i++) {
155
+ const item = this.#results[i]!;
156
+ const selected = i === this.#selectedIndex;
157
+ const marker = selected ? theme.fg("accent", "▶ ") : " ";
158
+ const label = selected ? theme.fg("accent", item.label) : theme.fg("text", item.label);
159
+ lines.push(row(`${marker}${label}`, w));
160
+ }
161
+ }
162
+
163
+ lines.push(row("", w));
164
+ lines.push(row(theme.fg("dim", "Type to filter · ↑↓ navigate · Tab accept · Enter confirm · Esc cancel"), w));
165
+ lines.push(bottomBorder(w));
166
+ this.#renderMemo = { width: w, fieldLines, revision: this.#revision, lines };
167
+ return lines;
168
+ }
169
+
170
+ invalidate(): void {
171
+ this.#field.input.prompt = theme.fg("dim", "Path: ");
172
+ this.#field.invalidate();
173
+ this.#revision++;
174
+ this.#renderMemo = undefined;
175
+ }
176
+
177
+ #updateResults(): void {
178
+ this.#results = this.#source.search(this.#field.getValue(), this.#cwd, MAX_RESULTS + 5);
179
+ this.#revision++;
180
+ if (this.#selectedIndex >= this.#results.length) {
181
+ this.#selectedIndex = Math.max(0, this.#results.length - 1);
182
+ }
183
+ }
184
+
185
+ #confirm(): void {
186
+ const selected = this.#results[this.#selectedIndex];
187
+ if (selected) {
188
+ this.#done({ directory: selected.value });
189
+ return;
190
+ }
191
+ if (this.#field.getValue().trim().length > 0) {
192
+ this.#done({ directory: this.#field.getValue().trim() });
193
+ return;
194
+ }
195
+ this.#done(undefined);
196
+ }
197
+ }