@akiojin/gwt 2.13.0 → 3.0.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 (295) hide show
  1. package/README.ja.md +41 -0
  2. package/README.md +38 -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 +27 -88
  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.map +1 -1
  13. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  14. package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts.map +1 -1
  15. package/dist/cli/ui/components/screens/BranchQuickStartScreen.js +3 -3
  16. package/dist/cli/ui/components/screens/BranchQuickStartScreen.js.map +1 -1
  17. package/dist/cli/ui/utils/continueSession.d.ts.map +1 -1
  18. package/dist/cli/ui/utils/continueSession.js +1 -1
  19. package/dist/cli/ui/utils/continueSession.js.map +1 -1
  20. package/dist/client/assets/index-DsDNCy5f.css +1 -0
  21. package/dist/client/assets/index-f5D2XwDh.js +72 -0
  22. package/dist/client/index.html +2 -2
  23. package/dist/codex.d.ts.map +1 -1
  24. package/dist/codex.js +21 -11
  25. package/dist/codex.js.map +1 -1
  26. package/dist/config/builtin-tools.d.ts.map +1 -1
  27. package/dist/config/builtin-tools.js +3 -2
  28. package/dist/config/builtin-tools.js.map +1 -1
  29. package/dist/config/shared-env.d.ts +41 -0
  30. package/dist/config/shared-env.d.ts.map +1 -0
  31. package/dist/config/shared-env.js +114 -0
  32. package/dist/config/shared-env.js.map +1 -0
  33. package/dist/gemini.d.ts.map +1 -1
  34. package/dist/gemini.js +20 -17
  35. package/dist/gemini.js.map +1 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +13 -8
  38. package/dist/index.js.map +1 -1
  39. package/dist/logging/logger.d.ts.map +1 -1
  40. package/dist/logging/logger.js +4 -1
  41. package/dist/logging/logger.js.map +1 -1
  42. package/dist/qwen.d.ts.map +1 -1
  43. package/dist/qwen.js +15 -11
  44. package/dist/qwen.js.map +1 -1
  45. package/dist/services/aiToolResolver.d.ts +41 -0
  46. package/dist/services/aiToolResolver.d.ts.map +1 -0
  47. package/dist/services/aiToolResolver.js +194 -0
  48. package/dist/services/aiToolResolver.js.map +1 -0
  49. package/dist/services/customToolResolver.d.ts +10 -0
  50. package/dist/services/customToolResolver.d.ts.map +1 -0
  51. package/dist/services/customToolResolver.js +71 -0
  52. package/dist/services/customToolResolver.js.map +1 -0
  53. package/dist/shared/aiToolConstants.d.ts +9 -0
  54. package/dist/shared/aiToolConstants.d.ts.map +1 -0
  55. package/dist/shared/aiToolConstants.js +29 -0
  56. package/dist/shared/aiToolConstants.js.map +1 -0
  57. package/dist/types/tools.d.ts +12 -0
  58. package/dist/types/tools.d.ts.map +1 -1
  59. package/dist/utils/prompt.d.ts.map +1 -1
  60. package/dist/utils/prompt.js.map +1 -1
  61. package/dist/utils/session.d.ts.map +1 -1
  62. package/dist/utils/session.js +15 -6
  63. package/dist/utils/session.js.map +1 -1
  64. package/dist/utils/terminal.d.ts +12 -3
  65. package/dist/utils/terminal.d.ts.map +1 -1
  66. package/dist/utils/terminal.js +5 -34
  67. package/dist/utils/terminal.js.map +1 -1
  68. package/dist/utils/webui.d.ts +8 -0
  69. package/dist/utils/webui.d.ts.map +1 -0
  70. package/dist/utils/webui.js +35 -0
  71. package/dist/utils/webui.js.map +1 -0
  72. package/dist/web/client/src/components/AIToolLaunchModal.d.ts +9 -0
  73. package/dist/web/client/src/components/AIToolLaunchModal.d.ts.map +1 -0
  74. package/dist/web/client/src/components/AIToolLaunchModal.js +363 -0
  75. package/dist/web/client/src/components/AIToolLaunchModal.js.map +1 -0
  76. package/dist/web/client/src/components/BranchGraph.d.ts.map +1 -1
  77. package/dist/web/client/src/components/BranchGraph.js +46 -49
  78. package/dist/web/client/src/components/BranchGraph.js.map +1 -1
  79. package/dist/web/client/src/components/CustomToolForm.d.ts +23 -0
  80. package/dist/web/client/src/components/CustomToolForm.d.ts.map +1 -0
  81. package/dist/web/client/src/components/CustomToolForm.js +209 -0
  82. package/dist/web/client/src/components/CustomToolForm.js.map +1 -0
  83. package/dist/web/client/src/components/CustomToolList.d.ts +10 -0
  84. package/dist/web/client/src/components/CustomToolList.d.ts.map +1 -0
  85. package/dist/web/client/src/components/CustomToolList.js +57 -0
  86. package/dist/web/client/src/components/CustomToolList.js.map +1 -0
  87. package/dist/web/client/src/components/EnvEditor.d.ts.map +1 -1
  88. package/dist/web/client/src/components/EnvEditor.js +33 -26
  89. package/dist/web/client/src/components/EnvEditor.js.map +1 -1
  90. package/dist/web/client/src/components/EnvironmentEditor.d.ts +17 -0
  91. package/dist/web/client/src/components/EnvironmentEditor.d.ts.map +1 -0
  92. package/dist/web/client/src/components/EnvironmentEditor.js +22 -0
  93. package/dist/web/client/src/components/EnvironmentEditor.js.map +1 -0
  94. package/dist/web/client/src/components/Terminal.d.ts.map +1 -1
  95. package/dist/web/client/src/components/Terminal.js +10 -3
  96. package/dist/web/client/src/components/Terminal.js.map +1 -1
  97. package/dist/web/client/src/components/branch-detail/BranchInfoCards.d.ts +10 -0
  98. package/dist/web/client/src/components/branch-detail/BranchInfoCards.d.ts.map +1 -0
  99. package/dist/web/client/src/components/branch-detail/BranchInfoCards.js +104 -0
  100. package/dist/web/client/src/components/branch-detail/BranchInfoCards.js.map +1 -0
  101. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts +22 -0
  102. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts.map +1 -0
  103. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js +79 -0
  104. package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js.map +1 -0
  105. package/dist/web/client/src/components/branch-detail/TerminalPanel.d.ts +11 -0
  106. package/dist/web/client/src/components/branch-detail/TerminalPanel.d.ts.map +1 -0
  107. package/dist/web/client/src/components/branch-detail/TerminalPanel.js +32 -0
  108. package/dist/web/client/src/components/branch-detail/TerminalPanel.js.map +1 -0
  109. package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts +40 -0
  110. package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts.map +1 -0
  111. package/dist/web/client/src/components/branch-detail/ToolLauncher.js +147 -0
  112. package/dist/web/client/src/components/branch-detail/ToolLauncher.js.map +1 -0
  113. package/dist/web/client/src/components/branch-detail/index.d.ts +5 -0
  114. package/dist/web/client/src/components/branch-detail/index.d.ts.map +1 -0
  115. package/dist/web/client/src/components/branch-detail/index.js +5 -0
  116. package/dist/web/client/src/components/branch-detail/index.js.map +1 -0
  117. package/dist/web/client/src/components/common/BranchCard.d.ts +17 -0
  118. package/dist/web/client/src/components/common/BranchCard.d.ts.map +1 -0
  119. package/dist/web/client/src/components/common/BranchCard.js +36 -0
  120. package/dist/web/client/src/components/common/BranchCard.js.map +1 -0
  121. package/dist/web/client/src/components/common/MetricCard.d.ts +10 -0
  122. package/dist/web/client/src/components/common/MetricCard.d.ts.map +1 -0
  123. package/dist/web/client/src/components/common/MetricCard.js +10 -0
  124. package/dist/web/client/src/components/common/MetricCard.js.map +1 -0
  125. package/dist/web/client/src/components/common/PageHeader.d.ts +12 -0
  126. package/dist/web/client/src/components/common/PageHeader.d.ts.map +1 -0
  127. package/dist/web/client/src/components/common/PageHeader.js +14 -0
  128. package/dist/web/client/src/components/common/PageHeader.js.map +1 -0
  129. package/dist/web/client/src/components/common/SearchInput.d.ts +14 -0
  130. package/dist/web/client/src/components/common/SearchInput.d.ts.map +1 -0
  131. package/dist/web/client/src/components/common/SearchInput.js +15 -0
  132. package/dist/web/client/src/components/common/SearchInput.js.map +1 -0
  133. package/dist/web/client/src/components/common/StatusBadge.d.ts +10 -0
  134. package/dist/web/client/src/components/common/StatusBadge.d.ts.map +1 -0
  135. package/dist/web/client/src/components/common/StatusBadge.js +15 -0
  136. package/dist/web/client/src/components/common/StatusBadge.js.map +1 -0
  137. package/dist/web/client/src/components/common/index.d.ts +6 -0
  138. package/dist/web/client/src/components/common/index.d.ts.map +1 -0
  139. package/dist/web/client/src/components/common/index.js +6 -0
  140. package/dist/web/client/src/components/common/index.js.map +1 -0
  141. package/dist/web/client/src/components/ui/alert.d.ts +9 -0
  142. package/dist/web/client/src/components/ui/alert.d.ts.map +1 -0
  143. package/dist/web/client/src/components/ui/alert.js +25 -0
  144. package/dist/web/client/src/components/ui/alert.js.map +1 -0
  145. package/dist/web/client/src/components/ui/badge.d.ts +10 -0
  146. package/dist/web/client/src/components/ui/badge.d.ts.map +1 -0
  147. package/dist/web/client/src/components/ui/badge.js +25 -0
  148. package/dist/web/client/src/components/ui/badge.js.map +1 -0
  149. package/dist/web/client/src/components/ui/button.d.ts +12 -0
  150. package/dist/web/client/src/components/ui/button.d.ts.map +1 -0
  151. package/dist/web/client/src/components/ui/button.js +33 -0
  152. package/dist/web/client/src/components/ui/button.js.map +1 -0
  153. package/dist/web/client/src/components/ui/card.d.ts +9 -0
  154. package/dist/web/client/src/components/ui/card.d.ts.map +1 -0
  155. package/dist/web/client/src/components/ui/card.js +16 -0
  156. package/dist/web/client/src/components/ui/card.js.map +1 -0
  157. package/dist/web/client/src/components/ui/index.d.ts +8 -0
  158. package/dist/web/client/src/components/ui/index.d.ts.map +1 -0
  159. package/dist/web/client/src/components/ui/index.js +8 -0
  160. package/dist/web/client/src/components/ui/index.js.map +1 -0
  161. package/dist/web/client/src/components/ui/input.d.ts +4 -0
  162. package/dist/web/client/src/components/ui/input.d.ts.map +1 -0
  163. package/dist/web/client/src/components/ui/input.js +8 -0
  164. package/dist/web/client/src/components/ui/input.js.map +1 -0
  165. package/dist/web/client/src/components/ui/select.d.ts +14 -0
  166. package/dist/web/client/src/components/ui/select.d.ts.map +1 -0
  167. package/dist/web/client/src/components/ui/select.js +39 -0
  168. package/dist/web/client/src/components/ui/select.js.map +1 -0
  169. package/dist/web/client/src/components/ui/table.d.ts +11 -0
  170. package/dist/web/client/src/components/ui/table.d.ts.map +1 -0
  171. package/dist/web/client/src/components/ui/table.js +21 -0
  172. package/dist/web/client/src/components/ui/table.js.map +1 -0
  173. package/dist/web/client/src/hooks/useSessions.d.ts.map +1 -1
  174. package/dist/web/client/src/hooks/useSessions.js +6 -1
  175. package/dist/web/client/src/hooks/useSessions.js.map +1 -1
  176. package/dist/web/client/src/lib/utils.d.ts +7 -0
  177. package/dist/web/client/src/lib/utils.d.ts.map +1 -0
  178. package/dist/web/client/src/lib/utils.js +10 -0
  179. package/dist/web/client/src/lib/utils.js.map +1 -0
  180. package/dist/web/client/src/lib/websocket.d.ts +7 -0
  181. package/dist/web/client/src/lib/websocket.d.ts.map +1 -1
  182. package/dist/web/client/src/lib/websocket.js +44 -0
  183. package/dist/web/client/src/lib/websocket.js.map +1 -1
  184. package/dist/web/client/src/pages/BranchDetailPage.d.ts.map +1 -1
  185. package/dist/web/client/src/pages/BranchDetailPage.js +125 -376
  186. package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
  187. package/dist/web/client/src/pages/BranchListPage.d.ts.map +1 -1
  188. package/dist/web/client/src/pages/BranchListPage.js +89 -127
  189. package/dist/web/client/src/pages/BranchListPage.js.map +1 -1
  190. package/dist/web/client/src/pages/ConfigManagementPage.d.ts.map +1 -1
  191. package/dist/web/client/src/pages/ConfigManagementPage.js +46 -41
  192. package/dist/web/client/src/pages/ConfigManagementPage.js.map +1 -1
  193. package/dist/web/client/src/pages/ConfigPage.d.ts +3 -0
  194. package/dist/web/client/src/pages/ConfigPage.d.ts.map +1 -0
  195. package/dist/web/client/src/pages/ConfigPage.js +216 -0
  196. package/dist/web/client/src/pages/ConfigPage.js.map +1 -0
  197. package/dist/web/client/vite.config.d.ts.map +1 -1
  198. package/dist/web/client/vite.config.js +8 -1
  199. package/dist/web/client/vite.config.js.map +1 -1
  200. package/dist/web/server/index.d.ts +24 -2
  201. package/dist/web/server/index.d.ts.map +1 -1
  202. package/dist/web/server/index.js +46 -15
  203. package/dist/web/server/index.js.map +1 -1
  204. package/dist/web/server/pty/manager.d.ts +12 -10
  205. package/dist/web/server/pty/manager.d.ts.map +1 -1
  206. package/dist/web/server/pty/manager.js +76 -43
  207. package/dist/web/server/pty/manager.js.map +1 -1
  208. package/dist/web/server/routes/sessions.d.ts.map +1 -1
  209. package/dist/web/server/routes/sessions.js +35 -2
  210. package/dist/web/server/routes/sessions.js.map +1 -1
  211. package/dist/web/server/routes/worktrees.js +2 -2
  212. package/dist/web/server/routes/worktrees.js.map +1 -1
  213. package/dist/web/server/services/worktrees.d.ts.map +1 -1
  214. package/dist/web/server/services/worktrees.js +7 -1
  215. package/dist/web/server/services/worktrees.js.map +1 -1
  216. package/dist/web/server/tray.d.ts +25 -0
  217. package/dist/web/server/tray.d.ts.map +1 -0
  218. package/dist/web/server/tray.js +98 -0
  219. package/dist/web/server/tray.js.map +1 -0
  220. package/dist/web/server/websocket/handler.d.ts +18 -2
  221. package/dist/web/server/websocket/handler.d.ts.map +1 -1
  222. package/dist/web/server/websocket/handler.js +82 -9
  223. package/dist/web/server/websocket/handler.js.map +1 -1
  224. package/package.json +15 -2
  225. package/src/claude.ts +26 -15
  226. package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +1 -1
  227. package/src/cli/ui/__tests__/components/common/Select.test.tsx +11 -0
  228. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +3 -1
  229. package/src/cli/ui/__tests__/components/screens/BranchQuickStartScreen.test.tsx +4 -4
  230. package/src/cli/ui/components/App.tsx +33 -133
  231. package/src/cli/ui/components/common/Select.tsx +2 -2
  232. package/src/cli/ui/components/screens/BranchListScreen.tsx +28 -21
  233. package/src/cli/ui/components/screens/BranchQuickStartScreen.tsx +41 -46
  234. package/src/cli/ui/utils/continueSession.ts +1 -7
  235. package/src/codex.ts +31 -22
  236. package/src/config/builtin-tools.ts +6 -2
  237. package/src/config/shared-env.ts +139 -0
  238. package/src/gemini.ts +35 -22
  239. package/src/index.ts +13 -8
  240. package/src/logging/logger.ts +5 -2
  241. package/src/qwen.ts +28 -19
  242. package/src/services/aiToolResolver.ts +276 -0
  243. package/src/services/customToolResolver.ts +98 -0
  244. package/src/shared/aiToolConstants.ts +30 -0
  245. package/src/trayicon.d.ts +30 -0
  246. package/src/types/tools.ts +15 -0
  247. package/src/utils/prompt.ts +15 -9
  248. package/src/utils/session.ts +80 -26
  249. package/src/utils/terminal.ts +11 -41
  250. package/src/utils/webui.ts +43 -0
  251. package/src/web/client/components.json +21 -0
  252. package/src/web/client/src/components/AIToolLaunchModal.tsx +575 -0
  253. package/src/web/client/src/components/BranchGraph.tsx +95 -75
  254. package/src/web/client/src/components/CustomToolForm.tsx +386 -0
  255. package/src/web/client/src/components/CustomToolList.tsx +119 -0
  256. package/src/web/client/src/components/EnvEditor.tsx +91 -81
  257. package/src/web/client/src/components/EnvironmentEditor.tsx +97 -0
  258. package/src/web/client/src/components/Terminal.tsx +11 -3
  259. package/src/web/client/src/components/branch-detail/BranchInfoCards.tsx +179 -0
  260. package/src/web/client/src/components/branch-detail/SessionHistoryTable.tsx +181 -0
  261. package/src/web/client/src/components/branch-detail/TerminalPanel.tsx +92 -0
  262. package/src/web/client/src/components/branch-detail/ToolLauncher.tsx +327 -0
  263. package/src/web/client/src/components/branch-detail/index.ts +4 -0
  264. package/src/web/client/src/components/common/BranchCard.tsx +117 -0
  265. package/src/web/client/src/components/common/MetricCard.tsx +22 -0
  266. package/src/web/client/src/components/common/PageHeader.tsx +44 -0
  267. package/src/web/client/src/components/common/SearchInput.tsx +40 -0
  268. package/src/web/client/src/components/common/StatusBadge.tsx +37 -0
  269. package/src/web/client/src/components/common/index.ts +5 -0
  270. package/src/web/client/src/components/ui/alert.tsx +63 -0
  271. package/src/web/client/src/components/ui/badge.tsx +44 -0
  272. package/src/web/client/src/components/ui/button.tsx +57 -0
  273. package/src/web/client/src/components/ui/card.tsx +82 -0
  274. package/src/web/client/src/components/ui/index.ts +32 -0
  275. package/src/web/client/src/components/ui/input.tsx +21 -0
  276. package/src/web/client/src/components/ui/select.tsx +156 -0
  277. package/src/web/client/src/components/ui/table.tsx +119 -0
  278. package/src/web/client/src/hooks/useSessions.ts +10 -1
  279. package/src/web/client/src/index.css +46 -816
  280. package/src/web/client/src/lib/utils.ts +10 -0
  281. package/src/web/client/src/lib/websocket.ts +48 -1
  282. package/src/web/client/src/pages/BranchDetailPage.tsx +247 -723
  283. package/src/web/client/src/pages/BranchListPage.tsx +190 -236
  284. package/src/web/client/src/pages/ConfigManagementPage.tsx +94 -76
  285. package/src/web/client/src/pages/ConfigPage.tsx +362 -0
  286. package/src/web/client/vite.config.ts +8 -1
  287. package/src/web/server/index.ts +72 -15
  288. package/src/web/server/pty/manager.ts +128 -55
  289. package/src/web/server/routes/sessions.ts +59 -7
  290. package/src/web/server/routes/worktrees.ts +3 -3
  291. package/src/web/server/services/worktrees.ts +12 -4
  292. package/src/web/server/tray.ts +120 -0
  293. package/src/web/server/websocket/handler.ts +119 -13
  294. package/dist/client/assets/index-DeNwPosA.css +0 -1
  295. package/dist/client/assets/index-Dl798X5w.js +0 -32
