@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
@@ -0,0 +1,1395 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@opentui/solid/jsx-runtime";
2
+ /** @jsxImportSource @opentui/solid */
3
+ import { useKeyboard, useRenderer } from "@opentui/solid";
4
+ import { batch, createEffect, createMemo, createSignal, onCleanup, onMount, } from "solid-js";
5
+ import { BranchListScreen } from "./screens/solid/BranchListScreen.js";
6
+ import { HelpOverlay } from "./components/solid/HelpOverlay.js";
7
+ import { WizardController, } from "./components/solid/WizardController.js";
8
+ import { SelectorScreen, } from "./screens/solid/SelectorScreen.js";
9
+ import { LogScreen } from "./screens/solid/LogScreen.js";
10
+ import { LogDetailScreen } from "./screens/solid/LogDetailScreen.js";
11
+ import { ErrorScreen } from "./screens/solid/ErrorScreen.js";
12
+ import { LoadingIndicatorScreen } from "./screens/solid/LoadingIndicator.js";
13
+ import { WorktreeCreateScreen } from "./screens/solid/WorktreeCreateScreen.js";
14
+ import { InputScreen } from "./screens/solid/InputScreen.js";
15
+ import { ConfirmScreen } from "./screens/solid/ConfirmScreen.js";
16
+ import { useTerminalSize } from "./hooks/solid/useTerminalSize.js";
17
+ import { EnvironmentScreen } from "./screens/solid/EnvironmentScreen.js";
18
+ import { ProfileScreen } from "./screens/solid/ProfileScreen.js";
19
+ import { ProfileEnvScreen } from "./screens/solid/ProfileEnvScreen.js";
20
+ import { calculateStatistics } from "./utils/statisticsCalculator.js";
21
+ import { formatBranchItems } from "./utils/branchFormatter.js";
22
+ import { createLogger } from "../../logging/logger.js";
23
+ const logger = createLogger({ category: "app" });
24
+ import { getDefaultInferenceForModel, getDefaultModelOption, normalizeModelId, } from "./utils/modelOptions.js";
25
+ import { resolveBaseBranchLabel, resolveBaseBranchRef, } from "./utils/baseBranch.js";
26
+ import { getAllBranches, getCurrentBranch, getLocalBranches, getRepositoryRoot, deleteBranch, } from "../../git.js";
27
+ import { isProtectedBranchName, getCleanupStatus, listAdditionalWorktrees, removeWorktree, repairWorktrees, } from "../../worktree.js";
28
+ import { getConfig, getLastToolUsageMap, loadSession, } from "../../config/index.js";
29
+ import { findLatestBranchSessionsByTool, refreshQuickStartEntries, } from "./utils/continueSession.js";
30
+ import { getAllCodingAgents } from "../../config/tools.js";
31
+ import { clearLogFiles, getTodayLogDate, readLogLinesForDate, resolveLogTarget, } from "../../logging/reader.js";
32
+ import { parseLogLines } from "../../logging/formatter.js";
33
+ import { copyToClipboard } from "./utils/clipboard.js";
34
+ import { getPackageVersion } from "../../utils.js";
35
+ import { createProfile, deleteProfile, loadProfiles, setActiveProfile, updateProfile, } from "../../config/profiles.js";
36
+ import { isValidProfileName, } from "../../types/profiles.js";
37
+ import { BRANCH_PREFIXES } from "../../config/constants.js";
38
+ import { prefetchAgentVersions } from "./utils/versionCache.js";
39
+ import { getBunxAgentIds } from "./utils/versionFetcher.js";
40
+ const UNSAFE_SELECTION_MESSAGE = "Unsafe branch selected. Select anyway?";
41
+ const DEFAULT_SCREEN = "branch-list";
42
+ const buildStats = (branches) => calculateStatistics(branches);
43
+ const applyCleanupStatus = (items, statusByBranch) => items.map((branch) => {
44
+ const status = statusByBranch.get(branch.name);
45
+ if (!status) {
46
+ return { ...branch, safeToCleanup: false, isUnmerged: false };
47
+ }
48
+ const safeToCleanup = status.hasUpstream && status.reasons.includes("no-diff-with-base");
49
+ const isUnmerged = status.hasUpstream && status.hasUniqueCommits;
50
+ const worktree = branch.worktree
51
+ ? {
52
+ ...branch.worktree,
53
+ ...(status.hasUncommittedChanges !== undefined
54
+ ? { hasUncommittedChanges: status.hasUncommittedChanges }
55
+ : {}),
56
+ }
57
+ : undefined;
58
+ const base = {
59
+ ...branch,
60
+ safeToCleanup,
61
+ isUnmerged,
62
+ hasUnpushedCommits: status.hasUnpushedCommits,
63
+ };
64
+ return worktree ? { ...base, worktree } : base;
65
+ });
66
+ const buildCleanupSafetyPending = (items) => {
67
+ const pending = new Set();
68
+ for (const branch of items) {
69
+ if (branch.type === "remote") {
70
+ continue;
71
+ }
72
+ if (branch.worktree) {
73
+ pending.add(branch.name);
74
+ continue;
75
+ }
76
+ if (isProtectedBranchName(branch.name)) {
77
+ continue;
78
+ }
79
+ pending.add(branch.name);
80
+ }
81
+ return pending;
82
+ };
83
+ const toLocalBranchName = (name) => {
84
+ const segments = name.split("/");
85
+ if (segments.length <= 1) {
86
+ return name;
87
+ }
88
+ return segments.slice(1).join("/");
89
+ };
90
+ const toSelectedBranchState = (branch) => {
91
+ const isRemote = branch.type === "remote";
92
+ const baseName = isRemote ? toLocalBranchName(branch.name) : branch.name;
93
+ return {
94
+ name: baseName,
95
+ displayName: branch.name,
96
+ branchType: branch.type,
97
+ branchCategory: branch.branchType,
98
+ worktreePath: branch.worktree?.path ?? null,
99
+ ...(isRemote ? { remoteBranch: branch.name } : {}),
100
+ };
101
+ };
102
+ export function AppSolid(props) {
103
+ const renderer = useRenderer();
104
+ const terminal = useTerminalSize();
105
+ let hasExited = false;
106
+ const exitApp = (result) => {
107
+ if (hasExited)
108
+ return;
109
+ hasExited = true;
110
+ props.onExit?.(result);
111
+ renderer.destroy();
112
+ };
113
+ const [currentScreen, setCurrentScreen] = createSignal(props.initialScreen ?? DEFAULT_SCREEN);
114
+ const [screenStack, setScreenStack] = createSignal([]);
115
+ const [helpVisible, setHelpVisible] = createSignal(false);
116
+ const [wizardVisible, setWizardVisible] = createSignal(false);
117
+ const [branchItems, setBranchItems] = createSignal(props.branches ?? []);
118
+ const [stats, setStats] = createSignal(props.stats ?? buildStats(props.branches ?? []));
119
+ const [loading, setLoading] = createSignal(!props.branches);
120
+ const [error, setError] = createSignal(null);
121
+ // ブランチ一覧のカーソル位置(グローバル管理で再マウント時もリセットされない)
122
+ const [branchCursorPosition, setBranchCursorPosition] = createSignal(0);
123
+ const [toolItems, setToolItems] = createSignal([]);
124
+ const [toolError, setToolError] = createSignal(null);
125
+ const [version, setVersion] = createSignal(props.version ?? null);
126
+ const workingDirectory = createMemo(() => props.workingDirectory ?? process.cwd());
127
+ const [selectedBranch, setSelectedBranch] = createSignal(null);
128
+ const [selectedTool, setSelectedTool] = createSignal(null);
129
+ const [selectedMode, setSelectedMode] = createSignal("normal");
130
+ const [selectedBranches, setSelectedBranches] = createSignal([]);
131
+ const [unsafeSelectionConfirmVisible, setUnsafeSelectionConfirmVisible] = createSignal(false);
132
+ const [unsafeConfirmInputLocked, setUnsafeConfirmInputLocked] = createSignal(false);
133
+ const [unsafeSelectionTarget, setUnsafeSelectionTarget] = createSignal(null);
134
+ const [branchFooterMessage, setBranchFooterMessage] = createSignal(null);
135
+ const [branchInputLocked, setBranchInputLocked] = createSignal(false);
136
+ const [cleanupIndicators, setCleanupIndicators] = createSignal({});
137
+ const [cleanupStatusByBranch, setCleanupStatusByBranch] = createSignal(new Map());
138
+ const [cleanupSafetyLoading, setCleanupSafetyLoading] = createSignal(false);
139
+ const [cleanupSafetyPending, setCleanupSafetyPending] = createSignal(new Set());
140
+ const [isNewBranch, setIsNewBranch] = createSignal(false);
141
+ const [newBranchBaseRef, setNewBranchBaseRef] = createSignal(null);
142
+ const [creationSource, setCreationSource] = createSignal(null);
143
+ const [createBranchName, setCreateBranchName] = createSignal("", {
144
+ equals: false,
145
+ });
146
+ const [suppressCreateKey, setSuppressCreateKey] = createSignal(null);
147
+ const [defaultBaseBranch, setDefaultBaseBranch] = createSignal("main");
148
+ const suppressBranchInputOnce = () => {
149
+ setUnsafeConfirmInputLocked(true);
150
+ queueMicrotask(() => {
151
+ setUnsafeConfirmInputLocked(false);
152
+ });
153
+ };
154
+ const unsafeConfirmBoxWidth = createMemo(() => {
155
+ const columns = terminal().columns || 80;
156
+ return Math.max(1, Math.floor(columns * 0.6));
157
+ });
158
+ const unsafeConfirmContentWidth = createMemo(() => Math.max(0, unsafeConfirmBoxWidth() - 4));
159
+ // セッション履歴(最終使用エージェントなど)
160
+ const [sessionHistory, setSessionHistory] = createSignal([]);
161
+ const [quickStartHistory, setQuickStartHistory] = createSignal([]);
162
+ // 選択中ブランチの履歴をフィルタリング
163
+ const historyForBranch = createMemo(() => {
164
+ const history = sessionHistory();
165
+ const branch = selectedBranch();
166
+ if (!branch)
167
+ return [];
168
+ return findLatestBranchSessionsByTool(history, branch.name, branch.worktreePath ?? null);
169
+ });
170
+ createEffect(() => {
171
+ setQuickStartHistory(historyForBranch());
172
+ });
173
+ createEffect(() => {
174
+ const branch = selectedBranch();
175
+ const baseHistory = historyForBranch();
176
+ if (!wizardVisible() || !branch || baseHistory.length === 0) {
177
+ return;
178
+ }
179
+ const worktreePath = branch.worktreePath ?? null;
180
+ if (!worktreePath) {
181
+ return;
182
+ }
183
+ const branchName = branch.name;
184
+ void (async () => {
185
+ const refreshed = await refreshQuickStartEntries(baseHistory, {
186
+ branch: branchName,
187
+ worktreePath,
188
+ });
189
+ if (selectedBranch()?.name !== branchName) {
190
+ return;
191
+ }
192
+ setQuickStartHistory(refreshed);
193
+ })();
194
+ });
195
+ const [logEntries, setLogEntries] = createSignal([]);
196
+ const [logLoading, setLogLoading] = createSignal(false);
197
+ const [logError, setLogError] = createSignal(null);
198
+ const [logSelectedEntry, setLogSelectedEntry] = createSignal(null);
199
+ const [logSelectedDate, setLogSelectedDate] = createSignal(getTodayLogDate());
200
+ const [logNotification, setLogNotification] = createSignal(null);
201
+ const [logTailEnabled, setLogTailEnabled] = createSignal(false);
202
+ const [logTargetBranch, setLogTargetBranch] = createSignal(null);
203
+ const [profileItems, setProfileItems] = createSignal([]);
204
+ const [activeProfile, setActiveProfileName] = createSignal(null);
205
+ const [profileError, setProfileError] = createSignal(null);
206
+ const [profilesConfig, setProfilesConfig] = createSignal(null);
207
+ const [profileActionError, setProfileActionError] = createSignal(null);
208
+ const [profileActionHint, setProfileActionHint] = createSignal(null);
209
+ const [selectedProfileName, setSelectedProfileName] = createSignal(null);
210
+ const [profileInputValue, setProfileInputValue] = createSignal("", {
211
+ equals: false,
212
+ });
213
+ const [profileInputMode, setProfileInputMode] = createSignal("create-profile");
214
+ const [profileInputSuppressKey, setProfileInputSuppressKey] = createSignal(null);
215
+ const [profileEnvKey, setProfileEnvKey] = createSignal(null);
216
+ const [profileConfirmMode, setProfileConfirmMode] = createSignal("delete-profile");
217
+ const logTarget = createMemo(() => resolveLogTarget(logTargetBranch(), workingDirectory()));
218
+ const logBranchLabel = createMemo(() => logTargetBranch()?.label ?? null);
219
+ const logSourceLabel = createMemo(() => {
220
+ const target = logTarget();
221
+ if (!target.sourcePath) {
222
+ return "(none)";
223
+ }
224
+ if (target.reason === "current-working-directory" ||
225
+ target.reason === "working-directory") {
226
+ return `${target.sourcePath} (cwd)`;
227
+ }
228
+ if (target.reason === "worktree-inaccessible") {
229
+ return `${target.sourcePath} (inaccessible)`;
230
+ }
231
+ return target.sourcePath;
232
+ });
233
+ const selectedProfileConfig = createMemo(() => {
234
+ const name = selectedProfileName();
235
+ const config = profilesConfig();
236
+ if (!name || !config?.profiles?.[name]) {
237
+ return null;
238
+ }
239
+ return { name, profile: config.profiles[name] };
240
+ });
241
+ const profileEnvVariables = createMemo(() => {
242
+ const entry = selectedProfileConfig();
243
+ if (!entry) {
244
+ return [];
245
+ }
246
+ return Object.entries(entry.profile.env ?? {})
247
+ .map(([key, value]) => ({ key, value }))
248
+ .sort((a, b) => a.key.localeCompare(b.key));
249
+ });
250
+ const osEnvVariables = createMemo(() => Object.entries(process.env)
251
+ .filter(([, value]) => typeof value === "string")
252
+ .map(([key, value]) => ({ key, value: String(value) }))
253
+ .sort((a, b) => a.key.localeCompare(b.key)));
254
+ let cleanupSafetyRequestId = 0;
255
+ const refreshCleanupSafety = async () => {
256
+ const requestId = ++cleanupSafetyRequestId;
257
+ const pendingBranches = buildCleanupSafetyPending(branchItems());
258
+ setCleanupSafetyPending(pendingBranches);
259
+ setCleanupSafetyLoading(pendingBranches.size > 0);
260
+ const statusByBranch = new Map();
261
+ const applyProgress = (status) => {
262
+ if (requestId !== cleanupSafetyRequestId) {
263
+ return;
264
+ }
265
+ statusByBranch.set(status.branch, status);
266
+ batch(() => {
267
+ setCleanupStatusByBranch(new Map(statusByBranch));
268
+ setBranchItems((items) => applyCleanupStatus(items, statusByBranch));
269
+ setCleanupSafetyPending((prev) => {
270
+ if (!prev.has(status.branch)) {
271
+ return prev;
272
+ }
273
+ const next = new Set(prev);
274
+ next.delete(status.branch);
275
+ return next;
276
+ });
277
+ });
278
+ };
279
+ try {
280
+ const cleanupStatuses = await getCleanupStatus({
281
+ onProgress: applyProgress,
282
+ });
283
+ if (requestId !== cleanupSafetyRequestId) {
284
+ return;
285
+ }
286
+ if (cleanupStatuses.length > statusByBranch.size) {
287
+ cleanupStatuses.forEach((status) => {
288
+ if (!statusByBranch.has(status.branch)) {
289
+ applyProgress(status);
290
+ }
291
+ });
292
+ }
293
+ }
294
+ catch (err) {
295
+ if (requestId !== cleanupSafetyRequestId) {
296
+ return;
297
+ }
298
+ logger.warn({ err }, "Failed to refresh cleanup safety indicators");
299
+ const empty = new Map();
300
+ batch(() => {
301
+ setCleanupStatusByBranch(empty);
302
+ setBranchItems((items) => applyCleanupStatus(items, empty));
303
+ });
304
+ }
305
+ finally {
306
+ if (requestId === cleanupSafetyRequestId) {
307
+ setCleanupSafetyLoading(false);
308
+ setCleanupSafetyPending(new Set());
309
+ }
310
+ }
311
+ };
312
+ let logNotificationTimer = null;
313
+ let logTailTimer = null;
314
+ let branchFooterTimer = null;
315
+ const BRANCH_LOAD_TIMEOUT_MS = 3000;
316
+ const BRANCH_FULL_LOAD_TIMEOUT_MS = 8000;
317
+ const isHelpKey = (key) => {
318
+ if (key.ctrl || key.meta || key.super || key.hyper || key.option) {
319
+ return false;
320
+ }
321
+ return key.name === "h" || key.sequence === "h" || key.sequence === "?";
322
+ };
323
+ useKeyboard((key) => {
324
+ if (key.repeated) {
325
+ return;
326
+ }
327
+ if (helpVisible()) {
328
+ if (key.name === "escape" || isHelpKey(key)) {
329
+ setHelpVisible(false);
330
+ }
331
+ return;
332
+ }
333
+ if (isHelpKey(key)) {
334
+ setHelpVisible(true);
335
+ }
336
+ });
337
+ const navigateTo = (screen) => {
338
+ setScreenStack((prev) => [...prev, currentScreen()]);
339
+ setCurrentScreen(screen);
340
+ };
341
+ const goBack = () => {
342
+ const stack = screenStack();
343
+ if (stack.length === 0) {
344
+ return;
345
+ }
346
+ const previous = stack[stack.length - 1] ?? DEFAULT_SCREEN;
347
+ setScreenStack(stack.slice(0, -1));
348
+ // branch-list に戻る場合は選択状態をリセット
349
+ if (previous === "branch-list") {
350
+ setSelectedBranch(null);
351
+ setSelectedTool(null);
352
+ setSelectedMode("normal");
353
+ setIsNewBranch(false);
354
+ setNewBranchBaseRef(null);
355
+ setCreationSource(null);
356
+ }
357
+ setCurrentScreen(previous);
358
+ };
359
+ const openProfileError = (err, hint) => {
360
+ setProfileActionError(err instanceof Error ? err : new Error(String(err)));
361
+ setProfileActionHint(hint);
362
+ navigateTo("profile-error");
363
+ };
364
+ const showLogNotification = (message, tone) => {
365
+ setLogNotification({ message, tone });
366
+ if (logNotificationTimer) {
367
+ clearTimeout(logNotificationTimer);
368
+ }
369
+ logNotificationTimer = setTimeout(() => {
370
+ setLogNotification(null);
371
+ }, 2000);
372
+ };
373
+ const loadLogEntries = async (date) => {
374
+ const targetDate = date ?? getTodayLogDate();
375
+ setLogLoading(true);
376
+ setLogError(null);
377
+ try {
378
+ const target = logTarget();
379
+ if (!target.logDir) {
380
+ setLogEntries([]);
381
+ setLogSelectedDate(targetDate);
382
+ return;
383
+ }
384
+ const result = await readLogLinesForDate(target.logDir, targetDate);
385
+ if (!result) {
386
+ setLogEntries([]);
387
+ setLogSelectedDate(targetDate);
388
+ return;
389
+ }
390
+ setLogSelectedDate(result.date);
391
+ const parsed = parseLogLines(result.lines, { limit: 100 });
392
+ setLogEntries(parsed);
393
+ }
394
+ catch (err) {
395
+ setLogEntries([]);
396
+ setLogError(err instanceof Error ? err.message : "Failed to load logs");
397
+ }
398
+ finally {
399
+ setLogLoading(false);
400
+ }
401
+ };
402
+ const clearLogTailTimer = () => {
403
+ if (logTailTimer) {
404
+ clearInterval(logTailTimer);
405
+ logTailTimer = null;
406
+ }
407
+ };
408
+ const toggleLogTail = () => {
409
+ setLogTailEnabled((prev) => !prev);
410
+ };
411
+ const resetLogFiles = async () => {
412
+ const target = logTarget();
413
+ if (!target.logDir) {
414
+ showLogNotification("No logs available.", "error");
415
+ return;
416
+ }
417
+ try {
418
+ const cleared = await clearLogFiles(target.logDir);
419
+ if (cleared === 0) {
420
+ showLogNotification("No logs to reset.", "error");
421
+ }
422
+ else {
423
+ showLogNotification("Logs cleared.", "success");
424
+ }
425
+ await loadLogEntries(logSelectedDate());
426
+ }
427
+ catch (err) {
428
+ logger.warn({ err }, "Failed to clear log files");
429
+ showLogNotification("Failed to reset logs.", "error");
430
+ }
431
+ };
432
+ const refreshBranches = async () => {
433
+ setLoading(true);
434
+ setError(null);
435
+ try {
436
+ const repoRoot = await getRepositoryRoot();
437
+ const worktreesPromise = listAdditionalWorktrees();
438
+ const localBranchesPromise = getLocalBranches(repoRoot);
439
+ const currentBranchPromise = getCurrentBranch(repoRoot);
440
+ const lastToolUsagePromise = getLastToolUsageMap(repoRoot);
441
+ const [localBranches, currentBranch, worktrees, lastToolUsageMap] = await Promise.all([
442
+ withTimeout(localBranchesPromise, BRANCH_LOAD_TIMEOUT_MS).catch(() => []),
443
+ withTimeout(currentBranchPromise, BRANCH_LOAD_TIMEOUT_MS).catch(() => null),
444
+ withTimeout(worktreesPromise, BRANCH_LOAD_TIMEOUT_MS).catch(() => []),
445
+ withTimeout(lastToolUsagePromise, BRANCH_LOAD_TIMEOUT_MS).catch(() => new Map()),
446
+ ]);
447
+ if (currentBranch) {
448
+ localBranches.forEach((branch) => {
449
+ if (branch.name === currentBranch) {
450
+ branch.isCurrent = true;
451
+ }
452
+ });
453
+ }
454
+ const initial = buildBranchList(localBranches, worktrees, lastToolUsageMap);
455
+ const initialItems = applyCleanupStatus(initial.items, cleanupStatusByBranch());
456
+ setBranchItems(initialItems);
457
+ setStats(buildStats(initialItems));
458
+ void refreshCleanupSafety();
459
+ void (async () => {
460
+ const [branches, latestWorktrees] = await Promise.all([
461
+ withTimeout(getAllBranches(repoRoot), BRANCH_FULL_LOAD_TIMEOUT_MS).catch(() => localBranches),
462
+ withTimeout(listAdditionalWorktrees(), BRANCH_FULL_LOAD_TIMEOUT_MS).catch(() => worktrees),
463
+ ]);
464
+ const full = buildBranchList(branches, latestWorktrees, lastToolUsageMap);
465
+ const fullItems = applyCleanupStatus(full.items, cleanupStatusByBranch());
466
+ setBranchItems(fullItems);
467
+ setStats(buildStats(fullItems));
468
+ })();
469
+ }
470
+ catch (err) {
471
+ setError(err instanceof Error ? err : new Error(String(err)));
472
+ }
473
+ finally {
474
+ setLoading(false);
475
+ }
476
+ };
477
+ const refreshProfiles = async () => {
478
+ try {
479
+ const config = await loadProfiles();
480
+ setProfilesConfig(config);
481
+ const items = Object.entries(config.profiles ?? {}).map(([name, profile]) => ({
482
+ name,
483
+ displayName: profile.displayName,
484
+ isActive: config.activeProfile === name,
485
+ }));
486
+ items.sort((a, b) => a.name.localeCompare(b.name));
487
+ setProfileItems(items);
488
+ setActiveProfileName(config.activeProfile ?? null);
489
+ setProfileError(null);
490
+ }
491
+ catch (err) {
492
+ setProfilesConfig(null);
493
+ setProfileItems([]);
494
+ setActiveProfileName(null);
495
+ setProfileError(err instanceof Error ? err : new Error(String(err)));
496
+ }
497
+ };
498
+ createEffect(() => {
499
+ if (props.branches) {
500
+ const statusByBranch = cleanupStatusByBranch();
501
+ const nextItems = applyCleanupStatus(props.branches, statusByBranch);
502
+ setBranchItems(nextItems);
503
+ setStats(props.stats ?? buildStats(nextItems));
504
+ setLoading(false);
505
+ }
506
+ });
507
+ onMount(() => {
508
+ if (!props.branches) {
509
+ void refreshBranches();
510
+ }
511
+ });
512
+ onMount(() => {
513
+ if (props.branches) {
514
+ void refreshCleanupSafety();
515
+ }
516
+ });
517
+ onMount(() => {
518
+ if (props.version === undefined) {
519
+ void getPackageVersion()
520
+ .then((value) => setVersion(value ?? null))
521
+ .catch(() => setVersion(null));
522
+ }
523
+ });
524
+ onMount(() => {
525
+ void refreshProfiles();
526
+ });
527
+ onMount(() => {
528
+ void getConfig()
529
+ .then((config) => setDefaultBaseBranch(config.defaultBaseBranch))
530
+ .catch(() => setDefaultBaseBranch("main"));
531
+ });
532
+ // セッション履歴をロード(最終使用エージェントなど)
533
+ onMount(() => {
534
+ void getRepositoryRoot()
535
+ .then((repoRoot) => loadSession(repoRoot))
536
+ .then((session) => {
537
+ if (session?.history) {
538
+ setSessionHistory(session.history);
539
+ }
540
+ })
541
+ .catch(() => setSessionHistory([]));
542
+ });
543
+ onMount(() => {
544
+ void getAllCodingAgents()
545
+ .then((agents) => {
546
+ setToolItems(agents.map((agent) => ({
547
+ label: agent.displayName,
548
+ value: agent.id,
549
+ })));
550
+ })
551
+ .catch((err) => {
552
+ setToolItems([]);
553
+ setToolError(err instanceof Error ? err : new Error(String(err)));
554
+ });
555
+ });
556
+ // FR-028: Prefetch npm versions for all bunx-type agents at startup (background)
557
+ onMount(() => {
558
+ const bunxAgentIds = getBunxAgentIds();
559
+ void prefetchAgentVersions(bunxAgentIds).catch(() => {
560
+ // Silently handle errors - cache will return null and UI will show "latest" only
561
+ });
562
+ });
563
+ createEffect(() => {
564
+ if (currentScreen() === "log-list") {
565
+ logTarget();
566
+ void loadLogEntries(logSelectedDate());
567
+ }
568
+ });
569
+ createEffect(() => {
570
+ if (currentScreen() !== "log-list" || !logTailEnabled()) {
571
+ clearLogTailTimer();
572
+ return;
573
+ }
574
+ clearLogTailTimer();
575
+ logTailTimer = setInterval(() => {
576
+ void loadLogEntries(logSelectedDate());
577
+ }, 1500);
578
+ });
579
+ onCleanup(() => {
580
+ if (logNotificationTimer) {
581
+ clearTimeout(logNotificationTimer);
582
+ }
583
+ clearLogTailTimer();
584
+ if (branchFooterTimer) {
585
+ clearTimeout(branchFooterTimer);
586
+ }
587
+ });
588
+ const showBranchFooterMessage = (text, color, options) => {
589
+ if (branchFooterTimer) {
590
+ clearTimeout(branchFooterTimer);
591
+ branchFooterTimer = null;
592
+ }
593
+ setBranchFooterMessage({
594
+ text,
595
+ color,
596
+ ...(options?.spinning ? { isSpinning: true } : {}),
597
+ });
598
+ const timeout = options?.timeoutMs ?? 2000;
599
+ if (timeout > 0) {
600
+ branchFooterTimer = setTimeout(() => {
601
+ setBranchFooterMessage(null);
602
+ }, timeout);
603
+ }
604
+ };
605
+ const setCleanupIndicator = (branchName, indicator) => {
606
+ setCleanupIndicators((prev) => {
607
+ const next = { ...prev };
608
+ if (indicator) {
609
+ next[branchName] = indicator;
610
+ }
611
+ else {
612
+ delete next[branchName];
613
+ }
614
+ return next;
615
+ });
616
+ };
617
+ const handleBranchSelect = (branch) => {
618
+ setSelectedBranch(toSelectedBranchState(branch));
619
+ setIsNewBranch(false);
620
+ setNewBranchBaseRef(null);
621
+ setCreationSource(null);
622
+ setSelectedTool(null);
623
+ setSelectedMode("normal");
624
+ // FR-044: ウィザードポップアップをレイヤー表示
625
+ setWizardVisible(true);
626
+ };
627
+ const handleQuickCreate = (branch) => {
628
+ // 選択中のブランチをベースにウィザードを開始
629
+ if (branch) {
630
+ setSelectedBranch(toSelectedBranchState(branch));
631
+ }
632
+ setCreationSource(branch ? toSelectedBranchState(branch) : null);
633
+ setCreateBranchName("");
634
+ setSuppressCreateKey("n");
635
+ // FR-044: ウィザードポップアップをレイヤー表示(アクション選択から開始)
636
+ setWizardVisible(true);
637
+ };
638
+ // FR-049: Escapeキーでウィザードをキャンセル
639
+ const handleWizardClose = () => {
640
+ setWizardVisible(false);
641
+ };
642
+ // ウィザード完了時の処理
643
+ const handleWizardComplete = (result) => {
644
+ setWizardVisible(false);
645
+ const branch = selectedBranch();
646
+ if (!branch) {
647
+ return;
648
+ }
649
+ // 新規ブランチ作成の場合、ブランチ名を設定
650
+ const isCreatingNew = result.isNewBranch ?? false;
651
+ const finalBranchName = result.branchName
652
+ ? `${result.branchType ?? ""}${result.branchName}`
653
+ : branch.name;
654
+ // 新規作成時は選択中のブランチがベースとなる
655
+ const baseBranchRef = isCreatingNew ? branch.name : null;
656
+ const normalizedModel = normalizeModelId(result.tool, result.model);
657
+ exitApp({
658
+ branch: finalBranchName,
659
+ displayName: branch.displayName,
660
+ branchType: branch.branchType,
661
+ ...(branch.remoteBranch ? { remoteBranch: branch.remoteBranch } : {}),
662
+ ...(isCreatingNew
663
+ ? {
664
+ isNewBranch: true,
665
+ ...(baseBranchRef ? { baseBranch: baseBranchRef } : {}),
666
+ }
667
+ : {}),
668
+ tool: result.tool,
669
+ mode: result.mode,
670
+ skipPermissions: result.skipPermissions,
671
+ ...(normalizedModel !== undefined ? { model: normalizedModel } : {}),
672
+ ...(result.reasoningLevel !== undefined
673
+ ? { inferenceLevel: result.reasoningLevel }
674
+ : {}),
675
+ ...(result.toolVersion !== undefined
676
+ ? { toolVersion: result.toolVersion }
677
+ : {}),
678
+ });
679
+ };
680
+ // FR-010: クイックスタートからのResume(前回設定で続きから)
681
+ const handleWizardResume = (entry) => {
682
+ if (!entry.sessionId) {
683
+ handleWizardStartNew(entry);
684
+ return;
685
+ }
686
+ setWizardVisible(false);
687
+ const branch = selectedBranch();
688
+ if (!branch) {
689
+ return;
690
+ }
691
+ const normalizedModel = normalizeModelId(entry.toolId, entry.model ?? undefined);
692
+ exitApp({
693
+ branch: branch.name,
694
+ displayName: branch.displayName,
695
+ branchType: branch.branchType,
696
+ ...(branch.remoteBranch ? { remoteBranch: branch.remoteBranch } : {}),
697
+ tool: entry.toolId,
698
+ mode: "continue",
699
+ skipPermissions: entry.skipPermissions ?? false,
700
+ ...(normalizedModel !== undefined ? { model: normalizedModel } : {}),
701
+ ...(entry.reasoningLevel
702
+ ? { inferenceLevel: entry.reasoningLevel }
703
+ : {}),
704
+ ...(entry.sessionId ? { sessionId: entry.sessionId } : {}),
705
+ ...(entry.toolVersion !== undefined
706
+ ? { toolVersion: entry.toolVersion }
707
+ : {}),
708
+ });
709
+ };
710
+ // FR-010: クイックスタートからのStartNew(前回設定で新規)
711
+ const handleWizardStartNew = (entry) => {
712
+ setWizardVisible(false);
713
+ const branch = selectedBranch();
714
+ if (!branch) {
715
+ return;
716
+ }
717
+ const normalizedModel = normalizeModelId(entry.toolId, entry.model ?? undefined);
718
+ exitApp({
719
+ branch: branch.name,
720
+ displayName: branch.displayName,
721
+ branchType: branch.branchType,
722
+ ...(branch.remoteBranch ? { remoteBranch: branch.remoteBranch } : {}),
723
+ tool: entry.toolId,
724
+ mode: "normal",
725
+ skipPermissions: entry.skipPermissions ?? false,
726
+ ...(normalizedModel !== undefined ? { model: normalizedModel } : {}),
727
+ ...(entry.reasoningLevel
728
+ ? { inferenceLevel: entry.reasoningLevel }
729
+ : {}),
730
+ ...(entry.toolVersion !== undefined
731
+ ? { toolVersion: entry.toolVersion }
732
+ : {}),
733
+ });
734
+ };
735
+ const buildSkipNotice = (skip, unsafeLabel) => {
736
+ const parts = [];
737
+ if (skip.unsafe > 0) {
738
+ parts.push(`${skip.unsafe} ${unsafeLabel}`);
739
+ }
740
+ if (skip.protected > 0) {
741
+ parts.push(`${skip.protected} protected`);
742
+ }
743
+ if (skip.remote > 0) {
744
+ parts.push(`${skip.remote} remote-only`);
745
+ }
746
+ if (skip.current > 0) {
747
+ parts.push(`${skip.current} current`);
748
+ }
749
+ if (parts.length === 0) {
750
+ return null;
751
+ }
752
+ return `Skipped branches: ${parts.join(", ")}.`;
753
+ };
754
+ const handleCleanupCommand = async () => {
755
+ if (branchInputLocked()) {
756
+ return;
757
+ }
758
+ const selection = selectedBranches();
759
+ const hasSelection = selection.length > 0;
760
+ const skipCounts = {
761
+ unsafe: 0,
762
+ protected: 0,
763
+ remote: 0,
764
+ current: 0,
765
+ };
766
+ setBranchInputLocked(true);
767
+ setCleanupIndicators({});
768
+ showBranchFooterMessage(hasSelection
769
+ ? "Preparing cleanup..."
770
+ : "Scanning for cleanup candidates...", "yellow", { spinning: true, timeoutMs: 0 });
771
+ try {
772
+ const tasks = [];
773
+ if (hasSelection) {
774
+ const branchMap = new Map(branchItems().map((branch) => [branch.name, branch]));
775
+ for (const branchName of selection) {
776
+ const branch = branchMap.get(branchName);
777
+ if (!branch) {
778
+ continue;
779
+ }
780
+ if (branch.type === "remote") {
781
+ skipCounts.remote += 1;
782
+ continue;
783
+ }
784
+ if (branch.isCurrent) {
785
+ skipCounts.current += 1;
786
+ continue;
787
+ }
788
+ const worktreePath = branch.worktree?.path ?? null;
789
+ const cleanupType = worktreePath
790
+ ? "worktree-and-branch"
791
+ : "branch-only";
792
+ const baseTask = {
793
+ branch: branch.name,
794
+ worktreePath,
795
+ cleanupType,
796
+ };
797
+ const isAccessible = branch.worktree?.isAccessible;
798
+ tasks.push(isAccessible === undefined
799
+ ? baseTask
800
+ : { ...baseTask, isAccessible });
801
+ }
802
+ }
803
+ else {
804
+ // FR-028: 選択が0件の場合は警告を表示して処理をスキップ
805
+ setBranchInputLocked(false);
806
+ showBranchFooterMessage("No branches selected.", "yellow");
807
+ return;
808
+ }
809
+ const skipNotice = buildSkipNotice(skipCounts, hasSelection
810
+ ? "unsafe (uncommitted/unpushed, unmerged, or missing upstream)"
811
+ : "with uncommitted or unpushed changes");
812
+ if (tasks.length === 0) {
813
+ const baseMessage = hasSelection
814
+ ? "No eligible branches selected for cleanup."
815
+ : "No cleanup candidates found.";
816
+ showBranchFooterMessage(skipNotice ? `${baseMessage} ${skipNotice}` : baseMessage, "yellow");
817
+ return;
818
+ }
819
+ setCleanupIndicators(() => {
820
+ const next = {};
821
+ tasks.forEach((task) => {
822
+ next[task.branch] = {
823
+ icon: "-",
824
+ isSpinning: true,
825
+ color: "yellow",
826
+ };
827
+ });
828
+ return next;
829
+ });
830
+ showBranchFooterMessage(`Cleaning up ${tasks.length} branch(es)...`, "yellow", { spinning: true, timeoutMs: 0 });
831
+ let successCount = 0;
832
+ let failedCount = 0;
833
+ for (const task of tasks) {
834
+ try {
835
+ if (task.cleanupType === "worktree-and-branch" && task.worktreePath) {
836
+ await removeWorktree(task.worktreePath, task.isAccessible === false);
837
+ }
838
+ await deleteBranch(task.branch, true);
839
+ setCleanupIndicator(task.branch, { icon: "v", color: "green" });
840
+ successCount += 1;
841
+ }
842
+ catch {
843
+ setCleanupIndicator(task.branch, { icon: "x", color: "red" });
844
+ failedCount += 1;
845
+ }
846
+ }
847
+ setSelectedBranches([]);
848
+ await refreshBranches();
849
+ const skippedTotal = skipCounts.unsafe +
850
+ skipCounts.protected +
851
+ skipCounts.remote +
852
+ skipCounts.current;
853
+ const summaryParts = [`${successCount} cleaned`];
854
+ if (failedCount > 0) {
855
+ summaryParts.push(`${failedCount} failed`);
856
+ }
857
+ if (skippedTotal > 0) {
858
+ summaryParts.push(`${skippedTotal} skipped`);
859
+ }
860
+ const summary = `Cleanup finished: ${summaryParts.join(", ")}.`;
861
+ const message = skipNotice ? `${summary} ${skipNotice}` : summary;
862
+ showBranchFooterMessage(message, failedCount > 0 ? "red" : "green");
863
+ }
864
+ catch (err) {
865
+ const errorMessage = err instanceof Error ? err.message : String(err);
866
+ showBranchFooterMessage(`Cleanup failed: ${errorMessage}`, "red");
867
+ }
868
+ finally {
869
+ setBranchInputLocked(false);
870
+ }
871
+ };
872
+ const handleRepairWorktrees = async () => {
873
+ if (branchInputLocked()) {
874
+ return;
875
+ }
876
+ // FR-002/FR-007: 選択済みブランチのみを対象とする
877
+ const selection = selectedBranches();
878
+ if (selection.length === 0) {
879
+ showBranchFooterMessage("No branches selected.", "yellow");
880
+ return;
881
+ }
882
+ // 選択されたローカルブランチのうち、Worktreeを持つものを修復対象とする
883
+ const selectionSet = new Set(selection);
884
+ const targets = branchItems()
885
+ .filter((branch) => selectionSet.has(branch.name) &&
886
+ branch.type !== "remote" &&
887
+ branch.worktreeStatus !== undefined)
888
+ .map((branch) => branch.name);
889
+ if (targets.length === 0) {
890
+ showBranchFooterMessage("No worktrees to repair.", "yellow");
891
+ return;
892
+ }
893
+ setBranchInputLocked(true);
894
+ showBranchFooterMessage("Repairing worktrees...", "yellow", {
895
+ spinning: true,
896
+ timeoutMs: 0,
897
+ });
898
+ try {
899
+ const result = await repairWorktrees(targets);
900
+ await refreshBranches();
901
+ // エラー詳細をログに出力
902
+ if (result.failedCount > 0) {
903
+ logger.error({ failures: result.failures, targets }, "Worktree repair failed for some branches");
904
+ }
905
+ const message = result.failedCount > 0
906
+ ? `Repair finished: ${result.repairedCount} repaired, ${result.failedCount} failed.`
907
+ : result.repairedCount > 0
908
+ ? `Repaired ${result.repairedCount} worktree(s).`
909
+ : "No worktrees repaired.";
910
+ showBranchFooterMessage(message, result.failedCount > 0 ? "red" : "green");
911
+ }
912
+ catch (err) {
913
+ const errorMessage = err instanceof Error ? err.message : String(err);
914
+ logger.error({ error: err, targets }, "Worktree repair threw an error");
915
+ showBranchFooterMessage(`Repair failed: ${errorMessage}`, "red");
916
+ }
917
+ finally {
918
+ setBranchInputLocked(false);
919
+ }
920
+ };
921
+ const openProfileCreate = () => {
922
+ setProfileInputMode("create-profile");
923
+ setProfileInputValue("");
924
+ setProfileEnvKey(null);
925
+ setProfileInputSuppressKey("n");
926
+ navigateTo("profile-input");
927
+ };
928
+ const openProfileDelete = (profile) => {
929
+ setSelectedProfileName(profile.name);
930
+ setProfileConfirmMode("delete-profile");
931
+ navigateTo("profile-confirm");
932
+ };
933
+ const openProfileEnv = (profile) => {
934
+ setSelectedProfileName(profile.name);
935
+ navigateTo("profile-env");
936
+ };
937
+ const openProfileEnvAdd = () => {
938
+ setProfileInputMode("add-env");
939
+ setProfileInputValue("");
940
+ setProfileEnvKey(null);
941
+ setProfileInputSuppressKey("a");
942
+ navigateTo("profile-input");
943
+ };
944
+ const openProfileEnvEdit = (variable) => {
945
+ setProfileInputMode("edit-env");
946
+ setProfileEnvKey(variable.key);
947
+ setProfileInputValue(variable.value);
948
+ setProfileInputSuppressKey("e");
949
+ navigateTo("profile-input");
950
+ };
951
+ const openProfileEnvDelete = (variable) => {
952
+ setProfileConfirmMode("delete-env");
953
+ setProfileEnvKey(variable.key);
954
+ navigateTo("profile-confirm");
955
+ };
956
+ const handleProfileInputChange = (value) => {
957
+ const suppressKey = profileInputSuppressKey();
958
+ if (suppressKey && profileInputValue() === "" && value === suppressKey) {
959
+ setProfileInputSuppressKey(null);
960
+ setProfileInputValue("");
961
+ return;
962
+ }
963
+ setProfileInputSuppressKey(null);
964
+ setProfileInputValue(value);
965
+ };
966
+ const submitProfileInput = async (value) => {
967
+ const mode = profileInputMode();
968
+ const trimmed = value.trim();
969
+ if (mode === "create-profile") {
970
+ if (!trimmed) {
971
+ openProfileError(new Error("Profile name is required."), "Invalid name.");
972
+ return;
973
+ }
974
+ if (!isValidProfileName(trimmed)) {
975
+ openProfileError(new Error(`Invalid profile name: "${trimmed}".`), "Profile names must use lowercase letters, numbers, and hyphens.");
976
+ return;
977
+ }
978
+ try {
979
+ await createProfile(trimmed, { displayName: trimmed, env: {} });
980
+ await refreshProfiles();
981
+ setSelectedProfileName(trimmed);
982
+ setProfileInputValue("");
983
+ setProfileInputSuppressKey(null);
984
+ goBack();
985
+ }
986
+ catch (err) {
987
+ openProfileError(err, "Unable to create profile.");
988
+ }
989
+ return;
990
+ }
991
+ const entry = selectedProfileConfig();
992
+ if (!entry) {
993
+ openProfileError(new Error("Profile not selected."), "Profile not found.");
994
+ return;
995
+ }
996
+ if (mode === "add-env") {
997
+ const separatorIndex = trimmed.indexOf("=");
998
+ if (separatorIndex <= 0) {
999
+ openProfileError(new Error("Environment variable must be in KEY=VALUE format."), "Invalid environment variable.");
1000
+ return;
1001
+ }
1002
+ const key = trimmed.slice(0, separatorIndex).trim();
1003
+ const valuePart = trimmed.slice(separatorIndex + 1);
1004
+ if (!key) {
1005
+ openProfileError(new Error("Environment variable key is required."), "Invalid environment variable.");
1006
+ return;
1007
+ }
1008
+ const nextEnv = { ...(entry.profile.env ?? {}) };
1009
+ nextEnv[key] = valuePart;
1010
+ try {
1011
+ await updateProfile(entry.name, { env: nextEnv });
1012
+ await refreshProfiles();
1013
+ setProfileInputValue("");
1014
+ setProfileInputSuppressKey(null);
1015
+ goBack();
1016
+ }
1017
+ catch (err) {
1018
+ openProfileError(err, "Unable to update profile.");
1019
+ }
1020
+ return;
1021
+ }
1022
+ if (mode === "edit-env") {
1023
+ const envKey = profileEnvKey();
1024
+ if (!envKey) {
1025
+ openProfileError(new Error("Environment variable not selected."), "Select a variable to edit.");
1026
+ return;
1027
+ }
1028
+ const nextEnv = { ...(entry.profile.env ?? {}) };
1029
+ nextEnv[envKey] = value;
1030
+ try {
1031
+ await updateProfile(entry.name, { env: nextEnv });
1032
+ await refreshProfiles();
1033
+ setProfileInputValue("");
1034
+ setProfileInputSuppressKey(null);
1035
+ goBack();
1036
+ }
1037
+ catch (err) {
1038
+ openProfileError(err, "Unable to update profile.");
1039
+ }
1040
+ }
1041
+ };
1042
+ const confirmProfileAction = async (confirmed) => {
1043
+ if (!confirmed) {
1044
+ goBack();
1045
+ return;
1046
+ }
1047
+ const mode = profileConfirmMode();
1048
+ const entry = selectedProfileConfig();
1049
+ if (mode === "delete-profile") {
1050
+ const name = selectedProfileName();
1051
+ if (!name) {
1052
+ openProfileError(new Error("Profile not selected."), "Profile not found.");
1053
+ return;
1054
+ }
1055
+ try {
1056
+ await deleteProfile(name);
1057
+ await refreshProfiles();
1058
+ setProfileEnvKey(null);
1059
+ goBack();
1060
+ }
1061
+ catch (err) {
1062
+ openProfileError(err, "Unable to delete profile.");
1063
+ }
1064
+ return;
1065
+ }
1066
+ if (mode === "delete-env") {
1067
+ if (!entry) {
1068
+ openProfileError(new Error("Profile not selected."), "Profile not found.");
1069
+ return;
1070
+ }
1071
+ const envKey = profileEnvKey();
1072
+ if (!envKey) {
1073
+ openProfileError(new Error("Environment variable not selected."), "Select a variable to delete.");
1074
+ return;
1075
+ }
1076
+ const nextEnv = { ...(entry.profile.env ?? {}) };
1077
+ delete nextEnv[envKey];
1078
+ try {
1079
+ await updateProfile(entry.name, { env: nextEnv });
1080
+ await refreshProfiles();
1081
+ setProfileEnvKey(null);
1082
+ goBack();
1083
+ }
1084
+ catch (err) {
1085
+ openProfileError(err, "Unable to update profile.");
1086
+ }
1087
+ }
1088
+ };
1089
+ const toggleSelectedBranch = (branchName) => {
1090
+ if (unsafeSelectionConfirmVisible()) {
1091
+ return;
1092
+ }
1093
+ const currentSelection = new Set(selectedBranches());
1094
+ if (currentSelection.has(branchName)) {
1095
+ currentSelection.delete(branchName);
1096
+ setSelectedBranches(Array.from(currentSelection));
1097
+ return;
1098
+ }
1099
+ const branch = branchItems().find((item) => item.name === branchName);
1100
+ const pending = cleanupSafetyPending();
1101
+ const hasSafetyPending = pending.has(branchName);
1102
+ const hasUncommitted = branch?.worktree?.hasUncommittedChanges === true;
1103
+ const hasUnpushed = branch?.hasUnpushedCommits === true;
1104
+ const isUnmerged = branch?.isUnmerged === true;
1105
+ const safeToCleanup = branch?.safeToCleanup === true;
1106
+ const isRemoteBranch = branch?.type === "remote";
1107
+ const isUnsafe = Boolean(branch) &&
1108
+ !isRemoteBranch &&
1109
+ !hasSafetyPending &&
1110
+ (hasUncommitted || hasUnpushed || isUnmerged || !safeToCleanup);
1111
+ if (branch && isUnsafe) {
1112
+ setUnsafeSelectionTarget(branch.name);
1113
+ setUnsafeSelectionConfirmVisible(true);
1114
+ return;
1115
+ }
1116
+ currentSelection.add(branchName);
1117
+ setSelectedBranches(Array.from(currentSelection));
1118
+ };
1119
+ const confirmUnsafeSelection = (confirmed) => {
1120
+ suppressBranchInputOnce();
1121
+ const target = unsafeSelectionTarget();
1122
+ setUnsafeSelectionConfirmVisible(false);
1123
+ setUnsafeSelectionTarget(null);
1124
+ if (!confirmed || !target) {
1125
+ return;
1126
+ }
1127
+ setSelectedBranches((prev) => prev.includes(target) ? prev : [...prev, target]);
1128
+ };
1129
+ const handleToolSelect = (item) => {
1130
+ setSelectedTool(item.value);
1131
+ navigateTo("mode-select");
1132
+ };
1133
+ const handleModeSelect = (item) => {
1134
+ setSelectedMode(item.value);
1135
+ navigateTo("skip-permissions");
1136
+ };
1137
+ const finalizeSelection = (skipPermissions) => {
1138
+ const branch = selectedBranch();
1139
+ const tool = selectedTool();
1140
+ if (!branch || !tool) {
1141
+ return;
1142
+ }
1143
+ const defaultModel = getDefaultModelOption(tool);
1144
+ const resolvedModel = defaultModel?.id ?? null;
1145
+ const normalizedModel = normalizeModelId(tool, resolvedModel);
1146
+ const resolvedInference = getDefaultInferenceForModel(defaultModel);
1147
+ const baseRef = newBranchBaseRef();
1148
+ exitApp({
1149
+ branch: branch.name,
1150
+ displayName: branch.displayName,
1151
+ branchType: branch.branchType,
1152
+ ...(branch.remoteBranch ? { remoteBranch: branch.remoteBranch } : {}),
1153
+ ...(isNewBranch()
1154
+ ? {
1155
+ isNewBranch: true,
1156
+ ...(baseRef ? { baseBranch: baseRef } : {}),
1157
+ }
1158
+ : {}),
1159
+ tool,
1160
+ mode: selectedMode(),
1161
+ skipPermissions,
1162
+ ...(normalizedModel !== undefined ? { model: normalizedModel } : {}),
1163
+ ...(resolvedInference !== undefined
1164
+ ? { inferenceLevel: resolvedInference }
1165
+ : {}),
1166
+ });
1167
+ };
1168
+ const renderCurrentScreen = () => {
1169
+ const screen = currentScreen();
1170
+ if (screen === "branch-list") {
1171
+ const cleanupUI = {
1172
+ indicators: cleanupIndicators(),
1173
+ footerMessage: branchFooterMessage(),
1174
+ inputLocked: branchInputLocked() || unsafeConfirmInputLocked(),
1175
+ safetyLoading: cleanupSafetyLoading(),
1176
+ safetyPendingBranches: cleanupSafetyPending(),
1177
+ };
1178
+ return (_jsx(BranchListScreen, { branches: branchItems(), stats: stats(), onSelect: handleBranchSelect, onQuit: () => exitApp(undefined), onCleanupCommand: handleCleanupCommand, onRefresh: refreshBranches, onRepairWorktrees: handleRepairWorktrees, loading: loading(), error: error(), loadingIndicatorDelay: props.loadingIndicatorDelay ?? 0, lastUpdated: stats().lastUpdated, version: version(), workingDirectory: workingDirectory(), activeProfile: activeProfile(), onOpenLogs: (branch) => {
1179
+ setLogTargetBranch(branch);
1180
+ setLogSelectedEntry(null);
1181
+ setLogSelectedDate(getTodayLogDate());
1182
+ setLogTailEnabled(false);
1183
+ navigateTo("log-list");
1184
+ }, onOpenProfiles: () => navigateTo("profile"), selectedBranches: selectedBranches(), onToggleSelect: toggleSelectedBranch, onCreateBranch: handleQuickCreate, cleanupUI: cleanupUI, helpVisible: helpVisible(), wizardVisible: wizardVisible(), confirmVisible: unsafeSelectionConfirmVisible(), cursorPosition: branchCursorPosition(), onCursorPositionChange: setBranchCursorPosition }));
1185
+ }
1186
+ if (screen === "tool-select") {
1187
+ if (toolError()) {
1188
+ return (_jsx(ErrorScreen, { error: toolError(), onBack: goBack, hint: "Unable to load available tools." }));
1189
+ }
1190
+ return (_jsx(SelectorScreen, { title: "Select tool", items: toolItems(), onSelect: handleToolSelect, onBack: goBack, helpVisible: helpVisible() }));
1191
+ }
1192
+ if (screen === "mode-select") {
1193
+ return (_jsx(SelectorScreen, { title: "Execution mode", items: [
1194
+ { label: "Normal", value: "normal" },
1195
+ { label: "Continue", value: "continue" },
1196
+ { label: "Resume", value: "resume" },
1197
+ ], onSelect: handleModeSelect, onBack: goBack, helpVisible: helpVisible() }));
1198
+ }
1199
+ if (screen === "skip-permissions") {
1200
+ return (_jsx(SelectorScreen, { title: "Skip permission prompts?", items: [
1201
+ { label: "Yes", value: "true" },
1202
+ { label: "No", value: "false" },
1203
+ ], onSelect: (item) => finalizeSelection(item.value === "true"), onBack: goBack, helpVisible: helpVisible() }));
1204
+ }
1205
+ if (screen === "log-list") {
1206
+ return (_jsx(LogScreen, { entries: logEntries(), loading: logLoading(), error: logError(), onBack: goBack, onSelect: (entry) => {
1207
+ setLogSelectedEntry(entry);
1208
+ navigateTo("log-detail");
1209
+ }, onCopy: async (entry) => {
1210
+ try {
1211
+ await copyToClipboard(entry.json);
1212
+ showLogNotification("Copied to clipboard.", "success");
1213
+ }
1214
+ catch {
1215
+ showLogNotification("Failed to copy to clipboard.", "error");
1216
+ }
1217
+ }, onReload: () => void loadLogEntries(logSelectedDate()), onToggleTail: toggleLogTail, onReset: () => void resetLogFiles(), notification: logNotification(), version: version(), selectedDate: logSelectedDate(), branchLabel: logBranchLabel(), sourceLabel: logSourceLabel(), tailing: logTailEnabled(), helpVisible: helpVisible() }));
1218
+ }
1219
+ if (screen === "log-detail") {
1220
+ return (_jsx(LogDetailScreen, { entry: logSelectedEntry(), onBack: goBack, onCopy: async (entry) => {
1221
+ try {
1222
+ await copyToClipboard(entry.json);
1223
+ showLogNotification("Copied to clipboard.", "success");
1224
+ }
1225
+ catch {
1226
+ showLogNotification("Failed to copy to clipboard.", "error");
1227
+ }
1228
+ }, notification: logNotification(), version: version(), helpVisible: helpVisible() }));
1229
+ }
1230
+ if (screen === "profile") {
1231
+ if (profileError()) {
1232
+ return (_jsx(ErrorScreen, { error: profileError(), onBack: goBack, hint: "Unable to load profiles." }));
1233
+ }
1234
+ return (_jsx(ProfileScreen, { profiles: profileItems(), version: version(), helpVisible: helpVisible(), onCreate: openProfileCreate, onDelete: openProfileDelete, onEdit: openProfileEnv, onSelect: (profile) => {
1235
+ void setActiveProfile(profile.name)
1236
+ .then(() => {
1237
+ void refreshProfiles();
1238
+ })
1239
+ .catch((err) => {
1240
+ openProfileError(err, "Unable to set active profile.");
1241
+ });
1242
+ }, onBack: goBack }));
1243
+ }
1244
+ if (screen === "profile-env") {
1245
+ const entry = selectedProfileConfig();
1246
+ if (!entry) {
1247
+ return (_jsx(ErrorScreen, { error: "Profile not found.", onBack: goBack, hint: "Select a profile before editing." }));
1248
+ }
1249
+ return (_jsx(ProfileEnvScreen, { profileName: entry.name, variables: profileEnvVariables(), onAdd: openProfileEnvAdd, onEdit: openProfileEnvEdit, onDelete: openProfileEnvDelete, onViewOsEnv: () => navigateTo("profile-os-env"), onBack: goBack, version: version(), helpVisible: helpVisible() }));
1250
+ }
1251
+ if (screen === "profile-input") {
1252
+ const mode = profileInputMode();
1253
+ const envKey = profileEnvKey();
1254
+ const message = mode === "create-profile"
1255
+ ? "New profile name"
1256
+ : mode === "add-env"
1257
+ ? "Add environment variable"
1258
+ : `Edit value for ${envKey ?? "(unknown)"}`;
1259
+ const label = mode === "create-profile"
1260
+ ? "Profile name"
1261
+ : mode === "add-env"
1262
+ ? "KEY=VALUE"
1263
+ : "Value";
1264
+ const placeholder = mode === "create-profile"
1265
+ ? "development"
1266
+ : mode === "add-env"
1267
+ ? "MY_VAR=value"
1268
+ : undefined;
1269
+ return (_jsx(InputScreen, { message: message, value: profileInputValue(), onChange: handleProfileInputChange, onSubmit: (value) => void submitProfileInput(value), onCancel: () => {
1270
+ setProfileInputSuppressKey(null);
1271
+ goBack();
1272
+ }, label: label, ...(placeholder !== undefined ? { placeholder } : {}), width: 32, helpVisible: helpVisible() }));
1273
+ }
1274
+ if (screen === "profile-confirm") {
1275
+ const mode = profileConfirmMode();
1276
+ const profileName = selectedProfileName();
1277
+ const envKey = profileEnvKey();
1278
+ const message = mode === "delete-profile"
1279
+ ? `Delete profile ${profileName ?? "(unknown)"}?`
1280
+ : `Delete ${envKey ?? "(unknown)"}?`;
1281
+ return (_jsx(ConfirmScreen, { message: message, onConfirm: (confirmed) => void confirmProfileAction(confirmed), defaultNo: true, helpVisible: helpVisible() }));
1282
+ }
1283
+ if (screen === "profile-os-env") {
1284
+ const highlightKeys = profileEnvVariables().map((variable) => variable.key);
1285
+ return (_jsx(EnvironmentScreen, { variables: osEnvVariables(), highlightKeys: highlightKeys, onBack: goBack, version: version(), helpVisible: helpVisible() }));
1286
+ }
1287
+ if (screen === "profile-error") {
1288
+ return (_jsx(ErrorScreen, { error: profileActionError() ?? "Profile error", onBack: () => {
1289
+ setProfileActionError(null);
1290
+ setProfileActionHint(null);
1291
+ goBack();
1292
+ }, ...(profileActionHint()
1293
+ ? { hint: profileActionHint() }
1294
+ : {}), helpVisible: helpVisible() }));
1295
+ }
1296
+ if (screen === "worktree-create") {
1297
+ const baseBranchRef = resolveBaseBranchRef(creationSource(), null, () => defaultBaseBranch());
1298
+ const baseBranchLabel = resolveBaseBranchLabel(creationSource(), null, () => defaultBaseBranch());
1299
+ return (_jsx(WorktreeCreateScreen, { branchName: createBranchName(), baseBranch: baseBranchLabel, version: version(), helpVisible: helpVisible(), onChange: (value) => {
1300
+ const suppressKey = suppressCreateKey();
1301
+ if (suppressKey &&
1302
+ createBranchName() === "" &&
1303
+ value === suppressKey) {
1304
+ setSuppressCreateKey(null);
1305
+ setCreateBranchName("");
1306
+ return;
1307
+ }
1308
+ setSuppressCreateKey(null);
1309
+ setCreateBranchName(value);
1310
+ }, onSubmit: (value, branchType) => {
1311
+ const trimmed = value.trim();
1312
+ if (!trimmed) {
1313
+ return;
1314
+ }
1315
+ // Add prefix based on selected branch type
1316
+ const prefixKey = branchType.toUpperCase();
1317
+ const prefix = BRANCH_PREFIXES[prefixKey] ?? "";
1318
+ const fullBranchName = `${prefix}${trimmed}`;
1319
+ setSelectedBranch({
1320
+ name: fullBranchName,
1321
+ displayName: fullBranchName,
1322
+ branchType: "local",
1323
+ branchCategory: branchType,
1324
+ });
1325
+ setIsNewBranch(true);
1326
+ setNewBranchBaseRef(baseBranchRef);
1327
+ setSelectedTool(null);
1328
+ setSelectedMode("normal");
1329
+ setSuppressCreateKey(null);
1330
+ navigateTo("tool-select");
1331
+ }, onCancel: () => {
1332
+ setSuppressCreateKey(null);
1333
+ goBack();
1334
+ } }));
1335
+ }
1336
+ if (screen === "loading") {
1337
+ return (_jsx(LoadingIndicatorScreen, { message: "Loading...", delay: props.loadingIndicatorDelay ?? 0 }));
1338
+ }
1339
+ if (screen === "error") {
1340
+ return (_jsx(ErrorScreen, { error: error() ?? "Unknown error", helpVisible: helpVisible() }));
1341
+ }
1342
+ return (_jsx(ErrorScreen, { error: `Unknown screen: ${screen}`, onBack: goBack, helpVisible: helpVisible() }));
1343
+ };
1344
+ return (_jsxs(_Fragment, { children: [renderCurrentScreen(), unsafeSelectionConfirmVisible() && (_jsx("box", { position: "absolute", top: "30%", left: "20%", width: unsafeConfirmBoxWidth(), zIndex: 110, border: true, borderStyle: "single", borderColor: "yellow", backgroundColor: "black", padding: 1, children: _jsx(ConfirmScreen, { message: UNSAFE_SELECTION_MESSAGE, onConfirm: confirmUnsafeSelection, yesLabel: "OK", noLabel: "Cancel", defaultNo: true, helpVisible: helpVisible(), width: unsafeConfirmContentWidth() }) })), _jsx(HelpOverlay, { visible: helpVisible(), context: currentScreen() }), _jsx(WizardController, { visible: wizardVisible(), selectedBranchName: selectedBranch()?.name ?? "", history: quickStartHistory(), onClose: handleWizardClose, onComplete: handleWizardComplete, onResume: handleWizardResume, onStartNew: handleWizardStartNew })] }));
1345
+ }
1346
+ const withTimeout = async (promise, timeoutMs) => new Promise((resolve, reject) => {
1347
+ const timer = setTimeout(() => {
1348
+ reject(new Error("timeout"));
1349
+ }, timeoutMs);
1350
+ promise
1351
+ .then((value) => {
1352
+ clearTimeout(timer);
1353
+ resolve(value);
1354
+ })
1355
+ .catch((err) => {
1356
+ clearTimeout(timer);
1357
+ reject(err);
1358
+ });
1359
+ });
1360
+ const buildBranchList = (branches, worktrees, lastToolUsageMap) => {
1361
+ const localBranchNames = new Set(branches.filter((branch) => branch.type === "local").map((b) => b.name));
1362
+ const filtered = branches.filter((branch) => {
1363
+ if (branch.type === "remote") {
1364
+ const remoteName = branch.name.replace(/^origin\//, "");
1365
+ return !localBranchNames.has(remoteName);
1366
+ }
1367
+ return true;
1368
+ });
1369
+ const worktreeMap = new Map();
1370
+ for (const worktree of worktrees) {
1371
+ worktreeMap.set(worktree.branch, {
1372
+ path: worktree.path,
1373
+ locked: worktree.locked ?? false,
1374
+ prunable: worktree.prunable ?? false,
1375
+ isAccessible: worktree.isAccessible ?? true,
1376
+ ...(worktree.hasUncommittedChanges !== undefined
1377
+ ? { hasUncommittedChanges: worktree.hasUncommittedChanges }
1378
+ : {}),
1379
+ });
1380
+ }
1381
+ const enriched = filtered.map((branch) => {
1382
+ const lastToolUsage = lastToolUsageMap?.get(branch.name);
1383
+ const baseBranch = lastToolUsage ? { ...branch, lastToolUsage } : branch;
1384
+ if (branch.type === "local") {
1385
+ const worktree = worktreeMap.get(branch.name);
1386
+ if (worktree) {
1387
+ return { ...baseBranch, worktree };
1388
+ }
1389
+ }
1390
+ return baseBranch;
1391
+ });
1392
+ const items = formatBranchItems(enriched, worktreeMap);
1393
+ return { items, worktreeMap };
1394
+ };
1395
+ //# sourceMappingURL=App.solid.js.map