@townco/cli 0.1.85 → 0.1.88
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/deploy.js +2 -25
- package/package.json +9 -9
- package/dist/commands/delete.d.ts +0 -1
- package/dist/commands/delete.js +0 -60
- package/dist/commands/edit.d.ts +0 -1
- package/dist/commands/edit.js +0 -92
- package/dist/commands/list.d.ts +0 -1
- package/dist/commands/list.js +0 -55
- package/dist/commands/mcp-add.d.ts +0 -14
- package/dist/commands/mcp-add.js +0 -494
- package/dist/commands/mcp-list.d.ts +0 -3
- package/dist/commands/mcp-list.js +0 -63
- package/dist/commands/mcp-remove.d.ts +0 -3
- package/dist/commands/mcp-remove.js +0 -120
- package/dist/commands/tool-add.d.ts +0 -6
- package/dist/commands/tool-add.js +0 -349
- package/dist/commands/tool-list.d.ts +0 -3
- package/dist/commands/tool-list.js +0 -61
- package/dist/commands/tool-register.d.ts +0 -7
- package/dist/commands/tool-register.js +0 -291
- package/dist/commands/tool-remove.d.ts +0 -3
- package/dist/commands/tool-remove.js +0 -202
- package/dist/components/MergedLogsPane.d.ts +0 -11
- package/dist/components/MergedLogsPane.js +0 -205
- package/dist/lib/auth-storage.d.ts +0 -38
- package/dist/lib/auth-storage.js +0 -89
- package/dist/lib/mcp-storage.d.ts +0 -32
- package/dist/lib/mcp-storage.js +0 -111
package/dist/commands/deploy.js
CHANGED
|
@@ -3,12 +3,10 @@ import afs from "node:fs/promises";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { command, constant, message, object, option, string, } from "@optique/core";
|
|
5
5
|
import { isInsideTownProject } from "@townco/agent/storage";
|
|
6
|
+
import { createClient } from "@townco/apiclient";
|
|
6
7
|
import { findRoot } from "@townco/core/path";
|
|
7
|
-
import { createTRPCClient, httpLink, httpSubscriptionLink, loggerLink, splitLink, } from "@trpc/client";
|
|
8
8
|
import archiver from "archiver";
|
|
9
|
-
import { EventSource } from "eventsource";
|
|
10
9
|
import walk from "ignore-walk";
|
|
11
|
-
import superjson from "superjson";
|
|
12
10
|
import { getValidCredentials } from "@/lib/auth-fetch";
|
|
13
11
|
import { createCommand } from "@/lib/command";
|
|
14
12
|
const MAX_ARCHIVE_SIZE = 4.5 * 1024 * 1024; // 4.5MB
|
|
@@ -28,28 +26,7 @@ export default createCommand({
|
|
|
28
26
|
if (!(await afs.exists(join(projectRoot, "agents", agent))))
|
|
29
27
|
throw new Error(`Agent ${agent} not found`);
|
|
30
28
|
const { accessToken, shedUrl } = await getValidCredentials();
|
|
31
|
-
const
|
|
32
|
-
const url = `${shedUrl}/api/trpc`;
|
|
33
|
-
const baseLinkOpts = { url, transformer: superjson };
|
|
34
|
-
const client = createTRPCClient({
|
|
35
|
-
links: [
|
|
36
|
-
loggerLink({ enabled: (_) => debug }),
|
|
37
|
-
splitLink({
|
|
38
|
-
condition: (op) => op.type === "subscription",
|
|
39
|
-
true: httpSubscriptionLink({
|
|
40
|
-
...baseLinkOpts,
|
|
41
|
-
EventSource,
|
|
42
|
-
eventSourceOptions: {
|
|
43
|
-
fetch: async (url, init) => fetch(url, {
|
|
44
|
-
...init,
|
|
45
|
-
headers: { ...init.headers, ...authHeader },
|
|
46
|
-
}),
|
|
47
|
-
},
|
|
48
|
-
}),
|
|
49
|
-
false: httpLink({ ...baseLinkOpts, headers: authHeader }),
|
|
50
|
-
}),
|
|
51
|
-
],
|
|
52
|
-
});
|
|
29
|
+
const client = createClient({ accessToken, shedUrl, debug });
|
|
53
30
|
console.log("Creating archive...");
|
|
54
31
|
const root = await findRoot({ rootMarker: "package.json" });
|
|
55
32
|
const chunks = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@townco/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.88",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"town": "./dist/index.js"
|
|
@@ -15,22 +15,22 @@
|
|
|
15
15
|
"build": "tsgo"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@townco/tsconfig": "0.1.
|
|
18
|
+
"@townco/tsconfig": "0.1.80",
|
|
19
19
|
"@types/archiver": "^7.0.0",
|
|
20
20
|
"@types/bun": "^1.3.1",
|
|
21
21
|
"@types/ignore-walk": "^4.0.3",
|
|
22
|
-
"@townco/api": "workspace:*",
|
|
23
22
|
"@types/react": "^19.2.2"
|
|
24
23
|
},
|
|
25
24
|
"dependencies": {
|
|
26
25
|
"@optique/core": "^0.6.2",
|
|
27
26
|
"@optique/run": "^0.6.2",
|
|
28
|
-
"@townco/agent": "0.1.
|
|
29
|
-
"@townco/
|
|
30
|
-
"@townco/
|
|
31
|
-
"@townco/
|
|
32
|
-
"@townco/
|
|
33
|
-
"@townco/
|
|
27
|
+
"@townco/agent": "0.1.88",
|
|
28
|
+
"@townco/apiclient": "0.0.2",
|
|
29
|
+
"@townco/core": "0.0.61",
|
|
30
|
+
"@townco/debugger": "0.1.38",
|
|
31
|
+
"@townco/env": "0.1.33",
|
|
32
|
+
"@townco/secret": "0.1.83",
|
|
33
|
+
"@townco/ui": "0.1.83",
|
|
34
34
|
"@trpc/client": "^11.7.2",
|
|
35
35
|
"archiver": "^7.0.1",
|
|
36
36
|
"eventsource": "^4.1.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function deleteCommand(name: string): Promise<void>;
|
package/dist/commands/delete.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { agentExists, deleteAgent } from "@townco/agent/storage";
|
|
3
|
-
import { SingleSelect } from "@townco/ui/tui";
|
|
4
|
-
import { Box, render, Text } from "ink";
|
|
5
|
-
import { useState } from "react";
|
|
6
|
-
function DeleteApp({ name }) {
|
|
7
|
-
const [confirmed, setConfirmed] = useState(null);
|
|
8
|
-
if (confirmed === null) {
|
|
9
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, children: ["Are you sure you want to delete agent", " ", _jsx(Text, { color: "red", children: name }), "?"] }) }), _jsx(Text, { dimColor: true, children: "This action cannot be undone." }), _jsx(Box, { marginTop: 1, children: _jsx(SingleSelect, { options: [
|
|
10
|
-
{
|
|
11
|
-
label: "Yes, delete",
|
|
12
|
-
value: "yes",
|
|
13
|
-
description: "Permanently delete this agent",
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
label: "No, cancel",
|
|
17
|
-
value: "no",
|
|
18
|
-
description: "Keep the agent",
|
|
19
|
-
},
|
|
20
|
-
], selected: null, onChange: () => { }, onSubmit: async (value) => {
|
|
21
|
-
if (value === "yes") {
|
|
22
|
-
setConfirmed(true);
|
|
23
|
-
try {
|
|
24
|
-
await deleteAgent(name);
|
|
25
|
-
setTimeout(() => process.exit(0), 1500);
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
console.error(`Error deleting agent: ${error instanceof Error ? error.message : String(error)}`);
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
setConfirmed(false);
|
|
34
|
-
setTimeout(() => process.exit(0), 500);
|
|
35
|
-
}
|
|
36
|
-
}, onCancel: () => {
|
|
37
|
-
setConfirmed(false);
|
|
38
|
-
setTimeout(() => process.exit(0), 500);
|
|
39
|
-
} }) })] }));
|
|
40
|
-
}
|
|
41
|
-
if (confirmed) {
|
|
42
|
-
return (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { color: "green", children: "\u2713 Agent deleted successfully" }) }));
|
|
43
|
-
}
|
|
44
|
-
return (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { dimColor: true, children: "Cancelled" }) }));
|
|
45
|
-
}
|
|
46
|
-
export async function deleteCommand(name) {
|
|
47
|
-
// Check if agent exists
|
|
48
|
-
const exists = await agentExists(name);
|
|
49
|
-
if (!exists) {
|
|
50
|
-
console.error(`Error: Agent "${name}" not found.`);
|
|
51
|
-
console.log('\nList agents with "town list"');
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
// Set stdin to raw mode to capture input
|
|
55
|
-
if (process.stdin.isTTY) {
|
|
56
|
-
process.stdin.setRawMode(true);
|
|
57
|
-
}
|
|
58
|
-
const { waitUntilExit } = render(_jsx(DeleteApp, { name: name }));
|
|
59
|
-
await waitUntilExit();
|
|
60
|
-
}
|
package/dist/commands/edit.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function editCommand(name: string): Promise<void>;
|
package/dist/commands/edit.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { isInsideTownProject } from "@townco/agent/storage";
|
|
4
|
-
import { createCommand } from "./create.js";
|
|
5
|
-
async function loadAgentConfig(name, agentPath) {
|
|
6
|
-
try {
|
|
7
|
-
const indexPath = join(agentPath, "index.ts");
|
|
8
|
-
const content = await readFile(indexPath, "utf-8");
|
|
9
|
-
// Parse model
|
|
10
|
-
const modelMatch = content.match(/model:\s*"([^"]+)"/);
|
|
11
|
-
if (!modelMatch) {
|
|
12
|
-
throw new Error("Failed to parse model from agent configuration");
|
|
13
|
-
}
|
|
14
|
-
const model = modelMatch[1];
|
|
15
|
-
// Parse tools
|
|
16
|
-
const toolsMatch = content.match(/tools:\s*\[([^\]]*)\]/);
|
|
17
|
-
let tools = [];
|
|
18
|
-
if (toolsMatch?.[1]) {
|
|
19
|
-
const toolsStr = toolsMatch[1];
|
|
20
|
-
tools = toolsStr
|
|
21
|
-
.split(",")
|
|
22
|
-
.map((t) => t.trim().replace(/["']/g, ""))
|
|
23
|
-
.filter((t) => t.length > 0);
|
|
24
|
-
}
|
|
25
|
-
// Parse systemPrompt - handle multiline strings and null
|
|
26
|
-
const systemPromptMatch = content.match(/systemPrompt:\s*(null|"([^"]*)"|`([^`]*)`)/s);
|
|
27
|
-
let systemPrompt;
|
|
28
|
-
if (systemPromptMatch) {
|
|
29
|
-
if (systemPromptMatch[1] === "null") {
|
|
30
|
-
systemPrompt = "";
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
// Get either double-quoted (group 2) or backtick-quoted (group 3) content
|
|
34
|
-
systemPrompt = systemPromptMatch[2] || systemPromptMatch[3] || "";
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
if (systemPrompt !== undefined && systemPrompt !== "") {
|
|
38
|
-
return {
|
|
39
|
-
name,
|
|
40
|
-
model: model,
|
|
41
|
-
tools,
|
|
42
|
-
systemPrompt,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
name,
|
|
47
|
-
model: model,
|
|
48
|
-
tools,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
console.error(`Error loading agent config: ${error instanceof Error ? error.message : String(error)}`);
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
export async function editCommand(name) {
|
|
57
|
-
// Check if we're inside a Town project
|
|
58
|
-
const projectRoot = await isInsideTownProject();
|
|
59
|
-
if (projectRoot === null) {
|
|
60
|
-
console.error("Error: Not inside a Town project.\n\n" +
|
|
61
|
-
"Please run 'town edit' inside a project directory.");
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
const agentPath = join(projectRoot, "agents", name);
|
|
65
|
-
// Check if the agent exists
|
|
66
|
-
try {
|
|
67
|
-
await readFile(join(agentPath, "agent.json"), "utf-8");
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
console.error(`Error: Agent "${name}" not found.`);
|
|
71
|
-
console.log('\nCreate an agent with "town create" or list agents with "town list"');
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
// Load existing config
|
|
75
|
-
const config = await loadAgentConfig(name, agentPath);
|
|
76
|
-
if (!config) {
|
|
77
|
-
console.error(`Error: Failed to load agent configuration for "${name}".`);
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
80
|
-
console.log(`Editing agent: ${name}\n`);
|
|
81
|
-
// Reuse create command with existing values and overwrite flag
|
|
82
|
-
await createCommand({
|
|
83
|
-
name: config.name,
|
|
84
|
-
model: config.model,
|
|
85
|
-
tools: config.tools,
|
|
86
|
-
...(config.systemPrompt !== undefined && {
|
|
87
|
-
systemPrompt: config.systemPrompt,
|
|
88
|
-
}),
|
|
89
|
-
overwrite: true,
|
|
90
|
-
agentsDir: join(projectRoot, "agents"),
|
|
91
|
-
});
|
|
92
|
-
}
|
package/dist/commands/list.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function listCommand(): Promise<void>;
|
package/dist/commands/list.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { getAgentPath, listAgents } from "@townco/agent/storage";
|
|
4
|
-
async function getAgentInfo(name) {
|
|
5
|
-
try {
|
|
6
|
-
const agentPath = getAgentPath(name);
|
|
7
|
-
const configPath = join(agentPath, "agent.json");
|
|
8
|
-
const content = await readFile(configPath, "utf-8");
|
|
9
|
-
const config = JSON.parse(content);
|
|
10
|
-
return {
|
|
11
|
-
name,
|
|
12
|
-
model: config.model,
|
|
13
|
-
tools: config.tools || [],
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
catch (error) {
|
|
17
|
-
return {
|
|
18
|
-
name,
|
|
19
|
-
error: error instanceof Error ? error.message : "Failed to read agent",
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
export async function listCommand() {
|
|
24
|
-
const agents = await listAgents();
|
|
25
|
-
if (agents.length === 0) {
|
|
26
|
-
console.log("No agents found.");
|
|
27
|
-
console.log('\x1b[2mCreate your first agent with "town create"\x1b[0m');
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
console.log(`\x1b[1mFound ${agents.length} agent${agents.length === 1 ? "" : "s"}:\x1b[0m\n`);
|
|
31
|
-
// Get info for all agents
|
|
32
|
-
const agentInfos = await Promise.all(agents.map((name) => getAgentInfo(name)));
|
|
33
|
-
// Display each agent
|
|
34
|
-
for (const info of agentInfos) {
|
|
35
|
-
const agentPath = getAgentPath(info.name);
|
|
36
|
-
if (info.error) {
|
|
37
|
-
console.log(` \x1b[31m✗\x1b[0m \x1b[1m${info.name}\x1b[0m`);
|
|
38
|
-
console.log(` \x1b[2mError: ${info.error}\x1b[0m`);
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
const modelLabel = info.model
|
|
42
|
-
? info.model.replace("claude-", "")
|
|
43
|
-
: "unknown";
|
|
44
|
-
console.log(` \x1b[32m●\x1b[0m \x1b[1m${info.name}\x1b[0m`);
|
|
45
|
-
console.log(` \x1b[2mModel: ${modelLabel}\x1b[0m`);
|
|
46
|
-
if (info.tools && info.tools.length > 0) {
|
|
47
|
-
console.log(` \x1b[2mTools: ${info.tools.join(", ")}\x1b[0m`);
|
|
48
|
-
}
|
|
49
|
-
console.log(` \x1b[2mPath: ${agentPath}\x1b[0m`);
|
|
50
|
-
}
|
|
51
|
-
console.log(); // Empty line between agents
|
|
52
|
-
}
|
|
53
|
-
console.log(`\x1b[2mRun an agent with: town run <name>\x1b[0m`);
|
|
54
|
-
console.log(`\x1b[2mTUI mode (default), --gui for web interface, --http for API server\x1b[0m`);
|
|
55
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
interface MCPAddProps {
|
|
2
|
-
name?: string;
|
|
3
|
-
url?: string;
|
|
4
|
-
command?: string;
|
|
5
|
-
args?: readonly string[];
|
|
6
|
-
}
|
|
7
|
-
declare function MCPAddApp({
|
|
8
|
-
name: initialName,
|
|
9
|
-
url: initialUrl,
|
|
10
|
-
command: initialCommand,
|
|
11
|
-
args: initialArgs,
|
|
12
|
-
}: MCPAddProps): import("react/jsx-runtime").JSX.Element | null;
|
|
13
|
-
export default MCPAddApp;
|
|
14
|
-
export declare function runMCPAdd(props?: MCPAddProps): Promise<void>;
|