skilld 0.9.6 → 0.10.1
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/_chunks/detect-imports.mjs +101 -68
- package/dist/_chunks/detect-imports.mjs.map +1 -1
- package/dist/_chunks/npm.mjs +204 -121
- package/dist/_chunks/npm.mjs.map +1 -1
- package/dist/_chunks/storage.mjs +12 -1
- package/dist/_chunks/storage.mjs.map +1 -1
- package/dist/_chunks/utils.d.mts +18 -2
- package/dist/_chunks/utils.d.mts.map +1 -1
- package/dist/_chunks/version.d.mts.map +1 -1
- package/dist/_chunks/yaml.mjs +7 -1
- package/dist/_chunks/yaml.mjs.map +1 -1
- package/dist/agent/index.d.mts +4 -0
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/cli.mjs +410 -271
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/sources/index.d.mts +2 -2
- package/dist/sources/index.mjs +3 -3
- package/dist/types.d.mts +1 -1
- package/package.json +3 -3
package/dist/_chunks/npm.mjs
CHANGED
|
@@ -116,7 +116,7 @@ function hasCodeBlock$1(text) {
|
|
|
116
116
|
function isNonTechnical(issue) {
|
|
117
117
|
const body = (issue.body || "").trim();
|
|
118
118
|
if (body.length < 200 && !hasCodeBlock$1(body) && issue.reactions > 50) return true;
|
|
119
|
-
if (/\b(?:
|
|
119
|
+
if (/\b(?:love|thank|awesome|great work)\b/i.test(issue.title) && !hasCodeBlock$1(body)) return true;
|
|
120
120
|
return false;
|
|
121
121
|
}
|
|
122
122
|
function freshnessScore(reactions, createdAt) {
|
|
@@ -197,18 +197,26 @@ function fetchIssuesByState(owner, repo, state, count, releasedAt, fromDate) {
|
|
|
197
197
|
"api",
|
|
198
198
|
`search/issues?q=${`repo:${owner}/${repo}+is:issue+is:${state}${datePart}`}&sort=reactions&order=desc&per_page=${fetchCount}`,
|
|
199
199
|
"-q",
|
|
200
|
-
".items[] | {number, title, state, labels: [.labels[]?.name], body, createdAt: .created_at, url: .html_url, reactions: .reactions[\"+1\"], comments: .comments, user: .user.login, userType: .user.type}"
|
|
200
|
+
".items[] | {number, title, state, labels: [.labels[]?.name], body, createdAt: .created_at, url: .html_url, reactions: .reactions[\"+1\"], comments: .comments, user: .user.login, userType: .user.type, authorAssociation: .author_association}"
|
|
201
201
|
], {
|
|
202
202
|
encoding: "utf-8",
|
|
203
203
|
maxBuffer: 10 * 1024 * 1024
|
|
204
204
|
});
|
|
205
205
|
if (!result) return [];
|
|
206
|
-
return result.trim().split("\n").filter(Boolean).map((line) => JSON.parse(line)).filter((issue) => !BOT_USERS.has(issue.user) && issue.userType !== "Bot").filter((issue) => !isNoiseIssue(issue)).filter((issue) => !isNonTechnical(issue)).map(({ user: _, userType: __, ...issue }) =>
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
206
|
+
return result.trim().split("\n").filter(Boolean).map((line) => JSON.parse(line)).filter((issue) => !BOT_USERS.has(issue.user) && issue.userType !== "Bot").filter((issue) => !isNoiseIssue(issue)).filter((issue) => !isNonTechnical(issue)).map(({ user: _, userType: __, authorAssociation, ...issue }) => {
|
|
207
|
+
const isMaintainer = [
|
|
208
|
+
"OWNER",
|
|
209
|
+
"MEMBER",
|
|
210
|
+
"COLLABORATOR"
|
|
211
|
+
].includes(authorAssociation);
|
|
212
|
+
const isRoadmap = /\broadmap\b/i.test(issue.title) || issue.labels.some((l) => /roadmap/i.test(l));
|
|
213
|
+
return {
|
|
214
|
+
...issue,
|
|
215
|
+
type: classifyIssue(issue.labels),
|
|
216
|
+
topComments: [],
|
|
217
|
+
score: freshnessScore(issue.reactions, issue.createdAt) * (isMaintainer && isRoadmap ? 5 : 1)
|
|
218
|
+
};
|
|
219
|
+
}).sort((a, b) => b.score - a.score).slice(0, count);
|
|
212
220
|
}
|
|
213
221
|
function oneYearAgo() {
|
|
214
222
|
const d = /* @__PURE__ */ new Date();
|
|
@@ -418,6 +426,25 @@ function parseGitHubUrl(url) {
|
|
|
418
426
|
function normalizeRepoUrl(url) {
|
|
419
427
|
return url.replace(/^git\+/, "").replace(/#.*$/, "").replace(/\.git$/, "").replace(/^git:\/\//, "https://").replace(/^ssh:\/\/git@github\.com/, "https://github.com").replace(/^git@github\.com:/, "https://github.com/");
|
|
420
428
|
}
|
|
429
|
+
function parsePackageSpec(spec) {
|
|
430
|
+
if (spec.startsWith("@")) {
|
|
431
|
+
const slashIdx = spec.indexOf("/");
|
|
432
|
+
if (slashIdx !== -1) {
|
|
433
|
+
const atIdx = spec.indexOf("@", slashIdx + 1);
|
|
434
|
+
if (atIdx !== -1) return {
|
|
435
|
+
name: spec.slice(0, atIdx),
|
|
436
|
+
tag: spec.slice(atIdx + 1)
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
return { name: spec };
|
|
440
|
+
}
|
|
441
|
+
const atIdx = spec.indexOf("@");
|
|
442
|
+
if (atIdx !== -1) return {
|
|
443
|
+
name: spec.slice(0, atIdx),
|
|
444
|
+
tag: spec.slice(atIdx + 1)
|
|
445
|
+
};
|
|
446
|
+
return { name: spec };
|
|
447
|
+
}
|
|
421
448
|
function extractBranchHint(url) {
|
|
422
449
|
const hash = url.indexOf("#");
|
|
423
450
|
if (hash === -1) return void 0;
|
|
@@ -461,22 +488,23 @@ function compareSemver(a, b) {
|
|
|
461
488
|
}
|
|
462
489
|
function fetchReleasesViaGh(owner, repo) {
|
|
463
490
|
try {
|
|
464
|
-
const { stdout:
|
|
491
|
+
const { stdout: ndjson } = spawnSync("gh", [
|
|
465
492
|
"api",
|
|
466
|
-
`repos/${owner}/${repo}/releases
|
|
493
|
+
`repos/${owner}/${repo}/releases`,
|
|
494
|
+
"--paginate",
|
|
467
495
|
"--jq",
|
|
468
|
-
"
|
|
496
|
+
".[] | {id: .id, tag: .tag_name, name: .name, prerelease: .prerelease, createdAt: .created_at, publishedAt: .published_at, markdown: .body}"
|
|
469
497
|
], {
|
|
470
498
|
encoding: "utf-8",
|
|
471
|
-
timeout:
|
|
499
|
+
timeout: 3e4,
|
|
472
500
|
stdio: [
|
|
473
501
|
"ignore",
|
|
474
502
|
"pipe",
|
|
475
503
|
"ignore"
|
|
476
504
|
]
|
|
477
505
|
});
|
|
478
|
-
if (!
|
|
479
|
-
return JSON.parse(
|
|
506
|
+
if (!ndjson) return [];
|
|
507
|
+
return ndjson.trim().split("\n").filter(Boolean).map((line) => JSON.parse(line));
|
|
480
508
|
} catch {
|
|
481
509
|
return [];
|
|
482
510
|
}
|
|
@@ -574,21 +602,21 @@ function generateReleaseIndex(releasesOrOpts, packageName) {
|
|
|
574
602
|
}
|
|
575
603
|
return lines.join("\n");
|
|
576
604
|
}
|
|
577
|
-
function
|
|
578
|
-
const
|
|
579
|
-
|
|
580
|
-
return sample.every((r) => {
|
|
581
|
-
const body = (r.markdown || "").trim();
|
|
582
|
-
return body.length < 500 && /changelog\.md/i.test(body);
|
|
583
|
-
});
|
|
605
|
+
function isStubRelease(release) {
|
|
606
|
+
const body = (release.markdown || "").trim();
|
|
607
|
+
return body.length < 500 && /changelog\.md/i.test(body);
|
|
584
608
|
}
|
|
585
|
-
async function fetchChangelog(owner, repo, ref) {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
"
|
|
590
|
-
|
|
591
|
-
const
|
|
609
|
+
async function fetchChangelog(owner, repo, ref, packageName) {
|
|
610
|
+
const paths = [];
|
|
611
|
+
if (packageName) {
|
|
612
|
+
const shortName = packageName.replace(/^@.*\//, "");
|
|
613
|
+
const scopeless = packageName.replace(/^@/, "").replace("/", "-");
|
|
614
|
+
const candidates = [...new Set([shortName, scopeless])];
|
|
615
|
+
for (const name of candidates) paths.push(`packages/${name}/CHANGELOG.md`);
|
|
616
|
+
}
|
|
617
|
+
paths.push("CHANGELOG.md", "changelog.md", "CHANGES.md");
|
|
618
|
+
for (const path of paths) {
|
|
619
|
+
const content = await $fetch(`https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${path}`, {
|
|
592
620
|
responseType: "text",
|
|
593
621
|
signal: AbortSignal.timeout(1e4)
|
|
594
622
|
}).catch(() => null);
|
|
@@ -596,30 +624,23 @@ async function fetchChangelog(owner, repo, ref) {
|
|
|
596
624
|
}
|
|
597
625
|
return null;
|
|
598
626
|
}
|
|
599
|
-
async function fetchReleaseNotes(owner, repo, installedVersion, gitRef, packageName, fromDate) {
|
|
627
|
+
async function fetchReleaseNotes(owner, repo, installedVersion, gitRef, packageName, fromDate, changelogRef) {
|
|
600
628
|
const selected = selectReleases(await fetchAllReleases(owner, repo), packageName, installedVersion, fromDate);
|
|
601
629
|
if (selected.length > 0) {
|
|
602
|
-
|
|
603
|
-
const changelog = await fetchChangelog(owner, repo, gitRef || selected[0].tag);
|
|
604
|
-
if (changelog) return [{
|
|
605
|
-
path: "releases/CHANGELOG.md",
|
|
606
|
-
content: changelog
|
|
607
|
-
}];
|
|
608
|
-
}
|
|
609
|
-
const docs = selected.map((r) => {
|
|
630
|
+
const docs = selected.filter((r) => !isStubRelease(r)).map((r) => {
|
|
610
631
|
return {
|
|
611
632
|
path: `releases/${r.tag.includes("@") || r.tag.startsWith("v") ? r.tag : `v${r.tag}`}.md`,
|
|
612
633
|
content: formatRelease(r, packageName)
|
|
613
634
|
};
|
|
614
635
|
});
|
|
615
|
-
const changelog = await fetchChangelog(owner, repo, gitRef || selected[0].tag);
|
|
636
|
+
const changelog = await fetchChangelog(owner, repo, changelogRef || gitRef || selected[0].tag, packageName);
|
|
616
637
|
if (changelog && changelog.length < 5e5) docs.push({
|
|
617
638
|
path: "releases/CHANGELOG.md",
|
|
618
639
|
content: changelog
|
|
619
640
|
});
|
|
620
641
|
return docs;
|
|
621
642
|
}
|
|
622
|
-
const changelog = await fetchChangelog(owner, repo, gitRef || "main");
|
|
643
|
+
const changelog = await fetchChangelog(owner, repo, changelogRef || gitRef || "main", packageName);
|
|
623
644
|
if (!changelog) return [];
|
|
624
645
|
return [{
|
|
625
646
|
path: "releases/CHANGELOG.md",
|
|
@@ -1169,6 +1190,89 @@ async function fetchGitLabSkills(source, onProgress) {
|
|
|
1169
1190
|
async function fetchRawGitLab(owner, repo, ref, path) {
|
|
1170
1191
|
return $fetch(`https://gitlab.com/${owner}/${repo}/-/raw/${ref}/${path}`, { responseType: "text" }).catch(() => null);
|
|
1171
1192
|
}
|
|
1193
|
+
async function fetchLlmsUrl(docsUrl) {
|
|
1194
|
+
const llmsUrl = `${new URL(docsUrl).origin}/llms.txt`;
|
|
1195
|
+
if (await verifyUrl(llmsUrl)) return llmsUrl;
|
|
1196
|
+
return null;
|
|
1197
|
+
}
|
|
1198
|
+
async function fetchLlmsTxt(url) {
|
|
1199
|
+
const content = await fetchText(url);
|
|
1200
|
+
if (!content || content.length < 50) return null;
|
|
1201
|
+
return {
|
|
1202
|
+
raw: content,
|
|
1203
|
+
links: parseMarkdownLinks(content)
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
function parseMarkdownLinks(content) {
|
|
1207
|
+
const links = [];
|
|
1208
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1209
|
+
const linkRegex = /\[([^\]]+)\]\(([^)]+\.md)\)/g;
|
|
1210
|
+
for (let match = linkRegex.exec(content); match !== null; match = linkRegex.exec(content)) {
|
|
1211
|
+
const url = match[2];
|
|
1212
|
+
if (!seen.has(url)) {
|
|
1213
|
+
seen.add(url);
|
|
1214
|
+
links.push({
|
|
1215
|
+
title: match[1],
|
|
1216
|
+
url
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
return links;
|
|
1221
|
+
}
|
|
1222
|
+
function isSafeUrl(url) {
|
|
1223
|
+
try {
|
|
1224
|
+
const parsed = new URL(url);
|
|
1225
|
+
if (parsed.protocol !== "https:") return false;
|
|
1226
|
+
const host = parsed.hostname;
|
|
1227
|
+
if (host === "localhost" || host === "127.0.0.1" || host === "::1") return false;
|
|
1228
|
+
if (host === "169.254.169.254") return false;
|
|
1229
|
+
if (/^(?:10\.|172\.(?:1[6-9]|2\d|3[01])\.|192\.168\.)/.test(host)) return false;
|
|
1230
|
+
if (host.startsWith("[")) return false;
|
|
1231
|
+
return true;
|
|
1232
|
+
} catch {
|
|
1233
|
+
return false;
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
async function downloadLlmsDocs(llmsContent, baseUrl, onProgress) {
|
|
1237
|
+
const limit = pLimit(5);
|
|
1238
|
+
let completed = 0;
|
|
1239
|
+
return (await Promise.all(llmsContent.links.map((link) => limit(async () => {
|
|
1240
|
+
const url = link.url.startsWith("http") ? link.url : `${baseUrl.replace(/\/$/, "")}${link.url.startsWith("/") ? "" : "/"}${link.url}`;
|
|
1241
|
+
if (!isSafeUrl(url)) return null;
|
|
1242
|
+
onProgress?.(link.url, completed++, llmsContent.links.length);
|
|
1243
|
+
const content = await fetchText(url);
|
|
1244
|
+
if (content && content.length > 100) return {
|
|
1245
|
+
url: link.url,
|
|
1246
|
+
title: link.title,
|
|
1247
|
+
content
|
|
1248
|
+
};
|
|
1249
|
+
return null;
|
|
1250
|
+
})))).filter((d) => d !== null);
|
|
1251
|
+
}
|
|
1252
|
+
function normalizeLlmsLinks(content, baseUrl) {
|
|
1253
|
+
let normalized = content;
|
|
1254
|
+
if (baseUrl) {
|
|
1255
|
+
const escaped = baseUrl.replace(/\/$/, "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1256
|
+
normalized = normalized.replace(new RegExp(`\\]\\(${escaped}(/[^)]+\\.md)\\)`, "g"), "](./docs$1)");
|
|
1257
|
+
}
|
|
1258
|
+
normalized = normalized.replace(/\]\(\/([^)]+\.md)\)/g, "](./docs/$1)");
|
|
1259
|
+
return normalized;
|
|
1260
|
+
}
|
|
1261
|
+
function extractSections(content, patterns) {
|
|
1262
|
+
const sections = [];
|
|
1263
|
+
const parts = content.split(/\n---\n/);
|
|
1264
|
+
for (const part of parts) {
|
|
1265
|
+
const urlMatch = part.match(/^url: *(\S.*)$/m);
|
|
1266
|
+
if (!urlMatch) continue;
|
|
1267
|
+
const url = urlMatch[1];
|
|
1268
|
+
if (patterns.some((p) => url.includes(p))) {
|
|
1269
|
+
const contentStart = part.indexOf("\n", part.indexOf("url:"));
|
|
1270
|
+
if (contentStart > -1) sections.push(part.slice(contentStart + 1));
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
if (sections.length === 0) return null;
|
|
1274
|
+
return sections.join("\n\n---\n\n");
|
|
1275
|
+
}
|
|
1172
1276
|
const MIN_GIT_DOCS = 5;
|
|
1173
1277
|
const isShallowGitDocs = (n) => n > 0 && n < MIN_GIT_DOCS;
|
|
1174
1278
|
async function listFilesAtRef(owner, repo, ref) {
|
|
@@ -1316,7 +1420,8 @@ async function fetchGitDocs(owner, repo, version, packageName, repoUrl) {
|
|
|
1316
1420
|
baseUrl: `https://raw.githubusercontent.com/${override.owner}/${override.repo}/${ref}`,
|
|
1317
1421
|
ref,
|
|
1318
1422
|
files,
|
|
1319
|
-
fallback
|
|
1423
|
+
fallback,
|
|
1424
|
+
docsPrefix: `${override.path}/` !== "docs/" ? `${override.path}/` : void 0
|
|
1320
1425
|
};
|
|
1321
1426
|
}
|
|
1322
1427
|
const tag = await findGitTag(owner, repo, version, packageName, repoUrl ? extractBranchHint(repoUrl) : void 0);
|
|
@@ -1492,89 +1597,67 @@ async function fetchReadmeContent(url) {
|
|
|
1492
1597
|
}
|
|
1493
1598
|
return fetchText(url);
|
|
1494
1599
|
}
|
|
1495
|
-
async function
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1600
|
+
async function resolveGitHubRepo(owner, repo, onProgress) {
|
|
1601
|
+
onProgress?.("Fetching repo metadata");
|
|
1602
|
+
const repoUrl = `https://github.com/${owner}/${repo}`;
|
|
1603
|
+
let homepage;
|
|
1604
|
+
let description;
|
|
1605
|
+
if (isGhAvailable()) try {
|
|
1606
|
+
const { stdout: json } = spawnSync("gh", [
|
|
1607
|
+
"api",
|
|
1608
|
+
`repos/${owner}/${repo}`,
|
|
1609
|
+
"--jq",
|
|
1610
|
+
"{homepage: .homepage, description: .description}"
|
|
1611
|
+
], {
|
|
1612
|
+
encoding: "utf-8",
|
|
1613
|
+
timeout: 1e4
|
|
1614
|
+
});
|
|
1615
|
+
if (json) {
|
|
1616
|
+
const data = JSON.parse(json);
|
|
1617
|
+
homepage = data.homepage || void 0;
|
|
1618
|
+
description = data.description || void 0;
|
|
1619
|
+
}
|
|
1620
|
+
} catch {}
|
|
1621
|
+
if (!homepage && !description) {
|
|
1622
|
+
const data = await $fetch(`https://api.github.com/repos/${owner}/${repo}`).catch(() => null);
|
|
1623
|
+
homepage = data?.homepage || void 0;
|
|
1624
|
+
description = data?.description || void 0;
|
|
1625
|
+
}
|
|
1626
|
+
onProgress?.("Fetching latest release");
|
|
1627
|
+
const releasesData = await $fetch(`https://ungh.cc/repos/${owner}/${repo}/releases`).catch(() => null);
|
|
1628
|
+
let version = "main";
|
|
1629
|
+
let releasedAt;
|
|
1630
|
+
const latestRelease = releasesData?.releases?.[0];
|
|
1631
|
+
if (latestRelease) {
|
|
1632
|
+
version = latestRelease.tag.replace(/^v/, "");
|
|
1633
|
+
releasedAt = latestRelease.publishedAt;
|
|
1634
|
+
}
|
|
1635
|
+
onProgress?.("Resolving docs");
|
|
1636
|
+
const gitDocs = await fetchGitDocs(owner, repo, version);
|
|
1637
|
+
const gitDocsUrl = gitDocs ? `${repoUrl}/tree/${gitDocs.ref}/docs` : void 0;
|
|
1638
|
+
const gitRef = gitDocs?.ref;
|
|
1639
|
+
onProgress?.("Fetching README");
|
|
1640
|
+
const readmeUrl = await fetchReadme(owner, repo);
|
|
1641
|
+
let llmsUrl;
|
|
1642
|
+
if (homepage) {
|
|
1643
|
+
onProgress?.("Checking llms.txt");
|
|
1644
|
+
llmsUrl = await fetchLlmsUrl(homepage).catch(() => null) ?? void 0;
|
|
1645
|
+
}
|
|
1646
|
+
if (!gitDocsUrl && !readmeUrl && !llmsUrl) return null;
|
|
1503
1647
|
return {
|
|
1504
|
-
|
|
1505
|
-
|
|
1648
|
+
name: repo,
|
|
1649
|
+
version: latestRelease ? version : void 0,
|
|
1650
|
+
releasedAt,
|
|
1651
|
+
description,
|
|
1652
|
+
repoUrl,
|
|
1653
|
+
docsUrl: homepage,
|
|
1654
|
+
gitDocsUrl,
|
|
1655
|
+
gitRef,
|
|
1656
|
+
gitDocsFallback: gitDocs?.fallback,
|
|
1657
|
+
readmeUrl: readmeUrl ?? void 0,
|
|
1658
|
+
llmsUrl
|
|
1506
1659
|
};
|
|
1507
1660
|
}
|
|
1508
|
-
function parseMarkdownLinks(content) {
|
|
1509
|
-
const links = [];
|
|
1510
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1511
|
-
const linkRegex = /\[([^\]]+)\]\(([^)]+\.md)\)/g;
|
|
1512
|
-
for (let match = linkRegex.exec(content); match !== null; match = linkRegex.exec(content)) {
|
|
1513
|
-
const url = match[2];
|
|
1514
|
-
if (!seen.has(url)) {
|
|
1515
|
-
seen.add(url);
|
|
1516
|
-
links.push({
|
|
1517
|
-
title: match[1],
|
|
1518
|
-
url
|
|
1519
|
-
});
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
return links;
|
|
1523
|
-
}
|
|
1524
|
-
function isSafeUrl(url) {
|
|
1525
|
-
try {
|
|
1526
|
-
const parsed = new URL(url);
|
|
1527
|
-
if (parsed.protocol !== "https:") return false;
|
|
1528
|
-
const host = parsed.hostname;
|
|
1529
|
-
if (host === "localhost" || host === "127.0.0.1" || host === "::1") return false;
|
|
1530
|
-
if (host === "169.254.169.254") return false;
|
|
1531
|
-
if (/^(?:10\.|172\.(?:1[6-9]|2\d|3[01])\.|192\.168\.)/.test(host)) return false;
|
|
1532
|
-
if (host.startsWith("[")) return false;
|
|
1533
|
-
return true;
|
|
1534
|
-
} catch {
|
|
1535
|
-
return false;
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
|
-
async function downloadLlmsDocs(llmsContent, baseUrl, onProgress) {
|
|
1539
|
-
const limit = pLimit(5);
|
|
1540
|
-
let completed = 0;
|
|
1541
|
-
return (await Promise.all(llmsContent.links.map((link) => limit(async () => {
|
|
1542
|
-
const url = link.url.startsWith("http") ? link.url : `${baseUrl.replace(/\/$/, "")}${link.url.startsWith("/") ? "" : "/"}${link.url}`;
|
|
1543
|
-
if (!isSafeUrl(url)) return null;
|
|
1544
|
-
onProgress?.(link.url, completed++, llmsContent.links.length);
|
|
1545
|
-
const content = await fetchText(url);
|
|
1546
|
-
if (content && content.length > 100) return {
|
|
1547
|
-
url: link.url,
|
|
1548
|
-
title: link.title,
|
|
1549
|
-
content
|
|
1550
|
-
};
|
|
1551
|
-
return null;
|
|
1552
|
-
})))).filter((d) => d !== null);
|
|
1553
|
-
}
|
|
1554
|
-
function normalizeLlmsLinks(content, baseUrl) {
|
|
1555
|
-
let normalized = content;
|
|
1556
|
-
if (baseUrl) {
|
|
1557
|
-
const escaped = baseUrl.replace(/\/$/, "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1558
|
-
normalized = normalized.replace(new RegExp(`\\]\\(${escaped}(/[^)]+\\.md)\\)`, "g"), "](./docs$1)");
|
|
1559
|
-
}
|
|
1560
|
-
normalized = normalized.replace(/\]\(\/([^)]+\.md)\)/g, "](./docs/$1)");
|
|
1561
|
-
return normalized;
|
|
1562
|
-
}
|
|
1563
|
-
function extractSections(content, patterns) {
|
|
1564
|
-
const sections = [];
|
|
1565
|
-
const parts = content.split(/\n---\n/);
|
|
1566
|
-
for (const part of parts) {
|
|
1567
|
-
const urlMatch = part.match(/^url: *(\S.*)$/m);
|
|
1568
|
-
if (!urlMatch) continue;
|
|
1569
|
-
const url = urlMatch[1];
|
|
1570
|
-
if (patterns.some((p) => url.includes(p))) {
|
|
1571
|
-
const contentStart = part.indexOf("\n", part.indexOf("url:"));
|
|
1572
|
-
if (contentStart > -1) sections.push(part.slice(contentStart + 1));
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
if (sections.length === 0) return null;
|
|
1576
|
-
return sections.join("\n\n---\n\n");
|
|
1577
|
-
}
|
|
1578
1661
|
async function searchNpmPackages(query, size = 5) {
|
|
1579
1662
|
const data = await $fetch(`https://registry.npmjs.org/-/v1/search?text=${encodeURIComponent(query)}&size=${size}`).catch(() => null);
|
|
1580
1663
|
if (!data?.objects?.length) return [];
|
|
@@ -1965,6 +2048,6 @@ function getInstalledSkillVersion(skillDir) {
|
|
|
1965
2048
|
if (!existsSync(skillPath)) return null;
|
|
1966
2049
|
return readFileSync(skillPath, "utf-8").match(/^version:\s*"?([^"\n]+)"?/m)?.[1] || null;
|
|
1967
2050
|
}
|
|
1968
|
-
export {
|
|
2051
|
+
export { SHARED_SKILLS_DIR as $, parseSkillFrontmatterName as A, parseSemver as B, extractSections as C, parseMarkdownLinks as D, normalizeLlmsLinks as E, fetchBlogReleases as F, normalizeRepoUrl as G, extractBranchHint as H, compareSemver as I, verifyUrl as J, parseGitHubUrl as K, fetchReleaseNotes as L, fetchGitHubDiscussions as M, formatDiscussionAsMarkdown as N, fetchGitSkills as O, generateDiscussionIndex as P, isGhAvailable as Q, generateReleaseIndex as R, downloadLlmsDocs as S, fetchLlmsUrl as T, fetchText as U, $fetch as V, isGitHubRepoUrl as W, formatIssueAsMarkdown as X, fetchGitHubIssues as Y, generateIssueIndex as Z, fetchReadme as _, getInstalledSkillVersion as a, resolveGitHubRepo as b, readLocalPackageInfo as c, resolvePackageDocs as d, getSharedSkillsDir as et, resolvePackageDocsWithAttempts as f, fetchGitHubRepoMeta as g, fetchGitDocs as h, fetchPkgDist as i, resolveEntryFiles as j, parseGitSkillInput as k, resolveInstalledVersion as l, MIN_GIT_DOCS as m, fetchNpmPackage as n, semverGt as nt, parseVersionSpecifier as o, searchNpmPackages as p, parsePackageSpec as q, fetchNpmRegistryMeta as r, readLocalDependencies as s, fetchLatestVersion as t, mapInsert as tt, resolveLocalPackageDocs as u, fetchReadmeContent as v, fetchLlmsTxt as w, validateGitDocsWithLlms as x, isShallowGitDocs as y, isPrerelease as z };
|
|
1969
2052
|
|
|
1970
2053
|
//# sourceMappingURL=npm.mjs.map
|