@akiojin/gwt 2.2.0 → 2.3.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 +4 -4
- package/README.md +4 -4
- package/dist/cli/ui/components/App.d.ts +4 -4
- package/dist/cli/ui/components/App.d.ts.map +1 -1
- package/dist/cli/ui/components/App.js +144 -105
- package/dist/cli/ui/components/App.js.map +1 -1
- package/dist/cli/ui/components/common/Confirm.d.ts +1 -1
- package/dist/cli/ui/components/common/Confirm.d.ts.map +1 -1
- package/dist/cli/ui/components/common/Confirm.js +7 -7
- package/dist/cli/ui/components/common/Confirm.js.map +1 -1
- package/dist/cli/ui/components/common/ErrorBoundary.d.ts +1 -1
- package/dist/cli/ui/components/common/ErrorBoundary.d.ts.map +1 -1
- package/dist/cli/ui/components/common/ErrorBoundary.js +4 -4
- package/dist/cli/ui/components/common/ErrorBoundary.js.map +1 -1
- package/dist/cli/ui/components/common/Input.d.ts +2 -2
- package/dist/cli/ui/components/common/Input.d.ts.map +1 -1
- package/dist/cli/ui/components/common/Input.js +4 -4
- package/dist/cli/ui/components/common/Input.js.map +1 -1
- package/dist/cli/ui/components/common/LoadingIndicator.d.ts +1 -1
- package/dist/cli/ui/components/common/LoadingIndicator.d.ts.map +1 -1
- package/dist/cli/ui/components/common/LoadingIndicator.js +4 -4
- package/dist/cli/ui/components/common/LoadingIndicator.js.map +1 -1
- package/dist/cli/ui/components/common/Select.d.ts +1 -1
- package/dist/cli/ui/components/common/Select.d.ts.map +1 -1
- package/dist/cli/ui/components/common/Select.js +11 -12
- package/dist/cli/ui/components/common/Select.js.map +1 -1
- package/dist/cli/ui/components/screens/AIToolSelectorScreen.d.ts +2 -2
- package/dist/cli/ui/components/screens/AIToolSelectorScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/AIToolSelectorScreen.js +11 -11
- package/dist/cli/ui/components/screens/AIToolSelectorScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchCreatorScreen.d.ts +1 -1
- package/dist/cli/ui/components/screens/BranchCreatorScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchCreatorScreen.js +39 -36
- package/dist/cli/ui/components/screens/BranchCreatorScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts +3 -3
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.js +55 -50
- package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.d.ts +2 -2
- package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.js +25 -25
- package/dist/cli/ui/components/screens/ExecutionModeSelectorScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/PRCleanupScreen.d.ts +2 -2
- package/dist/cli/ui/components/screens/PRCleanupScreen.js +21 -21
- package/dist/cli/ui/components/screens/SessionSelectorScreen.d.ts +1 -1
- package/dist/cli/ui/components/screens/SessionSelectorScreen.js +8 -8
- package/dist/cli/ui/components/screens/WorktreeManagerScreen.d.ts +1 -1
- package/dist/cli/ui/components/screens/WorktreeManagerScreen.js +8 -8
- package/dist/cli/ui/screens/BranchActionSelectorScreen.d.ts.map +1 -1
- package/dist/cli/ui/screens/BranchActionSelectorScreen.js +7 -4
- package/dist/cli/ui/screens/BranchActionSelectorScreen.js.map +1 -1
- package/dist/cli/ui/types.d.ts.map +1 -1
- package/dist/client/assets/{index-V6hDu9KS.js → index-Difv1Hwu.js} +2 -2
- package/dist/client/index.html +1 -1
- package/dist/config/builtin-tools.d.ts +10 -2
- package/dist/config/builtin-tools.d.ts.map +1 -1
- package/dist/config/builtin-tools.js +40 -4
- package/dist/config/builtin-tools.js.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/tools.d.ts.map +1 -1
- package/dist/config/tools.js +4 -3
- package/dist/config/tools.js.map +1 -1
- package/dist/gemini.d.ts +12 -0
- package/dist/gemini.d.ts.map +1 -0
- package/dist/gemini.js +154 -0
- package/dist/gemini.js.map +1 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -1
- package/dist/qwen.d.ts +12 -0
- package/dist/qwen.d.ts.map +1 -0
- package/dist/qwen.js +154 -0
- package/dist/qwen.js.map +1 -0
- package/dist/services/git.service.d.ts.map +1 -1
- package/dist/services/git.service.js.map +1 -1
- package/dist/web/client/src/components/BranchGraph.d.ts.map +1 -1
- package/dist/web/client/src/components/BranchGraph.js +1 -1
- package/dist/web/client/src/components/BranchGraph.js.map +1 -1
- package/dist/web/client/src/components/EnvEditor.d.ts.map +1 -1
- package/dist/web/client/src/components/EnvEditor.js +7 -4
- package/dist/web/client/src/components/EnvEditor.js.map +1 -1
- package/dist/web/client/src/pages/BranchDetailPage.d.ts.map +1 -1
- package/dist/web/client/src/pages/BranchDetailPage.js +55 -18
- 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 +10 -4
- 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 +4 -2
- package/dist/web/client/src/pages/ConfigManagementPage.js.map +1 -1
- package/package.json +2 -1
- package/src/cli/ui/__tests__/acceptance/navigation.acceptance.test.tsx +69 -50
- package/src/cli/ui/__tests__/components/App.protected-branch.test.tsx +67 -45
- package/src/cli/ui/__tests__/components/App.shortcuts.test.tsx +117 -75
- package/src/cli/ui/__tests__/components/App.test.tsx +45 -37
- package/src/cli/ui/__tests__/components/common/Confirm.test.tsx +35 -22
- package/src/cli/ui/__tests__/components/common/ErrorBoundary.test.tsx +22 -22
- package/src/cli/ui/__tests__/components/common/Input.test.tsx +29 -22
- package/src/cli/ui/__tests__/components/common/LoadingIndicator.test.tsx +40 -34
- package/src/cli/ui/__tests__/components/common/Select.memo.test.tsx +57 -66
- package/src/cli/ui/__tests__/components/common/Select.test.tsx +121 -91
- package/src/cli/ui/__tests__/components/parts/Footer.test.tsx +18 -16
- package/src/cli/ui/__tests__/components/parts/Header.test.tsx +13 -13
- package/src/cli/ui/__tests__/components/parts/ScrollableList.test.tsx +20 -20
- package/src/cli/ui/__tests__/components/parts/Stats.test.tsx +38 -26
- package/src/cli/ui/__tests__/components/screens/AIToolSelectorScreen.test.tsx +31 -31
- package/src/cli/ui/__tests__/components/screens/BranchCreatorScreen.test.tsx +73 -37
- package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +261 -153
- package/src/cli/ui/__tests__/components/screens/ExecutionModeSelectorScreen.test.tsx +38 -32
- package/src/cli/ui/__tests__/components/screens/PRCleanupScreen.test.tsx +39 -39
- package/src/cli/ui/__tests__/components/screens/SessionSelectorScreen.test.tsx +49 -21
- package/src/cli/ui/__tests__/components/screens/WorktreeManagerScreen.test.tsx +52 -28
- package/src/cli/ui/__tests__/integration/edgeCases.test.tsx +84 -48
- package/src/cli/ui/__tests__/integration/navigation.test.tsx +111 -83
- package/src/cli/ui/__tests__/integration/realtimeUpdate.test.tsx +111 -108
- package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +50 -37
- package/src/cli/ui/__tests__/performance/useMemoOptimization.test.tsx +75 -76
- package/src/cli/ui/components/App.tsx +247 -150
- package/src/cli/ui/components/common/Confirm.tsx +13 -9
- package/src/cli/ui/components/common/ErrorBoundary.tsx +8 -5
- package/src/cli/ui/components/common/Input.tsx +12 -4
- package/src/cli/ui/components/common/LoadingIndicator.tsx +8 -5
- package/src/cli/ui/components/common/Select.tsx +28 -17
- package/src/cli/ui/components/parts/Header.test.tsx +5 -15
- package/src/cli/ui/components/screens/AIToolSelectorScreen.tsx +19 -13
- package/src/cli/ui/components/screens/BranchCreatorScreen.tsx +74 -54
- package/src/cli/ui/components/screens/BranchListScreen.tsx +92 -75
- package/src/cli/ui/components/screens/ExecutionModeSelectorScreen.tsx +35 -28
- package/src/cli/ui/components/screens/PRCleanupScreen.tsx +22 -22
- package/src/cli/ui/components/screens/SessionSelectorScreen.tsx +8 -8
- package/src/cli/ui/components/screens/WorktreeManagerScreen.tsx +8 -8
- package/src/cli/ui/screens/BranchActionSelectorScreen.tsx +9 -4
- package/src/cli/ui/types.ts +8 -1
- package/src/config/builtin-tools.ts +42 -4
- package/src/config/index.ts +2 -12
- package/src/config/tools.ts +16 -6
- package/src/gemini.ts +202 -0
- package/src/git.ts +2 -1
- package/src/index.ts +30 -0
- package/src/qwen.ts +208 -0
- package/src/services/git.service.ts +2 -1
- package/src/web/client/src/components/BranchGraph.tsx +3 -2
- package/src/web/client/src/components/EnvEditor.tsx +44 -11
- package/src/web/client/src/pages/BranchDetailPage.tsx +165 -54
- package/src/web/client/src/pages/BranchListPage.tsx +37 -13
- package/src/web/client/src/pages/ConfigManagementPage.tsx +28 -9
|
@@ -21,7 +21,9 @@ const KEY_PATTERN = /^[A-Z0-9_]+$/;
|
|
|
21
21
|
|
|
22
22
|
export function createEnvRow(variable?: Partial<EnvRow>): EnvRow {
|
|
23
23
|
const row: EnvRow = {
|
|
24
|
-
id:
|
|
24
|
+
id:
|
|
25
|
+
variable?.id ??
|
|
26
|
+
`env-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
25
27
|
key: variable?.key ?? "",
|
|
26
28
|
value: variable?.value ?? "",
|
|
27
29
|
};
|
|
@@ -49,13 +51,20 @@ export function EnvEditor({
|
|
|
49
51
|
allowAdd = true,
|
|
50
52
|
emptyLabel = "環境変数はまだありません",
|
|
51
53
|
}: EnvEditorProps) {
|
|
52
|
-
const handleFieldChange = (
|
|
54
|
+
const handleFieldChange = (
|
|
55
|
+
id: string,
|
|
56
|
+
field: "key" | "value",
|
|
57
|
+
value: string,
|
|
58
|
+
) => {
|
|
53
59
|
onChange(
|
|
54
60
|
rows.map((row) =>
|
|
55
61
|
row.id === id
|
|
56
62
|
? {
|
|
57
63
|
...row,
|
|
58
|
-
[field]:
|
|
64
|
+
[field]:
|
|
65
|
+
field === "key"
|
|
66
|
+
? value.toUpperCase().replace(/[^A-Z0-9_]/g, "_")
|
|
67
|
+
: value,
|
|
59
68
|
}
|
|
60
69
|
: row,
|
|
61
70
|
),
|
|
@@ -75,10 +84,16 @@ export function EnvEditor({
|
|
|
75
84
|
<header className="env-editor__header">
|
|
76
85
|
<div>
|
|
77
86
|
<h3>{title}</h3>
|
|
78
|
-
{description &&
|
|
87
|
+
{description && (
|
|
88
|
+
<p className="env-editor__description">{description}</p>
|
|
89
|
+
)}
|
|
79
90
|
</div>
|
|
80
91
|
{allowAdd && (
|
|
81
|
-
<button
|
|
92
|
+
<button
|
|
93
|
+
type="button"
|
|
94
|
+
className="button button--secondary"
|
|
95
|
+
onClick={handleAdd}
|
|
96
|
+
>
|
|
82
97
|
変数を追加
|
|
83
98
|
</button>
|
|
84
99
|
)}
|
|
@@ -99,29 +114,47 @@ export function EnvEditor({
|
|
|
99
114
|
{rows.map((row) => {
|
|
100
115
|
const keyInvalid = isInvalidKey(row);
|
|
101
116
|
return (
|
|
102
|
-
<tr
|
|
117
|
+
<tr
|
|
118
|
+
key={row.id}
|
|
119
|
+
className={
|
|
120
|
+
keyInvalid ? "env-editor__row--invalid" : undefined
|
|
121
|
+
}
|
|
122
|
+
>
|
|
103
123
|
<td>
|
|
104
124
|
<input
|
|
105
125
|
type="text"
|
|
106
126
|
value={row.key}
|
|
107
|
-
onChange={(event) =>
|
|
127
|
+
onChange={(event) =>
|
|
128
|
+
handleFieldChange(row.id, "key", event.target.value)
|
|
129
|
+
}
|
|
108
130
|
placeholder="EXAMPLE_KEY"
|
|
109
131
|
/>
|
|
110
132
|
{row.importedFromOs && (
|
|
111
|
-
<span
|
|
133
|
+
<span
|
|
134
|
+
className="pill pill--info"
|
|
135
|
+
style={{ marginLeft: "0.5rem" }}
|
|
136
|
+
>
|
|
112
137
|
OSから取り込み
|
|
113
138
|
</span>
|
|
114
139
|
)}
|
|
115
140
|
{row.lastUpdated && (
|
|
116
|
-
<span className="env-editor__meta"
|
|
141
|
+
<span className="env-editor__meta">
|
|
142
|
+
更新: {new Date(row.lastUpdated).toLocaleString()}
|
|
143
|
+
</span>
|
|
144
|
+
)}
|
|
145
|
+
{keyInvalid && (
|
|
146
|
+
<p className="env-editor__error">
|
|
147
|
+
A-Z,0-9,_ のみ使用できます
|
|
148
|
+
</p>
|
|
117
149
|
)}
|
|
118
|
-
{keyInvalid && <p className="env-editor__error">A-Z,0-9,_ のみ使用できます</p>}
|
|
119
150
|
</td>
|
|
120
151
|
<td>
|
|
121
152
|
<input
|
|
122
153
|
type="text"
|
|
123
154
|
value={row.value}
|
|
124
|
-
onChange={(event) =>
|
|
155
|
+
onChange={(event) =>
|
|
156
|
+
handleFieldChange(row.id, "value", event.target.value)
|
|
157
|
+
}
|
|
125
158
|
placeholder="値"
|
|
126
159
|
/>
|
|
127
160
|
</td>
|
|
@@ -69,7 +69,10 @@ const MERGE_STATUS_LABEL: Record<Branch["mergeStatus"], string> = {
|
|
|
69
69
|
unknown: "状態不明",
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
const MERGE_STATUS_TONE: Record<
|
|
72
|
+
const MERGE_STATUS_TONE: Record<
|
|
73
|
+
Branch["mergeStatus"],
|
|
74
|
+
"success" | "warning" | "muted"
|
|
75
|
+
> = {
|
|
73
76
|
merged: "success",
|
|
74
77
|
unmerged: "warning",
|
|
75
78
|
unknown: "muted",
|
|
@@ -99,7 +102,9 @@ export function BranchDetailPage() {
|
|
|
99
102
|
const [selectedMode, setSelectedMode] = useState<ToolMode>("normal");
|
|
100
103
|
const [skipPermissions, setSkipPermissions] = useState(false);
|
|
101
104
|
const [extraArgsText, setExtraArgsText] = useState("");
|
|
102
|
-
const [terminatingSessionId, setTerminatingSessionId] = useState<
|
|
105
|
+
const [terminatingSessionId, setTerminatingSessionId] = useState<
|
|
106
|
+
string | null
|
|
107
|
+
>(null);
|
|
103
108
|
|
|
104
109
|
const formattedCommitDate = useMemo(
|
|
105
110
|
() => formatDate(branch?.commitDate),
|
|
@@ -177,12 +182,14 @@ export function BranchDetailPage() {
|
|
|
177
182
|
() => [
|
|
178
183
|
{ id: "claude-code", label: "Claude Code", target: "claude" },
|
|
179
184
|
{ id: "codex-cli", label: "Codex CLI", target: "codex" },
|
|
180
|
-
...customTools.map(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
185
|
+
...customTools.map(
|
|
186
|
+
(tool): SelectableTool => ({
|
|
187
|
+
id: tool.id,
|
|
188
|
+
label: tool.displayName,
|
|
189
|
+
target: "custom" as const,
|
|
190
|
+
definition: tool,
|
|
191
|
+
}),
|
|
192
|
+
),
|
|
186
193
|
],
|
|
187
194
|
[customTools],
|
|
188
195
|
);
|
|
@@ -200,7 +207,9 @@ export function BranchDetailPage() {
|
|
|
200
207
|
}
|
|
201
208
|
}, [availableTools, selectedToolId]);
|
|
202
209
|
|
|
203
|
-
const selectedTool = availableTools.find(
|
|
210
|
+
const selectedTool = availableTools.find(
|
|
211
|
+
(tool) => tool.id === selectedToolId,
|
|
212
|
+
);
|
|
204
213
|
|
|
205
214
|
const selectedToolSummary: ToolSummary | null = useMemo(() => {
|
|
206
215
|
if (!selectedTool) {
|
|
@@ -267,14 +276,18 @@ export function BranchDetailPage() {
|
|
|
267
276
|
}
|
|
268
277
|
|
|
269
278
|
if (!selectedTool) {
|
|
270
|
-
setBanner({
|
|
279
|
+
setBanner({
|
|
280
|
+
type: "error",
|
|
281
|
+
message: "起動するAIツールを選択してください",
|
|
282
|
+
});
|
|
271
283
|
return;
|
|
272
284
|
}
|
|
273
285
|
|
|
274
286
|
if (needsRemoteSync) {
|
|
275
287
|
setBanner({
|
|
276
288
|
type: "error",
|
|
277
|
-
message:
|
|
289
|
+
message:
|
|
290
|
+
"リモートの更新を取り込むまでAIツールは起動できません。『最新の変更を同期』を実行してください。",
|
|
278
291
|
});
|
|
279
292
|
return;
|
|
280
293
|
}
|
|
@@ -288,7 +301,12 @@ export function BranchDetailPage() {
|
|
|
288
301
|
return;
|
|
289
302
|
}
|
|
290
303
|
|
|
291
|
-
if (
|
|
304
|
+
if (
|
|
305
|
+
skipPermissions &&
|
|
306
|
+
!window.confirm(
|
|
307
|
+
"権限チェックをスキップして起動します。自己責任で実行してください。続行しますか?",
|
|
308
|
+
)
|
|
309
|
+
) {
|
|
292
310
|
return;
|
|
293
311
|
}
|
|
294
312
|
|
|
@@ -342,7 +360,10 @@ export function BranchDetailPage() {
|
|
|
342
360
|
setActiveSessionId(null);
|
|
343
361
|
}
|
|
344
362
|
} catch (err) {
|
|
345
|
-
setBanner({
|
|
363
|
+
setBanner({
|
|
364
|
+
type: "error",
|
|
365
|
+
message: formatError(err, "セッションの終了に失敗しました"),
|
|
366
|
+
});
|
|
346
367
|
} finally {
|
|
347
368
|
setTerminatingSessionId(null);
|
|
348
369
|
}
|
|
@@ -350,23 +371,36 @@ export function BranchDetailPage() {
|
|
|
350
371
|
|
|
351
372
|
const handleSyncBranch = async () => {
|
|
352
373
|
if (!branch.worktreePath) {
|
|
353
|
-
setBanner({
|
|
374
|
+
setBanner({
|
|
375
|
+
type: "error",
|
|
376
|
+
message: "Worktreeが存在しないため同期できません。",
|
|
377
|
+
});
|
|
354
378
|
return;
|
|
355
379
|
}
|
|
356
380
|
|
|
357
381
|
try {
|
|
358
|
-
const result = await syncBranch.mutateAsync({
|
|
382
|
+
const result = await syncBranch.mutateAsync({
|
|
383
|
+
worktreePath: branch.worktreePath,
|
|
384
|
+
});
|
|
359
385
|
if (result.pullStatus === "success") {
|
|
360
|
-
setBanner({
|
|
386
|
+
setBanner({
|
|
387
|
+
type: "success",
|
|
388
|
+
message: "リモートの最新変更を取り込みました。",
|
|
389
|
+
});
|
|
361
390
|
} else {
|
|
362
|
-
const warning =
|
|
391
|
+
const warning =
|
|
392
|
+
result.warnings?.join("\n") ??
|
|
393
|
+
"fast-forward pull が完了しませんでした";
|
|
363
394
|
setBanner({
|
|
364
395
|
type: "error",
|
|
365
396
|
message: `git pull --ff-only が失敗しました。\n${warning}`,
|
|
366
397
|
});
|
|
367
398
|
}
|
|
368
399
|
} catch (err) {
|
|
369
|
-
setBanner({
|
|
400
|
+
setBanner({
|
|
401
|
+
type: "error",
|
|
402
|
+
message: formatError(err, "Git同期に失敗しました"),
|
|
403
|
+
});
|
|
370
404
|
}
|
|
371
405
|
};
|
|
372
406
|
|
|
@@ -400,12 +434,16 @@ export function BranchDetailPage() {
|
|
|
400
434
|
<span className={`status-badge status-badge--${branch.type}`}>
|
|
401
435
|
{BRANCH_TYPE_LABEL[branch.type]}
|
|
402
436
|
</span>
|
|
403
|
-
<span
|
|
437
|
+
<span
|
|
438
|
+
className={`status-badge status-badge--${MERGE_STATUS_TONE[branch.mergeStatus]}`}
|
|
439
|
+
>
|
|
404
440
|
{MERGE_STATUS_LABEL[branch.mergeStatus]}
|
|
405
441
|
</span>
|
|
406
442
|
<span
|
|
407
443
|
className={`status-badge ${
|
|
408
|
-
branch.worktreePath
|
|
444
|
+
branch.worktreePath
|
|
445
|
+
? "status-badge--success"
|
|
446
|
+
: "status-badge--muted"
|
|
409
447
|
}`}
|
|
410
448
|
>
|
|
411
449
|
{branch.worktreePath ? "Worktreeあり" : "Worktree未作成"}
|
|
@@ -450,11 +488,14 @@ export function BranchDetailPage() {
|
|
|
450
488
|
<div>
|
|
451
489
|
<h2>AIツール起動</h2>
|
|
452
490
|
<p className="section-card__body">
|
|
453
|
-
Web UI
|
|
491
|
+
Web UI
|
|
492
|
+
から直接AIツールを起動できます。設定したカスタムツールも一覧に表示されます。
|
|
454
493
|
</p>
|
|
455
494
|
</div>
|
|
456
495
|
{configError && (
|
|
457
|
-
<span className="pill pill--warning"
|
|
496
|
+
<span className="pill pill--warning">
|
|
497
|
+
設定の取得に失敗しました
|
|
498
|
+
</span>
|
|
458
499
|
)}
|
|
459
500
|
</header>
|
|
460
501
|
|
|
@@ -469,7 +510,9 @@ export function BranchDetailPage() {
|
|
|
469
510
|
<span>AIツール</span>
|
|
470
511
|
<select
|
|
471
512
|
value={selectedToolId}
|
|
472
|
-
onChange={(event) =>
|
|
513
|
+
onChange={(event) =>
|
|
514
|
+
setSelectedToolId(event.target.value)
|
|
515
|
+
}
|
|
473
516
|
disabled={isConfigLoading}
|
|
474
517
|
>
|
|
475
518
|
{availableTools.map((tool) => (
|
|
@@ -484,7 +527,9 @@ export function BranchDetailPage() {
|
|
|
484
527
|
<span>起動モード</span>
|
|
485
528
|
<select
|
|
486
529
|
value={selectedMode}
|
|
487
|
-
onChange={(event) =>
|
|
530
|
+
onChange={(event) =>
|
|
531
|
+
setSelectedMode(event.target.value as ToolMode)
|
|
532
|
+
}
|
|
488
533
|
>
|
|
489
534
|
<option value="normal">normal</option>
|
|
490
535
|
<option value="continue">continue</option>
|
|
@@ -497,7 +542,9 @@ export function BranchDetailPage() {
|
|
|
497
542
|
<input
|
|
498
543
|
type="text"
|
|
499
544
|
value={extraArgsText}
|
|
500
|
-
onChange={(event) =>
|
|
545
|
+
onChange={(event) =>
|
|
546
|
+
setExtraArgsText(event.target.value)
|
|
547
|
+
}
|
|
501
548
|
placeholder="--flag value"
|
|
502
549
|
/>
|
|
503
550
|
</label>
|
|
@@ -508,39 +555,61 @@ export function BranchDetailPage() {
|
|
|
508
555
|
<input
|
|
509
556
|
type="checkbox"
|
|
510
557
|
checked={skipPermissions}
|
|
511
|
-
onChange={(event) =>
|
|
558
|
+
onChange={(event) =>
|
|
559
|
+
setSkipPermissions(event.target.checked)
|
|
560
|
+
}
|
|
512
561
|
/>
|
|
513
|
-
<span style={{ marginLeft: "0.5rem" }}
|
|
562
|
+
<span style={{ marginLeft: "0.5rem" }}>
|
|
563
|
+
権限チェックをスキップ (自己責任)
|
|
564
|
+
</span>
|
|
514
565
|
</span>
|
|
515
566
|
</label>
|
|
516
567
|
{skipPermissions && (
|
|
517
568
|
<div className="inline-banner inline-banner--warning">
|
|
518
569
|
<p>
|
|
519
|
-
権限チェックをスキップすることで、CLI での
|
|
570
|
+
権限チェックをスキップすることで、CLI での
|
|
571
|
+
`--dangerously-skip-permissions`
|
|
572
|
+
指定と同様のリスクを負います。
|
|
520
573
|
</p>
|
|
521
574
|
</div>
|
|
522
575
|
)}
|
|
523
576
|
{needsRemoteSync && (
|
|
524
|
-
<div
|
|
577
|
+
<div
|
|
578
|
+
className="inline-banner inline-banner--info"
|
|
579
|
+
data-testid="sync-required"
|
|
580
|
+
>
|
|
525
581
|
<p>
|
|
526
|
-
リモートに未取得の更新 ({branch.divergence?.behind ?? 0}
|
|
582
|
+
リモートに未取得の更新 ({branch.divergence?.behind ?? 0}{" "}
|
|
583
|
+
commits)
|
|
584
|
+
があるため、AIツールを起動する前に同期してください。
|
|
527
585
|
</p>
|
|
528
586
|
<p className="section-card__body">
|
|
529
|
-
CLI の `git fetch --all` と `git pull --ff-only`
|
|
587
|
+
CLI の `git fetch --all` と `git pull --ff-only`
|
|
588
|
+
と同じ処理を Web UI から実行できます。
|
|
530
589
|
</p>
|
|
531
590
|
</div>
|
|
532
591
|
)}
|
|
533
592
|
{hasBlockingDivergence && (
|
|
534
|
-
<div
|
|
593
|
+
<div
|
|
594
|
+
className="inline-banner inline-banner--warning"
|
|
595
|
+
data-testid="divergence-warning"
|
|
596
|
+
>
|
|
535
597
|
<p>
|
|
536
|
-
リモートとローカルの両方に未解決の差分があるため、Web UI
|
|
598
|
+
リモートとローカルの両方に未解決の差分があるため、Web UI
|
|
599
|
+
でも CLI と同様に起動をブロックしています。
|
|
537
600
|
</p>
|
|
538
601
|
<ul className="list-muted">
|
|
539
|
-
<li>
|
|
540
|
-
|
|
602
|
+
<li>
|
|
603
|
+
git fetch && git pull --ff-only origin {branch.name}
|
|
604
|
+
</li>
|
|
605
|
+
<li>
|
|
606
|
+
必要に応じて git push origin {branch.name}{" "}
|
|
607
|
+
でローカル進捗を共有
|
|
608
|
+
</li>
|
|
541
609
|
</ul>
|
|
542
610
|
<p className="section-card__body">
|
|
543
|
-
rebase / merge
|
|
611
|
+
rebase / merge
|
|
612
|
+
などで差分を解消した後にページを更新してください。
|
|
544
613
|
</p>
|
|
545
614
|
</div>
|
|
546
615
|
)}
|
|
@@ -577,7 +646,9 @@ export function BranchDetailPage() {
|
|
|
577
646
|
<dl className="metadata-grid metadata-grid--compact">
|
|
578
647
|
<div>
|
|
579
648
|
<dt>コマンド</dt>
|
|
580
|
-
<dd className="tool-card__command">
|
|
649
|
+
<dd className="tool-card__command">
|
|
650
|
+
{selectedToolSummary.command}
|
|
651
|
+
</dd>
|
|
581
652
|
</div>
|
|
582
653
|
<div>
|
|
583
654
|
<dt>defaultArgs</dt>
|
|
@@ -585,7 +656,9 @@ export function BranchDetailPage() {
|
|
|
585
656
|
</div>
|
|
586
657
|
<div>
|
|
587
658
|
<dt>permissionSkipArgs</dt>
|
|
588
|
-
<dd>
|
|
659
|
+
<dd>
|
|
660
|
+
{renderArgs(selectedToolSummary.permissionSkipArgs)}
|
|
661
|
+
</dd>
|
|
589
662
|
</div>
|
|
590
663
|
{argsPreview && (
|
|
591
664
|
<div className="metadata-grid__full">
|
|
@@ -605,13 +678,18 @@ export function BranchDetailPage() {
|
|
|
605
678
|
<div>
|
|
606
679
|
<h2>セッション履歴</h2>
|
|
607
680
|
<p className="section-card__body">
|
|
608
|
-
この Worktree に紐づいた最新の AI
|
|
681
|
+
この Worktree に紐づいた最新の AI
|
|
682
|
+
セッションが表示されます。CLI からの起動分も共有されます。
|
|
609
683
|
</p>
|
|
610
684
|
</div>
|
|
611
|
-
{isSessionsLoading &&
|
|
685
|
+
{isSessionsLoading && (
|
|
686
|
+
<span className="pill">読み込み中...</span>
|
|
687
|
+
)}
|
|
612
688
|
</header>
|
|
613
689
|
{branchSessions.length === 0 ? (
|
|
614
|
-
<p className="section-card__body"
|
|
690
|
+
<p className="section-card__body">
|
|
691
|
+
セッション履歴はまだありません。
|
|
692
|
+
</p>
|
|
615
693
|
) : (
|
|
616
694
|
<div className="session-table-wrapper">
|
|
617
695
|
<table className="session-table">
|
|
@@ -629,23 +707,40 @@ export function BranchDetailPage() {
|
|
|
629
707
|
{branchSessions.slice(0, 5).map((session) => (
|
|
630
708
|
<tr key={session.sessionId}>
|
|
631
709
|
<td>
|
|
632
|
-
<span
|
|
710
|
+
<span
|
|
711
|
+
className={`status-pill status-pill--${session.status}`}
|
|
712
|
+
>
|
|
633
713
|
{SESSION_STATUS_LABEL[session.status]}
|
|
634
714
|
</span>
|
|
635
715
|
</td>
|
|
636
|
-
<td>
|
|
716
|
+
<td>
|
|
717
|
+
{session.toolType === "custom"
|
|
718
|
+
? (session.toolName ?? "custom")
|
|
719
|
+
: toolLabel(session.toolType)}
|
|
720
|
+
</td>
|
|
637
721
|
<td>{session.mode}</td>
|
|
638
722
|
<td>{formatDate(session.startedAt)}</td>
|
|
639
|
-
<td>
|
|
723
|
+
<td>
|
|
724
|
+
{session.endedAt
|
|
725
|
+
? formatDate(session.endedAt)
|
|
726
|
+
: "--"}
|
|
727
|
+
</td>
|
|
640
728
|
<td>
|
|
641
729
|
{session.status === "running" ? (
|
|
642
730
|
<button
|
|
643
731
|
type="button"
|
|
644
732
|
className="button button--ghost"
|
|
645
|
-
onClick={() =>
|
|
646
|
-
|
|
733
|
+
onClick={() =>
|
|
734
|
+
handleTerminateSession(session.sessionId)
|
|
735
|
+
}
|
|
736
|
+
disabled={
|
|
737
|
+
terminatingSessionId === session.sessionId ||
|
|
738
|
+
deleteSession.isPending
|
|
739
|
+
}
|
|
647
740
|
>
|
|
648
|
-
{terminatingSessionId === session.sessionId
|
|
741
|
+
{terminatingSessionId === session.sessionId
|
|
742
|
+
? "終了中..."
|
|
743
|
+
: "終了"}
|
|
649
744
|
</button>
|
|
650
745
|
) : (
|
|
651
746
|
<span className="session-table__muted">--</span>
|
|
@@ -698,10 +793,14 @@ export function BranchDetailPage() {
|
|
|
698
793
|
</header>
|
|
699
794
|
<div className="pill-group">
|
|
700
795
|
<span className="pill">Ahead {branch.divergence.ahead}</span>
|
|
701
|
-
<span className="pill">
|
|
796
|
+
<span className="pill">
|
|
797
|
+
Behind {branch.divergence.behind}
|
|
798
|
+
</span>
|
|
702
799
|
<span
|
|
703
800
|
className={`pill ${
|
|
704
|
-
branch.divergence.upToDate
|
|
801
|
+
branch.divergence.upToDate
|
|
802
|
+
? "pill--success"
|
|
803
|
+
: "pill--warning"
|
|
705
804
|
}`}
|
|
706
805
|
>
|
|
707
806
|
{branch.divergence.upToDate ? "最新" : "更新あり"}
|
|
@@ -718,8 +817,12 @@ export function BranchDetailPage() {
|
|
|
718
817
|
<li>
|
|
719
818
|
パス: <strong>{branch.worktreePath ?? "未作成"}</strong>
|
|
720
819
|
</li>
|
|
721
|
-
<li>
|
|
722
|
-
|
|
820
|
+
<li>
|
|
821
|
+
AIツールの起動にはクリーンなワークツリーであることを推奨します。
|
|
822
|
+
</li>
|
|
823
|
+
<li>
|
|
824
|
+
Worktreeを再作成すると既存のローカル変更が失われる可能性があります。
|
|
825
|
+
</li>
|
|
723
826
|
</ul>
|
|
724
827
|
</section>
|
|
725
828
|
</div>
|
|
@@ -745,7 +848,9 @@ export function BranchDetailPage() {
|
|
|
745
848
|
className="button button--ghost"
|
|
746
849
|
onClick={() => setIsTerminalFullscreen((prev) => !prev)}
|
|
747
850
|
>
|
|
748
|
-
{isTerminalFullscreen
|
|
851
|
+
{isTerminalFullscreen
|
|
852
|
+
? "通常表示に戻す"
|
|
853
|
+
: "ターミナルを最大化"}
|
|
749
854
|
</button>
|
|
750
855
|
</div>
|
|
751
856
|
</div>
|
|
@@ -754,7 +859,10 @@ export function BranchDetailPage() {
|
|
|
754
859
|
sessionId={activeSessionId}
|
|
755
860
|
onExit={handleSessionExit}
|
|
756
861
|
onError={(message) =>
|
|
757
|
-
setBanner({
|
|
862
|
+
setBanner({
|
|
863
|
+
type: "error",
|
|
864
|
+
message: message ?? "不明なエラー",
|
|
865
|
+
})
|
|
758
866
|
}
|
|
759
867
|
/>
|
|
760
868
|
</div>
|
|
@@ -832,7 +940,10 @@ function renderArgs(args?: string[] | null) {
|
|
|
832
940
|
return args.join(" ");
|
|
833
941
|
}
|
|
834
942
|
|
|
835
|
-
const SESSION_STATUS_LABEL: Record<
|
|
943
|
+
const SESSION_STATUS_LABEL: Record<
|
|
944
|
+
"pending" | "running" | "completed" | "failed",
|
|
945
|
+
string
|
|
946
|
+
> = {
|
|
836
947
|
pending: "pending",
|
|
837
948
|
running: "running",
|
|
838
949
|
completed: "completed",
|
|
@@ -17,7 +17,10 @@ const MERGE_STATUS_LABEL: Record<Branch["mergeStatus"], string> = {
|
|
|
17
17
|
unknown: "状態不明",
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
const MERGE_STATUS_TONE: Record<
|
|
20
|
+
const MERGE_STATUS_TONE: Record<
|
|
21
|
+
Branch["mergeStatus"],
|
|
22
|
+
"success" | "warning" | "muted"
|
|
23
|
+
> = {
|
|
21
24
|
merged: "success",
|
|
22
25
|
unmerged: "warning",
|
|
23
26
|
unknown: "muted",
|
|
@@ -37,9 +40,13 @@ export function BranchListPage() {
|
|
|
37
40
|
const branches = data ?? [];
|
|
38
41
|
|
|
39
42
|
const metrics = useMemo(() => {
|
|
40
|
-
const worktrees = branches.filter((branch) =>
|
|
43
|
+
const worktrees = branches.filter((branch) =>
|
|
44
|
+
Boolean(branch.worktreePath),
|
|
45
|
+
).length;
|
|
41
46
|
const remote = branches.filter((branch) => branch.type === "remote").length;
|
|
42
|
-
const healthy = branches.filter(
|
|
47
|
+
const healthy = branches.filter(
|
|
48
|
+
(branch) => branch.divergence?.upToDate,
|
|
49
|
+
).length;
|
|
43
50
|
|
|
44
51
|
return {
|
|
45
52
|
total: branches.length,
|
|
@@ -82,14 +89,17 @@ export function BranchListPage() {
|
|
|
82
89
|
return {
|
|
83
90
|
title: "ブランチの取得に失敗しました",
|
|
84
91
|
description:
|
|
85
|
-
error instanceof Error
|
|
92
|
+
error instanceof Error
|
|
93
|
+
? error.message
|
|
94
|
+
: "未知のエラーが発生しました。",
|
|
86
95
|
};
|
|
87
96
|
}
|
|
88
97
|
|
|
89
98
|
if (!branches.length) {
|
|
90
99
|
return {
|
|
91
100
|
title: "ブランチが見つかりません",
|
|
92
|
-
description:
|
|
101
|
+
description:
|
|
102
|
+
"git fetch origin などで最新のブランチを取得してください。",
|
|
93
103
|
};
|
|
94
104
|
}
|
|
95
105
|
|
|
@@ -105,7 +115,9 @@ export function BranchListPage() {
|
|
|
105
115
|
ローカルのGitブランチとAIツールをブラウザ上で一元管理し、Worktree状態を瞬時に
|
|
106
116
|
可視化します。
|
|
107
117
|
</p>
|
|
108
|
-
<div className="page-hero__meta"
|
|
118
|
+
<div className="page-hero__meta">
|
|
119
|
+
リアルタイムで更新されるステータスビュー
|
|
120
|
+
</div>
|
|
109
121
|
</header>
|
|
110
122
|
|
|
111
123
|
<main className="page-content">
|
|
@@ -158,7 +170,7 @@ export function BranchListPage() {
|
|
|
158
170
|
/>
|
|
159
171
|
</label>
|
|
160
172
|
<span className="toolbar__count">
|
|
161
|
-
{numberFormatter.format(filteredBranches.length)} /
|
|
173
|
+
{numberFormatter.format(filteredBranches.length)} /{" "}
|
|
162
174
|
{numberFormatter.format(metrics.total)} branches
|
|
163
175
|
</span>
|
|
164
176
|
</section>
|
|
@@ -188,10 +200,14 @@ export function BranchListPage() {
|
|
|
188
200
|
<h2>{branch.name}</h2>
|
|
189
201
|
</div>
|
|
190
202
|
<div className="badge-group">
|
|
191
|
-
<span
|
|
203
|
+
<span
|
|
204
|
+
className={`status-badge status-badge--${branch.type}`}
|
|
205
|
+
>
|
|
192
206
|
{BRANCH_TYPE_LABEL[branch.type]}
|
|
193
207
|
</span>
|
|
194
|
-
<span
|
|
208
|
+
<span
|
|
209
|
+
className={`status-badge status-badge--${MERGE_STATUS_TONE[branch.mergeStatus]}`}
|
|
210
|
+
>
|
|
195
211
|
{MERGE_STATUS_LABEL[branch.mergeStatus]}
|
|
196
212
|
</span>
|
|
197
213
|
<span
|
|
@@ -227,11 +243,17 @@ export function BranchListPage() {
|
|
|
227
243
|
|
|
228
244
|
{branch.divergence && (
|
|
229
245
|
<div className="pill-group">
|
|
230
|
-
<span className="pill">
|
|
231
|
-
|
|
246
|
+
<span className="pill">
|
|
247
|
+
Ahead {branch.divergence.ahead}
|
|
248
|
+
</span>
|
|
249
|
+
<span className="pill">
|
|
250
|
+
Behind {branch.divergence.behind}
|
|
251
|
+
</span>
|
|
232
252
|
<span
|
|
233
253
|
className={`pill ${
|
|
234
|
-
branch.divergence.upToDate
|
|
254
|
+
branch.divergence.upToDate
|
|
255
|
+
? "pill--success"
|
|
256
|
+
: "pill--warning"
|
|
235
257
|
}`}
|
|
236
258
|
>
|
|
237
259
|
{branch.divergence.upToDate ? "最新" : "更新あり"}
|
|
@@ -248,7 +270,9 @@ export function BranchListPage() {
|
|
|
248
270
|
</Link>
|
|
249
271
|
<span
|
|
250
272
|
className={`info-pill ${
|
|
251
|
-
branch.worktreePath
|
|
273
|
+
branch.worktreePath
|
|
274
|
+
? "info-pill--success"
|
|
275
|
+
: "info-pill--warning"
|
|
252
276
|
}`}
|
|
253
277
|
>
|
|
254
278
|
{branch.worktreePath ?? "Worktree未作成"}
|