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.
- package/.claude-plugin/plugin.json +0 -1
- package/.env.example +5 -4
- package/CHANGELOG.md +2 -2
- package/CONTENT_CREATION_GUIDE.md +489 -3211
- package/DEVELOPER_USE_CASES.md +1 -1
- package/MODULAR_INSTALLATION.md +2 -2
- package/README.md +39 -33
- package/TECHNICAL_ARCHITECTURE.md +1 -1
- package/USER_GUIDE.md +242 -190
- package/agents/content-editor-agent.md +90 -0
- package/agents/content-planner-agent.md +97 -0
- package/agents/content-research-agent.md +62 -0
- package/agents/content-seo-agent.md +101 -0
- package/agents/content-writer-agent.md +69 -0
- package/agents/infographic-analyzer-agent.md +63 -0
- package/agents/infographic-designer-agent.md +72 -0
- package/bin/cli.js +777 -535
- package/{content-rules.example.md → content-rules-example.md} +2 -2
- package/dist/mcp/health-check.js +82 -68
- package/dist/mcp/mcp-config.json +8 -0
- package/dist/mcp/openstack-server.js +1746 -1262
- package/dist/server/.tsbuildinfo +1 -1
- package/extension.json +21 -4
- package/package.json +181 -184
- package/skills/company-config/SKILL.md +133 -0
- package/skills/configure/SKILL.md +1 -1
- package/skills/myai-configurator/SKILL.md +77 -0
- package/skills/myai-configurator/content-creation-configurator/SKILL.md +516 -0
- package/skills/myai-configurator/content-maintenance-configurator/SKILL.md +397 -0
- package/skills/myai-content-enrichment/SKILL.md +114 -0
- package/skills/myai-content-ideation/SKILL.md +288 -0
- package/skills/myai-content-ideation/evals/evals.json +182 -0
- package/skills/myai-content-production-coordinator/SKILL.md +946 -0
- package/skills/{content-rules-setup → myai-content-rules-setup}/SKILL.md +1 -1
- package/skills/{content-verifier → myai-content-verifier}/SKILL.md +1 -1
- package/skills/myai-content-writer/SKILL.md +333 -0
- package/skills/myai-content-writer/agents/editor-agent.md +138 -0
- package/skills/myai-content-writer/agents/planner-agent.md +121 -0
- package/skills/myai-content-writer/agents/research-agent.md +83 -0
- package/skills/myai-content-writer/agents/seo-agent.md +139 -0
- package/skills/myai-content-writer/agents/visual-planner-agent.md +110 -0
- package/skills/myai-content-writer/agents/writer-agent.md +85 -0
- package/skills/{infographic → myai-infographic}/SKILL.md +1 -1
- package/skills/myai-proprietary-content-verifier/SKILL.md +175 -0
- package/skills/myai-proprietary-content-verifier/evals/evals.json +36 -0
- package/skills/myai-skill-builder/SKILL.md +699 -0
- package/skills/myai-skill-builder/agents/analyzer-agent.md +137 -0
- package/skills/myai-skill-builder/agents/comparator-agent.md +77 -0
- package/skills/myai-skill-builder/agents/grader-agent.md +103 -0
- package/skills/myai-skill-builder/assets/eval_review.html +131 -0
- package/skills/myai-skill-builder/references/schemas.md +211 -0
- package/skills/myai-skill-builder/scripts/aggregate_benchmark.py +190 -0
- package/skills/myai-skill-builder/scripts/generate_review.py +381 -0
- package/skills/myai-skill-builder/scripts/package_skill.py +91 -0
- package/skills/myai-skill-builder/scripts/run_eval.py +105 -0
- package/skills/myai-skill-builder/scripts/run_loop.py +211 -0
- package/skills/myai-skill-builder/scripts/utils.py +123 -0
- package/skills/myai-visual-generator/SKILL.md +125 -0
- package/skills/myai-visual-generator/evals/evals.json +155 -0
- package/skills/myai-visual-generator/references/infographic-pipeline.md +73 -0
- package/skills/myai-visual-generator/references/research-visuals.md +57 -0
- package/skills/myai-visual-generator/references/services.md +89 -0
- package/skills/myai-visual-generator/scripts/visual-generation-utils.js +1272 -0
- package/skills/myaidev-analyze/agents/dependency-mapper-agent.md +236 -0
- package/skills/myaidev-analyze/agents/pattern-detector-agent.md +240 -0
- package/skills/myaidev-analyze/agents/structure-scanner-agent.md +171 -0
- package/skills/myaidev-analyze/agents/tech-profiler-agent.md +291 -0
- package/skills/myaidev-architect/agents/compliance-checker-agent.md +287 -0
- package/skills/myaidev-architect/agents/requirements-analyst-agent.md +194 -0
- package/skills/myaidev-architect/agents/system-designer-agent.md +315 -0
- package/skills/myaidev-coder/agents/implementer-agent.md +185 -0
- package/skills/myaidev-coder/agents/integration-agent.md +168 -0
- package/skills/myaidev-coder/agents/pattern-scanner-agent.md +161 -0
- package/skills/myaidev-coder/agents/self-reviewer-agent.md +168 -0
- package/skills/myaidev-debug/agents/fix-agent-debug.md +317 -0
- package/skills/myaidev-debug/agents/hypothesis-agent.md +226 -0
- package/skills/myaidev-debug/agents/investigator-agent.md +250 -0
- package/skills/myaidev-debug/agents/symptom-collector-agent.md +231 -0
- package/skills/myaidev-documenter/agents/code-reader-agent.md +172 -0
- package/skills/myaidev-documenter/agents/doc-validator-agent.md +174 -0
- package/skills/myaidev-documenter/agents/doc-writer-agent.md +379 -0
- package/skills/myaidev-figma/SKILL.md +212 -0
- package/skills/myaidev-figma/capture.js +133 -0
- package/skills/myaidev-figma/crawl.js +130 -0
- package/skills/myaidev-figma-configure/SKILL.md +130 -0
- package/skills/myaidev-migrate/agents/migration-planner-agent.md +237 -0
- package/skills/myaidev-migrate/agents/migration-writer-agent.md +248 -0
- package/skills/myaidev-migrate/agents/schema-analyzer-agent.md +190 -0
- package/skills/myaidev-performance/agents/benchmark-agent.md +281 -0
- package/skills/myaidev-performance/agents/optimizer-agent.md +277 -0
- package/skills/myaidev-performance/agents/profiler-agent.md +252 -0
- package/skills/myaidev-refactor/agents/refactor-executor-agent.md +221 -0
- package/skills/myaidev-refactor/agents/refactor-planner-agent.md +213 -0
- package/skills/myaidev-refactor/agents/regression-guard-agent.md +242 -0
- package/skills/myaidev-refactor/agents/smell-detector-agent.md +233 -0
- package/skills/myaidev-reviewer/agents/auto-fixer-agent.md +238 -0
- package/skills/myaidev-reviewer/agents/code-analyst-agent.md +220 -0
- package/skills/myaidev-reviewer/agents/security-scanner-agent.md +262 -0
- package/skills/myaidev-tester/agents/coverage-analyst-agent.md +163 -0
- package/skills/myaidev-tester/agents/tdd-driver-agent.md +242 -0
- package/skills/myaidev-tester/agents/test-runner-agent.md +176 -0
- package/skills/myaidev-tester/agents/test-strategist-agent.md +154 -0
- package/skills/myaidev-tester/agents/test-writer-agent.md +242 -0
- package/skills/myaidev-workflow/agents/analyzer-agent.md +317 -0
- package/skills/myaidev-workflow/agents/coordinator-agent.md +253 -0
- package/skills/openstack-manager/SKILL.md +1 -1
- package/skills/payloadcms-publisher/SKILL.md +141 -77
- package/skills/payloadcms-publisher/references/field-mapping.md +142 -0
- package/skills/payloadcms-publisher/references/lexical-format.md +97 -0
- package/skills/security-auditor/SKILL.md +1 -1
- package/src/cli/commands/addon.js +184 -123
- package/src/config/workflows.js +172 -228
- package/src/lib/ascii-banner.js +197 -182
- package/src/lib/{content-coordinator.js → content-production-coordinator.js} +649 -459
- package/src/lib/installation-detector.js +93 -59
- package/src/lib/payloadcms-utils.js +285 -510
- package/src/lib/update-manager.js +120 -61
- package/src/lib/workflow-installer.js +55 -0
- package/src/mcp/health-check.js +82 -68
- package/src/mcp/openstack-server.js +1746 -1262
- package/src/scripts/configure-visual-apis.js +224 -173
- package/src/scripts/configure-wordpress-mcp.js +96 -66
- package/src/scripts/init/install.js +109 -85
- package/src/scripts/init-project.js +138 -67
- package/src/scripts/utils/write-content.js +67 -52
- package/src/scripts/wordpress/publish-to-wordpress.js +128 -128
- package/src/templates/claude/CLAUDE.md +131 -0
- package/hooks/hooks.json +0 -26
- package/skills/content-coordinator/SKILL.md +0 -130
- package/skills/content-enrichment/SKILL.md +0 -80
- package/skills/content-writer/SKILL.md +0 -285
- 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, '
|
|
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, '
|
|
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}
|
|
596
|
-
const newLine = ` ├─ 🆕 New
|
|
597
|
-
const modifiedLine = ` ├─ ⚠️ Modified: ${summary.modified.length}
|
|
598
|
-
const deletedLine = ` └─ 🗑️ Removed: ${summary.deleted.length}
|
|
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}
|
|
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
|
|
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}
|
|
734
|
-
{ name: `Update all (replace ${files.length}
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
858
|
-
|
|
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
|
-
|
|
985
|
+
const totalChanges = results.updated.length + results.added.length + results.kept.length;
|
|
962
986
|
|
|
963
|
-
if (
|
|
964
|
-
|
|
965
|
-
|
|
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
|
-
|
|
969
|
-
|
|
970
|
-
|
|
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
|
-
|
|
974
|
-
|
|
975
|
-
|
|
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
|
-
|
|
979
|
-
const
|
|
980
|
-
|
|
981
|
-
|
|
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
|
-
//
|
|
1040
|
+
// Version and next steps
|
|
987
1041
|
console.log(chalk.green('║') + chalk.white.bold(` 🆕 Updated to v${newVersion}`.padEnd(boxWidth)) + chalk.green('║'));
|
|
988
|
-
|
|
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);
|
package/src/mcp/health-check.js
CHANGED
|
@@ -5,25 +5,25 @@
|
|
|
5
5
|
* Validates MCP server configuration and connectivity
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { spawn } from
|
|
9
|
-
import { promises as fs } from
|
|
10
|
-
import path from
|
|
11
|
-
import { fileURLToPath } from
|
|
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(
|
|
17
|
-
console.log(
|
|
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(
|
|
22
|
+
console.log("📋 Checking environment configuration...");
|
|
23
23
|
const envChecks = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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:
|
|
41
|
-
status: envConfigured ?
|
|
40
|
+
name: "Environment Configuration",
|
|
41
|
+
status: envConfigured ? "passed" : "failed",
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
// Check 2: MCP server files
|
|
45
|
-
console.log(
|
|
46
|
-
const mcpServerPath = path.resolve(
|
|
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(
|
|
53
|
+
console.log(" ✅ WordPress MCP server file exists");
|
|
51
54
|
checks.push({
|
|
52
|
-
name:
|
|
53
|
-
status:
|
|
55
|
+
name: "MCP Server Files",
|
|
56
|
+
status: "passed",
|
|
54
57
|
});
|
|
55
58
|
} catch (error) {
|
|
56
|
-
console.log(
|
|
59
|
+
console.log(" ❌ WordPress MCP server file missing");
|
|
57
60
|
checks.push({
|
|
58
|
-
name:
|
|
59
|
-
status:
|
|
61
|
+
name: "MCP Server Files",
|
|
62
|
+
status: "failed",
|
|
60
63
|
});
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
// Check 3: Dependencies
|
|
64
|
-
console.log(
|
|
67
|
+
console.log("\n📦 Checking dependencies...");
|
|
65
68
|
const requiredDeps = [
|
|
66
|
-
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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:
|
|
85
|
-
status: depsInstalled ?
|
|
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(
|
|
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:
|
|
97
|
-
status:
|
|
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:
|
|
103
|
-
status:
|
|
108
|
+
name: "MCP Server Startup",
|
|
109
|
+
status: "failed",
|
|
104
110
|
});
|
|
105
111
|
}
|
|
106
112
|
} else {
|
|
107
|
-
console.log(
|
|
113
|
+
console.log("\n⏭️ Skipping MCP server startup test (dependencies not met)");
|
|
108
114
|
checks.push({
|
|
109
|
-
name:
|
|
110
|
-
status:
|
|
115
|
+
name: "MCP Server Startup",
|
|
116
|
+
status: "skipped",
|
|
111
117
|
});
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
// Summary
|
|
115
|
-
console.log(
|
|
116
|
-
const passed = checks.filter(c => c.status ===
|
|
117
|
-
const failed = checks.filter(c => c.status ===
|
|
118
|
-
const skipped = checks.filter(c => c.status ===
|
|
119
|
-
|
|
120
|
-
checks.forEach(check => {
|
|
121
|
-
const icon =
|
|
122
|
-
|
|
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(
|
|
136
|
+
console.log(
|
|
137
|
+
`\nResult: ${passed} passed, ${failed} failed, ${skipped} skipped`,
|
|
138
|
+
);
|
|
127
139
|
|
|
128
140
|
if (failed === 0) {
|
|
129
|
-
console.log(
|
|
130
|
-
console.log(
|
|
131
|
-
console.log(
|
|
132
|
-
console.log(' • Or use: /
|
|
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(
|
|
135
|
-
console.log(
|
|
136
|
-
console.log(
|
|
137
|
-
console.log(
|
|
138
|
-
console.log(
|
|
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 ?
|
|
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(
|
|
153
|
-
stdio: [
|
|
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(
|
|
172
|
+
reject(new Error("Server startup timeout"));
|
|
161
173
|
}, 5000);
|
|
162
174
|
|
|
163
|
-
serverProcess.stderr.on(
|
|
175
|
+
serverProcess.stderr.on("data", (data) => {
|
|
164
176
|
startupOutput += data.toString();
|
|
165
|
-
if (
|
|
166
|
-
|
|
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(
|
|
187
|
+
serverProcess.on("error", (error) => {
|
|
174
188
|
clearTimeout(timeout);
|
|
175
189
|
reject(error);
|
|
176
190
|
});
|
|
177
191
|
|
|
178
|
-
serverProcess.on(
|
|
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
|
+
}
|