@farming-labs/docs 0.1.42 → 0.1.44
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/{agent-qcweNgy-.mjs → agent-CbAtuZAc.mjs} +1 -268
- package/dist/{agent-CoO9z8aW.mjs → agent-Dget5s8h.mjs} +3 -3
- package/dist/cli/index.mjs +21 -6
- package/dist/{config-CyqDp8tD.mjs → config-C7sUsMkm.mjs} +1 -1
- package/dist/doctor-Jm7T0qYS.mjs +507 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -1
- package/dist/{init-9U8AijRu.mjs → init-CShiL8Ch.mjs} +1 -1
- package/dist/{mcp-1j3-_z66.mjs → mcp-CYpMeMfi.mjs} +2 -2
- package/dist/mcp.d.mts +1 -1
- package/dist/metadata-CdrtTSz-.mjs +268 -0
- package/dist/{search-B2HvbbeE.mjs → search-D7DS0MLc.mjs} +2 -2
- package/dist/{search-C15yRNVE.d.mts → search-cPHa_3jJ.d.mts} +1 -1
- package/dist/server.d.mts +2 -2
- package/dist/server.mjs +1 -1
- package/dist/{upgrade-BGWZ_NLh.mjs → upgrade-2xcgMsj6.mjs} +1 -1
- package/package.json +1 -1
- /package/dist/{api-reference-GDAEzQn1.mjs → api-reference-y7cqtq4w.mjs} +0 -0
- /package/dist/{types-CKdSg7n8.d.mts → types-nlEL5lLq.d.mts} +0 -0
- /package/dist/{utils-CpTFbAiS.mjs → utils-DSMXVnEu.mjs} +0 -0
|
@@ -1,272 +1,5 @@
|
|
|
1
1
|
import { u as renderDocsRelatedMarkdownLines } from "./search-8oEskRtz.mjs";
|
|
2
2
|
|
|
3
|
-
//#region src/define-docs.ts
|
|
4
|
-
/**
|
|
5
|
-
* Define docs configuration. Validates and returns the config.
|
|
6
|
-
*/
|
|
7
|
-
function defineDocs(config) {
|
|
8
|
-
return {
|
|
9
|
-
entry: config.entry ?? "docs",
|
|
10
|
-
contentDir: config.contentDir,
|
|
11
|
-
i18n: config.i18n,
|
|
12
|
-
theme: config.theme,
|
|
13
|
-
nav: config.nav,
|
|
14
|
-
github: config.github,
|
|
15
|
-
themeToggle: config.themeToggle,
|
|
16
|
-
breadcrumb: config.breadcrumb,
|
|
17
|
-
sidebar: config.sidebar,
|
|
18
|
-
components: config.components,
|
|
19
|
-
onCopyClick: config.onCopyClick,
|
|
20
|
-
feedback: config.feedback,
|
|
21
|
-
search: config.search,
|
|
22
|
-
mcp: config.mcp,
|
|
23
|
-
icons: config.icons,
|
|
24
|
-
pageActions: config.pageActions,
|
|
25
|
-
lastUpdated: config.lastUpdated,
|
|
26
|
-
llmsTxt: config.llmsTxt,
|
|
27
|
-
ai: config.ai,
|
|
28
|
-
ordering: config.ordering,
|
|
29
|
-
metadata: config.metadata,
|
|
30
|
-
og: config.og,
|
|
31
|
-
changelog: config.changelog,
|
|
32
|
-
apiReference: config.apiReference,
|
|
33
|
-
agent: config.agent
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/changelog.ts
|
|
39
|
-
function normalizePathSegment(value, fallback) {
|
|
40
|
-
return (value ?? fallback).trim().replace(/^\/+|\/+$/g, "") || fallback;
|
|
41
|
-
}
|
|
42
|
-
function normalizeContentDir(value) {
|
|
43
|
-
const trimmed = value?.trim();
|
|
44
|
-
if (!trimmed) return "changelog";
|
|
45
|
-
return trimmed.replace(/\/+$/, "") || "changelog";
|
|
46
|
-
}
|
|
47
|
-
function resolveChangelogConfig(value) {
|
|
48
|
-
if (value === false || value === void 0) return {
|
|
49
|
-
enabled: false,
|
|
50
|
-
path: "changelog",
|
|
51
|
-
contentDir: "changelog",
|
|
52
|
-
title: "Changelog",
|
|
53
|
-
description: void 0,
|
|
54
|
-
search: true
|
|
55
|
-
};
|
|
56
|
-
if (value === true) return {
|
|
57
|
-
enabled: true,
|
|
58
|
-
path: "changelog",
|
|
59
|
-
contentDir: "changelog",
|
|
60
|
-
title: "Changelog",
|
|
61
|
-
description: void 0,
|
|
62
|
-
search: true
|
|
63
|
-
};
|
|
64
|
-
return {
|
|
65
|
-
enabled: value.enabled !== false,
|
|
66
|
-
path: normalizePathSegment(value.path, "changelog"),
|
|
67
|
-
contentDir: normalizeContentDir(value.contentDir),
|
|
68
|
-
title: value.title?.trim() || "Changelog",
|
|
69
|
-
description: value.description?.trim() || void 0,
|
|
70
|
-
search: value.search !== false,
|
|
71
|
-
actionsComponent: value.actionsComponent
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
//#endregion
|
|
76
|
-
//#region src/utils.ts
|
|
77
|
-
/**
|
|
78
|
-
* Deep merge utility for theme overrides.
|
|
79
|
-
* Merges objects recursively; later values override earlier ones.
|
|
80
|
-
*/
|
|
81
|
-
function deepMerge(target, ...sources) {
|
|
82
|
-
if (!sources.length) return target;
|
|
83
|
-
const source = sources.shift();
|
|
84
|
-
if (!source) return target;
|
|
85
|
-
const result = { ...target };
|
|
86
|
-
for (const key of Object.keys(source)) {
|
|
87
|
-
const sourceVal = source[key];
|
|
88
|
-
const targetVal = result[key];
|
|
89
|
-
if (sourceVal && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal && typeof targetVal === "object" && !Array.isArray(targetVal)) result[key] = deepMerge(targetVal, sourceVal);
|
|
90
|
-
else if (sourceVal !== void 0) result[key] = sourceVal;
|
|
91
|
-
}
|
|
92
|
-
if (sources.length) return deepMerge(result, ...sources);
|
|
93
|
-
return result;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
//#endregion
|
|
97
|
-
//#region src/create-theme.ts
|
|
98
|
-
/**
|
|
99
|
-
* Create a theme preset factory.
|
|
100
|
-
*
|
|
101
|
-
* Returns a function that accepts optional overrides and deep-merges them
|
|
102
|
-
* with the base theme defaults. This is the same pattern used by the
|
|
103
|
-
* built-in `fumadocs()`, `darksharp()`, and `pixelBorder()` presets.
|
|
104
|
-
*
|
|
105
|
-
* @param baseTheme - The default theme configuration
|
|
106
|
-
* @returns A factory function `(overrides?) => DocsTheme`
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
* ```ts
|
|
110
|
-
* import { createTheme } from "@farming-labs/docs";
|
|
111
|
-
*
|
|
112
|
-
* export const myTheme = createTheme({
|
|
113
|
-
* name: "my-theme",
|
|
114
|
-
* ui: {
|
|
115
|
-
* colors: { primary: "#6366f1" },
|
|
116
|
-
* layout: { contentWidth: 800 },
|
|
117
|
-
* },
|
|
118
|
-
* });
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
function createTheme(baseTheme) {
|
|
122
|
-
return function themeFactory(overrides = {}) {
|
|
123
|
-
const merged = deepMerge(baseTheme, overrides);
|
|
124
|
-
if (overrides.ui?.colors) merged._userColorOverrides = { ...overrides.ui.colors };
|
|
125
|
-
return merged;
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Extend an existing theme preset with additional defaults.
|
|
130
|
-
*
|
|
131
|
-
* Useful when you want to build on top of an existing theme (e.g. fumadocs)
|
|
132
|
-
* rather than starting from scratch.
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* ```ts
|
|
136
|
-
* import { extendTheme } from "@farming-labs/docs";
|
|
137
|
-
* import { fumadocs } from "@farming-labs/theme/default";
|
|
138
|
-
*
|
|
139
|
-
* // Start with fumadocs defaults, override some values
|
|
140
|
-
* export const myTheme = extendTheme(fumadocs(), {
|
|
141
|
-
* name: "my-custom-fumadocs",
|
|
142
|
-
* ui: { colors: { primary: "#22c55e" } },
|
|
143
|
-
* });
|
|
144
|
-
* ```
|
|
145
|
-
*/
|
|
146
|
-
function extendTheme(baseTheme, extensions) {
|
|
147
|
-
return deepMerge(baseTheme, extensions);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
//#endregion
|
|
151
|
-
//#region src/i18n.ts
|
|
152
|
-
function normalizeSegment(value) {
|
|
153
|
-
return value.replace(/^\/+|\/+$/g, "");
|
|
154
|
-
}
|
|
155
|
-
function splitSegments(value) {
|
|
156
|
-
const cleaned = normalizeSegment(value);
|
|
157
|
-
return cleaned ? cleaned.split("/").filter(Boolean) : [];
|
|
158
|
-
}
|
|
159
|
-
function resolveDocsI18n(config) {
|
|
160
|
-
if (!config || !Array.isArray(config.locales)) return null;
|
|
161
|
-
const locales = Array.from(new Set(config.locales.map((l) => l.trim()).filter(Boolean)));
|
|
162
|
-
if (locales.length === 0) return null;
|
|
163
|
-
return {
|
|
164
|
-
locales,
|
|
165
|
-
defaultLocale: config.defaultLocale && locales.includes(config.defaultLocale) ? config.defaultLocale : locales[0]
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
function resolveDocsLocale(searchParams, i18n) {
|
|
169
|
-
if (!i18n) return void 0;
|
|
170
|
-
const raw = searchParams.get("lang") ?? searchParams.get("locale");
|
|
171
|
-
if (!raw) return void 0;
|
|
172
|
-
if (i18n.locales.includes(raw)) return raw;
|
|
173
|
-
return i18n.defaultLocale;
|
|
174
|
-
}
|
|
175
|
-
function resolveDocsPath(pathname, entry) {
|
|
176
|
-
const entryBase = normalizeSegment(entry || "docs") || "docs";
|
|
177
|
-
const entryParts = splitSegments(entryBase);
|
|
178
|
-
const pathParts = splitSegments(pathname);
|
|
179
|
-
let rest = pathParts;
|
|
180
|
-
if (entryParts.length > 0) {
|
|
181
|
-
if (pathParts.slice(0, entryParts.length).join("/") === entryParts.join("/")) rest = pathParts.slice(entryParts.length);
|
|
182
|
-
}
|
|
183
|
-
return {
|
|
184
|
-
slug: rest.join("/"),
|
|
185
|
-
entryPath: entryBase
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
//#endregion
|
|
190
|
-
//#region src/metadata.ts
|
|
191
|
-
/**
|
|
192
|
-
* Resolve page title using metadata titleTemplate.
|
|
193
|
-
* %s is replaced with page title.
|
|
194
|
-
*/
|
|
195
|
-
function resolveTitle(pageTitle, metadata) {
|
|
196
|
-
return (metadata?.titleTemplate ?? "%s").replace("%s", pageTitle);
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Resolve OG image URL for a page.
|
|
200
|
-
* Prefers page.openGraph.images[0], then page.ogImage, then config endpoint/default.
|
|
201
|
-
*/
|
|
202
|
-
function resolveOGImage(page, ogConfig, baseUrl) {
|
|
203
|
-
if (page.openGraph?.images?.length) return resolveImageUrl(page.openGraph.images[0].url, baseUrl);
|
|
204
|
-
if (!ogConfig?.enabled) return void 0;
|
|
205
|
-
if (page.ogImage) return resolveImageUrl(page.ogImage, baseUrl);
|
|
206
|
-
if (ogConfig.type === "dynamic" && ogConfig.endpoint) return `${baseUrl ?? ""}${ogConfig.endpoint}`;
|
|
207
|
-
return ogConfig.defaultImage;
|
|
208
|
-
}
|
|
209
|
-
function resolveImageUrl(url, baseUrl) {
|
|
210
|
-
if (url.startsWith("/") || url.startsWith("http")) return url;
|
|
211
|
-
const base = baseUrl ?? "";
|
|
212
|
-
return `${base}${base.length > 0 && !base.endsWith("/") ? "/" : ""}${url}`;
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Build the Open Graph metadata object for a page.
|
|
216
|
-
* When the page has openGraph in frontmatter, uses it (with title/description filled from page if omitted).
|
|
217
|
-
* Otherwise uses ogImage or config (dynamic endpoint / defaultImage).
|
|
218
|
-
*/
|
|
219
|
-
function buildPageOpenGraph(page, ogConfig, baseUrl) {
|
|
220
|
-
if (page.openGraph) {
|
|
221
|
-
const images = page.openGraph.images?.length ? page.openGraph.images.map((img) => ({
|
|
222
|
-
url: resolveImageUrl(img.url, baseUrl),
|
|
223
|
-
width: img.width ?? 1200,
|
|
224
|
-
height: img.height ?? 630
|
|
225
|
-
})) : void 0;
|
|
226
|
-
return {
|
|
227
|
-
title: page.openGraph.title ?? page.title,
|
|
228
|
-
description: page.openGraph.description ?? page.description,
|
|
229
|
-
...images && { images }
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
const url = resolveOGImage(page, ogConfig, baseUrl);
|
|
233
|
-
if (!url) return void 0;
|
|
234
|
-
return {
|
|
235
|
-
title: page.title,
|
|
236
|
-
...page.description && { description: page.description },
|
|
237
|
-
images: [{
|
|
238
|
-
url,
|
|
239
|
-
width: 1200,
|
|
240
|
-
height: 630
|
|
241
|
-
}]
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Build the Twitter card metadata object for a page.
|
|
246
|
-
* When the page has twitter in frontmatter, uses it.
|
|
247
|
-
* Otherwise builds from ogImage or config (dynamic endpoint).
|
|
248
|
-
*/
|
|
249
|
-
function buildPageTwitter(page, ogConfig, baseUrl) {
|
|
250
|
-
if (page.twitter) {
|
|
251
|
-
const images = page.twitter.images?.length ? page.twitter.images.map((url) => resolveImageUrl(url, baseUrl)) : void 0;
|
|
252
|
-
return {
|
|
253
|
-
...page.twitter.card && { card: page.twitter.card },
|
|
254
|
-
...page.twitter.title !== void 0 && { title: page.twitter.title },
|
|
255
|
-
...page.twitter.description !== void 0 && { description: page.twitter.description },
|
|
256
|
-
...images && { images }
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
const url = resolveOGImage(page, ogConfig, baseUrl);
|
|
260
|
-
if (!url) return void 0;
|
|
261
|
-
return {
|
|
262
|
-
card: "summary_large_image",
|
|
263
|
-
title: page.title,
|
|
264
|
-
...page.description && { description: page.description },
|
|
265
|
-
images: [url]
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
//#endregion
|
|
270
3
|
//#region src/agent.ts
|
|
271
4
|
const DEFAULT_DOCS_API_ROUTE = "/api/docs";
|
|
272
5
|
const DEFAULT_AGENT_SPEC_ROUTE = "/api/docs/agent/spec";
|
|
@@ -585,4 +318,4 @@ function toYamlString(value) {
|
|
|
585
318
|
}
|
|
586
319
|
|
|
587
320
|
//#endregion
|
|
588
|
-
export {
|
|
321
|
+
export { renderDocsMarkdownDocument as C, resolveDocsMarkdownRequest as D, resolveDocsLlmsTxtFormat as E, resolveDocsSkillFormat as O, normalizeDocsUrlPath as S, resolveDocsAgentMdxContent as T, isDocsAgentDiscoveryRequest as _, DEFAULT_DOCS_API_ROUTE as a, isDocsSkillRequest as b, DEFAULT_LLMS_TXT_ROUTE as c, DEFAULT_MCP_ROUTE as d, DEFAULT_MCP_WELL_KNOWN_ROUTE as f, findDocsMarkdownPage as g, buildDocsAgentDiscoverySpec as h, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as i, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as l, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as m, DEFAULT_AGENT_SPEC_ROUTE as n, DEFAULT_LLMS_FULL_TXT_ROUTE as o, DEFAULT_SKILL_MD_ROUTE as p, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as r, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as s, DEFAULT_AGENT_FEEDBACK_ROUTE as t, DEFAULT_MCP_PUBLIC_ROUTE as u, isDocsMcpRequest as v, renderDocsSkillDocument as w, normalizeDocsPathSegment as x, isDocsPublicGetRequest as y };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { C as renderDocsMarkdownDocument, g as findDocsMarkdownPage } from "./agent-
|
|
2
|
-
import "./api-reference-
|
|
1
|
+
import { C as renderDocsMarkdownDocument, g as findDocsMarkdownPage } from "./agent-CbAtuZAc.mjs";
|
|
2
|
+
import "./api-reference-y7cqtq4w.mjs";
|
|
3
3
|
import { createFilesystemDocsMcpSource } from "./mcp.mjs";
|
|
4
4
|
import "./server.mjs";
|
|
5
|
-
import { a as
|
|
5
|
+
import { a as loadProjectEnv, c as readNavTitle, d as readTopLevelStringProperty, f as resolveDocsConfigPath, i as loadDocsConfigModule, l as readNumberProperty, o as readBooleanProperty, p as resolveDocsContentDir, s as readEnvReferenceProperty, t as extractNestedObjectLiteral, u as readStringProperty } from "./config-C7sUsMkm.mjs";
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import pc from "picocolors";
|
package/dist/cli/index.mjs
CHANGED
|
@@ -69,13 +69,13 @@ async function main() {
|
|
|
69
69
|
searchApiKey: typeof flags["search-api-key"] === "string" ? flags["search-api-key"] : void 0
|
|
70
70
|
};
|
|
71
71
|
if (!parsedCommand.command || parsedCommand.command === "init") {
|
|
72
|
-
const { init } = await import("../init-
|
|
72
|
+
const { init } = await import("../init-CShiL8Ch.mjs");
|
|
73
73
|
await init(initOptions);
|
|
74
74
|
} else if (parsedCommand.command === "mcp") {
|
|
75
|
-
const { runMcp } = await import("../mcp-
|
|
75
|
+
const { runMcp } = await import("../mcp-CYpMeMfi.mjs");
|
|
76
76
|
await runMcp(mcpOptions);
|
|
77
77
|
} else if (parsedCommand.command === "agent" && subcommand === "compact") {
|
|
78
|
-
const { compactAgentDocs, parseAgentCompactArgs, printAgentCompactHelp } = await import("../agent-
|
|
78
|
+
const { compactAgentDocs, parseAgentCompactArgs, printAgentCompactHelp } = await import("../agent-Dget5s8h.mjs");
|
|
79
79
|
const agentCompactOptions = parseAgentCompactArgs(args.slice(2));
|
|
80
80
|
if (agentCompactOptions.help) {
|
|
81
81
|
printAgentCompactHelp();
|
|
@@ -85,11 +85,19 @@ async function main() {
|
|
|
85
85
|
} else if (parsedCommand.command === "agent") {
|
|
86
86
|
console.error(pc.red(`Unknown agent subcommand: ${subcommand ?? "(missing)"}`));
|
|
87
87
|
console.error();
|
|
88
|
-
const { printAgentCompactHelp } = await import("../agent-
|
|
88
|
+
const { printAgentCompactHelp } = await import("../agent-Dget5s8h.mjs");
|
|
89
89
|
printAgentCompactHelp();
|
|
90
90
|
process.exit(1);
|
|
91
|
+
} else if (parsedCommand.command === "doctor") {
|
|
92
|
+
const { parseDoctorArgs, printDoctorHelp, runDoctor } = await import("../doctor-Jm7T0qYS.mjs");
|
|
93
|
+
const doctorOptions = parseDoctorArgs(args.slice(1));
|
|
94
|
+
if (doctorOptions.help) {
|
|
95
|
+
printDoctorHelp();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
await runDoctor(doctorOptions);
|
|
91
99
|
} else if (parsedCommand.command === "search" && subcommand === "sync") {
|
|
92
|
-
const { syncSearch } = await import("../search-
|
|
100
|
+
const { syncSearch } = await import("../search-D7DS0MLc.mjs");
|
|
93
101
|
await syncSearch(searchSyncOptions);
|
|
94
102
|
} else if (parsedCommand.command === "search") {
|
|
95
103
|
console.error(pc.red(`Unknown search subcommand: ${subcommand ?? "(missing)"}`));
|
|
@@ -97,7 +105,7 @@ async function main() {
|
|
|
97
105
|
printHelp();
|
|
98
106
|
process.exit(1);
|
|
99
107
|
} else if (parsedCommand.command === "upgrade") {
|
|
100
|
-
const { upgrade } = await import("../upgrade-
|
|
108
|
+
const { upgrade } = await import("../upgrade-2xcgMsj6.mjs");
|
|
101
109
|
await upgrade({
|
|
102
110
|
framework: (typeof flags.framework === "string" ? flags.framework : void 0) ?? (args[1] && !args[1].startsWith("--") ? args[1] : void 0),
|
|
103
111
|
tag: args.includes("--beta") ? "beta" : args.includes("--latest") ? "latest" : parsedCommand.tag ?? "latest"
|
|
@@ -121,6 +129,7 @@ ${pc.dim("Usage:")}
|
|
|
121
129
|
${pc.dim("Commands:")}
|
|
122
130
|
${pc.cyan("init")} Scaffold docs in your project (default)
|
|
123
131
|
${pc.cyan("agent")} Agent utilities (${pc.dim("compact")} to generate sibling agent.md files)
|
|
132
|
+
${pc.cyan("doctor")} Inspect and score agent-readiness for the current docs app
|
|
124
133
|
${pc.cyan("mcp")} Run the built-in docs MCP server over stdio
|
|
125
134
|
${pc.cyan("search")} Search utilities (${pc.dim("sync")} for external indexes)
|
|
126
135
|
${pc.cyan("upgrade")} Upgrade @farming-labs/* packages to latest (auto-detect or use --framework)
|
|
@@ -150,6 +159,12 @@ ${pc.dim("Options for agent compact:")}
|
|
|
150
159
|
${pc.cyan("--aggressiveness <0-1>")} Compression intensity for compacted output
|
|
151
160
|
${pc.cyan("--dry-run")} Resolve and compress pages without writing files
|
|
152
161
|
|
|
162
|
+
${pc.dim("Options for doctor:")}
|
|
163
|
+
${pc.cyan("doctor")} Score the current docs app for agent-readiness
|
|
164
|
+
${pc.cyan("doctor --agent")} Same as ${pc.cyan("doctor")}; explicit agent scoring mode
|
|
165
|
+
${pc.cyan("doctor agent")} Subcommand alias for agent scoring
|
|
166
|
+
${pc.cyan("--config <path>")} Use a custom docs config path instead of ${pc.dim("docs.config.ts[x]")}
|
|
167
|
+
|
|
153
168
|
${pc.dim("Options for search sync:")}
|
|
154
169
|
${pc.cyan("search sync --typesense")} Sync docs content to Typesense using env/flags
|
|
155
170
|
${pc.cyan("search sync --algolia")} Sync docs content to Algolia using env/flags
|
|
@@ -267,4 +267,4 @@ async function loadDocsConfigModule(rootDir, explicitPath) {
|
|
|
267
267
|
}
|
|
268
268
|
|
|
269
269
|
//#endregion
|
|
270
|
-
export {
|
|
270
|
+
export { loadProjectEnv as a, readNavTitle as c, readTopLevelStringProperty as d, resolveDocsConfigPath as f, loadDocsConfigModule as i, readNumberProperty as l, extractObjectLiteral as n, readBooleanProperty as o, resolveDocsContentDir as p, extractTopLevelConfigObject as r, readEnvReferenceProperty as s, extractNestedObjectLiteral as t, readStringProperty as u };
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
import { c as DEFAULT_LLMS_TXT_ROUTE, f as DEFAULT_MCP_WELL_KNOWN_ROUTE, i as DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, m as DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, o as DEFAULT_LLMS_FULL_TXT_ROUTE, p as DEFAULT_SKILL_MD_ROUTE, r as DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, t as DEFAULT_AGENT_FEEDBACK_ROUTE, u as DEFAULT_MCP_PUBLIC_ROUTE } from "./agent-CbAtuZAc.mjs";
|
|
2
|
+
import "./api-reference-y7cqtq4w.mjs";
|
|
3
|
+
import { createFilesystemDocsMcpSource, resolveDocsMcpConfig } from "./mcp.mjs";
|
|
4
|
+
import "./server.mjs";
|
|
5
|
+
import { a as loadProjectEnv, c as readNavTitle, d as readTopLevelStringProperty, f as resolveDocsConfigPath, i as loadDocsConfigModule, o as readBooleanProperty, p as resolveDocsContentDir, r as extractTopLevelConfigObject, t as extractNestedObjectLiteral } from "./config-C7sUsMkm.mjs";
|
|
6
|
+
import { t as detectFramework } from "./utils-DSMXVnEu.mjs";
|
|
7
|
+
import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import pc from "picocolors";
|
|
10
|
+
|
|
11
|
+
//#region src/cli/doctor.ts
|
|
12
|
+
const NEXT_CONFIG_PATTERN = /^next\.config\.(?:[cm]?js|[cm]?ts)$/;
|
|
13
|
+
const ASTRO_CONFIG_PATTERN = /^astro\.config\.(?:[cm]?js|[cm]?ts)$/;
|
|
14
|
+
const CODE_FILE_PATTERN = /\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/;
|
|
15
|
+
const IGNORED_DIRS = new Set([
|
|
16
|
+
".git",
|
|
17
|
+
".next",
|
|
18
|
+
".nuxt",
|
|
19
|
+
".output",
|
|
20
|
+
".svelte-kit",
|
|
21
|
+
".turbo",
|
|
22
|
+
"build",
|
|
23
|
+
"coverage",
|
|
24
|
+
"dist",
|
|
25
|
+
"node_modules",
|
|
26
|
+
"out"
|
|
27
|
+
]);
|
|
28
|
+
function parseInlineFlag(arg) {
|
|
29
|
+
const [rawKey, value] = arg.slice(2).split("=", 2);
|
|
30
|
+
return {
|
|
31
|
+
key: rawKey.trim(),
|
|
32
|
+
value
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function parseDoctorArgs(argv) {
|
|
36
|
+
const parsed = {};
|
|
37
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
38
|
+
const arg = argv[index];
|
|
39
|
+
if (arg === "--help" || arg === "-h") {
|
|
40
|
+
parsed.help = true;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (arg === "--agent" || arg === "agent") {
|
|
44
|
+
parsed.agent = true;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (arg.startsWith("--config=")) {
|
|
48
|
+
const value = parseInlineFlag(arg).value;
|
|
49
|
+
if (!value) throw new Error("Missing value for --config.");
|
|
50
|
+
parsed.configPath = value;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (arg === "--config") {
|
|
54
|
+
const value = argv[index + 1];
|
|
55
|
+
if (!value || value.startsWith("--")) throw new Error("Missing value for --config.");
|
|
56
|
+
parsed.configPath = value;
|
|
57
|
+
index += 1;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
throw new Error(`Unknown doctor flag or subcommand: ${arg}.`);
|
|
61
|
+
}
|
|
62
|
+
if (!parsed.help && parsed.agent !== true) parsed.agent = true;
|
|
63
|
+
return parsed;
|
|
64
|
+
}
|
|
65
|
+
function printDoctorHelp() {
|
|
66
|
+
console.log(`
|
|
67
|
+
${pc.bold("@farming-labs/docs doctor")}
|
|
68
|
+
|
|
69
|
+
${pc.dim("Usage:")}
|
|
70
|
+
pnpm exec docs doctor
|
|
71
|
+
pnpm exec docs doctor --agent
|
|
72
|
+
pnpm exec docs doctor agent
|
|
73
|
+
|
|
74
|
+
${pc.dim("Options:")}
|
|
75
|
+
${pc.cyan("--agent")} Score agent-readiness for the current docs app (default)
|
|
76
|
+
${pc.cyan("--config <path>")} Use a custom docs config path instead of ${pc.dim("docs.config.ts[x]")}
|
|
77
|
+
${pc.cyan("-h, --help")} Show this help message
|
|
78
|
+
`);
|
|
79
|
+
}
|
|
80
|
+
function escapeRegExp(value) {
|
|
81
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
82
|
+
}
|
|
83
|
+
function splitTopLevelProperties(content) {
|
|
84
|
+
const properties = [];
|
|
85
|
+
let start = 0;
|
|
86
|
+
let stringQuote = null;
|
|
87
|
+
let escaped = false;
|
|
88
|
+
let braceDepth = 0;
|
|
89
|
+
let bracketDepth = 0;
|
|
90
|
+
let parenDepth = 0;
|
|
91
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
92
|
+
const char = content[index];
|
|
93
|
+
if (stringQuote) {
|
|
94
|
+
if (escaped) {
|
|
95
|
+
escaped = false;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (char === "\\") {
|
|
99
|
+
escaped = true;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (char === stringQuote) stringQuote = null;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (char === "\"" || char === "'" || char === "`") {
|
|
106
|
+
stringQuote = char;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (char === "{") {
|
|
110
|
+
braceDepth += 1;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (char === "}") {
|
|
114
|
+
braceDepth = Math.max(0, braceDepth - 1);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (char === "[") {
|
|
118
|
+
bracketDepth += 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (char === "]") {
|
|
122
|
+
bracketDepth = Math.max(0, bracketDepth - 1);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (char === "(") {
|
|
126
|
+
parenDepth += 1;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (char === ")") {
|
|
130
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (char === "," && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
|
|
134
|
+
properties.push(content.slice(start, index));
|
|
135
|
+
start = index + 1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const trailing = content.slice(start);
|
|
139
|
+
if (trailing.trim().length > 0) properties.push(trailing);
|
|
140
|
+
return properties;
|
|
141
|
+
}
|
|
142
|
+
function readTopLevelBooleanProperty(content, key) {
|
|
143
|
+
const rootObject = extractTopLevelConfigObject(content) ?? content;
|
|
144
|
+
const propertyPattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*:\\s*(true|false)(?:\\s|$)`);
|
|
145
|
+
for (const property of splitTopLevelProperties(rootObject)) {
|
|
146
|
+
const match = property.trim().match(propertyPattern);
|
|
147
|
+
if (match) return match[1] === "true";
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function resolveFeatureEnabled(config, content, key) {
|
|
151
|
+
const current = config?.[key];
|
|
152
|
+
if (typeof current === "boolean") return current;
|
|
153
|
+
if (current && typeof current === "object") return current.enabled ?? true;
|
|
154
|
+
const topLevelBoolean = readTopLevelBooleanProperty(content, key);
|
|
155
|
+
if (typeof topLevelBoolean === "boolean") return topLevelBoolean;
|
|
156
|
+
const block = extractNestedObjectLiteral(content, [key]);
|
|
157
|
+
if (!block) return true;
|
|
158
|
+
return readBooleanProperty(block, "enabled") ?? true;
|
|
159
|
+
}
|
|
160
|
+
function resolveStaticExport(config, content) {
|
|
161
|
+
if (typeof config?.staticExport === "boolean") return config.staticExport;
|
|
162
|
+
return readTopLevelBooleanProperty(content, "staticExport") ?? false;
|
|
163
|
+
}
|
|
164
|
+
function resolveAgentFeedbackEnabled(config, content) {
|
|
165
|
+
const feedback = config?.feedback;
|
|
166
|
+
if (feedback && typeof feedback === "object") {
|
|
167
|
+
const agent = feedback.agent;
|
|
168
|
+
if (typeof agent === "boolean") return agent;
|
|
169
|
+
if (agent && typeof agent === "object") return agent.enabled ?? true;
|
|
170
|
+
}
|
|
171
|
+
const feedbackBlock = extractNestedObjectLiteral(content, ["feedback"]);
|
|
172
|
+
if (!feedbackBlock) return false;
|
|
173
|
+
const nestedAgentBlock = extractNestedObjectLiteral(content, ["feedback", "agent"]);
|
|
174
|
+
if (nestedAgentBlock) return readBooleanProperty(nestedAgentBlock, "enabled") ?? true;
|
|
175
|
+
return readBooleanProperty(feedbackBlock, "agent") ?? false;
|
|
176
|
+
}
|
|
177
|
+
function hasAgentCompactDefaults(config, content) {
|
|
178
|
+
if (config?.agent?.compact) return true;
|
|
179
|
+
return extractNestedObjectLiteral(content, ["agent", "compact"]) !== void 0;
|
|
180
|
+
}
|
|
181
|
+
function listProjectFiles(rootDir) {
|
|
182
|
+
const files = [];
|
|
183
|
+
const visit = (dir) => {
|
|
184
|
+
if (!existsSync(dir)) return;
|
|
185
|
+
for (const entry of readdirSync(dir).sort()) {
|
|
186
|
+
const fullPath = path.join(dir, entry);
|
|
187
|
+
const stat = lstatSync(fullPath);
|
|
188
|
+
if (stat.isSymbolicLink()) continue;
|
|
189
|
+
if (stat.isDirectory()) {
|
|
190
|
+
if (IGNORED_DIRS.has(entry)) continue;
|
|
191
|
+
visit(fullPath);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
files.push(path.relative(rootDir, fullPath).replace(/\\/g, "/"));
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
visit(rootDir);
|
|
198
|
+
return files;
|
|
199
|
+
}
|
|
200
|
+
function buildFileReader(rootDir) {
|
|
201
|
+
const cache = /* @__PURE__ */ new Map();
|
|
202
|
+
return (relativePath) => {
|
|
203
|
+
const cached = cache.get(relativePath);
|
|
204
|
+
if (cached !== void 0) return cached;
|
|
205
|
+
const content = readFileSync(path.join(rootDir, relativePath), "utf-8");
|
|
206
|
+
cache.set(relativePath, content);
|
|
207
|
+
return content;
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function formatPathList(paths) {
|
|
211
|
+
if (paths.length === 0) return "";
|
|
212
|
+
if (paths.length === 1) return paths[0];
|
|
213
|
+
return `${paths[0]} (+${paths.length - 1} more)`;
|
|
214
|
+
}
|
|
215
|
+
function findCodeFiles(files, predicate) {
|
|
216
|
+
return files.filter((relativePath) => CODE_FILE_PATTERN.test(relativePath) && predicate(relativePath));
|
|
217
|
+
}
|
|
218
|
+
function detectFrameworkFromFiles(files) {
|
|
219
|
+
if (files.some((file) => NEXT_CONFIG_PATTERN.test(path.basename(file)))) return "nextjs";
|
|
220
|
+
if (files.some((file) => file.startsWith("src/routes/") && file.includes("api.docs"))) return "tanstack-start";
|
|
221
|
+
if (files.some((file) => file === "src/hooks.server.js" || file === "src/hooks.server.ts")) return "sveltekit";
|
|
222
|
+
if (files.some((file) => ASTRO_CONFIG_PATTERN.test(path.basename(file)))) return "astro";
|
|
223
|
+
if (files.some((file) => file.startsWith("server/middleware/"))) return "nuxt";
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
function detectRouteSurface(rootDir, framework, staticExport, files) {
|
|
227
|
+
const read = buildFileReader(rootDir);
|
|
228
|
+
if (framework === "nextjs") {
|
|
229
|
+
const withDocsConfigs = files.filter((file) => NEXT_CONFIG_PATTERN.test(path.basename(file))).filter((file) => read(file).includes("withDocs("));
|
|
230
|
+
const apiRoutes = findCodeFiles(files, (file) => /(?:^|\/)route\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/.test(file) && read(file).includes("createDocsAPI("));
|
|
231
|
+
if (staticExport) return {
|
|
232
|
+
apiMounted: false,
|
|
233
|
+
apiDetail: "Next static export disables /api/docs and the shared agent endpoints.",
|
|
234
|
+
publicMounted: false,
|
|
235
|
+
publicDetail: "Public .md, llms.txt, skill.md, and agent discovery routes depend on /api/docs."
|
|
236
|
+
};
|
|
237
|
+
return {
|
|
238
|
+
apiMounted: apiRoutes.length > 0,
|
|
239
|
+
apiDetail: apiRoutes.length > 0 ? `Found docs API route at ${formatPathList(apiRoutes)}.` : "Could not find a Next docs API route that uses createDocsAPI().",
|
|
240
|
+
publicMounted: withDocsConfigs.length > 0,
|
|
241
|
+
publicDetail: withDocsConfigs.length > 0 ? `Found withDocs() in ${formatPathList(withDocsConfigs)}.` : "Could not find withDocs() in next.config.*, so public docs rewrites are not verified."
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
if (framework === "tanstack-start") {
|
|
245
|
+
const apiRoutes = findCodeFiles(files, (file) => file.startsWith("src/routes/") && read(file).includes("docsServer.GET") && /createFileRoute\((["'])\/api/.test(read(file)));
|
|
246
|
+
const publicHandlers = findCodeFiles(files, (file) => file.startsWith("src/routes/") && read(file).includes("isDocsPublicGetRequest(") && read(file).includes("isDocsMcpRequest("));
|
|
247
|
+
return {
|
|
248
|
+
apiMounted: apiRoutes.length > 0,
|
|
249
|
+
apiDetail: apiRoutes.length > 0 ? `Found TanStack docs API route at ${formatPathList(apiRoutes)}.` : "Could not find a TanStack route that forwards /api/docs into docsServer.GET.",
|
|
250
|
+
publicMounted: publicHandlers.length > 0,
|
|
251
|
+
publicDetail: publicHandlers.length > 0 ? `Found public docs forwarder at ${formatPathList(publicHandlers)}.` : "Could not find a TanStack public docs forwarder using isDocsPublicGetRequest()."
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
if (framework === "sveltekit") {
|
|
255
|
+
const apiRoutes = findCodeFiles(files, (file) => file.startsWith("src/routes/") && path.basename(file).startsWith("+server.") && read(file).includes("docs.server"));
|
|
256
|
+
const publicHandlers = findCodeFiles(files, (file) => /^src\/hooks\.server\.(?:[cm]?js|[cm]?ts)$/.test(file) && read(file).includes("isDocsPublicGetRequest("));
|
|
257
|
+
return {
|
|
258
|
+
apiMounted: apiRoutes.length > 0,
|
|
259
|
+
apiDetail: apiRoutes.length > 0 ? `Found SvelteKit docs API route at ${formatPathList(apiRoutes)}.` : "Could not find a SvelteKit +server route that re-exports docs.server.",
|
|
260
|
+
publicMounted: publicHandlers.length > 0,
|
|
261
|
+
publicDetail: publicHandlers.length > 0 ? `Found SvelteKit public docs hook at ${formatPathList(publicHandlers)}.` : "Could not find hooks.server with isDocsPublicGetRequest()."
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
if (framework === "astro") {
|
|
265
|
+
const apiRoutes = findCodeFiles(files, (file) => file.startsWith("src/pages/") && read(file).includes("docsGET") && read(file).includes("docsPOST"));
|
|
266
|
+
const publicHandlers = findCodeFiles(files, (file) => /^src\/middleware\.(?:[cm]?js|[cm]?ts)$/.test(file) && read(file).includes("isDocsPublicGetRequest("));
|
|
267
|
+
return {
|
|
268
|
+
apiMounted: apiRoutes.length > 0,
|
|
269
|
+
apiDetail: apiRoutes.length > 0 ? `Found Astro docs API route at ${formatPathList(apiRoutes)}.` : "Could not find an Astro docs API route that forwards to docs.server.",
|
|
270
|
+
publicMounted: publicHandlers.length > 0,
|
|
271
|
+
publicDetail: publicHandlers.length > 0 ? `Found Astro middleware forwarder at ${formatPathList(publicHandlers)}.` : "Could not find Astro middleware using isDocsPublicGetRequest()."
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
if (framework === "nuxt") {
|
|
275
|
+
const apiRoutes = findCodeFiles(files, (file) => file.startsWith("server/api/") && read(file).includes("defineDocsHandler("));
|
|
276
|
+
const publicHandlers = findCodeFiles(files, (file) => file.startsWith("server/middleware/") && read(file).includes("defineDocsPublicHandler("));
|
|
277
|
+
return {
|
|
278
|
+
apiMounted: apiRoutes.length > 0,
|
|
279
|
+
apiDetail: apiRoutes.length > 0 ? `Found Nuxt docs API handler at ${formatPathList(apiRoutes)}.` : "Could not find a Nuxt docs API handler using defineDocsHandler().",
|
|
280
|
+
publicMounted: publicHandlers.length > 0,
|
|
281
|
+
publicDetail: publicHandlers.length > 0 ? `Found Nuxt public docs middleware at ${formatPathList(publicHandlers)}.` : "Could not find Nuxt middleware using defineDocsPublicHandler()."
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
apiMounted: false,
|
|
286
|
+
apiDetail: "Could not detect a supported framework, so API route inspection was skipped.",
|
|
287
|
+
publicMounted: false,
|
|
288
|
+
publicDetail: "Could not detect a supported framework, so public route inspection was skipped."
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function coverageScore(explicitCoverage) {
|
|
292
|
+
if (explicitCoverage >= 80) return {
|
|
293
|
+
status: "pass",
|
|
294
|
+
score: 10
|
|
295
|
+
};
|
|
296
|
+
if (explicitCoverage >= 50) return {
|
|
297
|
+
status: "pass",
|
|
298
|
+
score: 8
|
|
299
|
+
};
|
|
300
|
+
if (explicitCoverage >= 20) return {
|
|
301
|
+
status: "warn",
|
|
302
|
+
score: 5
|
|
303
|
+
};
|
|
304
|
+
if (explicitCoverage > 0) return {
|
|
305
|
+
status: "warn",
|
|
306
|
+
score: 3
|
|
307
|
+
};
|
|
308
|
+
return {
|
|
309
|
+
status: "warn",
|
|
310
|
+
score: 0
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function metadataScore(descriptionCoverage, relatedCoverage) {
|
|
314
|
+
if (descriptionCoverage >= 90 && relatedCoverage >= 20) return {
|
|
315
|
+
status: "pass",
|
|
316
|
+
score: 5
|
|
317
|
+
};
|
|
318
|
+
if (descriptionCoverage >= 75) return {
|
|
319
|
+
status: "pass",
|
|
320
|
+
score: 4
|
|
321
|
+
};
|
|
322
|
+
if (descriptionCoverage >= 50) return {
|
|
323
|
+
status: "warn",
|
|
324
|
+
score: 2
|
|
325
|
+
};
|
|
326
|
+
if (descriptionCoverage > 0) return {
|
|
327
|
+
status: "warn",
|
|
328
|
+
score: 1
|
|
329
|
+
};
|
|
330
|
+
return {
|
|
331
|
+
status: "warn",
|
|
332
|
+
score: 0
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function gradeForScore(score) {
|
|
336
|
+
if (score >= 90) return "Agent-optimized";
|
|
337
|
+
if (score >= 75) return "Agent-ready";
|
|
338
|
+
if (score >= 60) return "Promising";
|
|
339
|
+
return "Needs work";
|
|
340
|
+
}
|
|
341
|
+
function formatStatus(status) {
|
|
342
|
+
if (status === "pass") return pc.green("PASS");
|
|
343
|
+
if (status === "warn") return pc.yellow("WARN");
|
|
344
|
+
return pc.red("FAIL");
|
|
345
|
+
}
|
|
346
|
+
function buildCoverage(pages) {
|
|
347
|
+
const totalPages = pages.length;
|
|
348
|
+
const pagesWithAgentFiles = pages.filter((page) => page.agentRawContent !== void 0).length;
|
|
349
|
+
const pagesWithAgentBlocks = pages.filter((page) => page.agentFallbackRawContent !== void 0).length;
|
|
350
|
+
const explicitPages = pages.filter((page) => page.agentRawContent !== void 0 || page.agentFallbackRawContent !== void 0).length;
|
|
351
|
+
return {
|
|
352
|
+
totalPages,
|
|
353
|
+
pagesWithAgentFiles,
|
|
354
|
+
pagesWithAgentBlocks,
|
|
355
|
+
explicitPages,
|
|
356
|
+
explicitCoverage: totalPages === 0 ? 0 : Math.round(explicitPages / Math.max(totalPages, 1) * 100)
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
function buildMetadataCoverage(pages) {
|
|
360
|
+
const totalPages = pages.length;
|
|
361
|
+
const describedPages = pages.filter((page) => typeof page.description === "string" && page.description.trim().length > 0).length;
|
|
362
|
+
const relatedPages = pages.filter((page) => Array.isArray(page.related) && page.related.length > 0).length;
|
|
363
|
+
return {
|
|
364
|
+
describedPages,
|
|
365
|
+
relatedPages,
|
|
366
|
+
descriptionCoverage: totalPages === 0 ? 0 : Math.round(describedPages / totalPages * 100),
|
|
367
|
+
relatedCoverage: totalPages === 0 ? 0 : Math.round(relatedPages / totalPages * 100)
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
async function loadDocsConfigModuleWithProjectEnv(rootDir, explicitPath) {
|
|
371
|
+
const env = loadProjectEnv(rootDir);
|
|
372
|
+
const injectedKeys = Object.entries(env).filter(([key]) => process.env[key] === void 0).map(([key, value]) => {
|
|
373
|
+
process.env[key] = value;
|
|
374
|
+
return key;
|
|
375
|
+
});
|
|
376
|
+
try {
|
|
377
|
+
return await loadDocsConfigModule(rootDir, explicitPath);
|
|
378
|
+
} finally {
|
|
379
|
+
for (const key of injectedKeys) delete process.env[key];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
function makeCheck(id, title, status, score, maxScore, detail, recommendation) {
|
|
383
|
+
return {
|
|
384
|
+
id,
|
|
385
|
+
title,
|
|
386
|
+
status,
|
|
387
|
+
score,
|
|
388
|
+
maxScore,
|
|
389
|
+
detail,
|
|
390
|
+
recommendation
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
async function inspectAgentReadiness(options = {}) {
|
|
394
|
+
const rootDir = process.cwd();
|
|
395
|
+
const files = listProjectFiles(rootDir);
|
|
396
|
+
const framework = detectFramework(rootDir) ?? detectFrameworkFromFiles(files) ?? "unknown";
|
|
397
|
+
const configCheckMax = 10;
|
|
398
|
+
let configPath;
|
|
399
|
+
try {
|
|
400
|
+
configPath = resolveDocsConfigPath(rootDir, options.configPath);
|
|
401
|
+
} catch (error) {
|
|
402
|
+
const checks = [makeCheck("config", "Docs config", "fail", 0, configCheckMax, error instanceof Error ? error.message : String(error), "Add docs.config.ts[x] or pass --config so the doctor can inspect the docs app.")];
|
|
403
|
+
return {
|
|
404
|
+
mode: "agent",
|
|
405
|
+
framework,
|
|
406
|
+
score: 0,
|
|
407
|
+
maxScore: 100,
|
|
408
|
+
grade: gradeForScore(0),
|
|
409
|
+
checks,
|
|
410
|
+
coverage: {
|
|
411
|
+
totalPages: 0,
|
|
412
|
+
pagesWithAgentFiles: 0,
|
|
413
|
+
pagesWithAgentBlocks: 0,
|
|
414
|
+
explicitPages: 0,
|
|
415
|
+
explicitCoverage: 0
|
|
416
|
+
},
|
|
417
|
+
recommendations: checks.map((check) => check.recommendation).filter(Boolean)
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
const configContent = readFileSync(configPath, "utf-8");
|
|
421
|
+
const loadedConfig = await loadDocsConfigModuleWithProjectEnv(rootDir, options.configPath);
|
|
422
|
+
const config = loadedConfig?.config;
|
|
423
|
+
const entry = config?.entry ?? readTopLevelStringProperty(configContent, "entry") ?? "docs";
|
|
424
|
+
const contentDir = config?.contentDir ?? resolveDocsContentDir(rootDir, configContent, entry);
|
|
425
|
+
const ordering = config?.ordering === "alphabetical" || config?.ordering === "numeric" || Array.isArray(config?.ordering) ? config.ordering : void 0;
|
|
426
|
+
const siteTitle = typeof config?.nav?.title === "string" ? config.nav.title : readNavTitle(configContent) ?? "Documentation";
|
|
427
|
+
const staticExport = resolveStaticExport(config, configContent);
|
|
428
|
+
const llmsEnabled = resolveFeatureEnabled(config, configContent, "llmsTxt");
|
|
429
|
+
const searchEnabled = resolveFeatureEnabled(config, configContent, "search");
|
|
430
|
+
const mcpEnabled = resolveFeatureEnabled(config, configContent, "mcp");
|
|
431
|
+
const agentFeedbackEnabled = resolveAgentFeedbackEnabled(config, configContent);
|
|
432
|
+
const compactConfigured = hasAgentCompactDefaults(config, configContent);
|
|
433
|
+
const skillFileExists = existsSync(path.join(rootDir, "skill.md"));
|
|
434
|
+
const source = createFilesystemDocsMcpSource({
|
|
435
|
+
rootDir,
|
|
436
|
+
entry,
|
|
437
|
+
contentDir,
|
|
438
|
+
siteTitle,
|
|
439
|
+
ordering
|
|
440
|
+
});
|
|
441
|
+
const pages = await Promise.resolve(source.getPages());
|
|
442
|
+
const coverage = buildCoverage(pages);
|
|
443
|
+
const metadataCoverage = buildMetadataCoverage(pages);
|
|
444
|
+
const metadataResult = metadataScore(metadataCoverage.descriptionCoverage, metadataCoverage.relatedCoverage);
|
|
445
|
+
const routeSurface = detectRouteSurface(rootDir, framework, staticExport, files);
|
|
446
|
+
const mcpConfig = resolveDocsMcpConfig(config?.mcp ?? void 0, { defaultName: siteTitle });
|
|
447
|
+
const feedbackRoute = DEFAULT_AGENT_FEEDBACK_ROUTE;
|
|
448
|
+
const feedbackSchemaRoute = `${feedbackRoute}/schema`;
|
|
449
|
+
const checks = [];
|
|
450
|
+
checks.push(makeCheck("config", "Docs config", "pass", 10, configCheckMax, loadedConfig ? `Resolved ${path.relative(rootDir, loadedConfig.path).replace(/\\/g, "/")} and evaluated the config module.` : `Resolved ${path.relative(rootDir, configPath).replace(/\\/g, "/")} using static parsing fallback.`));
|
|
451
|
+
const contentDirAbs = path.resolve(rootDir, contentDir);
|
|
452
|
+
checks.push(coverage.totalPages > 0 ? makeCheck("content", "Docs content", "pass", 10, 10, `Found ${coverage.totalPages} docs page${coverage.totalPages === 1 ? "" : "s"} in ${path.relative(rootDir, contentDirAbs).replace(/\\/g, "/")}.`) : makeCheck("content", "Docs content", "fail", 0, 10, `No folder-based docs pages were found in ${path.relative(rootDir, contentDirAbs).replace(/\\/g, "/")}.`, "Add index/page MDX files under the configured contentDir so the machine-readable surfaces have pages to serve."));
|
|
453
|
+
checks.push(makeCheck("api-route", "Docs API route", routeSurface.apiMounted ? "pass" : "fail", routeSurface.apiMounted ? 10 : 0, 10, routeSurface.apiDetail, routeSurface.apiMounted ? void 0 : "Wire the framework docs API route so /api/docs can serve markdown, llms.txt, skill.md, and discovery responses."));
|
|
454
|
+
checks.push(makeCheck("public-routes", "Public agent routes", routeSurface.publicMounted ? "pass" : "fail", routeSurface.publicMounted ? 10 : 0, 10, routeSurface.publicDetail, routeSurface.publicMounted ? void 0 : "Add the framework public forwarder so /.well-known/*, /llms.txt, /skill.md, /mcp, and .md routes resolve from the shared docs API."));
|
|
455
|
+
checks.push(makeCheck("agent-discovery", "Agent discovery spec", routeSurface.apiMounted && routeSurface.publicMounted ? "pass" : "fail", routeSurface.apiMounted && routeSurface.publicMounted ? 5 : 0, 5, routeSurface.apiMounted && routeSurface.publicMounted ? `Expected discovery endpoints are available through ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}, ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}, and /api/docs?agent=spec.` : "Could not verify the shared agent discovery spec endpoints because docs API/public route wiring is incomplete.", routeSurface.apiMounted && routeSurface.publicMounted ? void 0 : "Make sure both the docs API handler and the public docs forwarder are mounted so agents can discover the site through the well-known agent spec."));
|
|
456
|
+
checks.push(llmsEnabled ? makeCheck("llms", "llms.txt discovery", "pass", 10, 10, `Enabled via ${DEFAULT_LLMS_TXT_ROUTE} and ${DEFAULT_LLMS_FULL_TXT_ROUTE}.`) : makeCheck("llms", "llms.txt discovery", "warn", 0, 10, `${DEFAULT_LLMS_TXT_ROUTE} and ${DEFAULT_LLMS_FULL_TXT_ROUTE} are disabled in docs config.`, "Enable llmsTxt so agents and GEO crawlers can discover the docs index and full context surfaces."));
|
|
457
|
+
checks.push(skillFileExists ? makeCheck("skill", "Skill document", "pass", 5, 5, `Found root skill.md for ${DEFAULT_SKILL_MD_ROUTE} and ${DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE}.`) : makeCheck("skill", "Skill document", "warn", 3, 5, `No root skill.md found; the framework will serve the generated fallback at ${DEFAULT_SKILL_MD_ROUTE}.`, "Add a root skill.md if you want a custom site-specific bootstrap document instead of the generated fallback."));
|
|
458
|
+
checks.push(mcpEnabled ? makeCheck("mcp", "MCP access", "pass", 10, 10, `Enabled with public aliases ${DEFAULT_MCP_PUBLIC_ROUTE} and ${DEFAULT_MCP_WELL_KNOWN_ROUTE} (canonical route ${mcpConfig.route}).`) : makeCheck("mcp", "MCP access", "warn", 0, 10, "MCP is disabled in docs config.", "Enable mcp so agents can use list/search/read tools directly instead of only scraping markdown routes."));
|
|
459
|
+
checks.push(searchEnabled ? makeCheck("search", "Search surface", "pass", 5, 5, "Search is enabled for the shared docs API and agent flows.") : makeCheck("search", "Search surface", "warn", 0, 5, "Search is disabled in docs config.", "Enable search so agents can narrow retrieval before reading whole markdown pages."));
|
|
460
|
+
checks.push(agentFeedbackEnabled ? makeCheck("feedback", "Agent feedback", "pass", 5, 5, `Structured agent feedback is enabled at ${feedbackRoute} with schema ${feedbackSchemaRoute}.`) : makeCheck("feedback", "Agent feedback", "warn", 0, 5, "Structured agent feedback is not enabled.", "Enable feedback.agent if you want agents to discover and post feedback through the shared docs API."));
|
|
461
|
+
checks.push(makeCheck("metadata", "Page metadata", metadataResult.status, metadataResult.score, 5, coverage.totalPages > 0 ? `${metadataCoverage.describedPages}/${coverage.totalPages} pages include descriptions and ${metadataCoverage.relatedPages}/${coverage.totalPages} pages include related links (${metadataCoverage.descriptionCoverage}% described, ${metadataCoverage.relatedCoverage}% related).` : "No docs pages were available to score page metadata.", metadataCoverage.descriptionCoverage >= 75 ? void 0 : "Add page descriptions and related links to more docs pages so agent markdown output carries better context and navigation hints."));
|
|
462
|
+
const coverageResult = coverageScore(coverage.explicitCoverage);
|
|
463
|
+
checks.push(makeCheck("coverage", "Explicit page optimization", coverageResult.status, coverageResult.score, 10, coverage.totalPages > 0 ? `${coverage.explicitPages}/${coverage.totalPages} pages define explicit machine-only context (${coverage.pagesWithAgentFiles} agent.md, ${coverage.pagesWithAgentBlocks} Agent blocks, ${coverage.explicitCoverage}% of pages).` : "No docs pages were available to score explicit page optimization.", coverage.explicitCoverage >= 50 ? void 0 : "Add agent.md files or <Agent> blocks to more pages, or run docs agent compact to create page-level machine docs."));
|
|
464
|
+
checks.push(compactConfigured ? makeCheck("compact", "Compaction defaults", "pass", 5, 5, "agent.compact defaults are configured in docs.config for repeatable page compaction.") : makeCheck("compact", "Compaction defaults", "warn", 0, 5, "No agent.compact defaults were found in docs config.", "Add agent.compact defaults if you want docs agent compact to run without repeating model and key settings."));
|
|
465
|
+
const score = checks.reduce((total, check) => total + check.score, 0);
|
|
466
|
+
const maxScore = checks.reduce((total, check) => total + check.maxScore, 0);
|
|
467
|
+
return {
|
|
468
|
+
mode: "agent",
|
|
469
|
+
framework,
|
|
470
|
+
configPath: path.relative(rootDir, configPath).replace(/\\/g, "/"),
|
|
471
|
+
entry,
|
|
472
|
+
contentDir,
|
|
473
|
+
score,
|
|
474
|
+
maxScore,
|
|
475
|
+
grade: gradeForScore(score),
|
|
476
|
+
checks,
|
|
477
|
+
coverage,
|
|
478
|
+
recommendations: checks.map((check) => check.recommendation).filter((recommendation) => Boolean(recommendation)).slice(0, 3)
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
function printAgentDoctorReport(report) {
|
|
482
|
+
console.log(`${pc.bold("@farming-labs/docs doctor")} ${pc.dim("—")} ${pc.bold("agent")}`);
|
|
483
|
+
console.log();
|
|
484
|
+
console.log(`${pc.bold("Score:")} ${pc.cyan(`${report.score}/${report.maxScore}`)} ${pc.dim(`(${report.grade})`)}`);
|
|
485
|
+
console.log(`${pc.bold("Framework:")} ${report.framework} ${pc.dim("•")} ${pc.bold("Entry:")} ${report.entry ?? "docs"} ${pc.dim("•")} ${pc.bold("Content:")} ${report.contentDir ?? "-"}`);
|
|
486
|
+
console.log(`${pc.bold("Explicit agent-friendly pages:")} ${report.coverage.explicitPages}/${report.coverage.totalPages} pages ${pc.dim(`(${report.coverage.explicitCoverage}%)`)}`);
|
|
487
|
+
console.log();
|
|
488
|
+
for (const check of report.checks) {
|
|
489
|
+
console.log(`${formatStatus(check.status)} ${check.title} ${pc.dim(`(${check.score}/${check.maxScore})`)}`);
|
|
490
|
+
console.log(` ${check.detail}`);
|
|
491
|
+
}
|
|
492
|
+
if (report.recommendations.length > 0) {
|
|
493
|
+
console.log();
|
|
494
|
+
console.log(pc.bold("Next steps"));
|
|
495
|
+
for (const recommendation of report.recommendations) console.log(`- ${recommendation}`);
|
|
496
|
+
}
|
|
497
|
+
console.log();
|
|
498
|
+
console.log(pc.dim(`Expected public surfaces: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}, ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}, ${DEFAULT_LLMS_TXT_ROUTE}, ${DEFAULT_LLMS_FULL_TXT_ROUTE}, ${DEFAULT_SKILL_MD_ROUTE}, ${DEFAULT_MCP_PUBLIC_ROUTE}`));
|
|
499
|
+
}
|
|
500
|
+
async function runDoctor(options = {}) {
|
|
501
|
+
const report = await inspectAgentReadiness(options);
|
|
502
|
+
printAgentDoctorReport(report);
|
|
503
|
+
return report;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
//#endregion
|
|
507
|
+
export { parseDoctorArgs, printDoctorHelp, runDoctor };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { $ as SidebarFolderNode, A as DocsSearchQuery, B as McpDocsSearchConfig, C as DocsSearchAdapter, D as DocsSearchConfig, E as DocsSearchChunkingConfig, F as FeedbackConfig, G as OrderingItem, H as OpenDocsConfig, I as FontStyle, J as PageOpenGraph, K as PageActionsConfig, L as GithubConfig, M as DocsSearchResultType, N as DocsSearchSourcePage, O as DocsSearchDocument, P as DocsTheme, Q as SidebarConfig, R as LastUpdatedConfig, S as DocsRelatedItem, T as DocsSearchAdapterFactory, U as OpenDocsProvider, V as OGConfig, W as OpenGraphImage, X as ResolvedDocsRelatedLink, Y as PageTwitter, Z as SidebarComponentProps, _ as DocsI18nConfig, a as ApiReferenceRenderer, at as TypesenseDocsSearchConfig, b as DocsMetadata, c as ChangelogFrontmatter, d as CustomDocsSearchConfig, et as SidebarNode, f as DocsAgentFeedbackContext, g as DocsFeedbackValue, h as DocsFeedbackData, i as ApiReferenceConfig, it as ThemeToggleConfig, j as DocsSearchResult, k as DocsSearchEmbeddingsConfig, l as CodeBlockCopyData, m as DocsConfig, n as AgentFeedbackConfig, nt as SidebarTree, o as BreadcrumbConfig, ot as TypographyConfig, p as DocsAgentFeedbackData, q as PageFrontmatter, r as AlgoliaDocsSearchConfig, rt as SimpleDocsSearchConfig, s as ChangelogConfig, st as UIConfig, t as AIConfig, tt as SidebarPageNode, u as CopyMarkdownConfig, v as DocsMcpConfig, w as DocsSearchAdapterContext, x as DocsNav, y as DocsMcpToolsConfig, z as LlmsTxtConfig } from "./types-
|
|
1
|
+
import { $ as SidebarFolderNode, A as DocsSearchQuery, B as McpDocsSearchConfig, C as DocsSearchAdapter, D as DocsSearchConfig, E as DocsSearchChunkingConfig, F as FeedbackConfig, G as OrderingItem, H as OpenDocsConfig, I as FontStyle, J as PageOpenGraph, K as PageActionsConfig, L as GithubConfig, M as DocsSearchResultType, N as DocsSearchSourcePage, O as DocsSearchDocument, P as DocsTheme, Q as SidebarConfig, R as LastUpdatedConfig, S as DocsRelatedItem, T as DocsSearchAdapterFactory, U as OpenDocsProvider, V as OGConfig, W as OpenGraphImage, X as ResolvedDocsRelatedLink, Y as PageTwitter, Z as SidebarComponentProps, _ as DocsI18nConfig, a as ApiReferenceRenderer, at as TypesenseDocsSearchConfig, b as DocsMetadata, c as ChangelogFrontmatter, d as CustomDocsSearchConfig, et as SidebarNode, f as DocsAgentFeedbackContext, g as DocsFeedbackValue, h as DocsFeedbackData, i as ApiReferenceConfig, it as ThemeToggleConfig, j as DocsSearchResult, k as DocsSearchEmbeddingsConfig, l as CodeBlockCopyData, m as DocsConfig, n as AgentFeedbackConfig, nt as SidebarTree, o as BreadcrumbConfig, ot as TypographyConfig, p as DocsAgentFeedbackData, q as PageFrontmatter, r as AlgoliaDocsSearchConfig, rt as SimpleDocsSearchConfig, s as ChangelogConfig, st as UIConfig, t as AIConfig, tt as SidebarPageNode, u as CopyMarkdownConfig, v as DocsMcpConfig, w as DocsSearchAdapterContext, x as DocsNav, y as DocsMcpToolsConfig, z as LlmsTxtConfig } from "./types-nlEL5lLq.mjs";
|
|
2
2
|
import { DocsMcpPage, DocsMcpResolvedConfig } from "./mcp.mjs";
|
|
3
|
-
import { a as createSimpleSearchAdapter, c as resolveSearchRequestConfig, i as createMcpSearchAdapter, n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, r as createCustomSearchAdapter, s as performDocsSearch, t as buildDocsSearchDocuments } from "./search-
|
|
3
|
+
import { a as createSimpleSearchAdapter, c as resolveSearchRequestConfig, i as createMcpSearchAdapter, n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, r as createCustomSearchAdapter, s as performDocsSearch, t as buildDocsSearchDocuments } from "./search-cPHa_3jJ.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/define-docs.d.ts
|
|
6
6
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as resolveDocsI18n, c as createTheme, d as resolveChangelogConfig, f as defineDocs, i as resolveTitle, l as extendTheme, n as buildPageTwitter, o as resolveDocsLocale, r as resolveOGImage, s as resolveDocsPath, t as buildPageOpenGraph, u as deepMerge } from "./metadata-CdrtTSz-.mjs";
|
|
2
2
|
import { a as createSimpleSearchAdapter, c as resolveSearchRequestConfig, i as createMcpSearchAdapter, l as normalizeDocsRelated, n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, r as createCustomSearchAdapter, s as performDocsSearch, t as buildDocsSearchDocuments, u as renderDocsRelatedMarkdownLines } from "./search-8oEskRtz.mjs";
|
|
3
|
+
import { C as renderDocsMarkdownDocument, D as resolveDocsMarkdownRequest, E as resolveDocsLlmsTxtFormat, O as resolveDocsSkillFormat, S as normalizeDocsUrlPath, T as resolveDocsAgentMdxContent, _ as isDocsAgentDiscoveryRequest, a as DEFAULT_DOCS_API_ROUTE, b as isDocsSkillRequest, c as DEFAULT_LLMS_TXT_ROUTE, d as DEFAULT_MCP_ROUTE, f as DEFAULT_MCP_WELL_KNOWN_ROUTE, g as findDocsMarkdownPage, h as buildDocsAgentDiscoverySpec, i as DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, l as DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE, m as DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, n as DEFAULT_AGENT_SPEC_ROUTE, o as DEFAULT_LLMS_FULL_TXT_ROUTE, p as DEFAULT_SKILL_MD_ROUTE, r as DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, s as DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE, t as DEFAULT_AGENT_FEEDBACK_ROUTE, u as DEFAULT_MCP_PUBLIC_ROUTE, v as isDocsMcpRequest, w as renderDocsSkillDocument, x as normalizeDocsPathSegment, y as isDocsPublicGetRequest } from "./agent-CbAtuZAc.mjs";
|
|
3
4
|
|
|
4
5
|
export { DEFAULT_AGENT_FEEDBACK_ROUTE, DEFAULT_AGENT_SPEC_ROUTE, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, DEFAULT_DOCS_API_ROUTE, DEFAULT_LLMS_FULL_TXT_ROUTE, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE, DEFAULT_LLMS_TXT_ROUTE, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE, DEFAULT_MCP_PUBLIC_ROUTE, DEFAULT_MCP_ROUTE, DEFAULT_MCP_WELL_KNOWN_ROUTE, DEFAULT_SKILL_MD_ROUTE, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, buildDocsAgentDiscoverySpec, buildDocsSearchDocuments, buildPageOpenGraph, buildPageTwitter, createAlgoliaSearchAdapter, createCustomSearchAdapter, createMcpSearchAdapter, createSimpleSearchAdapter, createTheme, createTypesenseSearchAdapter, deepMerge, defineDocs, extendTheme, findDocsMarkdownPage, isDocsAgentDiscoveryRequest, isDocsMcpRequest, isDocsPublicGetRequest, isDocsSkillRequest, normalizeDocsPathSegment, normalizeDocsRelated, normalizeDocsUrlPath, performDocsSearch, renderDocsMarkdownDocument, renderDocsRelatedMarkdownLines, renderDocsSkillDocument, resolveChangelogConfig, resolveDocsAgentMdxContent, resolveDocsI18n, resolveDocsLlmsTxtFormat, resolveDocsLocale, resolveDocsMarkdownRequest, resolveDocsPath, resolveDocsSkillFormat, resolveOGImage, resolveSearchRequestConfig, resolveTitle };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as devInstallCommand, c as installCommand, d as writeFileSafe, i as detectPackageManagerFromLockfile, l as readFileSafe, n as detectGlobalCssFiles, o as exec, r as detectNextAppDir, s as fileExists, t as detectFramework, u as spawnAndWaitFor } from "./utils-
|
|
1
|
+
import { a as devInstallCommand, c as installCommand, d as writeFileSafe, i as detectPackageManagerFromLockfile, l as readFileSafe, n as detectGlobalCssFiles, o as exec, r as detectNextAppDir, s as fileExists, t as detectFramework, u as spawnAndWaitFor } from "./utils-DSMXVnEu.mjs";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import pc from "picocolors";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import "./api-reference-
|
|
1
|
+
import "./api-reference-y7cqtq4w.mjs";
|
|
2
2
|
import { createFilesystemDocsMcpSource, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
|
|
3
3
|
import "./server.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { c as readNavTitle, f as resolveDocsConfigPath, n as extractObjectLiteral, o as readBooleanProperty, p as resolveDocsContentDir, u as readStringProperty } from "./config-C7sUsMkm.mjs";
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
|
|
7
7
|
//#region src/cli/mcp.ts
|
package/dist/mcp.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as DocsSearchConfig, G as OrderingItem, N as DocsSearchSourcePage, v as DocsMcpConfig } from "./types-
|
|
1
|
+
import { D as DocsSearchConfig, G as OrderingItem, N as DocsSearchSourcePage, v as DocsMcpConfig } from "./types-nlEL5lLq.mjs";
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
|
|
4
4
|
//#region src/mcp.d.ts
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
//#region src/define-docs.ts
|
|
2
|
+
/**
|
|
3
|
+
* Define docs configuration. Validates and returns the config.
|
|
4
|
+
*/
|
|
5
|
+
function defineDocs(config) {
|
|
6
|
+
return {
|
|
7
|
+
entry: config.entry ?? "docs",
|
|
8
|
+
contentDir: config.contentDir,
|
|
9
|
+
i18n: config.i18n,
|
|
10
|
+
theme: config.theme,
|
|
11
|
+
nav: config.nav,
|
|
12
|
+
github: config.github,
|
|
13
|
+
themeToggle: config.themeToggle,
|
|
14
|
+
breadcrumb: config.breadcrumb,
|
|
15
|
+
sidebar: config.sidebar,
|
|
16
|
+
components: config.components,
|
|
17
|
+
onCopyClick: config.onCopyClick,
|
|
18
|
+
feedback: config.feedback,
|
|
19
|
+
search: config.search,
|
|
20
|
+
mcp: config.mcp,
|
|
21
|
+
icons: config.icons,
|
|
22
|
+
pageActions: config.pageActions,
|
|
23
|
+
lastUpdated: config.lastUpdated,
|
|
24
|
+
llmsTxt: config.llmsTxt,
|
|
25
|
+
ai: config.ai,
|
|
26
|
+
ordering: config.ordering,
|
|
27
|
+
metadata: config.metadata,
|
|
28
|
+
og: config.og,
|
|
29
|
+
changelog: config.changelog,
|
|
30
|
+
apiReference: config.apiReference,
|
|
31
|
+
agent: config.agent
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/changelog.ts
|
|
37
|
+
function normalizePathSegment(value, fallback) {
|
|
38
|
+
return (value ?? fallback).trim().replace(/^\/+|\/+$/g, "") || fallback;
|
|
39
|
+
}
|
|
40
|
+
function normalizeContentDir(value) {
|
|
41
|
+
const trimmed = value?.trim();
|
|
42
|
+
if (!trimmed) return "changelog";
|
|
43
|
+
return trimmed.replace(/\/+$/, "") || "changelog";
|
|
44
|
+
}
|
|
45
|
+
function resolveChangelogConfig(value) {
|
|
46
|
+
if (value === false || value === void 0) return {
|
|
47
|
+
enabled: false,
|
|
48
|
+
path: "changelog",
|
|
49
|
+
contentDir: "changelog",
|
|
50
|
+
title: "Changelog",
|
|
51
|
+
description: void 0,
|
|
52
|
+
search: true
|
|
53
|
+
};
|
|
54
|
+
if (value === true) return {
|
|
55
|
+
enabled: true,
|
|
56
|
+
path: "changelog",
|
|
57
|
+
contentDir: "changelog",
|
|
58
|
+
title: "Changelog",
|
|
59
|
+
description: void 0,
|
|
60
|
+
search: true
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
enabled: value.enabled !== false,
|
|
64
|
+
path: normalizePathSegment(value.path, "changelog"),
|
|
65
|
+
contentDir: normalizeContentDir(value.contentDir),
|
|
66
|
+
title: value.title?.trim() || "Changelog",
|
|
67
|
+
description: value.description?.trim() || void 0,
|
|
68
|
+
search: value.search !== false,
|
|
69
|
+
actionsComponent: value.actionsComponent
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/utils.ts
|
|
75
|
+
/**
|
|
76
|
+
* Deep merge utility for theme overrides.
|
|
77
|
+
* Merges objects recursively; later values override earlier ones.
|
|
78
|
+
*/
|
|
79
|
+
function deepMerge(target, ...sources) {
|
|
80
|
+
if (!sources.length) return target;
|
|
81
|
+
const source = sources.shift();
|
|
82
|
+
if (!source) return target;
|
|
83
|
+
const result = { ...target };
|
|
84
|
+
for (const key of Object.keys(source)) {
|
|
85
|
+
const sourceVal = source[key];
|
|
86
|
+
const targetVal = result[key];
|
|
87
|
+
if (sourceVal && typeof sourceVal === "object" && !Array.isArray(sourceVal) && targetVal && typeof targetVal === "object" && !Array.isArray(targetVal)) result[key] = deepMerge(targetVal, sourceVal);
|
|
88
|
+
else if (sourceVal !== void 0) result[key] = sourceVal;
|
|
89
|
+
}
|
|
90
|
+
if (sources.length) return deepMerge(result, ...sources);
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/create-theme.ts
|
|
96
|
+
/**
|
|
97
|
+
* Create a theme preset factory.
|
|
98
|
+
*
|
|
99
|
+
* Returns a function that accepts optional overrides and deep-merges them
|
|
100
|
+
* with the base theme defaults. This is the same pattern used by the
|
|
101
|
+
* built-in `fumadocs()`, `darksharp()`, and `pixelBorder()` presets.
|
|
102
|
+
*
|
|
103
|
+
* @param baseTheme - The default theme configuration
|
|
104
|
+
* @returns A factory function `(overrides?) => DocsTheme`
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* import { createTheme } from "@farming-labs/docs";
|
|
109
|
+
*
|
|
110
|
+
* export const myTheme = createTheme({
|
|
111
|
+
* name: "my-theme",
|
|
112
|
+
* ui: {
|
|
113
|
+
* colors: { primary: "#6366f1" },
|
|
114
|
+
* layout: { contentWidth: 800 },
|
|
115
|
+
* },
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
function createTheme(baseTheme) {
|
|
120
|
+
return function themeFactory(overrides = {}) {
|
|
121
|
+
const merged = deepMerge(baseTheme, overrides);
|
|
122
|
+
if (overrides.ui?.colors) merged._userColorOverrides = { ...overrides.ui.colors };
|
|
123
|
+
return merged;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Extend an existing theme preset with additional defaults.
|
|
128
|
+
*
|
|
129
|
+
* Useful when you want to build on top of an existing theme (e.g. fumadocs)
|
|
130
|
+
* rather than starting from scratch.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* import { extendTheme } from "@farming-labs/docs";
|
|
135
|
+
* import { fumadocs } from "@farming-labs/theme/default";
|
|
136
|
+
*
|
|
137
|
+
* // Start with fumadocs defaults, override some values
|
|
138
|
+
* export const myTheme = extendTheme(fumadocs(), {
|
|
139
|
+
* name: "my-custom-fumadocs",
|
|
140
|
+
* ui: { colors: { primary: "#22c55e" } },
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
function extendTheme(baseTheme, extensions) {
|
|
145
|
+
return deepMerge(baseTheme, extensions);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/i18n.ts
|
|
150
|
+
function normalizeSegment(value) {
|
|
151
|
+
return value.replace(/^\/+|\/+$/g, "");
|
|
152
|
+
}
|
|
153
|
+
function splitSegments(value) {
|
|
154
|
+
const cleaned = normalizeSegment(value);
|
|
155
|
+
return cleaned ? cleaned.split("/").filter(Boolean) : [];
|
|
156
|
+
}
|
|
157
|
+
function resolveDocsI18n(config) {
|
|
158
|
+
if (!config || !Array.isArray(config.locales)) return null;
|
|
159
|
+
const locales = Array.from(new Set(config.locales.map((l) => l.trim()).filter(Boolean)));
|
|
160
|
+
if (locales.length === 0) return null;
|
|
161
|
+
return {
|
|
162
|
+
locales,
|
|
163
|
+
defaultLocale: config.defaultLocale && locales.includes(config.defaultLocale) ? config.defaultLocale : locales[0]
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function resolveDocsLocale(searchParams, i18n) {
|
|
167
|
+
if (!i18n) return void 0;
|
|
168
|
+
const raw = searchParams.get("lang") ?? searchParams.get("locale");
|
|
169
|
+
if (!raw) return void 0;
|
|
170
|
+
if (i18n.locales.includes(raw)) return raw;
|
|
171
|
+
return i18n.defaultLocale;
|
|
172
|
+
}
|
|
173
|
+
function resolveDocsPath(pathname, entry) {
|
|
174
|
+
const entryBase = normalizeSegment(entry || "docs") || "docs";
|
|
175
|
+
const entryParts = splitSegments(entryBase);
|
|
176
|
+
const pathParts = splitSegments(pathname);
|
|
177
|
+
let rest = pathParts;
|
|
178
|
+
if (entryParts.length > 0) {
|
|
179
|
+
if (pathParts.slice(0, entryParts.length).join("/") === entryParts.join("/")) rest = pathParts.slice(entryParts.length);
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
slug: rest.join("/"),
|
|
183
|
+
entryPath: entryBase
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/metadata.ts
|
|
189
|
+
/**
|
|
190
|
+
* Resolve page title using metadata titleTemplate.
|
|
191
|
+
* %s is replaced with page title.
|
|
192
|
+
*/
|
|
193
|
+
function resolveTitle(pageTitle, metadata) {
|
|
194
|
+
return (metadata?.titleTemplate ?? "%s").replace("%s", pageTitle);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Resolve OG image URL for a page.
|
|
198
|
+
* Prefers page.openGraph.images[0], then page.ogImage, then config endpoint/default.
|
|
199
|
+
*/
|
|
200
|
+
function resolveOGImage(page, ogConfig, baseUrl) {
|
|
201
|
+
if (page.openGraph?.images?.length) return resolveImageUrl(page.openGraph.images[0].url, baseUrl);
|
|
202
|
+
if (!ogConfig?.enabled) return void 0;
|
|
203
|
+
if (page.ogImage) return resolveImageUrl(page.ogImage, baseUrl);
|
|
204
|
+
if (ogConfig.type === "dynamic" && ogConfig.endpoint) return `${baseUrl ?? ""}${ogConfig.endpoint}`;
|
|
205
|
+
return ogConfig.defaultImage;
|
|
206
|
+
}
|
|
207
|
+
function resolveImageUrl(url, baseUrl) {
|
|
208
|
+
if (url.startsWith("/") || url.startsWith("http")) return url;
|
|
209
|
+
const base = baseUrl ?? "";
|
|
210
|
+
return `${base}${base.length > 0 && !base.endsWith("/") ? "/" : ""}${url}`;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Build the Open Graph metadata object for a page.
|
|
214
|
+
* When the page has openGraph in frontmatter, uses it (with title/description filled from page if omitted).
|
|
215
|
+
* Otherwise uses ogImage or config (dynamic endpoint / defaultImage).
|
|
216
|
+
*/
|
|
217
|
+
function buildPageOpenGraph(page, ogConfig, baseUrl) {
|
|
218
|
+
if (page.openGraph) {
|
|
219
|
+
const images = page.openGraph.images?.length ? page.openGraph.images.map((img) => ({
|
|
220
|
+
url: resolveImageUrl(img.url, baseUrl),
|
|
221
|
+
width: img.width ?? 1200,
|
|
222
|
+
height: img.height ?? 630
|
|
223
|
+
})) : void 0;
|
|
224
|
+
return {
|
|
225
|
+
title: page.openGraph.title ?? page.title,
|
|
226
|
+
description: page.openGraph.description ?? page.description,
|
|
227
|
+
...images && { images }
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const url = resolveOGImage(page, ogConfig, baseUrl);
|
|
231
|
+
if (!url) return void 0;
|
|
232
|
+
return {
|
|
233
|
+
title: page.title,
|
|
234
|
+
...page.description && { description: page.description },
|
|
235
|
+
images: [{
|
|
236
|
+
url,
|
|
237
|
+
width: 1200,
|
|
238
|
+
height: 630
|
|
239
|
+
}]
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Build the Twitter card metadata object for a page.
|
|
244
|
+
* When the page has twitter in frontmatter, uses it.
|
|
245
|
+
* Otherwise builds from ogImage or config (dynamic endpoint).
|
|
246
|
+
*/
|
|
247
|
+
function buildPageTwitter(page, ogConfig, baseUrl) {
|
|
248
|
+
if (page.twitter) {
|
|
249
|
+
const images = page.twitter.images?.length ? page.twitter.images.map((url) => resolveImageUrl(url, baseUrl)) : void 0;
|
|
250
|
+
return {
|
|
251
|
+
...page.twitter.card && { card: page.twitter.card },
|
|
252
|
+
...page.twitter.title !== void 0 && { title: page.twitter.title },
|
|
253
|
+
...page.twitter.description !== void 0 && { description: page.twitter.description },
|
|
254
|
+
...images && { images }
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
const url = resolveOGImage(page, ogConfig, baseUrl);
|
|
258
|
+
if (!url) return void 0;
|
|
259
|
+
return {
|
|
260
|
+
card: "summary_large_image",
|
|
261
|
+
title: page.title,
|
|
262
|
+
...page.description && { description: page.description },
|
|
263
|
+
images: [url]
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
//#endregion
|
|
268
|
+
export { resolveDocsI18n as a, createTheme as c, resolveChangelogConfig as d, defineDocs as f, resolveTitle as i, extendTheme as l, buildPageTwitter as n, resolveDocsLocale as o, resolveOGImage as r, resolveDocsPath as s, buildPageOpenGraph as t, deepMerge as u };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, t as buildDocsSearchDocuments } from "./search-8oEskRtz.mjs";
|
|
2
|
-
import "./api-reference-
|
|
2
|
+
import "./api-reference-y7cqtq4w.mjs";
|
|
3
3
|
import { createFilesystemDocsMcpSource } from "./mcp.mjs";
|
|
4
4
|
import "./server.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { a as loadProjectEnv, d as readTopLevelStringProperty, f as resolveDocsConfigPath, p as resolveDocsContentDir } from "./config-C7sUsMkm.mjs";
|
|
6
6
|
import { readFileSync } from "node:fs";
|
|
7
7
|
import pc from "picocolors";
|
|
8
8
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as McpDocsSearchConfig, C as DocsSearchAdapter, D as DocsSearchConfig, E as DocsSearchChunkingConfig, N as DocsSearchSourcePage, O as DocsSearchDocument, T as DocsSearchAdapterFactory, at as TypesenseDocsSearchConfig, d as CustomDocsSearchConfig, j as DocsSearchResult, r as AlgoliaDocsSearchConfig } from "./types-
|
|
1
|
+
import { B as McpDocsSearchConfig, C as DocsSearchAdapter, D as DocsSearchConfig, E as DocsSearchChunkingConfig, N as DocsSearchSourcePage, O as DocsSearchDocument, T as DocsSearchAdapterFactory, at as TypesenseDocsSearchConfig, d as CustomDocsSearchConfig, j as DocsSearchResult, r as AlgoliaDocsSearchConfig } from "./types-nlEL5lLq.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/search.d.ts
|
|
4
4
|
declare function buildDocsSearchDocuments(pages: DocsSearchSourcePage[], chunking?: DocsSearchChunkingConfig): DocsSearchDocument[];
|
package/dist/server.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { A as DocsSearchQuery, B as McpDocsSearchConfig, C as DocsSearchAdapter, D as DocsSearchConfig, N as DocsSearchSourcePage, O as DocsSearchDocument, T as DocsSearchAdapterFactory, a as ApiReferenceRenderer, j as DocsSearchResult, m as DocsConfig, w as DocsSearchAdapterContext } from "./types-
|
|
1
|
+
import { A as DocsSearchQuery, B as McpDocsSearchConfig, C as DocsSearchAdapter, D as DocsSearchConfig, N as DocsSearchSourcePage, O as DocsSearchDocument, T as DocsSearchAdapterFactory, a as ApiReferenceRenderer, j as DocsSearchResult, m as DocsConfig, w as DocsSearchAdapterContext } from "./types-nlEL5lLq.mjs";
|
|
2
2
|
import { DocsMcpHttpHandlers, DocsMcpNavigationNode, DocsMcpNavigationTree, DocsMcpPage, DocsMcpResolvedConfig, DocsMcpSource, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
|
|
3
|
-
import { a as createSimpleSearchAdapter, c as resolveSearchRequestConfig, i as createMcpSearchAdapter, n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, r as createCustomSearchAdapter, s as performDocsSearch, t as buildDocsSearchDocuments } from "./search-
|
|
3
|
+
import { a as createSimpleSearchAdapter, c as resolveSearchRequestConfig, i as createMcpSearchAdapter, n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, r as createCustomSearchAdapter, s as performDocsSearch, t as buildDocsSearchDocuments } from "./search-cPHa_3jJ.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/api-reference.d.ts
|
|
6
6
|
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD";
|
package/dist/server.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as createSimpleSearchAdapter, c as resolveSearchRequestConfig, i as createMcpSearchAdapter, n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, r as createCustomSearchAdapter, s as performDocsSearch, t as buildDocsSearchDocuments } from "./search-8oEskRtz.mjs";
|
|
2
|
-
import { a as buildApiReferencePageTitle, c as resolveApiReferenceRenderer, i as buildApiReferenceOpenApiDocumentAsync, n as buildApiReferenceHtmlDocumentAsync, o as buildApiReferenceScalarCss, r as buildApiReferenceOpenApiDocument, s as resolveApiReferenceConfig, t as buildApiReferenceHtmlDocument } from "./api-reference-
|
|
2
|
+
import { a as buildApiReferencePageTitle, c as resolveApiReferenceRenderer, i as buildApiReferenceOpenApiDocumentAsync, n as buildApiReferenceHtmlDocumentAsync, o as buildApiReferenceScalarCss, r as buildApiReferenceOpenApiDocument, s as resolveApiReferenceConfig, t as buildApiReferenceHtmlDocument } from "./api-reference-y7cqtq4w.mjs";
|
|
3
3
|
import { createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
|
|
4
4
|
|
|
5
5
|
export { buildApiReferenceHtmlDocument, buildApiReferenceHtmlDocumentAsync, buildApiReferenceOpenApiDocument, buildApiReferenceOpenApiDocumentAsync, buildApiReferencePageTitle, buildApiReferenceScalarCss, buildDocsSearchDocuments, createAlgoliaSearchAdapter, createCustomSearchAdapter, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, createMcpSearchAdapter, createSimpleSearchAdapter, createTypesenseSearchAdapter, normalizeDocsMcpRoute, performDocsSearch, resolveApiReferenceConfig, resolveApiReferenceRenderer, resolveDocsMcpConfig, resolveSearchRequestConfig, runDocsMcpStdio };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as installCommand, i as detectPackageManagerFromLockfile, o as exec, s as fileExists, t as detectFramework } from "./utils-
|
|
1
|
+
import { c as installCommand, i as detectPackageManagerFromLockfile, o as exec, s as fileExists, t as detectFramework } from "./utils-DSMXVnEu.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import pc from "picocolors";
|
|
4
4
|
import * as p from "@clack/prompts";
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|