@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,93 @@
1
+ /**
2
+ * Version cache for coding agents (FR-028 ~ FR-031)
3
+ *
4
+ * Provides caching mechanism for npm package versions to avoid
5
+ * repeated API calls during wizard navigation.
6
+ */
7
+
8
+ import type { VersionInfo } from "../../../utils/npmRegistry.js";
9
+
10
+ /**
11
+ * In-memory cache for agent versions
12
+ * Maps agentId -> VersionInfo[]
13
+ */
14
+ const versionCache = new Map<string, VersionInfo[]>();
15
+
16
+ /**
17
+ * Type for version fetch function (injectable for testing)
18
+ */
19
+ export type VersionFetcher = (agentId: string) => Promise<VersionInfo[]>;
20
+
21
+ /**
22
+ * Get cached versions for an agent
23
+ * @returns Cached versions or null if not cached
24
+ */
25
+ export function getVersionCache(agentId: string): VersionInfo[] | null {
26
+ const cached = versionCache.get(agentId);
27
+ return cached !== undefined ? cached : null;
28
+ }
29
+
30
+ /**
31
+ * Check if versions are cached for an agent
32
+ */
33
+ export function isVersionCachePopulated(agentId: string): boolean {
34
+ return versionCache.has(agentId);
35
+ }
36
+
37
+ /**
38
+ * Clear all cached versions
39
+ */
40
+ export function clearVersionCache(): void {
41
+ versionCache.clear();
42
+ }
43
+
44
+ /**
45
+ * Prefetch versions for multiple agents in parallel
46
+ * This should be called at application startup
47
+ *
48
+ * @param agentIds - List of agent IDs to prefetch versions for
49
+ * @param fetchFn - Optional custom fetch function (for testing)
50
+ */
51
+ export async function prefetchAgentVersions(
52
+ agentIds: string[],
53
+ fetchFn?: VersionFetcher,
54
+ ): Promise<void> {
55
+ // Import default fetcher if not provided
56
+ const fetcher =
57
+ fetchFn ??
58
+ (async (agentId: string) => {
59
+ const { fetchVersionOptionsForAgent } =
60
+ await import("./versionFetcher.js");
61
+ return fetchVersionOptionsForAgent(agentId);
62
+ });
63
+
64
+ // Fetch all versions in parallel
65
+ const results = await Promise.allSettled(
66
+ agentIds.map(async (agentId) => {
67
+ try {
68
+ const versions = await fetcher(agentId);
69
+ versionCache.set(agentId, versions);
70
+ } catch {
71
+ // On error, don't set cache (getVersionCache will return null)
72
+ }
73
+ }),
74
+ );
75
+
76
+ // Log any failures for debugging (silently handled)
77
+ for (let i = 0; i < results.length; i++) {
78
+ const result = results[i];
79
+ if (result && result.status === "rejected") {
80
+ // Silently handle - cache will return null for this agent
81
+ }
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Set versions in cache (for testing or direct population)
87
+ */
88
+ export function setVersionCache(
89
+ agentId: string,
90
+ versions: VersionInfo[],
91
+ ): void {
92
+ versionCache.set(agentId, versions);
93
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Version fetcher for coding agents
3
+ *
4
+ * Provides functions to fetch version information from npm registry
5
+ * and local installations.
6
+ */
7
+
8
+ import type { VersionInfo } from "../../../utils/npmRegistry.js";
9
+ import {
10
+ fetchPackageVersions,
11
+ parsePackageCommand,
12
+ } from "../../../utils/npmRegistry.js";
13
+ import { BUILTIN_CODING_AGENTS } from "../../../config/builtin-coding-agents.js";
14
+ import { findCommand } from "../../../utils/command.js";
15
+ import type { SelectInputItem } from "../components/solid/SelectInput.js";
16
+
17
+ /**
18
+ * Get package name for an agent ID (only for bunx-type agents)
19
+ */
20
+ export function getPackageNameForAgent(agentId: string): string | null {
21
+ const agent = BUILTIN_CODING_AGENTS.find((a) => a.id === agentId);
22
+ if (!agent || agent.type !== "bunx") {
23
+ return null;
24
+ }
25
+ const { packageName } = parsePackageCommand(agent.command);
26
+ return packageName;
27
+ }
28
+
29
+ /**
30
+ * Fetch version options for an agent from npm registry
31
+ */
32
+ export async function fetchVersionOptionsForAgent(
33
+ agentId: string,
34
+ ): Promise<VersionInfo[]> {
35
+ const packageName = getPackageNameForAgent(agentId);
36
+ if (!packageName) {
37
+ return [];
38
+ }
39
+ return fetchPackageVersions(packageName);
40
+ }
41
+
42
+ /**
43
+ * Agent ID to command name mapping
44
+ */
45
+ const AGENT_COMMAND_MAP: Record<string, string> = {
46
+ "claude-code": "claude",
47
+ "codex-cli": "codex",
48
+ "gemini-cli": "gemini",
49
+ opencode: "opencode",
50
+ };
51
+
52
+ /**
53
+ * Installed version information
54
+ */
55
+ export interface InstalledVersionInfo {
56
+ version: string;
57
+ path: string;
58
+ }
59
+
60
+ /**
61
+ * Fetch installed version information for an agent
62
+ * Returns null if not installed locally
63
+ */
64
+ export async function fetchInstalledVersionForAgent(
65
+ agentId: string,
66
+ ): Promise<InstalledVersionInfo | null> {
67
+ const commandName = AGENT_COMMAND_MAP[agentId];
68
+ if (!commandName) {
69
+ return null;
70
+ }
71
+
72
+ const result = await findCommand(commandName);
73
+ if (result.source !== "installed" || !result.path) {
74
+ return null;
75
+ }
76
+
77
+ // Version format: v1.0.3 -> 1.0.3
78
+ const version = result.version?.replace(/^v/, "") ?? "unknown";
79
+
80
+ return {
81
+ version,
82
+ path: result.path,
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Convert VersionInfo to SelectInputItem for UI
88
+ */
89
+ export function versionInfoToSelectItem(v: VersionInfo): SelectInputItem {
90
+ const item: SelectInputItem = {
91
+ label: v.isPrerelease ? `${v.version} (pre)` : v.version,
92
+ value: v.version,
93
+ };
94
+ if (v.publishedAt) {
95
+ item.description = new Date(v.publishedAt).toLocaleDateString();
96
+ }
97
+ return item;
98
+ }
99
+
100
+ /**
101
+ * Create installed option for SelectInput
102
+ */
103
+ export function createInstalledOption(
104
+ installed: InstalledVersionInfo,
105
+ ): SelectInputItem {
106
+ return {
107
+ label: `installed@${installed.version}`,
108
+ value: "installed",
109
+ description: installed.path,
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Get all bunx-type agent IDs
115
+ */
116
+ export function getBunxAgentIds(): string[] {
117
+ return BUILTIN_CODING_AGENTS.filter((a) => a.type === "bunx").map(
118
+ (a) => a.id,
119
+ );
120
+ }
package/src/codex.ts CHANGED
@@ -6,10 +6,19 @@ import {
6
6
  createChildStdio,
7
7
  getTerminalStreams,
8
8
  resetTerminalModes,
9
+ writeTerminalLine,
9
10
  } from "./utils/terminal.js";
10
- import { findLatestCodexSession } from "./utils/session.js";
11
+ import {
12
+ findLatestCodexSession,
13
+ waitForCodexSessionId,
14
+ } from "./utils/session.js";
15
+ import { findCommand } from "./utils/command.js";
16
+ import {
17
+ runAgentWithPty,
18
+ shouldCaptureAgentOutput,
19
+ } from "./logging/agentOutput.js";
11
20
 
12
- const CODEX_CLI_PACKAGE = "@openai/codex@latest";
21
+ const CODEX_CLI_PACKAGE = "@openai/codex";
13
22
 
14
23
  /**
15
24
  * Reasoning effort levels supported by Codex CLI.
@@ -91,6 +100,8 @@ export async function launchCodexCLI(
91
100
  model?: string;
92
101
  reasoningEffort?: CodexReasoningEffort;
93
102
  sessionId?: string | null;
103
+ branch?: string | null;
104
+ version?: string | null;
94
105
  } = {},
95
106
  ): Promise<{ sessionId?: string | null }> {
96
107
  const terminal = getTerminalStreams();
@@ -101,16 +112,16 @@ export async function launchCodexCLI(
101
112
  throw new Error(`Worktree path does not exist: ${worktreePath}`);
102
113
  }
103
114
 
104
- console.log(chalk.blue("🚀 Launching Codex CLI..."));
105
- console.log(chalk.gray(` Working directory: ${worktreePath}`));
115
+ writeTerminalLine(chalk.blue("🚀 Launching Codex CLI..."));
116
+ writeTerminalLine(chalk.gray(` Working directory: ${worktreePath}`));
106
117
 
107
118
  const args: string[] = [];
108
119
  const model = options.model ?? DEFAULT_CODEX_MODEL;
109
120
  const reasoningEffort =
110
121
  options.reasoningEffort ?? DEFAULT_CODEX_REASONING_EFFORT;
111
122
 
112
- console.log(chalk.green(` 🎯 Model: ${model}`));
113
- console.log(chalk.green(` 🧠 Reasoning: ${reasoningEffort}`));
123
+ writeTerminalLine(chalk.green(` 🎯 Model: ${model}`));
124
+ writeTerminalLine(chalk.green(` 🧠 Reasoning: ${reasoningEffort}`));
114
125
 
115
126
  const resumeSessionId =
116
127
  options.sessionId && options.sessionId.trim().length > 0
@@ -124,36 +135,36 @@ export async function launchCodexCLI(
124
135
  case "continue":
125
136
  if (resumeSessionId) {
126
137
  args.push("resume", resumeSessionId);
127
- console.log(
138
+ writeTerminalLine(
128
139
  chalk.cyan(
129
140
  ` ⏭️ Resuming specific Codex session: ${resumeSessionId}`,
130
141
  ),
131
142
  );
132
143
  } else {
133
144
  args.push("resume", "--last");
134
- console.log(chalk.cyan(" ⏭️ Resuming last Codex session"));
145
+ writeTerminalLine(chalk.cyan(" ⏭️ Resuming last Codex session"));
135
146
  }
136
147
  break;
137
148
  case "resume":
138
149
  if (resumeSessionId) {
139
150
  args.push("resume", resumeSessionId);
140
- console.log(
151
+ writeTerminalLine(
141
152
  chalk.cyan(` 🔄 Resuming Codex session: ${resumeSessionId}`),
142
153
  );
143
154
  } else {
144
155
  args.push("resume");
145
- console.log(chalk.cyan(" 🔄 Resume command"));
156
+ writeTerminalLine(chalk.cyan(" 🔄 Resume command"));
146
157
  }
147
158
  break;
148
159
  case "normal":
149
160
  default:
150
- console.log(chalk.green(" ✨ Starting new session"));
161
+ writeTerminalLine(chalk.green(" ✨ Starting new session"));
151
162
  break;
152
163
  }
153
164
 
154
165
  if (options.bypassApprovals) {
155
166
  args.push("--yolo");
156
- console.log(chalk.yellow(" ⚠️ Bypassing approvals and sandbox"));
167
+ writeTerminalLine(chalk.yellow(" ⚠️ Bypassing approvals and sandbox"));
157
168
  }
158
169
 
159
170
  if (options.extraArgs && options.extraArgs.length > 0) {
@@ -164,13 +175,11 @@ export async function launchCodexCLI(
164
175
 
165
176
  args.push(...codexArgs);
166
177
 
167
- console.log(chalk.gray(` 📋 Args: ${args.join(" ")}`));
178
+ writeTerminalLine(chalk.gray(` 📋 Args: ${args.join(" ")}`));
168
179
 
169
180
  terminal.exitRawMode();
170
181
  resetTerminalModes(terminal.stdout);
171
182
 
172
- const childStdio = createChildStdio();
173
-
174
183
  const env = Object.fromEntries(
175
184
  Object.entries({
176
185
  ...process.env,
@@ -179,22 +188,53 @@ export async function launchCodexCLI(
179
188
  (entry): entry is [string, string] => typeof entry[1] === "string",
180
189
  ),
181
190
  );
191
+ const captureOutput = shouldCaptureAgentOutput(env);
192
+ const childStdio = captureOutput ? null : createChildStdio();
182
193
 
183
- try {
184
- const execChild = async (child: Promise<unknown>) => {
185
- try {
186
- await child;
187
- } catch (execError: unknown) {
188
- // Treat SIGINT/SIGTERM as normal exit (user pressed Ctrl+C)
189
- const signal = (execError as { signal?: unknown })?.signal;
190
- if (signal === "SIGINT" || signal === "SIGTERM") {
191
- return;
192
- }
193
- throw execError;
194
+ // Auto-detect locally installed codex command
195
+ const codexLookup = await findCommand("codex");
196
+
197
+ const execChild = async (child: Promise<unknown>) => {
198
+ try {
199
+ await child;
200
+ } catch (execError: unknown) {
201
+ // Treat SIGINT/SIGTERM as normal exit (user pressed Ctrl+C)
202
+ const signal = (execError as { signal?: unknown })?.signal;
203
+ if (signal === "SIGINT" || signal === "SIGTERM") {
204
+ return;
205
+ }
206
+ throw execError;
207
+ }
208
+ };
209
+ // Treat SIGHUP (1), SIGINT (2), SIGTERM (15) as normal exit signals
210
+ // SIGHUP can occur when the PTY closes, SIGINT/SIGTERM are user interrupts
211
+ const isNormalExitSignal = (signal?: number | null) =>
212
+ signal === 1 || signal === 2 || signal === 15;
213
+ const runCommand = async (command: string, commandArgs: string[]) => {
214
+ if (captureOutput) {
215
+ const result = await runAgentWithPty({
216
+ command,
217
+ args: commandArgs,
218
+ cwd: worktreePath,
219
+ env,
220
+ agentId: "codex-cli",
221
+ });
222
+ if (isNormalExitSignal(result.signal)) {
223
+ return;
194
224
  }
195
- };
225
+ if (result.exitCode !== null && result.exitCode !== 0) {
226
+ throw new Error(
227
+ `Codex CLI exited with code ${result.exitCode ?? "unknown"}`,
228
+ );
229
+ }
230
+ return;
231
+ }
232
+
233
+ if (!childStdio) {
234
+ return;
235
+ }
196
236
 
197
- const child = execa("bunx", [CODEX_CLI_PACKAGE, ...args], {
237
+ const child = execa(command, commandArgs, {
198
238
  cwd: worktreePath,
199
239
  stdin: childStdio.stdin,
200
240
  stdout: childStdio.stdout,
@@ -202,12 +242,50 @@ export async function launchCodexCLI(
202
242
  env,
203
243
  });
204
244
  await execChild(child);
245
+ };
246
+
247
+ // Determine execution strategy based on version selection
248
+ // FR-063b: "installed" option only appears when local command exists
249
+ const requestedVersion = options.version ?? "latest";
250
+ let selectedVersion = requestedVersion;
251
+
252
+ if (requestedVersion === "installed" && !codexLookup.path) {
253
+ writeTerminalLine(
254
+ chalk.yellow(
255
+ " ⚠️ Installed codex command not found. Falling back to latest.",
256
+ ),
257
+ );
258
+ selectedVersion = "latest";
259
+ }
260
+
261
+ // Log version information (FR-072)
262
+ if (selectedVersion === "installed") {
263
+ writeTerminalLine(chalk.green(` 📦 Version: installed`));
264
+ } else {
265
+ writeTerminalLine(chalk.green(` 📦 Version: @${selectedVersion}`));
266
+ }
267
+
268
+ try {
269
+ if (selectedVersion === "installed" && codexLookup.path) {
270
+ // FR-066: Use locally installed command when "installed" is selected
271
+ // FR-063b guarantees local command exists when this option is shown
272
+ writeTerminalLine(
273
+ chalk.green(" ✨ Using locally installed codex command"),
274
+ );
275
+ await runCommand(codexLookup.path, args);
276
+ } else {
277
+ // FR-067, FR-068: Use bunx with version suffix for latest/specific versions
278
+ const packageWithVersion = `${CODEX_CLI_PACKAGE}@${selectedVersion}`;
279
+ writeTerminalLine(chalk.cyan(` 🔄 Using bunx ${packageWithVersion}`));
280
+
281
+ await runCommand("bunx", [packageWithVersion, ...args]);
282
+ }
205
283
  } finally {
206
- childStdio.cleanup();
284
+ childStdio?.cleanup();
207
285
  }
208
286
 
209
287
  // File-based session detection only - no stdout capture
210
- // Use only findLatestCodexSession with short timeout, skip sessionProbe to avoid hanging
288
+ // Use only file inspection with a short wait to avoid hanging
211
289
  let capturedSessionId: string | null = null;
212
290
  const finishedAt = Date.now();
213
291
  try {
@@ -217,6 +295,10 @@ export async function launchCodexCLI(
217
295
  preferClosestTo: finishedAt,
218
296
  windowMs: 10 * 60 * 1000,
219
297
  cwd: worktreePath,
298
+ branch: options.branch ?? null,
299
+ worktrees: options.branch
300
+ ? [{ path: worktreePath, branch: options.branch }]
301
+ : null,
220
302
  });
221
303
  const detectedSessionId = latest?.id ?? null;
222
304
  // When we explicitly resumed a specific session, keep that ID as the source of truth.
@@ -226,14 +308,25 @@ export async function launchCodexCLI(
226
308
  } catch {
227
309
  capturedSessionId = usedExplicitSessionId ? resumeSessionId : null;
228
310
  }
311
+ const shouldSkipWait =
312
+ typeof process !== "undefined" &&
313
+ (process.env?.NODE_ENV === "test" || Boolean(process.env?.VITEST));
314
+ if (!capturedSessionId && !shouldSkipWait) {
315
+ capturedSessionId = await waitForCodexSessionId({
316
+ startedAt,
317
+ timeoutMs: 15_000,
318
+ pollIntervalMs: 1_000,
319
+ cwd: worktreePath,
320
+ });
321
+ }
229
322
 
230
323
  if (capturedSessionId) {
231
- console.log(chalk.cyan(`\n 🆔 Session ID: ${capturedSessionId}`));
232
- console.log(
324
+ writeTerminalLine(chalk.cyan(`\n 🆔 Session ID: ${capturedSessionId}`));
325
+ writeTerminalLine(
233
326
  chalk.gray(` Resume command: codex resume ${capturedSessionId}`),
234
327
  );
235
328
  } else {
236
- console.log(
329
+ writeTerminalLine(
237
330
  chalk.yellow(
238
331
  "\n ℹ️ Could not determine Codex session ID automatically.",
239
332
  ),
@@ -250,19 +343,25 @@ export async function launchCodexCLI(
250
343
  : `Failed to launch Codex CLI: ${details || "Unknown error"}`;
251
344
 
252
345
  if (platform() === "win32") {
253
- console.error(chalk.red("\n💡 Windows troubleshooting tips:"));
254
- console.error(
346
+ writeTerminalLine(
347
+ chalk.red("\n💡 Windows troubleshooting tips:"),
348
+ "stderr",
349
+ );
350
+ writeTerminalLine(
255
351
  chalk.yellow(
256
352
  " 1. Confirm that Bun is installed and bunx is available",
257
353
  ),
354
+ "stderr",
258
355
  );
259
- console.error(
356
+ writeTerminalLine(
260
357
  chalk.yellow(
261
358
  ' 2. Run "bunx @openai/codex@latest -- --help" to verify the setup',
262
359
  ),
360
+ "stderr",
263
361
  );
264
- console.error(
362
+ writeTerminalLine(
265
363
  chalk.yellow(" 3. Restart your terminal or IDE to refresh PATH"),
364
+ "stderr",
266
365
  );
267
366
  }
268
367
 
@@ -278,12 +377,12 @@ export async function launchCodexCLI(
278
377
  */
279
378
  export async function isCodexAvailable(): Promise<boolean> {
280
379
  try {
281
- await execa("bunx", [CODEX_CLI_PACKAGE, "--help"]);
380
+ await execa("bunx", [`${CODEX_CLI_PACKAGE}@latest`, "--help"]);
282
381
  return true;
283
382
  } catch (error: unknown) {
284
383
  const err = error as NodeJS.ErrnoException;
285
384
  if (err.code === "ENOENT") {
286
- console.error(chalk.yellow("\n⚠️ bunx command not found"));
385
+ writeTerminalLine(chalk.yellow("\n⚠️ bunx command not found"), "stderr");
287
386
  }
288
387
  return false;
289
388
  }
@@ -0,0 +1,143 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "bun:test";
2
+ import { mkdir, rm } from "fs/promises";
3
+ import { join } from "path";
4
+ import { tmpdir } from "os";
5
+ import { saveSession, loadSession } from "../index.js";
6
+
7
+ describe("saveSession", () => {
8
+ let testDir: string;
9
+ let testRepoRoot: string;
10
+
11
+ beforeEach(async () => {
12
+ // Create a unique temporary directory for each test
13
+ testDir = join(
14
+ tmpdir(),
15
+ `gwt-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
16
+ );
17
+ testRepoRoot = join(testDir, "test-repo");
18
+ await mkdir(testRepoRoot, { recursive: true });
19
+ });
20
+
21
+ afterEach(async () => {
22
+ // Clean up temporary directory
23
+ try {
24
+ await rm(testDir, { recursive: true, force: true });
25
+ } catch {
26
+ // Ignore cleanup errors
27
+ }
28
+ });
29
+
30
+ it("should save toolVersion to session history", async () => {
31
+ // Arrange
32
+ const sessionData = {
33
+ lastWorktreePath: testRepoRoot,
34
+ lastBranch: "feature/test",
35
+ lastUsedTool: "claude-code",
36
+ toolLabel: "Claude Code",
37
+ mode: "normal" as const,
38
+ model: "opus",
39
+ reasoningLevel: "high",
40
+ skipPermissions: false,
41
+ toolVersion: "2.1.1",
42
+ timestamp: Date.now(),
43
+ repositoryRoot: testRepoRoot,
44
+ };
45
+
46
+ // Act
47
+ await saveSession(sessionData);
48
+ const loaded = await loadSession(testRepoRoot);
49
+
50
+ // Assert
51
+ expect(loaded).not.toBeNull();
52
+ expect(loaded?.history).toHaveLength(1);
53
+ expect(loaded?.history?.[0]?.toolVersion).toBe("2.1.1");
54
+ });
55
+
56
+ it("should save latest toolVersion when not provided", async () => {
57
+ // Arrange
58
+ const sessionData = {
59
+ lastWorktreePath: testRepoRoot,
60
+ lastBranch: "feature/test",
61
+ lastUsedTool: "claude-code",
62
+ toolLabel: "Claude Code",
63
+ mode: "normal" as const,
64
+ model: "opus",
65
+ timestamp: Date.now(),
66
+ repositoryRoot: testRepoRoot,
67
+ };
68
+
69
+ // Act
70
+ await saveSession(sessionData);
71
+ const loaded = await loadSession(testRepoRoot);
72
+
73
+ // Assert
74
+ expect(loaded).not.toBeNull();
75
+ expect(loaded?.history).toHaveLength(1);
76
+ expect(loaded?.history?.[0]?.toolVersion).toBe("latest");
77
+ });
78
+
79
+ it("should preserve toolVersion across multiple saves", async () => {
80
+ // Arrange - first save with version 1.0.0
81
+ await saveSession({
82
+ lastWorktreePath: testRepoRoot,
83
+ lastBranch: "feature/test",
84
+ lastUsedTool: "claude-code",
85
+ toolLabel: "Claude Code",
86
+ toolVersion: "1.0.0",
87
+ timestamp: Date.now() - 1000,
88
+ repositoryRoot: testRepoRoot,
89
+ });
90
+
91
+ // Act - second save with version 2.0.0
92
+ await saveSession({
93
+ lastWorktreePath: testRepoRoot,
94
+ lastBranch: "feature/test",
95
+ lastUsedTool: "claude-code",
96
+ toolLabel: "Claude Code",
97
+ toolVersion: "2.0.0",
98
+ timestamp: Date.now(),
99
+ repositoryRoot: testRepoRoot,
100
+ });
101
+
102
+ const loaded = await loadSession(testRepoRoot);
103
+
104
+ // Assert - should have 2 entries with different versions
105
+ expect(loaded?.history).toHaveLength(2);
106
+ // History is stored oldest first (newest at the end)
107
+ expect(loaded?.history?.[0]?.toolVersion).toBe("1.0.0");
108
+ expect(loaded?.history?.[1]?.toolVersion).toBe("2.0.0");
109
+ });
110
+
111
+ it("should not add to history when skipHistory is true", async () => {
112
+ // Arrange - first save
113
+ await saveSession({
114
+ lastWorktreePath: testRepoRoot,
115
+ lastBranch: "feature/test",
116
+ lastUsedTool: "claude-code",
117
+ toolLabel: "Claude Code",
118
+ toolVersion: "1.0.0",
119
+ timestamp: Date.now(),
120
+ repositoryRoot: testRepoRoot,
121
+ });
122
+
123
+ // Act - second save with skipHistory
124
+ await saveSession(
125
+ {
126
+ lastWorktreePath: testRepoRoot,
127
+ lastBranch: "feature/test",
128
+ lastUsedTool: "claude-code",
129
+ toolLabel: "Claude Code",
130
+ toolVersion: "2.0.0",
131
+ timestamp: Date.now(),
132
+ repositoryRoot: testRepoRoot,
133
+ },
134
+ { skipHistory: true },
135
+ );
136
+
137
+ const loaded = await loadSession(testRepoRoot);
138
+
139
+ // Assert - should still have only 1 entry
140
+ expect(loaded?.history).toHaveLength(1);
141
+ expect(loaded?.history?.[0]?.toolVersion).toBe("1.0.0");
142
+ });
143
+ });