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
|
@@ -17,7 +17,7 @@ import inquirer from 'inquirer';
|
|
|
17
17
|
import fs from 'fs-extra';
|
|
18
18
|
import path from 'path';
|
|
19
19
|
import os from 'os';
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
import matter from 'gray-matter';
|
|
22
22
|
import { isAuthenticated, getAuthToken, getAuthData, authFetch } from '../../lib/auth-helper.js';
|
|
23
23
|
import { validateSkill, generateSlug } from '../../lib/skill-validator.js';
|
|
@@ -215,11 +215,12 @@ async function installSkill(name, options) {
|
|
|
215
215
|
const { location } = await inquirer.prompt([{
|
|
216
216
|
type: 'list',
|
|
217
217
|
name: 'location',
|
|
218
|
-
message: '
|
|
218
|
+
message: 'Where do you want to install this skill?',
|
|
219
219
|
choices: [
|
|
220
|
-
{ name: `Project
|
|
221
|
-
{ name: `Global
|
|
220
|
+
{ name: `Project ${chalk.gray('— .claude/skills/ (this project only)')}`, value: 'project' },
|
|
221
|
+
{ name: `Global ${chalk.gray('— ~/.claude/skills/ (available everywhere)')}`, value: 'global' },
|
|
222
222
|
],
|
|
223
|
+
default: 'project',
|
|
223
224
|
}]);
|
|
224
225
|
targetDir = location === 'project' ? projectSkillsDir() : globalSkillsDir();
|
|
225
226
|
}
|
|
@@ -227,17 +228,21 @@ async function installSkill(name, options) {
|
|
|
227
228
|
const slug = skill.slug || skill.name.toLowerCase().replace(/\s+/g, '-');
|
|
228
229
|
const installPath = path.join(targetDir, slug);
|
|
229
230
|
|
|
230
|
-
// Download
|
|
231
|
+
// Download (request JSON to get supporting files if available)
|
|
231
232
|
const dlSpinner = ora(`Downloading ${chalk.cyan(skill.name)}...`).start();
|
|
232
|
-
const dlRes = await fetchWithTimeout(`${API_BASE}/${skill.id}/download
|
|
233
|
+
const dlRes = await fetchWithTimeout(`${API_BASE}/${skill.id}/download`, {
|
|
234
|
+
headers: { 'Accept': 'application/json' },
|
|
235
|
+
});
|
|
233
236
|
if (!dlRes.ok) throw new Error(`Download failed: ${dlRes.status}`);
|
|
234
237
|
|
|
235
238
|
// Handle both JSON and raw markdown responses
|
|
236
239
|
const contentType = dlRes.headers.get('content-type') || '';
|
|
237
240
|
let content;
|
|
241
|
+
let supportingFiles = null;
|
|
238
242
|
if (contentType.includes('application/json')) {
|
|
239
243
|
const dlBody = await dlRes.json();
|
|
240
244
|
content = dlBody.content;
|
|
245
|
+
supportingFiles = dlBody.supportingFiles || null;
|
|
241
246
|
} else {
|
|
242
247
|
content = await dlRes.text();
|
|
243
248
|
}
|
|
@@ -247,10 +252,41 @@ async function installSkill(name, options) {
|
|
|
247
252
|
await fs.ensureDir(installPath);
|
|
248
253
|
await fs.writeFile(path.join(installPath, 'SKILL.md'), content, 'utf8');
|
|
249
254
|
|
|
255
|
+
// Install supporting files (agents, scripts, references, assets)
|
|
256
|
+
let extraFileCount = 0;
|
|
257
|
+
if (supportingFiles && typeof supportingFiles === 'object') {
|
|
258
|
+
for (const [relPath, fileContent] of Object.entries(supportingFiles)) {
|
|
259
|
+
const filePath = path.join(installPath, relPath);
|
|
260
|
+
await fs.ensureDir(path.dirname(filePath));
|
|
261
|
+
await fs.writeFile(filePath, fileContent, 'utf8');
|
|
262
|
+
extraFileCount++;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
250
266
|
dlSpinner.succeed(chalk.green(`Installed ${chalk.bold(skill.name)}`));
|
|
251
267
|
|
|
268
|
+
// Track installation (non-blocking, best-effort)
|
|
269
|
+
try {
|
|
270
|
+
const token = await getAuthToken();
|
|
271
|
+
if (token) {
|
|
272
|
+
fetchWithTimeout(`${API_BASE}/${skill.id}/install`, {
|
|
273
|
+
method: 'POST',
|
|
274
|
+
headers: {
|
|
275
|
+
'Authorization': `Bearer ${token}`,
|
|
276
|
+
'Content-Type': 'application/json',
|
|
277
|
+
},
|
|
278
|
+
body: JSON.stringify({ source: 'cli' }),
|
|
279
|
+
}).catch(() => {}); // Fire-and-forget
|
|
280
|
+
}
|
|
281
|
+
} catch {
|
|
282
|
+
// Silently ignore tracking failures
|
|
283
|
+
}
|
|
284
|
+
|
|
252
285
|
const rel = path.relative(process.cwd(), installPath);
|
|
253
286
|
console.log(chalk.gray(` → ${rel}/SKILL.md`));
|
|
287
|
+
if (extraFileCount > 0) {
|
|
288
|
+
console.log(chalk.gray(` → ${extraFileCount} supporting file(s) (agents, scripts, etc.)`));
|
|
289
|
+
}
|
|
254
290
|
console.log(chalk.cyan('\n Restart Claude Code to load the new skill.\n'));
|
|
255
291
|
} catch (err) {
|
|
256
292
|
if (err.name === 'AbortError') {
|
|
@@ -696,26 +732,10 @@ async function scaffoldSkill() {
|
|
|
696
732
|
return targetDir;
|
|
697
733
|
}
|
|
698
734
|
|
|
699
|
-
function ghAvailable() {
|
|
700
|
-
try {
|
|
701
|
-
execSync('gh auth status', { stdio: 'pipe' });
|
|
702
|
-
return true;
|
|
703
|
-
} catch {
|
|
704
|
-
return false;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
735
|
async function submitSkill(opts) {
|
|
709
|
-
// Step 1: Auth
|
|
736
|
+
// Step 1: Auth check
|
|
710
737
|
if (!(await requireAuth())) return;
|
|
711
738
|
|
|
712
|
-
if (!ghAvailable()) {
|
|
713
|
-
console.log(chalk.red('\n✗ GitHub CLI (gh) is required for submissions.'));
|
|
714
|
-
console.log(chalk.gray(' Install: https://cli.github.com'));
|
|
715
|
-
console.log(chalk.gray(' Then: gh auth login\n'));
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
739
|
// Step 2: Detect or scaffold SKILL.md
|
|
720
740
|
let targetPath = opts.dir ? path.resolve(opts.dir) : process.cwd();
|
|
721
741
|
let skillDir = targetPath;
|
|
@@ -747,14 +767,13 @@ async function submitSkill(opts) {
|
|
|
747
767
|
|
|
748
768
|
const scaffoldedDir = await scaffoldSkill();
|
|
749
769
|
if (!scaffoldedDir) return;
|
|
750
|
-
// User needs to edit the scaffold first
|
|
751
770
|
return;
|
|
752
771
|
}
|
|
753
772
|
|
|
754
|
-
// Step 3:
|
|
773
|
+
// Step 3: Local validation
|
|
755
774
|
const spinner = ora('Validating skill...').start();
|
|
756
775
|
const result = await validateSkill(skillDir, {
|
|
757
|
-
checkDuplicates:
|
|
776
|
+
checkDuplicates: false,
|
|
758
777
|
apiBase: API_BASE,
|
|
759
778
|
});
|
|
760
779
|
spinner.stop();
|
|
@@ -777,11 +796,11 @@ async function submitSkill(opts) {
|
|
|
777
796
|
}
|
|
778
797
|
|
|
779
798
|
// Step 4: Show summary and confirm
|
|
780
|
-
const slug = result.info.slug;
|
|
781
799
|
console.log(chalk.cyan('\n📤 Submit to MyAIDev Marketplace\n'));
|
|
782
800
|
console.log(` ${chalk.gray('Name:')} ${chalk.white.bold(result.info.name)}`);
|
|
783
|
-
console.log(` ${chalk.gray('Slug:')} ${chalk.white(slug)}`);
|
|
801
|
+
console.log(` ${chalk.gray('Slug:')} ${chalk.white(result.info.slug)}`);
|
|
784
802
|
console.log(` ${chalk.gray('Description:')} ${chalk.white(truncate(result.info.description, 60))}`);
|
|
803
|
+
console.log(` ${chalk.gray('Category:')} ${result.info.category || 'general'}`);
|
|
785
804
|
console.log(` ${chalk.gray('Sections:')} ${result.info.sectionCount}`);
|
|
786
805
|
console.log('');
|
|
787
806
|
|
|
@@ -798,116 +817,138 @@ async function submitSkill(opts) {
|
|
|
798
817
|
}
|
|
799
818
|
}
|
|
800
819
|
|
|
801
|
-
// Step 5:
|
|
802
|
-
const
|
|
803
|
-
const
|
|
820
|
+
// Step 5: Detect supporting files (agents, scripts, references, assets)
|
|
821
|
+
const supportingDirs = ['agents', 'scripts', 'references', 'assets', 'evals'];
|
|
822
|
+
const bundledFiles = {};
|
|
823
|
+
let hasSupportingFiles = false;
|
|
824
|
+
|
|
825
|
+
for (const dir of supportingDirs) {
|
|
826
|
+
const dirPath = path.join(skillDir, dir);
|
|
827
|
+
if (await fs.pathExists(dirPath)) {
|
|
828
|
+
const files = await collectFiles(dirPath, dir);
|
|
829
|
+
if (files.length > 0) {
|
|
830
|
+
hasSupportingFiles = true;
|
|
831
|
+
for (const f of files) {
|
|
832
|
+
bundledFiles[f.relativePath] = f.content;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
if (hasSupportingFiles) {
|
|
839
|
+
const fileCount = Object.keys(bundledFiles).length;
|
|
840
|
+
console.log(chalk.gray(` Bundling ${fileCount} supporting file(s) (agents, scripts, etc.)\n`));
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// Step 6: Submit via API
|
|
844
|
+
const submitSpinner = ora('Submitting skill for review...').start();
|
|
804
845
|
|
|
805
846
|
try {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
//
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
execSync(`git -C "${tmpDir}" checkout -b ${branch}`, { stdio: 'pipe' });
|
|
822
|
-
|
|
823
|
-
// Copy skill files
|
|
824
|
-
const destDir = path.join(tmpDir, 'skills', slug);
|
|
825
|
-
await fs.ensureDir(destDir);
|
|
826
|
-
await fs.copy(skillDir, destDir, {
|
|
827
|
-
filter: (src) => {
|
|
828
|
-
const ext = path.extname(src).toLowerCase();
|
|
829
|
-
const base = path.basename(src);
|
|
830
|
-
// Copy directories and allowed file types
|
|
831
|
-
if (fs.statSync(src).isDirectory()) return true;
|
|
832
|
-
return ['.md', '.json', '.yaml', '.yml', '.sh', '.js', '.ts', '.py', '.txt'].includes(ext) || base === '.gitkeep';
|
|
833
|
-
},
|
|
847
|
+
const content = await fs.readFile(skillFile, 'utf8');
|
|
848
|
+
|
|
849
|
+
const payload = {
|
|
850
|
+
content,
|
|
851
|
+
category: result.info.category || undefined,
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
// Include supporting files if present
|
|
855
|
+
if (hasSupportingFiles) {
|
|
856
|
+
payload.supportingFiles = bundledFiles;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
const res = await authFetch(`${API_BASE}/submissions`, {
|
|
860
|
+
method: 'POST',
|
|
861
|
+
body: JSON.stringify(payload),
|
|
834
862
|
});
|
|
835
863
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
'',
|
|
847
|
-
`**Description**: ${result.info.description || 'N/A'}`,
|
|
848
|
-
`**Category**: ${result.info.category || 'general'}`,
|
|
849
|
-
'',
|
|
850
|
-
'### Checklist',
|
|
851
|
-
'- [x] SKILL.md has valid YAML frontmatter',
|
|
852
|
-
'- [x] Passes local validation',
|
|
853
|
-
'- [ ] Tested locally with Claude Code',
|
|
854
|
-
].join('\n');
|
|
855
|
-
|
|
856
|
-
const prOutput = execSync(
|
|
857
|
-
`gh pr create --repo ${MARKETPLACE_REPO} --head ${ghUser}:${branch} --title "feat: add skill ${result.info.name}" --body "${prBody.replace(/"/g, '\\"')}"`,
|
|
858
|
-
{ encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
|
|
859
|
-
).trim();
|
|
860
|
-
|
|
861
|
-
prSpinner.succeed(chalk.green('Pull request created!'));
|
|
862
|
-
|
|
863
|
-
// Extract PR URL from output
|
|
864
|
-
const prUrl = prOutput.match(/https:\/\/github\.com\S+/)?.[0] || prOutput;
|
|
865
|
-
console.log(chalk.gray(` PR: ${prUrl}`));
|
|
866
|
-
|
|
867
|
-
// Step 6: Record submission
|
|
868
|
-
try {
|
|
869
|
-
await authFetch(`${API_BASE}/submissions`, {
|
|
870
|
-
method: 'POST',
|
|
871
|
-
body: JSON.stringify({
|
|
872
|
-
skillName: result.info.name,
|
|
873
|
-
slug,
|
|
874
|
-
description: result.info.description || '',
|
|
875
|
-
prUrl,
|
|
876
|
-
}),
|
|
877
|
-
});
|
|
878
|
-
} catch {
|
|
879
|
-
// Non-fatal: submission tracking is optional
|
|
864
|
+
if (!res.ok) {
|
|
865
|
+
const body = await res.json().catch(() => ({}));
|
|
866
|
+
if (body.validation?.errors?.length) {
|
|
867
|
+
submitSpinner.fail(chalk.red('Server validation failed:'));
|
|
868
|
+
for (const err of body.validation.errors) {
|
|
869
|
+
console.log(chalk.red(` • ${err}`));
|
|
870
|
+
}
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
throw new Error(body.error || `API error: ${res.status}`);
|
|
880
874
|
}
|
|
881
875
|
|
|
882
|
-
|
|
883
|
-
|
|
876
|
+
const body = await res.json();
|
|
877
|
+
const submission = body.submission;
|
|
878
|
+
|
|
879
|
+
submitSpinner.succeed(chalk.green('Skill submitted for review!'));
|
|
880
|
+
|
|
881
|
+
console.log('');
|
|
882
|
+
console.log(` ${chalk.gray('Submission ID:')} ${chalk.white(submission.id)}`);
|
|
883
|
+
console.log(` ${chalk.gray('Status:')} ${chalk.yellow(submission.status)}`);
|
|
884
|
+
if (hasSupportingFiles) {
|
|
885
|
+
console.log(` ${chalk.gray('Files:')} ${chalk.white(`SKILL.md + ${Object.keys(bundledFiles).length} supporting files`)}`);
|
|
886
|
+
}
|
|
887
|
+
console.log('');
|
|
888
|
+
console.log(chalk.gray(' AI analysis will run automatically.'));
|
|
889
|
+
console.log(chalk.gray(' An admin will review and approve your skill.'));
|
|
890
|
+
console.log(chalk.gray(` Check status: ${chalk.white('myaidev-method addon status')}\n`));
|
|
884
891
|
} catch (err) {
|
|
885
|
-
|
|
892
|
+
submitSpinner.fail(chalk.red(`Submission failed: ${err.message}`));
|
|
886
893
|
process.exit(1);
|
|
887
|
-
} finally {
|
|
888
|
-
// Clean up temp directory
|
|
889
|
-
await fs.remove(tmpDir).catch(() => {});
|
|
890
894
|
}
|
|
891
895
|
}
|
|
892
896
|
|
|
897
|
+
/**
|
|
898
|
+
* Recursively collect files from a directory for bundling.
|
|
899
|
+
* Skips __pycache__, .pyc, and other artifacts.
|
|
900
|
+
*/
|
|
901
|
+
async function collectFiles(dirPath, prefix) {
|
|
902
|
+
const results = [];
|
|
903
|
+
const SKIP_PATTERNS = ['__pycache__', '.pyc', '.DS_Store', 'node_modules'];
|
|
904
|
+
|
|
905
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
906
|
+
for (const entry of entries) {
|
|
907
|
+
if (SKIP_PATTERNS.some(p => entry.name.includes(p))) continue;
|
|
908
|
+
|
|
909
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
910
|
+
const relativePath = path.join(prefix, entry.name);
|
|
911
|
+
|
|
912
|
+
if (entry.isDirectory()) {
|
|
913
|
+
const subFiles = await collectFiles(fullPath, relativePath);
|
|
914
|
+
results.push(...subFiles);
|
|
915
|
+
} else if (entry.isFile()) {
|
|
916
|
+
try {
|
|
917
|
+
const content = await fs.readFile(fullPath, 'utf8');
|
|
918
|
+
results.push({ relativePath, content });
|
|
919
|
+
} catch {
|
|
920
|
+
// Skip binary files
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return results;
|
|
925
|
+
}
|
|
926
|
+
|
|
893
927
|
// ── Status Command ─────────────────────────────────────────────────────
|
|
894
928
|
|
|
895
|
-
async function checkStatus(
|
|
929
|
+
async function checkStatus(nameOrId) {
|
|
896
930
|
if (!(await requireAuth())) return;
|
|
897
931
|
|
|
898
932
|
const spinner = ora('Fetching submission status...').start();
|
|
899
933
|
|
|
900
934
|
try {
|
|
901
|
-
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
935
|
+
// If it looks like a UUID, fetch by ID
|
|
936
|
+
const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(nameOrId || '');
|
|
937
|
+
|
|
938
|
+
let submissions;
|
|
939
|
+
if (isUuid) {
|
|
940
|
+
const res = await authFetch(`${API_BASE}/submissions/${nameOrId}`);
|
|
941
|
+
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
|
942
|
+
const body = await res.json();
|
|
943
|
+
submissions = body.submission ? [body.submission] : [];
|
|
944
|
+
} else {
|
|
945
|
+
const params = nameOrId ? `?name=${encodeURIComponent(nameOrId)}` : '';
|
|
946
|
+
const res = await authFetch(`${API_BASE}/submissions${params}`);
|
|
947
|
+
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
|
948
|
+
const body = await res.json();
|
|
949
|
+
submissions = body.submissions || [];
|
|
906
950
|
}
|
|
907
951
|
|
|
908
|
-
const body = await res.json();
|
|
909
|
-
const submissions = body.submissions || [];
|
|
910
|
-
|
|
911
952
|
spinner.stop();
|
|
912
953
|
|
|
913
954
|
if (submissions.length === 0) {
|
|
@@ -921,16 +962,36 @@ async function checkStatus(name) {
|
|
|
921
962
|
for (const sub of submissions) {
|
|
922
963
|
const statusColor = {
|
|
923
964
|
pending_review: chalk.yellow,
|
|
965
|
+
ai_analyzing: chalk.magenta,
|
|
966
|
+
ready_for_review: chalk.blue,
|
|
924
967
|
approved: chalk.green,
|
|
925
|
-
merged: chalk.green.bold,
|
|
926
968
|
rejected: chalk.red,
|
|
927
969
|
changes_requested: chalk.yellow,
|
|
928
970
|
}[sub.status] || chalk.gray;
|
|
929
971
|
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
972
|
+
const statusLabel = {
|
|
973
|
+
pending_review: 'pending review',
|
|
974
|
+
ai_analyzing: 'AI analyzing...',
|
|
975
|
+
ready_for_review: 'ready for review',
|
|
976
|
+
approved: 'approved',
|
|
977
|
+
rejected: 'rejected',
|
|
978
|
+
changes_requested: 'changes requested',
|
|
979
|
+
}[sub.status] || sub.status;
|
|
980
|
+
|
|
981
|
+
console.log(` ${chalk.white.bold(sub.skillName)} ${statusColor(`[${statusLabel}]`)}`);
|
|
982
|
+
|
|
983
|
+
// Show AI score if available
|
|
984
|
+
if (sub.aiAnalysis?.overallScore != null) {
|
|
985
|
+
const score = sub.aiAnalysis.overallScore;
|
|
986
|
+
const scoreColor = score >= 75 ? chalk.green : score >= 50 ? chalk.yellow : chalk.red;
|
|
987
|
+
console.log(` ${chalk.gray('AI Score:')} ${scoreColor(`${score}/100`)} ${chalk.gray(`(${sub.aiAnalysis.recommendation})`)}`);
|
|
988
|
+
} else if (sub.aiAnalysisStatus === 'running') {
|
|
989
|
+
console.log(` ${chalk.gray('AI Score:')} ${chalk.magenta('analyzing...')}`);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
if (sub.reviewNotes) console.log(` ${chalk.gray('Review:')} ${sub.reviewNotes}`);
|
|
993
|
+
console.log(` ${chalk.gray('Submitted:')} ${new Date(sub.createdAt).toLocaleDateString()}`);
|
|
994
|
+
if (sub.reviewedAt) console.log(` ${chalk.gray('Reviewed:')} ${new Date(sub.reviewedAt).toLocaleDateString()}`);
|
|
934
995
|
console.log('');
|
|
935
996
|
}
|
|
936
997
|
} catch (err) {
|