stigmergy 1.2.0 → 1.2.6
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/LICENSE +18 -18
- package/README.md +28 -223
- package/STIGMERGY.md +61 -61
- package/docs/PROJECT_CONSTITUTION.md +433 -433
- package/docs/PROJECT_STRUCTURE_CURRENT.md +80 -80
- package/examples/calculator-example.js +72 -72
- package/examples/cline_usage_examples.md +364 -364
- package/examples/encryption-example.js +67 -67
- package/examples/json-parser-example.js +120 -120
- package/examples/json-validation-example.js +64 -64
- package/examples/rest-client-example.js +52 -52
- package/examples/rest_client_example.js +54 -54
- package/package.json +36 -15
- package/scripts/build.js +74 -74
- package/scripts/post-deployment-config.js +296 -296
- package/scripts/preinstall-check.js +173 -173
- package/scripts/publish.js +58 -268
- package/scripts/run-layered-tests.js +247 -0
- package/scripts/safe-install.js +139 -139
- package/scripts/simple-publish.js +57 -59
- package/src/adapters/claude/install_claude_integration.js +292 -0
- package/src/adapters/codebuddy/install_codebuddy_integration.js +349 -0
- package/src/adapters/codex/install_codex_integration.js +395 -0
- package/src/adapters/copilot/install_copilot_integration.js +716 -0
- package/src/adapters/gemini/install_gemini_integration.js +304 -0
- package/src/adapters/iflow/install_iflow_integration.js +304 -0
- package/src/adapters/qoder/install_qoder_integration.js +1090 -0
- package/src/adapters/qwen/install_qwen_integration.js +285 -0
- package/src/auth.js +173 -173
- package/src/auth_command.js +208 -208
- package/src/calculator.js +313 -313
- package/src/cli/router.js +417 -38
- package/src/core/cache_cleaner.js +767 -744
- package/src/core/cli_help_analyzer.js +680 -674
- package/src/core/cli_parameter_handler.js +132 -127
- package/src/core/cli_tools.js +89 -89
- package/src/core/coordination/index.js +16 -16
- package/src/core/coordination/nodejs/AdapterManager.js +102 -89
- package/src/core/coordination/nodejs/CLCommunication.js +132 -124
- package/src/core/coordination/nodejs/CLIIntegrationManager.js +272 -236
- package/src/core/coordination/nodejs/HealthChecker.js +76 -77
- package/src/core/coordination/nodejs/HookDeploymentManager.js +263 -190
- package/src/core/coordination/nodejs/StatisticsCollector.js +71 -71
- package/src/core/coordination/nodejs/index.js +90 -72
- package/src/core/coordination/nodejs/utils/Logger.js +29 -29
- package/src/core/enhanced_installer.js +479 -456
- package/src/core/enhanced_uninstaller.js +638 -618
- package/src/core/error_handler.js +406 -406
- package/src/core/installer.js +815 -294
- package/src/core/memory_manager.js +83 -83
- package/src/core/rest_client.js +160 -160
- package/src/core/smart_router.js +249 -146
- package/src/core/upgrade_manager.js +76 -59
- package/src/data_encryption.js +143 -143
- package/src/data_structures.js +440 -440
- package/src/deploy.js +55 -55
- package/src/index.js +30 -30
- package/src/test/cli-availability-checker.js +194 -0
- package/src/test/test-environment.js +289 -0
- package/src/utils/helpers.js +35 -35
- package/src/utils.js +921 -915
- package/src/weatherProcessor.js +228 -228
- package/test/cache-cleaner-implemented.test.js +0 -328
- package/test/cache-cleaner.test.js +0 -390
- package/test/calculator.test.js +0 -215
- package/test/collision-test.js +0 -26
- package/test/comprehensive-enhanced-features.test.js +0 -252
- package/test/comprehensive-execution-test.js +0 -428
- package/test/conflict-prevention-test.js +0 -95
- package/test/cross-cli-detection-test.js +0 -33
- package/test/csv-processing-test.js +0 -36
- package/test/deploy-hooks-test.js +0 -250
- package/test/e2e/claude-cli-test.js +0 -128
- package/test/e2e/collaboration-test.js +0 -75
- package/test/e2e/comprehensive-test.js +0 -431
- package/test/e2e/error-handling-test.js +0 -90
- package/test/e2e/individual-tool-test.js +0 -143
- package/test/e2e/other-cli-test.js +0 -130
- package/test/e2e/qoder-cli-test.js +0 -128
- package/test/e2e/run-e2e-tests.js +0 -73
- package/test/e2e/test-data.js +0 -88
- package/test/e2e/test-utils.js +0 -222
- package/test/encryption-simple-test.js +0 -110
- package/test/encryption.test.js +0 -129
- package/test/enhanced-main-alignment.test.js +0 -298
- package/test/enhanced-uninstaller-implemented.test.js +0 -271
- package/test/enhanced-uninstaller.test.js +0 -284
- package/test/error-handling-test.js +0 -341
- package/test/fibonacci.test.js +0 -178
- package/test/final-deploy-test.js +0 -221
- package/test/final-install-test.js +0 -226
- package/test/hash-table-demo.js +0 -33
- package/test/hash-table-test.js +0 -26
- package/test/hash_table_test.js +0 -114
- package/test/hook-system-integration-test.js +0 -307
- package/test/iflow-integration-test.js +0 -292
- package/test/improved-install-test.js +0 -362
- package/test/install-command-test.js +0 -370
- package/test/json-parser-test.js +0 -161
- package/test/json-validation-test.js +0 -164
- package/test/natural-language-skills-test.js +0 -320
- package/test/nl-integration-test.js +0 -179
- package/test/parameter-parsing-test.js +0 -143
- package/test/plugin-deployment-test.js +0 -316
- package/test/postinstall-test.js +0 -269
- package/test/python-plugins-test.js +0 -259
- package/test/real-test.js +0 -435
- package/test/remaining-adapters-test.js +0 -256
- package/test/rest-client-test.js +0 -56
- package/test/rest_client.test.js +0 -85
- package/test/safe-installation-cleaner.test.js +0 -343
- package/test/simple-iflow-hook-test.js +0 -137
- package/test/stigmergy-upgrade-test.js +0 -243
- package/test/system-compatibility-test.js +0 -467
- package/test/tdd-deploy-fix-test.js +0 -324
- package/test/tdd-fixes-test.js +0 -211
- package/test/third-party-skills-test.js +0 -321
- package/test/tool-selection-integration-test.js +0 -158
- package/test/unit/calculator-full.test.js +0 -191
- package/test/unit/calculator-simple.test.js +0 -96
- package/test/unit/calculator.test.js +0 -97
- package/test/unit/cli-scanner.test.js +0 -291
- package/test/unit/cli_parameter_handler.test.js +0 -116
- package/test/unit/cross-cli-executor.test.js +0 -399
- package/test/weather-processor.test.js +0 -104
package/src/core/smart_router.js
CHANGED
|
@@ -1,146 +1,249 @@
|
|
|
1
|
-
const CLIHelpAnalyzer = require('./cli_help_analyzer');
|
|
2
|
-
const { CLI_TOOLS, validateCLITool } = require('./cli_tools');
|
|
3
|
-
const { errorHandler } = require('./error_handler');
|
|
4
|
-
|
|
5
|
-
class SmartRouter {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.tools = CLI_TOOLS;
|
|
8
|
-
try {
|
|
9
|
-
this.analyzer = new CLIHelpAnalyzer();
|
|
10
|
-
this.analyzer.setCLITools(this.tools);
|
|
11
|
-
} catch (error) {
|
|
12
|
-
errorHandler.logError(error, 'ERROR', 'SmartRouter.constructor');
|
|
13
|
-
throw error;
|
|
14
|
-
}
|
|
15
|
-
this.routeKeywords = [
|
|
16
|
-
'use',
|
|
17
|
-
'help',
|
|
18
|
-
'please',
|
|
19
|
-
'write',
|
|
20
|
-
'generate',
|
|
21
|
-
'explain',
|
|
22
|
-
'analyze',
|
|
23
|
-
'translate',
|
|
24
|
-
'
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
1
|
+
const CLIHelpAnalyzer = require('./cli_help_analyzer');
|
|
2
|
+
const { CLI_TOOLS, validateCLITool } = require('./cli_tools');
|
|
3
|
+
const { errorHandler } = require('./error_handler');
|
|
4
|
+
|
|
5
|
+
class SmartRouter {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.tools = CLI_TOOLS;
|
|
8
|
+
try {
|
|
9
|
+
this.analyzer = new CLIHelpAnalyzer();
|
|
10
|
+
this.analyzer.setCLITools(this.tools);
|
|
11
|
+
} catch (error) {
|
|
12
|
+
errorHandler.logError(error, 'ERROR', 'SmartRouter.constructor');
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
this.routeKeywords = [
|
|
16
|
+
'use',
|
|
17
|
+
'help',
|
|
18
|
+
'please',
|
|
19
|
+
'write',
|
|
20
|
+
'generate',
|
|
21
|
+
'explain',
|
|
22
|
+
'analyze',
|
|
23
|
+
'translate',
|
|
24
|
+
'article',
|
|
25
|
+
];
|
|
26
|
+
this.defaultTool = 'claude';
|
|
27
|
+
// Track recently failed tools to avoid repeated analysis attempts
|
|
28
|
+
this.recentFailures = new Map();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Initialize the smart router
|
|
33
|
+
*/
|
|
34
|
+
async initialize() {
|
|
35
|
+
await this.analyzer.initialize();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Check if input should be routed to a specific CLI tool
|
|
40
|
+
*/
|
|
41
|
+
shouldRoute(userInput) {
|
|
42
|
+
return this.routeKeywords.some((keyword) =>
|
|
43
|
+
userInput.toLowerCase().includes(keyword.toLowerCase()),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Perform smart routing based on user input and CLI patterns
|
|
49
|
+
* Optimized to reduce unnecessary error messages and improve performance
|
|
50
|
+
* Prioritizes exact tool name matches over keyword matches
|
|
51
|
+
*/
|
|
52
|
+
async smartRoute(userInput) {
|
|
53
|
+
const input = userInput.trim();
|
|
54
|
+
const inputLower = input.toLowerCase();
|
|
55
|
+
|
|
56
|
+
// First, check for exact tool name matches (higher priority)
|
|
57
|
+
for (const [toolName, _] of Object.entries(this.tools)) {
|
|
58
|
+
try {
|
|
59
|
+
// Validate tool configuration
|
|
60
|
+
validateCLITool(toolName);
|
|
61
|
+
|
|
62
|
+
if (inputLower.includes(toolName)) {
|
|
63
|
+
// Extract clean parameters when the tool name itself is mentioned
|
|
64
|
+
const cleanInput = input
|
|
65
|
+
.replace(new RegExp(`.*${toolName}\\s*`, 'gi'), '')
|
|
66
|
+
.replace(/^(use|please|help|using|with)\s*/i, '')
|
|
67
|
+
.trim();
|
|
68
|
+
return { tool: toolName, prompt: cleanInput };
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
// Only log error if it's a real issue, not just a missing pattern
|
|
72
|
+
if (
|
|
73
|
+
error.message &&
|
|
74
|
+
!error.message.includes('no such file or directory')
|
|
75
|
+
) {
|
|
76
|
+
await errorHandler.logError(
|
|
77
|
+
error,
|
|
78
|
+
'WARN',
|
|
79
|
+
`SmartRouter.smartRoute.${toolName}`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
// Continue with next tool
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Then check for keyword matches (lower priority)
|
|
88
|
+
// Only analyze tools that are likely to match to reduce overhead
|
|
89
|
+
const potentialMatches = [];
|
|
90
|
+
for (const [toolName, _] of Object.entries(this.tools)) {
|
|
91
|
+
// Quick check: if the input is very short, only analyze a few key tools
|
|
92
|
+
if (input.length < 20) {
|
|
93
|
+
// For short inputs, only analyze commonly used tools
|
|
94
|
+
const commonTools = ['claude', 'gemini', 'qwen'];
|
|
95
|
+
if (!commonTools.includes(toolName)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Add tool to potential matches for detailed analysis
|
|
101
|
+
potentialMatches.push(toolName);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Analyze potential matches
|
|
105
|
+
for (const toolName of potentialMatches) {
|
|
106
|
+
try {
|
|
107
|
+
// Validate tool configuration
|
|
108
|
+
validateCLITool(toolName);
|
|
109
|
+
|
|
110
|
+
// Get CLI pattern for this tool - with optimized caching
|
|
111
|
+
let cliPattern = await this.getOptimizedCLIPattern(toolName);
|
|
112
|
+
|
|
113
|
+
// Check if input contains any of the tool's keywords or subcommands
|
|
114
|
+
const keywords = this.extractKeywords(toolName, cliPattern);
|
|
115
|
+
for (const keyword of keywords) {
|
|
116
|
+
// Skip the tool name itself since we already checked for exact matches
|
|
117
|
+
if (
|
|
118
|
+
keyword.toLowerCase() !== toolName.toLowerCase() &&
|
|
119
|
+
inputLower.includes(keyword.toLowerCase())
|
|
120
|
+
) {
|
|
121
|
+
// Extract clean parameters
|
|
122
|
+
const cleanInput = input
|
|
123
|
+
.replace(new RegExp(`.*${keyword}\\s*`, 'gi'), '')
|
|
124
|
+
.replace(/^(use|please|help|using|with)\s*/i, '')
|
|
125
|
+
.trim();
|
|
126
|
+
return { tool: toolName, prompt: cleanInput };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
// Only log error if it's a real issue, not just a missing pattern
|
|
131
|
+
if (
|
|
132
|
+
error.message &&
|
|
133
|
+
!error.message.includes('no such file or directory')
|
|
134
|
+
) {
|
|
135
|
+
await errorHandler.logError(
|
|
136
|
+
error,
|
|
137
|
+
'WARN',
|
|
138
|
+
`SmartRouter.smartRoute.${toolName}`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
// Continue with next tool
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Default routing
|
|
147
|
+
const cleanInput = input
|
|
148
|
+
.replace(/^(use|please|help|using|with)\s*/i, '')
|
|
149
|
+
.trim();
|
|
150
|
+
return { tool: this.defaultTool, prompt: cleanInput };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Get CLI pattern with optimized error handling to reduce noise
|
|
155
|
+
*/
|
|
156
|
+
async getOptimizedCLIPattern(toolName) {
|
|
157
|
+
try {
|
|
158
|
+
// Quick check for missing tools to avoid unnecessary analysis
|
|
159
|
+
const config = await this.analyzer.loadPersistentConfig();
|
|
160
|
+
const failedAttempt = config.failedAttempts[toolName];
|
|
161
|
+
|
|
162
|
+
// If there was a recent failure (less than 1 hour ago), skip analysis entirely
|
|
163
|
+
if (failedAttempt && this.isRecentFailure(failedAttempt.timestamp)) {
|
|
164
|
+
if (process.env.DEBUG === 'true') {
|
|
165
|
+
console.log(
|
|
166
|
+
`[INFO] Skipping analysis for ${toolName} due to recent failure`,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
// Return cached analysis if available, otherwise null
|
|
170
|
+
const cached = await this.analyzer.getCachedAnalysis(toolName);
|
|
171
|
+
return cached || null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const cached = await this.analyzer.getCachedAnalysis(toolName);
|
|
175
|
+
|
|
176
|
+
if (cached && !this.analyzer.isCacheExpired(cached.timestamp)) {
|
|
177
|
+
return cached;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Analyze CLI if no cache or failure is old
|
|
181
|
+
return await this.analyzer.analyzeCLI(toolName);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
// Only log serious errors, suppress file not found errors
|
|
184
|
+
if (
|
|
185
|
+
error.message &&
|
|
186
|
+
!error.message.includes('ENOENT') &&
|
|
187
|
+
!error.message.includes('no such file or directory')
|
|
188
|
+
) {
|
|
189
|
+
console.warn(`[WARN] Unable to get help information for ${toolName}`);
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Check if failure timestamp is recent (less than 1 hour)
|
|
197
|
+
*/
|
|
198
|
+
isRecentFailure(timestamp) {
|
|
199
|
+
const failureTime = new Date(timestamp);
|
|
200
|
+
const now = new Date();
|
|
201
|
+
const hoursDiff = (now - failureTime) / (1000 * 60 * 60);
|
|
202
|
+
return hoursDiff < 1; // Recent if less than 1 hour
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Extract keywords for a tool from its CLI patterns
|
|
207
|
+
*/
|
|
208
|
+
extractKeywords(toolName, cliPattern) {
|
|
209
|
+
const keywords = [toolName];
|
|
210
|
+
|
|
211
|
+
// Add tool-specific keywords
|
|
212
|
+
const toolSpecificKeywords = {
|
|
213
|
+
claude: ['claude', 'anthropic'],
|
|
214
|
+
gemini: ['gemini', 'google'],
|
|
215
|
+
qwen: ['qwen', 'alibaba', 'tongyi'],
|
|
216
|
+
iflow: ['iflow', 'workflow', 'intelligent'],
|
|
217
|
+
qodercli: ['qoder', 'code'], // 'code' is specifically for qodercli only
|
|
218
|
+
codebuddy: ['codebuddy', 'buddy', 'assistant'],
|
|
219
|
+
copilot: ['copilot', 'github', 'gh'],
|
|
220
|
+
codex: ['codex', 'openai', 'gpt'], // Remove 'code' from here to avoid conflicts
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
if (toolSpecificKeywords[toolName]) {
|
|
224
|
+
keywords.push(...toolSpecificKeywords[toolName]);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Add subcommands from CLI pattern if available
|
|
228
|
+
if (cliPattern && cliPattern.patterns && cliPattern.patterns.subcommands) {
|
|
229
|
+
cliPattern.patterns.subcommands.forEach((subcommand) => {
|
|
230
|
+
if (subcommand.name) {
|
|
231
|
+
keywords.push(subcommand.name);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Add commands from CLI pattern if available
|
|
237
|
+
if (cliPattern && cliPattern.patterns && cliPattern.patterns.commands) {
|
|
238
|
+
cliPattern.patterns.commands.forEach((command) => {
|
|
239
|
+
if (command.name && command.name !== toolName) {
|
|
240
|
+
keywords.push(command.name);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return [...new Set(keywords)]; // Remove duplicates
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
module.exports = SmartRouter;
|