@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,1478 +0,0 @@
1
- import React, {
2
- useCallback,
3
- useEffect,
4
- useMemo,
5
- useRef,
6
- useState,
7
- } from "react";
8
- import { useApp } from "ink";
9
- import { ErrorBoundary } from "./common/ErrorBoundary.js";
10
- import {
11
- BranchListScreen,
12
- type BranchListScreenProps,
13
- } from "./screens/BranchListScreen.js";
14
- import { LogListScreen } from "./screens/LogListScreen.js";
15
- import { LogDetailScreen } from "./screens/LogDetailScreen.js";
16
- import { LogDatePickerScreen } from "./screens/LogDatePickerScreen.js";
17
- import { BranchCreatorScreen } from "./screens/BranchCreatorScreen.js";
18
- import { BranchActionSelectorScreen } from "../screens/BranchActionSelectorScreen.js";
19
- import { CodingAgentSelectorScreen } from "./screens/CodingAgentSelectorScreen.js";
20
- import { ExecutionModeSelectorScreen } from "./screens/ExecutionModeSelectorScreen.js";
21
- import type { ExecutionMode } from "./screens/ExecutionModeSelectorScreen.js";
22
- import { BranchQuickStartScreen } from "./screens/BranchQuickStartScreen.js";
23
- import type { QuickStartAction } from "./screens/BranchQuickStartScreen.js";
24
- import {
25
- ModelSelectorScreen,
26
- type ModelSelectionResult,
27
- } from "./screens/ModelSelectorScreen.js";
28
- import { EnvironmentProfileScreen } from "./screens/EnvironmentProfileScreen.js";
29
- import { useGitData } from "../hooks/useGitData.js";
30
- import { useProfiles } from "../hooks/useProfiles.js";
31
- import { useScreenState } from "../hooks/useScreenState.js";
32
- import { useToolStatus } from "../hooks/useToolStatus.js";
33
- import { formatBranchItems } from "../utils/branchFormatter.js";
34
- import { calculateStatistics } from "../utils/statisticsCalculator.js";
35
- import { copyToClipboard } from "../utils/clipboard.js";
36
- import {
37
- parseLogLines,
38
- type FormattedLogEntry,
39
- } from "../../../logging/formatter.js";
40
- import {
41
- buildLogFilePath,
42
- getTodayLogDate,
43
- listRecentLogFiles,
44
- readLogFileLines,
45
- resolveLogDir,
46
- type LogFileInfo,
47
- } from "../../../logging/reader.js";
48
- import type {
49
- CodingAgentId,
50
- BranchInfo,
51
- BranchItem,
52
- CleanupTarget,
53
- InferenceLevel,
54
- SelectedBranchState,
55
- } from "../types.js";
56
- import { getRepositoryRoot, deleteBranch } from "../../../git.js";
57
- import { loadSession } from "../../../config/index.js";
58
- import {
59
- createWorktree,
60
- generateWorktreePath,
61
- isProtectedBranchName,
62
- removeWorktree,
63
- switchToProtectedBranch,
64
- } from "../../../worktree.js";
65
- import { getPackageVersion } from "../../../utils.js";
66
- import {
67
- resolveBaseBranchLabel,
68
- resolveBaseBranchRef,
69
- } from "../utils/baseBranch.js";
70
- import {
71
- getDefaultInferenceForModel,
72
- getDefaultModelOption,
73
- normalizeModelId,
74
- } from "../utils/modelOptions.js";
75
- import {
76
- resolveContinueSessionId,
77
- findLatestBranchSessionsByTool,
78
- } from "../utils/continueSession.js";
79
- import {
80
- findLatestCodexSession,
81
- findLatestCodexSessionId,
82
- findLatestClaudeSession,
83
- findLatestGeminiSession,
84
- findLatestOpenCodeSession,
85
- } from "../../../utils/session.js";
86
- import type { ToolSessionEntry } from "../../../config/index.js";
87
-
88
- const COMPLETION_HOLD_DURATION_MS = 3000;
89
- const PROTECTED_BRANCH_WARNING =
90
- "Root branches operate directly in the repository root. Create a new branch if you need a dedicated worktree.";
91
-
92
- export interface SelectionResult {
93
- branch: string; // Local branch name (without remote prefix)
94
- displayName: string; // Name that was selected in the UI (may include remote prefix)
95
- branchType: "local" | "remote";
96
- remoteBranch?: string; // Full remote ref when branchType === 'remote'
97
- tool: CodingAgentId;
98
- mode: ExecutionMode;
99
- skipPermissions: boolean;
100
- model?: string | null;
101
- inferenceLevel?: InferenceLevel;
102
- sessionId?: string | null;
103
- }
104
-
105
- export interface AppProps {
106
- onExit: (result?: SelectionResult) => void;
107
- loadingIndicatorDelay?: number;
108
- }
109
-
110
- /**
111
- * App - Top-level component for Ink.js UI
112
- * Integrates ErrorBoundary, data fetching, screen navigation, and all screens
113
- */
114
- export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
115
- const { exit } = useApp();
116
-
117
- // 起動ディレクトリの取得
118
- const workingDirectory = process.cwd();
119
-
120
- const { branches, worktrees, loading, error, refresh, lastUpdated } =
121
- useGitData({
122
- enableAutoRefresh: false, // Manual refresh with 'r' key
123
- });
124
- const { currentScreen, navigateTo, goBack } = useScreenState();
125
-
126
- // Profile state
127
- const { activeProfileName, refresh: refreshProfiles } = useProfiles();
128
-
129
- // Tool status state (FR-017: 起動時に検出してキャッシュ)
130
- const { tools: toolStatuses } = useToolStatus();
131
-
132
- // Version state
133
- const [version, setVersion] = useState<string | null>(null);
134
- const [repoRoot, setRepoRoot] = useState<string | null>(null);
135
- const [continueSessionId, setContinueSessionId] = useState<string | null>(
136
- null,
137
- );
138
- const [branchQuickStart, setBranchQuickStart] = useState<
139
- {
140
- toolId: CodingAgentId;
141
- toolLabel: string;
142
- model?: string | null;
143
- sessionId?: string | null;
144
- inferenceLevel?: InferenceLevel | null;
145
- skipPermissions?: boolean | null;
146
- timestamp?: number | null;
147
- }[]
148
- >([]);
149
- const [branchQuickStartLoading, setBranchQuickStartLoading] = useState(false);
150
-
151
- // Log viewer state
152
- const logDir = useMemo(
153
- () => resolveLogDir(workingDirectory),
154
- [workingDirectory],
155
- );
156
- const [logEntries, setLogEntries] = useState<FormattedLogEntry[]>([]);
157
- const [logLoading, setLogLoading] = useState(false);
158
- const [logError, setLogError] = useState<string | null>(null);
159
- const [logSelectedDate, setLogSelectedDate] = useState<string | null>(
160
- getTodayLogDate(),
161
- );
162
- const [logDates, setLogDates] = useState<LogFileInfo[]>([]);
163
- const [logSelectedEntry, setLogSelectedEntry] =
164
- useState<FormattedLogEntry | null>(null);
165
- const [logNotification, setLogNotification] = useState<{
166
- message: string;
167
- tone: "success" | "error";
168
- } | null>(null);
169
- const logNotificationTimerRef = useRef<NodeJS.Timeout | null>(null);
170
-
171
- // Selection state (for branch → tool → mode flow)
172
- const [selectedBranch, setSelectedBranch] =
173
- useState<SelectedBranchState | null>(null);
174
- const [creationSourceBranch, setCreationSourceBranch] =
175
- useState<SelectedBranchState | null>(null);
176
- const [selectedTool, setSelectedTool] = useState<CodingAgentId | null>(null);
177
- const [selectedModel, setSelectedModel] =
178
- useState<ModelSelectionResult | null>(null);
179
- const [lastModelByTool, setLastModelByTool] = useState<
180
- Record<CodingAgentId, ModelSelectionResult | undefined>
181
- >({});
182
- const [preferredToolId, setPreferredToolId] = useState<CodingAgentId | null>(
183
- null,
184
- );
185
-
186
- // PR cleanup feedback
187
- const [cleanupIndicators, setCleanupIndicators] = useState<
188
- Record<
189
- string,
190
- {
191
- icon: string;
192
- isSpinning?: boolean;
193
- color?: "cyan" | "green" | "yellow" | "red";
194
- }
195
- >
196
- >({});
197
- const [_cleanupProcessingBranch, setCleanupProcessingBranch] = useState<
198
- string | null
199
- >(null);
200
- const [cleanupInputLocked, setCleanupInputLocked] = useState(false);
201
- const [cleanupFooterMessage, setCleanupFooterMessage] = useState<{
202
- text: string;
203
- isSpinning?: boolean;
204
- color?: "cyan" | "green" | "yellow" | "red";
205
- } | null>(null);
206
- const [hiddenBranches, setHiddenBranches] = useState<string[]>([]);
207
- const [selectedBranches, setSelectedBranches] = useState<string[]>([]);
208
- const completionTimerRef = useRef<NodeJS.Timeout | null>(null);
209
-
210
- // Fetch version on mount
211
- useEffect(() => {
212
- getPackageVersion()
213
- .then(setVersion)
214
- .catch(() => setVersion(null));
215
- }, []);
216
-
217
- // Fetch repository root once for session lookups
218
- useEffect(() => {
219
- getRepositoryRoot()
220
- .then(setRepoRoot)
221
- .catch(() => setRepoRoot(null));
222
- }, []);
223
-
224
- const showLogNotification = useCallback(
225
- (message: string, tone: "success" | "error" = "success") => {
226
- setLogNotification({ message, tone });
227
- if (logNotificationTimerRef.current) {
228
- clearTimeout(logNotificationTimerRef.current);
229
- }
230
- logNotificationTimerRef.current = setTimeout(() => {
231
- setLogNotification(null);
232
- }, 2000);
233
- },
234
- [],
235
- );
236
-
237
- useEffect(() => {
238
- return () => {
239
- if (logNotificationTimerRef.current) {
240
- clearTimeout(logNotificationTimerRef.current);
241
- }
242
- };
243
- }, []);
244
-
245
- const loadLogEntries = useCallback(
246
- async (date: string | null) => {
247
- const targetDate = date ?? getTodayLogDate();
248
- setLogLoading(true);
249
- setLogError(null);
250
- try {
251
- const filePath = buildLogFilePath(logDir, targetDate);
252
- const lines = await readLogFileLines(filePath);
253
- const parsed = parseLogLines(lines, { limit: 100 });
254
- setLogEntries(parsed);
255
- } catch (error) {
256
- setLogEntries([]);
257
- setLogError(
258
- error instanceof Error ? error.message : "Failed to load logs",
259
- );
260
- } finally {
261
- setLogLoading(false);
262
- }
263
- },
264
- [logDir],
265
- );
266
-
267
- const loadLogDates = useCallback(async () => {
268
- try {
269
- const files = await listRecentLogFiles(logDir, 7);
270
- setLogDates(files);
271
- } catch {
272
- setLogDates([]);
273
- }
274
- }, [logDir]);
275
-
276
- useEffect(() => {
277
- if (currentScreen === "log-list") {
278
- void loadLogEntries(logSelectedDate);
279
- }
280
- }, [currentScreen, loadLogEntries, logSelectedDate]);
281
-
282
- useEffect(() => {
283
- if (currentScreen === "log-date-picker") {
284
- void loadLogDates();
285
- }
286
- }, [currentScreen, loadLogDates]);
287
-
288
- useEffect(() => {
289
- if (!hiddenBranches.length) {
290
- return;
291
- }
292
-
293
- const existing = new Set(branches.map((branch) => branch.name));
294
- const filtered = hiddenBranches.filter((name) => existing.has(name));
295
-
296
- if (filtered.length !== hiddenBranches.length) {
297
- setHiddenBranches(filtered);
298
- }
299
- }, [branches, hiddenBranches]);
300
-
301
- // Remove selections that no longer exist (hidden or disappeared)
302
- useEffect(() => {
303
- setSelectedBranches((prev) =>
304
- prev.filter(
305
- (name) =>
306
- branches.some((b) => b.name === name) &&
307
- !hiddenBranches.includes(name),
308
- ),
309
- );
310
- }, [branches, hiddenBranches]);
311
-
312
- // Load quick start options for selected branch (latest per tool)
313
- useEffect(() => {
314
- if (!selectedBranch) {
315
- setBranchQuickStart([]);
316
- return;
317
- }
318
- let cancelled = false;
319
- setBranchQuickStartLoading(true);
320
- (async () => {
321
- try {
322
- const root = repoRoot ?? (await getRepositoryRoot());
323
- if (!repoRoot && root) {
324
- setRepoRoot(root);
325
- }
326
- if (!root) {
327
- if (!cancelled) setBranchQuickStart([]);
328
- return;
329
- }
330
- const sessionData = await loadSession(root);
331
- const history = sessionData?.history ?? [];
332
-
333
- const combinedHistory = [...history];
334
- if (
335
- sessionData?.lastSessionId &&
336
- sessionData.lastBranch === selectedBranch.name &&
337
- sessionData.lastUsedTool
338
- ) {
339
- const synthetic: ToolSessionEntry = {
340
- branch: sessionData.lastBranch,
341
- worktreePath: sessionData.lastWorktreePath ?? null,
342
- toolId: sessionData.lastUsedTool,
343
- toolLabel: sessionData.toolLabel ?? sessionData.lastUsedTool,
344
- sessionId: sessionData.lastSessionId,
345
- mode: sessionData.mode ?? null,
346
- model: sessionData.model ?? null,
347
- reasoningLevel: sessionData.reasoningLevel ?? null,
348
- skipPermissions: sessionData.skipPermissions ?? null,
349
- timestamp: sessionData.timestamp ?? Date.now(),
350
- };
351
- combinedHistory.push(synthetic);
352
- }
353
- const latestPerTool = findLatestBranchSessionsByTool(
354
- combinedHistory,
355
- selectedBranch.name,
356
- selectedWorktreePath,
357
- );
358
-
359
- const mapped = await Promise.all(
360
- latestPerTool.map(async (entry) => {
361
- let sessionId = entry.sessionId ?? null;
362
- const worktree = selectedWorktreePath ?? workingDirectory;
363
-
364
- // For Codex, prefer a newer filesystem session over stale history
365
- if (!sessionId && entry.toolId === "codex-cli") {
366
- try {
367
- const historyTs = entry.timestamp ?? null;
368
- const latestCodex = await findLatestCodexSession({
369
- ...(historyTs
370
- ? {
371
- since: historyTs - 60_000,
372
- preferClosestTo: historyTs,
373
- windowMs: 60 * 60 * 1000,
374
- }
375
- : {}),
376
- cwd: worktree,
377
- });
378
- sessionId =
379
- latestCodex?.id ??
380
- (await findLatestCodexSessionId({ cwd: worktree })) ??
381
- null;
382
- } catch {
383
- // ignore lookup failure
384
- }
385
- }
386
-
387
- // For Claude Code, prefer the newest session file in the worktree even if history is stale.
388
- if (!sessionId && entry.toolId === "claude-code") {
389
- try {
390
- // Always resolve freshest on-disk session for this worktree (no window restriction)
391
- const latestAny = await findLatestClaudeSession(worktree);
392
- sessionId = latestAny?.id ?? null;
393
- } catch {
394
- // ignore lookup failure
395
- }
396
- }
397
-
398
- // For Gemini, prefer newest session file (Gemini keeps per-project chats)
399
- if (!sessionId && entry.toolId === "gemini-cli") {
400
- try {
401
- const gemOptions: Parameters<
402
- typeof findLatestGeminiSession
403
- >[0] = {
404
- windowMs: 60 * 60 * 1000,
405
- cwd: worktree,
406
- };
407
- if (entry.timestamp !== null && entry.timestamp !== undefined) {
408
- gemOptions.since = entry.timestamp - 60_000;
409
- gemOptions.preferClosestTo = entry.timestamp;
410
- }
411
- const gemSession = await findLatestGeminiSession(gemOptions);
412
- sessionId = gemSession?.id ?? null;
413
- } catch {
414
- // ignore
415
- }
416
- }
417
-
418
- // For OpenCode, prefer newest session file
419
- if (!sessionId && entry.toolId === "opencode") {
420
- try {
421
- const openCodeOptions: Parameters<
422
- typeof findLatestOpenCodeSession
423
- >[0] = {
424
- windowMs: 60 * 60 * 1000,
425
- cwd: worktree,
426
- };
427
- if (entry.timestamp !== null && entry.timestamp !== undefined) {
428
- openCodeOptions.since = entry.timestamp - 60_000;
429
- openCodeOptions.preferClosestTo = entry.timestamp;
430
- }
431
- const openCodeSession =
432
- await findLatestOpenCodeSession(openCodeOptions);
433
- sessionId = openCodeSession?.id ?? null;
434
- } catch {
435
- // ignore
436
- }
437
- }
438
-
439
- const normalizedModel = normalizeModelId(
440
- entry.toolId as CodingAgentId,
441
- entry.model ?? null,
442
- );
443
-
444
- return {
445
- toolId: entry.toolId as CodingAgentId,
446
- toolLabel: entry.toolLabel,
447
- model: normalizedModel ?? null,
448
- inferenceLevel: (entry.reasoningLevel ??
449
- sessionData?.reasoningLevel ??
450
- null) as InferenceLevel | null,
451
- sessionId,
452
- skipPermissions:
453
- entry.skipPermissions ?? sessionData?.skipPermissions ?? null,
454
- timestamp: entry.timestamp ?? null,
455
- };
456
- }),
457
- );
458
-
459
- if (!cancelled) {
460
- setBranchQuickStart(mapped);
461
- }
462
- } catch {
463
- if (!cancelled) setBranchQuickStart([]);
464
- } finally {
465
- if (!cancelled) setBranchQuickStartLoading(false);
466
- }
467
- })();
468
-
469
- return () => {
470
- cancelled = true;
471
- };
472
- }, [selectedBranch, repoRoot]);
473
-
474
- // Load last session ID for "Continue" label when entering execution mode selector
475
- useEffect(() => {
476
- if (currentScreen !== "execution-mode-selector") {
477
- return;
478
- }
479
- if (!selectedTool || !selectedBranch) {
480
- setContinueSessionId(null);
481
- return;
482
- }
483
- (async () => {
484
- try {
485
- const root = repoRoot ?? (await getRepositoryRoot());
486
- if (!repoRoot && root) {
487
- setRepoRoot(root);
488
- }
489
- const sessionData = root ? await loadSession(root) : null;
490
- const history = sessionData?.history ?? [];
491
-
492
- const found = await resolveContinueSessionId({
493
- history,
494
- sessionData,
495
- branch: selectedBranch.name,
496
- toolId: selectedTool,
497
- repoRoot: root,
498
- });
499
-
500
- setContinueSessionId(found ?? null);
501
- } catch {
502
- setContinueSessionId(null);
503
- }
504
- })();
505
- }, [currentScreen, selectedTool, selectedBranch, repoRoot]);
506
-
507
- // Update preferred tool when branch or data changes
508
- useEffect(() => {
509
- if (!selectedBranch) return;
510
- const branchMatch =
511
- branches.find((b) => b.name === selectedBranch.name) ||
512
- branches.find(
513
- (b) =>
514
- selectedBranch.branchType === "remote" &&
515
- b.name === selectedBranch.displayName,
516
- );
517
- setPreferredToolId(branchMatch?.lastToolUsage?.toolId ?? null);
518
- }, [branches, selectedBranch]);
519
-
520
- useEffect(
521
- () => () => {
522
- if (completionTimerRef.current) {
523
- clearTimeout(completionTimerRef.current);
524
- completionTimerRef.current = null;
525
- }
526
- },
527
- [],
528
- );
529
-
530
- const visibleBranches = useMemo(
531
- () => branches.filter((branch) => !hiddenBranches.includes(branch.name)),
532
- [branches, hiddenBranches],
533
- );
534
-
535
- const selectedWorktreePath = useMemo(() => {
536
- if (!selectedBranch) return null;
537
- const wt = worktrees.find((w) => w.branch === selectedBranch.name);
538
- return wt?.path ?? null;
539
- }, [selectedBranch, worktrees]);
540
-
541
- // Helper function to create content-based hash for branches
542
- const branchHash = useMemo(
543
- () =>
544
- visibleBranches
545
- .map((b) => `${b.name}-${b.type}-${b.isCurrent}`)
546
- .join(","),
547
- [visibleBranches],
548
- );
549
-
550
- // Helper function to create content-based hash for worktrees
551
- const worktreeHash = useMemo(
552
- () => worktrees.map((w) => `${w.branch}-${w.path}`).join(","),
553
- [worktrees],
554
- );
555
-
556
- // Format branches to BranchItems (memoized for performance with content-based dependencies)
557
- const branchItems: BranchItem[] = useMemo(() => {
558
- // Build worktreeMap for sorting
559
- const worktreeMap = new Map();
560
- for (const wt of worktrees) {
561
- worktreeMap.set(wt.branch, {
562
- path: wt.path,
563
- locked: false,
564
- prunable: wt.isAccessible === false,
565
- isAccessible: wt.isAccessible ?? true,
566
- ...(wt.hasUncommittedChanges !== undefined
567
- ? { hasUncommittedChanges: wt.hasUncommittedChanges }
568
- : {}),
569
- });
570
- }
571
- const baseItems = formatBranchItems(visibleBranches, worktreeMap);
572
- return baseItems.map((item) => {
573
- const hasUncommitted = item.worktree?.hasUncommittedChanges ?? false;
574
- const hasUnpushed = Boolean(item.hasUnpushedCommits);
575
- const isMerged = Boolean(item.mergedPR);
576
- const safeToCleanup =
577
- item.type === "local" && isMerged && !hasUncommitted && !hasUnpushed;
578
- return { ...item, safeToCleanup };
579
- });
580
- }, [branchHash, worktreeHash, visibleBranches, worktrees]);
581
-
582
- // Calculate statistics (memoized for performance)
583
- const stats = useMemo(
584
- () => calculateStatistics(visibleBranches),
585
- [visibleBranches],
586
- );
587
-
588
- const resolveBaseBranch = useCallback(() => {
589
- const localMain = branches.find(
590
- (branch) =>
591
- branch.type === "local" &&
592
- (branch.name === "main" || branch.name === "master"),
593
- );
594
- if (localMain) {
595
- return localMain.name;
596
- }
597
-
598
- const develop = branches.find(
599
- (branch) =>
600
- branch.type === "local" &&
601
- (branch.name === "develop" || branch.name === "dev"),
602
- );
603
- if (develop) {
604
- return develop.name;
605
- }
606
-
607
- return "main";
608
- }, [branches]);
609
-
610
- const baseBranchLabel = useMemo(
611
- () =>
612
- resolveBaseBranchLabel(
613
- creationSourceBranch,
614
- selectedBranch,
615
- resolveBaseBranch,
616
- ),
617
- [creationSourceBranch, resolveBaseBranch, selectedBranch],
618
- );
619
-
620
- // Handle branch selection
621
- const toLocalBranchName = useCallback((remoteName: string) => {
622
- const segments = remoteName.split("/");
623
- if (segments.length <= 1) {
624
- return remoteName;
625
- }
626
- return segments.slice(1).join("/");
627
- }, []);
628
-
629
- const inferBranchCategory = useCallback(
630
- (branchName: string): BranchInfo["branchType"] => {
631
- const matched = branches.find((branch) => branch.name === branchName);
632
- if (matched) {
633
- return matched.branchType;
634
- }
635
- if (branchName === "main" || branchName === "master") {
636
- return "main";
637
- }
638
- if (branchName === "develop" || branchName === "dev") {
639
- return "develop";
640
- }
641
- if (branchName.startsWith("feature/")) {
642
- return "feature";
643
- }
644
- if (branchName.startsWith("hotfix/")) {
645
- return "hotfix";
646
- }
647
- if (branchName.startsWith("release/")) {
648
- return "release";
649
- }
650
- return "other";
651
- },
652
- [branches],
653
- );
654
-
655
- const isProtectedSelection = useCallback(
656
- (branch: SelectedBranchState | null): boolean => {
657
- if (!branch) {
658
- return false;
659
- }
660
- return (
661
- isProtectedBranchName(branch.name) ||
662
- isProtectedBranchName(branch.displayName) ||
663
- (branch.remoteBranch
664
- ? isProtectedBranchName(branch.remoteBranch)
665
- : false) ||
666
- branch.branchCategory === "main" ||
667
- branch.branchCategory === "develop"
668
- );
669
- },
670
- [isProtectedBranchName],
671
- );
672
-
673
- const toggleBranchSelection = useCallback(
674
- (branchName: string) => {
675
- const branch = branches.find((b) => b.name === branchName);
676
- if (!branch || branch.type === "remote") {
677
- return;
678
- }
679
- if (
680
- isProtectedBranchName(branch.name) ||
681
- branch.branchType === "main" ||
682
- branch.branchType === "develop"
683
- ) {
684
- return;
685
- }
686
- setSelectedBranches((prev) => {
687
- const set = new Set(prev);
688
- if (set.has(branchName)) {
689
- set.delete(branchName);
690
- } else {
691
- set.add(branchName);
692
- }
693
- return Array.from(set);
694
- });
695
- },
696
- [branches, isProtectedBranchName],
697
- );
698
-
699
- const protectedBranchInfo = useMemo(() => {
700
- if (!selectedBranch) {
701
- return null;
702
- }
703
- if (!isProtectedSelection(selectedBranch)) {
704
- return null;
705
- }
706
- const label = selectedBranch.displayName ?? selectedBranch.name;
707
- return {
708
- label,
709
- message: `${label} is a root branch. Switch within the repository root instead of creating a worktree.`,
710
- };
711
- }, [selectedBranch, isProtectedSelection]);
712
-
713
- const handleSelect = useCallback(
714
- (item: BranchItem) => {
715
- const selection: SelectedBranchState =
716
- item.type === "remote"
717
- ? {
718
- name: toLocalBranchName(item.name),
719
- displayName: item.name,
720
- branchType: "remote",
721
- branchCategory: item.branchType,
722
- remoteBranch: item.name,
723
- }
724
- : {
725
- name: item.name,
726
- displayName: item.name,
727
- branchType: "local",
728
- branchCategory: item.branchType,
729
- };
730
-
731
- const protectedSelected = isProtectedSelection(selection);
732
-
733
- setSelectedBranch(selection);
734
- setSelectedTool(null);
735
- setSelectedModel(null);
736
- setCreationSourceBranch(null);
737
- setPreferredToolId(item.lastToolUsage?.toolId ?? null);
738
-
739
- if (protectedSelected) {
740
- setCleanupFooterMessage({
741
- text: PROTECTED_BRANCH_WARNING,
742
- color: "yellow",
743
- });
744
- } else {
745
- setCleanupFooterMessage(null);
746
- }
747
-
748
- navigateTo("branch-action-selector");
749
- },
750
- [
751
- isProtectedSelection,
752
- navigateTo,
753
- setCleanupFooterMessage,
754
- setCreationSourceBranch,
755
- setSelectedTool,
756
- toLocalBranchName,
757
- ],
758
- );
759
-
760
- // Handle branch action selection
761
- const handleProtectedBranchSwitch = useCallback(async () => {
762
- if (!selectedBranch) {
763
- return;
764
- }
765
-
766
- try {
767
- setCleanupFooterMessage({
768
- text: `Preparing root branch '${selectedBranch.displayName ?? selectedBranch.name}'...`,
769
- color: "cyan",
770
- });
771
- const repoRoot = await getRepositoryRoot();
772
- const remoteRef =
773
- selectedBranch.remoteBranch ??
774
- (selectedBranch.branchType === "remote"
775
- ? (selectedBranch.displayName ?? selectedBranch.name)
776
- : null);
777
-
778
- const result = await switchToProtectedBranch({
779
- branchName: selectedBranch.name,
780
- repoRoot,
781
- remoteRef: remoteRef ?? null,
782
- });
783
-
784
- let successMessage = `'${selectedBranch.displayName ?? selectedBranch.name}' will use the repository root.`;
785
- if (result === "remote") {
786
- successMessage = `Created a local tracking branch for '${selectedBranch.displayName ?? selectedBranch.name}' and switched to the protected branch.`;
787
- } else if (result === "local") {
788
- successMessage = `Checked out '${selectedBranch.displayName ?? selectedBranch.name}' in the repository root.`;
789
- }
790
-
791
- setCleanupFooterMessage({
792
- text: successMessage,
793
- color: "green",
794
- });
795
- refresh();
796
- const nextScreen =
797
- branchQuickStart.length || branchQuickStartLoading
798
- ? "branch-quick-start"
799
- : "coding-agent-selector";
800
- navigateTo(nextScreen);
801
- } catch (error) {
802
- const message = error instanceof Error ? error.message : String(error);
803
- setCleanupFooterMessage({
804
- text: `Failed to switch root branch: ${message}`,
805
- color: "red",
806
- });
807
- console.error("Failed to switch protected branch:", error);
808
- }
809
- }, [
810
- branchQuickStart,
811
- branchQuickStartLoading,
812
- navigateTo,
813
- refresh,
814
- selectedBranch,
815
- setCleanupFooterMessage,
816
- ]);
817
-
818
- const handleUseExistingBranch = useCallback(() => {
819
- if (selectedBranch && isProtectedSelection(selectedBranch)) {
820
- void handleProtectedBranchSwitch();
821
- return;
822
- }
823
- if (branchQuickStart.length) {
824
- navigateTo("branch-quick-start");
825
- } else {
826
- navigateTo("coding-agent-selector");
827
- }
828
- }, [
829
- handleProtectedBranchSwitch,
830
- isProtectedSelection,
831
- navigateTo,
832
- branchQuickStart.length,
833
- selectedBranch,
834
- ]);
835
-
836
- const handleCreateNewBranch = useCallback(() => {
837
- setCreationSourceBranch(selectedBranch);
838
- navigateTo("branch-creator");
839
- }, [navigateTo, selectedBranch]);
840
-
841
- // Handle quit
842
- const handleQuit = useCallback(() => {
843
- onExit();
844
- exit();
845
- }, [onExit, exit]);
846
-
847
- const handleOpenLogs = useCallback(() => {
848
- setLogSelectedDate(getTodayLogDate());
849
- setLogSelectedEntry(null);
850
- navigateTo("log-list");
851
- }, [navigateTo]);
852
-
853
- const handleSelectLogEntry = useCallback(
854
- (entry: FormattedLogEntry) => {
855
- setLogSelectedEntry(entry);
856
- navigateTo("log-detail");
857
- },
858
- [navigateTo],
859
- );
860
-
861
- const handleCopyLogEntry = useCallback(
862
- async (entry: FormattedLogEntry) => {
863
- try {
864
- await copyToClipboard(entry.json);
865
- showLogNotification("Copied to clipboard.", "success");
866
- } catch {
867
- showLogNotification("Failed to copy to clipboard.", "error");
868
- }
869
- },
870
- [showLogNotification],
871
- );
872
-
873
- const handleOpenLogDates = useCallback(() => {
874
- navigateTo("log-date-picker");
875
- }, [navigateTo]);
876
-
877
- const handleSelectLogDate = useCallback(
878
- (date: string) => {
879
- setLogSelectedDate(date);
880
- setLogSelectedEntry(null);
881
- navigateTo("log-list");
882
- },
883
- [navigateTo],
884
- );
885
-
886
- // Handle branch creation
887
- const handleCreate = useCallback(
888
- async (branchName: string) => {
889
- try {
890
- const repoRoot = await getRepositoryRoot();
891
- const worktreePath = await generateWorktreePath(repoRoot, branchName);
892
- // Use selectedBranch as base if available, otherwise resolve from repo
893
- const baseBranch = resolveBaseBranchRef(
894
- creationSourceBranch,
895
- selectedBranch,
896
- resolveBaseBranch,
897
- );
898
-
899
- await createWorktree({
900
- branchName,
901
- worktreePath,
902
- repoRoot,
903
- isNewBranch: true,
904
- baseBranch,
905
- });
906
-
907
- refresh();
908
- setCreationSourceBranch(null);
909
- setSelectedBranch({
910
- name: branchName,
911
- displayName: branchName,
912
- branchType: "local",
913
- branchCategory: inferBranchCategory(branchName),
914
- });
915
- setSelectedTool(null);
916
- setSelectedModel(null);
917
- setPreferredToolId(null);
918
- setCleanupFooterMessage(null);
919
-
920
- navigateTo("coding-agent-selector");
921
- } catch (error) {
922
- // On error, go back to branch list
923
- console.error("Failed to create branch:", error);
924
- goBack();
925
- refresh();
926
- }
927
- },
928
- [
929
- navigateTo,
930
- goBack,
931
- refresh,
932
- resolveBaseBranch,
933
- selectedBranch,
934
- creationSourceBranch,
935
- inferBranchCategory,
936
- setCleanupFooterMessage,
937
- ],
938
- );
939
-
940
- const handleCleanupCommand = useCallback(async () => {
941
- if (cleanupInputLocked) {
942
- return;
943
- }
944
-
945
- if (completionTimerRef.current) {
946
- clearTimeout(completionTimerRef.current);
947
- completionTimerRef.current = null;
948
- }
949
-
950
- if (selectedBranches.length === 0) {
951
- setCleanupIndicators({});
952
- setCleanupFooterMessage({
953
- text: "No cleanup targets selected.",
954
- color: "yellow",
955
- });
956
- setCleanupInputLocked(false);
957
- completionTimerRef.current = setTimeout(() => {
958
- setCleanupFooterMessage(null);
959
- completionTimerRef.current = null;
960
- }, COMPLETION_HOLD_DURATION_MS);
961
- return;
962
- }
963
-
964
- const succeededBranches: string[] = [];
965
-
966
- const resetAfterWait = () => {
967
- setCleanupIndicators({});
968
- setCleanupInputLocked(false);
969
- setCleanupFooterMessage(null);
970
- if (succeededBranches.length > 0) {
971
- setHiddenBranches((prev) => {
972
- const merged = new Set(prev);
973
- succeededBranches.forEach((branch) => merged.add(branch));
974
- return Array.from(merged);
975
- });
976
- setSelectedBranches((prev) =>
977
- prev.filter((name) => !succeededBranches.includes(name)),
978
- );
979
- }
980
- refresh();
981
- completionTimerRef.current = null;
982
- };
983
-
984
- // Provide immediate feedback before fetching targets
985
- setCleanupInputLocked(true);
986
- setCleanupIndicators({});
987
- setCleanupFooterMessage({
988
- text: "Processing...",
989
- isSpinning: true,
990
- color: "cyan",
991
- });
992
- setCleanupProcessingBranch(null);
993
-
994
- const branchMap = new Map(branches.map((branch) => [branch.name, branch]));
995
- const worktreeMap = new Map(
996
- worktrees.map((worktree) => [worktree.branch, worktree]),
997
- );
998
- const targets = selectedBranches.reduce<CleanupTarget[]>((acc, name) => {
999
- const branch = branchMap.get(name);
1000
- if (!branch || branch.type === "remote") {
1001
- return acc;
1002
- }
1003
- if (
1004
- isProtectedBranchName(branch.name) ||
1005
- branch.branchType === "main" ||
1006
- branch.branchType === "develop"
1007
- ) {
1008
- return acc;
1009
- }
1010
-
1011
- const worktree = worktreeMap.get(branch.name);
1012
- const hasRemoteBranch =
1013
- typeof branch.hasRemoteCounterpart === "boolean"
1014
- ? branch.hasRemoteCounterpart
1015
- : undefined;
1016
- const isAccessible =
1017
- typeof worktree?.isAccessible === "boolean"
1018
- ? worktree.isAccessible
1019
- : undefined;
1020
- acc.push({
1021
- branch: branch.name,
1022
- pullRequest: null,
1023
- worktreePath: worktree?.path ?? null,
1024
- cleanupType: worktree ? "worktree-and-branch" : "branch-only",
1025
- hasUncommittedChanges: worktree?.hasUncommittedChanges ?? false,
1026
- hasUnpushedCommits: Boolean(branch.hasUnpushedCommits),
1027
- ...(hasRemoteBranch !== undefined ? { hasRemoteBranch } : {}),
1028
- ...(isAccessible !== undefined ? { isAccessible } : {}),
1029
- });
1030
- return acc;
1031
- }, []);
1032
-
1033
- if (targets.length === 0) {
1034
- setCleanupIndicators({});
1035
- setCleanupFooterMessage({
1036
- text: "⚠️ No cleanup candidates among selected branches.",
1037
- color: "yellow",
1038
- });
1039
- setCleanupInputLocked(false);
1040
- completionTimerRef.current = setTimeout(() => {
1041
- setCleanupFooterMessage(null);
1042
- completionTimerRef.current = null;
1043
- }, COMPLETION_HOLD_DURATION_MS);
1044
- return;
1045
- }
1046
-
1047
- // Reset hidden branches that may already be gone
1048
- setHiddenBranches((prev) =>
1049
- prev.filter(
1050
- (name) => targets.find((t) => t.branch === name) === undefined,
1051
- ),
1052
- );
1053
-
1054
- const initialIndicators = targets.reduce<
1055
- Record<
1056
- string,
1057
- {
1058
- icon: string;
1059
- isSpinning?: boolean;
1060
- color?: "cyan" | "green" | "yellow" | "red";
1061
- }
1062
- >
1063
- >((acc, target, index) => {
1064
- if (index === 0) {
1065
- acc[target.branch] = { icon: "", isSpinning: true, color: "cyan" };
1066
- } else {
1067
- acc[target.branch] = { icon: "⏳", color: "yellow" };
1068
- }
1069
- return acc;
1070
- }, {});
1071
-
1072
- setCleanupIndicators(initialIndicators);
1073
- const firstTarget = targets.length > 0 ? targets[0] : undefined;
1074
- setCleanupProcessingBranch(firstTarget ? firstTarget.branch : null);
1075
- setCleanupFooterMessage({
1076
- text: "Processing...",
1077
- isSpinning: true,
1078
- color: "cyan",
1079
- });
1080
-
1081
- for (let index = 0; index < targets.length; index += 1) {
1082
- const currentTarget = targets[index];
1083
- if (!currentTarget) {
1084
- continue;
1085
- }
1086
- const target = currentTarget;
1087
-
1088
- setCleanupProcessingBranch(target.branch);
1089
-
1090
- setCleanupIndicators((prev) => {
1091
- const updated = { ...prev };
1092
- updated[target.branch] = { icon: "", isSpinning: true, color: "cyan" };
1093
- for (const pending of targets.slice(index + 1)) {
1094
- const current = updated[pending.branch];
1095
- if (!current || current.icon !== "⏳") {
1096
- updated[pending.branch] = { icon: "⏳", color: "yellow" };
1097
- }
1098
- }
1099
- return updated;
1100
- });
1101
-
1102
- const shouldSkip =
1103
- target.hasUncommittedChanges ||
1104
- target.hasUnpushedCommits ||
1105
- (target.cleanupType === "worktree-and-branch" &&
1106
- (!target.worktreePath || target.isAccessible === false));
1107
-
1108
- if (shouldSkip) {
1109
- setCleanupIndicators((prev) => ({
1110
- ...prev,
1111
- [target.branch]: { icon: "⏭️", color: "yellow" },
1112
- }));
1113
- setCleanupProcessingBranch(null);
1114
- continue;
1115
- }
1116
-
1117
- try {
1118
- if (
1119
- target.cleanupType === "worktree-and-branch" &&
1120
- target.worktreePath
1121
- ) {
1122
- await removeWorktree(target.worktreePath, true);
1123
- }
1124
-
1125
- await deleteBranch(target.branch, true);
1126
-
1127
- // 自動クリーンアップではリモートブランチは削除しない
1128
- // リモートブランチはユーザーが明示的に削除する必要がある
1129
-
1130
- succeededBranches.push(target.branch);
1131
- setCleanupIndicators((prev) => ({
1132
- ...prev,
1133
- [target.branch]: { icon: "✅", color: "green" },
1134
- }));
1135
- } catch {
1136
- const icon = "❌";
1137
- setCleanupIndicators((prev) => ({
1138
- ...prev,
1139
- [target.branch]: { icon, color: "red" },
1140
- }));
1141
- }
1142
-
1143
- setCleanupProcessingBranch(null);
1144
- }
1145
-
1146
- setCleanupProcessingBranch(null);
1147
- setCleanupInputLocked(false);
1148
- setCleanupFooterMessage({
1149
- text: "Cleanup completed. Finalizing...",
1150
- color: "green",
1151
- });
1152
-
1153
- const holdDuration =
1154
- typeof process !== "undefined" && process.env?.NODE_ENV === "test"
1155
- ? 0
1156
- : COMPLETION_HOLD_DURATION_MS;
1157
-
1158
- completionTimerRef.current = setTimeout(resetAfterWait, holdDuration);
1159
- }, [
1160
- cleanupInputLocked,
1161
- branches,
1162
- deleteBranch,
1163
- refresh,
1164
- removeWorktree,
1165
- selectedBranches,
1166
- worktrees,
1167
- ]);
1168
-
1169
- // Handle AI tool selection
1170
- const handleToolSelect = useCallback(
1171
- (tool: CodingAgentId) => {
1172
- setSelectedTool(tool);
1173
- setSelectedModel(lastModelByTool[tool] ?? null);
1174
- navigateTo("model-selector");
1175
- },
1176
- [lastModelByTool, navigateTo],
1177
- );
1178
-
1179
- const handleModelSelect = useCallback(
1180
- (selection: ModelSelectionResult) => {
1181
- setSelectedModel(selection);
1182
- setLastModelByTool((prev) => ({
1183
- ...prev,
1184
- ...(selectedTool ? { [selectedTool]: selection } : {}),
1185
- }));
1186
- navigateTo("execution-mode-selector");
1187
- },
1188
- [navigateTo, selectedTool],
1189
- );
1190
-
1191
- const completeSelection = useCallback(
1192
- (
1193
- executionMode: ExecutionMode,
1194
- skip: boolean,
1195
- sessionId?: string | null,
1196
- ) => {
1197
- if (selectedBranch && selectedTool) {
1198
- const defaultModel = getDefaultModelOption(selectedTool);
1199
- const resolvedModel = selectedModel?.model ?? defaultModel?.id ?? null;
1200
- const normalizedModel = normalizeModelId(selectedTool, resolvedModel);
1201
- const resolvedInference =
1202
- selectedModel?.inferenceLevel ??
1203
- getDefaultInferenceForModel(defaultModel ?? undefined);
1204
-
1205
- const payload: SelectionResult = {
1206
- branch: selectedBranch.name,
1207
- displayName: selectedBranch.displayName,
1208
- branchType: selectedBranch.branchType,
1209
- tool: selectedTool,
1210
- mode: executionMode,
1211
- skipPermissions: skip,
1212
- ...(normalizedModel !== undefined ? { model: normalizedModel } : {}),
1213
- ...(resolvedInference !== undefined
1214
- ? { inferenceLevel: resolvedInference }
1215
- : {}),
1216
- ...(selectedBranch.remoteBranch
1217
- ? { remoteBranch: selectedBranch.remoteBranch }
1218
- : {}),
1219
- ...(sessionId ? { sessionId } : {}),
1220
- };
1221
-
1222
- onExit(payload);
1223
- exit();
1224
- }
1225
- },
1226
- [
1227
- selectedBranch,
1228
- selectedTool,
1229
- selectedModel,
1230
- onExit,
1231
- exit,
1232
- getDefaultModelOption,
1233
- getDefaultInferenceForModel,
1234
- ],
1235
- );
1236
-
1237
- const handleQuickStartSelect = useCallback(
1238
- (action: QuickStartAction, toolId?: CodingAgentId | null) => {
1239
- if (action === "manual" || !branchQuickStart.length) {
1240
- navigateTo("coding-agent-selector");
1241
- return;
1242
- }
1243
-
1244
- const selected =
1245
- branchQuickStart.find((opt) => opt.toolId === toolId) ??
1246
- branchQuickStart[0];
1247
- if (!selected) {
1248
- navigateTo("coding-agent-selector");
1249
- return;
1250
- }
1251
-
1252
- setSelectedTool(selected.toolId);
1253
- setPreferredToolId(selected.toolId);
1254
- const normalizedQuickStartModel = normalizeModelId(
1255
- selected.toolId as CodingAgentId,
1256
- selected.model ?? null,
1257
- );
1258
- setSelectedModel(
1259
- normalizedQuickStartModel
1260
- ? ({
1261
- model: normalizedQuickStartModel,
1262
- inferenceLevel: selected.inferenceLevel ?? undefined,
1263
- } as ModelSelectionResult)
1264
- : null,
1265
- );
1266
-
1267
- const skip = selected.skipPermissions ?? false;
1268
-
1269
- if (action === "reuse-continue") {
1270
- const hasSession = Boolean(selected.sessionId);
1271
- const mode: ExecutionMode = hasSession ? "resume" : "continue";
1272
- completeSelection(mode, skip, selected.sessionId ?? null);
1273
- return;
1274
- }
1275
-
1276
- // "Start new with previous settings" skips the execution mode screen and launches immediately
1277
- completeSelection("normal", skip, null);
1278
- },
1279
- [
1280
- branchQuickStart,
1281
- navigateTo,
1282
- setPreferredToolId,
1283
- setSelectedModel,
1284
- setSelectedTool,
1285
- completeSelection,
1286
- ],
1287
- );
1288
-
1289
- // Handle execution mode and skipPermissions selection
1290
- const handleModeSelect = useCallback(
1291
- (result: { mode: ExecutionMode; skipPermissions: boolean }) => {
1292
- completeSelection(result.mode, result.skipPermissions, null);
1293
- },
1294
- [completeSelection],
1295
- );
1296
-
1297
- // Render screen based on currentScreen
1298
- const renderScreen = () => {
1299
- const renderBranchListScreen = (
1300
- additionalProps?: Partial<BranchListScreenProps>,
1301
- ) => (
1302
- <BranchListScreen
1303
- branches={branchItems}
1304
- stats={stats}
1305
- onSelect={handleSelect}
1306
- onQuit={handleQuit}
1307
- onRefresh={refresh}
1308
- loading={loading}
1309
- error={error}
1310
- lastUpdated={lastUpdated}
1311
- loadingIndicatorDelay={loadingIndicatorDelay}
1312
- version={version}
1313
- workingDirectory={workingDirectory}
1314
- activeProfile={activeProfileName}
1315
- onOpenProfiles={() => navigateTo("environment-profile")}
1316
- onOpenLogs={handleOpenLogs}
1317
- toolStatuses={toolStatuses}
1318
- {...additionalProps}
1319
- />
1320
- );
1321
-
1322
- switch (currentScreen) {
1323
- case "branch-list":
1324
- return renderBranchListScreen({
1325
- onCleanupCommand: handleCleanupCommand,
1326
- cleanupUI: {
1327
- indicators: cleanupIndicators,
1328
- footerMessage: cleanupFooterMessage,
1329
- inputLocked: cleanupInputLocked,
1330
- },
1331
- selectedBranches,
1332
- onToggleSelect: toggleBranchSelection,
1333
- });
1334
-
1335
- case "log-list":
1336
- return (
1337
- <LogListScreen
1338
- entries={logEntries}
1339
- loading={logLoading}
1340
- error={logError}
1341
- onBack={goBack}
1342
- onSelect={handleSelectLogEntry}
1343
- onCopy={handleCopyLogEntry}
1344
- onPickDate={handleOpenLogDates}
1345
- notification={logNotification}
1346
- version={version}
1347
- selectedDate={logSelectedDate}
1348
- />
1349
- );
1350
-
1351
- case "log-detail":
1352
- return (
1353
- <LogDetailScreen
1354
- entry={logSelectedEntry}
1355
- onBack={goBack}
1356
- onCopy={handleCopyLogEntry}
1357
- notification={logNotification}
1358
- version={version}
1359
- />
1360
- );
1361
-
1362
- case "log-date-picker":
1363
- return (
1364
- <LogDatePickerScreen
1365
- dates={logDates}
1366
- onBack={goBack}
1367
- onSelect={handleSelectLogDate}
1368
- version={version}
1369
- />
1370
- );
1371
-
1372
- case "branch-creator":
1373
- return (
1374
- <BranchCreatorScreen
1375
- onBack={goBack}
1376
- onCreate={handleCreate}
1377
- baseBranch={baseBranchLabel}
1378
- version={version}
1379
- />
1380
- );
1381
-
1382
- case "branch-action-selector": {
1383
- const isProtected = Boolean(protectedBranchInfo);
1384
- const baseProps = {
1385
- selectedBranch: selectedBranch?.displayName ?? "",
1386
- onUseExisting: handleUseExistingBranch,
1387
- onCreateNew: handleCreateNewBranch,
1388
- onBack: goBack,
1389
- canCreateNew: Boolean(selectedBranch),
1390
- };
1391
-
1392
- if (isProtected) {
1393
- return (
1394
- <BranchActionSelectorScreen
1395
- {...baseProps}
1396
- mode="protected"
1397
- infoMessage={protectedBranchInfo?.message ?? null}
1398
- primaryLabel="Use root branch (no worktree)"
1399
- secondaryLabel="Create new branch from this branch"
1400
- />
1401
- );
1402
- }
1403
-
1404
- return <BranchActionSelectorScreen {...baseProps} />;
1405
- }
1406
-
1407
- case "branch-quick-start":
1408
- return (
1409
- <BranchQuickStartScreen
1410
- branchName={selectedBranch?.displayName ?? ""}
1411
- previousOptions={branchQuickStart.map((opt) => ({
1412
- toolId: opt.toolId,
1413
- toolLabel: opt.toolLabel,
1414
- model: opt.model ?? null,
1415
- inferenceLevel: opt.inferenceLevel ?? null,
1416
- skipPermissions: opt.skipPermissions ?? null,
1417
- sessionId: opt.sessionId ?? null,
1418
- }))}
1419
- loading={branchQuickStartLoading}
1420
- onBack={goBack}
1421
- onSelect={handleQuickStartSelect}
1422
- version={version}
1423
- />
1424
- );
1425
-
1426
- case "coding-agent-selector":
1427
- return (
1428
- <CodingAgentSelectorScreen
1429
- onBack={goBack}
1430
- onSelect={handleToolSelect}
1431
- version={version}
1432
- initialAgentId={selectedTool ?? preferredToolId ?? null}
1433
- />
1434
- );
1435
-
1436
- case "model-selector":
1437
- if (!selectedTool) {
1438
- goBack();
1439
- return null;
1440
- }
1441
- return (
1442
- <ModelSelectorScreen
1443
- tool={selectedTool}
1444
- onBack={goBack}
1445
- onSelect={handleModelSelect}
1446
- version={version}
1447
- initialSelection={selectedModel}
1448
- />
1449
- );
1450
-
1451
- case "execution-mode-selector":
1452
- return (
1453
- <ExecutionModeSelectorScreen
1454
- onBack={goBack}
1455
- onSelect={handleModeSelect}
1456
- version={version}
1457
- continueSessionId={continueSessionId}
1458
- />
1459
- );
1460
-
1461
- case "environment-profile":
1462
- return (
1463
- <EnvironmentProfileScreen
1464
- onBack={() => {
1465
- void refreshProfiles();
1466
- goBack();
1467
- }}
1468
- version={version}
1469
- />
1470
- );
1471
-
1472
- default:
1473
- return renderBranchListScreen();
1474
- }
1475
- };
1476
-
1477
- return <ErrorBoundary>{renderScreen()}</ErrorBoundary>;
1478
- }