stigmergy 1.2.12 → 1.3.2-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.
Files changed (48) hide show
  1. package/README.md +39 -3
  2. package/STIGMERGY.md +3 -0
  3. package/config/enhanced-cli-config.json +438 -0
  4. package/docs/CLI_TOOLS_AGENT_SKILL_ANALYSIS.md +463 -0
  5. package/docs/ENHANCED_CLI_AGENT_SKILL_CONFIG.md +285 -0
  6. package/docs/INSTALLER_ARCHITECTURE.md +257 -0
  7. package/docs/SUDO_PROBLEM_AND_SOLUTION.md +529 -0
  8. package/package.json +14 -5
  9. package/scripts/analyze-router.js +168 -0
  10. package/scripts/test-runner.js +344 -0
  11. package/src/cli/commands/autoinstall.js +158 -0
  12. package/src/cli/commands/errors.js +190 -0
  13. package/src/cli/commands/install.js +142 -0
  14. package/src/cli/commands/permissions.js +108 -0
  15. package/src/cli/commands/project.js +449 -0
  16. package/src/cli/commands/resume.js +136 -0
  17. package/src/cli/commands/scan.js +97 -0
  18. package/src/cli/commands/skills.js +158 -0
  19. package/src/cli/commands/status.js +106 -0
  20. package/src/cli/commands/system.js +301 -0
  21. package/src/cli/router-beta.js +477 -0
  22. package/src/cli/utils/environment.js +75 -0
  23. package/src/cli/utils/formatters.js +47 -0
  24. package/src/cli/utils/skills_cache.js +92 -0
  25. package/src/core/cache_cleaner.js +1 -0
  26. package/src/core/cli_adapters.js +345 -0
  27. package/src/core/cli_help_analyzer.js +473 -1
  28. package/src/core/cli_path_detector.js +2 -1
  29. package/src/core/cli_tools.js +107 -0
  30. package/src/core/coordination/nodejs/HookDeploymentManager.js +185 -422
  31. package/src/core/coordination/nodejs/HookDeploymentManager.refactored.js +323 -0
  32. package/src/core/coordination/nodejs/generators/CLIAdapterGenerator.js +363 -0
  33. package/src/core/coordination/nodejs/generators/ResumeSessionGenerator.js +701 -0
  34. package/src/core/coordination/nodejs/generators/SkillsIntegrationGenerator.js +1210 -0
  35. package/src/core/coordination/nodejs/generators/index.js +12 -0
  36. package/src/core/enhanced_cli_installer.js +220 -30
  37. package/src/core/enhanced_cli_parameter_handler.js +395 -0
  38. package/src/core/execution_mode_detector.js +222 -0
  39. package/src/core/installer.js +51 -70
  40. package/src/core/local_skill_scanner.js +732 -0
  41. package/src/core/multilingual/language-pattern-manager.js +1 -1
  42. package/src/core/skills/StigmergySkillManager.js +26 -8
  43. package/src/core/smart_router.js +279 -2
  44. package/src/index.js +10 -4
  45. package/test/cli-integration.test.js +304 -0
  46. package/test/enhanced-cli-agent-skill-test.js +485 -0
  47. package/test/specific-cli-agent-skill-analysis.js +385 -0
  48. package/src/cli/router.js +0 -1737
