@nexus-cortex/tui 4.47.0

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 (409) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +2 -0
  3. package/README.md +13 -0
  4. package/bin/cli-full.js +23 -0
  5. package/bin/cortex-ui.js +26 -0
  6. package/bin/ink-ui.js +108 -0
  7. package/bin/launcher-dev.js +266 -0
  8. package/bin/launcher.js +516 -0
  9. package/dist/commands/agent/InteractiveAgentMenu.d.ts +100 -0
  10. package/dist/commands/agent/InteractiveAgentMenu.d.ts.map +1 -0
  11. package/dist/commands/agent/InteractiveAgentMenu.js +909 -0
  12. package/dist/commands/agent/InteractiveAgentMenu.js.map +1 -0
  13. package/dist/commands/agent/index.d.ts +55 -0
  14. package/dist/commands/agent/index.d.ts.map +1 -0
  15. package/dist/commands/agent/index.js +714 -0
  16. package/dist/commands/agent/index.js.map +1 -0
  17. package/dist/commands/chat/interactive.d.ts +13 -0
  18. package/dist/commands/chat/interactive.d.ts.map +1 -0
  19. package/dist/commands/chat/interactive.js +2055 -0
  20. package/dist/commands/chat/interactive.js.map +1 -0
  21. package/dist/commands/system-message/EditorLauncher.d.ts +65 -0
  22. package/dist/commands/system-message/EditorLauncher.d.ts.map +1 -0
  23. package/dist/commands/system-message/EditorLauncher.js +143 -0
  24. package/dist/commands/system-message/EditorLauncher.js.map +1 -0
  25. package/dist/commands/system-message/InlineEditor.d.ts +23 -0
  26. package/dist/commands/system-message/InlineEditor.d.ts.map +1 -0
  27. package/dist/commands/system-message/InlineEditor.js +225 -0
  28. package/dist/commands/system-message/InlineEditor.js.map +1 -0
  29. package/dist/commands/system-message/InteractiveMenu.d.ts +76 -0
  30. package/dist/commands/system-message/InteractiveMenu.d.ts.map +1 -0
  31. package/dist/commands/system-message/InteractiveMenu.js +979 -0
  32. package/dist/commands/system-message/InteractiveMenu.js.map +1 -0
  33. package/dist/commands/system-message/index.d.ts +56 -0
  34. package/dist/commands/system-message/index.d.ts.map +1 -0
  35. package/dist/commands/system-message/index.js +694 -0
  36. package/dist/commands/system-message/index.js.map +1 -0
  37. package/dist/commands/ui/artifacts.d.ts +14 -0
  38. package/dist/commands/ui/artifacts.d.ts.map +1 -0
  39. package/dist/commands/ui/artifacts.js +22 -0
  40. package/dist/commands/ui/artifacts.js.map +1 -0
  41. package/dist/commands/ui/config.d.ts +12 -0
  42. package/dist/commands/ui/config.d.ts.map +1 -0
  43. package/dist/commands/ui/config.js +26 -0
  44. package/dist/commands/ui/config.js.map +1 -0
  45. package/dist/commands/ui/context.d.ts +16 -0
  46. package/dist/commands/ui/context.d.ts.map +1 -0
  47. package/dist/commands/ui/context.js +28 -0
  48. package/dist/commands/ui/context.js.map +1 -0
  49. package/dist/commands/ui/middleware.d.ts +14 -0
  50. package/dist/commands/ui/middleware.d.ts.map +1 -0
  51. package/dist/commands/ui/middleware.js +22 -0
  52. package/dist/commands/ui/middleware.js.map +1 -0
  53. package/dist/commands/ui/models.d.ts +14 -0
  54. package/dist/commands/ui/models.d.ts.map +1 -0
  55. package/dist/commands/ui/models.js +50 -0
  56. package/dist/commands/ui/models.js.map +1 -0
  57. package/dist/commands/ui/permissions.d.ts +14 -0
  58. package/dist/commands/ui/permissions.d.ts.map +1 -0
  59. package/dist/commands/ui/permissions.js +22 -0
  60. package/dist/commands/ui/permissions.js.map +1 -0
  61. package/dist/commands/ui/sessions.d.ts +13 -0
  62. package/dist/commands/ui/sessions.d.ts.map +1 -0
  63. package/dist/commands/ui/sessions.js +45 -0
  64. package/dist/commands/ui/sessions.js.map +1 -0
  65. package/dist/commands/ui/system-messages.d.ts +5 -0
  66. package/dist/commands/ui/system-messages.d.ts.map +1 -0
  67. package/dist/commands/ui/system-messages.js +19 -0
  68. package/dist/commands/ui/system-messages.js.map +1 -0
  69. package/dist/commands/ui/themes.d.ts +12 -0
  70. package/dist/commands/ui/themes.d.ts.map +1 -0
  71. package/dist/commands/ui/themes.js +40 -0
  72. package/dist/commands/ui/themes.js.map +1 -0
  73. package/dist/commands/ui/tmux.d.ts +5 -0
  74. package/dist/commands/ui/tmux.d.ts.map +1 -0
  75. package/dist/commands/ui/tmux.js +19 -0
  76. package/dist/commands/ui/tmux.js.map +1 -0
  77. package/dist/cortex.d.ts +12 -0
  78. package/dist/cortex.d.ts.map +1 -0
  79. package/dist/cortex.js +320 -0
  80. package/dist/cortex.js.map +1 -0
  81. package/dist/index.d.ts +3 -0
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +112 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/ink-ui/CortexApp.d.ts +28 -0
  86. package/dist/ink-ui/CortexApp.d.ts.map +1 -0
  87. package/dist/ink-ui/CortexApp.js +2291 -0
  88. package/dist/ink-ui/CortexApp.js.map +1 -0
  89. package/dist/ink-ui/SimpleInputBuffer.d.ts +63 -0
  90. package/dist/ink-ui/SimpleInputBuffer.d.ts.map +1 -0
  91. package/dist/ink-ui/SimpleInputBuffer.js +369 -0
  92. package/dist/ink-ui/SimpleInputBuffer.js.map +1 -0
  93. package/dist/ink-ui/commands/slashCommands.d.ts +40 -0
  94. package/dist/ink-ui/commands/slashCommands.d.ts.map +1 -0
  95. package/dist/ink-ui/commands/slashCommands.js +111 -0
  96. package/dist/ink-ui/commands/slashCommands.js.map +1 -0
  97. package/dist/ink-ui/commands/types.d.ts +161 -0
  98. package/dist/ink-ui/commands/types.d.ts.map +1 -0
  99. package/dist/ink-ui/commands/types.js +12 -0
  100. package/dist/ink-ui/commands/types.js.map +1 -0
  101. package/dist/ink-ui/components/ApprovalDialog.d.ts +21 -0
  102. package/dist/ink-ui/components/ApprovalDialog.d.ts.map +1 -0
  103. package/dist/ink-ui/components/ApprovalDialog.js +81 -0
  104. package/dist/ink-ui/components/ApprovalDialog.js.map +1 -0
  105. package/dist/ink-ui/components/CommandSuggestions.d.ts +19 -0
  106. package/dist/ink-ui/components/CommandSuggestions.d.ts.map +1 -0
  107. package/dist/ink-ui/components/CommandSuggestions.js +36 -0
  108. package/dist/ink-ui/components/CommandSuggestions.js.map +1 -0
  109. package/dist/ink-ui/components/DiffPreview.d.ts +60 -0
  110. package/dist/ink-ui/components/DiffPreview.d.ts.map +1 -0
  111. package/dist/ink-ui/components/DiffPreview.js +195 -0
  112. package/dist/ink-ui/components/DiffPreview.js.map +1 -0
  113. package/dist/ink-ui/components/DocumentPreview.d.ts +50 -0
  114. package/dist/ink-ui/components/DocumentPreview.d.ts.map +1 -0
  115. package/dist/ink-ui/components/DocumentPreview.js +92 -0
  116. package/dist/ink-ui/components/DocumentPreview.js.map +1 -0
  117. package/dist/ink-ui/components/MarkdownText.d.ts +27 -0
  118. package/dist/ink-ui/components/MarkdownText.d.ts.map +1 -0
  119. package/dist/ink-ui/components/MarkdownText.js +342 -0
  120. package/dist/ink-ui/components/MarkdownText.js.map +1 -0
  121. package/dist/ink-ui/components/MenuRenderer.d.ts +26 -0
  122. package/dist/ink-ui/components/MenuRenderer.d.ts.map +1 -0
  123. package/dist/ink-ui/components/MenuRenderer.js +264 -0
  124. package/dist/ink-ui/components/MenuRenderer.js.map +1 -0
  125. package/dist/ink-ui/components/ModelPickerDialog.d.ts +33 -0
  126. package/dist/ink-ui/components/ModelPickerDialog.d.ts.map +1 -0
  127. package/dist/ink-ui/components/ModelPickerDialog.js +98 -0
  128. package/dist/ink-ui/components/ModelPickerDialog.js.map +1 -0
  129. package/dist/ink-ui/components/StreamDisplay.d.ts +31 -0
  130. package/dist/ink-ui/components/StreamDisplay.d.ts.map +1 -0
  131. package/dist/ink-ui/components/StreamDisplay.js +573 -0
  132. package/dist/ink-ui/components/StreamDisplay.js.map +1 -0
  133. package/dist/ink-ui/components/SubAgentPanel.d.ts +98 -0
  134. package/dist/ink-ui/components/SubAgentPanel.d.ts.map +1 -0
  135. package/dist/ink-ui/components/SubAgentPanel.js +155 -0
  136. package/dist/ink-ui/components/SubAgentPanel.js.map +1 -0
  137. package/dist/ink-ui/components/ThinkingDisplay.d.ts +46 -0
  138. package/dist/ink-ui/components/ThinkingDisplay.d.ts.map +1 -0
  139. package/dist/ink-ui/components/ThinkingDisplay.js +176 -0
  140. package/dist/ink-ui/components/ThinkingDisplay.js.map +1 -0
  141. package/dist/ink-ui/components/ToolCallDisplay.d.ts +51 -0
  142. package/dist/ink-ui/components/ToolCallDisplay.d.ts.map +1 -0
  143. package/dist/ink-ui/components/ToolCallDisplay.js +378 -0
  144. package/dist/ink-ui/components/ToolCallDisplay.js.map +1 -0
  145. package/dist/ink-ui/components/WritePreview.d.ts +42 -0
  146. package/dist/ink-ui/components/WritePreview.d.ts.map +1 -0
  147. package/dist/ink-ui/components/WritePreview.js +100 -0
  148. package/dist/ink-ui/components/WritePreview.js.map +1 -0
  149. package/dist/ink-ui/contexts/KeypressContext.d.ts +32 -0
  150. package/dist/ink-ui/contexts/KeypressContext.d.ts.map +1 -0
  151. package/dist/ink-ui/contexts/KeypressContext.js +529 -0
  152. package/dist/ink-ui/contexts/KeypressContext.js.map +1 -0
  153. package/dist/ink-ui/contexts/SessionContext.d.ts +46 -0
  154. package/dist/ink-ui/contexts/SessionContext.d.ts.map +1 -0
  155. package/dist/ink-ui/contexts/SessionContext.js +162 -0
  156. package/dist/ink-ui/contexts/SessionContext.js.map +1 -0
  157. package/dist/ink-ui/core-stubs.d.ts +270 -0
  158. package/dist/ink-ui/core-stubs.d.ts.map +1 -0
  159. package/dist/ink-ui/core-stubs.js +276 -0
  160. package/dist/ink-ui/core-stubs.js.map +1 -0
  161. package/dist/ink-ui/cortex-types.d.ts +214 -0
  162. package/dist/ink-ui/cortex-types.d.ts.map +1 -0
  163. package/dist/ink-ui/cortex-types.js +52 -0
  164. package/dist/ink-ui/cortex-types.js.map +1 -0
  165. package/dist/ink-ui/hooks/useCortexStream.d.ts +75 -0
  166. package/dist/ink-ui/hooks/useCortexStream.d.ts.map +1 -0
  167. package/dist/ink-ui/hooks/useCortexStream.js +518 -0
  168. package/dist/ink-ui/hooks/useCortexStream.js.map +1 -0
  169. package/dist/ink-ui/hooks/useFocus.d.ts +11 -0
  170. package/dist/ink-ui/hooks/useFocus.d.ts.map +1 -0
  171. package/dist/ink-ui/hooks/useFocus.js +51 -0
  172. package/dist/ink-ui/hooks/useFocus.js.map +1 -0
  173. package/dist/ink-ui/hooks/useHistoryManager.d.ts +23 -0
  174. package/dist/ink-ui/hooks/useHistoryManager.d.ts.map +1 -0
  175. package/dist/ink-ui/hooks/useHistoryManager.js +63 -0
  176. package/dist/ink-ui/hooks/useHistoryManager.js.map +1 -0
  177. package/dist/ink-ui/hooks/useKeypress.d.ts +18 -0
  178. package/dist/ink-ui/hooks/useKeypress.d.ts.map +1 -0
  179. package/dist/ink-ui/hooks/useKeypress.js +27 -0
  180. package/dist/ink-ui/hooks/useKeypress.js.map +1 -0
  181. package/dist/ink-ui/hooks/useReactApprovalHandler.d.ts +74 -0
  182. package/dist/ink-ui/hooks/useReactApprovalHandler.d.ts.map +1 -0
  183. package/dist/ink-ui/hooks/useReactApprovalHandler.js +83 -0
  184. package/dist/ink-ui/hooks/useReactApprovalHandler.js.map +1 -0
  185. package/dist/ink-ui/hooks/useTerminalSize.d.ts +10 -0
  186. package/dist/ink-ui/hooks/useTerminalSize.d.ts.map +1 -0
  187. package/dist/ink-ui/hooks/useTerminalSize.js +28 -0
  188. package/dist/ink-ui/hooks/useTerminalSize.js.map +1 -0
  189. package/dist/ink-ui/semantic-colors.d.ts +8 -0
  190. package/dist/ink-ui/semantic-colors.d.ts.map +1 -0
  191. package/dist/ink-ui/semantic-colors.js +24 -0
  192. package/dist/ink-ui/semantic-colors.js.map +1 -0
  193. package/dist/ink-ui/state/extensions.d.ts +68 -0
  194. package/dist/ink-ui/state/extensions.d.ts.map +1 -0
  195. package/dist/ink-ui/state/extensions.js +97 -0
  196. package/dist/ink-ui/state/extensions.js.map +1 -0
  197. package/dist/ink-ui/themes/ansi-light.d.ts +8 -0
  198. package/dist/ink-ui/themes/ansi-light.d.ts.map +1 -0
  199. package/dist/ink-ui/themes/ansi-light.js +143 -0
  200. package/dist/ink-ui/themes/ansi-light.js.map +1 -0
  201. package/dist/ink-ui/themes/ansi.d.ts +8 -0
  202. package/dist/ink-ui/themes/ansi.d.ts.map +1 -0
  203. package/dist/ink-ui/themes/ansi.js +153 -0
  204. package/dist/ink-ui/themes/ansi.js.map +1 -0
  205. package/dist/ink-ui/themes/atom-one-dark.d.ts +8 -0
  206. package/dist/ink-ui/themes/atom-one-dark.d.ts.map +1 -0
  207. package/dist/ink-ui/themes/atom-one-dark.js +140 -0
  208. package/dist/ink-ui/themes/atom-one-dark.js.map +1 -0
  209. package/dist/ink-ui/themes/ayu-light.d.ts +8 -0
  210. package/dist/ink-ui/themes/ayu-light.d.ts.map +1 -0
  211. package/dist/ink-ui/themes/ayu-light.js +132 -0
  212. package/dist/ink-ui/themes/ayu-light.js.map +1 -0
  213. package/dist/ink-ui/themes/ayu.d.ts +8 -0
  214. package/dist/ink-ui/themes/ayu.d.ts.map +1 -0
  215. package/dist/ink-ui/themes/ayu.js +106 -0
  216. package/dist/ink-ui/themes/ayu.js.map +1 -0
  217. package/dist/ink-ui/themes/color-utils.d.ts +23 -0
  218. package/dist/ink-ui/themes/color-utils.d.ts.map +1 -0
  219. package/dist/ink-ui/themes/color-utils.js +237 -0
  220. package/dist/ink-ui/themes/color-utils.js.map +1 -0
  221. package/dist/ink-ui/themes/default-light.d.ts +8 -0
  222. package/dist/ink-ui/themes/default-light.d.ts.map +1 -0
  223. package/dist/ink-ui/themes/default-light.js +100 -0
  224. package/dist/ink-ui/themes/default-light.js.map +1 -0
  225. package/dist/ink-ui/themes/default.d.ts +8 -0
  226. package/dist/ink-ui/themes/default.d.ts.map +1 -0
  227. package/dist/ink-ui/themes/default.js +143 -0
  228. package/dist/ink-ui/themes/default.js.map +1 -0
  229. package/dist/ink-ui/themes/dracula.d.ts +8 -0
  230. package/dist/ink-ui/themes/dracula.d.ts.map +1 -0
  231. package/dist/ink-ui/themes/dracula.js +117 -0
  232. package/dist/ink-ui/themes/dracula.js.map +1 -0
  233. package/dist/ink-ui/themes/github-dark.d.ts +8 -0
  234. package/dist/ink-ui/themes/github-dark.d.ts.map +1 -0
  235. package/dist/ink-ui/themes/github-dark.js +140 -0
  236. package/dist/ink-ui/themes/github-dark.js.map +1 -0
  237. package/dist/ink-ui/themes/github-light.d.ts +8 -0
  238. package/dist/ink-ui/themes/github-light.d.ts.map +1 -0
  239. package/dist/ink-ui/themes/github-light.js +142 -0
  240. package/dist/ink-ui/themes/github-light.js.map +1 -0
  241. package/dist/ink-ui/themes/googlecode.d.ts +8 -0
  242. package/dist/ink-ui/themes/googlecode.d.ts.map +1 -0
  243. package/dist/ink-ui/themes/googlecode.js +139 -0
  244. package/dist/ink-ui/themes/googlecode.js.map +1 -0
  245. package/dist/ink-ui/themes/no-color.d.ts +8 -0
  246. package/dist/ink-ui/themes/no-color.d.ts.map +1 -0
  247. package/dist/ink-ui/themes/no-color.js +118 -0
  248. package/dist/ink-ui/themes/no-color.js.map +1 -0
  249. package/dist/ink-ui/themes/semantic-tokens.d.ts +40 -0
  250. package/dist/ink-ui/themes/semantic-tokens.d.ts.map +1 -0
  251. package/dist/ink-ui/themes/semantic-tokens.js +100 -0
  252. package/dist/ink-ui/themes/semantic-tokens.js.map +1 -0
  253. package/dist/ink-ui/themes/shades-of-purple.d.ts +12 -0
  254. package/dist/ink-ui/themes/shades-of-purple.d.ts.map +1 -0
  255. package/dist/ink-ui/themes/shades-of-purple.js +306 -0
  256. package/dist/ink-ui/themes/shades-of-purple.js.map +1 -0
  257. package/dist/ink-ui/themes/theme-manager.d.ts +67 -0
  258. package/dist/ink-ui/themes/theme-manager.d.ts.map +1 -0
  259. package/dist/ink-ui/themes/theme-manager.js +263 -0
  260. package/dist/ink-ui/themes/theme-manager.js.map +1 -0
  261. package/dist/ink-ui/themes/theme.d.ts +134 -0
  262. package/dist/ink-ui/themes/theme.d.ts.map +1 -0
  263. package/dist/ink-ui/themes/theme.js +390 -0
  264. package/dist/ink-ui/themes/theme.js.map +1 -0
  265. package/dist/ink-ui/themes/xcode.d.ts +8 -0
  266. package/dist/ink-ui/themes/xcode.d.ts.map +1 -0
  267. package/dist/ink-ui/themes/xcode.js +147 -0
  268. package/dist/ink-ui/themes/xcode.js.map +1 -0
  269. package/dist/ink-ui/types.d.ts +306 -0
  270. package/dist/ink-ui/types.d.ts.map +1 -0
  271. package/dist/ink-ui/types.js +65 -0
  272. package/dist/ink-ui/types.js.map +1 -0
  273. package/dist/ink-ui/utils/input.d.ts +18 -0
  274. package/dist/ink-ui/utils/input.d.ts.map +1 -0
  275. package/dist/ink-ui/utils/input.js +51 -0
  276. package/dist/ink-ui/utils/input.js.map +1 -0
  277. package/dist/ink-ui/utils/mouse.d.ts +33 -0
  278. package/dist/ink-ui/utils/mouse.d.ts.map +1 -0
  279. package/dist/ink-ui/utils/mouse.js +182 -0
  280. package/dist/ink-ui/utils/mouse.js.map +1 -0
  281. package/dist/services/BuiltinCommandLoader.d.ts +21 -0
  282. package/dist/services/BuiltinCommandLoader.d.ts.map +1 -0
  283. package/dist/services/BuiltinCommandLoader.js +182 -0
  284. package/dist/services/BuiltinCommandLoader.js.map +1 -0
  285. package/dist/services/CommandService.d.ts +39 -0
  286. package/dist/services/CommandService.d.ts.map +1 -0
  287. package/dist/services/CommandService.js +49 -0
  288. package/dist/services/CommandService.js.map +1 -0
  289. package/dist/services/FileCommandLoader.d.ts +16 -0
  290. package/dist/services/FileCommandLoader.d.ts.map +1 -0
  291. package/dist/services/FileCommandLoader.js +19 -0
  292. package/dist/services/FileCommandLoader.js.map +1 -0
  293. package/dist/services/McpPromptLoader.d.ts +16 -0
  294. package/dist/services/McpPromptLoader.d.ts.map +1 -0
  295. package/dist/services/McpPromptLoader.js +19 -0
  296. package/dist/services/McpPromptLoader.js.map +1 -0
  297. package/dist/services/index.d.ts +8 -0
  298. package/dist/services/index.d.ts.map +1 -0
  299. package/dist/services/index.js +8 -0
  300. package/dist/services/index.js.map +1 -0
  301. package/dist/ui/ChalkMenuRenderer.d.ts +22 -0
  302. package/dist/ui/ChalkMenuRenderer.d.ts.map +1 -0
  303. package/dist/ui/ChalkMenuRenderer.js +478 -0
  304. package/dist/ui/ChalkMenuRenderer.js.map +1 -0
  305. package/dist/ui/ChalkModelPicker.d.ts +20 -0
  306. package/dist/ui/ChalkModelPicker.d.ts.map +1 -0
  307. package/dist/ui/ChalkModelPicker.js +363 -0
  308. package/dist/ui/ChalkModelPicker.js.map +1 -0
  309. package/dist/ui/ChalkThemePicker.d.ts +20 -0
  310. package/dist/ui/ChalkThemePicker.d.ts.map +1 -0
  311. package/dist/ui/ChalkThemePicker.js +370 -0
  312. package/dist/ui/ChalkThemePicker.js.map +1 -0
  313. package/dist/ui/InkApprovalDialog.d.ts +8 -0
  314. package/dist/ui/InkApprovalDialog.d.ts.map +1 -0
  315. package/dist/ui/InkApprovalDialog.js +25 -0
  316. package/dist/ui/InkApprovalDialog.js.map +1 -0
  317. package/dist/ui/InkCommandPalette.d.ts +43 -0
  318. package/dist/ui/InkCommandPalette.d.ts.map +1 -0
  319. package/dist/ui/InkCommandPalette.js +105 -0
  320. package/dist/ui/InkCommandPalette.js.map +1 -0
  321. package/dist/ui/InkConfigMenu.d.ts +24 -0
  322. package/dist/ui/InkConfigMenu.d.ts.map +1 -0
  323. package/dist/ui/InkConfigMenu.js +259 -0
  324. package/dist/ui/InkConfigMenu.js.map +1 -0
  325. package/dist/ui/InkHelp.d.ts +25 -0
  326. package/dist/ui/InkHelp.d.ts.map +1 -0
  327. package/dist/ui/InkHelp.js +55 -0
  328. package/dist/ui/InkHelp.js.map +1 -0
  329. package/dist/ui/InkMenuPicker.d.ts +19 -0
  330. package/dist/ui/InkMenuPicker.d.ts.map +1 -0
  331. package/dist/ui/InkMenuPicker.js +33 -0
  332. package/dist/ui/InkMenuPicker.js.map +1 -0
  333. package/dist/ui/InkModelPicker.d.ts +23 -0
  334. package/dist/ui/InkModelPicker.d.ts.map +1 -0
  335. package/dist/ui/InkModelPicker.js +53 -0
  336. package/dist/ui/InkModelPicker.js.map +1 -0
  337. package/dist/ui/PersistentInput.d.ts +91 -0
  338. package/dist/ui/PersistentInput.d.ts.map +1 -0
  339. package/dist/ui/PersistentInput.js +283 -0
  340. package/dist/ui/PersistentInput.js.map +1 -0
  341. package/dist/ui/RawInput.d.ts +27 -0
  342. package/dist/ui/RawInput.d.ts.map +1 -0
  343. package/dist/ui/RawInput.js +731 -0
  344. package/dist/ui/RawInput.js.map +1 -0
  345. package/dist/ui/SlashCommandAutocomplete.d.ts +94 -0
  346. package/dist/ui/SlashCommandAutocomplete.d.ts.map +1 -0
  347. package/dist/ui/SlashCommandAutocomplete.js +274 -0
  348. package/dist/ui/SlashCommandAutocomplete.js.map +1 -0
  349. package/dist/ui/SplashScreen.d.ts +76 -0
  350. package/dist/ui/SplashScreen.d.ts.map +1 -0
  351. package/dist/ui/SplashScreen.js +316 -0
  352. package/dist/ui/SplashScreen.js.map +1 -0
  353. package/dist/ui/components/ArtifactDashboard.d.ts +16 -0
  354. package/dist/ui/components/ArtifactDashboard.d.ts.map +1 -0
  355. package/dist/ui/components/ArtifactDashboard.js +102 -0
  356. package/dist/ui/components/ArtifactDashboard.js.map +1 -0
  357. package/dist/ui/components/ChatInput.d.ts +36 -0
  358. package/dist/ui/components/ChatInput.d.ts.map +1 -0
  359. package/dist/ui/components/ChatInput.js +11 -0
  360. package/dist/ui/components/ChatInput.js.map +1 -0
  361. package/dist/ui/components/ConfigWizard.d.ts +17 -0
  362. package/dist/ui/components/ConfigWizard.d.ts.map +1 -0
  363. package/dist/ui/components/ConfigWizard.js +134 -0
  364. package/dist/ui/components/ConfigWizard.js.map +1 -0
  365. package/dist/ui/components/ContextViewer.d.ts +18 -0
  366. package/dist/ui/components/ContextViewer.d.ts.map +1 -0
  367. package/dist/ui/components/ContextViewer.js +85 -0
  368. package/dist/ui/components/ContextViewer.js.map +1 -0
  369. package/dist/ui/components/MiddlewareDashboard.d.ts +16 -0
  370. package/dist/ui/components/MiddlewareDashboard.d.ts.map +1 -0
  371. package/dist/ui/components/MiddlewareDashboard.js +98 -0
  372. package/dist/ui/components/MiddlewareDashboard.js.map +1 -0
  373. package/dist/ui/components/ModelPicker.d.ts +24 -0
  374. package/dist/ui/components/ModelPicker.d.ts.map +1 -0
  375. package/dist/ui/components/ModelPicker.js +96 -0
  376. package/dist/ui/components/ModelPicker.js.map +1 -0
  377. package/dist/ui/components/MultiLineInput.d.ts +27 -0
  378. package/dist/ui/components/MultiLineInput.d.ts.map +1 -0
  379. package/dist/ui/components/MultiLineInput.js +182 -0
  380. package/dist/ui/components/MultiLineInput.js.map +1 -0
  381. package/dist/ui/components/PermissionsBrowser.d.ts +16 -0
  382. package/dist/ui/components/PermissionsBrowser.d.ts.map +1 -0
  383. package/dist/ui/components/PermissionsBrowser.js +110 -0
  384. package/dist/ui/components/PermissionsBrowser.js.map +1 -0
  385. package/dist/ui/components/SessionBrowser.d.ts +19 -0
  386. package/dist/ui/components/SessionBrowser.d.ts.map +1 -0
  387. package/dist/ui/components/SessionBrowser.js +66 -0
  388. package/dist/ui/components/SessionBrowser.js.map +1 -0
  389. package/dist/ui/components/StatusBar.d.ts +32 -0
  390. package/dist/ui/components/StatusBar.d.ts.map +1 -0
  391. package/dist/ui/components/StatusBar.js +27 -0
  392. package/dist/ui/components/StatusBar.js.map +1 -0
  393. package/dist/ui/components/SystemMessageBrowser.d.ts +11 -0
  394. package/dist/ui/components/SystemMessageBrowser.d.ts.map +1 -0
  395. package/dist/ui/components/SystemMessageBrowser.js +106 -0
  396. package/dist/ui/components/SystemMessageBrowser.js.map +1 -0
  397. package/dist/ui/components/ThemePicker.d.ts +11 -0
  398. package/dist/ui/components/ThemePicker.d.ts.map +1 -0
  399. package/dist/ui/components/ThemePicker.js +62 -0
  400. package/dist/ui/components/ThemePicker.js.map +1 -0
  401. package/dist/ui/components/TmuxBrowser.d.ts +11 -0
  402. package/dist/ui/components/TmuxBrowser.d.ts.map +1 -0
  403. package/dist/ui/components/TmuxBrowser.js +85 -0
  404. package/dist/ui/components/TmuxBrowser.js.map +1 -0
  405. package/dist/ui/components/index.d.ts +22 -0
  406. package/dist/ui/components/index.d.ts.map +1 -0
  407. package/dist/ui/components/index.js +21 -0
  408. package/dist/ui/components/index.js.map +1 -0
  409. package/package.json +70 -0
