myaidev-method 0.2.19 → 0.2.22

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 (31) hide show
  1. package/.claude/mcp/sparc-orchestrator-server.js +0 -0
  2. package/.claude/mcp/wordpress-server.js +0 -0
  3. package/CHANGELOG.md +123 -5
  4. package/README.md +205 -13
  5. package/TECHNICAL_ARCHITECTURE.md +64 -2
  6. package/bin/cli.js +169 -2
  7. package/dist/mcp/mcp-config.json +138 -1
  8. package/dist/mcp/openstack-server.js +1607 -0
  9. package/package.json +2 -2
  10. package/src/config/workflows.js +532 -0
  11. package/src/lib/payloadcms-utils.js +206 -0
  12. package/src/lib/visual-generation-utils.js +445 -294
  13. package/src/lib/workflow-installer.js +512 -0
  14. package/src/libs/security/authorization-checker.js +606 -0
  15. package/src/mcp/openstack-server.js +1607 -0
  16. package/src/scripts/openstack-setup.sh +110 -0
  17. package/src/scripts/security/environment-detect.js +425 -0
  18. package/src/templates/claude/agents/openstack-vm-manager.md +281 -0
  19. package/src/templates/claude/agents/osint-researcher.md +1075 -0
  20. package/src/templates/claude/agents/penetration-tester.md +908 -0
  21. package/src/templates/claude/agents/security-auditor.md +244 -0
  22. package/src/templates/claude/agents/security-setup.md +1094 -0
  23. package/src/templates/claude/agents/webapp-security-tester.md +581 -0
  24. package/src/templates/claude/commands/myai-configure.md +84 -0
  25. package/src/templates/claude/commands/myai-openstack.md +229 -0
  26. package/src/templates/claude/commands/sc:security-exploit.md +464 -0
  27. package/src/templates/claude/commands/sc:security-recon.md +281 -0
  28. package/src/templates/claude/commands/sc:security-report.md +756 -0
  29. package/src/templates/claude/commands/sc:security-scan.md +441 -0
  30. package/src/templates/claude/commands/sc:security-setup.md +501 -0
  31. package/src/templates/claude/mcp_config.json +44 -0