@@ -13,6 +13,180 @@ class CLIHelpAnalyzer {
13
13
  this.lastAnalysisFile = path.join(this.configDir, 'last-analysis.json');
14
14
  this.cliTools = CLI_TOOLS;
15
15
 
16
+ // Enhanced CLI Agent and Skill Patterns Configuration
17
+ this.enhancedPatterns = {
18
+ 'claude': {
19
+ commandFormat: 'claude -p "{prompt}"',
20
+ agentDetection: true,
21
+ skillDetection: true,
22
+ naturalLanguageSupport: true,
23
+ agentTypes: ['expert', 'skill', 'analysis', 'agent'],
24
+ skillKeywords: ['技能', '智能体', '分析', '工具', '方法'],
25
+ examples: [
26
+ 'claude -p "请使用异化分析技能分析程序员异化现象"',
27
+ 'claude -p "请使用数字马克思智能体进行阶级分析"'
28
+ ]
29
+ },
30
+ 'iflow': {
31
+ commandFormat: 'iflow -p "{prompt}"',
32
+ agentDetection: true,
33
+ skillDetection: true,
34
+ naturalLanguageSupport: true,
35
+ agentTypes: ['expert', 'skill', 'analysis', 'agent'],
36
+ skillKeywords: ['技能', '智能体', '分析', '工具', '方法'],
37
+ examples: [
38
+ 'iflow -p "请使用异化分析技能分析程序员异化现象"',
39
+ 'iflow -p "请使用数字马克思智能体进行异化分析"'
40
+ ]
41
+ },
42
+ 'qwen': {
43
+ commandFormat: 'qwen "{prompt}"',
44
+ agentDetection: true,
45
+ skillDetection: true,
46
+ naturalLanguageSupport: true,
47
+ positionalArgs: true,
48
+ agentTypes: ['expert', 'skill', 'analysis', 'agent'],
49
+ skillKeywords: ['智能体', '分析技能', '马克思', '异化', '阶级'],
50
+ examples: [
51
+ 'qwen "使用数字马克思智能体进行异化分析,分析程序员的技术异化现象"',
52
+ 'qwen "使用异化分析技能分析程序员在AI开发中的异化现象"'
53
+ ]
54
+ },
55
+ 'codebuddy': {
56
+ commandFormat: 'codebuddy -y -p "{prompt}"',
57
+ agentDetection: false,
58
+ skillDetection: true,
59
+ skillPrefixRequired: true,
60
+ agentTypes: ['skill'],
61
+ skillKeywords: ['skill:', '技能', '分析'],
62
+ examples: [
63
+ 'codebuddy -y -p "skill:alienation-analysis 分析程序员异化现象"',
64
+ 'codebuddy -y -p "skill:marxist-analysis 分析技术异化"'
65
+ ]
66
+ },
67
+ 'qodercli': {
68
+ commandFormat: 'qodercli -p "{prompt}"',
69
+ agentDetection: false,
70
+ skillDetection: false,
71
+ basicAISupport: true,
72
+ agentTypes: ['basic'],
73
+ skillKeywords: ['分析', '理解'],
74
+ examples: [
75
+ 'qodercli -p "分析程序员在AI开发中的异化现象"',
76
+ 'qodercli -p "进行技术异化的基础分析"'
77
+ ]
78
+ },
79
+ 'gemini': {
80
+ commandFormat: 'gemini -p "{prompt}"',
81
+ agentDetection: true,
82
+ skillDetection: true,
83
+ naturalLanguageSupport: true,
84
+ agentTypes: ['expert', 'skill', 'analysis', 'agent'],
85
+ skillKeywords: ['技能', '智能体', '分析', '工具', '方法'],
86
+ examples: [
87
+ 'gemini -p "请使用分析技能分析程序员异化现象"',
88
+ 'gemini -p "使用智能体进行技术分析"'
89
+ ]
90
+ },
91
+ 'copilot': {
92
+ commandFormat: 'copilot "{prompt}"',
93
+ agentDetection: true,
94
+ skillDetection: true,
95
+ naturalLanguageSupport: true,
96
+ positionalArgs: true,
97
+ agentTypes: ['expert', 'skill', 'analysis', 'agent'],
98
+ skillKeywords: ['技能', '智能体', '分析', '工具', '方法'],
99
+ examples: [
100
+ 'copilot "请使用分析技能分析程序员异化现象"',
101
+ 'copilot "使用智能体进行技术分析"'
102
+ ]
103
+ },
104
+ 'codex': {
105
+ commandFormat: 'codex -m gpt-5 "{prompt}"',
106
+ agentDetection: true,
107
+ skillDetection: true,
108
+ naturalLanguageSupport: true,
109
+ positionalArgs: true,
110
+ agentTypes: ['expert', 'skill', 'analysis', 'agent'],
111
+ skillKeywords: ['技能', '智能体', '分析', '工具', '方法', '代码', '审查'],
112
+ examples: [
113
+ 'codex "请使用异化分析技能分析程序员异化现象"',
114
+ 'codex exec "使用数字马克思智能体分析代码库"',
115
+ 'codex review "分析这段代码的异化现象"'
116
+ ]
117
+ },
118
+ 'kode': {
119
+ commandFormat: 'kode -p "{prompt}"',
120
+ agentDetection: true,
121
+ skillDetection: true,
122
+ naturalLanguageSupport: true,
123
+ positionalArgs: true,
124
+ agentTypes: ['expert', 'skill', 'analysis', 'agent'],
125
+ skillKeywords: ['技能', '智能体', '分析', '工具', '方法', '多模型', '协作'],
126
+ examples: [
127
+ 'kode -p "请使用异化分析技能分析程序员异化现象"',
128
+ 'kode -p "使用数字马克思智能体进行异化分析"',
129
+ 'kode -p "@ask-claude-sonnet-4 分析这个问题"'
130
+ ]
131
+ }
132
+ };
133
+
134
+ // Agent and Skill Recognition Patterns
135
+ this.agentSkillPatterns = {
136
+ // Agent type detection patterns
137
+ agentTypes: {
138
+ 'expert': ['专家', 'expert', 'specialist', '马克思', 'marxist', '数字马克思'],
139
+ 'skill': ['技能', 'skill', '能力', '方法', '工具'],
140
+ 'analysis': ['分析', 'analysis', '解析', '评估'],
141
+ 'agent': ['智能体', 'agent', '助手', '助手'],
142
+ 'basic': ['基础', 'basic', '简单', '初步']
143
+ },
144
+
145
+ // Skill name patterns for different CLIs
146
+ skillMapping: {
147
+ '异化分析': {
148
+ 'claude': '异化分析技能',
149
+ 'iflow': '异化分析技能',
150
+ 'qwen': '异化分析技能',
151
+ 'codebuddy': 'alienation-analysis',
152
+ 'gemini': '异化分析技能',
153
+ 'copilot': '异化分析技能',
154
+ 'codex': 'alienation-analysis',
155
+ 'kode': '异化分析技能'
156
+ },
157
+ '马克思分析': {
158
+ 'claude': '数字马克思智能体',
159
+ 'iflow': '数字马克思智能体',
160
+ 'qwen': '数字马克思智能体',
161
+ 'codebuddy': 'marxist-analysis',
162
+ 'gemini': '马克思分析技能',
163
+ 'copilot': '马克思分析智能体',
164
+ 'codex': 'marxist-analysis',
165
+ 'kode': '数字马克思智能体'
166
+ },
167
+ '技术分析': {
168
+ 'claude': '技术分析技能',
169
+ 'iflow': '技术分析技能',
170
+ 'qwen': '技术分析技能',
171
+ 'codebuddy': 'tech-analysis',
172
+ 'gemini': '技术分析技能',
173
+ 'copilot': '技术分析技能',
174
+ 'codex': 'tech-analysis',
175
+ 'kode': '技术分析技能'
176
+ },
177
+ '阶级分析': {
178
+ 'claude': '阶级分析技能',
179
+ 'iflow': '阶级分析技能',
180
+ 'qwen': '阶级分析技能',
181
+ 'codebuddy': 'class-analysis',
182
+ 'gemini': '阶级分析技能',
183
+ 'copilot': '阶级分析技能',
184
+ 'codex': 'class-analysis',
185
+ 'kode': '阶级分析技能'
186
+ }
187
+ }
188
+ };
189
+
16
190
  // Pattern recognition rules for different CLI types
17
191
  this.patternRules = {
18
192
  // OpenAI style CLI (codex, chatgpt)
@@ -403,7 +577,10 @@ class CLIHelpAnalyzer {
403
577
  option.includes('non-interactive') ||
404
578
  option.includes('batch') ||
405
579
  option.includes('no-input') ||
406
- option.includes('stdin'),
580
+ option.includes('stdin') ||
581
+ option.includes('print') || // For CLI tools like kode with --print flag
582
+ option.includes('pipe') || // Pipes mentioned in description
583
+ option.includes('exit'), // Exit after execution
407
584
  );
408
585
  patterns.nonInteractiveFlag =
409
586
  nonInteractiveFlags.length > 0 ? nonInteractiveFlags[0] : null;
@@ -675,6 +852,301 @@ class CLIHelpAnalyzer {
675
852
  setCLITools(tools) {
676
853
  this.cliTools = tools;
677
854
  }
855
+
856
+ /**
857
+ * Enhanced analysis with agent and skill detection
858
+ */
859
+ async analyzeCLIEnhanced(cliName) {
860
+ const basicAnalysis = await this.analyzeCLI(cliName);
861
+
862
+ if (!basicAnalysis.success) {
863
+ return basicAnalysis;
864
+ }
865
+
866
+ // Add enhanced agent and skill information
867
+ const enhancedPatterns = this.enhancedPatterns[cliName] || {};
868
+
869
+ basicAnalysis.agentSkillSupport = {
870
+ supportsAgents: enhancedPatterns.agentDetection || false,
871
+ supportsSkills: enhancedPatterns.skillDetection || false,
872
+ naturalLanguageSupport: enhancedPatterns.naturalLanguageSupport || false,
873
+ skillPrefixRequired: enhancedPatterns.skillPrefixRequired || false,
874
+ positionalArgs: enhancedPatterns.positionalArgs || false,
875
+ agentTypes: enhancedPatterns.agentTypes || [],
876
+ skillKeywords: enhancedPatterns.skillKeywords || [],
877
+ commandFormat: enhancedPatterns.commandFormat || '',
878
+ examples: enhancedPatterns.examples || []
879
+ };
880
+
881
+ return basicAnalysis;
882
+ }
883
+
884
+ /**
885
+ * Detect agent and skill mentions in user input
886
+ */
887
+ detectAgentSkillMentions(input, cliName) {
888
+ const enhancedPattern = this.enhancedPatterns[cliName];
889
+ if (!enhancedPattern) {
890
+ return { hasAgent: false, hasSkill: false, confidence: 0 };
891
+ }
892
+
893
+ const inputLower = input.toLowerCase();
894
+ let hasAgent = false;
895
+ let hasSkill = false;
896
+ let confidence = 0;
897
+
898
+ // Check for agent keywords
899
+ if (enhancedPattern.agentDetection) {
900
+ const agentKeywords = [
901
+ ...this.agentSkillPatterns.agentTypes['expert'],
902
+ ...this.agentSkillPatterns.agentTypes['agent'],
903
+ ...enhancedPattern.skillKeywords
904
+ ];
905
+
906
+ for (const keyword of agentKeywords) {
907
+ if (inputLower.includes(keyword.toLowerCase())) {
908
+ hasAgent = true;
909
+ confidence += 0.3;
910
+ break;
911
+ }
912
+ }
913
+ }
914
+
915
+ // Check for skill keywords
916
+ if (enhancedPattern.skillDetection) {
917
+ const skillKeywords = enhancedPattern.skillKeywords;
918
+
919
+ for (const keyword of skillKeywords) {
920
+ if (inputLower.includes(keyword.toLowerCase())) {
921
+ hasSkill = true;
922
+ confidence += 0.4;
923
+ break;
924
+ }
925
+ }
926
+
927
+ // Special check for skill: prefix (codebuddy)
928
+ if (enhancedPattern.skillPrefixRequired && inputLower.includes('skill:')) {
929
+ hasSkill = true;
930
+ confidence += 0.6;
931
+ }
932
+ }
933
+
934
+ // Boost confidence based on CLI-specific patterns
935
+ if (cliName === 'qwen' && enhancedPattern.positionalArgs) {
936
+ // Qwen CLI has higher confidence for natural language
937
+ confidence *= 1.2;
938
+ }
939
+
940
+ return { hasAgent, hasSkill, confidence: Math.min(confidence, 1.0) };
941
+ }
942
+
943
+ /**
944
+ * Optimize prompt for specific CLI tool
945
+ */
946
+ optimizePromptForCLI(prompt, cliName, detectedMentions) {
947
+ const enhancedPattern = this.enhancedPatterns[cliName];
948
+ if (!enhancedPattern) {
949
+ return prompt;
950
+ }
951
+
952
+ let optimizedPrompt = prompt;
953
+
954
+ // Apply skill mapping if applicable
955
+ for (const [chineseSkill, mapping] of Object.entries(this.agentSkillPatterns.skillMapping)) {
956
+ if (prompt.includes(chineseSkill) && mapping[cliName]) {
957
+ if (enhancedPattern.skillPrefixRequired && !prompt.includes('skill:')) {
958
+ // For codebuddy, add skill: prefix
959
+ optimizedPrompt = prompt.replace(
960
+ chineseSkill,
961
+ `skill:${mapping[cliName]}`
962
+ );
963
+ } else if (enhancedPattern.naturalLanguageSupport) {
964
+ // For CLIs that support natural language, use the mapped term
965
+ optimizedPrompt = prompt.replace(
966
+ chineseSkill,
967
+ mapping[cliName]
968
+ );
969
+ }
970
+ break;
971
+ }
972
+ }
973
+
974
+ return optimizedPrompt;
975
+ }
976
+
977
+ /**
978
+ * Get enhanced CLI pattern with agent/skill support
979
+ */
980
+ async getEnhancedCLIPattern(cliName) {
981
+ const cached = await this.getCachedAnalysis(cliName);
982
+
983
+ if (cached && cached.timestamp && !this.isCacheExpired(cached.timestamp)) {
984
+ // Enhance cached data with agent/skill information
985
+ const enhancedPatterns = this.enhancedPatterns[cliName];
986
+ if (enhancedPatterns) {
987
+ cached.agentSkillSupport = {
988
+ supportsAgents: enhancedPatterns.agentDetection || false,
989
+ supportsSkills: enhancedPatterns.skillDetection || false,
990
+ naturalLanguageSupport: enhancedPatterns.naturalLanguageSupport || false,
991
+ skillPrefixRequired: enhancedPatterns.skillPrefixRequired || false,
992
+ positionalArgs: enhancedPatterns.positionalArgs || false,
993
+ agentTypes: enhancedPatterns.agentTypes || [],
994
+ skillKeywords: enhancedPatterns.skillKeywords || [],
995
+ commandFormat: enhancedPatterns.commandFormat || '',
996
+ examples: enhancedPatterns.examples || []
997
+ };
998
+ }
999
+ return cached;
1000
+ }
1001
+
1002
+ // Perform enhanced analysis
1003
+ return await this.analyzeCLIEnhanced(cliName);
1004
+ }
1005
+
1006
+ /**
1007
+ * Analyze call success and update patterns accordingly
1008
+ */
1009
+ async updatePatternOnAgentSkillFailure(cliName, error, attemptedCommand, userPrompt) {
1010
+ if (process.env.DEBUG === 'true') {
1011
+ console.log(`Updating agent/skill pattern for ${cliName} due to failure:`, error.message);
1012
+ }
1013
+
1014
+ try {
1015
+ // Re-analyze with enhanced capabilities
1016
+ const newAnalysis = await this.analyzeCLIEnhanced(cliName);
1017
+
1018
+ // Add failure context with agent/skill information
1019
+ const detectedMentions = this.detectAgentSkillMentions(userPrompt, cliName);
1020
+ newAnalysis.lastFailure = {
1021
+ error: error.message,
1022
+ attemptedCommand,
1023
+ userPrompt,
1024
+ agentSkillDetected: detectedMentions,
1025
+ timestamp: new Date().toISOString(),
1026
+ };
1027
+
1028
+ // Update the cached analysis
1029
+ await this.cacheAnalysis(cliName, newAnalysis);
1030
+ return newAnalysis;
1031
+ } catch (analysisError) {
1032
+ if (process.env.DEBUG === 'true') {
1033
+ console.error(`Failed to re-analyze ${cliName}:`, analysisError.message);
1034
+ }
1035
+ return null;
1036
+ }
1037
+ }
1038
+
1039
+ /**
1040
+ * Get agent/skill compatibility score for CLI tool
1041
+ */
1042
+ getAgentSkillCompatibilityScore(cliName, prompt) {
1043
+ const enhancedPattern = this.enhancedPatterns[cliName];
1044
+ if (!enhancedPattern) {
1045
+ return { score: 0, reasons: ['CLI not supported'] };
1046
+ }
1047
+
1048
+ const detectedMentions = this.detectAgentSkillMentions(prompt, cliName);
1049
+ let score = 0.5; // Base score
1050
+ const reasons = [];
1051
+
1052
+ // Base compatibility
1053
+ if (enhancedPattern.agentDetection) {
1054
+ score += 0.2;
1055
+ reasons.push('支持智能体检测');
1056
+ }
1057
+
1058
+ if (enhancedPattern.skillDetection) {
1059
+ score += 0.2;
1060
+ reasons.push('支持技能检测');
1061
+ }
1062
+
1063
+ // Detection results
1064
+ if (detectedMentions.hasAgent) {
1065
+ score += 0.1;
1066
+ reasons.push('检测到智能体提及');
1067
+ }
1068
+
1069
+ if (detectedMentions.hasSkill) {
1070
+ score += 0.1;
1071
+ reasons.push('检测到技能提及');
1072
+ }
1073
+
1074
+ // CLI-specific advantages
1075
+ if (cliName === 'qwen' && enhancedPattern.positionalArgs) {
1076
+ score += 0.1;
1077
+ reasons.push('位置参数支持,自然语言理解优秀');
1078
+ }
1079
+
1080
+ if (cliName === 'codebuddy' && enhancedPattern.skillPrefixRequired) {
1081
+ score += 0.1;
1082
+ reasons.push('明确的技能语法支持');
1083
+ }
1084
+
1085
+ // Penalty for mismatches
1086
+ if (enhancedPattern.skillPrefixRequired && !detectedMentions.hasSkill) {
1087
+ score -= 0.2;
1088
+ reasons.push('需要技能语法但未检测到技能');
1089
+ }
1090
+
1091
+ return {
1092
+ score: Math.max(0, Math.min(1, score)),
1093
+ reasons,
1094
+ detected: detectedMentions
1095
+ };
1096
+ }
1097
+
1098
+ /**
1099
+ * Generate optimized call command for CLI tool
1100
+ */
1101
+ generateOptimizedCall(cliName, userPrompt) {
1102
+ const enhancedPattern = this.enhancedPatterns[cliName];
1103
+ if (!enhancedPattern) {
1104
+ return null;
1105
+ }
1106
+
1107
+ // Optimize the prompt
1108
+ const detectedMentions = this.detectAgentSkillMentions(userPrompt, cliName);
1109
+ const optimizedPrompt = this.optimizePromptForCLI(userPrompt, cliName, detectedMentions);
1110
+
1111
+ // Generate command based on CLI format
1112
+ let command;
1113
+ let args;
1114
+
1115
+ switch (cliName) {
1116
+ case 'qwen':
1117
+ // Qwen uses positional arguments
1118
+ command = 'qwen';
1119
+ args = [optimizedPrompt];
1120
+ break;
1121
+
1122
+ case 'codebuddy':
1123
+ // Codebuddy requires -y flag and skill prefix
1124
+ command = 'codebuddy';
1125
+ args = ['-y', '-p', optimizedPrompt];
1126
+ break;
1127
+
1128
+ case 'claude':
1129
+ case 'iflow':
1130
+ case 'qodercli':
1131
+ // These use -p flag
1132
+ command = cliName;
1133
+ args = ['-p', optimizedPrompt];
1134
+ break;
1135
+
1136
+ default:
1137
+ command = cliName;
1138
+ args = ['-p', optimizedPrompt];
1139
+ }
1140
+
1141
+ return {
1142
+ command,
1143
+ args,
1144
+ fullCommand: `${command} ${args.join(' ')}`,
1145
+ optimizedPrompt,
1146
+ detectedMentions,
1147
+ compatibilityScore: this.getAgentSkillCompatibilityScore(cliName, userPrompt)
1148
+ };
1149
+ }
678
1150
  }
679
1151
 
680
1152
  module.exports = CLIHelpAnalyzer;
@@ -29,7 +29,8 @@ class CLIPathDetector {
29
29
  'qodercli': ['qodercli'],
30
30
  'codebuddy': ['codebuddy'],
31
31
  'copilot': ['copilot'],
32
- 'codex': ['codex']
32
+ 'codex': ['codex'],
33
+ 'kode': ['kode']
33
34
  };
34
35
  }
35
36
 
@@ -61,6 +61,20 @@ const CLI_TOOLS = {
61
61
  hooksDir: path.join(os.homedir(), '.config', 'codex', 'slash_commands'),
62
62
  config: path.join(os.homedir(), '.codex', 'config.json'),
63
63
  },
64
+ kode: {
65
+ name: 'Kode CLI',
66
+ version: 'kode --version',
67
+ install: 'npm install -g @shareai-lab/kode',
68
+ hooksDir: path.join(os.homedir(), '.kode', 'agents'),
69
+ config: path.join(os.homedir(), '.kode', 'config.json'),
70
+ },
71
+ resumesession: {
72
+ name: 'ResumeSession CLI',
73
+ version: 'resumesession --version',
74
+ install: 'npm install -g resumesession',
75
+ hooksDir: path.join(os.homedir(), '.resumesession', 'hooks'),
76
+ config: path.join(os.homedir(), '.resumesession', 'config.json'),
77
+ },
64
78
  };