@@ -0,0 +1,731 @@
1
+ /**
2
+ * Raw Terminal Input with Persistent Status Line
3
+ *
4
+ * Provides a readline-like interface but with full control over terminal rendering,
5
+ * allowing us to show a status line below the input while the user types.
6
+ */
7
+ import { renderStatusLine } from './SplashScreen.js';
8
+ import { slashCommandAutocomplete } from './SlashCommandAutocomplete.js';
9
+ // ANSI escape codes
10
+ const ESC = '\x1b';
11
+ const CSI = `${ESC}[`;
12
+ const ANSI = {
13
+ clearLine: `${CSI}2K`,
14
+ clearToEnd: `${CSI}0K`,
15
+ cursorUp: (n) => `${CSI}${n}A`,
16
+ cursorDown: (n) => `${CSI}${n}B`,
17
+ cursorForward: (n) => `${CSI}${n}C`,
18
+ cursorBack: (n) => `${CSI}${n}D`,
19
+ cursorToColumn: (n) => `${CSI}${n}G`,
20
+ saveCursor: `${ESC}7`,
21
+ restoreCursor: `${ESC}8`,
22
+ hideCursor: `${CSI}?25l`,
23
+ showCursor: `${CSI}?25h`,
24
+ };
25
+ // Bracketed paste mode markers (some terminals send these)
26
+ const PASTE_START = `${CSI}200~`;
27
+ const PASTE_END = `${CSI}201~`;
28
+ /**
29
+ * Calculate display width of a string (accounting for wide characters)
30
+ * Wide characters (emoji, CJK) take 2 columns
31
+ */
32
+ function getDisplayWidth(str) {
33
+ let width = 0;
34
+ for (const char of str) {
35
+ const code = char.codePointAt(0) || 0;
36
+ // Wide characters: CJK, emoji, fullwidth
37
+ if ((code >= 0x1100 && code <= 0x115F) || // Hangul Jamo
38
+ (code >= 0x2E80 && code <= 0x9FFF) || // CJK
39
+ (code >= 0xAC00 && code <= 0xD7A3) || // Hangul Syllables
40
+ (code >= 0xF900 && code <= 0xFAFF) || // CJK Compatibility
41
+ (code >= 0xFE10 && code <= 0xFE1F) || // Vertical forms
42
+ (code >= 0xFE30 && code <= 0xFE6F) || // CJK Compatibility Forms
43
+ (code >= 0xFF00 && code <= 0xFF60) || // Fullwidth
44
+ (code >= 0xFFE0 && code <= 0xFFE6) || // Fullwidth symbols
45
+ (code >= 0x1F300 && code <= 0x1F9FF) || // Emoji
46
+ (code >= 0x20000 && code <= 0x2FFFF) // CJK Extension B+
47
+ ) {
48
+ width += 2;
49
+ }
50
+ else if (code >= 0x20) {
51
+ width += 1;
52
+ }
53
+ // Control characters (< 0x20) have width 0
54
+ }
55
+ return width;
56
+ }
57
+ /**
58
+ * Get display width up to a character position (for cursor positioning)
59
+ */
60
+ function getDisplayWidthUpTo(str, charPos) {
61
+ return getDisplayWidth(str.slice(0, charPos));
62
+ }
63
+ /**
64
+ * Calculate multiline metrics for input with explicit newlines and terminal wrapping
65
+ * Returns info about total visual lines and cursor position
66
+ */
67
+ function getMultilineMetrics(input, cursorPos, termWidth, prefixWidth) {
68
+ const lines = input.split('\n');
69
+ let totalVisualLines = 0;
70
+ let cursorVisualRow = 0;
71
+ let cursorVisualCol = 0;
72
+ let charCount = 0;
73
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
74
+ const line = lines[lineIdx];
75
+ const lineDisplayWidth = getDisplayWidth(line);
76
+ // First line has prefix, subsequent lines start at column 0
77
+ const effectiveWidth = lineIdx === 0 ? prefixWidth + lineDisplayWidth : lineDisplayWidth;
78
+ const lineVisualRows = Math.max(1, Math.ceil(effectiveWidth / termWidth) || 1);
79
+ // Check if cursor is on this line
80
+ const lineStart = charCount;
81
+ const lineEnd = charCount + line.length;
82
+ if (cursorPos >= lineStart && cursorPos <= lineEnd) {
83
+ // Cursor is on this line
84
+ const posInLine = cursorPos - lineStart;
85
+ const displayPosInLine = getDisplayWidthUpTo(line, posInLine);
86
+ const absoluteCol = lineIdx === 0 ? prefixWidth + displayPosInLine : displayPosInLine;
87
+ cursorVisualRow = totalVisualLines + Math.floor(absoluteCol / termWidth);
88
+ cursorVisualCol = absoluteCol % termWidth;
89
+ }
90
+ totalVisualLines += lineVisualRows;
91
+ charCount += line.length + 1; // +1 for newline
92
+ }
93
+ return { totalVisualLines, cursorVisualRow, cursorVisualCol };
94
+ }
95
+ /**
96
+ * Find the character position in input that corresponds to a visual row/col
97
+ * Used for up/down arrow navigation in multiline input
98
+ */
99
+ function findCharPosForVisualPosition(input, targetRow, targetCol, termWidth, prefixWidth) {
100
+ const lines = input.split('\n');
101
+ let currentVisualRow = 0;
102
+ let charCount = 0;
103
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
104
+ const line = lines[lineIdx];
105
+ const lineDisplayWidth = getDisplayWidth(line);
106
+ // First line has prefix, subsequent lines start at column 0
107
+ const effectiveWidth = lineIdx === 0 ? prefixWidth + lineDisplayWidth : lineDisplayWidth;
108
+ const lineVisualRows = Math.max(1, Math.ceil(effectiveWidth / termWidth) || 1);
109
+ // Check if target row is within this line's visual rows
110
+ if (targetRow >= currentVisualRow && targetRow < currentVisualRow + lineVisualRows) {
111
+ // Target is on this line - find exact character position
112
+ const rowWithinLine = targetRow - currentVisualRow;
113
+ const targetDisplayPos = rowWithinLine * termWidth + targetCol - (rowWithinLine === 0 && lineIdx === 0 ? prefixWidth : 0);
114
+ // Find character position for this display position within the line
115
+ let displayWidth = 0;
116
+ for (let i = 0; i < line.length; i++) {
117
+ const charWidth = getDisplayWidth(line.charAt(i));
118
+ if (displayWidth >= targetDisplayPos) {
119
+ return charCount + i;
120
+ }
121
+ displayWidth += charWidth;
122
+ }
123
+ // If we reach end of line, return end of line position
124
+ return charCount + line.length;
125
+ }
126
+ currentVisualRow += lineVisualRows;
127
+ charCount += line.length + 1; // +1 for newline
128
+ }
129
+ // If target row is beyond input, return end of input
130
+ return input.length;
131
+ }
132
+ /**
133
+ * Check if a character is a word character (alphanumeric or underscore)
134
+ */
135
+ function isWordChar(char) {
136
+ return /[\w\u00C0-\u024F\u1E00-\u1EFF]/.test(char);
137
+ }
138
+ /**
139
+ * Find the start of the previous word from cursor position
140
+ * Mimics Option+Left behavior: skip whitespace, then skip word chars
141
+ */
142
+ function findPrevWordStart(str, pos) {
143
+ if (pos <= 0)
144
+ return 0;
145
+ let i = pos - 1;
146
+ // Skip any whitespace/non-word chars immediately before cursor
147
+ while (i > 0 && !isWordChar(str[i])) {
148
+ i--;
149
+ }
150
+ // Now skip the word characters to find the start of the word
151
+ while (i > 0 && isWordChar(str[i - 1])) {
152
+ i--;
153
+ }
154
+ return i;
155
+ }
156
+ /**
157
+ * Find the end of the next word from cursor position
158
+ * Mimics Option+Right behavior: skip current word, then skip whitespace
159
+ */
160
+ function findNextWordEnd(str, pos) {
161
+ if (pos >= str.length)
162
+ return str.length;
163
+ let i = pos;
164
+ // Skip current word characters
165
+ while (i < str.length && isWordChar(str[i])) {
166
+ i++;
167
+ }
168
+ // Skip whitespace/non-word chars to reach the next word
169
+ while (i < str.length && !isWordChar(str[i])) {
170
+ i++;
171
+ }
172
+ return i;
173
+ }
174
+ // Track frame state for redraws
175
+ let lastFrameTotalLines = 0;
176
+ let lastCursorRowInFrame = 0; // Which row (0-indexed from top of frame) cursor is on
177
+ // Module-level history that persists across rawQuestion calls
178
+ const inputHistory = [];
179
+ const MAX_HISTORY_SIZE = 100;
180
+ /**
181
+ * Draw the input frame with status line below
182
+ *
183
+ * Uses explicit line counting and cursor movement (not save/restore which fails on scroll).
184
+ * Supports multiline input with explicit newlines and terminal wrapping.
185
+ */
186
+ function drawInputFrame(inputLine, cursorPos, options) {
187
+ const theme = options.theme;
188
+ const termWidth = process.stdout.columns || 80;
189
+ const borderWidth = Math.min(70, termWidth);
190
+ const statusLine = renderStatusLine(options.getStatusState());
191
+ const shortcuts = ' / commands • ←→↑↓ nav • ⌥←→ word • ⌥↑↓ 5 lines • ⌥⌫ del word';
192
+ const prefixWidth = 3; // " > "
193
+ const prefix = theme.colors.info(' > ');
194
+ // Calculate multiline metrics (handles explicit newlines + terminal wrapping)
195
+ const metrics = getMultilineMetrics(inputLine, cursorPos, termWidth, prefixWidth);
196
+ const inputLinesCount = metrics.totalVisualLines;
197
+ // Get autocomplete popup lines (if visible)
198
+ const autocompleteLines = slashCommandAutocomplete.render();
199
+ const autocompleteLineCount = autocompleteLines.length;
200
+ // For redraws, move cursor back to top of previous frame
201
+ // Use tracked cursor position for accurate repositioning
202
+ if (lastFrameTotalLines > 0 && lastCursorRowInFrame > 0) {
203
+ // Move to start of line first
204
+ process.stdout.write('\r');
205
+ // Move up from cursor's current row to top of frame
206
+ process.stdout.write(ANSI.cursorUp(lastCursorRowInFrame));
207
+ }
208
+ // Calculate total lines this frame will use
209
+ // Frame = autocomplete popup + top border (1) + input lines + bottom border (1) + shortcuts (1) + status (1)
210
+ const totalFrameLines = autocompleteLineCount + 1 + inputLinesCount + 1 + 1 + 1;
211
+ lastFrameTotalLines = totalFrameLines;
212
+ // Draw autocomplete popup (if visible) - above the input box
213
+ for (const line of autocompleteLines) {
214
+ process.stdout.write(ANSI.clearLine);
215
+ process.stdout.write(line + '\n');
216
+ }
217
+ // Draw top border
218
+ process.stdout.write(ANSI.clearLine);
219
+ process.stdout.write(theme.dimmed('─'.repeat(borderWidth)) + '\n');
220
+ // Draw input line(s) - terminal handles wrapping naturally
221
+ // For multiline input, we need to clear each line as we go
222
+ const inputLines = inputLine.split('\n');
223
+ for (let i = 0; i < inputLines.length; i++) {
224
+ process.stdout.write(ANSI.clearLine);
225
+ if (i === 0) {
226
+ process.stdout.write(prefix + inputLines[i]);
227
+ }
228
+ else {
229
+ process.stdout.write(inputLines[i]);
230
+ }
231
+ process.stdout.write(ANSI.clearToEnd);
232
+ if (i < inputLines.length - 1) {
233
+ process.stdout.write('\n');
234
+ }
235
+ }
236
+ // Move to next line after input
237
+ process.stdout.write('\n');
238
+ // Draw bottom border
239
+ process.stdout.write(ANSI.clearLine);
240
+ process.stdout.write(theme.dimmed('─'.repeat(borderWidth)) + '\n');
241
+ // Draw shortcuts
242
+ process.stdout.write(ANSI.clearLine);
243
+ process.stdout.write(theme.dimmed(shortcuts) + '\n');
244
+ // Draw status line
245
+ process.stdout.write(ANSI.clearLine);
246
+ process.stdout.write(statusLine + ANSI.clearToEnd);
247
+ // Clear any extra lines below (in case previous input was longer or autocomplete was visible)
248
+ const extraLinesToClear = 5 + (autocompleteLineCount > 0 ? 15 : 0); // Extra space for autocomplete
249
+ for (let i = 0; i < extraLinesToClear; i++) {
250
+ process.stdout.write('\n' + ANSI.clearLine);
251
+ }
252
+ // Move back up past the extra cleared lines
253
+ process.stdout.write(ANSI.cursorUp(extraLinesToClear));
254
+ // Move cursor back to input line
255
+ // From status line, go up: shortcuts(1) + bottom border(1) + input lines to reach first input row
256
+ // Then we'll move down to the correct row within input
257
+ const linesUp = 3 + (inputLinesCount - 1);
258
+ process.stdout.write(ANSI.cursorUp(linesUp));
259
+ // Move down to correct visual row within input
260
+ if (metrics.cursorVisualRow > 0) {
261
+ process.stdout.write(ANSI.cursorDown(metrics.cursorVisualRow));
262
+ }
263
+ // Move to correct column (1-indexed for ANSI)
264
+ process.stdout.write(ANSI.cursorToColumn(metrics.cursorVisualCol + 1));
265
+ // Track where cursor ends up (row within frame, 0-indexed from top)
266
+ // Cursor is at: autocomplete lines + top border (row 0) + 1 + cursorVisualRow
267
+ lastCursorRowInFrame = autocompleteLineCount + 1 + metrics.cursorVisualRow;
268
+ }
269
+ /**
270
+ * Reset frame position tracking (call when starting new input session)
271
+ */
272
+ function resetFramePosition() {
273
+ lastFrameTotalLines = 0;
274
+ lastCursorRowInFrame = 0;
275
+ }
276
+ /**
277
+ * Clear the input frame completely (erase all lines)
278
+ * This ensures the frame doesn't appear in scrollback history
279
+ * Optionally echoes the submitted input text
280
+ */
281
+ function clearInputFrame(input, theme) {
282
+ // Move to top of frame using tracked cursor position
283
+ if (lastCursorRowInFrame > 0) {
284
+ process.stdout.write('\r');
285
+ process.stdout.write(ANSI.cursorUp(lastCursorRowInFrame));
286
+ }
287
+ // Clear all lines of the frame + extra padding we added
288
+ const totalLinesToClear = lastFrameTotalLines + 5; // frame + padding
289
+ for (let i = 0; i < totalLinesToClear; i++) {
290
+ process.stdout.write(ANSI.clearLine);
291
+ if (i < totalLinesToClear - 1) {
292
+ process.stdout.write('\n');
293
+ }
294
+ }
295
+ // Move back to top
296
+ process.stdout.write(ANSI.cursorUp(totalLinesToClear - 1));
297
+ process.stdout.write('\r');
298
+ // Reset frame position tracking
299
+ lastFrameTotalLines = 0;
300
+ lastCursorRowInFrame = 0;
301
+ // Echo just the user's input for history
302
+ if (input.trim()) {
303
+ process.stdout.write(theme.colors.info('> ') + input + '\n');
304
+ }
305
+ }
306
+ /**
307
+ * Prompt for input with persistent status line below
308
+ */
309
+ export function rawQuestion(options) {
310
+ return new Promise((resolve) => {
311
+ let input = '';
312
+ let cursorPos = 0;
313
+ let historyIndex = -1; // -1 means not browsing history
314
+ let drawTimeout = null;
315
+ // Reset frame position for new input session
316
+ resetFramePosition();
317
+ // Debounced redraw to prevent flickering during paste
318
+ const scheduleRedraw = () => {
319
+ if (drawTimeout) {
320
+ clearTimeout(drawTimeout);
321
+ }
322
+ drawTimeout = setTimeout(() => {
323
+ drawInputFrame(input, cursorPos, options);
324
+ drawTimeout = null;
325
+ }, 16); // ~60fps max
326
+ };
327
+ // Initial draw
328
+ drawInputFrame(input, cursorPos, options);
329
+ // Enable raw mode - use try-catch to prevent crashes if stdin is in unexpected state
330
+ if (process.stdin.isTTY) {
331
+ try {
332
+ process.stdin.setRawMode(true);
333
+ }
334
+ catch {
335
+ // Ignore errors if stdin is already closed or in unexpected state
336
+ }
337
+ }
338
+ process.stdin.resume();
339
+ // Helper to update autocomplete suggestions after input changes
340
+ const updateAutocomplete = async () => {
341
+ await slashCommandAutocomplete.update(input);
342
+ };
343
+ const handleData = (data) => {
344
+ const str = data.toString();
345
+ // Handle special keys
346
+ if (str === '\r' || str === '\n') {
347
+ // Enter - if autocomplete is visible with selection, accept it; otherwise submit
348
+ if (slashCommandAutocomplete.isVisible()) {
349
+ const newInput = slashCommandAutocomplete.accept();
350
+ if (newInput !== null) {
351
+ input = newInput + ' '; // Add space after command for arguments
352
+ cursorPos = input.length;
353
+ updateAutocomplete();
354
+ drawInputFrame(input, cursorPos, options);
355
+ return;
356
+ }
357
+ }
358
+ // Hide autocomplete before submitting
359
+ slashCommandAutocomplete.hide();
360
+ try {
361
+ process.stdin.removeListener('data', handleData);
362
+ }
363
+ catch {
364
+ // Ignore errors during listener removal
365
+ }
366
+ if (process.stdin.isTTY) {
367
+ try {
368
+ process.stdin.setRawMode(false);
369
+ }
370
+ catch {
371
+ // Ignore errors if stdin is already closed or in unexpected state
372
+ }
373
+ }
374
+ // Cancel any pending debounced redraw and do a final synchronous draw
375
+ // to ensure frame metrics are accurate before clearing
376
+ if (drawTimeout) {
377
+ clearTimeout(drawTimeout);
378
+ drawTimeout = null;
379
+ }
380
+ // Final draw to update lastCursorRowInFrame with current input state
381
+ drawInputFrame(input, cursorPos, options);
382
+ clearInputFrame(input, options.theme);
383
+ if (input.trim()) {
384
+ // Add to persistent history, avoiding duplicates of the last entry
385
+ if (inputHistory.length === 0 || inputHistory[inputHistory.length - 1] !== input) {
386
+ inputHistory.push(input);
387
+ // Trim history if it exceeds max size
388
+ if (inputHistory.length > MAX_HISTORY_SIZE) {
389
+ inputHistory.shift();
390
+ }
391
+ }
392
+ }
393
+ resolve(input);
394
+ return;
395
+ }
396
+ if (str === '\x03') {
397
+ // Ctrl+C - clean exit via signal handler
398
+ if (process.stdin.isTTY) {
399
+ try {
400
+ process.stdin.setRawMode(false);
401
+ }
402
+ catch {
403
+ // Ignore errors if stdin is already closed or in unexpected state
404
+ }
405
+ }
406
+ process.kill(process.pid, 'SIGINT');
407
+ return;
408
+ }
409
+ if (str === '\x1b') {
410
+ // Escape - hide autocomplete if visible, otherwise call onEscape
411
+ if (slashCommandAutocomplete.isVisible()) {
412
+ slashCommandAutocomplete.hide();
413
+ drawInputFrame(input, cursorPos, options);
414
+ return;
415
+ }
416
+ if (options.onEscape) {
417
+ options.onEscape();
418
+ }
419
+ return;
420
+ }
421
+ if (str === '\x09') {
422
+ // Tab - accept autocomplete if visible, otherwise toggle thinking
423
+ if (slashCommandAutocomplete.isVisible()) {
424
+ const newInput = slashCommandAutocomplete.accept();
425
+ if (newInput !== null) {
426
+ input = newInput + ' '; // Add space after command for arguments
427
+ cursorPos = input.length;
428
+ updateAutocomplete();
429
+ drawInputFrame(input, cursorPos, options);
430
+ }
431
+ return;
432
+ }
433
+ if (options.onToggleThinking) {
434
+ options.onToggleThinking();
435
+ drawInputFrame(input, cursorPos, options);
436
+ }
437
+ return;
438
+ }
439
+ if (str === '\x1b[Z') {
440
+ // Shift+Tab - toggle auto-approve
441
+ if (options.onToggleAutoApprove) {
442
+ options.onToggleAutoApprove();
443
+ drawInputFrame(input, cursorPos, options);
444
+ }
445
+ return;
446
+ }
447
+ // Backspace or Ctrl+H
448
+ if (str === '\x7f' || str === '\b' || str === '\x08') {
449
+ if (cursorPos > 0) {
450
+ input = input.slice(0, cursorPos - 1) + input.slice(cursorPos);
451
+ cursorPos--;
452
+ historyIndex = -1; // Reset history browsing when input is modified
453
+ updateAutocomplete(); // Update autocomplete after deletion
454
+ scheduleRedraw();
455
+ }
456
+ return;
457
+ }
458
+ // Left arrow or Ctrl+B (emacs style)
459
+ if (str === '\x1b[D' || str === '\x02') {
460
+ if (cursorPos > 0) {
461
+ cursorPos--;
462
+ drawInputFrame(input, cursorPos, options);
463
+ }
464
+ return;
465
+ }
466
+ // Right arrow or Ctrl+F (emacs style)
467
+ if (str === '\x1b[C' || str === '\x06') {
468
+ if (cursorPos < input.length) {
469
+ cursorPos++;
470
+ drawInputFrame(input, cursorPos, options);
471
+ }
472
+ return;
473
+ }
474
+ // Home key - go to start of line
475
+ if (str === '\x1b[H' || str === '\x1b[1~' || str === '\x1bOH') {
476
+ cursorPos = 0;
477
+ drawInputFrame(input, cursorPos, options);
478
+ return;
479
+ }
480
+ // End key - go to end of line
481
+ if (str === '\x1b[F' || str === '\x1b[4~' || str === '\x1bOF') {
482
+ cursorPos = input.length;
483
+ drawInputFrame(input, cursorPos, options);
484
+ return;
485
+ }
486
+ // Ctrl+D - delete character forward (like Delete key)
487
+ if (str === '\x04') {
488
+ if (cursorPos < input.length) {
489
+ input = input.slice(0, cursorPos) + input.slice(cursorPos + 1);
490
+ historyIndex = -1; // Reset history browsing
491
+ drawInputFrame(input, cursorPos, options);
492
+ }
493
+ return;
494
+ }
495
+ // Option+Left or Ctrl+Left - jump to previous word
496
+ // Option: \x1bb (ESC b) or \x1b[1;3D
497
+ // Ctrl: \x1b[1;5D
498
+ if (str === '\x1bb' || str === '\x1b[1;3D' || str === '\x1b[1;5D') {
499
+ cursorPos = findPrevWordStart(input, cursorPos);
500
+ drawInputFrame(input, cursorPos, options);
501
+ return;
502
+ }
503
+ // Option+Right or Ctrl+Right - jump to next word
504
+ // Option: \x1bf (ESC f) or \x1b[1;3C
505
+ // Ctrl: \x1b[1;5C
506
+ if (str === '\x1bf' || str === '\x1b[1;3C' || str === '\x1b[1;5C') {
507
+ cursorPos = findNextWordEnd(input, cursorPos);
508
+ drawInputFrame(input, cursorPos, options);
509
+ return;
510
+ }
511
+ // Option+Up or Ctrl+Up - jump 5 lines up
512
+ // Option: \x1b[1;3A, Ctrl: \x1b[1;5A
513
+ if (str === '\x1b[1;3A' || str === '\x1b[1;5A') {
514
+ const termWidth = process.stdout.columns || 80;
515
+ const prefixWidth = 3;
516
+ const metrics = getMultilineMetrics(input, cursorPos, termWidth, prefixWidth);
517
+ const targetRow = Math.max(0, metrics.cursorVisualRow - 5);
518
+ if (targetRow !== metrics.cursorVisualRow) {
519
+ cursorPos = findCharPosForVisualPosition(input, targetRow, metrics.cursorVisualCol, termWidth, prefixWidth);
520
+ drawInputFrame(input, cursorPos, options);
521
+ }
522
+ return;
523
+ }
524
+ // Option+Down or Ctrl+Down - jump 5 lines down
525
+ // Option: \x1b[1;3B, Ctrl: \x1b[1;5B
526
+ if (str === '\x1b[1;3B' || str === '\x1b[1;5B') {
527
+ const termWidth = process.stdout.columns || 80;
528
+ const prefixWidth = 3;
529
+ const metrics = getMultilineMetrics(input, cursorPos, termWidth, prefixWidth);
530
+ const targetRow = Math.min(metrics.totalVisualLines - 1, metrics.cursorVisualRow + 5);
531
+ if (targetRow !== metrics.cursorVisualRow) {
532
+ cursorPos = findCharPosForVisualPosition(input, targetRow, metrics.cursorVisualCol, termWidth, prefixWidth);
533
+ drawInputFrame(input, cursorPos, options);
534
+ }
535
+ return;
536
+ }
537
+ // Option+Backspace - delete previous word
538
+ // macOS sends \x1b\x7f (ESC DEL)
539
+ if (str === '\x1b\x7f') {
540
+ const newPos = findPrevWordStart(input, cursorPos);
541
+ input = input.slice(0, newPos) + input.slice(cursorPos);
542
+ cursorPos = newPos;
543
+ historyIndex = -1; // Reset history browsing
544
+ drawInputFrame(input, cursorPos, options);
545
+ return;
546
+ }
547
+ // Ctrl+W - delete previous word (bash-style)
548
+ if (str === '\x17') {
549
+ const newPos = findPrevWordStart(input, cursorPos);
550
+ input = input.slice(0, newPos) + input.slice(cursorPos);
551
+ cursorPos = newPos;
552
+ historyIndex = -1; // Reset history browsing
553
+ drawInputFrame(input, cursorPos, options);
554
+ return;
555
+ }
556
+ // Option+Delete or Ctrl+Delete - delete next word
557
+ // Option: \x1bd (ESC d) or \x1b[3;3~
558
+ // Ctrl: \x1b[3;5~
559
+ if (str === '\x1bd' || str === '\x1b[3;3~' || str === '\x1b[3;5~') {
560
+ const endPos = findNextWordEnd(input, cursorPos);
561
+ input = input.slice(0, cursorPos) + input.slice(endPos);
562
+ historyIndex = -1; // Reset history browsing
563
+ drawInputFrame(input, cursorPos, options);
564
+ return;
565
+ }
566
+ // Forward delete (Fn+Backspace on Mac, Delete key)
567
+ // Sends \x1b[3~
568
+ if (str === '\x1b[3~') {
569
+ if (cursorPos < input.length) {
570
+ input = input.slice(0, cursorPos) + input.slice(cursorPos + 1);
571
+ historyIndex = -1; // Reset history browsing
572
+ drawInputFrame(input, cursorPos, options);
573
+ }
574
+ return;
575
+ }
576
+ if (str === '\x1b[A') {
577
+ // Up arrow - navigate autocomplete when visible, otherwise normal behavior
578
+ if (slashCommandAutocomplete.isVisible()) {
579
+ slashCommandAutocomplete.moveUp();
580
+ drawInputFrame(input, cursorPos, options);
581
+ return;
582
+ }
583
+ // Navigate visual lines (including newlines), then jump to beginning, then history
584
+ const termWidth = process.stdout.columns || 80;
585
+ const prefixWidth = 3;
586
+ const metrics = getMultilineMetrics(input, cursorPos, termWidth, prefixWidth);
587
+ if (metrics.cursorVisualRow > 0) {
588
+ // Move cursor up one visual row - find char position for target row
589
+ const targetRow = metrics.cursorVisualRow - 1;
590
+ const targetCol = metrics.cursorVisualCol;
591
+ cursorPos = findCharPosForVisualPosition(input, targetRow, targetCol, termWidth, prefixWidth);
592
+ drawInputFrame(input, cursorPos, options);
593
+ }
594
+ else if (cursorPos > 0) {
595
+ // At first visual row but not at beginning - jump to beginning
596
+ cursorPos = 0;
597
+ drawInputFrame(input, cursorPos, options);
598
+ }
599
+ else {
600
+ // At first visual row AND at beginning - access history
601
+ if (inputHistory.length > 0 && historyIndex < inputHistory.length - 1) {
602
+ historyIndex++;
603
+ input = inputHistory[inputHistory.length - 1 - historyIndex] || '';
604
+ cursorPos = input.length;
605
+ drawInputFrame(input, cursorPos, options);
606
+ }
607
+ }
608
+ return;
609
+ }
610
+ if (str === '\x1b[B') {
611
+ // Down arrow - navigate autocomplete when visible, otherwise normal behavior
612
+ if (slashCommandAutocomplete.isVisible()) {
613
+ slashCommandAutocomplete.moveDown();
614
+ drawInputFrame(input, cursorPos, options);
615
+ return;
616
+ }
617
+ // Navigate visual lines (including newlines), then jump to end of text
618
+ const termWidth = process.stdout.columns || 80;
619
+ const prefixWidth = 3;
620
+ const metrics = getMultilineMetrics(input, cursorPos, termWidth, prefixWidth);
621
+ if (metrics.cursorVisualRow < metrics.totalVisualLines - 1) {
622
+ // Move cursor down one visual row - find char position for target row
623
+ const targetRow = metrics.cursorVisualRow + 1;
624
+ const targetCol = metrics.cursorVisualCol;
625
+ cursorPos = findCharPosForVisualPosition(input, targetRow, targetCol, termWidth, prefixWidth);
626
+ drawInputFrame(input, cursorPos, options);
627
+ }
628
+ else if (cursorPos < input.length) {
629
+ // At last visual row but not at end - jump to end of text
630
+ cursorPos = input.length;
631
+ drawInputFrame(input, cursorPos, options);
632
+ }
633
+ // If already at end of last row, do nothing
634
+ return;
635
+ }
636
+ if (str === '\x01') {
637
+ // Ctrl+A - start of line
638
+ cursorPos = 0;
639
+ drawInputFrame(input, cursorPos, options);
640
+ return;
641
+ }
642
+ if (str === '\x05') {
643
+ // Ctrl+E - toggle document expand/collapse
644
+ if (options.onToggleDocuments) {
645
+ options.onToggleDocuments();
646
+ drawInputFrame(input, cursorPos, options);
647
+ }
648
+ return;
649
+ }
650
+ if (str === '\x0b') {
651
+ // Ctrl+K - kill to end of line
652
+ input = input.slice(0, cursorPos);
653
+ historyIndex = -1; // Reset history browsing
654
+ drawInputFrame(input, cursorPos, options);
655
+ return;
656
+ }
657
+ if (str === '\x15') {
658
+ // Ctrl+U - kill whole line
659
+ input = '';
660
+ cursorPos = 0;
661
+ historyIndex = -1; // Reset history browsing
662
+ drawInputFrame(input, cursorPos, options);
663
+ return;
664
+ }
665
+ // Regular character input (handles both single chars and paste)
666
+ // Strip bracketed paste mode markers if present
667
+ let cleanStr = str;
668
+ if (cleanStr.includes(PASTE_START)) {
669
+ cleanStr = cleanStr.replace(PASTE_START, '');
670
+ }
671
+ if (cleanStr.includes(PASTE_END)) {
672
+ cleanStr = cleanStr.replace(PASTE_END, '');
673
+ }
674
+ // Normalize line endings: \r\n -> \n, \r -> \n
675
+ cleanStr = cleanStr.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
676
+ // Filter to printable characters and newlines (including Unicode)
677
+ let printable = '';
678
+ for (const char of cleanStr) {
679
+ const code = char.codePointAt(0) || 0;
680
+ // Accept printable ASCII, newlines, and all Unicode above ASCII
681
+ // Reject control characters (0x00-0x1F except newline 0x0A, and 0x7F)
682
+ if ((code >= 0x20 && code !== 0x7F) || code === 0x0A) {
683
+ printable += char;
684
+ }
685
+ }
686
+ if (printable.length > 0) {
687
+ // Insert all printable characters at cursor position
688
+ input = input.slice(0, cursorPos) + printable + input.slice(cursorPos);
689
+ cursorPos += printable.length;
690
+ historyIndex = -1; // Reset history browsing when input is modified
691
+ // Update autocomplete suggestions
692
+ updateAutocomplete();
693
+ // For paste (multiple characters), do immediate redraw to keep cursor in sync
694
+ // For single char, use debounced redraw
695
+ if (printable.length > 1) {
696
+ if (drawTimeout) {
697
+ clearTimeout(drawTimeout);
698
+ drawTimeout = null;
699
+ }
700
+ drawInputFrame(input, cursorPos, options);
701
+ }
702
+ else {
703
+ scheduleRedraw();
704
+ }
705
+ }
706
+ };
707
+ process.stdin.on('data', handleData);
708
+ });
709
+ }
710
+ /**
711
+ * Simple wrapper that mimics readline.question interface
712
+ */
713
+ export function createRawReadline(options) {
714
+ return {
715
+ question: async (_prompt, callback) => {
716
+ const answer = await rawQuestion(options);
717
+ callback(answer);
718
+ },
719
+ close: () => {
720
+ if (process.stdin.isTTY) {
721
+ try {
722
+ process.stdin.setRawMode(false);
723
+ }
724
+ catch {
725
+ // Ignore errors if stdin is already closed or in unexpected state
726
+ }
727
+ }
728
+ }
729
+ };
730
+ }
731
+ //# sourceMappingURL=RawInput.js.map