stigmergy 1.0.95 → 1.0.98

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.
@@ -6,7 +6,9 @@
6
6
  * Version: 1.0.94
7
7
  */
8
8
 
9
- console.log('[DEBUG] Stigmergy CLI script started...');
9
+ if (process.env.DEBUG === 'true') {
10
+ console.log('[DEBUG] Stigmergy CLI script started...');
11
+ }
10
12
 
11
13
  const { spawn, spawnSync } = require('child_process');
12
14
  const path = require('path');
@@ -22,515 +24,617 @@ const SmartRouter = require('./core/smart_router');
22
24
  const CLIHelpAnalyzer = require('./core/cli_help_analyzer');
23
25
  const { CLI_TOOLS } = require('./core/cli_tools');
24
26
  const { errorHandler } = require('./core/error_handler');
27
+ const { executeCommand, executeJSFile } = require('./utils');
28
+ const {
29
+ handleRegister,
30
+ handleLogin,
31
+ handleLogout,
32
+ handleStatus,
33
+ } = require('./auth_command');
34
+ const { UserAuthenticator } = require('./auth');
35
+ const fsSync = require('fs');
36
+
37
+ // Set up global error handlers using our error handler module
38
+ const { setupGlobalErrorHandlers } = require('./core/error_handler');
39
+ setupGlobalErrorHandlers();
25
40
 
