skillhub 0.2.5 → 0.2.7
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/dist/index.js +44 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3516,6 +3516,12 @@ var VALID_PLATFORMS = ["claude", "codex", "copilot", "cursor", "windsurf"];
|
|
|
3516
3516
|
var NAME_PATTERN = /^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/;
|
|
3517
3517
|
var MAX_DESCRIPTION_LENGTH = 1024;
|
|
3518
3518
|
var MAX_NAME_LENGTH = 64;
|
|
3519
|
+
function sanitizeUtf8(input) {
|
|
3520
|
+
let result = input.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "");
|
|
3521
|
+
result = Buffer.from(result, "utf8").toString("utf8");
|
|
3522
|
+
result = result.replace(/[\uD800-\uDFFF]/g, "");
|
|
3523
|
+
return result;
|
|
3524
|
+
}
|
|
3519
3525
|
var INSTRUCTION_FILE_PATTERNS = [
|
|
3520
3526
|
{
|
|
3521
3527
|
format: "skill.md",
|
|
@@ -3600,8 +3606,8 @@ function parseSkillMd(content) {
|
|
|
3600
3606
|
validateTriggers(frontmatter.triggers, warnings);
|
|
3601
3607
|
}
|
|
3602
3608
|
const metadata = {
|
|
3603
|
-
name: String(frontmatter.name || ""),
|
|
3604
|
-
description: String(frontmatter.description || ""),
|
|
3609
|
+
name: sanitizeUtf8(String(frontmatter.name || "")),
|
|
3610
|
+
description: sanitizeUtf8(String(frontmatter.description || "")),
|
|
3605
3611
|
version: frontmatter.version ? String(frontmatter.version) : void 0,
|
|
3606
3612
|
license: frontmatter.license ? String(frontmatter.license) : void 0,
|
|
3607
3613
|
author: frontmatter.author ? String(frontmatter.author) : void 0,
|
|
@@ -3784,8 +3790,8 @@ function parseGenericInstructionFile(content, format, repoMeta) {
|
|
|
3784
3790
|
const derivedDescription = frontmatter.description || repoMeta.description || extractFirstParagraph(body) || `${FORMAT_LABELS[format]} from ${repoMeta.owner}/${repoMeta.name}`;
|
|
3785
3791
|
const inferredPlatform = pattern?.inferredPlatform || "claude";
|
|
3786
3792
|
const metadata = {
|
|
3787
|
-
name: derivedName,
|
|
3788
|
-
description: derivedDescription.slice(0, MAX_DESCRIPTION_LENGTH),
|
|
3793
|
+
name: sanitizeUtf8(derivedName),
|
|
3794
|
+
description: sanitizeUtf8(derivedDescription.slice(0, MAX_DESCRIPTION_LENGTH)),
|
|
3789
3795
|
version: frontmatter.version ? String(frontmatter.version) : void 0,
|
|
3790
3796
|
license: frontmatter.license ? String(frontmatter.license) : void 0,
|
|
3791
3797
|
author: frontmatter.author ? String(frontmatter.author) : repoMeta.owner,
|
|
@@ -3828,6 +3834,21 @@ function extractFirstParagraph(content) {
|
|
|
3828
3834
|
}
|
|
3829
3835
|
return null;
|
|
3830
3836
|
}
|
|
3837
|
+
var TAG_KEYS = [
|
|
3838
|
+
"RATIONALE",
|
|
3839
|
+
"USE-CASES",
|
|
3840
|
+
"AUDIENCE",
|
|
3841
|
+
"COMPLEMENTS",
|
|
3842
|
+
"SEO-EN",
|
|
3843
|
+
"BUNDLE-FIT",
|
|
3844
|
+
"FRAMEWORK-LOCK",
|
|
3845
|
+
"CONTRIBUTING-REPO",
|
|
3846
|
+
"MATURITY",
|
|
3847
|
+
"COMPLEXITY",
|
|
3848
|
+
"DEPENDENCIES",
|
|
3849
|
+
"PLATFORM"
|
|
3850
|
+
];
|
|
3851
|
+
var TAG_REGEX = new RegExp(`(${TAG_KEYS.join("|")}):\\s*`, "g");
|
|
3831
3852
|
|
|
3832
3853
|
// src/utils/api.ts
|
|
3833
3854
|
import https from "https";
|
|
@@ -4298,7 +4319,8 @@ async function install(skillId, options2) {
|
|
|
4298
4319
|
try {
|
|
4299
4320
|
skillInfo = await getSkill(skillId);
|
|
4300
4321
|
if (skillInfo) {
|
|
4301
|
-
|
|
4322
|
+
const reviewBadge = skillInfo.aiScore && skillInfo.reviewStatus === "ai-reviewed" ? chalk.dim(` | AI: ${skillInfo.aiScore}/100`) : skillInfo.reviewStatus === "verified" ? chalk.green(` | AI: ${skillInfo.aiScore}/100 \u2713`) : "";
|
|
4323
|
+
spinner.succeed(`Found in registry: ${skillInfo.name}${reviewBadge}`);
|
|
4302
4324
|
spinner.start("Preparing installation...");
|
|
4303
4325
|
}
|
|
4304
4326
|
} catch (error) {
|
|
@@ -4344,6 +4366,12 @@ async function install(skillId, options2) {
|
|
|
4344
4366
|
spinner.text = "Downloading skill files...";
|
|
4345
4367
|
const cachedFiles = await getSkillFiles(skillInfo.id);
|
|
4346
4368
|
if (cachedFiles && cachedFiles.files.length > 0) {
|
|
4369
|
+
if (cachedFiles.isStale) {
|
|
4370
|
+
spinner.warn(chalk.yellow(
|
|
4371
|
+
"This skill may have been removed from its GitHub repository.\n Files were served from the SkillHub cache and may be outdated."
|
|
4372
|
+
));
|
|
4373
|
+
spinner.start("Installing from cached files...");
|
|
4374
|
+
}
|
|
4347
4375
|
if (cachedFiles.sourceFormat) {
|
|
4348
4376
|
sourceFormat = cachedFiles.sourceFormat;
|
|
4349
4377
|
}
|
|
@@ -4573,7 +4601,7 @@ async function search(query, options2) {
|
|
|
4573
4601
|
try {
|
|
4574
4602
|
const limit = parseInt(options2.limit || "10");
|
|
4575
4603
|
const page = parseInt(options2.page || "1");
|
|
4576
|
-
const sort = options2.sort || "
|
|
4604
|
+
const sort = options2.sort || "recommended";
|
|
4577
4605
|
const result = await searchSkills(query, {
|
|
4578
4606
|
platform: options2.platform,
|
|
4579
4607
|
limit,
|
|
@@ -4586,7 +4614,7 @@ async function search(query, options2) {
|
|
|
4586
4614
|
console.log(chalk2.dim("Try a different search term or check the spelling."));
|
|
4587
4615
|
return;
|
|
4588
4616
|
}
|
|
4589
|
-
const sortLabel = { downloads: "downloads", stars: "GitHub stars", rating: "rating", recent: "recently updated" }[sort] || sort;
|
|
4617
|
+
const sortLabel = { recommended: "recommended", downloads: "downloads", stars: "GitHub stars", rating: "rating", recent: "recently updated", aiScore: "AI score" }[sort] || sort;
|
|
4590
4618
|
console.log(chalk2.bold(`Found ${result.pagination.total} skills (sorted by ${sortLabel}):
|
|
4591
4619
|
`));
|
|
4592
4620
|
console.log(
|
|
@@ -4610,6 +4638,12 @@ async function search(query, options2) {
|
|
|
4610
4638
|
` ${chalk2.yellow("\u2605")} ${skill.rating.toFixed(1)} ${chalk2.dim(`(${skill.ratingCount} ratings)`)}`
|
|
4611
4639
|
);
|
|
4612
4640
|
}
|
|
4641
|
+
if (skill.aiScore && skill.reviewStatus && skill.reviewStatus !== "unreviewed" && skill.reviewStatus !== "auto-scored") {
|
|
4642
|
+
const scoreColor = skill.aiScore >= 75 ? chalk2.green : skill.aiScore >= 50 ? chalk2.yellow : chalk2.dim;
|
|
4643
|
+
console.log(
|
|
4644
|
+
` ${chalk2.magenta("AI")} ${scoreColor(String(skill.aiScore))} ${chalk2.dim(`(${skill.reviewStatus})`)}`
|
|
4645
|
+
);
|
|
4646
|
+
}
|
|
4613
4647
|
console.log(chalk2.dim("\u2500".repeat(80)));
|
|
4614
4648
|
}
|
|
4615
4649
|
console.log();
|
|
@@ -4620,8 +4654,8 @@ async function search(query, options2) {
|
|
|
4620
4654
|
chalk2.dim(`Page ${page} of ${totalPages}. Use ${chalk2.white(`--page ${page + 1}`)} for next page.`)
|
|
4621
4655
|
);
|
|
4622
4656
|
}
|
|
4623
|
-
if (sort === "
|
|
4624
|
-
console.log(chalk2.dim(`Sort options: ${chalk2.white("--sort stars|rating|recent")}`));
|
|
4657
|
+
if (sort === "recommended") {
|
|
4658
|
+
console.log(chalk2.dim(`Sort options: ${chalk2.white("--sort downloads|stars|rating|recent|aiScore")}`));
|
|
4625
4659
|
}
|
|
4626
4660
|
} catch (error) {
|
|
4627
4661
|
spinner.fail("Search failed");
|
|
@@ -4855,7 +4889,7 @@ program.command("install <skill-id>").description("Install a skill from the regi
|
|
|
4855
4889
|
// Commander converts --no-api to api: false
|
|
4856
4890
|
});
|
|
4857
4891
|
});
|
|
4858
|
-
program.command("search <query>").description("Search for skills in the registry").option("-p, --platform <platform>", "Filter by platform").option("-s, --sort <sort>", "Sort by: downloads, stars, rating, recent", "
|
|
4892
|
+
program.command("search <query>").description("Search for skills in the registry").option("-p, --platform <platform>", "Filter by platform").option("-s, --sort <sort>", "Sort by: recommended, downloads, stars, rating, recent, aiScore", "recommended").option("-l, --limit <number>", "Number of results", "10").option("--page <number>", "Page number", "1").action(async (query, options2) => {
|
|
4859
4893
|
await search(query, options2);
|
|
4860
4894
|
});
|
|
4861
4895
|
program.command("list").description("List installed skills").option("-p, --platform <platform>", "Filter by platform").option("--project", "List skills in the current project").option("--all", "List both global and project skills").action(async (options2) => {
|
package/package.json
CHANGED