stigmergy 1.2.13 → 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 -1783
@@ -179,7 +179,7 @@ class LanguagePatternManager {
179
179
 
180
180
  // Validate that the target CLI is supported
181
181
  const supportedCLIs = [
182
- 'claude', 'gemini', 'qwen', 'iflow', 'qodercli', 'codebuddy', 'codex', 'copilot'
182
+ 'claude', 'gemini', 'qwen', 'iflow', 'qodercli', 'codebuddy', 'codex', 'copilot', 'kode'
183
183
  ];
184
184
 
185
185
  if (supportedCLIs.includes(targetCLI)) {
@@ -121,22 +121,40 @@ export class StigmergySkillManager {
121
121
 
122
122
  /**
123
123
  * Sync skills to CLI configuration files
124
+ * Also refreshes the LocalSkillScanner cache
124
125
  * @returns {Promise<void>}
125
126
  */
126
127
  async sync() {
127
128
  console.log('[INFO] Syncing skills to CLI configuration files...');
128
-
129
+
129
130
  try {
131
+ // Refresh the LocalSkillScanner cache
132
+ try {
133
+ // Import LocalSkillScanner (it's a CommonJS module)
134
+ const { createRequire } = await import('module');
135
+ const require = createRequire(import.meta.url);
136
+ const LocalSkillScanner = require('./local_skill_scanner.js');
137
+
138
+ const scanner = new LocalSkillScanner();
139
+ await scanner.initialize(true); // Force refresh
140
+ console.log('[INFO] Refreshed skills/agents cache');
141
+ } catch (err) {
142
+ // LocalSkillScanner might not be available, ignore
143
+ if (process.env.DEBUG === 'true') {
144
+ console.log('[DEBUG] LocalSkillScanner not available:', err.message);
145
+ }
146
+ }
147
+
130
148
  const skills = await this.reader.listSkills();
131
-
149
+
132
150
  if (skills.length === 0) {
133
151
  console.log('[INFO] No skills to sync');
134
152
  return;
135
153
  }
136
-
154
+
137
155
  // Generate <available_skills> XML
138
156
  const skillsXml = this.generateSkillsXml(skills);
139
-
157
+
140
158
  // All CLI configuration files to update
141
159
  const cliFiles = [
142
160
  'AGENTS.md', // Universal config
@@ -149,15 +167,15 @@ export class StigmergySkillManager {
149
167
  'copilot.md', // Copilot CLI
150
168
  'codex.md' // Codex CLI
151
169
  ];
152
-
170
+
153
171
  let syncedCount = 0;
154
172
  let createdCount = 0;
155
173
  let skippedCount = 0;
156
-
174
+
157
175
  // Iterate through all CLI configuration files
158
176
  for (const fileName of cliFiles) {
159
177
  const filePath = path.join(process.cwd(), fileName);
160
-
178
+
161
179
  try {
162
180
  const result = await this.syncToFile(filePath, fileName, skillsXml);
163
181
  if (result === 'synced') {
@@ -170,7 +188,7 @@ export class StigmergySkillManager {
170
188
  skippedCount++;
171
189
  }
172
190
  }
173
-
191
+
174
192
  // Output sync result summary
175
193
  console.log(`\n[OK] Sync completed:`);
176
194
  console.log(` - Updated: ${syncedCount} file(s)`);
@@ -2,9 +2,23 @@ const CLIHelpAnalyzer = require('./cli_help_analyzer');
2
2
  const { CLI_TOOLS, validateCLITool } = require('./cli_tools');
3
3
  const { errorHandler } = require('./error_handler');
4
4
 
5
+ // Valid CLI tools whitelist - excludes helper functions attached to CLI_TOOLS
6
+ const VALID_CLI_TOOLS = [
7
+ 'claude',
8
+ 'gemini',
9
+ 'qwen',
10
+ 'iflow',
11
+ 'codebuddy',
12
+ 'codex',
13
+ 'qodercli',
14
+ 'copilot',
15
+ 'kode'
16
+ ];
17
+
5
18
  class SmartRouter {
6
19
  constructor() {
7
20
  this.tools = CLI_TOOLS;
21
+ this.validTools = VALID_CLI_TOOLS;
8
22
  try {
9
23
  this.analyzer = new CLIHelpAnalyzer();
10
24
  this.analyzer.setCLITools(this.tools);
@@ -66,7 +80,8 @@ class SmartRouter {
66
80
  const inputLower = input.toLowerCase();
67
81
 
68
82
  // First, check for exact tool name matches (higher priority)
69
- for (const [toolName, _] of Object.entries(this.tools)) {
83
+ // Only iterate through valid CLI tools (exclude helper functions)
84
+ for (const toolName of this.validTools) {
70
85
  try {
71
86
  // Validate tool configuration
72
87
  validateCLITool(toolName);
@@ -99,7 +114,7 @@ class SmartRouter {
99
114
  // Then check for keyword matches (lower priority)
100
115
  // Only analyze tools that are likely to match to reduce overhead
101
116
  const potentialMatches = [];
102
- for (const [toolName, _] of Object.entries(this.tools)) {
117
+ for (const toolName of this.validTools) {
103
118
  // Quick check: if the input is very short, only analyze a few key tools
104
119
  if (input.length < 20) {
105
120
  // For short inputs, only analyze commonly used tools
@@ -230,6 +245,7 @@ class SmartRouter {
230
245
  codebuddy: ['codebuddy', 'buddy', 'assistant'],
231
246
  copilot: ['copilot', 'github', 'gh'],
232
247
  codex: ['codex', 'openai', 'gpt'], // Remove 'code' from here to avoid conflicts
248
+ kode: ['kode', 'multi-model', 'collaboration', 'multi模型']
233
249
  };
234
250
 
235
251
  if (toolSpecificKeywords[toolName]) {
@@ -256,6 +272,267 @@ class SmartRouter {
256
272
 
257
273
  return [...new Set(keywords)]; // Remove duplicates
258
274
  }
275
+
276
+ /**
277
+ * Enhanced smart routing with agent and skill support
278
+ */
279
+ async smartRouteEnhanced(userInput, options = {}) {
280
+ const input = userInput.trim();
281
+ const inputLower = input.toLowerCase();
282
+
283
+ // Enhanced routing priorities based on agent/skill detection
284
+ const routingResults = [];
285
+
286
+ // Analyze all valid CLI tools for agent/skill compatibility
287
+ for (const toolName of this.validTools) {
288
+ try {
289
+ validateCLITool(toolName);
290
+
291
+ // Get compatibility score for this tool
292
+ const compatibility = await this.getAgentSkillCompatibilityScore(toolName, input);
293
+
294
+ // Check for exact tool name matches (highest priority)
295
+ let matchScore = 0;
296
+ if (inputLower.includes(toolName)) {
297
+ matchScore = 1.0;
298
+ } else if (compatibility.score > 0) {
299
+ matchScore = compatibility.score;
300
+ }
301
+
302
+ if (matchScore > 0) {
303
+ // Get enhanced CLI pattern
304
+ const enhancedPattern = await this.getEnhancedCLIPattern(toolName);
305
+
306
+ // Generate optimized command
307
+ const optimizedCall = this.analyzer.generateOptimizedCall(toolName, input);
308
+
309
+ routingResults.push({
310
+ tool: toolName,
311
+ score: matchScore,
312
+ compatibility,
313
+ pattern: enhancedPattern,
314
+ optimizedCall,
315
+ reasons: this.getRoutingReasons(toolName, input, compatibility)
316
+ });
317
+ }
318
+ } catch (error) {
319
+ // Skip tools with configuration errors
320
+ continue;
321
+ }
322
+ }
323
+
324
+ // Sort by score (descending)
325
+ routingResults.sort((a, b) => b.score - a.score);
326
+
327
+ // Return best match or default
328
+ if (routingResults.length > 0) {
329
+ const bestMatch = routingResults[0];
330
+ return {
331
+ tool: bestMatch.tool,
332
+ prompt: bestMatch.optimizedCall?.optimizedPrompt || input,
333
+ confidence: bestMatch.score,
334
+ compatibility: bestMatch.compatibility,
335
+ optimizedCall: bestMatch.optimizedCall,
336
+ routingReasons: bestMatch.reasons,
337
+ alternativeOptions: routingResults.slice(1, 3) // Top 2 alternatives
338
+ };
339
+ }
340
+
341
+ // Default routing with enhanced pattern
342
+ const cleanInput = input
343
+ .replace(/^(use|please|help|using|with)\s*/i, '')
344
+ .trim();
345
+
346
+ return {
347
+ tool: this.defaultTool,
348
+ prompt: cleanInput,
349
+ confidence: 0.3,
350
+ compatibility: await this.getAgentSkillCompatibilityScore(this.defaultTool, input),
351
+ routingReasons: ['默认路由'],
352
+ alternativeOptions: []
353
+ };
354
+ }
355
+
356
+ /**
357
+ * Get agent/skill compatibility score for CLI tool
358
+ */
359
+ async getAgentSkillCompatibilityScore(toolName, prompt) {
360
+ try {
361
+ if (this.analyzer && this.analyzer.getAgentSkillCompatibilityScore) {
362
+ return this.analyzer.getAgentSkillCompatibilityScore(toolName, prompt);
363
+ }
364
+ } catch (error) {
365
+ if (process.env.DEBUG === 'true') {
366
+ console.log(`Error getting compatibility score for ${toolName}:`, error.message);
367
+ }
368
+ }
369
+
370
+ // Fallback scoring
371
+ return { score: 0.5, reasons: ['基础兼容性'] };
372
+ }
373
+
374
+ /**
375
+ * Get enhanced CLI pattern with agent/skill support
376
+ */
377
+ async getEnhancedCLIPattern(toolName) {
378
+ try {
379
+ if (this.analyzer && this.analyzer.getEnhancedCLIPattern) {
380
+ return await this.analyzer.getEnhancedCLIPattern(toolName);
381
+ }
382
+ } catch (error) {
383
+ if (process.env.DEBUG === 'true') {
384
+ console.log(`Error getting enhanced pattern for ${toolName}:`, error.message);
385
+ }
386
+ }
387
+
388
+ // Fallback to regular pattern
389
+ return await this.getOptimizedCLIPattern(toolName);
390
+ }
391
+
392
+ /**
393
+ * Get routing reasons for debugging
394
+ */
395
+ getRoutingReasons(toolName, input, compatibility) {
396
+ const reasons = [];
397
+
398
+ // Input-based reasons
399
+ const inputLower = input.toLowerCase();
400
+ if (inputLower.includes(toolName)) {
401
+ reasons.push(`输入包含工具名称: ${toolName}`);
402
+ }
403
+
404
+ // Compatibility-based reasons
405
+ if (compatibility.reasons) {
406
+ reasons.push(...compatibility.reasons);
407
+ }
408
+
409
+ // CLI-specific advantages
410
+ const cliAdvantages = {
411
+ 'claude': ['高质量输出', '自然语言理解'],
412
+ 'iflow': ['智能工作流', '中文优化'],
413
+ 'qwen': ['优秀的中文语义理解', '位置参数支持'],
414
+ 'codebuddy': ['明确的技能语法', '系统性强'],
415
+ 'qodercli': ['基础分析能力']
416
+ };
417
+
418
+ if (cliAdvantages[toolName]) {
419
+ reasons.push(...cliAdvantages[toolName]);
420
+ }
421
+
422
+ return reasons;
423
+ }
424
+
425
+ /**
426
+ * Generate fallback routing options when primary fails
427
+ */
428
+ async generateFallbackRoutes(primaryRoute, error) {
429
+ const fallbackRoutes = [];
430
+
431
+ // Get compatibility scores for all valid CLI tools
432
+ for (const toolName of this.validTools) {
433
+ if (toolName === primaryRoute.tool) {
434
+ continue; // Skip the failed tool
435
+ }
436
+
437
+ try {
438
+ const compatibility = await this.getAgentSkillCompatibilityScore(toolName, primaryRoute.prompt);
439
+ const enhancedPattern = await this.getEnhancedCLIPattern(toolName);
440
+
441
+ if (compatibility.score > 0.3) { // Only consider reasonably compatible tools
442
+ fallbackRoutes.push({
443
+ tool: toolName,
444
+ prompt: primaryRoute.prompt,
445
+ confidence: compatibility.score * 0.8, // Reduce confidence for fallbacks
446
+ compatibility,
447
+ pattern: enhancedPattern,
448
+ reason: `备用选项 (原工具失败: ${error.message.substring(0, 50)}...)`
449
+ });
450
+ }
451
+ } catch (routeError) {
452
+ continue; // Skip tools that can't be routed
453
+ }
454
+ }
455
+
456
+ // Sort by compatibility score
457
+ fallbackRoutes.sort((a, b) => b.confidence - a.confidence);
458
+
459
+ return fallbackRoutes.slice(0, 3); // Return top 3 fallbacks
460
+ }
461
+
462
+ /**
463
+ * Enhanced route execution with agent/skill support and fallback
464
+ */
465
+ async executeEnhancedRoute(userInput, maxRetries = 2) {
466
+ let currentRoute = await this.smartRouteEnhanced(userInput);
467
+ let retryCount = 0;
468
+
469
+ while (retryCount <= maxRetries) {
470
+ try {
471
+ if (process.env.DEBUG === 'true') {
472
+ console.log(`[DEBUG] Executing route: ${currentRoute.tool} with confidence ${currentRoute.confidence}`);
473
+ }
474
+
475
+ // Return the successful route
476
+ return currentRoute;
477
+
478
+ } catch (error) {
479
+ retryCount++;
480
+
481
+ if (retryCount > maxRetries) {
482
+ // All retries failed, throw the error
483
+ throw new Error(`Route execution failed after ${maxRetries} retries: ${error.message}`);
484
+ }
485
+
486
+ if (process.env.DEBUG === 'true') {
487
+ console.log(`[DEBUG] Route failed, generating fallback (attempt ${retryCount}):`, error.message);
488
+ }
489
+
490
+ // Generate fallback routes
491
+ const fallbackRoutes = await this.generateFallbackRoutes(currentRoute, error);
492
+
493
+ if (fallbackRoutes.length === 0) {
494
+ throw new Error('No fallback routes available');
495
+ }
496
+
497
+ // Use the best fallback route
498
+ currentRoute = fallbackRoutes[0];
499
+
500
+ if (process.env.DEBUG === 'true') {
501
+ console.log(`[DEBUG] Using fallback route: ${currentRoute.tool}`);
502
+ }
503
+ }
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Batch route multiple inputs efficiently
509
+ */
510
+ async batchRouteEnhanced(inputs, options = {}) {
511
+ const results = [];
512
+ const { parallel = true, maxConcurrent = 3 } = options;
513
+
514
+ if (parallel && inputs.length > 1) {
515
+ // Process in batches to avoid overwhelming the system
516
+ const batches = [];
517
+ for (let i = 0; i < inputs.length; i += maxConcurrent) {
518
+ batches.push(inputs.slice(i, i + maxConcurrent));
519
+ }
520
+
521
+ for (const batch of batches) {
522
+ const batchPromises = batch.map(input => this.smartRouteEnhanced(input));
523
+ const batchResults = await Promise.all(batchPromises);
524
+ results.push(...batchResults);
525
+ }
526
+ } else {
527
+ // Process sequentially
528
+ for (const input of inputs) {
529
+ const result = await this.smartRouteEnhanced(input);
530
+ results.push(result);
531
+ }
532
+ }
533
+
534
+ return results;
535
+ }
259
536
  }
260
537
 
261
538
  module.exports = SmartRouter;
package/src/index.js CHANGED
@@ -3,15 +3,21 @@
3
3
  /**
4
4
  * Stigmergy CLI - Multi-Agents Cross-AI CLI Tools Collaboration System
5
5
  * Unified Entry Point
6
- * International Version - Pure English & ANSI Only
7
- * Version: 1.0.94
6
+ * Version: 1.3.1-beta.0
7
+ *
8
+ * Migration Note:
9
+ * - The old monolithic router.js has been archived (2025-12-23)
10
+ * - Now using router-beta.js with modular command handlers
11
+ * - See archived_files/ROUTER_JS_ARCHIVE.md for details
8
12
  */
9
13
 
10
- // Import all components
14
+ // Import the modular router (router-beta.js)
15
+ const main = require('./cli/router-beta');
16
+
17
+ // Export core components for backward compatibility
11
18
  const MemoryManager = require('./core/memory_manager');
12
19
  const StigmergyInstaller = require('./core/installer');
13
20
  const { maxOfTwo, isAuthenticated } = require('./utils/helpers');
14
- const main = require('./cli/router');
15
21
 
16
22
  // Run the main application
17
23
  if (require.main === module) {