stigmergy 1.0.57

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 (94) hide show
  1. package/LICENSE +19 -0
  2. package/README.de.md +301 -0
  3. package/README.en.md +301 -0
  4. package/README.es.md +301 -0
  5. package/README.fr.md +301 -0
  6. package/README.ja.md +301 -0
  7. package/README.ko.md +301 -0
  8. package/README.md +301 -0
  9. package/README.ru.md +301 -0
  10. package/README.zh.md +301 -0
  11. package/package.json +82 -0
  12. package/src/adapters/claude/__init__.py +13 -0
  13. package/src/adapters/claude/claude_skills_integration.py +609 -0
  14. package/src/adapters/claude/hook_adapter.py +663 -0
  15. package/src/adapters/claude/install_claude_integration.py +265 -0
  16. package/src/adapters/claude/skills_hook_adapter.py +841 -0
  17. package/src/adapters/claude/standalone_claude_adapter.py +384 -0
  18. package/src/adapters/cline/__init__.py +20 -0
  19. package/src/adapters/cline/config.py +108 -0
  20. package/src/adapters/cline/install_cline_integration.py +617 -0
  21. package/src/adapters/cline/mcp_server.py +713 -0
  22. package/src/adapters/cline/standalone_cline_adapter.py +459 -0
  23. package/src/adapters/codebuddy/__init__.py +13 -0
  24. package/src/adapters/codebuddy/buddy_adapter.py +1125 -0
  25. package/src/adapters/codebuddy/install_codebuddy_integration.py +279 -0
  26. package/src/adapters/codebuddy/skills_hook_adapter.py +672 -0
  27. package/src/adapters/codebuddy/skills_integration.py +395 -0
  28. package/src/adapters/codebuddy/standalone_codebuddy_adapter.py +403 -0
  29. package/src/adapters/codex/__init__.py +11 -0
  30. package/src/adapters/codex/base.py +46 -0
  31. package/src/adapters/codex/install_codex_integration.py +311 -0
  32. package/src/adapters/codex/mcp_server.py +493 -0
  33. package/src/adapters/codex/natural_language_parser.py +82 -0
  34. package/src/adapters/codex/slash_command_adapter.py +326 -0
  35. package/src/adapters/codex/standalone_codex_adapter.py +362 -0
  36. package/src/adapters/copilot/__init__.py +13 -0
  37. package/src/adapters/copilot/install_copilot_integration.py +564 -0
  38. package/src/adapters/copilot/mcp_adapter.py +772 -0
  39. package/src/adapters/copilot/mcp_server.py +168 -0
  40. package/src/adapters/copilot/standalone_copilot_adapter.py +114 -0
  41. package/src/adapters/gemini/__init__.py +13 -0
  42. package/src/adapters/gemini/extension_adapter.py +690 -0
  43. package/src/adapters/gemini/install_gemini_integration.py +257 -0
  44. package/src/adapters/gemini/standalone_gemini_adapter.py +366 -0
  45. package/src/adapters/iflow/__init__.py +7 -0
  46. package/src/adapters/iflow/hook_adapter.py +1038 -0
  47. package/src/adapters/iflow/hook_installer.py +536 -0
  48. package/src/adapters/iflow/install_iflow_integration.py +271 -0
  49. package/src/adapters/iflow/official_hook_adapter.py +1272 -0
  50. package/src/adapters/iflow/standalone_iflow_adapter.py +48 -0
  51. package/src/adapters/iflow/workflow_adapter.py +793 -0
  52. package/src/adapters/qoder/hook_installer.py +732 -0
  53. package/src/adapters/qoder/install_qoder_integration.py +265 -0
  54. package/src/adapters/qoder/notification_hook_adapter.py +863 -0
  55. package/src/adapters/qoder/standalone_qoder_adapter.py +48 -0
  56. package/src/adapters/qwen/__init__.py +17 -0
  57. package/src/adapters/qwencode/__init__.py +13 -0
  58. package/src/adapters/qwencode/inheritance_adapter.py +818 -0
  59. package/src/adapters/qwencode/install_qwencode_integration.py +276 -0
  60. package/src/adapters/qwencode/standalone_qwencode_adapter.py +399 -0
  61. package/src/atomic_collaboration_handler.py +461 -0
  62. package/src/cli_collaboration_agent.py +697 -0
  63. package/src/collaboration/hooks.py +315 -0
  64. package/src/core/__init__.py +21 -0
  65. package/src/core/ai_environment_scanner.py +331 -0
  66. package/src/core/base_adapter.py +220 -0
  67. package/src/core/cli_hook_integration.py +406 -0
  68. package/src/core/cross_cli_executor.py +713 -0
  69. package/src/core/cross_cli_mapping.py +1163 -0
  70. package/src/core/cross_platform_encoding.py +365 -0
  71. package/src/core/cross_platform_safe_cli.py +894 -0
  72. package/src/core/direct_cli_executor.py +805 -0
  73. package/src/core/direct_cli_hook_system.py +958 -0
  74. package/src/core/enhanced_init_processor.py +427 -0
  75. package/src/core/graceful_cli_executor.py +912 -0
  76. package/src/core/md_enhancer.py +342 -0
  77. package/src/core/md_generator.py +619 -0
  78. package/src/core/models.py +218 -0
  79. package/src/core/parser.py +108 -0
  80. package/src/core/real_cli_hook_system.py +852 -0
  81. package/src/core/real_cross_cli_system.py +925 -0
  82. package/src/core/verified_cross_cli_system.py +961 -0
  83. package/src/deploy.js +737 -0
  84. package/src/enhanced_deploy.js +303 -0
  85. package/src/enhanced_universal_cli_setup.py +930 -0
  86. package/src/kimi_wrapper.py +104 -0
  87. package/src/main.js +1309 -0
  88. package/src/shell_integration.py +398 -0
  89. package/src/simple-main.js +315 -0
  90. package/src/smart_router_creator.py +323 -0
  91. package/src/universal_cli_setup.py +1289 -0
  92. package/src/utils/__init__.py +12 -0
  93. package/src/utils/cli_detector.py +445 -0
  94. package/src/utils/file_utils.py +246 -0
