@townco/cli 0.1.7 → 0.1.9

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.
@@ -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 "@town/agent/scaffold";
7
- import { InputBox, MultiSelect, SingleSelect } from "@town/ui/tui";
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";
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { agentExists, deleteAgent } from "@town/agent/storage";
3
- import { SingleSelect } from "@town/ui/tui";
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 }) {
@@ -1,6 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { agentExists, getAgentPath } from "@town/agent/storage";
3
+ import { agentExists, getAgentPath } from "@townco/agent/storage";
4
4
  import { createCommand } from "./create.js";
5
5
  async function loadAgentConfig(name) {
6
6
  try {
@@ -1,6 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { getAgentPath, listAgents } from "@town/agent/storage";
3
+ import { getAgentPath, listAgents } from "@townco/agent/storage";
4
4
  async function getAgentInfo(name) {
5
5
  try {
6
6
  const agentPath = getAgentPath(name);
@@ -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 "@town/agent/storage";
5
- import { MultiSelect, SingleSelect } from "@town/ui/tui";
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 { SingleSelect } from "@town/ui/tui";
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 { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
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
- const [stage, setStage] = useState("loading");
16
- const [configs, setConfigs] = useState([]);
17
- const [selectedName, setSelectedName] = useState(null);
18
- const [selectedConfig, setSelectedConfig] = useState(null);
19
- const [errorMessage, setErrorMessage] = useState("");
20
- // Load configs on mount
21
- useEffect(() => {
22
- function loadConfigs() {
23
- try {
24
- const configList = listMCPConfigs();
25
- setConfigs(configList);
26
- setStage(configList.length > 0 ? "select" : "error");
27
- if (configList.length === 0) {
28
- setErrorMessage("No MCP servers configured");
29
- }
30
- } catch (error) {
31
- const errorMsg = error instanceof Error ? error.message : String(error);
32
- setErrorMessage(errorMsg);
33
- setStage("error");
34
- }
35
- }
36
- loadConfigs();
37
- }, []);
38
- // Handle removal
39
- const handleRemove = () => {
40
- if (!selectedName) return;
41
- setStage("removing");
42
- try {
43
- const success = deleteMCPConfig(selectedName);
44
- if (success) {
45
- setStage("done");
46
- // Exit immediately
47
- process.exit(0);
48
- } else {
49
- throw new Error("Failed to delete MCP config");
50
- }
51
- } catch (error) {
52
- const errorMsg = error instanceof Error ? error.message : String(error);
53
- setErrorMessage(errorMsg);
54
- setStage("error");
55
- }
56
- };
57
- if (stage === "loading") {
58
- return _jsx(Box, {
59
- children: _jsx(Text, { children: "Loading MCP servers..." }),
60
- });
61
- }
62
- if (stage === "error") {
63
- return _jsxs(Box, {
64
- flexDirection: "column",
65
- children: [
66
- _jsx(Box, {
67
- marginBottom: 1,
68
- children: _jsx(Text, {
69
- bold: true,
70
- color: "red",
71
- children: "\u274C Error",
72
- }),
73
- }),
74
- _jsx(Box, { children: _jsx(Text, { children: errorMessage }) }),
75
- ],
76
- });
77
- }
78
- if (stage === "select") {
79
- const options = configs.map((config) => ({
80
- label: config.name,
81
- value: config.name,
82
- description: getMCPSummary(config),
83
- }));
84
- return _jsxs(Box, {
85
- flexDirection: "column",
86
- children: [
87
- _jsx(Box, {
88
- marginBottom: 1,
89
- children: _jsx(Text, {
90
- bold: true,
91
- children: "Select MCP server to remove",
92
- }),
93
- }),
94
- _jsx(SingleSelect, {
95
- options: options,
96
- selected: selectedName,
97
- onChange: setSelectedName,
98
- onSubmit: (name) => {
99
- const found = configs.find((c) => c.name === name);
100
- if (found) {
101
- setSelectedName(name);
102
- setSelectedConfig(found);
103
- setStage("confirm");
104
- }
105
- },
106
- onCancel: () => process.exit(0),
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
- const { waitUntilExit, clear } = render(_jsx(MCPRemoveApp, {}));
201
- try {
202
- await waitUntilExit();
203
- } finally {
204
- clear();
205
- // Ensure cursor is visible
206
- process.stdout.write("\x1B[?25h");
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
  }
@@ -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 "@town/agent/storage";
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");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@townco/cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "townco": "./dist/index.js"
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "@optique/core": "^0.6.2",
28
28
  "@optique/run": "^0.6.2",
29
- "@townco/agent": "0.1.6",
29
+ "@townco/agent": "0.1.9",
30
30
  "@townco/secret": "0.1.6",
31
31
  "@townco/ui": "0.1.6",
32
32
  "@types/inquirer": "^9.0.9",