stigmergy 1.0.68 → 1.0.70

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 (102) hide show
  1. package/README.en.md +306 -300
  2. package/README.md +469 -301
  3. package/package.json +97 -81
  4. package/scripts/publish.js +268 -0
  5. package/scripts/simple-publish.js +59 -0
  6. package/src/index.js +12 -0
  7. package/test/enhanced-main-alignment.test.js +298 -0
  8. package/test/hook-system-integration-test.js +307 -0
  9. package/test/natural-language-skills-test.js +320 -0
  10. package/test/nl-integration-test.js +179 -0
  11. package/test/parameter-parsing-test.js +143 -0
  12. package/test/real-test.js +435 -0
  13. package/test/system-compatibility-test.js +447 -0
  14. package/test/tdd-fixes-test.js +211 -0
  15. package/test/third-party-skills-test.js +321 -0
  16. package/test/tool-selection-integration-test.js +157 -0
  17. package/test/unit/cli-scanner.test.js +291 -0
  18. package/test/unit/cross-cli-executor.test.js +399 -0
  19. package/src/adapters/claude/__init__.py +0 -13
  20. package/src/adapters/claude/claude_skills_integration.py +0 -609
  21. package/src/adapters/claude/hook_adapter.py +0 -663
  22. package/src/adapters/claude/install_claude_integration.py +0 -265
  23. package/src/adapters/claude/skills_hook_adapter.py +0 -841
  24. package/src/adapters/claude/standalone_claude_adapter.py +0 -384
  25. package/src/adapters/cline/__init__.py +0 -20
  26. package/src/adapters/cline/config.py +0 -108
  27. package/src/adapters/cline/install_cline_integration.py +0 -617
  28. package/src/adapters/cline/mcp_server.py +0 -713
  29. package/src/adapters/cline/standalone_cline_adapter.py +0 -459
  30. package/src/adapters/codebuddy/__init__.py +0 -13
  31. package/src/adapters/codebuddy/buddy_adapter.py +0 -1125
  32. package/src/adapters/codebuddy/install_codebuddy_integration.py +0 -279
  33. package/src/adapters/codebuddy/skills_hook_adapter.py +0 -672
  34. package/src/adapters/codebuddy/skills_integration.py +0 -395
  35. package/src/adapters/codebuddy/standalone_codebuddy_adapter.py +0 -403
  36. package/src/adapters/codex/__init__.py +0 -11
  37. package/src/adapters/codex/base.py +0 -46
  38. package/src/adapters/codex/install_codex_integration.py +0 -311
  39. package/src/adapters/codex/mcp_server.py +0 -493
  40. package/src/adapters/codex/natural_language_parser.py +0 -82
  41. package/src/adapters/codex/slash_command_adapter.py +0 -326
  42. package/src/adapters/codex/standalone_codex_adapter.py +0 -362
  43. package/src/adapters/copilot/__init__.py +0 -13
  44. package/src/adapters/copilot/install_copilot_integration.py +0 -564
  45. package/src/adapters/copilot/mcp_adapter.py +0 -772
  46. package/src/adapters/copilot/mcp_server.py +0 -168
  47. package/src/adapters/copilot/standalone_copilot_adapter.py +0 -114
  48. package/src/adapters/gemini/__init__.py +0 -13
  49. package/src/adapters/gemini/extension_adapter.py +0 -690
  50. package/src/adapters/gemini/install_gemini_integration.py +0 -257
  51. package/src/adapters/gemini/standalone_gemini_adapter.py +0 -366
  52. package/src/adapters/iflow/__init__.py +0 -7
  53. package/src/adapters/iflow/hook_adapter.py +0 -1038
  54. package/src/adapters/iflow/hook_installer.py +0 -536
  55. package/src/adapters/iflow/install_iflow_integration.py +0 -271
  56. package/src/adapters/iflow/official_hook_adapter.py +0 -1272
  57. package/src/adapters/iflow/standalone_iflow_adapter.py +0 -48
  58. package/src/adapters/iflow/workflow_adapter.py +0 -793
  59. package/src/adapters/qoder/hook_installer.py +0 -732
  60. package/src/adapters/qoder/install_qoder_integration.py +0 -265
  61. package/src/adapters/qoder/notification_hook_adapter.py +0 -863
  62. package/src/adapters/qoder/standalone_qoder_adapter.py +0 -48
  63. package/src/adapters/qwen/__init__.py +0 -17
  64. package/src/adapters/qwencode/__init__.py +0 -13
  65. package/src/adapters/qwencode/inheritance_adapter.py +0 -818
  66. package/src/adapters/qwencode/install_qwencode_integration.py +0 -276
  67. package/src/adapters/qwencode/standalone_qwencode_adapter.py +0 -399
  68. package/src/atomic_collaboration_handler.py +0 -461
  69. package/src/cli_collaboration_agent.py +0 -697
  70. package/src/collaboration/hooks.py +0 -315
  71. package/src/core/__init__.py +0 -21
  72. package/src/core/ai_environment_scanner.py +0 -331
  73. package/src/core/base_adapter.py +0 -220
  74. package/src/core/cli_hook_integration.py +0 -406
  75. package/src/core/cross_cli_executor.py +0 -713
  76. package/src/core/cross_cli_mapping.py +0 -1165
  77. package/src/core/cross_platform_encoding.py +0 -365
  78. package/src/core/cross_platform_safe_cli.py +0 -894
  79. package/src/core/direct_cli_executor.py +0 -805
  80. package/src/core/direct_cli_hook_system.py +0 -958
  81. package/src/core/enhanced_init_processor.py +0 -467
  82. package/src/core/graceful_cli_executor.py +0 -912
  83. package/src/core/md_enhancer.py +0 -342
  84. package/src/core/md_generator.py +0 -619
  85. package/src/core/models.py +0 -218
  86. package/src/core/parser.py +0 -108
  87. package/src/core/real_cli_hook_system.py +0 -852
  88. package/src/core/real_cross_cli_system.py +0 -925
  89. package/src/core/verified_cross_cli_system.py +0 -961
  90. package/src/deploy.js +0 -737
  91. package/src/enhanced-main.js +0 -626
  92. package/src/enhanced_deploy.js +0 -303
  93. package/src/enhanced_universal_cli_setup.py +0 -930
  94. package/src/kimi_wrapper.py +0 -104
  95. package/src/main.js +0 -1309
  96. package/src/shell_integration.py +0 -398
  97. package/src/simple-main.js +0 -315
  98. package/src/smart_router_creator.py +0 -323
  99. package/src/universal_cli_setup.py +0 -1289
  100. package/src/utils/__init__.py +0 -12
  101. package/src/utils/cli_detector.py +0 -445
  102. package/src/utils/file_utils.py +0 -246
