@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,559 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import ora from 'ora';
|
|
6
|
-
import inquirer from 'inquirer';
|
|
7
|
-
import fs from 'fs';
|
|
8
|
-
import yaml from 'yaml';
|
|
9
|
-
import { execSync } from 'child_process';
|
|
10
|
-
import output from '../../lib/output.js';
|
|
11
|
-
import { ArkDevToolAnalyzer } from '../../lib/dev/tools/analyzer.js';
|
|
12
|
-
import { toMCPTool } from '../../lib/dev/tools/mcp-types.js';
|
|
13
|
-
async function statusTool(toolPath, options) {
|
|
14
|
-
const absolutePath = path.resolve(toolPath);
|
|
15
|
-
const analyzer = new ArkDevToolAnalyzer();
|
|
16
|
-
const isJson = options.output === 'json';
|
|
17
|
-
// Build up result object as we go
|
|
18
|
-
const result = {
|
|
19
|
-
path: absolutePath,
|
|
20
|
-
projectRoot: null,
|
|
21
|
-
error: null,
|
|
22
|
-
platform: null,
|
|
23
|
-
projectType: null,
|
|
24
|
-
projectName: null,
|
|
25
|
-
projectVersion: null,
|
|
26
|
-
hasFastmcp: false,
|
|
27
|
-
fastmcpVersion: null,
|
|
28
|
-
tools: [],
|
|
29
|
-
toolDiscoveryError: null
|
|
30
|
-
};
|
|
31
|
-
if (!isJson) {
|
|
32
|
-
console.log();
|
|
33
|
-
}
|
|
34
|
-
// Single spinner for all analysis (skip for JSON output)
|
|
35
|
-
const analyzeSpinner = isJson ? null : ora(`analyzing ${absolutePath}`).start();
|
|
36
|
-
// Small delay to let user see what's happening (skip for JSON)
|
|
37
|
-
if (!isJson) {
|
|
38
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
39
|
-
}
|
|
40
|
-
// Collect all information
|
|
41
|
-
const project = await analyzer.discoverProject(absolutePath);
|
|
42
|
-
if (!project || !project.exists) {
|
|
43
|
-
result.error = 'path not found';
|
|
44
|
-
if (isJson) {
|
|
45
|
-
console.log(JSON.stringify(result, null, 2));
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
analyzeSpinner.stop();
|
|
49
|
-
output.error(`path not found: ${absolutePath}`);
|
|
50
|
-
}
|
|
51
|
-
process.exit(1);
|
|
52
|
-
}
|
|
53
|
-
if (!project.is_directory) {
|
|
54
|
-
result.error = 'path is not a directory';
|
|
55
|
-
if (isJson) {
|
|
56
|
-
console.log(JSON.stringify(result, null, 2));
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
analyzeSpinner.stop();
|
|
60
|
-
output.error(`path is not a directory: ${absolutePath}`);
|
|
61
|
-
}
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
if (!project.platform) {
|
|
65
|
-
result.error = 'platform unknown - no pyproject.toml or requirements.txt found';
|
|
66
|
-
if (isJson) {
|
|
67
|
-
console.log(JSON.stringify(result, null, 2));
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
analyzeSpinner.stop();
|
|
71
|
-
output.error(`no pyproject.toml or requirements.txt found in: ${absolutePath}`);
|
|
72
|
-
}
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
// Update result with project info
|
|
76
|
-
result.platform = project.platform;
|
|
77
|
-
result.projectType = project.project_type;
|
|
78
|
-
result.projectName = project.project_name;
|
|
79
|
-
result.projectVersion = project.project_version;
|
|
80
|
-
result.hasFastmcp = project.has_fastmcp;
|
|
81
|
-
result.fastmcpVersion = project.fastmcp_version;
|
|
82
|
-
result.projectRoot = absolutePath; // Store the project root
|
|
83
|
-
// Discover tools recursively in the project
|
|
84
|
-
const rawTools = [];
|
|
85
|
-
try {
|
|
86
|
-
const projectTools = await analyzer.findProjectTools(absolutePath);
|
|
87
|
-
if (projectTools && projectTools.tools) {
|
|
88
|
-
rawTools.push(...projectTools.tools);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
catch (error) {
|
|
92
|
-
result.toolDiscoveryError = error instanceof Error ? error.message : 'Unknown error';
|
|
93
|
-
}
|
|
94
|
-
// Store tools in the appropriate format
|
|
95
|
-
result.tools = isJson ? rawTools.map(toMCPTool) : rawTools;
|
|
96
|
-
if (isJson) {
|
|
97
|
-
// Output raw JSON
|
|
98
|
-
console.log(JSON.stringify(result, null, 2));
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
analyzeSpinner.succeed('analysis complete');
|
|
102
|
-
console.log();
|
|
103
|
-
// Display summary in cleaner format
|
|
104
|
-
output.section(path.basename(absolutePath));
|
|
105
|
-
// Platform
|
|
106
|
-
output.statusCheck('found', 'platform', result.platform);
|
|
107
|
-
// Project type with name and version in gray
|
|
108
|
-
let projectDetails = '';
|
|
109
|
-
if (result.projectName) {
|
|
110
|
-
projectDetails = result.projectName;
|
|
111
|
-
if (result.projectVersion) {
|
|
112
|
-
projectDetails += ` v${result.projectVersion}`;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
output.statusCheck('found', 'project', result.projectType, projectDetails);
|
|
116
|
-
// Framework with version in gray
|
|
117
|
-
if (result.hasFastmcp) {
|
|
118
|
-
const fastmcpDetails = result.fastmcpVersion ? `v${result.fastmcpVersion}` : undefined;
|
|
119
|
-
output.statusCheck('found', 'framework', 'fastmcp', fastmcpDetails);
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
output.statusCheck('missing', 'framework', 'fastmcp');
|
|
123
|
-
}
|
|
124
|
-
// Tools with details
|
|
125
|
-
output.statusCheck('found', 'tools', result.tools.length.toString());
|
|
126
|
-
if (result.tools.length > 0) {
|
|
127
|
-
for (const tool of result.tools) {
|
|
128
|
-
const description = tool.docstring ? tool.docstring.split('\n')[0] : '';
|
|
129
|
-
console.log(chalk.gray(` - ${tool.name}: ${description}`));
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
async function generateProjectFiles(toolPath, options = { interactive: true, dryRun: false, overwrite: false }) {
|
|
134
|
-
const absolutePath = path.resolve(toolPath);
|
|
135
|
-
const arkConfigPath = path.join(absolutePath, '.ark.yaml');
|
|
136
|
-
// Check if .ark.yaml exists
|
|
137
|
-
if (!fs.existsSync(arkConfigPath)) {
|
|
138
|
-
output.error('.ark.yaml not found. Run "ark dev tool init" first.');
|
|
139
|
-
process.exit(1);
|
|
140
|
-
}
|
|
141
|
-
// Load .ark.yaml
|
|
142
|
-
const arkConfig = yaml.parse(fs.readFileSync(arkConfigPath, 'utf-8'));
|
|
143
|
-
const generateSpinner = options.dryRun ? null : ora('Generating project files...').start();
|
|
144
|
-
try {
|
|
145
|
-
// Find template directory - templates are in the source tree
|
|
146
|
-
const currentFile = fileURLToPath(import.meta.url);
|
|
147
|
-
const distDir = path.dirname(path.dirname(path.dirname(currentFile))); // Goes to dist/
|
|
148
|
-
const arkCliDir = path.dirname(distDir); // Goes to ark-cli/
|
|
149
|
-
const templateDir = path.join(arkCliDir, 'templates', 'python-mcp-tool');
|
|
150
|
-
if (!fs.existsSync(templateDir)) {
|
|
151
|
-
if (generateSpinner) {
|
|
152
|
-
generateSpinner.fail('Template directory not found');
|
|
153
|
-
}
|
|
154
|
-
console.log(chalk.yellow('Could not find templates at: ' + templateDir));
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
// Find all template files (starting with 'template.')
|
|
158
|
-
const templateFiles = fs.readdirSync(templateDir)
|
|
159
|
-
.filter(f => f.startsWith('template.'));
|
|
160
|
-
if (options.dryRun && templateFiles.length === 0) {
|
|
161
|
-
console.log(chalk.yellow('No template files found in: ' + templateDir));
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
let generatedCount = 0;
|
|
165
|
-
let skippedCount = 0;
|
|
166
|
-
const errors = [];
|
|
167
|
-
const generatedFiles = [];
|
|
168
|
-
for (const templateFile of templateFiles) {
|
|
169
|
-
// Extract target filename (remove 'template.' prefix)
|
|
170
|
-
// Note: targetFile keeps the original name including leading dots (e.g., .dockerignore)
|
|
171
|
-
const targetFile = templateFile.replace('template.', '');
|
|
172
|
-
const targetPath = path.join(absolutePath, targetFile);
|
|
173
|
-
// Check if file already exists (skip this check in dry-run mode or overwrite mode)
|
|
174
|
-
if (!options.dryRun && !options.overwrite && fs.existsSync(targetPath)) {
|
|
175
|
-
if (options.interactive) {
|
|
176
|
-
console.log(chalk.yellow(` Skipping ${targetFile} (already exists)`));
|
|
177
|
-
}
|
|
178
|
-
skippedCount++;
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
try {
|
|
182
|
-
// Prepare consistent values structure for all templates
|
|
183
|
-
const projectName = arkConfig.project?.name || path.basename(absolutePath);
|
|
184
|
-
const values = {
|
|
185
|
-
project: {
|
|
186
|
-
name: projectName,
|
|
187
|
-
type: arkConfig.project?.type || 'pyproject',
|
|
188
|
-
platform: arkConfig.project?.platform || 'python3',
|
|
189
|
-
version: arkConfig.project?.version || '0.1.0',
|
|
190
|
-
framework: arkConfig.project?.framework || 'fastmcp'
|
|
191
|
-
},
|
|
192
|
-
python: {
|
|
193
|
-
version: '3.11', // Default Python version
|
|
194
|
-
module_name: projectName.replace(/-/g, '_') // Convert kebab-case to snake_case
|
|
195
|
-
},
|
|
196
|
-
devspace: {
|
|
197
|
-
namespace: 'default',
|
|
198
|
-
image: {
|
|
199
|
-
repository: projectName // Default repository name
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
// Create temp values file for helm
|
|
204
|
-
const tempValuesFile = path.join(absolutePath, '.ark-template-values.yaml');
|
|
205
|
-
fs.writeFileSync(tempValuesFile, yaml.stringify(values));
|
|
206
|
-
// Read template
|
|
207
|
-
const templatePath = path.join(templateDir, templateFile);
|
|
208
|
-
// Create a minimal chart structure for helm to process this single file
|
|
209
|
-
const tempChartDir = path.join(absolutePath, '.ark-helm-temp');
|
|
210
|
-
const tempTemplatesDir = path.join(tempChartDir, 'templates');
|
|
211
|
-
fs.mkdirSync(tempChartDir, { recursive: true });
|
|
212
|
-
fs.mkdirSync(tempTemplatesDir, { recursive: true });
|
|
213
|
-
// Write minimal Chart.yaml
|
|
214
|
-
fs.writeFileSync(path.join(tempChartDir, 'Chart.yaml'), 'apiVersion: v2\nname: temp\nversion: 0.1.0\n');
|
|
215
|
-
// Copy template to templates dir
|
|
216
|
-
// For non-YAML files, wrap them in a YAML structure for helm to process
|
|
217
|
-
const originalTemplateName = targetFile; // This is already the target filename
|
|
218
|
-
const isYamlFile = targetFile.endsWith('.yaml') || targetFile.endsWith('.yml');
|
|
219
|
-
// For dotfiles, replace the leading dot with 'dot' for helm processing
|
|
220
|
-
// (helm has issues with files starting with dots)
|
|
221
|
-
const helmTemplateName = originalTemplateName.startsWith('.')
|
|
222
|
-
? 'dot' + originalTemplateName.substring(1)
|
|
223
|
-
: originalTemplateName;
|
|
224
|
-
if (isYamlFile) {
|
|
225
|
-
// Copy YAML files directly
|
|
226
|
-
fs.copyFileSync(templatePath, path.join(tempTemplatesDir, helmTemplateName));
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
// Wrap non-YAML content in a YAML structure for helm
|
|
230
|
-
const originalContent = fs.readFileSync(templatePath, 'utf-8');
|
|
231
|
-
const wrappedContent = `# Wrapped for helm processing\ncontent: |\n${originalContent.split('\n').map(line => ' ' + line).join('\n')}`;
|
|
232
|
-
fs.writeFileSync(path.join(tempTemplatesDir, helmTemplateName + '.yaml'), wrappedContent);
|
|
233
|
-
}
|
|
234
|
-
// Run helm template to process the file
|
|
235
|
-
const actualHelmFile = isYamlFile ? helmTemplateName : helmTemplateName + '.yaml';
|
|
236
|
-
const helmCommand = `helm template temp ${tempChartDir} --values ${tempValuesFile} -s templates/${actualHelmFile}`;
|
|
237
|
-
let content;
|
|
238
|
-
try {
|
|
239
|
-
content = execSync(helmCommand, { encoding: 'utf-8' });
|
|
240
|
-
// Remove the YAML document separator that helm adds
|
|
241
|
-
content = content.replace(/^---\n/, '');
|
|
242
|
-
// Remove helm's source comment
|
|
243
|
-
content = content.replace(/^# Source:.*\n/gm, '');
|
|
244
|
-
// For non-YAML files, extract the content from the wrapped YAML
|
|
245
|
-
if (!isYamlFile) {
|
|
246
|
-
// Parse the YAML to extract the content field
|
|
247
|
-
const yamlContent = yaml.parse(content);
|
|
248
|
-
content = yamlContent.content || '';
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
catch (helmError) {
|
|
252
|
-
const errorMsg = helmError.stderr || helmError.message || 'Unknown error';
|
|
253
|
-
// Debug: Check if values file exists and is readable
|
|
254
|
-
if (options.dryRun) {
|
|
255
|
-
console.log(chalk.yellow(`Debug: Helm command failed: ${helmCommand}`));
|
|
256
|
-
console.log(chalk.yellow(`Debug: Values file exists: ${fs.existsSync(tempValuesFile)}`));
|
|
257
|
-
if (fs.existsSync(tempValuesFile)) {
|
|
258
|
-
console.log(chalk.yellow(`Debug: Values content:`));
|
|
259
|
-
console.log(fs.readFileSync(tempValuesFile, 'utf-8'));
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
throw new Error(`Failed to template ${targetFile}: ${errorMsg}`);
|
|
263
|
-
}
|
|
264
|
-
finally {
|
|
265
|
-
// Clean up temp chart
|
|
266
|
-
fs.rmSync(tempChartDir, { recursive: true, force: true });
|
|
267
|
-
}
|
|
268
|
-
// In dry-run mode, print to stdout; otherwise write the file
|
|
269
|
-
if (options.dryRun) {
|
|
270
|
-
console.log(chalk.cyan(`\n=== ${targetFile} ===`));
|
|
271
|
-
console.log(content);
|
|
272
|
-
console.log(chalk.cyan(`=== END ${targetFile} ===\n`));
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
fs.writeFileSync(targetPath, content);
|
|
276
|
-
generatedFiles.push(targetFile);
|
|
277
|
-
// Don't log individual files while spinner is active
|
|
278
|
-
// We'll show them after stopping the spinner
|
|
279
|
-
}
|
|
280
|
-
// Clean up temp values file
|
|
281
|
-
if (fs.existsSync(tempValuesFile)) {
|
|
282
|
-
fs.unlinkSync(tempValuesFile);
|
|
283
|
-
}
|
|
284
|
-
generatedCount++;
|
|
285
|
-
}
|
|
286
|
-
catch (err) {
|
|
287
|
-
const errorMsg = `${targetFile}: ${err instanceof Error ? err.message : 'Unknown error'}`;
|
|
288
|
-
errors.push(errorMsg);
|
|
289
|
-
if (options.dryRun) {
|
|
290
|
-
console.log(chalk.red(`Error processing ${targetFile}: ${err instanceof Error ? err.message : 'Unknown error'}`));
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
if (!options.dryRun) {
|
|
295
|
-
if (generatedCount > 0) {
|
|
296
|
-
generateSpinner.succeed(`Generated ${generatedCount} file(s)`);
|
|
297
|
-
// Show the generated files after stopping the spinner
|
|
298
|
-
if (options.interactive && generatedFiles.length > 0) {
|
|
299
|
-
generatedFiles.forEach(file => {
|
|
300
|
-
console.log(chalk.green(` ✓ Generated ${file}`));
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
else if (skippedCount > 0) {
|
|
305
|
-
generateSpinner.warn(`No new files generated (${skippedCount} already exist)`);
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
generateSpinner.warn('No files to generate');
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
if (errors.length > 0 && options.interactive) {
|
|
312
|
-
console.log(chalk.red('Errors:'));
|
|
313
|
-
errors.forEach(e => console.log(chalk.red(` - ${e}`)));
|
|
314
|
-
}
|
|
315
|
-
return generatedCount > 0;
|
|
316
|
-
}
|
|
317
|
-
catch (error) {
|
|
318
|
-
if (!options.dryRun && generateSpinner) {
|
|
319
|
-
generateSpinner.fail('Failed to generate project files');
|
|
320
|
-
}
|
|
321
|
-
if (options.interactive) {
|
|
322
|
-
console.log(chalk.red(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
323
|
-
}
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
async function generateTool(toolPath, options = {}) {
|
|
328
|
-
const absolutePath = path.resolve(toolPath);
|
|
329
|
-
if (!options.dryRun) {
|
|
330
|
-
if (options.overwrite) {
|
|
331
|
-
console.log(chalk.yellow('Overwrite mode: existing files will be replaced'));
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
const success = await generateProjectFiles(absolutePath, { interactive: !options.dryRun, dryRun: options.dryRun, overwrite: options.overwrite });
|
|
335
|
-
if (success && !options.dryRun) {
|
|
336
|
-
console.log();
|
|
337
|
-
console.log('Next steps:');
|
|
338
|
-
console.log(' • Review generated files and customize as needed');
|
|
339
|
-
console.log(' • Build Docker image: ' + chalk.cyan('docker build -t my-tool .'));
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
async function initTool(toolPath) {
|
|
343
|
-
const absolutePath = path.resolve(toolPath);
|
|
344
|
-
const analyzer = new ArkDevToolAnalyzer();
|
|
345
|
-
// Check if .ark.yaml already exists
|
|
346
|
-
const arkConfigPath = path.join(absolutePath, '.ark.yaml');
|
|
347
|
-
if (fs.existsSync(arkConfigPath)) {
|
|
348
|
-
const { overwrite } = await inquirer.prompt([
|
|
349
|
-
{
|
|
350
|
-
type: 'confirm',
|
|
351
|
-
name: 'overwrite',
|
|
352
|
-
message: chalk.yellow('.ark.yaml already exists. Overwrite?'),
|
|
353
|
-
default: false
|
|
354
|
-
}
|
|
355
|
-
]);
|
|
356
|
-
if (!overwrite) {
|
|
357
|
-
console.log(chalk.gray('Initialization cancelled'));
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
// Initialize configuration object
|
|
362
|
-
const arkConfig = {
|
|
363
|
-
version: '1.0',
|
|
364
|
-
project: {}
|
|
365
|
-
};
|
|
366
|
-
// Step 1: Check if path exists and is a directory
|
|
367
|
-
const checkSpinner = ora('Checking project path...').start();
|
|
368
|
-
const project = await analyzer.discoverProject(absolutePath);
|
|
369
|
-
if (!project || !project.exists) {
|
|
370
|
-
checkSpinner.fail('Path not found');
|
|
371
|
-
output.error(`Path not found: ${absolutePath}`);
|
|
372
|
-
process.exit(1);
|
|
373
|
-
}
|
|
374
|
-
if (!project.is_directory) {
|
|
375
|
-
checkSpinner.fail('Path is not a directory');
|
|
376
|
-
output.error(`Path is not a directory: ${absolutePath}`);
|
|
377
|
-
process.exit(1);
|
|
378
|
-
}
|
|
379
|
-
checkSpinner.succeed('Project path verified');
|
|
380
|
-
arkConfig.project.path = absolutePath;
|
|
381
|
-
// Step 2: Detect platform
|
|
382
|
-
console.log();
|
|
383
|
-
if (!project.platform) {
|
|
384
|
-
console.log(chalk.yellow('⚠ No Python project files found (pyproject.toml or requirements.txt)'));
|
|
385
|
-
const { continueWithoutProject } = await inquirer.prompt([
|
|
386
|
-
{
|
|
387
|
-
type: 'confirm',
|
|
388
|
-
name: 'continueWithoutProject',
|
|
389
|
-
message: 'Continue without project files?',
|
|
390
|
-
default: false
|
|
391
|
-
}
|
|
392
|
-
]);
|
|
393
|
-
if (!continueWithoutProject) {
|
|
394
|
-
console.log(chalk.gray('Initialization cancelled'));
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
// Set defaults but don't create anything
|
|
398
|
-
arkConfig.project.platform = 'python3';
|
|
399
|
-
arkConfig.project.type = 'none';
|
|
400
|
-
}
|
|
401
|
-
else {
|
|
402
|
-
console.log(chalk.green(`✓ Detected platform: ${chalk.white(project.platform)}`));
|
|
403
|
-
console.log(chalk.gray(` Found from: ${project.project_type === 'pyproject' ? 'pyproject.toml' : 'requirements.txt'}`));
|
|
404
|
-
const { confirmPlatform } = await inquirer.prompt([
|
|
405
|
-
{
|
|
406
|
-
type: 'confirm',
|
|
407
|
-
name: 'confirmPlatform',
|
|
408
|
-
message: `Confirm platform is ${project.platform}?`,
|
|
409
|
-
default: true
|
|
410
|
-
}
|
|
411
|
-
]);
|
|
412
|
-
if (!confirmPlatform) {
|
|
413
|
-
console.log(chalk.gray('Initialization cancelled'));
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
arkConfig.project.platform = project.platform;
|
|
417
|
-
arkConfig.project.type = project.project_type;
|
|
418
|
-
// Step 3: Project metadata
|
|
419
|
-
if (project.project_name) {
|
|
420
|
-
console.log();
|
|
421
|
-
console.log(chalk.green(`✓ Found project name: ${chalk.white(project.project_name)}`));
|
|
422
|
-
console.log(chalk.gray(` From: pyproject.toml [project] section`));
|
|
423
|
-
const { confirmName } = await inquirer.prompt([
|
|
424
|
-
{
|
|
425
|
-
type: 'confirm',
|
|
426
|
-
name: 'confirmName',
|
|
427
|
-
message: `Save project name as "${project.project_name}"?`,
|
|
428
|
-
default: true
|
|
429
|
-
}
|
|
430
|
-
]);
|
|
431
|
-
if (confirmName) {
|
|
432
|
-
arkConfig.project.name = project.project_name;
|
|
433
|
-
}
|
|
434
|
-
if (project.project_version) {
|
|
435
|
-
console.log();
|
|
436
|
-
console.log(chalk.green(`✓ Found project version: ${chalk.white(project.project_version)}`));
|
|
437
|
-
console.log(chalk.gray(` From: pyproject.toml [project] section`));
|
|
438
|
-
const { confirmVersion } = await inquirer.prompt([
|
|
439
|
-
{
|
|
440
|
-
type: 'confirm',
|
|
441
|
-
name: 'confirmVersion',
|
|
442
|
-
message: `Save project version as "${project.project_version}"?`,
|
|
443
|
-
default: true
|
|
444
|
-
}
|
|
445
|
-
]);
|
|
446
|
-
if (confirmVersion) {
|
|
447
|
-
arkConfig.project.version = project.project_version;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
// Step 4: Check for FastMCP
|
|
452
|
-
console.log();
|
|
453
|
-
if (project.has_fastmcp) {
|
|
454
|
-
console.log(chalk.green(`✓ Found FastMCP framework: ${chalk.white(`v${project.fastmcp_version || 'unknown'}`)}`));
|
|
455
|
-
console.log(chalk.gray(` From: ${project.project_type === 'pyproject' ? 'pyproject.toml dependencies' : 'requirements.txt'}`));
|
|
456
|
-
const { confirmFramework } = await inquirer.prompt([
|
|
457
|
-
{
|
|
458
|
-
type: 'confirm',
|
|
459
|
-
name: 'confirmFramework',
|
|
460
|
-
message: `Save framework as FastMCP v${project.fastmcp_version}?`,
|
|
461
|
-
default: true
|
|
462
|
-
}
|
|
463
|
-
]);
|
|
464
|
-
if (confirmFramework) {
|
|
465
|
-
arkConfig.project.framework = 'fastmcp';
|
|
466
|
-
arkConfig.project.frameworkVersion = project.fastmcp_version;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
console.log(chalk.yellow('⚠ FastMCP not found in dependencies'));
|
|
471
|
-
console.log(chalk.gray(` Checked: ${project.project_type === 'pyproject' ? 'pyproject.toml' : 'requirements.txt'}`));
|
|
472
|
-
const { recordMissing } = await inquirer.prompt([
|
|
473
|
-
{
|
|
474
|
-
type: 'confirm',
|
|
475
|
-
name: 'recordMissing',
|
|
476
|
-
message: 'Record that FastMCP is not installed?',
|
|
477
|
-
default: true
|
|
478
|
-
}
|
|
479
|
-
]);
|
|
480
|
-
if (recordMissing) {
|
|
481
|
-
arkConfig.project.framework = 'none';
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
// Step 5: Write .ark.yaml
|
|
486
|
-
console.log();
|
|
487
|
-
const writeSpinner = ora('Writing .ark.yaml configuration...').start();
|
|
488
|
-
try {
|
|
489
|
-
const yamlContent = yaml.stringify(arkConfig);
|
|
490
|
-
fs.writeFileSync(arkConfigPath, yamlContent, 'utf-8');
|
|
491
|
-
writeSpinner.succeed('.ark.yaml created successfully');
|
|
492
|
-
console.log();
|
|
493
|
-
console.log(chalk.blue('Configuration Summary:'));
|
|
494
|
-
console.log(chalk.gray('─'.repeat(40)));
|
|
495
|
-
console.log(`Platform: ${arkConfig.project.platform}`);
|
|
496
|
-
console.log(`Type: ${arkConfig.project.type}`);
|
|
497
|
-
if (arkConfig.project.name) {
|
|
498
|
-
console.log(`Name: ${arkConfig.project.name}`);
|
|
499
|
-
console.log(`Version: ${arkConfig.project.version || 'unknown'}`);
|
|
500
|
-
}
|
|
501
|
-
if (arkConfig.project.framework) {
|
|
502
|
-
console.log(`Framework: ${arkConfig.project.framework}`);
|
|
503
|
-
}
|
|
504
|
-
console.log(chalk.gray('─'.repeat(40)));
|
|
505
|
-
console.log();
|
|
506
|
-
console.log(chalk.green('✓ Initialization complete!'));
|
|
507
|
-
// Step 6: Ask about generating project files
|
|
508
|
-
console.log();
|
|
509
|
-
const { generateFiles } = await inquirer.prompt([
|
|
510
|
-
{
|
|
511
|
-
type: 'confirm',
|
|
512
|
-
name: 'generateFiles',
|
|
513
|
-
message: 'Generate project files (Dockerfile, .dockerignore, etc.)?',
|
|
514
|
-
default: true
|
|
515
|
-
}
|
|
516
|
-
]);
|
|
517
|
-
if (generateFiles) {
|
|
518
|
-
console.log();
|
|
519
|
-
await generateProjectFiles(absolutePath, { interactive: true, dryRun: false, overwrite: false });
|
|
520
|
-
}
|
|
521
|
-
console.log();
|
|
522
|
-
console.log('Next steps:');
|
|
523
|
-
console.log(' • Edit ' + chalk.cyan('.ark.yaml') + ' to update configuration');
|
|
524
|
-
if (generateFiles) {
|
|
525
|
-
console.log(' • Review generated files and customize as needed');
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
catch (error) {
|
|
529
|
-
writeSpinner.fail('Failed to write .ark.yaml');
|
|
530
|
-
output.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
531
|
-
process.exit(1);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
export function createToolCommand() {
|
|
535
|
-
const toolCommand = new Command('tool');
|
|
536
|
-
toolCommand.description('MCP tool development utilities');
|
|
537
|
-
const statusCommand = new Command('status');
|
|
538
|
-
statusCommand
|
|
539
|
-
.description('Check the status of an MCP tool project')
|
|
540
|
-
.argument('<path>', 'Path to the tool directory')
|
|
541
|
-
.option('-o, --output <format>', 'Output format (json)', 'text')
|
|
542
|
-
.action(statusTool);
|
|
543
|
-
const initCommand = new Command('init');
|
|
544
|
-
initCommand
|
|
545
|
-
.description('Initialize an MCP tool project with .ark.yaml configuration')
|
|
546
|
-
.argument('<path>', 'Path to the tool directory')
|
|
547
|
-
.action(initTool);
|
|
548
|
-
const generateCommand = new Command('generate');
|
|
549
|
-
generateCommand
|
|
550
|
-
.description('Generate project files (Dockerfile, .dockerignore, etc.) from templates')
|
|
551
|
-
.argument('<path>', 'Path to the tool directory')
|
|
552
|
-
.option('--dry-run', 'Show generated template files without creating them')
|
|
553
|
-
.option('--overwrite', 'Overwrite existing files')
|
|
554
|
-
.action(generateTool);
|
|
555
|
-
toolCommand.addCommand(statusCommand);
|
|
556
|
-
toolCommand.addCommand(initCommand);
|
|
557
|
-
toolCommand.addCommand(generateCommand);
|
|
558
|
-
return toolCommand;
|
|
559
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from '@jest/globals';
|
|
2
|
-
import { execSync } from 'child_process';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = path.dirname(__filename);
|
|
7
|
-
describe('sample-projects', () => {
|
|
8
|
-
describe('reverse-tool', () => {
|
|
9
|
-
it('should output correct MCP tool format in JSON', () => {
|
|
10
|
-
const projectPath = path.join(__dirname, '../../../samples/reverse_tool');
|
|
11
|
-
const cliPath = path.join(__dirname, '../../../dist/index.js');
|
|
12
|
-
// Run the command and capture output
|
|
13
|
-
const output = execSync(`node ${cliPath} dev tool check ${projectPath} --output json`, { encoding: 'utf8' });
|
|
14
|
-
// Parse the JSON output
|
|
15
|
-
const result = JSON.parse(output);
|
|
16
|
-
// Assert the structure
|
|
17
|
-
expect(result).toHaveProperty('path');
|
|
18
|
-
expect(result).toHaveProperty('projectRoot');
|
|
19
|
-
expect(result.projectRoot).toContain('reverse_tool');
|
|
20
|
-
expect(result).toHaveProperty('platform', 'python3');
|
|
21
|
-
expect(result).toHaveProperty('projectType', 'pyproject');
|
|
22
|
-
expect(result).toHaveProperty('projectName', 'reverse-tool');
|
|
23
|
-
expect(result).toHaveProperty('projectVersion', '0.1.0');
|
|
24
|
-
expect(result).toHaveProperty('hasFastmcp', true);
|
|
25
|
-
expect(result).toHaveProperty('fastmcpVersion', '0.5.0');
|
|
26
|
-
expect(result).toHaveProperty('tools');
|
|
27
|
-
// Assert tools array contains MCP-formatted tool
|
|
28
|
-
expect(result.tools).toHaveLength(1);
|
|
29
|
-
const tool = result.tools[0];
|
|
30
|
-
// Check MCP tool structure
|
|
31
|
-
expect(tool).toHaveProperty('name', 'reverse_message');
|
|
32
|
-
expect(tool).toHaveProperty('title', 'Reverse Message');
|
|
33
|
-
expect(tool).toHaveProperty('description', 'Reverses the text of a message');
|
|
34
|
-
expect(tool).toHaveProperty('inputSchema');
|
|
35
|
-
// Check inputSchema structure
|
|
36
|
-
expect(tool.inputSchema).toEqual({
|
|
37
|
-
type: 'object',
|
|
38
|
-
properties: {
|
|
39
|
-
message: {
|
|
40
|
-
type: 'string',
|
|
41
|
-
description: 'Parameter message',
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
required: ['message'],
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import type { ArkConfig } from '../../lib/config.js';
|
|
3
|
-
export declare function installArk(serviceName?: string, options?: {
|
|
4
|
-
yes?: boolean;
|
|
5
|
-
waitForReady?: string;
|
|
6
|
-
verbose?: boolean;
|
|
7
|
-
}): Promise<void>;
|
|
8
|
-
export declare function createInstallCommand(_: ArkConfig): Command;
|