stigmergy 1.2.0 → 1.2.8

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 (130) hide show
  1. package/LICENSE +18 -18
  2. package/README.md +31 -211
  3. package/STIGMERGY.md +70 -61
  4. package/docs/MULTI_USER_WIKI_COLLABORATION_SYSTEM.md +523 -0
  5. package/docs/PROJECT_CONSTITUTION.md +433 -433
  6. package/docs/PROJECT_STRUCTURE_CURRENT.md +80 -80
  7. package/docs/PROMPT_BASED_SKILLS_SYSTEM_DESIGN.md +458 -0
  8. package/docs/SKILL_IMPLEMENTATION_CONSTRAINTS_AND_ALIGNMENT.md +423 -0
  9. package/docs/TECHNICAL_FEASIBILITY_ANALYSIS.md +308 -0
  10. package/examples/calculator-example.js +72 -72
  11. package/examples/cline_usage_examples.md +364 -364
  12. package/examples/encryption-example.js +67 -67
  13. package/examples/json-parser-example.js +120 -120
  14. package/examples/json-validation-example.js +64 -64
  15. package/examples/multilingual-hook-demo.js +125 -0
  16. package/examples/rest-client-example.js +52 -52
  17. package/examples/rest_client_example.js +54 -54
  18. package/package.json +38 -20
  19. package/scripts/build.js +74 -74
  20. package/scripts/dependency-analyzer.js +101 -0
  21. package/scripts/generate-cli-docs.js +64 -0
  22. package/scripts/post-deployment-config.js +296 -296
  23. package/scripts/postuninstall.js +46 -0
  24. package/scripts/preinstall-check.js +173 -173
  25. package/scripts/preuninstall.js +75 -0
  26. package/scripts/publish.js +58 -268
  27. package/scripts/run-layered-tests.js +247 -0
  28. package/scripts/safe-install.js +139 -139
  29. package/scripts/simple-publish.js +57 -59
  30. package/src/adapters/claude/install_claude_integration.js +292 -0
  31. package/src/adapters/codebuddy/install_codebuddy_integration.js +349 -0
  32. package/src/adapters/codex/install_codex_integration.js +395 -0
  33. package/src/adapters/copilot/install_copilot_integration.js +716 -0
  34. package/src/adapters/gemini/install_gemini_integration.js +304 -0
  35. package/src/adapters/iflow/install_iflow_integration.js +304 -0
  36. package/src/adapters/qoder/install_qoder_integration.js +1090 -0
  37. package/src/adapters/qwen/install_qwen_integration.js +285 -0
  38. package/src/cli/router.js +562 -39
  39. package/src/core/cache_cleaner.js +82 -59
  40. package/src/core/cli_help_analyzer.js +297 -291
  41. package/src/core/cli_parameter_handler.js +5 -0
  42. package/src/core/cli_tools.js +6 -6
  43. package/src/core/coordination/index.js +2 -2
  44. package/src/core/coordination/nodejs/AdapterManager.js +30 -17
  45. package/src/core/coordination/nodejs/CLCommunication.js +28 -20
  46. package/src/core/coordination/nodejs/CLIIntegrationManager.js +72 -36
  47. package/src/core/coordination/nodejs/HealthChecker.js +13 -14
  48. package/src/core/coordination/nodejs/HookDeploymentManager.js +325 -63
  49. package/src/core/coordination/nodejs/StatisticsCollector.js +6 -6
  50. package/src/core/coordination/nodejs/index.js +29 -11
  51. package/src/core/coordination/nodejs/utils/Logger.js +1 -1
  52. package/src/core/enhanced_installer.js +92 -69
  53. package/src/core/enhanced_uninstaller.js +73 -53
  54. package/src/core/installer.js +815 -294
  55. package/src/core/multilingual/language-pattern-manager.js +172 -0
  56. package/src/core/smart_router.js +141 -26
  57. package/src/core/upgrade_manager.js +91 -46
  58. package/src/data_structures.js +1 -1
  59. package/src/deploy.js +2 -2
  60. package/src/index.js +3 -3
  61. package/src/test/cli-availability-checker.js +194 -0
  62. package/src/test/test-environment.js +289 -0
  63. package/src/utils/helpers.js +2 -2
  64. package/src/utils.js +7 -1
  65. package/test/multilingual/hook-deployment.test.js +91 -0
  66. package/test/multilingual/language-pattern-manager.test.js +140 -0
  67. package/test/multilingual/system-test.js +85 -0
  68. package/test/cache-cleaner-implemented.test.js +0 -328
  69. package/test/cache-cleaner.test.js +0 -390
  70. package/test/calculator.test.js +0 -215
  71. package/test/collision-test.js +0 -26
  72. package/test/comprehensive-enhanced-features.test.js +0 -252
  73. package/test/comprehensive-execution-test.js +0 -428
  74. package/test/conflict-prevention-test.js +0 -95
  75. package/test/cross-cli-detection-test.js +0 -33
  76. package/test/csv-processing-test.js +0 -36
  77. package/test/deploy-hooks-test.js +0 -250
  78. package/test/e2e/claude-cli-test.js +0 -128
  79. package/test/e2e/collaboration-test.js +0 -75
  80. package/test/e2e/comprehensive-test.js +0 -431
  81. package/test/e2e/error-handling-test.js +0 -90
  82. package/test/e2e/individual-tool-test.js +0 -143
  83. package/test/e2e/other-cli-test.js +0 -130
  84. package/test/e2e/qoder-cli-test.js +0 -128
  85. package/test/e2e/run-e2e-tests.js +0 -73
  86. package/test/e2e/test-data.js +0 -88
  87. package/test/e2e/test-utils.js +0 -222
  88. package/test/encryption-simple-test.js +0 -110
  89. package/test/encryption.test.js +0 -129
  90. package/test/enhanced-main-alignment.test.js +0 -298
  91. package/test/enhanced-uninstaller-implemented.test.js +0 -271
  92. package/test/enhanced-uninstaller.test.js +0 -284
  93. package/test/error-handling-test.js +0 -341
  94. package/test/fibonacci.test.js +0 -178
  95. package/test/final-deploy-test.js +0 -221
  96. package/test/final-install-test.js +0 -226
  97. package/test/hash-table-demo.js +0 -33
  98. package/test/hash-table-test.js +0 -26
  99. package/test/hash_table_test.js +0 -114
  100. package/test/hook-system-integration-test.js +0 -307
  101. package/test/iflow-integration-test.js +0 -292
  102. package/test/improved-install-test.js +0 -362
  103. package/test/install-command-test.js +0 -370
  104. package/test/json-parser-test.js +0 -161
  105. package/test/json-validation-test.js +0 -164
  106. package/test/natural-language-skills-test.js +0 -320
  107. package/test/nl-integration-test.js +0 -179
  108. package/test/parameter-parsing-test.js +0 -143
  109. package/test/plugin-deployment-test.js +0 -316
  110. package/test/postinstall-test.js +0 -269
  111. package/test/python-plugins-test.js +0 -259
  112. package/test/real-test.js +0 -435
  113. package/test/remaining-adapters-test.js +0 -256
  114. package/test/rest-client-test.js +0 -56
  115. package/test/rest_client.test.js +0 -85
  116. package/test/safe-installation-cleaner.test.js +0 -343
  117. package/test/simple-iflow-hook-test.js +0 -137
  118. package/test/stigmergy-upgrade-test.js +0 -243
  119. package/test/system-compatibility-test.js +0 -467
  120. package/test/tdd-deploy-fix-test.js +0 -324
  121. package/test/tdd-fixes-test.js +0 -211
  122. package/test/third-party-skills-test.js +0 -321
  123. package/test/tool-selection-integration-test.js +0 -158
  124. package/test/unit/calculator-full.test.js +0 -191
  125. package/test/unit/calculator-simple.test.js +0 -96
  126. package/test/unit/calculator.test.js +0 -97
  127. package/test/unit/cli-scanner.test.js +0 -291
  128. package/test/unit/cli_parameter_handler.test.js +0 -116
  129. package/test/unit/cross-cli-executor.test.js +0 -399
  130. package/test/weather-processor.test.js +0 -104