@@ -0,0 +1,119 @@
1
+ import React from "react";
2
+ import {
3
+ Card,
4
+ CardHeader,
5
+ CardContent,
6
+ CardFooter,
7
+ } from "@/components/ui/card";
8
+ import { Button } from "@/components/ui/button";
9
+ import { Badge } from "@/components/ui/badge";
10
+ import type { CustomAITool } from "../../../../types/api.js";
11
+
12
+ interface CustomToolListProps {
13
+ tools: CustomAITool[];
14
+ onEdit: (tool: CustomAITool) => void;
15
+ onDelete: (tool: CustomAITool) => void;
16
+ }
17
+
18
+ export function CustomToolList({
19
+ tools,
20
+ onEdit,
21
+ onDelete,
22
+ }: CustomToolListProps) {
23
+ if (!tools.length) {
24
+ return (
25
+ <Card className="border-dashed">
26
+ <CardContent className="flex flex-col items-center justify-center py-12 text-center">
27
+ <h3 className="text-lg font-semibold">
28
+ カスタムツールが登録されていません
29
+ </h3>
30
+ <p className="mt-2 text-sm text-muted-foreground">
31
+ 「カスタムツールを追加」から最初のツールを登録してください。
32
+ </p>
33
+ </CardContent>
34
+ </Card>
35
+ );
36
+ }
37
+
38
+ return (
39
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
40
+ {tools.map((tool) => (
41
+ <Card key={tool.id} className="flex flex-col">
42
+ <CardHeader className="pb-3">
43
+ <div className="flex items-start justify-between gap-2">
44
+ <div className="min-w-0 flex-1">
45
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
46
+ ID: {tool.id}
47
+ </p>
48
+ <h3 className="mt-1 flex items-center gap-2 font-semibold">
49
+ {tool.icon && <span>{tool.icon}</span>}
50
+ <span className="truncate">{tool.displayName}</span>
51
+ </h3>
52
+ </div>
53
+ <Badge variant="outline">
54
+ {renderExecutionLabel(tool.executionType)}
55
+ </Badge>
56
+ </div>
57
+ </CardHeader>
58
+
59
+ <CardContent className="flex-1 space-y-3 pb-3">
60
+ <p className="rounded bg-muted px-2 py-1 font-mono text-sm">
61
+ {tool.command}
62
+ </p>
63
+
64
+ {tool.description && (
65
+ <p className="text-sm text-muted-foreground">
66
+ {tool.description}
67
+ </p>
68
+ )}
69
+
70
+ <dl className="grid grid-cols-3 gap-2 text-xs">
71
+ <div>
72
+ <dt className="text-muted-foreground">normal</dt>
73
+ <dd className="mt-0.5">{renderArgs(tool.modeArgs?.normal)}</dd>
74
+ </div>
75
+ <div>
76
+ <dt className="text-muted-foreground">continue</dt>
77
+ <dd className="mt-0.5">
78
+ {renderArgs(tool.modeArgs?.continue)}
79
+ </dd>
80
+ </div>
81
+ <div>
82
+ <dt className="text-muted-foreground">resume</dt>
83
+ <dd className="mt-0.5">{renderArgs(tool.modeArgs?.resume)}</dd>
84
+ </div>
85
+ </dl>
86
+ </CardContent>
87
+
88
+ <CardFooter className="flex gap-2 pt-0">
89
+ <Button variant="secondary" size="sm" onClick={() => onEdit(tool)}>
90
+ 編集
91
+ </Button>
92
+ <Button variant="ghost" size="sm" onClick={() => onDelete(tool)}>
93
+ 削除
94
+ </Button>
95
+ </CardFooter>
96
+ </Card>
97
+ ))}
98
+ </div>
99
+ );
100
+ }
101
+
102
+ function renderExecutionLabel(type: CustomAITool["executionType"]) {
103
+ switch (type) {
104
+ case "path":
105
+ return "実行ファイル";
106
+ case "bunx":
107
+ return "bunx";
108
+ case "command":
109
+ default:
110
+ return "コマンド";
111
+ }
112
+ }
113
+
114
+ function renderArgs(args?: string[] | null) {
115
+ if (!args || args.length === 0) {
116
+ return <span className="text-muted-foreground/50">未設定</span>;
117
+ }
118
+ return args.join(" ");
119
+ }
@@ -1,4 +1,16 @@
1
1
  import React from "react";