65
79
 
66
80
  /**
@@ -150,6 +164,99 @@ async function setupCLIPaths() {
150
164
  };
151
165
  }
152
166
 
167
+ /**
168
+ * Scan for available CLI tools
169
+ * @param {Object} options - Scan options
170
+ * @param {boolean} options.deep - Deep scan
171
+ * @param {boolean} options.verbose - Verbose output
172
+ * @returns {Promise<Object>} Scan results
173
+ */
174
+ async function scanForTools(options = {}) {
175
+ const detector = getPathDetector();
176
+
177
+ // Load cached paths first
178
+ await detector.loadDetectedPaths();
179
+
180
+ // Detect all CLI paths
181
+ const detectedPaths = await detector.detectAllCLIPaths();
182
+
183
+ const found = [];
184
+ const missing = [];
185
+
186
+ for (const [toolName, toolPath] of Object.entries(detectedPaths)) {
187
+ if (toolPath) {
188
+ found.push({
189
+ name: toolName,
190
+ path: toolPath,
191
+ type: 'cli',
192
+ status: 'installed',
193
+ description: CLI_TOOLS[toolName]?.name || toolName
194
+ });
195
+ } else {
196
+ missing.push(toolName);
197
+ }
198
+ }
199
+
200
+ return {
201
+ found,
202
+ missing,
203
+ total: Object.keys(CLI_TOOLS).length
204
+ };
205
+ }
206
+
207
+ /**
208
+ * Check installation status of a specific CLI tool
209
+ * @param {string} toolName - Name of the tool
210
+ * @returns {Promise<Object>} Installation status
211
+ */
212
+ async function checkInstallation(toolName) {
213
+ validateCLITool(toolName);
214
+
215
+ const detector = getPathDetector();
216
+ await detector.loadDetectedPaths();
217
+
218
+ let toolPath = detector.getDetectedPath(toolName);
219
+
220
+ // If not cached, detect it
221
+ if (!toolPath) {
222
+ toolPath = await detector.detectCLIPath(toolName);
223
+ }
224
+
225
+ const installed = !!toolPath;
226
+
227
+ let version = null;
228
+ if (installed) {
229
+ try {
230
+ const { spawnSync } = require('child_process');
231
+ const toolConfig = CLI_TOOLS[toolName];
232
+ const versionCmd = toolConfig.version || `${toolName} --version`;
233
+
234
+ const result = spawnSync(versionCmd.split(' ')[0], versionCmd.split(' ').slice(1), {
235
+ encoding: 'utf8',
236
+ shell: true,
237
+ timeout: 5000
238
+ });
239
+
240
+ if (result.status === 0) {
241
+ version = result.stdout.trim() || result.stderr.trim();
242
+ }
243
+ } catch (error) {
244
+ // Version check failed, but tool is still installed
245
+ }
246
+ }
247
+
248
+ return {
249
+ installed,
250
+ path: toolPath,
251
+ version,
252
+ lastChecked: new Date().toISOString()
253
+ };
254
+ }
255
+
256
+ // Attach methods to CLI_TOOLS object for backward compatibility
257
+ CLI_TOOLS.scanForTools = scanForTools;
258
+ CLI_TOOLS.checkInstallation = checkInstallation;
259
+
153
260
  module.exports = {
154
261
  CLI_TOOLS,
155
262
  validateCLITool,