@akiojin/gwt 2.12.1 → 2.14.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 (344) hide show
  1. package/README.ja.md +33 -0
  2. package/README.md +31 -0
  3. package/dist/claude.d.ts.map +1 -1
  4. package/dist/claude.js +17 -11
  5. package/dist/claude.js.map +1 -1
  6. package/dist/cli/ui/components/App.d.ts +0 -6
  7. package/dist/cli/ui/components/App.d.ts.map +1 -1
  8. package/dist/cli/ui/components/App.js +93 -85
  9. package/dist/cli/ui/components/App.js.map +1 -1
  10. package/dist/cli/ui/components/common/Select.js +2 -2
  11. package/dist/cli/ui/components/common/Select.js.map +1 -1
  12. package/dist/cli/ui/components/screens/BranchListScreen.d.ts +3 -1
  13. package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
  14. package/dist/cli/ui/components/screens/BranchListScreen.js +168 -34
  15. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  16. package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts.map +1 -1
  17. package/dist/cli/ui/components/screens/BranchQuickStartScreen.js +3 -3
  18. package/dist/cli/ui/components/screens/BranchQuickStartScreen.js.map +1 -1
  19. package/dist/cli/ui/hooks/useGitData.d.ts.map +1 -1
  20. package/dist/cli/ui/hooks/useGitData.js +17 -0
  21. package/dist/cli/ui/hooks/useGitData.js.map +1 -1
  22. package/dist/cli/ui/types.d.ts +2 -0
  23. package/dist/cli/ui/types.d.ts.map +1 -1
  24. package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
  25. package/dist/cli/ui/utils/branchFormatter.js +7 -2
  26. package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
  27. package/dist/cli/ui/utils/continueSession.d.ts.map +1 -1
  28. package/dist/cli/ui/utils/continueSession.js +1 -1
  29. package/dist/cli/ui/utils/continueSession.js.map +1 -1
  30. package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
  31. package/dist/cli/ui/utils/modelOptions.js +7 -0
  32. package/dist/cli/ui/utils/modelOptions.js.map +1 -1
  33. package/dist/client/assets/index-DPWWHorC.js +72 -0
  34. package/dist/client/assets/index-DsDNCy5f.css +1 -0
  35. package/dist/client/index.html +2 -2
  36. package/dist/codex.d.ts.map +1 -1
  37. package/dist/codex.js +21 -11
  38. package/dist/codex.js.map +1 -1
  39. package/dist/config/builtin-tools.d.ts.map +1 -1
  40. package/dist/config/builtin-tools.js +3 -2
  41. package/dist/config/builtin-tools.js.map +1 -1
  42. package/dist/config/shared-env.d.ts +41 -0
  43. package/dist/config/shared-env.d.ts.map +1 -0
  44. package/dist/config/shared-env.js +114 -0
  45. package/dist/config/shared-env.js.map +1 -0
  46. package/dist/gemini.d.ts.map +1 -1
  47. package/dist/gemini.js +20 -17
  48. package/dist/gemini.js.map +1 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +55 -7
  51. package/dist/index.js.map +1 -1
  52. package/dist/logging/logger.d.ts +24 -0
  53. package/dist/logging/logger.d.ts.map +1 -0
  54. package/dist/logging/logger.js +60 -0
  55. package/dist/logging/logger.js.map +1 -0
  56. package/dist/logging/rotation.d.ts +6 -0
  57. package/dist/logging/rotation.d.ts.map +1 -0
  58. package/dist/logging/rotation.js +26 -0
  59. package/dist/logging/rotation.js.map +1 -0
  60. package/dist/qwen.d.ts.map +1 -1
  61. package/dist/qwen.js +15 -11
  62. package/dist/qwen.js.map +1 -1
  63. package/dist/services/aiToolResolver.d.ts +41 -0
  64. package/dist/services/aiToolResolver.d.ts.map +1 -0
  65. package/dist/services/aiToolResolver.js +194 -0
  66. package/dist/services/aiToolResolver.js.map +1 -0
  67. package/dist/services/customToolResolver.d.ts +10 -0
  68. package/dist/services/customToolResolver.d.ts.map +1 -0
  69. package/dist/services/customToolResolver.js +71 -0
  70. package/dist/services/customToolResolver.js.map +1 -0
  71. package/dist/shared/aiToolConstants.d.ts +9 -0
  72. package/dist/shared/aiToolConstants.d.ts.map +1 -0
  73. package/dist/shared/aiToolConstants.js +29 -0
  74. package/dist/shared/aiToolConstants.js.map +1 -0
  75. package/dist/types/tools.d.ts +12 -0
  76. package/dist/types/tools.d.ts.map +1 -1
  77. package/dist/utils/prompt.d.ts.map +1 -1
  78. package/dist/utils/prompt.js.map +1 -1
  79. package/dist/utils/session.d.ts.map +1 -1
  80. package/dist/utils/session.js +15 -6
  81. package/dist/utils/session.js.map +1 -1
  82. package/dist/utils/terminal.d.ts +12 -3
  83. package/dist/utils/terminal.d.ts.map +1 -1
  84. package/dist/utils/terminal.js +5 -34
  85. package/dist/utils/terminal.js.map +1 -1
  86. package/dist/utils/webui.d.ts +8 -0
  87. package/dist/utils/webui.d.ts.map +1 -0
  88. package/dist/utils/webui.js +35 -0
  89. package/dist/utils/webui.js.map +1 -0
  90. package/dist/web/client/src/components/AIToolLaunchModal.d.ts +9 -0
  91. package/dist/web/client/src/components/AIToolLaunchModal.d.ts.map +1 -0
  92. package/dist/web/client/src/components/AIToolLaunchModal.js +363 -0
  93. package/dist/web/client/src/components/AIToolLaunchModal.js.map +1 -0
  94. package/dist/web/client/src/components/BranchGraph.d.ts.map +1 -1
  95. package/dist/web/client/src/components/BranchGraph.js +46 -49
  96. package/dist/web/client/src/components/BranchGraph.js.map +1 -1
  97. package/dist/web/client/src/components/CustomToolForm.d.ts +23 -0
  98. package/dist/web/client/src/components/CustomToolForm.d.ts.map +1 -0
  99. package/dist/web/client/src/components/CustomToolForm.js +209 -0
  100. package/dist/web/client/src/components/CustomToolForm.js.map +1 -0
  101. package/dist/web/client/src/components/CustomToolList.d.ts +10 -0
  102. package/dist/web/client/src/components/CustomToolList.d.ts.map +1 -0
  103. package/dist/web/client/src/components/CustomToolList.js +57 -0
  104. package/dist/web/client/src/components/CustomToolList.js.map +1 -0
  105. package/dist/web/client/src/components/EnvEditor.d.ts.map +1 -1
  106. package/dist/web/client/src/components/EnvEditor.js +33 -26
  107. package/dist/web/client/src/components/EnvEditor.js.map +1 -1
  108. package/dist/web/client/src/components/EnvironmentEditor.d.ts +17 -0
  109. package/dist/web/client/src/components/EnvironmentEditor.d.ts.map +1 -0
  110. package/dist/web/client/src/components/EnvironmentEditor.js +22 -0
  111. package/dist/web/client/src/components/EnvironmentEditor.js.map +1 -0
  112. package/dist/web/client/src/components/Terminal.d.ts.map +1 -1
  113. package/dist/web/client/src/components/Terminal.js +10 -3
  114. package/dist/web/client/src/components/Terminal.js.map +1 -1
  115. package/dist/web/client/src/components/branch-detail/BranchInfoCards.d.ts +10 -0
  116. package/dist/web/client/src/components/branch-detail/BranchInfoCards.d.ts.map +1 -0
  117. package/dist/web/client/src/components/branch-detail/BranchInfoCards.js +104 -0
  118. package/dist/web/client/src/components/branch-detail/BranchInfoCards.js.map +1 -0
  119. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts +22 -0
  120. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts.map +1 -0
  121. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js +79 -0
  122. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js.map +1 -0
  123. package/dist/web/client/src/components/branch-detail/TerminalPanel.d.ts +11 -0
  124. package/dist/web/client/src/components/branch-detail/TerminalPanel.d.ts.map +1 -0
  125. package/dist/web/client/src/components/branch-detail/TerminalPanel.js +32 -0
  126. package/dist/web/client/src/components/branch-detail/TerminalPanel.js.map +1 -0
  127. package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts +40 -0
  128. package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts.map +1 -0
  129. package/dist/web/client/src/components/branch-detail/ToolLauncher.js +147 -0
  130. package/dist/web/client/src/components/branch-detail/ToolLauncher.js.map +1 -0
  131. package/dist/web/client/src/components/branch-detail/index.d.ts +5 -0
  132. package/dist/web/client/src/components/branch-detail/index.d.ts.map +1 -0
  133. package/dist/web/client/src/components/branch-detail/index.js +5 -0
  134. package/dist/web/client/src/components/branch-detail/index.js.map +1 -0
  135. package/dist/web/client/src/components/common/BranchCard.d.ts +17 -0
  136. package/dist/web/client/src/components/common/BranchCard.d.ts.map +1 -0
  137. package/dist/web/client/src/components/common/BranchCard.js +36 -0
  138. package/dist/web/client/src/components/common/BranchCard.js.map +1 -0
  139. package/dist/web/client/src/components/common/MetricCard.d.ts +10 -0
  140. package/dist/web/client/src/components/common/MetricCard.d.ts.map +1 -0
  141. package/dist/web/client/src/components/common/MetricCard.js +10 -0
  142. package/dist/web/client/src/components/common/MetricCard.js.map +1 -0
  143. package/dist/web/client/src/components/common/PageHeader.d.ts +12 -0
  144. package/dist/web/client/src/components/common/PageHeader.d.ts.map +1 -0
  145. package/dist/web/client/src/components/common/PageHeader.js +14 -0
  146. package/dist/web/client/src/components/common/PageHeader.js.map +1 -0
  147. package/dist/web/client/src/components/common/SearchInput.d.ts +14 -0
  148. package/dist/web/client/src/components/common/SearchInput.d.ts.map +1 -0
  149. package/dist/web/client/src/components/common/SearchInput.js +15 -0
  150. package/dist/web/client/src/components/common/SearchInput.js.map +1 -0
  151. package/dist/web/client/src/components/common/StatusBadge.d.ts +10 -0
  152. package/dist/web/client/src/components/common/StatusBadge.d.ts.map +1 -0
  153. package/dist/web/client/src/components/common/StatusBadge.js +15 -0
  154. package/dist/web/client/src/components/common/StatusBadge.js.map +1 -0
  155. package/dist/web/client/src/components/common/index.d.ts +6 -0
  156. package/dist/web/client/src/components/common/index.d.ts.map +1 -0
  157. package/dist/web/client/src/components/common/index.js +6 -0
  158. package/dist/web/client/src/components/common/index.js.map +1 -0
  159. package/dist/web/client/src/components/ui/alert.d.ts +9 -0
  160. package/dist/web/client/src/components/ui/alert.d.ts.map +1 -0
  161. package/dist/web/client/src/components/ui/alert.js +25 -0
  162. package/dist/web/client/src/components/ui/alert.js.map +1 -0
  163. package/dist/web/client/src/components/ui/badge.d.ts +10 -0
  164. package/dist/web/client/src/components/ui/badge.d.ts.map +1 -0
  165. package/dist/web/client/src/components/ui/badge.js +25 -0
  166. package/dist/web/client/src/components/ui/badge.js.map +1 -0
  167. package/dist/web/client/src/components/ui/button.d.ts +12 -0
  168. package/dist/web/client/src/components/ui/button.d.ts.map +1 -0
  169. package/dist/web/client/src/components/ui/button.js +33 -0
  170. package/dist/web/client/src/components/ui/button.js.map +1 -0
  171. package/dist/web/client/src/components/ui/card.d.ts +9 -0
  172. package/dist/web/client/src/components/ui/card.d.ts.map +1 -0
  173. package/dist/web/client/src/components/ui/card.js +16 -0
  174. package/dist/web/client/src/components/ui/card.js.map +1 -0
  175. package/dist/web/client/src/components/ui/index.d.ts +8 -0
  176. package/dist/web/client/src/components/ui/index.d.ts.map +1 -0
  177. package/dist/web/client/src/components/ui/index.js +8 -0
  178. package/dist/web/client/src/components/ui/index.js.map +1 -0
  179. package/dist/web/client/src/components/ui/input.d.ts +4 -0
  180. package/dist/web/client/src/components/ui/input.d.ts.map +1 -0
  181. package/dist/web/client/src/components/ui/input.js +8 -0
  182. package/dist/web/client/src/components/ui/input.js.map +1 -0
  183. package/dist/web/client/src/components/ui/select.d.ts +14 -0
  184. package/dist/web/client/src/components/ui/select.d.ts.map +1 -0
  185. package/dist/web/client/src/components/ui/select.js +39 -0
  186. package/dist/web/client/src/components/ui/select.js.map +1 -0
  187. package/dist/web/client/src/components/ui/table.d.ts +11 -0
  188. package/dist/web/client/src/components/ui/table.d.ts.map +1 -0
  189. package/dist/web/client/src/components/ui/table.js +21 -0
  190. package/dist/web/client/src/components/ui/table.js.map +1 -0
  191. package/dist/web/client/src/hooks/useSessions.d.ts.map +1 -1
  192. package/dist/web/client/src/hooks/useSessions.js +6 -1
  193. package/dist/web/client/src/hooks/useSessions.js.map +1 -1
  194. package/dist/web/client/src/lib/utils.d.ts +7 -0
  195. package/dist/web/client/src/lib/utils.d.ts.map +1 -0
  196. package/dist/web/client/src/lib/utils.js +10 -0
  197. package/dist/web/client/src/lib/utils.js.map +1 -0
  198. package/dist/web/client/src/lib/websocket.d.ts +7 -0
  199. package/dist/web/client/src/lib/websocket.d.ts.map +1 -1
  200. package/dist/web/client/src/lib/websocket.js +44 -0
  201. package/dist/web/client/src/lib/websocket.js.map +1 -1
  202. package/dist/web/client/src/pages/BranchDetailPage.d.ts.map +1 -1
  203. package/dist/web/client/src/pages/BranchDetailPage.js +113 -361
  204. package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
  205. package/dist/web/client/src/pages/BranchListPage.d.ts.map +1 -1
  206. package/dist/web/client/src/pages/BranchListPage.js +89 -127
  207. package/dist/web/client/src/pages/BranchListPage.js.map +1 -1
  208. package/dist/web/client/src/pages/ConfigManagementPage.d.ts.map +1 -1
  209. package/dist/web/client/src/pages/ConfigManagementPage.js +46 -41
  210. package/dist/web/client/src/pages/ConfigManagementPage.js.map +1 -1
  211. package/dist/web/client/src/pages/ConfigPage.d.ts +3 -0
  212. package/dist/web/client/src/pages/ConfigPage.d.ts.map +1 -0
  213. package/dist/web/client/src/pages/ConfigPage.js +216 -0
  214. package/dist/web/client/src/pages/ConfigPage.js.map +1 -0
  215. package/dist/web/client/vite.config.d.ts.map +1 -1
  216. package/dist/web/client/vite.config.js +8 -1
  217. package/dist/web/client/vite.config.js.map +1 -1
  218. package/dist/web/server/index.d.ts +24 -2
  219. package/dist/web/server/index.d.ts.map +1 -1
  220. package/dist/web/server/index.js +49 -18
  221. package/dist/web/server/index.js.map +1 -1
  222. package/dist/web/server/pty/manager.d.ts +12 -10
  223. package/dist/web/server/pty/manager.d.ts.map +1 -1
  224. package/dist/web/server/pty/manager.js +76 -43
  225. package/dist/web/server/pty/manager.js.map +1 -1
  226. package/dist/web/server/routes/branches.d.ts +2 -2
  227. package/dist/web/server/routes/branches.d.ts.map +1 -1
  228. package/dist/web/server/routes/branches.js.map +1 -1
  229. package/dist/web/server/routes/config.d.ts +2 -2
  230. package/dist/web/server/routes/config.d.ts.map +1 -1
  231. package/dist/web/server/routes/config.js.map +1 -1
  232. package/dist/web/server/routes/index.d.ts +2 -2
  233. package/dist/web/server/routes/index.d.ts.map +1 -1
  234. package/dist/web/server/routes/index.js.map +1 -1
  235. package/dist/web/server/routes/sessions.d.ts +2 -2
  236. package/dist/web/server/routes/sessions.d.ts.map +1 -1
  237. package/dist/web/server/routes/sessions.js +35 -2
  238. package/dist/web/server/routes/sessions.js.map +1 -1
  239. package/dist/web/server/routes/worktrees.d.ts +2 -2
  240. package/dist/web/server/routes/worktrees.d.ts.map +1 -1
  241. package/dist/web/server/routes/worktrees.js +2 -2
  242. package/dist/web/server/routes/worktrees.js.map +1 -1
  243. package/dist/web/server/services/worktrees.d.ts.map +1 -1
  244. package/dist/web/server/services/worktrees.js +7 -1
  245. package/dist/web/server/services/worktrees.js.map +1 -1
  246. package/dist/web/server/tray.d.ts +24 -0
  247. package/dist/web/server/tray.d.ts.map +1 -0
  248. package/dist/web/server/tray.js +79 -0
  249. package/dist/web/server/tray.js.map +1 -0
  250. package/dist/web/server/types.d.ts +4 -0
  251. package/dist/web/server/types.d.ts.map +1 -0
  252. package/dist/web/server/types.js +2 -0
  253. package/dist/web/server/types.js.map +1 -0
  254. package/dist/web/server/websocket/handler.d.ts +18 -2
  255. package/dist/web/server/websocket/handler.d.ts.map +1 -1
  256. package/dist/web/server/websocket/handler.js +82 -9
  257. package/dist/web/server/websocket/handler.js.map +1 -1
  258. package/dist/worktree.d.ts +1 -0
  259. package/dist/worktree.d.ts.map +1 -1
  260. package/dist/worktree.js.map +1 -1
  261. package/package.json +17 -3
  262. package/src/claude.ts +26 -15
  263. package/src/cli/ui/__tests__/components/ModelSelectorScreen.initial.test.tsx +13 -13
  264. package/src/cli/ui/__tests__/components/common/Select.test.tsx +11 -0
  265. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +97 -33
  266. package/src/cli/ui/__tests__/components/screens/BranchQuickStartScreen.test.tsx +4 -4
  267. package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +7 -3
  268. package/src/cli/ui/components/App.tsx +111 -125
  269. package/src/cli/ui/components/common/Select.tsx +2 -2
  270. package/src/cli/ui/components/screens/BranchListScreen.tsx +220 -34
  271. package/src/cli/ui/components/screens/BranchQuickStartScreen.tsx +41 -46
  272. package/src/cli/ui/hooks/useGitData.ts +20 -0
  273. package/src/cli/ui/types.ts +3 -0
  274. package/src/cli/ui/utils/branchFormatter.ts +7 -2
  275. package/src/cli/ui/utils/continueSession.ts +1 -7
  276. package/src/cli/ui/utils/modelOptions.test.ts +14 -0
  277. package/src/cli/ui/utils/modelOptions.ts +7 -0
  278. package/src/codex.ts +31 -22
  279. package/src/config/builtin-tools.ts +6 -2
  280. package/src/config/shared-env.ts +139 -0
  281. package/src/gemini.ts +35 -22
  282. package/src/index.ts +61 -7
  283. package/src/logging/logger.ts +82 -0
  284. package/src/logging/rotation.ts +25 -0
  285. package/src/qwen.ts +28 -19
  286. package/src/services/aiToolResolver.ts +276 -0
  287. package/src/services/customToolResolver.ts +98 -0
  288. package/src/shared/aiToolConstants.ts +30 -0
  289. package/src/trayicon.d.ts +30 -0
  290. package/src/types/tools.ts +15 -0
  291. package/src/utils/prompt.ts +15 -9
  292. package/src/utils/session.ts +80 -26
  293. package/src/utils/terminal.ts +11 -41
  294. package/src/utils/webui.ts +43 -0
  295. package/src/web/client/components.json +21 -0
  296. package/src/web/client/src/components/AIToolLaunchModal.tsx +575 -0
  297. package/src/web/client/src/components/BranchGraph.tsx +95 -75
  298. package/src/web/client/src/components/CustomToolForm.tsx +386 -0
  299. package/src/web/client/src/components/CustomToolList.tsx +119 -0
  300. package/src/web/client/src/components/EnvEditor.tsx +91 -81
  301. package/src/web/client/src/components/EnvironmentEditor.tsx +97 -0
  302. package/src/web/client/src/components/Terminal.tsx +11 -3
  303. package/src/web/client/src/components/branch-detail/BranchInfoCards.tsx +179 -0
  304. package/src/web/client/src/components/branch-detail/SessionHistoryTable.tsx +181 -0
  305. package/src/web/client/src/components/branch-detail/TerminalPanel.tsx +92 -0
  306. package/src/web/client/src/components/branch-detail/ToolLauncher.tsx +327 -0
  307. package/src/web/client/src/components/branch-detail/index.ts +4 -0
  308. package/src/web/client/src/components/common/BranchCard.tsx +117 -0
  309. package/src/web/client/src/components/common/MetricCard.tsx +22 -0
  310. package/src/web/client/src/components/common/PageHeader.tsx +44 -0
  311. package/src/web/client/src/components/common/SearchInput.tsx +40 -0
  312. package/src/web/client/src/components/common/StatusBadge.tsx +37 -0
  313. package/src/web/client/src/components/common/index.ts +5 -0
  314. package/src/web/client/src/components/ui/alert.tsx +63 -0
  315. package/src/web/client/src/components/ui/badge.tsx +44 -0
  316. package/src/web/client/src/components/ui/button.tsx +57 -0
  317. package/src/web/client/src/components/ui/card.tsx +82 -0
  318. package/src/web/client/src/components/ui/index.ts +32 -0
  319. package/src/web/client/src/components/ui/input.tsx +21 -0
  320. package/src/web/client/src/components/ui/select.tsx +156 -0
  321. package/src/web/client/src/components/ui/table.tsx +119 -0
  322. package/src/web/client/src/hooks/useSessions.ts +10 -1
  323. package/src/web/client/src/index.css +46 -816
  324. package/src/web/client/src/lib/utils.ts +10 -0
  325. package/src/web/client/src/lib/websocket.ts +48 -1
  326. package/src/web/client/src/pages/BranchDetailPage.tsx +222 -694
  327. package/src/web/client/src/pages/BranchListPage.tsx +190 -236
  328. package/src/web/client/src/pages/ConfigManagementPage.tsx +94 -76
  329. package/src/web/client/src/pages/ConfigPage.tsx +362 -0
  330. package/src/web/client/vite.config.ts +8 -1
  331. package/src/web/server/index.ts +78 -19
  332. package/src/web/server/pty/manager.ts +128 -55
  333. package/src/web/server/routes/branches.ts +2 -2
  334. package/src/web/server/routes/config.ts +2 -2
  335. package/src/web/server/routes/index.ts +2 -2
  336. package/src/web/server/routes/sessions.ts +61 -9
  337. package/src/web/server/routes/worktrees.ts +5 -5
  338. package/src/web/server/services/worktrees.ts +12 -4
  339. package/src/web/server/tray.ts +93 -0
  340. package/src/web/server/types.ts +14 -0
  341. package/src/web/server/websocket/handler.ts +119 -13
  342. package/src/worktree.ts +1 -0
  343. package/dist/client/assets/index-DeNwPosA.css +0 -1
  344. package/dist/client/assets/index-Dl798X5w.js +0 -32
