stigmergy 1.3.29-beta.0 → 1.3.30-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/cli_help_analyzer.js +114 -35
- package/src/core/cli_tools.js +18 -20
package/package.json
CHANGED
|
@@ -273,12 +273,20 @@ class CLIHelpAnalyzer {
|
|
|
273
273
|
*/
|
|
274
274
|
async analyzeAllCLI() {
|
|
275
275
|
const results = {};
|
|
276
|
-
|
|
276
|
+
const cliNames = Object.keys(this.cliTools);
|
|
277
|
+
|
|
278
|
+
// 优化:并行分析所有 CLI,添加超时保护
|
|
279
|
+
const analysisPromises = cliNames.map(async (cliName) => {
|
|
277
280
|
try {
|
|
278
281
|
if (process.env.DEBUG === 'true') {
|
|
279
282
|
console.log(`Analyzing ${cliName}...`);
|
|
280
283
|
}
|
|
281
|
-
|
|
284
|
+
// 添加超时保护,单个 CLI 分析最多 60 秒(因为需要尝试多个 help 方法)
|
|
285
|
+
const timeoutPromise = new Promise((_, reject) =>
|
|
286
|
+
setTimeout(() => reject(new Error('Analysis timeout')), 60000)
|
|
287
|
+
);
|
|
288
|
+
const result = await Promise.race([this.analyzeCLI(cliName), timeoutPromise]);
|
|
289
|
+
return { cliName, result };
|
|
282
290
|
} catch (error) {
|
|
283
291
|
// Only log important errors, suppress expected file not found errors
|
|
284
292
|
if (
|
|
@@ -286,7 +294,8 @@ class CLIHelpAnalyzer {
|
|
|
286
294
|
!error.message.includes('no such file or directory') &&
|
|
287
295
|
!error.message.includes(
|
|
288
296
|
'not recognized as an internal or external command',
|
|
289
|
-
)
|
|
297
|
+
) &&
|
|
298
|
+
!error.message.includes('Analysis timeout')
|
|
290
299
|
) {
|
|
291
300
|
await errorHandler.logError(
|
|
292
301
|
error,
|
|
@@ -294,9 +303,21 @@ class CLIHelpAnalyzer {
|
|
|
294
303
|
`CLIHelpAnalyzer.analyzeAllCLI.${cliName}`,
|
|
295
304
|
);
|
|
296
305
|
}
|
|
297
|
-
|
|
306
|
+
return { cliName, result: { success: false, error: error.message } };
|
|
298
307
|
}
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// 等待所有分析完成,添加整体超时保护
|
|
311
|
+
const overallTimeoutPromise = new Promise((_, reject) =>
|
|
312
|
+
setTimeout(() => reject(new Error('Overall analysis timeout')), 120000)
|
|
313
|
+
);
|
|
314
|
+
const analysisResults = await Promise.race([Promise.all(analysisPromises), overallTimeoutPromise]);
|
|
315
|
+
|
|
316
|
+
// 整理结果
|
|
317
|
+
for (const { cliName, result } of analysisResults) {
|
|
318
|
+
results[cliName] = result;
|
|
299
319
|
}
|
|
320
|
+
|
|
300
321
|
return results;
|
|
301
322
|
}
|
|
302
323
|
|
|
@@ -309,6 +330,24 @@ class CLIHelpAnalyzer {
|
|
|
309
330
|
throw new Error(`CLI tool ${cliName} not found in configuration`);
|
|
310
331
|
}
|
|
311
332
|
try {
|
|
333
|
+
// 优化:检查缓存版本,只在版本变化时重新分析
|
|
334
|
+
const cachedAnalysis = await this.getCachedAnalysis(cliName);
|
|
335
|
+
if (cachedAnalysis && cachedAnalysis.success) {
|
|
336
|
+
// 获取当前版本
|
|
337
|
+
const currentVersion = await this.getCurrentVersion(cliName, cliConfig);
|
|
338
|
+
// 如果版本未变化,使用缓存
|
|
339
|
+
if (currentVersion === cachedAnalysis.version && !this.isCacheExpired(cachedAnalysis.timestamp)) {
|
|
340
|
+
if (process.env.DEBUG === 'true') {
|
|
341
|
+
console.log(`[DEBUG] ${cliName}: 使用缓存的分析结果 (版本: ${cachedAnalysis.version})`);
|
|
342
|
+
}
|
|
343
|
+
return cachedAnalysis;
|
|
344
|
+
} else {
|
|
345
|
+
if (process.env.DEBUG === 'true') {
|
|
346
|
+
console.log(`[DEBUG] ${cliName}: 版本变化 (${cachedAnalysis.version} -> ${currentVersion}) 或缓存过期,重新分析`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
312
351
|
// Get help information
|
|
313
352
|
const helpInfo = await this.getHelpInfo(cliName, cliConfig);
|
|
314
353
|
// Detect CLI type
|
|
@@ -368,14 +407,8 @@ class CLIHelpAnalyzer {
|
|
|
368
407
|
}
|
|
369
408
|
|
|
370
409
|
const helpMethods = [
|
|
371
|
-
['--help'],
|
|
372
|
-
['-h'],
|
|
373
|
-
['help'],
|
|
374
|
-
['--usage'],
|
|
375
|
-
[''],
|
|
376
|
-
['version'],
|
|
377
|
-
['--version'],
|
|
378
|
-
['-v'],
|
|
410
|
+
['--help'], // 最常用
|
|
411
|
+
['-h'], // 常用
|
|
379
412
|
];
|
|
380
413
|
let rawHelp = '';
|
|
381
414
|
let version = 'unknown';
|
|
@@ -385,7 +418,7 @@ class CLIHelpAnalyzer {
|
|
|
385
418
|
try {
|
|
386
419
|
const result = spawnSync(cliName, helpArgs, {
|
|
387
420
|
encoding: 'utf8',
|
|
388
|
-
timeout:
|
|
421
|
+
timeout: 5000,
|
|
389
422
|
shell: true,
|
|
390
423
|
});
|
|
391
424
|
if (result.status === 0 && result.stdout) {
|
|
@@ -407,11 +440,10 @@ class CLIHelpAnalyzer {
|
|
|
407
440
|
try {
|
|
408
441
|
const versionCmd = cliConfig.version.split(' ');
|
|
409
442
|
const versionResult = spawnSync(versionCmd[0], versionCmd.slice(1), {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
if (versionResult.status === 0) {
|
|
443
|
+
encoding: 'utf8',
|
|
444
|
+
timeout: 3000, // 优化:减少超时时间从 10 秒到 3 秒
|
|
445
|
+
shell: true,
|
|
446
|
+
}); if (versionResult.status === 0) {
|
|
415
447
|
version = versionResult.stdout.trim() || versionResult.stderr.trim();
|
|
416
448
|
}
|
|
417
449
|
} catch (error) {
|
|
@@ -720,7 +752,23 @@ class CLIHelpAnalyzer {
|
|
|
720
752
|
* Get CLI pattern (wrapper for getCachedAnalysis)
|
|
721
753
|
*/
|
|
722
754
|
async getCLIPattern(cliName) {
|
|
723
|
-
|
|
755
|
+
const cached = await this.getCachedAnalysis(cliName);
|
|
756
|
+
|
|
757
|
+
// 优化:添加版本变化检测
|
|
758
|
+
if (cached && cached.success && cached.timestamp && !this.isCacheExpired(cached.timestamp)) {
|
|
759
|
+
// 检查版本是否变化
|
|
760
|
+
const cliConfig = this.cliTools[cliName];
|
|
761
|
+
if (cliConfig) {
|
|
762
|
+
const currentVersion = await this.getCurrentVersion(cliName, cliConfig);
|
|
763
|
+
// 如果版本未变化,使用缓存
|
|
764
|
+
if (currentVersion === cached.version) {
|
|
765
|
+
return cached;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// 版本变化或缓存过期,重新分析
|
|
771
|
+
return await this.analyzeCLI(cliName);
|
|
724
772
|
}
|
|
725
773
|
|
|
726
774
|
/**
|
|
@@ -775,6 +823,28 @@ class CLIHelpAnalyzer {
|
|
|
775
823
|
}
|
|
776
824
|
}
|
|
777
825
|
|
|
826
|
+
/**
|
|
827
|
+
* Get current CLI version
|
|
828
|
+
*/
|
|
829
|
+
async getCurrentVersion(cliName, cliConfig) {
|
|
830
|
+
try {
|
|
831
|
+
const versionCmd = cliConfig.version || `${cliName} --version`;
|
|
832
|
+
const result = spawnSync(versionCmd.split(' ')[0], versionCmd.split(' ').slice(1), {
|
|
833
|
+
encoding: 'utf8',
|
|
834
|
+
shell: true,
|
|
835
|
+
timeout: 3000,
|
|
836
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
if (result.status === 0) {
|
|
840
|
+
return (result.stdout.trim() || result.stderr.trim()).split('\n')[0];
|
|
841
|
+
}
|
|
842
|
+
return 'unknown';
|
|
843
|
+
} catch (error) {
|
|
844
|
+
return 'unknown';
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
778
848
|
/**
|
|
779
849
|
* Record failed attempt
|
|
780
850
|
*/
|
|
@@ -980,23 +1050,32 @@ class CLIHelpAnalyzer {
|
|
|
980
1050
|
async getEnhancedCLIPattern(cliName) {
|
|
981
1051
|
const cached = await this.getCachedAnalysis(cliName);
|
|
982
1052
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1053
|
+
// 优化:添加版本变化检测
|
|
1054
|
+
if (cached && cached.success && cached.timestamp && !this.isCacheExpired(cached.timestamp)) {
|
|
1055
|
+
// 检查版本是否变化
|
|
1056
|
+
const cliConfig = this.cliTools[cliName];
|
|
1057
|
+
if (cliConfig) {
|
|
1058
|
+
const currentVersion = await this.getCurrentVersion(cliName, cliConfig);
|
|
1059
|
+
// 如果版本未变化,使用缓存
|
|
1060
|
+
if (currentVersion === cached.version) {
|
|
1061
|
+
// Enhance cached data with agent/skill information
|
|
1062
|
+
const enhancedPatterns = this.enhancedPatterns[cliName];
|
|
1063
|
+
if (enhancedPatterns) {
|
|
1064
|
+
cached.agentSkillSupport = {
|
|
1065
|
+
supportsAgents: enhancedPatterns.agentDetection || false,
|
|
1066
|
+
supportsSkills: enhancedPatterns.skillDetection || false,
|
|
1067
|
+
naturalLanguageSupport: enhancedPatterns.naturalLanguageSupport || false,
|
|
1068
|
+
skillPrefixRequired: enhancedPatterns.skillPrefixRequired || false,
|
|
1069
|
+
positionalArgs: enhancedPatterns.positionalArgs || false,
|
|
1070
|
+
agentTypes: enhancedPatterns.agentTypes || [],
|
|
1071
|
+
skillKeywords: enhancedPatterns.skillKeywords || [],
|
|
1072
|
+
commandFormat: enhancedPatterns.commandFormat || '',
|
|
1073
|
+
examples: enhancedPatterns.examples || []
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
return cached;
|
|
1077
|
+
}
|
|
998
1078
|
}
|
|
999
|
-
return cached;
|
|
1000
1079
|
}
|
|
1001
1080
|
|
|
1002
1081
|
// Perform enhanced analysis
|
package/src/core/cli_tools.js
CHANGED
|
@@ -649,38 +649,36 @@ async function checkInstallation(toolName) {
|
|
|
649
649
|
}
|
|
650
650
|
|
|
651
651
|
// Check if the tool is actually executable, not just if the path exists
|
|
652
|
-
//
|
|
653
|
-
const isExecutable = true;
|
|
654
|
-
const installed = !!toolPath && isExecutable;
|
|
655
|
-
|
|
652
|
+
// 优化:合并可执行性测试和版本检查,只执行一次命令
|
|
656
653
|
let version = null;
|
|
657
|
-
|
|
654
|
+
let isExecutable = false;
|
|
655
|
+
|
|
656
|
+
if (toolPath) {
|
|
658
657
|
try {
|
|
659
658
|
const { spawnSync } = require('child_process');
|
|
660
659
|
const toolConfig = CLI_TOOLS[toolName];
|
|
661
660
|
const versionCmd = toolConfig.version || `${toolName} --version`;
|
|
662
661
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
encoding: 'utf8',
|
|
670
|
-
shell: true,
|
|
671
|
-
timeout: 3000,
|
|
672
|
-
stdio: ['ignore', 'pipe', 'pipe']
|
|
673
|
-
});
|
|
662
|
+
const result = spawnSync(versionCmd.split(' ')[0], versionCmd.split(' ').slice(1), {
|
|
663
|
+
encoding: 'utf8',
|
|
664
|
+
shell: true,
|
|
665
|
+
timeout: 5000,
|
|
666
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
667
|
+
});
|
|
674
668
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
669
|
+
// 如果版本检查成功,说明 CLI 可执行
|
|
670
|
+
isExecutable = result.status === 0;
|
|
671
|
+
|
|
672
|
+
if (isExecutable) {
|
|
673
|
+
version = result.stdout.trim() || result.stderr.trim();
|
|
678
674
|
}
|
|
679
675
|
} catch (error) {
|
|
680
|
-
|
|
676
|
+
isExecutable = false;
|
|
681
677
|
}
|
|
682
678
|
}
|
|
683
679
|
|
|
680
|
+
const installed = !!toolPath && isExecutable;
|
|
681
|
+
|
|
684
682
|
return {
|
|
685
683
|
installed,
|
|
686
684
|
path: toolPath,
|