@yeshwanthyk/coding-agent 0.3.0 → 0.3.2

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 (379) hide show
  1. package/README.md +8 -6
  2. package/dist/adapters/acp/index.d.ts +10 -0
  3. package/dist/adapters/acp/index.d.ts.map +1 -0
  4. package/dist/adapters/acp/index.js +250 -0
  5. package/dist/adapters/acp/index.js.map +1 -0
  6. package/dist/adapters/acp/protocol.d.ts +171 -0
  7. package/dist/adapters/acp/protocol.d.ts.map +1 -0
  8. package/dist/adapters/acp/protocol.js +25 -0
  9. package/dist/adapters/acp/protocol.js.map +1 -0
  10. package/dist/adapters/acp/session.d.ts +33 -0
  11. package/dist/adapters/acp/session.d.ts.map +1 -0
  12. package/dist/adapters/acp/session.js +216 -0
  13. package/dist/adapters/acp/session.js.map +1 -0
  14. package/dist/adapters/acp/updates.d.ts +17 -0
  15. package/dist/adapters/acp/updates.d.ts.map +1 -0
  16. package/dist/adapters/acp/updates.js +62 -0
  17. package/dist/adapters/acp/updates.js.map +1 -0
  18. package/dist/adapters/cli/headless.d.ts +7 -0
  19. package/dist/adapters/cli/headless.d.ts.map +1 -0
  20. package/dist/adapters/cli/headless.js +93 -0
  21. package/dist/adapters/cli/headless.js.map +1 -0
  22. package/dist/adapters/cli/validate.d.ts +3 -0
  23. package/dist/adapters/cli/validate.d.ts.map +1 -0
  24. package/dist/adapters/cli/validate.js +40 -0
  25. package/dist/adapters/cli/validate.js.map +1 -0
  26. package/dist/adapters/tui/app.d.ts +8 -0
  27. package/dist/adapters/tui/app.d.ts.map +1 -0
  28. package/dist/adapters/tui/app.jsx +25 -0
  29. package/dist/adapters/tui/app.jsx.map +1 -0
  30. package/dist/agent-events.d.ts +63 -0
  31. package/dist/agent-events.d.ts.map +1 -0
  32. package/dist/agent-events.js +510 -0
  33. package/dist/agent-events.js.map +1 -0
  34. package/dist/args.d.ts +18 -0
  35. package/dist/args.d.ts.map +1 -0
  36. package/dist/args.js +87 -0
  37. package/dist/args.js.map +1 -0
  38. package/dist/autocomplete-commands.d.ts +26 -0
  39. package/dist/autocomplete-commands.d.ts.map +1 -0
  40. package/dist/autocomplete-commands.js +82 -0
  41. package/dist/autocomplete-commands.js.map +1 -0
  42. package/dist/commands.d.ts +10 -0
  43. package/dist/commands.d.ts.map +1 -0
  44. package/dist/commands.js +17 -0
  45. package/dist/commands.js.map +1 -0
  46. package/dist/compact-handler.d.ts +42 -0
  47. package/dist/compact-handler.d.ts.map +1 -0
  48. package/dist/compact-handler.js +211 -0
  49. package/dist/compact-handler.js.map +1 -0
  50. package/dist/components/Footer.d.ts +9 -0
  51. package/dist/components/Footer.d.ts.map +1 -0
  52. package/dist/components/Footer.jsx +36 -0
  53. package/dist/components/Footer.jsx.map +1 -0
  54. package/dist/components/Header.d.ts +23 -0
  55. package/dist/components/Header.d.ts.map +1 -0
  56. package/dist/components/Header.jsx +174 -0
  57. package/dist/components/Header.jsx.map +1 -0
  58. package/dist/components/MessageList.d.ts +19 -0
  59. package/dist/components/MessageList.d.ts.map +1 -0
  60. package/dist/components/MessageList.jsx +237 -0
  61. package/dist/components/MessageList.jsx.map +1 -0
  62. package/dist/config.d.ts +2 -0
  63. package/dist/config.d.ts.map +1 -0
  64. package/dist/config.js +2 -0
  65. package/dist/config.js.map +1 -0
  66. package/dist/domain/commands/builtin/clear.d.ts +3 -0
  67. package/dist/domain/commands/builtin/clear.d.ts.map +1 -0
  68. package/dist/domain/commands/builtin/clear.js +13 -0
  69. package/dist/domain/commands/builtin/clear.js.map +1 -0
  70. package/dist/domain/commands/builtin/compact.d.ts +3 -0
  71. package/dist/domain/commands/builtin/compact.d.ts.map +1 -0
  72. package/dist/domain/commands/builtin/compact.js +84 -0
  73. package/dist/domain/commands/builtin/compact.js.map +1 -0
  74. package/dist/domain/commands/builtin/conceal.d.ts +3 -0
  75. package/dist/domain/commands/builtin/conceal.d.ts.map +1 -0
  76. package/dist/domain/commands/builtin/conceal.js +8 -0
  77. package/dist/domain/commands/builtin/conceal.js.map +1 -0
  78. package/dist/domain/commands/builtin/diffwrap.d.ts +3 -0
  79. package/dist/domain/commands/builtin/diffwrap.d.ts.map +1 -0
  80. package/dist/domain/commands/builtin/diffwrap.js +8 -0
  81. package/dist/domain/commands/builtin/diffwrap.js.map +1 -0
  82. package/dist/domain/commands/builtin/editor.d.ts +3 -0
  83. package/dist/domain/commands/builtin/editor.d.ts.map +1 -0
  84. package/dist/domain/commands/builtin/editor.js +22 -0
  85. package/dist/domain/commands/builtin/editor.js.map +1 -0
  86. package/dist/domain/commands/builtin/exit.d.ts +3 -0
  87. package/dist/domain/commands/builtin/exit.d.ts.map +1 -0
  88. package/dist/domain/commands/builtin/exit.js +14 -0
  89. package/dist/domain/commands/builtin/exit.js.map +1 -0
  90. package/dist/domain/commands/builtin/followup.d.ts +3 -0
  91. package/dist/domain/commands/builtin/followup.d.ts.map +1 -0
  92. package/dist/domain/commands/builtin/followup.js +20 -0
  93. package/dist/domain/commands/builtin/followup.js.map +1 -0
  94. package/dist/domain/commands/builtin/index.d.ts +2 -0
  95. package/dist/domain/commands/builtin/index.d.ts.map +1 -0
  96. package/dist/domain/commands/builtin/index.js +29 -0
  97. package/dist/domain/commands/builtin/index.js.map +1 -0
  98. package/dist/domain/commands/builtin/login.d.ts +3 -0
  99. package/dist/domain/commands/builtin/login.d.ts.map +1 -0
  100. package/dist/domain/commands/builtin/login.js +92 -0
  101. package/dist/domain/commands/builtin/login.js.map +1 -0
  102. package/dist/domain/commands/builtin/model.d.ts +3 -0
  103. package/dist/domain/commands/builtin/model.d.ts.map +1 -0
  104. package/dist/domain/commands/builtin/model.js +53 -0
  105. package/dist/domain/commands/builtin/model.js.map +1 -0
  106. package/dist/domain/commands/builtin/status.d.ts +3 -0
  107. package/dist/domain/commands/builtin/status.d.ts.map +1 -0
  108. package/dist/domain/commands/builtin/status.js +30 -0
  109. package/dist/domain/commands/builtin/status.js.map +1 -0
  110. package/dist/domain/commands/builtin/steer.d.ts +3 -0
  111. package/dist/domain/commands/builtin/steer.d.ts.map +1 -0
  112. package/dist/domain/commands/builtin/steer.js +20 -0
  113. package/dist/domain/commands/builtin/steer.js.map +1 -0
  114. package/dist/domain/commands/builtin/theme.d.ts +3 -0
  115. package/dist/domain/commands/builtin/theme.d.ts.map +1 -0
  116. package/dist/domain/commands/builtin/theme.js +19 -0
  117. package/dist/domain/commands/builtin/theme.js.map +1 -0
  118. package/dist/domain/commands/builtin/thinking.d.ts +3 -0
  119. package/dist/domain/commands/builtin/thinking.d.ts.map +1 -0
  120. package/dist/domain/commands/builtin/thinking.js +16 -0
  121. package/dist/domain/commands/builtin/thinking.js.map +1 -0
  122. package/dist/domain/commands/helpers.d.ts +7 -0
  123. package/dist/domain/commands/helpers.d.ts.map +1 -0
  124. package/dist/domain/commands/helpers.js +34 -0
  125. package/dist/domain/commands/helpers.js.map +1 -0
  126. package/dist/domain/commands/registry.d.ts +10 -0
  127. package/dist/domain/commands/registry.d.ts.map +1 -0
  128. package/dist/domain/commands/registry.js +36 -0
  129. package/dist/domain/commands/registry.js.map +1 -0
  130. package/dist/domain/commands/types.d.ts +62 -0
  131. package/dist/domain/commands/types.d.ts.map +1 -0
  132. package/dist/domain/commands/types.js +2 -0
  133. package/dist/domain/commands/types.js.map +1 -0
  134. package/dist/domain/messaging/content.d.ts +37 -0
  135. package/dist/domain/messaging/content.d.ts.map +1 -0
  136. package/dist/domain/messaging/content.js +103 -0
  137. package/dist/domain/messaging/content.js.map +1 -0
  138. package/dist/editor.d.ts +26 -0
  139. package/dist/editor.d.ts.map +1 -0
  140. package/dist/editor.js +81 -0
  141. package/dist/editor.js.map +1 -0
  142. package/dist/extensibility/schema.d.ts +2 -0
  143. package/dist/extensibility/schema.d.ts.map +1 -0
  144. package/{src/extensibility/schema.ts → dist/extensibility/schema.js} +2 -1
  145. package/dist/extensibility/schema.js.map +1 -0
  146. package/dist/extensibility/validation.d.ts +2 -0
  147. package/dist/extensibility/validation.d.ts.map +1 -0
  148. package/{src/extensibility/validation.ts → dist/extensibility/validation.js} +2 -1
  149. package/dist/extensibility/validation.js.map +1 -0
  150. package/dist/hooks/index.d.ts +2 -0
  151. package/dist/hooks/index.d.ts.map +1 -0
  152. package/dist/hooks/index.js +2 -0
  153. package/dist/hooks/index.js.map +1 -0
  154. package/dist/hooks/useAgentEvents.d.ts +8 -0
  155. package/dist/hooks/useAgentEvents.d.ts.map +1 -0
  156. package/dist/hooks/useAgentEvents.js +22 -0
  157. package/dist/hooks/useAgentEvents.js.map +1 -0
  158. package/dist/hooks/useEditorBridge.d.ts +20 -0
  159. package/dist/hooks/useEditorBridge.d.ts.map +1 -0
  160. package/dist/hooks/useEditorBridge.js +80 -0
  161. package/dist/hooks/useEditorBridge.js.map +1 -0
  162. package/dist/hooks/useGitStatus.d.ts +2 -0
  163. package/dist/hooks/useGitStatus.d.ts.map +1 -0
  164. package/dist/hooks/useGitStatus.js +26 -0
  165. package/dist/hooks/useGitStatus.js.map +1 -0
  166. package/dist/hooks/usePromptQueue.d.ts +2 -0
  167. package/dist/hooks/usePromptQueue.d.ts.map +1 -0
  168. package/dist/hooks/usePromptQueue.js +2 -0
  169. package/dist/hooks/usePromptQueue.js.map +1 -0
  170. package/dist/hooks/useSessionController.d.ts +2 -0
  171. package/dist/hooks/useSessionController.d.ts.map +1 -0
  172. package/dist/hooks/useSessionController.js +2 -0
  173. package/dist/hooks/useSessionController.js.map +1 -0
  174. package/dist/hooks/useSpinner.d.ts +4 -0
  175. package/dist/hooks/useSpinner.d.ts.map +1 -0
  176. package/dist/hooks/useSpinner.js +25 -0
  177. package/dist/hooks/useSpinner.js.map +1 -0
  178. package/dist/hooks/useToastManager.d.ts +6 -0
  179. package/dist/hooks/useToastManager.d.ts.map +1 -0
  180. package/dist/hooks/useToastManager.js +22 -0
  181. package/dist/hooks/useToastManager.js.map +1 -0
  182. package/dist/index.d.ts +3 -0
  183. package/dist/index.d.ts.map +1 -0
  184. package/dist/index.js +156 -0
  185. package/dist/index.js.map +1 -0
  186. package/dist/keyboard-handler.d.ts +30 -0
  187. package/dist/keyboard-handler.d.ts.map +1 -0
  188. package/dist/keyboard-handler.js +96 -0
  189. package/dist/keyboard-handler.js.map +1 -0
  190. package/dist/profiler.d.ts +2 -0
  191. package/dist/profiler.d.ts.map +1 -0
  192. package/dist/profiler.js +41 -0
  193. package/dist/profiler.js.map +1 -0
  194. package/dist/runtime/context.d.ts +8 -0
  195. package/dist/runtime/context.d.ts.map +1 -0
  196. package/dist/runtime/context.jsx +11 -0
  197. package/dist/runtime/context.jsx.map +1 -0
  198. package/dist/runtime/factory.d.ts +12 -0
  199. package/dist/runtime/factory.d.ts.map +1 -0
  200. package/dist/runtime/factory.js +37 -0
  201. package/dist/runtime/factory.js.map +1 -0
  202. package/dist/runtime/git/git-info.d.ts +3 -0
  203. package/dist/runtime/git/git-info.d.ts.map +1 -0
  204. package/dist/runtime/git/git-info.js +29 -0
  205. package/dist/runtime/git/git-info.js.map +1 -0
  206. package/dist/runtime/session/session-controller.d.ts +48 -0
  207. package/dist/runtime/session/session-controller.d.ts.map +1 -0
  208. package/dist/runtime/session/session-controller.js +159 -0
  209. package/dist/runtime/session/session-controller.js.map +1 -0
  210. package/dist/session-manager.d.ts +2 -0
  211. package/dist/session-manager.d.ts.map +1 -0
  212. package/dist/session-manager.js +2 -0
  213. package/dist/session-manager.js.map +1 -0
  214. package/dist/session-picker.d.ts +6 -0
  215. package/dist/session-picker.d.ts.map +1 -0
  216. package/dist/session-picker.jsx +96 -0
  217. package/dist/session-picker.jsx.map +1 -0
  218. package/dist/shell-runner.d.ts +21 -0
  219. package/dist/shell-runner.d.ts.map +1 -0
  220. package/dist/shell-runner.js +106 -0
  221. package/dist/shell-runner.js.map +1 -0
  222. package/dist/syntax-highlighting.d.ts +4 -0
  223. package/dist/syntax-highlighting.d.ts.map +1 -0
  224. package/dist/syntax-highlighting.js +108 -0
  225. package/dist/syntax-highlighting.js.map +1 -0
  226. package/dist/theme-names.d.ts +7 -0
  227. package/dist/theme-names.d.ts.map +1 -0
  228. package/dist/theme-names.js +38 -0
  229. package/dist/theme-names.js.map +1 -0
  230. package/dist/tool-ui-contracts.d.ts +30 -0
  231. package/dist/tool-ui-contracts.d.ts.map +1 -0
  232. package/dist/tool-ui-contracts.js +53 -0
  233. package/dist/tool-ui-contracts.js.map +1 -0
  234. package/dist/tui-open-rendering.d.ts +37 -0
  235. package/dist/tui-open-rendering.d.ts.map +1 -0
  236. package/dist/tui-open-rendering.jsx +462 -0
  237. package/dist/tui-open-rendering.jsx.map +1 -0
  238. package/dist/types.d.ts +117 -0
  239. package/dist/types.d.ts.map +1 -0
  240. package/dist/types.js +4 -0
  241. package/dist/types.js.map +1 -0
  242. package/dist/ui/app-shell/TuiApp.d.ts +6 -0
  243. package/dist/ui/app-shell/TuiApp.d.ts.map +1 -0
  244. package/dist/ui/app-shell/TuiApp.jsx +480 -0
  245. package/dist/ui/app-shell/TuiApp.jsx.map +1 -0
  246. package/dist/ui/clipboard/osc52.d.ts +2 -0
  247. package/dist/ui/clipboard/osc52.d.ts.map +1 -0
  248. package/dist/ui/clipboard/osc52.js +19 -0
  249. package/dist/ui/clipboard/osc52.js.map +1 -0
  250. package/dist/ui/components/modals/ConfirmModal.d.ts +8 -0
  251. package/dist/ui/components/modals/ConfirmModal.d.ts.map +1 -0
  252. package/dist/ui/components/modals/ConfirmModal.jsx +39 -0
  253. package/dist/ui/components/modals/ConfirmModal.jsx.map +1 -0
  254. package/dist/ui/components/modals/EditorModal.d.ts +8 -0
  255. package/dist/ui/components/modals/EditorModal.d.ts.map +1 -0
  256. package/dist/ui/components/modals/EditorModal.jsx +23 -0
  257. package/dist/ui/components/modals/EditorModal.jsx.map +1 -0
  258. package/dist/ui/components/modals/InputModal.d.ts +8 -0
  259. package/dist/ui/components/modals/InputModal.d.ts.map +1 -0
  260. package/dist/ui/components/modals/InputModal.jsx +15 -0
  261. package/dist/ui/components/modals/InputModal.jsx.map +1 -0
  262. package/dist/ui/components/modals/ModalContainer.d.ts +8 -0
  263. package/dist/ui/components/modals/ModalContainer.d.ts.map +1 -0
  264. package/dist/ui/components/modals/ModalContainer.jsx +34 -0
  265. package/dist/ui/components/modals/ModalContainer.jsx.map +1 -0
  266. package/dist/ui/components/modals/SelectModal.d.ts +8 -0
  267. package/dist/ui/components/modals/SelectModal.d.ts.map +1 -0
  268. package/dist/ui/components/modals/SelectModal.jsx +32 -0
  269. package/dist/ui/components/modals/SelectModal.jsx.map +1 -0
  270. package/{src/ui/components/modals/index.ts → dist/ui/components/modals/index.d.ts} +5 -4
  271. package/dist/ui/components/modals/index.d.ts.map +1 -0
  272. package/dist/ui/components/modals/index.js +5 -0
  273. package/dist/ui/components/modals/index.js.map +1 -0
  274. package/dist/ui/features/composer/Composer.d.ts +16 -0
  275. package/dist/ui/features/composer/Composer.d.ts.map +1 -0
  276. package/dist/ui/features/composer/Composer.jsx +39 -0
  277. package/dist/ui/features/composer/Composer.jsx.map +1 -0
  278. package/dist/ui/features/composer/SlashCommandHandler.d.ts +14 -0
  279. package/dist/ui/features/composer/SlashCommandHandler.d.ts.map +1 -0
  280. package/dist/ui/features/composer/SlashCommandHandler.js +43 -0
  281. package/dist/ui/features/composer/SlashCommandHandler.js.map +1 -0
  282. package/dist/ui/features/composer/keyboard.d.ts +3 -0
  283. package/dist/ui/features/composer/keyboard.d.ts.map +1 -0
  284. package/dist/ui/features/composer/keyboard.js +3 -0
  285. package/dist/ui/features/composer/keyboard.js.map +1 -0
  286. package/dist/ui/features/main-view/MainView.d.ts +52 -0
  287. package/dist/ui/features/main-view/MainView.d.ts.map +1 -0
  288. package/dist/ui/features/main-view/MainView.jsx +269 -0
  289. package/dist/ui/features/main-view/MainView.jsx.map +1 -0
  290. package/dist/ui/features/message-pane/MessagePane.d.ts +15 -0
  291. package/dist/ui/features/message-pane/MessagePane.d.ts.map +1 -0
  292. package/dist/ui/features/message-pane/MessagePane.jsx +7 -0
  293. package/dist/ui/features/message-pane/MessagePane.jsx.map +1 -0
  294. package/dist/ui/hooks/useModals.d.ts +35 -0
  295. package/dist/ui/hooks/useModals.d.ts.map +1 -0
  296. package/dist/ui/hooks/useModals.js +36 -0
  297. package/dist/ui/hooks/useModals.js.map +1 -0
  298. package/dist/ui/state/app-store.d.ts +42 -0
  299. package/dist/ui/state/app-store.d.ts.map +1 -0
  300. package/dist/ui/state/app-store.js +28 -0
  301. package/dist/ui/state/app-store.js.map +1 -0
  302. package/dist/utils.d.ts +3 -0
  303. package/dist/utils.d.ts.map +1 -0
  304. package/dist/utils.js +3 -0
  305. package/dist/utils.js.map +1 -0
  306. package/package.json +19 -6
  307. package/src/adapters/acp/index.ts +0 -305
  308. package/src/adapters/acp/protocol.ts +0 -191
  309. package/src/adapters/acp/session.ts +0 -289
  310. package/src/adapters/acp/updates.ts +0 -96
  311. package/src/adapters/cli/headless.ts +0 -112
  312. package/src/adapters/cli/validate.ts +0 -50
  313. package/src/adapters/tui/app.tsx +0 -39
  314. package/src/agent-events.ts +0 -671
  315. package/src/args.ts +0 -102
  316. package/src/autocomplete-commands.ts +0 -102
  317. package/src/commands.ts +0 -23
  318. package/src/compact-handler.ts +0 -272
  319. package/src/components/Footer.tsx +0 -49
  320. package/src/components/Header.tsx +0 -218
  321. package/src/components/MessageList.tsx +0 -380
  322. package/src/config.ts +0 -1
  323. package/src/domain/commands/builtin/clear.ts +0 -14
  324. package/src/domain/commands/builtin/compact.ts +0 -96
  325. package/src/domain/commands/builtin/conceal.ts +0 -9
  326. package/src/domain/commands/builtin/diffwrap.ts +0 -9
  327. package/src/domain/commands/builtin/editor.ts +0 -24
  328. package/src/domain/commands/builtin/exit.ts +0 -14
  329. package/src/domain/commands/builtin/followup.ts +0 -24
  330. package/src/domain/commands/builtin/index.ts +0 -29
  331. package/src/domain/commands/builtin/login.ts +0 -118
  332. package/src/domain/commands/builtin/model.ts +0 -66
  333. package/src/domain/commands/builtin/status.ts +0 -32
  334. package/src/domain/commands/builtin/steer.ts +0 -24
  335. package/src/domain/commands/builtin/theme.ts +0 -23
  336. package/src/domain/commands/builtin/thinking.ts +0 -16
  337. package/src/domain/commands/helpers.ts +0 -41
  338. package/src/domain/commands/registry.ts +0 -42
  339. package/src/domain/commands/types.ts +0 -69
  340. package/src/domain/messaging/content.ts +0 -117
  341. package/src/editor.ts +0 -103
  342. package/src/hooks/index.ts +0 -1
  343. package/src/hooks/useAgentEvents.ts +0 -28
  344. package/src/hooks/useEditorBridge.ts +0 -101
  345. package/src/hooks/useGitStatus.ts +0 -28
  346. package/src/hooks/usePromptQueue.ts +0 -7
  347. package/src/hooks/useSessionController.ts +0 -5
  348. package/src/hooks/useSpinner.ts +0 -28
  349. package/src/hooks/useToastManager.ts +0 -26
  350. package/src/index.ts +0 -188
  351. package/src/keyboard-handler.ts +0 -134
  352. package/src/profiler.ts +0 -40
  353. package/src/runtime/context.tsx +0 -16
  354. package/src/runtime/factory.ts +0 -63
  355. package/src/runtime/git/git-info.ts +0 -25
  356. package/src/runtime/session/session-controller.ts +0 -208
  357. package/src/session-manager.ts +0 -1
  358. package/src/session-picker.tsx +0 -134
  359. package/src/shell-runner.ts +0 -134
  360. package/src/syntax-highlighting.ts +0 -114
  361. package/src/theme-names.ts +0 -37
  362. package/src/tool-ui-contracts.ts +0 -77
  363. package/src/tui-open-rendering.tsx +0 -565
  364. package/src/types.ts +0 -89
  365. package/src/ui/app-shell/TuiApp.tsx +0 -586
  366. package/src/ui/clipboard/osc52.ts +0 -18
  367. package/src/ui/components/modals/ConfirmModal.tsx +0 -52
  368. package/src/ui/components/modals/EditorModal.tsx +0 -39
  369. package/src/ui/components/modals/InputModal.tsx +0 -30
  370. package/src/ui/components/modals/ModalContainer.tsx +0 -67
  371. package/src/ui/components/modals/SelectModal.tsx +0 -48
  372. package/src/ui/features/composer/Composer.tsx +0 -73
  373. package/src/ui/features/composer/SlashCommandHandler.ts +0 -58
  374. package/src/ui/features/composer/keyboard.ts +0 -3
  375. package/src/ui/features/main-view/MainView.tsx +0 -367
  376. package/src/ui/features/message-pane/MessagePane.tsx +0 -34
  377. package/src/ui/hooks/useModals.ts +0 -74
  378. package/src/ui/state/app-store.ts +0 -67
  379. package/src/utils.ts +0 -14
