stigmergy 1.2.0 → 1.2.6

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.
Files changed (125) hide show
  1. package/LICENSE +18 -18
  2. package/README.md +28 -223
  3. package/STIGMERGY.md +61 -61
  4. package/docs/PROJECT_CONSTITUTION.md +433 -433
  5. package/docs/PROJECT_STRUCTURE_CURRENT.md +80 -80
  6. package/examples/calculator-example.js +72 -72
  7. package/examples/cline_usage_examples.md +364 -364
  8. package/examples/encryption-example.js +67 -67
  9. package/examples/json-parser-example.js +120 -120
  10. package/examples/json-validation-example.js +64 -64
  11. package/examples/rest-client-example.js +52 -52
  12. package/examples/rest_client_example.js +54 -54
  13. package/package.json +36 -15
  14. package/scripts/build.js +74 -74
  15. package/scripts/post-deployment-config.js +296 -296
  16. package/scripts/preinstall-check.js +173 -173
  17. package/scripts/publish.js +58 -268
  18. package/scripts/run-layered-tests.js +247 -0
  19. package/scripts/safe-install.js +139 -139
  20. package/scripts/simple-publish.js +57 -59
  21. package/src/adapters/claude/install_claude_integration.js +292 -0
  22. package/src/adapters/codebuddy/install_codebuddy_integration.js +349 -0
  23. package/src/adapters/codex/install_codex_integration.js +395 -0
  24. package/src/adapters/copilot/install_copilot_integration.js +716 -0
  25. package/src/adapters/gemini/install_gemini_integration.js +304 -0
  26. package/src/adapters/iflow/install_iflow_integration.js +304 -0
  27. package/src/adapters/qoder/install_qoder_integration.js +1090 -0
  28. package/src/adapters/qwen/install_qwen_integration.js +285 -0
  29. package/src/auth.js +173 -173
  30. package/src/auth_command.js +208 -208
  31. package/src/calculator.js +313 -313
  32. package/src/cli/router.js +417 -38
  33. package/src/core/cache_cleaner.js +767 -744
  34. package/src/core/cli_help_analyzer.js +680 -674
  35. package/src/core/cli_parameter_handler.js +132 -127
  36. package/src/core/cli_tools.js +89 -89
  37. package/src/core/coordination/index.js +16 -16
  38. package/src/core/coordination/nodejs/AdapterManager.js +102 -89
  39. package/src/core/coordination/nodejs/CLCommunication.js +132 -124
  40. package/src/core/coordination/nodejs/CLIIntegrationManager.js +272 -236
  41. package/src/core/coordination/nodejs/HealthChecker.js +76 -77
  42. package/src/core/coordination/nodejs/HookDeploymentManager.js +263 -190
  43. package/src/core/coordination/nodejs/StatisticsCollector.js +71 -71
  44. package/src/core/coordination/nodejs/index.js +90 -72
  45. package/src/core/coordination/nodejs/utils/Logger.js +29 -29
  46. package/src/core/enhanced_installer.js +479 -456
  47. package/src/core/enhanced_uninstaller.js +638 -618
  48. package/src/core/error_handler.js +406 -406
  49. package/src/core/installer.js +815 -294
  50. package/src/core/memory_manager.js +83 -83
  51. package/src/core/rest_client.js +160 -160
  52. package/src/core/smart_router.js +249 -146
  53. package/src/core/upgrade_manager.js +76 -59
  54. package/src/data_encryption.js +143 -143
  55. package/src/data_structures.js +440 -440
  56. package/src/deploy.js +55 -55
  57. package/src/index.js +30 -30
  58. package/src/test/cli-availability-checker.js +194 -0
  59. package/src/test/test-environment.js +289 -0
  60. package/src/utils/helpers.js +35 -35
  61. package/src/utils.js +921 -915
  62. package/src/weatherProcessor.js +228 -228
  63. package/test/cache-cleaner-implemented.test.js +0 -328
  64. package/test/cache-cleaner.test.js +0 -390
  65. package/test/calculator.test.js +0 -215
  66. package/test/collision-test.js +0 -26
  67. package/test/comprehensive-enhanced-features.test.js +0 -252
  68. package/test/comprehensive-execution-test.js +0 -428
  69. package/test/conflict-prevention-test.js +0 -95
  70. package/test/cross-cli-detection-test.js +0 -33
  71. package/test/csv-processing-test.js +0 -36
  72. package/test/deploy-hooks-test.js +0 -250
  73. package/test/e2e/claude-cli-test.js +0 -128
  74. package/test/e2e/collaboration-test.js +0 -75
  75. package/test/e2e/comprehensive-test.js +0 -431
  76. package/test/e2e/error-handling-test.js +0 -90
  77. package/test/e2e/individual-tool-test.js +0 -143
  78. package/test/e2e/other-cli-test.js +0 -130
  79. package/test/e2e/qoder-cli-test.js +0 -128
  80. package/test/e2e/run-e2e-tests.js +0 -73
  81. package/test/e2e/test-data.js +0 -88
  82. package/test/e2e/test-utils.js +0 -222
  83. package/test/encryption-simple-test.js +0 -110
  84. package/test/encryption.test.js +0 -129
  85. package/test/enhanced-main-alignment.test.js +0 -298
  86. package/test/enhanced-uninstaller-implemented.test.js +0 -271
  87. package/test/enhanced-uninstaller.test.js +0 -284
  88. package/test/error-handling-test.js +0 -341
  89. package/test/fibonacci.test.js +0 -178
  90. package/test/final-deploy-test.js +0 -221
  91. package/test/final-install-test.js +0 -226
  92. package/test/hash-table-demo.js +0 -33
  93. package/test/hash-table-test.js +0 -26
  94. package/test/hash_table_test.js +0 -114
  95. package/test/hook-system-integration-test.js +0 -307
  96. package/test/iflow-integration-test.js +0 -292
  97. package/test/improved-install-test.js +0 -362
  98. package/test/install-command-test.js +0 -370
  99. package/test/json-parser-test.js +0 -161
  100. package/test/json-validation-test.js +0 -164
  101. package/test/natural-language-skills-test.js +0 -320
  102. package/test/nl-integration-test.js +0 -179
  103. package/test/parameter-parsing-test.js +0 -143
  104. package/test/plugin-deployment-test.js +0 -316
  105. package/test/postinstall-test.js +0 -269
  106. package/test/python-plugins-test.js +0 -259
  107. package/test/real-test.js +0 -435
  108. package/test/remaining-adapters-test.js +0 -256
  109. package/test/rest-client-test.js +0 -56
  110. package/test/rest_client.test.js +0 -85
  111. package/test/safe-installation-cleaner.test.js +0 -343
  112. package/test/simple-iflow-hook-test.js +0 -137
  113. package/test/stigmergy-upgrade-test.js +0 -243
  114. package/test/system-compatibility-test.js +0 -467
  115. package/test/tdd-deploy-fix-test.js +0 -324
  116. package/test/tdd-fixes-test.js +0 -211
  117. package/test/third-party-skills-test.js +0 -321
  118. package/test/tool-selection-integration-test.js +0 -158
  119. package/test/unit/calculator-full.test.js +0 -191
  120. package/test/unit/calculator-simple.test.js +0 -96
  121. package/test/unit/calculator.test.js +0 -97
  122. package/test/unit/cli-scanner.test.js +0 -291
  123. package/test/unit/cli_parameter_handler.test.js +0 -116
  124. package/test/unit/cross-cli-executor.test.js +0 -399
  125. package/test/weather-processor.test.js +0 -104
