@townco/cli 0.1.7 → 0.1.8
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/dist/commands/create.js +2 -2
- package/dist/commands/delete.js +2 -2
- package/dist/commands/edit.js +1 -1
- package/dist/commands/list.js +1 -1
- package/dist/commands/mcp-add.js +2 -2
- package/dist/commands/mcp-remove.js +107 -195
- package/dist/commands/run.js +1 -1
- package/package.json +1 -1
package/dist/commands/create.js
CHANGED
|
@@ -3,8 +3,8 @@ import { spawn } from "node:child_process";
|
|
|
3
3
|
import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
-
import { scaffoldAgent } from "@
|
|
7
|
-
import { InputBox, MultiSelect, SingleSelect } from "@
|
|
6
|
+
import { scaffoldAgent } from "@townco/agent/scaffold";
|
|
7
|
+
import { InputBox, MultiSelect, SingleSelect } from "@townco/ui/tui";
|
|
8
8
|
import { Box, render, Text, useInput } from "ink";
|
|
9
9
|
import TextInput from "ink-text-input";
|
|
10
10
|
import { useEffect, useState } from "react";
|
package/dist/commands/delete.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { agentExists, deleteAgent } from "@
|
|
3
|
-
import { SingleSelect } from "@
|
|
2
|
+
import { agentExists, deleteAgent } from "@townco/agent/storage";
|
|
3
|
+
import { SingleSelect } from "@townco/ui/tui";
|
|
4
4
|
import { Box, render, Text } from "ink";
|
|
5
5
|
import { useState } from "react";
|
|
6
6
|
function DeleteApp({ name }) {
|
package/dist/commands/edit.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { agentExists, getAgentPath } from "@
|
|
3
|
+
import { agentExists, getAgentPath } from "@townco/agent/storage";
|
|
4
4
|
import { createCommand } from "./create.js";
|
|
5
5
|
async function loadAgentConfig(name) {
|
|
6
6
|
try {
|
package/dist/commands/list.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { getAgentPath, listAgents } from "@
|
|
3
|
+
import { getAgentPath, listAgents } from "@townco/agent/storage";
|
|
4
4
|
async function getAgentInfo(name) {
|
|
5
5
|
try {
|
|
6
6
|
const agentPath = getAgentPath(name);
|
package/dist/commands/mcp-add.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { getAgentPath, listAgents } from "@
|
|
5
|
-
import { MultiSelect, SingleSelect } from "@
|
|
4
|
+
import { getAgentPath, listAgents } from "@townco/agent/storage";
|
|
5
|
+
import { MultiSelect, SingleSelect } from "@townco/ui/tui";
|
|
6
6
|
import { Box, render, Text, useApp, useInput } from "ink";
|
|
7
7
|
import TextInput from "ink-text-input";
|
|
8
8
|
import { useEffect, useState } from "react";
|
|
@@ -1,208 +1,120 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { SingleSelect } from "@townco/ui/tui";
|
|
2
3
|
import { Box, render, Text } from "ink";
|
|
3
4
|
import { useEffect, useState } from "react";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
deleteMCPConfig,
|
|
7
|
-
getMCPSummary,
|
|
8
|
-
listMCPConfigs,
|
|
9
|
-
} from "../lib/mcp-storage";
|
|
10
|
-
|
|
5
|
+
import { deleteMCPConfig, getMCPSummary, listMCPConfigs, } from "../lib/mcp-storage";
|
|
11
6
|
// ============================================================================
|
|
12
7
|
// Main Component
|
|
13
8
|
// ============================================================================
|
|
14
9
|
function MCPRemoveApp() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
if (stage === "confirm") {
|
|
112
|
-
return _jsxs(Box, {
|
|
113
|
-
flexDirection: "column",
|
|
114
|
-
children: [
|
|
115
|
-
_jsx(Box, {
|
|
116
|
-
marginBottom: 1,
|
|
117
|
-
children: _jsx(Text, { bold: true, children: "Confirm removal" }),
|
|
118
|
-
}),
|
|
119
|
-
_jsx(Box, {
|
|
120
|
-
marginBottom: 1,
|
|
121
|
-
children: _jsxs(Text, {
|
|
122
|
-
children: [
|
|
123
|
-
"Are you sure you want to remove:",
|
|
124
|
-
" ",
|
|
125
|
-
_jsx(Text, { bold: true, children: selectedConfig?.name }),
|
|
126
|
-
],
|
|
127
|
-
}),
|
|
128
|
-
}),
|
|
129
|
-
_jsx(Box, {
|
|
130
|
-
marginBottom: 1,
|
|
131
|
-
children: _jsx(Text, {
|
|
132
|
-
dimColor: true,
|
|
133
|
-
children: getMCPSummary(selectedConfig),
|
|
134
|
-
}),
|
|
135
|
-
}),
|
|
136
|
-
_jsx(SingleSelect, {
|
|
137
|
-
options: [
|
|
138
|
-
{
|
|
139
|
-
label: "Yes, remove it",
|
|
140
|
-
value: "yes",
|
|
141
|
-
description: "Permanently delete this MCP server configuration",
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
label: "No, cancel",
|
|
145
|
-
value: "no",
|
|
146
|
-
description: "Go back to selection",
|
|
147
|
-
},
|
|
148
|
-
],
|
|
149
|
-
selected: null,
|
|
150
|
-
onChange: () => {},
|
|
151
|
-
onSubmit: (choice) => {
|
|
152
|
-
if (choice === "yes") {
|
|
153
|
-
handleRemove();
|
|
154
|
-
} else {
|
|
155
|
-
setStage("select");
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
onCancel: () => setStage("select"),
|
|
159
|
-
}),
|
|
160
|
-
],
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
if (stage === "removing") {
|
|
164
|
-
return _jsx(Box, {
|
|
165
|
-
children: _jsx(Text, {
|
|
166
|
-
children: "\uD83D\uDDD1\uFE0F Removing MCP server...",
|
|
167
|
-
}),
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
if (stage === "done") {
|
|
171
|
-
return _jsxs(Box, {
|
|
172
|
-
flexDirection: "column",
|
|
173
|
-
children: [
|
|
174
|
-
_jsx(Box, {
|
|
175
|
-
marginBottom: 1,
|
|
176
|
-
children: _jsx(Text, {
|
|
177
|
-
bold: true,
|
|
178
|
-
color: "green",
|
|
179
|
-
children: "\u2705 MCP server removed successfully",
|
|
180
|
-
}),
|
|
181
|
-
}),
|
|
182
|
-
_jsx(Box, {
|
|
183
|
-
children: _jsxs(Text, {
|
|
184
|
-
children: [
|
|
185
|
-
"Removed: ",
|
|
186
|
-
_jsx(Text, { bold: true, children: selectedConfig?.name }),
|
|
187
|
-
],
|
|
188
|
-
}),
|
|
189
|
-
}),
|
|
190
|
-
],
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
return _jsxs(Text, { children: ["Unknown stage: ", stage] });
|
|
10
|
+
const [stage, setStage] = useState("loading");
|
|
11
|
+
const [configs, setConfigs] = useState([]);
|
|
12
|
+
const [selectedName, setSelectedName] = useState(null);
|
|
13
|
+
const [selectedConfig, setSelectedConfig] = useState(null);
|
|
14
|
+
const [errorMessage, setErrorMessage] = useState("");
|
|
15
|
+
// Load configs on mount
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
function loadConfigs() {
|
|
18
|
+
try {
|
|
19
|
+
const configList = listMCPConfigs();
|
|
20
|
+
setConfigs(configList);
|
|
21
|
+
setStage(configList.length > 0 ? "select" : "error");
|
|
22
|
+
if (configList.length === 0) {
|
|
23
|
+
setErrorMessage("No MCP servers configured");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
28
|
+
setErrorMessage(errorMsg);
|
|
29
|
+
setStage("error");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
loadConfigs();
|
|
33
|
+
}, []);
|
|
34
|
+
// Handle removal
|
|
35
|
+
const handleRemove = () => {
|
|
36
|
+
if (!selectedName)
|
|
37
|
+
return;
|
|
38
|
+
setStage("removing");
|
|
39
|
+
try {
|
|
40
|
+
const success = deleteMCPConfig(selectedName);
|
|
41
|
+
if (success) {
|
|
42
|
+
setStage("done");
|
|
43
|
+
// Exit immediately
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
throw new Error("Failed to delete MCP config");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
52
|
+
setErrorMessage(errorMsg);
|
|
53
|
+
setStage("error");
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
if (stage === "loading") {
|
|
57
|
+
return (_jsx(Box, { children: _jsx(Text, { children: "Loading MCP servers..." }) }));
|
|
58
|
+
}
|
|
59
|
+
if (stage === "error") {
|
|
60
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "red", children: "\u274C Error" }) }), _jsx(Box, { children: _jsx(Text, { children: errorMessage }) })] }));
|
|
61
|
+
}
|
|
62
|
+
if (stage === "select") {
|
|
63
|
+
const options = configs.map((config) => ({
|
|
64
|
+
label: config.name,
|
|
65
|
+
value: config.name,
|
|
66
|
+
description: getMCPSummary(config),
|
|
67
|
+
}));
|
|
68
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Select MCP server to remove" }) }), _jsx(SingleSelect, { options: options, selected: selectedName, onChange: setSelectedName, onSubmit: (name) => {
|
|
69
|
+
const found = configs.find((c) => c.name === name);
|
|
70
|
+
if (found) {
|
|
71
|
+
setSelectedName(name);
|
|
72
|
+
setSelectedConfig(found);
|
|
73
|
+
setStage("confirm");
|
|
74
|
+
}
|
|
75
|
+
}, onCancel: () => process.exit(0) })] }));
|
|
76
|
+
}
|
|
77
|
+
if (stage === "confirm") {
|
|
78
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Confirm removal" }) }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Are you sure you want to remove:", " ", _jsx(Text, { bold: true, children: selectedConfig?.name })] }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: getMCPSummary(selectedConfig) }) }), _jsx(SingleSelect, { options: [
|
|
79
|
+
{
|
|
80
|
+
label: "Yes, remove it",
|
|
81
|
+
value: "yes",
|
|
82
|
+
description: "Permanently delete this MCP server configuration",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
label: "No, cancel",
|
|
86
|
+
value: "no",
|
|
87
|
+
description: "Go back to selection",
|
|
88
|
+
},
|
|
89
|
+
], selected: null, onChange: () => { }, onSubmit: (choice) => {
|
|
90
|
+
if (choice === "yes") {
|
|
91
|
+
handleRemove();
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
setStage("select");
|
|
95
|
+
}
|
|
96
|
+
}, onCancel: () => setStage("select") })] }));
|
|
97
|
+
}
|
|
98
|
+
if (stage === "removing") {
|
|
99
|
+
return (_jsx(Box, { children: _jsx(Text, { children: "\uD83D\uDDD1\uFE0F Removing MCP server..." }) }));
|
|
100
|
+
}
|
|
101
|
+
if (stage === "done") {
|
|
102
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "\u2705 MCP server removed successfully" }) }), _jsx(Box, { children: _jsxs(Text, { children: ["Removed: ", _jsx(Text, { bold: true, children: selectedConfig?.name })] }) })] }));
|
|
103
|
+
}
|
|
104
|
+
return _jsxs(Text, { children: ["Unknown stage: ", stage] });
|
|
194
105
|
}
|
|
195
106
|
// ============================================================================
|
|
196
107
|
// Export and Runner
|
|
197
108
|
// ============================================================================
|
|
198
109
|
export default MCPRemoveApp;
|
|
199
110
|
export async function runMCPRemove() {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
111
|
+
const { waitUntilExit, clear } = render(_jsx(MCPRemoveApp, {}));
|
|
112
|
+
try {
|
|
113
|
+
await waitUntilExit();
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
clear();
|
|
117
|
+
// Ensure cursor is visible
|
|
118
|
+
process.stdout.write("\x1B[?25h");
|
|
119
|
+
}
|
|
208
120
|
}
|
package/dist/commands/run.js
CHANGED
|
@@ -3,7 +3,7 @@ import { existsSync } from "node:fs";
|
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
-
import { agentExists, getAgentPath } from "@
|
|
6
|
+
import { agentExists, getAgentPath } from "@townco/agent/storage";
|
|
7
7
|
import open from "open";
|
|
8
8
|
async function loadEnvVars() {
|
|
9
9
|
const envPath = join(homedir(), ".config", "town", ".env");
|