@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.
- package/README.ja.md +41 -0
- package/README.md +38 -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 +27 -88
- 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.map +1 -1
- 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/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/client/assets/index-DsDNCy5f.css +1 -0
- package/dist/client/assets/index-f5D2XwDh.js +72 -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 +13 -8
- package/dist/index.js.map +1 -1
- package/dist/logging/logger.d.ts.map +1 -1
- package/dist/logging/logger.js +4 -1
- package/dist/logging/logger.js.map +1 -1
- 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 +125 -376
- 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 +46 -15
- 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/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.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 +25 -0
- package/dist/web/server/tray.d.ts.map +1 -0
- package/dist/web/server/tray.js +98 -0
- package/dist/web/server/tray.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/package.json +15 -2
- package/src/claude.ts +26 -15
- package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +1 -1
- package/src/cli/ui/__tests__/components/common/Select.test.tsx +11 -0
- package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +3 -1
- package/src/cli/ui/__tests__/components/screens/BranchQuickStartScreen.test.tsx +4 -4
- package/src/cli/ui/components/App.tsx +33 -133
- package/src/cli/ui/components/common/Select.tsx +2 -2
- package/src/cli/ui/components/screens/BranchListScreen.tsx +28 -21
- package/src/cli/ui/components/screens/BranchQuickStartScreen.tsx +41 -46
- package/src/cli/ui/utils/continueSession.ts +1 -7
- 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 +13 -8
- package/src/logging/logger.ts +5 -2
- 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 +247 -723
- 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 +72 -15
- package/src/web/server/pty/manager.ts +128 -55
- package/src/web/server/routes/sessions.ts +59 -7
- package/src/web/server/routes/worktrees.ts +3 -3
- package/src/web/server/services/worktrees.ts +12 -4
- package/src/web/server/tray.ts +120 -0
- package/src/web/server/websocket/handler.ts +119 -13
- package/dist/client/assets/index-DeNwPosA.css +0 -1
- 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="
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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="
|
|
146
|
-
<
|
|
147
|
-
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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="
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
</
|
|
179
|
+
</Button>
|
|
177
180
|
</div>
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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="
|
|
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
|
-
|
|
218
|
-
|
|
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
|
},
|