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