@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.
- package/README.ja.md +33 -0
- package/README.md +31 -0
- package/dist/claude.d.ts.map +1 -1
- package/dist/claude.js +17 -11
- package/dist/claude.js.map +1 -1
- package/dist/cli/ui/components/App.d.ts +0 -6
- package/dist/cli/ui/components/App.d.ts.map +1 -1
- package/dist/cli/ui/components/App.js +93 -85
- package/dist/cli/ui/components/App.js.map +1 -1
- package/dist/cli/ui/components/common/Select.js +2 -2
- package/dist/cli/ui/components/common/Select.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts +3 -1
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.js +168 -34
- package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.js +3 -3
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.js.map +1 -1
- package/dist/cli/ui/hooks/useGitData.d.ts.map +1 -1
- package/dist/cli/ui/hooks/useGitData.js +17 -0
- package/dist/cli/ui/hooks/useGitData.js.map +1 -1
- package/dist/cli/ui/types.d.ts +2 -0
- package/dist/cli/ui/types.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.js +7 -2
- package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
- package/dist/cli/ui/utils/continueSession.d.ts.map +1 -1
- package/dist/cli/ui/utils/continueSession.js +1 -1
- package/dist/cli/ui/utils/continueSession.js.map +1 -1
- package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
- package/dist/cli/ui/utils/modelOptions.js +7 -0
- package/dist/cli/ui/utils/modelOptions.js.map +1 -1
- package/dist/client/assets/index-DPWWHorC.js +72 -0
- package/dist/client/assets/index-DsDNCy5f.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/codex.d.ts.map +1 -1
- package/dist/codex.js +21 -11
- package/dist/codex.js.map +1 -1
- package/dist/config/builtin-tools.d.ts.map +1 -1
- package/dist/config/builtin-tools.js +3 -2
- package/dist/config/builtin-tools.js.map +1 -1
- package/dist/config/shared-env.d.ts +41 -0
- package/dist/config/shared-env.d.ts.map +1 -0
- package/dist/config/shared-env.js +114 -0
- package/dist/config/shared-env.js.map +1 -0
- package/dist/gemini.d.ts.map +1 -1
- package/dist/gemini.js +20 -17
- package/dist/gemini.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +55 -7
- package/dist/index.js.map +1 -1
- package/dist/logging/logger.d.ts +24 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +60 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/logging/rotation.d.ts +6 -0
- package/dist/logging/rotation.d.ts.map +1 -0
- package/dist/logging/rotation.js +26 -0
- package/dist/logging/rotation.js.map +1 -0
- package/dist/qwen.d.ts.map +1 -1
- package/dist/qwen.js +15 -11
- package/dist/qwen.js.map +1 -1
- package/dist/services/aiToolResolver.d.ts +41 -0
- package/dist/services/aiToolResolver.d.ts.map +1 -0
- package/dist/services/aiToolResolver.js +194 -0
- package/dist/services/aiToolResolver.js.map +1 -0
- package/dist/services/customToolResolver.d.ts +10 -0
- package/dist/services/customToolResolver.d.ts.map +1 -0
- package/dist/services/customToolResolver.js +71 -0
- package/dist/services/customToolResolver.js.map +1 -0
- package/dist/shared/aiToolConstants.d.ts +9 -0
- package/dist/shared/aiToolConstants.d.ts.map +1 -0
- package/dist/shared/aiToolConstants.js +29 -0
- package/dist/shared/aiToolConstants.js.map +1 -0
- package/dist/types/tools.d.ts +12 -0
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/utils/prompt.d.ts.map +1 -1
- package/dist/utils/prompt.js.map +1 -1
- package/dist/utils/session.d.ts.map +1 -1
- package/dist/utils/session.js +15 -6
- package/dist/utils/session.js.map +1 -1
- package/dist/utils/terminal.d.ts +12 -3
- package/dist/utils/terminal.d.ts.map +1 -1
- package/dist/utils/terminal.js +5 -34
- package/dist/utils/terminal.js.map +1 -1
- package/dist/utils/webui.d.ts +8 -0
- package/dist/utils/webui.d.ts.map +1 -0
- package/dist/utils/webui.js +35 -0
- package/dist/utils/webui.js.map +1 -0
- package/dist/web/client/src/components/AIToolLaunchModal.d.ts +9 -0
- package/dist/web/client/src/components/AIToolLaunchModal.d.ts.map +1 -0
- package/dist/web/client/src/components/AIToolLaunchModal.js +363 -0
- package/dist/web/client/src/components/AIToolLaunchModal.js.map +1 -0
- package/dist/web/client/src/components/BranchGraph.d.ts.map +1 -1
- package/dist/web/client/src/components/BranchGraph.js +46 -49
- package/dist/web/client/src/components/BranchGraph.js.map +1 -1
- package/dist/web/client/src/components/CustomToolForm.d.ts +23 -0
- package/dist/web/client/src/components/CustomToolForm.d.ts.map +1 -0
- package/dist/web/client/src/components/CustomToolForm.js +209 -0
- package/dist/web/client/src/components/CustomToolForm.js.map +1 -0
- package/dist/web/client/src/components/CustomToolList.d.ts +10 -0
- package/dist/web/client/src/components/CustomToolList.d.ts.map +1 -0
- package/dist/web/client/src/components/CustomToolList.js +57 -0
- package/dist/web/client/src/components/CustomToolList.js.map +1 -0
- package/dist/web/client/src/components/EnvEditor.d.ts.map +1 -1
- package/dist/web/client/src/components/EnvEditor.js +33 -26
- package/dist/web/client/src/components/EnvEditor.js.map +1 -1
- package/dist/web/client/src/components/EnvironmentEditor.d.ts +17 -0
- package/dist/web/client/src/components/EnvironmentEditor.d.ts.map +1 -0
- package/dist/web/client/src/components/EnvironmentEditor.js +22 -0
- package/dist/web/client/src/components/EnvironmentEditor.js.map +1 -0
- package/dist/web/client/src/components/Terminal.d.ts.map +1 -1
- package/dist/web/client/src/components/Terminal.js +10 -3
- package/dist/web/client/src/components/Terminal.js.map +1 -1
- package/dist/web/client/src/components/branch-detail/BranchInfoCards.d.ts +10 -0
- package/dist/web/client/src/components/branch-detail/BranchInfoCards.d.ts.map +1 -0
- package/dist/web/client/src/components/branch-detail/BranchInfoCards.js +104 -0
- package/dist/web/client/src/components/branch-detail/BranchInfoCards.js.map +1 -0
- package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts +22 -0
- package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts.map +1 -0
- package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js +79 -0
- package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js.map +1 -0
- package/dist/web/client/src/components/branch-detail/TerminalPanel.d.ts +11 -0
- package/dist/web/client/src/components/branch-detail/TerminalPanel.d.ts.map +1 -0
- package/dist/web/client/src/components/branch-detail/TerminalPanel.js +32 -0
- package/dist/web/client/src/components/branch-detail/TerminalPanel.js.map +1 -0
- package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts +40 -0
- package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts.map +1 -0
- package/dist/web/client/src/components/branch-detail/ToolLauncher.js +147 -0
- package/dist/web/client/src/components/branch-detail/ToolLauncher.js.map +1 -0
- package/dist/web/client/src/components/branch-detail/index.d.ts +5 -0
- package/dist/web/client/src/components/branch-detail/index.d.ts.map +1 -0
- package/dist/web/client/src/components/branch-detail/index.js +5 -0
- package/dist/web/client/src/components/branch-detail/index.js.map +1 -0
- package/dist/web/client/src/components/common/BranchCard.d.ts +17 -0
- package/dist/web/client/src/components/common/BranchCard.d.ts.map +1 -0
- package/dist/web/client/src/components/common/BranchCard.js +36 -0
- package/dist/web/client/src/components/common/BranchCard.js.map +1 -0
- package/dist/web/client/src/components/common/MetricCard.d.ts +10 -0
- package/dist/web/client/src/components/common/MetricCard.d.ts.map +1 -0
- package/dist/web/client/src/components/common/MetricCard.js +10 -0
- package/dist/web/client/src/components/common/MetricCard.js.map +1 -0
- package/dist/web/client/src/components/common/PageHeader.d.ts +12 -0
- package/dist/web/client/src/components/common/PageHeader.d.ts.map +1 -0
- package/dist/web/client/src/components/common/PageHeader.js +14 -0
- package/dist/web/client/src/components/common/PageHeader.js.map +1 -0
- package/dist/web/client/src/components/common/SearchInput.d.ts +14 -0
- package/dist/web/client/src/components/common/SearchInput.d.ts.map +1 -0
- package/dist/web/client/src/components/common/SearchInput.js +15 -0
- package/dist/web/client/src/components/common/SearchInput.js.map +1 -0
- package/dist/web/client/src/components/common/StatusBadge.d.ts +10 -0
- package/dist/web/client/src/components/common/StatusBadge.d.ts.map +1 -0
- package/dist/web/client/src/components/common/StatusBadge.js +15 -0
- package/dist/web/client/src/components/common/StatusBadge.js.map +1 -0
- package/dist/web/client/src/components/common/index.d.ts +6 -0
- package/dist/web/client/src/components/common/index.d.ts.map +1 -0
- package/dist/web/client/src/components/common/index.js +6 -0
- package/dist/web/client/src/components/common/index.js.map +1 -0
- package/dist/web/client/src/components/ui/alert.d.ts +9 -0
- package/dist/web/client/src/components/ui/alert.d.ts.map +1 -0
- package/dist/web/client/src/components/ui/alert.js +25 -0
- package/dist/web/client/src/components/ui/alert.js.map +1 -0
- package/dist/web/client/src/components/ui/badge.d.ts +10 -0
- package/dist/web/client/src/components/ui/badge.d.ts.map +1 -0
- package/dist/web/client/src/components/ui/badge.js +25 -0
- package/dist/web/client/src/components/ui/badge.js.map +1 -0
- package/dist/web/client/src/components/ui/button.d.ts +12 -0
- package/dist/web/client/src/components/ui/button.d.ts.map +1 -0
- package/dist/web/client/src/components/ui/button.js +33 -0
- package/dist/web/client/src/components/ui/button.js.map +1 -0
- package/dist/web/client/src/components/ui/card.d.ts +9 -0
- package/dist/web/client/src/components/ui/card.d.ts.map +1 -0
- package/dist/web/client/src/components/ui/card.js +16 -0
- package/dist/web/client/src/components/ui/card.js.map +1 -0
- package/dist/web/client/src/components/ui/index.d.ts +8 -0
- package/dist/web/client/src/components/ui/index.d.ts.map +1 -0
- package/dist/web/client/src/components/ui/index.js +8 -0
- package/dist/web/client/src/components/ui/index.js.map +1 -0
- package/dist/web/client/src/components/ui/input.d.ts +4 -0
- package/dist/web/client/src/components/ui/input.d.ts.map +1 -0
- package/dist/web/client/src/components/ui/input.js +8 -0
- package/dist/web/client/src/components/ui/input.js.map +1 -0
- package/dist/web/client/src/components/ui/select.d.ts +14 -0
- package/dist/web/client/src/components/ui/select.d.ts.map +1 -0
- package/dist/web/client/src/components/ui/select.js +39 -0
- package/dist/web/client/src/components/ui/select.js.map +1 -0
- package/dist/web/client/src/components/ui/table.d.ts +11 -0
- package/dist/web/client/src/components/ui/table.d.ts.map +1 -0
- package/dist/web/client/src/components/ui/table.js +21 -0
- package/dist/web/client/src/components/ui/table.js.map +1 -0
- package/dist/web/client/src/hooks/useSessions.d.ts.map +1 -1
- package/dist/web/client/src/hooks/useSessions.js +6 -1
- package/dist/web/client/src/hooks/useSessions.js.map +1 -1
- package/dist/web/client/src/lib/utils.d.ts +7 -0
- package/dist/web/client/src/lib/utils.d.ts.map +1 -0
- package/dist/web/client/src/lib/utils.js +10 -0
- package/dist/web/client/src/lib/utils.js.map +1 -0
- package/dist/web/client/src/lib/websocket.d.ts +7 -0
- package/dist/web/client/src/lib/websocket.d.ts.map +1 -1
- package/dist/web/client/src/lib/websocket.js +44 -0
- package/dist/web/client/src/lib/websocket.js.map +1 -1
- package/dist/web/client/src/pages/BranchDetailPage.d.ts.map +1 -1
- package/dist/web/client/src/pages/BranchDetailPage.js +113 -361
- package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
- package/dist/web/client/src/pages/BranchListPage.d.ts.map +1 -1
- package/dist/web/client/src/pages/BranchListPage.js +89 -127
- package/dist/web/client/src/pages/BranchListPage.js.map +1 -1
- package/dist/web/client/src/pages/ConfigManagementPage.d.ts.map +1 -1
- package/dist/web/client/src/pages/ConfigManagementPage.js +46 -41
- package/dist/web/client/src/pages/ConfigManagementPage.js.map +1 -1
- package/dist/web/client/src/pages/ConfigPage.d.ts +3 -0
- package/dist/web/client/src/pages/ConfigPage.d.ts.map +1 -0
- package/dist/web/client/src/pages/ConfigPage.js +216 -0
- package/dist/web/client/src/pages/ConfigPage.js.map +1 -0
- package/dist/web/client/vite.config.d.ts.map +1 -1
- package/dist/web/client/vite.config.js +8 -1
- package/dist/web/client/vite.config.js.map +1 -1
- package/dist/web/server/index.d.ts +24 -2
- package/dist/web/server/index.d.ts.map +1 -1
- package/dist/web/server/index.js +49 -18
- package/dist/web/server/index.js.map +1 -1
- package/dist/web/server/pty/manager.d.ts +12 -10
- package/dist/web/server/pty/manager.d.ts.map +1 -1
- package/dist/web/server/pty/manager.js +76 -43
- package/dist/web/server/pty/manager.js.map +1 -1
- package/dist/web/server/routes/branches.d.ts +2 -2
- package/dist/web/server/routes/branches.d.ts.map +1 -1
- package/dist/web/server/routes/branches.js.map +1 -1
- package/dist/web/server/routes/config.d.ts +2 -2
- package/dist/web/server/routes/config.d.ts.map +1 -1
- package/dist/web/server/routes/config.js.map +1 -1
- package/dist/web/server/routes/index.d.ts +2 -2
- package/dist/web/server/routes/index.d.ts.map +1 -1
- package/dist/web/server/routes/index.js.map +1 -1
- package/dist/web/server/routes/sessions.d.ts +2 -2
- package/dist/web/server/routes/sessions.d.ts.map +1 -1
- package/dist/web/server/routes/sessions.js +35 -2
- package/dist/web/server/routes/sessions.js.map +1 -1
- package/dist/web/server/routes/worktrees.d.ts +2 -2
- package/dist/web/server/routes/worktrees.d.ts.map +1 -1
- package/dist/web/server/routes/worktrees.js +2 -2
- package/dist/web/server/routes/worktrees.js.map +1 -1
- package/dist/web/server/services/worktrees.d.ts.map +1 -1
- package/dist/web/server/services/worktrees.js +7 -1
- package/dist/web/server/services/worktrees.js.map +1 -1
- package/dist/web/server/tray.d.ts +24 -0
- package/dist/web/server/tray.d.ts.map +1 -0
- package/dist/web/server/tray.js +79 -0
- package/dist/web/server/tray.js.map +1 -0
- package/dist/web/server/types.d.ts +4 -0
- package/dist/web/server/types.d.ts.map +1 -0
- package/dist/web/server/types.js +2 -0
- package/dist/web/server/types.js.map +1 -0
- package/dist/web/server/websocket/handler.d.ts +18 -2
- package/dist/web/server/websocket/handler.d.ts.map +1 -1
- package/dist/web/server/websocket/handler.js +82 -9
- package/dist/web/server/websocket/handler.js.map +1 -1
- package/dist/worktree.d.ts +1 -0
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js.map +1 -1
- package/package.json +17 -3
- package/src/claude.ts +26 -15
- package/src/cli/ui/__tests__/components/ModelSelectorScreen.initial.test.tsx +13 -13
- package/src/cli/ui/__tests__/components/common/Select.test.tsx +11 -0
- package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +97 -33
- package/src/cli/ui/__tests__/components/screens/BranchQuickStartScreen.test.tsx +4 -4
- package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +7 -3
- package/src/cli/ui/components/App.tsx +111 -125
- package/src/cli/ui/components/common/Select.tsx +2 -2
- package/src/cli/ui/components/screens/BranchListScreen.tsx +220 -34
- package/src/cli/ui/components/screens/BranchQuickStartScreen.tsx +41 -46
- package/src/cli/ui/hooks/useGitData.ts +20 -0
- package/src/cli/ui/types.ts +3 -0
- package/src/cli/ui/utils/branchFormatter.ts +7 -2
- package/src/cli/ui/utils/continueSession.ts +1 -7
- package/src/cli/ui/utils/modelOptions.test.ts +14 -0
- package/src/cli/ui/utils/modelOptions.ts +7 -0
- package/src/codex.ts +31 -22
- package/src/config/builtin-tools.ts +6 -2
- package/src/config/shared-env.ts +139 -0
- package/src/gemini.ts +35 -22
- package/src/index.ts +61 -7
- package/src/logging/logger.ts +82 -0
- package/src/logging/rotation.ts +25 -0
- package/src/qwen.ts +28 -19
- package/src/services/aiToolResolver.ts +276 -0
- package/src/services/customToolResolver.ts +98 -0
- package/src/shared/aiToolConstants.ts +30 -0
- package/src/trayicon.d.ts +30 -0
- package/src/types/tools.ts +15 -0
- package/src/utils/prompt.ts +15 -9
- package/src/utils/session.ts +80 -26
- package/src/utils/terminal.ts +11 -41
- package/src/utils/webui.ts +43 -0
- package/src/web/client/components.json +21 -0
- package/src/web/client/src/components/AIToolLaunchModal.tsx +575 -0
- package/src/web/client/src/components/BranchGraph.tsx +95 -75
- package/src/web/client/src/components/CustomToolForm.tsx +386 -0
- package/src/web/client/src/components/CustomToolList.tsx +119 -0
- package/src/web/client/src/components/EnvEditor.tsx +91 -81
- package/src/web/client/src/components/EnvironmentEditor.tsx +97 -0
- package/src/web/client/src/components/Terminal.tsx +11 -3
- package/src/web/client/src/components/branch-detail/BranchInfoCards.tsx +179 -0
- package/src/web/client/src/components/branch-detail/SessionHistoryTable.tsx +181 -0
- package/src/web/client/src/components/branch-detail/TerminalPanel.tsx +92 -0
- package/src/web/client/src/components/branch-detail/ToolLauncher.tsx +327 -0
- package/src/web/client/src/components/branch-detail/index.ts +4 -0
- package/src/web/client/src/components/common/BranchCard.tsx +117 -0
- package/src/web/client/src/components/common/MetricCard.tsx +22 -0
- package/src/web/client/src/components/common/PageHeader.tsx +44 -0
- package/src/web/client/src/components/common/SearchInput.tsx +40 -0
- package/src/web/client/src/components/common/StatusBadge.tsx +37 -0
- package/src/web/client/src/components/common/index.ts +5 -0
- package/src/web/client/src/components/ui/alert.tsx +63 -0
- package/src/web/client/src/components/ui/badge.tsx +44 -0
- package/src/web/client/src/components/ui/button.tsx +57 -0
- package/src/web/client/src/components/ui/card.tsx +82 -0
- package/src/web/client/src/components/ui/index.ts +32 -0
- package/src/web/client/src/components/ui/input.tsx +21 -0
- package/src/web/client/src/components/ui/select.tsx +156 -0
- package/src/web/client/src/components/ui/table.tsx +119 -0
- package/src/web/client/src/hooks/useSessions.ts +10 -1
- package/src/web/client/src/index.css +46 -816
- package/src/web/client/src/lib/utils.ts +10 -0
- package/src/web/client/src/lib/websocket.ts +48 -1
- package/src/web/client/src/pages/BranchDetailPage.tsx +222 -694
- package/src/web/client/src/pages/BranchListPage.tsx +190 -236
- package/src/web/client/src/pages/ConfigManagementPage.tsx +94 -76
- package/src/web/client/src/pages/ConfigPage.tsx +362 -0
- package/src/web/client/vite.config.ts +8 -1
- package/src/web/server/index.ts +78 -19
- package/src/web/server/pty/manager.ts +128 -55
- package/src/web/server/routes/branches.ts +2 -2
- package/src/web/server/routes/config.ts +2 -2
- package/src/web/server/routes/index.ts +2 -2
- package/src/web/server/routes/sessions.ts +61 -9
- package/src/web/server/routes/worktrees.ts +5 -5
- package/src/web/server/services/worktrees.ts +12 -4
- package/src/web/server/tray.ts +93 -0
- package/src/web/server/types.ts +14 -0
- package/src/web/server/websocket/handler.ts +119 -13
- package/src/worktree.ts +1 -0
- package/dist/client/assets/index-DeNwPosA.css +0 -1
- package/dist/client/assets/index-Dl798X5w.js +0 -32
|
@@ -9,7 +9,17 @@ import {
|
|
|
9
9
|
} from "../hooks/useSessions";
|
|
10
10
|
import { useConfig } from "../hooks/useConfig";
|
|
11
11
|
import { ApiError } from "../lib/api";
|
|
12
|
-
import {
|
|
12
|
+
import { PageHeader } from "@/components/common/PageHeader";
|
|
13
|
+
import { Button } from "@/components/ui/button";
|
|
14
|
+
import { Badge } from "@/components/ui/badge";
|
|
15
|
+
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
16
|
+
import {
|
|
17
|
+
SessionHistoryTable,
|
|
18
|
+
ToolLauncher,
|
|
19
|
+
BranchInfoCards,
|
|
20
|
+
TerminalPanel,
|
|
21
|
+
type SelectableTool,
|
|
22
|
+
} from "@/components/branch-detail";
|
|
13
23
|
import type {
|
|
14
24
|
Branch,
|
|
15
25
|
CustomAITool,
|
|
@@ -19,44 +29,6 @@ import type {
|
|
|
19
29
|
type ToolType = "claude-code" | "codex-cli" | "custom";
|
|
20
30
|
type ToolMode = "normal" | "continue" | "resume";
|
|
21
31
|
|
|
22
|
-
type SelectableTool =
|
|
23
|
-
| { id: "claude-code"; label: string; target: "claude" }
|
|
24
|
-
| { id: "codex-cli"; label: string; target: "codex" }
|
|
25
|
-
| { id: string; label: string; target: "custom"; definition: CustomAITool };
|
|
26
|
-
|
|
27
|
-
interface ToolSummary {
|
|
28
|
-
command: string;
|
|
29
|
-
defaultArgs?: string[] | null;
|
|
30
|
-
modeArgs?: {
|
|
31
|
-
normal?: string[];
|
|
32
|
-
continue?: string[];
|
|
33
|
-
resume?: string[];
|
|
34
|
-
};
|
|
35
|
-
permissionSkipArgs?: string[] | null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const BUILTIN_TOOL_SUMMARIES: Record<string, ToolSummary> = {
|
|
39
|
-
"claude-code": {
|
|
40
|
-
command: "claude",
|
|
41
|
-
defaultArgs: [],
|
|
42
|
-
modeArgs: {
|
|
43
|
-
normal: [],
|
|
44
|
-
continue: ["-c"],
|
|
45
|
-
resume: ["-r"],
|
|
46
|
-
},
|
|
47
|
-
permissionSkipArgs: ["--dangerously-skip-permissions"],
|
|
48
|
-
},
|
|
49
|
-
"codex-cli": {
|
|
50
|
-
command: "codex",
|
|
51
|
-
defaultArgs: ["--auto-approve", "--verbose"],
|
|
52
|
-
modeArgs: {
|
|
53
|
-
normal: [],
|
|
54
|
-
continue: ["resume", "--last"],
|
|
55
|
-
resume: ["resume"],
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
|
|
60
32
|
interface BannerState {
|
|
61
33
|
type: "success" | "error" | "info";
|
|
62
34
|
message: string;
|
|
@@ -73,15 +45,6 @@ const MERGE_STATUS_LABEL: Record<Branch["mergeStatus"], string> = {
|
|
|
73
45
|
unknown: "状態不明",
|
|
74
46
|
};
|
|
75
47
|
|
|
76
|
-
const MERGE_STATUS_TONE: Record<
|
|
77
|
-
Branch["mergeStatus"],
|
|
78
|
-
"success" | "warning" | "muted"
|
|
79
|
-
> = {
|
|
80
|
-
merged: "success",
|
|
81
|
-
unmerged: "warning",
|
|
82
|
-
unknown: "muted",
|
|
83
|
-
};
|
|
84
|
-
|
|
85
48
|
export function BranchDetailPage() {
|
|
86
49
|
const { branchName } = useParams<{ branchName: string }>();
|
|
87
50
|
const decodedBranchName = branchName ? decodeURIComponent(branchName) : "";
|
|
@@ -115,58 +78,76 @@ export function BranchDetailPage() {
|
|
|
115
78
|
[branch?.commitDate],
|
|
116
79
|
);
|
|
117
80
|
|
|
81
|
+
// Handle fullscreen body overflow
|
|
118
82
|
useEffect(() => {
|
|
119
|
-
if (!isTerminalFullscreen)
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
|
|
83
|
+
if (!isTerminalFullscreen) return undefined;
|
|
123
84
|
const previousOverflow = document.body.style.overflow;
|
|
124
85
|
document.body.style.overflow = "hidden";
|
|
125
|
-
|
|
126
86
|
return () => {
|
|
127
87
|
document.body.style.overflow = previousOverflow;
|
|
128
88
|
};
|
|
129
89
|
}, [isTerminalFullscreen]);
|
|
130
90
|
|
|
91
|
+
// Loading state
|
|
131
92
|
if (isLoading) {
|
|
132
93
|
return (
|
|
133
|
-
<div className="
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
94
|
+
<div className="min-h-screen bg-background">
|
|
95
|
+
<PageHeader
|
|
96
|
+
eyebrow="BRANCH DETAIL"
|
|
97
|
+
title="読み込み中..."
|
|
98
|
+
subtitle="ブランチ情報を取得しています"
|
|
99
|
+
/>
|
|
100
|
+
<main className="mx-auto max-w-7xl px-6 py-8">
|
|
101
|
+
<div className="flex items-center justify-center py-20">
|
|
102
|
+
<div className="text-center">
|
|
103
|
+
<div className="mb-4 text-4xl">⏳</div>
|
|
104
|
+
<p className="text-muted-foreground">Loading branch...</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</main>
|
|
138
108
|
</div>
|
|
139
109
|
);
|
|
140
110
|
}
|
|
141
111
|
|
|
112
|
+
// Error state
|
|
142
113
|
if (error) {
|
|
143
114
|
return (
|
|
144
|
-
<div className="
|
|
145
|
-
<
|
|
146
|
-
|
|
147
|
-
<
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
115
|
+
<div className="min-h-screen bg-background">
|
|
116
|
+
<PageHeader eyebrow="BRANCH DETAIL" title="エラー" />
|
|
117
|
+
<main className="mx-auto max-w-7xl px-6 py-8">
|
|
118
|
+
<Alert variant="destructive">
|
|
119
|
+
<AlertDescription>
|
|
120
|
+
{error instanceof Error ? error.message : "未知のエラーです"}
|
|
121
|
+
</AlertDescription>
|
|
122
|
+
</Alert>
|
|
123
|
+
<div className="mt-4">
|
|
124
|
+
<Button variant="ghost" asChild>
|
|
125
|
+
<Link to="/">← ブランチ一覧に戻る</Link>
|
|
126
|
+
</Button>
|
|
127
|
+
</div>
|
|
128
|
+
</main>
|
|
152
129
|
</div>
|
|
153
130
|
);
|
|
154
131
|
}
|
|
155
132
|
|
|
133
|
+
// Not found state
|
|
156
134
|
if (!branch) {
|
|
157
135
|
return (
|
|
158
|
-
<div className="
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
<p
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
136
|
+
<div className="min-h-screen bg-background">
|
|
137
|
+
<PageHeader eyebrow="BRANCH DETAIL" title="Branch not found" />
|
|
138
|
+
<main className="mx-auto max-w-7xl px-6 py-8">
|
|
139
|
+
<p className="mb-4 text-muted-foreground">
|
|
140
|
+
指定されたブランチは存在しません。
|
|
141
|
+
</p>
|
|
142
|
+
<Button variant="ghost" asChild>
|
|
143
|
+
<Link to="/">← ブランチ一覧に戻る</Link>
|
|
144
|
+
</Button>
|
|
145
|
+
</main>
|
|
166
146
|
</div>
|
|
167
147
|
);
|
|
168
148
|
}
|
|
169
149
|
|
|
150
|
+
// Computed values
|
|
170
151
|
const canStartSession = Boolean(branch.worktreePath);
|
|
171
152
|
const divergenceInfo = branch.divergence ?? null;
|
|
172
153
|
const hasBlockingDivergence = Boolean(
|
|
@@ -174,13 +155,14 @@ export function BranchDetailPage() {
|
|
|
174
155
|
);
|
|
175
156
|
const needsRemoteSync = Boolean(
|
|
176
157
|
branch.worktreePath &&
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
158
|
+
divergenceInfo &&
|
|
159
|
+
divergenceInfo.behind > 0 &&
|
|
160
|
+
divergenceInfo.ahead === 0 &&
|
|
161
|
+
!hasBlockingDivergence,
|
|
181
162
|
);
|
|
182
163
|
const isSyncingBranch = syncBranch.isPending;
|
|
183
164
|
|
|
165
|
+
// Available tools
|
|
184
166
|
const customTools: CustomAITool[] = config?.tools ?? [];
|
|
185
167
|
const availableTools: SelectableTool[] = useMemo(
|
|
186
168
|
() => [
|
|
@@ -198,6 +180,7 @@ export function BranchDetailPage() {
|
|
|
198
180
|
[customTools],
|
|
199
181
|
);
|
|
200
182
|
|
|
183
|
+
// Ensure selected tool is valid
|
|
201
184
|
useEffect(() => {
|
|
202
185
|
if (!availableTools.length) {
|
|
203
186
|
setSelectedToolId("claude-code");
|
|
@@ -205,9 +188,7 @@ export function BranchDetailPage() {
|
|
|
205
188
|
}
|
|
206
189
|
if (!availableTools.find((tool) => tool.id === selectedToolId)) {
|
|
207
190
|
const first = availableTools[0];
|
|
208
|
-
if (first)
|
|
209
|
-
setSelectedToolId(first.id);
|
|
210
|
-
}
|
|
191
|
+
if (first) setSelectedToolId(first.id);
|
|
211
192
|
}
|
|
212
193
|
}, [availableTools, selectedToolId]);
|
|
213
194
|
|
|
@@ -215,43 +196,41 @@ export function BranchDetailPage() {
|
|
|
215
196
|
(tool) => tool.id === selectedToolId,
|
|
216
197
|
);
|
|
217
198
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
command: selectedTool.definition.command,
|
|
225
|
-
defaultArgs: selectedTool.definition.defaultArgs ?? null,
|
|
226
|
-
modeArgs: selectedTool.definition.modeArgs,
|
|
227
|
-
permissionSkipArgs: selectedTool.definition.permissionSkipArgs ?? null,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
return BUILTIN_TOOL_SUMMARIES[selectedTool.id] ?? null;
|
|
231
|
-
}, [selectedTool]);
|
|
199
|
+
// Branch sessions
|
|
200
|
+
const branchSessions = useMemo(() => {
|
|
201
|
+
return (sessionsData ?? [])
|
|
202
|
+
.filter((session) => session.worktreePath === branch?.worktreePath)
|
|
203
|
+
.sort((a, b) => (b.startedAt ?? "").localeCompare(a.startedAt ?? ""));
|
|
204
|
+
}, [sessionsData, branch?.worktreePath]);
|
|
232
205
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}, [
|
|
206
|
+
// Latest tool usage
|
|
207
|
+
const latestToolUsage: LastToolUsage | null = useMemo(() => {
|
|
208
|
+
if (branch?.lastToolUsage) return branch.lastToolUsage;
|
|
209
|
+
const first = branchSessions[0];
|
|
210
|
+
if (!first) return null;
|
|
211
|
+
return {
|
|
212
|
+
branch: branch.name,
|
|
213
|
+
worktreePath: branch.worktreePath ?? null,
|
|
214
|
+
toolId:
|
|
215
|
+
first.toolType === "custom"
|
|
216
|
+
? (first.toolName ?? "custom")
|
|
217
|
+
: (first.toolType as LastToolUsage["toolId"]),
|
|
218
|
+
toolLabel:
|
|
219
|
+
first.toolType === "custom"
|
|
220
|
+
? (first.toolName ?? "Custom")
|
|
221
|
+
: toolLabel(first.toolType),
|
|
222
|
+
mode: first.mode ?? "normal",
|
|
223
|
+
model: null,
|
|
224
|
+
timestamp: first.startedAt ? Date.parse(first.startedAt) : Date.now(),
|
|
225
|
+
};
|
|
226
|
+
}, [
|
|
227
|
+
branch?.lastToolUsage,
|
|
228
|
+
branch?.name,
|
|
229
|
+
branch?.worktreePath,
|
|
230
|
+
branchSessions,
|
|
231
|
+
]);
|
|
254
232
|
|
|
233
|
+
// Handlers
|
|
255
234
|
const handleCreateWorktree = async () => {
|
|
256
235
|
try {
|
|
257
236
|
await createWorktree.mutateAsync({
|
|
@@ -290,8 +269,7 @@ export function BranchDetailPage() {
|
|
|
290
269
|
if (needsRemoteSync) {
|
|
291
270
|
setBanner({
|
|
292
271
|
type: "error",
|
|
293
|
-
message:
|
|
294
|
-
"リモートの更新を取り込むまでAIツールは起動できません。『最新の変更を同期』を実行してください。",
|
|
272
|
+
message: "リモートの更新を取り込むまでAIツールは起動できません。",
|
|
295
273
|
});
|
|
296
274
|
return;
|
|
297
275
|
}
|
|
@@ -299,17 +277,14 @@ export function BranchDetailPage() {
|
|
|
299
277
|
if (hasBlockingDivergence) {
|
|
300
278
|
setBanner({
|
|
301
279
|
type: "error",
|
|
302
|
-
message:
|
|
303
|
-
"リモートとローカルの双方で進捗が発生しているため、CLIと同様にAIツールの起動をブロックしました。先に rebase/merge 等で差分を解消してください。",
|
|
280
|
+
message: "差分を解消してから起動してください。",
|
|
304
281
|
});
|
|
305
282
|
return;
|
|
306
283
|
}
|
|
307
284
|
|
|
308
285
|
if (
|
|
309
286
|
skipPermissions &&
|
|
310
|
-
!window.confirm(
|
|
311
|
-
"権限チェックをスキップして起動します。自己責任で実行してください。続行しますか?",
|
|
312
|
-
)
|
|
287
|
+
!window.confirm("権限チェックをスキップして起動します。続行しますか?")
|
|
313
288
|
) {
|
|
314
289
|
return;
|
|
315
290
|
}
|
|
@@ -322,7 +297,10 @@ export function BranchDetailPage() {
|
|
|
322
297
|
: selectedTool.target === "custom"
|
|
323
298
|
? "custom"
|
|
324
299
|
: "claude-code";
|
|
325
|
-
const extraArgs =
|
|
300
|
+
const extraArgs = extraArgsText
|
|
301
|
+
.split(/\s+/)
|
|
302
|
+
.map((c) => c.trim())
|
|
303
|
+
.filter(Boolean);
|
|
326
304
|
const sessionRequest = {
|
|
327
305
|
toolType,
|
|
328
306
|
toolName: selectedTool.target === "custom" ? selectedTool.id : null,
|
|
@@ -360,9 +338,7 @@ export function BranchDetailPage() {
|
|
|
360
338
|
try {
|
|
361
339
|
await deleteSession.mutateAsync(sessionId);
|
|
362
340
|
setBanner({ type: "success", message: "セッションを終了しました" });
|
|
363
|
-
if (activeSessionId === sessionId)
|
|
364
|
-
setActiveSessionId(null);
|
|
365
|
-
}
|
|
341
|
+
if (activeSessionId === sessionId) setActiveSessionId(null);
|
|
366
342
|
} catch (err) {
|
|
367
343
|
setBanner({
|
|
368
344
|
type: "error",
|
|
@@ -408,40 +384,6 @@ export function BranchDetailPage() {
|
|
|
408
384
|
}
|
|
409
385
|
};
|
|
410
386
|
|
|
411
|
-
const branchSessions = useMemo(() => {
|
|
412
|
-
return (sessionsData ?? [])
|
|
413
|
-
.filter((session) => session.worktreePath === branch?.worktreePath)
|
|
414
|
-
.sort((a, b) => (b.startedAt ?? "").localeCompare(a.startedAt ?? ""));
|
|
415
|
-
}, [sessionsData, branch?.worktreePath]);
|
|
416
|
-
|
|
417
|
-
const latestToolUsage: LastToolUsage | null = useMemo(() => {
|
|
418
|
-
if (branch?.lastToolUsage) {
|
|
419
|
-
return branch.lastToolUsage;
|
|
420
|
-
}
|
|
421
|
-
const first = branchSessions[0];
|
|
422
|
-
if (!first) return null;
|
|
423
|
-
return {
|
|
424
|
-
branch: branch.name,
|
|
425
|
-
worktreePath: branch.worktreePath ?? null,
|
|
426
|
-
toolId:
|
|
427
|
-
first.toolType === "custom"
|
|
428
|
-
? (first.toolName ?? "custom")
|
|
429
|
-
: (first.toolType as LastToolUsage["toolId"]),
|
|
430
|
-
toolLabel:
|
|
431
|
-
first.toolType === "custom"
|
|
432
|
-
? (first.toolName ?? "Custom")
|
|
433
|
-
: toolLabel(first.toolType),
|
|
434
|
-
mode: first.mode ?? "normal",
|
|
435
|
-
model: null,
|
|
436
|
-
timestamp: first.startedAt ? Date.parse(first.startedAt) : Date.now(),
|
|
437
|
-
};
|
|
438
|
-
}, [
|
|
439
|
-
branch?.lastToolUsage,
|
|
440
|
-
branch?.name,
|
|
441
|
-
branch?.worktreePath,
|
|
442
|
-
branchSessions,
|
|
443
|
-
]);
|
|
444
|
-
|
|
445
387
|
const handleSessionExit = (code: number) => {
|
|
446
388
|
setActiveSessionId(null);
|
|
447
389
|
setIsTerminalFullscreen(false);
|
|
@@ -452,488 +394,132 @@ export function BranchDetailPage() {
|
|
|
452
394
|
};
|
|
453
395
|
|
|
454
396
|
return (
|
|
455
|
-
<div className="
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
397
|
+
<div className="min-h-screen bg-background">
|
|
398
|
+
{/* Fullscreen backdrop */}
|
|
399
|
+
{isTerminalFullscreen && (
|
|
400
|
+
<div
|
|
401
|
+
className="fixed inset-0 z-40 bg-black/80"
|
|
402
|
+
aria-hidden="true"
|
|
403
|
+
onClick={() => setIsTerminalFullscreen(false)}
|
|
404
|
+
/>
|
|
405
|
+
)}
|
|
406
|
+
|
|
407
|
+
{/* Header */}
|
|
408
|
+
<PageHeader
|
|
409
|
+
eyebrow="BRANCH DETAIL"
|
|
410
|
+
title={branch.name}
|
|
411
|
+
subtitle={`最新コミット ${branch.commitHash.slice(0, 7)} · ${formattedCommitDate}`}
|
|
412
|
+
>
|
|
413
|
+
<div className="mt-4 flex flex-wrap gap-2">
|
|
414
|
+
<Badge variant={branch.type === "local" ? "local" : "remote"}>
|
|
467
415
|
{BRANCH_TYPE_LABEL[branch.type]}
|
|
468
|
-
</
|
|
469
|
-
<
|
|
470
|
-
|
|
416
|
+
</Badge>
|
|
417
|
+
<Badge
|
|
418
|
+
variant={
|
|
419
|
+
branch.mergeStatus === "merged"
|
|
420
|
+
? "success"
|
|
421
|
+
: branch.mergeStatus === "unmerged"
|
|
422
|
+
? "warning"
|
|
423
|
+
: "outline"
|
|
424
|
+
}
|
|
471
425
|
>
|
|
472
426
|
{MERGE_STATUS_LABEL[branch.mergeStatus]}
|
|
473
|
-
</
|
|
474
|
-
<
|
|
475
|
-
className={`status-badge ${
|
|
476
|
-
branch.worktreePath
|
|
477
|
-
? "status-badge--success"
|
|
478
|
-
: "status-badge--muted"
|
|
479
|
-
}`}
|
|
480
|
-
>
|
|
427
|
+
</Badge>
|
|
428
|
+
<Badge variant={branch.worktreePath ? "success" : "outline"}>
|
|
481
429
|
{branch.worktreePath ? "Worktreeあり" : "Worktree未作成"}
|
|
482
|
-
</
|
|
483
|
-
</div>
|
|
484
|
-
<div className="badge-group" style={{ marginTop: "0.5rem" }}>
|
|
485
|
-
{latestToolUsage ? (
|
|
486
|
-
<>
|
|
487
|
-
<span className="status-badge status-badge--muted">
|
|
488
|
-
{renderToolUsage(latestToolUsage)}
|
|
489
|
-
</span>
|
|
490
|
-
<span className="status-badge status-badge--muted">
|
|
491
|
-
{formatUsageTimestamp(latestToolUsage.timestamp)} ・ worktree:{" "}
|
|
492
|
-
{latestToolUsage.worktreePath ?? branch.worktreePath ?? "N/A"}
|
|
493
|
-
</span>
|
|
494
|
-
</>
|
|
495
|
-
) : (
|
|
496
|
-
<span className="status-badge status-badge--muted">Unknown</span>
|
|
497
|
-
)}
|
|
430
|
+
</Badge>
|
|
498
431
|
</div>
|
|
499
|
-
<div className="
|
|
432
|
+
<div className="mt-4 flex flex-wrap gap-2">
|
|
433
|
+
<Button variant="ghost" size="sm" asChild>
|
|
434
|
+
<Link to="/">← ブランチ一覧</Link>
|
|
435
|
+
</Button>
|
|
500
436
|
{!canStartSession ? (
|
|
501
|
-
<
|
|
502
|
-
type="button"
|
|
503
|
-
className="button button--primary"
|
|
437
|
+
<Button
|
|
504
438
|
onClick={handleCreateWorktree}
|
|
505
439
|
disabled={createWorktree.isPending}
|
|
506
440
|
>
|
|
507
441
|
{createWorktree.isPending ? "作成中..." : "Worktreeを作成"}
|
|
508
|
-
</
|
|
442
|
+
</Button>
|
|
509
443
|
) : (
|
|
510
|
-
<
|
|
511
|
-
|
|
512
|
-
</
|
|
444
|
+
<Button variant="secondary" asChild>
|
|
445
|
+
<Link to="/config">カスタムツール設定</Link>
|
|
446
|
+
</Button>
|
|
513
447
|
)}
|
|
514
448
|
</div>
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
449
|
+
</PageHeader>
|
|
450
|
+
|
|
451
|
+
{/* Banner */}
|
|
452
|
+
{banner && (
|
|
453
|
+
<div className="mx-auto max-w-7xl px-6 pt-4">
|
|
454
|
+
<Alert
|
|
455
|
+
variant={
|
|
456
|
+
banner.type === "error"
|
|
457
|
+
? "destructive"
|
|
458
|
+
: banner.type === "success"
|
|
459
|
+
? "success"
|
|
460
|
+
: "info"
|
|
461
|
+
}
|
|
462
|
+
>
|
|
463
|
+
<AlertDescription>{banner.message}</AlertDescription>
|
|
464
|
+
</Alert>
|
|
465
|
+
</div>
|
|
529
466
|
)}
|
|
530
|
-
<main className="page-content page-content--wide">
|
|
531
|
-
<div className="page-layout page-layout--split">
|
|
532
|
-
<div className="info-stack">
|
|
533
|
-
<section className="section-card">
|
|
534
|
-
<header className="terminal-section__header">
|
|
535
|
-
<div>
|
|
536
|
-
<h2>AIツール起動</h2>
|
|
537
|
-
<p className="section-card__body">
|
|
538
|
-
Web UI
|
|
539
|
-
から直接AIツールを起動できます。設定したカスタムツールも一覧に表示されます。
|
|
540
|
-
</p>
|
|
541
|
-
</div>
|
|
542
|
-
{configError && (
|
|
543
|
-
<span className="pill pill--warning">
|
|
544
|
-
設定の取得に失敗しました
|
|
545
|
-
</span>
|
|
546
|
-
)}
|
|
547
|
-
</header>
|
|
548
|
-
|
|
549
|
-
{!canStartSession ? (
|
|
550
|
-
<p className="section-card__body">
|
|
551
|
-
Worktreeが未作成のため、先にWorktreeを作成してください。
|
|
552
|
-
</p>
|
|
553
|
-
) : (
|
|
554
|
-
<div className="tool-form">
|
|
555
|
-
<div className="form-grid">
|
|
556
|
-
<label className="form-field">
|
|
557
|
-
<span>AIツール</span>
|
|
558
|
-
<select
|
|
559
|
-
value={selectedToolId}
|
|
560
|
-
onChange={(event) =>
|
|
561
|
-
setSelectedToolId(event.target.value)
|
|
562
|
-
}
|
|
563
|
-
disabled={isConfigLoading}
|
|
564
|
-
>
|
|
565
|
-
{availableTools.map((tool) => (
|
|
566
|
-
<option key={tool.id} value={tool.id}>
|
|
567
|
-
{tool.label}
|
|
568
|
-
</option>
|
|
569
|
-
))}
|
|
570
|
-
</select>
|
|
571
|
-
</label>
|
|
572
467
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
</label>
|
|
614
|
-
{skipPermissions && (
|
|
615
|
-
<div className="inline-banner inline-banner--warning">
|
|
616
|
-
<p>
|
|
617
|
-
権限チェックをスキップすることで、CLI での
|
|
618
|
-
`--dangerously-skip-permissions`
|
|
619
|
-
指定と同様のリスクを負います。
|
|
620
|
-
</p>
|
|
621
|
-
</div>
|
|
622
|
-
)}
|
|
623
|
-
{needsRemoteSync && (
|
|
624
|
-
<div
|
|
625
|
-
className="inline-banner inline-banner--info"
|
|
626
|
-
data-testid="sync-required"
|
|
627
|
-
>
|
|
628
|
-
<p>
|
|
629
|
-
リモートに未取得の更新 ({branch.divergence?.behind ?? 0}{" "}
|
|
630
|
-
commits)
|
|
631
|
-
があるため、AIツールを起動する前に同期してください。
|
|
632
|
-
</p>
|
|
633
|
-
<p className="section-card__body">
|
|
634
|
-
CLI の `git fetch --all` と `git pull --ff-only`
|
|
635
|
-
と同じ処理を Web UI から実行できます。
|
|
636
|
-
</p>
|
|
637
|
-
</div>
|
|
638
|
-
)}
|
|
639
|
-
{hasBlockingDivergence && (
|
|
640
|
-
<div
|
|
641
|
-
className="inline-banner inline-banner--warning"
|
|
642
|
-
data-testid="divergence-warning"
|
|
643
|
-
>
|
|
644
|
-
<p>
|
|
645
|
-
リモートとローカルの両方に未解決の差分があるため、Web UI
|
|
646
|
-
でも CLI と同様に起動をブロックしています。
|
|
647
|
-
</p>
|
|
648
|
-
<ul className="list-muted">
|
|
649
|
-
<li>
|
|
650
|
-
git fetch && git pull --ff-only origin {branch.name}
|
|
651
|
-
</li>
|
|
652
|
-
<li>
|
|
653
|
-
必要に応じて git push origin {branch.name}{" "}
|
|
654
|
-
でローカル進捗を共有
|
|
655
|
-
</li>
|
|
656
|
-
</ul>
|
|
657
|
-
<p className="section-card__body">
|
|
658
|
-
rebase / merge
|
|
659
|
-
などで差分を解消した後にページを更新してください。
|
|
660
|
-
</p>
|
|
661
|
-
</div>
|
|
662
|
-
)}
|
|
663
|
-
|
|
664
|
-
<div className="tool-card__actions">
|
|
665
|
-
<button
|
|
666
|
-
type="button"
|
|
667
|
-
className="button button--primary"
|
|
668
|
-
onClick={handleStartSession}
|
|
669
|
-
disabled={
|
|
670
|
-
isStartingSession ||
|
|
671
|
-
!selectedTool ||
|
|
672
|
-
hasBlockingDivergence ||
|
|
673
|
-
needsRemoteSync ||
|
|
674
|
-
isSyncingBranch
|
|
675
|
-
}
|
|
676
|
-
>
|
|
677
|
-
{isStartingSession ? "起動中..." : "セッションを起動"}
|
|
678
|
-
</button>
|
|
679
|
-
<button
|
|
680
|
-
type="button"
|
|
681
|
-
className="button button--secondary"
|
|
682
|
-
onClick={handleSyncBranch}
|
|
683
|
-
disabled={!branch.worktreePath || isSyncingBranch}
|
|
684
|
-
>
|
|
685
|
-
{isSyncingBranch ? "同期中..." : "最新の変更を同期"}
|
|
686
|
-
</button>
|
|
687
|
-
<Link to="/config" className="button button--ghost">
|
|
688
|
-
設定を編集
|
|
689
|
-
</Link>
|
|
690
|
-
</div>
|
|
691
|
-
|
|
692
|
-
{selectedToolSummary && (
|
|
693
|
-
<dl className="metadata-grid metadata-grid--compact">
|
|
694
|
-
<div>
|
|
695
|
-
<dt>コマンド</dt>
|
|
696
|
-
<dd className="tool-card__command">
|
|
697
|
-
{selectedToolSummary.command}
|
|
698
|
-
</dd>
|
|
699
|
-
</div>
|
|
700
|
-
<div>
|
|
701
|
-
<dt>defaultArgs</dt>
|
|
702
|
-
<dd>{renderArgs(selectedToolSummary.defaultArgs)}</dd>
|
|
703
|
-
</div>
|
|
704
|
-
<div>
|
|
705
|
-
<dt>permissionSkipArgs</dt>
|
|
706
|
-
<dd>
|
|
707
|
-
{renderArgs(selectedToolSummary.permissionSkipArgs)}
|
|
708
|
-
</dd>
|
|
709
|
-
</div>
|
|
710
|
-
{argsPreview && (
|
|
711
|
-
<div className="metadata-grid__full">
|
|
712
|
-
<dt>最終的に実行されるコマンド</dt>
|
|
713
|
-
<dd className="tool-card__command">
|
|
714
|
-
{argsPreview.command} {argsPreview.args.join(" ")}
|
|
715
|
-
</dd>
|
|
716
|
-
</div>
|
|
717
|
-
)}
|
|
718
|
-
</dl>
|
|
719
|
-
)}
|
|
720
|
-
</div>
|
|
721
|
-
)}
|
|
722
|
-
</section>
|
|
723
|
-
<section className="section-card">
|
|
724
|
-
<header className="terminal-section__header">
|
|
725
|
-
<div>
|
|
726
|
-
<h2>セッション履歴</h2>
|
|
727
|
-
<p className="section-card__body">
|
|
728
|
-
この Worktree に紐づいた最新の AI
|
|
729
|
-
セッションが表示されます。CLI からの起動分も共有されます。
|
|
730
|
-
</p>
|
|
731
|
-
</div>
|
|
732
|
-
{isSessionsLoading && (
|
|
733
|
-
<span className="pill">読み込み中...</span>
|
|
734
|
-
)}
|
|
735
|
-
</header>
|
|
736
|
-
{branchSessions.length === 0 ? (
|
|
737
|
-
<p className="section-card__body">
|
|
738
|
-
セッション履歴はまだありません。
|
|
739
|
-
</p>
|
|
740
|
-
) : (
|
|
741
|
-
<div className="session-table-wrapper">
|
|
742
|
-
<table className="session-table">
|
|
743
|
-
<thead>
|
|
744
|
-
<tr>
|
|
745
|
-
<th>状態</th>
|
|
746
|
-
<th>ツール</th>
|
|
747
|
-
<th>モード</th>
|
|
748
|
-
<th>開始時刻</th>
|
|
749
|
-
<th>終了時刻</th>
|
|
750
|
-
<th>操作</th>
|
|
751
|
-
</tr>
|
|
752
|
-
</thead>
|
|
753
|
-
<tbody>
|
|
754
|
-
{branchSessions.slice(0, 5).map((session) => (
|
|
755
|
-
<tr key={session.sessionId}>
|
|
756
|
-
<td>
|
|
757
|
-
<span
|
|
758
|
-
className={`status-pill status-pill--${session.status}`}
|
|
759
|
-
>
|
|
760
|
-
{SESSION_STATUS_LABEL[session.status]}
|
|
761
|
-
</span>
|
|
762
|
-
</td>
|
|
763
|
-
<td>
|
|
764
|
-
{session.toolType === "custom"
|
|
765
|
-
? (session.toolName ?? "custom")
|
|
766
|
-
: toolLabel(session.toolType)}
|
|
767
|
-
</td>
|
|
768
|
-
<td>{session.mode}</td>
|
|
769
|
-
<td>{formatDate(session.startedAt)}</td>
|
|
770
|
-
<td>
|
|
771
|
-
{session.endedAt
|
|
772
|
-
? formatDate(session.endedAt)
|
|
773
|
-
: "--"}
|
|
774
|
-
</td>
|
|
775
|
-
<td>
|
|
776
|
-
{session.status === "running" ? (
|
|
777
|
-
<button
|
|
778
|
-
type="button"
|
|
779
|
-
className="button button--ghost"
|
|
780
|
-
onClick={() =>
|
|
781
|
-
handleTerminateSession(session.sessionId)
|
|
782
|
-
}
|
|
783
|
-
disabled={
|
|
784
|
-
terminatingSessionId === session.sessionId ||
|
|
785
|
-
deleteSession.isPending
|
|
786
|
-
}
|
|
787
|
-
>
|
|
788
|
-
{terminatingSessionId === session.sessionId
|
|
789
|
-
? "終了中..."
|
|
790
|
-
: "終了"}
|
|
791
|
-
</button>
|
|
792
|
-
) : (
|
|
793
|
-
<span className="session-table__muted">--</span>
|
|
794
|
-
)}
|
|
795
|
-
</td>
|
|
796
|
-
</tr>
|
|
797
|
-
))}
|
|
798
|
-
</tbody>
|
|
799
|
-
</table>
|
|
800
|
-
</div>
|
|
801
|
-
)}
|
|
802
|
-
</section>
|
|
803
|
-
<section className="section-card">
|
|
804
|
-
<header>
|
|
805
|
-
<h2>ブランチインサイト</h2>
|
|
806
|
-
</header>
|
|
807
|
-
<dl className="metadata-grid">
|
|
808
|
-
<div>
|
|
809
|
-
<dt>コミット</dt>
|
|
810
|
-
<dd>{branch.commitHash}</dd>
|
|
811
|
-
</div>
|
|
812
|
-
<div>
|
|
813
|
-
<dt>Author</dt>
|
|
814
|
-
<dd>{branch.author ?? "N/A"}</dd>
|
|
815
|
-
</div>
|
|
816
|
-
<div>
|
|
817
|
-
<dt>更新日</dt>
|
|
818
|
-
<dd>{formattedCommitDate}</dd>
|
|
819
|
-
</div>
|
|
820
|
-
<div>
|
|
821
|
-
<dt>Worktree</dt>
|
|
822
|
-
<dd>{branch.worktreePath ?? "未作成"}</dd>
|
|
823
|
-
</div>
|
|
824
|
-
</dl>
|
|
825
|
-
</section>
|
|
826
|
-
|
|
827
|
-
<section className="section-card">
|
|
828
|
-
<header>
|
|
829
|
-
<h2>コミット情報</h2>
|
|
830
|
-
</header>
|
|
831
|
-
<p className="section-card__body">
|
|
832
|
-
{branch.commitMessage ?? "コミットメッセージがありません。"}
|
|
833
|
-
</p>
|
|
834
|
-
</section>
|
|
835
|
-
|
|
836
|
-
{branch.divergence && (
|
|
837
|
-
<section className="section-card">
|
|
838
|
-
<header>
|
|
839
|
-
<h2>差分状況</h2>
|
|
840
|
-
</header>
|
|
841
|
-
<div className="pill-group">
|
|
842
|
-
<span className="pill">Ahead {branch.divergence.ahead}</span>
|
|
843
|
-
<span className="pill">
|
|
844
|
-
Behind {branch.divergence.behind}
|
|
845
|
-
</span>
|
|
846
|
-
<span
|
|
847
|
-
className={`pill ${
|
|
848
|
-
branch.divergence.upToDate
|
|
849
|
-
? "pill--success"
|
|
850
|
-
: "pill--warning"
|
|
851
|
-
}`}
|
|
852
|
-
>
|
|
853
|
-
{branch.divergence.upToDate ? "最新" : "更新あり"}
|
|
854
|
-
</span>
|
|
855
|
-
</div>
|
|
856
|
-
</section>
|
|
857
|
-
)}
|
|
858
|
-
|
|
859
|
-
<section className="section-card">
|
|
860
|
-
<header>
|
|
861
|
-
<h2>Worktree情報</h2>
|
|
862
|
-
</header>
|
|
863
|
-
<ul className="list-muted">
|
|
864
|
-
<li>
|
|
865
|
-
パス: <strong>{branch.worktreePath ?? "未作成"}</strong>
|
|
866
|
-
</li>
|
|
867
|
-
<li>
|
|
868
|
-
AIツールの起動にはクリーンなワークツリーであることを推奨します。
|
|
869
|
-
</li>
|
|
870
|
-
<li>
|
|
871
|
-
Worktreeを再作成すると既存のローカル変更が失われる可能性があります。
|
|
872
|
-
</li>
|
|
873
|
-
</ul>
|
|
874
|
-
</section>
|
|
468
|
+
{/* Main Content */}
|
|
469
|
+
<main className="mx-auto max-w-7xl space-y-6 px-6 py-8">
|
|
470
|
+
<div className="grid gap-6 lg:grid-cols-[1fr_400px]">
|
|
471
|
+
{/* Left Column - Tool Launcher & Session History */}
|
|
472
|
+
<div className="space-y-6">
|
|
473
|
+
<ToolLauncher
|
|
474
|
+
branch={branch}
|
|
475
|
+
availableTools={availableTools}
|
|
476
|
+
selectedToolId={selectedToolId}
|
|
477
|
+
selectedMode={selectedMode}
|
|
478
|
+
skipPermissions={skipPermissions}
|
|
479
|
+
extraArgsText={extraArgsText}
|
|
480
|
+
isConfigLoading={isConfigLoading}
|
|
481
|
+
configError={configError ?? null}
|
|
482
|
+
isStartingSession={isStartingSession}
|
|
483
|
+
isSyncingBranch={isSyncingBranch}
|
|
484
|
+
needsRemoteSync={needsRemoteSync}
|
|
485
|
+
hasBlockingDivergence={hasBlockingDivergence}
|
|
486
|
+
onToolChange={setSelectedToolId}
|
|
487
|
+
onModeChange={setSelectedMode}
|
|
488
|
+
onSkipPermissionsChange={setSkipPermissions}
|
|
489
|
+
onExtraArgsChange={setExtraArgsText}
|
|
490
|
+
onStartSession={handleStartSession}
|
|
491
|
+
onSyncBranch={handleSyncBranch}
|
|
492
|
+
/>
|
|
493
|
+
|
|
494
|
+
<SessionHistoryTable
|
|
495
|
+
sessions={branchSessions}
|
|
496
|
+
isLoading={isSessionsLoading}
|
|
497
|
+
terminatingSessionId={terminatingSessionId}
|
|
498
|
+
isDeleting={deleteSession.isPending}
|
|
499
|
+
onTerminate={handleTerminateSession}
|
|
500
|
+
onSelectSession={setActiveSessionId}
|
|
501
|
+
/>
|
|
502
|
+
|
|
503
|
+
<BranchInfoCards
|
|
504
|
+
branch={branch}
|
|
505
|
+
formattedCommitDate={formattedCommitDate}
|
|
506
|
+
latestToolUsage={latestToolUsage}
|
|
507
|
+
/>
|
|
875
508
|
</div>
|
|
876
509
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
</p>
|
|
891
|
-
</div>
|
|
892
|
-
<div className="terminal-section__controls">
|
|
893
|
-
<button
|
|
894
|
-
type="button"
|
|
895
|
-
className="button button--ghost"
|
|
896
|
-
onClick={() => setIsTerminalFullscreen((prev) => !prev)}
|
|
897
|
-
>
|
|
898
|
-
{isTerminalFullscreen
|
|
899
|
-
? "通常表示に戻す"
|
|
900
|
-
: "ターミナルを最大化"}
|
|
901
|
-
</button>
|
|
902
|
-
</div>
|
|
903
|
-
</div>
|
|
904
|
-
<div className="terminal-surface">
|
|
905
|
-
<Terminal
|
|
906
|
-
sessionId={activeSessionId}
|
|
907
|
-
onExit={handleSessionExit}
|
|
908
|
-
onError={(message) =>
|
|
909
|
-
setBanner({
|
|
910
|
-
type: "error",
|
|
911
|
-
message: message ?? "不明なエラー",
|
|
912
|
-
})
|
|
913
|
-
}
|
|
914
|
-
/>
|
|
915
|
-
</div>
|
|
916
|
-
{isTerminalFullscreen && (
|
|
917
|
-
<button
|
|
918
|
-
type="button"
|
|
919
|
-
className="terminal-section__close"
|
|
920
|
-
aria-label="ターミナルを閉じる"
|
|
921
|
-
onClick={() => setIsTerminalFullscreen(false)}
|
|
922
|
-
>
|
|
923
|
-
×
|
|
924
|
-
</button>
|
|
925
|
-
)}
|
|
926
|
-
</section>
|
|
927
|
-
) : (
|
|
928
|
-
<section className="section-card session-hint">
|
|
929
|
-
<header>
|
|
930
|
-
<h2>セッションは未起動</h2>
|
|
931
|
-
</header>
|
|
932
|
-
<p className="section-card__body">
|
|
933
|
-
上部のアクションからAIツールを起動すると、このエリアにターミナルが表示されます。
|
|
934
|
-
</p>
|
|
935
|
-
</section>
|
|
936
|
-
)}
|
|
510
|
+
{/* Right Column - Terminal */}
|
|
511
|
+
<div className="lg:sticky lg:top-6 lg:self-start">
|
|
512
|
+
<TerminalPanel
|
|
513
|
+
sessionId={activeSessionId}
|
|
514
|
+
isFullscreen={isTerminalFullscreen}
|
|
515
|
+
onToggleFullscreen={() =>
|
|
516
|
+
setIsTerminalFullscreen((prev) => !prev)
|
|
517
|
+
}
|
|
518
|
+
onExit={handleSessionExit}
|
|
519
|
+
onError={(message) =>
|
|
520
|
+
setBanner({ type: "error", message: message ?? "不明なエラー" })
|
|
521
|
+
}
|
|
522
|
+
/>
|
|
937
523
|
</div>
|
|
938
524
|
</div>
|
|
939
525
|
</main>
|
|
@@ -941,91 +527,33 @@ export function BranchDetailPage() {
|
|
|
941
527
|
);
|
|
942
528
|
}
|
|
943
529
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
}
|
|
948
|
-
|
|
530
|
+
// Helper functions
|
|
531
|
+
function formatDate(value?: string | null): string {
|
|
532
|
+
if (!value) return "日時不明";
|
|
949
533
|
try {
|
|
950
|
-
const date = new Date(value);
|
|
951
534
|
return new Intl.DateTimeFormat("ja-JP", {
|
|
952
535
|
year: "numeric",
|
|
953
536
|
month: "short",
|
|
954
537
|
day: "numeric",
|
|
955
538
|
hour: "2-digit",
|
|
956
539
|
minute: "2-digit",
|
|
957
|
-
}).format(
|
|
958
|
-
} catch
|
|
540
|
+
}).format(new Date(value));
|
|
541
|
+
} catch {
|
|
959
542
|
return value;
|
|
960
543
|
}
|
|
961
544
|
}
|
|
962
545
|
|
|
963
|
-
function formatError(error: unknown, fallback: string) {
|
|
546
|
+
function formatError(error: unknown, fallback: string): string {
|
|
964
547
|
if (error instanceof ApiError) {
|
|
965
548
|
return `${error.message}${error.details ? `\n${error.details}` : ""}`;
|
|
966
549
|
}
|
|
967
|
-
if (error instanceof Error)
|
|
968
|
-
return error.message;
|
|
969
|
-
}
|
|
550
|
+
if (error instanceof Error) return error.message;
|
|
970
551
|
return fallback;
|
|
971
552
|
}
|
|
972
553
|
|
|
973
|
-
function toolLabel(tool:
|
|
974
|
-
if (tool === "custom" && selectedTool?.target === "custom")
|
|
554
|
+
function toolLabel(tool: string, selectedTool?: SelectableTool): string {
|
|
555
|
+
if (tool === "custom" && selectedTool?.target === "custom")
|
|
975
556
|
return selectedTool.label;
|
|
976
|
-
|
|
977
|
-
if (tool === "codex-cli") {
|
|
978
|
-
return "Codex CLI";
|
|
979
|
-
}
|
|
557
|
+
if (tool === "codex-cli") return "Codex CLI";
|
|
980
558
|
return "Claude Code";
|
|
981
559
|
}
|
|
982
|
-
|
|
983
|
-
function renderArgs(args?: string[] | null) {
|
|
984
|
-
if (!args || args.length === 0) {
|
|
985
|
-
return <span className="tool-card__muted">未設定</span>;
|
|
986
|
-
}
|
|
987
|
-
return args.join(" ");
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
const SESSION_STATUS_LABEL: Record<
|
|
991
|
-
"pending" | "running" | "completed" | "failed",
|
|
992
|
-
string
|
|
993
|
-
> = {
|
|
994
|
-
pending: "pending",
|
|
995
|
-
running: "running",
|
|
996
|
-
completed: "completed",
|
|
997
|
-
failed: "failed",
|
|
998
|
-
};
|
|
999
|
-
|
|
1000
|
-
function renderToolUsage(usage: LastToolUsage): string {
|
|
1001
|
-
const modeLabel =
|
|
1002
|
-
usage.mode === "normal"
|
|
1003
|
-
? "New"
|
|
1004
|
-
: usage.mode === "continue"
|
|
1005
|
-
? "Continue"
|
|
1006
|
-
: usage.mode === "resume"
|
|
1007
|
-
? "Resume"
|
|
1008
|
-
: null;
|
|
1009
|
-
const toolText = mapToolLabel(usage.toolId, usage.toolLabel);
|
|
1010
|
-
return [toolText, modeLabel, usage.model].filter(Boolean).join(" | ");
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
function formatUsageTimestamp(value: number): string {
|
|
1014
|
-
return formatDate(new Date(value).toISOString());
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
function mapToolLabel(toolId: string, toolLabel?: string | null): string {
|
|
1018
|
-
if (toolId === "claude-code") return "Claude";
|
|
1019
|
-
if (toolId === "codex-cli") return "Codex";
|
|
1020
|
-
if (toolId === "gemini-cli") return "Gemini";
|
|
1021
|
-
if (toolId === "qwen-cli") return "Qwen";
|
|
1022
|
-
if (toolLabel) return toolLabel;
|
|
1023
|
-
return "Custom";
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
function parseExtraArgs(value: string): string[] {
|
|
1027
|
-
return value
|
|
1028
|
-
.split(/\s+/)
|
|
1029
|
-
.map((chunk) => chunk.trim())
|
|
1030
|
-
.filter(Boolean);
|
|
1031
|
-
}
|