@oh-my-pi/pi-tui 18.2.3 → 18.2.5

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 (750) hide show
  1. package/CHANGELOG.md +29 -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/image.d.ts +18 -16
  92. package/dist/types/components/key-value-list.d.ts +24 -0
  93. package/dist/types/components/layout/geometry.d.ts +73 -0
  94. package/dist/types/components/layout/row.d.ts +55 -0
  95. package/dist/types/components/layout/split-pane.d.ts +80 -0
  96. package/dist/types/components/layout/stack.d.ts +50 -0
  97. package/dist/types/components/menu-selection.d.ts +71 -0
  98. package/dist/types/components/metric.d.ts +44 -0
  99. package/dist/types/components/progress-bar.d.ts +36 -0
  100. package/dist/types/components/scroll-view.d.ts +53 -19
  101. package/dist/types/components/scroll-viewport.d.ts +46 -0
  102. package/dist/types/components/section.d.ts +19 -0
  103. package/dist/types/components/select-list.d.ts +46 -2
  104. package/dist/types/components/settings-list.d.ts +20 -0
  105. package/dist/types/components/table.d.ts +32 -0
  106. package/dist/types/components/tree-view.d.ts +130 -0
  107. package/dist/types/components/wizard-step.d.ts +60 -0
  108. package/dist/types/hotkeys-markdown.d.ts +7 -0
  109. package/dist/types/index.d.ts +17 -0
  110. package/dist/types/keybinding-matchers.d.ts +35 -0
  111. package/dist/types/keys.d.ts +2 -2
  112. package/dist/types/lang-from-path.d.ts +9 -0
  113. package/dist/types/overlays/advisor-config.d.ts +114 -0
  114. package/dist/types/overlays/agent-activity.d.ts +41 -0
  115. package/dist/types/overlays/agent-hub-projection.d.ts +33 -0
  116. package/dist/types/overlays/agent-hub-renderer.d.ts +53 -0
  117. package/dist/types/overlays/agent-hub-types.d.ts +99 -0
  118. package/dist/types/overlays/agent-hub.d.ts +126 -0
  119. package/dist/types/overlays/agent-transcript-viewer.d.ts +71 -0
  120. package/dist/types/overlays/agents-hub.d.ts +72 -0
  121. package/dist/types/overlays/ask-dialog.d.ts +88 -0
  122. package/dist/types/overlays/bordered-loader.d.ts +11 -0
  123. package/dist/types/overlays/btw-history-panel.d.ts +29 -0
  124. package/dist/types/overlays/btw-history.d.ts +17 -0
  125. package/dist/types/overlays/btw-panel.d.ts +26 -0
  126. package/dist/types/overlays/cleanse-panel.d.ts +36 -0
  127. package/dist/types/overlays/codex-reset-fireworks.d.ts +52 -0
  128. package/dist/types/overlays/composer-shape-preview.d.ts +47 -0
  129. package/dist/types/overlays/composer-shape-registry.d.ts +50 -0
  130. package/dist/types/overlays/copy-selector.d.ts +48 -0
  131. package/dist/types/overlays/copy-targets.d.ts +63 -0
  132. package/dist/types/overlays/error-banner.d.ts +13 -0
  133. package/dist/types/overlays/extensions/display-text.d.ts +10 -0
  134. package/dist/types/overlays/extensions/extension-dashboard.d.ts +63 -0
  135. package/dist/types/overlays/extensions/extension-list.d.ts +54 -0
  136. package/dist/types/overlays/extensions/inspector-model.d.ts +109 -0
  137. package/dist/types/overlays/extensions/inspector-panel.d.ts +17 -0
  138. package/dist/types/overlays/extensions/live-tool-session.d.ts +28 -0
  139. package/dist/types/overlays/extensions/mcp-runtime.d.ts +107 -0
  140. package/dist/types/overlays/extensions/state-manager.d.ts +42 -0
  141. package/dist/types/overlays/extensions/types.d.ts +165 -0
  142. package/dist/types/overlays/history-search.d.ts +16 -0
  143. package/dist/types/overlays/hook-editor.d.ts +44 -0
  144. package/dist/types/overlays/hook-input.d.ts +20 -0
  145. package/dist/types/overlays/hook-selector.d.ts +71 -0
  146. package/dist/types/overlays/hub-frame.d.ts +77 -0
  147. package/dist/types/overlays/login-dialog.d.ts +43 -0
  148. package/dist/types/overlays/logout-account-selector.d.ts +15 -0
  149. package/dist/types/overlays/mcp-add-wizard.d.ts +87 -0
  150. package/dist/types/overlays/model-browser.d.ts +213 -0
  151. package/dist/types/overlays/model-hub.d.ts +72 -0
  152. package/dist/types/overlays/model-picker.d.ts +74 -0
  153. package/dist/types/overlays/model-selector.d.ts +52 -0
  154. package/dist/types/overlays/move-overlay.d.ts +39 -0
  155. package/dist/types/overlays/oauth-selector.d.ts +41 -0
  156. package/dist/types/overlays/omfg-panel.d.ts +20 -0
  157. package/dist/types/overlays/pause-screen.d.ts +43 -0
  158. package/dist/types/overlays/plan-review-overlay.d.ts +89 -0
  159. package/dist/types/overlays/plan-save-overlay.d.ts +19 -0
  160. package/dist/types/overlays/plan-toc.d.ts +41 -0
  161. package/dist/types/overlays/plugin-selector.d.ts +28 -0
  162. package/dist/types/overlays/plugin-settings.d.ts +180 -0
  163. package/dist/types/overlays/queue-mode-selector.d.ts +11 -0
  164. package/dist/types/overlays/reset-usage-selector.d.ts +23 -0
  165. package/dist/types/overlays/rewind-selector.d.ts +61 -0
  166. package/dist/types/overlays/running-subagent-badge.d.ts +6 -0
  167. package/dist/types/overlays/session-account-selector.d.ts +24 -0
  168. package/dist/types/overlays/session-info-overlay.d.ts +17 -0
  169. package/dist/types/overlays/session-observer-registry.d.ts +77 -0
  170. package/dist/types/overlays/session-selector.d.ts +131 -0
  171. package/dist/types/overlays/settings-defs.d.ts +119 -0
  172. package/dist/types/overlays/settings-selector.d.ts +73 -0
  173. package/dist/types/overlays/show-images-selector.d.ts +11 -0
  174. package/dist/types/overlays/snapcompact-shape-preview.d.ts +31 -0
  175. package/dist/types/overlays/theme-selector.d.ts +12 -0
  176. package/dist/types/overlays/thinking-selector.d.ts +12 -0
  177. package/dist/types/overlays/tiny-title-download-progress.d.ts +21 -0
  178. package/dist/types/overlays/tree-selector.d.ts +92 -0
  179. package/dist/types/overlays/usage-dashboard.d.ts +94 -0
  180. package/dist/types/overlays/usage-display.d.ts +5 -0
  181. package/dist/types/overlays/usage-row.d.ts +17 -0
  182. package/dist/types/prompt/attachment-chips.d.ts +19 -0
  183. package/dist/types/prompt/composer-attachments.d.ts +71 -0
  184. package/dist/types/prompt/composer-cache.d.ts +37 -0
  185. package/dist/types/prompt/composer.d.ts +159 -0
  186. package/dist/types/prompt/custom-editor.d.ts +261 -0
  187. package/dist/types/prompt/editor-top-gap.d.ts +18 -0
  188. package/dist/types/prompt/emoji-autocomplete.d.ts +16 -0
  189. package/dist/types/prompt/github-ref-autocomplete.d.ts +35 -0
  190. package/dist/types/prompt/gradient-highlight.d.ts +32 -0
  191. package/dist/types/prompt/image-format.d.ts +4 -0
  192. package/dist/types/prompt/image-references.d.ts +26 -0
  193. package/dist/types/prompt/interactive-context-helpers.d.ts +43 -0
  194. package/dist/types/prompt/internal-url-autocomplete.d.ts +56 -0
  195. package/dist/types/prompt/macos-spelling.d.ts +44 -0
  196. package/dist/types/prompt/magic-keyword-boundary.d.ts +9 -0
  197. package/dist/types/prompt/magic-keywords.d.ts +26 -0
  198. package/dist/types/prompt/markdown-prose.d.ts +15 -0
  199. package/dist/types/prompt/model-mention-autocomplete.d.ts +25 -0
  200. package/dist/types/prompt/model-mention-syntax.d.ts +24 -0
  201. package/dist/types/prompt/orchestrate.d.ts +13 -0
  202. package/dist/types/prompt/prompt-action-autocomplete.d.ts +56 -0
  203. package/dist/types/prompt/queue-input.d.ts +8 -0
  204. package/dist/types/prompt/skill-tokens.d.ts +13 -0
  205. package/dist/types/prompt/tools-markdown.d.ts +12 -0
  206. package/dist/types/prompt/ultrathink.d.ts +13 -0
  207. package/dist/types/prompt/usage-amounts.d.ts +26 -0
  208. package/dist/types/prompt/video.d.ts +18 -0
  209. package/dist/types/prompt/welcome.d.ts +83 -0
  210. package/dist/types/prompt/workflow.d.ts +13 -0
  211. package/dist/types/render/code-cell.d.ts +51 -0
  212. package/dist/types/render/file-list.d.ts +22 -0
  213. package/dist/types/render/hyperlink.d.ts +80 -0
  214. package/dist/types/render/index.d.ts +16 -0
  215. package/dist/types/render/output-block.d.ts +54 -0
  216. package/dist/types/render/output-pane.d.ts +80 -0
  217. package/dist/types/render/render-utils.d.ts +312 -0
  218. package/dist/types/render/sixel.d.ts +21 -0
  219. package/dist/types/render/status-line.d.ts +23 -0
  220. package/dist/types/render/tool-card.d.ts +71 -0
  221. package/dist/types/render/tree-list.d.ts +29 -0
  222. package/dist/types/render/types.d.ts +17 -0
  223. package/dist/types/render/utils.d.ts +43 -0
  224. package/dist/types/render/width-aware-text.d.ts +23 -0
  225. package/dist/types/setup/lazy.d.ts +3 -0
  226. package/dist/types/setup/scenes/composer.d.ts +3 -0
  227. package/dist/types/setup/scenes/glyph.d.ts +3 -0
  228. package/dist/types/setup/scenes/model.d.ts +3 -0
  229. package/dist/types/setup/scenes/outro.d.ts +2 -0
  230. package/dist/types/setup/scenes/providers.d.ts +3 -0
  231. package/dist/types/setup/scenes/sign-in.d.ts +21 -0
  232. package/dist/types/setup/scenes/splash.d.ts +11 -0
  233. package/dist/types/setup/scenes/theme.d.ts +3 -0
  234. package/dist/types/setup/scenes/types.d.ts +110 -0
  235. package/dist/types/setup/scenes/web-search.d.ts +22 -0
  236. package/dist/types/setup/setup-version.d.ts +11 -0
  237. package/dist/types/setup/startup-splash.d.ts +9 -0
  238. package/dist/types/setup/wizard-overlay.d.ts +16 -0
  239. package/dist/types/setup/wizard.d.ts +25 -0
  240. package/dist/types/status-line/component.d.ts +182 -0
  241. package/dist/types/status-line/context-usage.d.ts +156 -0
  242. package/dist/types/status-line/footer.d.ts +30 -0
  243. package/dist/types/status-line/git-utils.d.ts +22 -0
  244. package/dist/types/status-line/host.d.ts +129 -0
  245. package/dist/types/status-line/index.d.ts +6 -0
  246. package/dist/types/status-line/loop.d.ts +18 -0
  247. package/dist/types/status-line/metrics.d.ts +21 -0
  248. package/dist/types/status-line/presets.d.ts +3 -0
  249. package/dist/types/status-line/schema.d.ts +15 -0
  250. package/dist/types/status-line/segments.d.ts +5 -0
  251. package/dist/types/status-line/separators.d.ts +3 -0
  252. package/dist/types/status-line/types.d.ts +236 -0
  253. package/dist/types/stdin-buffer.d.ts +4 -0
  254. package/dist/types/theme/color.d.ts +24 -0
  255. package/dist/types/theme/defaults/index.d.ts +9489 -0
  256. package/dist/types/theme/index.d.ts +4 -0
  257. package/dist/types/theme/loader.d.ts +23 -0
  258. package/dist/types/theme/mermaid-cache.d.ts +26 -0
  259. package/dist/types/theme/schema-validation.d.ts +3 -0
  260. package/dist/types/theme/schema.d.ts +25 -0
  261. package/dist/types/theme/session-color.d.ts +43 -0
  262. package/dist/types/theme/shimmer.d.ts +44 -0
  263. package/dist/types/theme/symbols.d.ts +34 -0
  264. package/dist/types/theme/theme-class.d.ts +299 -0
  265. package/dist/types/theme/theme.d.ts +111 -0
  266. package/dist/types/theme/tui-adapters.d.ts +30 -0
  267. package/dist/types/thinking.d.ts +165 -0
  268. package/dist/types/tools/agent-tree.d.ts +36 -0
  269. package/dist/types/tools/ask.d.ts +67 -0
  270. package/dist/types/tools/ast-edit.d.ts +53 -0
  271. package/dist/types/tools/ast-grep.d.ts +52 -0
  272. package/dist/types/tools/autoresearch.d.ts +156 -0
  273. package/dist/types/tools/bash-interactive.d.ts +28 -0
  274. package/dist/types/tools/bash.d.ts +103 -0
  275. package/dist/types/tools/conflict-detect.d.ts +43 -0
  276. package/dist/types/tools/debug.d.ts +60 -0
  277. package/dist/types/tools/default-renderer.d.ts +24 -0
  278. package/dist/types/tools/edit.d.ts +158 -0
  279. package/dist/types/tools/eval-format/code-mode-declarations.d.ts +5 -0
  280. package/dist/types/tools/eval-format/index.d.ts +5 -0
  281. package/dist/types/tools/eval-format/javascript.d.ts +2 -0
  282. package/dist/types/tools/eval-format/python.d.ts +2 -0
  283. package/dist/types/tools/eval.d.ts +94 -0
  284. package/dist/types/tools/fetch.d.ts +42 -0
  285. package/dist/types/tools/gh-format.d.ts +8 -0
  286. package/dist/types/tools/github.d.ts +144 -0
  287. package/dist/types/tools/glob.d.ts +44 -0
  288. package/dist/types/tools/goal.d.ts +42 -0
  289. package/dist/types/tools/grep.d.ts +64 -0
  290. package/dist/types/tools/grouped-file-output.d.ts +71 -0
  291. package/dist/types/tools/hashline-format.d.ts +28 -0
  292. package/dist/types/tools/hub.d.ts +340 -0
  293. package/dist/types/tools/index.d.ts +4 -0
  294. package/dist/types/tools/json-tree.d.ts +59 -0
  295. package/dist/types/tools/line-ranges.d.ts +29 -0
  296. package/dist/types/tools/list-limit.d.ts +15 -0
  297. package/dist/types/tools/lsp.d.ts +72 -0
  298. package/dist/types/tools/match-line-format.d.ts +11 -0
  299. package/dist/types/tools/mcp.d.ts +81 -0
  300. package/dist/types/tools/memory.d.ts +67 -0
  301. package/dist/types/tools/output-meta.d.ts +151 -0
  302. package/dist/types/tools/read.d.ts +139 -0
  303. package/dist/types/tools/renderer.d.ts +98 -0
  304. package/dist/types/tools/report-tool-issue.d.ts +8 -0
  305. package/dist/types/tools/resolve.d.ts +47 -0
  306. package/dist/types/tools/streaming-output.d.ts +282 -0
  307. package/dist/types/tools/subprocess.d.ts +24 -0
  308. package/dist/types/tools/task-repair-args.d.ts +53 -0
  309. package/dist/types/tools/task-yield-assembly.d.ts +20 -0
  310. package/dist/types/tools/task.d.ts +425 -0
  311. package/dist/types/tools/terminal-output.d.ts +8 -0
  312. package/dist/types/tools/think.d.ts +13 -0
  313. package/dist/types/tools/todo.d.ts +118 -0
  314. package/dist/types/tools/tool-errors.d.ts +7 -0
  315. package/dist/types/tools/vibe.d.ts +120 -0
  316. package/dist/types/tools/web-search.d.ts +195 -0
  317. package/dist/types/tools/write.d.ts +76 -0
  318. package/dist/types/tools/xd-url.d.ts +13 -0
  319. package/dist/types/tools/xdev.d.ts +52 -0
  320. package/dist/types/tui.d.ts +18 -0
  321. package/dist/types/utils.d.ts +2 -0
  322. package/package.json +37 -3
  323. package/src/app-keybindings.ts +760 -0
  324. package/src/apps/autoresearch-dashboard.ts +500 -0
  325. package/src/apps/autoresearch-data.ts +64 -0
  326. package/src/apps/cleanse-board.ts +341 -0
  327. package/src/apps/cleanse-picker.ts +57 -0
  328. package/src/apps/debug/log-formatting.ts +53 -0
  329. package/src/apps/debug/log-viewer.ts +868 -0
  330. package/src/apps/debug/protocol-probe.ts +267 -0
  331. package/src/apps/debug/raw-sse-buffer.ts +449 -0
  332. package/src/apps/debug/raw-sse.ts +282 -0
  333. package/src/apps/debug/terminal-info.ts +115 -0
  334. package/src/apps/debug/viewer-frame.ts +174 -0
  335. package/src/apps/git/avatar.ts +52 -0
  336. package/src/apps/git/colors.ts +109 -0
  337. package/src/apps/git/diff-pane.ts +1512 -0
  338. package/src/apps/git/git-tui.ts +889 -0
  339. package/src/apps/git/sidebar.ts +1204 -0
  340. package/src/apps/git/state.ts +113 -0
  341. package/src/apps/if-bench-board.ts +324 -0
  342. package/src/apps/live-visualizer.ts +238 -0
  343. package/src/apps/ps-data.ts +116 -0
  344. package/src/apps/ps-top.ts +422 -0
  345. package/src/apps/session-picker.ts +95 -0
  346. package/src/apps/setup-model-picker.ts +21 -0
  347. package/src/apps/standalone-picker.ts +111 -0
  348. package/src/autocomplete.ts +9 -13
  349. package/src/chat/advisor-message.ts +175 -0
  350. package/src/chat/assistant-message.ts +1214 -0
  351. package/src/chat/background-tan-message.ts +35 -0
  352. package/src/chat/bash-execution.ts +394 -0
  353. package/src/chat/cache-invalidation-marker.ts +94 -0
  354. package/src/chat/chat-transcript-builder.ts +593 -0
  355. package/src/chat/collab-prompt-message.ts +34 -0
  356. package/src/chat/compaction-summary-message.ts +261 -0
  357. package/src/chat/custom-message.ts +23 -0
  358. package/src/chat/display-preferences.ts +24 -0
  359. package/src/chat/eval-execution.ts +172 -0
  360. package/src/chat/execution-shared.ts +113 -0
  361. package/src/chat/extension-types.ts +46 -0
  362. package/src/chat/hook-message.ts +20 -0
  363. package/src/chat/image-loading.ts +122 -0
  364. package/src/chat/late-diagnostics-message.ts +92 -0
  365. package/src/chat/messages.ts +305 -0
  366. package/src/chat/reaction.ts +65 -0
  367. package/src/chat/read-target.ts +7 -0
  368. package/src/chat/read-tool-group.ts +873 -0
  369. package/src/chat/served-model-marker.ts +91 -0
  370. package/src/chat/skill-message.ts +220 -0
  371. package/src/chat/skill-title-input.ts +41 -0
  372. package/src/chat/stripped-tool-calls-placeholder.ts +35 -0
  373. package/src/chat/thinking-display.ts +312 -0
  374. package/src/chat/todo-reminder.ts +33 -0
  375. package/src/chat/tool-execution.ts +1395 -0
  376. package/src/chat/transcript-browser.ts +268 -0
  377. package/src/chat/transcript-entry.ts +96 -0
  378. package/src/chat/transcript-outline.ts +260 -0
  379. package/src/chat/transcript-render-helpers.ts +315 -0
  380. package/src/chat/ttsr-notification.ts +123 -0
  381. package/src/chat/user-message.ts +287 -0
  382. package/src/chrome/chat-block.ts +110 -0
  383. package/src/chrome/collab-qrcode.ts +74 -0
  384. package/src/chrome/context-thresholds.ts +85 -0
  385. package/src/chrome/countdown-timer.ts +74 -0
  386. package/src/chrome/diff.ts +266 -0
  387. package/src/chrome/dynamic-border.ts +36 -0
  388. package/src/chrome/error-block.ts +63 -0
  389. package/src/chrome/form-theme.ts +10 -0
  390. package/src/chrome/format.ts +66 -0
  391. package/src/chrome/index.ts +21 -0
  392. package/src/chrome/keybinding-hints.ts +55 -0
  393. package/src/chrome/live-board.ts +123 -0
  394. package/src/chrome/local-date.ts +20 -0
  395. package/src/chrome/message-divider.ts +51 -0
  396. package/src/chrome/message-frame.ts +164 -0
  397. package/src/chrome/message-notice.ts +103 -0
  398. package/src/chrome/overlay-box.ts +301 -0
  399. package/src/chrome/qrcode.ts +539 -0
  400. package/src/chrome/segment-track.ts +86 -0
  401. package/src/chrome/select-list-mouse-routing.ts +11 -0
  402. package/src/chrome/selector-helpers.ts +119 -0
  403. package/src/chrome/shared.ts +27 -0
  404. package/src/chrome/streaming-panel.ts +72 -0
  405. package/src/chrome/tool-activity.ts +44 -0
  406. package/src/chrome/transcript-container.ts +902 -0
  407. package/src/chrome/transcript-status.ts +27 -0
  408. package/src/chrome/visual-truncate.ts +70 -0
  409. package/src/components/disclosure.ts +235 -0
  410. package/src/components/editor.ts +10 -12
  411. package/src/components/form.ts +566 -0
  412. package/src/components/image.ts +80 -53
  413. package/src/components/input.ts +6 -27
  414. package/src/components/key-value-list.ts +88 -0
  415. package/src/components/layout/geometry.ts +202 -0
  416. package/src/components/layout/row.ts +283 -0
  417. package/src/components/layout/split-pane.ts +349 -0
  418. package/src/components/layout/stack.ts +261 -0
  419. package/src/components/markdown.ts +16 -12
  420. package/src/components/menu-selection.ts +248 -0
  421. package/src/components/metric.ts +132 -0
  422. package/src/components/progress-bar.ts +140 -0
  423. package/src/components/scroll-view.ts +372 -70
  424. package/src/components/scroll-viewport.ts +154 -0
  425. package/src/components/section.ts +77 -0
  426. package/src/components/select-list.ts +238 -159
  427. package/src/components/settings-list.ts +103 -80
  428. package/src/components/table.ts +127 -0
  429. package/src/components/tree-view.ts +481 -0
  430. package/src/components/wizard-step.ts +229 -0
  431. package/src/deccara.ts +1 -3
  432. package/src/hotkeys-markdown.ts +100 -0
  433. package/src/index.ts +18 -0
  434. package/src/keybinding-matchers.ts +99 -0
  435. package/src/keys.ts +2 -2
  436. package/src/lang-from-path.ts +252 -0
  437. package/src/overlays/advisor-config.ts +761 -0
  438. package/src/overlays/agent-activity.ts +113 -0
  439. package/src/overlays/agent-hub-projection.ts +250 -0
  440. package/src/overlays/agent-hub-renderer.ts +281 -0
  441. package/src/overlays/agent-hub-types.ts +74 -0
  442. package/src/overlays/agent-hub.ts +1562 -0
  443. package/src/overlays/agent-transcript-viewer.ts +669 -0
  444. package/src/overlays/agents-hub.ts +1203 -0
  445. package/src/overlays/ask-dialog.ts +1202 -0
  446. package/src/overlays/bordered-loader.ts +41 -0
  447. package/src/overlays/btw-history-panel.ts +591 -0
  448. package/src/overlays/btw-history.ts +33 -0
  449. package/src/overlays/btw-panel.ts +167 -0
  450. package/src/overlays/cleanse-panel.ts +167 -0
  451. package/src/overlays/codex-reset-fireworks.ts +375 -0
  452. package/src/overlays/composer-shape-preview.ts +137 -0
  453. package/src/overlays/composer-shape-registry.ts +82 -0
  454. package/src/overlays/copy-selector.ts +618 -0
  455. package/src/overlays/copy-targets.ts +210 -0
  456. package/src/overlays/error-banner.ts +39 -0
  457. package/src/overlays/extensions/display-text.ts +39 -0
  458. package/src/overlays/extensions/extension-dashboard.ts +645 -0
  459. package/src/overlays/extensions/extension-list.ts +667 -0
  460. package/src/overlays/extensions/inspector-model.ts +484 -0
  461. package/src/overlays/extensions/inspector-panel.ts +669 -0
  462. package/src/overlays/extensions/live-tool-session.ts +67 -0
  463. package/src/overlays/extensions/mcp-runtime.ts +289 -0
  464. package/src/overlays/extensions/state-manager.ts +337 -0
  465. package/src/overlays/extensions/types.ts +208 -0
  466. package/src/overlays/history-search.ts +268 -0
  467. package/src/overlays/hook-editor.ts +272 -0
  468. package/src/overlays/hook-input.ts +84 -0
  469. package/src/overlays/hook-selector.ts +635 -0
  470. package/src/overlays/hub-frame.ts +262 -0
  471. package/src/overlays/login-dialog.ts +231 -0
  472. package/src/overlays/logout-account-selector.ts +115 -0
  473. package/src/overlays/mcp-add-wizard.ts +1436 -0
  474. package/src/overlays/model-browser.ts +1176 -0
  475. package/src/overlays/model-hub.ts +2279 -0
  476. package/src/overlays/model-picker.ts +285 -0
  477. package/src/overlays/model-selector.ts +107 -0
  478. package/src/overlays/move-overlay.ts +197 -0
  479. package/src/overlays/oauth-selector.ts +446 -0
  480. package/src/overlays/omfg-panel.ts +136 -0
  481. package/src/overlays/pause-screen.ts +198 -0
  482. package/src/overlays/plan-review-overlay.ts +1227 -0
  483. package/src/overlays/plan-save-overlay.ts +74 -0
  484. package/src/overlays/plan-toc.ts +139 -0
  485. package/src/overlays/plugin-selector.ts +97 -0
  486. package/src/overlays/plugin-settings.ts +839 -0
  487. package/src/overlays/queue-mode-selector.ts +55 -0
  488. package/src/overlays/reset-usage-selector.ts +170 -0
  489. package/src/overlays/rewind-selector.ts +499 -0
  490. package/src/overlays/running-subagent-badge.ts +19 -0
  491. package/src/overlays/session-account-selector.ts +68 -0
  492. package/src/overlays/session-info-overlay.ts +96 -0
  493. package/src/overlays/session-observer-registry.ts +289 -0
  494. package/src/overlays/session-selector.ts +1137 -0
  495. package/src/overlays/settings-defs.ts +315 -0
  496. package/src/overlays/settings-selector.ts +1415 -0
  497. package/src/overlays/show-images-selector.ts +44 -0
  498. package/src/overlays/snapcompact-shape-preview-doc.md +14 -0
  499. package/src/overlays/snapcompact-shape-preview.ts +192 -0
  500. package/src/overlays/theme-selector.ts +62 -0
  501. package/src/overlays/thinking-selector.ts +51 -0
  502. package/src/overlays/tiny-title-download-progress.ts +102 -0
  503. package/src/overlays/tree-selector.ts +1121 -0
  504. package/src/overlays/usage-dashboard.ts +629 -0
  505. package/src/overlays/usage-display.ts +45 -0
  506. package/src/overlays/usage-row.ts +118 -0
  507. package/src/prompt/attachment-chips.ts +201 -0
  508. package/src/prompt/composer-attachments.ts +280 -0
  509. package/src/prompt/composer-cache.ts +304 -0
  510. package/src/prompt/composer.ts +934 -0
  511. package/src/prompt/custom-editor.ts +1392 -0
  512. package/src/prompt/data/emojis.json +1 -0
  513. package/src/prompt/editor-top-gap.ts +28 -0
  514. package/src/prompt/emoji-autocomplete.ts +285 -0
  515. package/src/prompt/github-ref-autocomplete.ts +75 -0
  516. package/src/prompt/gradient-highlight.ts +101 -0
  517. package/src/prompt/image-format.ts +28 -0
  518. package/src/prompt/image-references.ts +102 -0
  519. package/src/prompt/interactive-context-helpers.ts +126 -0
  520. package/src/prompt/internal-url-autocomplete.ts +155 -0
  521. package/src/prompt/macos-spelling.ts +456 -0
  522. package/src/prompt/magic-keyword-boundary.ts +23 -0
  523. package/src/prompt/magic-keywords.ts +42 -0
  524. package/src/prompt/markdown-prose.ts +245 -0
  525. package/src/prompt/model-mention-autocomplete.ts +94 -0
  526. package/src/prompt/model-mention-syntax.ts +41 -0
  527. package/src/prompt/orchestrate.ts +26 -0
  528. package/src/prompt/prompt-action-autocomplete.ts +337 -0
  529. package/src/prompt/queue-input.ts +132 -0
  530. package/src/prompt/skill-tokens.ts +36 -0
  531. package/src/prompt/tips.txt +27 -0
  532. package/src/prompt/tools-markdown.ts +29 -0
  533. package/src/prompt/ultrathink.ts +26 -0
  534. package/src/prompt/usage-amounts.ts +99 -0
  535. package/src/prompt/video.ts +47 -0
  536. package/src/prompt/welcome.ts +605 -0
  537. package/src/prompt/workflow.ts +26 -0
  538. package/src/render/code-cell.ts +244 -0
  539. package/src/render/file-list.ts +58 -0
  540. package/src/render/hyperlink.ts +192 -0
  541. package/src/render/index.ts +17 -0
  542. package/src/render/output-block.ts +267 -0
  543. package/src/render/output-pane.ts +299 -0
  544. package/src/render/render-utils.ts +1182 -0
  545. package/src/render/sixel.ts +69 -0
  546. package/src/render/status-line.ts +55 -0
  547. package/src/render/tool-card.ts +272 -0
  548. package/src/render/tree-list.ts +188 -0
  549. package/src/render/types.ts +19 -0
  550. package/src/render/utils.ts +109 -0
  551. package/src/render/width-aware-text.ts +60 -0
  552. package/src/setup/lazy.ts +17 -0
  553. package/src/setup/scenes/composer.ts +127 -0
  554. package/src/setup/scenes/glyph.ts +120 -0
  555. package/src/setup/scenes/model.ts +138 -0
  556. package/src/setup/scenes/outro.ts +24 -0
  557. package/src/setup/scenes/providers.ts +107 -0
  558. package/src/setup/scenes/sign-in.ts +373 -0
  559. package/src/setup/scenes/splash.ts +192 -0
  560. package/src/setup/scenes/theme.ts +343 -0
  561. package/src/setup/scenes/types.ts +111 -0
  562. package/src/setup/scenes/web-search.ts +165 -0
  563. package/src/setup/setup-version.ts +11 -0
  564. package/src/setup/startup-splash.ts +107 -0
  565. package/src/setup/wizard-overlay.ts +319 -0
  566. package/src/setup/wizard.ts +101 -0
  567. package/src/status-line/component.ts +3003 -0
  568. package/src/status-line/context-usage.ts +688 -0
  569. package/src/status-line/footer.ts +323 -0
  570. package/src/status-line/git-utils.ts +42 -0
  571. package/src/status-line/host.ts +97 -0
  572. package/src/status-line/index.ts +6 -0
  573. package/src/status-line/loop.ts +28 -0
  574. package/src/status-line/metrics.ts +94 -0
  575. package/src/status-line/presets.ts +107 -0
  576. package/src/status-line/schema.ts +57 -0
  577. package/src/status-line/segments.ts +934 -0
  578. package/src/status-line/separators.ts +55 -0
  579. package/src/status-line/types.ts +227 -0
  580. package/src/stdin-buffer.ts +4 -2
  581. package/src/theme/color.ts +95 -0
  582. package/src/theme/dark.json +95 -0
  583. package/src/theme/defaults/alabaster.json +93 -0
  584. package/src/theme/defaults/amethyst.json +96 -0
  585. package/src/theme/defaults/anthracite.json +93 -0
  586. package/src/theme/defaults/basalt.json +91 -0
  587. package/src/theme/defaults/birch.json +95 -0
  588. package/src/theme/defaults/dark-abyss.json +91 -0
  589. package/src/theme/defaults/dark-arctic.json +104 -0
  590. package/src/theme/defaults/dark-aurora.json +95 -0
  591. package/src/theme/defaults/dark-catppuccin.json +107 -0
  592. package/src/theme/defaults/dark-cavern.json +91 -0
  593. package/src/theme/defaults/dark-celestial.json +106 -0
  594. package/src/theme/defaults/dark-copper.json +95 -0
  595. package/src/theme/defaults/dark-cosmos.json +90 -0
  596. package/src/theme/defaults/dark-cyberpunk.json +102 -0
  597. package/src/theme/defaults/dark-dracula.json +98 -0
  598. package/src/theme/defaults/dark-eclipse.json +91 -0
  599. package/src/theme/defaults/dark-ember.json +95 -0
  600. package/src/theme/defaults/dark-equinox.json +90 -0
  601. package/src/theme/defaults/dark-forest.json +96 -0
  602. package/src/theme/defaults/dark-github.json +105 -0
  603. package/src/theme/defaults/dark-gruvbox.json +112 -0
  604. package/src/theme/defaults/dark-lavender.json +95 -0
  605. package/src/theme/defaults/dark-lunar.json +89 -0
  606. package/src/theme/defaults/dark-midnight.json +95 -0
  607. package/src/theme/defaults/dark-monochrome.json +94 -0
  608. package/src/theme/defaults/dark-monokai.json +98 -0
  609. package/src/theme/defaults/dark-nebula.json +90 -0
  610. package/src/theme/defaults/dark-nord.json +98 -0
  611. package/src/theme/defaults/dark-ocean.json +101 -0
  612. package/src/theme/defaults/dark-one.json +100 -0
  613. package/src/theme/defaults/dark-poimandres.json +115 -0
  614. package/src/theme/defaults/dark-rainforest.json +91 -0
  615. package/src/theme/defaults/dark-reef.json +91 -0
  616. package/src/theme/defaults/dark-retro.json +92 -0
  617. package/src/theme/defaults/dark-rose-pine.json +96 -0
  618. package/src/theme/defaults/dark-sakura.json +95 -0
  619. package/src/theme/defaults/dark-slate.json +95 -0
  620. package/src/theme/defaults/dark-solarized.json +97 -0
  621. package/src/theme/defaults/dark-solstice.json +90 -0
  622. package/src/theme/defaults/dark-starfall.json +91 -0
  623. package/src/theme/defaults/dark-sunset.json +99 -0
  624. package/src/theme/defaults/dark-swamp.json +90 -0
  625. package/src/theme/defaults/dark-synthwave.json +103 -0
  626. package/src/theme/defaults/dark-taiga.json +91 -0
  627. package/src/theme/defaults/dark-terminal.json +95 -0
  628. package/src/theme/defaults/dark-tokyo-night.json +101 -0
  629. package/src/theme/defaults/dark-tundra.json +91 -0
  630. package/src/theme/defaults/dark-twilight.json +91 -0
  631. package/src/theme/defaults/dark-volcanic.json +91 -0
  632. package/src/theme/defaults/graphite.json +92 -0
  633. package/src/theme/defaults/index.ts +201 -0
  634. package/src/theme/defaults/light-arctic.json +107 -0
  635. package/src/theme/defaults/light-aurora-day.json +91 -0
  636. package/src/theme/defaults/light-canyon.json +91 -0
  637. package/src/theme/defaults/light-catppuccin.json +106 -0
  638. package/src/theme/defaults/light-cirrus.json +90 -0
  639. package/src/theme/defaults/light-coral.json +95 -0
  640. package/src/theme/defaults/light-cyberpunk.json +96 -0
  641. package/src/theme/defaults/light-dawn.json +90 -0
  642. package/src/theme/defaults/light-dunes.json +91 -0
  643. package/src/theme/defaults/light-eucalyptus.json +95 -0
  644. package/src/theme/defaults/light-forest.json +100 -0
  645. package/src/theme/defaults/light-frost.json +95 -0
  646. package/src/theme/defaults/light-github.json +115 -0
  647. package/src/theme/defaults/light-glacier.json +91 -0
  648. package/src/theme/defaults/light-gruvbox.json +108 -0
  649. package/src/theme/defaults/light-haze.json +90 -0
  650. package/src/theme/defaults/light-honeycomb.json +95 -0
  651. package/src/theme/defaults/light-lagoon.json +91 -0
  652. package/src/theme/defaults/light-lavender.json +95 -0
  653. package/src/theme/defaults/light-meadow.json +91 -0
  654. package/src/theme/defaults/light-mint.json +95 -0
  655. package/src/theme/defaults/light-monochrome.json +101 -0
  656. package/src/theme/defaults/light-ocean.json +99 -0
  657. package/src/theme/defaults/light-one.json +99 -0
  658. package/src/theme/defaults/light-opal.json +91 -0
  659. package/src/theme/defaults/light-orchard.json +91 -0
  660. package/src/theme/defaults/light-paper.json +95 -0
  661. package/src/theme/defaults/light-poimandres.json +115 -0
  662. package/src/theme/defaults/light-prism.json +90 -0
  663. package/src/theme/defaults/light-retro.json +98 -0
  664. package/src/theme/defaults/light-sand.json +95 -0
  665. package/src/theme/defaults/light-savanna.json +91 -0
  666. package/src/theme/defaults/light-solarized.json +102 -0
  667. package/src/theme/defaults/light-soleil.json +90 -0
  668. package/src/theme/defaults/light-sunset.json +99 -0
  669. package/src/theme/defaults/light-synthwave.json +98 -0
  670. package/src/theme/defaults/light-tokyo-night.json +111 -0
  671. package/src/theme/defaults/light-wetland.json +91 -0
  672. package/src/theme/defaults/light-zenith.json +89 -0
  673. package/src/theme/defaults/limestone.json +94 -0
  674. package/src/theme/defaults/mahogany.json +97 -0
  675. package/src/theme/defaults/marble.json +93 -0
  676. package/src/theme/defaults/obsidian.json +91 -0
  677. package/src/theme/defaults/onyx.json +91 -0
  678. package/src/theme/defaults/pearl.json +93 -0
  679. package/src/theme/defaults/porcelain.json +91 -0
  680. package/src/theme/defaults/quartz.json +96 -0
  681. package/src/theme/defaults/sandstone.json +95 -0
  682. package/src/theme/defaults/titanium.json +90 -0
  683. package/src/theme/index.ts +5 -0
  684. package/src/theme/light.json +93 -0
  685. package/src/theme/loader.ts +200 -0
  686. package/src/theme/mermaid-cache.ts +92 -0
  687. package/src/theme/schema-validation.ts +119 -0
  688. package/src/theme/schema.ts +168 -0
  689. package/src/theme/session-color.ts +253 -0
  690. package/src/theme/shimmer.ts +307 -0
  691. package/src/theme/symbols.ts +1433 -0
  692. package/src/theme/theme-class.ts +787 -0
  693. package/src/theme/theme-schema.json +463 -0
  694. package/src/theme/theme.ts +810 -0
  695. package/src/theme/tui-adapters.ts +339 -0
  696. package/src/thinking.ts +380 -0
  697. package/src/tools/agent-tree.ts +128 -0
  698. package/src/tools/ask.ts +482 -0
  699. package/src/tools/ast-edit.ts +210 -0
  700. package/src/tools/ast-grep.ts +171 -0
  701. package/src/tools/autoresearch.ts +287 -0
  702. package/src/tools/bash-interactive.ts +295 -0
  703. package/src/tools/bash.ts +468 -0
  704. package/src/tools/conflict-detect.ts +77 -0
  705. package/src/tools/debug.ts +167 -0
  706. package/src/tools/default-renderer.ts +172 -0
  707. package/src/tools/edit.ts +1258 -0
  708. package/src/tools/eval-format/code-mode-declarations.ts +61 -0
  709. package/src/tools/eval-format/index.ts +16 -0
  710. package/src/tools/eval-format/javascript.ts +952 -0
  711. package/src/tools/eval-format/python.ts +544 -0
  712. package/src/tools/eval.ts +835 -0
  713. package/src/tools/fetch.ts +226 -0
  714. package/src/tools/gh-format.ts +18 -0
  715. package/src/tools/github.ts +686 -0
  716. package/src/tools/glob.ts +213 -0
  717. package/src/tools/goal.ts +153 -0
  718. package/src/tools/grep.ts +385 -0
  719. package/src/tools/grouped-file-output.ts +211 -0
  720. package/src/tools/hashline-format.ts +59 -0
  721. package/src/tools/hub.ts +1488 -0
  722. package/src/tools/index.ts +71 -0
  723. package/src/tools/json-tree.ts +388 -0
  724. package/src/tools/line-ranges.ts +98 -0
  725. package/src/tools/list-limit.ts +43 -0
  726. package/src/tools/lsp.ts +702 -0
  727. package/src/tools/match-line-format.ts +20 -0
  728. package/src/tools/mcp.ts +309 -0
  729. package/src/tools/memory.ts +220 -0
  730. package/src/tools/output-meta.ts +367 -0
  731. package/src/tools/read.ts +628 -0
  732. package/src/tools/renderer.ts +107 -0
  733. package/src/tools/report-tool-issue.ts +13 -0
  734. package/src/tools/resolve.ts +139 -0
  735. package/src/tools/streaming-output.ts +1576 -0
  736. package/src/tools/subprocess.ts +39 -0
  737. package/src/tools/task-repair-args.ts +118 -0
  738. package/src/tools/task-yield-assembly.ts +147 -0
  739. package/src/tools/task.ts +2110 -0
  740. package/src/tools/terminal-output.ts +153 -0
  741. package/src/tools/think.ts +28 -0
  742. package/src/tools/todo.ts +580 -0
  743. package/src/tools/tool-errors.ts +15 -0
  744. package/src/tools/vibe.ts +420 -0
  745. package/src/tools/web-search.ts +409 -0
  746. package/src/tools/write.ts +511 -0
  747. package/src/tools/xd-url.ts +28 -0
  748. package/src/tools/xdev.ts +201 -0
  749. package/src/tui.ts +70 -8
  750. package/src/utils.ts +8 -0
