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.
- package/LICENSE +18 -18
- package/README.md +31 -211
- package/STIGMERGY.md +70 -61
- package/docs/MULTI_USER_WIKI_COLLABORATION_SYSTEM.md +523 -0
- package/docs/PROJECT_CONSTITUTION.md +433 -433
- package/docs/PROJECT_STRUCTURE_CURRENT.md +80 -80
- package/docs/PROMPT_BASED_SKILLS_SYSTEM_DESIGN.md +458 -0
- package/docs/SKILL_IMPLEMENTATION_CONSTRAINTS_AND_ALIGNMENT.md +423 -0
- package/docs/TECHNICAL_FEASIBILITY_ANALYSIS.md +308 -0
- package/examples/calculator-example.js +72 -72
- package/examples/cline_usage_examples.md +364 -364
- package/examples/encryption-example.js +67 -67
- package/examples/json-parser-example.js +120 -120
- package/examples/json-validation-example.js +64 -64
- package/examples/multilingual-hook-demo.js +125 -0
- package/examples/rest-client-example.js +52 -52
- package/examples/rest_client_example.js +54 -54
- package/package.json +38 -20
- package/scripts/build.js +74 -74
- package/scripts/dependency-analyzer.js +101 -0
- package/scripts/generate-cli-docs.js +64 -0
- package/scripts/post-deployment-config.js +296 -296
- package/scripts/postuninstall.js +46 -0
- package/scripts/preinstall-check.js +173 -173
- package/scripts/preuninstall.js +75 -0
- package/scripts/publish.js +58 -268
- package/scripts/run-layered-tests.js +247 -0
- package/scripts/safe-install.js +139 -139
- package/scripts/simple-publish.js +57 -59
- package/src/adapters/claude/install_claude_integration.js +292 -0
- package/src/adapters/codebuddy/install_codebuddy_integration.js +349 -0
- package/src/adapters/codex/install_codex_integration.js +395 -0
- package/src/adapters/copilot/install_copilot_integration.js +716 -0
- package/src/adapters/gemini/install_gemini_integration.js +304 -0
- package/src/adapters/iflow/install_iflow_integration.js +304 -0
- package/src/adapters/qoder/install_qoder_integration.js +1090 -0
- package/src/adapters/qwen/install_qwen_integration.js +285 -0
- package/src/cli/router.js +562 -39
- package/src/core/cache_cleaner.js +82 -59
- package/src/core/cli_help_analyzer.js +297 -291
- package/src/core/cli_parameter_handler.js +5 -0
- package/src/core/cli_tools.js +6 -6
- package/src/core/coordination/index.js +2 -2
- package/src/core/coordination/nodejs/AdapterManager.js +30 -17
- package/src/core/coordination/nodejs/CLCommunication.js +28 -20
- package/src/core/coordination/nodejs/CLIIntegrationManager.js +72 -36
- package/src/core/coordination/nodejs/HealthChecker.js +13 -14
- package/src/core/coordination/nodejs/HookDeploymentManager.js +325 -63
- package/src/core/coordination/nodejs/StatisticsCollector.js +6 -6
- package/src/core/coordination/nodejs/index.js +29 -11
- package/src/core/coordination/nodejs/utils/Logger.js +1 -1
- package/src/core/enhanced_installer.js +92 -69
- package/src/core/enhanced_uninstaller.js +73 -53
- package/src/core/installer.js +815 -294
- package/src/core/multilingual/language-pattern-manager.js +172 -0
- package/src/core/smart_router.js +141 -26
- package/src/core/upgrade_manager.js +91 -46
- package/src/data_structures.js +1 -1
- package/src/deploy.js +2 -2
- package/src/index.js +3 -3
- package/src/test/cli-availability-checker.js +194 -0
- package/src/test/test-environment.js +289 -0
- package/src/utils/helpers.js +2 -2
- package/src/utils.js +7 -1
- package/test/multilingual/hook-deployment.test.js +91 -0
- package/test/multilingual/language-pattern-manager.test.js +140 -0
- package/test/multilingual/system-test.js +85 -0
- package/test/cache-cleaner-implemented.test.js +0 -328
- package/test/cache-cleaner.test.js +0 -390
- package/test/calculator.test.js +0 -215
- package/test/collision-test.js +0 -26
- package/test/comprehensive-enhanced-features.test.js +0 -252
- package/test/comprehensive-execution-test.js +0 -428
- package/test/conflict-prevention-test.js +0 -95
- package/test/cross-cli-detection-test.js +0 -33
- package/test/csv-processing-test.js +0 -36
- package/test/deploy-hooks-test.js +0 -250
- package/test/e2e/claude-cli-test.js +0 -128
- package/test/e2e/collaboration-test.js +0 -75
- package/test/e2e/comprehensive-test.js +0 -431
- package/test/e2e/error-handling-test.js +0 -90
- package/test/e2e/individual-tool-test.js +0 -143
- package/test/e2e/other-cli-test.js +0 -130
- package/test/e2e/qoder-cli-test.js +0 -128
- package/test/e2e/run-e2e-tests.js +0 -73
- package/test/e2e/test-data.js +0 -88
- package/test/e2e/test-utils.js +0 -222
- package/test/encryption-simple-test.js +0 -110
- package/test/encryption.test.js +0 -129
- package/test/enhanced-main-alignment.test.js +0 -298
- package/test/enhanced-uninstaller-implemented.test.js +0 -271
- package/test/enhanced-uninstaller.test.js +0 -284
- package/test/error-handling-test.js +0 -341
- package/test/fibonacci.test.js +0 -178
- package/test/final-deploy-test.js +0 -221
- package/test/final-install-test.js +0 -226
- package/test/hash-table-demo.js +0 -33
- package/test/hash-table-test.js +0 -26
- package/test/hash_table_test.js +0 -114
- package/test/hook-system-integration-test.js +0 -307
- package/test/iflow-integration-test.js +0 -292
- package/test/improved-install-test.js +0 -362
- package/test/install-command-test.js +0 -370
- package/test/json-parser-test.js +0 -161
- package/test/json-validation-test.js +0 -164
- package/test/natural-language-skills-test.js +0 -320
- package/test/nl-integration-test.js +0 -179
- package/test/parameter-parsing-test.js +0 -143
- package/test/plugin-deployment-test.js +0 -316
- package/test/postinstall-test.js +0 -269
- package/test/python-plugins-test.js +0 -259
- package/test/real-test.js +0 -435
- package/test/remaining-adapters-test.js +0 -256
- package/test/rest-client-test.js +0 -56
- package/test/rest_client.test.js +0 -85
- package/test/safe-installation-cleaner.test.js +0 -343
- package/test/simple-iflow-hook-test.js +0 -137
- package/test/stigmergy-upgrade-test.js +0 -243
- package/test/system-compatibility-test.js +0 -467
- package/test/tdd-deploy-fix-test.js +0 -324
- package/test/tdd-fixes-test.js +0 -211
- package/test/third-party-skills-test.js +0 -321
- package/test/tool-selection-integration-test.js +0 -158
- package/test/unit/calculator-full.test.js +0 -191
- package/test/unit/calculator-simple.test.js +0 -96
- package/test/unit/calculator.test.js +0 -97
- package/test/unit/cli-scanner.test.js +0 -291
- package/test/unit/cli_parameter_handler.test.js +0 -116
- package/test/unit/cross-cli-executor.test.js +0 -399
- 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
|
+
}
|