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
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Skills Management Commands
3
+ * Modular implementation for all skill-related commands
4
+ */
5
+
6
+ const chalk = require('chalk');
7
+ const { handleSkillCommand } = require('../../commands/skill-handler');
8
+
9
+ /**
10
+ * Handle main skill command with all subcommands
11
+ * @param {string} subcommand - Skill subcommand (install/list/read/remove/validate/sync)
12
+ * @param {Array} args - Additional arguments
13
+ * @param {Object} options - Command options
14
+ */
15
+ async function handleSkillMainCommand(subcommand, args = [], options = {}) {
16
+ try {
17
+ // Handle skill command aliases from router-beta.js
18
+ let action;
19
+ let skillArgs;
20
+
21
+ switch (subcommand) {
22
+ case 'skill-i':
23
+ action = 'install';
24
+ skillArgs = args;
25
+ break;
26
+ case 'skill-l':
27
+ action = 'list';
28
+ skillArgs = args;
29
+ break;
30
+ case 'skill-v':
31
+ // skill-v can be validate or read, based on parameters
32
+ action = args[0] && (args[0].endsWith('.md') || args[0].includes('/') || args[0].includes('\\'))
33
+ ? 'validate'
34
+ : 'read';
35
+ skillArgs = args;
36
+ break;
37
+ case 'skill-r':
38
+ action = 'read';
39
+ skillArgs = args;
40
+ break;
41
+ case 'skill-d':
42
+ case 'skill-m':
43
+ action = 'remove';
44
+ skillArgs = args;
45
+ break;
46
+ default:
47
+ action = subcommand || 'help';
48
+ skillArgs = args;
49
+ break;
50
+ }
51
+
52
+ const exitCode = await handleSkillCommand(action, skillArgs, {
53
+ verbose: options.verbose || false,
54
+ force: options.force || false,
55
+ autoSync: !options.noAutoSync
56
+ });
57
+
58
+ return { success: exitCode === 0, exitCode };
59
+ } catch (error) {
60
+ console.error(chalk.red(`[ERROR] Skill command failed: ${error.message}`));
61
+ return { success: false, error: error.message };
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Handle skill install command (skill-i alias)
67
+ * @param {Array} args - Arguments
68
+ * @param {Object} options - Options
69
+ */
70
+ async function handleSkillInstallCommand(args = [], options = {}) {
71
+ return await handleSkillMainCommand('install', args, options);
72
+ }
73
+
74
+ /**
75
+ * Handle skill list command (skill-l alias)
76
+ * @param {Array} args - Arguments
77
+ * @param {Object} options - Options
78
+ */
79
+ async function handleSkillListCommand(args = [], options = {}) {
80
+ return await handleSkillMainCommand('list', args, options);
81
+ }
82
+
83
+ /**
84
+ * Handle skill read command (skill-r alias)
85
+ * @param {Array} args - Arguments
86
+ * @param {Object} options - Options
87
+ */
88
+ async function handleSkillReadCommand(args = [], options = {}) {
89
+ return await handleSkillMainCommand('read', args, options);
90
+ }
91
+
92
+ /**
93
+ * Handle skill validate/read command (skill-v alias)
94
+ * @param {Array} args - Arguments
95
+ * @param {Object} options - Options
96
+ */
97
+ async function handleSkillValidateCommand(args = [], options = {}) {
98
+ return await handleSkillMainCommand('validate', args, options);
99
+ }
100
+
101
+ /**
102
+ * Handle skill remove command (skill-d, skill-m aliases)
103
+ * @param {Array} args - Arguments
104
+ * @param {Object} options - Options
105
+ */
106
+ async function handleSkillRemoveCommand(args = [], options = {}) {
107
+ return await handleSkillMainCommand('remove', args, options);
108
+ }
109
+
110
+ /**
111
+ * Print skills help information
112
+ */
113
+ function printSkillsHelp() {
114
+ console.log(chalk.cyan(`
115
+ šŸŽÆ Stigmergy Skills Management System
116
+
117
+ šŸ“‹ Available Commands:
118
+ stigmergy skill install <source> Install a skill from source
119
+ stigmergy skill list List all installed skills
120
+ stigmergy skill read <skill-name> Read skill content and description
121
+ stigmergy skill validate <path> Validate skill file or directory
122
+ stigmergy skill remove <skill-name> Remove installed skill
123
+ stigmergy skill sync Sync skills with remote repositories
124
+
125
+ šŸ”— Aliases (Shortcuts):
126
+ skill-i → skill install
127
+ skill-l → skill list
128
+ skill-r → skill read
129
+ skill-v → skill validate/read (auto-detect)
130
+ skill-d → skill remove
131
+ skill-m → skill remove (移除)
132
+
133
+ šŸ’” Examples:
134
+ stigmergy skill install anthropics/skills
135
+ stigmergy skill-i anthropics/skills # Using alias
136
+ stigmergy skill list
137
+ stigmergy skill-l # Using alias
138
+ stigmergy skill read canvas-design
139
+ stigmergy skill-v ./my-skill.md # Validate file
140
+ stigmergy skill-r docx # Using alias
141
+ stigmergy skill remove old-skill
142
+ stigmergy skill-d old-skill # Using alias
143
+
144
+ šŸ“š More Information:
145
+ Skills extend CLI tool capabilities with specialized workflows and tools.
146
+ Each skill contains instructions for specific tasks and integrations.
147
+ `));
148
+ }
149
+
150
+ module.exports = {
151
+ handleSkillMainCommand,
152
+ handleSkillInstallCommand,
153
+ handleSkillListCommand,
154
+ handleSkillReadCommand,
155
+ handleSkillValidateCommand,
156
+ handleSkillRemoveCommand,
157
+ printSkillsHelp
158
+ };
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Status Command Module
3
+ * Handles CLI tool status checking commands
4
+ */
5
+
6
+ const { CLI_TOOLS } = require('../../core/cli_tools');
7
+ const chalk = require('chalk');
8
+ const { formatToolStatus } = require('../utils/formatters');
9
+
10
+ /**
11
+ * Handle status command
12
+ * @param {Object} options - Command options
13
+ * @param {string} options.cli - Specific CLI to check
14
+ * @param {boolean} options.json - Output in JSON format
15
+ * @param {boolean} options.verbose - Verbose output
16
+ */
17
+ async function handleStatusCommand(options = {}) {
18
+ try {
19
+ const supportedTools = ['claude', 'gemini', 'qwen', 'codebuddy', 'codex', 'iflow', 'qodercli', 'copilot'];
20
+
21
+ if (options.cli) {
22
+ // Check specific CLI
23
+ if (!supportedTools.includes(options.cli)) {
24
+ console.log(chalk.red(`āŒ Unknown CLI tool: ${options.cli}`));
25
+ console.log(chalk.yellow(`Supported tools: ${supportedTools.join(', ')}`));
26
+ process.exit(1);
27
+ }
28
+
29
+ try {
30
+ const status = await CLI_TOOLS.checkInstallation(options.cli);
31
+
32
+ if (options.json) {
33
+ console.log(JSON.stringify(status, null, 2));
34
+ } else {
35
+ console.log(chalk.cyan(`šŸ“Š ${options.cli} Status:`));
36
+ console.log(formatToolStatus({ ...status, tool: options.cli }));
37
+
38
+ if (options.verbose && status.installed) {
39
+ if (status.version) {
40
+ console.log(chalk.gray(` šŸ“¦ Version: ${status.version}`));
41
+ }
42
+ if (status.path) {
43
+ console.log(chalk.gray(` šŸ“ Path: ${status.path}`));
44
+ }
45
+ if (status.lastChecked) {
46
+ console.log(chalk.gray(` šŸ• Last checked: ${status.lastChecked}`));
47
+ }
48
+ }
49
+ }
50
+ } catch (error) {
51
+ console.log(chalk.red(`āŒ Error checking ${options.cli}: ${error.message}`));
52
+ process.exit(1);
53
+ }
54
+ } else {
55
+ // Check all CLIs
56
+ console.log(chalk.cyan('šŸ“Š CLI Tools Status:'));
57
+
58
+ let installedCount = 0;
59
+ const results = [];
60
+
61
+ for (const tool of supportedTools) {
62
+ try {
63
+ const status = await CLI_TOOLS.checkInstallation(tool);
64
+ results.push({ tool, ...status });
65
+
66
+ if (status.installed) {
67
+ installedCount++;
68
+ console.log(chalk.green(` āœ… ${tool}`));
69
+ } else {
70
+ console.log(chalk.red(` āŒ ${tool}`));
71
+ }
72
+ } catch (error) {
73
+ results.push({ tool, installed: false, error: error.message });
74
+ console.log(chalk.yellow(` āš ļø ${tool}: Error checking status`));
75
+ }
76
+ }
77
+
78
+ // Summary
79
+ console.log('');
80
+ console.log(chalk.blue(`šŸ“ˆ Summary: ${installedCount}/${supportedTools.length} tools installed`));
81
+
82
+ if (installedCount < supportedTools.length) {
83
+ console.log(chalk.yellow('\nšŸ’” To install missing tools, run:'));
84
+ console.log(chalk.cyan(' stigmergy install'));
85
+
86
+ const missing = results.filter(r => !r.installed);
87
+ if (missing.length > 0 && missing.length < supportedTools.length) {
88
+ console.log(chalk.cyan(` stigmergy install --cli ${missing.map(r => r.tool).join(',')}`));
89
+ }
90
+ }
91
+
92
+ if (options.json) {
93
+ console.log('');
94
+ console.log(chalk.blue('šŸ“„ Detailed JSON output:'));
95
+ console.log(JSON.stringify(results, null, 2));
96
+ }
97
+ }
98
+ } catch (error) {
99
+ console.log(chalk.red(`āŒ Status check failed: ${error.message}`));
100
+ process.exit(1);
101
+ }
102
+ }
103
+
104
+ module.exports = {
105
+ handleStatusCommand
106
+ };
@@ -0,0 +1,301 @@
1
+ /**
2
+ * System Commands
3
+ * Modular implementation for clean, diagnostic, and other system commands
4
+ */
5
+
6
+ const chalk = require('chalk');
7
+ const fs = require('fs').promises;
8
+ const path = require('path');
9
+ const os = require('os');
10
+
11
+ /**
12
+ * Handle diagnostic command
13
+ * @param {Object} options - Command options
14
+ */
15
+ async function handleDiagnosticCommand(options = {}) {
16
+ try {
17
+ console.log(chalk.cyan('[DIAGNOSTIC] Stigmergy CLI System Diagnostic...\n'));
18
+
19
+ const results = {
20
+ system: {},
21
+ directories: {},
22
+ files: {},
23
+ permissions: {},
24
+ summary: { issues: 0, warnings: 0, ok: 0 }
25
+ };
26
+
27
+ // System information
28
+ console.log(chalk.blue('šŸ–„ļø System Information:'));
29
+ const systemInfo = {
30
+ platform: os.platform(),
31
+ arch: os.arch(),
32
+ nodeVersion: process.version,
33
+ memory: Math.round(os.totalmem() / 1024 / 1024) + ' MB',
34
+ freeMemory: Math.round(os.freemem() / 1024 / 1024) + ' MB',
35
+ homeDir: os.homedir(),
36
+ currentDir: process.cwd()
37
+ };
38
+
39
+ results.system = systemInfo;
40
+ Object.entries(systemInfo).forEach(([key, value]) => {
41
+ console.log(` ${key}: ${chalk.green(value)}`);
42
+ });
43
+
44
+ // Directory checks
45
+ console.log(chalk.blue('\nšŸ“ Directory Structure:'));
46
+ const directories = [
47
+ path.join(os.homedir(), '.stigmergy'),
48
+ path.join(os.homedir(), '.claude'),
49
+ path.join(os.homedir(), '.gemini'),
50
+ path.join(os.homedir(), '.qwen'),
51
+ path.join(process.cwd(), 'node_modules')
52
+ ];
53
+
54
+ for (const dir of directories) {
55
+ try {
56
+ const stats = await fs.stat(dir);
57
+ results.directories[dir] = { exists: true, size: stats.size };
58
+ console.log(` ${chalk.green('āœ…')} ${dir}`);
59
+ results.summary.ok++;
60
+ } catch (error) {
61
+ results.directories[dir] = { exists: false, error: error.code };
62
+ console.log(` ${chalk.yellow('āš ļø')} ${dir} (${error.code})`);
63
+ results.summary.warnings++;
64
+ }
65
+ }
66
+
67
+ // Permission checks
68
+ console.log(chalk.blue('\nšŸ” Permission Checks:'));
69
+ try {
70
+ await fs.access(process.cwd(), fs.constants.W_OK);
71
+ console.log(` ${chalk.green('āœ…')} Current directory writable`);
72
+ results.permissions.currentDir = true;
73
+ results.summary.ok++;
74
+ } catch (error) {
75
+ console.log(` ${chalk.red('āŒ')} Current directory not writable`);
76
+ results.permissions.currentDir = false;
77
+ results.summary.issues++;
78
+ }
79
+
80
+ try {
81
+ await fs.access(os.homedir(), fs.constants.W_OK);
82
+ console.log(` ${chalk.green('āœ…')} Home directory writable`);
83
+ results.permissions.homeDir = true;
84
+ results.summary.ok++;
85
+ } catch (error) {
86
+ console.log(` ${chalk.red('āŒ')} Home directory not writable`);
87
+ results.permissions.homeDir = false;
88
+ results.summary.issues++;
89
+ }
90
+
91
+ // Summary
92
+ console.log(chalk.blue('\nšŸ“Š Diagnostic Summary:'));
93
+ console.log(` Issues: ${chalk.red(results.summary.issues)}`);
94
+ console.log(` Warnings: ${chalk.yellow(results.summary.warnings)}`);
95
+ console.log(` OK: ${chalk.green(results.summary.ok)}`);
96
+
97
+ if (results.summary.issues > 0) {
98
+ console.log(chalk.red('\nāŒ Critical issues found - Fix recommended'));
99
+ console.log('Run: stigmergy fix-perms');
100
+ } else if (results.summary.warnings > 0) {
101
+ console.log(chalk.yellow('\nāš ļø Some warnings found - Check recommended'));
102
+ } else {
103
+ console.log(chalk.green('\nāœ… System looks healthy!'));
104
+ }
105
+
106
+ return { success: true, results };
107
+ } catch (error) {
108
+ console.error(chalk.red('[ERROR] Diagnostic failed:'), error.message);
109
+ return { success: false, error: error.message };
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Handle clean command
115
+ * @param {Object} options - Command options
116
+ */
117
+ async function handleCleanCommand(options = {}) {
118
+ try {
119
+ console.log(chalk.cyan('[CLEAN] Starting intelligent cache cleaning...\n'));
120
+
121
+ const stats = {
122
+ found: 0,
123
+ cleaned: 0,
124
+ skipped: 0,
125
+ totalSize: 0,
126
+ cleanedSize: 0,
127
+ errors: []
128
+ };
129
+
130
+ // Define cleanup targets with priority and safety levels
131
+ const cleanupTargets = [
132
+ // Priority 1: Always safe to clean
133
+ {
134
+ path: path.join(os.tmpdir(), 'stigmergy-*'),
135
+ priority: 1,
136
+ safe: true,
137
+ description: 'Stigmergy temporary files'
138
+ },
139
+ {
140
+ path: path.join(os.homedir(), '.stigmergy', 'cache'),
141
+ priority: 1,
142
+ safe: true,
143
+ description: 'Stigmergy cache'
144
+ },
145
+
146
+ // Priority 2: Generally safe (user data)
147
+ {
148
+ path: path.join(process.cwd(), 'node_modules', '.cache'),
149
+ priority: 2,
150
+ safe: true,
151
+ description: 'Project cache'
152
+ },
153
+
154
+ // Priority 3: CLI tool caches (may have permission issues)
155
+ {
156
+ path: path.join(os.homedir(), '.claude', 'cache'),
157
+ priority: 3,
158
+ safe: false,
159
+ description: 'Claude CLI cache'
160
+ },
161
+ {
162
+ path: path.join(os.homedir(), '.gemini', 'cache'),
163
+ priority: 3,
164
+ safe: false,
165
+ description: 'Gemini CLI cache'
166
+ },
167
+ {
168
+ path: path.join(os.homedir(), '.qwen', 'cache'),
169
+ priority: 3,
170
+ safe: false,
171
+ description: 'Qwen CLI cache'
172
+ }
173
+ ];
174
+
175
+ // Sort by priority
176
+ cleanupTargets.sort((a, b) => a.priority - b.priority);
177
+
178
+ console.log(chalk.blue('šŸ” Scanning cleanup targets...'));
179
+
180
+ for (const target of cleanupTargets) {
181
+ try {
182
+ const isPattern = target.path.includes('*');
183
+ let targetPaths = [];
184
+
185
+ if (isPattern) {
186
+ // Simple glob pattern handling
187
+ const baseDir = path.dirname(target.path);
188
+ const pattern = path.basename(target.path).replace('*', '');
189
+ try {
190
+ const files = await fs.readdir(baseDir);
191
+ targetPaths = files
192
+ .filter(file => file.includes(pattern))
193
+ .map(file => path.join(baseDir, file));
194
+ } catch (error) {
195
+ // Directory doesn't exist, skip silently
196
+ continue;
197
+ }
198
+ } else {
199
+ targetPaths = [target.path];
200
+ }
201
+
202
+ for (const targetPath of targetPaths) {
203
+ try {
204
+ const targetStats = await fs.stat(targetPath);
205
+ stats.found++;
206
+ stats.totalSize += targetStats.size;
207
+
208
+ if (!options.dryRun) {
209
+ // Attempt to clean with better error handling
210
+ try {
211
+ if (targetStats.isDirectory()) {
212
+ await fs.rmdir(targetPath, { recursive: true });
213
+ } else {
214
+ await fs.unlink(targetPath);
215
+ }
216
+ stats.cleaned++;
217
+ stats.cleanedSize += targetStats.size;
218
+
219
+ // Only show successful cleanups in normal mode
220
+ if (!options.quiet) {
221
+ console.log(` ${chalk.green('āœ…')} Cleaned ${target.description}`);
222
+ }
223
+ } catch (cleanError) {
224
+ // Silent failure for permission issues
225
+ stats.skipped++;
226
+ stats.errors.push({
227
+ path: targetPath,
228
+ error: cleanError.code,
229
+ safe: target.safe
230
+ });
231
+ }
232
+ } else {
233
+ // Dry run mode
234
+ console.log(` ${chalk.blue('šŸ”')} Would clean: ${target.description} (${Math.round(targetStats.size / 1024)} KB)`);
235
+ }
236
+ } catch (statError) {
237
+ // File might be locked or in use
238
+ stats.skipped++;
239
+ }
240
+ }
241
+ } catch (error) {
242
+ // Silently skip inaccessible targets
243
+ stats.skipped++;
244
+ }
245
+ }
246
+
247
+ // Show summary with user-friendly output
248
+ console.log(chalk.blue('\nšŸ“Š Cleanup Results:'));
249
+
250
+ if (stats.cleaned > 0) {
251
+ console.log(` ${chalk.green('āœ…')} Cleaned: ${stats.cleaned} items (${Math.round(stats.cleanedSize / 1024)} KB)`);
252
+ }
253
+
254
+ if (stats.skipped > 0) {
255
+ console.log(` ${chalk.yellow('āš ļø')} Skipped: ${stats.skipped} items (in use or permission protected)`);
256
+ }
257
+
258
+ // Show critical errors only (safe targets that failed)
259
+ const criticalErrors = stats.errors.filter(e => e.safe && e.error === 'EPERM');
260
+ if (criticalErrors.length > 0 && options.verbose) {
261
+ console.log(` ${chalk.red('āŒ')} Permission issues on ${criticalErrors.length} safe targets`);
262
+ }
263
+
264
+ // Final user-friendly message
265
+ if (!options.dryRun) {
266
+ if (stats.cleaned > 0) {
267
+ console.log(chalk.green('\nāœ… Cache cleanup completed successfully!'));
268
+ } else {
269
+ console.log(chalk.yellow('\nšŸ’” No cache files were available for cleaning'));
270
+ }
271
+
272
+ if (stats.skipped > 0 && stats.cleaned === 0) {
273
+ console.log(chalk.gray(' Some files were in use or require admin permissions'));
274
+ }
275
+ } else {
276
+ console.log(chalk.blue('\nšŸ’” Dry run completed. Run without --dry-run to actually clean.'));
277
+ }
278
+
279
+ return {
280
+ success: true,
281
+ stats: {
282
+ cleaned: stats.cleaned,
283
+ skipped: stats.skipped,
284
+ totalSize: Math.round(stats.totalSize / 1024),
285
+ cleanedSize: Math.round(stats.cleanedSize / 1024)
286
+ }
287
+ };
288
+
289
+ } catch (error) {
290
+ // Show only critical errors to user
291
+ if (options.verbose) {
292
+ console.error(chalk.red('[ERROR] Cache cleaning failed:'), error.message);
293
+ }
294
+ return { success: false, error: error.message };
295
+ }
296
+ }
297
+
298
+ module.exports = {
299
+ handleDiagnosticCommand,
300
+ handleCleanCommand
301
+ };