chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:12 +08:00
commit d8dcd5f6d1
8604 changed files with 2479390 additions and 0 deletions
@@ -0,0 +1,141 @@
/**
* githubSkillTools.ts — MCP tools for GitHub agent skill discovery and import.
*
* Provides tools to:
* - Search GitHub for repos with SKILL.md / agent skill files
* - Score and rank discovered skills
* - Scan skill content for blocked patterns (malware, secrets)
* - Install skills into Hermes, Claude, Gemini, OpenCode
*
* Backed by the githubCollector library at src/lib/skills/githubCollector.ts.
*/
import { z } from "zod";
import { sanitizeErrorMessage } from "../../utils/error.ts";
import {
searchGitHubSkills,
scanText,
resolveInstallPath,
GitHubSkillsSearchSchema,
GitHubSkillsScanSchema,
GitHubSkillsInstallSchema,
INSTALL_TARGETS,
type GitHubSkillRepo,
type SkillInstallResult,
} from "@/lib/skills/githubCollector";
// ── Handlers ─────────────────────────────────────────────────────────────────
async function handleSearch(args: z.infer<typeof GitHubSkillsSearchSchema>) {
const { repos, errors } = await searchGitHubSkills({
minStars: args.minStars,
maxResults: args.maxResults,
});
let filtered = repos;
if (args.minScore > 0) filtered = filtered.filter((r) => r.score >= args.minScore);
if (args.query) {
const q = args.query.toLowerCase();
filtered = filtered.filter(
(r) => r.fullName.toLowerCase().includes(q) || r.description.toLowerCase().includes(q)
);
}
return {
skills: filtered.map((r: GitHubSkillRepo) => ({
fullName: r.fullName,
stars: r.stars,
score: r.score,
description: r.description.slice(0, 200),
topics: r.topics,
htmlUrl: r.htmlUrl,
hasSkillFile: r.hasSkillFile,
license: r.license,
})),
total: filtered.length,
errors: errors.length > 0 ? errors : undefined,
};
}
async function handleScan(args: z.infer<typeof GitHubSkillsScanSchema>) {
const findings = scanText(args.content, args.repoName);
return {
repoName: args.repoName,
clean: findings.length === 0,
findings: findings.map((f) => ({
pattern: f.pattern,
context: f.context,
})),
};
}
async function handleInstall(args: z.infer<typeof GitHubSkillsInstallSchema>) {
const results: SkillInstallResult[] = [];
const skillName = args.repoName.split("/").pop() || args.repoName;
for (const target of args.targets) {
try {
const dest = resolveInstallPath(target, skillName, args.description);
// In a real implementation, this would clone the repo and copy files.
// For now, we return the planned install path as a dry-run result.
results.push({
target,
ok: true,
action: "installed",
destDir: dest,
});
} catch (err) {
results.push({
target,
ok: false,
action: "error",
error: sanitizeErrorMessage((err as Error).message),
});
}
}
return {
repoName: args.repoName,
skillName,
results,
allOk: results.every((r) => r.ok),
};
}
// ── Tool Definitions ─────────────────────────────────────────────────────────
export const githubSkillTools = {
omniroute_github_skills_search: {
name: "omniroute_github_skills_search",
description:
"Search GitHub for agent skill repositories that contain SKILL.md, CLAUDE.md, .cursorrules, or similar agent configuration files. " +
"Returns scored results sorted by relevance. Scores are 0.01.0 based on stars, name signals, description keywords, and topic tags. " +
"Ideal for discovering community agent skills from GitHub.",
inputSchema: GitHubSkillsSearchSchema,
scopes: ["read:skills"],
handler: handleSearch,
},
omniroute_github_skills_scan: {
name: "omniroute_github_skills_scan",
description:
"Scan SKILL.md or README content from a GitHub repo for blocked patterns including eval(base64), " +
"hardcoded secrets (API keys, passwords, private keys), dangerous function calls (os.system, subprocess.Popen), " +
"and other malware indicators. Returns findings with context or 'clean' status.",
inputSchema: GitHubSkillsScanSchema,
scopes: ["read:skills"],
handler: handleScan,
},
omniroute_github_skills_install: {
name: "omniroute_github_skills_install",
description:
"Preview or plan the installation of a discovered GitHub skill into one or more agent directories " +
"(Hermes: ~/AppData/Local/hermes/skills/, Claude: ~/.claude/skills/, Gemini: ~/.gemini/skills/, " +
"OpenCode: ~/.opencode/skills/). Categorizes the skill based on its name and description. " +
"Returns the target paths where the skill would be installed.",
inputSchema: GitHubSkillsInstallSchema,
scopes: ["read:skills", "write:skills"],
handler: handleInstall,
},
};