@akiojin/gwt 4.9.0 → 4.10.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 +58 -34
- package/README.md +18 -34
- package/dist/cli/ui/components/App.d.ts +2 -2
- package/dist/cli/ui/components/App.d.ts.map +1 -1
- package/dist/cli/ui/components/App.js +27 -9
- package/dist/cli/ui/components/App.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts +1 -1
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.js +4 -1
- package/dist/cli/ui/components/screens/BranchQuickStartScreen.js.map +1 -1
- package/dist/cli/ui/components/screens/CodingAgentSelectorScreen.d.ts +27 -0
- package/dist/cli/ui/components/screens/CodingAgentSelectorScreen.d.ts.map +1 -0
- package/dist/cli/ui/components/screens/{AIToolSelectorScreen.js → CodingAgentSelectorScreen.js} +35 -35
- package/dist/cli/ui/components/screens/CodingAgentSelectorScreen.js.map +1 -0
- package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts +2 -2
- package/dist/cli/ui/components/screens/ModelSelectorScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/ModelSelectorScreen.js.map +1 -1
- package/dist/cli/ui/types.d.ts +2 -2
- package/dist/cli/ui/types.d.ts.map +1 -1
- package/dist/cli/ui/utils/modelOptions.d.ts +4 -4
- package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
- package/dist/cli/ui/utils/modelOptions.js.map +1 -1
- package/dist/client/assets/{index-PqK9jkug.js → index-LNPtOrn3.js} +17 -17
- package/dist/client/index.html +1 -1
- package/dist/config/builtin-coding-agents.d.ts +27 -0
- package/dist/config/builtin-coding-agents.d.ts.map +1 -0
- package/dist/config/{builtin-tools.js → builtin-coding-agents.js} +21 -6
- package/dist/config/builtin-coding-agents.js.map +1 -0
- package/dist/config/tools.d.ts +16 -16
- package/dist/config/tools.d.ts.map +1 -1
- package/dist/config/tools.js +92 -78
- package/dist/config/tools.js.map +1 -1
- package/dist/index.js +19 -19
- package/dist/index.js.map +1 -1
- package/dist/launcher.d.ts +8 -8
- package/dist/launcher.d.ts.map +1 -1
- package/dist/launcher.js +32 -28
- package/dist/launcher.js.map +1 -1
- package/dist/services/codingAgentCommandResolver.d.ts +10 -0
- package/dist/services/codingAgentCommandResolver.d.ts.map +1 -0
- package/dist/services/{customToolResolver.js → codingAgentCommandResolver.js} +25 -20
- package/dist/services/codingAgentCommandResolver.js.map +1 -0
- package/dist/services/{aiToolResolver.d.ts → codingAgentResolver.d.ts} +6 -6
- package/dist/services/codingAgentResolver.d.ts.map +1 -0
- package/dist/services/{aiToolResolver.js → codingAgentResolver.js} +23 -23
- package/dist/services/codingAgentResolver.js.map +1 -0
- package/dist/shared/{aiToolConstants.d.ts → codingAgentConstants.d.ts} +2 -2
- package/dist/shared/codingAgentConstants.d.ts.map +1 -0
- package/dist/shared/{aiToolConstants.js → codingAgentConstants.js} +2 -2
- package/dist/shared/codingAgentConstants.js.map +1 -0
- package/dist/types/api.d.ts +12 -12
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/tools.d.ts +30 -30
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/types/tools.js +1 -1
- package/dist/utils/command.d.ts.map +1 -1
- package/dist/utils/command.js +9 -0
- package/dist/utils/command.js.map +1 -1
- package/dist/utils/session/index.d.ts +5 -3
- package/dist/utils/session/index.d.ts.map +1 -1
- package/dist/utils/session/index.js +5 -2
- package/dist/utils/session/index.js.map +1 -1
- package/dist/utils/session/parsers/index.d.ts +1 -0
- package/dist/utils/session/parsers/index.d.ts.map +1 -1
- package/dist/utils/session/parsers/index.js +2 -0
- package/dist/utils/session/parsers/index.js.map +1 -1
- package/dist/utils/session/parsers/opencode.d.ts +23 -0
- package/dist/utils/session/parsers/opencode.d.ts.map +1 -0
- package/dist/utils/session/parsers/opencode.js +89 -0
- package/dist/utils/session/parsers/opencode.js.map +1 -0
- package/dist/utils/session/types.d.ts +4 -0
- package/dist/utils/session/types.d.ts.map +1 -1
- package/dist/web/client/src/components/CodingAgentLaunchModal.d.ts +9 -0
- package/dist/web/client/src/components/CodingAgentLaunchModal.d.ts.map +1 -0
- package/dist/web/client/src/components/{AIToolLaunchModal.js → CodingAgentLaunchModal.js} +58 -58
- package/dist/web/client/src/components/CodingAgentLaunchModal.js.map +1 -0
- package/dist/web/client/src/components/CustomCodingAgentForm.d.ts +23 -0
- package/dist/web/client/src/components/CustomCodingAgentForm.d.ts.map +1 -0
- package/dist/web/client/src/components/{CustomToolForm.js → CustomCodingAgentForm.js} +5 -5
- package/dist/web/client/src/components/CustomCodingAgentForm.js.map +1 -0
- package/dist/web/client/src/components/CustomCodingAgentList.d.ts +10 -0
- package/dist/web/client/src/components/CustomCodingAgentList.d.ts.map +1 -0
- package/dist/web/client/src/components/{CustomToolList.js → CustomCodingAgentList.js} +17 -17
- package/dist/web/client/src/components/CustomCodingAgentList.js.map +1 -0
- package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts +2 -2
- package/dist/web/client/src/components/branch-detail/SessionHistoryTable.d.ts.map +1 -1
- package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js +6 -6
- package/dist/web/client/src/components/branch-detail/SessionHistoryTable.js.map +1 -1
- package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts +2 -2
- package/dist/web/client/src/components/branch-detail/ToolLauncher.d.ts.map +1 -1
- package/dist/web/client/src/components/branch-detail/ToolLauncher.js +5 -5
- package/dist/web/client/src/components/branch-detail/ToolLauncher.js.map +1 -1
- package/dist/web/client/src/hooks/useSessions.d.ts +4 -4
- package/dist/web/client/src/hooks/useSessions.d.ts.map +1 -1
- package/dist/web/client/src/hooks/useSessions.js.map +1 -1
- package/dist/web/client/src/lib/api.d.ts +5 -5
- package/dist/web/client/src/lib/api.d.ts.map +1 -1
- package/dist/web/client/src/lib/api.js +1 -1
- package/dist/web/client/src/lib/api.js.map +1 -1
- package/dist/web/client/src/pages/BranchDetailPage.js +24 -24
- package/dist/web/client/src/pages/BranchDetailPage.js.map +1 -1
- package/dist/web/client/src/pages/ConfigManagementPage.d.ts.map +1 -1
- package/dist/web/client/src/pages/ConfigManagementPage.js +15 -15
- package/dist/web/client/src/pages/ConfigManagementPage.js.map +1 -1
- package/dist/web/client/src/pages/ConfigPage.d.ts.map +1 -1
- package/dist/web/client/src/pages/ConfigPage.js +43 -39
- package/dist/web/client/src/pages/ConfigPage.js.map +1 -1
- package/dist/web/server/env/importer.d.ts.map +1 -1
- package/dist/web/server/env/importer.js +3 -3
- package/dist/web/server/env/importer.js.map +1 -1
- package/dist/web/server/pty/manager.d.ts +6 -6
- package/dist/web/server/pty/manager.d.ts.map +1 -1
- package/dist/web/server/pty/manager.js +11 -11
- package/dist/web/server/pty/manager.js.map +1 -1
- package/dist/web/server/routes/config.d.ts.map +1 -1
- package/dist/web/server/routes/config.js +34 -34
- package/dist/web/server/routes/config.js.map +1 -1
- package/dist/web/server/routes/sessions.d.ts +1 -1
- package/dist/web/server/routes/sessions.d.ts.map +1 -1
- package/dist/web/server/routes/sessions.js +20 -20
- package/dist/web/server/routes/sessions.js.map +1 -1
- package/package.json +2 -2
- package/src/cli/ui/__tests__/components/screens/{AIToolSelectorScreen.test.tsx → CodingAgentSelectorScreen.test.tsx} +38 -38
- package/src/cli/ui/components/App.tsx +44 -20
- package/src/cli/ui/components/screens/BranchQuickStartScreen.tsx +6 -3
- package/src/cli/ui/components/screens/CodingAgentSelectorScreen.tsx +159 -0
- package/src/cli/ui/components/screens/ModelSelectorScreen.tsx +6 -2
- package/src/cli/ui/types.ts +2 -2
- package/src/cli/ui/utils/modelOptions.ts +6 -4
- package/src/config/{builtin-tools.ts → builtin-coding-agents.ts} +25 -9
- package/src/config/tools.ts +120 -92
- package/src/index.ts +19 -19
- package/src/launcher.ts +38 -31
- package/src/services/{customToolResolver.ts → codingAgentCommandResolver.ts} +33 -28
- package/src/services/{aiToolResolver.ts → codingAgentResolver.ts} +28 -28
- package/src/shared/{aiToolConstants.ts → codingAgentConstants.ts} +1 -1
- package/src/types/api.ts +12 -12
- package/src/types/tools.ts +30 -30
- package/src/utils/command.ts +9 -0
- package/src/utils/session/index.ts +10 -2
- package/src/utils/session/parsers/index.ts +6 -0
- package/src/utils/session/parsers/opencode.ts +110 -0
- package/src/utils/session/types.ts +5 -0
- package/src/web/client/src/components/{AIToolLaunchModal.tsx → CodingAgentLaunchModal.tsx} +74 -70
- package/src/web/client/src/components/{CustomToolForm.tsx → CustomCodingAgentForm.tsx} +14 -14
- package/src/web/client/src/components/{CustomToolList.tsx → CustomCodingAgentList.tsx} +26 -26
- package/src/web/client/src/components/branch-detail/SessionHistoryTable.tsx +7 -7
- package/src/web/client/src/components/branch-detail/ToolLauncher.tsx +9 -9
- package/src/web/client/src/hooks/useSessions.ts +5 -5
- package/src/web/client/src/lib/api.ts +8 -8
- package/src/web/client/src/pages/BranchDetailPage.tsx +26 -26
- package/src/web/client/src/pages/ConfigManagementPage.tsx +32 -24
- package/src/web/client/src/pages/ConfigPage.tsx +55 -49
- package/src/web/server/env/importer.ts +6 -3
- package/src/web/server/pty/manager.ts +20 -20
- package/src/web/server/routes/config.ts +45 -39
- package/src/web/server/routes/sessions.ts +29 -26
- package/dist/cli/ui/components/screens/AIToolSelectorScreen.d.ts +0 -27
- package/dist/cli/ui/components/screens/AIToolSelectorScreen.d.ts.map +0 -1
- package/dist/cli/ui/components/screens/AIToolSelectorScreen.js.map +0 -1
- package/dist/config/builtin-tools.d.ts +0 -23
- package/dist/config/builtin-tools.d.ts.map +0 -1
- package/dist/config/builtin-tools.js.map +0 -1
- package/dist/services/aiToolResolver.d.ts.map +0 -1
- package/dist/services/aiToolResolver.js.map +0 -1
- package/dist/services/customToolResolver.d.ts +0 -10
- package/dist/services/customToolResolver.d.ts.map +0 -1
- package/dist/services/customToolResolver.js.map +0 -1
- package/dist/shared/aiToolConstants.d.ts.map +0 -1
- package/dist/shared/aiToolConstants.js.map +0 -1
- package/dist/web/client/src/components/AIToolLaunchModal.d.ts +0 -9
- package/dist/web/client/src/components/AIToolLaunchModal.d.ts.map +0 -1
- package/dist/web/client/src/components/AIToolLaunchModal.js.map +0 -1
- package/dist/web/client/src/components/CustomToolForm.d.ts +0 -23
- package/dist/web/client/src/components/CustomToolForm.d.ts.map +0 -1
- package/dist/web/client/src/components/CustomToolForm.js.map +0 -1
- package/dist/web/client/src/components/CustomToolList.d.ts +0 -10
- package/dist/web/client/src/components/CustomToolList.d.ts.map +0 -1
- package/dist/web/client/src/components/CustomToolList.js.map +0 -1
- package/src/cli/ui/components/screens/AIToolSelectorScreen.tsx +0 -153
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session Routes
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* コーディングエージェントセッション関連のREST APIエンドポイント。
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { CodingAgentResolutionError } from "../../../services/codingAgentResolver.js";
|
|
7
7
|
import { saveSession } from "../../../config/index.js";
|
|
8
8
|
import { execa } from "execa";
|
|
9
9
|
import { createLogger } from "../../../logging/logger.js";
|
|
@@ -32,11 +32,11 @@ export async function registerSessionRoutes(fastify, ptyManager) {
|
|
|
32
32
|
// POST /api/sessions - 新しいセッションを開始
|
|
33
33
|
fastify.post("/api/sessions", async (request, reply) => {
|
|
34
34
|
try {
|
|
35
|
-
const {
|
|
36
|
-
logger.debug({
|
|
35
|
+
const { agentType, agentName, mode, worktreePath, skipPermissions, bypassApprovals, extraArgs, customAgentId, } = request.body;
|
|
36
|
+
logger.debug({ agentType, mode, worktreePath }, "Session start requested");
|
|
37
37
|
const spawnOptions = {};
|
|
38
|
-
if (typeof
|
|
39
|
-
spawnOptions.toolName =
|
|
38
|
+
if (typeof agentName !== "undefined") {
|
|
39
|
+
spawnOptions.toolName = agentName;
|
|
40
40
|
}
|
|
41
41
|
if (typeof skipPermissions !== "undefined") {
|
|
42
42
|
spawnOptions.skipPermissions = skipPermissions;
|
|
@@ -47,18 +47,18 @@ export async function registerSessionRoutes(fastify, ptyManager) {
|
|
|
47
47
|
if (Array.isArray(extraArgs) && extraArgs.length > 0) {
|
|
48
48
|
spawnOptions.extraArgs = extraArgs;
|
|
49
49
|
}
|
|
50
|
-
if (typeof
|
|
51
|
-
spawnOptions.customToolId =
|
|
50
|
+
if (typeof customAgentId !== "undefined") {
|
|
51
|
+
spawnOptions.customToolId = customAgentId;
|
|
52
52
|
}
|
|
53
|
-
if (
|
|
53
|
+
if (agentType === "custom" && !agentName && !customAgentId) {
|
|
54
54
|
reply.code(400);
|
|
55
55
|
return {
|
|
56
56
|
success: false,
|
|
57
|
-
error: "Custom
|
|
57
|
+
error: "Custom coding agent requires agentName or customAgentId",
|
|
58
58
|
details: null,
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
|
-
const { session } = await ptyManager.spawn(
|
|
61
|
+
const { session } = await ptyManager.spawn(agentType, worktreePath, mode, spawnOptions);
|
|
62
62
|
// 履歴を永続化(best-effort)
|
|
63
63
|
try {
|
|
64
64
|
const { stdout: repoRoot } = await execa("git", ["rev-parse", "--show-toplevel"], {
|
|
@@ -75,10 +75,10 @@ export async function registerSessionRoutes(fastify, ptyManager) {
|
|
|
75
75
|
await saveSession({
|
|
76
76
|
lastWorktreePath: worktreePath,
|
|
77
77
|
lastBranch: branchName,
|
|
78
|
-
lastUsedTool:
|
|
79
|
-
toolLabel:
|
|
80
|
-
? (
|
|
81
|
-
:
|
|
78
|
+
lastUsedTool: agentType === "custom" ? (agentName ?? "custom") : agentType,
|
|
79
|
+
toolLabel: agentType === "custom"
|
|
80
|
+
? (agentName ?? "Custom")
|
|
81
|
+
: agentLabelFromType(agentType),
|
|
82
82
|
mode,
|
|
83
83
|
timestamp: Date.now(),
|
|
84
84
|
repositoryRoot: repoRoot.trim(),
|
|
@@ -87,12 +87,12 @@ export async function registerSessionRoutes(fastify, ptyManager) {
|
|
|
87
87
|
catch {
|
|
88
88
|
// ignore persistence errors
|
|
89
89
|
}
|
|
90
|
-
logger.info({ sessionId: session.sessionId,
|
|
90
|
+
logger.info({ sessionId: session.sessionId, agentType }, "Session created");
|
|
91
91
|
reply.code(201);
|
|
92
92
|
return { success: true, data: session };
|
|
93
93
|
}
|
|
94
94
|
catch (error) {
|
|
95
|
-
if (error instanceof
|
|
95
|
+
if (error instanceof CodingAgentResolutionError) {
|
|
96
96
|
reply.code(400);
|
|
97
97
|
return {
|
|
98
98
|
success: false,
|
|
@@ -162,10 +162,10 @@ export async function registerSessionRoutes(fastify, ptyManager) {
|
|
|
162
162
|
}
|
|
163
163
|
});
|
|
164
164
|
}
|
|
165
|
-
function
|
|
166
|
-
if (
|
|
165
|
+
function agentLabelFromType(agentType) {
|
|
166
|
+
if (agentType === "claude-code")
|
|
167
167
|
return "Claude";
|
|
168
|
-
if (
|
|
168
|
+
if (agentType === "codex-cli")
|
|
169
169
|
return "Codex";
|
|
170
170
|
return "Custom";
|
|
171
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../../src/web/server/routes/sessions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../../src/web/server/routes/sessions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AAMtF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;AAEtD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAA2B,EAC3B,UAAsB;IAEtB,qCAAqC;IACrC,OAAO,CAAC,GAAG,CACT,eAAe,EACf,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC;YAC5D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,0BAA0B;gBACjC,OAAO,EAAE,QAAQ;aAClB,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,mCAAmC;IACnC,OAAO,CAAC,IAAI,CAGT,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,MAAM,EACJ,SAAS,EACT,SAAS,EACT,IAAI,EACJ,YAAY,EACZ,eAAe,EACf,eAAe,EACf,SAAS,EACT,aAAa,GACd,GAAG,OAAO,CAAC,IAAI,CAAC;YAEjB,MAAM,CAAC,KAAK,CACV,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,EACjC,yBAAyB,CAC1B,CAAC;YAEF,MAAM,YAAY,GAMd,EAAE,CAAC;YAEP,IAAI,OAAO,SAAS,KAAK,WAAW,EAAE,CAAC;gBACrC,YAAY,CAAC,QAAQ,GAAG,SAAS,CAAC;YACpC,CAAC;YACD,IAAI,OAAO,eAAe,KAAK,WAAW,EAAE,CAAC;gBAC3C,YAAY,CAAC,eAAe,GAAG,eAAe,CAAC;YACjD,CAAC;YACD,IAAI,OAAO,eAAe,KAAK,WAAW,EAAE,CAAC;gBAC3C,YAAY,CAAC,eAAe,GAAG,eAAe,CAAC;YACjD,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrD,YAAY,CAAC,SAAS,GAAG,SAAS,CAAC;YACrC,CAAC;YACD,IAAI,OAAO,aAAa,KAAK,WAAW,EAAE,CAAC;gBACzC,YAAY,CAAC,YAAY,GAAG,aAAa,CAAC;YAC5C,CAAC;YAED,IAAI,SAAS,KAAK,QAAQ,IAAI,CAAC,SAAS,IAAI,CAAC,aAAa,EAAE,CAAC;gBAC3D,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAChB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,yDAAyD;oBAChE,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,UAAU,CAAC,KAAK,CACxC,SAAS,EACT,YAAY,EACZ,IAAI,EACJ,YAAY,CACb,CAAC;YAEF,sBAAsB;YACtB,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,KAAK,CACtC,KAAK,EACL,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAChC;oBACE,GAAG,EAAE,YAAY;iBAClB,CACF,CAAC;gBACF,IAAI,UAAU,GAAkB,IAAI,CAAC;gBACrC,IAAI,CAAC;oBACH,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,KAAK,CAC1C,KAAK,EACL,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EACrC,EAAE,GAAG,EAAE,YAAY,EAAE,CACtB,CAAC;oBACF,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;gBAC3C,CAAC;gBAAC,MAAM,CAAC;oBACP,UAAU,GAAG,IAAI,CAAC;gBACpB,CAAC;gBAED,MAAM,WAAW,CAAC;oBAChB,gBAAgB,EAAE,YAAY;oBAC9B,UAAU,EAAE,UAAU;oBACtB,YAAY,EACV,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;oBAC9D,SAAS,EACP,SAAS,KAAK,QAAQ;wBACpB,CAAC,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC;wBACzB,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC;oBACnC,IAAI;oBACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,cAAc,EAAE,QAAQ,CAAC,IAAI,EAAE;iBAChC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,4BAA4B;YAC9B,CAAC;YAED,MAAM,CAAC,IAAI,CACT,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,EAC3C,iBAAiB,CAClB,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,KAAK,YAAY,0BAA0B,EAAE,CAAC;gBAChD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAChB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,KAAK,CAAC,OAAO;oBACpB,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI;iBACzC,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,yBAAyB;gBAChC,OAAO,EAAE,QAAQ;aAClB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,+CAA+C;IAC/C,OAAO,CAAC,GAAG,CAGR,0BAA0B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACtD,IAAI,CAAC;YACH,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;YAErC,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAChB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,mBAAmB;oBAC1B,OAAO,EAAE,WAAW,SAAS,iBAAiB;iBAC/C,CAAC;YACJ,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,yBAAyB;gBAChC,OAAO,EAAE,QAAQ;aAClB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,6CAA6C;IAC7C,OAAO,CAAC,MAAM,CAKX,0BAA0B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACtD,IAAI,CAAC;YACH,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;YAErC,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,CAAC,IAAI,CACT,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,EAClC,uBAAuB,CACxB,CAAC;gBACF,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAChB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,mBAAmB;oBAC1B,OAAO,EAAE,WAAW,SAAS,iBAAiB;iBAC/C,CAAC;YACJ,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,yBAAyB,CAAC,CAAC;YACtD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,0BAA0B;gBACjC,OAAO,EAAE,QAAQ;aAClB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAiD;IAC3E,IAAI,SAAS,KAAK,aAAa;QAAE,OAAO,QAAQ,CAAC;IACjD,IAAI,SAAS,KAAK,WAAW;QAAE,OAAO,OAAO,CAAC;IAC9C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akiojin/gwt",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Interactive Git worktree manager
|
|
3
|
+
"version": "4.10.0",
|
|
4
|
+
"description": "Interactive Git worktree manager with Coding Agent selection (Claude Code / Codex CLI / Gemini CLI)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"gwt": "bin/gwt.js"
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
5
5
|
import { render, waitFor } from "@testing-library/react";
|
|
6
6
|
import React from "react";
|
|
7
|
-
import {
|
|
7
|
+
import { CodingAgentSelectorScreen } from "../../../components/screens/CodingAgentSelectorScreen.js";
|
|
8
8
|
import { Window } from "happy-dom";
|
|
9
9
|
|
|
10
|
-
// Mock
|
|
10
|
+
// Mock getAllCodingAgents
|
|
11
11
|
vi.mock("../../../config/tools.js", () => ({
|
|
12
|
-
|
|
12
|
+
getAllCodingAgents: vi.fn().mockResolvedValue([
|
|
13
13
|
{
|
|
14
14
|
id: "claude-code",
|
|
15
15
|
displayName: "Claude Code",
|
|
@@ -23,7 +23,7 @@ vi.mock("../../../config/tools.js", () => ({
|
|
|
23
23
|
]),
|
|
24
24
|
}));
|
|
25
25
|
|
|
26
|
-
describe("
|
|
26
|
+
describe("CodingAgentSelectorScreen", () => {
|
|
27
27
|
beforeEach(() => {
|
|
28
28
|
// Setup happy-dom
|
|
29
29
|
const window = new Window();
|
|
@@ -36,20 +36,20 @@ describe("AIToolSelectorScreen", () => {
|
|
|
36
36
|
const onBack = vi.fn();
|
|
37
37
|
const onSelect = vi.fn();
|
|
38
38
|
const { getByText } = render(
|
|
39
|
-
<
|
|
39
|
+
<CodingAgentSelectorScreen onBack={onBack} onSelect={onSelect} />,
|
|
40
40
|
);
|
|
41
41
|
|
|
42
|
-
expect(getByText(/
|
|
42
|
+
expect(getByText(/Coding Agent Selection/i)).toBeDefined();
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
it("should render
|
|
45
|
+
it("should render Coding Agent options", async () => {
|
|
46
46
|
const onBack = vi.fn();
|
|
47
47
|
const onSelect = vi.fn();
|
|
48
48
|
const { getByText } = render(
|
|
49
|
-
<
|
|
49
|
+
<CodingAgentSelectorScreen onBack={onBack} onSelect={onSelect} />,
|
|
50
50
|
);
|
|
51
51
|
|
|
52
|
-
// Wait for
|
|
52
|
+
// Wait for agents to load
|
|
53
53
|
await waitFor(() => {
|
|
54
54
|
expect(getByText(/Claude Code/i)).toBeDefined();
|
|
55
55
|
expect(getByText(/Codex/i)).toBeDefined();
|
|
@@ -60,7 +60,7 @@ describe("AIToolSelectorScreen", () => {
|
|
|
60
60
|
const onBack = vi.fn();
|
|
61
61
|
const onSelect = vi.fn();
|
|
62
62
|
const { getAllByText } = render(
|
|
63
|
-
<
|
|
63
|
+
<CodingAgentSelectorScreen onBack={onBack} onSelect={onSelect} />,
|
|
64
64
|
);
|
|
65
65
|
|
|
66
66
|
expect(getAllByText(/enter/i).length).toBeGreaterThan(0);
|
|
@@ -74,7 +74,7 @@ describe("AIToolSelectorScreen", () => {
|
|
|
74
74
|
const onBack = vi.fn();
|
|
75
75
|
const onSelect = vi.fn();
|
|
76
76
|
const { container } = render(
|
|
77
|
-
<
|
|
77
|
+
<CodingAgentSelectorScreen onBack={onBack} onSelect={onSelect} />,
|
|
78
78
|
);
|
|
79
79
|
|
|
80
80
|
expect(container).toBeDefined();
|
|
@@ -86,32 +86,32 @@ describe("AIToolSelectorScreen", () => {
|
|
|
86
86
|
const onBack = vi.fn();
|
|
87
87
|
const onSelect = vi.fn();
|
|
88
88
|
const { container } = render(
|
|
89
|
-
<
|
|
89
|
+
<CodingAgentSelectorScreen onBack={onBack} onSelect={onSelect} />,
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
// Test will verify onBack is called when ESC is pressed
|
|
93
93
|
expect(container).toBeDefined();
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
-
it("should handle
|
|
96
|
+
it("should handle coding agent selection", () => {
|
|
97
97
|
const onBack = vi.fn();
|
|
98
98
|
const onSelect = vi.fn();
|
|
99
99
|
const { container } = render(
|
|
100
|
-
<
|
|
100
|
+
<CodingAgentSelectorScreen onBack={onBack} onSelect={onSelect} />,
|
|
101
101
|
);
|
|
102
102
|
|
|
103
|
-
// Test will verify onSelect is called with correct
|
|
103
|
+
// Test will verify onSelect is called with correct agent
|
|
104
104
|
expect(container).toBeDefined();
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
it("should preselect the last used
|
|
107
|
+
it("should preselect the last used coding agent when provided", async () => {
|
|
108
108
|
const onBack = vi.fn();
|
|
109
109
|
const onSelect = vi.fn();
|
|
110
110
|
const { container } = render(
|
|
111
|
-
<
|
|
111
|
+
<CodingAgentSelectorScreen
|
|
112
112
|
onBack={onBack}
|
|
113
113
|
onSelect={onSelect}
|
|
114
|
-
|
|
114
|
+
initialAgentId="codex-cli"
|
|
115
115
|
/>,
|
|
116
116
|
);
|
|
117
117
|
|
|
@@ -125,49 +125,49 @@ describe("AIToolSelectorScreen", () => {
|
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
|
-
* T210:
|
|
128
|
+
* T210: カスタムコーディングエージェント表示のテスト
|
|
129
129
|
*/
|
|
130
|
-
describe("Custom
|
|
131
|
-
it("should load
|
|
130
|
+
describe("Custom coding agent display", () => {
|
|
131
|
+
it("should load coding agents from getAllCodingAgents() dynamically", async () => {
|
|
132
132
|
// TODO: 実装後にテストを記述
|
|
133
|
-
//
|
|
134
|
-
//
|
|
133
|
+
// getAllCodingAgents()がモックされ、呼び出されることを確認
|
|
134
|
+
// モックの戻り値がエージェントアイテムとして表示されることを確認
|
|
135
135
|
expect(true).toBe(true);
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
-
it("should display both builtin and custom
|
|
138
|
+
it("should display both builtin and custom coding agents", async () => {
|
|
139
139
|
// TODO: 実装後にテストを記述
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
140
|
+
// getAllCodingAgents()がビルトインエージェント(claude-code, codex-cli)と
|
|
141
|
+
// カスタムエージェント(例: aider)を返す場合、
|
|
142
|
+
// すべてのエージェントが表示されることを確認
|
|
143
143
|
expect(true).toBe(true);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
-
it("should display custom
|
|
146
|
+
it("should display custom coding agent with icon if defined", async () => {
|
|
147
147
|
// TODO: 実装後にテストを記述
|
|
148
|
-
//
|
|
148
|
+
// カスタムエージェントにiconフィールドがある場合、
|
|
149
149
|
// それが表示されることを確認
|
|
150
150
|
expect(true).toBe(true);
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
-
it("should display custom
|
|
153
|
+
it("should display custom coding agent without icon if not defined", async () => {
|
|
154
154
|
// TODO: 実装後にテストを記述
|
|
155
|
-
//
|
|
156
|
-
//
|
|
155
|
+
// カスタムエージェントにiconフィールドがない場合、
|
|
156
|
+
// エージェント名のみが表示されることを確認
|
|
157
157
|
expect(true).toBe(true);
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
-
it("should handle custom
|
|
160
|
+
it("should handle custom coding agent selection", async () => {
|
|
161
161
|
// TODO: 実装後にテストを記述
|
|
162
|
-
//
|
|
163
|
-
// onSelect()
|
|
162
|
+
// カスタムエージェントを選択した場合、
|
|
163
|
+
// onSelect()がカスタムエージェントのIDで呼び出されることを確認
|
|
164
164
|
expect(true).toBe(true);
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
it("should display only builtin
|
|
167
|
+
it("should display only builtin coding agents if no custom agents exist", async () => {
|
|
168
168
|
// TODO: 実装後にテストを記述
|
|
169
|
-
//
|
|
170
|
-
//
|
|
169
|
+
// getAllCodingAgents()がビルトインエージェントのみを返す場合、
|
|
170
|
+
// ビルトインエージェントのみが表示されることを確認
|
|
171
171
|
expect(true).toBe(true);
|
|
172
172
|
});
|
|
173
173
|
});
|
|
@@ -16,7 +16,7 @@ import { LogDetailScreen } from "./screens/LogDetailScreen.js";
|
|
|
16
16
|
import { LogDatePickerScreen } from "./screens/LogDatePickerScreen.js";
|
|
17
17
|
import { BranchCreatorScreen } from "./screens/BranchCreatorScreen.js";
|
|
18
18
|
import { BranchActionSelectorScreen } from "../screens/BranchActionSelectorScreen.js";
|
|
19
|
-
import {
|
|
19
|
+
import { CodingAgentSelectorScreen } from "./screens/CodingAgentSelectorScreen.js";
|
|
20
20
|
import { ExecutionModeSelectorScreen } from "./screens/ExecutionModeSelectorScreen.js";
|
|
21
21
|
import type { ExecutionMode } from "./screens/ExecutionModeSelectorScreen.js";
|
|
22
22
|
import { BranchQuickStartScreen } from "./screens/BranchQuickStartScreen.js";
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
type LogFileInfo,
|
|
47
47
|
} from "../../../logging/reader.js";
|
|
48
48
|
import type {
|
|
49
|
-
|
|
49
|
+
CodingAgentId,
|
|
50
50
|
BranchInfo,
|
|
51
51
|
BranchItem,
|
|
52
52
|
CleanupTarget,
|
|
@@ -81,6 +81,7 @@ import {
|
|
|
81
81
|
findLatestCodexSessionId,
|
|
82
82
|
findLatestClaudeSession,
|
|
83
83
|
findLatestGeminiSession,
|
|
84
|
+
findLatestOpenCodeSession,
|
|
84
85
|
} from "../../../utils/session.js";
|
|
85
86
|
import type { ToolSessionEntry } from "../../../config/index.js";
|
|
86
87
|
|
|
@@ -93,7 +94,7 @@ export interface SelectionResult {
|
|
|
93
94
|
displayName: string; // Name that was selected in the UI (may include remote prefix)
|
|
94
95
|
branchType: "local" | "remote";
|
|
95
96
|
remoteBranch?: string; // Full remote ref when branchType === 'remote'
|
|
96
|
-
tool:
|
|
97
|
+
tool: CodingAgentId;
|
|
97
98
|
mode: ExecutionMode;
|
|
98
99
|
skipPermissions: boolean;
|
|
99
100
|
model?: string | null;
|
|
@@ -136,7 +137,7 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
136
137
|
);
|
|
137
138
|
const [branchQuickStart, setBranchQuickStart] = useState<
|
|
138
139
|
{
|
|
139
|
-
toolId:
|
|
140
|
+
toolId: CodingAgentId;
|
|
140
141
|
toolLabel: string;
|
|
141
142
|
model?: string | null;
|
|
142
143
|
sessionId?: string | null;
|
|
@@ -172,13 +173,15 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
172
173
|
useState<SelectedBranchState | null>(null);
|
|
173
174
|
const [creationSourceBranch, setCreationSourceBranch] =
|
|
174
175
|
useState<SelectedBranchState | null>(null);
|
|
175
|
-
const [selectedTool, setSelectedTool] = useState<
|
|
176
|
+
const [selectedTool, setSelectedTool] = useState<CodingAgentId | null>(null);
|
|
176
177
|
const [selectedModel, setSelectedModel] =
|
|
177
178
|
useState<ModelSelectionResult | null>(null);
|
|
178
179
|
const [lastModelByTool, setLastModelByTool] = useState<
|
|
179
|
-
Record<
|
|
180
|
+
Record<CodingAgentId, ModelSelectionResult | undefined>
|
|
180
181
|
>({});
|
|
181
|
-
const [preferredToolId, setPreferredToolId] = useState<
|
|
182
|
+
const [preferredToolId, setPreferredToolId] = useState<CodingAgentId | null>(
|
|
183
|
+
null,
|
|
184
|
+
);
|
|
182
185
|
|
|
183
186
|
// PR cleanup feedback
|
|
184
187
|
const [cleanupIndicators, setCleanupIndicators] = useState<
|
|
@@ -412,13 +415,34 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
412
415
|
}
|
|
413
416
|
}
|
|
414
417
|
|
|
418
|
+
// For OpenCode, prefer newest session file
|
|
419
|
+
if (!sessionId && entry.toolId === "opencode") {
|
|
420
|
+
try {
|
|
421
|
+
const openCodeOptions: Parameters<
|
|
422
|
+
typeof findLatestOpenCodeSession
|
|
423
|
+
>[0] = {
|
|
424
|
+
windowMs: 60 * 60 * 1000,
|
|
425
|
+
cwd: worktree,
|
|
426
|
+
};
|
|
427
|
+
if (entry.timestamp !== null && entry.timestamp !== undefined) {
|
|
428
|
+
openCodeOptions.since = entry.timestamp - 60_000;
|
|
429
|
+
openCodeOptions.preferClosestTo = entry.timestamp;
|
|
430
|
+
}
|
|
431
|
+
const openCodeSession =
|
|
432
|
+
await findLatestOpenCodeSession(openCodeOptions);
|
|
433
|
+
sessionId = openCodeSession?.id ?? null;
|
|
434
|
+
} catch {
|
|
435
|
+
// ignore
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
415
439
|
const normalizedModel = normalizeModelId(
|
|
416
|
-
entry.toolId as
|
|
440
|
+
entry.toolId as CodingAgentId,
|
|
417
441
|
entry.model ?? null,
|
|
418
442
|
);
|
|
419
443
|
|
|
420
444
|
return {
|
|
421
|
-
toolId: entry.toolId as
|
|
445
|
+
toolId: entry.toolId as CodingAgentId,
|
|
422
446
|
toolLabel: entry.toolLabel,
|
|
423
447
|
model: normalizedModel ?? null,
|
|
424
448
|
inferenceLevel: (entry.reasoningLevel ??
|
|
@@ -772,7 +796,7 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
772
796
|
const nextScreen =
|
|
773
797
|
branchQuickStart.length || branchQuickStartLoading
|
|
774
798
|
? "branch-quick-start"
|
|
775
|
-
: "
|
|
799
|
+
: "coding-agent-selector";
|
|
776
800
|
navigateTo(nextScreen);
|
|
777
801
|
} catch (error) {
|
|
778
802
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -799,7 +823,7 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
799
823
|
if (branchQuickStart.length) {
|
|
800
824
|
navigateTo("branch-quick-start");
|
|
801
825
|
} else {
|
|
802
|
-
navigateTo("
|
|
826
|
+
navigateTo("coding-agent-selector");
|
|
803
827
|
}
|
|
804
828
|
}, [
|
|
805
829
|
handleProtectedBranchSwitch,
|
|
@@ -893,7 +917,7 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
893
917
|
setPreferredToolId(null);
|
|
894
918
|
setCleanupFooterMessage(null);
|
|
895
919
|
|
|
896
|
-
navigateTo("
|
|
920
|
+
navigateTo("coding-agent-selector");
|
|
897
921
|
} catch (error) {
|
|
898
922
|
// On error, go back to branch list
|
|
899
923
|
console.error("Failed to create branch:", error);
|
|
@@ -1144,7 +1168,7 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
1144
1168
|
|
|
1145
1169
|
// Handle AI tool selection
|
|
1146
1170
|
const handleToolSelect = useCallback(
|
|
1147
|
-
(tool:
|
|
1171
|
+
(tool: CodingAgentId) => {
|
|
1148
1172
|
setSelectedTool(tool);
|
|
1149
1173
|
setSelectedModel(lastModelByTool[tool] ?? null);
|
|
1150
1174
|
navigateTo("model-selector");
|
|
@@ -1211,9 +1235,9 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
1211
1235
|
);
|
|
1212
1236
|
|
|
1213
1237
|
const handleQuickStartSelect = useCallback(
|
|
1214
|
-
(action: QuickStartAction, toolId?:
|
|
1238
|
+
(action: QuickStartAction, toolId?: CodingAgentId | null) => {
|
|
1215
1239
|
if (action === "manual" || !branchQuickStart.length) {
|
|
1216
|
-
navigateTo("
|
|
1240
|
+
navigateTo("coding-agent-selector");
|
|
1217
1241
|
return;
|
|
1218
1242
|
}
|
|
1219
1243
|
|
|
@@ -1221,14 +1245,14 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
1221
1245
|
branchQuickStart.find((opt) => opt.toolId === toolId) ??
|
|
1222
1246
|
branchQuickStart[0];
|
|
1223
1247
|
if (!selected) {
|
|
1224
|
-
navigateTo("
|
|
1248
|
+
navigateTo("coding-agent-selector");
|
|
1225
1249
|
return;
|
|
1226
1250
|
}
|
|
1227
1251
|
|
|
1228
1252
|
setSelectedTool(selected.toolId);
|
|
1229
1253
|
setPreferredToolId(selected.toolId);
|
|
1230
1254
|
const normalizedQuickStartModel = normalizeModelId(
|
|
1231
|
-
selected.toolId as
|
|
1255
|
+
selected.toolId as CodingAgentId,
|
|
1232
1256
|
selected.model ?? null,
|
|
1233
1257
|
);
|
|
1234
1258
|
setSelectedModel(
|
|
@@ -1399,13 +1423,13 @@ export function App({ onExit, loadingIndicatorDelay = 300 }: AppProps) {
|
|
|
1399
1423
|
/>
|
|
1400
1424
|
);
|
|
1401
1425
|
|
|
1402
|
-
case "
|
|
1426
|
+
case "coding-agent-selector":
|
|
1403
1427
|
return (
|
|
1404
|
-
<
|
|
1428
|
+
<CodingAgentSelectorScreen
|
|
1405
1429
|
onBack={goBack}
|
|
1406
1430
|
onSelect={handleToolSelect}
|
|
1407
1431
|
version={version}
|
|
1408
|
-
|
|
1432
|
+
initialAgentId={selectedTool ?? preferredToolId ?? null}
|
|
1409
1433
|
/>
|
|
1410
1434
|
);
|
|
1411
1435
|
|
|
@@ -17,7 +17,7 @@ export type QuickStartAction = "reuse-continue" | "reuse-new" | "manual";
|
|
|
17
17
|
export interface BranchQuickStartOption {
|
|
18
18
|
toolId?: string | null;
|
|
19
19
|
toolLabel: string;
|
|
20
|
-
toolCategory?: "Codex" | "Claude" | "Gemini" | "Other";
|
|
20
|
+
toolCategory?: "Codex" | "Claude" | "Gemini" | "OpenCode" | "Other";
|
|
21
21
|
model?: string | null;
|
|
22
22
|
sessionId?: string | null;
|
|
23
23
|
inferenceLevel?: string | null;
|
|
@@ -58,7 +58,7 @@ type QuickStartItem = SelectItem & {
|
|
|
58
58
|
action: QuickStartAction;
|
|
59
59
|
groupStart?: boolean;
|
|
60
60
|
category: string;
|
|
61
|
-
categoryColor: "cyan" | "yellow" | "magenta" | "green" | "white";
|
|
61
|
+
categoryColor: "cyan" | "yellow" | "magenta" | "green" | "white"; // Includes green for OpenCode
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
/**
|
|
@@ -88,6 +88,7 @@ export function BranchQuickStartScreen({
|
|
|
88
88
|
"codex-cli": { label: "Codex", color: "cyan" },
|
|
89
89
|
"claude-code": { label: "Claude", color: "yellow" },
|
|
90
90
|
"gemini-cli": { label: "Gemini", color: "magenta" },
|
|
91
|
+
opencode: { label: "OpenCode", color: "green" },
|
|
91
92
|
other: { label: "Other", color: "white" },
|
|
92
93
|
} as const;
|
|
93
94
|
|
|
@@ -101,6 +102,8 @@ export function BranchQuickStartScreen({
|
|
|
101
102
|
return CATEGORY_META["claude-code"];
|
|
102
103
|
case "gemini-cli":
|
|
103
104
|
return CATEGORY_META["gemini-cli"];
|
|
105
|
+
case "opencode":
|
|
106
|
+
return CATEGORY_META["opencode"];
|
|
104
107
|
default:
|
|
105
108
|
return CATEGORY_META.other;
|
|
106
109
|
}
|
|
@@ -108,7 +111,7 @@ export function BranchQuickStartScreen({
|
|
|
108
111
|
|
|
109
112
|
const items: QuickStartItem[] = previousOptions.length
|
|
110
113
|
? (() => {
|
|
111
|
-
const order = ["Claude", "Codex", "Gemini", "Other"];
|
|
114
|
+
const order = ["Claude", "Codex", "Gemini", "OpenCode", "Other"];
|
|
112
115
|
const sorted = [...previousOptions].sort((a, b) => {
|
|
113
116
|
const ca = resolveCategory(a.toolId).label;
|
|
114
117
|
const cb = resolveCategory(b.toolId).label;
|