26
41
  class MemoryManager {
27
- constructor() {
28
- this.globalMemoryFile = path.join(os.homedir(), '.stigmergy', 'memory.json');
29
- this.projectMemoryFile = path.join(process.cwd(), 'STIGMERGY.md');
30
- }
31
-
32
- async addInteraction(tool, prompt, response) {
33
- const interaction = {
34
- timestamp: new Date().toISOString(),
35
- tool,
36
- prompt,
37
- response,
38
- duration: Date.now() - new Date().getTime()
39
- };
42
+ constructor() {
43
+ this.globalMemoryFile = path.join(
44
+ os.homedir(),
45
+ '.stigmergy',
46
+ 'memory.json',
47
+ );
48
+ this.projectMemoryFile = path.join(process.cwd(), 'STIGMERGY.md');
49
+ }
50
+
51
+ async addInteraction(tool, prompt, response) {
52
+ const interaction = {
53
+ timestamp: new Date().toISOString(),
54
+ tool,
55
+ prompt,
56
+ response,
57
+ duration: Date.now() - new Date().getTime(),
58
+ };
40
59
 
41
- try {
42
- // Add to global memory
43
- await this.saveGlobalMemory(interaction);
60
+ try {
61
+ // Add to global memory
62
+ await this.saveGlobalMemory(interaction);
44
63
 
45
- // Add to project memory
46
- await this.saveProjectMemory(interaction);
47
- } catch (error) {
48
- await errorHandler.logError(error, 'ERROR', 'MemoryManager.addInteraction');
49
- }
64
+ // Add to project memory
65
+ await this.saveProjectMemory(interaction);
66
+ } catch (error) {
67
+ await errorHandler.logError(
68
+ error,
69
+ 'ERROR',
70
+ 'MemoryManager.addInteraction',
71
+ );
50
72
  }
73
+ }
51
74
 
52
- async saveGlobalMemory(interaction) {
53
- try {
54
- const memory = await this.loadGlobalMemory();
55
- memory.interactions = memory.interactions.concat(interaction).slice(-100); // Keep last 100
56
- memory.lastInteraction = interaction;
57
-
58
- await fs.mkdir(path.dirname(this.globalMemoryFile), { recursive: true });
59
- await fs.writeFile(this.globalMemoryFile, JSON.stringify(memory, null, 2));
60
- } catch (error) {
61
- await errorHandler.logError(error, 'ERROR', 'MemoryManager.saveGlobalMemory');
62
- console.error(`[MEMORY] Failed to save global memory: ${error.message}`);
63
- }
75
+ async saveGlobalMemory(interaction) {
76
+ try {
77
+ const memory = await this.loadGlobalMemory();
78
+ memory.interactions = memory.interactions.concat(interaction).slice(-100); // Keep last 100
79
+ memory.lastInteraction = interaction;
80
+
81
+ await fs.mkdir(path.dirname(this.globalMemoryFile), { recursive: true });
82
+ await fs.writeFile(
83
+ this.globalMemoryFile,
84
+ JSON.stringify(memory, null, 2),
85
+ );
86
+ } catch (error) {
87
+ await errorHandler.logError(
88
+ error,
89
+ 'ERROR',
90
+ 'MemoryManager.saveGlobalMemory',
91
+ );
92
+ console.error(`[MEMORY] Failed to save global memory: ${error.message}`);
64
93
  }
94
+ }
65
95
 
66
- async saveProjectMemory(interaction) {
67
- try {
68
- const memory = await this.loadProjectMemory();
69
- memory.interactions = memory.interactions.concat(interaction).slice(-50); // Keep last 50
70
- memory.lastInteraction = interaction;
71
-
72
- await fs.writeFile(this.projectMemoryFile, this.formatProjectMemory(memory));
73
- } catch (error) {
74
- await errorHandler.logError(error, 'ERROR', 'MemoryManager.saveProjectMemory');
75
- console.error(`[MEMORY] Failed to save project memory: ${error.message}`);
76
- }
96
+ async saveProjectMemory(interaction) {
97
+ try {
98
+ const memory = await this.loadProjectMemory();
99
+ memory.interactions = memory.interactions.concat(interaction).slice(-50); // Keep last 50
100
+ memory.lastInteraction = interaction;
101
+
102
+ await fs.writeFile(
103
+ this.projectMemoryFile,
104
+ this.formatProjectMemory(memory),
105
+ );
106
+ } catch (error) {
107
+ await errorHandler.logError(
108
+ error,
109
+ 'ERROR',
110
+ 'MemoryManager.saveProjectMemory',
111
+ );
112
+ console.error(`[MEMORY] Failed to save project memory: ${error.message}`);
77
113
  }
114
+ }
78
115
 
79
- async loadGlobalMemory() {
80
- try {
81
- const data = await fs.readFile(this.globalMemoryFile, 'utf8');
82
- return JSON.parse(data);
83
- } catch {
84
- return {
85
- projectName: 'Global Stigmergy Memory',
86
- interactions: [],
87
- createdAt: new Date().toISOString()
88
- };
89
- }
116
+ async loadGlobalMemory() {
117
+ try {
118
+ const data = await fs.readFile(this.globalMemoryFile, 'utf8');
119
+ return JSON.parse(data);
120
+ } catch {
121
+ return {
122
+ projectName: 'Global Stigmergy Memory',
123
+ interactions: [],
124
+ createdAt: new Date().toISOString(),
125
+ };
90
126
  }
127
+ }
91
128
 
92
- async loadProjectMemory() {
93
- try {
94
- const data = await fs.readFile(this.projectMemoryFile, 'utf8');
95
- return this.parseProjectMemory(data);
96
- } catch {
97
- return {
98
- projectName: path.basename(process.cwd()),
99
- interactions: [],
100
- createdAt: new Date().toISOString()
101
- };
102
- }
129
+ async loadProjectMemory() {
130
+ try {
131
+ const data = await fs.readFile(this.projectMemoryFile, 'utf8');
132
+ return this.parseProjectMemory(data);
133
+ } catch {
134
+ return {
135
+ projectName: path.basename(process.cwd()),
136
+ interactions: [],
137
+ createdAt: new Date().toISOString(),
138
+ };
139
+ }
140
+ }
141
+
142
+ formatProjectMemory(memory) {
143
+ let content = '# Stigmergy Project Memory\n\n';
144
+ content += `**Project**: ${memory.projectName}\n`;
145
+ content += `**Created**: ${memory.createdAt}\n`;
146
+ content += `**Last Updated**: ${new Date().toISOString()}\n\n`;
147
+
148
+ if (memory.lastInteraction) {
149
+ content += '## Last Interaction\n\n';
150
+ content += `- **Tool**: ${memory.lastInteraction.tool}\n`;
151
+ content += `- **Timestamp**: ${memory.lastInteraction.timestamp}\n`;
152
+ content += `- **Prompt**: ${memory.lastInteraction.prompt}\n`;
153
+ content += `- **Response**: ${memory.lastInteraction.response.substring(0, 200)}...\n\n`;
103
154
  }
104
155
 
105
- formatProjectMemory(memory) {
106
- let content = `# Stigmergy Project Memory\n\n`;
107
- content += `**Project**: ${memory.projectName}\n`;
108
- content += `**Created**: ${memory.createdAt}\n`;
109
- content += `**Last Updated**: ${new Date().toISOString()}\n\n`;
156
+ content += `## Recent Interactions (${memory.interactions.length})\n\n`;
157
+ memory.interactions.slice(-10).forEach((interaction, index) => {
158
+ content += `### ${index + 1}. ${interaction.tool} - ${interaction.timestamp}\n\n`;
159
+ content += `**Prompt**: ${interaction.prompt}\n\n`;
160
+ content += `**Response**: ${interaction.response.substring(0, 200)}...\n\n`;
161
+ });
110
162
 
111
- if (memory.lastInteraction) {
112
- content += `## Last Interaction\n\n`;
113
- content += `- **Tool**: ${memory.lastInteraction.tool}\n`;
114
- content += `- **Timestamp**: ${memory.lastInteraction.timestamp}\n`;
115
- content += `- **Prompt**: ${memory.lastInteraction.prompt}\n`;
116
- content += `- **Response**: ${memory.lastInteraction.response.substring(0, 200)}...\n\n`;
117
- }
163
+ return content;
164
+ }
165
+
166
+ parseProjectMemory(markdown) {
167
+ // Simple parser for project memory
168
+ return {
169
+ projectName: 'Project',
170
+ interactions: [],
171
+ createdAt: new Date().toISOString(),
172
+ };
173
+ }
174
+ }
118
175
 
119
- content += `## Recent Interactions (${memory.interactions.length})\n\n`;
120
- memory.interactions.slice(-10).forEach((interaction, index) => {
121
- content += `### ${index + 1}. ${interaction.tool} - ${interaction.timestamp}\n\n`;
122
- content += `**Prompt**: ${interaction.prompt}\n\n`;
123
- content += `**Response**: ${interaction.response.substring(0, 200)}...\n\n`;
176
+ class StigmergyInstaller {
177
+ constructor() {
178
+ this.router = new SmartRouter();
179
+ this.memory = new MemoryManager();
180
+ this.configDir = path.join(os.homedir(), '.stigmergy');
181
+ }
182
+
183
+ async checkCLI(toolName) {
184
+ const tool = this.router.tools[toolName];
185
+ if (!tool) return false;
186
+
187
+ // Try multiple ways to check if CLI is available
188
+ const checks = [
189
+ // Method 1: Try version command
190
+ { args: ['--version'], expected: 0 },
191
+ // Method 2: Try help command
192
+ { args: ['--help'], expected: 0 },
193
+ // Method 3: Try help command with -h
194
+ { args: ['-h'], expected: 0 },
195
+ // Method 4: Try just the command (help case)
196
+ { args: [], expected: 0 },
197
+ ];
198
+
199
+ for (const check of checks) {
200
+ try {
201
+ const result = spawnSync(toolName, check.args, {
202
+ encoding: 'utf8',
203
+ timeout: 5000,
204
+ shell: true,
124
205
  });
125
206
 
126
- return content;
207
+ // Check if command executed successfully or at least didn't fail with "command not found"
208
+ if (
209
+ result.status === check.expected ||
210
+ (result.status !== 127 && result.status !== 9009)
211
+ ) {
212
+ // 127 = command not found on Unix, 9009 = command not found on Windows
213
+ return true;
214
+ }
215
+ } catch (error) {
216
+ // Continue to next check method
217
+ continue;
218
+ }
127
219
  }
128
220
 
129
- parseProjectMemory(markdown) {
130
- // Simple parser for project memory
131
- return {
132
- projectName: 'Project',
133
- interactions: [],
134
- createdAt: new Date().toISOString()
135
- };
221
+ return false;
222
+ }
223
+
224
+ async scanCLI() {
225
+ console.log('[SCAN] Scanning for AI CLI tools...');
226
+ const available = {};
227
+ const missing = {};
228
+
229
+ for (const [toolName, toolInfo] of Object.entries(this.router.tools)) {
230
+ try {
231
+ console.log(`[SCAN] Checking ${toolInfo.name}...`);
232
+ const isAvailable = await this.checkCLI(toolName);
233
+
234
+ if (isAvailable) {
235
+ console.log(`[OK] ${toolInfo.name} is available`);
236
+ available[toolName] = toolInfo;
237
+ } else {
238
+ console.log(`[MISSING] ${toolInfo.name} is not installed`);
239
+ missing[toolName] = toolInfo;
240
+ }
241
+ } catch (error) {
242
+ await errorHandler.logError(
243
+ error,
244
+ 'WARN',
245
+ `StigmergyInstaller.scanCLI.${toolName}`,
246
+ );
247
+ console.log(
248
+ `[ERROR] Failed to check ${toolInfo.name}: ${error.message}`,
249
+ );
250
+ missing[toolName] = toolInfo;
251
+ }
136
252
  }
137
- }
138
253
 
139
- class StigmergyInstaller {
140
- constructor() {
141
- this.router = new SmartRouter();
142
- this.memory = new MemoryManager();
143
- this.configDir = path.join(os.homedir(), '.stigmergy');
144
- }
145
-
146
- async checkCLI(toolName) {
147
- const tool = this.router.tools[toolName];
148
- if (!tool) return false;
149
-
150
- // Try multiple ways to check if CLI is available
151
- const checks = [
152
- // Method 1: Try version command
153
- { args: ['--version'], expected: 0 },
154
- // Method 2: Try help command
155
- { args: ['--help'], expected: 0 },
156
- // Method 3: Try help command with -h
157
- { args: ['-h'], expected: 0 },
158
- // Method 4: Try just the command (help case)
159
- { args: [], expected: 0 },
160
- ];
161
-
162
- for (const check of checks) {
163
- try {
164
- const result = spawnSync(toolName, check.args, {
165
- encoding: 'utf8',
166
- timeout: 5000,
167
- shell: true
168
- });
169
-
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
173
- return true;
174
- }
175
- } catch (error) {
176
- // Continue to next check method
177
- continue;
178
- }
179
- }
254
+ return { available, missing };
255
+ }
180
256
 
181
- return false;
182
- }
183
-
184
- async scanCLI() {
185
- console.log('[SCAN] Scanning for AI CLI tools...');
186
- const available = {};
187
- const missing = {};
188
-
189
- for (const [toolName, toolInfo] of Object.entries(this.router.tools)) {
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}`);
204
- missing[toolName] = toolInfo;
205
- }
206
- }
257
+ async installTools(selectedTools, missingTools) {
258
+ console.log(
259
+ `\n[INSTALL] Installing ${selectedTools.length} AI CLI tools...`,
260
+ );
207
261
 
208
- return { available, missing };
209
- }
210
-
211
- async installTools(selectedTools, missingTools) {
212
- console.log(`\n[INSTALL] Installing ${selectedTools.length} AI CLI tools...`);
213
-
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;
219
- }
220
-
221
- try {
222
- console.log(`\n[INSTALL] Installing ${toolInfo.name}...`);
223
- console.log(`[CMD] ${toolInfo.install}`);
224
-
225
- const result = spawnSync(toolInfo.install, {
226
- shell: true,
227
- stdio: 'inherit'
228
- });
229
-
230
- if (result.status === 0) {
231
- console.log(`[OK] ${toolInfo.name} installed successfully`);
232
- } else {
233
- console.log(`[ERROR] Failed to install ${toolInfo.name} (exit code: ${result.status})`);
234
- if (result.error) {
235
- console.log(`[ERROR] Installation error: ${result.error.message}`);
236
- }
237
- console.log(`[INFO] Please run manually: ${toolInfo.install}`);
238
- }
239
- } catch (error) {
240
- await errorHandler.logError(error, 'ERROR', `StigmergyInstaller.installTools.${toolName}`);
241
- console.log(`[ERROR] Failed to install ${toolInfo.name}: ${error.message}`);
242
- console.log(`[INFO] Please run manually: ${toolInfo.install}`);
243
- }
244
- }
262
+ for (const toolName of selectedTools) {
263
+ const toolInfo = missingTools[toolName];
264
+ if (!toolInfo) {
265
+ console.log(`[SKIP] Tool ${toolName} not found in missing tools list`);
266
+ continue;
267
+ }
245
268
 
246
- return true;
247
- }
269
+ try {
270
+ console.log(`\n[INSTALL] Installing ${toolInfo.name}...`);
271
+ console.log(`[CMD] ${toolInfo.install}`);
248
272
 
249
- async downloadRequiredAssets() {
250
- console.log('\n[DOWNLOAD] Downloading required assets and plugins...');
251
-
252
- // SAFETY CHECK: Verify no conflicting packages exist
253
- await this.safetyCheck();
254
-
255
- try {
256
- // Create local assets directory
257
- const assetsDir = path.join(os.homedir(), '.stigmergy', 'assets');
258
- await fs.mkdir(assetsDir, { recursive: true });
259
-
260
- // Copy template files from package
261
- const packageTemplatesDir = path.join(__dirname, '..', 'templates', 'project-docs');
262
- const localTemplatesDir = path.join(assetsDir, 'templates');
263
-
264
- if (await this.fileExists(packageTemplatesDir)) {
265
- await fs.mkdir(localTemplatesDir, { recursive: true });
266
-
267
- // Copy all template files
268
- const templateFiles = await fs.readdir(packageTemplatesDir);
269
- for (const file of templateFiles) {
270
- const srcPath = path.join(packageTemplatesDir, file);
271
- const dstPath = path.join(localTemplatesDir, file);
272
- await fs.copyFile(srcPath, dstPath);
273
- console.log(`[OK] Copied template: ${file}`);
274
- }
275
- }
276
-
277
- // Download/copy CLI adapters
278
- const adaptersDir = path.join(__dirname, '..', 'src', 'adapters');
279
- const localAdaptersDir = path.join(assetsDir, 'adapters');
280
-
281
- if (await this.fileExists(adaptersDir)) {
282
- await fs.mkdir(localAdaptersDir, { recursive: true });
283
-
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
- }
299
- }
300
-
301
- console.log('[OK] All required assets downloaded successfully');
302
- return true;
303
-
304
- } catch (error) {
305
- await errorHandler.logError(error, 'ERROR', 'StigmergyInstaller.downloadRequiredAssets');
306
- console.log(`[ERROR] Failed to download required assets: ${error.message}`);
307
- return false;
308
- }
309
- }
273
+ const result = spawnSync(toolInfo.install, {
274
+ shell: true,
275
+ stdio: 'inherit',
276
+ });
310
277
 
311
- async safetyCheck() {
312
- console.log('\n[SAFETY] Performing safety check for conflicting packages...');
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
326
- try {
327
- const result = spawnSync('npm', ['list', '-g', '--depth=0'], {
328
- encoding: 'utf8',
329
- timeout: 10000
330
- });
331
-
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');
347
- }
348
- }
349
- } catch (error) {
350
- console.log(`[WARN] Unable to perform safety check: ${error.message}`);
278
+ if (result.status === 0) {
279
+ console.log(`[OK] ${toolInfo.name} installed successfully`);
280
+ } else {
281
+ console.log(
282
+ `[ERROR] Failed to install ${toolInfo.name} (exit code: ${result.status})`,
283
+ );
284
+ if (result.error) {
285
+ console.log(`[ERROR] Installation error: ${result.error.message}`);
286
+ }
287
+ console.log(`[INFO] Please run manually: ${toolInfo.install}`);
351
288
  }
289
+ } catch (error) {
290
+ await errorHandler.logError(
291
+ error,
292
+ 'ERROR',
293
+ `StigmergyInstaller.installTools.${toolName}`,
294
+ );
295
+ console.log(
296
+ `[ERROR] Failed to install ${toolInfo.name}: ${error.message}`,
297
+ );
298
+ console.log(`[INFO] Please run manually: ${toolInfo.install}`);
299
+ }
352
300
  }
353
301
 
354
- async copyDirectory(src, dest) {
355
- try {
356
- await fs.mkdir(dest, { recursive: true });
357
- const entries = await fs.readdir(src, { withFileTypes: true });
358
-
359
- for (const entry of entries) {
360
- const srcPath = path.join(src, entry.name);
361
- const destPath = path.join(dest, entry.name);
362
-
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
- }
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}`);
374
- }
375
- }
302
+ return true;
303
+ }
376
304
 
377
- async fileExists(filePath) {
378
- try {
379
- await fs.access(filePath);
380
- return true;
381
- } catch {
382
- return false;
383
- }
384
- }
305
+ async downloadRequiredAssets() {
306
+ console.log('\n[DOWNLOAD] Downloading required assets and plugins...');
385
307
 
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 [];
308
+ // SAFETY CHECK: Verify no conflicting packages exist
309
+ await this.safetyCheck();
310
+
311
+ try {
312
+ // Create local assets directory
313
+ const assetsDir = path.join(os.homedir(), '.stigmergy', 'assets');
314
+ await fs.mkdir(assetsDir, { recursive: true });
315
+
316
+ // Copy template files from package
317
+ const packageTemplatesDir = path.join(
318
+ __dirname,
319
+ '..',
320
+ 'templates',
321
+ 'project-docs',
322
+ );
323
+ const localTemplatesDir = path.join(assetsDir, 'templates');
324
+
325
+ if (await this.fileExists(packageTemplatesDir)) {
326
+ await fs.mkdir(localTemplatesDir, { recursive: true });
327
+
328
+ // Copy all template files
329
+ const templateFiles = await fs.readdir(packageTemplatesDir);
330
+ for (const file of templateFiles) {
331
+ const srcPath = path.join(packageTemplatesDir, file);
332
+ const dstPath = path.join(localTemplatesDir, file);
333
+ await fs.copyFile(srcPath, dstPath);
334
+ console.log(`[OK] Copied template: ${file}`);
390
335
  }
336
+ }
391
337
 
392
- console.log('\n[INSTALL] Missing AI CLI tools detected:');
393
- const choices = [];
338
+ // Download/copy CLI adapters
339
+ const adaptersDir = path.join(__dirname, '..', 'src', 'adapters');
340
+ const localAdaptersDir = path.join(assetsDir, 'adapters');
394
341
 
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
- }
342
+ if (await this.fileExists(adaptersDir)) {
343
+ await fs.mkdir(localAdaptersDir, { recursive: true });
402
344
 
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
- ]);
345
+ // Copy all adapter directories
346
+ const adapterDirs = await fs.readdir(adaptersDir);
347
+ for (const dir of adapterDirs) {
348
+ // Skip non-directory items
349
+ const dirPath = path.join(adaptersDir, dir);
350
+ const stat = await fs.stat(dirPath);
351
+ if (!stat.isDirectory()) continue;
412
352
 
413
- return answers.tools;
414
- }
353
+ // Skip __pycache__ directories
354
+ if (dir === '__pycache__') continue;
415
355
 
416
- async getUserSelection(options, missingTools) {
417
- if (options.length === 0) {
418
- return [];
356
+ const dstPath = path.join(localAdaptersDir, dir);
357
+ await this.copyDirectory(dirPath, dstPath);
358
+ console.log(`[OK] Copied adapter: ${dir}`);
419
359
  }
360
+ }
420
361
 
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;
362
+ console.log('[OK] All required assets downloaded successfully');
363
+ return true;
364
+ } catch (error) {
365
+ await errorHandler.logError(
366
+ error,
367
+ 'ERROR',
368
+ 'StigmergyInstaller.downloadRequiredAssets',
369
+ );
370
+ console.log(
371
+ `[ERROR] Failed to download required assets: ${error.message}`,
372
+ );
373
+ return false;
374
+ }
375
+ }
376
+
377
+ async safetyCheck() {
378
+ console.log(
379
+ '\n[SAFETY] Performing safety check for conflicting packages...',
380
+ );
381
+
382
+ // List of potentially conflicting packages
383
+ const conflictingPackages = [
384
+ '@aws-amplify/cli',
385
+ 'firebase-tools',
386
+ 'heroku',
387
+ 'netlify-cli',
388
+ 'vercel',
389
+ 'surge',
390
+ 'now',
391
+ ];
392
+
393
+ // Check for globally installed conflicting packages
394
+ try {
395
+ const result = spawnSync('npm', ['list', '-g', '--depth=0'], {
396
+ encoding: 'utf8',
397
+ timeout: 10000,
398
+ });
399
+
400
+ if (result.status === 0) {
401
+ const installedPackages = result.stdout;
402
+ const conflicts = [];
403
+
404
+ for (const pkg of conflictingPackages) {
405
+ if (installedPackages.includes(pkg)) {
406
+ conflicts.push(pkg);
407
+ }
432
408
  }
433
409
 
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
- }));
410
+ if (conflicts.length > 0) {
411
+ console.log(
412
+ `[WARN] Potential conflicting packages detected: ${conflicts.join(', ')}`,
413
+ );
414
+ console.log(
415
+ '[INFO] These packages may interfere with Stigmergy CLI functionality',
416
+ );
417
+ } else {
418
+ console.log('[OK] No conflicting packages detected');
419
+ }
420
+ }
421
+ } catch (error) {
422
+ console.log(`[WARN] Unable to perform safety check: ${error.message}`);
423
+ }
424
+ }
440
425
 
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
- ]);
426
+ async copyDirectory(src, dest) {
427
+ try {
428
+ await fs.mkdir(dest, { recursive: true });
429
+ const entries = await fs.readdir(src, { withFileTypes: true });
430
+
431
+ for (const entry of entries) {
432
+ const srcPath = path.join(src, entry.name);
433
+ const destPath = path.join(dest, entry.name);
434
+
435
+ if (entry.isDirectory()) {
436
+ // Skip __pycache__ directories
437
+ if (entry.name === '__pycache__') continue;
438
+ await this.copyDirectory(srcPath, destPath);
439
+ } else {
440
+ await fs.copyFile(srcPath, destPath);
441
+ }
442
+ }
443
+ } catch (error) {
444
+ await errorHandler.logError(
445
+ error,
446
+ 'WARN',
447
+ 'StigmergyInstaller.copyDirectory',
448
+ );
449
+ console.log(
450
+ `[WARN] Failed to copy directory ${src} to ${dest}: ${error.message}`,
451
+ );
452
+ }
453
+ }
450
454
 
