|
|
@@ -33,24 +33,58 @@ class GitHubRepoCollector implements DataSource {
|
|
|
const raw = (await response.json()) as Record<string, any>;
|
|
|
const data = (raw.data ?? raw) as Record<string, any>;
|
|
|
|
|
|
- const name = data.fullName || data.full_name || "unknown";
|
|
|
- const lines: string[] = [`# ${name}\n`];
|
|
|
- if (data.description) lines.push(`${data.description}\n`);
|
|
|
- if (data.language) lines.push(`- Language: ${data.language}`);
|
|
|
- if (data.stars != null) lines.push(`- Stars: ${formatCount(data.stars)}`);
|
|
|
- if (data.forks != null) lines.push(`- Forks: ${formatCount(data.forks)}`);
|
|
|
- if (data.openIssues != null) lines.push(`- Open Issues: ${formatCount(data.openIssues)}`);
|
|
|
- if (data.topics?.length) lines.push(`- Topics: ${data.topics.join(", ")}`);
|
|
|
+ return { type: "text", content: formatRepoDetail(owner, repo, data) };
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function formatRepoDetail(queryOwner: string, queryRepo: string, data: any): string {
|
|
|
+ // The API returns the REAL owner (transferred repos report their current
|
|
|
+ // owner). Prefer data.fullName; fall back to the query params.
|
|
|
+ const fullName = data.fullName || `${queryOwner}/${queryRepo}`;
|
|
|
+ const [detailOwner, detailName] = fullName.split("/");
|
|
|
+
|
|
|
+ const lines: string[] = [`# ${fullName}\n`];
|
|
|
+ if (data.description) lines.push(`${data.description}\n`);
|
|
|
+
|
|
|
+ // Structured metadata block — LLM copies verbatim into scene.github.repo.
|
|
|
+ const meta = {
|
|
|
+ owner: detailOwner || queryOwner,
|
|
|
+ name: detailName || queryRepo,
|
|
|
+ fullName,
|
|
|
+ language: data.language ?? "",
|
|
|
+ languageColor: data.languageColor ?? "",
|
|
|
+ stars: data.stars,
|
|
|
+ forks: data.forks,
|
|
|
+ license: data.license ?? "",
|
|
|
+ };
|
|
|
+ lines.push(`<!-- repo-meta: ${JSON.stringify(meta)} -->`);
|
|
|
+
|
|
|
+ // Image refs — LLM copies verbatim into scene.images[].
|
|
|
+ const imageRefs = {
|
|
|
+ socialPreview: `${detailOwner || queryOwner}/${detailName || queryRepo}`,
|
|
|
+ starHistory: `https://api.star-history.com/svg?repos=${fullName}&type=Date`,
|
|
|
+ };
|
|
|
+ lines.push(`<!-- repo-images: ${JSON.stringify(imageRefs)} -->`);
|
|
|
+
|
|
|
+ const meta2: string[] = [];
|
|
|
+ if (data.language) meta2.push(`Language: ${data.language}`);
|
|
|
+ if (data.stars != null) meta2.push(`Stars: ${formatCount(data.stars)}`);
|
|
|
+ if (data.forks != null) meta2.push(`Forks: ${formatCount(data.forks)}`);
|
|
|
+ if (data.openIssues != null) meta2.push(`Open Issues: ${formatCount(data.openIssues)}`);
|
|
|
+ if (data.topics?.length) meta2.push(`Topics: ${data.topics.join(", ")}`);
|
|
|
+ if (meta2.length) {
|
|
|
lines.push("");
|
|
|
- if (data.readme) {
|
|
|
- const readme = data.readme.length > 3000
|
|
|
- ? data.readme.slice(0, 3000) + "\n..."
|
|
|
- : data.readme;
|
|
|
- lines.push("## README\n", readme);
|
|
|
- }
|
|
|
+ lines.push(meta2.map((m) => `- ${m}`).join("\n"));
|
|
|
+ }
|
|
|
|
|
|
- return { type: "text", content: lines.join("\n") };
|
|
|
+ if (data.readme) {
|
|
|
+ const readme = data.readme.length > 3000
|
|
|
+ ? data.readme.slice(0, 3000) + "\n..."
|
|
|
+ : data.readme;
|
|
|
+ lines.push("\n## README\n", readme);
|
|
|
}
|
|
|
+
|
|
|
+ return lines.join("\n");
|
|
|
}
|
|
|
|
|
|
registerCollector("github-repo", (config) => new GitHubRepoCollector(config));
|