2
+ import { Button } from "@/components/ui/button";
3
+ import { Input } from "@/components/ui/input";
4
+ import { Badge } from "@/components/ui/badge";
5
+ import {
6
+ Table,
7
+ TableHeader,
8
+ TableBody,
9
+ TableRow,
10
+ TableHead,
11
+ TableCell,
12
+ } from "@/components/ui/table";
13
+ import { cn } from "@/lib/utils";
2
14
 
3
15
  export interface EnvRow {
4
16
  id: string;
@@ -80,98 +92,96 @@ export function EnvEditor({
80
92
  };
81
93
 
82
94
  return (
83
- <div className="env-editor">
84
- <header className="env-editor__header">
95
+ <div className="space-y-4">
96
+ <div className="flex items-start justify-between gap-4">
85
97
  <div>
86
- <h3>{title}</h3>
98
+ <h3 className="font-semibold">{title}</h3>
87
99
  {description && (
88
- <p className="env-editor__description">{description}</p>
100
+ <p className="mt-1 text-sm text-muted-foreground">{description}</p>
89
101
  )}
90
102
  </div>
91
103
  {allowAdd && (
92
- <button
93
- type="button"
94
- className="button button--secondary"
95
- onClick={handleAdd}
96
- >
104
+ <Button variant="secondary" size="sm" onClick={handleAdd}>
97
105
  変数を追加
98
- </button>
106
+ </Button>
99
107
  )}
100
- </header>
108
+ </div>
101
109
 
102
110
  {rows.length === 0 ? (
103
- <p className="env-editor__empty">{emptyLabel}</p>
111
+ <p className="py-4 text-center text-sm text-muted-foreground">
112
+ {emptyLabel}
113
+ </p>
104
114
  ) : (
105
- <table className="env-editor__table">
106
- <thead>
107
- <tr>
108
- <th>キー</th>
109
- <th>値</th>
110
- <th style={{ width: "140px" }}>操作</th>
111
- </tr>
112
- </thead>
113
- <tbody>
114
- {rows.map((row) => {
115
- const keyInvalid = isInvalidKey(row);
116
- return (
117
- <tr
118
- key={row.id}
119
- className={
120
- keyInvalid ? "env-editor__row--invalid" : undefined
121
- }
122
- >
123
- <td>
124
- <input
125
- type="text"
126
- value={row.key}
127
- onChange={(event) =>
128
- handleFieldChange(row.id, "key", event.target.value)
129
- }
130
- placeholder="EXAMPLE_KEY"
131
- />
132
- {row.importedFromOs && (
133
- <span
134
- className="pill pill--info"
135
- style={{ marginLeft: "0.5rem" }}
115
+ <div className="rounded-md border">
116
+ <Table>
117
+ <TableHeader>
118
+ <TableRow>
119
+ <TableHead>キー</TableHead>
120
+ <TableHead>値</TableHead>
121
+ <TableHead className="w-24 text-right">操作</TableHead>
122
+ </TableRow>
123
+ </TableHeader>
124
+ <TableBody>
125
+ {rows.map((row) => {
126
+ const keyInvalid = isInvalidKey(row);
127
+ return (
128
+ <TableRow
129
+ key={row.id}
130
+ className={cn(keyInvalid && "bg-destructive/10")}
131
+ >
132
+ <TableCell className="space-y-1">
133
+ <Input
134
+ type="text"
135
+ value={row.key}
136
+ onChange={(event) =>
137
+ handleFieldChange(row.id, "key", event.target.value)
138
+ }
139
+ placeholder="EXAMPLE_KEY"
140
+ className={cn(keyInvalid && "border-destructive")}
141
+ />
142
+ <div className="flex flex-wrap items-center gap-2">
143
+ {row.importedFromOs && (
144
+ <Badge variant="outline" className="text-xs">
145
+ OSから取り込み
146
+ </Badge>
147
+ )}
148
+ {row.lastUpdated && (
149
+ <span className="text-xs text-muted-foreground">
150
+ 更新: {new Date(row.lastUpdated).toLocaleString()}
151
+ </span>
152
+ )}
153
+ </div>
154
+ {keyInvalid && (
155
+ <p className="text-xs text-destructive">
156
+ A-Z,0-9,_ のみ使用できます
157
+ </p>
158
+ )}
159
+ </TableCell>
160
+ <TableCell>
161
+ <Input
162
+ type="text"
163
+ value={row.value}
164
+ onChange={(event) =>
165
+ handleFieldChange(row.id, "value", event.target.value)
166
+ }
167
+ placeholder="値"
168
+ />
169
+ </TableCell>
170
+ <TableCell className="text-right">
171
+ <Button
172
+ variant="ghost"
173
+ size="sm"
174
+ onClick={() => handleRemove(row.id)}
136
175
  >
137
- OSから取り込み
138
- </span>
139
- )}
140
- {row.lastUpdated && (
141
- <span className="env-editor__meta">
142
- 更新: {new Date(row.lastUpdated).toLocaleString()}
143
- </span>
144
- )}
145
- {keyInvalid && (
146
- <p className="env-editor__error">
147
- A-Z,0-9,_ のみ使用できます
148
- </p>
149
- )}
150
- </td>
151
- <td>
152
- <input
153
- type="text"
154
- value={row.value}
155
- onChange={(event) =>
156
- handleFieldChange(row.id, "value", event.target.value)
157
- }
158
- placeholder="値"
159
- />
160
- </td>
161
- <td>
162
- <button
163
- type="button"
164
- className="button button--ghost"
165
- onClick={() => handleRemove(row.id)}
166
- >
167
- 削除
168
- </button>
169
- </td>
170
- </tr>
171
- );
172
- })}
173
- </tbody>
174
- </table>
176
+ 削除
177
+ </Button>
178
+ </TableCell>
179
+ </TableRow>
180
+ );
181
+ })}
182
+ </TableBody>
183
+ </Table>
184
+ </div>
175
185
  )}
176
186
  </div>
177
187
  );
@@ -0,0 +1,97 @@
1
+ import React from "react";
2
+ import { Button } from "@/components/ui/button";
3
+ import { Input } from "@/components/ui/input";
4
+
5
+ export interface EnvEntry {
6
+ id: string;
7
+ key: string;
8
+ value: string;
9
+ }
10
+
11
+ interface EnvironmentEditorProps {
12
+ entries: EnvEntry[];
13
+ onEntryChange: (id: string, field: "key" | "value", value: string) => void;
14
+ onAddEntry: () => void;
15
+ onRemoveEntry: (id: string) => void;
16
+ onSave: () => void;
17
+ isSaving?: boolean;
18
+ }
19
+
20
+ export function EnvironmentEditor({
21
+ entries,
22
+ onEntryChange,
23
+ onAddEntry,
24
+ onRemoveEntry,
25
+ onSave,
26
+ isSaving,
27
+ }: EnvironmentEditorProps) {
28
+ const hasEntries = entries.length > 0;
29
+
30
+ return (
31
+ <div className="space-y-4">
32
+ <p className="text-sm text-muted-foreground">
33
+ Claude Code / Codex CLI などが参照する共有環境変数を管理します。例:
34
+ ANTHROPIC_API_KEY, OPENAI_API_KEY, GITHUB_TOKEN
35
+ </p>
36
+
37
+ <div className="space-y-3">
38
+ {!hasEntries && (
39
+ <p className="py-4 text-center text-sm text-muted-foreground">
40
+ 環境変数はまだ設定されていません。
41
+ </p>
42
+ )}
43
+
44
+ {entries.map((entry) => (
45
+ <div key={entry.id} className="flex items-end gap-3">
46
+ <div className="flex-1 space-y-1">
47
+ <label className="text-sm font-medium">キー</label>
48
+ <Input
49
+ type="text"
50
+ value={entry.key}
51
+ onChange={(event) =>
52
+ onEntryChange(entry.id, "key", event.target.value)
53
+ }
54
+ placeholder="ANTHROPIC_API_KEY"
55
+ maxLength={100}
56
+ disabled={isSaving}
57
+ />
58
+ </div>
59
+
60
+ <div className="flex-1 space-y-1">
61
+ <label className="text-sm font-medium">値</label>
62
+ <Input
63
+ type="text"
64
+ value={entry.value}
65
+ onChange={(event) =>
66
+ onEntryChange(entry.id, "value", event.target.value)
67
+ }
68
+ placeholder="sk-..."
69
+ maxLength={500}
70
+ disabled={isSaving}
71
+ />
72
+ </div>
73
+
74
+ <Button
75
+ variant="ghost"
76
+ size="sm"
77
+ onClick={() => onRemoveEntry(entry.id)}
78
+ disabled={isSaving}
79
+ >
80
+ 削除
81
+ </Button>
82
+ </div>
83
+ ))}
84
+ </div>
85
+
86
+ <div className="flex gap-2 pt-2">
87
+ <Button variant="secondary" onClick={onAddEntry} disabled={isSaving}>
88
+ 環境変数を追加
89
+ </Button>
90
+
91
+ <Button onClick={onSave} disabled={isSaving}>
92
+ {isSaving ? "保存中..." : "保存"}
93
+ </Button>
94
+ </div>
95
+ </div>
96
+ );
97
+ }
@@ -22,6 +22,14 @@ export function Terminal({ sessionId, onExit, onError }: TerminalProps) {
22
22
  const xtermRef = useRef<XTerm | null>(null);
23
23
  const fitAddonRef = useRef<FitAddon | null>(null);
24
24
  const wsRef = useRef<PTYWebSocket | null>(null);
25
+ const onExitRef = useRef(onExit);
26
+ const onErrorRef = useRef(onError);
27
+
28
+ // Keep refs up to date
29
+ useEffect(() => {
30
+ onExitRef.current = onExit;
31
+ onErrorRef.current = onError;
32
+ }, [onExit, onError]);
25
33
 
26
34
  useEffect(() => {
27
35
  if (!terminalRef.current) {
@@ -74,11 +82,11 @@ export function Terminal({ sessionId, onExit, onError }: TerminalProps) {
74
82
  },
75
83
  onExit: (code) => {
76
84
  xterm.write(`\r\n\r\n[Process exited with code ${code}]\r\n`);
77
- onExit?.(code);
85
+ onExitRef.current?.(code);
78
86
  },
79
87
  onError: (message) => {
80
88
  xterm.write(`\r\n\r\n[Error: ${message}]\r\n`);
81
- onError?.(message);
89
+ onErrorRef.current?.(message);
82
90
  },
83
91
  onOpen: () => {
84
92
  xterm.write("Connected to session...\r\n");
@@ -121,7 +129,7 @@ export function Terminal({ sessionId, onExit, onError }: TerminalProps) {
121
129
  ws.disconnect();
122
130
  xterm.dispose();
123
131
  };
124
- }, [sessionId, onExit, onError]);
132
+ }, [sessionId]);
125
133
 
126
134
  return (
127
135
  <div
@@ -0,0 +1,179 @@
1
+ import React from "react";
2
+ import { Card, CardHeader, CardContent } from "@/components/ui/card";
3
+ import { Badge } from "@/components/ui/badge";
4
+ import type { Branch, LastToolUsage } from "../../../../../types/api.js";
5
+
6
+ interface BranchInfoCardsProps {
7
+ branch: Branch;
8
+ formattedCommitDate: string;
9
+ latestToolUsage: LastToolUsage | null;
10
+ }
11
+
12
+ function mapToolLabel(toolId: string, toolLabel?: string | null): string {
13
+ if (toolId === "claude-code") return "Claude";
14
+ if (toolId === "codex-cli") return "Codex";
15
+ if (toolId === "gemini-cli") return "Gemini";
16
+ if (toolId === "qwen-cli") return "Qwen";
17
+ if (toolLabel) return toolLabel;
18
+ return "Custom";
19
+ }
20
+
21
+ function renderToolUsage(usage: LastToolUsage): string {
22
+ const modeLabel =
23
+ usage.mode === "normal"
24
+ ? "New"
25
+ : usage.mode === "continue"
26
+ ? "Continue"
27
+ : usage.mode === "resume"
28
+ ? "Resume"
29
+ : null;
30
+ const toolText = mapToolLabel(usage.toolId, usage.toolLabel);
31
+ return [toolText, modeLabel, usage.model].filter(Boolean).join(" | ");
32
+ }
33
+
34
+ function formatUsageTimestamp(value: number): string {
35
+ try {
36
+ return new Intl.DateTimeFormat("ja-JP", {
37
+ month: "short",
38
+ day: "numeric",
39
+ hour: "2-digit",
40
+ minute: "2-digit",
41
+ }).format(new Date(value));
42
+ } catch {
43
+ return "--";
44
+ }
45
+ }
46
+
47
+ export function BranchInfoCards({
48
+ branch,
49
+ formattedCommitDate,
50
+ latestToolUsage,
51
+ }: BranchInfoCardsProps) {
52
+ return (
53
+ <div className="grid gap-4 lg:grid-cols-2">
54
+ {/* Branch Insights */}
55
+ <Card>
56
+ <CardHeader className="pb-2">
57
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
58
+ Branch Insights
59
+ </p>
60
+ <h3 className="text-lg font-semibold">ブランチインサイト</h3>
61
+ </CardHeader>
62
+ <CardContent>
63
+ <dl className="grid gap-3 text-sm">
64
+ <div className="flex justify-between border-b border-border/50 pb-2">
65
+ <dt className="text-muted-foreground">コミット</dt>
66
+ <dd className="font-mono text-xs">{branch.commitHash}</dd>
67
+ </div>
68
+ <div className="flex justify-between border-b border-border/50 pb-2">
69
+ <dt className="text-muted-foreground">Author</dt>
70
+ <dd>{branch.author ?? "N/A"}</dd>
71
+ </div>
72
+ <div className="flex justify-between border-b border-border/50 pb-2">
73
+ <dt className="text-muted-foreground">更新日</dt>
74
+ <dd>{formattedCommitDate}</dd>
75
+ </div>
76
+ <div className="flex justify-between">
77
+ <dt className="text-muted-foreground">Worktree</dt>
78
+ <dd
79
+ className="max-w-[200px] truncate text-right"
80
+ title={branch.worktreePath ?? undefined}
81
+ >
82
+ {branch.worktreePath ?? "未作成"}
83
+ </dd>
84
+ </div>
85
+ </dl>
86
+ </CardContent>
87
+ </Card>
88
+
89
+ {/* Commit Message */}
90
+ <Card>
91
+ <CardHeader className="pb-2">
92
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
93
+ Latest Commit
94
+ </p>
95
+ <h3 className="text-lg font-semibold">コミット情報</h3>
96
+ </CardHeader>
97
+ <CardContent>
98
+ <p className="text-sm text-muted-foreground">
99
+ {branch.commitMessage ?? "コミットメッセージがありません。"}
100
+ </p>
101
+ </CardContent>
102
+ </Card>
103
+
104
+ {/* Divergence Status */}
105
+ {branch.divergence && (
106
+ <Card>
107
+ <CardHeader className="pb-2">
108
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
109
+ Divergence
110
+ </p>
111
+ <h3 className="text-lg font-semibold">差分状況</h3>
112
+ </CardHeader>
113
+ <CardContent>
114
+ <div className="flex flex-wrap gap-2">
115
+ <Badge variant="outline">↑ Ahead {branch.divergence.ahead}</Badge>
116
+ <Badge variant="outline">
117
+ ↓ Behind {branch.divergence.behind}
118
+ </Badge>
119
+ <Badge
120
+ variant={branch.divergence.upToDate ? "success" : "warning"}
121
+ >
122
+ {branch.divergence.upToDate ? "最新" : "更新あり"}
123
+ </Badge>
124
+ </div>
125
+ </CardContent>
126
+ </Card>
127
+ )}
128
+
129
+ {/* Worktree Info */}
130
+ <Card>
131
+ <CardHeader className="pb-2">
132
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
133
+ Worktree
134
+ </p>
135
+ <h3 className="text-lg font-semibold">Worktree情報</h3>
136
+ </CardHeader>
137
+ <CardContent className="space-y-2 text-sm text-muted-foreground">
138
+ <p>
139
+ パス:{" "}
140
+ <strong className="text-foreground">
141
+ {branch.worktreePath ?? "未作成"}
142
+ </strong>
143
+ </p>
144
+ <ul className="list-inside list-disc space-y-1 text-xs">
145
+ <li>AIツールの起動にはクリーンなワークツリーであることを推奨</li>
146
+ <li>Worktree再作成で既存のローカル変更が失われる可能性あり</li>
147
+ </ul>
148
+ </CardContent>
149
+ </Card>
150
+
151
+ {/* Last Tool Usage */}
152
+ {latestToolUsage && (
153
+ <Card className="lg:col-span-2">
154
+ <CardHeader className="pb-2">
155
+ <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
156
+ Last Activity
157
+ </p>
158
+ <h3 className="text-lg font-semibold">最終ツール使用</h3>
159
+ </CardHeader>
160
+ <CardContent>
161
+ <div className="flex flex-wrap items-center gap-2 text-sm">
162
+ <Badge variant="outline">
163
+ {renderToolUsage(latestToolUsage)}
164
+ </Badge>
165
+ <span className="text-muted-foreground">
166
+ {formatUsageTimestamp(latestToolUsage.timestamp)}
167
+ </span>
168
+ {latestToolUsage.worktreePath && (
169
+ <span className="text-xs text-muted-foreground">
170
+ @ {latestToolUsage.worktreePath}
171
+ </span>
172
+ )}
173
+ </div>
174
+ </CardContent>
175
+ </Card>
176
+ )}
177
+ </div>
178
+ );
179
+ }