@akiojin/gwt 4.8.0 → 4.9.1
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 +19 -35
- 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 +8 -8
- package/dist/cli/ui/components/App.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.js +3 -1
- package/dist/cli/ui/components/screens/BranchListScreen.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 +23 -0
- package/dist/config/builtin-coding-agents.d.ts.map +1 -0
- package/dist/config/{builtin-tools.js → builtin-coding-agents.js} +6 -6
- package/dist/config/builtin-coding-agents.js.map +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -7
- package/dist/config/index.js.map +1 -1
- package/dist/config/profiles.d.ts +2 -2
- package/dist/config/profiles.d.ts.map +1 -1
- package/dist/config/profiles.js +4 -7
- package/dist/config/profiles.js.map +1 -1
- package/dist/config/tools.d.ts +17 -17
- package/dist/config/tools.d.ts.map +1 -1
- package/dist/config/tools.js +84 -121
- 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 +11 -0
- package/dist/utils/command.d.ts.map +1 -1
- package/dist/utils/command.js +33 -0
- package/dist/utils/command.js.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 +44 -40
- 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 +22 -20
- package/src/cli/ui/components/screens/BranchListScreen.tsx +4 -2
- 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} +9 -9
- package/src/config/index.ts +3 -7
- package/src/config/profiles.ts +4 -7
- package/src/config/tools.ts +107 -148
- 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 +37 -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 +57 -51
- 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
- package/src/index.ts.backup +0 -1543
package/src/config/tools.ts
CHANGED
|
@@ -1,116 +1,66 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* コーディングエージェント設定管理
|
|
3
3
|
*
|
|
4
4
|
* ~/.gwt/tools.jsonから設定を読み込み、
|
|
5
|
-
*
|
|
5
|
+
* ビルトインエージェントと統合して管理します。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
9
|
import path from "node:path";
|
|
10
|
-
import {
|
|
11
|
-
readFile,
|
|
12
|
-
writeFile,
|
|
13
|
-
mkdir,
|
|
14
|
-
rename,
|
|
15
|
-
access,
|
|
16
|
-
cp,
|
|
17
|
-
} from "node:fs/promises";
|
|
10
|
+
import { readFile, writeFile, mkdir, rename } from "node:fs/promises";
|
|
18
11
|
import type {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
CodingAgentsConfig,
|
|
13
|
+
CodingAgent,
|
|
14
|
+
CodingAgentConfig,
|
|
22
15
|
} from "../types/tools.js";
|
|
23
|
-
import {
|
|
16
|
+
import { BUILTIN_CODING_AGENTS } from "./builtin-coding-agents.js";
|
|
24
17
|
import { createLogger } from "../logging/logger.js";
|
|
25
18
|
import { resolveProfileEnv } from "./profiles.js";
|
|
26
19
|
|
|
27
20
|
const logger = createLogger({ category: "config" });
|
|
28
21
|
|
|
29
22
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
23
|
+
* コーディングエージェント設定ファイルのパス
|
|
24
|
+
* 環境変数 GWT_HOME が設定されている場合はそれを使用、それ以外はホームディレクトリ
|
|
32
25
|
*/
|
|
33
26
|
export const WORKTREE_HOME =
|
|
34
27
|
process.env.GWT_HOME && process.env.GWT_HOME.trim().length > 0
|
|
35
28
|
? process.env.GWT_HOME
|
|
36
|
-
:
|
|
37
|
-
process.env.CLAUDE_WORKTREE_HOME.trim().length > 0
|
|
38
|
-
? process.env.CLAUDE_WORKTREE_HOME
|
|
39
|
-
: homedir();
|
|
29
|
+
: homedir();
|
|
40
30
|
|
|
41
|
-
const LEGACY_CONFIG_DIR = path.join(homedir(), ".claude-worktree");
|
|
42
31
|
export const CONFIG_DIR = path.join(WORKTREE_HOME, ".gwt");
|
|
43
32
|
export const TOOLS_CONFIG_PATH = path.join(CONFIG_DIR, "tools.json");
|
|
44
33
|
const TEMP_CONFIG_PATH = `${TOOLS_CONFIG_PATH}.tmp`;
|
|
45
34
|
|
|
46
|
-
|
|
47
|
-
* レガシー設定ディレクトリから新しいディレクトリへ移行
|
|
48
|
-
*/
|
|
49
|
-
async function migrateLegacyConfig(): Promise<void> {
|
|
50
|
-
try {
|
|
51
|
-
// 新しいディレクトリが既に存在する場合は移行不要
|
|
52
|
-
try {
|
|
53
|
-
await access(CONFIG_DIR);
|
|
54
|
-
return;
|
|
55
|
-
} catch {
|
|
56
|
-
// 新しいディレクトリが存在しない場合は続行
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// レガシーディレクトリの存在を確認
|
|
60
|
-
try {
|
|
61
|
-
await access(LEGACY_CONFIG_DIR);
|
|
62
|
-
} catch {
|
|
63
|
-
// レガシーディレクトリも存在しない場合は移行不要
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// レガシーディレクトリを新しいディレクトリにコピー
|
|
68
|
-
await mkdir(path.dirname(CONFIG_DIR), { recursive: true });
|
|
69
|
-
await cp(LEGACY_CONFIG_DIR, CONFIG_DIR, { recursive: true });
|
|
70
|
-
logger.info(
|
|
71
|
-
{ from: LEGACY_CONFIG_DIR, to: CONFIG_DIR },
|
|
72
|
-
"Legacy config migrated",
|
|
73
|
-
);
|
|
74
|
-
console.log(
|
|
75
|
-
`✅ Migrated configuration from ${LEGACY_CONFIG_DIR} to ${CONFIG_DIR}`,
|
|
76
|
-
);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
// 移行に失敗しても継続(エラーログのみ)
|
|
79
|
-
if (process.env.DEBUG) {
|
|
80
|
-
console.error("Failed to migrate legacy config:", error);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const DEFAULT_CONFIG: ToolsConfig = {
|
|
35
|
+
const DEFAULT_CONFIG: CodingAgentsConfig = {
|
|
86
36
|
version: "1.0.0",
|
|
87
37
|
env: {},
|
|
88
|
-
|
|
38
|
+
customCodingAgents: [],
|
|
89
39
|
};
|
|
90
40
|
|
|
91
41
|
/**
|
|
92
|
-
*
|
|
42
|
+
* コーディングエージェント設定を読み込む
|
|
93
43
|
*
|
|
94
44
|
* ~/.gwt/tools.jsonから設定を読み込みます。
|
|
95
45
|
* ファイルが存在しない場合は空配列を返します。
|
|
96
46
|
*
|
|
97
|
-
* @returns
|
|
47
|
+
* @returns CodingAgentsConfig
|
|
98
48
|
* @throws JSON構文エラー時
|
|
99
49
|
*/
|
|
100
|
-
export async function
|
|
101
|
-
// 最初の呼び出し時にレガシー設定の移行を試行
|
|
102
|
-
await migrateLegacyConfig();
|
|
103
|
-
|
|
50
|
+
export async function loadCodingAgentsConfig(): Promise<CodingAgentsConfig> {
|
|
104
51
|
try {
|
|
105
52
|
const content = await readFile(TOOLS_CONFIG_PATH, "utf-8");
|
|
106
|
-
const config = JSON.parse(content) as
|
|
53
|
+
const config = JSON.parse(content) as CodingAgentsConfig;
|
|
107
54
|
|
|
108
55
|
// 検証
|
|
109
|
-
|
|
56
|
+
validateCodingAgentsConfig(config);
|
|
110
57
|
|
|
111
58
|
logger.debug(
|
|
112
|
-
{
|
|
113
|
-
|
|
59
|
+
{
|
|
60
|
+
path: TOOLS_CONFIG_PATH,
|
|
61
|
+
agentCount: config.customCodingAgents.length,
|
|
62
|
+
},
|
|
63
|
+
"Coding agents config loaded",
|
|
114
64
|
);
|
|
115
65
|
|
|
116
66
|
return {
|
|
@@ -122,7 +72,7 @@ export async function loadToolsConfig(): Promise<ToolsConfig> {
|
|
|
122
72
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
123
73
|
logger.debug(
|
|
124
74
|
{ path: TOOLS_CONFIG_PATH },
|
|
125
|
-
"
|
|
75
|
+
"Coding agents config not found, using defaults",
|
|
126
76
|
);
|
|
127
77
|
return { ...DEFAULT_CONFIG };
|
|
128
78
|
}
|
|
@@ -131,7 +81,7 @@ export async function loadToolsConfig(): Promise<ToolsConfig> {
|
|
|
131
81
|
if (error instanceof SyntaxError) {
|
|
132
82
|
logger.error(
|
|
133
83
|
{ path: TOOLS_CONFIG_PATH, error: error.message },
|
|
134
|
-
"
|
|
84
|
+
"Coding agents config parse error",
|
|
135
85
|
);
|
|
136
86
|
throw new Error(
|
|
137
87
|
`Failed to parse tools.json: ${error.message}\n` +
|
|
@@ -145,20 +95,20 @@ export async function loadToolsConfig(): Promise<ToolsConfig> {
|
|
|
145
95
|
}
|
|
146
96
|
|
|
147
97
|
/**
|
|
148
|
-
*
|
|
98
|
+
* CodingAgentsConfig全体を検証
|
|
149
99
|
*
|
|
150
100
|
* @param config - 検証対象の設定
|
|
151
101
|
* @throws 検証エラー時
|
|
152
102
|
*/
|
|
153
|
-
function
|
|
103
|
+
function validateCodingAgentsConfig(config: CodingAgentsConfig): void {
|
|
154
104
|
// versionフィールドの検証
|
|
155
105
|
if (!config.version || typeof config.version !== "string") {
|
|
156
106
|
throw new Error("version field is required and must be a string");
|
|
157
107
|
}
|
|
158
108
|
|
|
159
|
-
//
|
|
160
|
-
if (!Array.isArray(config.
|
|
161
|
-
throw new Error("
|
|
109
|
+
// customCodingAgentsフィールドの検証
|
|
110
|
+
if (!Array.isArray(config.customCodingAgents)) {
|
|
111
|
+
throw new Error("customCodingAgents field must be an array");
|
|
162
112
|
}
|
|
163
113
|
|
|
164
114
|
if (config.env && typeof config.env !== "object") {
|
|
@@ -176,40 +126,42 @@ function validateToolsConfig(config: ToolsConfig): void {
|
|
|
176
126
|
}
|
|
177
127
|
}
|
|
178
128
|
|
|
179
|
-
//
|
|
129
|
+
// 各エージェントの検証
|
|
180
130
|
const seenIds = new Set<string>();
|
|
181
|
-
for (const
|
|
182
|
-
|
|
131
|
+
for (const agent of config.customCodingAgents) {
|
|
132
|
+
validateCodingAgent(agent);
|
|
183
133
|
|
|
184
134
|
// ID重複チェック
|
|
185
|
-
if (seenIds.has(
|
|
135
|
+
if (seenIds.has(agent.id)) {
|
|
186
136
|
throw new Error(
|
|
187
|
-
`Duplicate
|
|
188
|
-
`Each
|
|
137
|
+
`Duplicate agent ID found: "${agent.id}"\n` +
|
|
138
|
+
`Each agent must have a unique ID in ${TOOLS_CONFIG_PATH}`,
|
|
189
139
|
);
|
|
190
140
|
}
|
|
191
|
-
seenIds.add(
|
|
141
|
+
seenIds.add(agent.id);
|
|
192
142
|
|
|
193
|
-
//
|
|
194
|
-
const builtinIds =
|
|
195
|
-
if (builtinIds.includes(
|
|
143
|
+
// ビルトインエージェントとのID重複チェック
|
|
144
|
+
const builtinIds = BUILTIN_CODING_AGENTS.map((t) => t.id);
|
|
145
|
+
if (builtinIds.includes(agent.id)) {
|
|
196
146
|
throw new Error(
|
|
197
|
-
`
|
|
198
|
-
`Builtin
|
|
147
|
+
`Agent ID "${agent.id}" conflicts with builtin agent\n` +
|
|
148
|
+
`Builtin agent IDs: ${builtinIds.join(", ")}`,
|
|
199
149
|
);
|
|
200
150
|
}
|
|
201
151
|
}
|
|
202
152
|
}
|
|
203
153
|
|
|
204
|
-
export async function
|
|
205
|
-
|
|
154
|
+
export async function saveCodingAgentsConfig(
|
|
155
|
+
config: CodingAgentsConfig,
|
|
156
|
+
): Promise<void> {
|
|
157
|
+
const normalized: CodingAgentsConfig = {
|
|
206
158
|
version: config.version,
|
|
207
159
|
updatedAt: config.updatedAt ?? new Date().toISOString(),
|
|
208
160
|
env: config.env ?? {},
|
|
209
|
-
|
|
161
|
+
customCodingAgents: config.customCodingAgents,
|
|
210
162
|
};
|
|
211
163
|
|
|
212
|
-
|
|
164
|
+
validateCodingAgentsConfig(normalized);
|
|
213
165
|
|
|
214
166
|
await mkdir(CONFIG_DIR, { recursive: true });
|
|
215
167
|
const payload = JSON.stringify(normalized, null, 2);
|
|
@@ -220,7 +172,7 @@ export async function saveToolsConfig(config: ToolsConfig): Promise<void> {
|
|
|
220
172
|
/**
|
|
221
173
|
* 共有環境変数を取得
|
|
222
174
|
*
|
|
223
|
-
*
|
|
175
|
+
* コーディングエージェント起動時に適用される環境変数を返します。
|
|
224
176
|
* マージ優先順位(後勝ち):
|
|
225
177
|
* 1. tools.json の env フィールド
|
|
226
178
|
* 2. profiles.yaml のアクティブプロファイル
|
|
@@ -229,7 +181,7 @@ export async function saveToolsConfig(config: ToolsConfig): Promise<void> {
|
|
|
229
181
|
*/
|
|
230
182
|
export async function getSharedEnvironment(): Promise<Record<string, string>> {
|
|
231
183
|
const [config, profileEnv] = await Promise.all([
|
|
232
|
-
|
|
184
|
+
loadCodingAgentsConfig(),
|
|
233
185
|
resolveProfileEnv(),
|
|
234
186
|
]);
|
|
235
187
|
|
|
@@ -240,104 +192,111 @@ export async function getSharedEnvironment(): Promise<Record<string, string>> {
|
|
|
240
192
|
}
|
|
241
193
|
|
|
242
194
|
/**
|
|
243
|
-
*
|
|
195
|
+
* CodingAgent単体を検証
|
|
244
196
|
*
|
|
245
|
-
* @param
|
|
197
|
+
* @param agent - 検証対象のエージェント
|
|
246
198
|
* @throws 検証エラー時
|
|
247
199
|
*/
|
|
248
|
-
function
|
|
200
|
+
function validateCodingAgent(agent: unknown): asserts agent is CodingAgent {
|
|
249
201
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
250
|
-
const
|
|
202
|
+
const a = agent as any;
|
|
251
203
|
|
|
252
204
|
// 必須フィールドの存在チェック
|
|
253
205
|
const requiredFields = ["id", "displayName", "type", "command", "modeArgs"];
|
|
254
206
|
for (const field of requiredFields) {
|
|
255
|
-
if (!
|
|
207
|
+
if (!a[field]) {
|
|
256
208
|
throw new Error(
|
|
257
|
-
`Required field "${field}" is missing in
|
|
209
|
+
`Required field "${field}" is missing in agent configuration`,
|
|
258
210
|
);
|
|
259
211
|
}
|
|
260
212
|
}
|
|
261
213
|
|
|
262
214
|
// id形式の検証(小文字英数字とハイフンのみ)
|
|
263
|
-
if (!/^[a-z0-9-]+$/.test(
|
|
215
|
+
if (!/^[a-z0-9-]+$/.test(a.id)) {
|
|
264
216
|
throw new Error(
|
|
265
|
-
`Invalid
|
|
266
|
-
`
|
|
217
|
+
`Invalid agent ID format: "${a.id}"\n` +
|
|
218
|
+
`Agent ID must contain only lowercase letters, numbers, and hyphens (pattern: ^[a-z0-9-]+$)`,
|
|
267
219
|
);
|
|
268
220
|
}
|
|
269
221
|
|
|
270
222
|
// typeフィールドの値検証
|
|
271
223
|
const validTypes = ["path", "bunx", "command"];
|
|
272
|
-
if (!validTypes.includes(
|
|
224
|
+
if (!validTypes.includes(a.type)) {
|
|
273
225
|
throw new Error(
|
|
274
|
-
`Invalid type: "${
|
|
226
|
+
`Invalid type: "${a.type}"\n` +
|
|
275
227
|
`Type must be one of: ${validTypes.join(", ")}`,
|
|
276
228
|
);
|
|
277
229
|
}
|
|
278
230
|
|
|
279
231
|
// type='path'の場合、commandが絶対パスであることを確認
|
|
280
|
-
if (
|
|
232
|
+
if (a.type === "path" && !path.isAbsolute(a.command)) {
|
|
281
233
|
throw new Error(
|
|
282
|
-
`For type="path", command must be an absolute path: "${
|
|
234
|
+
`For type="path", command must be an absolute path: "${a.command}"`,
|
|
283
235
|
);
|
|
284
236
|
}
|
|
285
237
|
|
|
286
238
|
// modeArgsの検証(少なくとも1つのモードが定義されている)
|
|
287
|
-
if (!
|
|
239
|
+
if (!a.modeArgs.normal && !a.modeArgs.continue && !a.modeArgs.resume) {
|
|
288
240
|
throw new Error(
|
|
289
|
-
`modeArgs must define at least one mode (normal, continue, or resume) for
|
|
241
|
+
`modeArgs must define at least one mode (normal, continue, or resume) for agent "${a.id}"`,
|
|
290
242
|
);
|
|
291
243
|
}
|
|
292
244
|
}
|
|
293
245
|
|
|
294
246
|
/**
|
|
295
|
-
* ID
|
|
247
|
+
* IDでコーディングエージェントを検索
|
|
296
248
|
*
|
|
297
|
-
* @param id -
|
|
298
|
-
* @returns
|
|
249
|
+
* @param id - エージェントID
|
|
250
|
+
* @returns エージェント設定(見つからない場合はundefined)
|
|
299
251
|
*/
|
|
300
|
-
export async function
|
|
252
|
+
export async function getCodingAgentById(
|
|
301
253
|
id: string,
|
|
302
|
-
): Promise<
|
|
303
|
-
//
|
|
304
|
-
const
|
|
305
|
-
if (
|
|
306
|
-
logger.debug({ id, found: true, isBuiltin: true }, "
|
|
307
|
-
return
|
|
254
|
+
): Promise<CodingAgent | undefined> {
|
|
255
|
+
// ビルトインエージェントから検索
|
|
256
|
+
const builtinAgent = BUILTIN_CODING_AGENTS.find((a) => a.id === id);
|
|
257
|
+
if (builtinAgent) {
|
|
258
|
+
logger.debug({ id, found: true, isBuiltin: true }, "Coding agent lookup");
|
|
259
|
+
return builtinAgent;
|
|
308
260
|
}
|
|
309
261
|
|
|
310
|
-
//
|
|
311
|
-
const config = await
|
|
312
|
-
const
|
|
313
|
-
logger.debug(
|
|
314
|
-
|
|
262
|
+
// カスタムエージェントから検索
|
|
263
|
+
const config = await loadCodingAgentsConfig();
|
|
264
|
+
const customAgent = config.customCodingAgents.find((a) => a.id === id);
|
|
265
|
+
logger.debug(
|
|
266
|
+
{ id, found: !!customAgent, isBuiltin: false },
|
|
267
|
+
"Coding agent lookup",
|
|
268
|
+
);
|
|
269
|
+
return customAgent;
|
|
315
270
|
}
|
|
316
271
|
|
|
317
272
|
/**
|
|
318
|
-
*
|
|
273
|
+
* すべてのコーディングエージェント(ビルトイン+カスタム)を取得
|
|
319
274
|
*
|
|
320
|
-
* @returns
|
|
275
|
+
* @returns CodingAgentConfigの配列
|
|
321
276
|
*/
|
|
322
|
-
export async function
|
|
323
|
-
const config = await
|
|
324
|
-
|
|
325
|
-
//
|
|
326
|
-
const builtinConfigs:
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
277
|
+
export async function getAllCodingAgents(): Promise<CodingAgentConfig[]> {
|
|
278
|
+
const config = await loadCodingAgentsConfig();
|
|
279
|
+
|
|
280
|
+
// ビルトインエージェントをCodingAgentConfig形式に変換
|
|
281
|
+
const builtinConfigs: CodingAgentConfig[] = BUILTIN_CODING_AGENTS.map(
|
|
282
|
+
(agent) => ({
|
|
283
|
+
id: agent.id,
|
|
284
|
+
displayName: agent.displayName,
|
|
285
|
+
...(agent.icon ? { icon: agent.icon } : {}),
|
|
286
|
+
isBuiltin: true,
|
|
287
|
+
}),
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
// カスタムエージェントをCodingAgentConfig形式に変換
|
|
291
|
+
const customConfigs: CodingAgentConfig[] = config.customCodingAgents.map(
|
|
292
|
+
(agent) => ({
|
|
293
|
+
id: agent.id,
|
|
294
|
+
displayName: agent.displayName,
|
|
295
|
+
...(agent.icon ? { icon: agent.icon } : {}),
|
|
296
|
+
isBuiltin: false,
|
|
297
|
+
customConfig: agent,
|
|
298
|
+
}),
|
|
299
|
+
);
|
|
341
300
|
|
|
342
301
|
// ビルトイン + カスタム の順で統合
|
|
343
302
|
return [...builtinConfigs, ...customConfigs];
|
package/src/index.ts
CHANGED
|
@@ -39,8 +39,8 @@ import {
|
|
|
39
39
|
waitForUserAcknowledgement,
|
|
40
40
|
} from "./utils/terminal.js";
|
|
41
41
|
import { createLogger } from "./logging/logger.js";
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
42
|
+
import { getCodingAgentById, getSharedEnvironment } from "./config/tools.js";
|
|
43
|
+
import { launchCodingAgent } from "./launcher.js";
|
|
44
44
|
import { saveSession, loadSession } from "./config/index.js";
|
|
45
45
|
import {
|
|
46
46
|
findLatestCodexSession,
|
|
@@ -543,24 +543,24 @@ export async function handleAIToolWorkflow(
|
|
|
543
543
|
);
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
-
// Get
|
|
547
|
-
const [
|
|
548
|
-
|
|
546
|
+
// Get coding agent definition and shared environment overrides
|
|
547
|
+
const [agentConfig, sharedEnv] = await Promise.all([
|
|
548
|
+
getCodingAgentById(tool),
|
|
549
549
|
getSharedEnvironment(),
|
|
550
550
|
]);
|
|
551
551
|
|
|
552
|
-
if (!
|
|
553
|
-
throw new Error(`
|
|
552
|
+
if (!agentConfig) {
|
|
553
|
+
throw new Error(`Coding agent not found: ${tool}`);
|
|
554
554
|
}
|
|
555
555
|
|
|
556
|
-
// Save selection immediately (including history) so "last
|
|
557
|
-
// even if the
|
|
558
|
-
// FR-042: Record timestamp to session history immediately on
|
|
556
|
+
// Save selection immediately (including history) so "last agent" is reflected
|
|
557
|
+
// even if the agent is interrupted or killed mid-run (e.g., Ctrl+C).
|
|
558
|
+
// FR-042: Record timestamp to session history immediately on agent start.
|
|
559
559
|
await saveSession({
|
|
560
560
|
lastWorktreePath: worktreePath,
|
|
561
561
|
lastBranch: branch,
|
|
562
562
|
lastUsedTool: tool,
|
|
563
|
-
toolLabel:
|
|
563
|
+
toolLabel: agentConfig.displayName ?? tool,
|
|
564
564
|
mode,
|
|
565
565
|
model: normalizedModel ?? null,
|
|
566
566
|
reasoningLevel: inferenceLevel ?? null,
|
|
@@ -607,7 +607,7 @@ export async function handleAIToolWorkflow(
|
|
|
607
607
|
lastWorktreePath: worktreePath,
|
|
608
608
|
lastBranch: branch,
|
|
609
609
|
lastUsedTool: tool,
|
|
610
|
-
toolLabel:
|
|
610
|
+
toolLabel: agentConfig.displayName ?? tool,
|
|
611
611
|
mode,
|
|
612
612
|
model: normalizedModel ?? null,
|
|
613
613
|
reasoningLevel: inferenceLevel ?? null,
|
|
@@ -622,9 +622,9 @@ export async function handleAIToolWorkflow(
|
|
|
622
622
|
}
|
|
623
623
|
}, SESSION_UPDATE_INTERVAL_MS);
|
|
624
624
|
|
|
625
|
-
// Launch selected
|
|
626
|
-
// Builtin
|
|
627
|
-
// Custom
|
|
625
|
+
// Launch selected coding agent
|
|
626
|
+
// Builtin agents use their dedicated launch functions
|
|
627
|
+
// Custom agents use the generic launchCodingAgent function
|
|
628
628
|
let launchResult: { sessionId?: string | null } | void;
|
|
629
629
|
try {
|
|
630
630
|
if (tool === "claude-code") {
|
|
@@ -701,9 +701,9 @@ export async function handleAIToolWorkflow(
|
|
|
701
701
|
}
|
|
702
702
|
launchResult = await launchGeminiCLI(worktreePath, launchOptions);
|
|
703
703
|
} else {
|
|
704
|
-
// Custom
|
|
705
|
-
printInfo(`Launching custom
|
|
706
|
-
launchResult = await
|
|
704
|
+
// Custom coding agent
|
|
705
|
+
printInfo(`Launching custom agent: ${agentConfig.displayName}`);
|
|
706
|
+
launchResult = await launchCodingAgent(agentConfig, {
|
|
707
707
|
mode:
|
|
708
708
|
mode === "resume"
|
|
709
709
|
? "resume"
|
|
@@ -786,7 +786,7 @@ export async function handleAIToolWorkflow(
|
|
|
786
786
|
lastWorktreePath: worktreePath,
|
|
787
787
|
lastBranch: branch,
|
|
788
788
|
lastUsedTool: tool,
|
|
789
|
-
toolLabel:
|
|
789
|
+
toolLabel: agentConfig.displayName ?? tool,
|
|
790
790
|
mode,
|
|
791
791
|
model: normalizedModel ?? null,
|
|
792
792
|
reasoningLevel: inferenceLevel ?? null,
|
package/src/launcher.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* コーディングエージェント起動機能
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* コーディングエージェントの起動処理を管理します。
|
|
5
5
|
* 3つの実行タイプ(path, bunx, command)をサポートします。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { execa } from "execa";
|
|
9
|
-
import type {
|
|
9
|
+
import type { CodingAgent, CodingAgentLaunchOptions } from "./types/tools.js";
|
|
10
10
|
import { createLogger } from "./logging/logger.js";
|
|
11
11
|
|
|
12
12
|
const logger = createLogger({ category: "launcher" });
|
|
@@ -63,21 +63,24 @@ export async function resolveCommand(commandName: string): Promise<string> {
|
|
|
63
63
|
* defaultArgs + modeArgs[mode] + extraArgs の順で引数を結合します。
|
|
64
64
|
* 未定義のフィールドは空配列として扱います。
|
|
65
65
|
*
|
|
66
|
-
* @param
|
|
66
|
+
* @param agent - コーディングエージェント定義
|
|
67
67
|
* @param options - 起動オプション
|
|
68
68
|
* @returns 結合された引数配列
|
|
69
69
|
*/
|
|
70
|
-
function buildArgs(
|
|
70
|
+
function buildArgs(
|
|
71
|
+
agent: CodingAgent,
|
|
72
|
+
options: CodingAgentLaunchOptions,
|
|
73
|
+
): string[] {
|
|
71
74
|
const args: string[] = [];
|
|
72
75
|
|
|
73
76
|
// 1. defaultArgs
|
|
74
|
-
if (
|
|
75
|
-
args.push(...
|
|
77
|
+
if (agent.defaultArgs) {
|
|
78
|
+
args.push(...agent.defaultArgs);
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
// 2. modeArgs[mode]
|
|
79
82
|
const mode = options.mode || "normal";
|
|
80
|
-
const modeArgs =
|
|
83
|
+
const modeArgs = agent.modeArgs[mode];
|
|
81
84
|
if (modeArgs) {
|
|
82
85
|
args.push(...modeArgs);
|
|
83
86
|
}
|
|
@@ -88,32 +91,36 @@ function buildArgs(tool: CustomAITool, options: LaunchOptions): string[] {
|
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
logger.debug(
|
|
91
|
-
{
|
|
94
|
+
{
|
|
95
|
+
agentId: agent.id,
|
|
96
|
+
mode: options.mode ?? "normal",
|
|
97
|
+
argsCount: args.length,
|
|
98
|
+
},
|
|
92
99
|
"Args built",
|
|
93
100
|
);
|
|
94
101
|
return args;
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
/**
|
|
98
|
-
*
|
|
105
|
+
* コーディングエージェントを起動
|
|
99
106
|
*
|
|
100
|
-
*
|
|
101
|
-
* stdio: "inherit"
|
|
107
|
+
* エージェントの実行タイプ(path/bunx/command)に応じて適切な方法で起動します。
|
|
108
|
+
* stdio: "inherit" で起動するため、エージェントの入出力は親プロセスに継承されます。
|
|
102
109
|
*
|
|
103
|
-
* @param
|
|
110
|
+
* @param agent - コーディングエージェント定義
|
|
104
111
|
* @param options - 起動オプション
|
|
105
112
|
* @throws 起動に失敗した場合
|
|
106
113
|
*/
|
|
107
|
-
export async function
|
|
108
|
-
|
|
109
|
-
options:
|
|
114
|
+
export async function launchCodingAgent(
|
|
115
|
+
agent: CodingAgent,
|
|
116
|
+
options: CodingAgentLaunchOptions = {},
|
|
110
117
|
): Promise<void> {
|
|
111
|
-
const args = buildArgs(
|
|
118
|
+
const args = buildArgs(agent, options);
|
|
112
119
|
|
|
113
120
|
const env = {
|
|
114
121
|
...process.env,
|
|
115
122
|
...(options.sharedEnv ?? {}),
|
|
116
|
-
...(
|
|
123
|
+
...(agent.env ?? {}),
|
|
117
124
|
};
|
|
118
125
|
|
|
119
126
|
// execa共通オプション(cwdがundefinedの場合は含めない)
|
|
@@ -125,43 +132,43 @@ export async function launchCustomAITool(
|
|
|
125
132
|
|
|
126
133
|
logger.info(
|
|
127
134
|
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
command:
|
|
135
|
+
agentId: agent.id,
|
|
136
|
+
agentType: agent.type,
|
|
137
|
+
command: agent.command,
|
|
131
138
|
mode: options.mode ?? "normal",
|
|
132
139
|
},
|
|
133
|
-
"Launching
|
|
140
|
+
"Launching coding agent",
|
|
134
141
|
);
|
|
135
142
|
|
|
136
|
-
switch (
|
|
143
|
+
switch (agent.type) {
|
|
137
144
|
case "path": {
|
|
138
145
|
// 絶対パスで直接実行
|
|
139
|
-
await execa(
|
|
140
|
-
logger.info({
|
|
146
|
+
await execa(agent.command, args, execaOptions);
|
|
147
|
+
logger.info({ agentId: agent.id }, "Coding agent completed (path)");
|
|
141
148
|
break;
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
case "bunx": {
|
|
145
152
|
// bunx経由でパッケージ実行
|
|
146
153
|
// bunx [package] [args...]
|
|
147
|
-
await execa("bunx", [
|
|
148
|
-
logger.info({
|
|
154
|
+
await execa("bunx", [agent.command, ...args], execaOptions);
|
|
155
|
+
logger.info({ agentId: agent.id }, "Coding agent completed (bunx)");
|
|
149
156
|
break;
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
case "command": {
|
|
153
160
|
// PATH解決 → 実行
|
|
154
|
-
const resolvedPath = await resolveCommand(
|
|
161
|
+
const resolvedPath = await resolveCommand(agent.command);
|
|
155
162
|
await execa(resolvedPath, args, execaOptions);
|
|
156
|
-
logger.info({
|
|
163
|
+
logger.info({ agentId: agent.id }, "Coding agent completed (command)");
|
|
157
164
|
break;
|
|
158
165
|
}
|
|
159
166
|
|
|
160
167
|
default: {
|
|
161
168
|
// TypeScriptの型チェックで到達不可能だが、実行時の安全性のため
|
|
162
|
-
const exhaustiveCheck: never =
|
|
169
|
+
const exhaustiveCheck: never = agent.type;
|
|
163
170
|
throw new Error(
|
|
164
|
-
`Unknown
|
|
171
|
+
`Unknown agent execution type: ${exhaustiveCheck as string}`,
|
|
165
172
|
);
|
|
166
173
|
}
|
|
167
174
|
}
|