@akiojin/gwt 4.10.0 → 4.12.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 (630) hide show
  1. package/README.ja.md +4 -4
  2. package/README.md +4 -4
  3. package/bin/gwt.js +1 -1
  4. package/dist/claude.d.ts +2 -0
  5. package/dist/claude.d.ts.map +1 -1
  6. package/dist/claude.js +97 -68
  7. package/dist/claude.js.map +1 -1
  8. package/dist/cli/ui/App.solid.d.ts +29 -0
  9. package/dist/cli/ui/App.solid.d.ts.map +1 -0
  10. package/dist/cli/ui/App.solid.js +1395 -0
  11. package/dist/cli/ui/App.solid.js.map +1 -0
  12. package/dist/cli/ui/components/solid/Footer.d.ts +10 -0
  13. package/dist/cli/ui/components/solid/Footer.d.ts.map +1 -0
  14. package/dist/cli/ui/components/solid/Footer.js +10 -0
  15. package/dist/cli/ui/components/solid/Footer.js.map +1 -0
  16. package/dist/cli/ui/components/{parts → solid}/Header.d.ts +1 -6
  17. package/dist/cli/ui/components/solid/Header.d.ts.map +1 -0
  18. package/dist/cli/ui/components/solid/Header.js +13 -0
  19. package/dist/cli/ui/components/solid/Header.js.map +1 -0
  20. package/dist/cli/ui/components/solid/HelpOverlay.d.ts +8 -0
  21. package/dist/cli/ui/components/solid/HelpOverlay.d.ts.map +1 -0
  22. package/dist/cli/ui/components/solid/HelpOverlay.js +118 -0
  23. package/dist/cli/ui/components/solid/HelpOverlay.js.map +1 -0
  24. package/dist/cli/ui/components/solid/QuickStartStep.d.ts +17 -0
  25. package/dist/cli/ui/components/solid/QuickStartStep.d.ts.map +1 -0
  26. package/dist/cli/ui/components/solid/QuickStartStep.js +152 -0
  27. package/dist/cli/ui/components/solid/QuickStartStep.js.map +1 -0
  28. package/dist/cli/ui/components/solid/SelectInput.d.ts +22 -0
  29. package/dist/cli/ui/components/solid/SelectInput.d.ts.map +1 -0
  30. package/dist/cli/ui/components/solid/SelectInput.js +45 -0
  31. package/dist/cli/ui/components/solid/SelectInput.js.map +1 -0
  32. package/dist/cli/ui/components/solid/TextInput.d.ts +12 -0
  33. package/dist/cli/ui/components/solid/TextInput.d.ts.map +1 -0
  34. package/dist/cli/ui/components/solid/TextInput.js +9 -0
  35. package/dist/cli/ui/components/solid/TextInput.js.map +1 -0
  36. package/dist/cli/ui/components/solid/WizardController.d.ts +34 -0
  37. package/dist/cli/ui/components/solid/WizardController.d.ts.map +1 -0
  38. package/dist/cli/ui/components/solid/WizardController.js +223 -0
  39. package/dist/cli/ui/components/solid/WizardController.js.map +1 -0
  40. package/dist/cli/ui/components/solid/WizardPopup.d.ts +26 -0
  41. package/dist/cli/ui/components/solid/WizardPopup.d.ts.map +1 -0
  42. package/dist/cli/ui/components/solid/WizardPopup.js +68 -0
  43. package/dist/cli/ui/components/solid/WizardPopup.js.map +1 -0
  44. package/dist/cli/ui/components/solid/WizardSteps.d.ts +52 -0
  45. package/dist/cli/ui/components/solid/WizardSteps.d.ts.map +1 -0
  46. package/dist/cli/ui/components/solid/WizardSteps.js +419 -0
  47. package/dist/cli/ui/components/solid/WizardSteps.js.map +1 -0
  48. package/dist/cli/ui/core/index.d.ts +12 -0
  49. package/dist/cli/ui/core/index.d.ts.map +1 -0
  50. package/dist/cli/ui/core/index.js +15 -0
  51. package/dist/cli/ui/core/index.js.map +1 -0
  52. package/dist/cli/ui/core/keybindings.d.ts +106 -0
  53. package/dist/cli/ui/core/keybindings.d.ts.map +1 -0
  54. package/dist/cli/ui/core/keybindings.js +270 -0
  55. package/dist/cli/ui/core/keybindings.js.map +1 -0
  56. package/dist/cli/ui/core/theme.d.ts +123 -0
  57. package/dist/cli/ui/core/theme.d.ts.map +1 -0
  58. package/dist/cli/ui/core/theme.js +191 -0
  59. package/dist/cli/ui/core/theme.js.map +1 -0
  60. package/dist/cli/ui/core/types.d.ts +156 -0
  61. package/dist/cli/ui/core/types.d.ts.map +1 -0
  62. package/dist/cli/ui/core/types.js +10 -0
  63. package/dist/cli/ui/core/types.js.map +1 -0
  64. package/dist/cli/ui/hooks/solid/useScrollableList.d.ts +26 -0
  65. package/dist/cli/ui/hooks/solid/useScrollableList.d.ts.map +1 -0
  66. package/dist/cli/ui/hooks/solid/useScrollableList.js +89 -0
  67. package/dist/cli/ui/hooks/solid/useScrollableList.js.map +1 -0
  68. package/dist/cli/ui/hooks/solid/useTerminalSize.d.ts +10 -0
  69. package/dist/cli/ui/hooks/solid/useTerminalSize.d.ts.map +1 -0
  70. package/dist/cli/ui/hooks/solid/useTerminalSize.js +16 -0
  71. package/dist/cli/ui/hooks/solid/useTerminalSize.js.map +1 -0
  72. package/dist/cli/ui/index.solid.d.ts +5 -0
  73. package/dist/cli/ui/index.solid.d.ts.map +1 -0
  74. package/dist/cli/ui/index.solid.js +21 -0
  75. package/dist/cli/ui/index.solid.js.map +1 -0
  76. package/dist/cli/ui/screens/solid/BranchListScreen.d.ts +53 -0
  77. package/dist/cli/ui/screens/solid/BranchListScreen.d.ts.map +1 -0
  78. package/dist/cli/ui/screens/solid/BranchListScreen.js +829 -0
  79. package/dist/cli/ui/screens/solid/BranchListScreen.js.map +1 -0
  80. package/dist/cli/ui/screens/solid/ConfirmScreen.d.ts +11 -0
  81. package/dist/cli/ui/screens/solid/ConfirmScreen.d.ts.map +1 -0
  82. package/dist/cli/ui/screens/solid/ConfirmScreen.js +45 -0
  83. package/dist/cli/ui/screens/solid/ConfirmScreen.js.map +1 -0
  84. package/dist/cli/ui/screens/solid/EnvironmentScreen.d.ts +14 -0
  85. package/dist/cli/ui/screens/solid/EnvironmentScreen.d.ts.map +1 -0
  86. package/dist/cli/ui/screens/solid/EnvironmentScreen.js +90 -0
  87. package/dist/cli/ui/screens/solid/EnvironmentScreen.js.map +1 -0
  88. package/dist/cli/ui/screens/solid/ErrorScreen.d.ts +8 -0
  89. package/dist/cli/ui/screens/solid/ErrorScreen.d.ts.map +1 -0
  90. package/dist/cli/ui/screens/solid/ErrorScreen.js +18 -0
  91. package/dist/cli/ui/screens/solid/ErrorScreen.js.map +1 -0
  92. package/dist/cli/ui/screens/solid/InputScreen.d.ts +13 -0
  93. package/dist/cli/ui/screens/solid/InputScreen.d.ts.map +1 -0
  94. package/dist/cli/ui/screens/solid/InputScreen.js +17 -0
  95. package/dist/cli/ui/screens/solid/InputScreen.js.map +1 -0
  96. package/dist/cli/ui/screens/solid/LoadingIndicator.d.ts +9 -0
  97. package/dist/cli/ui/screens/solid/LoadingIndicator.d.ts.map +1 -0
  98. package/dist/cli/ui/screens/solid/LoadingIndicator.js +43 -0
  99. package/dist/cli/ui/screens/solid/LoadingIndicator.js.map +1 -0
  100. package/dist/cli/ui/{components/screens → screens/solid}/LogDetailScreen.d.ts +2 -2
  101. package/dist/cli/ui/screens/solid/LogDetailScreen.d.ts.map +1 -0
  102. package/dist/cli/ui/screens/solid/LogDetailScreen.js +34 -0
  103. package/dist/cli/ui/screens/solid/LogDetailScreen.js.map +1 -0
  104. package/dist/cli/ui/{components/screens/LogListScreen.d.ts → screens/solid/LogScreen.d.ts} +10 -4
  105. package/dist/cli/ui/screens/solid/LogScreen.d.ts.map +1 -0
  106. package/dist/cli/ui/screens/solid/LogScreen.js +333 -0
  107. package/dist/cli/ui/screens/solid/LogScreen.js.map +1 -0
  108. package/dist/cli/ui/screens/solid/ProfileEnvScreen.d.ts +17 -0
  109. package/dist/cli/ui/screens/solid/ProfileEnvScreen.d.ts.map +1 -0
  110. package/dist/cli/ui/screens/solid/ProfileEnvScreen.js +115 -0
  111. package/dist/cli/ui/screens/solid/ProfileEnvScreen.js.map +1 -0
  112. package/dist/cli/ui/screens/solid/ProfileScreen.d.ts +17 -0
  113. package/dist/cli/ui/screens/solid/ProfileScreen.d.ts.map +1 -0
  114. package/dist/cli/ui/screens/solid/ProfileScreen.js +50 -0
  115. package/dist/cli/ui/screens/solid/ProfileScreen.js.map +1 -0
  116. package/dist/cli/ui/screens/solid/SelectorScreen.d.ts +20 -0
  117. package/dist/cli/ui/screens/solid/SelectorScreen.d.ts.map +1 -0
  118. package/dist/cli/ui/screens/solid/SelectorScreen.js +98 -0
  119. package/dist/cli/ui/screens/solid/SelectorScreen.js.map +1 -0
  120. package/dist/cli/ui/screens/solid/WorktreeCreateScreen.d.ts +13 -0
  121. package/dist/cli/ui/screens/solid/WorktreeCreateScreen.d.ts.map +1 -0
  122. package/dist/cli/ui/screens/solid/WorktreeCreateScreen.js +59 -0
  123. package/dist/cli/ui/screens/solid/WorktreeCreateScreen.js.map +1 -0
  124. package/dist/cli/ui/stores/appStore.d.ts +143 -0
  125. package/dist/cli/ui/stores/appStore.d.ts.map +1 -0
  126. package/dist/cli/ui/stores/appStore.js +158 -0
  127. package/dist/cli/ui/stores/appStore.js.map +1 -0
  128. package/dist/cli/ui/stores/branchStore.d.ts +159 -0
  129. package/dist/cli/ui/stores/branchStore.d.ts.map +1 -0
  130. package/dist/cli/ui/stores/branchStore.js +275 -0
  131. package/dist/cli/ui/stores/branchStore.js.map +1 -0
  132. package/dist/cli/ui/stores/index.d.ts +11 -0
  133. package/dist/cli/ui/stores/index.d.ts.map +1 -0
  134. package/dist/cli/ui/stores/index.js +14 -0
  135. package/dist/cli/ui/stores/index.js.map +1 -0
  136. package/dist/cli/ui/stores/uiStore.d.ts +146 -0
  137. package/dist/cli/ui/stores/uiStore.d.ts.map +1 -0
  138. package/dist/cli/ui/stores/uiStore.js +166 -0
  139. package/dist/cli/ui/stores/uiStore.js.map +1 -0
  140. package/dist/cli/ui/types.d.ts +17 -1
  141. package/dist/cli/ui/types.d.ts.map +1 -1
  142. package/dist/cli/ui/utils/branchFormatter.d.ts +1 -0
  143. package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
  144. package/dist/cli/ui/utils/branchFormatter.js +36 -217
  145. package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
  146. package/dist/cli/ui/utils/continueSession.d.ts +18 -0
  147. package/dist/cli/ui/utils/continueSession.d.ts.map +1 -1
  148. package/dist/cli/ui/utils/continueSession.js +90 -2
  149. package/dist/cli/ui/utils/continueSession.js.map +1 -1
  150. package/dist/cli/ui/utils/versionCache.d.ts +37 -0
  151. package/dist/cli/ui/utils/versionCache.d.ts.map +1 -0
  152. package/dist/cli/ui/utils/versionCache.js +70 -0
  153. package/dist/cli/ui/utils/versionCache.js.map +1 -0
  154. package/dist/cli/ui/utils/versionFetcher.d.ts +41 -0
  155. package/dist/cli/ui/utils/versionFetcher.d.ts.map +1 -0
  156. package/dist/cli/ui/utils/versionFetcher.js +89 -0
  157. package/dist/cli/ui/utils/versionFetcher.js.map +1 -0
  158. package/dist/client/assets/{index-ChHC-Puh.css → index-BbfV7Wuj.css} +1 -1
  159. package/dist/client/assets/index-CoAyq5x1.js +78 -0
  160. package/dist/client/index.html +2 -2
  161. package/dist/codex.d.ts +2 -0
  162. package/dist/codex.d.ts.map +1 -1
  163. package/dist/codex.js +109 -39
  164. package/dist/codex.js.map +1 -1
  165. package/dist/config/builtin-coding-agents.js +4 -4
  166. package/dist/config/builtin-coding-agents.js.map +1 -1
  167. package/dist/config/index.d.ts +2 -0
  168. package/dist/config/index.d.ts.map +1 -1
  169. package/dist/config/index.js +11 -0
  170. package/dist/config/index.js.map +1 -1
  171. package/dist/gemini.d.ts +2 -0
  172. package/dist/gemini.d.ts.map +1 -1
  173. package/dist/gemini.js +77 -39
  174. package/dist/gemini.js.map +1 -1
  175. package/dist/index.d.ts +1 -1
  176. package/dist/index.d.ts.map +1 -1
  177. package/dist/index.js +153 -103
  178. package/dist/index.js.map +1 -1
  179. package/dist/launcher.d.ts.map +1 -1
  180. package/dist/launcher.js +56 -6
  181. package/dist/launcher.js.map +1 -1
  182. package/dist/logging/agentOutput.d.ts +21 -0
  183. package/dist/logging/agentOutput.d.ts.map +1 -0
  184. package/dist/logging/agentOutput.js +164 -0
  185. package/dist/logging/agentOutput.js.map +1 -0
  186. package/dist/logging/formatter.d.ts.map +1 -1
  187. package/dist/logging/formatter.js +18 -4
  188. package/dist/logging/formatter.js.map +1 -1
  189. package/dist/logging/logger.d.ts.map +1 -1
  190. package/dist/logging/logger.js +28 -9
  191. package/dist/logging/logger.js.map +1 -1
  192. package/dist/logging/reader.d.ts +21 -0
  193. package/dist/logging/reader.d.ts.map +1 -1
  194. package/dist/logging/reader.js +79 -0
  195. package/dist/logging/reader.js.map +1 -1
  196. package/dist/opentui/highlights-eq9cgrbb.scm +604 -0
  197. package/dist/opentui/highlights-ghv9g403.scm +205 -0
  198. package/dist/opentui/highlights-hk7bwhj4.scm +284 -0
  199. package/dist/opentui/highlights-r812a2qc.scm +150 -0
  200. package/dist/opentui/highlights-x6tmsnaa.scm +115 -0
  201. package/dist/opentui/index.solid.d.ts +2 -0
  202. package/dist/opentui/index.solid.d.ts.map +1 -0
  203. package/dist/opentui/index.solid.js +53687 -0
  204. package/dist/opentui/index.solid.js.map +1 -0
  205. package/dist/opentui/injections-73j83es3.scm +27 -0
  206. package/dist/opentui/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  207. package/dist/opentui/tree-sitter-markdown-411r6y9b.wasm +0 -0
  208. package/dist/opentui/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  209. package/dist/opentui/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  210. package/dist/opentui/tree-sitter-zig-e78zbjpm.wasm +0 -0
  211. package/dist/repositories/worktree.repository.d.ts +1 -0
  212. package/dist/repositories/worktree.repository.d.ts.map +1 -1
  213. package/dist/repositories/worktree.repository.js +7 -0
  214. package/dist/repositories/worktree.repository.js.map +1 -1
  215. package/dist/services/codingAgentResolver.d.ts +2 -0
  216. package/dist/services/codingAgentResolver.d.ts.map +1 -1
  217. package/dist/services/codingAgentResolver.js +30 -4
  218. package/dist/services/codingAgentResolver.js.map +1 -1
  219. package/dist/services/dependency-installer.d.ts.map +1 -1
  220. package/dist/services/dependency-installer.js +2 -7
  221. package/dist/services/dependency-installer.js.map +1 -1
  222. package/dist/types/api.d.ts +3 -0
  223. package/dist/types/api.d.ts.map +1 -1
  224. package/dist/types/coding-agent.d.ts +62 -0
  225. package/dist/types/coding-agent.d.ts.map +1 -0
  226. package/dist/types/coding-agent.js +29 -0
  227. package/dist/types/coding-agent.js.map +1 -0
  228. package/dist/types/tools.d.ts +17 -0
  229. package/dist/types/tools.d.ts.map +1 -1
  230. package/dist/utils/coding-agent-colors.d.ts +88 -0
  231. package/dist/utils/coding-agent-colors.d.ts.map +1 -0
  232. package/dist/utils/coding-agent-colors.js +137 -0
  233. package/dist/utils/coding-agent-colors.js.map +1 -0
  234. package/dist/utils/command.d.ts +1 -1
  235. package/dist/utils/command.js +1 -1
  236. package/dist/utils/error-utils.d.ts +27 -0
  237. package/dist/utils/error-utils.d.ts.map +1 -0
  238. package/dist/utils/error-utils.js +98 -0
  239. package/dist/utils/error-utils.js.map +1 -0
  240. package/dist/utils/npmRegistry.d.ts +61 -0
  241. package/dist/utils/npmRegistry.d.ts.map +1 -0
  242. package/dist/utils/npmRegistry.js +180 -0
  243. package/dist/utils/npmRegistry.js.map +1 -0
  244. package/dist/utils/prompt.d.ts +1 -1
  245. package/dist/utils/prompt.js +1 -1
  246. package/dist/utils/session/common.d.ts +8 -0
  247. package/dist/utils/session/common.d.ts.map +1 -1
  248. package/dist/utils/session/common.js +22 -0
  249. package/dist/utils/session/common.js.map +1 -1
  250. package/dist/utils/session/parsers/claude.d.ts +10 -4
  251. package/dist/utils/session/parsers/claude.d.ts.map +1 -1
  252. package/dist/utils/session/parsers/claude.js +64 -18
  253. package/dist/utils/session/parsers/claude.js.map +1 -1
  254. package/dist/utils/session/parsers/codex.d.ts.map +1 -1
  255. package/dist/utils/session/parsers/codex.js +47 -20
  256. package/dist/utils/session/parsers/codex.js.map +1 -1
  257. package/dist/utils/session/parsers/gemini.d.ts.map +1 -1
  258. package/dist/utils/session/parsers/gemini.js +43 -6
  259. package/dist/utils/session/parsers/gemini.js.map +1 -1
  260. package/dist/utils/session/parsers/opencode.d.ts.map +1 -1
  261. package/dist/utils/session/parsers/opencode.js +43 -6
  262. package/dist/utils/session/parsers/opencode.js.map +1 -1
  263. package/dist/utils/session/types.d.ts +7 -0
  264. package/dist/utils/session/types.d.ts.map +1 -1
  265. package/dist/utils/terminal.d.ts +1 -0
  266. package/dist/utils/terminal.d.ts.map +1 -1
  267. package/dist/utils/terminal.js +20 -0
  268. package/dist/utils/terminal.js.map +1 -1
  269. package/dist/utils.d.ts +9 -0
  270. package/dist/utils.d.ts.map +1 -1
  271. package/dist/utils.js +33 -2
  272. package/dist/utils.js.map +1 -1
  273. package/dist/web/client/src/components/CodingAgentLaunchModal.d.ts.map +1 -1
  274. package/dist/web/client/src/components/CodingAgentLaunchModal.js +7 -16
  275. package/dist/web/client/src/components/CodingAgentLaunchModal.js.map +1 -1
  276. package/dist/web/client/src/components/branch-detail/BranchInfoCards.d.ts.map +1 -1
  277. package/dist/web/client/src/components/branch-detail/BranchInfoCards.js +7 -2
  278. package/dist/web/client/src/components/branch-detail/BranchInfoCards.js.map +1 -1
  279. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts.map +1 -1
  280. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js +2 -1
  281. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js.map +1 -1
  282. package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts +2 -2
  283. package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts.map +1 -1
  284. package/dist/web/client/src/components/branch-detail/ToolLauncher.js +5 -5
  285. package/dist/web/client/src/components/branch-detail/ToolLauncher.js.map +1 -1
  286. package/dist/web/client/src/components/ui/alert.d.ts +1 -1
  287. package/dist/web/client/src/lib/coding-agent-colors.d.ts +86 -0
  288. package/dist/web/client/src/lib/coding-agent-colors.d.ts.map +1 -0
  289. package/dist/web/client/src/lib/coding-agent-colors.js +135 -0
  290. package/dist/web/client/src/lib/coding-agent-colors.js.map +1 -0
  291. package/dist/web/client/src/pages/BranchDetailPage.js +10 -10
  292. package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
  293. package/dist/web/server/pty/manager.d.ts +2 -0
  294. package/dist/web/server/pty/manager.d.ts.map +1 -1
  295. package/dist/web/server/pty/manager.js +104 -0
  296. package/dist/web/server/pty/manager.js.map +1 -1
  297. package/dist/web/server/routes/sessions.d.ts.map +1 -1
  298. package/dist/web/server/routes/sessions.js +5 -1
  299. package/dist/web/server/routes/sessions.js.map +1 -1
  300. package/dist/web/server/services/branches.d.ts.map +1 -1
  301. package/dist/web/server/services/branches.js +10 -8
  302. package/dist/web/server/services/branches.js.map +1 -1
  303. package/dist/web/server/services/worktrees.js +2 -2
  304. package/dist/web/server/services/worktrees.js.map +1 -1
  305. package/dist/worktree.d.ts +50 -1
  306. package/dist/worktree.d.ts.map +1 -1
  307. package/dist/worktree.js +292 -100
  308. package/dist/worktree.js.map +1 -1
  309. package/package.json +13 -14
  310. package/src/claude.ts +129 -95
  311. package/src/cli/ui/App.solid.tsx +2096 -0
  312. package/src/cli/ui/__tests__/solid/AppSolid.cleanup.test.tsx +1084 -0
  313. package/src/cli/ui/__tests__/solid/BranchListScreen.test.tsx +343 -0
  314. package/src/cli/ui/__tests__/solid/ConfirmScreen.test.tsx +77 -0
  315. package/src/cli/ui/__tests__/solid/LogScreen.test.tsx +351 -0
  316. package/src/cli/ui/__tests__/solid/components/QuickStartStep.test.tsx +308 -0
  317. package/src/cli/ui/__tests__/solid/components/WizardPopup.test.tsx +231 -0
  318. package/src/cli/ui/__tests__/solid/components/WizardSteps.test.tsx +241 -0
  319. package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +79 -334
  320. package/src/cli/ui/__tests__/utils/clipboard.test.ts +3 -3
  321. package/src/cli/ui/__tests__/utils/statisticsCalculator.test.ts +1 -1
  322. package/src/cli/ui/components/solid/Footer.tsx +36 -0
  323. package/src/cli/ui/components/{parts → solid}/Header.tsx +17 -28
  324. package/src/cli/ui/components/solid/HelpOverlay.tsx +194 -0
  325. package/src/cli/ui/components/solid/QuickStartStep.tsx +209 -0
  326. package/src/cli/ui/components/{parts → solid}/ScrollableList.tsx +7 -8
  327. package/src/cli/ui/components/solid/SearchInput.tsx +42 -0
  328. package/src/cli/ui/components/solid/SelectInput.tsx +88 -0
  329. package/src/cli/ui/components/solid/Stats.tsx +92 -0
  330. package/src/cli/ui/components/solid/TextInput.tsx +49 -0
  331. package/src/cli/ui/components/solid/WizardController.tsx +393 -0
  332. package/src/cli/ui/components/solid/WizardPopup.tsx +135 -0
  333. package/src/cli/ui/components/solid/WizardSteps.tsx +736 -0
  334. package/src/cli/ui/core/index.ts +17 -0
  335. package/src/cli/ui/core/keybindings.ts +367 -0
  336. package/src/cli/ui/core/theme.ts +266 -0
  337. package/src/cli/ui/core/types.ts +235 -0
  338. package/src/cli/ui/hooks/solid/useAsyncOperation.ts +78 -0
  339. package/src/cli/ui/hooks/solid/useFilter.ts +86 -0
  340. package/src/cli/ui/hooks/solid/useGitOperations.ts +81 -0
  341. package/src/cli/ui/hooks/solid/useKeyHandler.ts +103 -0
  342. package/src/cli/ui/hooks/solid/useScrollableList.ts +149 -0
  343. package/src/cli/ui/hooks/solid/useSelection.ts +77 -0
  344. package/src/cli/ui/hooks/solid/useTerminalSize.ts +22 -0
  345. package/src/cli/ui/index.solid.ts +28 -0
  346. package/src/cli/ui/screens/solid/BranchListScreen.tsx +1153 -0
  347. package/src/cli/ui/screens/solid/ConfirmScreen.tsx +86 -0
  348. package/src/cli/ui/screens/solid/EnvironmentScreen.tsx +161 -0
  349. package/src/cli/ui/screens/solid/ErrorScreen.tsx +42 -0
  350. package/src/cli/ui/screens/solid/InputScreen.tsx +55 -0
  351. package/src/cli/ui/screens/solid/LoadingIndicator.tsx +77 -0
  352. package/src/cli/ui/screens/solid/LogDetailScreen.tsx +75 -0
  353. package/src/cli/ui/screens/solid/LogScreen.tsx +504 -0
  354. package/src/cli/ui/screens/solid/ProfileEnvScreen.tsx +196 -0
  355. package/src/cli/ui/screens/solid/ProfileScreen.tsx +98 -0
  356. package/src/cli/ui/screens/solid/SelectorScreen.tsx +181 -0
  357. package/src/cli/ui/screens/solid/SettingsScreen.tsx +52 -0
  358. package/src/cli/ui/screens/solid/WorktreeCreateScreen.tsx +136 -0
  359. package/src/cli/ui/screens/solid/WorktreeDeleteScreen.tsx +40 -0
  360. package/src/cli/ui/stores/appStore.ts +208 -0
  361. package/src/cli/ui/stores/branchStore.ts +357 -0
  362. package/src/cli/ui/stores/index.ts +31 -0
  363. package/src/cli/ui/stores/uiStore.ts +226 -0
  364. package/src/cli/ui/types.ts +21 -3
  365. package/src/cli/ui/utils/__tests__/branchFormatter.test.ts +227 -0
  366. package/src/cli/ui/utils/branchFormatter.ts +43 -222
  367. package/src/cli/ui/utils/continueSession.ts +133 -2
  368. package/src/cli/ui/utils/modelOptions.test.ts +1 -1
  369. package/src/cli/ui/utils/versionCache.ts +93 -0
  370. package/src/cli/ui/utils/versionFetcher.ts +120 -0
  371. package/src/codex.ts +138 -39
  372. package/src/config/__tests__/saveSession.test.ts +143 -0
  373. package/src/config/builtin-coding-agents.ts +4 -4
  374. package/src/config/index.ts +14 -0
  375. package/src/gemini.ts +107 -46
  376. package/src/index.test.ts +25 -19
  377. package/src/index.ts +202 -143
  378. package/src/launcher.ts +66 -6
  379. package/src/logging/agentOutput.ts +216 -0
  380. package/src/logging/formatter.ts +23 -4
  381. package/src/logging/logger.ts +34 -10
  382. package/src/logging/reader.ts +117 -0
  383. package/src/opentui/index.solid.ts +1 -0
  384. package/src/repositories/worktree.repository.ts +8 -0
  385. package/src/services/__tests__/BatchMergeService.test.ts +83 -67
  386. package/src/services/__tests__/WorktreeOrchestrator.test.ts +8 -7
  387. package/src/services/codingAgentResolver.ts +30 -4
  388. package/src/services/dependency-installer.ts +2 -9
  389. package/src/types/api.ts +3 -0
  390. package/src/types/coding-agent.ts +85 -0
  391. package/src/types/tools.ts +19 -0
  392. package/src/utils/__tests__/npmRegistry.test.ts +250 -0
  393. package/src/utils/__tests__/prompt.test.ts +4 -5
  394. package/src/utils/coding-agent-colors.ts +165 -0
  395. package/src/utils/command.ts +1 -1
  396. package/src/utils/error-utils.ts +133 -0
  397. package/src/utils/npmRegistry.ts +249 -0
  398. package/src/utils/prompt.ts +1 -1
  399. package/src/utils/session/common.ts +28 -0
  400. package/src/utils/session/parsers/claude.ts +79 -29
  401. package/src/utils/session/parsers/codex.ts +50 -18
  402. package/src/utils/session/parsers/gemini.ts +46 -5
  403. package/src/utils/session/parsers/opencode.ts +46 -5
  404. package/src/utils/session/types.ts +4 -0
  405. package/src/utils/terminal.ts +24 -0
  406. package/src/utils.test.ts +1 -1
  407. package/src/utils.ts +37 -4
  408. package/src/web/client/src/components/CodingAgentLaunchModal.tsx +12 -21
  409. package/src/web/client/src/components/branch-detail/BranchInfoCards.tsx +16 -1
  410. package/src/web/client/src/components/branch-detail/SessionHistoryTable.tsx +7 -1
  411. package/src/web/client/src/components/branch-detail/ToolLauncher.tsx +11 -6
  412. package/src/web/client/src/lib/coding-agent-colors.ts +149 -0
  413. package/src/web/client/src/pages/BranchDetailPage.tsx +11 -11
  414. package/src/web/server/pty/manager.ts +139 -0
  415. package/src/web/server/routes/sessions.ts +6 -0
  416. package/src/web/server/services/branches.ts +11 -8
  417. package/src/web/server/services/worktrees.ts +2 -2
  418. package/src/worktree.ts +386 -114
  419. package/dist/cli/ui/components/App.d.ts +0 -25
  420. package/dist/cli/ui/components/App.d.ts.map +0 -1
  421. package/dist/cli/ui/components/App.js +0 -1006
  422. package/dist/cli/ui/components/App.js.map +0 -1
  423. package/dist/cli/ui/components/common/Confirm.d.ts +0 -13
  424. package/dist/cli/ui/components/common/Confirm.d.ts.map +0 -1
  425. package/dist/cli/ui/components/common/Confirm.js +0 -20
  426. package/dist/cli/ui/components/common/Confirm.js.map +0 -1
  427. package/dist/cli/ui/components/common/ErrorBoundary.d.ts +0 -23
  428. package/dist/cli/ui/components/common/ErrorBoundary.d.ts.map +0 -1
  429. package/dist/cli/ui/components/common/ErrorBoundary.js +0 -37
  430. package/dist/cli/ui/components/common/ErrorBoundary.js.map +0 -1
  431. package/dist/cli/ui/components/common/Input.d.ts +0 -19
  432. package/dist/cli/ui/components/common/Input.d.ts.map +0 -1
  433. package/dist/cli/ui/components/common/Input.js +0 -22
  434. package/dist/cli/ui/components/common/Input.js.map +0 -1
  435. package/dist/cli/ui/components/common/LoadingIndicator.d.ts +0 -19
  436. package/dist/cli/ui/components/common/LoadingIndicator.d.ts.map +0 -1
  437. package/dist/cli/ui/components/common/LoadingIndicator.js +0 -61
  438. package/dist/cli/ui/components/common/LoadingIndicator.js.map +0 -1
  439. package/dist/cli/ui/components/common/Select.d.ts +0 -38
  440. package/dist/cli/ui/components/common/Select.d.ts.map +0 -1
  441. package/dist/cli/ui/components/common/Select.js +0 -151
  442. package/dist/cli/ui/components/common/Select.js.map +0 -1
  443. package/dist/cli/ui/components/common/SpinnerIcon.d.ts +0 -20
  444. package/dist/cli/ui/components/common/SpinnerIcon.d.ts.map +0 -1
  445. package/dist/cli/ui/components/common/SpinnerIcon.js +0 -61
  446. package/dist/cli/ui/components/common/SpinnerIcon.js.map +0 -1
  447. package/dist/cli/ui/components/parts/Footer.d.ts +0 -15
  448. package/dist/cli/ui/components/parts/Footer.d.ts.map +0 -1
  449. package/dist/cli/ui/components/parts/Footer.js +0 -20
  450. package/dist/cli/ui/components/parts/Footer.js.map +0 -1
  451. package/dist/cli/ui/components/parts/Header.d.ts.map +0 -1
  452. package/dist/cli/ui/components/parts/Header.js +0 -24
  453. package/dist/cli/ui/components/parts/Header.js.map +0 -1
  454. package/dist/cli/ui/components/parts/MergeStatusList.d.ts +0 -13
  455. package/dist/cli/ui/components/parts/MergeStatusList.d.ts.map +0 -1
  456. package/dist/cli/ui/components/parts/MergeStatusList.js +0 -52
  457. package/dist/cli/ui/components/parts/MergeStatusList.js.map +0 -1
  458. package/dist/cli/ui/components/parts/ProgressBar.d.ts +0 -13
  459. package/dist/cli/ui/components/parts/ProgressBar.d.ts.map +0 -1
  460. package/dist/cli/ui/components/parts/ProgressBar.js +0 -53
  461. package/dist/cli/ui/components/parts/ProgressBar.js.map +0 -1
  462. package/dist/cli/ui/components/parts/ScrollableList.d.ts +0 -12
  463. package/dist/cli/ui/components/parts/ScrollableList.d.ts.map +0 -1
  464. package/dist/cli/ui/components/parts/ScrollableList.js +0 -11
  465. package/dist/cli/ui/components/parts/ScrollableList.js.map +0 -1
  466. package/dist/cli/ui/components/parts/Stats.d.ts +0 -10
  467. package/dist/cli/ui/components/parts/Stats.d.ts.map +0 -1
  468. package/dist/cli/ui/components/parts/Stats.js +0 -55
  469. package/dist/cli/ui/components/parts/Stats.js.map +0 -1
  470. package/dist/cli/ui/components/screens/BatchMergeProgressScreen.d.ts +0 -17
  471. package/dist/cli/ui/components/screens/BatchMergeProgressScreen.d.ts.map +0 -1
  472. package/dist/cli/ui/components/screens/BatchMergeProgressScreen.js +0 -42
  473. package/dist/cli/ui/components/screens/BatchMergeProgressScreen.js.map +0 -1
  474. package/dist/cli/ui/components/screens/BatchMergeResultScreen.d.ts +0 -17
  475. package/dist/cli/ui/components/screens/BatchMergeResultScreen.d.ts.map +0 -1
  476. package/dist/cli/ui/components/screens/BatchMergeResultScreen.js +0 -72
  477. package/dist/cli/ui/components/screens/BatchMergeResultScreen.js.map +0 -1
  478. package/dist/cli/ui/components/screens/BranchCreatorScreen.d.ts +0 -18
  479. package/dist/cli/ui/components/screens/BranchCreatorScreen.d.ts.map +0 -1
  480. package/dist/cli/ui/components/screens/BranchCreatorScreen.js +0 -151
  481. package/dist/cli/ui/components/screens/BranchCreatorScreen.js.map +0 -1
  482. package/dist/cli/ui/components/screens/BranchListScreen.d.ts +0 -60
  483. package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +0 -1
  484. package/dist/cli/ui/components/screens/BranchListScreen.js +0 -476
  485. package/dist/cli/ui/components/screens/BranchListScreen.js.map +0 -1
  486. package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts +0 -30
  487. package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts.map +0 -1
  488. package/dist/cli/ui/components/screens/BranchQuickStartScreen.js +0 -148
  489. package/dist/cli/ui/components/screens/BranchQuickStartScreen.js.map +0 -1
  490. package/dist/cli/ui/components/screens/CodingAgentSelectorScreen.d.ts +0 -27
  491. package/dist/cli/ui/components/screens/CodingAgentSelectorScreen.d.ts.map +0 -1
  492. package/dist/cli/ui/components/screens/CodingAgentSelectorScreen.js +0 -93
  493. package/dist/cli/ui/components/screens/CodingAgentSelectorScreen.js.map +0 -1
  494. package/dist/cli/ui/components/screens/EnvironmentProfileScreen.d.ts +0 -19
  495. package/dist/cli/ui/components/screens/EnvironmentProfileScreen.d.ts.map +0 -1
  496. package/dist/cli/ui/components/screens/EnvironmentProfileScreen.js +0 -577
  497. package/dist/cli/ui/components/screens/EnvironmentProfileScreen.js.map +0 -1
  498. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.d.ts +0 -45
  499. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.d.ts.map +0 -1
  500. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.js +0 -95
  501. package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.js.map +0 -1
  502. package/dist/cli/ui/components/screens/LogDatePickerScreen.d.ts +0 -10
  503. package/dist/cli/ui/components/screens/LogDatePickerScreen.d.ts.map +0 -1
  504. package/dist/cli/ui/components/screens/LogDatePickerScreen.js +0 -44
  505. package/dist/cli/ui/components/screens/LogDatePickerScreen.js.map +0 -1
  506. package/dist/cli/ui/components/screens/LogDetailScreen.d.ts.map +0 -1
  507. package/dist/cli/ui/components/screens/LogDetailScreen.js +0 -34
  508. package/dist/cli/ui/components/screens/LogDetailScreen.js.map +0 -1
  509. package/dist/cli/ui/components/screens/LogListScreen.d.ts.map +0 -1
  510. package/dist/cli/ui/components/screens/LogListScreen.js +0 -107
  511. package/dist/cli/ui/components/screens/LogListScreen.js.map +0 -1
  512. package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts +0 -24
  513. package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts.map +0 -1
  514. package/dist/cli/ui/components/screens/ModelSelectorScreen.js +0 -197
  515. package/dist/cli/ui/components/screens/ModelSelectorScreen.js.map +0 -1
  516. package/dist/cli/ui/components/screens/PRCleanupScreen.d.ts +0 -29
  517. package/dist/cli/ui/components/screens/PRCleanupScreen.d.ts.map +0 -1
  518. package/dist/cli/ui/components/screens/PRCleanupScreen.js +0 -92
  519. package/dist/cli/ui/components/screens/PRCleanupScreen.js.map +0 -1
  520. package/dist/cli/ui/components/screens/SessionSelectorScreen.d.ts +0 -31
  521. package/dist/cli/ui/components/screens/SessionSelectorScreen.d.ts.map +0 -1
  522. package/dist/cli/ui/components/screens/SessionSelectorScreen.js +0 -67
  523. package/dist/cli/ui/components/screens/SessionSelectorScreen.js.map +0 -1
  524. package/dist/cli/ui/hooks/useAppInput.d.ts +0 -21
  525. package/dist/cli/ui/hooks/useAppInput.d.ts.map +0 -1
  526. package/dist/cli/ui/hooks/useAppInput.js +0 -138
  527. package/dist/cli/ui/hooks/useAppInput.js.map +0 -1
  528. package/dist/cli/ui/hooks/useBatchMerge.d.ts +0 -17
  529. package/dist/cli/ui/hooks/useBatchMerge.d.ts.map +0 -1
  530. package/dist/cli/ui/hooks/useBatchMerge.js +0 -77
  531. package/dist/cli/ui/hooks/useBatchMerge.js.map +0 -1
  532. package/dist/cli/ui/hooks/useGitData.d.ts +0 -21
  533. package/dist/cli/ui/hooks/useGitData.d.ts.map +0 -1
  534. package/dist/cli/ui/hooks/useGitData.js +0 -229
  535. package/dist/cli/ui/hooks/useGitData.js.map +0 -1
  536. package/dist/cli/ui/hooks/useProfiles.d.ts +0 -41
  537. package/dist/cli/ui/hooks/useProfiles.d.ts.map +0 -1
  538. package/dist/cli/ui/hooks/useProfiles.js +0 -136
  539. package/dist/cli/ui/hooks/useProfiles.js.map +0 -1
  540. package/dist/cli/ui/hooks/useScreenState.d.ts +0 -12
  541. package/dist/cli/ui/hooks/useScreenState.d.ts.map +0 -1
  542. package/dist/cli/ui/hooks/useScreenState.js +0 -30
  543. package/dist/cli/ui/hooks/useScreenState.js.map +0 -1
  544. package/dist/cli/ui/hooks/useTerminalSize.d.ts +0 -9
  545. package/dist/cli/ui/hooks/useTerminalSize.d.ts.map +0 -1
  546. package/dist/cli/ui/hooks/useTerminalSize.js +0 -24
  547. package/dist/cli/ui/hooks/useTerminalSize.js.map +0 -1
  548. package/dist/cli/ui/hooks/useToolStatus.d.ts +0 -30
  549. package/dist/cli/ui/hooks/useToolStatus.d.ts.map +0 -1
  550. package/dist/cli/ui/hooks/useToolStatus.js +0 -49
  551. package/dist/cli/ui/hooks/useToolStatus.js.map +0 -1
  552. package/dist/cli/ui/screens/BranchActionSelectorScreen.d.ts +0 -24
  553. package/dist/cli/ui/screens/BranchActionSelectorScreen.d.ts.map +0 -1
  554. package/dist/cli/ui/screens/BranchActionSelectorScreen.js +0 -65
  555. package/dist/cli/ui/screens/BranchActionSelectorScreen.js.map +0 -1
  556. package/dist/client/assets/index-LNPtOrn3.js +0 -78
  557. package/src/cli/ui/__tests__/SKIPPED_TESTS.md +0 -119
  558. package/src/cli/ui/__tests__/acceptance/branchList.acceptance.test.tsx.skip +0 -239
  559. package/src/cli/ui/__tests__/acceptance/navigation.acceptance.test.tsx +0 -225
  560. package/src/cli/ui/__tests__/acceptance/realtimeUpdate.acceptance.test.tsx.skip +0 -219
  561. package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +0 -212
  562. package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +0 -440
  563. package/src/cli/ui/__tests__/components/App.test.tsx +0 -365
  564. package/src/cli/ui/__tests__/components/ModelSelectorScreen.initial.test.tsx +0 -91
  565. package/src/cli/ui/__tests__/components/common/Confirm.test.tsx +0 -80
  566. package/src/cli/ui/__tests__/components/common/ErrorBoundary.test.tsx +0 -104
  567. package/src/cli/ui/__tests__/components/common/Input.test.tsx +0 -100
  568. package/src/cli/ui/__tests__/components/common/LoadingIndicator.test.tsx +0 -148
  569. package/src/cli/ui/__tests__/components/common/Select.memo.test.tsx +0 -255
  570. package/src/cli/ui/__tests__/components/common/Select.test.tsx +0 -335
  571. package/src/cli/ui/__tests__/components/parts/Footer.test.tsx +0 -65
  572. package/src/cli/ui/__tests__/components/parts/Header.test.tsx +0 -55
  573. package/src/cli/ui/__tests__/components/parts/ScrollableList.test.tsx +0 -69
  574. package/src/cli/ui/__tests__/components/parts/Stats.test.tsx +0 -148
  575. package/src/cli/ui/__tests__/components/screens/BranchCreatorScreen.test.tsx +0 -253
  576. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +0 -1070
  577. package/src/cli/ui/__tests__/components/screens/BranchQuickStartScreen.test.tsx +0 -142
  578. package/src/cli/ui/__tests__/components/screens/CodingAgentSelectorScreen.test.tsx +0 -174
  579. package/src/cli/ui/__tests__/components/screens/ExecutionModeSelectorScreen.test.tsx +0 -182
  580. package/src/cli/ui/__tests__/components/screens/LogDetailScreen.test.tsx +0 -57
  581. package/src/cli/ui/__tests__/components/screens/LogListScreen.test.tsx +0 -102
  582. package/src/cli/ui/__tests__/components/screens/PRCleanupScreen.test.tsx +0 -216
  583. package/src/cli/ui/__tests__/components/screens/SessionSelectorScreen.test.tsx +0 -147
  584. package/src/cli/ui/__tests__/hooks/useGitData.nonblocking.test.tsx +0 -206
  585. package/src/cli/ui/__tests__/hooks/useGitData.test.ts +0 -197
  586. package/src/cli/ui/__tests__/hooks/useGitData.test.ts.skip +0 -228
  587. package/src/cli/ui/__tests__/hooks/useScreenState.test.ts +0 -147
  588. package/src/cli/ui/__tests__/hooks/useTerminalSize.test.ts +0 -99
  589. package/src/cli/ui/__tests__/integration/branchList.test.tsx.skip +0 -253
  590. package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +0 -436
  591. package/src/cli/ui/__tests__/integration/navigation.test.tsx +0 -514
  592. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx +0 -509
  593. package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx.skip +0 -216
  594. package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +0 -193
  595. package/src/cli/ui/__tests__/performance/useMemoOptimization.test.tsx +0 -234
  596. package/src/cli/ui/components/App.tsx +0 -1478
  597. package/src/cli/ui/components/common/Confirm.tsx +0 -44
  598. package/src/cli/ui/components/common/ErrorBoundary.tsx +0 -60
  599. package/src/cli/ui/components/common/Input.tsx +0 -58
  600. package/src/cli/ui/components/common/LoadingIndicator.tsx +0 -98
  601. package/src/cli/ui/components/common/Select.tsx +0 -247
  602. package/src/cli/ui/components/common/SpinnerIcon.tsx +0 -86
  603. package/src/cli/ui/components/parts/Footer.tsx +0 -41
  604. package/src/cli/ui/components/parts/Header.test.tsx +0 -75
  605. package/src/cli/ui/components/parts/MergeStatusList.tsx +0 -75
  606. package/src/cli/ui/components/parts/ProgressBar.tsx +0 -73
  607. package/src/cli/ui/components/parts/Stats.tsx +0 -88
  608. package/src/cli/ui/components/screens/BatchMergeProgressScreen.tsx +0 -74
  609. package/src/cli/ui/components/screens/BatchMergeResultScreen.tsx +0 -108
  610. package/src/cli/ui/components/screens/BranchCreatorScreen.tsx +0 -242
  611. package/src/cli/ui/components/screens/BranchListScreen.tsx +0 -744
  612. package/src/cli/ui/components/screens/BranchQuickStartScreen.tsx +0 -244
  613. package/src/cli/ui/components/screens/CodingAgentSelectorScreen.tsx +0 -159
  614. package/src/cli/ui/components/screens/EnvironmentProfileScreen.tsx +0 -928
  615. package/src/cli/ui/components/screens/ExecutionModeSelectorScreen.tsx +0 -176
  616. package/src/cli/ui/components/screens/LogDatePickerScreen.tsx +0 -83
  617. package/src/cli/ui/components/screens/LogDetailScreen.tsx +0 -67
  618. package/src/cli/ui/components/screens/LogListScreen.tsx +0 -192
  619. package/src/cli/ui/components/screens/ModelSelectorScreen.tsx +0 -320
  620. package/src/cli/ui/components/screens/PRCleanupScreen.tsx +0 -171
  621. package/src/cli/ui/components/screens/SessionSelectorScreen.tsx +0 -135
  622. package/src/cli/ui/hooks/useAppInput.ts +0 -172
  623. package/src/cli/ui/hooks/useBatchMerge.ts +0 -96
  624. package/src/cli/ui/hooks/useGitData.ts +0 -347
  625. package/src/cli/ui/hooks/useProfiles.ts +0 -211
  626. package/src/cli/ui/hooks/useScreenState.ts +0 -44
  627. package/src/cli/ui/hooks/useTerminalSize.ts +0 -33
  628. package/src/cli/ui/hooks/useToolStatus.ts +0 -68
  629. package/src/cli/ui/screens/BranchActionSelectorScreen.tsx +0 -111
  630. package/src/cli/ui/screens/__tests__/BranchActionSelectorScreen.test.tsx +0 -264
