@agents-at-scale/ark 0.1.35-rc1 → 0.1.35
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/cluster/index.d.ts +1 -2
- package/dist/commands/cluster/index.js +5 -3
- package/dist/commands/completion.js +2 -159
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.js +321 -38
- package/dist/commands/generate/config.js +24 -5
- package/dist/commands/generate/generators/agent.js +2 -2
- package/dist/commands/generate/generators/mcpserver.d.ts +1 -2
- package/dist/commands/generate/generators/mcpserver.js +5 -26
- package/dist/commands/generate/generators/project.js +41 -22
- package/dist/commands/generate/generators/team.js +2 -2
- package/dist/commands/generate/index.d.ts +1 -2
- package/dist/commands/generate/index.js +1 -1
- package/dist/components/statusChecker.d.ts +23 -13
- package/dist/components/statusChecker.js +129 -275
- package/dist/config.d.ts +22 -3
- package/dist/config.js +161 -10
- package/dist/index.d.ts +1 -1
- package/dist/index.js +42 -40
- package/dist/lib/cluster.d.ts +1 -2
- package/dist/lib/cluster.js +16 -37
- package/dist/lib/config.d.ts +80 -26
- package/dist/lib/config.js +205 -70
- package/dist/lib/consts.d.ts +1 -0
- package/dist/lib/consts.js +2 -0
- package/dist/lib/errors.js +1 -1
- package/dist/lib/exec.d.ts +4 -0
- package/dist/lib/exec.js +11 -0
- package/dist/lib/types.d.ts +3 -10
- package/dist/ui/MainMenu.d.ts +1 -5
- package/dist/ui/MainMenu.js +91 -222
- package/dist/ui/statusFormatter.d.ts +7 -22
- package/dist/ui/statusFormatter.js +39 -39
- package/package.json +5 -17
- package/dist/arkServices.d.ts +0 -42
- package/dist/arkServices.js +0 -138
- package/dist/arkServices.spec.d.ts +0 -1
- package/dist/arkServices.spec.js +0 -24
- package/dist/charts/charts.d.ts +0 -5
- package/dist/charts/charts.js +0 -6
- package/dist/charts/dependencies.d.ts +0 -6
- package/dist/charts/dependencies.js +0 -50
- package/dist/charts/types.d.ts +0 -40
- package/dist/charts/types.js +0 -1
- package/dist/commands/agents/index.d.ts +0 -3
- package/dist/commands/agents/index.js +0 -51
- package/dist/commands/agents/index.spec.d.ts +0 -1
- package/dist/commands/agents/index.spec.js +0 -67
- package/dist/commands/agents/selector.d.ts +0 -8
- package/dist/commands/agents/selector.js +0 -53
- package/dist/commands/agents.d.ts +0 -2
- package/dist/commands/agents.js +0 -53
- package/dist/commands/chat/index.d.ts +0 -3
- package/dist/commands/chat/index.js +0 -29
- package/dist/commands/chat.d.ts +0 -2
- package/dist/commands/chat.js +0 -45
- package/dist/commands/cluster/get.d.ts +0 -2
- package/dist/commands/cluster/get.js +0 -39
- package/dist/commands/cluster/get.spec.d.ts +0 -1
- package/dist/commands/cluster/get.spec.js +0 -92
- package/dist/commands/cluster/index.spec.d.ts +0 -1
- package/dist/commands/cluster/index.spec.js +0 -24
- package/dist/commands/completion/index.d.ts +0 -3
- package/dist/commands/completion/index.js +0 -268
- package/dist/commands/completion/index.spec.d.ts +0 -1
- package/dist/commands/completion/index.spec.js +0 -34
- package/dist/commands/config/index.d.ts +0 -3
- package/dist/commands/config/index.js +0 -42
- package/dist/commands/config/index.spec.d.ts +0 -1
- package/dist/commands/config/index.spec.js +0 -78
- package/dist/commands/dashboard/index.d.ts +0 -4
- package/dist/commands/dashboard/index.js +0 -39
- package/dist/commands/dashboard.d.ts +0 -3
- package/dist/commands/dashboard.js +0 -39
- package/dist/commands/dev/index.d.ts +0 -3
- package/dist/commands/dev/index.js +0 -9
- package/dist/commands/dev/tool/check.d.ts +0 -2
- package/dist/commands/dev/tool/check.js +0 -142
- package/dist/commands/dev/tool/clean.d.ts +0 -2
- package/dist/commands/dev/tool/clean.js +0 -153
- package/dist/commands/dev/tool/generate.d.ts +0 -2
- package/dist/commands/dev/tool/generate.js +0 -28
- package/dist/commands/dev/tool/index.d.ts +0 -2
- package/dist/commands/dev/tool/index.js +0 -14
- package/dist/commands/dev/tool/init.d.ts +0 -2
- package/dist/commands/dev/tool/init.js +0 -320
- package/dist/commands/dev/tool/shared.d.ts +0 -5
- package/dist/commands/dev/tool/shared.js +0 -256
- package/dist/commands/dev/tool/status.d.ts +0 -2
- package/dist/commands/dev/tool/status.js +0 -136
- package/dist/commands/dev/tool-generate.spec.d.ts +0 -1
- package/dist/commands/dev/tool-generate.spec.js +0 -163
- package/dist/commands/dev/tool.d.ts +0 -2
- package/dist/commands/dev/tool.js +0 -559
- package/dist/commands/dev/tool.spec.d.ts +0 -1
- package/dist/commands/dev/tool.spec.js +0 -48
- package/dist/commands/install/index.d.ts +0 -8
- package/dist/commands/install/index.js +0 -302
- package/dist/commands/install/index.spec.d.ts +0 -1
- package/dist/commands/install/index.spec.js +0 -135
- package/dist/commands/install.d.ts +0 -3
- package/dist/commands/install.js +0 -147
- package/dist/commands/models/create.d.ts +0 -1
- package/dist/commands/models/create.js +0 -213
- package/dist/commands/models/create.spec.d.ts +0 -1
- package/dist/commands/models/create.spec.js +0 -125
- package/dist/commands/models/index.d.ts +0 -3
- package/dist/commands/models/index.js +0 -60
- package/dist/commands/models/index.spec.d.ts +0 -1
- package/dist/commands/models/index.spec.js +0 -76
- package/dist/commands/models/selector.d.ts +0 -8
- package/dist/commands/models/selector.js +0 -53
- package/dist/commands/routes/index.d.ts +0 -3
- package/dist/commands/routes/index.js +0 -93
- package/dist/commands/routes.d.ts +0 -2
- package/dist/commands/routes.js +0 -101
- package/dist/commands/status/index.d.ts +0 -4
- package/dist/commands/status/index.js +0 -232
- package/dist/commands/status.d.ts +0 -3
- package/dist/commands/status.js +0 -33
- package/dist/commands/targets/index.d.ts +0 -3
- package/dist/commands/targets/index.js +0 -65
- package/dist/commands/targets/index.spec.d.ts +0 -1
- package/dist/commands/targets/index.spec.js +0 -105
- package/dist/commands/targets.d.ts +0 -2
- package/dist/commands/targets.js +0 -65
- package/dist/commands/teams/index.d.ts +0 -3
- package/dist/commands/teams/index.js +0 -49
- package/dist/commands/teams/index.spec.d.ts +0 -1
- package/dist/commands/teams/index.spec.js +0 -70
- package/dist/commands/teams/selector.d.ts +0 -8
- package/dist/commands/teams/selector.js +0 -55
- package/dist/commands/tools/index.d.ts +0 -3
- package/dist/commands/tools/index.js +0 -49
- package/dist/commands/tools/index.spec.d.ts +0 -1
- package/dist/commands/tools/index.spec.js +0 -70
- package/dist/commands/tools/selector.d.ts +0 -8
- package/dist/commands/tools/selector.js +0 -53
- package/dist/commands/uninstall/index.d.ts +0 -3
- package/dist/commands/uninstall/index.js +0 -107
- package/dist/commands/uninstall/index.spec.d.ts +0 -1
- package/dist/commands/uninstall/index.spec.js +0 -117
- package/dist/commands/uninstall.d.ts +0 -2
- package/dist/commands/uninstall.js +0 -83
- package/dist/components/ChatUI.d.ts +0 -16
- package/dist/components/ChatUI.js +0 -801
- package/dist/components/StatusView.d.ts +0 -10
- package/dist/components/StatusView.js +0 -39
- package/dist/lib/arkApiClient.d.ts +0 -53
- package/dist/lib/arkApiClient.js +0 -102
- package/dist/lib/arkApiProxy.d.ts +0 -9
- package/dist/lib/arkApiProxy.js +0 -22
- package/dist/lib/arkServiceProxy.d.ts +0 -14
- package/dist/lib/arkServiceProxy.js +0 -95
- package/dist/lib/arkStatus.d.ts +0 -10
- package/dist/lib/arkStatus.js +0 -79
- package/dist/lib/arkStatus.spec.d.ts +0 -1
- package/dist/lib/arkStatus.spec.js +0 -49
- package/dist/lib/chatClient.d.ts +0 -33
- package/dist/lib/chatClient.js +0 -99
- package/dist/lib/cluster.spec.d.ts +0 -1
- package/dist/lib/cluster.spec.js +0 -338
- package/dist/lib/commandUtils.d.ts +0 -4
- package/dist/lib/commandUtils.js +0 -18
- package/dist/lib/commandUtils.test.d.ts +0 -1
- package/dist/lib/commandUtils.test.js +0 -44
- package/dist/lib/commands.d.ts +0 -16
- package/dist/lib/commands.js +0 -29
- package/dist/lib/commands.spec.d.ts +0 -1
- package/dist/lib/commands.spec.js +0 -146
- package/dist/lib/config.spec.d.ts +0 -1
- package/dist/lib/config.spec.js +0 -99
- package/dist/lib/config.test.d.ts +0 -1
- package/dist/lib/config.test.js +0 -93
- package/dist/lib/consts.spec.d.ts +0 -1
- package/dist/lib/consts.spec.js +0 -15
- package/dist/lib/dev/tools/analyzer.d.ts +0 -30
- package/dist/lib/dev/tools/analyzer.js +0 -190
- package/dist/lib/dev/tools/discover_tools.py +0 -392
- package/dist/lib/dev/tools/mcp-types.d.ts +0 -28
- package/dist/lib/dev/tools/mcp-types.js +0 -86
- package/dist/lib/dev/tools/types.d.ts +0 -50
- package/dist/lib/dev/tools/types.js +0 -1
- package/dist/lib/errors.spec.d.ts +0 -1
- package/dist/lib/errors.spec.js +0 -221
- package/dist/lib/output.d.ts +0 -36
- package/dist/lib/output.js +0 -89
- package/dist/lib/output.spec.d.ts +0 -1
- package/dist/lib/output.spec.js +0 -123
- package/dist/lib/portUtils.d.ts +0 -8
- package/dist/lib/portUtils.js +0 -39
- package/dist/lib/startup.d.ts +0 -5
- package/dist/lib/startup.js +0 -73
- package/dist/lib/startup.spec.d.ts +0 -1
- package/dist/lib/startup.spec.js +0 -168
- package/dist/types/types.d.ts +0 -40
- package/dist/types/types.js +0 -1
- package/dist/ui/AgentSelector.d.ts +0 -8
- package/dist/ui/AgentSelector.js +0 -53
- package/dist/ui/ModelSelector.d.ts +0 -8
- package/dist/ui/ModelSelector.js +0 -53
- package/dist/ui/TeamSelector.d.ts +0 -8
- package/dist/ui/TeamSelector.js +0 -55
- package/dist/ui/ToolSelector.d.ts +0 -8
- package/dist/ui/ToolSelector.js +0 -53
- package/dist/ui/statusFormatter.spec.d.ts +0 -1
- package/dist/ui/statusFormatter.spec.js +0 -58
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import ora from 'ora';
|
|
5
|
-
import output from '../../../lib/output.js';
|
|
6
|
-
import { ArkDevToolAnalyzer } from '../../../lib/dev/tools/analyzer.js';
|
|
7
|
-
import { toMCPTool } from '../../../lib/dev/tools/mcp-types.js';
|
|
8
|
-
async function checkTool(toolPath, options) {
|
|
9
|
-
const absolutePath = path.resolve(toolPath);
|
|
10
|
-
const analyzer = new ArkDevToolAnalyzer();
|
|
11
|
-
const isJson = options.output === 'json';
|
|
12
|
-
// Build up result object as we go
|
|
13
|
-
const result = {
|
|
14
|
-
path: absolutePath,
|
|
15
|
-
projectRoot: null,
|
|
16
|
-
error: null,
|
|
17
|
-
platform: null,
|
|
18
|
-
projectType: null,
|
|
19
|
-
projectName: null,
|
|
20
|
-
projectVersion: null,
|
|
21
|
-
hasFastmcp: false,
|
|
22
|
-
fastmcpVersion: null,
|
|
23
|
-
tools: [],
|
|
24
|
-
toolDiscoveryError: null,
|
|
25
|
-
};
|
|
26
|
-
if (!isJson) {
|
|
27
|
-
console.log();
|
|
28
|
-
}
|
|
29
|
-
// Single spinner for all analysis (skip for JSON output)
|
|
30
|
-
const analyzeSpinner = isJson
|
|
31
|
-
? null
|
|
32
|
-
: ora(`analyzing ${absolutePath}`).start();
|
|
33
|
-
// Small delay to let user see what's happening (skip for JSON)
|
|
34
|
-
if (!isJson) {
|
|
35
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
36
|
-
}
|
|
37
|
-
// Collect all information
|
|
38
|
-
const project = await analyzer.discoverProject(absolutePath);
|
|
39
|
-
if (!project || !project.exists) {
|
|
40
|
-
result.error = 'path not found';
|
|
41
|
-
if (isJson) {
|
|
42
|
-
console.log(JSON.stringify(result, null, 2));
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
analyzeSpinner.stop();
|
|
46
|
-
output.error(`path not found: ${absolutePath}`);
|
|
47
|
-
}
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
if (!project.is_directory) {
|
|
51
|
-
result.error = 'path is not a directory';
|
|
52
|
-
if (isJson) {
|
|
53
|
-
console.log(JSON.stringify(result, null, 2));
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
analyzeSpinner.stop();
|
|
57
|
-
output.error(`path is not a directory: ${absolutePath}`);
|
|
58
|
-
}
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
if (!project.platform) {
|
|
62
|
-
result.error =
|
|
63
|
-
'platform unknown - no pyproject.toml or requirements.txt found';
|
|
64
|
-
if (isJson) {
|
|
65
|
-
console.log(JSON.stringify(result, null, 2));
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
analyzeSpinner.stop();
|
|
69
|
-
output.error(`no pyproject.toml or requirements.txt found in: ${absolutePath}`);
|
|
70
|
-
}
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
// Update result with project info
|
|
74
|
-
result.platform = project.platform;
|
|
75
|
-
result.projectType = project.project_type;
|
|
76
|
-
result.projectName = project.project_name;
|
|
77
|
-
result.projectVersion = project.project_version;
|
|
78
|
-
result.hasFastmcp = project.has_fastmcp;
|
|
79
|
-
result.fastmcpVersion = project.fastmcp_version;
|
|
80
|
-
result.projectRoot = absolutePath; // Store the project root
|
|
81
|
-
// Discover tools recursively in the project
|
|
82
|
-
const rawTools = [];
|
|
83
|
-
try {
|
|
84
|
-
const projectTools = await analyzer.findProjectTools(absolutePath);
|
|
85
|
-
if (projectTools && projectTools.tools) {
|
|
86
|
-
rawTools.push(...projectTools.tools);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
result.toolDiscoveryError =
|
|
91
|
-
error instanceof Error ? error.message : 'Unknown error';
|
|
92
|
-
}
|
|
93
|
-
// Store tools in the appropriate format
|
|
94
|
-
result.tools = isJson ? rawTools.map(toMCPTool) : rawTools;
|
|
95
|
-
if (isJson) {
|
|
96
|
-
// Output raw JSON
|
|
97
|
-
console.log(JSON.stringify(result, null, 2));
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
analyzeSpinner.succeed('analysis complete');
|
|
101
|
-
console.log();
|
|
102
|
-
// Display summary in cleaner format
|
|
103
|
-
output.section(path.basename(absolutePath));
|
|
104
|
-
// Platform
|
|
105
|
-
output.statusCheck('found', 'platform', result.platform);
|
|
106
|
-
// Project type with name and version in gray
|
|
107
|
-
let projectDetails = '';
|
|
108
|
-
if (result.projectName) {
|
|
109
|
-
projectDetails = result.projectName;
|
|
110
|
-
if (result.projectVersion) {
|
|
111
|
-
projectDetails += ` v${result.projectVersion}`;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
output.statusCheck('found', 'project', result.projectType, projectDetails);
|
|
115
|
-
// Framework with version in gray
|
|
116
|
-
if (result.hasFastmcp) {
|
|
117
|
-
const fastmcpDetails = result.fastmcpVersion
|
|
118
|
-
? `v${result.fastmcpVersion}`
|
|
119
|
-
: undefined;
|
|
120
|
-
output.statusCheck('found', 'framework', 'fastmcp', fastmcpDetails);
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
output.statusCheck('missing', 'framework', 'fastmcp');
|
|
124
|
-
}
|
|
125
|
-
// Tools with details
|
|
126
|
-
output.statusCheck('found', 'tools', result.tools.length.toString());
|
|
127
|
-
if (result.tools.length > 0) {
|
|
128
|
-
for (const tool of result.tools) {
|
|
129
|
-
const description = tool.docstring ? tool.docstring.split('\n')[0] : '';
|
|
130
|
-
console.log(chalk.gray(` - ${tool.name}: ${description}`));
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
export function createCheckCommand() {
|
|
135
|
-
const checkCommand = new Command('check');
|
|
136
|
-
checkCommand
|
|
137
|
-
.description('Check the status of an MCP tool project')
|
|
138
|
-
.argument('<path>', 'Path to the tool directory')
|
|
139
|
-
.option('-o, --output <format>', 'Output format (json)', 'text')
|
|
140
|
-
.action(checkTool);
|
|
141
|
-
return checkCommand;
|
|
142
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import yaml from 'yaml';
|
|
7
|
-
import inquirer from 'inquirer';
|
|
8
|
-
import output from '../../../lib/output.js';
|
|
9
|
-
async function cleanTool(toolPath, options = {}) {
|
|
10
|
-
const absolutePath = path.resolve(toolPath);
|
|
11
|
-
const arkConfigPath = path.join(absolutePath, '.ark.yaml');
|
|
12
|
-
// Check if .ark.yaml exists
|
|
13
|
-
if (!fs.existsSync(arkConfigPath)) {
|
|
14
|
-
output.error('.ark.yaml not found. Run "ark dev tool init" first.');
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
// Load .ark.yaml to validate it's parseable
|
|
18
|
-
yaml.parse(fs.readFileSync(arkConfigPath, 'utf-8'));
|
|
19
|
-
// Find template directory
|
|
20
|
-
const currentFile = fileURLToPath(import.meta.url);
|
|
21
|
-
const distDir = path.dirname(path.dirname(path.dirname(path.dirname(currentFile)))); // Goes to dist/
|
|
22
|
-
const arkCliDir = path.dirname(distDir); // Goes to ark-cli/
|
|
23
|
-
const templateDir = path.join(arkCliDir, 'templates', 'python-mcp-tool');
|
|
24
|
-
if (!fs.existsSync(templateDir)) {
|
|
25
|
-
output.error('Template directory not found');
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
// Collect all template-based files (not directories)
|
|
29
|
-
const allTemplateFiles = [];
|
|
30
|
-
const dirsToCheck = new Set();
|
|
31
|
-
collectTemplateFiles(templateDir, absolutePath, allTemplateFiles, dirsToCheck);
|
|
32
|
-
// Filter to only existing files
|
|
33
|
-
const filesToClean = allTemplateFiles.filter((file) => {
|
|
34
|
-
const fullPath = path.join(absolutePath, file);
|
|
35
|
-
return fs.existsSync(fullPath);
|
|
36
|
-
});
|
|
37
|
-
if (filesToClean.length === 0) {
|
|
38
|
-
console.log(chalk.green('No template-generated files found to clean.'));
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
console.log(chalk.yellow(`Found ${filesToClean.length} template-generated file(s) to potentially remove:`));
|
|
42
|
-
// Display the list of files
|
|
43
|
-
filesToClean.forEach((file) => {
|
|
44
|
-
console.log(chalk.gray(` - ${file}`));
|
|
45
|
-
});
|
|
46
|
-
console.log();
|
|
47
|
-
let removedCount = 0;
|
|
48
|
-
let skippedCount = 0;
|
|
49
|
-
// First, delete individual files
|
|
50
|
-
for (const file of filesToClean) {
|
|
51
|
-
const fullPath = path.join(absolutePath, file);
|
|
52
|
-
// Ask for confirmation unless --yes flag is set
|
|
53
|
-
let shouldDelete = options.yes;
|
|
54
|
-
if (!shouldDelete) {
|
|
55
|
-
const answer = await inquirer.prompt([
|
|
56
|
-
{
|
|
57
|
-
type: 'confirm',
|
|
58
|
-
name: 'delete',
|
|
59
|
-
message: `Delete file ${chalk.cyan(file)}?`,
|
|
60
|
-
default: false,
|
|
61
|
-
},
|
|
62
|
-
]);
|
|
63
|
-
shouldDelete = answer.delete;
|
|
64
|
-
}
|
|
65
|
-
if (shouldDelete) {
|
|
66
|
-
try {
|
|
67
|
-
fs.unlinkSync(fullPath);
|
|
68
|
-
console.log(chalk.green(` ✓ Removed ${file}`));
|
|
69
|
-
removedCount++;
|
|
70
|
-
}
|
|
71
|
-
catch (err) {
|
|
72
|
-
console.log(chalk.red(` ✗ Failed to remove ${file}: ${err instanceof Error ? err.message : 'Unknown error'}`));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
console.log(chalk.gray(` - Skipped ${file}`));
|
|
77
|
-
skippedCount++;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// Now check for empty directories and offer to delete them
|
|
81
|
-
const sortedDirs = Array.from(dirsToCheck).sort((a, b) => b.length - a.length); // Process deepest dirs first
|
|
82
|
-
for (const dir of sortedDirs) {
|
|
83
|
-
const fullPath = path.join(absolutePath, dir);
|
|
84
|
-
// Check if directory exists and is empty
|
|
85
|
-
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {
|
|
86
|
-
const contents = fs.readdirSync(fullPath);
|
|
87
|
-
if (contents.length === 0) {
|
|
88
|
-
// Directory is empty, ask to delete it
|
|
89
|
-
let shouldDelete = options.yes;
|
|
90
|
-
if (!shouldDelete) {
|
|
91
|
-
const answer = await inquirer.prompt([
|
|
92
|
-
{
|
|
93
|
-
type: 'confirm',
|
|
94
|
-
name: 'delete',
|
|
95
|
-
message: `Delete empty directory ${chalk.cyan(dir)}?`,
|
|
96
|
-
default: false,
|
|
97
|
-
},
|
|
98
|
-
]);
|
|
99
|
-
shouldDelete = answer.delete;
|
|
100
|
-
}
|
|
101
|
-
if (shouldDelete) {
|
|
102
|
-
try {
|
|
103
|
-
fs.rmdirSync(fullPath);
|
|
104
|
-
console.log(chalk.green(` ✓ Removed empty directory ${dir}`));
|
|
105
|
-
}
|
|
106
|
-
catch (err) {
|
|
107
|
-
console.log(chalk.red(` ✗ Failed to remove directory ${dir}: ${err instanceof Error ? err.message : 'Unknown error'}`));
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
console.log(chalk.gray(` - Kept empty directory ${dir}`));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
console.log();
|
|
117
|
-
if (removedCount > 0) {
|
|
118
|
-
console.log(chalk.green(`✓ Removed ${removedCount} file(s)`));
|
|
119
|
-
}
|
|
120
|
-
if (skippedCount > 0) {
|
|
121
|
-
console.log(chalk.gray(`Skipped ${skippedCount} file(s)`));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function collectTemplateFiles(sourceDir, targetDir, files, dirsToCheck, relativePath = '') {
|
|
125
|
-
const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
|
|
126
|
-
for (const entry of entries) {
|
|
127
|
-
if (entry.isDirectory()) {
|
|
128
|
-
// Track directory for later checking
|
|
129
|
-
const dirPath = path.join(relativePath, entry.name);
|
|
130
|
-
dirsToCheck.add(dirPath);
|
|
131
|
-
// Recursively collect from subdirectory
|
|
132
|
-
const subSourceDir = path.join(sourceDir, entry.name);
|
|
133
|
-
collectTemplateFiles(subSourceDir, targetDir, files, dirsToCheck, dirPath);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
// Check if it's a template file
|
|
137
|
-
const targetFileName = entry.name.startsWith('template.')
|
|
138
|
-
? entry.name.replace('template.', '')
|
|
139
|
-
: entry.name;
|
|
140
|
-
const filePath = path.join(relativePath, targetFileName);
|
|
141
|
-
files.push(filePath);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
export function createCleanCommand() {
|
|
146
|
-
const cleanCommand = new Command('clean');
|
|
147
|
-
cleanCommand
|
|
148
|
-
.description('Remove template-generated files from an MCP tool project')
|
|
149
|
-
.argument('<path>', 'Path to the tool directory')
|
|
150
|
-
.option('-y, --yes', 'Skip confirmation prompts and delete all files')
|
|
151
|
-
.action(cleanTool);
|
|
152
|
-
return cleanCommand;
|
|
153
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { generateProjectFiles } from './shared.js';
|
|
5
|
-
async function generateTool(toolPath, options = {}) {
|
|
6
|
-
const absolutePath = path.resolve(toolPath);
|
|
7
|
-
if (!options.dryRun) {
|
|
8
|
-
if (options.overwrite) {
|
|
9
|
-
console.log(chalk.yellow('Overwrite mode: existing files will be replaced'));
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
await generateProjectFiles(absolutePath, {
|
|
13
|
-
interactive: !options.dryRun,
|
|
14
|
-
dryRun: options.dryRun,
|
|
15
|
-
overwrite: options.overwrite,
|
|
16
|
-
});
|
|
17
|
-
// Next steps message removed - files are ready to use
|
|
18
|
-
}
|
|
19
|
-
export function createGenerateCommand() {
|
|
20
|
-
const generateCommand = new Command('generate');
|
|
21
|
-
generateCommand
|
|
22
|
-
.description('Generate project files (Dockerfile, .dockerignore, etc.) from templates')
|
|
23
|
-
.argument('<path>', 'Path to the tool directory')
|
|
24
|
-
.option('--dry-run', 'Show generated template files without creating them')
|
|
25
|
-
.option('--overwrite', 'Overwrite existing files')
|
|
26
|
-
.action(generateTool);
|
|
27
|
-
return generateCommand;
|
|
28
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { createCheckCommand } from './check.js';
|
|
3
|
-
import { createInitCommand } from './init.js';
|
|
4
|
-
import { createGenerateCommand } from './generate.js';
|
|
5
|
-
import { createCleanCommand } from './clean.js';
|
|
6
|
-
export function createToolCommand() {
|
|
7
|
-
const toolCommand = new Command('tool');
|
|
8
|
-
toolCommand.description('MCP tool development utilities');
|
|
9
|
-
toolCommand.addCommand(createCheckCommand());
|
|
10
|
-
toolCommand.addCommand(createInitCommand());
|
|
11
|
-
toolCommand.addCommand(createGenerateCommand());
|
|
12
|
-
toolCommand.addCommand(createCleanCommand());
|
|
13
|
-
return toolCommand;
|
|
14
|
-
}
|
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import ora from 'ora';
|
|
5
|
-
import inquirer from 'inquirer';
|
|
6
|
-
import fs from 'fs';
|
|
7
|
-
import yaml from 'yaml';
|
|
8
|
-
import output from '../../../lib/output.js';
|
|
9
|
-
import { ArkDevToolAnalyzer } from '../../../lib/dev/tools/analyzer.js';
|
|
10
|
-
import { generateProjectFiles } from './shared.js';
|
|
11
|
-
async function initTool(toolPath) {
|
|
12
|
-
const absolutePath = path.resolve(toolPath);
|
|
13
|
-
const analyzer = new ArkDevToolAnalyzer();
|
|
14
|
-
// Check if .ark.yaml already exists
|
|
15
|
-
const arkConfigPath = path.join(absolutePath, '.ark.yaml');
|
|
16
|
-
if (fs.existsSync(arkConfigPath)) {
|
|
17
|
-
const { overwrite } = await inquirer.prompt([
|
|
18
|
-
{
|
|
19
|
-
type: 'confirm',
|
|
20
|
-
name: 'overwrite',
|
|
21
|
-
message: chalk.yellow('.ark.yaml already exists. Overwrite?'),
|
|
22
|
-
default: false,
|
|
23
|
-
},
|
|
24
|
-
]);
|
|
25
|
-
if (!overwrite) {
|
|
26
|
-
console.log(chalk.gray('Initialization cancelled'));
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
// Initialize configuration object
|
|
31
|
-
const arkConfig = {
|
|
32
|
-
version: '1.0',
|
|
33
|
-
project: {},
|
|
34
|
-
};
|
|
35
|
-
// Step 1: Check if path exists and is a directory
|
|
36
|
-
const checkSpinner = ora('Checking project path...').start();
|
|
37
|
-
const project = await analyzer.discoverProject(absolutePath);
|
|
38
|
-
if (!project || !project.exists) {
|
|
39
|
-
checkSpinner.fail('Path not found');
|
|
40
|
-
output.error(`Path not found: ${absolutePath}`);
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
if (!project.is_directory) {
|
|
44
|
-
checkSpinner.fail('Path is not a directory');
|
|
45
|
-
output.error(`Path is not a directory: ${absolutePath}`);
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
checkSpinner.succeed('Project path verified');
|
|
49
|
-
arkConfig.project.path = absolutePath;
|
|
50
|
-
// Step 2: Detect platform
|
|
51
|
-
console.log();
|
|
52
|
-
if (!project.platform) {
|
|
53
|
-
console.log(chalk.yellow('⚠ No Python project files found (pyproject.toml or requirements.txt)'));
|
|
54
|
-
const { continueWithoutProject } = await inquirer.prompt([
|
|
55
|
-
{
|
|
56
|
-
type: 'confirm',
|
|
57
|
-
name: 'continueWithoutProject',
|
|
58
|
-
message: 'Continue without project files?',
|
|
59
|
-
default: false,
|
|
60
|
-
},
|
|
61
|
-
]);
|
|
62
|
-
if (!continueWithoutProject) {
|
|
63
|
-
console.log(chalk.gray('Initialization cancelled'));
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
// Set defaults but don't create anything
|
|
67
|
-
arkConfig.project.platform = 'python3';
|
|
68
|
-
arkConfig.project.type = 'none';
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
console.log(chalk.green(`✓ Detected platform: ${chalk.white(project.platform)}`));
|
|
72
|
-
console.log(chalk.gray(` Found from: ${project.project_type === 'pyproject' ? 'pyproject.toml' : 'requirements.txt'}`));
|
|
73
|
-
const { confirmPlatform } = await inquirer.prompt([
|
|
74
|
-
{
|
|
75
|
-
type: 'confirm',
|
|
76
|
-
name: 'confirmPlatform',
|
|
77
|
-
message: `Confirm platform is ${project.platform}?`,
|
|
78
|
-
default: true,
|
|
79
|
-
},
|
|
80
|
-
]);
|
|
81
|
-
if (!confirmPlatform) {
|
|
82
|
-
console.log(chalk.gray('Initialization cancelled'));
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
arkConfig.project.platform = project.platform;
|
|
86
|
-
arkConfig.project.type = project.project_type;
|
|
87
|
-
// Step 3: Project metadata
|
|
88
|
-
if (project.project_name) {
|
|
89
|
-
console.log();
|
|
90
|
-
console.log(chalk.green(`✓ Found project name: ${chalk.white(project.project_name)}`));
|
|
91
|
-
console.log(chalk.gray(` From: pyproject.toml [project.name]`));
|
|
92
|
-
const { confirmName } = await inquirer.prompt([
|
|
93
|
-
{
|
|
94
|
-
type: 'confirm',
|
|
95
|
-
name: 'confirmName',
|
|
96
|
-
message: `Save project name as "${project.project_name}"?`,
|
|
97
|
-
default: true,
|
|
98
|
-
},
|
|
99
|
-
]);
|
|
100
|
-
if (confirmName) {
|
|
101
|
-
arkConfig.project.name = project.project_name;
|
|
102
|
-
}
|
|
103
|
-
if (project.project_version) {
|
|
104
|
-
console.log();
|
|
105
|
-
console.log(chalk.green(`✓ Found project version: ${chalk.white(project.project_version)}`));
|
|
106
|
-
console.log(chalk.gray(` From: pyproject.toml [project.version]`));
|
|
107
|
-
const { confirmVersion } = await inquirer.prompt([
|
|
108
|
-
{
|
|
109
|
-
type: 'confirm',
|
|
110
|
-
name: 'confirmVersion',
|
|
111
|
-
message: `Save project version as "${project.project_version}"?`,
|
|
112
|
-
default: true,
|
|
113
|
-
},
|
|
114
|
-
]);
|
|
115
|
-
if (confirmVersion) {
|
|
116
|
-
arkConfig.project.version = project.project_version;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
// Step 4: Check for FastMCP
|
|
121
|
-
console.log();
|
|
122
|
-
if (project.has_fastmcp) {
|
|
123
|
-
console.log(chalk.green(`✓ Found FastMCP framework: ${chalk.white(`v${project.fastmcp_version || 'unknown'}`)}`));
|
|
124
|
-
console.log(chalk.gray(` From: ${project.project_type === 'pyproject' ? 'pyproject.toml dependencies' : 'requirements.txt'}`));
|
|
125
|
-
const { confirmFramework } = await inquirer.prompt([
|
|
126
|
-
{
|
|
127
|
-
type: 'confirm',
|
|
128
|
-
name: 'confirmFramework',
|
|
129
|
-
message: `Save framework as FastMCP v${project.fastmcp_version}?`,
|
|
130
|
-
default: true,
|
|
131
|
-
},
|
|
132
|
-
]);
|
|
133
|
-
if (confirmFramework) {
|
|
134
|
-
arkConfig.project.framework = 'fastmcp';
|
|
135
|
-
arkConfig.project.frameworkVersion = project.fastmcp_version;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
console.log(chalk.yellow('⚠ FastMCP not found in dependencies'));
|
|
140
|
-
console.log(chalk.gray(` Checked: ${project.project_type === 'pyproject' ? 'pyproject.toml' : 'requirements.txt'}`));
|
|
141
|
-
const { recordMissing } = await inquirer.prompt([
|
|
142
|
-
{
|
|
143
|
-
type: 'confirm',
|
|
144
|
-
name: 'recordMissing',
|
|
145
|
-
message: 'Record that FastMCP is not installed?',
|
|
146
|
-
default: true,
|
|
147
|
-
},
|
|
148
|
-
]);
|
|
149
|
-
if (recordMissing) {
|
|
150
|
-
arkConfig.project.framework = 'none';
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
// Step 5: MCP Transport Configuration (only if FastMCP is detected)
|
|
155
|
-
if (arkConfig.project.framework === 'fastmcp') {
|
|
156
|
-
// Try to detect transport from existing code
|
|
157
|
-
let detectedTransport = null;
|
|
158
|
-
const pythonFiles = fs
|
|
159
|
-
.readdirSync(absolutePath)
|
|
160
|
-
.filter((f) => f.endsWith('.py'));
|
|
161
|
-
for (const file of pythonFiles) {
|
|
162
|
-
const content = fs.readFileSync(path.join(absolutePath, file), 'utf-8');
|
|
163
|
-
if (content.includes('transport="sse"')) {
|
|
164
|
-
detectedTransport = 'sse';
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
else if (content.includes('transport="http"')) {
|
|
168
|
-
detectedTransport = 'http';
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
else if (content.includes('transport="stdio"') ||
|
|
172
|
-
content.includes('.run()')) {
|
|
173
|
-
detectedTransport = 'stdio';
|
|
174
|
-
break;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (detectedTransport) {
|
|
178
|
-
console.log(chalk.green(`✓ MCP: Detected transport ${chalk.white(detectedTransport)}`));
|
|
179
|
-
const { confirmTransport } = await inquirer.prompt([
|
|
180
|
-
{
|
|
181
|
-
type: 'confirm',
|
|
182
|
-
name: 'confirmTransport',
|
|
183
|
-
message: `Use transport "${detectedTransport}"?`,
|
|
184
|
-
default: true,
|
|
185
|
-
},
|
|
186
|
-
]);
|
|
187
|
-
if (confirmTransport) {
|
|
188
|
-
arkConfig.mcp = { transport: detectedTransport };
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
// If not detected or not confirmed, ask
|
|
192
|
-
if (!arkConfig.mcp) {
|
|
193
|
-
const { transport } = await inquirer.prompt([
|
|
194
|
-
{
|
|
195
|
-
type: 'list',
|
|
196
|
-
name: 'transport',
|
|
197
|
-
message: 'Select MCP transport for deployment:',
|
|
198
|
-
choices: [
|
|
199
|
-
{
|
|
200
|
-
name: 'SSE (Server-Sent Events) - Recommended for Kubernetes',
|
|
201
|
-
value: 'sse',
|
|
202
|
-
short: 'SSE',
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
name: 'HTTP - Stateless request/response',
|
|
206
|
-
value: 'http',
|
|
207
|
-
short: 'HTTP',
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
name: 'STDIO - Standard input/output for CLI tools',
|
|
211
|
-
value: 'stdio',
|
|
212
|
-
short: 'STDIO',
|
|
213
|
-
},
|
|
214
|
-
],
|
|
215
|
-
default: 'sse',
|
|
216
|
-
},
|
|
217
|
-
]);
|
|
218
|
-
arkConfig.mcp = { transport };
|
|
219
|
-
}
|
|
220
|
-
// Ask for port if not stdio
|
|
221
|
-
if (arkConfig.mcp.transport !== 'stdio') {
|
|
222
|
-
const { port } = await inquirer.prompt([
|
|
223
|
-
{
|
|
224
|
-
type: 'input',
|
|
225
|
-
name: 'port',
|
|
226
|
-
message: 'MCP server port:',
|
|
227
|
-
default: '8080',
|
|
228
|
-
validate: (input) => {
|
|
229
|
-
const num = parseInt(input);
|
|
230
|
-
if (isNaN(num) || num < 1 || num > 65535) {
|
|
231
|
-
return 'Please enter a valid port number (1-65535)';
|
|
232
|
-
}
|
|
233
|
-
return true;
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
]);
|
|
237
|
-
arkConfig.mcp.port = parseInt(port);
|
|
238
|
-
// Show configuration snippet
|
|
239
|
-
console.log();
|
|
240
|
-
console.log(chalk.yellow('📝 Add this to your MCP server code:'));
|
|
241
|
-
console.log(chalk.gray('─'.repeat(40)));
|
|
242
|
-
if (arkConfig.mcp.transport === 'sse') {
|
|
243
|
-
console.log(chalk.green(`if __name__ == "__main__":
|
|
244
|
-
import os
|
|
245
|
-
port = int(os.environ.get("PORT", "${arkConfig.mcp.port}"))
|
|
246
|
-
mcp.run(transport="sse", host="0.0.0.0", port=port)`));
|
|
247
|
-
}
|
|
248
|
-
else if (arkConfig.mcp.transport === 'http') {
|
|
249
|
-
console.log(chalk.green(`if __name__ == "__main__":
|
|
250
|
-
import os
|
|
251
|
-
port = int(os.environ.get("PORT", "${arkConfig.mcp.port}"))
|
|
252
|
-
mcp.run(transport="http", host="0.0.0.0", port=port, path="/")`));
|
|
253
|
-
}
|
|
254
|
-
console.log(chalk.gray('─'.repeat(40)));
|
|
255
|
-
console.log(chalk.dim('The PORT environment variable will be set by Kubernetes'));
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
// Step 6: Write .ark.yaml
|
|
259
|
-
console.log();
|
|
260
|
-
const writeSpinner = ora('Writing .ark.yaml configuration...').start();
|
|
261
|
-
try {
|
|
262
|
-
const yamlContent = yaml.stringify(arkConfig);
|
|
263
|
-
fs.writeFileSync(arkConfigPath, yamlContent, 'utf-8');
|
|
264
|
-
writeSpinner.succeed('.ark.yaml created successfully');
|
|
265
|
-
console.log();
|
|
266
|
-
console.log(chalk.blue('Configuration Summary:'));
|
|
267
|
-
console.log(chalk.gray('─'.repeat(40)));
|
|
268
|
-
console.log(`Platform: ${arkConfig.project.platform}`);
|
|
269
|
-
console.log(`Type: ${arkConfig.project.type}`);
|
|
270
|
-
if (arkConfig.project.name) {
|
|
271
|
-
console.log(`Name: ${arkConfig.project.name}`);
|
|
272
|
-
console.log(`Version: ${arkConfig.project.version || 'unknown'}`);
|
|
273
|
-
}
|
|
274
|
-
if (arkConfig.project.framework) {
|
|
275
|
-
console.log(`Framework: ${arkConfig.project.framework}`);
|
|
276
|
-
}
|
|
277
|
-
if (arkConfig.mcp) {
|
|
278
|
-
console.log(`Transport: ${arkConfig.mcp.transport}`);
|
|
279
|
-
if (arkConfig.mcp.port) {
|
|
280
|
-
console.log(`Port: ${arkConfig.mcp.port}`);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
console.log(chalk.gray('─'.repeat(40)));
|
|
284
|
-
console.log();
|
|
285
|
-
console.log(chalk.green('✓ Initialization complete!'));
|
|
286
|
-
// Step 6: Ask about generating project files
|
|
287
|
-
console.log();
|
|
288
|
-
const { generateFiles } = await inquirer.prompt([
|
|
289
|
-
{
|
|
290
|
-
type: 'confirm',
|
|
291
|
-
name: 'generateFiles',
|
|
292
|
-
message: 'Generate project files (Dockerfile, .dockerignore, etc.)?',
|
|
293
|
-
default: true,
|
|
294
|
-
},
|
|
295
|
-
]);
|
|
296
|
-
if (generateFiles) {
|
|
297
|
-
console.log();
|
|
298
|
-
await generateProjectFiles(absolutePath, {
|
|
299
|
-
interactive: true,
|
|
300
|
-
dryRun: false,
|
|
301
|
-
overwrite: false,
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
console.log();
|
|
305
|
-
console.log(' • Edit ' + chalk.cyan('.ark.yaml') + ' to update configuration');
|
|
306
|
-
}
|
|
307
|
-
catch (error) {
|
|
308
|
-
writeSpinner.fail('Failed to write .ark.yaml');
|
|
309
|
-
output.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
310
|
-
process.exit(1);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
export function createInitCommand() {
|
|
314
|
-
const initCommand = new Command('init');
|
|
315
|
-
initCommand
|
|
316
|
-
.description('Initialize an MCP tool project with .ark.yaml configuration')
|
|
317
|
-
.argument('<path>', 'Path to the tool directory')
|
|
318
|
-
.action(initTool);
|
|
319
|
-
return initCommand;
|
|
320
|
-
}
|