@@ -0,0 +1,760 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import {
4
+ getActiveProfile,
5
+ getAgentDir,
6
+ getProfileRootDir,
7
+ isEnoent,
8
+ logger,
9
+ stringifyYamlConfig,
10
+ } from "@oh-my-pi/pi-utils";
11
+ import { JSONC, YAML } from "bun";
12
+ import {
13
+ type Keybinding,
14
+ type KeybindingDefinitions,
15
+ type KeybindingsConfig,
16
+ type KeyId,
17
+ setKeybindings,
18
+ TUI_KEYBINDINGS,
19
+ KeybindingsManager as TuiKeybindingsManager,
20
+ } from "./keybindings";
21
+
22
+ /**
23
+ * Application-level keybindings (coding agent specific).
24
+ * Values are always `true` — used for declaration merging.
25
+ */
26
+ interface AppKeybindings {
27
+ "app.interrupt": true;
28
+ "app.clear": true;
29
+ "app.exit": true;
30
+ "app.suspend": true;
31
+ "app.display.reset": true;
32
+ "app.thinking.cycle": true;
33
+ "app.thinking.toggle": true;
34
+ "app.model.cycleForward": true;
35
+ "app.model.cycleBackward": true;
36
+ "app.model.select": true;
37
+ "app.model.selectTemporary": true;
38
+ "app.tools.expand": true;
39
+ "app.tools.toggleVisibility": true;
40
+ "app.editor.external": true;
41
+ "app.message.followUp": true;
42
+ "app.retry": true;
43
+ "app.message.dequeue": true;
44
+ "app.clipboard.pasteImage": true;
45
+ "app.clipboard.pasteTextRaw": true;
46
+ "app.clipboard.copyLine": true;
47
+ "app.clipboard.copyPrompt": true;
48
+ "app.agents.hub": true;
49
+ "app.session.new": true;
50
+ "app.session.tree": true;
51
+ "app.session.fork": true;
52
+ "app.session.resume": true;
53
+ "app.session.observe": true;
54
+ "app.session.togglePath": true;
55
+ "app.session.toggleSort": true;
56
+ "app.session.rename": true;
57
+ "app.session.delete": true;
58
+ "app.session.deleteNoninvasive": true;
59
+ "app.tree.foldOrUp": true;
60
+ "app.tree.unfoldOrDown": true;
61
+ "app.plan.toggle": true;
62
+ "app.history.search": true;
63
+ "app.stt.toggle": true;
64
+ "app.live.toggle": true;
65
+ }
66
+
67
+ /** Application action identifier registered alongside the base TUI keybindings. */
68
+ export type AppKeybinding = keyof AppKeybindings;
69
+
70
+ declare module "./keybindings" {
71
+ interface Keybindings extends AppKeybindings {}
72
+ }
73
+
74
+ /**
75
+ * Resolve default image-paste shortcuts for the current terminal platform.
76
+ */
77
+ export function getDefaultPasteImageKeys(platform: NodeJS.Platform = process.platform): KeyId[] {
78
+ if (platform === "win32") return ["ctrl+v", "alt+v"];
79
+ if (platform === "darwin") return ["ctrl+v", "super+v"];
80
+ return ["ctrl+v"];
81
+ }
82
+
83
+ /**
84
+ * All keybindings definitions: TUI + app-specific.
85
+ */
86
+ export const KEYBINDINGS = {
87
+ ...TUI_KEYBINDINGS,
88
+ "app.interrupt": {
89
+ defaultKeys: "escape",
90
+ description: "Interrupt current operation",
91
+ },
92
+ "app.clear": {
93
+ defaultKeys: "ctrl+c",
94
+ description: "Clear screen or cancel",
95
+ },
96
+ "app.exit": {
97
+ defaultKeys: "ctrl+d",
98
+ description: "Exit application",
99
+ },
100
+ "app.suspend": {
101
+ defaultKeys: "ctrl+z",
102
+ description: "Suspend application",
103
+ },
104
+ "app.display.reset": {
105
+ defaultKeys: "alt+l",
106
+ description: "Reset terminal display",
107
+ },
108
+ "app.thinking.cycle": {
109
+ defaultKeys: "shift+tab",
110
+ description: "Cycle thinking level",
111
+ },
112
+ "app.thinking.toggle": {
113
+ defaultKeys: "ctrl+t",
114
+ description: "Toggle thinking mode",
115
+ },
116
+ "app.model.cycleForward": {
117
+ defaultKeys: "ctrl+p",
118
+ description: "Cycle to next model",
119
+ },
120
+ "app.model.cycleBackward": {
121
+ defaultKeys: "shift+ctrl+p",
122
+ description: "Cycle to previous model",
123
+ },
124
+ "app.model.select": {
125
+ defaultKeys: "alt+m",
126
+ description: "Select model",
127
+ },
128
+ "app.model.selectTemporary": {
129
+ defaultKeys: "alt+p",
130
+ description: "Select temporary model for current session",
131
+ },
132
+ "app.tools.expand": {
133
+ defaultKeys: "ctrl+o",
134
+ description: "Expand tools",
135
+ },
136
+ "app.tools.toggleVisibility": {
137
+ defaultKeys: "ctrl+shift+o",
138
+ description: "Show or hide tool activity",
139
+ },
140
+ "app.editor.external": {
141
+ defaultKeys: "ctrl+g",
142
+ description: "Open external editor",
143
+ },
144
+ "app.message.followUp": {
145
+ // Ctrl+Enter is preserved for terminals that deliver it (Kitty/iTerm2/WezTerm/Ghostty),
146
+ // but Windows Terminal does not emit a distinct event for Ctrl+Enter — Ctrl+Q is listed
147
+ // first so the default binding works there without remapping (#1903).
148
+ defaultKeys: ["ctrl+q", "ctrl+enter"],
149
+ description: "Send follow-up message",
150
+ },
151
+ "app.retry": {
152
+ // F5 leads: it is delivered verbatim by every terminal, unlike modified
153
+ // Enter chords (Ctrl/Alt/Cmd+Enter), which various terminals swallow or
154
+ // fold into plain Enter. The idle "F5 to Retry" status row advertises it.
155
+ defaultKeys: ["f5", "alt+r"],
156
+ description: "Retry last failed assistant turn",
157
+ },
158
+ "app.message.dequeue": {
159
+ // Shift+Up is listed alongside Alt+Up because macOS Terminal.app consumes Option
160
+ // for character composition, leaving Alt+Up unreachable there.
161
+ defaultKeys: ["alt+up", "shift+up"],
162
+ description: "Dequeue message",
163
+ },
164
+ "app.clipboard.pasteImage": {
165
+ defaultKeys: getDefaultPasteImageKeys(),
166
+ description: "Paste image or text from clipboard",
167
+ },
168
+ "app.clipboard.pasteTextRaw": {
169
+ defaultKeys: ["ctrl+shift+v", "alt+shift+v"],
170
+ description: "Paste text from clipboard as raw text (no collapse)",
171
+ },
172
+ "app.clipboard.copyLine": {
173
+ defaultKeys: "alt+shift+l",
174
+ description: "Copy current line",
175
+ },
176
+ "app.clipboard.copyPrompt": {
177
+ defaultKeys: "alt+shift+c",
178
+ description: "Copy prompt",
179
+ },
180
+ "app.session.new": {
181
+ defaultKeys: [],
182
+ description: "Create new session",
183
+ },
184
+ "app.session.tree": {
185
+ defaultKeys: [],
186
+ description: "Show session tree",
187
+ },
188
+ "app.session.fork": {
189
+ defaultKeys: [],
190
+ description: "Fork session",
191
+ },
192
+ "app.session.resume": {
193
+ defaultKeys: [],
194
+ description: "Resume session",
195
+ },
196
+ "app.agents.hub": {
197
+ defaultKeys: "alt+a",
198
+ description: "Open the agent hub",
199
+ },
200
+ "app.session.observe": {
201
+ defaultKeys: "ctrl+s",
202
+ description: "Open the agent hub",
203
+ },
204
+ "app.session.togglePath": {
205
+ defaultKeys: "ctrl+p",
206
+ description: "Toggle session path display",
207
+ },
208
+ "app.session.toggleSort": {
209
+ defaultKeys: "ctrl+s",
210
+ description: "Toggle session sort order",
211
+ },
212
+ "app.session.rename": {
213
+ defaultKeys: "ctrl+r",
214
+ description: "Rename session",
215
+ },
216
+ "app.session.delete": {
217
+ defaultKeys: "ctrl+d",
218
+ description: "Delete session",
219
+ },
220
+ "app.session.deleteNoninvasive": {
221
+ defaultKeys: "ctrl+backspace",
222
+ description: "Delete session (non-invasive)",
223
+ },
224
+ "app.tree.foldOrUp": {
225
+ defaultKeys: ["ctrl+left", "alt+left"],
226
+ description: "Fold or move up",
227
+ },
228
+ "app.tree.unfoldOrDown": {
229
+ defaultKeys: ["ctrl+right", "alt+right"],
230
+ description: "Unfold or move down",
231
+ },
232
+ "app.plan.toggle": {
233
+ defaultKeys: "alt+shift+p",
234
+ description: "Toggle plan mode",
235
+ },
236
+ "app.history.search": {
237
+ defaultKeys: "ctrl+r",
238
+ description: "Search history",
239
+ },
240
+ "app.stt.toggle": {
241
+ defaultKeys: [],
242
+ description: "Toggle speech-to-text (default gesture: hold Space)",
243
+ },
244
+ "app.live.toggle": {
245
+ defaultKeys: "ctrl+l",
246
+ description: "Start or stop live voice mode (/live)",
247
+ },
248
+ } as const satisfies KeybindingDefinitions;
249
+
250
+ /**
251
+ * Migration map from old keybinding names to new namespaced IDs.
252
+ */
253
+ const KEYBINDING_NAME_MIGRATIONS = {
254
+ // App-specific (old names)
255
+ interrupt: "app.interrupt",
256
+ clear: "app.clear",
257
+ exit: "app.exit",
258
+ suspend: "app.suspend",
259
+ displayReset: "app.display.reset",
260
+ cycleThinkingLevel: "app.thinking.cycle",
261
+ cycleModelForward: "app.model.cycleForward",
262
+ cycleModelBackward: "app.model.cycleBackward",
263
+ selectModel: "app.model.select",
264
+ selectModelTemporary: "app.model.selectTemporary",
265
+ togglePlanMode: "app.plan.toggle",
266
+ historySearch: "app.history.search",
267
+ expandTools: "app.tools.expand",
268
+ toggleThinking: "app.thinking.toggle",
269
+ externalEditor: "app.editor.external",
270
+ followUp: "app.message.followUp",
271
+ retry: "app.retry",
272
+ dequeue: "app.message.dequeue",
273
+ pasteImage: "app.clipboard.pasteImage",
274
+ pasteTextRaw: "app.clipboard.pasteTextRaw",
275
+ copyLine: "app.clipboard.copyLine",
276
+ copyPrompt: "app.clipboard.copyPrompt",
277
+ newSession: "app.session.new",
278
+ tree: "app.session.tree",
279
+ fork: "app.session.fork",
280
+ resume: "app.session.resume",
281
+ observeSessions: "app.session.observe",
282
+ toggleSTT: "app.stt.toggle",
283
+ // TUI editor (old names for backward compatibility)
284
+ cursorUp: "tui.editor.cursorUp",
285
+ cursorDown: "tui.editor.cursorDown",
286
+ cursorLeft: "tui.editor.cursorLeft",
287
+ cursorRight: "tui.editor.cursorRight",
288
+ cursorWordLeft: "tui.editor.cursorWordLeft",
289
+ cursorWordRight: "tui.editor.cursorWordRight",
290
+ cursorLineStart: "tui.editor.cursorLineStart",
291
+ cursorLineEnd: "tui.editor.cursorLineEnd",
292
+ jumpForward: "tui.editor.jumpForward",
293
+ jumpBackward: "tui.editor.jumpBackward",
294
+ pageUp: "tui.editor.pageUp",
295
+ pageDown: "tui.editor.pageDown",
296
+ deleteCharBackward: "tui.editor.deleteCharBackward",
297
+ deleteCharForward: "tui.editor.deleteCharForward",
298
+ deleteWordBackward: "tui.editor.deleteWordBackward",
299
+ deleteWordForward: "tui.editor.deleteWordForward",
300
+ deleteToLineStart: "tui.editor.deleteToLineStart",
301
+ deleteToLineEnd: "tui.editor.deleteToLineEnd",
302
+ yank: "tui.editor.yank",
303
+ yankPop: "tui.editor.yankPop",
304
+ undo: "tui.editor.undo",
305
+ // TUI input (old names for backward compatibility)
306
+ newLine: "tui.input.newLine",
307
+ submit: "tui.input.submit",
308
+ tab: "tui.input.tab",
309
+ copy: "tui.input.copy",
310
+ // TUI select (old names for backward compatibility)
311
+ selectUp: "tui.select.up",
312
+ selectDown: "tui.select.down",
313
+ selectPageUp: "tui.select.pageUp",
314
+ selectPageDown: "tui.select.pageDown",
315
+ selectConfirm: "tui.select.confirm",
316
+ selectCancel: "tui.select.cancel",
317
+ // Upstream additional migrations
318
+ toggleSessionNamedFilter: "app.session.togglePath",
319
+ } as const satisfies Record<string, Keybinding>;
320
+
321
+ /**
322
+ * Check if a key is a legacy keybinding name.
323
+ */
324
+ function isLegacyKeybindingName(key: string): key is keyof typeof KEYBINDING_NAME_MIGRATIONS {
325
+ return key in KEYBINDING_NAME_MIGRATIONS;
326
+ }
327
+
328
+ function toKeybindingsConfig(value: unknown): KeybindingsConfig {
329
+ if (typeof value !== "object" || value === null) {
330
+ return {};
331
+ }
332
+
333
+ const config: KeybindingsConfig = {};
334
+ for (const [key, val] of Object.entries(value)) {
335
+ if (val === undefined) {
336
+ config[key] = undefined;
337
+ } else if (typeof val === "string") {
338
+ config[key] = val as KeyId;
339
+ } else if (Array.isArray(val) && val.every(v => typeof v === "string")) {
340
+ config[key] = val as KeyId[];
341
+ }
342
+ }
343
+ return config;
344
+ }
345
+
346
+ /**
347
+ * Migrate old keybinding names to new namespaced IDs.
348
+ * Returns both the migrated config and a flag indicating if migration occurred.
349
+ */
350
+ function migrateKeybindingNames(rawConfig: unknown): {
351
+ config: KeybindingsConfig;
352
+ migrated: boolean;
353
+ } {
354
+ const config = toKeybindingsConfig(rawConfig);
355
+ const migrated: KeybindingsConfig = {};
356
+ let didMigrate = false;
357
+
358
+ for (const [key, value] of Object.entries(config)) {
359
+ if (isLegacyKeybindingName(key)) {
360
+ const newKey = KEYBINDING_NAME_MIGRATIONS[key];
361
+ migrated[newKey] = value;
362
+ didMigrate = true;
363
+ } else {
364
+ // Already a new-style key
365
+ migrated[key] = value;
366
+ }
367
+ }
368
+
369
+ return { config: migrated, migrated: didMigrate };
370
+ }
371
+
372
+ /**
373
+ * Order keybindings config to match KEYBINDINGS key order.
374
+ */
375
+ function orderKeybindingsConfig(config: KeybindingsConfig): KeybindingsConfig {
376
+ const ordered: KeybindingsConfig = {};
377
+ for (const key of Object.keys(KEYBINDINGS)) {
378
+ const value = config[key];
379
+ if (value !== undefined) {
380
+ ordered[key] = value;
381
+ }
382
+ }
383
+ // Add any remaining keys that aren't in KEYBINDINGS
384
+ for (const key of Object.keys(config)) {
385
+ if (!(key in ordered)) {
386
+ ordered[key] = config[key];
387
+ }
388
+ }
389
+ return ordered;
390
+ }
391
+
392
+ const KEYBINDINGS_YML = "keybindings.yml";
393
+ const KEYBINDINGS_YAML = "keybindings.yaml";
394
+ const LEGACY_KEYBINDINGS_JSON = "keybindings.json";
395
+
396
+ interface KeybindingsConfigPaths {
397
+ readPath: string;
398
+ writeBackPath: string;
399
+ }
400
+
401
+ /** Controls inherited keybinding lookup when creating a manager for a named profile. */
402
+ export interface KeybindingsCreateOptions {
403
+ /** Default-profile agent directory whose keybindings are merged before profile-specific bindings. */
404
+ inheritedAgentDir?: string;
405
+ }
406
+
407
+ /**
408
+ * Load raw config from a file synchronously.
409
+ * Returns parsed JSON/YAML or null if file doesn't exist or is invalid.
410
+ */
411
+ function loadRawConfig(filePath: string): unknown {
412
+ try {
413
+ const content = fs.readFileSync(filePath, "utf-8");
414
+ if (filePath.endsWith(".json")) {
415
+ return JSONC.parse(content);
416
+ }
417
+ if (filePath.endsWith(".yml") || filePath.endsWith(".yaml")) {
418
+ return YAML.parse(content);
419
+ }
420
+ throw new Error(`Unsupported keybindings config extension: ${filePath}`);
421
+ } catch (error) {
422
+ if (isEnoent(error)) {
423
+ return null;
424
+ }
425
+ logger.warn("Failed to parse keybindings config", { path: filePath, error: String(error) });
426
+ return null;
427
+ }
428
+ }
429
+
430
+ function writeKeybindingsConfig(filePath: string, config: KeybindingsConfig): boolean {
431
+ try {
432
+ fs.writeFileSync(filePath, stringifyYamlConfig(config), "utf-8");
433
+ logger.debug("Migrated keybindings config", { path: filePath });
434
+ return true;
435
+ } catch (error) {
436
+ logger.warn("Failed to write migrated keybindings config", { path: filePath, error: String(error) });
437
+ return false;
438
+ }
439
+ }
440
+
441
+ function resolveKeybindingsConfigPaths(agentDir: string): KeybindingsConfigPaths {
442
+ const ymlPath = path.join(agentDir, KEYBINDINGS_YML);
443
+ if (fs.existsSync(ymlPath)) {
444
+ return { readPath: ymlPath, writeBackPath: ymlPath };
445
+ }
446
+
447
+ const yamlPath = path.join(agentDir, KEYBINDINGS_YAML);
448
+ if (fs.existsSync(yamlPath)) {
449
+ return { readPath: yamlPath, writeBackPath: yamlPath };
450
+ }
451
+
452
+ const jsonPath = path.join(agentDir, LEGACY_KEYBINDINGS_JSON);
453
+ if (fs.existsSync(jsonPath)) {
454
+ return { readPath: jsonPath, writeBackPath: ymlPath };
455
+ }
456
+
457
+ return { readPath: ymlPath, writeBackPath: ymlPath };
458
+ }
459
+
460
+ function mergeKeybindingsConfig(
461
+ inheritedConfig: KeybindingsConfig,
462
+ profileConfig: KeybindingsConfig,
463
+ ): KeybindingsConfig {
464
+ return { ...inheritedConfig, ...profileConfig };
465
+ }
466
+
467
+ function resolveInheritedAgentDir(agentDir: string, options: KeybindingsCreateOptions): string | undefined {
468
+ const inheritedAgentDir =
469
+ options.inheritedAgentDir ?? (getActiveProfile() ? path.join(getProfileRootDir(undefined), "agent") : undefined);
470
+ if (!inheritedAgentDir) return undefined;
471
+ if (path.resolve(inheritedAgentDir) === path.resolve(agentDir)) return undefined;
472
+ return inheritedAgentDir;
473
+ }
474
+
475
+ function loadMergedKeybindingsConfig(
476
+ agentDir: string,
477
+ options: KeybindingsCreateOptions,
478
+ ): {
479
+ config: KeybindingsConfig;
480
+ profilePath: string;
481
+ inheritedPath: string | undefined;
482
+ } {
483
+ const profilePaths = resolveKeybindingsConfigPaths(agentDir);
484
+ const profile = loadKeybindingsConfig(profilePaths.readPath, profilePaths.writeBackPath);
485
+ const inheritedAgentDir = resolveInheritedAgentDir(agentDir, options);
486
+ if (!inheritedAgentDir) {
487
+ return { config: profile.config, profilePath: profile.persistedPath, inheritedPath: undefined };
488
+ }
489
+
490
+ const inheritedPaths = resolveKeybindingsConfigPaths(inheritedAgentDir);
491
+ // Read-only: a named-profile process must never write migration output into
492
+ // the default profile's agent dir. Name migration still applies in-memory;
493
+ // the on-disk migration happens when the default profile itself launches.
494
+ const inherited = loadKeybindingsConfig(inheritedPaths.readPath, undefined);
495
+ return {
496
+ config: mergeKeybindingsConfig(inherited.config, profile.config),
497
+ profilePath: profile.persistedPath,
498
+ inheritedPath: inherited.persistedPath,
499
+ };
500
+ }
501
+
502
+ /**
503
+ * Load and migrate keybindings config.
504
+ * Legacy JSON is read for compatibility, but successful write-back goes to YAML.
505
+ */
506
+ function loadKeybindingsConfig(
507
+ filePath: string,
508
+ writeBackPath: string | undefined,
509
+ ): {
510
+ config: KeybindingsConfig;
511
+ persistedPath: string;
512
+ } {
513
+ const rawConfig = loadRawConfig(filePath);
514
+
515
+ if (rawConfig === null) {
516
+ return { config: {}, persistedPath: filePath };
517
+ }
518
+
519
+ const { config: migratedConfig, migrated } = migrateKeybindingNames(rawConfig);
520
+ const shouldWriteBack = writeBackPath !== undefined && (migrated || writeBackPath !== filePath);
521
+ if (shouldWriteBack) {
522
+ const ordered = orderKeybindingsConfig(migratedConfig);
523
+ const persistedPath = writeKeybindingsConfig(writeBackPath, ordered) ? writeBackPath : filePath;
524
+ return { config: migratedConfig, persistedPath };
525
+ }
526
+
527
+ return { config: migratedConfig, persistedPath: filePath };
528
+ }
529
+
530
+ /** Migrate legacy keybinding names and JSON configuration in an agent directory. */
531
+ function migrateKeybindingsConfigFile(agentDir: string): void {
532
+ const { readPath, writeBackPath } = resolveKeybindingsConfigPaths(agentDir);
533
+ loadKeybindingsConfig(readPath, writeBackPath);
534
+ }
535
+
536
+ const FOLLOW_UP_KEYBINDING: AppKeybinding = "app.message.followUp";
537
+ const WINDOWS_FOLLOW_UP_FALLBACK_KEY: KeyId = "ctrl+q";
538
+ const DEQUEUE_KEYBINDING: AppKeybinding = "app.message.dequeue";
539
+ const MACOS_DEQUEUE_FALLBACK_KEY: KeyId = "shift+up";
540
+ function getFallbackKey(keybinding: Keybinding): KeyId | undefined {
541
+ if (keybinding === FOLLOW_UP_KEYBINDING) return WINDOWS_FOLLOW_UP_FALLBACK_KEY;
542
+ if (keybinding === DEQUEUE_KEYBINDING) return MACOS_DEQUEUE_FALLBACK_KEY;
543
+ return undefined;
544
+ }
545
+ function keyListIncludes(keys: KeyId | KeyId[] | undefined, target: KeyId): boolean {
546
+ if (keys === undefined) return false;
547
+ const keyList = Array.isArray(keys) ? keys : [keys];
548
+ for (const key of keyList) {
549
+ if (key.toLowerCase() === target) return true;
550
+ }
551
+ return false;
552
+ }
553
+
554
+ function userBindingClaimsKey(config: KeybindingsConfig, target: KeyId, except: Keybinding): boolean {
555
+ for (const [keybinding, keys] of Object.entries(config)) {
556
+ if (!(keybinding in KEYBINDINGS)) continue;
557
+ if (keybinding === except) continue;
558
+ if (keyListIncludes(keys, target)) return true;
559
+ }
560
+ return false;
561
+ }
562
+
563
+ function removeKey(keys: KeyId[], target: KeyId): KeyId[] {
564
+ return keys.filter(key => key !== target);
565
+ }
566
+
567
+ function keyConfigValue(keys: KeyId[]): KeyId | KeyId[] {
568
+ if (keys.length === 1) {
569
+ const key = keys[0];
570
+ if (key !== undefined) return key;
571
+ }
572
+ return [...keys];
573
+ }
574
+
575
+ /**
576
+ * Manages all keybindings (app + TUI).
577
+ * Extends the TUI KeybindingsManager with app-specific functionality.
578
+ */
579
+ export class KeybindingsManager extends TuiKeybindingsManager {
580
+ #configPath: string | undefined;
581
+ #inheritedConfigPath: string | undefined;
582
+ #userBindings: KeybindingsConfig;
583
+
584
+ constructor(userBindings: KeybindingsConfig = {}, configPath?: string, inheritedConfigPath?: string) {
585
+ super(KEYBINDINGS, userBindings);
586
+ this.#configPath = configPath;
587
+ this.#inheritedConfigPath = inheritedConfigPath;
588
+ this.#userBindings = userBindings;
589
+ }
590
+
591
+ /**
592
+ * Create from config files at agentDir/keybindings.yml and the default profile.
593
+ * Legacy keybindings.json is migrated to keybindings.yml on load.
594
+ */
595
+ static create(agentDir: string = getAgentDir(), options: KeybindingsCreateOptions = {}): KeybindingsManager {
596
+ const { config: userBindings, profilePath, inheritedPath } = loadMergedKeybindingsConfig(agentDir, options);
597
+ const manager = new KeybindingsManager(userBindings, profilePath, inheritedPath);
598
+ // Set globally so getKeybindings() returns this manager
599
+ setKeybindings(manager);
600
+ return manager;
601
+ }
602
+
603
+ /**
604
+ * Create an in-memory keybindings manager without file persistence.
605
+ */
606
+ static inMemory(userBindings: KeybindingsConfig = {}): KeybindingsManager {
607
+ return new KeybindingsManager(userBindings);
608
+ }
609
+
610
+ /**
611
+ * Reload keybindings from the config files.
612
+ */
613
+ reload(): void {
614
+ if (!this.#configPath) return;
615
+ const { config: inheritedConfig } = this.#inheritedConfigPath
616
+ ? KeybindingsManager.#loadFromFile(this.#inheritedConfigPath)
617
+ : { config: {} };
618
+ const { config: profileConfig } = KeybindingsManager.#loadFromFile(this.#configPath);
619
+ this.setUserBindings(mergeKeybindingsConfig(inheritedConfig, profileConfig));
620
+ }
621
+
622
+ override setUserBindings(userBindings: KeybindingsConfig): void {
623
+ this.#userBindings = userBindings;
624
+ super.setUserBindings(userBindings);
625
+ }
626
+
627
+ override getKeys(keybinding: Keybinding): KeyId[] {
628
+ const keys = super.getKeys(keybinding);
629
+ const fallbackKey = getFallbackKey(keybinding);
630
+ if (fallbackKey === undefined || this.#userBindings[keybinding] !== undefined) return keys;
631
+ if (!userBindingClaimsKey(this.#userBindings, fallbackKey, keybinding)) return keys;
632
+ return removeKey(keys, fallbackKey);
633
+ }
634
+
635
+ override getResolvedBindings(): KeybindingsConfig {
636
+ const resolved = super.getResolvedBindings();
637
+ resolved[FOLLOW_UP_KEYBINDING] = keyConfigValue(this.getKeys(FOLLOW_UP_KEYBINDING));
638
+ return resolved;
639
+ }
640
+
641
+ /**
642
+ * Get the effective resolved bindings (defaults + user overrides).
643
+ */
644
+ getEffectiveConfig(): KeybindingsConfig {
645
+ return this.getResolvedBindings();
646
+ }
647
+
648
+ /**
649
+ * Get display string for a keybinding (e.g., "ctrl+c/escape").
650
+ */
651
+ getDisplayString(keybinding: Keybinding): string {
652
+ const keys = this.getKeys(keybinding);
653
+ return formatKeyHints(keys.length === 0 ? [] : keys);
654
+ }
655
+
656
+ /**
657
+ * Load user bindings from a file, migrating old names if needed.
658
+ */
659
+ static #loadFromFile(
660
+ filePath: string,
661
+ writeBackPath?: string,
662
+ ): { config: KeybindingsConfig; persistedPath: string } {
663
+ return loadKeybindingsConfig(filePath, writeBackPath);
664
+ }
665
+ }
666
+
667
+ /**
668
+ * Key hint formatting utilities for UI labels.
669
+ *
670
+ * Modifier labels are platform-aware: macOS names the physical keys `Option`
671
+ * (`alt`) and `Cmd` (`super`), so rendering `Alt`/`Super` there would name keys
672
+ * absent from a Mac keyboard. Every other platform keeps `Alt`/`Super`.
673
+ */
674
+
675
+ /**
676
+ * Platform override for key-hint rendering; `undefined` resolves to the host
677
+ * `process.platform`. Mirrors `setKittyProtocolActive` in the TUI keys module:
678
+ * a single seam that keeps hint output deterministic in tests without mutating
679
+ * the global `process.platform`.
680
+ */
681
+ let keyHintPlatformOverride: NodeJS.Platform | undefined;
682
+
683
+ /** Pin the platform used to render modifier labels (test seam). */
684
+ export function setKeyHintPlatform(platform: NodeJS.Platform | undefined): void {
685
+ keyHintPlatformOverride = platform;
686
+ }
687
+
688
+ /** Platform currently used for key-hint rendering. */
689
+ export function keyHintPlatform(): NodeJS.Platform {
690
+ return keyHintPlatformOverride ?? process.platform;
691
+ }
692
+
693
+ type Modifier = "ctrl" | "shift" | "alt" | "super";
694
+
695
+ function isModifier(part: string): part is Modifier {
696
+ return part === "ctrl" || part === "shift" || part === "alt" || part === "super";
697
+ }
698
+
699
+ /**
700
+ * Human label for a modifier, using each platform's own key names. `ctrl` and
701
+ * `shift` are the same everywhere; `alt`/`super` become `Option`/`Cmd` on macOS.
702
+ */
703
+ export function modifierLabel(mod: Modifier, platform: NodeJS.Platform = keyHintPlatform()): string {
704
+ switch (mod) {
705
+ case "ctrl":
706
+ return "Ctrl";
707
+ case "shift":
708
+ return "Shift";
709
+ case "alt":
710
+ return platform === "darwin" ? "Option" : "Alt";
711
+ case "super":
712
+ return platform === "darwin" ? "Cmd" : "Super";
713
+ }
714
+ }
715
+
716
+ const KEY_LABELS: Record<string, string> = {
717
+ esc: "Esc",
718
+ escape: "Esc",
719
+ enter: "Enter",
720
+ return: "Enter",
721
+ space: "Space",
722
+ tab: "Tab",
723
+ backspace: "Backspace",
724
+ delete: "Delete",
725
+ home: "Home",
726
+ end: "End",
727
+ pageup: "PgUp",
728
+ pagedown: "PgDn",
729
+ up: "Up",
730
+ down: "Down",
731
+ left: "Left",
732
+ right: "Right",
733
+ };
734
+
735
+ function formatKeyPart(part: string, platform: NodeJS.Platform): string {
736
+ const lower = part.toLowerCase();
737
+ if (isModifier(lower)) return modifierLabel(lower, platform);
738
+ const label = KEY_LABELS[lower];
739
+ if (label) return label;
740
+ if (part.length === 1) return part.toUpperCase();
741
+ return `${part.charAt(0).toUpperCase()}${part.slice(1)}`;
742
+ }
743
+
744
+ /** Format a key chord with human-readable, platform-aware modifier labels. */
745
+ export function formatKeyHint(key: KeyId): string {
746
+ const platform = keyHintPlatform();
747
+ return key
748
+ .split("+")
749
+ .map(part => formatKeyPart(part, platform))
750
+ .join("+");
751
+ }
752
+
753
+ /** Format alternative key chords as slash-separated human-readable hints. */
754
+ export function formatKeyHints(keys: KeyId | KeyId[]): string {
755
+ const list = Array.isArray(keys) ? keys : [keys];
756
+ return list.map(formatKeyHint).join("/");
757
+ }
758
+
759
+ export type { Keybinding, KeybindingsConfig, KeyId };
760
+ export { migrateKeybindingsConfigFile };