@@ -1,14 +1,39 @@
1
- import { describe, it, expect } from "vitest";
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import { describe, it, expect } from "bun:test";
2
3
  import {
3
4
  formatBranchItem,
4
5
  formatBranchItems,
5
6
  } from "../../utils/branchFormatter.js";
6
7
  import type { BranchInfo } from "../../types.js";
7
- import stringWidth from "string-width";
8
+
9
+ const LOCAL_DATE_TIME_FORMATTER = new Intl.DateTimeFormat(undefined, {
10
+ year: "numeric",
11
+ month: "2-digit",
12
+ day: "2-digit",
13
+ hour: "2-digit",
14
+ minute: "2-digit",
15
+ hour12: false,
16
+ });
17
+
18
+ const formatLocalDateTime = (timestampMs: number): string => {
19
+ const date = new Date(timestampMs);
20
+ const parts = LOCAL_DATE_TIME_FORMATTER.formatToParts(date);
21
+ const get = (type: Intl.DateTimeFormatPartTypes) =>
22
+ parts.find((part) => part.type === type)?.value;
23
+ const year = get("year");
24
+ const month = get("month");
25
+ const day = get("day");
26
+ const hour = get("hour");
27
+ const minute = get("minute");
28
+ if (!year || !month || !day || !hour || !minute) {
29
+ return LOCAL_DATE_TIME_FORMATTER.format(date);
30
+ }
31
+ return `${year}-${month}-${day} ${hour}:${minute}`;
32
+ };
8
33
 
