@farming-labs/theme 0.1.73 → 0.1.75
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/docs-api.d.mts +4 -1
- package/dist/docs-api.mjs +81 -7
- package/package.json +2 -2
package/dist/docs-api.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChangelogConfig, DocsAnalyticsConfig, DocsI18nConfig, DocsMcpConfig, DocsObservabilityConfig, DocsSearchConfig, FeedbackConfig, OrderingItem } from "@farming-labs/docs";
|
|
1
|
+
import { ChangelogConfig, DocsAnalyticsConfig, DocsAskAIMcpConfig, DocsI18nConfig, DocsMcpConfig, DocsObservabilityConfig, DocsSearchConfig, DocsSitemapConfig, FeedbackConfig, OrderingItem } from "@farming-labs/docs";
|
|
2
2
|
|
|
3
3
|
//#region src/docs-api.d.ts
|
|
4
4
|
interface AIProviderConfig {
|
|
@@ -28,6 +28,7 @@ interface AIOptions {
|
|
|
28
28
|
/** Default apiKey when no per-model provider is configured. */
|
|
29
29
|
apiKey?: string;
|
|
30
30
|
maxResults?: number;
|
|
31
|
+
useMcp?: boolean | DocsAskAIMcpConfig;
|
|
31
32
|
}
|
|
32
33
|
interface DocsAPIOptions {
|
|
33
34
|
rootDir?: string;
|
|
@@ -53,6 +54,8 @@ interface DocsAPIOptions {
|
|
|
53
54
|
feedback?: boolean | FeedbackConfig;
|
|
54
55
|
/** MCP configuration used for the agent discovery spec. */
|
|
55
56
|
mcp?: boolean | DocsMcpConfig;
|
|
57
|
+
/** Sitemap configuration used for sitemap.xml and sitemap.md. */
|
|
58
|
+
sitemap?: boolean | DocsSitemapConfig;
|
|
56
59
|
}
|
|
57
60
|
interface DocsMCPAPIOptions {
|
|
58
61
|
rootDir?: string;
|
package/dist/docs-api.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import { getNextAppDir } from "./get-app-dir.mjs";
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import matter from "gray-matter";
|
|
6
|
-
import { buildDocsAskAIContext, createDocsAgentTraceContext, createDocsAgentTraceId, emitDocsAgentTraceEvent, emitDocsAnalyticsEvent, formatDocsAskAIPackageHints, normalizeDocsRelated, performDocsSearch, renderDocsRelatedMarkdownLines, resolveChangelogConfig, resolveDocsI18n, resolveDocsLocale, resolvePageSidebarFolderIndexBehavior, resolveSearchRequestConfig } from "@farming-labs/docs";
|
|
7
|
-
import { createDocsMcpHttpHandler, createFilesystemDocsMcpSource, resolveDocsMcpConfig } from "@farming-labs/docs/server";
|
|
6
|
+
import { buildDocsAskAIContext, createDocsAgentTraceContext, createDocsAgentTraceId, createDocsSitemapResponse, emitDocsAgentTraceEvent, emitDocsAnalyticsEvent, formatDocsAskAIPackageHints, normalizeDocsRelated, performDocsSearch, renderDocsRelatedMarkdownLines, resolveAskAISearchRequestConfig, resolveChangelogConfig, resolveDocsI18n, resolveDocsLocale, resolveDocsSitemapConfig, resolvePageSidebarFolderIndexBehavior, resolveSearchRequestConfig } from "@farming-labs/docs";
|
|
7
|
+
import { createDocsMcpHttpHandler, createFilesystemDocsMcpSource, readDocsSitemapManifest, resolveDocsMcpConfig } from "@farming-labs/docs/server";
|
|
8
8
|
|
|
9
9
|
//#region src/docs-api.ts
|
|
10
10
|
/**
|
|
@@ -172,10 +172,11 @@ function isSearchEnabled(search) {
|
|
|
172
172
|
if (search && typeof search === "object" && search.enabled === false) return false;
|
|
173
173
|
return true;
|
|
174
174
|
}
|
|
175
|
-
function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms }) {
|
|
175
|
+
function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms, sitemap }) {
|
|
176
176
|
const normalizedEntry = normalizePathSegment(entry) || "docs";
|
|
177
177
|
const localesEnabled = i18n !== null;
|
|
178
178
|
const searchEnabled = isSearchEnabled(search);
|
|
179
|
+
const sitemapConfig = resolveDocsSitemapConfig(sitemap, { baseUrl: llms.baseUrl });
|
|
179
180
|
return {
|
|
180
181
|
version: "1",
|
|
181
182
|
name: "@farming-labs/docs",
|
|
@@ -201,6 +202,7 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms }) {
|
|
|
201
202
|
skills: true,
|
|
202
203
|
mcp: mcp.enabled,
|
|
203
204
|
search: searchEnabled,
|
|
205
|
+
sitemap: sitemapConfig.enabled,
|
|
204
206
|
agentFeedback: feedback.enabled,
|
|
205
207
|
locales: localesEnabled
|
|
206
208
|
},
|
|
@@ -236,6 +238,20 @@ function buildAgentSpec({ origin, entry, i18n, search, mcp, feedback, llms }) {
|
|
|
236
238
|
wellKnownTxt: DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE,
|
|
237
239
|
wellKnownFull: DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE
|
|
238
240
|
},
|
|
241
|
+
sitemap: {
|
|
242
|
+
enabled: sitemapConfig.enabled,
|
|
243
|
+
xml: {
|
|
244
|
+
enabled: sitemapConfig.xml.enabled,
|
|
245
|
+
route: sitemapConfig.xml.route,
|
|
246
|
+
api: `${DEFAULT_DOCS_API_ROUTE}?format=sitemap-xml`
|
|
247
|
+
},
|
|
248
|
+
markdown: {
|
|
249
|
+
enabled: sitemapConfig.markdown.enabled,
|
|
250
|
+
route: sitemapConfig.markdown.route,
|
|
251
|
+
wellKnownRoute: sitemapConfig.markdown.wellKnownRoute,
|
|
252
|
+
api: `${DEFAULT_DOCS_API_ROUTE}?format=sitemap-md`
|
|
253
|
+
}
|
|
254
|
+
},
|
|
239
255
|
search: {
|
|
240
256
|
enabled: searchEnabled,
|
|
241
257
|
endpoint: `${DEFAULT_DOCS_API_ROUTE}?query={query}`,
|
|
@@ -413,6 +429,7 @@ function readAIConfig(root) {
|
|
|
413
429
|
const baseUrlMatch = content.match(/ai\s*:\s*\{[^}]*baseUrl\s*:\s*["']([^"']+)["']/s);
|
|
414
430
|
const apiKeyMatch = content.match(/ai\s*:\s*\{[^}]*apiKey\s*:\s*process\.env\.(\w+)/s);
|
|
415
431
|
const maxResultsMatch = content.match(/ai\s*:\s*\{[^}]*maxResults\s*:\s*(\d+)/s);
|
|
432
|
+
const useMcpMatch = content.match(/ai\s*:\s*\{[^}]*useMcp\s*:\s*(true|false)/s);
|
|
416
433
|
const systemPromptMatch = content.match(/ai\s*:\s*\{[^}]*systemPrompt\s*:\s*["'`]([^"'`]+)["'`]/s);
|
|
417
434
|
const packageNameMatch = content.match(/ai\s*:\s*\{[^}]*packageName\s*:\s*["'`]([^"'`]+)["'`]/s);
|
|
418
435
|
const docsUrlMatch = content.match(/ai\s*:\s*\{[^}]*docsUrl\s*:\s*["'`]([^"'`]+)["'`]/s);
|
|
@@ -422,6 +439,7 @@ function readAIConfig(root) {
|
|
|
422
439
|
baseUrl: baseUrlMatch?.[1],
|
|
423
440
|
apiKey: apiKeyMatch?.[1] ? process.env[apiKeyMatch[1]] : void 0,
|
|
424
441
|
maxResults: maxResultsMatch ? parseInt(maxResultsMatch[1], 10) : void 0,
|
|
442
|
+
useMcp: useMcpMatch ? useMcpMatch[1] === "true" : void 0,
|
|
425
443
|
systemPrompt: systemPromptMatch?.[1],
|
|
426
444
|
packageName: packageNameMatch?.[1],
|
|
427
445
|
docsUrl: docsUrlMatch?.[1]
|
|
@@ -735,6 +753,8 @@ function scanDocsDir(docsDir, entry, locale, excludedDirs = []) {
|
|
|
735
753
|
rawContent,
|
|
736
754
|
agentFallbackRawContent: agentRawContent !== rawContent ? agentRawContent : void 0,
|
|
737
755
|
url,
|
|
756
|
+
sourcePath: pageSource.replace(/\\/g, "/"),
|
|
757
|
+
lastModified: fs.statSync(pageSource).mtime.toISOString(),
|
|
738
758
|
locale
|
|
739
759
|
});
|
|
740
760
|
}
|
|
@@ -893,11 +913,12 @@ function renderMarkdownDocument(page) {
|
|
|
893
913
|
lines.push("", page.agentFallbackRawContent ?? page.rawContent ?? page.content);
|
|
894
914
|
return lines.join("\n");
|
|
895
915
|
}
|
|
896
|
-
function renderSkillDocument({ origin, entry, search, mcp, feedback, llms }) {
|
|
916
|
+
function renderSkillDocument({ origin, entry, search, mcp, feedback, llms, sitemap }) {
|
|
897
917
|
const normalizedEntry = normalizePathSegment(entry) || "docs";
|
|
898
918
|
const siteTitle = compactSkillText(llms.siteTitle ?? "Documentation");
|
|
899
919
|
const siteDescription = llms.siteDescription ? compactSkillText(llms.siteDescription) : void 0;
|
|
900
920
|
const searchEnabled = isSearchEnabled(search);
|
|
921
|
+
const sitemapConfig = resolveDocsSitemapConfig(sitemap, { baseUrl: llms.baseUrl });
|
|
901
922
|
const lines = [
|
|
902
923
|
"---",
|
|
903
924
|
"name: docs",
|
|
@@ -912,10 +933,18 @@ function renderSkillDocument({ origin, entry, search, mcp, feedback, llms }) {
|
|
|
912
933
|
lines.push("", "## When To Use", "Use this skill when you need to read or implement against this documentation site.", "", "## Start Here", `- Fetch ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}; fall back to ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE} or ${DEFAULT_AGENT_SPEC_ROUTE}.`, `- Fetch /${normalizedEntry}.md for the root docs page.`, `- Fetch /${normalizedEntry}/{slug}.md for page-specific context.`, "- You can also request text/markdown from normal page URLs.");
|
|
913
934
|
if (searchEnabled) lines.push(`- Search with ${DEFAULT_DOCS_API_ROUTE}?query={query} when you do not know the page.`);
|
|
914
935
|
if (llms.enabled) lines.push(`- Use ${DEFAULT_LLMS_TXT_ROUTE} for a compact docs index.`, `- Use ${DEFAULT_LLMS_FULL_TXT_ROUTE} for full markdown context.`);
|
|
936
|
+
if (sitemapConfig.enabled) {
|
|
937
|
+
if (sitemapConfig.xml.enabled) lines.push(`- Use ${sitemapConfig.xml.route} to check canonical page freshness.`);
|
|
938
|
+
if (sitemapConfig.markdown.enabled) lines.push(`- Use ${sitemapConfig.markdown.route} for a semantic docs map.`);
|
|
939
|
+
}
|
|
915
940
|
if (mcp.enabled) lines.push(`- Use ${DEFAULT_MCP_WELL_KNOWN_ROUTE} or ${DEFAULT_MCP_PUBLIC_ROUTE} for MCP tools when your environment supports MCP.`);
|
|
916
941
|
if (feedback.enabled) lines.push(`- Read ${feedback.schemaRoute} before posting agent feedback to ${feedback.route}.`);
|
|
917
942
|
lines.push("", "## Routes", `- Skill document: ${DEFAULT_SKILL_MD_ROUTE}`, `- Skill well-known alias: ${DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE}`, `- Skill API format: ${DEFAULT_DOCS_API_ROUTE}?format=skill`, `- Agent discovery: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}`, `- Agent discovery fallback: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}`, `- Markdown root: /${normalizedEntry}.md`, `- Markdown pages: /${normalizedEntry}/{slug}.md`);
|
|
918
943
|
if (llms.enabled) lines.push(`- llms.txt: ${DEFAULT_LLMS_TXT_ROUTE}`, `- llms-full.txt: ${DEFAULT_LLMS_FULL_TXT_ROUTE}`, `- llms well-known aliases: ${DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE}, ${DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE}`);
|
|
944
|
+
if (sitemapConfig.enabled) {
|
|
945
|
+
if (sitemapConfig.xml.enabled) lines.push(`- Sitemap XML: ${sitemapConfig.xml.route}`);
|
|
946
|
+
if (sitemapConfig.markdown.enabled) lines.push(`- Sitemap Markdown: ${sitemapConfig.markdown.route}`, `- Sitemap well-known alias: ${sitemapConfig.markdown.wellKnownRoute}`);
|
|
947
|
+
}
|
|
919
948
|
if (mcp.enabled) lines.push(`- MCP: ${DEFAULT_MCP_PUBLIC_ROUTE}, ${DEFAULT_MCP_WELL_KNOWN_ROUTE}`);
|
|
920
949
|
lines.push("", "## Reusable Framework Skills", "For framework setup, CLI, page actions, Ask AI, or configuration work, install the reusable Farming Labs skills:", "", "```sh", "npx skills add farming-labs/docs", "```");
|
|
921
950
|
return lines.join("\n");
|
|
@@ -1451,6 +1480,31 @@ function readLlmsTxtConfig(root) {
|
|
|
1451
1480
|
}
|
|
1452
1481
|
return { enabled: false };
|
|
1453
1482
|
}
|
|
1483
|
+
function readSitemapConfig(root) {
|
|
1484
|
+
for (const ext of FILE_EXTS) {
|
|
1485
|
+
const configPath = path.join(root, `docs.config.${ext}`);
|
|
1486
|
+
if (!fs.existsSync(configPath)) continue;
|
|
1487
|
+
try {
|
|
1488
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
1489
|
+
if (!content.includes("sitemap")) return void 0;
|
|
1490
|
+
if (/sitemap\s*:\s*false/.test(content)) return false;
|
|
1491
|
+
if (/sitemap\s*:\s*true/.test(content)) return true;
|
|
1492
|
+
const sitemapBlock = content.match(/sitemap\s*:\s*\{([\s\S]*?)\n\s*\}/)?.[1] ?? "";
|
|
1493
|
+
const routePrefix = sitemapBlock.match(/routePrefix\s*:\s*["']([^"']+)["']/)?.[1];
|
|
1494
|
+
const baseUrl = sitemapBlock.match(/baseUrl\s*:\s*["']([^"']+)["']/)?.[1];
|
|
1495
|
+
const manifestPath = sitemapBlock.match(/manifestPath\s*:\s*["']([^"']+)["']/)?.[1];
|
|
1496
|
+
const enabledMatch = sitemapBlock.match(/enabled\s*:\s*(true|false)/);
|
|
1497
|
+
return {
|
|
1498
|
+
enabled: enabledMatch ? enabledMatch[1] === "true" : true,
|
|
1499
|
+
routePrefix,
|
|
1500
|
+
baseUrl,
|
|
1501
|
+
manifestPath
|
|
1502
|
+
};
|
|
1503
|
+
} catch {
|
|
1504
|
+
return;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1454
1508
|
function generateLlmsTxt(indexes, options) {
|
|
1455
1509
|
const { siteTitle = "Documentation", siteDescription, baseUrl = "" } = options;
|
|
1456
1510
|
let llmsTxt = `# ${siteTitle}\n\n`;
|
|
@@ -1511,6 +1565,7 @@ function createDocsAPI(options) {
|
|
|
1511
1565
|
const aiConfig = options?.ai ?? readAIConfig(root);
|
|
1512
1566
|
const searchConfig = options?.search;
|
|
1513
1567
|
const llmsConfig = readLlmsTxtConfig(root);
|
|
1568
|
+
const sitemapConfig = options?.sitemap ?? readSitemapConfig(root);
|
|
1514
1569
|
const mcpConfig = resolveDocsMcpConfig(options?.mcp ?? readMcpConfig(root), { defaultName: llmsConfig.siteTitle ?? "Documentation" });
|
|
1515
1570
|
function resolveDocsDirCandidates(locale) {
|
|
1516
1571
|
const relativeCandidates = /* @__PURE__ */ new Set();
|
|
@@ -1650,7 +1705,8 @@ function createDocsAPI(options) {
|
|
|
1650
1705
|
search: searchConfig,
|
|
1651
1706
|
mcp: mcpConfig,
|
|
1652
1707
|
feedback: agentFeedbackConfig,
|
|
1653
|
-
llms: llmsConfig
|
|
1708
|
+
llms: llmsConfig,
|
|
1709
|
+
sitemap: sitemapConfig
|
|
1654
1710
|
}), { headers: {
|
|
1655
1711
|
"Cache-Control": "public, max-age=0, s-maxage=3600",
|
|
1656
1712
|
"X-Robots-Tag": "noindex"
|
|
@@ -1692,13 +1748,24 @@ function createDocsAPI(options) {
|
|
|
1692
1748
|
search: searchConfig,
|
|
1693
1749
|
mcp: mcpConfig,
|
|
1694
1750
|
feedback: agentFeedbackConfig,
|
|
1695
|
-
llms: llmsConfig
|
|
1751
|
+
llms: llmsConfig,
|
|
1752
|
+
sitemap: sitemapConfig
|
|
1696
1753
|
}), { headers: {
|
|
1697
1754
|
"Content-Type": "text/markdown; charset=utf-8",
|
|
1698
1755
|
"Cache-Control": "public, max-age=0, s-maxage=3600",
|
|
1699
1756
|
"X-Robots-Tag": "noindex"
|
|
1700
1757
|
} });
|
|
1701
1758
|
}
|
|
1759
|
+
const sitemapResponse = createDocsSitemapResponse({
|
|
1760
|
+
request,
|
|
1761
|
+
sitemap: sitemapConfig,
|
|
1762
|
+
entry,
|
|
1763
|
+
siteTitle: llmsConfig.siteTitle ?? "Documentation",
|
|
1764
|
+
baseUrl: llmsConfig.baseUrl ?? url.origin,
|
|
1765
|
+
pages: getIndexes(ctx),
|
|
1766
|
+
manifest: readDocsSitemapManifest(root, sitemapConfig)
|
|
1767
|
+
});
|
|
1768
|
+
if (sitemapResponse) return sitemapResponse;
|
|
1702
1769
|
const markdownRequest = resolveMarkdownRequest(entry, url, request);
|
|
1703
1770
|
if (markdownRequest) {
|
|
1704
1771
|
const document = await getMarkdownDocument(ctx, markdownRequest.requestedPath);
|
|
@@ -1901,7 +1968,14 @@ function createDocsAPI(options) {
|
|
|
1901
1968
|
return Response.json({ error: "AI is not enabled. Set `ai: { enabled: true }` in your docs.config to enable it." }, { status: 404 });
|
|
1902
1969
|
}
|
|
1903
1970
|
const ctx = resolveContextFromRequest(request);
|
|
1904
|
-
return handleAskAI(request, getIndexes(ctx), aiConfig,
|
|
1971
|
+
return handleAskAI(request, getIndexes(ctx), aiConfig, resolveAskAISearchRequestConfig({
|
|
1972
|
+
search: searchConfig,
|
|
1973
|
+
useMcp: aiConfig.useMcp,
|
|
1974
|
+
mcpEndpoint: mcpConfig.route,
|
|
1975
|
+
mcpEnabled: mcpConfig.enabled,
|
|
1976
|
+
mcpSearchEnabled: mcpConfig.tools.searchDocs,
|
|
1977
|
+
requestUrl: request.url
|
|
1978
|
+
}), analytics, observability, { locale: ctx.locale });
|
|
1905
1979
|
}
|
|
1906
1980
|
};
|
|
1907
1981
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/theme",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.75",
|
|
4
4
|
"description": "Theme package for @farming-labs/docs — layout, provider, MDX components, and styles",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
"tsdown": "^0.20.3",
|
|
140
140
|
"typescript": "^5.9.3",
|
|
141
141
|
"vitest": "^3.2.4",
|
|
142
|
-
"@farming-labs/docs": "0.1.
|
|
142
|
+
"@farming-labs/docs": "0.1.75"
|
|
143
143
|
},
|
|
144
144
|
"peerDependencies": {
|
|
145
145
|
"@farming-labs/docs": ">=0.0.1",
|