@@ -7,26 +7,23 @@ import type {
7
7
  } from "../../../../types/api.js";
8
8
  import { useConfig, useUpdateConfig } from "../hooks/useConfig";
9
9
  import { EnvEditor, createEnvRow, type EnvRow } from "../components/EnvEditor";
10
+ import { PageHeader } from "@/components/common/PageHeader";
11
+ import { Button } from "@/components/ui/button";
12
+ import { Card, CardHeader, CardContent } from "@/components/ui/card";
13
+ import { Alert, AlertDescription } from "@/components/ui/alert";
10
14
 
11
15
  type ToolEnvState = Record<string, EnvRow[]>;
12
16
 
13
17
  function rowsFromVariables(variables?: EnvironmentVariable[] | null): EnvRow[] {
14
- if (!variables) {
15
- return [];
16
- }
18
+ if (!variables) return [];
17
19
  return variables.map((variable) => {
18
20
  const partial: Partial<EnvRow> = {
19
21
  key: variable.key,
20
22
  value: variable.value,
21
23
  };
22
-
23
- if (typeof variable.importedFromOs === "boolean") {
24
+ if (typeof variable.importedFromOs === "boolean")
24
25
  partial.importedFromOs = variable.importedFromOs;
25
- }
26
- if (variable.lastUpdated) {
27
- partial.lastUpdated = variable.lastUpdated;
28
- }
29
-
26
+ if (variable.lastUpdated) partial.lastUpdated = variable.lastUpdated;
30
27
  return createEnvRow(partial);
31
28
  });
32
29
  }