package/src/main.js DELETED
@@ -1,1309 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Stigmergy CLI - Multi-Agents NPX Deployment Manager
5
- * Support one-click deployment to AI CLI tools, enabling true Stigmergy collaboration
6
- */
7
- import { spawn } from 'child_process';
8
- import fs from 'fs/promises';
9
- import { join, dirname } from 'path';
10
- import { fileURLToPath } from 'url';
11
- import { homedir } from 'os';
12
- import { createHash } from 'crypto';
13
-
14
- const __filename = fileURLToPath(import.meta.url);
15
- const __dirname = dirname(__filename);
16
-
17
- const CONFIG = {
18
- repo: 'https://github.com/ptreezh/stigmergy-CLI-Multi-Agents.git',
19
- localConfig: join(homedir(), '.stigmergy'),
20
- templatesDir: join(__dirname, 'templates'),
21
- adaptersDir: join(__dirname, 'adapters')
22
- };
23
-
24
- class StigmergyCLIRouter {
25
- constructor() {
26
- this.config = CONFIG;
27
- this.adapters = new Map();
28
- this.isInstalling = false;
29
- }
30
-
31
- async loadAdapter(adapterName) {
32
- // 适配器名称映射 - 将用户可见的名称映射到实际目录名
33
- const adapterDirName = this.mapAdapterName(adapterName);
34
-
35
- // 尝试多个可能的路径
36
- const possibleBasePaths = [
37
- join(__dirname, 'adapters'), // 从当前文件目录查找
38
- join(dirname(__dirname), 'adapters'), // 从当前目录的父目录查找
39
- ];
40
-
41
- for (const basePath of possibleBasePaths) {
42
- try {
43
- const configPath = join(basePath, adapterDirName, 'config.json');
44
- const configData = await fs.readFile(configPath, 'utf8');
45
- const config = JSON.parse(configData);
46
- // 成功找到配置,返回
47
- return { ...config, loaded: true };
48
- } catch (error) {
49
- // 继续尝试下一个路径
50
- continue;
51
- }
52
- }
53
-
54
- // 所有路径都尝试过了但失败
55
- const lastPathAttempted = join(possibleBasePaths[possibleBasePaths.length - 1], adapterDirName, 'config.json');
56
- console.error(`❌ Failed to load ${adapterName} adapter configuration: Config file not found in any possible paths, last attempt: ${lastPathAttempted}`);
57
- return { loaded: false, error: "Unable to find adapter configuration file" };
58
- }
59
-
60
- async checkAdapterExists(adapterName) {
61
- // 适配器名称映射 - 将用户可见的名称映射到实际目录名
62
- const adapterDirName = this.mapAdapterName(adapterName);
63
-
64
- // 使用与loadAdapter相同的路径检测逻辑
65
- const possibleBasePaths = [
66
- join(__dirname, 'adapters'), // 从当前文件目录查找
67
- join(dirname(__dirname), 'adapters'), // 从当前目录的父目录查找
68
- ];
69
-
70
- for (const basePath of possibleBasePaths) {
71
- try {
72
- const configPath = join(basePath, adapterDirName, 'config.json');
73
- await fs.access(configPath);
74
- return true;
75
- } catch {
76
- // 继续尝试下一个路径
77
- continue;
78
- }
79
- }
80
-
81
- return false;
82
- }
83
-
84
- // 适配器名称映射方法
85
- mapAdapterName(adapterName) {
86
- // 将用户接口名称映射到实际的适配器目录名称
87
- const nameMap = {
88
- 'qwen': 'qwencode' // qwen在内部对应qwencode目录
89
- };
90
- return nameMap[adapterName] || adapterName;
91
- }
92
-
93
- async installAdapter(adapterName, force = false) {
94
- if (this.isInstalling) {
95
- console.log('[WARN] Installation in progress, please wait...');
96
- return;
97
- }
98
-
99
- this.isInstalling = true;
100
-
101
- try {
102
- console.log(`[INSTALL] Starting installation of ${adapterName} adapter...`);
103
-
104
- // 检查适配器是否已存在
105
- const exists = await this.checkAdapterExists(adapterName);
106
- if (exists && !force) {
107
- console.log(`[OK] ${adapterName} adapter already exists`);
108
- this.isInstalling = false;
109
- return;
110
- }
111
-
112
- // 加载适配器配置
113
- const config = await this.loadAdapter(adapterName);
114
- if (!config.loaded) {
115
- console.error(`❌ ${adapterName} adapter configuration loading failed: ${config.error}`);
116
- this.isInstalling = false;
117
- return;
118
- }
119
-
120
- // 创建配置目录
121
- const adapterConfigDir = join(this.config.localConfig, adapterName);
122
- await fs.mkdir(adapterConfigDir, { recursive: true });
123
-
124
- // 使用映射后的目录名查找源配置文件
125
- const adapterDirName = this.mapAdapterName(adapterName);
126
- const adapterConfigFile = join(__dirname, 'src', 'adapters', adapterDirName, 'config.json');
127
- const targetConfigFile = join(adapterConfigDir, 'config.json');
128
- await fs.copyFile(adapterConfigFile, targetConfigFile);
129
-
130
- // 创建钩子目录
131
- const hooksDir = join(adapterConfigDir, 'hooks');
132
- await fs.mkdir(hooksDir, { recursive: true });
133
-
134
- // 复制钩子文件
135
- const adapterHooksDir = join(__dirname, 'src', 'adapters', adapterDirName);
136
- await this.copyDirectory(adapterHooksDir, hooksDir);
137
-
138
- // 创建日志目录
139
- const logsDir = join(adapterConfigDir, 'logs');
140
- await fs.mkdir(logsDir, { recursive: true });
141
-
142
- console.log(`[OK] ${adapterName} adapter installation completed`);
143
-
144
- this.adapters.set(adapterName, config);
145
- this.isInstalling = false;
146
-
147
- } catch (error) {
148
- console.error(`❌ ${adapterName} adapter installation failed: ${error.message}`);
149
- } finally {
150
- this.isInstalling = false;
151
- }
152
- }
153
-
154
- async copyDirectory(src, dest) {
155
- const entries = await fs.readdir(src, { withFileTypes: true });
156
-
157
- for (const entry of entries) {
158
- const srcPath = join(src, entry);
159
- const destPath = join(dest, entry);
160
-
161
- const stat = await fs.stat(srcPath);
162
- if (stat.isDirectory()) {
163
- await fs.mkdir(destPath, { recursive: true });
164
- await this.copyDirectory(srcPath, destPath);
165
- } else {
166
- await fs.copyFile(srcPath, destPath);
167
- }
168
- }
169
- }
170
-
171
- async copyFile(src, dest) {
172
- const data = await fs.readFile(src);
173
- await fs.writeFile(dest, data);
174
- }
175
-
176
- async directoryExists(dirPath) {
177
- try {
178
- const stat = await fs.stat(dirPath);
179
- return stat.isDirectory();
180
- } catch (error) {
181
- return false;
182
- }
183
- }
184
-
185
- async deployAll(force = false) {
186
- console.log('🚀 Starting deployment of all adapters...');
187
-
188
- const adapterNames = ['claude', 'gemini', 'qwen', 'iflow', 'qoder', 'codebuddy', 'copilot', 'codex'];
189
-
190
- for (const adapterName of adapterNames) {
191
- await this.installAdapter(adapterName, force);
192
- }
193
-
194
- console.log('✅ All adapters deployed successfully!');
195
-
196
- // 更新全局配置
197
- await this.updateGlobalConfig();
198
- }
199
-
200
- async updateGlobalConfig() {
201
- const globalConfigPath = join(this.config.localConfig, 'global-config.json');
202
-
203
- const adapters = {};
204
- for (const [name, adapter] of this.adapters) {
205
- adapters[name] = adapter;
206
- }
207
-
208
- const globalConfig = {
209
- adapters,
210
- lastUpdate: new Date().toISOString(),
211
- version: '1.0.0'
212
- };
213
-
214
- await fs.writeFile(globalConfigPath, JSON.stringify(globalConfig, null, 2));
215
- console.log('✅ Global configuration updated');
216
- }
217
-
218
- async initProject(projectPath = process.cwd()) {
219
- console.log('🚀 Initializing Stigmergy CLI project...');
220
-
221
- // 验证并修复路径 - 确保不在系统根目录创建项目文件
222
- let safeProjectPath = projectPath;
223
- if (safeProjectPath === '/' || safeProjectPath === 'C:\\' || safeProjectPath === 'D:\\' ||
224
- safeProjectPath === 'E:\\' || safeProjectPath.endsWith(':\\')) {
225
- // 如果用户在磁盘根目录运行,创建一个专门的项目目录
226
- console.log('⚠️ Detected running in disk root directory, will automatically create project directory for initialization');
227
-
228
- // 创建带序号的项目目录
229
- let projectDirName = 'ProjStig';
230
- let counter = 1;
231
- let targetDir = join(safeProjectPath, projectDirName);
232
-
233
- // 检查目录是否存在,如果存在则添加序号
234
- while (await directoryExists(targetDir)) {
235
- targetDir = join(safeProjectPath, `${projectDirName}${counter}`);
236
- counter++;
237
- }
238
-
239
- // 创建项目目录
240
- await fs.mkdir(targetDir, { recursive: true });
241
- safeProjectPath = targetDir;
242
- console.log(`📁 Project directory created successfully: ${safeProjectPath}`);
243
- }
244
-
245
- // 创建项目配置目录
246
- const projectConfigDir = join(safeProjectPath, '.stigmergy-project');
247
- await fs.mkdir(projectConfigDir, { recursive: true });
248
-
249
- // 生成项目配置
250
- const projectConfig = {
251
- projectType: 'initialized',
252
- createdAt: new Date().toISOString(),
253
- adapters: {}
254
- };
255
-
256
- // 检查可用的适配器
257
- const availableAdapters = [];
258
- for (const adapterName of ['claude', 'gemini', 'qwen', 'iflow', 'qoder', 'codebuddy', 'copilot', 'codex']) {
259
- const config = await this.loadAdapter(adapterName);
260
- if (config.loaded) {
261
- availableAdapters.push({
262
- name: adapterName,
263
- version: config.version,
264
- integrationType: config.integration_type,
265
- status: 'available'
266
- });
267
- }
268
- }
269
-
270
- projectConfig.adapters = availableAdapters;
271
-
272
- // 保存项目配置
273
- const projectConfigPath = join(projectConfigDir, 'stigmergy-config.json');
274
- await fs.writeFile(projectConfigPath, JSON.stringify(projectConfig, null, 2));
275
-
276
- console.log(`✅ Stigmergy project initialization completed!`);
277
- console.log(`📊 Discovered ${availableAdapters.length} available AI CLI tools:`, availableAdapters.map(a => a.name).join(', '));
278
-
279
- // 生成增强的MD文档
280
- for (const adapter of availableAdapters) {
281
- // 确保md文件生成在项目目录中而不是系统根目录
282
- const mdPath = join(safeProjectPath, `${adapter.name}.md`);
283
- const config = await this.loadAdapter(adapter.name);
284
-
285
- if (config.loaded) {
286
- const mdContent = await this.generateEnhancedMarkdown(adapter, projectConfig);
287
- await fs.writeFile(mdPath, mdContent, 'utf8');
288
- console.log(`✅ Generated ${adapter.name}.md`);
289
- }
290
- }
291
- }
292
-
293
- async generateEnhancedMarkdown(adapter, projectConfig) {
294
- const templatePath = join(this.config.templatesDir, 'enhanced-cli-doc.md.j2');
295
-
296
- try {
297
- const template = await fs.readFile(templatePath, 'utf8');
298
-
299
- // 替换模板变量
300
- let content = template
301
- .replace(/\{adapterName\}/g, adapter.name)
302
- .replace(/\{displayName\}/g, adapter.displayName || adapter.name)
303
- .replace(/\{version\}/g, adapter.version)
304
- .replace(/\{integrationType\}/g, adapter.integrationType || 'N/A')
305
- .replace(/\{configFile\}/g, adapter.config_file || 'N/A')
306
- .replace(/\{globalDoc\}/g, adapter.global_doc || 'N/A')
307
- .replace(/\{projectPath\}/g, process.cwd())
308
- .replace(/\{availableTools\}/g, projectConfig.adapters.map(a => a.name).join(', '))
309
- .replace(/\{currentTime\}/g, new Date().toLocaleString('zh-CN'))
310
- .replace(/\{currentTimeISO\}/g, new Date().toISOString())
311
- .replace(/\{repoUrl\}/g, this.config.repo);
312
-
313
- // 添加协作指南
314
- const collaborationSection = this.generateCollaborationSection(adapter, projectConfig.adapters);
315
- content = content.replace(/\{collaborationSection\}/g, collaborationSection);
316
-
317
- return content; // 返回内容而不是直接写入文件
318
- } catch (error) {
319
- console.error(`❌ Failed to generate ${adapter.name}.md: ${error.message}`);
320
- throw error;
321
- }
322
- }
323
-
324
- generateCollaborationSection(adapter, availableAdapters) {
325
- const currentAdapter = adapter.name;
326
- const otherAdapters = availableAdapters.filter(a => a.name !== currentAdapter);
327
-
328
- let section = '\n### 🔄 Cross-AI Tool Collaboration Guide\n\n';
329
-
330
- // 中文协作示例
331
- section += '#### Chinese Collaboration Commands\n\n';
332
- for (const otherAdapter of otherAdapters.slice(0, 3)) {
333
- section += `- 请用${otherAdapter.name}帮我{this.getRandomTask()}\n`;
334
- }
335
-
336
- // 英文协作示例
337
- section += '\n#### English Collaboration Commands\n\n';
338
- for (const otherAdapter of otherAdapters.slice(0, 3)) {
339
- section += `- use ${otherAdapter.name} to ${this.getRandomTask()}\n`;
340
- }
341
-
342
- return section;
343
- }
344
-
345
- getRandomTask() {
346
- const tasks = [
347
- '生成用户认证模块',
348
- '分析代码性能问题',
349
- '创建数据库迁移脚本',
350
- '实现API端点',
351
- '优化SQL查询',
352
- '生成测试用例',
353
- '审查代码架构',
354
- '重构遗留代码',
355
- '设计系统架构文档',
356
- '处理CSV数据并生成可视化图表',
357
- '分析关键业务指标',
358
- '实现缓存策略',
359
- '优化应用启动时间'
360
- ];
361
- return tasks[Math.floor(Math.random() * tasks.length)];
362
- }
363
-
364
- async checkProject(projectPath = process.cwd()) {
365
- console.log('[CHECK] Checking project configuration...');
366
-
367
- try {
368
- // 检查项目配置目录
369
- const projectConfigDir = join(projectPath, '.stigmergy-project');
370
- try {
371
- await fs.access(projectConfigDir);
372
- console.log('✅ Project configuration directory exists');
373
- } catch {
374
- console.log('⚠️ Project configuration directory does not exist, needs initialization');
375
- return;
376
- }
377
-
378
- // 检查项目配置文件
379
- const projectConfigPath = join(projectConfigDir, 'stigmergy-config.json');
380
- try {
381
- const projectConfig = await fs.readFile(projectConfigPath, 'utf8');
382
- const config = JSON.parse(projectConfig);
383
-
384
- console.log('✅ Project configuration file exists');
385
- console.log(`📊 Project type: ${config.projectType}`);
386
- console.log(`📅 Created at: ${config.createdAt}`);
387
-
388
- if (config.adapters) {
389
- console.log(`🔧 Configured adapters: ${config.adapters.length}`);
390
- for (const adapter of config.adapters) {
391
- console.log(` - ${adapter.name} (${adapter.status})`);
392
- }
393
- }
394
- } catch (configErr) {
395
- console.log('⚠️ Project configuration file does not exist or has incorrect format');
396
- }
397
-
398
- // 检查全局配置
399
- try {
400
- const globalConfigPath = join(this.config.localConfig, 'global-config.json');
401
- await fs.access(globalConfigPath);
402
- console.log('✅ Global configuration exists');
403
- } catch {
404
- console.log('⚠️ Global configuration does not exist, needs deployment');
405
- }
406
-
407
- console.log('✅ Project check completed');
408
- } catch (error) {
409
- console.error(`❌ Error checking project: ${error.message}`);
410
- }
411
- }
412
-
413
- async scanSystem() {
414
- console.log('[SCAN] Scanning system environment...');
415
-
416
- // 这里会实现扫描逻辑,类似于deploy.js中的功能
417
- const CLI_TOOLS = [
418
- { name: 'claude', displayName: 'Claude CLI', required: true },
419
- { name: 'gemini', displayName: 'Gemini CLI', required: true },
420
- { name: 'qwen', displayName: 'QwenCode CLI', required: false },
421
- { name: 'iflow', displayName: 'iFlow CLI', required: false },
422
- { name: 'qoder', displayName: 'Qoder CLI', required: false },
423
- { name: 'codebuddy', displayName: 'CodeBuddy CLI', required: false },
424
- { name: 'copilot', displayName: 'GitHub Copilot CLI', required: false },
425
- { name: 'ollama', displayName: 'Ollama CLI', required: false }
426
- ];
427
-
428
- console.log('');
429
- console.log('[RESULTS] Scan results:');
430
-
431
- for (const cliInfo of CLI_TOOLS) {
432
- const available = await this.checkToolAvailable(cliInfo.name);
433
- const status = available ? '✅' : '❌';
434
- const required = cliInfo.required ? '(Required)' : '(Optional)';
435
- console.log(` ${status} ${cliInfo.displayName} ${required} - ${available ? 'Available' : 'Unavailable'}`);
436
- }
437
-
438
- console.log('');
439
- console.log('[TIP] Use "stigmergy deploy" to deploy uninstalled tools');
440
- }
441
-
442
- async checkToolAvailable(cliName) {
443
- try {
444
- const { spawnSync } = require('child_process');
445
- let result;
446
- if (process.platform === 'win32') {
447
- result = spawnSync('where', [cliName], { stdio: 'pipe' });
448
- } else {
449
- result = spawnSync('which', [cliName], { stdio: 'pipe' });
450
- }
451
-
452
- return result.status === 0;
453
- } catch (e) {
454
- // 如果系统命令失败,尝试npm检查
455
- try {
456
- const { spawnSync } = require('child_process');
457
- const npmResult = spawnSync('npm', ['list', '-g', '--depth=0'], { encoding: 'utf-8' });
458
- if (npmResult.status === 0 && npmResult.stdout) {
459
- return npmResult.stdout.includes(cliName);
460
- }
461
- } catch (e2) {
462
- // 忽略npm检查错误
463
- }
464
- return false;
465
- }
466
- }
467
-
468
- async checkStatus() {
469
- console.log('🔍 Checking Stigmergy CLI status...');
470
-
471
- // 检查全局配置
472
- const globalConfigPath = join(this.config.localConfig, 'global-config.json');
473
- let globalConfig;
474
- try {
475
- globalConfig = JSON.parse(await fs.readFile(globalConfigPath, 'utf8'));
476
- } catch {
477
- console.log('⚠️ Global configuration file does not exist');
478
- return;
479
- }
480
-
481
- // 检查本地配置
482
- const localConfigPath = join(process.cwd(), '.stigmergy-project', 'stigmergy-config.json');
483
- let localConfig;
484
- try {
485
- localConfig = JSON.parse(await fs.readFile(localConfigPath, 'utf8'));
486
- } catch {
487
- console.log('⚠️ Project configuration file does not exist');
488
- }
489
-
490
- // 检查适配器状态
491
- const adapterStatuses = [];
492
- for (const [adapterName, adapter] of this.adapters) {
493
- const exists = await this.checkAdapterExists(adapterName);
494
- adapterStatuses.push({
495
- name: adapterName,
496
- status: exists ? '[OK] Installed' : '[X] Not installed',
497
- config: adapter.config_file
498
- });
499
- }
500
-
501
- console.log('\n📊 Global configuration:');
502
- console.log(` Repository: ${globalConfig.repo}`);
503
- console.log(` Version: ${globalConfig.version}`);
504
- console.log(` Last updated: ${globalConfig.lastUpdate}`);
505
-
506
- console.log('\n🤖 Available adapters:');
507
- for (const status of adapterStatuses) {
508
- console.log(` ${status.name}: ${status.status} ${status.config ? `(${status.config})` : ''}`);
509
- }
510
-
511
- if (localConfig) {
512
- console.log('\n📁 Project configuration:');
513
- console.log(` Type: ${localConfig.projectType}`);
514
- console.log(` Created at: ${localConfig.createdAt}`);
515
- console.log(` Available tools: ${localConfig.adapters.map(a => a.name).join(', ')}`);
516
- }
517
-
518
- console.log('\n🔍 Adapter detailed status:');
519
- for (const status of adapterStatuses) {
520
- if (!status.status) {
521
- console.log(` ❌ ${status.name}: needs installation`);
522
- }
523
- }
524
- }
525
-
526
- async validate(scope = 'project') {
527
- console.log(`🔍 Validating ${scope} configuration...`);
528
-
529
- if (scope === 'project') {
530
- const projectConfigPath = join(process.cwd(), '.stigmergy-project', 'stigmergy-config.json');
531
- try {
532
- const projectConfig = await fs.readFile(projectConfigPath, 'utf8');
533
- const config = JSON.parse(projectConfig);
534
-
535
- console.log('✅ Project configuration validation passed');
536
- console.log(`📊 Project type: ${config.projectType}`);
537
- console.log(`📅 Created at: ${config.createdAt}`);
538
- console.log(`🔧 Number of adapters: ${config.adapters ? config.adapters.length : 0}`);
539
-
540
- return true;
541
- } catch (error) {
542
- console.log('⚠️ Project configuration validation failed or does not exist');
543
- console.log('💡 Tip: Use stigmergy init to initialize project configuration');
544
- return false;
545
- }
546
- } else if (scope === 'global') {
547
- const globalConfigPath = join(this.config.localConfig, 'global-config.json');
548
- try {
549
- const globalConfig = await fs.readFile(globalConfigPath, 'utf8');
550
- const config = JSON.parse(globalConfig);
551
-
552
- console.log('✅ Global configuration validation passed');
553
- console.log(`📊 Version: ${config.version}`);
554
- console.log(`📅 Last updated: ${config.lastUpdate}`);
555
-
556
- return true;
557
- } catch (error) {
558
- console.log('⚠️ Global configuration validation failed or does not exist');
559
- console.log('💡 Tip: Use stigmergy deploy to deploy global configuration');
560
- return false;
561
- }
562
- } else {
563
- console.log('⚠️ Unknown validation scope, use "project" or "global"');
564
- return false;
565
- }
566
- }
567
- }
568
-
569
- // 命令处理
570
- async function main() {
571
- const args = process.argv.slice(2);
572
- const command = args[0];
573
-
574
- // 检查是否为快速部署命令
575
- if (args.includes('quick-deploy') || args.includes('deploy')) {
576
- await runQuickDeploy();
577
- return;
578
- }
579
-
580
- const router = new StigmergyCLIRouter();
581
-
582
- switch (command) {
583
- case 'install':
584
- await router.installAll();
585
- break;
586
- case 'deploy':
587
- await router.deployAll(args.includes('--force'));
588
- break;
589
- case 'init':
590
- await router.initProject();
591
- break;
592
- case 'status':
593
- await router.checkStatus();
594
- break;
595
- case 'check-project':
596
- await router.checkProject();
597
- break;
598
- case 'scan':
599
- await router.scanSystem();
600
- break;
601
- case 'validate':
602
- await router.validate(args[1] || 'project');
603
- break;
604
- case 'clean':
605
- // 清理功能实现
606
- break;
607
- default:
608
- console.log(`
609
- [AI] Stigmergy CLI v1.0.0 - Multi-Agents Cross-AI CLI Tool Collaboration System
610
-
611
- [INFO] Available Commands:
612
- install - Install all AI CLI tool adapters
613
- deploy [options] - Deploy adapters to local configuration
614
- init [path] - Initialize project (default: current directory)
615
- status - Check system and adapter status
616
- check-project [path] - Check project configuration
617
- validate [scope] - Validate configuration
618
- clean [options] - Clean cache and temporary files
619
-
620
- [TIP] Quick Start:
621
- stigmergy init # Initialize current project
622
- stigmergy deploy # One-click deployment
623
- stigmergy status # Check status
624
-
625
- [DEPLOY] Quick Deploy:
626
- npx -y git+https://github.com/ptreezh/stigmergy-CLI-Multi-Agents.git#main quick-deploy
627
-
628
- [DOC] Documentation: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents#readme
629
- [CONFIG] Global Config: ~/.stigmergy/global-config.json
630
- [CONFIG] Project Config: .stigmergy-project/project-config.json
631
-
632
- [GLOBAL] Global Access:
633
- npm install -g stigmergy && stigmergy install --global
634
- `);
635
- break;
636
- }
637
- }
638
-
639
- // 添加一个全局的directoryExists函数
640
- async function directoryExists(dirPath) {
641
- try {
642
- const { stat } = await fs;
643
- const statResult = await stat(dirPath);
644
- return statResult.isDirectory();
645
- } catch (error) {
646
- return false;
647
- }
648
- }
649
-
650
- // 远程快速部署函数
651
- async function runQuickDeploy() {
652
- console.log('🤖 Stigmergy CLI - Remote Rapid Deployment System');
653
- console.log('==================================');
654
- console.log('This script will automatically detect, install and configure cross-AI CLI tool collaboration system');
655
- console.log('');
656
-
657
- // 定义支持的AI工具及其npm包名称
658
- const AI_TOOLS = [
659
- {
660
- name: 'claude',
661
- displayName: 'Claude CLI',
662
- npmPackage: '@anthropic-ai/claude-code',
663
- description: 'Anthropic Claude CLI工具',
664
- website: 'https://claude.ai/cli'
665
- },
666
- {
667
- name: 'gemini',
668
- displayName: 'Gemini CLI',
669
- npmPackage: '@google/gemini-cli',
670
- description: 'Google Gemini CLI工具',
671
- website: 'https://ai.google.dev/cli'
672
- },
673
- {
674
- name: 'qwen',
675
- displayName: 'QwenCode CLI',
676
- npmPackage: '@qwen-code/qwen-code@latest',
677
- description: '阿里云QwenCode CLI工具',
678
- website: 'https://qwen.aliyun.com'
679
- },
680
- {
681
- name: 'iflow',
682
- displayName: 'iFlow CLI',
683
- npmPackage: '@iflow-ai/iflow-cli@latest',
684
- description: 'iFlow工作流CLI工具',
685
- website: 'https://iflow.ai'
686
- },
687
- {
688
- name: 'qoder',
689
- displayName: 'Qoder CLI',
690
- npmPackage: '@qoder-ai/qodercli',
691
- description: 'Qoder Code Generation CLI Tool',
692
- website: 'https://qoder.ai'
693
- },
694
- {
695
- name: 'codebuddy',
696
- displayName: 'CodeBuddy CLI',
697
- npmPackage: '@tencent-ai/codebuddy-code',
698
- description: 'Tencent CodeBuddy Programming Assistant',
699
- website: 'https://codebuddy.qq.com'
700
- },
701
- {
702
- name: 'copilot',
703
- displayName: 'GitHub Copilot CLI',
704
- npmPackage: '@github/copilot',
705
- description: 'GitHub Copilot CLI工具',
706
- website: 'https://github.com/features/copilot'
707
- },
708
- {
709
- name: 'ollama',
710
- displayName: 'Ollama CLI',
711
- npmPackage: 'ollama',
712
- description: 'Ollama Local Model CLI Tool',
713
- website: 'https://ollama.ai'
714
- },
715
- {
716
- name: 'codex',
717
- displayName: 'OpenAI Codex CLI',
718
- npmPackage: '@openai/codex --registry=https://registry.npmmirror.com',
719
- description: 'OpenAI Codex代码分析CLI工具',
720
- website: 'https://platform.openai.com'
721
- }
722
- ];
723
-
724
- // 检测AI工具的函数
725
- async function checkToolInstallation(toolName) {
726
- try {
727
- // 检查命令是否可用
728
- const { spawnSync } = await import('child_process');
729
- let result;
730
- if (process.platform === 'win32') {
731
- result = spawnSync('where', [toolName], { stdio: 'pipe' });
732
- } else {
733
- result = spawnSync('which', [toolName], { stdio: 'pipe' });
734
- }
735
-
736
- return result.status === 0;
737
- } catch (e) {
738
- // 如果系统命令失败,尝试npm检查
739
- try {
740
- const { spawnSync } = require('child_process');
741
- const npmResult = spawnSync('npm', ['list', '-g', '--depth=0'], { encoding: 'utf-8' });
742
- if (npmResult.status === 0 && npmResult.stdout) {
743
- return npmResult.stdout.includes(toolName);
744
- }
745
- } catch (e2) {
746
- // 忽略npm检查错误
747
- }
748
- return false;
749
- }
750
- }
751
-
752
- // 检测已安装的AI工具
753
- async function detectInstalledTools() {
754
- console.log('🔍 Detecting AI tools installed in your system...');
755
-
756
- const installedTools = [];
757
- const notInstalledTools = [];
758
-
759
- for (const tool of AI_TOOLS) {
760
- const isInstalled = await checkToolInstallation(tool.name);
761
- if (isInstalled) {
762
- installedTools.push(tool);
763
- console.log(`✅ ${tool.displayName} - Installed`);
764
- } else {
765
- notInstalledTools.push(tool);
766
- console.log(`❌ ${tool.displayName} - Not installed`);
767
- }
768
- }
769
-
770
- return { installedTools, notInstalledTools };
771
- }
772
-
773
- // 安装指定的工具
774
- async function installTools(toolsToInstall) {
775
- if (toolsToInstall.length === 0) {
776
- console.log('\n✅ No additional tools needed, continuing system configuration...');
777
- return;
778
- }
779
-
780
- console.log(`\n📦 Installing ${toolsToInstall.length} AI tools...`);
781
-
782
- for (const toolName of toolsToInstall) {
783
- // 找到工具信息
784
- const tool = AI_TOOLS.find(t => t.name === toolName);
785
- if (!tool) continue;
786
-
787
- console.log(`\n🔄 Installing ${tool.displayName}...`);
788
-
789
- const { spawn } = await import('child_process');
790
- await new Promise((resolve) => {
791
- // 处理带额外参数的npm包名(如codex)
792
- let npmArgs = ['install', '-g'];
793
- const packageWithArgs = tool.npmPackage;
794
-
795
- // 分割包名和参数
796
- const parts = packageWithArgs.split(' ');
797
- npmArgs.push(parts[0]); // 添加包名
798
- if (parts.length > 1) {
799
- npmArgs = npmArgs.concat(parts.slice(1)); // 添加额外参数
800
- }
801
-
802
- const installProcess = spawn('npm', npmArgs, {
803
- stdio: ['pipe', 'pipe', 'pipe'],
804
- shell: true
805
- });
806
-
807
- installProcess.stdout.on('data', (data) => {
808
- const output = data.toString();
809
- if (output.includes('added') || output.includes('updated')) {
810
- console.log(`✅ ${tool.displayName} installation successful`);
811
- }
812
- });
813
-
814
- installProcess.stderr.on('data', (data) => {
815
- // 忽略大部分npm警告,只显示关键错误
816
- const errOutput = data.toString();
817
- if (errOutput.includes('WARN') || errOutput.includes('deprecated')) {
818
- return; // 忽略警告
819
- }
820
- if (errOutput.includes('ERR') || errOutput.includes('error')) {
821
- console.log(`❌ ${tool.displayName} installation error: ${errOutput.trim()}`);
822
- }
823
- });
824
-
825
- installProcess.on('close', (code) => {
826
- if (code === 0) {
827
- console.log(`✅ ${tool.displayName} installation completed`);
828
- } else {
829
- console.log(`⚠️ ${tool.displayName} installation may not be complete (exit code: ${code})`);
830
- }
831
- resolve(); // 继续下一个工具的安装
832
- });
833
- });
834
- }
835
- }
836
-
837
- // 适配器名称映射函数
838
- function mapAdapterName(adapterName) {
839
- // 将用户接口名称映射到实际的适配器目录名称
840
- const nameMap = {
841
- 'qwen': 'qwencode' // qwen在内部对应qwencode目录
842
- };
843
- return nameMap[adapterName] || adapterName;
844
- }
845
-
846
- // 确定特定CLI工具的安装参数
847
- function determineInstallArgs(cliName) {
848
- // 不同的CLI工具有不同的参数格式来触发安装
849
- const installArgMap = {
850
- 'claude': ['--install'], // Claude脚本支持--install
851
- 'gemini': ['--install'], // Gemini脚本支持--install
852
- 'qwen': ['--install'], // QwenCode脚本支持--install
853
- 'iflow': ['--install'], // iFlow脚本支持--install
854
- 'qoder': ['--install'], // Qoder脚本支持--install
855
- 'codebuddy': ['--install'], // CodeBuddy脚本支持--install
856
- 'codex': ['--install'], // Codex脚本支持--install
857
- 'copilot': ['--force'], // Copilot脚本使用--force进行安装
858
- 'ollama': [] // Ollama没有集成脚本
859
- };
860
-
861
- // 返回相应的安装参数数组
862
- return installArgMap[cliName] || ['--install'];
863
- }
864
-
865
- // 检测CLI工具是否可用的函数(与checkToolInstallation保持一致)
866
- async function checkToolAvailable(cliName) {
867
- try {
868
- // 检查命令是否可用
869
- const { spawnSync } = await import('child_process');
870
- let result;
871
- if (process.platform === 'win32') {
872
- result = spawnSync('where', [cliName], { stdio: 'pipe' });
873
- } else {
874
- result = spawnSync('which', [cliName], { stdio: 'pipe' });
875
- }
876
-
877
- return result.status === 0;
878
- } catch (e) {
879
- // 如果系统命令失败,尝试npm检查
880
- try {
881
- const { spawnSync } = require('child_process');
882
- const npmResult = spawnSync('npm', ['list', '-g', '--depth=0'], { encoding: 'utf-8' });
883
- if (npmResult.status === 0 && npmResult.stdout) {
884
- return npmResult.stdout.includes(cliName);
885
- }
886
- } catch (e2) {
887
- // 忽略npm检查错误
888
- }
889
- return false;
890
- }
891
- }
892
-
893
- // 配置系统 - 运行本地init命令,为所有已安装的CLI配置插件
894
- async function configureSystem() {
895
- console.log('\n⚙️ Configuring Stigmergy CLI collaboration system...');
896
-
897
- // 检测所有支持的CLI工具是否已安装
898
- const allCLITools = [
899
- { name: 'claude', displayName: 'Claude CLI', required: true },
900
- { name: 'gemini', displayName: 'Gemini CLI', required: true },
901
- { name: 'qwen', displayName: 'QwenCode CLI', required: false },
902
- { name: 'iflow', displayName: 'iFlow CLI', required: false },
903
- { name: 'qoder', displayName: 'Qoder CLI', required: false },
904
- { name: 'codebuddy', displayName: 'CodeBuddy CLI', required: false },
905
- { name: 'copilot', displayName: 'GitHub Copilot CLI', required: false },
906
- { name: 'codex', displayName: 'OpenAI Codex CLI', required: false },
907
- { name: 'ollama', displayName: 'Ollama CLI', required: false }
908
- ];
909
-
910
- // 检测每个CLI工具是否可用
911
- const availableCLIs = [];
912
- const unavailableCLIs = [];
913
-
914
- for (const cliInfo of allCLITools) {
915
- const available = await checkToolAvailable(cliInfo.name);
916
- if (available) {
917
- availableCLIs.push(cliInfo);
918
- console.log(`✅ ${cliInfo.displayName} - Available`);
919
- } else {
920
- unavailableCLIs.push(cliInfo);
921
- console.log(`❌ ${cliInfo.displayName} - Unavailable`);
922
- }
923
- }
924
-
925
- console.log(`\n📊 Detection results: ${availableCLIs.length} available, ${unavailableCLIs.length} unavailable`);
926
-
927
- // 初始化项目配置
928
- try {
929
- const projectPath = process.cwd();
930
- console.log('\n🚀 Initializing Stigmergy CLI project...');
931
-
932
- // 验证并修复路径 - 确保不在系统根目录创建项目文件
933
- let safeProjectPath = projectPath;
934
- if (safeProjectPath === '/' || safeProjectPath === 'C:\\' || safeProjectPath === 'D:\\' ||
935
- safeProjectPath === 'E:\\' || safeProjectPath.endsWith(':\\')) {
936
- // 如果用户在磁盘根目录运行,创建一个专门的项目目录
937
- console.log('⚠️ Detected running in disk root directory, will automatically create project directory for initialization');
938
-
939
- // 创建带序号的项目目录
940
- let projectDirName = 'ProjStig';
941
- let counter = 1;
942
- let targetDir = join(safeProjectPath, projectDirName);
943
-
944
- // 检查目录是否存在,如果存在则添加序号
945
- while (await directoryExists(targetDir)) {
946
- targetDir = join(safeProjectPath, `${projectDirName}${counter}`);
947
- counter++;
948
- }
949
-
950
- // 创建项目目录
951
- await fs.mkdir(targetDir, { recursive: true });
952
- safeProjectPath = targetDir;
953
- console.log(`📁 Project directory created successfully: ${safeProjectPath}`);
954
- }
955
-
956
- // 创建项目配置目录
957
- const projectConfigDir = join(safeProjectPath, '.stigmergy-project');
958
- await fs.mkdir(projectConfigDir, { recursive: true });
959
-
960
- // 生成项目配置 - 只包含已安装的工具
961
- const projectConfig = {
962
- projectType: 'initialized',
963
- createdAt: new Date().toISOString(),
964
- adapters: availableCLIs.map(cli => ({
965
- name: cli.name,
966
- displayName: cli.displayName,
967
- required: cli.required,
968
- status: 'available'
969
- }))
970
- };
971
-
972
- // 保存项目配置
973
- const projectConfigPath = join(projectConfigDir, 'stigmergy-config.json');
974
- await fs.writeFile(projectConfigPath, JSON.stringify(projectConfig, null, 2));
975
-
976
- console.log(`✅ Stigmergy project initialization completed!`);
977
- if (availableCLIs.length > 0) {
978
- console.log(`📊 Configuring collaboration for ${availableCLIs.length} installed AI CLI tools:`, availableCLIs.map(a => a.name).join(', '));
979
- } else {
980
- console.log(`📊 No installed AI CLI tools detected`);
981
- }
982
-
983
- // 为所有已安装的CLI生成配置文档
984
- for (const cliInfo of availableCLIs) {
985
- // 确保md文件生成在项目目录中而不是系统根目录
986
- const mdPath = join(safeProjectPath, `${cliInfo.name}.md`);
987
-
988
- try {
989
- // 为CLI生成基本配置文档
990
- const mdContent = `# ${cliInfo.displayName} Configuration
991
-
992
- ## Basic Information
993
- - **Name**: ${cliInfo.name}
994
- - **Display Name**: ${cliInfo.displayName}
995
- - **Status**: Installed
996
- - **Required**: ${cliInfo.required ? 'Yes' : 'No'}
997
-
998
- ## Stigmergy Collaboration Configuration
999
- This tool has been configured to participate in the cross-AI tool collaboration system.
1000
-
1001
- ## Collaboration Command Examples
1002
- - Chinese: "请用${cliInfo.name}帮我{任务}"
1003
- - English: "use ${cliInfo.name} to {task}"
1004
-
1005
- ---
1006
- Generated at: ${new Date().toISOString()}
1007
- `;
1008
- await fs.writeFile(mdPath, mdContent);
1009
- console.log(`✅ Generated ${cliInfo.name}.md`);
1010
- } catch (error) {
1011
- console.log(`⚠️ Failed to generate ${cliInfo.name}.md: ${error.message}`);
1012
- }
1013
- }
1014
-
1015
- console.log('✅ Project configuration completed');
1016
-
1017
- // 为已安装的CLI配置集成插件(如果支持)
1018
- console.log('\n🔄 Configuring collaboration plugins for installed CLIs...');
1019
- for (const cliInfo of availableCLIs) {
1020
- try {
1021
- // 检查是否存在对应的集成安装脚本
1022
- const adapterDirName = mapAdapterName(cliInfo.name); // 使用映射函数处理qwen->qwencode
1023
- const installScriptPath = join(__dirname, 'adapters', adapterDirName, `install_${adapterDirName}_integration.py`);
1024
-
1025
- // 尝 versfs来检查文件是否存在
1026
- const { access } = await import('fs/promises');
1027
- let fileExists = false;
1028
- try {
1029
- await access(installScriptPath);
1030
- fileExists = true;
1031
- } catch {
1032
- // 文件不存在
1033
- fileExists = false;
1034
- }
1035
-
1036
- if (fileExists) {
1037
- console.log(`\n🔄 Configuring ${cliInfo.displayName} integration plugin...`);
1038
-
1039
- // 不同CLI工具有可能使用不同的安装参数
1040
- const installArgs = determineInstallArgs(cliInfo.name);
1041
-
1042
- const childProcess = await import('child_process');
1043
- const { spawn } = childProcess;
1044
-
1045
- // 对于Copilot,需要处理npx环境下的路径问题
1046
- let additionalEnv = {};
1047
- if (cliInfo.name === 'copilot') {
1048
- // 设置项目根目录环境变量,帮助Python脚本找到配置文件
1049
- // __dirname是src目录,所以需要获取父目录作为项目根目录
1050
- const projectRoot = join(__dirname, '..'); // 从src目录回到项目根目录
1051
- additionalEnv = {
1052
- ...process.env,
1053
- PROJECT_ROOT: projectRoot,
1054
- STIGMERGY_PROJECT_ROOT: projectRoot
1055
- };
1056
- } else {
1057
- additionalEnv = process.env;
1058
- }
1059
-
1060
- // 运行集成安装脚本,使用特定于该工具的安装参数
1061
- const integrationProcess = spawn('python', [
1062
- installScriptPath,
1063
- ...installArgs
1064
- ], {
1065
- stdio: ['pipe', 'pipe', 'pipe'],
1066
- shell: true,
1067
- env: additionalEnv
1068
- });
1069
-
1070
- integrationProcess.stdout.on('data', (data) => {
1071
- const line = data.toString();
1072
- // 过滤一些冗长的输出
1073
- if (!line.includes('CLI跨CLI协作集成安装器') &&
1074
- !line.includes('QwenCode CLI跨CLI协作集成安装器') &&
1075
- !line.includes('Copilot CLI跨CLI集成安装脚本')) {
1076
- console.log(line.trim());
1077
- }
1078
- });
1079
-
1080
- integrationProcess.stderr.on('data', (data) => {
1081
- const errorLine = data.toString().trim();
1082
- // 过滤特定的Python错误信息
1083
- if (!errorLine.includes('CLADE_CONFIG_DIR') && // Claude脚本错误
1084
- !errorLine.includes('argument --install: ignored explicit argument') && // Copilot参数错误
1085
- !errorLine.includes('No such file or directory') && // Copilot路径错误
1086
- !errorLine.includes('loading config file failed') && // Copilot配置文件错误
1087
- errorLine.length > 0) {
1088
- console.error(errorLine);
1089
- }
1090
- });
1091
-
1092
- await new Promise((resolve) => {
1093
- integrationProcess.on('close', (integrationCode) => {
1094
- if (integrationCode === 0) {
1095
- console.log(`✅ ${cliInfo.displayName} integration plugin configuration successful`);
1096
- } else {
1097
- console.log(`⚠️ ${cliInfo.displayName} integration plugin configuration may not be complete (exit code: ${integrationCode})`);
1098
- }
1099
- resolve();
1100
- });
1101
- });
1102
- } else {
1103
- console.log(`ℹ️ ${cliInfo.displayName} - No special integration plugin configuration available`);
1104
- }
1105
- } catch (error) {
1106
- console.log(`⚠️ ${cliInfo.displayName} integration plugin configuration error: ${error.message}`);
1107
- }
1108
- }
1109
-
1110
- console.log('\n✅ System configuration successful');
1111
- } catch (error) {
1112
- console.log(`❌ System configuration failed: ${error.message}`);
1113
- }
1114
- }
1115
-
1116
-
1117
- // 询问用户输入(使用命令行参数而不是inquirer)
1118
- async function promptForTools(notInstalledTools) {
1119
- if (notInstalledTools.length === 0) {
1120
- console.log('\n🎉 You have already installed all supported AI tools!');
1121
- return [];
1122
- }
1123
-
1124
- console.log('\n🎯 The following additional AI tools are available for installation:');
1125
- for (let i = 0; i < notInstalledTools.length; i++) {
1126
- const tool = notInstalledTools[i];
1127
- console.log(`${i + 1}. ${tool.displayName} - ${tool.description}`);
1128
- console.log(` npm package: ${tool.npmPackage}`);
1129
- }
1130
-
1131
- console.log('\n💡 Tip: You can manually install these tools later with "npm install -g <package>"');
1132
- console.log(' Or select tool numbers to install now, separated by spaces (e.g. 1 3 4), 0 to skip all:');
1133
-
1134
- return new Promise(async (resolve) => {
1135
- const readline = await import('readline');
1136
- const { createInterface } = readline;
1137
- const rl = createInterface({
1138
- input: process.stdin,
1139
- output: process.stdout
1140
- });
1141
-
1142
- rl.question('Please select tool numbers to install: ', (answer) => {
1143
- rl.close();
1144
-
1145
- const selections = answer.trim().split(/\s+/).map(Number).filter(n => !isNaN(n));
1146
- if (selections.includes(0)) {
1147
- resolve([]);
1148
- return;
1149
- }
1150
-
1151
- const selectedTools = [];
1152
- for (const selection of selections) {
1153
- const index = selection - 1; // 转换为0基索引
1154
- if (index >= 0 && index < notInstalledTools.length) {
1155
- selectedTools.push(notInstalledTools[index].name);
1156
- }
1157
- }
1158
-
1159
- resolve(selectedTools);
1160
- });
1161
- });
1162
- }
1163
-
1164
- // 自动全局安装 stigmergy
1165
- async function installStigmergyGlobally() {
1166
- console.log('\n🌍 Installing stigmergy globally...');
1167
-
1168
- try {
1169
- const { spawn } = await import('child_process');
1170
-
1171
- await new Promise((resolve, reject) => {
1172
- const installProcess = spawn('npm', ['install', '-g', '.'], {
1173
- stdio: ['pipe', 'pipe', 'pipe'],
1174
- shell: true,
1175
- cwd: process.cwd()
1176
- });
1177
-
1178
- let output = '';
1179
- installProcess.stdout.on('data', (data) => {
1180
- output += data.toString();
1181
- });
1182
-
1183
- installProcess.stderr.on('data', (data) => {
1184
- // 过滤npm的警告信息
1185
- const stderr = data.toString();
1186
- if (!stderr.includes('WARN')) {
1187
- output += stderr;
1188
- }
1189
- });
1190
-
1191
- installProcess.on('close', (code) => {
1192
- if (code === 0) {
1193
- console.log('[OK] stigmergy successfully installed globally!');
1194
- console.log(' You can now run from any directory: stigmergy <command>');
1195
- resolve();
1196
- } else {
1197
- console.log('[WARN] Global installation may not have succeeded, but you can install manually:');
1198
- console.log(' npm install -g stigmergy');
1199
- resolve(); // 不阻塞流程
1200
- }
1201
- });
1202
-
1203
- installProcess.on('error', (error) => {
1204
- console.log('[WARN] Global installation failed, you can install manually:');
1205
- console.log(' npm install -g stigmergy');
1206
- console.log(` Error: ${error.message}`);
1207
- resolve(); // 不阻塞流程
1208
- });
1209
- });
1210
- } catch (error) {
1211
- console.log('[WARN] Global installation failed, you can install manually:');
1212
- console.log(' npm install -g stigmergy');
1213
- console.log(` Error: ${error.message}`);
1214
- }
1215
- }
1216
-
1217
- // 显示初始化指南
1218
- function showInitializationGuide() {
1219
- console.log('\n🎉 Deployment completed! Here is the usage guide:');
1220
- console.log('\n📋 Quick Start:');
1221
- console.log(' Now globally installed! Can run from any directory:');
1222
- console.log(' • Initialize project: stigmergy init');
1223
- console.log(' • Check status: stigmergy status');
1224
- console.log(' • Scan environment: stigmergy scan');
1225
- console.log('');
1226
- console.log(' Or use NPX (no installation required):');
1227
- console.log(' • Initialize project: npx stigmergy@latest init');
1228
- console.log(' • Check status: npx stigmergy@latest status');
1229
- console.log(' • Scan environment: npx stigmergy@latest scan');
1230
-
1231
- console.log('\n⚠️ Important Notice:');
1232
- console.log(' Newly installed CLI tools require registration or configuration of third-party API tokens:');
1233
- console.log('');
1234
-
1235
- console.log('\n🔧 CLI Tool Startup Commands:');
1236
- console.log(' • Claude CLI: claude');
1237
- console.log(' • Gemini CLI: gemini');
1238
- console.log(' • QwenCode CLI: qwen');
1239
- console.log(' • iFlow CLI: iflow');
1240
- console.log(' • Qoder CLI: qodercli');
1241
- console.log(' • CodeBuddy CLI: codebuddy');
1242
- console.log(' • GitHub Copilot: gh copilot');
1243
- console.log(' • OpenAI Codex: codex');
1244
-
1245
- console.log('\n📁 Recommended Workflow:');
1246
- console.log(' 1. Create project directory:');
1247
- console.log(' mkdir my-ai-project');
1248
- console.log(' cd my-ai-project');
1249
- console.log('');
1250
- console.log(' 2. Initialize project:');
1251
- console.log(' stigmergy init');
1252
- console.log(' Or: npx stigmergy@latest init');
1253
- console.log('');
1254
- console.log(' 3. Use CLI tools from any directory:');
1255
- console.log(' claude "Design a user authentication system"');
1256
- console.log(' gemini "Implement this design using qwen"');
1257
- console.log(' qwen "Create development workflow using iflow"');
1258
-
1259
- console.log('\n🔑 API Configuration Guide:');
1260
- console.log(' • Claude: Requires ANTHROPIC_API_KEY');
1261
- console.log(' • Gemini: Requires GOOGLE_API_KEY');
1262
- console.log(' • QwenCode: Requires DASHSCOPE_API_KEY');
1263
- console.log(' • iFlow: Requires registration to get API key');
1264
- console.log(' • Qoder: Requires registration to get API key');
1265
- console.log(' • CodeBuddy: Requires WeChat QR authentication or TENCENT_SECRET_ID/KEY');
1266
- console.log(' • Copilot: Requires GitHub account login');
1267
- console.log(' • Codex: Requires OPENAI_API_KEY');
1268
-
1269
- console.log('\n🚀 Cross-AI Tool Collaboration Examples:');
1270
- console.log(' - Use collaboration commands directly in CLI tools:');
1271
- console.log(' Example: qwen "Help me translate this code using gemini"');
1272
- console.log(' Example: gemini "Analyze this requirement using qwen"');
1273
- console.log(' Example: claude "Create workflow using iflow"');
1274
-
1275
- console.log('\n💡 Advanced Features:');
1276
- console.log(' - Project background sharing: All AI tools share PROJECT_SPEC.json');
1277
- console.log(' - Task assignment: Automatic allocation and tracking of collaboration tasks');
1278
- console.log(' - Stigmergy collaboration: Indirect collaboration through environmental cues');
1279
-
1280
- console.log('\n🔗 Want to learn more? Visit: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
1281
- console.log('\n🎊 Success in your multi-AI tool collaboration!');
1282
- }
1283
-
1284
- try {
1285
- // 检测已安装的AI工具
1286
- const { installedTools, notInstalledTools } = await detectInstalledTools();
1287
-
1288
- // 询问用户是否安装更多工具
1289
- const toolsToInstall = await promptForTools(notInstalledTools);
1290
-
1291
- // 安装选中的工具
1292
- await installTools(toolsToInstall);
1293
-
1294
- // 配置系统
1295
- await configureSystem();
1296
-
1297
- // 自动全局安装 stigmergy
1298
- await installStigmergyGlobally();
1299
-
1300
- // 显示使用指南
1301
- showInitializationGuide();
1302
- } catch (error) {
1303
- console.error(`\n❌ Error occurred during deployment: ${error.message}`);
1304
- console.error(error.stack);
1305
- process.exit(1);
1306
- }
1307
- }
1308
-
1309
- main();