skilld 0.2.1 → 0.3.0

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.
@@ -1,4 +1,4 @@
1
- import { a as getCacheDir } from "./config.mjs";
1
+ import { i as getCacheDir } from "./config.mjs";
2
2
  import { basename, dirname, join, resolve } from "pathe";
3
3
  import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, unlinkSync } from "node:fs";
4
4
  import { spawnSync } from "node:child_process";
@@ -8,12 +8,6 @@ import pLimit from "p-limit";
8
8
  import { Writable } from "node:stream";
9
9
  import { pathToFileURL } from "node:url";
10
10
  import { resolvePathSync } from "mlly";
11
- let _ghAvailable;
12
- function isGhAvailable() {
13
- if (_ghAvailable !== void 0) return _ghAvailable;
14
- const { status } = spawnSync("gh", ["auth", "status"], { stdio: "ignore" });
15
- return _ghAvailable = status === 0;
16
- }
17
11
  const BOT_USERS = new Set([
18
12
  "renovate[bot]",
19
13
  "dependabot[bot]",
@@ -21,6 +15,19 @@ const BOT_USERS = new Set([
21
15
  "dependabot",
22
16
  "github-actions[bot]"
23
17
  ]);
18
+ const isoDate = (iso) => iso.split("T")[0];
19
+ function buildFrontmatter(fields) {
20
+ const lines = ["---"];
21
+ for (const [k, v] of Object.entries(fields)) if (v !== void 0) lines.push(`${k}: ${typeof v === "string" && /[:"[\]]/.test(v) ? `"${v.replace(/"/g, "\\\"")}"` : v}`);
22
+ lines.push("---");
23
+ return lines.join("\n");
24
+ }
25
+ let _ghAvailable;
26
+ function isGhAvailable() {
27
+ if (_ghAvailable !== void 0) return _ghAvailable;
28
+ const { status } = spawnSync("gh", ["auth", "status"], { stdio: "ignore" });
29
+ return _ghAvailable = status === 0;
30
+ }
24
31
  const NOISE_LABELS = new Set([
25
32
  "duplicate",
26
33
  "stale",
@@ -106,7 +113,7 @@ function fetchIssuesByState(owner, repo, state, count) {
106
113
  function oneYearAgo() {
107
114
  const d = /* @__PURE__ */ new Date();
108
115
  d.setFullYear(d.getFullYear() - 1);
109
- return d.toISOString().split("T")[0];
116
+ return isoDate(d.toISOString());
110
117
  }
111
118
  function enrichWithComments(owner, repo, issues, topN = 10) {
112
119
  const worth = issues.filter((i) => i.comments > 0 && (i.type === "bug" || i.type === "question" || i.reactions >= 3)).sort((a, b) => b.reactions - a.reactions).slice(0, topN);
@@ -156,21 +163,19 @@ async function fetchGitHubIssues(owner, repo, limit = 30) {
156
163
  }
157
164
  function formatIssueAsMarkdown(issue) {
158
165
  const limit = bodyLimit(issue.reactions);
159
- const fm = [
160
- "---",
161
- `number: ${issue.number}`,
162
- `title: "${issue.title.replace(/"/g, "\\\"")}"`,
163
- `type: ${issue.type}`,
164
- `state: ${issue.state}`,
165
- `created: ${issue.createdAt.split("T")[0]}`,
166
- `url: ${issue.url}`,
167
- `reactions: ${issue.reactions}`,
168
- `comments: ${issue.comments}`
169
- ];
170
- if (issue.labels.length > 0) fm.push(`labels: [${issue.labels.join(", ")}]`);
171
- fm.push("---");
166
+ const fmFields = {
167
+ number: issue.number,
168
+ title: issue.title,
169
+ type: issue.type,
170
+ state: issue.state,
171
+ created: isoDate(issue.createdAt),
172
+ url: issue.url,
173
+ reactions: issue.reactions,
174
+ comments: issue.comments
175
+ };
176
+ if (issue.labels.length > 0) fmFields.labels = `[${issue.labels.join(", ")}]`;
172
177
  const lines = [
173
- fm.join("\n"),
178
+ buildFrontmatter(fmFields),
174
179
  "",
175
180
  `# ${issue.title}`
176
181
  ];
@@ -264,13 +269,6 @@ async function fetchGitHubDiscussions(owner, repo, limit = 20) {
264
269
  if (!result) return [];
265
270
  const nodes = JSON.parse(result)?.data?.repository?.discussions?.nodes;
266
271
  if (!Array.isArray(nodes)) return [];
267
- const BOT_USERS = new Set([
268
- "renovate[bot]",
269
- "dependabot[bot]",
270
- "renovate-bot",
271
- "dependabot",
272
- "github-actions[bot]"
273
- ]);
274
272
  return nodes.filter((d) => d.author && !BOT_USERS.has(d.author.login)).filter((d) => {
275
273
  const cat = (d.category?.name || "").toLowerCase();
276
274
  return !LOW_VALUE_CATEGORIES.has(cat);
@@ -299,21 +297,19 @@ async function fetchGitHubDiscussions(owner, repo, limit = 20) {
299
297
  }
300
298
  }
301
299
  function formatDiscussionAsMarkdown(d) {
302
- const fm = [
303
- "---",
304
- `number: ${d.number}`,
305
- `title: "${d.title.replace(/"/g, "\\\"")}"`,
306
- `category: ${d.category}`,
307
- `created: ${d.createdAt.split("T")[0]}`,
308
- `url: ${d.url}`,
309
- `upvotes: ${d.upvoteCount}`,
310
- `comments: ${d.comments}`,
311
- `answered: ${!!d.answer}`,
312
- "---"
313
- ];
300
+ const fm = buildFrontmatter({
301
+ number: d.number,
302
+ title: d.title,
303
+ category: d.category,
304
+ created: isoDate(d.createdAt),
305
+ url: d.url,
306
+ upvotes: d.upvoteCount,
307
+ comments: d.comments,
308
+ answered: !!d.answer
309
+ });
314
310
  const bodyLimit = d.upvoteCount >= 5 ? 1500 : 800;
315
311
  const lines = [
316
- fm.join("\n"),
312
+ fm,
317
313
  "",
318
314
  `# ${d.title}`
319
315
  ];
@@ -936,6 +932,63 @@ async function fetchNpmRegistryMeta(packageName, version) {
936
932
  distTags
937
933
  };
938
934
  }
935
+ async function resolveGitHub(gh, targetVersion, pkg, result, attempts, onProgress, opts) {
936
+ let allFiles;
937
+ if (targetVersion) {
938
+ onProgress?.("github-docs");
939
+ const gitDocs = await fetchGitDocs(gh.owner, gh.repo, targetVersion, pkg.name, opts?.rawRepoUrl);
940
+ if (gitDocs) {
941
+ result.gitDocsUrl = gitDocs.baseUrl;
942
+ result.gitRef = gitDocs.ref;
943
+ allFiles = gitDocs.allFiles;
944
+ attempts.push({
945
+ source: "github-docs",
946
+ url: gitDocs.baseUrl,
947
+ status: "success",
948
+ message: `Found ${gitDocs.files.length} docs at ${gitDocs.ref}`
949
+ });
950
+ } else attempts.push({
951
+ source: "github-docs",
952
+ url: `${result.repoUrl}/tree/v${targetVersion}/docs`,
953
+ status: "not-found",
954
+ message: "No docs/ folder found at version tag"
955
+ });
956
+ }
957
+ if (!result.docsUrl) {
958
+ onProgress?.("github-meta");
959
+ const repoMeta = await fetchGitHubRepoMeta(gh.owner, gh.repo, pkg.name);
960
+ if (repoMeta?.homepage && !isUselessDocsUrl(repoMeta.homepage)) {
961
+ result.docsUrl = repoMeta.homepage;
962
+ attempts.push({
963
+ source: "github-meta",
964
+ url: result.repoUrl,
965
+ status: "success",
966
+ message: `Found homepage: ${repoMeta.homepage}`
967
+ });
968
+ } else attempts.push({
969
+ source: "github-meta",
970
+ url: result.repoUrl,
971
+ status: "not-found",
972
+ message: "No homepage in repo metadata"
973
+ });
974
+ }
975
+ onProgress?.("readme");
976
+ const readmeUrl = await fetchReadme(gh.owner, gh.repo, opts?.subdir);
977
+ if (readmeUrl) {
978
+ result.readmeUrl = readmeUrl;
979
+ attempts.push({
980
+ source: "readme",
981
+ url: readmeUrl,
982
+ status: "success"
983
+ });
984
+ } else attempts.push({
985
+ source: "readme",
986
+ url: `${result.repoUrl}/README.md`,
987
+ status: "not-found",
988
+ message: "No README found"
989
+ });
990
+ return allFiles;
991
+ }
939
992
  async function resolvePackageDocs(packageName, options = {}) {
940
993
  return (await resolvePackageDocsWithAttempts(packageName, options)).package;
941
994
  }
@@ -990,62 +1043,10 @@ async function resolvePackageDocsWithAttempts(packageName, options = {}) {
990
1043
  if (pkg.homepage && !isGitHubRepoUrl(pkg.homepage) && !isUselessDocsUrl(pkg.homepage)) result.docsUrl = pkg.homepage;
991
1044
  if (result.repoUrl?.includes("github.com")) {
992
1045
  const gh = parseGitHubUrl(result.repoUrl);
993
- if (gh) {
994
- const targetVersion = options.version || pkg.version;
995
- if (targetVersion) {
996
- onProgress?.("github-docs");
997
- const gitDocs = await fetchGitDocs(gh.owner, gh.repo, targetVersion, pkg.name, rawRepoUrl);
998
- if (gitDocs) {
999
- result.gitDocsUrl = gitDocs.baseUrl;
1000
- result.gitRef = gitDocs.ref;
1001
- gitDocsAllFiles = gitDocs.allFiles;
1002
- attempts.push({
1003
- source: "github-docs",
1004
- url: gitDocs.baseUrl,
1005
- status: "success",
1006
- message: `Found ${gitDocs.files.length} docs at ${gitDocs.ref}`
1007
- });
1008
- } else attempts.push({
1009
- source: "github-docs",
1010
- url: `${result.repoUrl}/tree/v${targetVersion}/docs`,
1011
- status: "not-found",
1012
- message: "No docs/ folder found at version tag"
1013
- });
1014
- }
1015
- if (!result.docsUrl) {
1016
- onProgress?.("github-meta");
1017
- const repoMeta = await fetchGitHubRepoMeta(gh.owner, gh.repo, pkg.name);
1018
- if (repoMeta?.homepage && !isUselessDocsUrl(repoMeta.homepage)) {
1019
- result.docsUrl = repoMeta.homepage;
1020
- attempts.push({
1021
- source: "github-meta",
1022
- url: result.repoUrl,
1023
- status: "success",
1024
- message: `Found homepage: ${repoMeta.homepage}`
1025
- });
1026
- } else attempts.push({
1027
- source: "github-meta",
1028
- url: result.repoUrl,
1029
- status: "not-found",
1030
- message: "No homepage in repo metadata"
1031
- });
1032
- }
1033
- onProgress?.("readme");
1034
- const readmeUrl = await fetchReadme(gh.owner, gh.repo, subdir);
1035
- if (readmeUrl) {
1036
- result.readmeUrl = readmeUrl;
1037
- attempts.push({
1038
- source: "readme",
1039
- url: readmeUrl,
1040
- status: "success"
1041
- });
1042
- } else attempts.push({
1043
- source: "readme",
1044
- url: `${result.repoUrl}/README.md`,
1045
- status: "not-found",
1046
- message: "No README found"
1047
- });
1048
- }
1046
+ if (gh) gitDocsAllFiles = await resolveGitHub(gh, options.version || pkg.version, pkg, result, attempts, onProgress, {
1047
+ rawRepoUrl,
1048
+ subdir
1049
+ });
1049
1050
  } else if (!result.repoUrl) {
1050
1051
  onProgress?.("github-search");
1051
1052
  const searchedUrl = await searchGitHubRepo(pkg.name);
@@ -1058,32 +1059,7 @@ async function resolvePackageDocsWithAttempts(packageName, options = {}) {
1058
1059
  message: `Found via GitHub search: ${searchedUrl}`
1059
1060
  });
1060
1061
  const gh = parseGitHubUrl(searchedUrl);
1061
- if (gh) {
1062
- const targetVersion = options.version || pkg.version;
1063
- if (targetVersion) {
1064
- onProgress?.("github-docs");
1065
- const gitDocs = await fetchGitDocs(gh.owner, gh.repo, targetVersion, pkg.name);
1066
- if (gitDocs) {
1067
- result.gitDocsUrl = gitDocs.baseUrl;
1068
- result.gitRef = gitDocs.ref;
1069
- gitDocsAllFiles = gitDocs.allFiles;
1070
- attempts.push({
1071
- source: "github-docs",
1072
- url: gitDocs.baseUrl,
1073
- status: "success",
1074
- message: `Found ${gitDocs.files.length} docs at ${gitDocs.ref}`
1075
- });
1076
- }
1077
- }
1078
- if (!result.docsUrl) {
1079
- onProgress?.("github-meta");
1080
- const repoMeta = await fetchGitHubRepoMeta(gh.owner, gh.repo, pkg.name);
1081
- if (repoMeta?.homepage && !isUselessDocsUrl(repoMeta.homepage)) result.docsUrl = repoMeta.homepage;
1082
- }
1083
- onProgress?.("readme");
1084
- const readmeUrl = await fetchReadme(gh.owner, gh.repo);
1085
- if (readmeUrl) result.readmeUrl = readmeUrl;
1086
- }
1062
+ if (gh) gitDocsAllFiles = await resolveGitHub(gh, options.version || pkg.version, pkg, result, attempts, onProgress);
1087
1063
  } else attempts.push({
1088
1064
  source: "github-search",
1089
1065
  status: "not-found",
@@ -1406,7 +1382,7 @@ function selectReleases(releases, packageName) {
1406
1382
  }).slice(0, 20);
1407
1383
  }
1408
1384
  function formatRelease(release, packageName) {
1409
- const date = (release.publishedAt || release.createdAt).split("T")[0];
1385
+ const date = isoDate(release.publishedAt || release.createdAt);
1410
1386
  const version = extractVersion(release.tag, packageName) || release.tag;
1411
1387
  const fm = [
1412
1388
  "---",
@@ -1431,7 +1407,7 @@ function generateReleaseIndex(releases, packageName) {
1431
1407
  ""
1432
1408
  ];
1433
1409
  for (const r of releases) {
1434
- const date = (r.publishedAt || r.createdAt).split("T")[0];
1410
+ const date = isoDate(r.publishedAt || r.createdAt);
1435
1411
  const filename = r.tag.includes("@") || r.tag.startsWith("v") ? r.tag : `v${r.tag}`;
1436
1412
  const sv = parseSemver(extractVersion(r.tag, packageName) || r.tag);
1437
1413
  const label = sv?.patch === 0 && sv.minor === 0 ? " **[MAJOR]**" : sv?.patch === 0 ? " **[MINOR]**" : "";