@@ -34,10 +31,7 @@ function rowsFromVariables(variables?: EnvironmentVariable[] | null): EnvRow[] {
34
31
  function serializeRows(rows: EnvRow[]): EnvironmentVariable[] {
35
32
  return rows
36
33
  .filter((row) => row.key.trim().length > 0)
37
- .map((row) => ({
38
- key: row.key.trim().toUpperCase(),
39
- value: row.value,
40
- }));
34
+ .map((row) => ({ key: row.key.trim().toUpperCase(), value: row.value }));
41
35
  }
42
36
 
43
37
  function buildPayload(
@@ -105,9 +99,7 @@ export function ConfigManagementPage() {
105
99
  }, [sharedEnv, toolEnv]);
106
100
 
107
101
  const hasChanges = useMemo(() => {
108
- if (serializedOriginalShared !== serializedCurrentShared) {
109
- return true;
110
- }
102
+ if (serializedOriginalShared !== serializedCurrentShared) return true;
111
103
  if (!data) return false;
112
104
  const currentTool =
113
105
  data.tools?.map((tool) => serializeRows(toolEnv[tool.id] ?? [])) ?? [];
@@ -129,93 +121,119 @@ export function ConfigManagementPage() {
129
121
  }
130
122
  };
131
123
 
124
+ // Loading state
132
125
  if (isLoading) {
133
126
  return (
134
- <div className="app-shell">
135
- <div className="page-state page-state--centered">
136
- <h1>読み込み中</h1>
137
- <p>設定を読み込んでいます...</p>
138
- </div>
127
+ <div className="min-h-screen bg-background">
128
+ <PageHeader
129
+ eyebrow="CONFIG"
130
+ title="環境変数の管理"
131
+ subtitle="読み込み中..."
132
+ />
133
+ <main className="mx-auto max-w-7xl px-6 py-8">
134
+ <div className="flex items-center justify-center py-20">
135
+ <p className="text-muted-foreground">設定を読み込んでいます...</p>
136
+ </div>
137
+ </main>
139
138
  </div>
140
139
  );
141
140
  }
142
141
 
142
+ // Error state
143
143
  if (error) {
144
144
  return (
145
- <div className="app-shell">
146
- <div className="page-state page-state--centered">
147
- <h1>設定の取得に失敗しました</h1>
148
- <p>{error instanceof Error ? error.message : "未知のエラーです"}</p>
149
- <Link to="/" className="button button--ghost">
150
- ブランチ一覧に戻る
151
- </Link>
152
- </div>
145
+ <div className="min-h-screen bg-background">
146
+ <PageHeader eyebrow="CONFIG" title="エラー" />
147
+ <main className="mx-auto max-w-7xl px-6 py-8">
148
+ <Alert variant="destructive">
149
+ <AlertDescription>
150
+ {error instanceof Error ? error.message : "未知のエラーです"}
151
+ </AlertDescription>
152
+ </Alert>
153
+ <div className="mt-4">
154
+ <Button variant="ghost" asChild>
155
+ <Link to="/">← ブランチ一覧に戻る</Link>
156
+ </Button>
157
+ </div>
158
+ </main>
153
159
  </div>
154
160
  );
155
161
  }
156
162
 
157
163
  return (
158
- <div className="app-shell">
159
- <header className="page-hero">
160
- <Link to="/" className="page-hero__back">
161
- ← ブランチ一覧へ
162
- </Link>
163
- <p className="page-hero__eyebrow">CONFIG</p>
164
- <h1>環境変数の管理</h1>
165
- <p className="page-hero__subtitle">
166
- 共通環境変数とツールごとの上書きをブラウザから編集できます。
167
- </p>
168
- <div className="page-hero__actions">
169
- <button
170
- type="button"
171
- className="button button--primary"
164
+ <div className="min-h-screen bg-background">
165
+ <PageHeader
166
+ eyebrow="CONFIG"
167
+ title="環境変数の管理"
168
+ subtitle="共通環境変数とツールごとの上書きをブラウザから編集できます。"
169
+ >
170
+ <div className="mt-4 flex flex-wrap gap-2">
171
+ <Button variant="ghost" size="sm" asChild>
172
+ <Link to="/">← ブランチ一覧へ</Link>
173
+ </Button>
174
+ <Button
172
175
  onClick={handleSave}
173
176
  disabled={updateConfig.isPending || hasInvalidRows || !hasChanges}
174
177
  >
175
178
  {updateConfig.isPending ? "保存中..." : "保存"}
176
- </button>
179
+ </Button>
177
180
  </div>
178
- {banner && (
179
- <div className={`inline-banner inline-banner--${banner.type}`}>
180
- {banner.message}
181
- </div>
182
- )}
183
- </header>
184
-
185
- <main className="page-content page-content--wide">
186
- <section className="section-card">
187
- <EnvEditor
188
- title="共通環境変数"
189
- description="全てのAIツールで共有される値。PAT やプロキシ設定などはこちらに入力してください。"
190
- rows={sharedEnv}
191
- onChange={setSharedEnv}
192
- />
193
- </section>
194
-
195
- <section className="section-card">
196
- <h2>ツール固有の環境変数</h2>
197
- <p className="section-card__body">
198
- 各ツール固有に上書きしたい値がある場合はこちらから設定します。共通設定との競合がある場合は
199
- ツール設定が優先されます。
200
- </p>
201
- <div className="env-editor__tool-list">
181
+ </PageHeader>
182
+
183
+ {/* Banner */}
184
+ {banner && (
185
+ <div className="mx-auto max-w-7xl px-6 pt-4">
186
+ <Alert variant={banner.type === "error" ? "destructive" : "success"}>
187
+ <AlertDescription>{banner.message}</AlertDescription>
188
+ </Alert>
189
+ </div>
190
+ )}
191
+
192
+ <main className="mx-auto max-w-7xl space-y-6 px-6 py-8">
193
+ {/* Shared Environment Variables */}
194
+ <Card>
195
+ <CardContent className="pt-6">
196
+ <EnvEditor
197
+ title="共通環境変数"
198
+ description="全てのAIツールで共有される値。PAT やプロキシ設定などはこちらに入力してください。"
199
+ rows={sharedEnv}
200
+ onChange={setSharedEnv}
201
+ />
202
+ </CardContent>
203
+ </Card>
204
+
205
+ {/* Tool-specific Environment Variables */}
206
+ <Card>
207
+ <CardHeader className="pb-3">
208
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
209
+ Tool-specific
210
+ </p>
211
+ <h3 className="mt-1 text-lg font-semibold">ツール固有の環境変数</h3>
212
+ <p className="mt-2 text-sm text-muted-foreground">
213
+ 各ツール固有に上書きしたい値がある場合はこちらから設定します。
214
+ 共通設定との競合がある場合はツール設定が優先されます。
215
+ </p>
216
+ </CardHeader>
217
+ <CardContent className="space-y-6">
202
218
  {data?.tools?.map((tool) => (
203
- <div key={tool.id} className="env-editor__tool">
219
+ <div key={tool.id} className="rounded-lg border p-4">
204
220
  <EnvEditor
205
221
  title={tool.displayName}
206
222
  description={`${tool.executionType} / ${tool.command}`}
207
223
  rows={toolEnv[tool.id] ?? []}
208
224
  onChange={(rows) =>
209
- setToolEnv((prev) => ({
210
- ...prev,
211
- [tool.id]: rows,
212
- }))
225
+ setToolEnv((prev) => ({ ...prev, [tool.id]: rows }))
213
226
  }
214
227
  />
215
228
  </div>
216
229
  ))}
217
- </div>
218
- </section>
230
+ {!data?.tools?.length && (
231
+ <p className="py-4 text-center text-sm text-muted-foreground">
232
+ 登録されているツールがありません。
233
+ </p>
234
+ )}
235
+ </CardContent>
236
+ </Card>
219
237
  </main>
220
238
  </div>
221
239
  );
@@ -0,0 +1,362 @@
1
+ import React, { useEffect, useMemo, useState } from "react";
2
+ import { Link } from "react-router-dom";
3
+ import type {
4
+ CustomAITool,
5
+ EnvironmentVariable,
6
+ } from "../../../../types/api.js";
7
+ import { useConfig, useUpdateConfig } from "../hooks/useConfig";
8
+ import { CustomToolList } from "../components/CustomToolList";
9
+ import {
10
+ CustomToolForm,
11
+ type CustomToolFormValue,
12
+ } from "../components/CustomToolForm";
13
+ import {
14
+ EnvironmentEditor,
15
+ type EnvEntry,
16
+ } from "../components/EnvironmentEditor";
17
+ import { PageHeader } from "@/components/common/PageHeader";
18
+ import { Button } from "@/components/ui/button";
19
+ import { Card, CardHeader, CardContent } from "@/components/ui/card";
20
+ import { Alert, AlertDescription } from "@/components/ui/alert";
21
+
22
+ interface BannerState {
23
+ type: "success" | "error" | "info";
24
+ message: string;
25
+ }
26
+
27
+ const ENV_KEY_REGEX = /^[A-Z0-9_]+$/;
28
+ const ENV_KEY_MAX = 100;
29
+ const ENV_VALUE_MAX = 500;
30
+
31
+ export function ConfigPage() {
32
+ const { data, isLoading, error } = useConfig();
33
+ const updateConfig = useUpdateConfig();
34
+ const [tools, setTools] = useState<CustomAITool[]>([]);
35
+ const [editingTool, setEditingTool] = useState<CustomAITool | undefined>(
36
+ undefined,
37
+ );
38
+ const [banner, setBanner] = useState<BannerState | null>(null);
39
+ const [isCreating, setIsCreating] = useState(false);
40
+ const [envEntries, setEnvEntries] = useState<EnvEntry[]>([]);
41
+
42
+ useEffect(() => {
43
+ if (data?.tools) setTools(data.tools);
44
+ if (data) setEnvEntries(entriesFromVariables(data.env));
45
+ }, [data]);
46
+
47
+ const sortedTools = useMemo(() => {
48
+ return [...tools].sort((a, b) =>
49
+ a.displayName.localeCompare(b.displayName, "ja"),
50
+ );
51
+ }, [tools]);
52
+
53
+ const handleEdit = (tool: CustomAITool) => {
54
+ setEditingTool(tool);
55
+ setIsCreating(false);
56
+ };
57
+
58
+ const handleDelete = (tool: CustomAITool) => {
59
+ if (!window.confirm(`${tool.displayName} を削除しますか?`)) return;
60
+ const next = tools.filter((t) => t.id !== tool.id);
61
+ persistConfig(next, envEntries, `${tool.displayName} を削除しました。`);
62
+ };
63
+
64
+ const handleCreate = () => {
65
+ setEditingTool(undefined);
66
+ setIsCreating(true);
67
+ };
68
+
69
+ const handleFormSubmit = (value: CustomToolFormValue) => {
70
+ const now = new Date().toISOString();
71
+ const existing = tools.find((tool) => tool.id === value.id);
72
+ const nextTool: CustomAITool = {
73
+ id: value.id,
74
+ displayName: value.displayName,
75
+ icon: value.icon ?? null,
76
+ description: value.description ?? null,
77
+ executionType: value.executionType,
78
+ command: value.command,
79
+ defaultArgs: value.defaultArgs ?? null,
80
+ modeArgs: {
81
+ normal: value.modeArgs.normal ?? [],
82
+ continue: value.modeArgs.continue ?? [],
83
+ resume: value.modeArgs.resume ?? [],
84
+ },
85
+ permissionSkipArgs: value.permissionSkipArgs ?? null,
86
+ env: value.env ?? null,
87
+ createdAt: existing?.createdAt ?? now,
88
+ updatedAt: now,
89
+ };
90
+
91
+ const nextList = existing
92
+ ? tools.map((tool) => (tool.id === nextTool.id ? nextTool : tool))
93
+ : [...tools, nextTool];
94
+
95
+ persistConfig(
96
+ nextList,
97
+ envEntries,
98
+ `${nextTool.displayName} を保存しました。`,
99
+ );
100
+ };
101
+
102
+ const persistConfig = (
103
+ nextTools: CustomAITool[],
104
+ nextEnvEntries: EnvEntry[],
105
+ successMessage: string,
106
+ options?: { resetToolForm?: boolean },
107
+ ) => {
108
+ let envPayload: EnvironmentVariable[];
109
+ try {
110
+ envPayload = buildEnvVariables(nextEnvEntries);
111
+ } catch (err) {
112
+ const message = err instanceof Error ? err.message : String(err);
113
+ setBanner({ type: "error", message });
114
+ return;
115
+ }
116
+
117
+ const nextVersion = data?.version ?? "1.0.0";
118
+ updateConfig
119
+ .mutateAsync({ version: nextVersion, tools: nextTools, env: envPayload })
120
+ .then((response) => {
121
+ setTools(response.tools);
122
+ setEnvEntries(entriesFromVariables(response.env));
123
+ setBanner({ type: "success", message: successMessage });
124
+ if (options?.resetToolForm ?? true) {
125
+ setEditingTool(undefined);
126
+ setIsCreating(false);
127
+ }
128
+ })
129
+ .catch((err) => {
130
+ const message = err instanceof Error ? err.message : String(err);
131
+ setBanner({ type: "error", message });
132
+ });
133
+ };
134
+
135
+ const handleEnvEntryChange = (
136
+ id: string,
137
+ field: "key" | "value",
138
+ value: string,
139
+ ) => {
140
+ setEnvEntries((prev) =>
141
+ prev.map((entry) =>
142
+ entry.id === id
143
+ ? {
144
+ ...entry,
145
+ [field]: field === "key" ? sanitizeEnvKey(value) : value,
146
+ }
147
+ : entry,
148
+ ),
149
+ );
150
+ };
151
+
152
+ const handleEnvAdd = () =>
153
+ setEnvEntries((prev) => [...prev, createEnvEntry()]);
154
+ const handleEnvRemove = (id: string) =>
155
+ setEnvEntries((prev) => prev.filter((e) => e.id !== id));
156
+ const handleEnvSave = () =>
157
+ persistConfig(tools, envEntries, "環境変数を保存しました。", {
158
+ resetToolForm: false,
159
+ });
160
+ const handleCancel = () => {
161
+ setEditingTool(undefined);
162
+ setIsCreating(false);
163
+ };
164
+
165
+ const activeFormTool = isCreating ? undefined : editingTool;
166
+
167
+ // Loading state
168
+ if (isLoading) {
169
+ return (
170
+ <div className="min-h-screen bg-background">
171
+ <PageHeader
172
+ eyebrow="CONFIGURATION"
173
+ title="カスタムAIツール設定"
174
+ subtitle="読み込み中..."
175
+ />
176
+ <main className="mx-auto max-w-7xl px-6 py-8">
177
+ <div className="flex items-center justify-center py-20">
178
+ <p className="text-muted-foreground">設定を取得しています...</p>
179
+ </div>
180
+ </main>
181
+ </div>
182
+ );
183
+ }
184
+
185
+ // Error state
186
+ if (error) {
187
+ return (
188
+ <div className="min-h-screen bg-background">
189
+ <PageHeader eyebrow="CONFIGURATION" title="エラー" />
190
+ <main className="mx-auto max-w-7xl px-6 py-8">
191
+ <Alert variant="destructive">
192
+ <AlertDescription>
193
+ {error instanceof Error ? error.message : "未知のエラーです"}
194
+ </AlertDescription>
195
+ </Alert>
196
+ <div className="mt-4">
197
+ <Button variant="ghost" asChild>
198
+ <Link to="/">← ブランチ一覧に戻る</Link>
199
+ </Button>
200
+ </div>
201
+ </main>
202
+ </div>
203
+ );
204
+ }
205
+
206
+ return (
207
+ <div className="min-h-screen bg-background">
208
+ <PageHeader
209
+ eyebrow="CONFIGURATION"
210
+ title="カスタムAIツール設定"
211
+ subtitle="tools.json を編集して、独自のAIツールをCLI / Web UI 両方から利用できます。"
212
+ >
213
+ <div className="mt-4 flex flex-wrap gap-2">
214
+ <Button variant="ghost" size="sm" asChild>
215
+ <Link to="/">← ブランチ一覧</Link>
216
+ </Button>
217
+ <Button variant="secondary" onClick={handleCreate}>
218
+ カスタムツールを追加
219
+ </Button>
220
+ </div>
221
+ </PageHeader>
222
+
223
+ {/* Banner */}
224
+ {banner && (
225
+ <div className="mx-auto max-w-7xl px-6 pt-4">
226
+ <Alert
227
+ variant={
228
+ banner.type === "error"
229
+ ? "destructive"
230
+ : banner.type === "success"
231
+ ? "success"
232
+ : "info"
233
+ }
234
+ >
235
+ <AlertDescription className="flex items-center justify-between">
236
+ <span>{banner.message}</span>
237
+ <Button variant="ghost" size="sm" onClick={() => setBanner(null)}>
238
+ 閉じる
239
+ </Button>
240
+ </AlertDescription>
241
+ </Alert>
242
+ </div>
243
+ )}
244
+
245
+ <main className="mx-auto max-w-7xl space-y-6 px-6 py-8">
246
+ {/* Environment Variables */}
247
+ <Card>
248
+ <CardHeader className="pb-3">
249
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
250
+ Environment Variables
251
+ </p>
252
+ <h3 className="mt-1 text-lg font-semibold">共有環境変数</h3>
253
+ <p className="mt-2 text-sm text-muted-foreground">
254
+ Web UI で起動する AI
255
+ ツールはここに定義された環境変数を自動的に引き継ぎます。
256
+ </p>
257
+ </CardHeader>
258
+ <CardContent>
259
+ <EnvironmentEditor
260
+ entries={envEntries}
261
+ onEntryChange={handleEnvEntryChange}
262
+ onAddEntry={handleEnvAdd}
263
+ onRemoveEntry={handleEnvRemove}
264
+ onSave={handleEnvSave}
265
+ isSaving={updateConfig.isPending}
266
+ />
267
+ </CardContent>
268
+ </Card>
269
+
270
+ {/* Tool List */}
271
+ <Card>
272
+ <CardHeader className="pb-3">
273
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
274
+ Registered Tools
275
+ </p>
276
+ <h3 className="mt-1 text-lg font-semibold">登録済みツール</h3>
277
+ <p className="mt-2 text-sm text-muted-foreground">
278
+ CLI と Web UI は同じ設定を参照します。更新すると
279
+ ~/.claude-worktree/tools.json に保存されます。
280
+ </p>
281
+ </CardHeader>
282
+ <CardContent>
283
+ <CustomToolList
284
+ tools={sortedTools}
285
+ onEdit={handleEdit}
286
+ onDelete={handleDelete}
287
+ />
288
+ </CardContent>
289
+ </Card>
290
+
291
+ {/* Tool Form */}
292
+ {(isCreating || editingTool) && (
293
+ <Card>
294
+ <CardContent className="pt-6">
295
+ <CustomToolForm
296
+ {...(activeFormTool ? { initialValue: activeFormTool } : {})}
297
+ onSubmit={handleFormSubmit}
298
+ onCancel={handleCancel}
299
+ isSaving={updateConfig.isPending}
300
+ />
301
+ </CardContent>
302
+ </Card>
303
+ )}
304
+ </main>
305
+ </div>
306
+ );
307
+ }
308
+
309
+ // Helpers
310
+ function sanitizeEnvKey(value: string): string {
311
+ return value
312
+ .toUpperCase()
313
+ .replace(/[^A-Z0-9_]/g, "")
314
+ .slice(0, ENV_KEY_MAX);
315
+ }
316
+
317
+ function createEnvEntry(initial?: Partial<EnvEntry>): EnvEntry {
318
+ return {
319
+ id: `${initial?.key ?? "env"}-${Math.random().toString(36).slice(2, 8)}${Date.now().toString(36)}`,
320
+ key: initial?.key ?? "",
321
+ value: initial?.value ?? "",
322
+ };
323
+ }
324
+
325
+ function entriesFromVariables(
326
+ variables?: EnvironmentVariable[] | null,
327
+ ): EnvEntry[] {
328
+ if (!variables?.length) return [];
329
+ return [...variables]
330
+ .sort((a, b) => a.key.localeCompare(b.key, "en"))
331
+ .map((v) => createEnvEntry({ key: v.key, value: v.value }));
332
+ }
333
+
334
+ function buildEnvVariables(entries: EnvEntry[]): EnvironmentVariable[] {
335
+ const result: EnvironmentVariable[] = [];
336
+ const seen = new Set<string>();
337
+ const timestamp = new Date().toISOString();
338
+
339
+ for (const entry of entries) {
340
+ const key = entry.key.trim();
341
+ const value = entry.value;
342
+ if (!key && !value) continue;
343
+
344
+ if (!key) throw new Error("環境変数のキーを入力してください。");
345
+ if (!ENV_KEY_REGEX.test(key))
346
+ throw new Error(
347
+ "環境変数キーは英大文字・数字・アンダースコアのみ使用できます。",
348
+ );
349
+ if (key.length > ENV_KEY_MAX)
350
+ throw new Error(`環境変数キーは最大${ENV_KEY_MAX}文字です。(${key})`);
351
+ if (!value) throw new Error(`${key} の値を入力してください。`);
352
+ if (value.length > ENV_VALUE_MAX)
353
+ throw new Error(`${key} の値は最大${ENV_VALUE_MAX}文字です。`);
354
+ if (seen.has(key))
355
+ throw new Error(`環境変数キー "${key}" が重複しています。`);
356
+ seen.add(key);
357
+
358
+ result.push({ key, value, lastUpdated: timestamp });
359
+ }
360
+
361
+ return result;
362
+ }
@@ -1,9 +1,15 @@
1
1
  import { defineConfig } from "vite";
2
2
  import react from "@vitejs/plugin-react";
3
+ import tailwindcss from "@tailwindcss/vite";
3
4
  import path from "node:path";
4
5
 
5
6
  export default defineConfig({
6
- plugins: [react()],
7
+ plugins: [react(), tailwindcss()],
8
+ resolve: {
9
+ alias: {
10
+ "@": path.resolve(__dirname, "./src"),
11
+ },
12
+ },
7
13
  root: path.resolve(__dirname),
8
14
  build: {
9
15
  outDir: path.resolve(__dirname, "../../../dist/client"),
@@ -15,6 +21,7 @@ export default defineConfig({
15
21
  "/api": {
16
22
  target: "http://localhost:3000",
17
23
  changeOrigin: true,
24
+ ws: true,
18
25
  },
19
26
  },
20
27
  },