@akiojin/gwt 4.9.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 +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 +8 -8
- package/dist/cli/ui/components/App.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/tools.d.ts +16 -16
- package/dist/config/tools.d.ts.map +1 -1
- package/dist/config/tools.js +81 -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/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 +22 -20
- 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/tools.ts +104 -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/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,15 +1,15 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useState } from "react";
|
|
2
2
|
import { Link } from "react-router-dom";
|
|
3
3
|
import type {
|
|
4
|
-
|
|
4
|
+
ApiCodingAgent,
|
|
5
5
|
EnvironmentVariable,
|
|
6
6
|
} from "../../../../types/api.js";
|
|
7
7
|
import { useConfig, useUpdateConfig } from "../hooks/useConfig";
|
|
8
|
-
import {
|
|
8
|
+
import { CustomCodingAgentList } from "../components/CustomCodingAgentList";
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
type
|
|
12
|
-
} from "../components/
|
|
10
|
+
CustomCodingAgentForm,
|
|
11
|
+
type CustomCodingAgentFormValue,
|
|
12
|
+
} from "../components/CustomCodingAgentForm";
|
|
13
13
|
import {
|
|
14
14
|
EnvironmentEditor,
|
|
15
15
|
type EnvEntry,
|
|
@@ -31,8 +31,8 @@ const ENV_VALUE_MAX = 500;
|
|
|
31
31
|
export function ConfigPage() {
|
|
32
32
|
const { data, isLoading, error } = useConfig();
|
|
33
33
|
const updateConfig = useUpdateConfig();
|
|
34
|
-
const [
|
|
35
|
-
const [
|
|
34
|
+
const [agents, setAgents] = useState<ApiCodingAgent[]>([]);
|
|
35
|
+
const [editingAgent, setEditingAgent] = useState<ApiCodingAgent | undefined>(
|
|
36
36
|
undefined,
|
|
37
37
|
);
|
|
38
38
|
const [banner, setBanner] = useState<BannerState | null>(null);
|
|
@@ -40,36 +40,36 @@ export function ConfigPage() {
|
|
|
40
40
|
const [envEntries, setEnvEntries] = useState<EnvEntry[]>([]);
|
|
41
41
|
|
|
42
42
|
useEffect(() => {
|
|
43
|
-
if (data?.
|
|
43
|
+
if (data?.codingAgents) setAgents(data.codingAgents);
|
|
44
44
|
if (data) setEnvEntries(entriesFromVariables(data.env));
|
|
45
45
|
}, [data]);
|
|
46
46
|
|
|
47
|
-
const
|
|
48
|
-
return [...
|
|
47
|
+
const sortedAgents = useMemo(() => {
|
|
48
|
+
return [...agents].sort((a, b) =>
|
|
49
49
|
a.displayName.localeCompare(b.displayName, "ja"),
|
|
50
50
|
);
|
|
51
|
-
}, [
|
|
51
|
+
}, [agents]);
|
|
52
52
|
|
|
53
|
-
const handleEdit = (
|
|
54
|
-
|
|
53
|
+
const handleEdit = (agent: ApiCodingAgent) => {
|
|
54
|
+
setEditingAgent(agent);
|
|
55
55
|
setIsCreating(false);
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
const handleDelete = (
|
|
59
|
-
if (!window.confirm(`${
|
|
60
|
-
const next =
|
|
61
|
-
persistConfig(next, envEntries, `${
|
|
58
|
+
const handleDelete = (agent: ApiCodingAgent) => {
|
|
59
|
+
if (!window.confirm(`${agent.displayName} を削除しますか?`)) return;
|
|
60
|
+
const next = agents.filter((a) => a.id !== agent.id);
|
|
61
|
+
persistConfig(next, envEntries, `${agent.displayName} を削除しました。`);
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
const handleCreate = () => {
|
|
65
|
-
|
|
65
|
+
setEditingAgent(undefined);
|
|
66
66
|
setIsCreating(true);
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
const handleFormSubmit = (value:
|
|
69
|
+
const handleFormSubmit = (value: CustomCodingAgentFormValue) => {
|
|
70
70
|
const now = new Date().toISOString();
|
|
71
|
-
const existing =
|
|
72
|
-
const
|
|
71
|
+
const existing = agents.find((agent) => agent.id === value.id);
|
|
72
|
+
const nextAgent: ApiCodingAgent = {
|
|
73
73
|
id: value.id,
|
|
74
74
|
displayName: value.displayName,
|
|
75
75
|
icon: value.icon ?? null,
|
|
@@ -89,21 +89,21 @@ export function ConfigPage() {
|
|
|
89
89
|
};
|
|
90
90
|
|
|
91
91
|
const nextList = existing
|
|
92
|
-
?
|
|
93
|
-
: [...
|
|
92
|
+
? agents.map((agent) => (agent.id === nextAgent.id ? nextAgent : agent))
|
|
93
|
+
: [...agents, nextAgent];
|
|
94
94
|
|
|
95
95
|
persistConfig(
|
|
96
96
|
nextList,
|
|
97
97
|
envEntries,
|
|
98
|
-
`${
|
|
98
|
+
`${nextAgent.displayName} を保存しました。`,
|
|
99
99
|
);
|
|
100
100
|
};
|
|
101
101
|
|
|
102
102
|
const persistConfig = (
|
|
103
|
-
|
|
103
|
+
nextAgents: ApiCodingAgent[],
|
|
104
104
|
nextEnvEntries: EnvEntry[],
|
|
105
105
|
successMessage: string,
|
|
106
|
-
options?: {
|
|
106
|
+
options?: { resetForm?: boolean },
|
|
107
107
|
) => {
|
|
108
108
|
let envPayload: EnvironmentVariable[];
|
|
109
109
|
try {
|
|
@@ -116,13 +116,17 @@ export function ConfigPage() {
|
|
|
116
116
|
|
|
117
117
|
const nextVersion = data?.version ?? "1.0.0";
|
|
118
118
|
updateConfig
|
|
119
|
-
.mutateAsync({
|
|
119
|
+
.mutateAsync({
|
|
120
|
+
version: nextVersion,
|
|
121
|
+
codingAgents: nextAgents,
|
|
122
|
+
env: envPayload,
|
|
123
|
+
})
|
|
120
124
|
.then((response) => {
|
|
121
|
-
|
|
125
|
+
setAgents(response.codingAgents);
|
|
122
126
|
setEnvEntries(entriesFromVariables(response.env));
|
|
123
127
|
setBanner({ type: "success", message: successMessage });
|
|
124
|
-
if (options?.
|
|
125
|
-
|
|
128
|
+
if (options?.resetForm ?? true) {
|
|
129
|
+
setEditingAgent(undefined);
|
|
126
130
|
setIsCreating(false);
|
|
127
131
|
}
|
|
128
132
|
})
|
|
@@ -154,15 +158,15 @@ export function ConfigPage() {
|
|
|
154
158
|
const handleEnvRemove = (id: string) =>
|
|
155
159
|
setEnvEntries((prev) => prev.filter((e) => e.id !== id));
|
|
156
160
|
const handleEnvSave = () =>
|
|
157
|
-
persistConfig(
|
|
158
|
-
|
|
161
|
+
persistConfig(agents, envEntries, "環境変数を保存しました。", {
|
|
162
|
+
resetForm: false,
|
|
159
163
|
});
|
|
160
164
|
const handleCancel = () => {
|
|
161
|
-
|
|
165
|
+
setEditingAgent(undefined);
|
|
162
166
|
setIsCreating(false);
|
|
163
167
|
};
|
|
164
168
|
|
|
165
|
-
const
|
|
169
|
+
const activeFormAgent = isCreating ? undefined : editingAgent;
|
|
166
170
|
|
|
167
171
|
// Loading state
|
|
168
172
|
if (isLoading) {
|
|
@@ -170,7 +174,7 @@ export function ConfigPage() {
|
|
|
170
174
|
<div className="min-h-screen bg-background">
|
|
171
175
|
<PageHeader
|
|
172
176
|
eyebrow="CONFIGURATION"
|
|
173
|
-
title="
|
|
177
|
+
title="Custom Coding Agent"
|
|
174
178
|
subtitle="読み込み中..."
|
|
175
179
|
/>
|
|
176
180
|
<main className="mx-auto max-w-7xl px-6 py-8">
|
|
@@ -207,15 +211,15 @@ export function ConfigPage() {
|
|
|
207
211
|
<div className="min-h-screen bg-background">
|
|
208
212
|
<PageHeader
|
|
209
213
|
eyebrow="CONFIGURATION"
|
|
210
|
-
title="
|
|
211
|
-
subtitle="tools.json を編集して、独自の
|
|
214
|
+
title="Custom Coding Agent"
|
|
215
|
+
subtitle="tools.json を編集して、独自の Coding Agent を CLI / Web UI 両方から利用できます。"
|
|
212
216
|
>
|
|
213
217
|
<div className="mt-4 flex flex-wrap gap-2">
|
|
214
218
|
<Button variant="ghost" size="sm" asChild>
|
|
215
219
|
<Link to="/">← ブランチ一覧</Link>
|
|
216
220
|
</Button>
|
|
217
221
|
<Button variant="secondary" onClick={handleCreate}>
|
|
218
|
-
|
|
222
|
+
Coding Agent を追加
|
|
219
223
|
</Button>
|
|
220
224
|
</div>
|
|
221
225
|
</PageHeader>
|
|
@@ -251,8 +255,8 @@ export function ConfigPage() {
|
|
|
251
255
|
</p>
|
|
252
256
|
<h3 className="mt-1 text-lg font-semibold">共有環境変数</h3>
|
|
253
257
|
<p className="mt-2 text-sm text-muted-foreground">
|
|
254
|
-
Web UI で起動する
|
|
255
|
-
|
|
258
|
+
Web UI で起動する Coding Agent
|
|
259
|
+
はここに定義された環境変数を自動的に引き継ぎます。
|
|
256
260
|
</p>
|
|
257
261
|
</CardHeader>
|
|
258
262
|
<CardContent>
|
|
@@ -267,33 +271,35 @@ export function ConfigPage() {
|
|
|
267
271
|
</CardContent>
|
|
268
272
|
</Card>
|
|
269
273
|
|
|
270
|
-
{/*
|
|
274
|
+
{/* Coding Agent List */}
|
|
271
275
|
<Card>
|
|
272
276
|
<CardHeader className="pb-3">
|
|
273
277
|
<p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
|
|
274
|
-
Registered
|
|
278
|
+
Registered Coding Agents
|
|
275
279
|
</p>
|
|
276
|
-
<h3 className="mt-1 text-lg font-semibold"
|
|
280
|
+
<h3 className="mt-1 text-lg font-semibold">
|
|
281
|
+
登録済み Coding Agent
|
|
282
|
+
</h3>
|
|
277
283
|
<p className="mt-2 text-sm text-muted-foreground">
|
|
278
284
|
CLI と Web UI は同じ設定を参照します。更新すると ~/.gwt/tools.json
|
|
279
285
|
に保存されます。
|
|
280
286
|
</p>
|
|
281
287
|
</CardHeader>
|
|
282
288
|
<CardContent>
|
|
283
|
-
<
|
|
284
|
-
|
|
289
|
+
<CustomCodingAgentList
|
|
290
|
+
agents={sortedAgents}
|
|
285
291
|
onEdit={handleEdit}
|
|
286
292
|
onDelete={handleDelete}
|
|
287
293
|
/>
|
|
288
294
|
</CardContent>
|
|
289
295
|
</Card>
|
|
290
296
|
|
|
291
|
-
{/*
|
|
292
|
-
{(isCreating ||
|
|
297
|
+
{/* Coding Agent Form */}
|
|
298
|
+
{(isCreating || editingAgent) && (
|
|
293
299
|
<Card>
|
|
294
300
|
<CardContent className="pt-6">
|
|
295
|
-
<
|
|
296
|
-
{...(
|
|
301
|
+
<CustomCodingAgentForm
|
|
302
|
+
{...(activeFormAgent ? { initialValue: activeFormAgent } : {})}
|
|
297
303
|
onSubmit={handleFormSubmit}
|
|
298
304
|
onCancel={handleCancel}
|
|
299
305
|
isSaving={updateConfig.isPending}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
loadCodingAgentsConfig,
|
|
3
|
+
saveCodingAgentsConfig,
|
|
4
|
+
} from "../../../config/tools.js";
|
|
2
5
|
import { recordEnvHistory } from "../../../config/env-history.js";
|
|
3
6
|
import type { EnvironmentHistoryEntry } from "../../../types/api.js";
|
|
4
7
|
import { createLogger } from "../../../logging/logger.js";
|
|
@@ -18,7 +21,7 @@ const IMPORTABLE_KEYS = [
|
|
|
18
21
|
const importedKeySet = new Set<string>();
|
|
19
22
|
|
|
20
23
|
export async function importOsEnvIntoSharedConfig(): Promise<string[]> {
|
|
21
|
-
const config = await
|
|
24
|
+
const config = await loadCodingAgentsConfig();
|
|
22
25
|
const sharedEnv = { ...(config.env ?? {}) };
|
|
23
26
|
const importedKeys: string[] = [];
|
|
24
27
|
|
|
@@ -36,7 +39,7 @@ export async function importOsEnvIntoSharedConfig(): Promise<string[]> {
|
|
|
36
39
|
return [];
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
await
|
|
42
|
+
await saveCodingAgentsConfig({
|
|
40
43
|
...config,
|
|
41
44
|
env: sharedEnv,
|
|
42
45
|
});
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PTY Manager
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* コーディングエージェントセッションの疑似端末(PTY)を管理します。
|
|
5
5
|
* node-ptyを使用してプロセスをスポーンし、WebSocketを通じて入出力を中継します。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import * as pty from "node-pty";
|
|
9
9
|
import type { IPty } from "node-pty";
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
|
-
import type {
|
|
11
|
+
import type { CodingAgentSession } from "../../../types/api.js";
|
|
12
12
|
import {
|
|
13
13
|
resolveClaudeCommand,
|
|
14
14
|
resolveCodexCommand,
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
resolveCodingAgentCommand,
|
|
16
|
+
CodingAgentResolutionError,
|
|
17
17
|
type ResolvedCommand,
|
|
18
|
-
} from "../../../services/
|
|
19
|
-
import {
|
|
18
|
+
} from "../../../services/codingAgentResolver.js";
|
|
19
|
+
import { loadCodingAgentsConfig } from "../../../config/tools.js";
|
|
20
20
|
import { createLogger } from "../../../logging/logger.js";
|
|
21
21
|
|
|
22
22
|
const logger = createLogger({ category: "pty" });
|
|
23
23
|
|
|
24
24
|
export interface PTYInstance {
|
|
25
25
|
ptyProcess: IPty;
|
|
26
|
-
session:
|
|
26
|
+
session: CodingAgentSession;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -48,7 +48,7 @@ export class PTYManager {
|
|
|
48
48
|
extraArgs?: string[];
|
|
49
49
|
customToolId?: string | null;
|
|
50
50
|
} = {},
|
|
51
|
-
): Promise<{ sessionId: string; session:
|
|
51
|
+
): Promise<{ sessionId: string; session: CodingAgentSession }> {
|
|
52
52
|
const cols = options.cols ?? 80;
|
|
53
53
|
const rows = options.rows ?? 24;
|
|
54
54
|
const toolName = options.toolName ?? null;
|
|
@@ -136,10 +136,10 @@ export class PTYManager {
|
|
|
136
136
|
"PTY process spawned",
|
|
137
137
|
);
|
|
138
138
|
|
|
139
|
-
const session:
|
|
139
|
+
const session: CodingAgentSession = {
|
|
140
140
|
sessionId,
|
|
141
|
-
toolType,
|
|
142
|
-
|
|
141
|
+
agentType: toolType,
|
|
142
|
+
agentName: options.customToolId ?? toolName ?? null,
|
|
143
143
|
mode,
|
|
144
144
|
worktreePath,
|
|
145
145
|
ptyPid: ptyProcess.pid,
|
|
@@ -190,7 +190,7 @@ export class PTYManager {
|
|
|
190
190
|
*/
|
|
191
191
|
public updateStatus(
|
|
192
192
|
sessionId: string,
|
|
193
|
-
status:
|
|
193
|
+
status: CodingAgentSession["status"],
|
|
194
194
|
exitCode?: number,
|
|
195
195
|
errorMessage?: string,
|
|
196
196
|
): boolean {
|
|
@@ -217,7 +217,7 @@ export class PTYManager {
|
|
|
217
217
|
/**
|
|
218
218
|
* すべてのセッション一覧を取得
|
|
219
219
|
*/
|
|
220
|
-
public list():
|
|
220
|
+
public list(): CodingAgentSession[] {
|
|
221
221
|
return Array.from(this.instances.values()).map((inst) => inst.session);
|
|
222
222
|
}
|
|
223
223
|
|
|
@@ -233,16 +233,16 @@ export class PTYManager {
|
|
|
233
233
|
},
|
|
234
234
|
): Promise<ResolvedCommand> {
|
|
235
235
|
if (toolType === "custom") {
|
|
236
|
-
const
|
|
237
|
-
if (!
|
|
238
|
-
throw new
|
|
236
|
+
const agentId = options.customToolId ?? options.toolName;
|
|
237
|
+
if (!agentId) {
|
|
238
|
+
throw new CodingAgentResolutionError(
|
|
239
239
|
"COMMAND_NOT_FOUND",
|
|
240
|
-
"
|
|
240
|
+
"Coding agent identifier is required to start a session.",
|
|
241
241
|
);
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
return
|
|
245
|
-
|
|
244
|
+
return resolveCodingAgentCommand({
|
|
245
|
+
agentId,
|
|
246
246
|
mode,
|
|
247
247
|
...(options.skipPermissions !== undefined
|
|
248
248
|
? { skipPermissions: options.skipPermissions }
|
|
@@ -285,7 +285,7 @@ export class PTYManager {
|
|
|
285
285
|
}
|
|
286
286
|
|
|
287
287
|
private async loadSharedEnv(): Promise<Record<string, string>> {
|
|
288
|
-
const config = await
|
|
288
|
+
const config = await loadCodingAgentsConfig();
|
|
289
289
|
const sharedEnv = { ...(config.env ?? {}) };
|
|
290
290
|
logger.debug(
|
|
291
291
|
{ keyCount: Object.keys(sharedEnv).length },
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Config Routes
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
loadCodingAgentsConfig,
|
|
7
|
+
saveCodingAgentsConfig,
|
|
8
|
+
} from "../../../config/tools.js";
|
|
6
9
|
import {
|
|
7
10
|
loadEnvHistory,
|
|
8
11
|
recordEnvHistory,
|
|
@@ -10,11 +13,11 @@ import {
|
|
|
10
13
|
import type {
|
|
11
14
|
ApiResponse,
|
|
12
15
|
ConfigPayload,
|
|
13
|
-
|
|
16
|
+
ApiCodingAgent,
|
|
14
17
|
EnvironmentHistoryEntry,
|
|
15
18
|
EnvironmentVariable,
|
|
16
19
|
} from "../../../types/api.js";
|
|
17
|
-
import type {
|
|
20
|
+
import type { CodingAgent } from "../../../types/tools.js";
|
|
18
21
|
import { getImportedEnvKeys } from "../env/importer.js";
|
|
19
22
|
import type { WebFastifyInstance } from "../types.js";
|
|
20
23
|
|
|
@@ -62,51 +65,51 @@ function envArrayToRecord(
|
|
|
62
65
|
return record;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
function
|
|
66
|
-
|
|
68
|
+
function toApiCodingAgent(
|
|
69
|
+
agent: CodingAgent,
|
|
67
70
|
history: EnvironmentHistoryEntry[],
|
|
68
71
|
importedKeys: Set<string>,
|
|
69
|
-
):
|
|
72
|
+
): ApiCodingAgent {
|
|
70
73
|
return {
|
|
71
|
-
id:
|
|
72
|
-
displayName:
|
|
73
|
-
icon:
|
|
74
|
-
command:
|
|
75
|
-
executionType:
|
|
76
|
-
defaultArgs:
|
|
77
|
-
modeArgs:
|
|
78
|
-
permissionSkipArgs:
|
|
79
|
-
env: normalizeEnv(
|
|
74
|
+
id: agent.id,
|
|
75
|
+
displayName: agent.displayName,
|
|
76
|
+
icon: agent.icon ?? null,
|
|
77
|
+
command: agent.command,
|
|
78
|
+
executionType: agent.type,
|
|
79
|
+
defaultArgs: agent.defaultArgs ?? null,
|
|
80
|
+
modeArgs: agent.modeArgs,
|
|
81
|
+
permissionSkipArgs: agent.permissionSkipArgs ?? null,
|
|
82
|
+
env: normalizeEnv(agent.env, importedKeys, history),
|
|
80
83
|
description: null,
|
|
81
84
|
createdAt: null,
|
|
82
85
|
updatedAt: null,
|
|
83
86
|
};
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
function
|
|
87
|
-
const envRecord = envArrayToRecord(
|
|
88
|
-
const
|
|
89
|
-
id:
|
|
90
|
-
displayName:
|
|
91
|
-
type:
|
|
92
|
-
command:
|
|
93
|
-
modeArgs:
|
|
89
|
+
function toFileCodingAgent(agent: ApiCodingAgent): CodingAgent {
|
|
90
|
+
const envRecord = envArrayToRecord(agent.env);
|
|
91
|
+
const fileAgent: CodingAgent = {
|
|
92
|
+
id: agent.id,
|
|
93
|
+
displayName: agent.displayName,
|
|
94
|
+
type: agent.executionType,
|
|
95
|
+
command: agent.command,
|
|
96
|
+
modeArgs: agent.modeArgs,
|
|
94
97
|
};
|
|
95
98
|
|
|
96
|
-
if (
|
|
97
|
-
|
|
99
|
+
if (agent.icon) {
|
|
100
|
+
fileAgent.icon = agent.icon;
|
|
98
101
|
}
|
|
99
|
-
if (
|
|
100
|
-
|
|
102
|
+
if (agent.defaultArgs && agent.defaultArgs.length > 0) {
|
|
103
|
+
fileAgent.defaultArgs = agent.defaultArgs;
|
|
101
104
|
}
|
|
102
|
-
if (
|
|
103
|
-
|
|
105
|
+
if (agent.permissionSkipArgs && agent.permissionSkipArgs.length > 0) {
|
|
106
|
+
fileAgent.permissionSkipArgs = agent.permissionSkipArgs;
|
|
104
107
|
}
|
|
105
108
|
if (Object.keys(envRecord).length > 0) {
|
|
106
|
-
|
|
109
|
+
fileAgent.env = envRecord;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
return
|
|
112
|
+
return fileAgent;
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
function diffEnvHistory(
|
|
@@ -141,7 +144,7 @@ export async function registerConfigRoutes(
|
|
|
141
144
|
"/api/config",
|
|
142
145
|
async (request, reply) => {
|
|
143
146
|
try {
|
|
144
|
-
const config = await
|
|
147
|
+
const config = await loadCodingAgentsConfig();
|
|
145
148
|
const history = await loadEnvHistory();
|
|
146
149
|
const importedSet = new Set(getImportedEnvKeys());
|
|
147
150
|
|
|
@@ -152,13 +155,16 @@ export async function registerConfigRoutes(
|
|
|
152
155
|
updatedAt: config.updatedAt ?? null,
|
|
153
156
|
env: normalizeEnv(config.env, importedSet, history),
|
|
154
157
|
history,
|
|
155
|
-
|
|
156
|
-
|
|
158
|
+
codingAgents: config.customCodingAgents.map((agent) =>
|
|
159
|
+
toApiCodingAgent(agent, history, importedSet),
|
|
157
160
|
),
|
|
158
161
|
},
|
|
159
162
|
} satisfies ApiResponse<ConfigPayload>;
|
|
160
163
|
} catch (error) {
|
|
161
|
-
request.log.error(
|
|
164
|
+
request.log.error(
|
|
165
|
+
{ err: error },
|
|
166
|
+
"Failed to load coding agents config",
|
|
167
|
+
);
|
|
162
168
|
reply.code(500);
|
|
163
169
|
return {
|
|
164
170
|
success: false,
|
|
@@ -175,7 +181,7 @@ export async function registerConfigRoutes(
|
|
|
175
181
|
}>("/api/config", async (request, reply) => {
|
|
176
182
|
try {
|
|
177
183
|
const payload = request.body;
|
|
178
|
-
const existing = await
|
|
184
|
+
const existing = await loadCodingAgentsConfig();
|
|
179
185
|
const nextEnvRecord = envArrayToRecord(payload.env);
|
|
180
186
|
const envHistory = diffEnvHistory(
|
|
181
187
|
existing.env ?? {},
|
|
@@ -183,10 +189,10 @@ export async function registerConfigRoutes(
|
|
|
183
189
|
"ui",
|
|
184
190
|
);
|
|
185
191
|
|
|
186
|
-
await
|
|
192
|
+
await saveCodingAgentsConfig({
|
|
187
193
|
version: payload.version || existing.version,
|
|
188
194
|
env: nextEnvRecord,
|
|
189
|
-
|
|
195
|
+
customCodingAgents: payload.codingAgents.map(toFileCodingAgent),
|
|
190
196
|
});
|
|
191
197
|
|
|
192
198
|
if (envHistory.length) {
|
|
@@ -203,7 +209,7 @@ export async function registerConfigRoutes(
|
|
|
203
209
|
updatedAt: new Date().toISOString(),
|
|
204
210
|
env: normalizeEnv(nextEnvRecord, importedSet, history),
|
|
205
211
|
history,
|
|
206
|
-
|
|
212
|
+
codingAgents: payload.codingAgents,
|
|
207
213
|
},
|
|
208
214
|
} satisfies ApiResponse<ConfigPayload>;
|
|
209
215
|
} catch (error) {
|