stigmergy 1.0.93 → 1.0.95
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/bin/stigmergy +26 -12
- package/bin/stigmergy.cmd +1 -1
- package/docs/HASH_TABLE.md +83 -0
- package/docs/WEATHER_PROCESSOR_API.md +230 -0
- package/docs/best_practices.md +135 -0
- package/docs/development_guidelines.md +392 -0
- package/docs/requirements_specification.md +148 -0
- package/docs/system_design.md +314 -0
- package/docs/tdd_implementation_plan.md +384 -0
- package/docs/test_report.md +49 -0
- package/examples/calculator-example.js +72 -0
- package/examples/json-validation-example.js +64 -0
- package/examples/rest-client-example.js +52 -0
- package/package.json +21 -17
- package/scripts/post-deployment-config.js +9 -2
- package/src/auth.js +171 -0
- package/src/auth_command.js +195 -0
- package/src/calculator.js +220 -0
- package/src/core/cli_help_analyzer.js +625 -562
- package/src/core/cli_parameter_handler.js +121 -0
- package/src/core/cli_tools.js +89 -0
- package/src/core/error_handler.js +307 -0
- package/src/core/memory_manager.js +76 -0
- package/src/core/smart_router.js +133 -0
- package/src/deploy.js +50 -0
- package/src/main_english.js +643 -720
- package/src/main_fixed.js +1035 -0
- package/src/utils.js +529 -0
- package/src/weatherProcessor.js +205 -0
- package/test/calculator.test.js +215 -0
- package/test/collision-test.js +26 -0
- package/test/csv-processing-test.js +36 -0
- package/test/e2e/claude-cli-test.js +128 -0
- package/test/e2e/collaboration-test.js +75 -0
- package/test/e2e/comprehensive-test.js +431 -0
- package/test/e2e/error-handling-test.js +90 -0
- package/test/e2e/individual-tool-test.js +143 -0
- package/test/e2e/other-cli-test.js +130 -0
- package/test/e2e/qoder-cli-test.js +128 -0
- package/test/e2e/run-e2e-tests.js +73 -0
- package/test/e2e/test-data.js +88 -0
- package/test/e2e/test-utils.js +222 -0
- package/test/hash-table-demo.js +33 -0
- package/test/hash-table-test.js +26 -0
- package/test/json-validation-test.js +164 -0
- package/test/rest-client-test.js +56 -0
- package/test/unit/calculator-full.test.js +191 -0
- package/test/unit/calculator-simple.test.js +96 -0
- package/test/unit/calculator.test.js +97 -0
- package/test/unit/cli_parameter_handler.test.js +116 -0
- package/test/weather-processor.test.js +104 -0
package/src/main_english.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System
|
|
5
5
|
* International Version - Pure English & ANSI Only
|
|
6
|
-
* Version: 1.0.
|
|
6
|
+
* Version: 1.0.94
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
console.log('[DEBUG] Stigmergy CLI script started...');
|
|
@@ -12,117 +12,16 @@ const { spawn, spawnSync } = require('child_process');
|
|
|
12
12
|
const path = require('path');
|
|
13
13
|
const fs = require('fs/promises');
|
|
14
14
|
const os = require('os');
|
|
15
|
+
const { Command } = require('commander');
|
|
16
|
+
const inquirer = require('inquirer');
|
|
17
|
+
const chalk = require('chalk');
|
|
18
|
+
const yaml = require('js-yaml');
|
|
15
19
|
|
|
16
|
-
//
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
install: 'npm install -g @anthropic-ai/claude-cli',
|
|
22
|
-
hooksDir: path.join(os.homedir(), '.claude', 'hooks'),
|
|
23
|
-
config: path.join(os.homedir(), '.claude', 'config.json')
|
|
24
|
-
},
|
|
25
|
-
gemini: {
|
|
26
|
-
name: 'Gemini CLI',
|
|
27
|
-
version: 'gemini --version',
|
|
28
|
-
install: 'npm install -g @google/generative-ai-cli',
|
|
29
|
-
hooksDir: path.join(os.homedir(), '.gemini', 'extensions'),
|
|
30
|
-
config: path.join(os.homedir(), '.gemini', 'config.json')
|
|
31
|
-
},
|
|
32
|
-
qwen: {
|
|
33
|
-
name: 'Qwen CLI',
|
|
34
|
-
version: 'qwen --version',
|
|
35
|
-
install: 'npm install -g @alibaba/qwen-cli',
|
|
36
|
-
hooksDir: path.join(os.homedir(), '.qwen', 'hooks'),
|
|
37
|
-
config: path.join(os.homedir(), '.qwen', 'config.json')
|
|
38
|
-
},
|
|
39
|
-
iflow: {
|
|
40
|
-
name: 'iFlow CLI',
|
|
41
|
-
version: 'iflow --version',
|
|
42
|
-
install: 'npm install -g iflow-cli',
|
|
43
|
-
hooksDir: path.join(os.homedir(), '.iflow', 'hooks'),
|
|
44
|
-
config: path.join(os.homedir(), '.iflow', 'config.json')
|
|
45
|
-
},
|
|
46
|
-
qodercli: {
|
|
47
|
-
name: 'Qoder CLI',
|
|
48
|
-
version: 'qodercli --version',
|
|
49
|
-
install: 'npm install -g @qoder-ai/qodercli',
|
|
50
|
-
hooksDir: path.join(os.homedir(), '.qoder', 'hooks'),
|
|
51
|
-
config: path.join(os.homedir(), '.qoder', 'config.json')
|
|
52
|
-
},
|
|
53
|
-
codebuddy: {
|
|
54
|
-
name: 'CodeBuddy CLI',
|
|
55
|
-
version: 'codebuddy --version',
|
|
56
|
-
install: 'npm install -g codebuddy-cli',
|
|
57
|
-
hooksDir: path.join(os.homedir(), '.codebuddy', 'hooks'),
|
|
58
|
-
config: path.join(os.homedir(), '.codebuddy', 'config.json')
|
|
59
|
-
},
|
|
60
|
-
copilot: {
|
|
61
|
-
name: 'GitHub Copilot CLI',
|
|
62
|
-
version: 'copilot --version',
|
|
63
|
-
install: 'npm install -g @github/copilot-cli',
|
|
64
|
-
hooksDir: path.join(os.homedir(), '.copilot', 'mcp'),
|
|
65
|
-
config: path.join(os.homedir(), '.copilot', 'config.json')
|
|
66
|
-
},
|
|
67
|
-
codex: {
|
|
68
|
-
name: 'OpenAI Codex CLI',
|
|
69
|
-
version: 'codex --version',
|
|
70
|
-
install: 'npm install -g openai-codex-cli',
|
|
71
|
-
hooksDir: path.join(os.homedir(), '.config', 'codex', 'slash_commands'),
|
|
72
|
-
config: path.join(os.homedir(), '.codex', 'config.json')
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
class SmartRouter {
|
|
77
|
-
constructor() {
|
|
78
|
-
this.tools = CLI_TOOLS;
|
|
79
|
-
this.routeKeywords = ['use', 'help', 'please', 'write', 'generate', 'explain', 'analyze', 'translate', 'code', 'article'];
|
|
80
|
-
this.defaultTool = 'claude';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
shouldRoute(userInput) {
|
|
84
|
-
return this.routeKeywords.some(keyword =>
|
|
85
|
-
userInput.toLowerCase().includes(keyword.toLowerCase())
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
smartRoute(userInput) {
|
|
90
|
-
const input = userInput.trim();
|
|
91
|
-
|
|
92
|
-
// Detect tool-specific keywords
|
|
93
|
-
for (const [toolName, toolInfo] of Object.entries(this.tools)) {
|
|
94
|
-
for (const keyword of this.extractKeywords(toolName)) {
|
|
95
|
-
if (input.toLowerCase().includes(keyword.toLowerCase())) {
|
|
96
|
-
// Extract clean parameters
|
|
97
|
-
const cleanInput = input
|
|
98
|
-
.replace(new RegExp(`.*${keyword}\\s*`, 'gi'), '')
|
|
99
|
-
.replace(/^(use|please|help|using|with)\s*/i, '')
|
|
100
|
-
.trim();
|
|
101
|
-
return { tool: toolName, prompt: cleanInput };
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Default routing
|
|
107
|
-
const cleanInput = input.replace(/^(use|please|help|using|with)\s*/i, '').trim();
|
|
108
|
-
return { tool: this.defaultTool, prompt: cleanInput };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
extractKeywords(toolName) {
|
|
112
|
-
const keywords = {
|
|
113
|
-
claude: ['claude', 'anthropic'],
|
|
114
|
-
gemini: ['gemini', 'google'],
|
|
115
|
-
qwen: ['qwen', 'alibaba', 'tongyi'],
|
|
116
|
-
iflow: ['iflow', 'workflow', 'intelligent'],
|
|
117
|
-
qodercli: ['qoder', 'code'],
|
|
118
|
-
codebuddy: ['codebuddy', 'buddy', 'assistant'],
|
|
119
|
-
copilot: ['copilot', 'github', 'gh'],
|
|
120
|
-
codex: ['codex', 'openai', 'gpt']
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
return keywords[toolName] || [toolName];
|
|
124
|
-
}
|
|
125
|
-
}
|
|
20
|
+
// Import our custom modules
|
|
21
|
+
const SmartRouter = require('./core/smart_router');
|
|
22
|
+
const CLIHelpAnalyzer = require('./core/cli_help_analyzer');
|
|
23
|
+
const { CLI_TOOLS } = require('./core/cli_tools');
|
|
24
|
+
const { errorHandler } = require('./core/error_handler');
|
|
126
25
|
|
|
127
26
|
class MemoryManager {
|
|
128
27
|
constructor() {
|
|
@@ -139,11 +38,15 @@ class MemoryManager {
|
|
|
139
38
|
duration: Date.now() - new Date().getTime()
|
|
140
39
|
};
|
|
141
40
|
|
|
142
|
-
|
|
143
|
-
|
|
41
|
+
try {
|
|
42
|
+
// Add to global memory
|
|
43
|
+
await this.saveGlobalMemory(interaction);
|
|
144
44
|
|
|
145
|
-
|
|
146
|
-
|
|
45
|
+
// Add to project memory
|
|
46
|
+
await this.saveProjectMemory(interaction);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
await errorHandler.logError(error, 'ERROR', 'MemoryManager.addInteraction');
|
|
49
|
+
}
|
|
147
50
|
}
|
|
148
51
|
|
|
149
52
|
async saveGlobalMemory(interaction) {
|
|
@@ -155,6 +58,7 @@ class MemoryManager {
|
|
|
155
58
|
await fs.mkdir(path.dirname(this.globalMemoryFile), { recursive: true });
|
|
156
59
|
await fs.writeFile(this.globalMemoryFile, JSON.stringify(memory, null, 2));
|
|
157
60
|
} catch (error) {
|
|
61
|
+
await errorHandler.logError(error, 'ERROR', 'MemoryManager.saveGlobalMemory');
|
|
158
62
|
console.error(`[MEMORY] Failed to save global memory: ${error.message}`);
|
|
159
63
|
}
|
|
160
64
|
}
|
|
@@ -167,6 +71,7 @@ class MemoryManager {
|
|
|
167
71
|
|
|
168
72
|
await fs.writeFile(this.projectMemoryFile, this.formatProjectMemory(memory));
|
|
169
73
|
} catch (error) {
|
|
74
|
+
await errorHandler.logError(error, 'ERROR', 'MemoryManager.saveProjectMemory');
|
|
170
75
|
console.error(`[MEMORY] Failed to save project memory: ${error.message}`);
|
|
171
76
|
}
|
|
172
77
|
}
|
|
@@ -252,61 +157,23 @@ class StigmergyInstaller {
|
|
|
252
157
|
{ args: ['-h'], expected: 0 },
|
|
253
158
|
// Method 4: Try just the command (help case)
|
|
254
159
|
{ args: [], expected: 0 },
|
|
255
|
-
// Method 5: Try version with alternative format
|
|
256
|
-
{ args: ['version'], expected: 0 }
|
|
257
160
|
];
|
|
258
161
|
|
|
259
162
|
for (const check of checks) {
|
|
260
163
|
try {
|
|
261
164
|
const result = spawnSync(toolName, check.args, {
|
|
262
165
|
encoding: 'utf8',
|
|
263
|
-
timeout:
|
|
264
|
-
|
|
166
|
+
timeout: 5000,
|
|
167
|
+
shell: true
|
|
265
168
|
});
|
|
266
169
|
|
|
267
|
-
// Check if command
|
|
268
|
-
if (result.status ===
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Also check if command exists but returns non-zero (some CLIs do this)
|
|
273
|
-
if (result.error === undefined && (result.stdout.length > 0 || result.stderr.length > 0)) {
|
|
274
|
-
const output = (result.stdout + result.stderr).toLowerCase();
|
|
275
|
-
if (output.includes(toolName) || output.includes('cli') || output.includes('ai') || output.includes('help')) {
|
|
276
|
-
return true;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
} catch (error) {
|
|
280
|
-
// Command not found, continue to next check
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// Method 6: Check if command exists in PATH using `which`/`where` (platform specific)
|
|
286
|
-
try {
|
|
287
|
-
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
288
|
-
const result = spawnSync(whichCmd, [toolName], {
|
|
289
|
-
encoding: 'utf8',
|
|
290
|
-
timeout: 5000
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
if (result.status === 0 && result.stdout.trim().length > 0) {
|
|
294
|
-
// Found in PATH
|
|
295
|
-
return true;
|
|
296
|
-
}
|
|
297
|
-
} catch (error) {
|
|
298
|
-
// Continue
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Method 7: Check common installation paths
|
|
302
|
-
const commonPaths = this.getCommonCLIPaths(toolName);
|
|
303
|
-
for (const cliPath of commonPaths) {
|
|
304
|
-
try {
|
|
305
|
-
if (await this.fileExists(cliPath)) {
|
|
306
|
-
// Found at specific path
|
|
170
|
+
// Check if command executed successfully or at least didn't fail with "command not found"
|
|
171
|
+
if (result.status === check.expected ||
|
|
172
|
+
(result.status !== 127 && result.status !== 9009)) { // 127 = command not found on Unix, 9009 = command not found on Windows
|
|
307
173
|
return true;
|
|
308
174
|
}
|
|
309
175
|
} catch (error) {
|
|
176
|
+
// Continue to next check method
|
|
310
177
|
continue;
|
|
311
178
|
}
|
|
312
179
|
}
|
|
@@ -314,223 +181,51 @@ class StigmergyInstaller {
|
|
|
314
181
|
return false;
|
|
315
182
|
}
|
|
316
183
|
|
|
317
|
-
getCommonCLIPaths(toolName) {
|
|
318
|
-
const homeDir = os.homedir();
|
|
319
|
-
const paths = [];
|
|
320
|
-
|
|
321
|
-
// Add platform-specific paths
|
|
322
|
-
if (process.platform === 'win32') {
|
|
323
|
-
// Local and global npm paths
|
|
324
|
-
paths.push(
|
|
325
|
-
path.join(homeDir, 'AppData', 'Roaming', 'npm', `${toolName}.cmd`),
|
|
326
|
-
path.join(homeDir, 'AppData', 'Roaming', 'npm', `${toolName}.ps1`),
|
|
327
|
-
path.join(homeDir, 'AppData', 'Local', 'npm', `${toolName}.cmd`),
|
|
328
|
-
path.join(homeDir, 'AppData', 'Local', 'npm', `${toolName}.ps1`),
|
|
329
|
-
// Program Files
|
|
330
|
-
path.join(process.env.ProgramFiles || 'C:\\Program Files', `${toolName}`, `${toolName}.exe`),
|
|
331
|
-
path.join(process.env['ProgramFiles(x86)'] || 'C:\\Program Files (x86)', `${toolName}`, `${toolName}.exe`),
|
|
332
|
-
// Node.js global packages
|
|
333
|
-
path.join(homeDir, '.npm', `${toolName}.cmd`),
|
|
334
|
-
path.join(homeDir, '.npm', `${toolName}.js`),
|
|
335
|
-
// User directories
|
|
336
|
-
path.join(homeDir, `${toolName}.cmd`),
|
|
337
|
-
path.join(homeDir, `${toolName}.exe`),
|
|
338
|
-
// Custom test directories
|
|
339
|
-
path.join(homeDir, '.stigmergy-test', `${toolName}.cmd`),
|
|
340
|
-
path.join(homeDir, '.stigmergy-test', `${toolName}.js`)
|
|
341
|
-
);
|
|
342
|
-
} else {
|
|
343
|
-
paths.push(
|
|
344
|
-
// Global npm paths
|
|
345
|
-
path.join(homeDir, '.npm', 'global', 'bin', toolName),
|
|
346
|
-
path.join(homeDir, '.npm', 'global', 'bin', `${toolName}.js`),
|
|
347
|
-
// Local npm paths
|
|
348
|
-
path.join(homeDir, '.npm', 'bin', toolName),
|
|
349
|
-
path.join(homeDir, '.local', 'bin', toolName),
|
|
350
|
-
path.join(homeDir, '.local', 'bin', `${toolName}.js`),
|
|
351
|
-
// System paths
|
|
352
|
-
path.join('/usr', 'local', 'bin', toolName),
|
|
353
|
-
path.join('/usr', 'local', 'bin', `${toolName}.js`),
|
|
354
|
-
path.join('/usr', 'bin', toolName),
|
|
355
|
-
path.join('/usr', 'bin', `${toolName}.js`),
|
|
356
|
-
// User home
|
|
357
|
-
path.join(homeDir, '.local', 'bin', toolName),
|
|
358
|
-
path.join(homeDir, '.local', 'bin', `${toolName}.js`),
|
|
359
|
-
// Custom test directories
|
|
360
|
-
path.join(homeDir, '.stigmergy-test', toolName),
|
|
361
|
-
path.join(homeDir, '.stigmergy-test', `${toolName}.js`)
|
|
362
|
-
);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Add NPM global bin directory
|
|
366
|
-
try {
|
|
367
|
-
const { spawnSync } = require('child_process');
|
|
368
|
-
const npmRoot = spawnSync('npm', ['root', '-g'], { encoding: 'utf8' }).stdout.trim();
|
|
369
|
-
if (npmRoot) {
|
|
370
|
-
paths.push(path.join(npmRoot, 'bin', toolName));
|
|
371
|
-
paths.push(path.join(npmRoot, `${toolName}.js`));
|
|
372
|
-
paths.push(path.join(npmRoot, `${toolName}.cmd`));
|
|
373
|
-
}
|
|
374
|
-
} catch (error) {
|
|
375
|
-
// Continue
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
return paths;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
async fileExists(filePath) {
|
|
382
|
-
try {
|
|
383
|
-
await fs.access(filePath);
|
|
384
|
-
return true;
|
|
385
|
-
} catch {
|
|
386
|
-
return false;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
184
|
async scanCLI() {
|
|
391
|
-
console.log('[SCAN] Scanning for AI CLI tools
|
|
392
|
-
console.log('='.repeat(60));
|
|
393
|
-
|
|
185
|
+
console.log('[SCAN] Scanning for AI CLI tools...');
|
|
394
186
|
const available = {};
|
|
395
187
|
const missing = {};
|
|
396
188
|
|
|
397
189
|
for (const [toolName, toolInfo] of Object.entries(this.router.tools)) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
190
|
+
try {
|
|
191
|
+
console.log(`[SCAN] Checking ${toolInfo.name}...`);
|
|
192
|
+
const isAvailable = await this.checkCLI(toolName);
|
|
193
|
+
|
|
194
|
+
if (isAvailable) {
|
|
195
|
+
console.log(`[OK] ${toolInfo.name} is available`);
|
|
196
|
+
available[toolName] = toolInfo;
|
|
197
|
+
} else {
|
|
198
|
+
console.log(`[MISSING] ${toolInfo.name} is not installed`);
|
|
199
|
+
missing[toolName] = toolInfo;
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
await errorHandler.logError(error, 'WARN', `StigmergyInstaller.scanCLI.${toolName}`);
|
|
203
|
+
console.log(`[ERROR] Failed to check ${toolInfo.name}: ${error.message}`);
|
|
404
204
|
missing[toolName] = toolInfo;
|
|
405
|
-
console.log(`[X] ${toolInfo.name}: Not Available`);
|
|
406
205
|
}
|
|
407
206
|
}
|
|
408
207
|
|
|
409
|
-
console.log('='.repeat(60));
|
|
410
|
-
console.log(`[SUMMARY] ${Object.keys(available).length}/${Object.keys(this.router.tools).length} tools available`);
|
|
411
|
-
|
|
412
208
|
return { available, missing };
|
|
413
209
|
}
|
|
414
210
|
|
|
415
|
-
async
|
|
416
|
-
|
|
417
|
-
console.log('[INFO] All AI CLI tools are already installed!');
|
|
418
|
-
return [];
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
console.log('\n[INSTALL] The following AI CLI tools can be automatically installed:\n');
|
|
422
|
-
|
|
423
|
-
const options = [];
|
|
424
|
-
let index = 1;
|
|
425
|
-
|
|
426
|
-
for (const [toolName, toolInfo] of Object.entries(missing)) {
|
|
427
|
-
console.log(` ${index}. ${toolInfo.name}`);
|
|
428
|
-
console.log(` Install: ${toolInfo.install}`);
|
|
429
|
-
options.push({ index, toolName, toolInfo });
|
|
430
|
-
index++;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
if (isNonInteractive) {
|
|
434
|
-
console.log('\n[INFO] Non-interactive mode detected. Skipping automatic installation.');
|
|
435
|
-
console.log('[INFO] To install these tools manually, run: stigmergy install');
|
|
436
|
-
return [];
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
console.log('\n[OPTIONS] Installation Options:');
|
|
440
|
-
console.log('- Enter numbers separated by spaces (e.g: 1 3 5)');
|
|
441
|
-
console.log('- Enter "all" to install all missing tools');
|
|
442
|
-
console.log('- Enter "skip" to skip CLI installation');
|
|
443
|
-
|
|
444
|
-
return options;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
async getUserSelection(options, missing) {
|
|
448
|
-
if (options.length === 0) {
|
|
449
|
-
return [];
|
|
450
|
-
}
|
|
211
|
+
async installTools(selectedTools, missingTools) {
|
|
212
|
+
console.log(`\n[INSTALL] Installing ${selectedTools.length} AI CLI tools...`);
|
|
451
213
|
|
|
452
|
-
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
value: opt.toolName
|
|
458
|
-
}));
|
|
459
|
-
|
|
460
|
-
choices.push(new inquirer.Separator(' = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ='),
|
|
461
|
-
{ name: 'All missing tools', value: 'all' },
|
|
462
|
-
{ name: 'Skip installation', value: 'skip' });
|
|
463
|
-
|
|
464
|
-
const answers = await inquirer.prompt([
|
|
465
|
-
{
|
|
466
|
-
type: 'checkbox',
|
|
467
|
-
name: 'selectedTools',
|
|
468
|
-
message: 'Select tools to install (Space to select, Enter to confirm):',
|
|
469
|
-
choices: choices,
|
|
470
|
-
validate: function (answer) {
|
|
471
|
-
if (answer.length < 1) {
|
|
472
|
-
return 'You must choose at least one option.';
|
|
473
|
-
}
|
|
474
|
-
return true;
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
]);
|
|
478
|
-
|
|
479
|
-
if (answers.selectedTools.includes('skip')) {
|
|
480
|
-
console.log('[INFO] Skipping CLI tool installation');
|
|
481
|
-
return [];
|
|
482
|
-
} else {
|
|
483
|
-
let toolsToInstall;
|
|
484
|
-
if (answers.selectedTools.includes('all')) {
|
|
485
|
-
toolsToInstall = options;
|
|
486
|
-
} else {
|
|
487
|
-
toolsToInstall = options.filter(opt => answers.selectedTools.includes(opt.toolName));
|
|
488
|
-
}
|
|
489
|
-
return toolsToInstall;
|
|
214
|
+
for (const toolName of selectedTools) {
|
|
215
|
+
const toolInfo = missingTools[toolName];
|
|
216
|
+
if (!toolInfo) {
|
|
217
|
+
console.log(`[SKIP] Tool ${toolName} not found in missing tools list`);
|
|
218
|
+
continue;
|
|
490
219
|
}
|
|
491
|
-
} catch (error) {
|
|
492
|
-
console.log('[ERROR] Interactive selection failed:', error.message);
|
|
493
|
-
console.log('[INFO] Skipping CLI tool installation due to input error');
|
|
494
|
-
console.log('[INFO] To install tools manually, run: stigmergy install');
|
|
495
|
-
return [];
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
async installTools(selectedTools, missing) {
|
|
500
|
-
if (!selectedTools || selectedTools.length === 0) {
|
|
501
|
-
console.log('[INFO] Skipping CLI tool installation');
|
|
502
|
-
return true;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
console.log('\n[INSTALL] Installing selected AI CLI tools...');
|
|
506
|
-
|
|
507
|
-
for (const selection of selectedTools) {
|
|
508
|
-
const { toolName, toolInfo } = selection;
|
|
509
|
-
console.log(`\n[INSTALLING] ${toolInfo.name}...`);
|
|
510
220
|
|
|
511
221
|
try {
|
|
512
|
-
|
|
513
|
-
console.log(`[
|
|
514
|
-
|
|
515
|
-
// Try with shell=true first (works better on Windows)
|
|
516
|
-
let result = spawnSync(installCmd[0], installCmd.slice(1), {
|
|
517
|
-
encoding: 'utf8',
|
|
518
|
-
timeout: 300000, // Increased to 5 minutes for CLI tools that download binaries
|
|
519
|
-
stdio: 'inherit',
|
|
520
|
-
env: process.env,
|
|
521
|
-
shell: true
|
|
522
|
-
});
|
|
222
|
+
console.log(`\n[INSTALL] Installing ${toolInfo.name}...`);
|
|
223
|
+
console.log(`[CMD] ${toolInfo.install}`);
|
|
523
224
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
encoding: 'utf8',
|
|
529
|
-
timeout: 300000,
|
|
530
|
-
stdio: 'inherit',
|
|
531
|
-
env: process.env
|
|
532
|
-
});
|
|
533
|
-
}
|
|
225
|
+
const result = spawnSync(toolInfo.install, {
|
|
226
|
+
shell: true,
|
|
227
|
+
stdio: 'inherit'
|
|
228
|
+
});
|
|
534
229
|
|
|
535
230
|
if (result.status === 0) {
|
|
536
231
|
console.log(`[OK] ${toolInfo.name} installed successfully`);
|
|
@@ -542,6 +237,7 @@ class StigmergyInstaller {
|
|
|
542
237
|
console.log(`[INFO] Please run manually: ${toolInfo.install}`);
|
|
543
238
|
}
|
|
544
239
|
} catch (error) {
|
|
240
|
+
await errorHandler.logError(error, 'ERROR', `StigmergyInstaller.installTools.${toolName}`);
|
|
545
241
|
console.log(`[ERROR] Failed to install ${toolInfo.name}: ${error.message}`);
|
|
546
242
|
console.log(`[INFO] Please run manually: ${toolInfo.install}`);
|
|
547
243
|
}
|
|
@@ -585,168 +281,174 @@ class StigmergyInstaller {
|
|
|
585
281
|
if (await this.fileExists(adaptersDir)) {
|
|
586
282
|
await fs.mkdir(localAdaptersDir, { recursive: true });
|
|
587
283
|
|
|
588
|
-
// Copy adapter
|
|
589
|
-
await
|
|
590
|
-
|
|
284
|
+
// Copy all adapter directories
|
|
285
|
+
const adapterDirs = await fs.readdir(adaptersDir);
|
|
286
|
+
for (const dir of adapterDirs) {
|
|
287
|
+
// Skip non-directory items
|
|
288
|
+
const dirPath = path.join(adaptersDir, dir);
|
|
289
|
+
const stat = await fs.stat(dirPath);
|
|
290
|
+
if (!stat.isDirectory()) continue;
|
|
291
|
+
|
|
292
|
+
// Skip __pycache__ directories
|
|
293
|
+
if (dir === '__pycache__') continue;
|
|
294
|
+
|
|
295
|
+
const dstPath = path.join(localAdaptersDir, dir);
|
|
296
|
+
await this.copyDirectory(dirPath, dstPath);
|
|
297
|
+
console.log(`[OK] Copied adapter: ${dir}`);
|
|
298
|
+
}
|
|
591
299
|
}
|
|
592
300
|
|
|
593
|
-
console.log('[OK]
|
|
301
|
+
console.log('[OK] All required assets downloaded successfully');
|
|
594
302
|
return true;
|
|
303
|
+
|
|
595
304
|
} catch (error) {
|
|
596
|
-
|
|
305
|
+
await errorHandler.logError(error, 'ERROR', 'StigmergyInstaller.downloadRequiredAssets');
|
|
306
|
+
console.log(`[ERROR] Failed to download required assets: ${error.message}`);
|
|
597
307
|
return false;
|
|
598
308
|
}
|
|
599
309
|
}
|
|
600
|
-
|
|
601
|
-
// Safety check to prevent conflicts with other CLI tools
|
|
310
|
+
|
|
602
311
|
async safetyCheck() {
|
|
603
|
-
console.log('[SAFETY]
|
|
312
|
+
console.log('\n[SAFETY] Performing safety check for conflicting packages...');
|
|
604
313
|
|
|
314
|
+
// List of potentially conflicting packages
|
|
315
|
+
const conflictingPackages = [
|
|
316
|
+
'@aws-amplify/cli',
|
|
317
|
+
'firebase-tools',
|
|
318
|
+
'heroku',
|
|
319
|
+
'netlify-cli',
|
|
320
|
+
'vercel',
|
|
321
|
+
'surge',
|
|
322
|
+
'now'
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
// Check for globally installed conflicting packages
|
|
605
326
|
try {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
try {
|
|
611
|
-
await fs.access(nodePackageDir);
|
|
612
|
-
console.warn('[WARNING] Conflicting "node" package detected!');
|
|
613
|
-
console.warn('[WARNING] This may interfere with other CLI tools.');
|
|
614
|
-
console.warn('[WARNING] Consider running: npm uninstall -g node');
|
|
615
|
-
} catch (error) {
|
|
616
|
-
// Package doesn't exist, that's good
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// Check for broken node executable
|
|
620
|
-
const npmDir = path.join(os.homedir(), 'AppData', 'Roaming', 'npm');
|
|
621
|
-
const nodeExecutable = path.join(npmDir, 'node');
|
|
327
|
+
const result = spawnSync('npm', ['list', '-g', '--depth=0'], {
|
|
328
|
+
encoding: 'utf8',
|
|
329
|
+
timeout: 10000
|
|
330
|
+
});
|
|
622
331
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
const
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
332
|
+
if (result.status === 0) {
|
|
333
|
+
const installedPackages = result.stdout;
|
|
334
|
+
const conflicts = [];
|
|
335
|
+
|
|
336
|
+
for (const pkg of conflictingPackages) {
|
|
337
|
+
if (installedPackages.includes(pkg)) {
|
|
338
|
+
conflicts.push(pkg);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (conflicts.length > 0) {
|
|
343
|
+
console.log(`[WARN] Potential conflicting packages detected: ${conflicts.join(', ')}`);
|
|
344
|
+
console.log('[INFO] These packages may interfere with Stigmergy CLI functionality');
|
|
345
|
+
} else {
|
|
346
|
+
console.log('[OK] No conflicting packages detected');
|
|
631
347
|
}
|
|
632
|
-
} catch (error) {
|
|
633
|
-
// File doesn't exist, that's fine
|
|
634
348
|
}
|
|
635
|
-
|
|
636
|
-
console.log('[SAFETY] Check completed.');
|
|
637
349
|
} catch (error) {
|
|
638
|
-
console.log(
|
|
350
|
+
console.log(`[WARN] Unable to perform safety check: ${error.message}`);
|
|
639
351
|
}
|
|
640
352
|
}
|
|
641
353
|
|
|
642
|
-
async copyDirectory(src,
|
|
643
|
-
|
|
644
|
-
|
|
354
|
+
async copyDirectory(src, dest) {
|
|
355
|
+
try {
|
|
356
|
+
await fs.mkdir(dest, { recursive: true });
|
|
357
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
645
358
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
359
|
+
for (const entry of entries) {
|
|
360
|
+
const srcPath = path.join(src, entry.name);
|
|
361
|
+
const destPath = path.join(dest, entry.name);
|
|
649
362
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
363
|
+
if (entry.isDirectory()) {
|
|
364
|
+
// Skip __pycache__ directories
|
|
365
|
+
if (entry.name === '__pycache__') continue;
|
|
366
|
+
await this.copyDirectory(srcPath, destPath);
|
|
367
|
+
} else {
|
|
368
|
+
await fs.copyFile(srcPath, destPath);
|
|
369
|
+
}
|
|
654
370
|
}
|
|
371
|
+
} catch (error) {
|
|
372
|
+
await errorHandler.logError(error, 'WARN', 'StigmergyInstaller.copyDirectory');
|
|
373
|
+
console.log(`[WARN] Failed to copy directory ${src} to ${dest}: ${error.message}`);
|
|
655
374
|
}
|
|
656
375
|
}
|
|
657
376
|
|
|
658
|
-
async
|
|
659
|
-
console.log('\n[DEPLOY] Deploying project documentation...');
|
|
660
|
-
|
|
377
|
+
async fileExists(filePath) {
|
|
661
378
|
try {
|
|
662
|
-
|
|
663
|
-
const assetsTemplatesDir = path.join(os.homedir(), '.stigmergy', 'assets', 'templates');
|
|
664
|
-
|
|
665
|
-
if (!(await this.fileExists(assetsTemplatesDir))) {
|
|
666
|
-
console.log('[SKIP] No template files found');
|
|
667
|
-
return true;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
const templateFiles = await fs.readdir(assetsTemplatesDir);
|
|
671
|
-
let deployedCount = 0;
|
|
672
|
-
|
|
673
|
-
for (const templateFile of templateFiles) {
|
|
674
|
-
if (templateFile.endsWith('.j2')) {
|
|
675
|
-
const dstFileName = templateFile.replace('.j2', '');
|
|
676
|
-
const dstPath = path.join(projectDir, dstFileName);
|
|
677
|
-
|
|
678
|
-
// Read template and substitute variables
|
|
679
|
-
const templateContent = await fs.readFile(path.join(assetsTemplatesDir, templateFile), 'utf8');
|
|
680
|
-
const processedContent = this.substituteTemplateVariables(templateContent);
|
|
681
|
-
|
|
682
|
-
await fs.writeFile(dstPath, processedContent);
|
|
683
|
-
console.log(`[OK] Deployed project doc: ${dstFileName}`);
|
|
684
|
-
deployedCount++;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
console.log(`[RESULT] ${deployedCount} project documentation files deployed`);
|
|
379
|
+
await fs.access(filePath);
|
|
689
380
|
return true;
|
|
690
|
-
} catch
|
|
691
|
-
console.log(`[ERROR] Failed to deploy project documentation: ${error.message}`);
|
|
381
|
+
} catch {
|
|
692
382
|
return false;
|
|
693
383
|
}
|
|
694
384
|
}
|
|
695
385
|
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
const variables = {
|
|
701
|
-
'{{PROJECT_NAME}}': projectName,
|
|
702
|
-
'{{PROJECT_TYPE}}': 'Node.js Project',
|
|
703
|
-
'{{TECH_STACK}}': 'Node.js, JavaScript, TypeScript',
|
|
704
|
-
'{{CREATED_DATE}}': now.toISOString(),
|
|
705
|
-
'{{LAST_UPDATED}}': now.toISOString(),
|
|
706
|
-
'{{GENERATION_TIME}}': now.toLocaleString(),
|
|
707
|
-
'{{CODE_STYLE}}': 'ESLint + Prettier',
|
|
708
|
-
'{{TEST_FRAMEWORK}}': 'Jest',
|
|
709
|
-
'{{BUILD_TOOL}}': 'npm',
|
|
710
|
-
'{{DEPLOY_METHOD}}': 'npm publish',
|
|
711
|
-
'{{PRIMARY_LANGUAGE}}': 'English',
|
|
712
|
-
'{{TARGET_LANGUAGES}}': 'Chinese, Japanese, Spanish',
|
|
713
|
-
'{{DOC_STYLE}}': 'Markdown',
|
|
714
|
-
'{{OUTPUT_FORMAT}}': 'Markdown',
|
|
715
|
-
'{{RECENT_CHANGES}}': 'No recent changes recorded',
|
|
716
|
-
'{{KNOWN_ISSUES}}': 'No known issues',
|
|
717
|
-
'{{TODO_ITEMS}}': 'No todo items',
|
|
718
|
-
'{{TEAM_PREFERENCES}}': 'Standard development practices',
|
|
719
|
-
'{{TRANSLATION_PREFERENCES}}': 'Technical accuracy first',
|
|
720
|
-
'{{DOC_STANDARDS}}': 'Markdown with code examples',
|
|
721
|
-
'{{ANALYSIS_TEMPLATES}}': 'Standard analysis templates',
|
|
722
|
-
'{{COMMON_LANGUAGES}}': 'English, Chinese, Japanese',
|
|
723
|
-
'{{CHINESE_TERMINOLOGY}}': 'Standard Chinese technical terms',
|
|
724
|
-
'{{LOCALIZATION_STANDARDS}}': 'Chinese localization standards',
|
|
725
|
-
'{{USER_HABITS}}': 'Chinese user preferences',
|
|
726
|
-
'{{COMPLIANCE_REQUIREMENTS}}': 'Local regulations compliance',
|
|
727
|
-
'{{CHINESE_DOC_STYLE}}': '简体中文技术文档',
|
|
728
|
-
'{{ENCODING_STANDARD}}': 'UTF-8',
|
|
729
|
-
'{{TECHNICAL_DOMAIN}}': 'Software Development',
|
|
730
|
-
'{{WORKFLOW_ENGINE}}': 'iFlow CLI',
|
|
731
|
-
'{{EXECUTION_ENVIRONMENT}}': 'Node.js',
|
|
732
|
-
'{{DATA_SOURCES}}': 'Local files, APIs',
|
|
733
|
-
'{{OUTPUT_TARGETS}}': 'Files, databases, APIs',
|
|
734
|
-
'{{AGENT_COMMUNICATION_PROTOCOL}}': 'JSON-based messaging',
|
|
735
|
-
'{{COLLABORATION_MODE}}': 'Sequential and Parallel',
|
|
736
|
-
'{{DECISION_MECHANISM}}': 'Consensus-based',
|
|
737
|
-
'{{CONFLICT_RESOLUTION}}': 'Expert arbitration',
|
|
738
|
-
'{{AGENT_PROFILES}}': 'Default agent configurations',
|
|
739
|
-
'{{COLLABORATION_HISTORY}}': 'No history yet',
|
|
740
|
-
'{{DECISION_RECORDS}}': 'No decisions recorded yet',
|
|
741
|
-
'{{PERFORMANCE_METRICS}}': 'To be collected'
|
|
742
|
-
};
|
|
743
|
-
|
|
744
|
-
let processedContent = content;
|
|
745
|
-
for (const [placeholder, value] of Object.entries(variables)) {
|
|
746
|
-
processedContent = processedContent.replace(new RegExp(placeholder.replace(/[{}]/g, '\\$&'), 'g'), value);
|
|
386
|
+
async showInstallOptions(missingTools) {
|
|
387
|
+
if (Object.keys(missingTools).length === 0) {
|
|
388
|
+
console.log('[INFO] All required AI CLI tools are already installed!');
|
|
389
|
+
return [];
|
|
747
390
|
}
|
|
748
|
-
|
|
749
|
-
|
|
391
|
+
|
|
392
|
+
console.log('\n[INSTALL] Missing AI CLI tools detected:');
|
|
393
|
+
const choices = [];
|
|
394
|
+
|
|
395
|
+
for (const [toolName, toolInfo] of Object.entries(missingTools)) {
|
|
396
|
+
choices.push({
|
|
397
|
+
name: `${toolInfo.name} (${toolName}) - ${toolInfo.install}`,
|
|
398
|
+
value: toolName,
|
|
399
|
+
checked: true
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const answers = await inquirer.prompt([
|
|
404
|
+
{
|
|
405
|
+
type: 'checkbox',
|
|
406
|
+
name: 'tools',
|
|
407
|
+
message: 'Select which tools to install (Space to select, Enter to confirm):',
|
|
408
|
+
choices: choices,
|
|
409
|
+
pageSize: 10
|
|
410
|
+
}
|
|
411
|
+
]);
|
|
412
|
+
|
|
413
|
+
return answers.tools;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
async getUserSelection(options, missingTools) {
|
|
417
|
+
if (options.length === 0) {
|
|
418
|
+
return [];
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const answers = await inquirer.prompt([
|
|
422
|
+
{
|
|
423
|
+
type: 'confirm',
|
|
424
|
+
name: 'proceed',
|
|
425
|
+
message: `Install ${options.length} missing AI CLI tools?`,
|
|
426
|
+
default: true
|
|
427
|
+
}
|
|
428
|
+
]);
|
|
429
|
+
|
|
430
|
+
if (answers.proceed) {
|
|
431
|
+
return options;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// If user doesn't want to install all, let them choose individually
|
|
435
|
+
const individualChoices = options.map(toolName => ({
|
|
436
|
+
name: missingTools[toolName].name,
|
|
437
|
+
value: toolName,
|
|
438
|
+
checked: true
|
|
439
|
+
}));
|
|
440
|
+
|
|
441
|
+
const individualAnswers = await inquirer.prompt([
|
|
442
|
+
{
|
|
443
|
+
type: 'checkbox',
|
|
444
|
+
name: 'selectedTools',
|
|
445
|
+
message: 'Select which tools to install:',
|
|
446
|
+
choices: individualChoices,
|
|
447
|
+
pageSize: 10
|
|
448
|
+
}
|
|
449
|
+
]);
|
|
450
|
+
|
|
451
|
+
return individualAnswers.selectedTools;
|
|
750
452
|
}
|
|
751
453
|
|
|
752
454
|
async deployHooks(available) {
|
|
@@ -782,87 +484,144 @@ class StigmergyInstaller {
|
|
|
782
484
|
console.log(`[OK] Copied adapter files for ${toolInfo.name}`);
|
|
783
485
|
}
|
|
784
486
|
|
|
785
|
-
//
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
console.log(`[OK] ${toolInfo.name} configured successfully`);
|
|
487
|
+
// Execute post-deployment configuration
|
|
488
|
+
try {
|
|
489
|
+
await configurer.configureTool(toolName);
|
|
490
|
+
console.log(`[OK] Post-deployment configuration completed for ${toolInfo.name}`);
|
|
790
491
|
successCount++;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
console.log(`[
|
|
492
|
+
} catch (configError) {
|
|
493
|
+
await errorHandler.logError(configError, 'WARN', `StigmergyInstaller.deployHooks.${toolName}.config`);
|
|
494
|
+
console.log(`[WARN] Post-deployment configuration failed for ${toolInfo.name}: ${configError.message}`);
|
|
495
|
+
// Continue with other tools even if one fails
|
|
794
496
|
}
|
|
795
497
|
|
|
796
|
-
console.log(`[OK] Created directories for ${toolInfo.name}`);
|
|
797
|
-
console.log(`[INFO] Hooks directory: ${toolInfo.hooksDir}`);
|
|
798
|
-
console.log(`[INFO] Config directory: ${configDir}`);
|
|
799
498
|
} catch (error) {
|
|
499
|
+
await errorHandler.logError(error, 'ERROR', `StigmergyInstaller.deployHooks.${toolName}`);
|
|
800
500
|
console.log(`[ERROR] Failed to deploy hooks for ${toolInfo.name}: ${error.message}`);
|
|
801
|
-
console.log(
|
|
501
|
+
console.log('[INFO] Continuing with other tools...');
|
|
802
502
|
}
|
|
803
503
|
}
|
|
804
504
|
|
|
805
|
-
console.log(`\n[SUMMARY] Hook deployment completed: ${successCount}/${totalCount} tools
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
505
|
+
console.log(`\n[SUMMARY] Hook deployment completed: ${successCount}/${totalCount} tools successful`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
async deployProjectDocumentation() {
|
|
509
|
+
console.log('\n[DEPLOY] Deploying project documentation...');
|
|
510
|
+
|
|
511
|
+
try {
|
|
512
|
+
// Create standard project documentation files
|
|
513
|
+
const docs = {
|
|
514
|
+
'STIGMERGY.md': this.generateProjectMemoryTemplate(),
|
|
515
|
+
'README.md': this.generateProjectReadme()
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
for (const [filename, content] of Object.entries(docs)) {
|
|
519
|
+
const filepath = path.join(process.cwd(), filename);
|
|
520
|
+
if (!(await this.fileExists(filepath))) {
|
|
521
|
+
await fs.writeFile(filepath, content);
|
|
522
|
+
console.log(`[OK] Created ${filename}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
console.log('[OK] Project documentation deployed successfully');
|
|
527
|
+
} catch (error) {
|
|
528
|
+
console.log(`[ERROR] Failed to deploy project documentation: ${error.message}`);
|
|
810
529
|
}
|
|
811
|
-
|
|
812
|
-
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
generateProjectMemoryTemplate() {
|
|
533
|
+
return `# Stigmergy Project Memory
|
|
534
|
+
|
|
535
|
+
## Project Information
|
|
536
|
+
- **Project Name**: ${path.basename(process.cwd())}
|
|
537
|
+
- **Created**: ${new Date().toISOString()}
|
|
538
|
+
- **Stigmergy Version**: 1.0.94
|
|
539
|
+
|
|
540
|
+
## Usage Instructions
|
|
541
|
+
This file automatically tracks all interactions with AI CLI tools through the Stigmergy system.
|
|
542
|
+
|
|
543
|
+
## Recent Interactions
|
|
544
|
+
No interactions recorded yet.
|
|
545
|
+
|
|
546
|
+
## Collaboration History
|
|
547
|
+
No collaboration history yet.
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
*This file is automatically managed by Stigmergy CLI*
|
|
551
|
+
*Last updated: ${new Date().toISOString()}*
|
|
552
|
+
`;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
generateProjectReadme() {
|
|
556
|
+
return `# ${path.basename(process.cwd())}
|
|
557
|
+
|
|
558
|
+
This project uses Stigmergy CLI for AI-assisted development.
|
|
559
|
+
|
|
560
|
+
## Getting Started
|
|
561
|
+
1. Install Stigmergy CLI: \`npm install -g stigmergy\`
|
|
562
|
+
2. Run \`stigmergy setup\` to configure the environment
|
|
563
|
+
3. Use \`stigmergy call "<your prompt>"\` to interact with AI tools
|
|
564
|
+
|
|
565
|
+
## Available AI Tools
|
|
566
|
+
- Claude (Anthropic)
|
|
567
|
+
- Qwen (Alibaba)
|
|
568
|
+
- Gemini (Google)
|
|
569
|
+
- And others configured in your environment
|
|
570
|
+
|
|
571
|
+
## Project Memory
|
|
572
|
+
See [STIGMERGY.md](STIGMERGY.md) for interaction history and collaboration records.
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
*Generated by Stigmergy CLI*
|
|
576
|
+
`;
|
|
813
577
|
}
|
|
814
578
|
|
|
815
579
|
async initializeConfig() {
|
|
816
580
|
console.log('\n[CONFIG] Initializing Stigmergy configuration...');
|
|
817
581
|
|
|
818
582
|
try {
|
|
819
|
-
|
|
583
|
+
// Create config directory
|
|
584
|
+
const configDir = path.join(os.homedir(), '.stigmergy');
|
|
585
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
820
586
|
|
|
821
|
-
|
|
587
|
+
// Create initial configuration
|
|
822
588
|
const config = {
|
|
823
|
-
version: '1.0.
|
|
589
|
+
version: '1.0.94',
|
|
824
590
|
initialized: true,
|
|
825
591
|
createdAt: new Date().toISOString(),
|
|
826
592
|
lastUpdated: new Date().toISOString(),
|
|
827
593
|
defaultCLI: 'claude',
|
|
828
594
|
enableCrossCLI: true,
|
|
829
|
-
enableMemory: true
|
|
595
|
+
enableMemory: true,
|
|
596
|
+
tools: {}
|
|
830
597
|
};
|
|
831
598
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
599
|
+
// Save configuration
|
|
600
|
+
const configPath = path.join(configDir, 'config.json');
|
|
601
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
835
602
|
|
|
836
|
-
|
|
603
|
+
console.log('[OK] Configuration initialized successfully');
|
|
837
604
|
} catch (error) {
|
|
838
605
|
console.log(`[ERROR] Failed to initialize configuration: ${error.message}`);
|
|
839
|
-
return false;
|
|
840
606
|
}
|
|
841
607
|
}
|
|
842
608
|
|
|
843
609
|
showUsageInstructions() {
|
|
844
|
-
console.log('\n
|
|
610
|
+
console.log('\n' + '='.repeat(60));
|
|
611
|
+
console.log('🎉 Stigmergy CLI Setup Complete!');
|
|
845
612
|
console.log('='.repeat(60));
|
|
846
613
|
console.log('');
|
|
847
|
-
console.log('
|
|
848
|
-
console.log('
|
|
849
|
-
console.log('');
|
|
850
|
-
console.log('
|
|
851
|
-
console.log(' stigmergy scan');
|
|
852
|
-
console.log('');
|
|
853
|
-
console.log('3. Start Using AI CLI Collaboration:');
|
|
854
|
-
console.log(' stigmergy call claude "help me debug this code"');
|
|
855
|
-
console.log(' stigmergy call gemini "generate documentation"');
|
|
856
|
-
console.log(' stigmergy call qwen "translate to English"');
|
|
614
|
+
console.log('Next steps:');
|
|
615
|
+
console.log(' 1. Run "stigmergy install" to scan and install AI CLI tools');
|
|
616
|
+
console.log(' 2. Run "stigmergy deploy" to set up cross-CLI integration');
|
|
617
|
+
console.log(' 3. Use "stigmergy call \\"<your prompt>\\"" to start collaborating');
|
|
857
618
|
console.log('');
|
|
858
|
-
console.log('
|
|
859
|
-
console.log('
|
|
860
|
-
console.log('');
|
|
861
|
-
console.log('
|
|
862
|
-
console.log(' - Global Config: ~/.stigmergy/config.json');
|
|
863
|
-
console.log(' - Project Docs: ./STIGMERGY.md');
|
|
864
|
-
console.log(' - GitHub: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
|
|
619
|
+
console.log('Example usage:');
|
|
620
|
+
console.log(' stigmergy call "用claude分析项目架构"');
|
|
621
|
+
console.log(' stigmergy call "用qwen写一个hello world程序"');
|
|
622
|
+
console.log(' stigmergy call "用gemini设计数据库表结构"');
|
|
865
623
|
console.log('');
|
|
624
|
+
console.log('For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
|
|
866
625
|
console.log('[END] Happy collaborating with multiple AI CLI tools!');
|
|
867
626
|
}
|
|
868
627
|
}
|
|
@@ -870,229 +629,393 @@ class StigmergyInstaller {
|
|
|
870
629
|
// Main CLI functionality
|
|
871
630
|
async function main() {
|
|
872
631
|
console.log('[DEBUG] Main function called with args:', process.argv);
|
|
873
|
-
|
|
874
632
|
const args = process.argv.slice(2);
|
|
875
633
|
const installer = new StigmergyInstaller();
|
|
634
|
+
|
|
635
|
+
try {
|
|
636
|
+
// Handle case when no arguments are provided
|
|
637
|
+
if (args.length === 0) {
|
|
638
|
+
console.log('Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System');
|
|
639
|
+
console.log('Version: 1.0.94');
|
|
640
|
+
console.log('');
|
|
641
|
+
console.log('[SYSTEM] Automated Installation and Deployment System');
|
|
642
|
+
console.log('');
|
|
643
|
+
console.log('Usage: stigmergy [command] [options]');
|
|
644
|
+
console.log('');
|
|
645
|
+
console.log('Commands:');
|
|
646
|
+
console.log(' help, --help Show this help message');
|
|
647
|
+
console.log(' version, --version Show version information');
|
|
648
|
+
console.log(' status Check CLI tools status');
|
|
649
|
+
console.log(' scan Scan for available AI CLI tools');
|
|
650
|
+
console.log(' install Auto-install missing CLI tools');
|
|
651
|
+
console.log(' deploy Deploy hooks and integration to installed tools');
|
|
652
|
+
console.log(' setup Complete setup and configuration');
|
|
653
|
+
console.log(' call "<prompt>" Execute prompt with auto-routed AI CLI');
|
|
654
|
+
console.log('');
|
|
655
|
+
console.log('[WORKFLOW] Automated Workflow:');
|
|
656
|
+
console.log(' 1. npm install -g stigmergy # Install Stigmergy');
|
|
657
|
+
console.log(' 2. stigmergy install # Auto-scan & install CLI tools');
|
|
658
|
+
console.log(' 3. stigmergy setup # Deploy hooks & config');
|
|
659
|
+
console.log(' 4. stigmergy call "<prompt>" # Start collaborating');
|
|
660
|
+
console.log('');
|
|
661
|
+
console.log('[INFO] For first-time setup, run: stigmergy setup');
|
|
662
|
+
console.log('[INFO] To scan and install AI tools, run: stigmergy install');
|
|
663
|
+
console.log('');
|
|
664
|
+
console.log('For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Handle help commands
|
|
669
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
670
|
+
console.log('Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System');
|
|
671
|
+
console.log('Version: 1.0.94');
|
|
672
|
+
console.log('');
|
|
673
|
+
console.log('[SYSTEM] Automated Installation and Deployment System');
|
|
674
|
+
console.log('');
|
|
675
|
+
console.log('Usage: stigmergy [command] [options]');
|
|
676
|
+
console.log('');
|
|
677
|
+
console.log('Commands:');
|
|
678
|
+
console.log(' help, --help Show this help message');
|
|
679
|
+
console.log(' version, --version Show version information');
|
|
680
|
+
console.log(' status Check CLI tools status');
|
|
681
|
+
console.log(' scan Scan for available AI CLI tools');
|
|
682
|
+
console.log(' install Auto-install missing CLI tools');
|
|
683
|
+
console.log(' deploy Deploy hooks and integration to installed tools');
|
|
684
|
+
console.log(' setup Complete setup and configuration');
|
|
685
|
+
console.log(' call "<prompt>" Execute prompt with auto-routed AI CLI');
|
|
686
|
+
console.log('');
|
|
687
|
+
console.log('[WORKFLOW] Automated Workflow:');
|
|
688
|
+
console.log(' 1. npm install -g stigmergy # Install Stigmergy');
|
|
689
|
+
console.log(' 2. stigmergy install # Auto-scan & install CLI tools');
|
|
690
|
+
console.log(' 3. stigmergy setup # Deploy hooks & config');
|
|
691
|
+
console.log(' 4. stigmergy call "<prompt>" # Start collaborating');
|
|
692
|
+
console.log('');
|
|
693
|
+
console.log('For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const command = args[0];
|
|
698
|
+
switch (command) {
|
|
699
|
+
case 'version':
|
|
700
|
+
case '--version':
|
|
701
|
+
// Use the version from configuration instead of hardcoding
|
|
702
|
+
const config = {
|
|
703
|
+
version: '1.0.94',
|
|
704
|
+
initialized: true,
|
|
705
|
+
createdAt: new Date().toISOString(),
|
|
706
|
+
lastUpdated: new Date().toISOString(),
|
|
707
|
+
defaultCLI: 'claude',
|
|
708
|
+
enableCrossCLI: true,
|
|
709
|
+
enableMemory: true
|
|
710
|
+
};
|
|
711
|
+
console.log(`Stigmergy CLI v${config.version}`);
|
|
712
|
+
break;
|
|
876
713
|
|
|
877
|
-
|
|
878
|
-
console.log('Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System');
|
|
879
|
-
console.log('Version: 1.0.90');
|
|
880
|
-
console.log('');
|
|
881
|
-
console.log('[SYSTEM] Automated Installation and Deployment System');
|
|
882
|
-
console.log('');
|
|
883
|
-
console.log('Usage: stigmergy [command] [options]');
|
|
884
|
-
console.log('');
|
|
885
|
-
console.log('Commands:');
|
|
886
|
-
console.log(' help, --help Show this help message');
|
|
887
|
-
console.log(' version, --version Show version information');
|
|
888
|
-
console.log(' status Check CLI tools status');
|
|
889
|
-
console.log(' scan Scan for available AI CLI tools');
|
|
890
|
-
console.log(' install Auto-install missing CLI tools');
|
|
891
|
-
console.log(' deploy Deploy hooks and integration to installed tools');
|
|
892
|
-
console.log(' setup Complete setup and configuration');
|
|
893
|
-
console.log(' call <tool> Execute prompt with specified or auto-routed AI CLI');
|
|
894
|
-
console.log('');
|
|
895
|
-
console.log('[WORKFLOW] Automated Workflow:');
|
|
896
|
-
console.log(' 1. npm install -g stigmergy # Install Stigmergy');
|
|
897
|
-
console.log(' 2. stigmergy install # Auto-scan & install CLI tools');
|
|
898
|
-
console.log(' 3. stigmergy setup # Deploy hooks & config');
|
|
899
|
-
console.log(' 4. stigmergy call <ai> <prompt> # Start collaborating');
|
|
900
|
-
console.log('');
|
|
901
|
-
console.log('For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
const command = args[0];
|
|
906
|
-
|
|
907
|
-
switch (command) {
|
|
908
|
-
case 'version':
|
|
909
|
-
case '--version':
|
|
910
|
-
console.log('Stigmergy CLI v1.0.89');
|
|
911
|
-
break;
|
|
912
|
-
|
|
913
|
-
case 'status':
|
|
914
|
-
const { available, missing } = await installer.scanCLI();
|
|
915
|
-
console.log('\n[STATUS] System Status:');
|
|
916
|
-
console.log(`Available: ${Object.keys(available).length} tools`);
|
|
917
|
-
console.log(`Missing: ${Object.keys(missing).length} tools`);
|
|
918
|
-
break;
|
|
919
|
-
|
|
920
|
-
case 'scan':
|
|
921
|
-
await installer.scanCLI();
|
|
922
|
-
break;
|
|
923
|
-
|
|
924
|
-
case 'install':
|
|
925
|
-
const { missing: missingTools } = await installer.scanCLI();
|
|
926
|
-
const options = await installer.showInstallOptions(missingTools);
|
|
927
|
-
|
|
928
|
-
if (options.length > 0) {
|
|
929
|
-
const selectedTools = await installer.getUserSelection(options, missingTools);
|
|
930
|
-
if (selectedTools.length > 0) {
|
|
931
|
-
console.log('\n[INFO] Installing selected tools (this may take several minutes for tools that download binaries)...');
|
|
932
|
-
await installer.installTools(selectedTools, missingTools);
|
|
933
|
-
}
|
|
934
|
-
} else {
|
|
935
|
-
console.log('\n[INFO] All required tools are already installed!');
|
|
936
|
-
}
|
|
937
|
-
break;
|
|
938
|
-
|
|
939
|
-
case 'deploy':
|
|
940
|
-
const { available: deployedTools } = await installer.scanCLI();
|
|
941
|
-
await installer.deployHooks(deployedTools);
|
|
942
|
-
break;
|
|
943
|
-
|
|
944
|
-
case 'setup':
|
|
945
|
-
console.log('[SETUP] Starting complete Stigmergy setup...\n');
|
|
946
|
-
|
|
947
|
-
// Step 1: Download required assets
|
|
948
|
-
await installer.downloadRequiredAssets();
|
|
949
|
-
|
|
950
|
-
// Step 2: Scan for CLI tools
|
|
951
|
-
const { available: setupAvailable, missing: setupMissing } = await installer.scanCLI();
|
|
952
|
-
const setupOptions = await installer.showInstallOptions(setupMissing);
|
|
953
|
-
|
|
954
|
-
// Step 3: Install missing CLI tools if user chooses
|
|
955
|
-
if (setupOptions.length > 0) {
|
|
956
|
-
const selectedTools = await installer.getUserSelection(setupOptions, setupMissing);
|
|
957
|
-
if (selectedTools.length > 0) {
|
|
958
|
-
console.log('\n[INFO] Installing selected tools (this may take several minutes for tools that download binaries)...');
|
|
959
|
-
await installer.installTools(selectedTools, setupMissing);
|
|
960
|
-
}
|
|
961
|
-
} else {
|
|
962
|
-
console.log('\n[INFO] All required tools are already installed!');
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
// Step 4: Deploy hooks to available CLI tools
|
|
966
|
-
await installer.deployHooks(setupAvailable);
|
|
967
|
-
|
|
968
|
-
// Step 5: Deploy project documentation
|
|
969
|
-
await installer.deployProjectDocumentation();
|
|
970
|
-
|
|
971
|
-
// Step 6: Initialize configuration
|
|
972
|
-
await installer.initializeConfig();
|
|
973
|
-
|
|
974
|
-
// Step 7: Show usage instructions
|
|
975
|
-
installer.showUsageInstructions();
|
|
976
|
-
break;
|
|
977
|
-
|
|
978
|
-
case 'call':
|
|
979
|
-
if (args.length < 2) {
|
|
980
|
-
console.log('[ERROR] Usage: stigmergy call <tool> "<prompt>"');
|
|
981
|
-
process.exit(1);
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
const targetTool = args[1];
|
|
985
|
-
const prompt = args.slice(2).join(' ');
|
|
986
|
-
|
|
987
|
-
// Handle call command logic
|
|
988
|
-
console.log(`[CALL] Executing with ${targetTool}: ${prompt}`);
|
|
989
|
-
// Implementation would go here
|
|
990
|
-
break;
|
|
991
|
-
|
|
992
|
-
case 'auto-install':
|
|
993
|
-
// Auto-install mode for npm postinstall - NON-INTERACTIVE
|
|
994
|
-
console.log('[AUTO-INSTALL] Stigmergy CLI automated setup');
|
|
995
|
-
console.log('='.repeat(60));
|
|
996
|
-
|
|
997
|
-
try {
|
|
998
|
-
// Step 1: Download required assets
|
|
714
|
+
case 'status':
|
|
999
715
|
try {
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
console.log('
|
|
716
|
+
const { available, missing } = await installer.scanCLI();
|
|
717
|
+
console.log('\n[STATUS] AI CLI Tools Status Report');
|
|
718
|
+
console.log('=====================================');
|
|
719
|
+
|
|
720
|
+
if (Object.keys(available).length > 0) {
|
|
721
|
+
console.log('\n✅ Available Tools:');
|
|
722
|
+
for (const [toolName, toolInfo] of Object.entries(available)) {
|
|
723
|
+
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (Object.keys(missing).length > 0) {
|
|
728
|
+
console.log('\n❌ Missing Tools:');
|
|
729
|
+
for (const [toolName, toolInfo] of Object.entries(missing)) {
|
|
730
|
+
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
731
|
+
console.log(` Install command: ${toolInfo.install}`);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
console.log(`\n[SUMMARY] ${Object.keys(available).length} available, ${Object.keys(missing).length} missing`);
|
|
1003
736
|
} catch (error) {
|
|
1004
|
-
|
|
1005
|
-
console.log(
|
|
737
|
+
await errorHandler.logError(error, 'ERROR', 'main.status');
|
|
738
|
+
console.log(`[ERROR] Failed to get status: ${error.message}`);
|
|
739
|
+
process.exit(1);
|
|
1006
740
|
}
|
|
741
|
+
break;
|
|
1007
742
|
|
|
1008
|
-
|
|
1009
|
-
let autoAvailable = {}, autoMissing = {};
|
|
743
|
+
case 'scan':
|
|
1010
744
|
try {
|
|
1011
|
-
|
|
1012
|
-
const scanResult = await installer.scanCLI();
|
|
1013
|
-
autoAvailable = scanResult.available;
|
|
1014
|
-
autoMissing = scanResult.missing;
|
|
1015
|
-
console.log('[OK] CLI tools scanned successfully');
|
|
745
|
+
await installer.scanCLI();
|
|
1016
746
|
} catch (error) {
|
|
1017
|
-
|
|
1018
|
-
console.log(
|
|
747
|
+
await errorHandler.logError(error, 'ERROR', 'main.scan');
|
|
748
|
+
console.log(`[ERROR] Failed to scan CLI tools: ${error.message}`);
|
|
749
|
+
process.exit(1);
|
|
1019
750
|
}
|
|
751
|
+
break;
|
|
1020
752
|
|
|
1021
|
-
|
|
753
|
+
case 'install':
|
|
1022
754
|
try {
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
755
|
+
console.log('[INSTALL] Starting AI CLI tools installation...');
|
|
756
|
+
const { missing: missingTools } = await installer.scanCLI();
|
|
757
|
+
const options = await installer.showInstallOptions(missingTools);
|
|
758
|
+
|
|
759
|
+
if (options.length > 0) {
|
|
760
|
+
const selectedTools = await installer.getUserSelection(options, missingTools);
|
|
761
|
+
if (selectedTools.length > 0) {
|
|
762
|
+
console.log('\n[INFO] Installing selected tools (this may take several minutes for tools that download binaries)...');
|
|
763
|
+
await installer.installTools(selectedTools, missingTools);
|
|
1027
764
|
}
|
|
1028
|
-
console.log('\n[INFO] Auto-install mode detected. Skipping automatic installation of missing tools.');
|
|
1029
|
-
console.log('[INFO] For full functionality, please run "stigmergy install" after installation completes.');
|
|
1030
765
|
} else {
|
|
1031
|
-
console.log('\n[INFO] All
|
|
766
|
+
console.log('\n[INFO] All required tools are already installed!');
|
|
1032
767
|
}
|
|
1033
768
|
} catch (error) {
|
|
1034
|
-
|
|
769
|
+
await errorHandler.logError(error, 'ERROR', 'main.install');
|
|
770
|
+
console.log(`[ERROR] Installation failed: ${error.message}`);
|
|
771
|
+
process.exit(1);
|
|
1035
772
|
}
|
|
773
|
+
break;
|
|
1036
774
|
|
|
1037
|
-
|
|
775
|
+
case 'deploy':
|
|
1038
776
|
try {
|
|
1039
|
-
|
|
1040
|
-
await installer.deployHooks(
|
|
1041
|
-
console.log('[OK] Hooks deployed successfully');
|
|
777
|
+
const { available: deployedTools } = await installer.scanCLI();
|
|
778
|
+
await installer.deployHooks(deployedTools);
|
|
1042
779
|
} catch (error) {
|
|
1043
|
-
|
|
1044
|
-
console.log(
|
|
780
|
+
await errorHandler.logError(error, 'ERROR', 'main.deploy');
|
|
781
|
+
console.log(`[ERROR] Deployment failed: ${error.message}`);
|
|
782
|
+
process.exit(1);
|
|
1045
783
|
}
|
|
784
|
+
break;
|
|
1046
785
|
|
|
1047
|
-
|
|
786
|
+
case 'setup':
|
|
1048
787
|
try {
|
|
1049
|
-
console.log('[
|
|
788
|
+
console.log('[SETUP] Starting complete Stigmergy setup...\n');
|
|
789
|
+
|
|
790
|
+
// Step 1: Download required assets
|
|
791
|
+
await installer.downloadRequiredAssets();
|
|
792
|
+
|
|
793
|
+
// Step 2: Scan for CLI tools
|
|
794
|
+
const { available: setupAvailable, missing: setupMissing } = await installer.scanCLI();
|
|
795
|
+
const setupOptions = await installer.showInstallOptions(setupMissing);
|
|
796
|
+
|
|
797
|
+
// Step 3: Install missing CLI tools if user chooses
|
|
798
|
+
if (setupOptions.length > 0) {
|
|
799
|
+
const selectedTools = await installer.getUserSelection(setupOptions, setupMissing);
|
|
800
|
+
if (selectedTools.length > 0) {
|
|
801
|
+
console.log('\n[INFO] Installing selected tools (this may take several minutes for tools that download binaries)...');
|
|
802
|
+
await installer.installTools(selectedTools, setupMissing);
|
|
803
|
+
}
|
|
804
|
+
} else {
|
|
805
|
+
console.log('\n[INFO] All required tools are already installed!');
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Step 4: Deploy hooks to available CLI tools
|
|
809
|
+
await installer.deployHooks(setupAvailable);
|
|
810
|
+
|
|
811
|
+
// Step 5: Deploy project documentation
|
|
1050
812
|
await installer.deployProjectDocumentation();
|
|
1051
|
-
|
|
813
|
+
|
|
814
|
+
// Step 6: Initialize configuration
|
|
815
|
+
await installer.initializeConfig();
|
|
816
|
+
|
|
817
|
+
// Step 7: Show usage instructions
|
|
818
|
+
installer.showUsageInstructions();
|
|
1052
819
|
} catch (error) {
|
|
1053
|
-
|
|
1054
|
-
console.log(
|
|
820
|
+
await errorHandler.logError(error, 'ERROR', 'main.setup');
|
|
821
|
+
console.log(`[ERROR] Setup failed: ${error.message}`);
|
|
822
|
+
console.log('\n[TROUBLESHOOTING] To manually complete setup:');
|
|
823
|
+
console.log('1. Run: stigmergy deploy # Deploy hooks manually');
|
|
824
|
+
console.log('2. Run: stigmergy setup # Try setup again');
|
|
825
|
+
process.exit(1);
|
|
1055
826
|
}
|
|
827
|
+
break;
|
|
1056
828
|
|
|
1057
|
-
|
|
829
|
+
case 'call':
|
|
830
|
+
if (args.length < 2) {
|
|
831
|
+
console.log('[ERROR] Usage: stigmergy call "<prompt>"');
|
|
832
|
+
process.exit(1);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Get the prompt (everything after the command)
|
|
836
|
+
const prompt = args.slice(1).join(' ');
|
|
837
|
+
|
|
838
|
+
// Use smart router to determine which tool to use
|
|
839
|
+
const router = new SmartRouter();
|
|
840
|
+
await router.initialize(); // Initialize the router first
|
|
841
|
+
const route = await router.smartRoute(prompt);
|
|
842
|
+
|
|
843
|
+
console.log(`[CALL] Routing to ${route.tool}: ${route.prompt}`);
|
|
844
|
+
|
|
845
|
+
// Execute the routed command
|
|
1058
846
|
try {
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
console.log(
|
|
847
|
+
// Get the actual executable path for the tool
|
|
848
|
+
const toolPath = route.tool;
|
|
849
|
+
console.log(`[DEBUG] Tool path: ${toolPath}, Prompt: ${route.prompt}`);
|
|
850
|
+
|
|
851
|
+
// For different tools, we need to pass the prompt differently
|
|
852
|
+
// Use unified parameter handler for better parameter handling
|
|
853
|
+
let toolArgs = [];
|
|
854
|
+
|
|
855
|
+
try {
|
|
856
|
+
// Get CLI pattern for this tool
|
|
857
|
+
const cliPattern = await router.analyzer.getCLIPattern(route.tool);
|
|
858
|
+
|
|
859
|
+
// Use the unified CLI parameter handler
|
|
860
|
+
const CLIParameterHandler = require('./core/cli_parameter_handler');
|
|
861
|
+
toolArgs = CLIParameterHandler.generateArguments(route.tool, route.prompt, cliPattern);
|
|
862
|
+
} catch (patternError) {
|
|
863
|
+
// Fallback to original logic if pattern analysis fails
|
|
864
|
+
if (route.tool === 'claude') {
|
|
865
|
+
// Claude CLI expects the prompt with -p flag for non-interactive mode
|
|
866
|
+
toolArgs = ['-p', `"${route.prompt}"`];
|
|
867
|
+
} else if (route.tool === 'qodercli' || route.tool === 'iflow') {
|
|
868
|
+
// Qoder CLI and iFlow expect the prompt with -p flag
|
|
869
|
+
toolArgs = ['-p', `"${route.prompt}"`];
|
|
870
|
+
} else if (route.tool === 'codex') {
|
|
871
|
+
// Codex CLI needs 'exec' subcommand for non-interactive mode
|
|
872
|
+
toolArgs = ['exec', '-p', `"${route.prompt}"`];
|
|
873
|
+
} else {
|
|
874
|
+
// For other tools, pass the prompt with -p flag
|
|
875
|
+
toolArgs = ['-p', `"${route.prompt}"`];
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// Use the correct way to spawn the process
|
|
880
|
+
const child = spawn(toolPath, toolArgs, {
|
|
881
|
+
stdio: 'inherit',
|
|
882
|
+
shell: true
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
child.on('close', (code) => {
|
|
886
|
+
if (code !== 0) {
|
|
887
|
+
console.log(`[WARN] ${route.tool} exited with code ${code}`);
|
|
888
|
+
}
|
|
889
|
+
process.exit(code);
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
child.on('error', async (error) => {
|
|
893
|
+
const cliError = await errorHandler.handleCLIError(route.tool, error, toolArgs.join(' '));
|
|
894
|
+
console.log(`[ERROR] Failed to execute ${route.tool}:`, cliError.message);
|
|
895
|
+
process.exit(1);
|
|
896
|
+
});
|
|
1062
897
|
} catch (error) {
|
|
1063
|
-
|
|
1064
|
-
console.log(
|
|
898
|
+
const cliError = await errorHandler.handleCLIError(route.tool, error, prompt);
|
|
899
|
+
console.log(`[ERROR] Failed to execute ${route.tool}:`, cliError.message);
|
|
900
|
+
process.exit(1);
|
|
1065
901
|
}
|
|
902
|
+
break;
|
|
1066
903
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
console.log('[
|
|
1070
|
-
console.log('
|
|
1071
|
-
console.log('[USAGE] Run "stigmergy --help" to see all available commands.');
|
|
1072
|
-
} catch (fatalError) {
|
|
1073
|
-
console.error('[FATAL] Auto-install process failed:', fatalError.message);
|
|
1074
|
-
console.log('\n[TROUBLESHOOTING] To manually complete installation:');
|
|
1075
|
-
console.log('1. Run: stigmergy setup # Complete setup');
|
|
1076
|
-
console.log('2. Run: stigmergy install # Install missing tools');
|
|
1077
|
-
console.log('3. Run: stigmergy deploy # Deploy hooks manually');
|
|
1078
|
-
process.exit(1);
|
|
1079
|
-
}
|
|
1080
|
-
break;
|
|
904
|
+
case 'auto-install':
|
|
905
|
+
// Auto-install mode for npm postinstall - NON-INTERACTIVE
|
|
906
|
+
console.log('[AUTO-INSTALL] Stigmergy CLI automated setup');
|
|
907
|
+
console.log('='.repeat(60));
|
|
1081
908
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
909
|
+
try {
|
|
910
|
+
// Step 1: Download required assets
|
|
911
|
+
try {
|
|
912
|
+
console.log('[STEP] Downloading required assets...');
|
|
913
|
+
await installer.downloadRequiredAssets();
|
|
914
|
+
console.log('[OK] Assets downloaded successfully');
|
|
915
|
+
} catch (error) {
|
|
916
|
+
console.log(`[WARN] Failed to download assets: ${error.message}`);
|
|
917
|
+
console.log('[INFO] Continuing with installation...');
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// Step 2: Scan for CLI tools
|
|
921
|
+
let autoAvailable = {}, autoMissing = {};
|
|
922
|
+
try {
|
|
923
|
+
console.log('[STEP] Scanning for CLI tools...');
|
|
924
|
+
const scanResult = await installer.scanCLI();
|
|
925
|
+
autoAvailable = scanResult.available;
|
|
926
|
+
autoMissing = scanResult.missing;
|
|
927
|
+
console.log('[OK] CLI tools scanned successfully');
|
|
928
|
+
} catch (error) {
|
|
929
|
+
console.log(`[WARN] Failed to scan CLI tools: ${error.message}`);
|
|
930
|
+
console.log('[INFO] Continuing with installation...');
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// Step 3: Show summary to user after installation
|
|
934
|
+
try {
|
|
935
|
+
if (Object.keys(autoMissing).length > 0) {
|
|
936
|
+
console.log('\n[INFO] Found ' + Object.keys(autoMissing).length + ' missing AI CLI tools:');
|
|
937
|
+
for (const [toolName, toolInfo] of Object.entries(autoMissing)) {
|
|
938
|
+
console.log(` - ${toolInfo.name} (${toolName})`);
|
|
939
|
+
}
|
|
940
|
+
console.log('\n[INFO] Auto-install mode detected. Skipping automatic installation of missing tools.');
|
|
941
|
+
console.log('[INFO] For full functionality, please run "stigmergy install" after installation completes.');
|
|
942
|
+
} else {
|
|
943
|
+
console.log('\n[INFO] All AI CLI tools are already installed! No additional tools required.');
|
|
944
|
+
}
|
|
945
|
+
} catch (error) {
|
|
946
|
+
console.log(`[WARN] Failed to show tool summary: ${error.message}`);
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// Step 4: Deploy hooks to available CLI tools
|
|
950
|
+
try {
|
|
951
|
+
console.log('[STEP] Deploying hooks to available CLI tools...');
|
|
952
|
+
await installer.deployHooks(autoAvailable);
|
|
953
|
+
console.log('[OK] Hooks deployed successfully');
|
|
954
|
+
} catch (error) {
|
|
955
|
+
console.log(`[ERROR] Failed to deploy hooks: ${error.message}`);
|
|
956
|
+
console.log('[INFO] You can manually deploy hooks later by running: stigmergy deploy');
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// Step 5: Deploy project documentation
|
|
960
|
+
try {
|
|
961
|
+
console.log('[STEP] Deploying project documentation...');
|
|
962
|
+
await installer.deployProjectDocumentation();
|
|
963
|
+
console.log('[OK] Documentation deployed successfully');
|
|
964
|
+
} catch (error) {
|
|
965
|
+
console.log(`[WARN] Failed to deploy documentation: ${error.message}`);
|
|
966
|
+
console.log('[INFO] Continuing with installation...');
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
// Step 6: Initialize configuration
|
|
970
|
+
try {
|
|
971
|
+
console.log('[STEP] Initializing configuration...');
|
|
972
|
+
await installer.initializeConfig();
|
|
973
|
+
console.log('[OK] Configuration initialized successfully');
|
|
974
|
+
} catch (error) {
|
|
975
|
+
console.log(`[ERROR] Failed to initialize configuration: ${error.message}`);
|
|
976
|
+
console.log('[INFO] You can manually initialize configuration later by running: stigmergy setup');
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// Step 7: Show final message to guide users
|
|
980
|
+
console.log('\n[SUCCESS] Stigmergy CLI installed successfully!');
|
|
981
|
+
console.log('[USAGE] Run "stigmergy setup" to complete full configuration and install missing AI CLI tools.');
|
|
982
|
+
console.log('[USAGE] Run "stigmergy install" to install only missing AI CLI tools.');
|
|
983
|
+
console.log('[USAGE] Run "stigmergy --help" to see all available commands.');
|
|
984
|
+
} catch (fatalError) {
|
|
985
|
+
await errorHandler.logError(fatalError, 'ERROR', 'main.auto-install');
|
|
986
|
+
console.error('[FATAL] Auto-install process failed:', fatalError.message);
|
|
987
|
+
console.log('\n[TROUBLESHOOTING] To manually complete installation:');
|
|
988
|
+
console.log('1. Run: stigmergy setup # Complete setup');
|
|
989
|
+
console.log('2. Run: stigmergy install # Install missing tools');
|
|
990
|
+
console.log('3. Run: stigmergy deploy # Deploy hooks manually');
|
|
991
|
+
process.exit(1);
|
|
992
|
+
}
|
|
993
|
+
break;
|
|
994
|
+
|
|
995
|
+
default:
|
|
996
|
+
console.log(`[ERROR] Unknown command: ${command}`);
|
|
997
|
+
console.log('[INFO] Run "stigmergy --help" for usage information');
|
|
998
|
+
process.exit(1);
|
|
999
|
+
}
|
|
1000
|
+
} catch (error) {
|
|
1001
|
+
await errorHandler.logError(error, 'ERROR', 'main');
|
|
1002
|
+
console.error('[FATAL] Stigmergy CLI encountered an error:', error.message);
|
|
1003
|
+
process.exit(1);
|
|
1086
1004
|
}
|
|
1087
1005
|
}
|
|
1088
1006
|
|
|
1007
|
+
// Function to find maximum of two numbers
|
|
1008
|
+
function maxOfTwo(a, b) {
|
|
1009
|
+
return a > b ? a : b;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1089
1012
|
// Export for testing
|
|
1090
|
-
module.exports = { StigmergyInstaller, SmartRouter, MemoryManager, CLI_TOOLS };
|
|
1013
|
+
module.exports = { StigmergyInstaller, SmartRouter, MemoryManager, CLI_TOOLS, maxOfTwo };
|
|
1091
1014
|
|
|
1092
1015
|
// Run main function
|
|
1093
1016
|
if (require.main === module) {
|
|
1094
1017
|
main().catch(error => {
|
|
1095
|
-
console.error('[FATAL] Stigmergy CLI encountered an error:', error);
|
|
1018
|
+
console.error('[FATAL] Stigmergy CLI encountered an unhandled error:', error);
|
|
1096
1019
|
process.exit(1);
|
|
1097
1020
|
});
|
|
1098
1021
|
}
|