stigmergy 1.2.13 → 1.3.1-beta
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/README.md +39 -3
- package/STIGMERGY.md +3 -0
- package/config/builtin-skills.json +43 -0
- package/config/enhanced-cli-config.json +438 -0
- package/docs/CLI_TOOLS_AGENT_SKILL_ANALYSIS.md +463 -0
- package/docs/DESIGN_CLI_HELP_ANALYZER_REFACTOR.md +726 -0
- package/docs/ENHANCED_CLI_AGENT_SKILL_CONFIG.md +285 -0
- package/docs/IMPLEMENTATION_CHECKLIST_CLI_HELP_ANALYZER_REFACTOR.md +1268 -0
- package/docs/INSTALLER_ARCHITECTURE.md +257 -0
- package/docs/LESSONS_LEARNED.md +252 -0
- package/docs/SPECS_CLI_HELP_ANALYZER_REFACTOR.md +287 -0
- package/docs/SUDO_PROBLEM_AND_SOLUTION.md +529 -0
- package/docs/correct-skillsio-implementation.md +368 -0
- package/docs/development_guidelines.md +276 -0
- package/docs/independent-resume-implementation.md +198 -0
- package/docs/resumesession-final-implementation.md +195 -0
- package/docs/resumesession-usage.md +87 -0
- package/package.json +19 -9
- package/scripts/analyze-router.js +168 -0
- package/scripts/run-comprehensive-tests.js +230 -0
- package/scripts/run-quick-tests.js +90 -0
- package/scripts/test-runner.js +344 -0
- package/skills/resumesession/INDEPENDENT_SKILL.md +171 -0
- package/skills/resumesession/SKILL.md +127 -0
- package/skills/resumesession/__init__.py +33 -0
- package/skills/resumesession/implementations/simple-resume.js +13 -0
- package/src/adapters/claude/install_claude_integration.js +9 -1
- package/src/adapters/codebuddy/install_codebuddy_integration.js +3 -1
- package/src/adapters/codex/install_codex_integration.js +15 -5
- package/src/adapters/gemini/install_gemini_integration.js +3 -1
- package/src/adapters/qwen/install_qwen_integration.js +3 -1
- package/src/cli/commands/autoinstall.js +65 -0
- package/src/cli/commands/errors.js +190 -0
- package/src/cli/commands/independent-resume.js +395 -0
- package/src/cli/commands/install.js +179 -0
- package/src/cli/commands/permissions.js +108 -0
- package/src/cli/commands/project.js +485 -0
- package/src/cli/commands/scan.js +97 -0
- package/src/cli/commands/simple-resume.js +377 -0
- package/src/cli/commands/skills.js +158 -0
- package/src/cli/commands/status.js +113 -0
- package/src/cli/commands/stigmergy-resume.js +775 -0
- package/src/cli/commands/system.js +301 -0
- package/src/cli/commands/universal-resume.js +394 -0
- package/src/cli/router-beta.js +471 -0
- package/src/cli/utils/environment.js +75 -0
- package/src/cli/utils/formatters.js +47 -0
- package/src/cli/utils/skills_cache.js +92 -0
- package/src/core/cache_cleaner.js +1 -0
- package/src/core/cli_adapters.js +345 -0
- package/src/core/cli_help_analyzer.js +582 -26
- package/src/core/cli_path_detector.js +702 -709
- package/src/core/cli_tools.js +515 -160
- package/src/core/coordination/nodejs/CLIIntegrationManager.js +18 -0
- package/src/core/coordination/nodejs/HookDeploymentManager.js +242 -412
- package/src/core/coordination/nodejs/HookDeploymentManager.refactored.js +323 -0
- package/src/core/coordination/nodejs/generators/CLIAdapterGenerator.js +363 -0
- package/src/core/coordination/nodejs/generators/ResumeSessionGenerator.js +932 -0
- package/src/core/coordination/nodejs/generators/SkillsIntegrationGenerator.js +1395 -0
- package/src/core/coordination/nodejs/generators/index.js +12 -0
- package/src/core/enhanced_cli_installer.js +1208 -608
- package/src/core/enhanced_cli_parameter_handler.js +402 -0
- package/src/core/execution_mode_detector.js +222 -0
- package/src/core/installer.js +151 -106
- package/src/core/local_skill_scanner.js +732 -0
- package/src/core/multilingual/language-pattern-manager.js +1 -1
- package/src/core/skills/BuiltinSkillsDeployer.js +188 -0
- package/src/core/skills/StigmergySkillManager.js +123 -16
- package/src/core/skills/embedded-openskills/SkillParser.js +7 -3
- package/src/core/smart_router.js +291 -2
- package/src/index.js +10 -4
- package/src/utils.js +66 -7
- package/test/cli-integration.test.js +304 -0
- package/test/direct_smart_router_test.js +88 -0
- package/test/enhanced-cli-agent-skill-test.js +485 -0
- package/test/simple_test.js +82 -0
- package/test/smart_router_test_runner.js +123 -0
- package/test/smart_routing_edge_cases.test.js +284 -0
- package/test/smart_routing_simple_verification.js +139 -0
- package/test/smart_routing_verification.test.js +346 -0
- package/test/specific-cli-agent-skill-analysis.js +385 -0
- package/test/unit/smart_router.test.js +295 -0
- package/test/very_simple_test.js +54 -0
- package/src/cli/router.js +0 -1783
|
@@ -1,4 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced CLI Help Analyzer with better pattern extraction
|
|
3
|
+
*
|
|
4
|
+
* 📚 参考文档:
|
|
5
|
+
* - 重构文档:REFACTORING_CLI_HELP_ANALYZER.md
|
|
6
|
+
* - 实现清单:IMPLEMENTATION_CHECKLIST_CLI_HELP_ANALYZER_REFACTOR.md
|
|
7
|
+
* - 设计文档:DESIGN_CLI_HELP_ANALYZER_REFACTOR.md
|
|
8
|
+
* - 规格说明:SPECS_CLI_HELP_ANALYZER_REFACTOR.md
|
|
9
|
+
*
|
|
10
|
+
* 🎯 重构说明(v1.4.0):
|
|
11
|
+
* - 统一 analyzeCLI() 入口点,支持 options 参数
|
|
12
|
+
* - 提取 addEnhancedInfo() 方法,实现不可变对象模式
|
|
13
|
+
* - 简化包装器方法(getCLIPattern, getEnhancedCLIPattern, analyzeCLIEnhanced)
|
|
14
|
+
* - 所有方法保持向后兼容,已添加 @deprecated 注释
|
|
15
|
+
*
|
|
16
|
+
* 🧪 测试覆盖:36/36 测试通过(23单元测试 + 13集成测试)
|
|
17
|
+
*/
|
|
2
18
|
const { spawnSync } = require('child_process');
|
|
3
19
|
const fs = require('fs/promises');
|
|
4
20
|
const path = require('path');
|
|
@@ -13,6 +29,180 @@ class CLIHelpAnalyzer {
|
|
|
13
29
|
this.lastAnalysisFile = path.join(this.configDir, 'last-analysis.json');
|
|
14
30
|
this.cliTools = CLI_TOOLS;
|
|
15
31
|
|
|
32
|
+
// Enhanced CLI Agent and Skill Patterns Configuration
|
|
33
|
+
this.enhancedPatterns = {
|
|
34
|
+
'claude': {
|
|
35
|
+
commandFormat: 'claude -p "{prompt}"',
|
|
36
|
+
agentDetection: true,
|
|
37
|
+
skillDetection: true,
|
|
38
|
+
naturalLanguageSupport: true,
|
|
39
|
+
agentTypes: ['expert', 'skill', 'analysis', 'agent'],
|
|
40
|
+
skillKeywords: ['技能', '智能体', '分析', '工具', '方法'],
|
|
41
|
+
examples: [
|
|
42
|
+
'claude -p "请使用异化分析技能分析程序员异化现象"',
|
|
43
|
+
'claude -p "请使用数字马克思智能体进行阶级分析"'
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
'iflow': {
|
|
47
|
+
commandFormat: 'iflow -p "{prompt}"',
|
|
48
|
+
agentDetection: true,
|
|
49
|
+
skillDetection: true,
|
|
50
|
+
naturalLanguageSupport: true,
|
|
51
|
+
agentTypes: ['expert', 'skill', 'analysis', 'agent'],
|
|
52
|
+
skillKeywords: ['技能', '智能体', '分析', '工具', '方法'],
|
|
53
|
+
examples: [
|
|
54
|
+
'iflow -p "请使用异化分析技能分析程序员异化现象"',
|
|
55
|
+
'iflow -p "请使用数字马克思智能体进行异化分析"'
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
'qwen': {
|
|
59
|
+
commandFormat: 'qwen "{prompt}"',
|
|
60
|
+
agentDetection: true,
|
|
61
|
+
skillDetection: true,
|
|
62
|
+
naturalLanguageSupport: true,
|
|
63
|
+
positionalArgs: true,
|
|
64
|
+
agentTypes: ['expert', 'skill', 'analysis', 'agent'],
|
|
65
|
+
skillKeywords: ['智能体', '分析技能', '马克思', '异化', '阶级'],
|
|
66
|
+
examples: [
|
|
67
|
+
'qwen "使用数字马克思智能体进行异化分析,分析程序员的技术异化现象"',
|
|
68
|
+
'qwen "使用异化分析技能分析程序员在AI开发中的异化现象"'
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
'codebuddy': {
|
|
72
|
+
commandFormat: 'codebuddy -y -p "{prompt}"',
|
|
73
|
+
agentDetection: false,
|
|
74
|
+
skillDetection: true,
|
|
75
|
+
skillPrefixRequired: true,
|
|
76
|
+
agentTypes: ['skill'],
|
|
77
|
+
skillKeywords: ['skill:', '技能', '分析'],
|
|
78
|
+
examples: [
|
|
79
|
+
'codebuddy -y -p "skill:alienation-analysis 分析程序员异化现象"',
|
|
80
|
+
'codebuddy -y -p "skill:marxist-analysis 分析技术异化"'
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
'qodercli': {
|
|
84
|
+
commandFormat: 'qodercli -p "{prompt}"',
|
|
85
|
+
agentDetection: false,
|
|
86
|
+
skillDetection: false,
|
|
87
|
+
basicAISupport: true,
|
|
88
|
+
agentTypes: ['basic'],
|
|
89
|
+
skillKeywords: ['分析', '理解'],
|
|
90
|
+
examples: [
|
|
91
|
+
'qodercli -p "分析程序员在AI开发中的异化现象"',
|
|
92
|
+
'qodercli -p "进行技术异化的基础分析"'
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
'gemini': {
|
|
96
|
+
commandFormat: 'gemini -p "{prompt}"',
|
|
97
|
+
agentDetection: true,
|
|
98
|
+
skillDetection: true,
|
|
99
|
+
naturalLanguageSupport: true,
|
|
100
|
+
agentTypes: ['expert', 'skill', 'analysis', 'agent'],
|
|
101
|
+
skillKeywords: ['技能', '智能体', '分析', '工具', '方法'],
|
|
102
|
+
examples: [
|
|
103
|
+
'gemini -p "请使用分析技能分析程序员异化现象"',
|
|
104
|
+
'gemini -p "使用智能体进行技术分析"'
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
'copilot': {
|
|
108
|
+
commandFormat: 'copilot "{prompt}"',
|
|
109
|
+
agentDetection: true,
|
|
110
|
+
skillDetection: true,
|
|
111
|
+
naturalLanguageSupport: true,
|
|
112
|
+
positionalArgs: true,
|
|
113
|
+
agentTypes: ['expert', 'skill', 'analysis', 'agent'],
|
|
114
|
+
skillKeywords: ['技能', '智能体', '分析', '工具', '方法'],
|
|
115
|
+
examples: [
|
|
116
|
+
'copilot "请使用分析技能分析程序员异化现象"',
|
|
117
|
+
'copilot "使用智能体进行技术分析"'
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
'codex': {
|
|
121
|
+
commandFormat: 'codex -m gpt-5 "{prompt}"',
|
|
122
|
+
agentDetection: true,
|
|
123
|
+
skillDetection: true,
|
|
124
|
+
naturalLanguageSupport: true,
|
|
125
|
+
positionalArgs: true,
|
|
126
|
+
agentTypes: ['expert', 'skill', 'analysis', 'agent'],
|
|
127
|
+
skillKeywords: ['技能', '智能体', '分析', '工具', '方法', '代码', '审查'],
|
|
128
|
+
examples: [
|
|
129
|
+
'codex "请使用异化分析技能分析程序员异化现象"',
|
|
130
|
+
'codex exec "使用数字马克思智能体分析代码库"',
|
|
131
|
+
'codex review "分析这段代码的异化现象"'
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
'kode': {
|
|
135
|
+
commandFormat: 'kode -p "{prompt}"',
|
|
136
|
+
agentDetection: true,
|
|
137
|
+
skillDetection: true,
|
|
138
|
+
naturalLanguageSupport: true,
|
|
139
|
+
positionalArgs: true,
|
|
140
|
+
agentTypes: ['expert', 'skill', 'analysis', 'agent'],
|
|
141
|
+
skillKeywords: ['技能', '智能体', '分析', '工具', '方法', '多模型', '协作'],
|
|
142
|
+
examples: [
|
|
143
|
+
'kode -p "请使用异化分析技能分析程序员异化现象"',
|
|
144
|
+
'kode -p "使用数字马克思智能体进行异化分析"',
|
|
145
|
+
'kode -p "@ask-claude-sonnet-4 分析这个问题"'
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Agent and Skill Recognition Patterns
|
|
151
|
+
this.agentSkillPatterns = {
|
|
152
|
+
// Agent type detection patterns
|
|
153
|
+
agentTypes: {
|
|
154
|
+
'expert': ['专家', 'expert', 'specialist', '马克思', 'marxist', '数字马克思'],
|
|
155
|
+
'skill': ['技能', 'skill', '能力', '方法', '工具'],
|
|
156
|
+
'analysis': ['分析', 'analysis', '解析', '评估'],
|
|
157
|
+
'agent': ['智能体', 'agent', '助手', '助手'],
|
|
158
|
+
'basic': ['基础', 'basic', '简单', '初步']
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
// Skill name patterns for different CLIs
|
|
162
|
+
skillMapping: {
|
|
163
|
+
'异化分析': {
|
|
164
|
+
'claude': '异化分析技能',
|
|
165
|
+
'iflow': '异化分析技能',
|
|
166
|
+
'qwen': '异化分析技能',
|
|
167
|
+
'codebuddy': 'alienation-analysis',
|
|
168
|
+
'gemini': '异化分析技能',
|
|
169
|
+
'copilot': '异化分析技能',
|
|
170
|
+
'codex': 'alienation-analysis',
|
|
171
|
+
'kode': '异化分析技能'
|
|
172
|
+
},
|
|
173
|
+
'马克思分析': {
|
|
174
|
+
'claude': '数字马克思智能体',
|
|
175
|
+
'iflow': '数字马克思智能体',
|
|
176
|
+
'qwen': '数字马克思智能体',
|
|
177
|
+
'codebuddy': 'marxist-analysis',
|
|
178
|
+
'gemini': '马克思分析技能',
|
|
179
|
+
'copilot': '马克思分析智能体',
|
|
180
|
+
'codex': 'marxist-analysis',
|
|
181
|
+
'kode': '数字马克思智能体'
|
|
182
|
+
},
|
|
183
|
+
'技术分析': {
|
|
184
|
+
'claude': '技术分析技能',
|
|
185
|
+
'iflow': '技术分析技能',
|
|
186
|
+
'qwen': '技术分析技能',
|
|
187
|
+
'codebuddy': 'tech-analysis',
|
|
188
|
+
'gemini': '技术分析技能',
|
|
189
|
+
'copilot': '技术分析技能',
|
|
190
|
+
'codex': 'tech-analysis',
|
|
191
|
+
'kode': '技术分析技能'
|
|
192
|
+
},
|
|
193
|
+
'阶级分析': {
|
|
194
|
+
'claude': '阶级分析技能',
|
|
195
|
+
'iflow': '阶级分析技能',
|
|
196
|
+
'qwen': '阶级分析技能',
|
|
197
|
+
'codebuddy': 'class-analysis',
|
|
198
|
+
'gemini': '阶级分析技能',
|
|
199
|
+
'copilot': '阶级分析技能',
|
|
200
|
+
'codex': 'class-analysis',
|
|
201
|
+
'kode': '阶级分析技能'
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
16
206
|
// Pattern recognition rules for different CLI types
|
|
17
207
|
this.patternRules = {
|
|
18
208
|
// OpenAI style CLI (codex, chatgpt)
|
|
@@ -95,16 +285,28 @@ class CLIHelpAnalyzer {
|
|
|
95
285
|
}
|
|
96
286
|
|
|
97
287
|
/**
|
|
98
|
-
*
|
|
288
|
+
* 分析所有配置的CLI工具
|
|
289
|
+
* @param {Object} options - 分析选项
|
|
290
|
+
* @param {boolean} options.enhanced - 是否返回增强信息
|
|
291
|
+
* @param {boolean} options.forceRefresh - 是否强制刷新缓存
|
|
292
|
+
* @returns {Promise<Object>} 所有CLI的分析结果
|
|
99
293
|
*/
|
|
100
|
-
async analyzeAllCLI() {
|
|
294
|
+
async analyzeAllCLI(options = {}) {
|
|
101
295
|
const results = {};
|
|
102
|
-
|
|
296
|
+
const cliNames = Object.keys(this.cliTools);
|
|
297
|
+
|
|
298
|
+
// 优化:并行分析所有 CLI,添加超时保护
|
|
299
|
+
const analysisPromises = cliNames.map(async (cliName) => {
|
|
103
300
|
try {
|
|
104
301
|
if (process.env.DEBUG === 'true') {
|
|
105
302
|
console.log(`Analyzing ${cliName}...`);
|
|
106
303
|
}
|
|
107
|
-
|
|
304
|
+
// 添加超时保护,单个 CLI 分析最多 60 秒(因为需要尝试多个 help 方法)
|
|
305
|
+
const timeoutPromise = new Promise((_, reject) =>
|
|
306
|
+
setTimeout(() => reject(new Error('Analysis timeout')), 60000)
|
|
307
|
+
);
|
|
308
|
+
const result = await Promise.race([this.analyzeCLI(cliName, options), timeoutPromise]);
|
|
309
|
+
return { cliName, result };
|
|
108
310
|
} catch (error) {
|
|
109
311
|
// Only log important errors, suppress expected file not found errors
|
|
110
312
|
if (
|
|
@@ -112,7 +314,8 @@ class CLIHelpAnalyzer {
|
|
|
112
314
|
!error.message.includes('no such file or directory') &&
|
|
113
315
|
!error.message.includes(
|
|
114
316
|
'not recognized as an internal or external command',
|
|
115
|
-
)
|
|
317
|
+
) &&
|
|
318
|
+
!error.message.includes('Analysis timeout')
|
|
116
319
|
) {
|
|
117
320
|
await errorHandler.logError(
|
|
118
321
|
error,
|
|
@@ -120,21 +323,64 @@ class CLIHelpAnalyzer {
|
|
|
120
323
|
`CLIHelpAnalyzer.analyzeAllCLI.${cliName}`,
|
|
121
324
|
);
|
|
122
325
|
}
|
|
123
|
-
|
|
326
|
+
return { cliName, result: { success: false, error: error.message } };
|
|
124
327
|
}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// 等待所有分析完成,添加整体超时保护
|
|
331
|
+
const overallTimeoutPromise = new Promise((_, reject) =>
|
|
332
|
+
setTimeout(() => reject(new Error('Overall analysis timeout')), 120000)
|
|
333
|
+
);
|
|
334
|
+
const analysisResults = await Promise.race([Promise.all(analysisPromises), overallTimeoutPromise]);
|
|
335
|
+
|
|
336
|
+
// 整理结果
|
|
337
|
+
for (const { cliName, result } of analysisResults) {
|
|
338
|
+
results[cliName] = result;
|
|
125
339
|
}
|
|
340
|
+
|
|
126
341
|
return results;
|
|
127
342
|
}
|
|
128
343
|
|
|
129
344
|
/**
|
|
130
|
-
*
|
|
345
|
+
* 分析CLI工具
|
|
346
|
+
* @param {string} cliName - CLI工具名称
|
|
347
|
+
* @param {Object} options - 分析选项
|
|
348
|
+
* @param {boolean} options.enhanced - 是否返回增强信息
|
|
349
|
+
* @param {boolean} options.forceRefresh - 是否强制刷新缓存
|
|
350
|
+
* @returns {Promise<Object>} 分析结果
|
|
131
351
|
*/
|
|
132
|
-
async analyzeCLI(cliName) {
|
|
352
|
+
async analyzeCLI(cliName, options = {}) {
|
|
353
|
+
const { enhanced = false, forceRefresh = false } = options;
|
|
133
354
|
const cliConfig = this.cliTools[cliName];
|
|
134
355
|
if (!cliConfig) {
|
|
135
356
|
throw new Error(`CLI tool ${cliName} not found in configuration`);
|
|
136
357
|
}
|
|
137
358
|
try {
|
|
359
|
+
// 检查是否强制刷新
|
|
360
|
+
if (!forceRefresh) {
|
|
361
|
+
// 优化:检查缓存版本,只在版本变化时重新分析
|
|
362
|
+
const cachedAnalysis = await this.getCachedAnalysis(cliName);
|
|
363
|
+
if (cachedAnalysis && cachedAnalysis.success) {
|
|
364
|
+
// 获取当前版本
|
|
365
|
+
const currentVersion = await this.getCurrentVersion(cliName, cliConfig);
|
|
366
|
+
// 如果版本未变化,使用缓存
|
|
367
|
+
if (currentVersion === cachedAnalysis.version && !this.isCacheExpired(cachedAnalysis.timestamp)) {
|
|
368
|
+
if (process.env.DEBUG === 'true') {
|
|
369
|
+
console.log(`[DEBUG] ${cliName}: 使用缓存的分析结果 (版本: ${cachedAnalysis.version})`);
|
|
370
|
+
}
|
|
371
|
+
// 添加增强信息
|
|
372
|
+
if (enhanced) {
|
|
373
|
+
return this.addEnhancedInfo(cachedAnalysis, cliName);
|
|
374
|
+
}
|
|
375
|
+
return cachedAnalysis;
|
|
376
|
+
} else {
|
|
377
|
+
if (process.env.DEBUG === 'true') {
|
|
378
|
+
console.log(`[DEBUG] ${cliName}: 版本变化 (${cachedAnalysis.version} -> ${currentVersion}) 或缓存过期,重新分析`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
138
384
|
// Get help information
|
|
139
385
|
const helpInfo = await this.getHelpInfo(cliName, cliConfig);
|
|
140
386
|
// Detect CLI type
|
|
@@ -161,6 +407,10 @@ class CLIHelpAnalyzer {
|
|
|
161
407
|
};
|
|
162
408
|
// Cache the analysis
|
|
163
409
|
await this.cacheAnalysis(cliName, analysis);
|
|
410
|
+
// 添加增强信息
|
|
411
|
+
if (enhanced) {
|
|
412
|
+
return this.addEnhancedInfo(analysis, cliName);
|
|
413
|
+
}
|
|
164
414
|
return analysis;
|
|
165
415
|
} catch (error) {
|
|
166
416
|
// Record failed attempt but suppress error if it's an expected issue
|
|
@@ -184,6 +434,33 @@ class CLIHelpAnalyzer {
|
|
|
184
434
|
}
|
|
185
435
|
}
|
|
186
436
|
|
|
437
|
+
/**
|
|
438
|
+
* 添加增强信息
|
|
439
|
+
* @param {Object} analysis - 基础分析结果
|
|
440
|
+
* @param {string} cliName - CLI工具名称
|
|
441
|
+
* @returns {Object} 增强分析结果
|
|
442
|
+
* @重要说明:必须返回新对象,不能修改原对象
|
|
443
|
+
*/
|
|
444
|
+
addEnhancedInfo(analysis, cliName) {
|
|
445
|
+
const enhancedPatterns = this.enhancedPatterns[cliName] || {};
|
|
446
|
+
|
|
447
|
+
// 使用展开运算符创建新对象,不修改原对象
|
|
448
|
+
return {
|
|
449
|
+
...analysis,
|
|
450
|
+
agentSkillSupport: {
|
|
451
|
+
supportsAgents: enhancedPatterns.agentDetection || false,
|
|
452
|
+
supportsSkills: enhancedPatterns.skillDetection || false,
|
|
453
|
+
naturalLanguageSupport: enhancedPatterns.naturalLanguageSupport || false,
|
|
454
|
+
skillPrefixRequired: enhancedPatterns.skillPrefixRequired || false,
|
|
455
|
+
positionalArgs: enhancedPatterns.positionalArgs || false,
|
|
456
|
+
agentTypes: enhancedPatterns.agentTypes || [],
|
|
457
|
+
skillKeywords: enhancedPatterns.skillKeywords || [],
|
|
458
|
+
commandFormat: enhancedPatterns.commandFormat || "",
|
|
459
|
+
examples: enhancedPatterns.examples || []
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
187
464
|
/**
|
|
188
465
|
* Get help information using multiple methods
|
|
189
466
|
*/
|
|
@@ -194,14 +471,8 @@ class CLIHelpAnalyzer {
|
|
|
194
471
|
}
|
|
195
472
|
|
|
196
473
|
const helpMethods = [
|
|
197
|
-
['--help'],
|
|
198
|
-
['-h'],
|
|
199
|
-
['help'],
|
|
200
|
-
['--usage'],
|
|
201
|
-
[''],
|
|
202
|
-
['version'],
|
|
203
|
-
['--version'],
|
|
204
|
-
['-v'],
|
|
474
|
+
['--help'], // 最常用
|
|
475
|
+
['-h'], // 常用
|
|
205
476
|
];
|
|
206
477
|
let rawHelp = '';
|
|
207
478
|
let version = 'unknown';
|
|
@@ -211,7 +482,7 @@ class CLIHelpAnalyzer {
|
|
|
211
482
|
try {
|
|
212
483
|
const result = spawnSync(cliName, helpArgs, {
|
|
213
484
|
encoding: 'utf8',
|
|
214
|
-
timeout:
|
|
485
|
+
timeout: 5000,
|
|
215
486
|
shell: true,
|
|
216
487
|
});
|
|
217
488
|
if (result.status === 0 && result.stdout) {
|
|
@@ -233,11 +504,10 @@ class CLIHelpAnalyzer {
|
|
|
233
504
|
try {
|
|
234
505
|
const versionCmd = cliConfig.version.split(' ');
|
|
235
506
|
const versionResult = spawnSync(versionCmd[0], versionCmd.slice(1), {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (versionResult.status === 0) {
|
|
507
|
+
encoding: 'utf8',
|
|
508
|
+
timeout: 3000, // 优化:减少超时时间从 10 秒到 3 秒
|
|
509
|
+
shell: true,
|
|
510
|
+
}); if (versionResult.status === 0) {
|
|
241
511
|
version = versionResult.stdout.trim() || versionResult.stderr.trim();
|
|
242
512
|
}
|
|
243
513
|
} catch (error) {
|
|
@@ -403,7 +673,10 @@ class CLIHelpAnalyzer {
|
|
|
403
673
|
option.includes('non-interactive') ||
|
|
404
674
|
option.includes('batch') ||
|
|
405
675
|
option.includes('no-input') ||
|
|
406
|
-
option.includes('stdin')
|
|
676
|
+
option.includes('stdin') ||
|
|
677
|
+
option.includes('print') || // For CLI tools like kode with --print flag
|
|
678
|
+
option.includes('pipe') || // Pipes mentioned in description
|
|
679
|
+
option.includes('exit'), // Exit after execution
|
|
407
680
|
);
|
|
408
681
|
patterns.nonInteractiveFlag =
|
|
409
682
|
nonInteractiveFlags.length > 0 ? nonInteractiveFlags[0] : null;
|
|
@@ -540,10 +813,13 @@ class CLIHelpAnalyzer {
|
|
|
540
813
|
}
|
|
541
814
|
|
|
542
815
|
/**
|
|
543
|
-
*
|
|
816
|
+
* 获取CLI模式(包装器方法)
|
|
817
|
+
* @deprecated 此方法已弃用,请使用 analyzeCLI(cliName, { enhanced: false }) 代替
|
|
818
|
+
* @param {string} cliName - CLI工具名称
|
|
819
|
+
* @returns {Promise<Object>} 分析结果
|
|
544
820
|
*/
|
|
545
821
|
async getCLIPattern(cliName) {
|
|
546
|
-
return await this.
|
|
822
|
+
return await this.analyzeCLI(cliName, { enhanced: false });
|
|
547
823
|
}
|
|
548
824
|
|
|
549
825
|
/**
|
|
@@ -598,6 +874,28 @@ class CLIHelpAnalyzer {
|
|
|
598
874
|
}
|
|
599
875
|
}
|
|
600
876
|
|
|
877
|
+
/**
|
|
878
|
+
* Get current CLI version
|
|
879
|
+
*/
|
|
880
|
+
async getCurrentVersion(cliName, cliConfig) {
|
|
881
|
+
try {
|
|
882
|
+
const versionCmd = cliConfig.version || `${cliName} --version`;
|
|
883
|
+
const result = spawnSync(versionCmd.split(' ')[0], versionCmd.split(' ').slice(1), {
|
|
884
|
+
encoding: 'utf8',
|
|
885
|
+
shell: true,
|
|
886
|
+
timeout: 3000,
|
|
887
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
if (result.status === 0) {
|
|
891
|
+
return (result.stdout.trim() || result.stderr.trim()).split('\n')[0];
|
|
892
|
+
}
|
|
893
|
+
return 'unknown';
|
|
894
|
+
} catch (error) {
|
|
895
|
+
return 'unknown';
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
601
899
|
/**
|
|
602
900
|
* Record failed attempt
|
|
603
901
|
*/
|
|
@@ -675,6 +973,264 @@ class CLIHelpAnalyzer {
|
|
|
675
973
|
setCLITools(tools) {
|
|
676
974
|
this.cliTools = tools;
|
|
677
975
|
}
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* 增强分析,包含智能体和技能检测(包装器方法)
|
|
979
|
+
* @deprecated 此方法已弃用,请使用 analyzeCLI(cliName, { enhanced: true }) 代替
|
|
980
|
+
* @param {string} cliName - CLI工具名称
|
|
981
|
+
* @returns {Promise<Object>} 增强分析结果
|
|
982
|
+
*/
|
|
983
|
+
async analyzeCLIEnhanced(cliName) {
|
|
984
|
+
return await this.analyzeCLI(cliName, { enhanced: true });
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
/**
|
|
988
|
+
* Detect agent and skill mentions in user input
|
|
989
|
+
*/
|
|
990
|
+
detectAgentSkillMentions(input, cliName) {
|
|
991
|
+
const enhancedPattern = this.enhancedPatterns[cliName];
|
|
992
|
+
if (!enhancedPattern) {
|
|
993
|
+
return { hasAgent: false, hasSkill: false, confidence: 0 };
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
const inputLower = input.toLowerCase();
|
|
997
|
+
let hasAgent = false;
|
|
998
|
+
let hasSkill = false;
|
|
999
|
+
let confidence = 0;
|
|
1000
|
+
|
|
1001
|
+
// Check for agent keywords
|
|
1002
|
+
if (enhancedPattern.agentDetection) {
|
|
1003
|
+
const agentKeywords = [
|
|
1004
|
+
...this.agentSkillPatterns.agentTypes['expert'],
|
|
1005
|
+
...this.agentSkillPatterns.agentTypes['agent'],
|
|
1006
|
+
...enhancedPattern.skillKeywords
|
|
1007
|
+
];
|
|
1008
|
+
|
|
1009
|
+
for (const keyword of agentKeywords) {
|
|
1010
|
+
if (inputLower.includes(keyword.toLowerCase())) {
|
|
1011
|
+
hasAgent = true;
|
|
1012
|
+
confidence += 0.3;
|
|
1013
|
+
break;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// Check for skill keywords
|
|
1019
|
+
if (enhancedPattern.skillDetection) {
|
|
1020
|
+
const skillKeywords = enhancedPattern.skillKeywords;
|
|
1021
|
+
|
|
1022
|
+
for (const keyword of skillKeywords) {
|
|
1023
|
+
if (inputLower.includes(keyword.toLowerCase())) {
|
|
1024
|
+
hasSkill = true;
|
|
1025
|
+
confidence += 0.4;
|
|
1026
|
+
break;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
// Special check for skill: prefix (codebuddy)
|
|
1031
|
+
if (enhancedPattern.skillPrefixRequired && inputLower.includes('skill:')) {
|
|
1032
|
+
hasSkill = true;
|
|
1033
|
+
confidence += 0.6;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// Boost confidence based on CLI-specific patterns
|
|
1038
|
+
if (cliName === 'qwen' && enhancedPattern.positionalArgs) {
|
|
1039
|
+
// Qwen CLI has higher confidence for natural language
|
|
1040
|
+
confidence *= 1.2;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
return { hasAgent, hasSkill, confidence: Math.min(confidence, 1.0) };
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* Optimize prompt for specific CLI tool
|
|
1048
|
+
*/
|
|
1049
|
+
optimizePromptForCLI(prompt, cliName, detectedMentions) {
|
|
1050
|
+
const enhancedPattern = this.enhancedPatterns[cliName];
|
|
1051
|
+
if (!enhancedPattern) {
|
|
1052
|
+
return prompt;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
let optimizedPrompt = prompt;
|
|
1056
|
+
|
|
1057
|
+
// Apply skill mapping if applicable
|
|
1058
|
+
for (const [chineseSkill, mapping] of Object.entries(this.agentSkillPatterns.skillMapping)) {
|
|
1059
|
+
if (prompt.includes(chineseSkill) && mapping[cliName]) {
|
|
1060
|
+
if (enhancedPattern.skillPrefixRequired && !prompt.includes('skill:')) {
|
|
1061
|
+
// For codebuddy, add skill: prefix
|
|
1062
|
+
optimizedPrompt = prompt.replace(
|
|
1063
|
+
chineseSkill,
|
|
1064
|
+
`skill:${mapping[cliName]}`
|
|
1065
|
+
);
|
|
1066
|
+
} else if (enhancedPattern.naturalLanguageSupport) {
|
|
1067
|
+
// For CLIs that support natural language, use the mapped term
|
|
1068
|
+
optimizedPrompt = prompt.replace(
|
|
1069
|
+
chineseSkill,
|
|
1070
|
+
mapping[cliName]
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
break;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
return optimizedPrompt;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* 获取增强CLI模式,包含智能体/技能支持(包装器方法)
|
|
1082
|
+
* @deprecated 此方法已弃用,请使用 analyzeCLI(cliName, { enhanced: true }) 代替
|
|
1083
|
+
* @param {string} cliName - CLI工具名称
|
|
1084
|
+
* @returns {Promise<Object>} 增强分析结果
|
|
1085
|
+
*/
|
|
1086
|
+
async getEnhancedCLIPattern(cliName) {
|
|
1087
|
+
return await this.analyzeCLI(cliName, { enhanced: true });
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* Analyze call success and update patterns accordingly
|
|
1092
|
+
*/
|
|
1093
|
+
async updatePatternOnAgentSkillFailure(cliName, error, attemptedCommand, userPrompt) {
|
|
1094
|
+
if (process.env.DEBUG === 'true') {
|
|
1095
|
+
console.log(`Updating agent/skill pattern for ${cliName} due to failure:`, error.message);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
try {
|
|
1099
|
+
// Re-analyze with enhanced capabilities
|
|
1100
|
+
const newAnalysis = await this.analyzeCLIEnhanced(cliName);
|
|
1101
|
+
|
|
1102
|
+
// Add failure context with agent/skill information
|
|
1103
|
+
const detectedMentions = this.detectAgentSkillMentions(userPrompt, cliName);
|
|
1104
|
+
newAnalysis.lastFailure = {
|
|
1105
|
+
error: error.message,
|
|
1106
|
+
attemptedCommand,
|
|
1107
|
+
userPrompt,
|
|
1108
|
+
agentSkillDetected: detectedMentions,
|
|
1109
|
+
timestamp: new Date().toISOString(),
|
|
1110
|
+
};
|
|
1111
|
+
|
|
1112
|
+
// Update the cached analysis
|
|
1113
|
+
await this.cacheAnalysis(cliName, newAnalysis);
|
|
1114
|
+
return newAnalysis;
|
|
1115
|
+
} catch (analysisError) {
|
|
1116
|
+
if (process.env.DEBUG === 'true') {
|
|
1117
|
+
console.error(`Failed to re-analyze ${cliName}:`, analysisError.message);
|
|
1118
|
+
}
|
|
1119
|
+
return null;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Get agent/skill compatibility score for CLI tool
|
|
1125
|
+
*/
|
|
1126
|
+
getAgentSkillCompatibilityScore(cliName, prompt) {
|
|
1127
|
+
const enhancedPattern = this.enhancedPatterns[cliName];
|
|
1128
|
+
if (!enhancedPattern) {
|
|
1129
|
+
return { score: 0, reasons: ['CLI not supported'] };
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
const detectedMentions = this.detectAgentSkillMentions(prompt, cliName);
|
|
1133
|
+
let score = 0.5; // Base score
|
|
1134
|
+
const reasons = [];
|
|
1135
|
+
|
|
1136
|
+
// Base compatibility
|
|
1137
|
+
if (enhancedPattern.agentDetection) {
|
|
1138
|
+
score += 0.2;
|
|
1139
|
+
reasons.push('支持智能体检测');
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
if (enhancedPattern.skillDetection) {
|
|
1143
|
+
score += 0.2;
|
|
1144
|
+
reasons.push('支持技能检测');
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
// Detection results
|
|
1148
|
+
if (detectedMentions.hasAgent) {
|
|
1149
|
+
score += 0.1;
|
|
1150
|
+
reasons.push('检测到智能体提及');
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
if (detectedMentions.hasSkill) {
|
|
1154
|
+
score += 0.1;
|
|
1155
|
+
reasons.push('检测到技能提及');
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// CLI-specific advantages
|
|
1159
|
+
if (cliName === 'qwen' && enhancedPattern.positionalArgs) {
|
|
1160
|
+
score += 0.1;
|
|
1161
|
+
reasons.push('位置参数支持,自然语言理解优秀');
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
if (cliName === 'codebuddy' && enhancedPattern.skillPrefixRequired) {
|
|
1165
|
+
score += 0.1;
|
|
1166
|
+
reasons.push('明确的技能语法支持');
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// Penalty for mismatches
|
|
1170
|
+
if (enhancedPattern.skillPrefixRequired && !detectedMentions.hasSkill) {
|
|
1171
|
+
score -= 0.2;
|
|
1172
|
+
reasons.push('需要技能语法但未检测到技能');
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
return {
|
|
1176
|
+
score: Math.max(0, Math.min(1, score)),
|
|
1177
|
+
reasons,
|
|
1178
|
+
detected: detectedMentions
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
/**
|
|
1183
|
+
* Generate optimized call command for CLI tool
|
|
1184
|
+
*/
|
|
1185
|
+
generateOptimizedCall(cliName, userPrompt) {
|
|
1186
|
+
const enhancedPattern = this.enhancedPatterns[cliName];
|
|
1187
|
+
if (!enhancedPattern) {
|
|
1188
|
+
return null;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
// Optimize the prompt
|
|
1192
|
+
const detectedMentions = this.detectAgentSkillMentions(userPrompt, cliName);
|
|
1193
|
+
const optimizedPrompt = this.optimizePromptForCLI(userPrompt, cliName, detectedMentions);
|
|
1194
|
+
|
|
1195
|
+
// Generate command based on CLI format
|
|
1196
|
+
let command;
|
|
1197
|
+
let args;
|
|
1198
|
+
|
|
1199
|
+
switch (cliName) {
|
|
1200
|
+
case 'qwen':
|
|
1201
|
+
// Qwen uses positional arguments
|
|
1202
|
+
command = 'qwen';
|
|
1203
|
+
args = [optimizedPrompt];
|
|
1204
|
+
break;
|
|
1205
|
+
|
|
1206
|
+
case 'codebuddy':
|
|
1207
|
+
// Codebuddy requires -y flag and skill prefix
|
|
1208
|
+
command = 'codebuddy';
|
|
1209
|
+
args = ['-y', '-p', optimizedPrompt];
|
|
1210
|
+
break;
|
|
1211
|
+
|
|
1212
|
+
case 'claude':
|
|
1213
|
+
case 'iflow':
|
|
1214
|
+
case 'qodercli':
|
|
1215
|
+
// These use -p flag
|
|
1216
|
+
command = cliName;
|
|
1217
|
+
args = ['-p', optimizedPrompt];
|
|
1218
|
+
break;
|
|
1219
|
+
|
|
1220
|
+
default:
|
|
1221
|
+
command = cliName;
|
|
1222
|
+
args = ['-p', optimizedPrompt];
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
return {
|
|
1226
|
+
command,
|
|
1227
|
+
args,
|
|
1228
|
+
fullCommand: `${command} ${args.join(' ')}`,
|
|
1229
|
+
optimizedPrompt,
|
|
1230
|
+
detectedMentions,
|
|
1231
|
+
compatibilityScore: this.getAgentSkillCompatibilityScore(cliName, userPrompt)
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
678
1234
|
}
|
|
679
1235
|
|
|
680
1236
|
module.exports = CLIHelpAnalyzer;
|