451
- return individualAnswers.selectedTools;
455
+ async fileExists(filePath) {
456
+ try {
457
+ await fs.access(filePath);
458
+ return true;
459
+ } catch {
460
+ return false;
452
461
  }
462
+ }
453
463
 
454
- async deployHooks(available) {
455
- console.log('\n[DEPLOY] Deploying cross-CLI integration hooks...');
464
+ async showInstallOptions(missingTools) {
465
+ if (Object.keys(missingTools).length === 0) {
466
+ console.log('[INFO] All required AI CLI tools are already installed!');
467
+ return [];
468
+ }
456
469
 
457
- // Import the post-deployment configurer for executing installation scripts
458
- const { PostDeploymentConfigurer } = require('./../scripts/post-deployment-config.js');
459
- const configurer = new PostDeploymentConfigurer();
470
+ console.log('\n[INSTALL] Missing AI CLI tools detected:');
471
+ const choices = [];
460
472
 
461
- let successCount = 0;
462
- let totalCount = Object.keys(available).length;
473
+ for (const [toolName, toolInfo] of Object.entries(missingTools)) {
474
+ choices.push({
475
+ name: `${toolInfo.name} (${toolName}) - ${toolInfo.install}`,
476
+ value: toolName,
477
+ checked: true,
478
+ });
479
+ }
463
480
 
464
- for (const [toolName, toolInfo] of Object.entries(available)) {
465
- console.log(`\n[DEPLOY] Deploying hooks for ${toolInfo.name}...`);
466
-
467
- try {
468
- await fs.mkdir(toolInfo.hooksDir, { recursive: true });
469
-
470
- // Create config directory (not the config file itself)
471
- const configDir = path.dirname(toolInfo.config);
472
- await fs.mkdir(configDir, { recursive: true });
473
-
474
- // Copy adapter files from local assets
475
- // Mapping for tool names that don't match their adapter directory names
476
- const toolNameToAdapterDir = {
477
- 'qodercli': 'qoder',
478
- 'qwencode': 'qwen'
479
- };
480
- const adapterDirName = toolNameToAdapterDir[toolName] || toolName;
481
- const assetsAdaptersDir = path.join(os.homedir(), '.stigmergy', 'assets', 'adapters', adapterDirName);
482
- if (await this.fileExists(assetsAdaptersDir)) {
483
- await this.copyDirectory(assetsAdaptersDir, toolInfo.hooksDir);
484
- console.log(`[OK] Copied adapter files for ${toolInfo.name}`);
485
- }
486
-
487
- // Execute post-deployment configuration
488
- try {
489
- await configurer.configureTool(toolName);
490
- console.log(`[OK] Post-deployment configuration completed for ${toolInfo.name}`);
491
- successCount++;
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
496
- }
497
-
498
- } catch (error) {
499
- await errorHandler.logError(error, 'ERROR', `StigmergyInstaller.deployHooks.${toolName}`);
500
- console.log(`[ERROR] Failed to deploy hooks for ${toolInfo.name}: ${error.message}`);
501
- console.log('[INFO] Continuing with other tools...');
502
- }
503
- }
481
+ const answers = await inquirer.prompt([
482
+ {
483
+ type: 'checkbox',
484
+ name: 'tools',
485
+ message:
486
+ 'Select which tools to install (Space to select, Enter to confirm):',
487
+ choices: choices,
488
+ pageSize: 10,
489
+ },
490
+ ]);
491
+
492
+ return answers.tools;
493
+ }
494
+
495
+ async getUserSelection(options, missingTools) {
496
+ if (options.length === 0) {
497
+ return [];
498
+ }
504
499
 
505
- console.log(`\n[SUMMARY] Hook deployment completed: ${successCount}/${totalCount} tools successful`);
500
+ const answers = await inquirer.prompt([
501
+ {
502
+ type: 'confirm',
503
+ name: 'proceed',
504
+ message: `Install ${options.length} missing AI CLI tools?`,
505
+ default: true,
506
+ },
507
+ ]);
508
+
509
+ if (answers.proceed) {
510
+ return options;
506
511
  }
507
512
 
508
- async deployProjectDocumentation() {
509
- console.log('\n[DEPLOY] Deploying project documentation...');
513
+ // If user doesn't want to install all, let them choose individually
514
+ const individualChoices = options.map((toolName) => ({
515
+ name: missingTools[toolName].name,
516
+ value: toolName,
517
+ checked: true,
518
+ }));
519
+
520
+ const individualAnswers = await inquirer.prompt([
521
+ {
522
+ type: 'checkbox',
523
+ name: 'selectedTools',
524
+ message: 'Select which tools to install:',
525
+ choices: individualChoices,
526
+ pageSize: 10,
527
+ },
528
+ ]);
529
+
530
+ return individualAnswers.selectedTools;
531
+ }
532
+
533
+ async deployHooks(available) {
534
+ console.log('\n[DEPLOY] Deploying cross-CLI integration hooks...');
535
+
536
+ // Import the post-deployment configurer for executing installation scripts
537
+ const {
538
+ PostDeploymentConfigurer,
539
+ } = require('./../scripts/post-deployment-config.js');
540
+ const configurer = new PostDeploymentConfigurer();
541
+
542
+ let successCount = 0;
543
+ let totalCount = Object.keys(available).length;
544
+
545
+ for (const [toolName, toolInfo] of Object.entries(available)) {
546
+ console.log(`\n[DEPLOY] Deploying hooks for ${toolInfo.name}...`);
547
+
548
+ try {
549
+ await fs.mkdir(toolInfo.hooksDir, { recursive: true });
550
+
551
+ // Create config directory (not the config file itself)
552
+ const configDir = path.dirname(toolInfo.config);
553
+ await fs.mkdir(configDir, { recursive: true });
554
+
555
+ // Copy adapter files from local assets
556
+ // Mapping for tool names that don't match their adapter directory names
557
+ const toolNameToAdapterDir = {
558
+ qodercli: 'qoder',
559
+ qwencode: 'qwen',
560
+ };
561
+ const adapterDirName = toolNameToAdapterDir[toolName] || toolName;
562
+ const assetsAdaptersDir = path.join(
563
+ os.homedir(),
564
+ '.stigmergy',
565
+ 'assets',
566
+ 'adapters',
567
+ adapterDirName,
568
+ );
569
+ if (await this.fileExists(assetsAdaptersDir)) {
570
+ await this.copyDirectory(assetsAdaptersDir, toolInfo.hooksDir);
571
+ console.log(`[OK] Copied adapter files for ${toolInfo.name}`);
572
+ }
510
573
 
574
+ // Execute post-deployment configuration
511
575
  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}`);
576
+ await configurer.configureTool(toolName);
577
+ console.log(
578
+ `[OK] Post-deployment configuration completed for ${toolInfo.name}`,
579
+ );
580
+ successCount++;
581
+ } catch (configError) {
582
+ await errorHandler.logError(
583
+ configError,
584
+ 'WARN',
585
+ `StigmergyInstaller.deployHooks.${toolName}.config`,
586
+ );
587
+ console.log(
588
+ `[WARN] Post-deployment configuration failed for ${toolInfo.name}: ${configError.message}`,
589
+ );
590
+ // Continue with other tools even if one fails
529
591
  }
592
+ } catch (error) {
593
+ await errorHandler.logError(
594
+ error,
595
+ 'ERROR',
596
+ `StigmergyInstaller.deployHooks.${toolName}`,
597
+ );
598
+ console.log(
599
+ `[ERROR] Failed to deploy hooks for ${toolInfo.name}: ${error.message}`,
600
+ );
601
+ console.log('[INFO] Continuing with other tools...');
602
+ }
530
603
  }
531
604
 
532
- generateProjectMemoryTemplate() {
533
- return `# Stigmergy Project Memory
605
+ console.log(
606
+ `\n[SUMMARY] Hook deployment completed: ${successCount}/${totalCount} tools successful`,
607
+ );
608
+ }
609
+
610
+ async deployProjectDocumentation() {
611
+ console.log('\n[DEPLOY] Deploying project documentation...');
612
+
613
+ try {
614
+ // Create standard project documentation files
615
+ const docs = {
616
+ 'STIGMERGY.md': this.generateProjectMemoryTemplate(),
617
+ 'README.md': this.generateProjectReadme(),
618
+ };
619
+
620
+ for (const [filename, content] of Object.entries(docs)) {
621
+ const filepath = path.join(process.cwd(), filename);
622
+ if (!(await this.fileExists(filepath))) {
623
+ await fs.writeFile(filepath, content);
624
+ console.log(`[OK] Created ${filename}`);
625
+ }
626
+ }
627
+
628
+ console.log('[OK] Project documentation deployed successfully');
629
+ } catch (error) {
630
+ console.log(
631
+ `[ERROR] Failed to deploy project documentation: ${error.message}`,
632
+ );
633
+ }
634
+ }
635
+
636
+ generateProjectMemoryTemplate() {
637
+ return `# Stigmergy Project Memory
534
638
 
535
639
  ## Project Information
536
640
  - **Project Name**: ${path.basename(process.cwd())}
@@ -550,10 +654,10 @@ No collaboration history yet.
550
654
  *This file is automatically managed by Stigmergy CLI*
551
655
  *Last updated: ${new Date().toISOString()}*
552
656
  `;
553
- }
657
+ }
554
658
 
555
- generateProjectReadme() {
556
- return `# ${path.basename(process.cwd())}
659
+ generateProjectReadme() {
660
+ return `# ${path.basename(process.cwd())}
557
661
 
558
662
  This project uses Stigmergy CLI for AI-assisted development.
559
663
 
@@ -574,448 +678,744 @@ See [STIGMERGY.md](STIGMERGY.md) for interaction history and collaboration recor
574
678
  ---
575
679
  *Generated by Stigmergy CLI*
576
680
  `;
577
- }
681
+ }
578
682
 
579
- async initializeConfig() {
580
- console.log('\n[CONFIG] Initializing Stigmergy configuration...');
581
-
582
- try {
583
- // Create config directory
584
- const configDir = path.join(os.homedir(), '.stigmergy');
585
- await fs.mkdir(configDir, { recursive: true });
586
-
587
- // Create initial configuration
588
- const config = {
589
- version: '1.0.94',
590
- initialized: true,
591
- createdAt: new Date().toISOString(),
592
- lastUpdated: new Date().toISOString(),
593
- defaultCLI: 'claude',
594
- enableCrossCLI: true,
595
- enableMemory: true,
596
- tools: {}
597
- };
598
-
599
- // Save configuration
600
- const configPath = path.join(configDir, 'config.json');
601
- await fs.writeFile(configPath, JSON.stringify(config, null, 2));
602
-
603
- console.log('[OK] Configuration initialized successfully');
604
- } catch (error) {
605
- console.log(`[ERROR] Failed to initialize configuration: ${error.message}`);
606
- }
607
- }
683
+ async initializeConfig() {
684
+ console.log('\n[CONFIG] Initializing Stigmergy configuration...');
608
685
 
609
- showUsageInstructions() {
610
- console.log('\n' + '='.repeat(60));
611
- console.log('🎉 Stigmergy CLI Setup Complete!');
612
- console.log('='.repeat(60));
613
- console.log('');
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');
618
- console.log('');
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设计数据库表结构"');
623
- console.log('');
624
- console.log('For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
625
- console.log('[END] Happy collaborating with multiple AI CLI tools!');
686
+ try {
687
+ // Create config directory
688
+ const configDir = path.join(os.homedir(), '.stigmergy');
689
+ await fs.mkdir(configDir, { recursive: true });
690
+
691
+ // Create initial configuration
692
+ const config = {
693
+ version: '1.0.94',
694
+ initialized: true,
695
+ createdAt: new Date().toISOString(),
696
+ lastUpdated: new Date().toISOString(),
697
+ defaultCLI: 'claude',
698
+ enableCrossCLI: true,
699
+ enableMemory: true,
700
+ tools: {},
701
+ };
702
+
703
+ // Save configuration
704
+ const configPath = path.join(configDir, 'config.json');
705
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2));
706
+
707
+ console.log('[OK] Configuration initialized successfully');
708
+ } catch (error) {
709
+ console.log(
710
+ `[ERROR] Failed to initialize configuration: ${error.message}`,
711
+ );
626
712
  }
713
+ }
714
+
715
+ showUsageInstructions() {
716
+ console.log('\n' + '='.repeat(60));
717
+ console.log('🎉 Stigmergy CLI Setup Complete!');
718
+ console.log('='.repeat(60));
719
+ console.log('');
720
+ console.log('Next steps:');
721
+ console.log(
722
+ ' 1. Run "stigmergy install" to scan and install AI CLI tools',
723
+ );
724
+ console.log(' 2. Run "stigmergy deploy" to set up cross-CLI integration');
725
+ console.log(
726
+ ' 3. Use "stigmergy call \\"<your prompt>\\"" to start collaborating',
727
+ );
728
+ console.log('');
729
+ console.log('Example usage:');
730
+ console.log(' stigmergy call "用claude分析项目架构"');
731
+ console.log(' stigmergy call "用qwen写一个hello world程序"');
732
+ console.log(' stigmergy call "用gemini设计数据库表结构"');
733
+ console.log('');
734
+ console.log(
735
+ 'For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents',
736
+ );
737
+ console.log('[END] Happy collaborating with multiple AI CLI tools!');
738
+ }
627
739
  }
628
740
 
629
741
  // Main CLI functionality
630
742
  async function main() {
743
+ if (process.env.DEBUG === 'true') {
631
744
  console.log('[DEBUG] Main function called with args:', process.argv);
632
- const args = process.argv.slice(2);
633
- const installer = new StigmergyInstaller();
634
-
745
+ }
746
+ const args = process.argv.slice(2);
747
+ const installer = new StigmergyInstaller();
748
+
749
+ // Handle case when no arguments are provided
750
+ if (args.length === 0) {
751
+ console.log(
752
+ 'Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System',
753
+ );
754
+ console.log('Version: 1.0.94');
755
+ console.log('');
756
+ console.log('[SYSTEM] Automated Installation and Deployment System');
757
+ console.log('');
758
+ console.log('Usage: stigmergy [command] [options]');
759
+ console.log('');
760
+ console.log('Commands:');
761
+ console.log(' help, --help Show this help message');
762
+ console.log(' version, --version Show version information');
763
+ console.log(' status Check CLI tools status');
764
+ console.log(' scan Scan for available AI CLI tools');
765
+ console.log(' install Auto-install missing CLI tools');
766
+ console.log(
767
+ ' deploy Deploy hooks and integration to installed tools',
768
+ );
769
+ console.log(' setup Complete setup and configuration');
770
+ console.log(
771
+ ' init Initialize Stigmergy configuration (alias for setup)',
772
+ );
773
+ console.log(' call "<prompt>" Execute prompt with auto-routed AI CLI');
774
+ console.log(' errors Display error report and statistics');
775
+ console.log(
776
+ ' register <username> <password> Register a new user account',
777
+ );
778
+ console.log(' login <username> <password> Log in to your account');
779
+ console.log(' logout Log out of your account');
780
+ console.log(
781
+ ' auth-status Check authentication status',
782
+ );
783
+ console.log('');
784
+ console.log('Authentication Commands:');
785
+ console.log(
786
+ ' Register a new account: stigmergy register <username> <password>',
787
+ );
788
+ console.log(
789
+ ' Log in to your account: stigmergy login <username> <password>',
790
+ );
791
+ console.log(' Check auth status: stigmergy auth-status');
792
+ console.log(' Log out of your account: stigmergy logout');
793
+ console.log('');
794
+ console.log('[WORKFLOW] Automated Workflow:');
795
+ console.log(' 1. npm install -g stigmergy # Install Stigmergy');
796
+ console.log(
797
+ ' 2. stigmergy install # Auto-scan & install CLI tools',
798
+ );
799
+ console.log(' 3. stigmergy setup # Deploy hooks & config');
800
+ console.log(' 4. stigmergy call "<prompt>" # Start collaborating');
801
+ console.log('');
802
+ console.log('[INFO] For first-time setup, run: stigmergy setup');
803
+ console.log(
804
+ '[INFO] To scan and install AI tools, run: stigmergy install',
805
+ );
806
+ console.log('');
807
+ console.log(
808
+ 'For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents',
809
+ );
810
+ return;
811
+ }
812
+
813
+ // Handle help commands
814
+ if (args.includes('--help') || args.includes('-h')) {
815
+ console.log(
816
+ 'Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System',
817
+ );
818
+ console.log('Version: 1.0.94');
819
+ console.log('');
820
+ console.log('[SYSTEM] Automated Installation and Deployment System');
821
+ console.log('');
822
+ console.log('Usage: stigmergy [command] [options]');
823
+ console.log('');
824
+ console.log('Commands:');
825
+ console.log(' help, --help Show this help message');
826
+ console.log(' version, --version Show version information');
827
+ console.log(' status Check CLI tools status');
828
+ console.log(' scan Scan for available AI CLI tools');
829
+ console.log(' install Auto-install missing CLI tools');
830
+ console.log(
831
+ ' deploy Deploy hooks and integration to installed tools',
832
+ );
833
+ console.log(' setup Complete setup and configuration');
834
+ console.log(
835
+ ' init Initialize Stigmergy configuration (alias for setup)',
836
+ );
837
+ console.log(' call "<prompt>" Execute prompt with auto-routed AI CLI');
838
+ console.log(' errors Display error report and statistics');
839
+ console.log(
840
+ ' register <username> <password> Register a new user account',
841
+ );
842
+ console.log(' login <username> <password> Log in to your account');
843
+ console.log(' logout Log out of your account');
844
+ console.log(
845
+ ' auth-status Check authentication status',
846
+ );
847
+ console.log('');
848
+ console.log('Authentication Commands:');
849
+ console.log(
850
+ ' Register a new account: stigmergy register <username> <password>',
851
+ );
852
+ console.log(
853
+ ' Log in to your account: stigmergy login <username> <password>',
854
+ );
855
+ console.log(' Check auth status: stigmergy auth-status');
856
+ console.log(' Log out of your account: stigmergy logout');
857
+ console.log('');
858
+ console.log('[WORKFLOW] Automated Workflow:');
859
+ console.log(' 1. npm install -g stigmergy # Install Stigmergy');
860
+ console.log(
861
+ ' 2. stigmergy install # Auto-scan & install CLI tools',
862
+ );
863
+ console.log(' 3. stigmergy setup # Deploy hooks & config');
864
+ console.log(' 4. stigmergy call "<prompt>" # Start collaborating');
865
+ console.log('');
866
+ console.log(
867
+ 'For more information, visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents',
868
+ );
869
+ return;
870
+ }
871
+
872
+ const command = args[0];
873
+
874
+ // Define protected commands that require authentication
875
+ const protectedCommands = ['call', 'setup', 'deploy', 'install'];
876
+
877
+ // Check if command requires authentication
878
+ if (
879
+ protectedCommands.includes(command) &&
880
+ command !== 'version' &&
881
+ command !== '--version'
882
+ ) {
883
+ if (!isAuthenticated()) {
884
+ console.log('[ERROR] Authentication required. Please log in first.');
885
+ console.log(
886
+ '[INFO] Run "stigmergy login <username> <password>" to log in.',
887
+ );
888
+ process.exit(1);
889
+ }
890
+ }
891
+
892
+ switch (command) {
893
+ case 'version':
894
+ case '--version': {
895
+ // Use the version from configuration instead of hardcoding
896
+ const config = {
897
+ version: '1.0.94',
898
+ initialized: true,
899
+ createdAt: new Date().toISOString(),
900
+ lastUpdated: new Date().toISOString(),
901
+ defaultCLI: 'claude',
902
+ enableCrossCLI: true,
903
+ enableMemory: true,
904
+ };
905
+ console.log(`Stigmergy CLI v${config.version}`);
906
+ break;
907
+ }
908
+
909
+ case 'errors':
910
+ try {
911
+ console.log('[ERRORS] Generating Stigmergy CLI error report...\n');
912
+ await errorHandler.printErrorReport();
913
+ } catch (error) {
914
+ console.error(
915
+ '[ERROR] Failed to generate error report:',
916
+ error.message,
917
+ );
918
+ process.exit(1);
919
+ }
920
+ break;
921
+
922
+ case 'init':
923
+ // Alias for setup command
924
+ console.log('[INIT] Initializing Stigmergy CLI...');
925
+ // Fall through to setup case
926
+
927
+ case 'setup':
928
+ try {
929
+ console.log('[SETUP] Starting complete Stigmergy setup...\n');
930
+
931
+ // Step 1: Download required assets
932
+ await installer.downloadRequiredAssets();
933
+
934
+ // Step 2: Scan for CLI tools
935
+ const { available: setupAvailable, missing: setupMissing } =
936
+ await installer.scanCLI();
937
+ const setupOptions = await installer.showInstallOptions(setupMissing);
938
+
939
+ // Step 3: Install missing CLI tools if user chooses
940
+ if (setupOptions.length > 0) {
941
+ const selectedTools = await installer.getUserSelection(
942
+ setupOptions,
943
+ setupMissing,
944
+ );
945
+ if (selectedTools.length > 0) {
946
+ console.log(
947
+ '\n[INFO] Installing selected tools (this may take several minutes for tools that download binaries)...',
948
+ );
949
+ await installer.installTools(selectedTools, setupMissing);
950
+ }
951
+ } else {
952
+ console.log('\n[INFO] All required tools are already installed!');
953
+ }
954
+
955
+ // Step 4: Deploy hooks to available CLI tools
956
+ await installer.deployHooks(setupAvailable);
957
+
958
+ // Step 5: Deploy project documentation
959
+ await installer.deployProjectDocumentation();
960
+
961
+ // Step 6: Initialize configuration
962
+ await installer.initializeConfig();
963
+
964
+ // Step 7: Show usage instructions
965
+ installer.showUsageInstructions();
966
+ } catch (error) {
967
+ await errorHandler.logError(error, 'ERROR', 'main.setup');
968
+ console.log(`[ERROR] Setup failed: ${error.message}`);
969
+ console.log('\n[TROUBLESHOOTING] To manually complete setup:');
970
+ console.log('1. Run: stigmergy deploy # Deploy hooks manually');
971
+ console.log('2. Run: stigmergy setup # Try setup again');
972
+ process.exit(1);
973
+ }
974
+ break;
975
+
976
+ case 'status':
635
977
  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;
978
+ const { available, missing } = await installer.scanCLI();
979
+ console.log('\n[STATUS] AI CLI Tools Status Report');
980
+ console.log('=====================================');
981
+
982
+ if (Object.keys(available).length > 0) {
983
+ console.log('\n✅ Available Tools:');
984
+ for (const [toolName, toolInfo] of Object.entries(available)) {
985
+ console.log(` - ${toolInfo.name} (${toolName})`);
666
986
  }
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;
987
+ }
988
+
989
+ if (Object.keys(missing).length > 0) {
990
+ console.log('\n❌ Missing Tools:');
991
+ for (const [toolName, toolInfo] of Object.entries(missing)) {
992
+ console.log(` - ${toolInfo.name} (${toolName})`);
993
+ console.log(` Install command: ${toolInfo.install}`);
695
994
  }
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;
713
-
714
- case 'status':
715
- try {
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`);
736
- } catch (error) {
737
- await errorHandler.logError(error, 'ERROR', 'main.status');
738
- console.log(`[ERROR] Failed to get status: ${error.message}`);
739
- process.exit(1);
740
- }
741
- break;
742
-
743
- case 'scan':
744
- try {
745
- await installer.scanCLI();
746
- } catch (error) {
747
- await errorHandler.logError(error, 'ERROR', 'main.scan');
748
- console.log(`[ERROR] Failed to scan CLI tools: ${error.message}`);
749
- process.exit(1);
750
- }
751
- break;
752
-
753
- case 'install':
754
- try {
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);
764
- }
765
- } else {
766
- console.log('\n[INFO] All required tools are already installed!');
767
- }
768
- } catch (error) {
769
- await errorHandler.logError(error, 'ERROR', 'main.install');
770
- console.log(`[ERROR] Installation failed: ${error.message}`);
771
- process.exit(1);
772
- }
773
- break;
774
-
775
- case 'deploy':
776
- try {
777
- const { available: deployedTools } = await installer.scanCLI();
778
- await installer.deployHooks(deployedTools);
779
- } catch (error) {
780
- await errorHandler.logError(error, 'ERROR', 'main.deploy');
781
- console.log(`[ERROR] Deployment failed: ${error.message}`);
782
- process.exit(1);
783
- }
784
- break;
785
-
786
- case 'setup':
787
- try {
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
812
- await installer.deployProjectDocumentation();
813
-
814
- // Step 6: Initialize configuration
815
- await installer.initializeConfig();
816
-
817
- // Step 7: Show usage instructions
818
- installer.showUsageInstructions();
819
- } catch (error) {
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);
826
- }
827
- break;
828
-
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
846
- try {
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
- });
897
- } catch (error) {
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);
901
- }
902
- break;
903
-
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));
908
-
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);
995
+ }
996
+
997
+ console.log(
998
+ `\n[SUMMARY] ${Object.keys(available).length} available, ${Object.keys(missing).length} missing`,
999
+ );
1000
+ } catch (error) {
1001
+ await errorHandler.logError(error, 'ERROR', 'main.status');
1002
+ console.log(`[ERROR] Failed to get status: ${error.message}`);
1003
+ process.exit(1);
1004
+ }
1005
+ break;
1006
+
1007
+ case 'scan':
1008
+ try {
1009
+ await installer.scanCLI();
1010
+ } catch (error) {
1011
+ await errorHandler.logError(error, 'ERROR', 'main.scan');
1012
+ console.log(`[ERROR] Failed to scan CLI tools: ${error.message}`);
1013
+ process.exit(1);
1014
+ }
1015
+ break;
1016
+
1017
+ case 'install':
1018
+ try {
1019
+ console.log('[INSTALL] Starting AI CLI tools installation...');
1020
+ const { missing: missingTools } = await installer.scanCLI();
1021
+ const options = await installer.showInstallOptions(missingTools);
1022
+
1023
+ if (options.length > 0) {
1024
+ const selectedTools = await installer.getUserSelection(
1025
+ options,
1026
+ missingTools,
1027
+ );
1028
+ if (selectedTools.length > 0) {
1029
+ console.log(
1030
+ '\n[INFO] Installing selected tools (this may take several minutes for tools that download binaries)...',
1031
+ );
1032
+ await installer.installTools(selectedTools, missingTools);
999
1033
  }
1034
+ } else {
1035
+ console.log('\n[INFO] All required tools are already installed!');
1036
+ }
1037
+ } catch (error) {
1038
+ await errorHandler.logError(error, 'ERROR', 'main.install');
1039
+ console.log(`[ERROR] Installation failed: ${error.message}`);
1040
+ process.exit(1);
1041
+ }
1042
+ break;
1043
+
1044
+ case 'deploy':
1045
+ try {
1046
+ const { available: deployedTools } = await installer.scanCLI();
1047
+ await installer.deployHooks(deployedTools);
1000
1048
  } catch (error) {
1001
- await errorHandler.logError(error, 'ERROR', 'main');
1002
- console.error('[FATAL] Stigmergy CLI encountered an error:', error.message);
1049
+ await errorHandler.logError(error, 'ERROR', 'main.deploy');
1050
+ console.log(`[ERROR] Deployment failed: ${error.message}`);
1051
+ process.exit(1);
1052
+ }
1053
+ break;
1054
+
1055
+ case 'register':
1056
+ if (args.length < 3) {
1057
+ console.log(
1058
+ '[ERROR] Usage: stigmergy register <username> <password>',
1059
+ );
1060
+ process.exit(1);
1061
+ }
1062
+ handleRegister(args[1], args[2]);
1063
+ break;
1064
+
1065
+ case 'login':
1066
+ if (args.length < 3) {
1067
+ console.log('[ERROR] Usage: stigmergy login <username> <password>');
1068
+ process.exit(1);
1069
+ }
1070
+ handleLogin(args[1], args[2]);
1071
+ break;
1072
+
1073
+ case 'logout':
1074
+ handleLogout();
1075
+ break;
1076
+
1077
+ case 'auth-status':
1078
+ handleStatus();
1079
+ break;
1080
+
1081
+ case 'call': {
1082
+ if (args.length < 2) {
1083
+ console.log('[ERROR] Usage: stigmergy call "<prompt>"');
1084
+ process.exit(1);
1085
+ }
1086
+
1087
+ // Get the prompt (everything after the command)
1088
+ const prompt = args.slice(1).join(' ');
1089
+
1090
+ // Use smart router to determine which tool to use
1091
+ const router = new SmartRouter();
1092
+ await router.initialize(); // Initialize the router first
1093
+ const route = await router.smartRoute(prompt);
1094
+
1095
+ console.log(`[CALL] Routing to ${route.tool}: ${route.prompt}`);
1096
+
1097
+ // Execute the routed command
1098
+ try {
1099
+ // Get the actual executable path for the tool
1100
+ const toolPath = route.tool;
1101
+
1102
+ // SPECIAL TEST CASE: Simulate a non-existent tool for testing
1103
+ // This is for demonstration purposes only
1104
+ /*
1105
+ if (route.tool === "nonexistenttool") {
1106
+ toolPath = "this_tool_definitely_does_not_exist_12345";
1107
+ }
1108
+ */
1109
+
1110
+ console.log(
1111
+ `[DEBUG] Tool path: ${toolPath}, Prompt: ${route.prompt}`,
1112
+ );
1113
+
1114
+ // For different tools, we need to pass the prompt differently
1115
+ // Use unified parameter handler for better parameter handling
1116
+ let toolArgs = [];
1117
+
1118
+ try {
1119
+ // Get CLI pattern for this tool
1120
+ const cliPattern = await router.analyzer.getCLIPattern(route.tool);
1121
+
1122
+ // Use the unified CLI parameter handler
1123
+ const CLIParameterHandler = require('./core/cli_parameter_handler');
1124
+ toolArgs = CLIParameterHandler.generateArguments(
1125
+ route.tool,
1126
+ route.prompt,
1127
+ cliPattern,
1128
+ );
1129
+ } catch (patternError) {
1130
+ // Fallback to original logic if pattern analysis fails
1131
+ if (route.tool === 'claude') {
1132
+ // Claude CLI expects the prompt with -p flag for non-interactive mode
1133
+ toolArgs = ['-p', `"${route.prompt}"`];
1134
+ } else if (route.tool === 'qodercli' || route.tool === 'iflow') {
1135
+ // Qoder CLI and iFlow expect the prompt with -p flag
1136
+ toolArgs = ['-p', `"${route.prompt}"`];
1137
+ } else if (route.tool === 'codex') {
1138
+ // Codex CLI needs 'exec' subcommand for non-interactive mode
1139
+ toolArgs = ['exec', '-p', `"${route.prompt}"`];
1140
+ } else {
1141
+ // For other tools, pass the prompt with -p flag
1142
+ toolArgs = ['-p', `"${route.prompt}"`];
1143
+ }
1144
+ }
1145
+
1146
+ // Use the reliable cross-platform execution function
1147
+ try {
1148
+ // Validate that the tool exists before attempting to execute
1149
+ if (!toolPath || typeof toolPath !== 'string') {
1150
+ throw new Error(`Invalid tool path: ${toolPath}`);
1151
+ }
1152
+
1153
+ // Special handling for JS files to ensure proper execution
1154
+ if (toolPath.endsWith('.js') || toolPath.endsWith('.cjs')) {
1155
+ // Use safe JS file execution
1156
+ console.log(
1157
+ `[EXEC] Safely executing JS file: ${toolPath} ${toolArgs.join(' ')}`,
1158
+ );
1159
+ const result = await executeJSFile(toolPath, toolArgs, {
1160
+ stdio: 'inherit',
1161
+ shell: true,
1162
+ });
1163
+
1164
+ if (!result.success) {
1165
+ console.log(
1166
+ `[WARN] ${route.tool} exited with code ${result.code}`,
1167
+ );
1168
+ }
1169
+ process.exit(result.code || 0);
1170
+ } else {
1171
+ // Regular command execution
1172
+ console.log(`[EXEC] Running: ${toolPath} ${toolArgs.join(' ')}`);
1173
+ const result = await executeCommand(toolPath, toolArgs, {
1174
+ stdio: 'inherit',
1175
+ shell: true,
1176
+ });
1177
+
1178
+ if (!result.success) {
1179
+ console.log(
1180
+ `[WARN] ${route.tool} exited with code ${result.code}`,
1181
+ );
1182
+ }
1183
+ process.exit(result.code || 0);
1184
+ }
1185
+ } catch (executionError) {
1186
+ const cliError = await errorHandler.handleCLIError(
1187
+ route.tool,
1188
+ executionError.error || executionError,
1189
+ toolArgs.join(' '),
1190
+ );
1191
+
1192
+ // Provide clear ANSI English error message
1193
+ console.log('==================================================');
1194
+ console.log('ERROR: Failed to execute AI CLI tool');
1195
+ console.log('==================================================');
1196
+ console.log(`Tool: ${route.tool}`);
1197
+ console.log(`Error: ${cliError.message}`);
1198
+ if (executionError.stderr) {
1199
+ console.log(`Stderr: ${executionError.stderr}`);
1200
+ }
1201
+ console.log('');
1202
+ console.log('Possible solutions:');
1203
+ console.log('1. Check if the AI CLI tool is properly installed');
1204
+ console.log('2. Verify the tool is in your system PATH');
1205
+ console.log('3. Try reinstalling the tool with: stigmergy install');
1206
+ console.log('4. Run stigmergy status to check tool availability');
1207
+ console.log('');
1208
+ console.log('For manual execution, you can run:');
1209
+ console.log(`${toolPath} ${toolArgs.join(' ')}`);
1210
+ console.log('==================================================');
1211
+
1003
1212
  process.exit(1);
1213
+ }
1214
+ } catch (error) {
1215
+ const cliError = await errorHandler.handleCLIError(
1216
+ route.tool,
1217
+ error,
1218
+ prompt,
1219
+ );
1220
+ console.log(
1221
+ `[ERROR] Failed to execute ${route.tool}:`,
1222
+ cliError.message,
1223
+ );
1224
+ process.exit(1);
1225
+ }
1226
+ break;
1227
+ }
1228
+
1229
+ case 'auto-install':
1230
+ // Auto-install mode for npm postinstall - NON-INTERACTIVE
1231
+ console.log('[AUTO-INSTALL] Stigmergy CLI automated setup');
1232
+ console.log('='.repeat(60));
1233
+
1234
+ try {
1235
+ // Step 1: Download required assets
1236
+ try {
1237
+ console.log('[STEP] Downloading required assets...');
1238
+ await installer.downloadRequiredAssets();
1239
+ console.log('[OK] Assets downloaded successfully');
1240
+ } catch (error) {
1241
+ console.log(`[WARN] Failed to download assets: ${error.message}`);
1242
+ console.log('[INFO] Continuing with installation...');
1243
+ }
1244
+
1245
+ // Step 2: Scan for CLI tools
1246
+ let autoAvailable = {},
1247
+ autoMissing = {};
1248
+ try {
1249
+ console.log('[STEP] Scanning for CLI tools...');
1250
+ const scanResult = await installer.scanCLI();
1251
+ autoAvailable = scanResult.available;
1252
+ autoMissing = scanResult.missing;
1253
+ console.log('[OK] CLI tools scanned successfully');
1254
+ } catch (error) {
1255
+ console.log(`[WARN] Failed to scan CLI tools: ${error.message}`);
1256
+ console.log('[INFO] Continuing with installation...');
1257
+ }
1258
+
1259
+ // Step 3: Show summary to user after installation
1260
+ try {
1261
+ if (Object.keys(autoMissing).length > 0) {
1262
+ console.log(
1263
+ '\n[INFO] Found ' +
1264
+ Object.keys(autoMissing).length +
1265
+ ' missing AI CLI tools:',
1266
+ );
1267
+ for (const [toolName, toolInfo] of Object.entries(autoMissing)) {
1268
+ console.log(` - ${toolInfo.name} (${toolName})`);
1269
+ }
1270
+ console.log(
1271
+ '\n[INFO] Auto-install mode detected. Skipping automatic installation of missing tools.',
1272
+ );
1273
+ console.log(
1274
+ '[INFO] For full functionality, please run "stigmergy install" after installation completes.',
1275
+ );
1276
+ } else {
1277
+ console.log(
1278
+ '\n[INFO] All AI CLI tools are already installed! No additional tools required.',
1279
+ );
1280
+ }
1281
+ } catch (error) {
1282
+ console.log(`[WARN] Failed to show tool summary: ${error.message}`);
1283
+ }
1284
+
1285
+ // Step 4: Deploy hooks to available CLI tools
1286
+ try {
1287
+ console.log('[STEP] Deploying hooks to available CLI tools...');
1288
+ await installer.deployHooks(autoAvailable);
1289
+ console.log('[OK] Hooks deployed successfully');
1290
+ } catch (error) {
1291
+ console.log(`[ERROR] Failed to deploy hooks: ${error.message}`);
1292
+ console.log(
1293
+ '[INFO] You can manually deploy hooks later by running: stigmergy deploy',
1294
+ );
1295
+ }
1296
+
1297
+ // Step 5: Deploy project documentation
1298
+ try {
1299
+ console.log('[STEP] Deploying project documentation...');
1300
+ await installer.deployProjectDocumentation();
1301
+ console.log('[OK] Documentation deployed successfully');
1302
+ } catch (error) {
1303
+ console.log(
1304
+ `[WARN] Failed to deploy documentation: ${error.message}`,
1305
+ );
1306
+ console.log('[INFO] Continuing with installation...');
1307
+ }
1308
+
1309
+ // Step 6: Initialize configuration
1310
+ try {
1311
+ console.log('[STEP] Initializing configuration...');
1312
+ await installer.initializeConfig();
1313
+ console.log('[OK] Configuration initialized successfully');
1314
+ } catch (error) {
1315
+ console.log(
1316
+ `[ERROR] Failed to initialize configuration: ${error.message}`,
1317
+ );
1318
+ console.log(
1319
+ '[INFO] You can manually initialize configuration later by running: stigmergy setup',
1320
+ );
1321
+ }
1322
+
1323
+ // Step 7: Show final message to guide users
1324
+ console.log('\n[SUCCESS] Stigmergy CLI installed successfully!');
1325
+ console.log(
1326
+ '[USAGE] Run "stigmergy setup" to complete full configuration and install missing AI CLI tools.',
1327
+ );
1328
+ console.log(
1329
+ '[USAGE] Run "stigmergy install" to install only missing AI CLI tools.',
1330
+ );
1331
+ console.log(
1332
+ '[USAGE] Run "stigmergy --help" to see all available commands.',
1333
+ );
1334
+ } catch (fatalError) {
1335
+ await errorHandler.logError(fatalError, 'ERROR', 'main.auto-install');
1336
+ console.error(
1337
+ '[FATAL] Auto-install process failed:',
1338
+ fatalError.message,
1339
+ );
1340
+ console.log('\n[TROUBLESHOOTING] To manually complete installation:');
1341
+ console.log('1. Run: stigmergy setup # Complete setup');
1342
+ console.log('2. Run: stigmergy install # Install missing tools');
1343
+ console.log('3. Run: stigmergy deploy # Deploy hooks manually');
1344
+ process.exit(1);
1004
1345
  }