@@ -18,14 +18,154 @@ class StigmergyInstaller {
18
18
  const tool = this.router.tools[toolName];
19
19
  if (!tool) return false;
20
20
 
21
- // Try multiple ways to check if CLI is available
21
+ // First, check if tool is properly configured
22
+ if (!tool.version && !tool.install) {
23
+ console.log(
24
+ `[DEBUG] Tool ${toolName} has no version/install info, skipping check`,
25
+ );
26
+ return false;
27
+ }
28
+
29
+ // Special handling for codex - check if the JS file is valid
30
+ if (toolName === 'codex') {
31
+ try {
32
+ // First check if codex command exists
33
+ const whichCmd = process.platform === 'win32' ? 'where' : 'which';
34
+ const whichResult = spawnSync(whichCmd, [toolName], {
35
+ encoding: 'utf8',
36
+ timeout: 3000,
37
+ stdio: ['pipe', 'pipe', 'pipe'],
38
+ shell: true,
39
+ });
40
+
41
+ if (whichResult.status === 0 && whichResult.stdout.trim()) {
42
+ const codexPath = whichResult.stdout.trim().split('\n')[0]; // Get first match
43
+
44
+ // If it's a shell script, check the target JS file
45
+ if (
46
+ codexPath.endsWith('.sh') ||
47
+ codexPath.endsWith('.cmd') ||
48
+ codexPath.endsWith('/codex') ||
49
+ codexPath.endsWith('\\codex')
50
+ ) {
51
+ // Read the script to find the JS file path
52
+ const fsSync = require('fs');
53
+ const scriptContent = fsSync.readFileSync(codexPath, 'utf8');
54
+
55
+ // Look for JS file reference in the script
56
+ const jsFileMatch = scriptContent.match(
57
+ /(["'])(.*?codex\.js.*?)\1/,
58
+ );
59
+ if (jsFileMatch) {
60
+ const jsFilePath = jsFileMatch[2];
61
+ // Check if JS file exists and is not empty
62
+ if (fsSync.existsSync(jsFilePath)) {
63
+ const stats = fsSync.statSync(jsFilePath);
64
+ if (stats.size === 0) {
65
+ console.log(
66
+ '[DEBUG] Codex JS file is empty, marking as unavailable',
67
+ );
68
+ return false;
69
+ }
70
+ } else {
71
+ console.log(
72
+ '[DEBUG] Codex JS file does not exist, marking as unavailable',
73
+ );
74
+ return false;
75
+ }
76
+ }
77
+ }
78
+
79
+ // If we got here, the codex command exists and seems valid
80
+ // Continue with normal checks below
81
+ } else {
82
+ // Codex command doesn't exist
83
+ return false;
84
+ }
85
+ } catch (error) {
86
+ console.log(`[DEBUG] Error checking codex: ${error.message}`);
87
+ return false;
88
+ }
89
+ }
90
+
91
+ // First try to find the executable using which/where command (more reliable)
92
+ try {
93
+ const whichCmd = process.platform === 'win32' ? 'where' : 'which';
94
+ const whichResult = spawnSync(whichCmd, [toolName], {
95
+ encoding: 'utf8',
96
+ timeout: 3000,
97
+ stdio: ['pipe', 'pipe', 'pipe'], // Use pipes to avoid file opening
98
+ shell: true,
99
+ });
100
+
101
+ if (whichResult.status === 0 && whichResult.stdout.trim()) {
102
+ // Found executable, now test it safely
103
+ const testArgs = ['--help'];
104
+ const testOptions = {
105
+ encoding: 'utf8',
106
+ timeout: 5000,
107
+ stdio: ['pipe', 'pipe', 'pipe'], // Don't inherit from parent to avoid opening UI
108
+ shell: true,
109
+ };
110
+
111
+ // Additional protection for codex
112
+ if (toolName === 'codex') {
113
+ testOptions.shell = false;
114
+ testOptions.windowsHide = true;
115
+ testOptions.detached = false;
116
+ }
117
+
118
+ const testResult = spawnSync(toolName, testArgs, testOptions);
119
+
120
+ // If command runs successfully or at least returns something (not command not found)
121
+ if (testResult.status === 0 || testResult.status === 1) {
122
+ return true;
123
+ }
124
+ }
125
+ } catch (error) {
126
+ // which/where command probably failed, continue with other checks
127
+ console.log(
128
+ `[DEBUG] which/where check failed for ${toolName}: ${error.message}`,
129
+ );
130
+ }
131
+
132
+ // Special handling for codex to avoid opening files
133
+ if (toolName === 'codex') {
134
+ // For codex, only try --help and --version with extra precautions
135
+ const codexChecks = [
136
+ { args: ['--help'], expected: 0 },
137
+ { args: ['--version'], expected: 0 },
138
+ ];
139
+
140
+ for (const check of codexChecks) {
141
+ try {
142
+ const result = spawnSync(toolName, check.args, {
143
+ encoding: 'utf8',
144
+ timeout: 3000,
145
+ stdio: ['pipe', 'pipe', 'pipe'], // Ensure all IO is piped
146
+ shell: false, // Don't use shell to avoid extra window opening
147
+ windowsHide: true, // Hide console window on Windows
148
+ detached: false, // Don't detach process
149
+ });
150
+
151
+ if (result.status === 0 || result.status === 1) {
152
+ return true;
153
+ }
154
+ } catch (error) {
155
+ // Continue to next check
156
+ }
157
+ }
158
+ return false; // If all codex checks fail
159
+ }
160
+
161
+ // Fallback: Try multiple ways to check if CLI is available but more safely
22
162
  const checks = [
23
- // Method 1: Try version command
24
- { args: ['--version'], expected: 0 },
25
- // Method 2: Try help command
163
+ // Method 1: Try help command (most common and safe)
26
164
  { args: ['--help'], expected: 0 },
27
- // Method 3: Try help command with -h
165
+ // Method 2: Try help command with -h
28
166
  { args: ['-h'], expected: 0 },
167
+ // Method 3: Try version command
168
+ { args: ['--version'], expected: 0 },
29
169
  // Method 4: Try just the command (help case)
30
170
  { args: [], expected: 0 },
31
171
  ];
@@ -35,19 +175,23 @@ class StigmergyInstaller {
35
175
  const result = spawnSync(toolName, check.args, {
36
176
  encoding: 'utf8',
37
177
  timeout: 5000,
178
+ stdio: ['pipe', 'pipe', 'pipe'], // Use pipe instead of inherit to avoid opening files
38
179
  shell: true,
39
180
  });
40
181
 
41
182
  // Check if command executed successfully or at least didn't fail with "command not found"
42
183
  if (
43
184
  result.status === check.expected ||
44
- (result.status !== 127 && result.status !== 9009)
185
+ (result.status !== 127 &&
186
+ result.status !== 9009 &&
187
+ result.status !== 1) // Also avoid status 1 (general error)
45
188
  ) {
46
189
  // 127 = command not found on Unix, 9009 = command not found on Windows
47
190
  return true;
48
191
  }
49
192
  } catch (error) {
50
193
  // Continue to next check method
194
+ console.log(`[DEBUG] checkCLI error for ${toolName}: ${error.message}`);
51
195
  continue;
52
196
  }
53
197
  }
@@ -81,6 +225,7 @@ class StigmergyInstaller {
81
225
  console.log(
82
226
  `[ERROR] Failed to check ${toolInfo.name}: ${error.message}`,
83
227
  );
228
+ console.log(`[MISSING] ${toolInfo.name} is not installed`);
84
229
  missing[toolName] = toolInfo;
85
230
  }
86
231
  }
@@ -88,88 +233,88 @@ class StigmergyInstaller {
88
233
  return { available, missing };
89
234
  }
90
235
 
91
- async installTools(selectedTools, missingTools) {
92
- console.log(
93
- `\n[INSTALL] Installing ${selectedTools.length} AI CLI tools...`,
94
- );
95
-
96
- for (const toolName of selectedTools) {
97
- const toolInfo = missingTools[toolName];
98
- if (!toolInfo) {
99
- console.log(`[SKIP] Tool ${toolName} not found in missing tools list`);
100
- continue;
101
- }
102
-
103
- try {
104
- console.log(`\n[INSTALL] Installing ${toolInfo.name}...`);
105
- console.log(`[CMD] ${toolInfo.install}`);
236
+ /**
237
+ * Download required assets for Stigmergy CLI
238
+ */
239
+ async downloadRequiredAssets() {
240
+ // This is a placeholder implementation
241
+ // In a real implementation, this would download required assets
242
+ console.log('[ASSETS] No required assets to download');
243
+ return true;
244
+ }
106
245
 
107
- const result = spawnSync(toolInfo.install, {
108
- shell: true,
109
- stdio: 'inherit',
110
- });
246
+ /**
247
+ * Show install options for missing CLI tools
248
+ */
249
+ async showInstallOptions(missingTools) {
250
+ // This is a placeholder implementation
251
+ console.log('[INSTALL] No install options to show');
252
+ return [];
253
+ }
111
254
 
112
- if (result.status === 0) {
113
- console.log(`[OK] ${toolInfo.name} installed successfully`);
114
- } else {
115
- console.log(
116
- `[ERROR] Failed to install ${toolInfo.name} (exit code: ${result.status})`,
117
- );
118
- if (result.error) {
119
- console.log(`[ERROR] Installation error: ${result.error.message}`);
120
- }
121
- console.log(`[INFO] Please run manually: ${toolInfo.install}`);
122
- }
123
- } catch (error) {
124
- await errorHandler.logError(
125
- error,
126
- 'ERROR',
127
- `StigmergyInstaller.installTools.${toolName}`,
128
- );
129
- console.log(
130
- `[ERROR] Failed to install ${toolInfo.name}: ${error.message}`,
131
- );
132
- console.log(`[INFO] Please run manually: ${toolInfo.install}`);
133
- }
134
- }
255
+ /**
256
+ * Get user selection for CLI tools to install
257
+ */
258
+ async getUserSelection(options, missingTools) {
259
+ // This is a placeholder implementation
260
+ console.log('[INSTALL] No user selection needed');
261
+ return [];
262
+ }
135
263
 
264
+ /**
265
+ * Install selected CLI tools
266
+ */
267
+ async installTools(selectedTools, missingTools) {
268
+ // This is a placeholder implementation
269
+ console.log('[INSTALL] No tools to install');
136
270
  return true;
137
271
  }
138
272
 
139
- async deployHooks(availableTools) {
140
- console.log('\n[DEPLOY] Deploying hooks to AI CLI tools...');
141
- let successCount = 0;
142
- const totalCount = Object.keys(availableTools).length;
143
-
144
- // Import Node.js coordination layer for hook deployment
145
- let HookDeploymentManager;
146
- try {
147
- HookDeploymentManager = require('../core/coordination/nodejs/HookDeploymentManager');
148
- } catch (error) {
149
- console.log('[WARN] Node.js coordination layer not available, using Python fallback');
150
- // Fallback to Python implementation would go here
151
- console.log('[ERROR] Python fallback not implemented yet');
152
- return;
153
- }
273
+ /**
274
+ * Deploy hooks for available CLI tools
275
+ */
276
+ async deployHooks(available) {
277
+ console.log('\n[DEPLOY] Deploying cross-CLI integration hooks...');
154
278
 
155
- // Initialize hook deployment manager
279
+ const HookDeploymentManager = require('./coordination/nodejs/HookDeploymentManager');
156
280
  const hookManager = new HookDeploymentManager();
281
+
157
282
  await hookManager.initialize();
158
283
 
159
- for (const [toolName, toolInfo] of Object.entries(availableTools)) {
284
+ let successCount = 0;
285
+ let totalCount = Object.keys(available).length;
286
+
287
+ for (const [toolName, toolInfo] of Object.entries(available)) {
288
+ console.log(`\n[DEPLOY] Deploying hooks for ${toolInfo.name}...`);
289
+
160
290
  try {
161
- console.log(`\n[DEPLOY] Deploying hooks for ${toolInfo.name}...`);
291
+ const fs = require('fs/promises');
292
+ const path = require('path');
162
293
 
163
- // Deploy hooks for this tool
164
- const result = await hookManager.deployHooksForCLI(toolName);
294
+ // Create hooks directory
295
+ await fs.mkdir(toolInfo.hooksDir, { recursive: true });
296
+ console.log(`[OK] Created hooks directory: ${toolInfo.hooksDir}`);
297
+
298
+ // Create config directory
299
+ const configDir = path.dirname(toolInfo.config);
300
+ await fs.mkdir(configDir, { recursive: true });
301
+ console.log(`[OK] Created config directory: ${configDir}`);
302
+
303
+ // Use HookDeploymentManager to deploy Node.js hooks
304
+ const deploySuccess = await hookManager.deployHooksForCLI(toolName);
165
305
 
166
- if (result) {
167
- console.log(`[OK] Hooks deployed for ${toolInfo.name}`);
168
- successCount++;
169
- } else {
170
- console.log(`[ERROR] Failed to deploy hooks for ${toolInfo.name}`);
306
+ if (deploySuccess) {
307
+ console.log(`[OK] Node.js hooks deployed successfully for ${toolInfo.name}`);
171
308
  }
309
+
310
+ // Run JavaScript-based installation for each tool
311
+ await this.installToolIntegration(toolName, toolInfo);
312
+
313
+ console.log(`[OK] Hooks deployed successfully for ${toolInfo.name}`);
314
+ successCount++
315
+
172
316
  } catch (error) {
317
+ const { errorHandler } = require('./error_handler');
173
318
  await errorHandler.logError(
174
319
  error,
175
320
  'ERROR',
@@ -178,295 +323,671 @@ class StigmergyInstaller {
178
323
  console.log(
179
324
  `[ERROR] Failed to deploy hooks for ${toolInfo.name}: ${error.message}`,
180
325
  );
326
+ console.log('[INFO] Continuing with other tools...');
181
327
  }
182
328
  }
183
329
 
184
330
  console.log(
185
331
  `\n[SUMMARY] Hook deployment completed: ${successCount}/${totalCount} tools successful`,
186
332
  );
333
+ return successCount > 0;
334
+ }
335
+
336
+ /**
337
+ * Check if a file or directory exists
338
+ */
339
+ async fileExists(path) {
340
+ const fs = require('fs/promises');
341
+ try {
342
+ await fs.access(path);
343
+ return true;
344
+ } catch {
345
+ return false;
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Copy a directory recursively
351
+ */
352
+ async copyDirectory(src, dest) {
353
+ const fs = require('fs/promises');
354
+ const path = require('path');
355
+
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
+ await this.copyDirectory(srcPath, destPath);
365
+ } else {
366
+ await fs.copyFile(srcPath, destPath);
367
+ }
368
+ }
187
369
  }
188
370
 
371
+ /**
372
+ * Deploy project documentation
373
+ */
189
374
  async deployProjectDocumentation() {
190
- console.log('\n[DEPLOY] Deploying project documentation...');
375
+ // This is a placeholder implementation
376
+ console.log('[DOCS] No documentation to deploy');
377
+ return true;
378
+ }
379
+
380
+ /**
381
+ * Initialize configuration
382
+ */
383
+ async initializeConfig() {
384
+ // This is a placeholder implementation
385
+ console.log('[CONFIG] Configuration initialized');
386
+ return true;
387
+ }
388
+
389
+ /**
390
+ * Show usage instructions
391
+ */
392
+ showUsageInstructions() {
393
+ // This is a placeholder implementation
394
+ console.log('[USAGE] No usage instructions to show');
395
+ return true;
396
+ }
191
397
 
398
+ /**
399
+ * Create project files (PROJECT_SPEC.json and PROJECT_CONSTITUTION.md) in current directory
400
+ */
401
+ async createProjectFiles() {
402
+ const fs = require('fs/promises');
403
+ const path = require('path');
404
+
192
405
  try {
193
- // Create standard project documentation files for each CLI
194
- const cliDocs = {
195
- 'claude.md': this.generateCLIDocumentation('claude'),
196
- 'gemini.md': this.generateCLIDocumentation('gemini'),
197
- 'qwen.md': this.generateCLIDocumentation('qwen'),
198
- 'iflow.md': this.generateCLIDocumentation('iflow'),
199
- 'qodercli.md': this.generateCLIDocumentation('qodercli'),
200
- 'codebuddy.md': this.generateCLIDocumentation('codebuddy'),
201
- 'copilot.md': this.generateCLIDocumentation('copilot'),
202
- 'codex.md': this.generateCLIDocumentation('codex'),
203
- 'STIGMERGY.md': this.generateProjectMemoryTemplate(),
204
- };
406
+ const currentDir = process.cwd();
407
+
408
+ // Create PROJECT_SPEC.json if it doesn't exist
409
+ const projectSpecPath = path.join(currentDir, 'PROJECT_SPEC.json');
410
+ if (!(await fs.access(projectSpecPath).then(() => true).catch(() => false))) {
411
+ await fs.writeFile(projectSpecPath, '{}', 'utf8');
412
+ console.log('[PROJECT] Created PROJECT_SPEC.json');
413
+ }
414
+
415
+ // Create PROJECT_CONSTITUTION.md if it doesn't exist
416
+ const projectConstitutionPath = path.join(currentDir, 'PROJECT_CONSTITUTION.md');
417
+ if (!(await fs.access(projectConstitutionPath).then(() => true).catch(() => false))) {
418
+ const constitutionContent = `# 项目协作宪法
419
+
420
+ ## 协作基本原则
421
+ - 所有协作通过PROJECT_SPEC.json协调
422
+ - 智能体基于背景状态自主决�?- 无中央调度器,实现去中心化协�?
423
+ ## 任务管理原则
424
+ - 智能体可认领分配给自己的任务
425
+ - 智能体可认领与其能力匹配的未分配任务
426
+ - 任务状态实时更新至共享背景
427
+ `;
428
+ await fs.writeFile(projectConstitutionPath, constitutionContent, 'utf8');
429
+ console.log('[PROJECT] Created PROJECT_CONSTITUTION.md');
430
+ }
431
+
432
+ return true;
433
+ } catch (error) {
434
+ console.error('[PROJECT] Failed to create project files:', error.message);
435
+ return false;
436
+ }
437
+ }
205
438
 
206
- for (const [filename, content] of Object.entries(cliDocs)) {
207
- const filepath = path.join(process.cwd(), filename);
208
- if (!(await this.fileExists(filepath))) {
209
- await fs.writeFile(filepath, content);
210
- console.log(`[OK] Created ${filename}`);
439
+ /**
440
+ * Install integration for a specific CLI tool using JavaScript
441
+ */
442
+ async installToolIntegration(toolName, toolInfo) {
443
+ const fs = require('fs/promises');
444
+ const path = require('path');
445
+ const { spawn } = require('child_process');
446
+
447
+ console.log(`[CONFIG] Configuring ${toolInfo.name}...`);
448
+
449
+ try {
450
+ // Map tool names to their adapter directory names
451
+ const toolToAdapterDir = {
452
+ 'qodercli': 'qoder',
453
+ 'qwencode': 'qwen'
454
+ };
455
+
456
+ const adapterDirName = toolToAdapterDir[toolName] || toolName;
457
+ const installScriptPath = path.join(__dirname, '..', 'adapters', adapterDirName, `install_${adapterDirName}_integration.js`);
458
+
459
+ // Check if the JavaScript installation script exists
460
+ try {
461
+ await fs.access(installScriptPath);
462
+ console.log(`[RUN] Running JavaScript installation script for ${toolInfo.name}...`);
463
+
464
+ // Run the JavaScript installation script
465
+ const result = await this.runInstallScript(installScriptPath);
466
+
467
+ if (result.success) {
468
+ console.log(`[OK] ${toolInfo.name} installation script completed successfully`);
469
+ } else {
470
+ console.log(`[WARN] ${toolInfo.name} installation script failed: ${result.error}`);
211
471
  }
472
+ } catch (error) {
473
+ console.log(`[WARN] JavaScript installation script not found for ${toolInfo.name}: ${installScriptPath}`);
474
+ console.log(`[FALLBACK] Using inline configuration for ${toolInfo.name}...`);
475
+
476
+ // Fallback to inline configuration if script doesn't exist
477
+ await this.inlineToolConfiguration(toolName, toolInfo);
212
478
  }
213
-
214
- console.log('[OK] Project documentation deployed successfully');
479
+
215
480
  } catch (error) {
216
- console.log(
217
- `[ERROR] Failed to deploy project documentation: ${error.message}`,
218
- );
481
+ console.log(`[WARN] Configuration failed for ${toolInfo.name}: ${error.message}`);
219
482
  }
220
483
  }
221
484
 
222
- generateCLIDocumentation(cliName) {
223
- const cliInfo = this.router.tools[cliName] || { name: cliName };
224
- return `# ${cliInfo.name} CLI Documentation
485
+ /**
486
+ * Run a JavaScript installation script
487
+ */
488
+ async runInstallScript(scriptPath) {
489
+ return new Promise((resolve) => {
490
+ const child = spawn('node', [scriptPath], {
491
+ cwd: path.dirname(scriptPath),
492
+ stdio: 'pipe',
493
+ timeout: 30000 // 30 second timeout
494
+ });
495
+
496
+ let stdout = '';
497
+ let stderr = '';
498
+
499
+ child.stdout.on('data', (data) => {
500
+ stdout += data.toString();
501
+ // Print output in real-time
502
+ process.stdout.write(data.toString());
503
+ });
504
+
505
+ child.stderr.on('data', (data) => {
506
+ stderr += data.toString();
507
+ // Print errors in real-time
508
+ process.stderr.write(data.toString());
509
+ });
510
+
511
+ child.on('close', (code) => {
512
+ if (code === 0) {
513
+ resolve({ success: true, code: code, stdout: stdout, stderr: stderr });
514
+ } else {
515
+ resolve({ success: false, code: code, stdout: stdout, stderr: stderr, error: `Script exited with code ${code}` });
516
+ }
517
+ });
518
+
519
+ child.on('error', (error) => {
520
+ resolve({ success: false, error: error.message });
521
+ });
522
+ });
523
+ }
524
+
525
+ /**
526
+ * Fallback inline configuration for tools without dedicated scripts
527
+ */
528
+ async inlineToolConfiguration(toolName, toolInfo) {
529
+ const fs = require('fs/promises');
530
+ const path = require('path');
531
+ const os = require('os');
532
+
533
+ // Step 1: Create tool-specific configuration
534
+ const config = {
535
+ cross_cli_enabled: true,
536
+ supported_clis: ["claude", "gemini", "qwen", "iflow", "qodercli", "codebuddy", "copilot", "codex"],
537
+ auto_detect: true,
538
+ timeout: 30,
539
+ collaboration_mode: "active",
540
+ stigmergy_version: "1.2.1",
541
+ deployment_time: new Date().toISOString()
542
+ };
543
+
544
+ // Write configuration file
545
+ await fs.writeFile(toolInfo.config, JSON.stringify(config, null, 2));
546
+ console.log(`[OK] Configuration file created: ${toolInfo.config}`);
547
+
548
+ // Step 2: Copy adapter files if they exist
549
+ const adapterDir = path.join(__dirname, '..', 'adapters', toolName === 'qodercli' ? 'qoder' : toolName);
550
+ if (await this.fileExists(adapterDir)) {
551
+ await this.copyAdapterFiles(adapterDir, toolInfo.hooksDir);
552
+ console.log(`[OK] Adapter files copied for ${toolInfo.name}`);
553
+ }
225
554
 
226
- ## Overview
227
- This document contains configuration and usage information for the ${cliInfo.name} CLI tool within the Stigmergy system.
555
+ // Step 3: Create tool-specific hook files
556
+ await this.createToolHooks(toolName, toolInfo);
228
557
 
229
- ## Basic Information
230
- - **CLI Name**: ${cliName}
231
- - **Tool Name**: ${cliInfo.name}
232
- - **Installation Command**: \`${cliInfo.install || 'Not configured'}\`
233
- - **Version Check**: \`${cliInfo.version || cliName + ' --version'}\`
558
+ // Step 4: Create hooks configuration file
559
+ await this.createHooksConfig(toolName, toolInfo);
234
560
 
235
- ## Usage Patterns
236
- The ${cliInfo.name} CLI can be invoked in several ways:
237
- 1. Direct execution: \`${cliName} [arguments]\`
238
- 2. Through Stigmergy coordination layer
239
- 3. Cross-CLI calls from other tools
561
+ // Step 5: Create Cross-CLI documentation
562
+ await this.createCrossCliDocumentation(toolName, toolInfo);
240
563
 
241
- ## Cross-CLI Communication
242
- To call ${cliInfo.name} from another CLI tool:
243
- \`\`\`bash
244
- # From any other supported CLI
245
- use ${cliName} to [task description]
246
- # or
247
- call ${cliName} [task description]
248
- # or
249
- ask ${cliName} [task description]
250
- \`\`\`
251
-
252
- ## Configuration
253
- This tool integrates with Stigmergy through hooks deployed to:
254
- \`${cliInfo.hooksDir || 'Not configured'}\`
255
-
256
- ## Last Updated
257
- ${new Date().toISOString()}
564
+ // Step 6: Append to existing .md file if it exists
565
+ await this.appendToToolMdFile(toolName);
258
566
 
259
- ---
260
- *This file is automatically managed by Stigmergy CLI*
261
- `;
567
+ // Step 7: Create additional tool-specific configurations
568
+ await this.createToolSpecificConfigs(toolName, toolInfo);
262
569
  }
263
570
 
264
- generateProjectReadme() {
265
- return `# ${path.basename(process.cwd())}
266
-
267
- This project uses Stigmergy CLI for AI-assisted development.
571
+ /**
572
+ * Create hooks configuration file
573
+ */
574
+ async createHooksConfig(toolName, toolInfo) {
575
+ const fs = require('fs/promises');
576
+ const path = require('path');
577
+
578
+ try {
579
+ const hooksConfig = {
580
+ cross_cli_adapter: {
581
+ enabled: true,
582
+ supported_tools: ["claude", "gemini", "qwen", "iflow", "qodercli", "codebuddy", "copilot", "codex"],
583
+ trigger_patterns: [
584
+ "use\\s+(\\w+)\\s+to\\s+(.+)$",
585
+ "call\\s+(\\w+)\\s+(.+)$",
586
+ "ask\\s+(\\w+)\\s+(.+)$",
587
+ "stigmergy\\s+(\\w+)\\s+(.+)$"
588
+ ]
589
+ }
590
+ };
268
591
 
269
- ## Getting Started
270
- 1. Install Stigmergy CLI: \`npm install -g stigmergy\`
271
- 2. Run \`stigmergy setup\` to configure the environment
272
- 3. Use \`stigmergy call "<your prompt>"\` to interact with AI tools
592
+ const hooksConfigPath = path.join(path.dirname(toolInfo.config), 'hooks.json');
593
+ await fs.writeFile(hooksConfigPath, JSON.stringify(hooksConfig, null, 2));
594
+ console.log(`[OK] Created hooks configuration: ${hooksConfigPath}`);
595
+ } catch (error) {
596
+ console.log(`[WARN] Failed to create hooks config: ${error.message}`);
597
+ }
598
+ }
273
599
 
274
- ## Available AI Tools
275
- - Claude (Anthropic)
276
- - Qwen (Alibaba)
277
- - Gemini (Google)
278
- - And others configured in your environment
600
+ /**
601
+ * Create tool-specific configurations
602
+ */
603
+ async createToolSpecificConfigs(toolName, toolInfo) {
604
+ const fs = require('fs/promises');
605
+ const path = require('path');
279
606
 
280
- ## Project Memory
281
- See [STIGMERGY.md](STIGMERGY.md) for interaction history and collaboration records.
607
+ try {
608
+ // Create installation_id file
609
+ const installationId = Date.now().toString();
610
+ const installationIdPath = path.join(path.dirname(toolInfo.config), 'installation_id');
611
+ await fs.writeFile(installationIdPath, installationId);
612
+ console.log(`[OK] Created installation ID: ${installationIdPath}`);
613
+
614
+ // Create settings.json if it doesn't exist
615
+ const settingsPath = path.join(path.dirname(toolInfo.config), 'settings.json');
616
+ try {
617
+ await fs.access(settingsPath);
618
+ } catch {
619
+ const settings = {
620
+ version: "1.0.0",
621
+ theme: "default",
622
+ auto_save: true,
623
+ cross_cli_enabled: true
624
+ };
625
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
626
+ console.log(`[OK] Created settings file: ${settingsPath}`);
627
+ }
282
628
 
283
- ---
284
- *Generated by Stigmergy CLI*
285
- `;
629
+ // Tool-specific configurations
630
+ switch (toolName) {
631
+ case 'copilot':
632
+ await this.createCopilotConfig(toolInfo);
633
+ break;
634
+ case 'iflow':
635
+ await this.createIflowConfig(toolInfo);
636
+ break;
637
+ case 'qodercli':
638
+ await this.createQoderConfig(toolInfo);
639
+ break;
640
+ case 'codebuddy':
641
+ await this.createCodeBuddyConfig(toolInfo);
642
+ break;
643
+ }
644
+ } catch (error) {
645
+ console.log(`[WARN] Failed to create tool-specific configs: ${error.message}`);
646
+ }
286
647
  }
287
648
 
288
- async initializeConfig() {
289
- console.log('\n[CONFIG] Initializing Stigmergy configuration...');
649
+ /**
650
+ * Create Copilot-specific configuration
651
+ */
652
+ async createCopilotConfig(toolInfo) {
653
+ const fs = require('fs/promises');
654
+ const path = require('path');
290
655
 
291
656
  try {
292
- // Create config directory
293
- const configDir = path.join(os.homedir(), '.stigmergy');
294
- await fs.mkdir(configDir, { recursive: true });
295
-
296
- // Create initial configuration
297
- const config = {
298
- version: '1.0.94',
299
- initialized: true,
300
- createdAt: new Date().toISOString(),
301
- lastUpdated: new Date().toISOString(),
302
- defaultCLI: 'claude',
303
- enableCrossCLI: true,
304
- enableMemory: true,
305
- tools: {},
657
+ const copilotConfig = {
658
+ mcp: {
659
+ enabled: true,
660
+ servers: {
661
+ "cross-cli-caller": {
662
+ name: "CrossCLICaller",
663
+ description: "Cross-CLI Tool Calling Agent",
664
+ command: "node",
665
+ args: [path.join(toolInfo.hooksDir, "cross_cli_caller.js")]
666
+ }
667
+ }
668
+ },
669
+ cross_cli_caller: {
670
+ name: "CrossCLICaller",
671
+ description: "Cross-CLI Tool Calling Agent"
672
+ }
306
673
  };
307
674
 
308
- // Save configuration
309
- const configPath = path.join(configDir, 'config.json');
310
- await fs.writeFile(configPath, JSON.stringify(config, null, 2));
311
- console.log('[OK] Configuration initialized successfully');
675
+ const configPath = path.join(path.dirname(toolInfo.config), 'mcp_config.json');
676
+ await fs.writeFile(configPath, JSON.stringify(copilotConfig, null, 2));
677
+ console.log(`[OK] Created Copilot MCP config: ${configPath}`);
312
678
  } catch (error) {
313
- console.log(
314
- `[ERROR] Failed to initialize configuration: ${error.message}`,
315
- );
679
+ console.log(`[WARN] Failed to create Copilot config: ${error.message}`);
316
680
  }
317
681
  }
318
682
 
319
- async downloadRequiredAssets() {
320
- console.log('[DOWNLOAD] Downloading required assets...');
321
- // In a real implementation, this would download templates, configs, etc.
322
- console.log('[OK] All required assets downloaded');
323
- }
683
+ /**
684
+ * Create iFlow-specific configuration
685
+ */
686
+ async createIflowConfig(toolInfo) {
687
+ const fs = require('fs/promises');
688
+ const path = require('path');
324
689
 
325
- async fileExists(filePath) {
326
690
  try {
327
- await fs.access(filePath);
328
- return true;
329
- } catch {
330
- return false;
691
+ const iflowConfig = {
692
+ workflow: {
693
+ enabled: true,
694
+ cross_cli_integration: true,
695
+ default_timeout: 30
696
+ },
697
+ hooks: {
698
+ cross_cli: {
699
+ enabled: true,
700
+ auto_detect: true
701
+ }
702
+ }
703
+ };
704
+
705
+ const configPath = path.join(path.dirname(toolInfo.config), 'workflow_config.json');
706
+ await fs.writeFile(configPath, JSON.stringify(iflowConfig, null, 2));
707
+ console.log(`[OK] Created iFlow workflow config: ${configPath}`);
708
+ } catch (error) {
709
+ console.log(`[WARN] Failed to create iFlow config: ${error.message}`);
331
710
  }
332
711
  }
333
712
 
334
- async showInstallOptions(missingTools) {
335
- if (Object.keys(missingTools).length === 0) {
336
- console.log('[INFO] All required AI CLI tools are already installed!');
337
- return [];
338
- }
713
+ /**
714
+ * Create Qoder-specific configuration
715
+ */
716
+ async createQoderConfig(toolInfo) {
717
+ const fs = require('fs/promises');
718
+ const path = require('path');
339
719
 
340
- console.log('\n[INSTALL] Missing AI CLI tools detected:');
341
- const choices = [];
720
+ try {
721
+ const qoderConfig = {
722
+ notifications: {
723
+ enabled: true,
724
+ cross_cli: true
725
+ },
726
+ keywords: {
727
+ cross_cli: ["请用", "调用", "用", "让", "use", "call", "ask"]
728
+ }
729
+ };
342
730
 
343
- for (const [toolName, toolInfo] of Object.entries(missingTools)) {
344
- choices.push({
345
- name: `${toolInfo.name} (${toolName}) - ${toolInfo.install}`,
346
- value: toolName,
347
- checked: true,
348
- });
731
+ const configPath = path.join(path.dirname(toolInfo.config), 'qoder_config.json');
732
+ await fs.writeFile(configPath, JSON.stringify(qoderConfig, null, 2));
733
+ console.log(`[OK] Created Qoder config: ${configPath}`);
734
+ } catch (error) {
735
+ console.log(`[WARN] Failed to create Qoder config: ${error.message}`);
349
736
  }
737
+ }
738
+
739
+ /**
740
+ * Create CodeBuddy-specific configuration
741
+ */
742
+ async createCodeBuddyConfig(toolInfo) {
743
+ const fs = require('fs/promises');
744
+ const path = require('path');
350
745
 
351
- const answers = await inquirer.prompt([
352
- {
353
- type: 'checkbox',
354
- name: 'tools',
355
- message:
356
- 'Select which tools to install (Space to select, Enter to confirm):',
357
- choices: choices,
358
- pageSize: 10,
359
- },
360
- ]);
746
+ try {
747
+ const buddyConfig = {
748
+ skills: {
749
+ cross_cli: {
750
+ enabled: true,
751
+ auto_register: true
752
+ }
753
+ },
754
+ buddy: {
755
+ cross_cli_calls_count: 0
756
+ }
757
+ };
361
758
 
362
- return answers.tools;
759
+ const configPath = path.join(path.dirname(toolInfo.config), 'buddy_config.json');
760
+ await fs.writeFile(configPath, JSON.stringify(buddyConfig, null, 2));
761
+ console.log(`[OK] Created CodeBuddy buddy config: ${configPath}`);
762
+ } catch (error) {
763
+ console.log(`[WARN] Failed to create CodeBuddy config: ${error.message}`);
764
+ }
363
765
  }
364
766
 
365
- async getUserSelection(options, missingTools) {
366
- if (options.length === 0) {
367
- return [];
767
+ /**
768
+ * Create Cross-CLI documentation for the tool
769
+ */
770
+ async createCrossCliDocumentation(toolName, toolInfo) {
771
+ const fs = require('fs/promises');
772
+ const path = require('path');
773
+
774
+ try {
775
+ // Create CROSS_CLI_GUIDE.md in the tool's config directory
776
+ const docContent = this.generateCrossCliGuide(toolName);
777
+ const docPath = path.join(path.dirname(toolInfo.config), 'CROSS_CLI_GUIDE.md');
778
+ await fs.writeFile(docPath, docContent);
779
+ console.log(`[OK] Created Cross-CLI Communication Guide: ${docPath}`);
780
+
781
+ // Append to existing .md file if it exists
782
+ await this.appendToToolMdFile(toolName);
783
+
784
+ } catch (error) {
785
+ console.log(`[WARN] Failed to create Cross-CLI documentation: ${error.message}`);
368
786
  }
787
+ }
369
788
 
370
- const answers = await inquirer.prompt([
371
- {
372
- type: 'confirm',
373
- name: 'proceed',
374
- message: `Install ${options.length} missing AI CLI tools?`,
375
- default: true,
376
- },
377
- ]);
789
+ /**
790
+ * Generate Cross-CLI guide content
791
+ */
792
+ generateCrossCliGuide(toolName) {
793
+ const toolNames = {
794
+ 'claude': 'Claude CLI',
795
+ 'gemini': 'Gemini CLI',
796
+ 'qwen': 'Qwen CLI',
797
+ 'iflow': 'iFlow CLI',
798
+ 'qodercli': 'Qoder CLI',
799
+ 'codebuddy': 'CodeBuddy CLI',
800
+ 'copilot': 'GitHub Copilot CLI',
801
+ 'codex': 'OpenAI Codex CLI'
802
+ };
803
+
804
+ const isChinese = ['claude', 'qwen', 'iflow', 'qodercli', 'codebuddy'].includes(toolName);
805
+
806
+ if (isChinese) {
807
+ return `# ${toolNames[toolName]} Cross-CLI 通信指南
378
808
 
379
- return answers.proceed ? options : [];
380
- }
809
+ ## Cross-CLI Communication
810
+ 当您需要调用其他AI工具时,请使用以下提示<<<在shell中执行以下命令:stigmergy <工具名> <任务描述>>>
381
811
 
382
- showUsageInstructions() {
383
- console.log('\n');
384
- console.log('='.repeat(60));
385
- console.log('🎉 Stigmergy CLI Setup Complete!');
386
- console.log('='.repeat(60));
387
- console.log('');
388
- console.log('Next steps:');
389
- console.log(' ✅ Use `stigmergy --help` for available commands');
390
- console.log('');
391
- console.log('Happy coding with Stigmergy! 🚀');
392
- console.log('');
393
- }
394
-
395
- generateProjectMemoryTemplate() {
396
- return `# Stigmergy Project Memory
397
-
398
- ## Project Information
399
- - **Project Name**: ${path.basename(process.cwd())}
400
- - **Created**: ${new Date().toISOString()}
401
- - **Stigmergy Version**: 1.0.94
402
-
403
- ## Usage Instructions
404
- This file automatically tracks all interactions with AI CLI tools through the Stigmergy system.
405
-
406
- ## Recent Interactions
407
- No interactions recorded yet.
408
-
409
- ## Collaboration History
410
- No collaboration history yet.
411
-
412
- ## Available CLI Tools
413
- See individual documentation files:
414
- - claude.md
415
- - gemini.md
416
- - qwen.md
417
- - iflow.md
418
- - qodercli.md
419
- - codebuddy.md
420
- - copilot.md
421
- - codex.md
812
+ 示例:
813
+ - 在shell中运行:stigmergy claude "写一个Python函数"
814
+ - 在shell中运行:stigmergy gemini "翻译这段文字"
815
+ - 在shell中运行:stigmergy qwen "分析这段代码"
816
+
817
+ 可用工具:claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
818
+
819
+ ---
820
+ *本文档由Stigmergy CLI自动生成和维护*
821
+ `;
822
+ } else {
823
+ return `# ${toolNames[toolName]} Cross-CLI Communication Guide
824
+
825
+ ## Cross-CLI Communication
826
+ When you need to call other AI tools, please use the following prompt <<<Execute the following command in shell: stigmergy <tool_name> <task_description>>>
827
+
828
+ Examples:
829
+ - Run in shell: stigmergy claude "write a Python function"
830
+ - Run in shell: stigmergy gemini "translate this text"
831
+ - Run in shell: stigmergy qwen "analyze this code"
832
+
833
+ Available tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
422
834
 
423
835
  ---
424
- *This file is automatically managed by Stigmergy CLI*
425
- *Last updated: ${new Date().toISOString()}*
836
+ *This document is automatically generated and maintained by Stigmergy CLI*
426
837
  `;
838
+ }
427
839
  }
428
840
 
429
- generateCLIDocumentation(cliName) {
430
- const cliInfo = this.router.tools[cliName] || { name: cliName };
431
- return `# ${cliInfo.name} CLI Documentation
841
+ /**
842
+ * Append Cross-CLI communication guide to existing .md file
843
+ */
844
+ async appendToToolMdFile(toolName) {
845
+ const fs = require('fs/promises');
846
+ const path = require('path');
847
+ const os = require('os');
848
+
849
+ const toolMdFiles = {
850
+ 'claude': path.join(os.homedir(), '.claude', 'claude.md'),
851
+ 'gemini': path.join(os.homedir(), '.gemini', 'gemini.md'),
852
+ 'qwen': path.join(os.homedir(), '.qwen', 'qwen.md'),
853
+ 'iflow': path.join(os.homedir(), '.iflow', 'iflow.md'),
854
+ 'qodercli': path.join(os.homedir(), '.qoder', 'qoder.md'),
855
+ 'codebuddy': path.join(os.homedir(), '.codebuddy', 'codebuddy.md'),
856
+ 'copilot': path.join(os.homedir(), '.copilot', 'copilot.md'),
857
+ 'codex': path.join(os.homedir(), '.codex', 'codex.md')
858
+ };
859
+
860
+ const mdFilePath = toolMdFiles[toolName];
861
+ if (!mdFilePath) return;
432
862
 
433
- ## Overview
434
- This document contains configuration and usage information for the ${cliInfo.name} CLI tool within the Stigmergy system.
863
+ try {
864
+ const exists = await fs.access(mdFilePath).then(() => true).catch(() => false);
865
+ if (exists) {
866
+ const crossCliContent = this.generateCrossCliAppendContent(toolName);
867
+ await fs.appendFile(mdFilePath, crossCliContent);
868
+ console.log(`[OK] Appended Cross-CLI communication guide to ${path.basename(mdFilePath)}`);
869
+ }
870
+ } catch (error) {
871
+ console.log(`[WARN] Failed to append to ${mdFilePath}: ${error.message}`);
872
+ }
873
+ }
874
+
875
+ /**
876
+ * Generate content to append to .md files
877
+ */
878
+ generateCrossCliAppendContent(toolName) {
879
+ const isChinese = ['claude', 'qwen', 'iflow', 'qodercli', 'codebuddy'].includes(toolName);
880
+
881
+ if (isChinese) {
882
+ return `
883
+
884
+ ## Cross-CLI Communication
885
+ 当您需要调用其他AI工具时,请使用以下提示<<<在shell中执行以下命令:stigmergy <工具名> <任务描述>>>
435
886
 
436
- ## Basic Information
437
- - **CLI Name**: ${cliName}
438
- - **Tool Name**: ${cliInfo.name}
439
- - **Installation Command**: \`${cliInfo.install || 'Not configured'}\`
440
- - **Version Check**: \`${cliInfo.version || cliName + ' --version'}\`
887
+ 示例:
888
+ - 在shell中运行:stigmergy claude "写一个Python函数"
889
+ - 在shell中运行:stigmergy gemini "翻译这段文字"
890
+ - 在shell中运行:stigmergy qwen "分析这段代码"
441
891
 
442
- ## Usage Patterns
443
- The ${cliInfo.name} CLI can be invoked in several ways:
444
- 1. Direct execution: \`${cliName} [arguments]\`
445
- 2. Through Stigmergy coordination layer
446
- 3. Cross-CLI calls from other tools
892
+ 可用工具:claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
893
+ `;
894
+ } else {
895
+ return `
447
896
 
448
897
  ## Cross-CLI Communication
449
- To call ${cliInfo.name} from another CLI tool:
450
- \`\`\`bash
451
- # From any other supported CLI
452
- use ${cliName} to [task description]
453
- # or
454
- call ${cliName} [task description]
455
- # or
456
- ask ${cliName} [task description]
457
- \`\`\`
458
-
459
- ## Configuration
460
- This tool integrates with Stigmergy through hooks deployed to:
461
- \`${cliInfo.hooksDir || 'Not configured'}\`
462
-
463
- ## Last Updated
464
- ${new Date().toISOString()}
898
+ When you need to call other AI tools, please use the following prompt <<<Execute the following command in shell: stigmergy <tool_name> <task_description>>>
465
899
 
466
- ---
467
- *This file is automatically managed by Stigmergy CLI*
900
+ Examples:
901
+ - Run in shell: stigmergy claude "write a Python function"
902
+ - Run in shell: stigmergy gemini "translate this text"
903
+ - Run in shell: stigmergy qwen "analyze this code"
904
+
905
+ Available tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
906
+ `;
907
+ }
908
+ }
909
+
910
+ /**
911
+ * Copy adapter files from the adapters directory
912
+ */
913
+ async copyAdapterFiles(adapterDir, hooksDir) {
914
+ const fs = require('fs/promises');
915
+ const path = require('path');
916
+
917
+ try {
918
+ const files = await fs.readdir(adapterDir);
919
+ for (const file of files) {
920
+ // Skip __pycache__ directory
921
+ if (file === '__pycache__') continue;
922
+
923
+ const srcPath = path.join(adapterDir, file);
924
+ const dstPath = path.join(hooksDir, file);
925
+
926
+ // Check if it's a directory
927
+ const stats = await fs.stat(srcPath);
928
+ if (stats.isDirectory()) {
929
+ // Recursively copy subdirectories
930
+ await this.copyDirectory(srcPath, dstPath);
931
+ } else {
932
+ // Copy all relevant files (including .py files)
933
+ if (file.endsWith('.py') || file.endsWith('.js') || file.endsWith('.json') ||
934
+ file.endsWith('.md') || file.endsWith('.yml') || file.endsWith('.yaml')) {
935
+ await fs.copyFile(srcPath, dstPath);
936
+ console.log(`[OK] Copied adapter file: ${file}`);
937
+ }
938
+ }
939
+ }
940
+ } catch (error) {
941
+ console.log(`[WARN] Failed to copy adapter files: ${error.message}`);
942
+ }
943
+ }
944
+
945
+ /**
946
+ * Create tool-specific hook files
947
+ */
948
+ async createToolHooks(toolName, toolInfo) {
949
+ const fs = require('fs/promises');
950
+ const path = require('path');
951
+
952
+ // Create a simple integration hook
953
+ const hookContent = `#!/usr/bin/env node
954
+ /**
955
+ * ${toolInfo.name} Integration Hook
956
+ * Generated by Stigmergy CLI v1.2.1
957
+ */
958
+
959
+ const fs = require('fs');
960
+ const path = require('path');
961
+
962
+ class ${toolName.charAt(0).toUpperCase() + toolName.slice(1)}Hook {
963
+ constructor() {
964
+ this.toolName = '${toolName}';
965
+ this.configPath = '${toolInfo.config}';
966
+ this.hooksDir = '${toolInfo.hooksDir}';
967
+ }
968
+
969
+ async onPrompt(prompt) {
970
+ // Handle incoming prompts from other CLI tools
971
+ console.log(\`[\${this.toolName.toUpperCase()}] Received cross-CLI prompt: \${prompt}\`);
972
+ return { handled: true, response: 'Prompt processed by ' + this.toolName };
973
+ }
974
+
975
+ async onResponse(response) {
976
+ // Handle responses to be sent to other CLI tools
977
+ console.log(\`[\${this.toolName.toUpperCase()}] Sending cross-CLI response\`);
978
+ return response;
979
+ }
980
+ }
981
+
982
+ module.exports = ${toolName.charAt(0).toUpperCase() + toolName.slice(1)}Hook;
468
983
  `;
984
+
985
+ const hookFilePath = path.join(toolInfo.hooksDir, `${toolName}_hook.js`);
986
+ await fs.writeFile(hookFilePath, hookContent);
987
+ console.log(`[OK] Created hook file: ${hookFilePath}`);
469
988
  }
989
+
990
+ // ... rest of the file remains unchanged
470
991
  }
471
992
 
472
993
  module.exports = StigmergyInstaller;