@@ -0,0 +1,716 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Copilot CLI Cross-CLI Integration Installer
5
+ *
6
+ * Automatically installs and configures Copilot CLI cross-CLI integration features
7
+ * including MCP server registration, custom agent creation, and permission configuration
8
+ *
9
+ * 使用方法:
10
+ * node install_copilot_integration.js [--config=path] [--force] [--uninstall] [--verbose]
11
+ */
12
+
13
+ const fs = require('fs').promises;
14
+ const path = require('path');
15
+ const os = require('os');
16
+ const { spawn } = require('child_process');
17
+
18
+ class CopilotIntegrationInstaller {
19
+ constructor(configPath = null, force = false) {
20
+ this.scriptDir = __dirname;
21
+ // Use script directory as project root for standalone installation
22
+ this.projectRoot = path.join(this.scriptDir, '..', '..', '..');
23
+ this.force = force;
24
+ this.startTime = Date.now();
25
+
26
+ if (configPath) {
27
+ this.configPath = path.resolve(configPath);
28
+ } else {
29
+ // In npx environment, may need to search for config file in multiple locations
30
+ const possiblePaths = [
31
+ path.join(this.scriptDir, 'config.json'), // Standard location - should be the most likely path
32
+ path.join(this.scriptDir, '..', 'copilot', 'config.json'), // In adapters/copilot/
33
+ path.join(__dirname, 'config.json'), // Using script directory - also standard location
34
+ ];
35
+
36
+ // Check environment variables to get project root directory
37
+ const projectRootEnv = process.env.STIGMERGY_PROJECT_ROOT || '';
38
+ if (projectRootEnv) {
39
+ // Add environment variable specified path to search list
40
+ const envConfigPath = path.join(projectRootEnv, 'src', 'adapters', 'copilot', 'config.json');
41
+ possiblePaths.push(envConfigPath);
42
+ }
43
+
44
+ let configFound = false;
45
+ for (const configPathOption of possiblePaths) {
46
+ try {
47
+ require('fs').accessSync(configPathOption);
48
+ this.configPath = configPathOption;
49
+ console.log(`Using config file: ${configPathOption}`);
50
+ configFound = true;
51
+ break;
52
+ } catch (error) {
53
+ // File doesn't exist, continue searching
54
+ }
55
+ }
56
+
57
+ if (!configFound) {
58
+ // If all options fail, use default location and dynamically create config
59
+ this.configPath = path.join(this.scriptDir, 'config.json');
60
+
61
+ // Create default config content
62
+ const defaultConfig = {
63
+ name: 'copilot',
64
+ displayName: 'GitHub Copilot CLI',
65
+ version: '1.0.0',
66
+ integration_type: 'mcp_server',
67
+ config_file: '~/.config/copilot/config.json',
68
+ global_doc: 'copilot.md',
69
+ description: 'GitHub Copilot CLI MCP Server Integration Adapter',
70
+ mcp_config: {
71
+ server_name: 'stigmergy-copilot-integration',
72
+ command: 'node',
73
+ args: [
74
+ 'src/adapters/copilot/mcp_server.js'
75
+ ],
76
+ environment: {
77
+ NODE_PATH: '.',
78
+ STIGMERGY_CONFIG_PATH: '~/.stigmergy',
79
+ COPILOT_ADAPTER_MODE: 'cross_cli'
80
+ },
81
+ health_check_interval: 30,
82
+ timeout: 60
83
+ },
84
+ custom_agents: {
85
+ cross_cli_caller: {
86
+ name: 'CrossCLICaller',
87
+ description: 'Cross-CLI Tool Calling Agent',
88
+ version: '1.0.0',
89
+ tools: [
90
+ 'cross_cli_execute',
91
+ 'get_available_clis',
92
+ 'check_cli_status'
93
+ ],
94
+ permissions: [
95
+ 'execute_external_cli',
96
+ 'read_config',
97
+ 'write_logs'
98
+ ]
99
+ }
100
+ },
101
+ supported_cli_tools: [
102
+ 'claude',
103
+ 'gemini',
104
+ 'qwen',
105
+ 'iflow',
106
+ 'qoder',
107
+ 'codebuddy',
108
+ 'codex'
109
+ ],
110
+ permissions: {
111
+ execute_external_cli: {
112
+ description: 'Execute external CLI tools',
113
+ level: 'high',
114
+ requires_approval: false
115
+ },
116
+ read_config: {
117
+ description: 'Read CLI config files',
118
+ level: 'medium',
119
+ requires_approval: false
120
+ },
121
+ write_logs: {
122
+ description: 'Write to log files',
123
+ level: 'low',
124
+ requires_approval: false
125
+ }
126
+ },
127
+ adapter: {
128
+ name: 'Copilot MCP Integration Adapter',
129
+ version: '1.0.0',
130
+ type: 'mcp_server',
131
+ module_path: 'src.adapters.copilot.mcp_adapter',
132
+ class_name: 'CopilotMCPIntegrationAdapter',
133
+ features: [
134
+ 'cross_cli_detection',
135
+ 'command_routing',
136
+ 'result_formatting',
137
+ 'collaboration_tracking'
138
+ ]
139
+ }
140
+ };
141
+
142
+ // Create config file
143
+ try {
144
+ require('fs').mkdirSync(path.dirname(this.configPath), { recursive: true });
145
+ require('fs').writeFileSync(this.configPath, JSON.stringify(defaultConfig, null, 2));
146
+ console.log(`[OK] Created default config file: ${this.configPath}`);
147
+ } catch (error) {
148
+ console.error(`Failed to create default config file: ${error.message}`);
149
+ throw error;
150
+ }
151
+
152
+ console.log(`Using dynamically created config file: ${this.configPath}`);
153
+ }
154
+ }
155
+
156
+ this.config = this._loadConfig();
157
+
158
+ // Copilot related paths
159
+ this.homeDir = os.homedir();
160
+ this.copilotDir = path.join(this.homeDir, '.copilot');
161
+ this.mcpConfigFile = path.join(this.copilotDir, 'mcp-config.json');
162
+ this.customAgentsDir = path.join(this.copilotDir, 'agents');
163
+
164
+ // Project paths - fallback to script directory if src doesn't exist
165
+ this.srcDir = path.join(this.projectRoot, 'src');
166
+ try {
167
+ require('fs').accessSync(this.srcDir);
168
+ } catch (error) {
169
+ this.srcDir = this.scriptDir;
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Load config file
175
+ */
176
+ _loadConfig() {
177
+ try {
178
+ const data = require('fs').readFileSync(this.configPath, 'utf8');
179
+ return JSON.parse(data);
180
+ } catch (error) {
181
+ console.error(`Failed to load config file: ${error.message}`);
182
+ process.exit(1);
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Execute full installation process
188
+ */
189
+ async install() {
190
+ try {
191
+ console.log('Starting Copilot CLI cross-CLI integration installation...');
192
+
193
+ // 1. Check environment
194
+ if (!await this._checkEnvironment()) {
195
+ return false;
196
+ }
197
+
198
+ // 2. Create config directories
199
+ if (!await this._createDirectories()) {
200
+ return false;
201
+ }
202
+
203
+ // 3. Install MCP server config
204
+ if (!await this._installMcpServer()) {
205
+ return false;
206
+ }
207
+
208
+ // 4. Create custom agents
209
+ if (!await this._createCustomAgents()) {
210
+ return false;
211
+ }
212
+
213
+ // 5. Setup permissions config
214
+ if (!await this._setupPermissions()) {
215
+ return false;
216
+ }
217
+
218
+ // 6. Create global Cross-CLI documentation
219
+ await this._createGlobalCrossCliDocumentation();
220
+
221
+ // 7. Verify installation
222
+ if (!await this._verifyInstallation()) {
223
+ return false;
224
+ }
225
+
226
+ console.log('[OK] Copilot CLI cross-CLI integration installed successfully!');
227
+ this._printUsageInstructions();
228
+ return true;
229
+
230
+ } catch (error) {
231
+ console.error(`Installation failed: ${error.message}`);
232
+ return false;
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Check installation environment
238
+ */
239
+ async _checkEnvironment() {
240
+ console.log('Checking installation environment...');
241
+
242
+ // Check Node.js version
243
+ const nodeVersion = process.version;
244
+ const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
245
+ if (majorVersion < 14) {
246
+ console.error('Node.js 14 or higher required');
247
+ return false;
248
+ }
249
+
250
+ // Check if Copilot CLI is installed
251
+ try {
252
+ await this._runCommand('copilot', ['--version'], { timeout: 5000 });
253
+ } catch (error) {
254
+ console.warn('Copilot command not found, please ensure GitHub Copilot CLI is installed');
255
+ console.info('Installation method: npm install -g @github/copilot');
256
+ }
257
+
258
+ // Check adapter file
259
+ const adapterFile = path.join(this.scriptDir, 'mcp_adapter.js');
260
+ try {
261
+ await fs.access(adapterFile);
262
+ } catch (error) {
263
+ console.warn(`Adapter file does not exist: ${adapterFile}`);
264
+ console.info('Continuing without adapter file...');
265
+ }
266
+
267
+ console.log('[OK] Environment check passed');
268
+ return true;
269
+ }
270
+
271
+ /**
272
+ * Create necessary directories
273
+ */
274
+ async _createDirectories() {
275
+ console.log('Creating config directories...');
276
+
277
+ const directories = [
278
+ this.copilotDir,
279
+ this.customAgentsDir,
280
+ path.join(this.copilotDir, 'logs'),
281
+ path.join(this.copilotDir, 'sessions')
282
+ ];
283
+
284
+ for (const directory of directories) {
285
+ try {
286
+ await fs.mkdir(directory, { recursive: true });
287
+ console.log(`Created directory: ${directory}`);
288
+ } catch (error) {
289
+ console.error(`Failed to create directory ${directory}: ${error.message}`);
290
+ return false;
291
+ }
292
+ }
293
+
294
+ console.log('[OK] Directories created successfully');
295
+ return true;
296
+ }
297
+
298
+ /**
299
+ * Install MCP server config
300
+ */
301
+ async _installMcpServer() {
302
+ console.log('Installing MCP server config...');
303
+
304
+ try {
305
+ // Read existing MCP config
306
+ const mcpConfig = await this._loadExistingMcpConfig();
307
+
308
+ // Add our MCP server
309
+ const mcpServers = mcpConfig.mcpServers || {};
310
+ const serverName = this.config.mcp_config.server_name;
311
+
312
+ if (serverName in mcpServers && !this.force) {
313
+ console.log(`MCP server '${serverName}' already exists, skipping...`);
314
+ return true;
315
+ }
316
+
317
+ // Build MCP server config
318
+ // Use script directory as base path
319
+ const mcpServerConfig = {
320
+ command: this.config.mcp_config.command,
321
+ args: this.config.mcp_config.args,
322
+ env: this.config.mcp_config.environment
323
+ };
324
+
325
+ // Add Node.js path to environment variables
326
+ const nodePath = this.scriptDir;
327
+ if ('NODE_PATH' in mcpServerConfig.env) {
328
+ mcpServerConfig.env.NODE_PATH = `${nodePath}:${mcpServerConfig.env.NODE_PATH}`;
329
+ } else {
330
+ mcpServerConfig.env.NODE_PATH = nodePath;
331
+ }
332
+
333
+ mcpServers[serverName] = mcpServerConfig;
334
+ mcpConfig.mcpServers = mcpServers;
335
+
336
+ // Save config
337
+ await fs.writeFile(this.mcpConfigFile, JSON.stringify(mcpConfig, null, 2));
338
+
339
+ console.log(`[OK] MCP server config saved to: ${this.mcpConfigFile}`);
340
+ return true;
341
+
342
+ } catch (error) {
343
+ console.error(`Failed to install MCP server: ${error.message}`);
344
+ return false;
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Load existing MCP config
350
+ */
351
+ async _loadExistingMcpConfig() {
352
+ try {
353
+ await fs.access(this.mcpConfigFile);
354
+ const data = await fs.readFile(this.mcpConfigFile, 'utf8');
355
+ return JSON.parse(data);
356
+ } catch (error) {
357
+ // File doesn't exist or can't be read, return default config
358
+ return {
359
+ mcpServers: {}
360
+ };
361
+ }
362
+ }
363
+
364
+ /**
365
+ * Create custom agents
366
+ */
367
+ async _createCustomAgents() {
368
+ console.log('Creating custom agents...');
369
+
370
+ try {
371
+ for (const [agentName, agentConfig] of Object.entries(this.config.custom_agents)) {
372
+ const agentFile = path.join(this.customAgentsDir, `${agentName}.json`);
373
+
374
+ try {
375
+ await fs.access(agentFile);
376
+ if (!this.force) {
377
+ console.log(`Agent '${agentName}' already exists, skipping...`);
378
+ continue;
379
+ }
380
+ } catch (error) {
381
+ // File doesn't exist, continue
382
+ }
383
+
384
+ // Create agent config
385
+ const agentData = {
386
+ name: agentConfig.name,
387
+ description: agentConfig.description,
388
+ version: agentConfig.version,
389
+ instructions: this._getAgentInstructions(agentName),
390
+ tools: agentConfig.tools,
391
+ permissions: agentConfig.permissions
392
+ };
393
+
394
+ await fs.writeFile(agentFile, JSON.stringify(agentData, null, 2));
395
+ console.log(`Created agent: ${agentName}`);
396
+ }
397
+
398
+ console.log('[OK] Custom agents created successfully');
399
+ return true;
400
+
401
+ } catch (error) {
402
+ console.error(`Failed to create custom agents: ${error.message}`);
403
+ return false;
404
+ }
405
+ }
406
+
407
+ /**
408
+ * Get agent instructions
409
+ */
410
+ _getAgentInstructions(agentName) {
411
+ const instructions = {
412
+ cross_cli_caller: `You are a cross-CLI integration agent that helps users collaborate between different AI CLI tools.
413
+
414
+ When you detect a request to use another CLI tool (like Claude, Gemini, Qwen, iFlow, etc.):
415
+ 1. Parse the target CLI and task from the user's request
416
+ 2. Execute the task using the appropriate CLI tool
417
+ 3. Return the results in a clear, structured format
418
+
419
+ Support both Chinese and English collaboration patterns:
420
+ - "请用{CLI}帮我{task}" -> Use {CLI} to help with {task}
421
+ - "调用{CLI}来{task}" -> Call {CLI} to {task}
422
+ - "use {CLI} to {task}" -> Execute {task} with {CLI}
423
+ - "call {CLI} to {task}" -> Call {CLI} to execute {task}
424
+
425
+ Available tools:
426
+ - cross_cli_execute: Execute tasks on other CLI tools
427
+ - get_available_clis: Get list of available CLI tools
428
+ - check_cli_status: Check status of a specific CLI tool
429
+
430
+ Always maintain the original intent and context of the user's request.
431
+ Provide clear, structured results with execution details.`
432
+ };
433
+
434
+ return instructions[agentName] || 'Cross-CLI integration agent';
435
+ }
436
+
437
+ /**
438
+ * Setup permissions config
439
+ */
440
+ async _setupPermissions() {
441
+ console.log('Setting up permissions config...');
442
+
443
+ try {
444
+ const permissionsConfigFile = path.join(this.copilotDir, 'permissions.json');
445
+
446
+ const permissionsConfig = {
447
+ version: '1.0',
448
+ permissions: this.config.permissions,
449
+ created_at: new Date().toISOString(),
450
+ adapter_version: this.config.adapter.version
451
+ };
452
+
453
+ await fs.writeFile(permissionsConfigFile, JSON.stringify(permissionsConfig, null, 2));
454
+
455
+ console.log('[OK] Permissions config setup completed');
456
+ return true;
457
+
458
+ } catch (error) {
459
+ console.error(`Failed to setup permissions config: ${error.message}`);
460
+ return false;
461
+ }
462
+ }
463
+
464
+ /**
465
+ * Verify installation
466
+ */
467
+ async _verifyInstallation() {
468
+ console.log('Verifying installation...');
469
+
470
+ // Check MCP config file
471
+ try {
472
+ await fs.access(this.mcpConfigFile);
473
+ } catch (error) {
474
+ console.error('MCP config file does not exist');
475
+ return false;
476
+ }
477
+
478
+ // Check custom agents
479
+ for (const agentName of Object.keys(this.config.custom_agents)) {
480
+ const agentFile = path.join(this.customAgentsDir, `${agentName}.json`);
481
+ try {
482
+ await fs.access(agentFile);
483
+ } catch (error) {
484
+ console.error(`Agent file does not exist: ${agentFile}`);
485
+ return false;
486
+ }
487
+ }
488
+
489
+ // Verify MCP config format
490
+ try {
491
+ const data = await fs.readFile(this.mcpConfigFile, 'utf8');
492
+ const mcpConfig = JSON.parse(data);
493
+
494
+ const serverName = this.config.mcp_config.server_name;
495
+ if (!(serverName in (mcpConfig.mcpServers || {}))) {
496
+ console.error(`MCP server config not found: ${serverName}`);
497
+ return false;
498
+ }
499
+
500
+ } catch (error) {
501
+ console.error(`Failed to verify MCP config: ${error.message}`);
502
+ return false;
503
+ }
504
+
505
+ console.log('[OK] Installation verified successfully');
506
+ return true;
507
+ }
508
+
509
+ /**
510
+ * Print usage instructions
511
+ */
512
+ _printUsageInstructions() {
513
+ console.log('\n' + '='.repeat(60));
514
+ console.log('Copilot CLI Cross-CLI Integration Installation Complete!');
515
+ console.log('='.repeat(60));
516
+ console.log('\n[INFO] Usage Instructions:');
517
+ console.log('1. Start Copilot CLI:');
518
+ console.log(' copilot');
519
+ console.log('\n2. Cross-CLI calling examples:');
520
+ console.log(' Chinese: "请用claude帮我写一个Python脚本"');
521
+ console.log(' English: "use gemini to analyze this code"');
522
+ console.log('\n3. Available agents:');
523
+ for (const agentName of Object.keys(this.config.custom_agents)) {
524
+ console.log(` - ${agentName}`);
525
+ }
526
+ console.log('\n4. Supported CLI tools:');
527
+ for (const cliTool of this.config.supported_cli_tools) {
528
+ console.log(` - ${cliTool}`);
529
+ }
530
+ console.log('\nConfig file locations:');
531
+ console.log(` MCP config: ${this.mcpConfigFile}`);
532
+ console.log(` Custom agents: ${this.customAgentsDir}`);
533
+ console.log('\nSee project documentation for more information');
534
+ }
535
+
536
+ /**
537
+ * Create global Cross-CLI communication documentation
538
+ */
539
+ async _createGlobalCrossCliDocumentation() {
540
+ try {
541
+ const docContent = `# Copilot CLI Cross-CLI Communication Guide
542
+
543
+ ## Cross-CLI Communication
544
+ When you need to call other AI tools, please use the following prompt <<<Execute the following command in shell: stigmergy <tool_name> <task_description>>>>
545
+
546
+ Examples:
547
+ - Run in shell: stigmergy claude "write a Python function"
548
+ - Run in shell: stigmergy gemini "translate this text"
549
+ - Run in shell: stigmergy qwen "analyze this code"
550
+
551
+ Available tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
552
+
553
+ ---
554
+ *This document is automatically generated and maintained by Stigmergy CLI*
555
+ `;
556
+
557
+ const docPath = path.join(this.copilotDir, 'CROSS_CLI_GUIDE.md');
558
+ await fs.writeFile(docPath, docContent);
559
+
560
+ console.log(`[OK] Created Cross-CLI Communication Guide: ${docPath}`);
561
+
562
+ // If copilot.md file exists, append Cross-CLI communication hint to the end
563
+ const copilotMdPath = path.join(this.copilotDir, 'copilot.md');
564
+ try {
565
+ await fs.access(copilotMdPath);
566
+
567
+ const crossCliContent = `
568
+
569
+ ## Cross-CLI Communication
570
+ When you need to call other AI tools, please use the following prompt <<<Execute the following command in shell: stigmergy <tool_name> <task_description>>>>
571
+
572
+ Examples:
573
+ - Run in shell: stigmergy claude "write a Python function"
574
+ - Run in shell: stigmergy gemini "translate this text"
575
+ - Run in shell: stigmergy qwen "analyze this code"
576
+
577
+ Available tools: claude, gemini, qwen, iflow, qodercli, codebuddy, copilot, codex
578
+ `;
579
+ await fs.appendFile(copilotMdPath, crossCliContent);
580
+ console.log('[OK] Appended Cross-CLI communication hint to COPILOT.MD');
581
+ } catch (error) {
582
+ // File may not exist, ignore
583
+ }
584
+
585
+ } catch (error) {
586
+ console.warn(`Failed to create Cross-CLI Communication Guide: ${error.message}`);
587
+ }
588
+ console.log('='.repeat(60));
589
+ }
590
+
591
+ /**
592
+ * Uninstall integration
593
+ */
594
+ async uninstall() {
595
+ console.log('Uninstalling Copilot CLI cross-CLI integration...');
596
+
597
+ try {
598
+ // 1. Remove MCP server config
599
+ try {
600
+ const mcpConfig = await this._loadExistingMcpConfig();
601
+ const serverName = this.config.mcp_config.server_name;
602
+
603
+ if (serverName in (mcpConfig.mcpServers || {})) {
604
+ delete mcpConfig.mcpServers[serverName];
605
+
606
+ await fs.writeFile(this.mcpConfigFile, JSON.stringify(mcpConfig, null, 2));
607
+ console.log(`Removed MCP server config: ${serverName}`);
608
+ }
609
+ } catch (error) {
610
+ console.warn(`Failed to remove MCP server config: ${error.message}`);
611
+ }
612
+
613
+ // 2. Remove custom agents
614
+ for (const agentName of Object.keys(this.config.custom_agents)) {
615
+ const agentFile = path.join(this.customAgentsDir, `${agentName}.json`);
616
+ try {
617
+ await fs.unlink(agentFile);
618
+ console.log(`Removed agent: ${agentName}`);
619
+ } catch (error) {
620
+ // File may not exist, ignore
621
+ }
622
+ }
623
+
624
+ console.log('[OK] Uninstallation completed');
625
+ return true;
626
+
627
+ } catch (error) {
628
+ console.error(`Uninstallation failed: ${error.message}`);
629
+ return false;
630
+ }
631
+ }
632
+
633
+ /**
634
+ * Helper method: Run command
635
+ */
636
+ async _runCommand(command, args, options = {}) {
637
+ return new Promise((resolve, reject) => {
638
+ const child = spawn(command, args, {
639
+ stdio: 'pipe',
640
+ ...options
641
+ });
642
+
643
+ let stdout = '';
644
+ let stderr = '';
645
+
646
+ child.stdout.on('data', (data) => {
647
+ stdout += data.toString();
648
+ });
649
+
650
+ child.stderr.on('data', (data) => {
651
+ stderr += data.toString();
652
+ });
653
+
654
+ child.on('close', (code) => {
655
+ if (code === 0) {
656
+ resolve({ stdout, stderr });
657
+ } else {
658
+ reject(new Error(`Command failed with code ${code}: ${stderr}`));
659
+ }
660
+ });
661
+
662
+ child.on('error', reject);
663
+ });
664
+ }
665
+ }
666
+
667
+ // Main function
668
+ async function main() {
669
+ const args = process.argv.slice(2);
670
+
671
+ let configPath = null;
672
+ let force = false;
673
+ let uninstall = false;
674
+ let verbose = false;
675
+
676
+ for (let i = 0; i < args.length; i++) {
677
+ const arg = args[i];
678
+ if (arg.startsWith('--config=')) {
679
+ configPath = arg.substring(9);
680
+ } else if (arg === '--config' && i + 1 < args.length) {
681
+ configPath = args[++i];
682
+ } else if (arg === '--force') {
683
+ force = true;
684
+ } else if (arg === '--uninstall') {
685
+ uninstall = true;
686
+ } else if (arg === '--verbose' || arg === '-v') {
687
+ verbose = true;
688
+ }
689
+ }
690
+
691
+ if (verbose) {
692
+ process.env.DEBUG = 'true';
693
+ }
694
+
695
+ const installer = new CopilotIntegrationInstaller(configPath, force);
696
+
697
+ let success;
698
+ if (uninstall) {
699
+ success = await installer.uninstall();
700
+ } else {
701
+ success = await installer.install();
702
+ }
703
+
704
+ process.exit(success ? 0 : 1);
705
+ }
706
+
707
+ // Export module
708
+ module.exports = CopilotIntegrationInstaller;
709
+
710
+ // If run directly
711
+ if (require.main === module) {
712
+ main().catch(error => {
713
+ console.error('[FATAL]', error.message);
714
+ process.exit(1);
715
+ });
716
+ }