package/src/main.js ADDED
@@ -0,0 +1,1309 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Stigmergy CLI - Multi-Agents NPX 部署管理器
5
+ * 支持一键部署到各个AI CLI工具,实现真正的Stigmergy协作
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-cli'),
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(`❌ 加载 ${adapterName} 适配器配置失败: 未找到配置文件在任何可能的路径中,最后尝试: ${lastPathAttempted}`);
57
+ return { loaded: false, error: "无法找到适配器配置文件" };
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('⚠️ 正在安装中,请稍候...');
96
+ return;
97
+ }
98
+
99
+ this.isInstalling = true;
100
+
101
+ try {
102
+ console.log(`🚀 开始安装 ${adapterName} 适配器...`);
103
+
104
+ // 检查适配器是否已存在
105
+ const exists = await this.checkAdapterExists(adapterName);
106
+ if (exists && !force) {
107
+ console.log(`✅ ${adapterName} 适配器已存在`);
108
+ this.isInstalling = false;
109
+ return;
110
+ }
111
+
112
+ // 加载适配器配置
113
+ const config = await this.loadAdapter(adapterName);
114
+ if (!config.loaded) {
115
+ console.error(`❌ ${adapterName} 适配器配置加载失败: ${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(`✅ ${adapterName} 适配器安装完成`);
143
+
144
+ this.adapters.set(adapterName, config);
145
+ this.isInstalling = false;
146
+
147
+ } catch (error) {
148
+ console.error(`❌ ${adapterName} 适配器安装失败: ${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('🚀 开始部署所有适配器...');
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('✅ 所有适配器部署完成!');
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('✅ 全局配置已更新');
216
+ }
217
+
218
+ async initProject(projectPath = process.cwd()) {
219
+ console.log('🚀 初始化Stigmergy CLI项目...');
220
+
221
+ // 验证并修复路径 - 确保不在系统根目录创建项目文件
222
+ let safeProjectPath = projectPath;
223
+ if (safeProjectPath === '/' || safeProjectPath === 'C:\\' || safeProjectPath === 'D:\\' ||
224
+ safeProjectPath === 'E:\\' || safeProjectPath.endsWith(':\\')) {
225
+ // 如果用户在磁盘根目录运行,创建一个专门的项目目录
226
+ console.log('⚠️ 检测到在磁盘根目录运行,将自动创建项目目录进行初始化');
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(`📁 项目目录创建成功: ${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项目初始化完成!`);
277
+ console.log(`📊 发现 ${availableAdapters.length} 个可用的AI CLI工具:`, 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(`✅ 生成 ${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(`❌ 生成 ${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### 🔄 跨AI工具协作指南\n\n';
329
+
330
+ // 中文协作示例
331
+ section += '#### 中文协作指令\n\n';
332
+ for (const otherAdapter of otherAdapters.slice(0, 3)) {
333
+ section += `- 请用${otherAdapter.name}帮我{this.getRandomTask()}\n`;
334
+ }
335
+
336
+ // 英文协作示例
337
+ section += '\n#### 英文协作指令\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('🔍 检查项目配置...');
366
+
367
+ try {
368
+ // 检查项目配置目录
369
+ const projectConfigDir = join(projectPath, '.stigmergy-project');
370
+ try {
371
+ await fs.access(projectConfigDir);
372
+ console.log('✅ 项目配置目录存在');
373
+ } catch {
374
+ console.log('⚠️ 项目配置目录不存在,需要初始化');
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('✅ 项目配置文件存在');
385
+ console.log(`📊 项目类型: ${config.projectType}`);
386
+ console.log(`📅 创建时间: ${config.createdAt}`);
387
+
388
+ if (config.adapters) {
389
+ console.log(`🔧 已配置适配器: ${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('⚠️ 项目配置文件不存在或格式错误');
396
+ }
397
+
398
+ // 检查全局配置
399
+ try {
400
+ const globalConfigPath = join(this.config.localConfig, 'global-config.json');
401
+ await fs.access(globalConfigPath);
402
+ console.log('✅ 全局配置存在');
403
+ } catch {
404
+ console.log('⚠️ 全局配置不存在,需要部署');
405
+ }
406
+
407
+ console.log('✅ 项目检查完成');
408
+ } catch (error) {
409
+ console.error(`❌ 检查项目时出错: ${error.message}`);
410
+ }
411
+ }
412
+
413
+ async scanSystem() {
414
+ console.log('🔍 扫描系统环境...');
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('📋 扫描结果:');
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 ? '(必需)' : '(可选)';
435
+ console.log(` ${status} ${cliInfo.displayName} ${required} - ${available ? '可用' : '不可用'}`);
436
+ }
437
+
438
+ console.log('');
439
+ console.log('💡 提示: 使用 "stigmergy-cli deploy" 部署未安装的工具');
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('🔍 检查Stigmergy CLI状态...');
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('⚠️ 全局配置文件不存在');
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('⚠️ 项目配置文件不存在');
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 ? '✅ 已安装' : '❌ 未安装',
497
+ config: adapter.config_file
498
+ });
499
+ }
500
+
501
+ console.log('\n📊 全局配置:');
502
+ console.log(` 仓库: ${globalConfig.repo}`);
503
+ console.log(` 版本: ${globalConfig.version}`);
504
+ console.log(` 最后更新: ${globalConfig.lastUpdate}`);
505
+
506
+ console.log('\n🤖 可用适配器:');
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📁 项目配置:');
513
+ console.log(` 类型: ${localConfig.projectType}`);
514
+ console.log(` 创建时间: ${localConfig.createdAt}`);
515
+ console.log(` 可用工具: ${localConfig.adapters.map(a => a.name).join(', ')}`);
516
+ }
517
+
518
+ console.log('\n🔍 适配器详细状态:');
519
+ for (const status of adapterStatuses) {
520
+ if (!status.status) {
521
+ console.log(` ❌ ${status.name}: 需要安装`);
522
+ }
523
+ }
524
+ }
525
+
526
+ async validate(scope = 'project') {
527
+ console.log(`🔍 验证 ${scope} 配置...`);
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('✅ 项目配置验证通过');
536
+ console.log(`📊 项目类型: ${config.projectType}`);
537
+ console.log(`📅 创建时间: ${config.createdAt}`);
538
+ console.log(`🔧 适配器数量: ${config.adapters ? config.adapters.length : 0}`);
539
+
540
+ return true;
541
+ } catch (error) {
542
+ console.log('⚠️ 项目配置验证失败或不存在');
543
+ console.log('💡 提示: 使用 stigmergy-cli init 初始化项目配置');
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('✅ 全局配置验证通过');
553
+ console.log(`📊 版本: ${config.version}`);
554
+ console.log(`📅 最后更新: ${config.lastUpdate}`);
555
+
556
+ return true;
557
+ } catch (error) {
558
+ console.log('⚠️ 全局配置验证失败或不存在');
559
+ console.log('💡 提示: 使用 stigmergy-cli deploy 部署全局配置');
560
+ return false;
561
+ }
562
+ } else {
563
+ console.log('⚠️ 未知的验证范围,使用 "project" 或 "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
+ 🤖 Stigmergy CLI v1.0.0 - Multi-Agents跨AI CLI工具协作系统
610
+
611
+ 📚 可用命令:
612
+ install - 安装所有AI CLI工具适配器
613
+ deploy [options] - 部署适配器到本地配置
614
+ init [path] - 初始化项目(默认当前目录)
615
+ status - 检查系统和适配器状态
616
+ check-project [path] - 检查项目配置
617
+ validate [scope] - 验证配置
618
+ clean [options] - 清理缓存和临时文件
619
+
620
+ 💡 快速开始:
621
+ npx stigmergy-cli init # 初始化当前项目
622
+ npx stigmergy-cli deploy # 一键部署
623
+ npx stigmergy-cli status # 查看状态
624
+
625
+ 🚀 快速部署:
626
+ npx -y git+https://github.com/ptreezh/stigmergy-CLI-Multi-Agents.git#main quick-deploy
627
+
628
+ 📖 文档: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents#readme
629
+ 🔧 配置: ~/.stigmergy-cli/global-config.json
630
+ 🔧 项目: .stigmergy-project/project-config.json
631
+
632
+ 🌟 全球访问:
633
+ npx stigmergy-cli 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 - 远程快速部署系统');
653
+ console.log('==================================');
654
+ console.log('此脚本将自动检测、安装和配置跨AI CLI工具协作系统');
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代码生成CLI工具',
692
+ website: 'https://qoder.ai'
693
+ },
694
+ {
695
+ name: 'codebuddy',
696
+ displayName: 'CodeBuddy CLI',
697
+ npmPackage: '@tencent-ai/codebuddy-code',
698
+ description: '腾讯CodeBuddy编程助手',
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本地模型CLI工具',
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('🔍 正在检测您系统中已安装的AI工具...');
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} - 已安装`);
764
+ } else {
765
+ notInstalledTools.push(tool);
766
+ console.log(`❌ ${tool.displayName} - 未安装`);
767
+ }
768
+ }
769
+
770
+ return { installedTools, notInstalledTools };
771
+ }
772
+
773
+ // 安装指定的工具
774
+ async function installTools(toolsToInstall) {
775
+ if (toolsToInstall.length === 0) {
776
+ console.log('\n✅ 无需安装额外工具,继续配置系统...');
777
+ return;
778
+ }
779
+
780
+ console.log(`\n📦 正在安装 ${toolsToInstall.length} 个AI工具...`);
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🔄 安装 ${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} 安装成功`);
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} 安装出错: ${errOutput.trim()}`);
822
+ }
823
+ });
824
+
825
+ installProcess.on('close', (code) => {
826
+ if (code === 0) {
827
+ console.log(`✅ ${tool.displayName} 安装完成`);
828
+ } else {
829
+ console.log(`⚠️ ${tool.displayName} 安装可能未完成 (退出码: ${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⚙️ 正在配置Stigmergy CLI协作系统...');
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} - 可用`);
919
+ } else {
920
+ unavailableCLIs.push(cliInfo);
921
+ console.log(`❌ ${cliInfo.displayName} - 不可用`);
922
+ }
923
+ }
924
+
925
+ console.log(`\n📊 检测结果: ${availableCLIs.length} 个可用, ${unavailableCLIs.length} 个不可用`);
926
+
927
+ // 初始化项目配置
928
+ try {
929
+ const projectPath = process.cwd();
930
+ console.log('\n🚀 初始化Stigmergy CLI项目...');
931
+
932
+ // 验证并修复路径 - 确保不在系统根目录创建项目文件
933
+ let safeProjectPath = projectPath;
934
+ if (safeProjectPath === '/' || safeProjectPath === 'C:\\' || safeProjectPath === 'D:\\' ||
935
+ safeProjectPath === 'E:\\' || safeProjectPath.endsWith(':\\')) {
936
+ // 如果用户在磁盘根目录运行,创建一个专门的项目目录
937
+ console.log('⚠️ 检测到在磁盘根目录运行,将自动创建项目目录进行初始化');
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(`📁 项目目录创建成功: ${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项目初始化完成!`);
977
+ if (availableCLIs.length > 0) {
978
+ console.log(`📊 为 ${availableCLIs.length} 个已安装的AI CLI工具配置协作:`, availableCLIs.map(a => a.name).join(', '));
979
+ } else {
980
+ console.log(`📊 没有检测到已安装的AI CLI工具`);
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} 配置
991
+
992
+ ## 基本信息
993
+ - **名称**: ${cliInfo.name}
994
+ - **显示名称**: ${cliInfo.displayName}
995
+ - **状态**: 已安装
996
+ - **必需**: ${cliInfo.required ? '是' : '否'}
997
+
998
+ ## Stigmergy协作配置
999
+ 此工具已配置为参与跨AI工具协作系统。
1000
+
1001
+ ## 协作指令示例
1002
+ - 中文: "请用${cliInfo.name}帮我{任务}"
1003
+ - 英文: "use ${cliInfo.name} to {task}"
1004
+
1005
+ ---
1006
+ 生成时间: ${new Date().toISOString()}
1007
+ `;
1008
+ await fs.writeFile(mdPath, mdContent);
1009
+ console.log(`✅ 生成 ${cliInfo.name}.md`);
1010
+ } catch (error) {
1011
+ console.log(`⚠️ 生成 ${cliInfo.name}.md 失败: ${error.message}`);
1012
+ }
1013
+ }
1014
+
1015
+ console.log('✅ 项目配置完成');
1016
+
1017
+ // 为已安装的CLI配置集成插件(如果支持)
1018
+ console.log('\n🔄 为已安装的CLI配置协作插件...');
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🔄 配置 ${cliInfo.displayName} 集成插件...`);
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} 集成插件配置成功`);
1096
+ } else {
1097
+ console.log(`⚠️ ${cliInfo.displayName} 集成插件配置可能未完成 (退出码: ${integrationCode})`);
1098
+ }
1099
+ resolve();
1100
+ });
1101
+ });
1102
+ } else {
1103
+ console.log(`ℹ️ ${cliInfo.displayName} - 暂无特殊集成插件配置`);
1104
+ }
1105
+ } catch (error) {
1106
+ console.log(`⚠️ ${cliInfo.displayName} 集成插件配置过程中出错: ${error.message}`);
1107
+ }
1108
+ }
1109
+
1110
+ console.log('\n✅ 系统配置成功');
1111
+ } catch (error) {
1112
+ console.log(`❌ 系统配置失败: ${error.message}`);
1113
+ }
1114
+ }
1115
+
1116
+
1117
+ // 询问用户输入(使用命令行参数而不是inquirer)
1118
+ async function promptForTools(notInstalledTools) {
1119
+ if (notInstalledTools.length === 0) {
1120
+ console.log('\n🎉 您已经安装了所有支持的AI工具!');
1121
+ return [];
1122
+ }
1123
+
1124
+ console.log('\n🎯 检测到您还可以安装以下AI工具:');
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包: ${tool.npmPackage}`);
1129
+ }
1130
+
1131
+ console.log('\n💡 提示: 您可以稍后通过 "npm install -g <package>" 手动安装这些工具');
1132
+ console.log(' 或者现在选择要安装的工具编号,用空格分隔 (如: 1 3 4), 0表示不安装任何工具:');
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('请选择要安装的工具编号: ', (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-cli
1165
+ async function installStigmergyGlobally() {
1166
+ console.log('\n🌍 正在全局安装 stigmergy-cli...');
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-cli 已成功全局安装!');
1194
+ console.log(' 现在可以在任何目录运行: stigmergy-cli <command>');
1195
+ resolve();
1196
+ } else {
1197
+ console.log('[WARN] 全局安装可能未成功,但您可以手动安装:');
1198
+ console.log(' npm install -g stigmergy-cli');
1199
+ resolve(); // 不阻塞流程
1200
+ }
1201
+ });
1202
+
1203
+ installProcess.on('error', (error) => {
1204
+ console.log('[WARN] 全局安装失败,您可以手动安装:');
1205
+ console.log(' npm install -g stigmergy-cli');
1206
+ console.log(` 错误: ${error.message}`);
1207
+ resolve(); // 不阻塞流程
1208
+ });
1209
+ });
1210
+ } catch (error) {
1211
+ console.log('[WARN] 全局安装失败,您可以手动安装:');
1212
+ console.log(' npm install -g stigmergy-cli');
1213
+ console.log(` 错误: ${error.message}`);
1214
+ }
1215
+ }
1216
+
1217
+ // 显示初始化指南
1218
+ function showInitializationGuide() {
1219
+ console.log('\n🎉 部署完成!以下是使用指南:');
1220
+ console.log('\n📋 快速开始:');
1221
+ console.log(' 现在已全局安装!可以在任何目录运行:');
1222
+ console.log(' • 初始化项目: stigmergy-cli init');
1223
+ console.log(' • 查看状态: stigmergy-cli status');
1224
+ console.log(' • 扫描环境: stigmergy-cli scan');
1225
+ console.log('');
1226
+ console.log(' 或者使用 NPX(无需安装):');
1227
+ console.log(' • 初始化项目: npx stigmergy-cli@latest init');
1228
+ console.log(' • 查看状态: npx stigmergy-cli@latest status');
1229
+ console.log(' • 扫描环境: npx stigmergy-cli@latest scan');
1230
+
1231
+ console.log('\n⚠️ 重要提示:');
1232
+ console.log(' 新安装的CLI工具需要注册或自行配置第三方API tokens接口:');
1233
+ console.log('');
1234
+
1235
+ console.log('\n🔧 各CLI工具启动指令:');
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📁 建议工作流程:');
1246
+ console.log(' 1. 新建项目目录:');
1247
+ console.log(' mkdir my-ai-project');
1248
+ console.log(' cd my-ai-project');
1249
+ console.log('');
1250
+ console.log(' 2. 初始化项目:');
1251
+ console.log(' stigmergy-cli init');
1252
+ console.log(' 或者: npx stigmergy-cli@latest init');
1253
+ console.log('');
1254
+ console.log(' 3. 在任何目录下使用CLI工具:');
1255
+ console.log(' claude "设计一个用户认证系统"');
1256
+ console.log(' gemini "请用qwen实现这个设计"');
1257
+ console.log(' qwen "用iflow创建开发流程"');
1258
+
1259
+ console.log('\n🔑 API配置指南:');
1260
+ console.log(' • Claude: 需要设置 ANTHROPIC_API_KEY');
1261
+ console.log(' • Gemini: 需要设置 GOOGLE_API_KEY');
1262
+ console.log(' • QwenCode: 需要设置 DASHSCOPE_API_KEY');
1263
+ console.log(' • iFlow: 需要注册账号获取API密钥');
1264
+ console.log(' • Qoder: 需要注册账号获取API密钥');
1265
+ console.log(' • CodeBuddy: 需要微信扫码认证或设置 TENCENT_SECRET_ID/KEY');
1266
+ console.log(' • Copilot: 需要登录 GitHub 账号');
1267
+ console.log(' • Codex: 需要设置 OPENAI_API_KEY');
1268
+
1269
+ console.log('\n🚀 跨AI工具协作示例:');
1270
+ console.log(' - 直接在各CLI工具中使用协作指令:');
1271
+ console.log(' 例: qwen "请用gemini帮我翻译这段代码"');
1272
+ console.log(' 例: gemini "调用qwen分析这个需求"');
1273
+ console.log(' 例: claude "使用iflow创建工作流"');
1274
+
1275
+ console.log('\n💡 高级功能:');
1276
+ console.log(' - 项目背景共享:所有AI工具共享PROJECT_SPEC.json');
1277
+ console.log(' - 任务分配:自动分配和跟踪协作任务');
1278
+ console.log(' - Stigmergy协作:通过环境线索实现间接协同');
1279
+
1280
+ console.log('\n🔗 想了解更多?访问: https://github.com/ptreezh/stigmergy-CLI-Multi-Agents');
1281
+ console.log('\n🎊 祝您在多AI工具协作中取得成功!');
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-cli
1298
+ await installStigmergyGlobally();
1299
+
1300
+ // 显示使用指南
1301
+ showInitializationGuide();
1302
+ } catch (error) {
1303
+ console.error(`\n❌ 部署过程中发生错误: ${error.message}`);
1304
+ console.error(error.stack);
1305
+ process.exit(1);
1306
+ }
1307
+ }
1308
+
1309
+ main();