myaidev-method 0.3.3 → 0.3.5

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 (132) hide show
  1. package/.claude-plugin/plugin.json +0 -1
  2. package/.env.example +5 -4
  3. package/CHANGELOG.md +2 -2
  4. package/CONTENT_CREATION_GUIDE.md +489 -3211
  5. package/DEVELOPER_USE_CASES.md +1 -1
  6. package/MODULAR_INSTALLATION.md +2 -2
  7. package/README.md +39 -33
  8. package/TECHNICAL_ARCHITECTURE.md +1 -1
  9. package/USER_GUIDE.md +242 -190
  10. package/agents/content-editor-agent.md +90 -0
  11. package/agents/content-planner-agent.md +97 -0
  12. package/agents/content-research-agent.md +62 -0
  13. package/agents/content-seo-agent.md +101 -0
  14. package/agents/content-writer-agent.md +69 -0
  15. package/agents/infographic-analyzer-agent.md +63 -0
  16. package/agents/infographic-designer-agent.md +72 -0
  17. package/bin/cli.js +777 -535
  18. package/{content-rules.example.md → content-rules-example.md} +2 -2
  19. package/dist/mcp/health-check.js +82 -68
  20. package/dist/mcp/mcp-config.json +8 -0
  21. package/dist/mcp/openstack-server.js +1746 -1262
  22. package/dist/server/.tsbuildinfo +1 -1
  23. package/extension.json +21 -4
  24. package/package.json +181 -184
  25. package/skills/company-config/SKILL.md +133 -0
  26. package/skills/configure/SKILL.md +1 -1
  27. package/skills/myai-configurator/SKILL.md +77 -0
  28. package/skills/myai-configurator/content-creation-configurator/SKILL.md +516 -0
  29. package/skills/myai-configurator/content-maintenance-configurator/SKILL.md +397 -0
  30. package/skills/myai-content-enrichment/SKILL.md +114 -0
  31. package/skills/myai-content-ideation/SKILL.md +288 -0
  32. package/skills/myai-content-ideation/evals/evals.json +182 -0
  33. package/skills/myai-content-production-coordinator/SKILL.md +946 -0
  34. package/skills/{content-rules-setup → myai-content-rules-setup}/SKILL.md +1 -1
  35. package/skills/{content-verifier → myai-content-verifier}/SKILL.md +1 -1
  36. package/skills/myai-content-writer/SKILL.md +333 -0
  37. package/skills/myai-content-writer/agents/editor-agent.md +138 -0
  38. package/skills/myai-content-writer/agents/planner-agent.md +121 -0
  39. package/skills/myai-content-writer/agents/research-agent.md +83 -0
  40. package/skills/myai-content-writer/agents/seo-agent.md +139 -0
  41. package/skills/myai-content-writer/agents/visual-planner-agent.md +110 -0
  42. package/skills/myai-content-writer/agents/writer-agent.md +85 -0
  43. package/skills/{infographic → myai-infographic}/SKILL.md +1 -1
  44. package/skills/myai-proprietary-content-verifier/SKILL.md +175 -0
  45. package/skills/myai-proprietary-content-verifier/evals/evals.json +36 -0
  46. package/skills/myai-skill-builder/SKILL.md +699 -0
  47. package/skills/myai-skill-builder/agents/analyzer-agent.md +137 -0
  48. package/skills/myai-skill-builder/agents/comparator-agent.md +77 -0
  49. package/skills/myai-skill-builder/agents/grader-agent.md +103 -0
  50. package/skills/myai-skill-builder/assets/eval_review.html +131 -0
  51. package/skills/myai-skill-builder/references/schemas.md +211 -0
  52. package/skills/myai-skill-builder/scripts/aggregate_benchmark.py +190 -0
  53. package/skills/myai-skill-builder/scripts/generate_review.py +381 -0
  54. package/skills/myai-skill-builder/scripts/package_skill.py +91 -0
  55. package/skills/myai-skill-builder/scripts/run_eval.py +105 -0
  56. package/skills/myai-skill-builder/scripts/run_loop.py +211 -0
  57. package/skills/myai-skill-builder/scripts/utils.py +123 -0
  58. package/skills/myai-visual-generator/SKILL.md +125 -0
  59. package/skills/myai-visual-generator/evals/evals.json +155 -0
  60. package/skills/myai-visual-generator/references/infographic-pipeline.md +73 -0
  61. package/skills/myai-visual-generator/references/research-visuals.md +57 -0
  62. package/skills/myai-visual-generator/references/services.md +89 -0
  63. package/skills/myai-visual-generator/scripts/visual-generation-utils.js +1272 -0
  64. package/skills/myaidev-analyze/agents/dependency-mapper-agent.md +236 -0
  65. package/skills/myaidev-analyze/agents/pattern-detector-agent.md +240 -0
  66. package/skills/myaidev-analyze/agents/structure-scanner-agent.md +171 -0
  67. package/skills/myaidev-analyze/agents/tech-profiler-agent.md +291 -0
  68. package/skills/myaidev-architect/agents/compliance-checker-agent.md +287 -0
  69. package/skills/myaidev-architect/agents/requirements-analyst-agent.md +194 -0
  70. package/skills/myaidev-architect/agents/system-designer-agent.md +315 -0
  71. package/skills/myaidev-coder/agents/implementer-agent.md +185 -0
  72. package/skills/myaidev-coder/agents/integration-agent.md +168 -0
  73. package/skills/myaidev-coder/agents/pattern-scanner-agent.md +161 -0
  74. package/skills/myaidev-coder/agents/self-reviewer-agent.md +168 -0
  75. package/skills/myaidev-debug/agents/fix-agent-debug.md +317 -0
  76. package/skills/myaidev-debug/agents/hypothesis-agent.md +226 -0
  77. package/skills/myaidev-debug/agents/investigator-agent.md +250 -0
  78. package/skills/myaidev-debug/agents/symptom-collector-agent.md +231 -0
  79. package/skills/myaidev-documenter/agents/code-reader-agent.md +172 -0
  80. package/skills/myaidev-documenter/agents/doc-validator-agent.md +174 -0
  81. package/skills/myaidev-documenter/agents/doc-writer-agent.md +379 -0
  82. package/skills/myaidev-figma/SKILL.md +212 -0
  83. package/skills/myaidev-figma/capture.js +133 -0
  84. package/skills/myaidev-figma/crawl.js +130 -0
  85. package/skills/myaidev-figma-configure/SKILL.md +130 -0
  86. package/skills/myaidev-migrate/agents/migration-planner-agent.md +237 -0
  87. package/skills/myaidev-migrate/agents/migration-writer-agent.md +248 -0
  88. package/skills/myaidev-migrate/agents/schema-analyzer-agent.md +190 -0
  89. package/skills/myaidev-performance/agents/benchmark-agent.md +281 -0
  90. package/skills/myaidev-performance/agents/optimizer-agent.md +277 -0
  91. package/skills/myaidev-performance/agents/profiler-agent.md +252 -0
  92. package/skills/myaidev-refactor/agents/refactor-executor-agent.md +221 -0
  93. package/skills/myaidev-refactor/agents/refactor-planner-agent.md +213 -0
  94. package/skills/myaidev-refactor/agents/regression-guard-agent.md +242 -0
  95. package/skills/myaidev-refactor/agents/smell-detector-agent.md +233 -0
  96. package/skills/myaidev-reviewer/agents/auto-fixer-agent.md +238 -0
  97. package/skills/myaidev-reviewer/agents/code-analyst-agent.md +220 -0
  98. package/skills/myaidev-reviewer/agents/security-scanner-agent.md +262 -0
  99. package/skills/myaidev-tester/agents/coverage-analyst-agent.md +163 -0
  100. package/skills/myaidev-tester/agents/tdd-driver-agent.md +242 -0
  101. package/skills/myaidev-tester/agents/test-runner-agent.md +176 -0
  102. package/skills/myaidev-tester/agents/test-strategist-agent.md +154 -0
  103. package/skills/myaidev-tester/agents/test-writer-agent.md +242 -0
  104. package/skills/myaidev-workflow/agents/analyzer-agent.md +317 -0
  105. package/skills/myaidev-workflow/agents/coordinator-agent.md +253 -0
  106. package/skills/openstack-manager/SKILL.md +1 -1
  107. package/skills/payloadcms-publisher/SKILL.md +141 -77
  108. package/skills/payloadcms-publisher/references/field-mapping.md +142 -0
  109. package/skills/payloadcms-publisher/references/lexical-format.md +97 -0
  110. package/skills/security-auditor/SKILL.md +1 -1
  111. package/src/cli/commands/addon.js +184 -123
  112. package/src/config/workflows.js +172 -228
  113. package/src/lib/ascii-banner.js +197 -182
  114. package/src/lib/{content-coordinator.js → content-production-coordinator.js} +649 -459
  115. package/src/lib/installation-detector.js +93 -59
  116. package/src/lib/payloadcms-utils.js +285 -510
  117. package/src/lib/update-manager.js +120 -61
  118. package/src/lib/workflow-installer.js +55 -0
  119. package/src/mcp/health-check.js +82 -68
  120. package/src/mcp/openstack-server.js +1746 -1262
  121. package/src/scripts/configure-visual-apis.js +224 -173
  122. package/src/scripts/configure-wordpress-mcp.js +96 -66
  123. package/src/scripts/init/install.js +109 -85
  124. package/src/scripts/init-project.js +138 -67
  125. package/src/scripts/utils/write-content.js +67 -52
  126. package/src/scripts/wordpress/publish-to-wordpress.js +128 -128
  127. package/src/templates/claude/CLAUDE.md +131 -0
  128. package/hooks/hooks.json +0 -26
  129. package/skills/content-coordinator/SKILL.md +0 -130
  130. package/skills/content-enrichment/SKILL.md +0 -80
  131. package/skills/content-writer/SKILL.md +0 -285
  132. package/skills/visual-generator/SKILL.md +0 -140
