stigmergy 1.0.88 → 1.0.92

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.
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * iFlow Stigmergy Integration Test
5
+ * This script tests if iFlow can properly detect and use Stigmergy hooks
6
+ */
7
+
8
+ const fs = require('fs').promises;
9
+ const path = require('path');
10
+ const os = require('os');
11
+ const { spawn } = require('child_process');
12
+
13
+ class IFlowIntegrationTester {
14
+ constructor() {
15
+ this.iflowConfigDir = path.join(os.homedir(), '.iflow');
16
+ this.iflowHooksDir = path.join(this.iflowConfigDir, 'hooks');
17
+ }
18
+
19
+ // Check if iFlow config directory exists
20
+ async checkIFlowConfig() {
21
+ try {
22
+ await fs.access(this.iflowConfigDir);
23
+ return true;
24
+ } catch (error) {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ // Check if iFlow hooks directory exists and has Stigmergy files
30
+ async checkIFlowHooks() {
31
+ try {
32
+ await fs.access(this.iflowHooksDir);
33
+ const files = await fs.readdir(this.iflowHooksDir);
34
+ const stigmergyFiles = files.filter(file =>
35
+ file.includes('stigmergy') ||
36
+ file.includes('Stigmergy') ||
37
+ file.includes('hook') ||
38
+ file.includes('adapter')
39
+ );
40
+
41
+ return {
42
+ exists: true,
43
+ files: files,
44
+ stigmergyFiles: stigmergyFiles,
45
+ path: this.iflowHooksDir
46
+ };
47
+ } catch (error) {
48
+ return {
49
+ exists: false,
50
+ files: [],
51
+ stigmergyFiles: [],
52
+ path: this.iflowHooksDir
53
+ };
54
+ }
55
+ }
56
+
57
+ // Check if iFlow has hooks configuration
58
+ async checkIFlowHooksConfig() {
59
+ // Check multiple possible config locations
60
+ const configLocations = [
61
+ path.join(os.homedir(), '.config', 'iflow', 'hooks.yml'),
62
+ path.join(os.homedir(), '.config', 'iflow', 'hooks.yaml'),
63
+ path.join(os.homedir(), '.iflow', 'hooks.yml'),
64
+ path.join(os.homedir(), '.iflow', 'hooks.yaml'),
65
+ path.join(os.homedir(), '.iflow', 'config.yml'),
66
+ path.join(os.homedir(), '.iflow', 'settings.json')
67
+ ];
68
+
69
+ for (const configFile of configLocations) {
70
+ try {
71
+ await fs.access(configFile);
72
+ const content = await fs.readFile(configFile, 'utf8');
73
+ if (content.includes('hooks') || content.includes('plugins') || content.includes('CrossCLIHookAdapter')) {
74
+ return {
75
+ exists: true,
76
+ path: configFile,
77
+ hasHooksSection: true,
78
+ contentPreview: content.substring(0, 200)
79
+ };
80
+ }
81
+ } catch (error) {
82
+ // File doesn't exist, continue to next
83
+ }
84
+ }
85
+
86
+ return {
87
+ exists: false,
88
+ path: null,
89
+ hasHooksSection: false,
90
+ contentPreview: ''
91
+ };
92
+ }
93
+
94
+ // Test iFlow hooks command
95
+ async testIFlowHooksCommand() {
96
+ return new Promise((resolve) => {
97
+ const child = spawn('iflow', ['hooks'], {
98
+ stdio: 'pipe',
99
+ timeout: 10000
100
+ });
101
+
102
+ let stdout = '';
103
+ let stderr = '';
104
+
105
+ child.stdout.on('data', (data) => {
106
+ stdout += data.toString();
107
+ });
108
+
109
+ child.stderr.on('data', (data) => {
110
+ stderr += data.toString();
111
+ });
112
+
113
+ child.on('close', (code) => {
114
+ resolve({
115
+ success: code === 0,
116
+ code: code,
117
+ stdout: stdout,
118
+ stderr: stderr,
119
+ output: stdout + stderr
120
+ });
121
+ });
122
+
123
+ child.on('error', (error) => {
124
+ resolve({
125
+ success: false,
126
+ error: error.message,
127
+ stdout: '',
128
+ stderr: '',
129
+ output: ''
130
+ });
131
+ });
132
+ });
133
+ }
134
+
135
+ // Test iFlow plugin command
136
+ async testIFlowPluginCommand() {
137
+ return new Promise((resolve) => {
138
+ const child = spawn('iflow', ['plugins'], {
139
+ stdio: 'pipe',
140
+ timeout: 10000
141
+ });
142
+
143
+ let stdout = '';
144
+ let stderr = '';
145
+
146
+ child.stdout.on('data', (data) => {
147
+ stdout += data.toString();
148
+ });
149
+
150
+ child.stderr.on('data', (data) => {
151
+ stderr += data.toString();
152
+ });
153
+
154
+ child.on('close', (code) => {
155
+ resolve({
156
+ success: code === 0,
157
+ code: code,
158
+ stdout: stdout,
159
+ stderr: stderr,
160
+ output: stdout + stderr
161
+ });
162
+ });
163
+
164
+ child.on('error', (error) => {
165
+ resolve({
166
+ success: false,
167
+ error: error.message,
168
+ stdout: '',
169
+ stderr: '',
170
+ output: ''
171
+ });
172
+ });
173
+ });
174
+ }
175
+
176
+ // Run comprehensive iFlow integration test
177
+ async runIntegrationTest() {
178
+ console.log('iFlow Stigmergy Integration Test');
179
+ console.log('='.repeat(40));
180
+
181
+ // Test 1: Check iFlow configuration
182
+ console.log('\n[Test 1] Checking iFlow configuration...');
183
+ const configExists = await this.checkIFlowConfig();
184
+ console.log(` Config directory exists: ${configExists ? '✓' : '✗'}`);
185
+
186
+ // Test 2: Check iFlow hooks directory
187
+ console.log('\n[Test 2] Checking iFlow hooks directory...');
188
+ const hooksInfo = await this.checkIFlowHooks();
189
+ console.log(` Hooks directory exists: ${hooksInfo.exists ? '✓' : '✗'}`);
190
+ console.log(` Total files: ${hooksInfo.files.length}`);
191
+ console.log(` Stigmergy-related files: ${hooksInfo.stigmergyFiles.length}`);
192
+ if (hooksInfo.stigmergyFiles.length > 0) {
193
+ console.log(' Stigmergy files found:');
194
+ hooksInfo.stigmergyFiles.forEach(file => console.log(` - ${file}`));
195
+ }
196
+
197
+ // Test 3: Check hooks configuration
198
+ console.log('\n[Test 3] Checking hooks configuration...');
199
+ const hooksConfig = await this.checkIFlowHooksConfig();
200
+ console.log(` Config file exists: ${hooksConfig.exists ? '✓' : '✗'}`);
201
+ console.log(` Has hooks section: ${hooksConfig.hasHooksSection ? '✓' : '✗'}`);
202
+
203
+ // Test 4: Test iFlow hooks command
204
+ console.log('\n[Test 4] Testing iFlow hooks command...');
205
+ const hooksCommandResult = await this.testIFlowHooksCommand();
206
+ console.log(` Command success: ${hooksCommandResult.success ? '✓' : '✗'}`);
207
+ console.log(` Exit code: ${hooksCommandResult.code}`);
208
+ if (hooksCommandResult.output) {
209
+ const preview = hooksCommandResult.output.substring(0, 200);
210
+ console.log(` Output preview: ${preview}${hooksCommandResult.output.length > 200 ? '...' : ''}`);
211
+
212
+ // Check if Stigmergy is mentioned in output
213
+ if (hooksCommandResult.output.toLowerCase().includes('stigmergy')) {
214
+ console.log(' ✓ Stigmergy detected in hooks output');
215
+ } else {
216
+ console.log(' ✗ Stigmergy not detected in hooks output');
217
+ }
218
+ }
219
+
220
+ // Test 5: Test iFlow plugin command
221
+ console.log('\n[Test 5] Testing iFlow plugin command...');
222
+ const pluginCommandResult = await this.testIFlowPluginCommand();
223
+ console.log(` Command success: ${pluginCommandResult.success ? '✓' : '✗'}`);
224
+ console.log(` Exit code: ${pluginCommandResult.code}`);
225
+ if (pluginCommandResult.output) {
226
+ const preview = pluginCommandResult.output.substring(0, 200);
227
+ console.log(` Output preview: ${preview}${pluginCommandResult.output.length > 200 ? '...' : ''}`);
228
+
229
+ // Check if Stigmergy is mentioned in output
230
+ if (pluginCommandResult.output.toLowerCase().includes('stigmergy')) {
231
+ console.log(' ✓ Stigmergy detected in plugins output');
232
+ } else {
233
+ console.log(' ✗ Stigmergy not detected in plugins output');
234
+ }
235
+ }
236
+
237
+ // Summary
238
+ console.log('\n' + '='.repeat(40));
239
+ console.log('Integration Test Summary:');
240
+ console.log('='.repeat(40));
241
+
242
+ const results = {
243
+ configExists,
244
+ hooksDirectoryExists: hooksInfo.exists,
245
+ stigmergyHooksPresent: hooksInfo.stigmergyFiles.length > 0,
246
+ hooksCommandWorks: hooksCommandResult.success,
247
+ pluginsCommandWorks: pluginCommandResult.success,
248
+ stigmergyDetectedInHooks: hooksCommandResult.output.toLowerCase().includes('stigmergy'),
249
+ stigmergyDetectedInPlugins: pluginCommandResult.output.toLowerCase().includes('stigmergy')
250
+ };
251
+
252
+ Object.entries(results).forEach(([test, result]) => {
253
+ console.log(`${test}: ${result ? '✓ PASS' : '✗ FAIL'}`);
254
+ });
255
+
256
+ const passedTests = Object.values(results).filter(Boolean).length;
257
+ const totalTests = Object.values(results).length;
258
+
259
+ console.log(`\nOverall Result: ${passedTests}/${totalTests} tests passed`);
260
+
261
+ if (passedTests === totalTests) {
262
+ console.log('✓ iFlow Stigmergy integration is working correctly!');
263
+ } else if (passedTests > 0) {
264
+ console.log('⚠ iFlow Stigmergy integration is partially working.');
265
+ } else {
266
+ console.log('✗ iFlow Stigmergy integration is not working.');
267
+ }
268
+
269
+ return results;
270
+ }
271
+ }
272
+
273
+ // Run the test
274
+ async function runIFlowIntegrationTest() {
275
+ const tester = new IFlowIntegrationTester();
276
+ const results = await tester.runIntegrationTest();
277
+
278
+ return results;
279
+ }
280
+
281
+ // Export for use in other modules
282
+ module.exports = { IFlowIntegrationTester };
283
+
284
+ // Run if called directly
285
+ if (require.main === module) {
286
+ runIFlowIntegrationTest().then(results => {
287
+ process.exit(0);
288
+ }).catch(error => {
289
+ console.error('[Test Failed]:', error.message);
290
+ process.exit(1);
291
+ });
292
+ }
@@ -0,0 +1,362 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Improved Test for CLI Installation with Better Error Handling
5
+ * This test verifies installation commands with improved error handling
6
+ * and Windows compatibility
7
+ */
8
+
9
+ const { spawnSync, spawn } = require('child_process');
10
+ const path = require('path');
11
+ const os = require('os');
12
+
13
+ class ImprovedInstallTester {
14
+ constructor() {
15
+ this.testResults = [];
16
+ }
17
+
18
+ // Test 1: Verify npm availability with multiple methods
19
+ async testNpmAvailability() {
20
+ console.log('[TEST 1] Verifying npm availability with multiple methods...');
21
+
22
+ try {
23
+ // Method 1: Direct npm command
24
+ console.log(' Testing direct npm command...');
25
+ const npmDirect = spawnSync('npm', ['--version'], {
26
+ encoding: 'utf8',
27
+ timeout: 10000
28
+ });
29
+
30
+ console.log(` Direct npm - Status: ${npmDirect.status}`);
31
+ if (npmDirect.stdout) {
32
+ console.log(` Direct npm - Version: ${npmDirect.stdout.trim()}`);
33
+ }
34
+
35
+ // Method 2: npm through cmd.exe on Windows
36
+ const isWindows = process.platform === 'win32';
37
+ let npmThroughCmd = { status: null };
38
+
39
+ if (isWindows) {
40
+ console.log(' Testing npm through cmd.exe...');
41
+ npmThroughCmd = spawnSync('cmd.exe', ['/c', 'npm', '--version'], {
42
+ encoding: 'utf8',
43
+ timeout: 10000
44
+ });
45
+ console.log(` npm through cmd.exe - Status: ${npmThroughCmd.status}`);
46
+ }
47
+
48
+ // Method 3: Check PATH for npm
49
+ console.log(' Checking PATH for npm...');
50
+ const pathEnv = process.env.PATH || '';
51
+ const hasNpmInPath = pathEnv.toLowerCase().includes('npm');
52
+ console.log(` npm in PATH: ${hasNpmInPath}`);
53
+
54
+ const npmAvailable = npmDirect.status === 0 || npmThroughCmd.status === 0;
55
+
56
+ this.testResults.push({
57
+ name: 'npm Availability',
58
+ passed: npmAvailable,
59
+ details: `Direct: ${npmDirect.status === 0}, Cmd: ${npmThroughCmd.status === 0}, PATH: ${hasNpmInPath}`
60
+ });
61
+
62
+ return npmAvailable;
63
+ } catch (error) {
64
+ console.log(` ✗ Failed to check npm availability: ${error.message}`);
65
+ this.testResults.push({
66
+ name: 'npm Availability',
67
+ passed: false,
68
+ details: `Failed to check: ${error.message}`
69
+ });
70
+ return false;
71
+ }
72
+ }
73
+
74
+ // Test 2: Test Qoder CLI installation with shell options
75
+ async testQoderInstallationWithShellOptions() {
76
+ console.log('\n[TEST 2] Testing Qoder CLI installation with shell options...');
77
+
78
+ try {
79
+ const installCommand = 'npm install -g @qoder-ai/qodercli';
80
+ const commandParts = installCommand.split(' ');
81
+ const command = commandParts[0];
82
+ const args = commandParts.slice(1);
83
+
84
+ console.log(` Installation command: ${installCommand}`);
85
+
86
+ // Test 1: Without shell option
87
+ console.log(' Testing without shell option...');
88
+ const test1 = spawnSync(command, args, {
89
+ encoding: 'utf8',
90
+ timeout: 15000,
91
+ stdio: 'pipe'
92
+ });
93
+
94
+ console.log(` Without shell - Status: ${test1.status}`);
95
+
96
+ // Test 2: With shell=true
97
+ console.log(' Testing with shell=true...');
98
+ const test2 = spawnSync(command, args, {
99
+ encoding: 'utf8',
100
+ timeout: 15000,
101
+ stdio: 'pipe',
102
+ shell: true
103
+ });
104
+
105
+ console.log(` With shell - Status: ${test2.status}`);
106
+
107
+ // Test 3: On Windows, try cmd.exe explicitly
108
+ let test3 = { status: null };
109
+ if (process.platform === 'win32') {
110
+ console.log(' Testing with explicit cmd.exe...');
111
+ const fullCommand = [command, ...args].join(' ');
112
+ test3 = spawnSync('cmd.exe', ['/c', fullCommand], {
113
+ encoding: 'utf8',
114
+ timeout: 15000,
115
+ stdio: 'pipe'
116
+ });
117
+ console.log(` Explicit cmd.exe - Status: ${test3.status}`);
118
+ }
119
+
120
+ // Determine which method works
121
+ const worksWithoutShell = test1.status === 0;
122
+ const worksWithShell = test2.status === 0;
123
+ const worksWithCmd = test3.status === 0;
124
+
125
+ console.log(` Results - Without shell: ${worksWithoutShell}, With shell: ${worksWithShell}, With cmd: ${worksWithCmd}`);
126
+
127
+ this.testResults.push({
128
+ name: 'Qoder Installation Shell Options',
129
+ passed: worksWithoutShell || worksWithShell || worksWithCmd,
130
+ details: `Without shell: ${worksWithoutShell}, With shell: ${worksWithShell}, With cmd: ${worksWithCmd}`
131
+ });
132
+
133
+ return worksWithoutShell || worksWithShell || worksWithCmd;
134
+ } catch (error) {
135
+ console.log(` ✗ Failed to test installation with shell options: ${error.message}`);
136
+ this.testResults.push({
137
+ name: 'Qoder Installation Shell Options',
138
+ passed: false,
139
+ details: `Failed to test: ${error.message}`
140
+ });
141
+ return false;
142
+ }
143
+ }
144
+
145
+ // Test 3: Test spawn vs spawnSync behavior
146
+ async testSpawnVsSpawnSync() {
147
+ console.log('\n[TEST 3] Testing spawn vs spawnSync behavior...');
148
+
149
+ try {
150
+ const command = 'npm';
151
+ const args = ['--version'];
152
+
153
+ // Test spawnSync
154
+ console.log(' Testing spawnSync...');
155
+ const syncResult = spawnSync(command, args, {
156
+ encoding: 'utf8',
157
+ timeout: 10000,
158
+ shell: true
159
+ });
160
+
161
+ console.log(` spawnSync - Status: ${syncResult.status}`);
162
+
163
+ // Test spawn
164
+ console.log(' Testing spawn...');
165
+ const spawnResult = await new Promise((resolve) => {
166
+ const child = spawn(command, args, {
167
+ encoding: 'utf8',
168
+ timeout: 10000,
169
+ shell: true
170
+ });
171
+
172
+ let stdout = '';
173
+ let stderr = '';
174
+
175
+ child.stdout.on('data', (data) => {
176
+ stdout += data.toString();
177
+ });
178
+
179
+ child.stderr.on('data', (data) => {
180
+ stderr += data.toString();
181
+ });
182
+
183
+ child.on('close', (code) => {
184
+ resolve({
185
+ status: code,
186
+ stdout: stdout,
187
+ stderr: stderr
188
+ });
189
+ });
190
+
191
+ child.on('error', (error) => {
192
+ resolve({
193
+ status: null,
194
+ error: error.message
195
+ });
196
+ });
197
+
198
+ // Timeout
199
+ setTimeout(() => {
200
+ child.kill();
201
+ resolve({
202
+ status: null,
203
+ error: 'Timeout'
204
+ });
205
+ }, 11000);
206
+ });
207
+
208
+ console.log(` spawn - Status: ${spawnResult.status}`);
209
+ if (spawnResult.error) {
210
+ console.log(` spawn - Error: ${spawnResult.error}`);
211
+ }
212
+
213
+ const bothWork = syncResult.status === 0 && spawnResult.status === 0;
214
+
215
+ this.testResults.push({
216
+ name: 'Spawn vs SpawnSync',
217
+ passed: bothWork,
218
+ details: `spawnSync: ${syncResult.status}, spawn: ${spawnResult.status}`
219
+ });
220
+
221
+ return bothWork;
222
+ } catch (error) {
223
+ console.log(` ✗ Failed to test spawn behavior: ${error.message}`);
224
+ this.testResults.push({
225
+ name: 'Spawn vs SpawnSync',
226
+ passed: false,
227
+ details: `Failed to test: ${error.message}`
228
+ });
229
+ return false;
230
+ }
231
+ }
232
+
233
+ // Test 4: Verify current installation implementation issues
234
+ async testCurrentInstallationImplementation() {
235
+ console.log('\n[TEST 4] Verifying current installation implementation...');
236
+
237
+ try {
238
+ // Simulate the current implementation from main_english.js
239
+ const toolInfo = {
240
+ name: 'Qoder CLI',
241
+ install: 'npm install -g @qoder-ai/qodercli'
242
+ };
243
+
244
+ console.log(` Simulating current implementation for: ${toolInfo.name}`);
245
+ console.log(` Install command: ${toolInfo.install}`);
246
+
247
+ const installCmd = toolInfo.install.split(' ');
248
+ console.log(` Command parts: ${JSON.stringify(installCmd)}`);
249
+
250
+ // Current implementation (similar to lines 512-518 in main_english.js)
251
+ console.log(' Testing current implementation approach...');
252
+ const result = spawnSync(installCmd[0], installCmd.slice(1), {
253
+ encoding: 'utf8',
254
+ timeout: 300000, // 5 minutes
255
+ stdio: 'pipe', // Changed from 'inherit' to 'pipe' for testing
256
+ env: process.env
257
+ });
258
+
259
+ console.log(` Current implementation - Status: ${result.status}`);
260
+ if (result.error) {
261
+ console.log(` Current implementation - Error: ${result.error.message}`);
262
+ }
263
+ if (result.stderr && result.stderr.length > 0) {
264
+ const stderrPreview = result.stderr.substring(0, 200);
265
+ console.log(` Current implementation - Stderr preview: ${stderrPreview}${result.stderr.length > 200 ? '...' : ''}`);
266
+ }
267
+
268
+ // Test with shell=true
269
+ console.log(' Testing current implementation with shell=true...');
270
+ const resultWithShell = spawnSync(installCmd[0], installCmd.slice(1), {
271
+ encoding: 'utf8',
272
+ timeout: 300000,
273
+ stdio: 'pipe',
274
+ env: process.env,
275
+ shell: true
276
+ });
277
+
278
+ console.log(` Current implementation with shell - Status: ${resultWithShell.status}`);
279
+ if (resultWithShell.error) {
280
+ console.log(` Current implementation with shell - Error: ${resultWithShell.error.message}`);
281
+ }
282
+ if (resultWithShell.stderr && resultWithShell.stderr.length > 0) {
283
+ const stderrPreview = resultWithShell.stderr.substring(0, 200);
284
+ console.log(` Current implementation with shell - Stderr preview: ${stderrPreview}${resultWithShell.stderr.length > 200 ? '...' : ''}`);
285
+ }
286
+
287
+ this.testResults.push({
288
+ name: 'Current Installation Implementation',
289
+ passed: result.status === 0 || resultWithShell.status === 0,
290
+ details: `Without shell: ${result.status}, With shell: ${resultWithShell.status}`
291
+ });
292
+
293
+ return result.status === 0 || resultWithShell.status === 0;
294
+ } catch (error) {
295
+ console.log(` ✗ Failed to test current implementation: ${error.message}`);
296
+ this.testResults.push({
297
+ name: 'Current Installation Implementation',
298
+ passed: false,
299
+ details: `Failed to test: ${error.message}`
300
+ });
301
+ return false;
302
+ }
303
+ }
304
+
305
+ // Run all tests
306
+ async runAllTests() {
307
+ console.log('Improved CLI Installation Test');
308
+ console.log('='.repeat(40));
309
+
310
+ await this.testNpmAvailability();
311
+ await this.testQoderInstallationWithShellOptions();
312
+ await this.testSpawnVsSpawnSync();
313
+ await this.testCurrentInstallationImplementation();
314
+
315
+ // Summary
316
+ console.log('\n' + '='.repeat(40));
317
+ console.log('Improved Installation Test Summary:');
318
+ console.log('='.repeat(40));
319
+
320
+ let passedTests = 0;
321
+ this.testResults.forEach(result => {
322
+ console.log(`${result.name}: ${result.passed ? '✓ PASS' : '✗ FAIL'} - ${result.details}`);
323
+ if (result.passed) passedTests++;
324
+ });
325
+
326
+ console.log(`\nOverall Result: ${passedTests}/${this.testResults.length} tests passed`);
327
+
328
+ if (passedTests === this.testResults.length) {
329
+ console.log('✓ All improved installation tests passed!');
330
+ } else if (passedTests > 0) {
331
+ console.log('⚠ Some improved installation tests passed.');
332
+ } else {
333
+ console.log('✗ All improved installation tests failed.');
334
+ }
335
+
336
+ return {
337
+ totalTests: this.testResults.length,
338
+ passedTests: passedTests,
339
+ results: this.testResults
340
+ };
341
+ }
342
+ }
343
+
344
+ // Run the tests
345
+ async function runImprovedInstallTests() {
346
+ const tester = new ImprovedInstallTester();
347
+ const results = await tester.runAllTests();
348
+ return results;
349
+ }
350
+
351
+ // Export for use in other modules
352
+ module.exports = { ImprovedInstallTester };
353
+
354
+ // Run if called directly
355
+ if (require.main === module) {
356
+ runImprovedInstallTests().then(results => {
357
+ process.exit(results.passedTests === results.totalTests ? 0 : 1);
358
+ }).catch(error => {
359
+ console.error('[Test Failed]:', error.message);
360
+ process.exit(1);
361
+ });
362
+ }