@@ -0,0 +1,512 @@
1
+ /**
2
+ * MyAIDev Method - Workflow Installer
3
+ *
4
+ * Handles modular installation of workflows with dependency resolution
5
+ */
6
+
7
+ import fs from 'fs/promises';
8
+ import path from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ import { WORKFLOWS, resolveWorkflowDependencies, validateWorkflow } from '../config/workflows.js';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ class WorkflowInstaller {
16
+ constructor(options = {}) {
17
+ this.projectRoot = options.projectRoot || process.cwd();
18
+ this.claudeDir = path.join(this.projectRoot, '.claude');
19
+ this.manifestPath = path.join(this.projectRoot, '.myaidev-manifest.json');
20
+ this.verbose = options.verbose || false;
21
+ this.dryRun = options.dryRun || false;
22
+ }
23
+
24
+ /**
25
+ * Log message if verbose mode is enabled
26
+ * @param {string} message - Message to log
27
+ */
28
+ log(message) {
29
+ if (this.verbose) {
30
+ console.log(message);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Read installation manifest
36
+ * @returns {Promise<Object>} Installation manifest
37
+ */
38
+ async readManifest() {
39
+ try {
40
+ const data = await fs.readFile(this.manifestPath, 'utf8');
41
+ return JSON.parse(data);
42
+ } catch (error) {
43
+ // Manifest doesn't exist, return empty
44
+ return {
45
+ version: '1.0.0',
46
+ installedWorkflows: [],
47
+ installedAt: new Date().toISOString(),
48
+ lastModified: new Date().toISOString()
49
+ };
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Write installation manifest
55
+ * @param {Object} manifest - Installation manifest
56
+ * @returns {Promise<void>}
57
+ */
58
+ async writeManifest(manifest) {
59
+ if (this.dryRun) {
60
+ this.log('[DRY RUN] Would write manifest to ' + this.manifestPath);
61
+ return;
62
+ }
63
+
64
+ manifest.lastModified = new Date().toISOString();
65
+ await fs.writeFile(
66
+ this.manifestPath,
67
+ JSON.stringify(manifest, null, 2),
68
+ 'utf8'
69
+ );
70
+ this.log('Updated installation manifest');
71
+ }
72
+
73
+ /**
74
+ * Resolve workflow dependencies
75
+ * @param {string[]} workflowNames - Workflow names to install
76
+ * @returns {string[]} Resolved workflow names in dependency order
77
+ */
78
+ resolveWorkflows(workflowNames) {
79
+ const resolved = new Set();
80
+ const order = [];
81
+
82
+ for (const name of workflowNames) {
83
+ const dependencies = resolveWorkflowDependencies(name, new Set());
84
+ for (const dep of dependencies) {
85
+ if (!resolved.has(dep)) {
86
+ order.push(dep);
87
+ resolved.add(dep);
88
+ }
89
+ }
90
+ }
91
+
92
+ return order;
93
+ }
94
+
95
+ /**
96
+ * Install agent files
97
+ * @param {string[]} agents - Agent names
98
+ * @returns {Promise<number>} Number of agents installed
99
+ */
100
+ async installAgents(agents) {
101
+ if (agents.length === 0) return 0;
102
+
103
+ const agentsDir = path.join(this.claudeDir, 'agents');
104
+ if (!this.dryRun) {
105
+ await fs.mkdir(agentsDir, { recursive: true });
106
+ }
107
+
108
+ let installed = 0;
109
+ for (const agent of agents) {
110
+ const sourcePath = path.join(__dirname, '..', 'agents', `${agent}.md`);
111
+ const targetPath = path.join(agentsDir, `${agent}.md`);
112
+
113
+ try {
114
+ if (this.dryRun) {
115
+ this.log(`[DRY RUN] Would copy agent: ${agent}`);
116
+ } else {
117
+ await fs.copyFile(sourcePath, targetPath);
118
+ this.log(`Installed agent: ${agent}`);
119
+ }
120
+ installed++;
121
+ } catch (error) {
122
+ console.warn(`Warning: Could not install agent ${agent}: ${error.message}`);
123
+ }
124
+ }
125
+
126
+ return installed;
127
+ }
128
+
129
+ /**
130
+ * Install command files
131
+ * @param {string[]} commands - Command names
132
+ * @returns {Promise<number>} Number of commands installed
133
+ */
134
+ async installCommands(commands) {
135
+ if (commands.length === 0) return 0;
136
+
137
+ const commandsDir = path.join(this.claudeDir, 'commands');
138
+ if (!this.dryRun) {
139
+ await fs.mkdir(commandsDir, { recursive: true });
140
+ }
141
+
142
+ let installed = 0;
143
+ for (const command of commands) {
144
+ const sourcePath = path.join(__dirname, '..', 'commands', `${command}.md`);
145
+ const targetPath = path.join(commandsDir, `${command}.md`);
146
+
147
+ try {
148
+ if (this.dryRun) {
149
+ this.log(`[DRY RUN] Would copy command: ${command}`);
150
+ } else {
151
+ await fs.copyFile(sourcePath, targetPath);
152
+ this.log(`Installed command: ${command}`);
153
+ }
154
+ installed++;
155
+ } catch (error) {
156
+ console.warn(`Warning: Could not install command ${command}: ${error.message}`);
157
+ }
158
+ }
159
+
160
+ return installed;
161
+ }
162
+
163
+ /**
164
+ * Install script files
165
+ * @param {string[]} scripts - Script paths
166
+ * @returns {Promise<number>} Number of scripts installed
167
+ */
168
+ async installScripts(scripts) {
169
+ if (scripts.length === 0) return 0;
170
+
171
+ let installed = 0;
172
+ for (const script of scripts) {
173
+ const sourcePath = path.join(__dirname, '..', 'scripts', script);
174
+ const targetPath = path.join(this.projectRoot, 'scripts', script);
175
+ const targetDir = path.dirname(targetPath);
176
+
177
+ try {
178
+ if (this.dryRun) {
179
+ this.log(`[DRY RUN] Would copy script: ${script}`);
180
+ } else {
181
+ await fs.mkdir(targetDir, { recursive: true });
182
+ await fs.copyFile(sourcePath, targetPath);
183
+ this.log(`Installed script: ${script}`);
184
+ }
185
+ installed++;
186
+ } catch (error) {
187
+ console.warn(`Warning: Could not install script ${script}: ${error.message}`);
188
+ }
189
+ }
190
+
191
+ return installed;
192
+ }
193
+
194
+ /**
195
+ * Install library files
196
+ * @param {string[]} libs - Library names
197
+ * @returns {Promise<number>} Number of libraries installed
198
+ */
199
+ async installLibraries(libs) {
200
+ if (libs.length === 0) return 0;
201
+
202
+ const libsDir = path.join(this.projectRoot, 'src', 'lib');
203
+ if (!this.dryRun) {
204
+ await fs.mkdir(libsDir, { recursive: true });
205
+ }
206
+
207
+ let installed = 0;
208
+ for (const lib of libs) {
209
+ const sourcePath = path.join(__dirname, lib);
210
+ const targetPath = path.join(libsDir, lib);
211
+
212
+ try {
213
+ if (this.dryRun) {
214
+ this.log(`[DRY RUN] Would copy library: ${lib}`);
215
+ } else {
216
+ await fs.copyFile(sourcePath, targetPath);
217
+ this.log(`Installed library: ${lib}`);
218
+ }
219
+ installed++;
220
+ } catch (error) {
221
+ console.warn(`Warning: Could not install library ${lib}: ${error.message}`);
222
+ }
223
+ }
224
+
225
+ return installed;
226
+ }
227
+
228
+ /**
229
+ * Install documentation files
230
+ * @param {string[]} docs - Documentation file names
231
+ * @returns {Promise<number>} Number of docs installed
232
+ */
233
+ async installDocs(docs) {
234
+ if (docs.length === 0) return 0;
235
+
236
+ const docsDir = path.join(this.projectRoot, 'docs');
237
+ if (!this.dryRun) {
238
+ await fs.mkdir(docsDir, { recursive: true });
239
+ }
240
+
241
+ let installed = 0;
242
+ for (const doc of docs) {
243
+ const sourcePath = path.join(__dirname, '..', '..', 'docs', doc);
244
+ const targetPath = path.join(docsDir, doc);
245
+
246
+ try {
247
+ if (this.dryRun) {
248
+ this.log(`[DRY RUN] Would copy doc: ${doc}`);
249
+ } else {
250
+ await fs.copyFile(sourcePath, targetPath);
251
+ this.log(`Installed documentation: ${doc}`);
252
+ }
253
+ installed++;
254
+ } catch (error) {
255
+ console.warn(`Warning: Could not install doc ${doc}: ${error.message}`);
256
+ }
257
+ }
258
+
259
+ return installed;
260
+ }
261
+
262
+ /**
263
+ * Configure MCP servers
264
+ * @param {string[]} mcpServers - MCP server names
265
+ * @returns {Promise<number>} Number of MCP servers configured
266
+ */
267
+ async configureMcpServers(mcpServers) {
268
+ if (mcpServers.length === 0) return 0;
269
+
270
+ const mcpConfigPath = path.join(this.claudeDir, 'mcp.json');
271
+
272
+ let config = { mcpServers: {} };
273
+ try {
274
+ const data = await fs.readFile(mcpConfigPath, 'utf8');
275
+ config = JSON.parse(data);
276
+ } catch (error) {
277
+ // Config doesn't exist, start fresh
278
+ }
279
+
280
+ let configured = 0;
281
+ for (const server of mcpServers) {
282
+ if (server === 'myaidev') {
283
+ config.mcpServers.myaidev = {
284
+ command: 'node',
285
+ args: [path.join(__dirname, 'mcp', 'wordpress-mcp-server.js')]
286
+ };
287
+ this.log(`Configured MCP server: ${server}`);
288
+ configured++;
289
+ }
290
+ }
291
+
292
+ if (configured > 0 && !this.dryRun) {
293
+ await fs.writeFile(mcpConfigPath, JSON.stringify(config, null, 2), 'utf8');
294
+ } else if (this.dryRun) {
295
+ this.log('[DRY RUN] Would configure MCP servers');
296
+ }
297
+
298
+ return configured;
299
+ }
300
+
301
+ /**
302
+ * Display environment variables needed
303
+ * @param {string[]} envVars - Environment variable names
304
+ */
305
+ displayEnvVars(envVars) {
306
+ if (envVars.length === 0) return;
307
+
308
+ console.log('\nāš ļø Environment Variables Required:');
309
+ for (const envVar of envVars) {
310
+ console.log(` - ${envVar}`);
311
+ }
312
+ console.log('\nConfigure these using: npx myaidev-method configure\n');
313
+ }
314
+
315
+ /**
316
+ * Install a single workflow
317
+ * @param {string} workflowName - Workflow name
318
+ * @returns {Promise<Object>} Installation results
319
+ */
320
+ async installWorkflow(workflowName) {
321
+ const workflow = WORKFLOWS[workflowName];
322
+ if (!workflow) {
323
+ throw new Error(`Unknown workflow: ${workflowName}`);
324
+ }
325
+
326
+ // Validate workflow definition
327
+ const validation = validateWorkflow(workflow);
328
+ if (!validation.valid) {
329
+ throw new Error(`Invalid workflow ${workflowName}: ${validation.errors.join(', ')}`);
330
+ }
331
+
332
+ this.log(`\nšŸ“¦ Installing workflow: ${workflow.name}`);
333
+
334
+ const results = {
335
+ workflow: workflowName,
336
+ agents: 0,
337
+ commands: 0,
338
+ scripts: 0,
339
+ libs: 0,
340
+ docs: 0,
341
+ mcpServers: 0
342
+ };
343
+
344
+ // Install components
345
+ results.agents = await this.installAgents(workflow.agents);
346
+ results.commands = await this.installCommands(workflow.commands);
347
+ results.scripts = await this.installScripts(workflow.scripts);
348
+ results.libs = await this.installLibraries(workflow.libs);
349
+ results.docs = await this.installDocs(workflow.docs);
350
+ results.mcpServers = await this.configureMcpServers(workflow.mcpServers);
351
+
352
+ // Display environment variables
353
+ this.displayEnvVars(workflow.envVars);
354
+
355
+ return results;
356
+ }
357
+
358
+ /**
359
+ * Install workflows with dependencies
360
+ * @param {string[]} workflowNames - Workflow names to install
361
+ * @returns {Promise<Object>} Installation summary
362
+ */
363
+ async install(workflowNames) {
364
+ console.log('šŸš€ MyAIDev Method - Modular Installation\n');
365
+
366
+ // Resolve dependencies
367
+ const resolvedWorkflows = this.resolveWorkflows(workflowNames);
368
+ this.log(`Resolved workflows: ${resolvedWorkflows.join(', ')}`);
369
+
370
+ // Read existing manifest
371
+ const manifest = await this.readManifest();
372
+ const alreadyInstalled = manifest.installedWorkflows || [];
373
+
374
+ // Filter out already installed workflows
375
+ const toInstall = resolvedWorkflows.filter(w => !alreadyInstalled.includes(w));
376
+
377
+ if (toInstall.length === 0) {
378
+ console.log('āœ… All requested workflows are already installed\n');
379
+ return { installed: [], alreadyInstalled };
380
+ }
381
+
382
+ console.log(`Installing: ${toInstall.join(', ')}\n`);
383
+
384
+ // Install each workflow
385
+ const results = [];
386
+ for (const workflowName of toInstall) {
387
+ try {
388
+ const result = await this.installWorkflow(workflowName);
389
+ results.push(result);
390
+
391
+ // Add to manifest
392
+ if (!manifest.installedWorkflows.includes(workflowName)) {
393
+ manifest.installedWorkflows.push(workflowName);
394
+ }
395
+ } catch (error) {
396
+ console.error(`āŒ Failed to install ${workflowName}: ${error.message}`);
397
+ }
398
+ }
399
+
400
+ // Update manifest
401
+ await this.writeManifest(manifest);
402
+
403
+ // Summary
404
+ console.log('\nāœ… Installation complete!\n');
405
+ console.log('Installed workflows:');
406
+ for (const result of results) {
407
+ const workflow = WORKFLOWS[result.workflow];
408
+ console.log(` • ${workflow.name}`);
409
+ console.log(` - ${result.agents} agents, ${result.commands} commands, ${result.scripts} scripts`);
410
+ }
411
+
412
+ return { installed: toInstall, alreadyInstalled, results };
413
+ }
414
+
415
+ /**
416
+ * Remove a workflow
417
+ * @param {string} workflowName - Workflow name to remove
418
+ * @returns {Promise<Object>} Removal results
419
+ */
420
+ async removeWorkflow(workflowName) {
421
+ const workflow = WORKFLOWS[workflowName];
422
+ if (!workflow) {
423
+ throw new Error(`Unknown workflow: ${workflowName}`);
424
+ }
425
+
426
+ console.log(`\nšŸ—‘ļø Removing workflow: ${workflow.name}`);
427
+
428
+ const manifest = await this.readManifest();
429
+
430
+ // Check if workflow is installed
431
+ if (!manifest.installedWorkflows.includes(workflowName)) {
432
+ console.log(`āš ļø Workflow ${workflowName} is not installed`);
433
+ return { removed: false };
434
+ }
435
+
436
+ // Check if other workflows depend on this one
437
+ const dependents = manifest.installedWorkflows.filter(w => {
438
+ const wf = WORKFLOWS[w];
439
+ return wf && wf.dependencies.includes(workflowName);
440
+ });
441
+
442
+ if (dependents.length > 0) {
443
+ throw new Error(
444
+ `Cannot remove ${workflowName}: Required by ${dependents.join(', ')}`
445
+ );
446
+ }
447
+
448
+ if (this.dryRun) {
449
+ console.log(`[DRY RUN] Would remove workflow: ${workflowName}`);
450
+ return { removed: true, dryRun: true };
451
+ }
452
+
453
+ // Remove files (in reverse order of installation)
454
+ // Note: We don't actually delete files to avoid breaking other workflows
455
+ // Just remove from manifest
456
+ manifest.installedWorkflows = manifest.installedWorkflows.filter(
457
+ w => w !== workflowName
458
+ );
459
+
460
+ await this.writeManifest(manifest);
461
+
462
+ console.log(`āœ… Removed workflow: ${workflow.name}\n`);
463
+ console.log('Note: Files were not deleted to preserve shared components');
464
+
465
+ return { removed: true };
466
+ }
467
+
468
+ /**
469
+ * List installed workflows
470
+ * @returns {Promise<Object>} List of installed workflows
471
+ */
472
+ async listInstalled() {
473
+ const manifest = await this.readManifest();
474
+ const installed = manifest.installedWorkflows || [];
475
+
476
+ console.log('\nšŸ“‹ Installed Workflows:\n');
477
+
478
+ if (installed.length === 0) {
479
+ console.log(' No workflows installed yet\n');
480
+ return { installed: [] };
481
+ }
482
+
483
+ for (const workflowName of installed) {
484
+ const workflow = WORKFLOWS[workflowName];
485
+ if (workflow) {
486
+ console.log(` • ${workflow.name} (${workflowName})`);
487
+ console.log(` ${workflow.description}`);
488
+ }
489
+ }
490
+
491
+ console.log('');
492
+ return { installed };
493
+ }
494
+
495
+ /**
496
+ * Show workflow status
497
+ * @returns {Promise<Object>} Workflow status
498
+ */
499
+ async status() {
500
+ const manifest = await this.readManifest();
501
+ const installed = manifest.installedWorkflows || [];
502
+ const available = Object.keys(WORKFLOWS);
503
+
504
+ console.log('\nšŸ“Š Workflow Status:\n');
505
+ console.log(`Installed: ${installed.length}/${available.length}`);
506
+ console.log(`Last modified: ${manifest.lastModified || 'Never'}\n`);
507
+
508
+ return { installed, available, manifest };
509
+ }
510
+ }
511
+
512
+ export default WorkflowInstaller;