返回 CodeWhale
llms-txt.ts
根目录 / web / lib / llms-txt.ts
1 import { DOC_TOPICS, REPO_DOCS_BASE, docTopicHref } from "./docs-map";
2 import { DISCORD_URL, REPO_URL } from "./i18n/links";
3 import { IDENTITY_PHRASE, SITE_NAME, SITE_URL } from "./page-meta";
4
5 /**
6 * First-party routes that are in the sitemap but are not a docs-map topic.
7 * English canonicals only — this file is the machine-readable index.
8 */
9 const EXTRA_PAGES: readonly { path: string; title: string; description: string }[] = [
10 {
11 path: "/product",
12 title: "Product",
13 description:
14 "What Codewhale is and what a person gains: their own models, capable agents, and control on their own machine — with availability stated per surface.",
15 },
16 {
17 path: "/docs",
18 title: "Documentation",
19 description:
20 "Documentation hub: install, guide, configuration, providers, modes, tools, MCP, sandbox, Fleet, and the Runtime API.",
21 },
22 {
23 path: "/faq",
24 title: "FAQ",
25 description:
26 "Frequently asked questions: install, config, providers, models, modes, security, and privacy.",
27 },
28 {
29 path: "/runtime",
30 title: "Runtime & Integrations",
31 description:
32 "Local Runtime API, HTTP/SSE, baseline ACP stdio adapter, MCP servers, and the Phase 0 VS Code companion.",
33 },
34 {
35 path: "/constitution",
36 title: "Three layers of law",
37 description:
38 "Nested constitution: bundled base law, standing law (/constitution), and the repo's .codewhale/constitution.json.",
39 },
40 {
41 path: "/roadmap",
42 title: "Roadmap",
43 description: "Shipped, underway, considered, and ruled-out work.",
44 },
45 {
46 path: "/feed",
47 title: "Activity",
48 description: "Recent repository issues, pull requests, and releases.",
49 },
50 {
51 path: "/digest",
52 title: "Community digest",
53 description: "The weekly project record, reviewed by a maintainer.",
54 },
55 {
56 path: "/community",
57 title: "Community",
58 description: "Release contributors, helpers, and ways to take part.",
59 },
60 {
61 path: "/contribute",
62 title: "Contribute",
63 description: "The pull-request workflow: scoped issue, fork, test the change, explain the result.",
64 },
65 {
66 path: "/legal/terms",
67 title: "Terms of service",
68 description: "Terms that govern your use of Codewhale, a Shannon Labs product.",
69 },
70 {
71 path: "/legal/privacy",
72 title: "Privacy policy",
73 description: "How Shannon Labs handles information when you use Codewhale.",
74 },
75 ];
76
77 function topicSitePath(topic: (typeof DOC_TOPICS)[number]): string | null {
78 if (topic.sitePath) return `/${topic.sitePath}`;
79 if (topic.hasPage) return `/docs/${topic.slug}`;
80 return null;
81 }
82
83 /** Plain-text /llms.txt body generated from the docs registry and sitemap extras. */
84 export function buildLlmsTxt(): string {
85 const covered = new Set<string>();
86 const lines: string[] = [
87 `# ${SITE_NAME}`,
88 "",
89 `> ${IDENTITY_PHRASE}`,
90 "",
91 `${SITE_NAME} is a terminal-native coding agent for hosted and local models.`,
92 `Official site: ${SITE_URL}`,
93 `Source: ${REPO_URL}`,
94 "",
95 "## Documentation",
96 "",
97 ];
98
99 for (const topic of DOC_TOPICS) {
100 const path = topicSitePath(topic);
101 if (!path) continue;
102 covered.add(path);
103 const href = `${SITE_URL}${docTopicHref(topic, "en")}`;
104 lines.push(`- [${topic.label.en}](${href}): ${topic.description.en}`);
105 }
106
107 lines.push("", "## Pages", "");
108 for (const page of EXTRA_PAGES) {
109 if (covered.has(page.path)) continue;
110 lines.push(`- [${page.title}](${SITE_URL}/en${page.path}): ${page.description}`);
111 }
112
113 lines.push("", "## Source documents", "");
114 for (const topic of DOC_TOPICS) {
115 if (topic.hasPage) continue;
116 const source = Array.isArray(topic.repoSource) ? topic.repoSource[0] : topic.repoSource;
117 lines.push(`- [${topic.label.en}](${REPO_DOCS_BASE}/${source}): ${topic.description.en}`);
118 }
119
120 lines.push("", "## Optional", "", `- [GitHub](${REPO_URL})`, `- [Discord](${DISCORD_URL})`, "");
121 return lines.join("\n");
122 }
123
123 lines TYPESCRIPT