@@ -9,6 +9,11 @@ import { createHash } from 'crypto';
9
9
  * Handles intelligent updates with conflict resolution
10
10
  */
11
11
 
12
+ /** Pluralize helper: returns "1 file" or "N files" */
13
+ function pf(count) {
14
+ return `${count} file${count === 1 ? '' : 's'}`;
15
+ }
16
+
12
17
  /**
13
18
  * Display ASCII art branding banner
14
19
  */
@@ -234,7 +239,11 @@ export async function updateComponent(componentType, projectDir, cliType, source
234
239
  break;
235
240
  case 'mcp':
236
241
  targetDir = path.join(projectDir, `.${cliType}`, 'mcp');
237
- sourceSubDir = path.join(sourceDir, '.claude', 'mcp');
242
+ sourceSubDir = path.join(sourceDir, 'src', 'mcp');
243
+ break;
244
+ case 'config':
245
+ targetDir = path.join(projectDir, `.${cliType}`);
246
+ sourceSubDir = path.join(sourceDir, 'src', 'templates', 'claude');
238
247
  break;
239
248
  case 'docs':
240
249
  targetDir = projectDir;
@@ -417,6 +426,10 @@ async function getLineCount(filePath) {
417
426
  async function getComponentFiles(componentType, dir) {
418
427
  if (!await fs.pathExists(dir)) return [];
419
428
 
429
+ if (componentType === 'config') {
430
+ return ['CLAUDE.md'];
431
+ }
432
+
420
433
  if (componentType === 'docs') {
421
434
  return ['USER_GUIDE.md', 'PUBLISHING_GUIDE.md', 'COOLIFY_DEPLOYMENT.md', 'DEV_WORKFLOW_GUIDE.md',
422
435
  'MCP_INTEGRATION.md', 'WORDPRESS_ADMIN_SCRIPTS.md', 'TECHNICAL_ARCHITECTURE.md',
@@ -488,7 +501,11 @@ export async function generateChangeSummary(components, projectDir, cliType, sou
488
501
  break;
489
502
  case 'mcp':
490
503
  targetDir = path.join(projectDir, `.${cliType}`, 'mcp');
491
- sourceSubDir = path.join(sourceDir, '.claude', 'mcp');
504
+ sourceSubDir = path.join(sourceDir, 'src', 'mcp');
505
+ break;
506
+ case 'config':
507
+ targetDir = path.join(projectDir, `.${cliType}`);
508
+ sourceSubDir = path.join(sourceDir, 'src', 'templates', 'claude');
492
509
  break;
493
510
  case 'docs':
494
511
  targetDir = projectDir;
@@ -592,16 +609,41 @@ export function displayChangeSummary(summary, currentVersion, newVersion) {
592
609
  // Change summary
593
610
  console.log(chalk.cyan('║') + chalk.white.bold(' 📊 CHANGE SUMMARY'.padEnd(boxWidth)) + chalk.cyan('║'));
594
611
 
595
- const unchangedLine = ` ├─ ✅ Unchanged: ${summary.unchanged.length} files (auto-skip)`;
596
- const newLine = ` ├─ 🆕 New files: ${summary.new.length} files (auto-add)`;
597
- const modifiedLine = ` ├─ ⚠️ Modified: ${summary.modified.length} files (need decision)`;
598
- const deletedLine = ` └─ 🗑️ Removed: ${summary.deleted.length} files (optional delete)`;
612
+ const unchangedLine = ` ├─ ✅ Unchanged: ${pf(summary.unchanged.length)} (no action needed)`;
613
+ const newLine = ` ├─ 🆕 New: ${pf(summary.new.length)} (will be added)`;
614
+ const modifiedLine = ` ├─ ⚠️ Modified: ${pf(summary.modified.length)} (need decision)`;
615
+ const deletedLine = ` └─ 🗑️ Removed: ${pf(summary.deleted.length)} (optional cleanup)`;
599
616
 
600
617
  console.log(chalk.cyan('║') + chalk.gray(unchangedLine.padEnd(boxWidth)) + chalk.cyan('║'));
601
618
  console.log(chalk.cyan('║') + chalk.green(newLine.padEnd(boxWidth)) + chalk.cyan('║'));
602
619
  console.log(chalk.cyan('║') + chalk.yellow(modifiedLine.padEnd(boxWidth)) + chalk.cyan('║'));
603
620
  console.log(chalk.cyan('║') + chalk.red(deletedLine.padEnd(boxWidth)) + chalk.cyan('║'));
604
621
 
622
+ // Show new skills if any (users care about what's new)
623
+ const newSkills = summary.new
624
+ .filter(f => f.componentType === 'skills' && f.file.endsWith('SKILL.md'))
625
+ .map(f => f.file.split('/')[0]);
626
+ if (newSkills.length > 0) {
627
+ console.log(chalk.cyan('║') + ' '.repeat(boxWidth) + chalk.cyan('║'));
628
+ const newSkillsLabel = ` 🎯 New skills available:`;
629
+ console.log(chalk.cyan('║') + chalk.white.bold(newSkillsLabel.padEnd(boxWidth)) + chalk.cyan('║'));
630
+ // Wrap skill names into lines that fit the box (max ~63 chars per line)
631
+ const maxLineLen = boxWidth - 6; // " " prefix + 1 padding
632
+ let currentLine = '';
633
+ for (let i = 0; i < newSkills.length; i++) {
634
+ const separator = currentLine ? ', ' : '';
635
+ if ((currentLine + separator + newSkills[i]).length > maxLineLen) {
636
+ console.log(chalk.cyan('║') + chalk.green(` ${currentLine}`.padEnd(boxWidth)) + chalk.cyan('║'));
637
+ currentLine = newSkills[i];
638
+ } else {
639
+ currentLine += separator + newSkills[i];
640
+ }
641
+ }
642
+ if (currentLine) {
643
+ console.log(chalk.cyan('║') + chalk.green(` ${currentLine}`.padEnd(boxWidth)) + chalk.cyan('║'));
644
+ }
645
+ }
646
+
605
647
  // Show modified files by category if any
606
648
  if (summary.modified.length > 0) {
607
649
  console.log(chalk.cyan('║') + ' '.repeat(boxWidth) + chalk.cyan('║'));
@@ -612,7 +654,7 @@ export function displayChangeSummary(summary, currentVersion, newVersion) {
612
654
  if (data.modified.length === 0) continue;
613
655
 
614
656
  const catName = category.toUpperCase();
615
- const catLine = ` │ ${catName} (${data.modified.length} files)`;
657
+ const catLine = ` │ ${catName} (${pf(data.modified.length)})`;
616
658
  console.log(chalk.cyan('║') + chalk.white.bold(catLine.padEnd(boxWidth)) + chalk.cyan('║'));
617
659
 
618
660
  for (let i = 0; i < data.modified.length && i < 3; i++) {
@@ -708,7 +750,7 @@ export async function promptCategoryDecision(category, files) {
708
750
  const botBorder = '╚' + '═'.repeat(boxWidth) + '╝';
709
751
 
710
752
  console.log(chalk.cyan(topBorder));
711
- console.log(chalk.cyan('║') + chalk.white.bold(` ${category.toUpperCase()} (${files.length} modified files)`.padEnd(boxWidth)) + chalk.cyan('║'));
753
+ console.log(chalk.cyan('║') + chalk.white.bold(` ${category.toUpperCase()} (${pf(files.length)} modified)`.padEnd(boxWidth)) + chalk.cyan('║'));
712
754
  console.log(chalk.cyan(midBorder));
713
755
 
714
756
  for (let i = 0; i < files.length; i++) {
@@ -730,9 +772,9 @@ export async function promptCategoryDecision(category, files) {
730
772
  name: 'decision',
731
773
  message: `What would you like to do with ${category.toUpperCase()}?`,
732
774
  choices: [
733
- { name: `Keep all my customizations (skip ${files.length} files)`, value: 'keep' },
734
- { name: `Update all (replace ${files.length} files, backup originals)`, value: 'update' },
735
- { name: `Review these ${files.length} files individually`, value: 'individual' }
775
+ { name: `Keep all my customizations (skip ${pf(files.length)})`, value: 'keep' },
776
+ { name: `Update all (replace ${pf(files.length)}, backup originals)`, value: 'update' },
777
+ { name: `Review ${files.length === 1 ? 'this file' : `these ${files.length} files`} individually`, value: 'individual' }
736
778
  ]
737
779
  }
738
780
  ]);
@@ -755,32 +797,24 @@ export async function executeSmartUpdate(summary, backupDir, options = {}) {
755
797
  backedUp: []
756
798
  };
757
799
 
758
- // Add all new files
800
+ // Add all new files — always show progress
759
801
  for (const f of summary.new) {
760
802
  await fs.ensureDir(path.dirname(f.targetPath));
761
803
  await fs.copy(f.sourcePath, f.targetPath);
762
804
  results.added.push(f.file);
763
- if (options.verbose) {
764
- console.log(chalk.green(` ➕ ${f.file} (new)`));
765
- }
805
+ console.log(chalk.green(` ➕ ${f.file}`));
766
806
  }
767
807
 
768
- // Keep all modified files (smart = preserve customizations)
808
+ // Keep all modified files (smart = preserve customizations) — always show
769
809
  for (const f of summary.modified) {
770
- // Create backup
771
810
  const backupPath = path.join(backupDir, f.componentType, f.file);
772
811
  await fs.ensureDir(path.dirname(backupPath));
773
812
  await fs.copy(f.targetPath, backupPath);
774
813
  results.backedUp.push(f.file);
775
814
  results.kept.push(f.file);
776
- if (options.verbose) {
777
- console.log(chalk.gray(` 🛡️ ${f.file} (kept, backup created)`));
778
- }
815
+ console.log(chalk.gray(` 🛡️ ${f.file} (kept, backup created)`));
779
816
  }
780
817
 
781
- // Update unchanged files (they're identical so no-op, but count them)
782
- results.updated = summary.unchanged.map(f => f.file);
783
-
784
818
  return results;
785
819
  }
786
820
 
@@ -799,30 +833,24 @@ export async function executeAcceptAll(summary, backupDir, options = {}) {
799
833
  backedUp: []
800
834
  };
801
835
 
802
- // Add all new files
836
+ // Add all new files — always show progress
803
837
  for (const f of summary.new) {
804
838
  await fs.ensureDir(path.dirname(f.targetPath));
805
839
  await fs.copy(f.sourcePath, f.targetPath);
806
840
  results.added.push(f.file);
807
- if (options.verbose) {
808
- console.log(chalk.green(` ➕ ${f.file} (new)`));
809
- }
841
+ console.log(chalk.green(` ➕ ${f.file}`));
810
842
  }
811
843
 
812
- // Replace all modified files with backups
844
+ // Replace all modified files with backups — always show progress
813
845
  for (const f of summary.modified) {
814
- // Create backup
815
846
  const backupPath = path.join(backupDir, f.componentType, f.file);
816
847
  await fs.ensureDir(path.dirname(backupPath));
817
848
  await fs.copy(f.targetPath, backupPath);
818
849
  results.backedUp.push(f.file);
819
850
 
820
- // Replace with new version
821
851
  await fs.copy(f.sourcePath, f.targetPath);
822
852
  results.updated.push(f.file);
823
- if (options.verbose) {
824
- console.log(chalk.blue(` ✅ ${f.file} (updated, backup created)`));
825
- }
853
+ console.log(chalk.blue(` ✅ ${f.file} (updated)`));
826
854
  }
827
855
 
828
856
  return results;
@@ -842,22 +870,18 @@ export async function executeKeepAll(summary, options = {}) {
842
870
  backedUp: []
843
871
  };
844
872
 
845
- // Add all new files
873
+ // Add all new files — always show progress
846
874
  for (const f of summary.new) {
847
875
  await fs.ensureDir(path.dirname(f.targetPath));
848
876
  await fs.copy(f.sourcePath, f.targetPath);
849
877
  results.added.push(f.file);
850
- if (options.verbose) {
851
- console.log(chalk.green(` ➕ ${f.file} (new)`));
852
- }
878
+ console.log(chalk.green(` ➕ ${f.file}`));
853
879
  }
854
880
 
855
- // Keep all modified files
881
+ // Keep all modified files — always show
856
882
  results.kept = summary.modified.map(f => f.file);
857
- if (options.verbose) {
858
- for (const f of summary.modified) {
859
- console.log(chalk.gray(` 🛡️ ${f.file} (kept)`));
860
- }
883
+ for (const f of summary.modified) {
884
+ console.log(chalk.gray(` 🛡️ ${f.file} (kept)`));
861
885
  }
862
886
 
863
887
  return results;
@@ -958,34 +982,69 @@ export function displayUpdateResults(results, backupDir, newVersion) {
958
982
  console.log(chalk.green('║') + chalk.white.bold(' ✅ Update Complete! '.padEnd(boxWidth)) + chalk.green('║'));
959
983
  console.log(chalk.green(midBorder));
960
984
 
961
- console.log(chalk.green('║') + chalk.white.bold(' 📊 Results:'.padEnd(boxWidth)) + chalk.green('║'));
985
+ const totalChanges = results.updated.length + results.added.length + results.kept.length;
962
986
 
963
- if (results.updated.length > 0) {
964
- const line = ` ├─ Updated: ${results.updated.length} files`;
965
- console.log(chalk.green('║') + chalk.blue(line.padEnd(boxWidth)) + chalk.green('║'));
966
- }
987
+ if (totalChanges === 0) {
988
+ console.log(chalk.green('║') + chalk.white(' Everything is already current — no changes needed.'.padEnd(boxWidth)) + chalk.green('║'));
989
+ } else {
990
+ console.log(chalk.green('║') + chalk.white.bold(' 📊 Results:'.padEnd(boxWidth)) + chalk.green('║'));
967
991
 
968
- if (results.kept.length > 0) {
969
- const line = ` ├─ Kept: ${results.kept.length} files (your customizations preserved)`;
970
- console.log(chalk.green('') + chalk.gray(line.padEnd(boxWidth)) + chalk.green('║'));
971
- }
992
+ const lines = [];
993
+ if (results.updated.length > 0) {
994
+ lines.push({ color: 'blue', text: `Updated: ${pf(results.updated.length)}` });
995
+ }
996
+ if (results.kept.length > 0) {
997
+ lines.push({ color: 'gray', text: `Kept: ${pf(results.kept.length)} (your customizations preserved)` });
998
+ }
999
+ if (results.added.length > 0) {
1000
+ lines.push({ color: 'green', text: `Added: ${pf(results.added.length)}` });
1001
+ }
1002
+ if (results.backedUp.length > 0) {
1003
+ const relativePath = path.relative(process.cwd(), backupDir);
1004
+ lines.push({ color: 'yellow', text: `Backed up: ${pf(results.backedUp.length)} → ${relativePath}/` });
1005
+ }
972
1006
 
973
- if (results.added.length > 0) {
974
- const line = ` ├─ Added: ${results.added.length} new files`;
975
- console.log(chalk.green('║') + chalk.green(line.padEnd(boxWidth)) + chalk.green('║'));
976
- }
1007
+ for (let i = 0; i < lines.length; i++) {
1008
+ const prefix = i === lines.length - 1 ? '└─' : '├─';
1009
+ const line = ` ${prefix} ${lines[i].text}`;
1010
+ console.log(chalk.green('║') + chalk[lines[i].color](line.padEnd(boxWidth)) + chalk.green('║'));
1011
+ }
977
1012
 
978
- if (results.backedUp.length > 0) {
979
- const relativePath = path.relative(process.cwd(), backupDir);
980
- const line = ` └─ Backed up: ${results.backedUp.length} files → ${relativePath}/`;
981
- console.log(chalk.green('║') + chalk.yellow(line.padEnd(boxWidth)) + chalk.green(''));
1013
+ // Show new skills that were added
1014
+ const newSkills = results.added
1015
+ .filter(f => f.endsWith('SKILL.md'))
1016
+ .map(f => f.split('/')[0]);
1017
+ if (newSkills.length > 0) {
1018
+ console.log(chalk.green('║') + ' '.repeat(boxWidth) + chalk.green('║'));
1019
+ const label = ` 🎯 New skills installed:`;
1020
+ console.log(chalk.green('║') + chalk.white.bold(label.padEnd(boxWidth)) + chalk.green('║'));
1021
+ const maxLineLen = boxWidth - 6;
1022
+ let currentLine = '';
1023
+ for (let i = 0; i < newSkills.length; i++) {
1024
+ const separator = currentLine ? ', ' : '';
1025
+ if ((currentLine + separator + newSkills[i]).length > maxLineLen) {
1026
+ console.log(chalk.green('║') + chalk.cyan(` ${currentLine}`.padEnd(boxWidth)) + chalk.green('║'));
1027
+ currentLine = newSkills[i];
1028
+ } else {
1029
+ currentLine += separator + newSkills[i];
1030
+ }
1031
+ }
1032
+ if (currentLine) {
1033
+ console.log(chalk.green('║') + chalk.cyan(` ${currentLine}`.padEnd(boxWidth)) + chalk.green('║'));
1034
+ }
1035
+ }
982
1036
  }
983
1037
 
984
1038
  console.log(chalk.green('║') + ' '.repeat(boxWidth) + chalk.green('║'));
985
1039
 
986
- // What's new section
1040
+ // Version and next steps
987
1041
  console.log(chalk.green('║') + chalk.white.bold(` 🆕 Updated to v${newVersion}`.padEnd(boxWidth)) + chalk.green('║'));
988
- console.log(chalk.green('║') + chalk.gray(' Run /myai-configure --status to see your configuration'.padEnd(boxWidth)) + chalk.green('║'));
1042
+
1043
+ // Only show restart reminder if skills were actually changed
1044
+ const skillsChanged = results.added.some(f => f.includes('/')) || results.updated.some(f => f.includes('/'));
1045
+ if (skillsChanged) {
1046
+ console.log(chalk.green('║') + chalk.yellow(' ⚠️ Restart your AI assistant to load updated skills'.padEnd(boxWidth)) + chalk.green('║'));
1047
+ }
989
1048
 
990
1049
  console.log(chalk.green(botBorder));
991
1050
  console.log('');
@@ -191,6 +191,46 @@ class WorkflowInstaller {
191
191
  return installed;
192
192
  }
193
193
 
194
+ /**
195
+ * Install agent files
196
+ * @param {string[]} agents - Agent names (filenames without .md)
197
+ * @returns {Promise<number>} Number of agents installed
198
+ */
199
+ async installAgents(agents) {
200
+ if (!agents || agents.length === 0) return 0;
201
+
202
+ const agentsDir = path.join(this.claudeDir, 'agents');
203
+ const sourceAgentsDir = path.join(__dirname, '..', '..', 'agents');
204
+ if (!this.dryRun) {
205
+ await fs.mkdir(agentsDir, { recursive: true });
206
+ }
207
+
208
+ let installed = 0;
209
+ for (const agent of agents) {
210
+ const sourcePath = path.join(sourceAgentsDir, `${agent}.md`);
211
+ const targetPath = path.join(agentsDir, `${agent}.md`);
212
+
213
+ try {
214
+ const exists = await fs.access(sourcePath).then(() => true).catch(() => false);
215
+ if (!exists) {
216
+ this.log(`Warning: Agent ${agent} not found at ${sourcePath}`);
217
+ continue;
218
+ }
219
+ if (this.dryRun) {
220
+ this.log(`[DRY RUN] Would copy agent: ${agent}`);
221
+ } else {
222
+ await fs.copyFile(sourcePath, targetPath);
223
+ this.log(`Installed agent: ${agent}`);
224
+ }
225
+ installed++;
226
+ } catch (error) {
227
+ console.warn(`Warning: Could not install agent ${agent}: ${error.message}`);
228
+ }
229
+ }
230
+
231
+ return installed;
232
+ }
233
+
194
234
  /**
195
235
  * Install documentation files
196
236
  * @param {string[]} docs - Documentation file names
@@ -253,6 +293,17 @@ class WorkflowInstaller {
253
293
  this.log(`Configured MCP server: ${server}`);
254
294
  configured++;
255
295
  }
296
+ if (server === 'fal-ai') {
297
+ config.mcpServers['fal-ai'] = {
298
+ command: 'npx',
299
+ args: ['-y', 'fal-ai-mcp-server'],
300
+ env: {
301
+ FAL_KEY: ''
302
+ }
303
+ };
304
+ this.log(`Configured MCP server: ${server}`);
305
+ configured++;
306
+ }
256
307
  }
257
308
 
258
309
  if (configured > 0 && !this.dryRun) {
@@ -303,11 +354,15 @@ class WorkflowInstaller {
303
354
  scripts: 0,
304
355
  libs: 0,
305
356
  docs: 0,
357
+ agents: 0,
306
358
  mcpServers: 0
307
359
  };
308
360
 
309
361
  // Install components
310
362
  results.skills = await this.installSkills(workflow.skills);
363
+ if (workflow.agents && Array.isArray(workflow.agents)) {
364
+ results.agents = await this.installAgents(workflow.agents);
365
+ }
311
366
  results.scripts = await this.installScripts(workflow.scripts);
312
367
  results.libs = await this.installLibraries(workflow.libs);
313
368
  results.docs = await this.installDocs(workflow.docs);
@@ -5,25 +5,25 @@
5
5
  * Validates MCP server configuration and connectivity
6
6
  */
7
7
 
8
- import { spawn } from 'child_process';
9
- import { promises as fs } from 'fs';
10
- import path from 'path';
11
- import { fileURLToPath } from 'url';
8
+ import { spawn } from "child_process";
9
+ import { promises as fs } from "fs";
10
+ import path from "path";
11
+ import { fileURLToPath } from "url";
12
12
 
13
13
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
14
 
15
15
  export default async function healthCheck() {
16
- console.log('🔍 MyAIDev Method MCP Server Health Check');
17
- console.log('==========================================\n');
16
+ console.log("🔍 MyAIDev Method MCP Server Health Check");
17
+ console.log("==========================================\n");
18
18
 
19
19
  const checks = [];
20
-
20
+
21
21
  // Check 1: Environment variables
22
- console.log('📋 Checking environment configuration...');
22
+ console.log("📋 Checking environment configuration...");
23
23
  const envChecks = {
24
- 'WORDPRESS_URL': process.env.WORDPRESS_URL,
25
- 'WORDPRESS_USERNAME': process.env.WORDPRESS_USERNAME,
26
- 'WORDPRESS_APP_PASSWORD': process.env.WORDPRESS_APP_PASSWORD
24
+ WORDPRESS_URL: process.env.WORDPRESS_URL,
25
+ WORDPRESS_USERNAME: process.env.WORDPRESS_USERNAME,
26
+ WORDPRESS_APP_PASSWORD: process.env.WORDPRESS_APP_PASSWORD,
27
27
  };
28
28
 
29
29
  let envConfigured = true;
@@ -37,36 +37,42 @@ export default async function healthCheck() {
37
37
  });
38
38
 
39
39
  checks.push({
40
- name: 'Environment Configuration',
41
- status: envConfigured ? 'passed' : 'failed'
40
+ name: "Environment Configuration",
41
+ status: envConfigured ? "passed" : "failed",
42
42
  });
43
43
 
44
44
  // Check 2: MCP server files
45
- console.log('\n📁 Checking MCP server files...');
46
- const mcpServerPath = path.resolve(__dirname, '../../.claude/mcp/wordpress-server.js');
47
-
45
+ console.log("\n📁 Checking MCP server files...");
46
+ const mcpServerPath = path.resolve(
47
+ __dirname,
48
+ "../../.claude/mcp/wordpress-server.js",
49
+ );
50
+
48
51
  try {
49
52
  await fs.access(mcpServerPath);
50
- console.log(' ✅ WordPress MCP server file exists');
53
+ console.log(" ✅ WordPress MCP server file exists");
51
54
  checks.push({
52
- name: 'MCP Server Files',
53
- status: 'passed'
55
+ name: "MCP Server Files",
56
+ status: "passed",
54
57
  });
55
58
  } catch (error) {
56
- console.log(' ❌ WordPress MCP server file missing');
59
+ console.log(" ❌ WordPress MCP server file missing");
57
60
  checks.push({
58
- name: 'MCP Server Files',
59
- status: 'failed'
61
+ name: "MCP Server Files",
62
+ status: "failed",
60
63
  });
61
64
  }
62
65
 
63
66
  // Check 3: Dependencies
64
- console.log('\n📦 Checking dependencies...');
67
+ console.log("\n📦 Checking dependencies...");
65
68
  const requiredDeps = [
66
- { name: '@modelcontextprotocol/sdk', path: '@modelcontextprotocol/sdk/server/mcp.js' },
67
- { name: 'node-fetch', path: 'node-fetch' },
68
- { name: 'dotenv', path: 'dotenv' },
69
- { name: 'zod', path: 'zod' }
69
+ {
70
+ name: "@modelcontextprotocol/sdk",
71
+ path: "@modelcontextprotocol/sdk/server/mcp.js",
72
+ },
73
+ { name: "node-fetch", path: "node-fetch" },
74
+ { name: "dotenv", path: "dotenv" },
75
+ { name: "zod", path: "zod" },
70
76
  ];
71
77
 
72
78
  let depsInstalled = true;
@@ -81,61 +87,67 @@ export default async function healthCheck() {
81
87
  }
82
88
 
83
89
  checks.push({
84
- name: 'Dependencies',
85
- status: depsInstalled ? 'passed' : 'failed'
90
+ name: "Dependencies",
91
+ status: depsInstalled ? "passed" : "failed",
86
92
  });
87
93
 
88
94
  // Check 4: MCP server startup test
89
95
  if (envConfigured && depsInstalled) {
90
- console.log('\n🚀 Testing MCP server startup...');
91
-
96
+ console.log("\n🚀 Testing MCP server startup...");
97
+
92
98
  try {
93
99
  const startupTest = await testServerStartup(mcpServerPath);
94
100
  console.log(` ✅ MCP server starts successfully`);
95
101
  checks.push({
96
- name: 'MCP Server Startup',
97
- status: 'passed'
102
+ name: "MCP Server Startup",
103
+ status: "passed",
98
104
  });
99
105
  } catch (error) {
100
106
  console.log(` ❌ MCP server startup failed: ${error.message}`);
101
107
  checks.push({
102
- name: 'MCP Server Startup',
103
- status: 'failed'
108
+ name: "MCP Server Startup",
109
+ status: "failed",
104
110
  });
105
111
  }
106
112
  } else {
107
- console.log('\n⏭️ Skipping MCP server startup test (dependencies not met)');
113
+ console.log("\n⏭️ Skipping MCP server startup test (dependencies not met)");
108
114
  checks.push({
109
- name: 'MCP Server Startup',
110
- status: 'skipped'
115
+ name: "MCP Server Startup",
116
+ status: "skipped",
111
117
  });
112
118
  }
113
119
 
114
120
  // Summary
115
- console.log('\n📊 Health Check Summary:');
116
- const passed = checks.filter(c => c.status === 'passed').length;
117
- const failed = checks.filter(c => c.status === 'failed').length;
118
- const skipped = checks.filter(c => c.status === 'skipped').length;
119
-
120
- checks.forEach(check => {
121
- const icon = check.status === 'passed' ? '✅' :
122
- check.status === 'failed' ? '❌' : '⏭️';
121
+ console.log("\n📊 Health Check Summary:");
122
+ const passed = checks.filter((c) => c.status === "passed").length;
123
+ const failed = checks.filter((c) => c.status === "failed").length;
124
+ const skipped = checks.filter((c) => c.status === "skipped").length;
125
+
126
+ checks.forEach((check) => {
127
+ const icon =
128
+ check.status === "passed"
129
+ ? "✅"
130
+ : check.status === "failed"
131
+ ? "❌"
132
+ : "⏭️";
123
133
  console.log(` ${icon} ${check.name}: ${check.status}`);
124
134
  });
125
135
 
126
- console.log(`\nResult: ${passed} passed, ${failed} failed, ${skipped} skipped`);
136
+ console.log(
137
+ `\nResult: ${passed} passed, ${failed} failed, ${skipped} skipped`,
138
+ );
127
139
 
128
140
  if (failed === 0) {
129
- console.log('\n🎉 All checks passed! MCP server is ready to use.');
130
- console.log('\n💡 Next steps:');
131
- console.log(' • Run: npm run mcp:start');
132
- console.log(' • Or use: /myai-wordpress-publish "your-file.md"');
141
+ console.log("\n🎉 All checks passed! MCP server is ready to use.");
142
+ console.log("\n💡 Next steps:");
143
+ console.log(" • Run: npm run mcp:start");
144
+ console.log(' • Or use: /wordpress-publish "your-file.md"');
133
145
  } else {
134
- console.log('\n⚠️ Some checks failed. Please address the issues above.');
135
- console.log('\n💡 Common solutions:');
136
- console.log(' • Set environment variables: /myai-configure wordpress');
137
- console.log(' • Install dependencies: npm install');
138
- console.log(' • Check file permissions and paths');
146
+ console.log("\n⚠️ Some checks failed. Please address the issues above.");
147
+ console.log("\n💡 Common solutions:");
148
+ console.log(" • Set environment variables: /myai-configurator wordpress");
149
+ console.log(" • Install dependencies: npm install");
150
+ console.log(" • Check file permissions and paths");
139
151
  }
140
152
 
141
153
  return {
@@ -143,39 +155,41 @@ export default async function healthCheck() {
143
155
  failed,
144
156
  skipped,
145
157
  checks,
146
- overall: failed === 0 ? 'healthy' : 'unhealthy'
158
+ overall: failed === 0 ? "healthy" : "unhealthy",
147
159
  };
148
160
  }
149
161
 
150
162
  async function testServerStartup(serverPath) {
151
163
  return new Promise((resolve, reject) => {
152
- const serverProcess = spawn('node', [serverPath], {
153
- stdio: ['pipe', 'pipe', 'pipe'],
154
- env: process.env
164
+ const serverProcess = spawn("node", [serverPath], {
165
+ stdio: ["pipe", "pipe", "pipe"],
166
+ env: process.env,
155
167
  });
156
168
 
157
- let startupOutput = '';
169
+ let startupOutput = "";
158
170
  const timeout = setTimeout(() => {
159
171
  serverProcess.kill();
160
- reject(new Error('Server startup timeout'));
172
+ reject(new Error("Server startup timeout"));
161
173
  }, 5000);
162
174
 
163
- serverProcess.stderr.on('data', (data) => {
175
+ serverProcess.stderr.on("data", (data) => {
164
176
  startupOutput += data.toString();
165
- if (startupOutput.includes('Enhanced WordPress MCP Server') ||
166
- startupOutput.includes('running')) {
177
+ if (
178
+ startupOutput.includes("Enhanced WordPress MCP Server") ||
179
+ startupOutput.includes("running")
180
+ ) {
167
181
  clearTimeout(timeout);
168
182
  serverProcess.kill();
169
183
  resolve(true);
170
184
  }
171
185
  });
172
186
 
173
- serverProcess.on('error', (error) => {
187
+ serverProcess.on("error", (error) => {
174
188
  clearTimeout(timeout);
175
189
  reject(error);
176
190
  });
177
191
 
178
- serverProcess.on('exit', (code) => {
192
+ serverProcess.on("exit", (code) => {
179
193
  clearTimeout(timeout);
180
194
  if (code !== 0 && code !== null) {
181
195
  reject(new Error(`Server exited with code ${code}`));
@@ -187,4 +201,4 @@ async function testServerStartup(serverPath) {
187
201
  // Run if called directly
188
202
  if (import.meta.url === `file://${process.argv[1]}`) {
189
203
  healthCheck().catch(console.error);
190
- }
204
+ }