1346
+ break;
1347
+
1348
+ default:
1349
+ console.log(`[ERROR] Unknown command: ${command}`);
1350
+ console.log('[INFO] Run "stigmergy --help" for usage information');
1351
+ process.exit(1);
1352
+ }
1005
1353
  }
1006
1354
 
1007
1355
  // Function to find maximum of two numbers
1008
1356
  function maxOfTwo(a, b) {
1009
- return a > b ? a : b;
1357
+ return a > b ? a : b;
1358
+ }
1359
+
1360
+ // Function to check if user is authenticated
1361
+ function isAuthenticated() {
1362
+ try {
1363
+ const authenticator = new UserAuthenticator();
1364
+ // Load authentication data
1365
+ const authFile = path.join(
1366
+ process.env.HOME || process.env.USERPROFILE,
1367
+ '.stigmergy',
1368
+ 'auth.json',
1369
+ );
1370
+
1371
+ if (!fsSync.existsSync(authFile)) {
1372
+ return false;
1373
+ }
1374
+
1375
+ // Load the authentication data into the authenticator
1376
+ const data = JSON.parse(fsSync.readFileSync(authFile, 'utf8'));
1377
+ if (data.sessions) {
1378
+ for (const [token, sessionData] of Object.entries(data.sessions)) {
1379
+ authenticator._sessions.set(token, sessionData);
1380
+ }
1381
+ }
1382
+
1383
+ // Read the current session token
1384
+ const sessionFile = path.join(
1385
+ process.env.HOME || process.env.USERPROFILE,
1386
+ '.stigmergy',
1387
+ 'session.token',
1388
+ );
1389
+
1390
+ if (!fsSync.existsSync(sessionFile)) {
1391
+ return false;
1392
+ }
1393
+
1394
+ const token = fsSync.readFileSync(sessionFile, 'utf8').trim();
1395
+ const username = authenticator.validateSession(token);
1396
+
1397
+ return !!username;
1398
+ } catch (error) {
1399
+ return false;
1400
+ }
1010
1401
  }
1011
1402
 
1012
1403
  // Export for testing
1013
- module.exports = { StigmergyInstaller, SmartRouter, MemoryManager, CLI_TOOLS, maxOfTwo };
1404
+ module.exports = {
1405
+ StigmergyInstaller,
1406
+ SmartRouter,
1407
+ MemoryManager,
1408
+ CLI_TOOLS,
1409
+ maxOfTwo,
1410
+ };
1014
1411
 
1015
1412
  // Run main function
1016
1413
  if (require.main === module) {
1017
- main().catch(error => {
1018
- console.error('[FATAL] Stigmergy CLI encountered an unhandled error:', error);
1019
- process.exit(1);
1020
- });
1414
+ main().catch((error) => {
1415
+ console.error(
1416
+ '[FATAL] Stigmergy CLI encountered an unhandled error:',
1417
+ error,
1418
+ );
1419
+ process.exit(1);
1420
+ });
1021
1421
  }