9
34
  describe("branchFormatter", () => {
10
35
  describe("formatBranchItem", () => {
11
- it("should format a main branch", () => {
36
+ it("should format a branch without icons", () => {
12
37
  const branchInfo: BranchInfo = {
13
38
  name: "main",
14
39
  type: "local",
@@ -22,29 +47,12 @@ describe("branchFormatter", () => {
22
47
  expect(result.type).toBe("local");
23
48
  expect(result.branchType).toBe("main");
24
49
  expect(result.isCurrent).toBe(true);
25
- expect(result.icons).toContain("⚡"); // main icon
26
- expect(result.icons).toContain("👉"); // current icon
27
- expect(result.label).toContain("main");
50
+ expect(result.icons).toHaveLength(0);
51
+ expect(result.label).toBe("main");
28
52
  expect(result.value).toBe("main");
29
53
  expect(result.hasChanges).toBe(false);
30
54
  });
31
55
 
32
- it("should format a feature branch", () => {
33
- const branchInfo: BranchInfo = {
34
- name: "feature/new-ui",
35
- type: "local",
36
- branchType: "feature",
37
- isCurrent: false,
38
- };
39
-
40
- const result = formatBranchItem(branchInfo);
41
-
42
- expect(result.icons).toContain("✨"); // feature icon
43
- expect(result.icons).not.toContain("👉"); // not current
44
- expect(result.label).toContain("feature/new-ui");
45
- expect(result.value).toBe("feature/new-ui");
46
- });
47
-
48
56
  it("should include last tool usage label when present", () => {
49
57
  const branchInfo: BranchInfo = {
50
58
  name: "feature/tool",
@@ -64,22 +72,9 @@ describe("branchFormatter", () => {
64
72
 
65
73
  const result = formatBranchItem(branchInfo);
66
74
 
67
- expect(result.lastToolUsageLabel).toContain("Codex");
68
- expect(result.lastToolUsageLabel).toContain("2025-11-26");
69
- });
70
-
71
- it("should format a bugfix branch", () => {
72
- const branchInfo: BranchInfo = {
73
- name: "bugfix/security-issue",
74
- type: "local",
75
- branchType: "bugfix",
76
- isCurrent: false,
77
- };
78
-
79
- const result = formatBranchItem(branchInfo);
80
-
81
- expect(result.icons).toContain("🐛"); // bugfix icon
82
- expect(result.label).toContain("bugfix/security-issue");
75
+ expect(result.lastToolUsageLabel).toBe(
76
+ `Codex@latest | ${formatLocalDateTime(branchInfo.lastToolUsage.timestamp)}`,
77
+ );
83
78
  });
84
79
 
85
80
  it("should set lastToolUsageLabel to null when no usage exists", () => {
@@ -95,34 +90,6 @@ describe("branchFormatter", () => {
95
90
  expect(result.lastToolUsageLabel).toBeNull();
96
91
  });
97
92
 
98
- it("should format a hotfix branch", () => {
99
- const branchInfo: BranchInfo = {
100
- name: "hotfix/critical-bug",
101
- type: "local",
102
- branchType: "hotfix",
103
- isCurrent: false,
104
- };
105
-
106
- const result = formatBranchItem(branchInfo);
107
-
108
- expect(result.icons).toContain("🔥"); // hotfix icon
109
- expect(result.label).toContain("hotfix/critical-bug");
110
- });
111
-
112
- it("should format a release branch", () => {
113
- const branchInfo: BranchInfo = {
114
- name: "release/v1.0.0",
115
- type: "local",
116
- branchType: "release",
117
- isCurrent: false,
118
- };
119
-
120
- const result = formatBranchItem(branchInfo);
121
-
122
- expect(result.icons).toContain("🚀"); // release icon
123
- expect(result.label).toContain("release/v1.0.0");
124
- });
125
-
126
93
  it("should format a remote branch", () => {
127
94
  const branchInfo: BranchInfo = {
128
95
  name: "origin/main",
@@ -133,64 +100,12 @@ describe("branchFormatter", () => {
133
100
 
134
101
  const result = formatBranchItem(branchInfo);
135
102
 
136
- expect(result.icons).toContain("⚡"); // main icon
137
- expect(result.icons).toContain("☁"); // remote icon
138
103
  expect(result.type).toBe("remote");
139
- expect(result.label).toContain("origin/main");
104
+ expect(result.label).toBe("origin/main");
105
+ expect(result.remoteName).toBe("origin/main");
140
106
  });
141
107
 
142
- it("should align branch names regardless of remote icon presence", () => {
143
- const localBranch: BranchInfo = {
144
- name: "feature/foo",
145
- type: "local",
146
- branchType: "feature",
147
- isCurrent: false,
148
- };
149
- const remoteBranch: BranchInfo = {
150
- name: "origin/feature/foo",
151
- type: "remote",
152
- branchType: "feature",
153
- isCurrent: false,
154
- };
155
-
156
- const localResult = formatBranchItem(localBranch);
157
- const remoteResult = formatBranchItem(remoteBranch);
158
-
159
- // Both should have the branch name in the label
160
- expect(localResult.label).toContain("feature/foo");
161
- expect(remoteResult.label).toContain("origin/feature/foo");
162
-
163
- // Remote branch should have ☁️ marker for remote-only status
164
- expect(remoteResult.label).toMatch(/☁️/);
165
- });
166
-
167
- it("should keep icon columns fixed-width when using wide emoji icons", () => {
168
- const branchInfo: BranchInfo = {
169
- name: "feature/wide-icons",
170
- type: "remote",
171
- branchType: "feature",
172
- isCurrent: false,
173
- hasUnpushedCommits: true,
174
- worktree: {
175
- path: "/path/to/worktree",
176
- locked: false,
177
- prunable: false,
178
- isAccessible: true,
179
- },
180
- };
181
-
182
- const result = formatBranchItem(branchInfo, { hasChanges: true });
183
-
184
- // Icon columns: [Type][Worktree][Changes][Remote] = 4 * 2 = 8
185
- // Sync column: 6 (fixed width for icon + up to 4 digits + space)
186
- // Total: 14
187
- const iconBlockWidth =
188
- stringWidth(result.label) - stringWidth(branchInfo.name);
189
-
190
- expect(iconBlockWidth).toBe(14);
191
- });
192
-
193
- it("should include worktree status icon when provided", () => {
108
+ it("should set worktree status when provided", () => {
194
109
  const branchInfo: BranchInfo = {
195
110
  name: "feature/test",
196
111
  type: "local",
@@ -205,7 +120,6 @@ describe("branchFormatter", () => {
205
120
 
206
121
  const result = formatBranchItem(branchInfo);
207
122
 
208
- expect(result.icons).toContain("🟢"); // active worktree icon
209
123
  expect(result.worktreeStatus).toBe("active");
210
124
  });
211
125
 
@@ -219,55 +133,9 @@ describe("branchFormatter", () => {
219
133
 
220
134
  const result = formatBranchItem(branchInfo, { hasChanges: true });
221
135
 
222
- expect(result.icons).toContain("💾"); // changes icon
223
136
  expect(result.hasChanges).toBe(true);
224
137
  });
225
138
 
226
- it("should show unpushed commits icon", () => {
227
- const branchInfo: BranchInfo = {
228
- name: "feature/unpushed",
229
- type: "local",
230
- branchType: "feature",
231
- isCurrent: false,
232
- hasUnpushedCommits: true,
233
- };
234
-
235
- const result = formatBranchItem(branchInfo);
236
-
237
- expect(result.icons).toContain("📤"); // unpushed icon
238
- expect(result.label).toContain("📤");
239
- });
240
-
241
- it("should show open PR icon", () => {
242
- const branchInfo: BranchInfo = {
243
- name: "feature/pr-open",
244
- type: "local",
245
- branchType: "feature",
246
- isCurrent: false,
247
- openPR: { number: 123, title: "Test PR" },
248
- };
249
-
250
- const result = formatBranchItem(branchInfo);
251
-
252
- expect(result.icons).toContain("🔃"); // open PR icon
253
- expect(result.label).toContain("🔃");
254
- });
255
-
256
- it("should show merged PR icon", () => {
257
- const branchInfo: BranchInfo = {
258
- name: "feature/pr-merged",
259
- type: "local",
260
- branchType: "feature",
261
- isCurrent: false,
262
- mergedPR: { number: 456, mergedAt: "2025-10-31T00:00:00Z" },
263
- };
264
-
265
- const result = formatBranchItem(branchInfo);
266
-
267
- expect(result.icons).toContain("✅"); // merged PR icon
268
- expect(result.label).toContain("✅");
269
- });
270
-
271
139
  it("should show warning icon for inaccessible worktree", () => {
272
140
  const branchInfo: BranchInfo = {
273
141
  name: "feature/broken-worktree",
@@ -284,131 +152,8 @@ describe("branchFormatter", () => {
284
152
 
285
153
  const result = formatBranchItem(branchInfo);
286
154
 
287
- expect(result.icons).toContain("🔴"); // inaccessible worktree icon
288
- expect(result.icons).toContain("⚠️"); // warning icon
289
155
  expect(result.worktreeStatus).toBe("inaccessible");
290
156
  });
291
-
292
- it("should prioritize hasChanges over unpushed commits", () => {
293
- const branchInfo: BranchInfo = {
294
- name: "feature/both",
295
- type: "local",
296
- branchType: "feature",
297
- isCurrent: false,
298
- hasUnpushedCommits: true,
299
- };
300
-
301
- const resultWithChanges = formatBranchItem(branchInfo, {
302
- hasChanges: true,
303
- });
304
- expect(resultWithChanges.icons).toContain("💾");
305
- expect(resultWithChanges.icons).not.toContain("📤");
306
-
307
- const resultWithoutChanges = formatBranchItem(branchInfo);
308
- expect(resultWithoutChanges.icons).toContain("📤");
309
- expect(resultWithoutChanges.icons).not.toContain("💾");
310
- });
311
-
312
- it("should prioritize unpushed over open PR", () => {
313
- const branchInfo: BranchInfo = {
314
- name: "feature/unpushed-pr",
315
- type: "local",
316
- branchType: "feature",
317
- isCurrent: false,
318
- hasUnpushedCommits: true,
319
- openPR: { number: 123, title: "Test PR" },
320
- };
321
-
322
- const result = formatBranchItem(branchInfo);
323
-
324
- expect(result.icons).toContain("📤");
325
- expect(result.icons).not.toContain("🔃");
326
- });
327
-
328
- it("should prioritize open PR over merged PR", () => {
329
- const branchInfo: BranchInfo = {
330
- name: "feature/both-pr",
331
- type: "local",
332
- branchType: "feature",
333
- isCurrent: false,
334
- openPR: { number: 123, title: "Test PR" },
335
- mergedPR: { number: 456, mergedAt: "2025-10-31T00:00:00Z" },
336
- };
337
-
338
- const result = formatBranchItem(branchInfo);
339
-
340
- expect(result.icons).toContain("🔃");
341
- expect(result.icons).not.toContain("✅");
342
- });
343
-
344
- it("should prioritize merged PR over warning", () => {
345
- const branchInfo: BranchInfo = {
346
- name: "feature/merged-broken",
347
- type: "local",
348
- branchType: "feature",
349
- isCurrent: false,
350
- mergedPR: { number: 456, mergedAt: "2025-10-31T00:00:00Z" },
351
- worktree: {
352
- path: "/path/to/worktree",
353
- locked: false,
354
- prunable: false,
355
- isAccessible: false,
356
- },
357
- };
358
-
359
- const result = formatBranchItem(branchInfo);
360
-
361
- expect(result.icons).toContain("✅");
362
- expect(result.icons).not.toContain("⚠️");
363
- });
364
-
365
- it("should prioritize warning over current branch icon", () => {
366
- const branchInfo: BranchInfo = {
367
- name: "feature/current-broken",
368
- type: "local",
369
- branchType: "feature",
370
- isCurrent: true,
371
- worktree: {
372
- path: "/path/to/worktree",
373
- locked: false,
374
- prunable: false,
375
- isAccessible: false,
376
- },
377
- };
378
-
379
- const result = formatBranchItem(branchInfo);
380
-
381
- expect(result.icons).toContain("⚠️");
382
- expect(result.icons).not.toContain("👉");
383
- });
384
-
385
- it("should handle develop branch", () => {
386
- const branchInfo: BranchInfo = {
387
- name: "develop",
388
- type: "local",
389
- branchType: "develop",
390
- isCurrent: false,
391
- };
392
-
393
- const result = formatBranchItem(branchInfo);
394
-
395
- expect(result.icons).toContain("⚡"); // develop icon (same as main)
396
- expect(result.label).toContain("develop");
397
- });
398
-
399
- it("should handle other branch type", () => {
400
- const branchInfo: BranchInfo = {
401
- name: "custom-branch",
402
- type: "local",
403
- branchType: "other",
404
- isCurrent: false,
405
- };
406
-
407
- const result = formatBranchItem(branchInfo);
408
-
409
- expect(result.icons).toContain("📌"); // other icon
410
- expect(result.label).toContain("custom-branch");
411
- });
412
157
  });
413
158
 
414
159
  describe("formatBranchItems", () => {
@@ -438,13 +183,13 @@ describe("branchFormatter", () => {
438
183
 
439
184
  expect(results).toHaveLength(3);
440
185
  // Current branch (main) should be first
441
- expect(results[0].name).toBe("main");
442
- expect(results[0].isCurrent).toBe(true);
186
+ expect(results[0]!.name).toBe("main");
187
+ expect(results[0]!.isCurrent).toBe(true);
443
188
  // origin/main is also main branch, so it comes second
444
- expect(results[1].name).toBe("origin/main");
445
- expect(results[1].type).toBe("remote");
189
+ expect(results[1]!.name).toBe("origin/main");
190
+ expect(results[1]!.type).toBe("remote");
446
191
  // feature/test comes last
447
- expect(results[2].name).toBe("feature/test");
192
+ expect(results[2]!.name).toBe("feature/test");
448
193
  });
449
194
 
450
195
  it("should handle empty array", () => {
@@ -471,8 +216,8 @@ describe("branchFormatter", () => {
471
216
 
472
217
  const results = formatBranchItems(branches);
473
218
 
474
- expect(results[0].name).toBe("a-branch");
475
- expect(results[1].name).toBe("z-branch");
219
+ expect(results[0]!.name).toBe("a-branch");
220
+ expect(results[1]!.name).toBe("z-branch");
476
221
  });
477
222
  });
478
223
 
@@ -501,8 +246,8 @@ describe("branchFormatter", () => {
501
246
 
502
247
  const results = formatBranchItems(branches);
503
248
 
504
- expect(results[0].name).toBe("feature/current");
505
- expect(results[0].isCurrent).toBe(true);
249
+ expect(results[0]!.name).toBe("feature/current");
250
+ expect(results[0]!.isCurrent).toBe(true);
506
251
  });
507
252
 
508
253
  it("should prioritize main branch as second (after current)", () => {
@@ -529,8 +274,8 @@ describe("branchFormatter", () => {
529
274
 
530
275
  const results = formatBranchItems(branches);
531
276
 
532
- expect(results[0].name).toBe("main");
533
- expect(results[1].name).toBe("develop");
277
+ expect(results[0]!.name).toBe("main");
278
+ expect(results[1]!.name).toBe("develop");
534
279
  });
535
280
 
536
281
  it("should prioritize develop branch after main (when main exists)", () => {
@@ -557,9 +302,9 @@ describe("branchFormatter", () => {
557
302
 
558
303
  const results = formatBranchItems(branches);
559
304
 
560
- expect(results[0].name).toBe("main");
561
- expect(results[1].name).toBe("develop");
562
- expect(results[2].name).toBe("feature/test");
305
+ expect(results[0]!.name).toBe("main");
306
+ expect(results[1]!.name).toBe("develop");
307
+ expect(results[2]!.name).toBe("feature/test");
563
308
  });
564
309
 
565
310
  it("should NOT prioritize develop branch when main does not exist", () => {
@@ -587,9 +332,9 @@ describe("branchFormatter", () => {
587
332
  const results = formatBranchItems(branches);
588
333
 
589
334
  // develop should be sorted alphabetically, not prioritized
590
- expect(results[0].name).toBe("develop");
591
- expect(results[1].name).toBe("feature/a");
592
- expect(results[2].name).toBe("feature/z");
335
+ expect(results[0]!.name).toBe("develop");
336
+ expect(results[1]!.name).toBe("feature/a");
337
+ expect(results[2]!.name).toBe("feature/z");
593
338
  });
594
339
 
595
340
  it("should prioritize branches with worktree", () => {
@@ -628,8 +373,8 @@ describe("branchFormatter", () => {
628
373
 
629
374
  const results = formatBranchItems(branches, worktreeMap);
630
375
 
631
- expect(results[0].name).toBe("feature/with-worktree");
632
- expect(results[1].name).toBe("feature/no-worktree");
376
+ expect(results[0]!.name).toBe("feature/with-worktree");
377
+ expect(results[1]!.name).toBe("feature/no-worktree");
633
378
  });
634
379
 
635
380
  it("should sort branches with worktree by latest commit timestamp", () => {
@@ -685,8 +430,8 @@ describe("branchFormatter", () => {
685
430
 
686
431
  const results = formatBranchItems(branches, worktreeMap);
687
432
 
688
- expect(results[0].name).toBe("feature/recent");
689
- expect(results[1].name).toBe("feature/older");
433
+ expect(results[0]!.name).toBe("feature/recent");
434
+ expect(results[1]!.name).toBe("feature/older");
690
435
  });
691
436
 
692
437
  it("should prioritize local branches over remote branches", () => {
@@ -707,10 +452,10 @@ describe("branchFormatter", () => {
707
452
 
708
453
  const results = formatBranchItems(branches);
709
454
 
710
- expect(results[0].name).toBe("feature/local");
711
- expect(results[0].type).toBe("local");
712
- expect(results[1].name).toBe("origin/feature/remote");
713
- expect(results[1].type).toBe("remote");
455
+ expect(results[0]!.name).toBe("feature/local");
456
+ expect(results[0]!.type).toBe("local");
457
+ expect(results[1]!.name).toBe("origin/feature/remote");
458
+ expect(results[1]!.type).toBe("remote");
714
459
  });
715
460
 
716
461
  it("should sort by latest commit timestamp when worktree status matches", () => {
@@ -733,8 +478,8 @@ describe("branchFormatter", () => {
733
478
 
734
479
  const results = formatBranchItems(branches);
735
480
 
736
- expect(results[0].name).toBe("origin/feature/newer");
737
- expect(results[1].name).toBe("feature/local-older");
481
+ expect(results[0]!.name).toBe("origin/feature/newer");
482
+ expect(results[1]!.name).toBe("feature/local-older");
738
483
  });
739
484
 
740
485
  it("should apply all sorting rules in correct priority order", () => {
@@ -810,13 +555,13 @@ describe("branchFormatter", () => {
810
555
  // 4. Branches with worktree
811
556
  // 5. Local branches (alphabetically)
812
557
  // 6. Remote branches
813
- expect(results[0].name).toBe("feature/current");
814
- expect(results[1].name).toBe("main");
815
- expect(results[2].name).toBe("develop");
816
- expect(results[3].name).toBe("feature/with-worktree");
817
- expect(results[4].name).toBe("feature/a-local-no-worktree");
818
- expect(results[5].name).toBe("feature/z-local-no-worktree");
819
- expect(results[6].name).toBe("origin/feature/z-remote");
558
+ expect(results[0]!.name).toBe("feature/current");
559
+ expect(results[1]!.name).toBe("main");
560
+ expect(results[2]!.name).toBe("develop");
561
+ expect(results[3]!.name).toBe("feature/with-worktree");
562
+ expect(results[4]!.name).toBe("feature/a-local-no-worktree");
563
+ expect(results[5]!.name).toBe("feature/z-local-no-worktree");
564
+ expect(results[6]!.name).toBe("origin/feature/z-remote");
820
565
  });
821
566
 
822
567
  it("should handle release and hotfix branches without special priority", () => {
@@ -844,9 +589,9 @@ describe("branchFormatter", () => {
844
589
  const results = formatBranchItems(branches);
845
590
 
846
591
  // Should be sorted alphabetically (no special priority)
847
- expect(results[0].name).toBe("feature/test");
848
- expect(results[1].name).toBe("hotfix/urgent");
849
- expect(results[2].name).toBe("release/v1.0");
592
+ expect(results[0]!.name).toBe("feature/test");
593
+ expect(results[1]!.name).toBe("hotfix/urgent");
594
+ expect(results[2]!.name).toBe("release/v1.0");
850
595
  });
851
596
 
852
597
  it("should sort by latest activity time (max of git commit and tool usage)", () => {
@@ -886,8 +631,8 @@ describe("branchFormatter", () => {
886
631
  // Both have same latest activity time (1_800_000_000), so alphabetical
887
632
  // feature/git-newer: max(1_800_000_000, 1_700_000_000) = 1_800_000_000
888
633
  // feature/tool-newer: max(1_700_000_000, 1_800_000_000) = 1_800_000_000
889
- expect(results[0].name).toBe("feature/git-newer");
890
- expect(results[1].name).toBe("feature/tool-newer");
634
+ expect(results[0]!.name).toBe("feature/git-newer");
635
+ expect(results[1]!.name).toBe("feature/tool-newer");
891
636
  });
892
637
 
893
638
  it("should prioritize branch with tool usage over branch with only git commit when tool is newer", () => {
@@ -918,8 +663,8 @@ describe("branchFormatter", () => {
918
663
  const results = formatBranchItems(branches);
919
664
 
920
665
  // feature/with-tool has newer activity (tool usage at 1_800_000_000)
921
- expect(results[0].name).toBe("feature/with-tool");
922
- expect(results[1].name).toBe("feature/git-only");
666
+ expect(results[0]!.name).toBe("feature/with-tool");
667
+ expect(results[1]!.name).toBe("feature/git-only");
923
668
  });
924
669
 
925
670
  it("should prioritize branch with newer git commit over branch with older tool usage", () => {
@@ -950,8 +695,8 @@ describe("branchFormatter", () => {
950
695
  const results = formatBranchItems(branches);
951
696
 
952
697
  // feature/new-git has newer activity (git commit at 1_800_000_000)
953
- expect(results[0].name).toBe("feature/new-git");
954
- expect(results[1].name).toBe("feature/old-tool");
698
+ expect(results[0]!.name).toBe("feature/new-git");
699
+ expect(results[1]!.name).toBe("feature/old-tool");
955
700
  });
956
701
  });
957
702
  });
@@ -1,9 +1,9 @@
1
- import { describe, it, expect, vi } from "vitest";
1
+ import { describe, it, expect, mock } from "bun:test";
2
2
  import { copyToClipboard } from "../../utils/clipboard.js";
3
3
 
4
- const execaMock = vi.fn();
4
+ const execaMock = mock();
5
5
 
6
- vi.mock("execa", () => ({
6
+ mock.module("execa", () => ({
7
7
  execa: (...args: unknown[]) => execaMock(...args),
8
8
  }));
9
9
 
@@ -1,4 +1,4 @@
1
- import { describe, it, expect } from "vitest";
1
+ import { describe, it, expect } from "bun:test";
2
2
  import { calculateStatistics } from "../../utils/statisticsCalculator.js";
3
3
  import type { BranchInfo } from "../../types.js";
4
4
 
@@ -0,0 +1,36 @@
1
+ /** @jsxImportSource @opentui/solid */
2
+ import { TextAttributes } from "@opentui/core";
3
+
4
+ export interface FooterAction {
5
+ key: string;
6
+ description: string;
7
+ }
8
+
9
+ export interface FooterProps {
10
+ actions: FooterAction[];
11
+ separator?: string;
12
+ }
13
+
14
+ export function Footer({ actions, separator = " " }: FooterProps) {
15
+ if (actions.length === 0) {
16
+ return null;
17
+ }
18
+
19
+ return (
20
+ <box flexDirection="row">
21
+ {actions.map((action, index) => (
22
+ <>
23
+ <text attributes={TextAttributes.DIM}>[</text>
24
+ <text fg="cyan" attributes={TextAttributes.BOLD}>
25
+ {action.key}
26
+ </text>
27
+ <text attributes={TextAttributes.DIM}>]</text>
28
+ <text>{` ${action.description}`}</text>
29
+ {index < actions.length - 1 ? (
30
+ <text attributes={TextAttributes.DIM}>{separator}</text>
31
+ ) : null}
32
+ </>
33
+ ))}
34
+ </box>
35
+ );
36
+ }