@@ -1,586 +0,0 @@
1
- import { ThemeProvider, type ThemeMode } from "@yeshwanthyk/open-tui"
2
- import { batch, onMount } from "solid-js"
3
- import { Effect } from "effect"
4
-
5
- /** Detect system dark/light mode (macOS only, defaults to dark) */
6
- function detectThemeMode(): ThemeMode {
7
- try {
8
- const result = Bun.spawnSync(["defaults", "read", "-g", "AppleInterfaceStyle"])
9
- return result.stdout.toString().trim().toLowerCase() === "dark" ? "dark" : "light"
10
- } catch {
11
- return "dark"
12
- }
13
- }
14
- import { useRuntime } from "../../runtime/context.js"
15
- import type { LoadedSession } from "../../session-manager.js"
16
- import { createSessionController } from "@runtime/session/session-controller.js"
17
- import { createPromptQueue, type PromptDeliveryMode } from "@yeshwanthyk/runtime-effect/session/prompt-queue.js"
18
- import { appendWithCap } from "@domain/messaging/content.js"
19
- import type { UIShellMessage, UIMessage } from "../../types.js"
20
- import type { AppMessage } from "@yeshwanthyk/agent-core"
21
- import { runShellCommand } from "../../shell-runner.js"
22
- import { MainView } from "../features/main-view/MainView.js"
23
- import { createAppStore } from "../state/app-store.js"
24
- import { useAgentEvents } from "../../hooks/useAgentEvents.js"
25
- import type { EventHandlerContext, ToolMeta } from "../../agent-events.js"
26
- import { THINKING_LEVELS, type CommandContext } from "../../commands.js"
27
- import { slashCommands } from "../../autocomplete-commands.js"
28
- import { updateAppConfig } from "../../config.js"
29
- import { handleSlashInput } from "../features/composer/SlashCommandHandler.js"
30
- import { createHookMessage, createHookUIContext, type HookMessage, type HookSessionContext, type CompletionResult } from "../../hooks/index.js"
31
- import { completeSimple, type Message } from "@yeshwanthyk/ai"
32
- import { useModals } from "../hooks/useModals.js"
33
- import { ModalContainer } from "../components/modals/ModalContainer.js"
34
-
35
- const SHELL_INJECTION_PREFIX = "[Shell output]" as const
36
-
37
- export interface TuiAppProps {
38
- initialSession: LoadedSession | null
39
- }
40
-
41
- export const TuiApp = ({ initialSession }: TuiAppProps) => {
42
- const runtime = useRuntime()
43
- const {
44
- agent,
45
- sessionManager,
46
- hookRunner,
47
- toolByName,
48
- customCommands,
49
- lsp,
50
- config,
51
- codexTransport,
52
- getApiKey,
53
- sendRef,
54
- lspActiveRef,
55
- cycleModels,
56
- validationIssues,
57
- } = runtime
58
-
59
- const toolMetaByName = new Map<string, ToolMeta>()
60
- for (const [name, entry] of toolByName.entries()) {
61
- toolMetaByName.set(name, {
62
- label: entry.label,
63
- source: entry.source,
64
- sourcePath: entry.sourcePath,
65
- renderCall: entry.renderCall as ToolMeta["renderCall"],
66
- renderResult: entry.renderResult as ToolMeta["renderResult"],
67
- })
68
- }
69
-
70
- const store = createAppStore({
71
- initialTheme: config.theme,
72
- initialModelId: config.modelId,
73
- initialThinking: config.thinking,
74
- initialContextWindow: config.model.contextWindow,
75
- initialProvider: config.provider,
76
- })
77
-
78
- const promptQueue = createPromptQueue((counts) => store.queueCounts.set(counts))
79
- const modals = useModals()
80
-
81
- const sessionController = createSessionController({
82
- initialProvider: config.provider,
83
- initialModel: config.model,
84
- initialModelId: config.modelId,
85
- initialThinking: config.thinking,
86
- agent,
87
- sessionManager,
88
- hookRunner,
89
- toolByName: toolMetaByName,
90
- setMessages: store.messages.set,
91
- setContextTokens: store.contextTokens.set,
92
- setDisplayProvider: store.currentProvider.set,
93
- setDisplayModelId: store.displayModelId.set,
94
- setDisplayThinking: store.displayThinking.set,
95
- setDisplayContextWindow: store.displayContextWindow.set,
96
- shellInjectionPrefix: SHELL_INJECTION_PREFIX,
97
- promptQueue,
98
- })
99
-
100
- onMount(() => {
101
- if (initialSession) {
102
- sessionController.restoreSession(initialSession)
103
- }
104
- })
105
-
106
- const ensureSession = () => sessionController.ensureSession()
107
-
108
- let cycleIndex = cycleModels.findIndex(
109
- (entry) => entry.model.id === config.modelId && entry.provider === config.provider,
110
- )
111
- if (cycleIndex < 0) cycleIndex = 0
112
-
113
- const streamingMessageIdRef = { current: null as string | null }
114
- const retryConfig = { enabled: true, maxRetries: 3, baseDelayMs: 2000 }
115
- const retryablePattern =
116
- /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error/i
117
- const retryState = { attempt: 0, abortController: null as AbortController | null }
118
-
119
- lspActiveRef.setActive = store.lspActive.set
120
-
121
- const eventCtx: EventHandlerContext = {
122
- setMessages: store.messages.set,
123
- setToolBlocks: store.toolBlocks.set,
124
- setActivityState: store.activityState.set,
125
- setIsResponding: store.isResponding.set,
126
- setContextTokens: store.contextTokens.set,
127
- setCacheStats: store.cacheStats.set,
128
- setRetryStatus: store.retryStatus.set,
129
- setTurnCount: store.turnCount.set,
130
- promptQueue,
131
- sessionManager,
132
- streamingMessageId: streamingMessageIdRef,
133
- retryConfig,
134
- retryablePattern,
135
- retryState,
136
- agent: agent as EventHandlerContext["agent"],
137
- hookRunner,
138
- toolByName: toolMetaByName,
139
- getContextWindow: () => store.displayContextWindow.value(),
140
- }
141
-
142
- useAgentEvents({ agent, context: eventCtx })
143
-
144
- const handleThemeChange = (name: string) => {
145
- store.theme.set(name)
146
- void updateAppConfig({ configDir: config.configDir, configPath: config.configPath }, { theme: name })
147
- }
148
-
149
- const exitHandlerRef = { current: () => process.exit(0) }
150
- const editorOpenRef = { current: async () => {} }
151
- const setEditorTextRef = { current: (_text: string) => {} }
152
- const getEditorTextRef = { current: () => "" }
153
- const showToastRef = { current: (_title: string, _message: string, _variant?: "info" | "warning" | "success" | "error") => {} }
154
- // Flag to skip editor clear when hooks populate the editor via setEditorText
155
- const skipNextEditorClearRef = { current: false }
156
-
157
- const handleBeforeExit = async () => {
158
- // Emit shutdown hook before exiting
159
- await hookRunner.emit({ type: "session.shutdown", sessionId: sessionManager.sessionId })
160
- }
161
-
162
- const submitPrompt = async (text: string, mode: PromptDeliveryMode = "followUp") => {
163
- const trimmed = text.trim()
164
- if (!trimmed) return
165
-
166
- ensureSession()
167
-
168
- let beforeStartResult: Awaited<ReturnType<typeof hookRunner.emitBeforeAgentStart>> | undefined
169
- try {
170
- beforeStartResult = await hookRunner.emitBeforeAgentStart(trimmed)
171
- const hookMsg = beforeStartResult?.message ? createHookMessage(beforeStartResult.message) : null
172
- if (hookMsg?.display) {
173
- const uiMsg: UIMessage = {
174
- id: crypto.randomUUID(),
175
- role: "assistant",
176
- content:
177
- typeof hookMsg.content === "string"
178
- ? hookMsg.content
179
- : hookMsg.content.map((p) => (p.type === "text" ? p.text : "[image]")).join(""),
180
- timestamp: hookMsg.timestamp,
181
- }
182
- store.messages.set((prev) => appendWithCap(prev, uiMsg))
183
- }
184
- } catch (err) {
185
- store.messages.set((prev) =>
186
- appendWithCap(prev, {
187
- id: crypto.randomUUID(),
188
- role: "assistant",
189
- content: `Hook error: ${err instanceof Error ? err.message : String(err)}`,
190
- timestamp: Date.now(),
191
- }),
192
- )
193
- }
194
-
195
- promptQueue.push({ text: trimmed, mode })
196
- batch(() => {
197
- store.toolBlocks.set([])
198
- store.isResponding.set(true)
199
- store.activityState.set("thinking")
200
- })
201
- try {
202
- await Effect.runPromise(
203
- runtime.sessionOrchestrator.submitPrompt(trimmed, { mode, beforeStartResult }),
204
- )
205
- } catch (err) {
206
- batch(() => {
207
- store.messages.set((prev) =>
208
- appendWithCap(prev, {
209
- id: crypto.randomUUID(),
210
- role: "assistant",
211
- content: `Error: ${err instanceof Error ? err.message : String(err)}`,
212
- }),
213
- )
214
- store.isResponding.set(false)
215
- store.activityState.set("idle")
216
- })
217
- }
218
- }
219
-
220
- const steerHelper = async (text: string) => {
221
- const trimmed = text.trim()
222
- if (!trimmed) return
223
- if (store.isResponding.value()) {
224
- await sessionController.steer(trimmed)
225
- return
226
- }
227
- await submitPrompt(trimmed, "steer")
228
- }
229
-
230
- const followUpHelper = async (text: string) => {
231
- const trimmed = text.trim()
232
- if (!trimmed) return
233
- if (store.isResponding.value()) {
234
- await sessionController.followUp(trimmed)
235
- return
236
- }
237
- await submitPrompt(trimmed, "followUp")
238
- }
239
-
240
- const sendUserMessageHelper = async (text: string, options?: { deliverAs?: PromptDeliveryMode }) => {
241
- const mode: PromptDeliveryMode = options?.deliverAs ?? "followUp"
242
- if (mode === "steer") {
243
- await steerHelper(text)
244
- return
245
- }
246
- await followUpHelper(text)
247
- }
248
-
249
- const cmdCtx: CommandContext = {
250
- agent,
251
- sessionManager,
252
- configDir: config.configDir,
253
- configPath: config.configPath,
254
- cwd: process.cwd(),
255
- editor: config.editor,
256
- codexTransport,
257
- getApiKey,
258
- get currentProvider() {
259
- return sessionController.currentProvider()
260
- },
261
- get currentModelId() {
262
- return sessionController.currentModelId()
263
- },
264
- get currentThinking() {
265
- return sessionController.currentThinking()
266
- },
267
- setCurrentProvider: (p) => sessionController.setCurrentProvider(p),
268
- setCurrentModelId: (id) => sessionController.setCurrentModelId(id),
269
- setCurrentThinking: (t) => sessionController.setCurrentThinking(t),
270
- isResponding: store.isResponding.value,
271
- setIsResponding: store.isResponding.set,
272
- setActivityState: store.activityState.set,
273
- setMessages: store.messages.set,
274
- setToolBlocks: store.toolBlocks.set,
275
- setContextTokens: store.contextTokens.set,
276
- setCacheStats: store.cacheStats.set,
277
- setDisplayModelId: store.displayModelId.set,
278
- setDisplayThinking: store.displayThinking.set,
279
- setDisplayContextWindow: store.displayContextWindow.set,
280
- setDiffWrapMode: store.diffWrapMode.set,
281
- setConcealMarkdown: store.concealMarkdown.set,
282
- setTheme: handleThemeChange,
283
- openEditor: () => editorOpenRef.current(),
284
- onExit: () => exitHandlerRef.current(),
285
- hookRunner,
286
- submitPrompt: (text, options) => submitPrompt(text, options?.mode ?? "followUp"),
287
- steer: (text) => steerHelper(text),
288
- followUp: (text) => followUpHelper(text),
289
- sendUserMessage: (text, options) => sendUserMessageHelper(text, options),
290
- }
291
-
292
- const builtInCommandNames = new Set(slashCommands.map((c) => c.name))
293
-
294
- const enqueueWhileResponding = (text: string, mode: PromptDeliveryMode) => {
295
- void sendUserMessageHelper(text, { deliverAs: mode }).catch((err) => {
296
- store.messages.set((prev) =>
297
- appendWithCap(prev, {
298
- id: crypto.randomUUID(),
299
- role: "assistant",
300
- content: `Error: ${err instanceof Error ? err.message : String(err)}`,
301
- }),
302
- )
303
- })
304
- }
305
-
306
- const handleSubmit = async (text: string, editorClearFn?: () => void) => {
307
- if (!text.trim()) return
308
-
309
- if (text.startsWith("!")) {
310
- const shouldInject = text.startsWith("!!")
311
- const command = text.slice(shouldInject ? 2 : 1).trim()
312
- if (!command) return
313
- editorClearFn?.()
314
- ensureSession()
315
-
316
- const shellMsgId = crypto.randomUUID()
317
- const pendingMsg: UIShellMessage = {
318
- id: shellMsgId,
319
- role: "shell",
320
- command,
321
- output: "",
322
- exitCode: null,
323
- truncated: false,
324
- timestamp: Date.now(),
325
- }
326
- store.messages.set((prev) => appendWithCap(prev, pendingMsg))
327
-
328
- const result = await runShellCommand(command, { timeout: 30000 })
329
- const finalMsg: UIShellMessage = {
330
- id: shellMsgId,
331
- role: "shell",
332
- command,
333
- output: result.output,
334
- exitCode: result.exitCode,
335
- truncated: result.truncated,
336
- tempFilePath: result.tempFilePath,
337
- timestamp: Date.now(),
338
- }
339
- store.messages.set((prev) => prev.map((m) => (m.id === shellMsgId ? finalMsg : m)))
340
-
341
- sessionManager.appendMessage({
342
- role: "shell",
343
- command,
344
- output: result.output,
345
- exitCode: result.exitCode,
346
- truncated: result.truncated,
347
- tempFilePath: result.tempFilePath,
348
- timestamp: Date.now(),
349
- } as unknown as AppMessage)
350
-
351
- if (shouldInject) {
352
- const injectionLines = [`${SHELL_INJECTION_PREFIX}`, `$ ${command}`, result.output]
353
- if (result.exitCode !== null && result.exitCode !== 0) injectionLines.push(`[exit ${result.exitCode}]`)
354
- if (result.truncated && result.tempFilePath) injectionLines.push(`[truncated, full output: ${result.tempFilePath}]`)
355
- const injectedText = injectionLines.filter((line) => line.length > 0).join("\n")
356
- const injectionMessage: AppMessage = {
357
- role: "user",
358
- content: [{ type: "text", text: injectedText }],
359
- timestamp: Date.now(),
360
- }
361
- agent.appendMessage(injectionMessage)
362
- sessionManager.appendMessage(injectionMessage)
363
- }
364
- return
365
- }
366
-
367
- if (text.startsWith("/")) {
368
- const trimmed = text.trim()
369
- const handled = await handleSlashInput(trimmed, {
370
- commandContext: cmdCtx,
371
- customCommands,
372
- builtInCommandNames,
373
- onExpand: async (expanded) => handleSubmit(expanded),
374
- })
375
- if (handled) {
376
- // Skip clear if hook populated editor via setEditorText
377
- if (!skipNextEditorClearRef.current) {
378
- editorClearFn?.()
379
- }
380
- skipNextEditorClearRef.current = false
381
- return
382
- }
383
- }
384
-
385
- if (store.isResponding.value()) {
386
- enqueueWhileResponding(text, "followUp")
387
- editorClearFn?.()
388
- return
389
- }
390
-
391
- editorClearFn?.()
392
- await submitPrompt(text, "followUp")
393
- }
394
-
395
- // Initialize hook runner with full context
396
- const hookUIContext = createHookUIContext({
397
- setEditorText: (text) => {
398
- skipNextEditorClearRef.current = true
399
- setEditorTextRef.current(text)
400
- },
401
- getEditorText: () => getEditorTextRef.current(),
402
- showSelect: modals.showSelect,
403
- showInput: modals.showInput,
404
- showConfirm: modals.showConfirm,
405
- showEditor: modals.showEditor,
406
- showNotify: (message, type = "info") => showToastRef.current(type, message, type)
407
- })
408
-
409
- const hookSessionContext: HookSessionContext = {
410
- summarize: async () => {
411
- // Trigger compaction through the /compact command flow
412
- await handleSlashInput("/compact", {
413
- commandContext: cmdCtx,
414
- customCommands,
415
- builtInCommandNames,
416
- onExpand: async (expanded) => handleSubmit(expanded),
417
- })
418
- },
419
- toast: (title, message, variant = "info") => showToastRef.current(title, message, variant),
420
- getTokenUsage: () => hookRunner["tokenUsage"],
421
- getContextLimit: () => hookRunner["contextLimit"],
422
- newSession: async (_opts) => {
423
- // Clear current session and start fresh
424
- store.messages.set([])
425
- store.toolBlocks.set([])
426
- store.contextTokens.set(0)
427
- agent.reset()
428
- void hookRunner.emit({ type: "session.clear", sessionId: null })
429
- // Start a new session
430
- sessionManager.startSession(
431
- sessionController.currentProvider(),
432
- sessionController.currentModelId(),
433
- sessionController.currentThinking(),
434
- )
435
- return { cancelled: false, sessionId: sessionManager.sessionId ?? undefined }
436
- },
437
- getApiKey: async (model) => getApiKey(model.provider),
438
- complete: async (systemPrompt, userText) => {
439
- const model = agent.state.model
440
- const apiKey = getApiKey(model.provider)
441
- if (!apiKey) {
442
- return { text: "", stopReason: "error" as const }
443
- }
444
- try {
445
- const userMessage: Message = {
446
- role: "user",
447
- content: [{ type: "text", text: userText }],
448
- timestamp: Date.now(),
449
- }
450
- const result = await completeSimple(model, { systemPrompt, messages: [userMessage] }, { apiKey })
451
- const text = result.content
452
- .filter((c): c is { type: "text"; text: string } => c.type === "text")
453
- .map((c) => c.text)
454
- .join("\n")
455
- // Map stopReason: stop -> end, length -> max_tokens, toolUse -> tool_use
456
- const stopMap: Record<string, CompletionResult["stopReason"]> = {
457
- stop: "end", length: "max_tokens", toolUse: "tool_use", error: "error", aborted: "aborted"
458
- }
459
- return { text, stopReason: stopMap[result.stopReason] ?? "end" }
460
- } catch (err) {
461
- return { text: err instanceof Error ? err.message : String(err), stopReason: "error" as const }
462
- }
463
- },
464
- }
465
-
466
- const sendMessageHandler = <T = unknown>(
467
- message: Pick<HookMessage<T>, "customType" | "content" | "display" | "details">,
468
- triggerTurn?: boolean,
469
- ) => {
470
- const hookMessage = createHookMessage(message)
471
- // Add to UI messages if display is true
472
- if (hookMessage.display) {
473
- const uiMsg: UIMessage = {
474
- id: crypto.randomUUID(),
475
- role: "assistant", // Render hook messages as assistant for now
476
- content: typeof hookMessage.content === "string"
477
- ? hookMessage.content
478
- : hookMessage.content.map(p => p.type === "text" ? p.text : "[image]").join(""),
479
- timestamp: hookMessage.timestamp,
480
- }
481
- store.messages.set((prev) => appendWithCap(prev, uiMsg))
482
- }
483
- // Persist hook message to session
484
- sessionManager.appendMessage(hookMessage as unknown as AppMessage)
485
- // Optionally trigger a new turn
486
- if (triggerTurn) {
487
- void handleSubmit(typeof hookMessage.content === "string" ? hookMessage.content : "")
488
- }
489
- }
490
-
491
- hookRunner.initialize({
492
- sendHandler: (text) => void handleSubmit(text),
493
- sendMessageHandler,
494
- sendUserMessageHandler: (text, options) => sendUserMessageHelper(text, options),
495
- steerHandler: (text) => steerHelper(text),
496
- followUpHandler: (text) => followUpHelper(text),
497
- isIdleHandler: () => !store.isResponding.value(),
498
- appendEntryHandler: (customType, data) => sessionManager.appendEntry(customType, data),
499
- getSessionId: () => sessionManager.sessionId,
500
- getModel: () => agent.state.model,
501
- uiContext: hookUIContext,
502
- sessionContext: hookSessionContext,
503
- hasUI: true,
504
- })
505
-
506
- sendRef.current = (text) => void handleSubmit(text)
507
-
508
- const handleAbort = (): string | null => {
509
- if (retryState.abortController) {
510
- retryState.abortController.abort()
511
- retryState.abortController = null
512
- retryState.attempt = 0
513
- store.retryStatus.set(null)
514
- }
515
- agent.abort()
516
- agent.clearMessageQueue()
517
- const restore = promptQueue.drainToScript()
518
- Effect.runFork(Effect.catchAll(runtime.sessionOrchestrator.drainToScript, () => Effect.succeed(null)))
519
- batch(() => {
520
- store.isResponding.set(false)
521
- store.activityState.set("idle")
522
- })
523
- return restore
524
- }
525
-
526
- const cycleModel = () => {
527
- if (cycleModels.length <= 1) return
528
- if (store.isResponding.value()) return
529
- cycleIndex = (cycleIndex + 1) % cycleModels.length
530
- const entry = cycleModels[cycleIndex]!
531
- sessionController.setCurrentProvider(entry.provider)
532
- sessionController.setCurrentModelId(entry.model.id)
533
- agent.setModel(entry.model)
534
- store.displayModelId.set(entry.model.id)
535
- store.displayContextWindow.set(entry.model.contextWindow)
536
- }
537
-
538
- const cycleThinking = () => {
539
- const current = sessionController.currentThinking()
540
- const next = THINKING_LEVELS[(THINKING_LEVELS.indexOf(current) + 1) % THINKING_LEVELS.length]!
541
- sessionController.setCurrentThinking(next)
542
- agent.setThinkingLevel(next)
543
- store.displayThinking.set(next)
544
- }
545
-
546
- const themeMode = detectThemeMode()
547
-
548
- return (
549
- <ThemeProvider mode={themeMode} themeName={store.theme.value()} onThemeChange={handleThemeChange}>
550
- <MainView
551
- validationIssues={validationIssues}
552
- messages={store.messages.value()}
553
- toolBlocks={store.toolBlocks.value()}
554
- isResponding={store.isResponding.value()}
555
- activityState={store.activityState.value()}
556
- thinkingVisible={store.thinkingVisible.value()}
557
- modelId={store.displayModelId.value()}
558
- thinking={store.displayThinking.value()}
559
- provider={store.currentProvider.value()}
560
- contextTokens={store.contextTokens.value()}
561
- contextWindow={store.displayContextWindow.value()}
562
- queueCounts={store.queueCounts.value()}
563
- retryStatus={store.retryStatus.value()}
564
- turnCount={store.turnCount.value()}
565
- lspActive={store.lspActive.value()}
566
- diffWrapMode={store.diffWrapMode.value()}
567
- concealMarkdown={store.concealMarkdown.value()}
568
- customCommands={customCommands}
569
- onSubmit={handleSubmit}
570
- onAbort={handleAbort}
571
- onToggleThinking={() => store.thinkingVisible.set((v) => !v)}
572
- onCycleModel={cycleModel}
573
- onCycleThinking={cycleThinking}
574
- exitHandlerRef={exitHandlerRef}
575
- editorOpenRef={editorOpenRef}
576
- setEditorTextRef={setEditorTextRef}
577
- getEditorTextRef={getEditorTextRef}
578
- showToastRef={showToastRef}
579
- onBeforeExit={handleBeforeExit}
580
- editor={config.editor}
581
- lsp={lsp}
582
- />
583
- <ModalContainer modalState={modals.modalState()} onClose={modals.closeModal} />
584
- </ThemeProvider>
585
- )
586
- }
@@ -1,18 +0,0 @@
1
- import { spawnSync } from "child_process"
2
-
3
- export const copyToClipboard = (text: string): void => {
4
- const base64 = Buffer.from(text).toString("base64")
5
- if (process.env["TMUX"]) {
6
- process.stdout.write(`\x1bPtmux;\x1b\x1b]52;c;${base64}\x07\x1b\\`)
7
- } else {
8
- process.stdout.write(`\x1b]52;c;${base64}\x07`)
9
- }
10
-
11
- if (process.platform === "darwin") {
12
- try {
13
- spawnSync("pbcopy", { input: text, encoding: "utf-8" })
14
- } catch {
15
- // Ignore clipboard failures on non-macOS systems
16
- }
17
- }
18
- }
@@ -1,52 +0,0 @@
1
- import { createSignal } from "solid-js"
2
- import { useKeyboard } from "@opentui/solid"
3
- import { Dialog, useTheme } from "@yeshwanthyk/open-tui"
4
- import type { JSX } from "solid-js"
5
-
6
- export interface ConfirmModalProps {
7
- title: string
8
- message: string
9
- onConfirm: (confirmed: boolean) => void
10
- }
11
-
12
- export function ConfirmModal(props: ConfirmModalProps): JSX.Element {
13
- const { theme } = useTheme()
14
- const [selected, setSelected] = createSignal<"yes" | "no">("no")
15
-
16
- useKeyboard((e: { name: string }) => {
17
- if (e.name === "left" || e.name === "h") {
18
- setSelected("yes")
19
- } else if (e.name === "right" || e.name === "l") {
20
- setSelected("no")
21
- } else if (e.name === "y") {
22
- props.onConfirm(true)
23
- } else if (e.name === "n" || e.name === "escape") {
24
- props.onConfirm(false)
25
- } else if (e.name === "return") {
26
- props.onConfirm(selected() === "yes")
27
- }
28
- })
29
-
30
- return (
31
- <Dialog open={true} title={props.title} closeOnOverlayClick={false}>
32
- <text fg={theme.text}>{props.message}</text>
33
- <box height={1} />
34
- <box flexDirection="row" gap={2}>
35
- <text
36
- fg={selected() === "yes" ? theme.selectionFg : theme.text}
37
- bg={selected() === "yes" ? theme.selectionBg : undefined}
38
- >
39
- {" [Y]es "}
40
- </text>
41
- <text
42
- fg={selected() === "no" ? theme.selectionFg : theme.text}
43
- bg={selected() === "no" ? theme.selectionBg : undefined}
44
- >
45
- {" [N]o "}
46
- </text>
47
- </box>
48
- <box height={1} />
49
- <text fg={theme.textMuted}>←/→ or y/n to select • Enter to confirm • Esc to cancel</text>
50
- </Dialog>
51
- )
52
- }
@@ -1,39 +0,0 @@
1
- import { useKeyboard } from "@opentui/solid"
2
- import { Dialog, Editor, useTheme, type EditorRef } from "@yeshwanthyk/open-tui"
3
- import type { JSX } from "solid-js"
4
-
5
- export interface EditorModalProps {
6
- title: string
7
- initialText?: string
8
- onSubmit: (value: string | undefined) => void
9
- }
10
-
11
- export function EditorModal(props: EditorModalProps): JSX.Element {
12
- const { theme } = useTheme()
13
- let editorRef: EditorRef | undefined
14
-
15
- useKeyboard((e: { name: string; ctrl?: boolean; meta?: boolean }) => {
16
- if (e.name === "escape") {
17
- props.onSubmit(undefined)
18
- } else if (e.name === "s" && (e.ctrl || e.meta)) {
19
- const text = editorRef?.getText()
20
- props.onSubmit(text)
21
- }
22
- })
23
-
24
- return (
25
- <Dialog open={true} title={props.title} closeOnOverlayClick={false}>
26
- <box height="80%" minHeight={10}>
27
- <Editor
28
- initialValue={props.initialText}
29
- focused={true}
30
- minHeight={10}
31
- maxHeight={30}
32
- ref={(ref) => { editorRef = ref }}
33
- />
34
- </box>
35
- <box height={1} />
36
- <text fg={theme.textMuted}>Ctrl+S to save • Esc to cancel</text>
37
- </Dialog>
38
- )
39
- }