@farming-labs/docs 0.2.60 → 0.2.62

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.
Files changed (51) hide show
  1. package/README.md +1 -1
  2. package/package.json +11 -1
  3. package/dist/agent-BFqyqEnC.mjs +0 -4547
  4. package/dist/agent-DlxriaTs.mjs +0 -624
  5. package/dist/agent-evals-kJs2Y9xR.mjs +0 -2144
  6. package/dist/agent-export-BgUaiW8f.mjs +0 -869
  7. package/dist/agent-scope-CCaIY1aK.mjs +0 -283
  8. package/dist/agents-Djh-HXih.mjs +0 -219
  9. package/dist/analytics-Bx44lg6d.mjs +0 -177
  10. package/dist/cli/index.d.mts +0 -15
  11. package/dist/cli/index.mjs +0 -452
  12. package/dist/client/react.d.mts +0 -45
  13. package/dist/client/react.mjs +0 -223
  14. package/dist/cloud-BH_sHX64.mjs +0 -1615
  15. package/dist/cloud-analytics-CSyFE6SS.mjs +0 -132
  16. package/dist/cloud-ask-ai-B2WnG4fF.d.mts +0 -23
  17. package/dist/cloud-ask-ai-hnJfj8-X.mjs +0 -382
  18. package/dist/code-blocks-qe0T8-xe.mjs +0 -871
  19. package/dist/codeblocks-Bq67u32v.mjs +0 -250
  20. package/dist/config-DASewQ0x.mjs +0 -363
  21. package/dist/dev-DgY5xGl9.mjs +0 -1333
  22. package/dist/docs-cloud-server.d.mts +0 -70
  23. package/dist/docs-cloud-server.mjs +0 -310
  24. package/dist/doctor-CO1VMcF_.mjs +0 -1906
  25. package/dist/downgrade-BZs86NVr.mjs +0 -184
  26. package/dist/errors-CVqZ3kOO.mjs +0 -20
  27. package/dist/golden-evaluations-BN9u2wxw.mjs +0 -1483
  28. package/dist/i18n-CAlj1ADU.mjs +0 -40
  29. package/dist/index.d.mts +0 -1099
  30. package/dist/index.mjs +0 -9
  31. package/dist/init-Bd_k06bR.mjs +0 -1233
  32. package/dist/mcp-B_yXL5G5.mjs +0 -137
  33. package/dist/mcp.d.mts +0 -287
  34. package/dist/mcp.mjs +0 -4135
  35. package/dist/metadata-BDuewuzq.mjs +0 -237
  36. package/dist/package-version-qik_4J6C.mjs +0 -128
  37. package/dist/reading-time-BkEft6SD.mjs +0 -741
  38. package/dist/review-NC-sOdXn.mjs +0 -665
  39. package/dist/robots-DskPvGPw.mjs +0 -178
  40. package/dist/robots-ltltiLJF.mjs +0 -197
  41. package/dist/search-C1JitPwi.d.mts +0 -397
  42. package/dist/search-D57JXQLj.mjs +0 -1758
  43. package/dist/search-o4Ud6OXv.mjs +0 -102
  44. package/dist/server.d.mts +0 -341
  45. package/dist/server.mjs +0 -11
  46. package/dist/sitemap-Cq-Yj_iA.mjs +0 -247
  47. package/dist/sitemap-server-C1ibVKOy.mjs +0 -1137
  48. package/dist/templates-DNw15P-x.mjs +0 -2373
  49. package/dist/types-XHABMh_f.d.mts +0 -3248
  50. package/dist/upgrade-BCJTCW3O.mjs +0 -56
  51. package/dist/utils-6UCLxv4B.mjs +0 -225
@@ -1,869 +0,0 @@
1
- import { Lt as renderDocsSitemapMarkdown, M as buildDocsAgentDiscoverySpec, Pt as buildDocsSitemapManifest, Rt as renderDocsSitemapXml, St as toDocsMarkdownUrl, T as DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, a as DEFAULT_AGENT_MD_ROUTE, at as renderDocsMarkdownDocument, c as DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, en as buildDocsAgentSkillsIndex, g as DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE, h as DEFAULT_LLMS_FULL_TXT_ROUTE, it as renderDocsLlmsTxt, l as DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, lt as resolveDocsAgentFeedbackConfig, n as DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE, o as DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE, on as resolveDocsPublishedAgentSkill, qt as DEFAULT_AGENT_SKILLS_INDEX_ROUTE, rt as renderDocsAgentsDocument, st as renderDocsSkillDocument, t as DEFAULT_AGENTS_MD_ROUTE, v as DEFAULT_LLMS_TXT_ROUTE, w as DEFAULT_SKILL_MD_ROUTE, y as DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE, zt as resolveDocsSitemapConfig } from "./agent-BFqyqEnC.mjs";
2
- import "./search-D57JXQLj.mjs";
3
- import { t as resolveDocsI18n } from "./i18n-CAlj1ADU.mjs";
4
- import { c as renderDocsRobotsGeneratedBlock, f as upsertDocsRobotsGeneratedBlock, i as DOCS_ROBOTS_GENERATED_BLOCK_START, r as DOCS_ROBOTS_GENERATED_BLOCK_END, u as resolveDocsRobotsConfig } from "./robots-ltltiLJF.mjs";
5
- import "./sitemap-server-C1ibVKOy.mjs";
6
- import "./agent-evals-kJs2Y9xR.mjs";
7
- import { createFilesystemDocsMcpSource, resolveDocsMcpConfig } from "./mcp.mjs";
8
- import "./code-blocks-qe0T8-xe.mjs";
9
- import "./server.mjs";
10
- import { d as readStringProperty, f as readTopLevelBooleanProperty, h as resolveDocsContentDir, i as loadDocsConfigModule, l as readNavTitle, m as resolveDocsConfigPath, p as readTopLevelStringProperty, r as extractTopLevelConfigObject, s as readBooleanProperty, t as extractNestedObjectLiteral } from "./config-DASewQ0x.mjs";
11
- import { t as detectFramework } from "./utils-6UCLxv4B.mjs";
12
- import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
13
- import path from "node:path";
14
- import { execFileSync } from "node:child_process";
15
- import pc from "picocolors";
16
- import { createHash, randomUUID } from "node:crypto";
17
-
18
- //#region src/cli/agent-export.ts
19
- const AGENT_EXPORT_AGENTS_MARKER = "<!-- Generated by @farming-labs/docs agent export. -->";
20
- const AGENTS_GENERATE_MARKER = "<!-- Generated by @farming-labs/docs agents generate. -->";
21
- const AGENT_BUNDLE_MANIFEST_ROUTE = "/.well-known/agent-bundle.json";
22
- const AGENT_BUNDLE_INTERNAL_MANIFEST = ".farming-labs/agent-bundle-manifest.json";
23
- const SKILL_CANONICAL_ROUTE = "/skills/docs/SKILL.md";
24
- function parseInlineFlag(arg) {
25
- const [rawKey, value] = arg.slice(2).split("=", 2);
26
- return {
27
- key: rawKey.trim(),
28
- value
29
- };
30
- }
31
- function parseAgentExportArgs(argv) {
32
- const parsed = {};
33
- for (let index = 0; index < argv.length; index += 1) {
34
- const arg = argv[index];
35
- if (arg === "--help" || arg === "-h") {
36
- parsed.help = true;
37
- continue;
38
- }
39
- if (arg === "--public") {
40
- parsed.public = true;
41
- continue;
42
- }
43
- if (arg === "--check") {
44
- parsed.check = 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 agent export flag: ${arg}.`);
61
- }
62
- return parsed;
63
- }
64
- function normalizePathSegment(value) {
65
- return value.replace(/^\/+|\/+$/g, "");
66
- }
67
- function normalizeContent(content) {
68
- return `${content.trimEnd()}\n`;
69
- }
70
- function publicFilePath(publicDir, route) {
71
- const resolved = resolveContainedPath(publicDir, route.replace(/^\/+/, ""));
72
- if (!resolved) throw new Error(`Agent Bundle route must stay inside the public directory: ${route}`);
73
- return resolved;
74
- }
75
- function publicRelativePath(publicDir, filePath) {
76
- return path.relative(publicDir, filePath).replace(/\\/g, "/");
77
- }
78
- function resolveContainedPath(baseDir, relativePath) {
79
- const base = path.resolve(baseDir);
80
- const resolved = path.resolve(base, relativePath);
81
- if (!isPathWithin(base, resolved)) return void 0;
82
- const realBase = resolveThroughNearestExistingAncestor(base);
83
- const realResolved = resolveThroughNearestExistingAncestor(resolved);
84
- if (!realBase || !realResolved || !isPathWithin(realBase, realResolved)) return void 0;
85
- return resolved;
86
- }
87
- function isPathWithin(baseDir, candidatePath) {
88
- const relative = path.relative(baseDir, candidatePath);
89
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
90
- }
91
- /**
92
- * Resolve the existing portion of a path so a symlinked ancestor cannot move a future write or
93
- * delete outside its declared root. Missing suffixes are appended to the nearest real ancestor.
94
- */
95
- function resolveThroughNearestExistingAncestor(absolutePath) {
96
- let cursor = path.resolve(absolutePath);
97
- const missingSegments = [];
98
- while (true) {
99
- let exists = false;
100
- try {
101
- lstatSync(cursor);
102
- exists = true;
103
- } catch (error) {
104
- const code = error.code;
105
- if (code !== "ENOENT" && code !== "ENOTDIR") return void 0;
106
- }
107
- if (exists) try {
108
- return path.resolve(realpathSync(cursor), ...missingSegments.reverse());
109
- } catch {
110
- return;
111
- }
112
- const parent = path.dirname(cursor);
113
- if (parent === cursor) return void 0;
114
- missingSegments.push(path.basename(cursor));
115
- cursor = parent;
116
- }
117
- }
118
- function sha256(content) {
119
- return createHash("sha256").update(content).digest("hex");
120
- }
121
- function byteLength(content) {
122
- return Buffer.byteLength(content, "utf-8");
123
- }
124
- function readExisting(filePath) {
125
- return existsSync(filePath) ? readFileSync(filePath, "utf-8") : void 0;
126
- }
127
- function atomicWriteFile(filePath, content) {
128
- mkdirSync(path.dirname(filePath), { recursive: true });
129
- const temporaryPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
130
- try {
131
- writeFileSync(temporaryPath, content, "utf-8");
132
- renameSync(temporaryPath, filePath);
133
- } finally {
134
- if (existsSync(temporaryPath)) rmSync(temporaryPath, { force: true });
135
- }
136
- }
137
- function readStaticLlmsConfig(content) {
138
- const enabled = readTopLevelBooleanProperty(content, "llmsTxt");
139
- if (enabled !== void 0) return enabled;
140
- const block = extractNestedObjectLiteral(content, ["llmsTxt"]);
141
- if (!block) return void 0;
142
- const maxCharsBlock = extractNestedObjectLiteral(content, ["llmsTxt", "maxChars"]);
143
- return {
144
- enabled: readBooleanProperty(block, "enabled") ?? true,
145
- baseUrl: readStringProperty(block, "baseUrl"),
146
- siteTitle: readStringProperty(block, "siteTitle"),
147
- siteDescription: readStringProperty(block, "siteDescription"),
148
- maxChars: maxCharsBlock ? {
149
- mode: readStringProperty(maxCharsBlock, "mode"),
150
- chars: readNumericProperty(maxCharsBlock, "chars")
151
- } : void 0,
152
- sections: readStaticLlmsSections(block)
153
- };
154
- }
155
- function readNumericProperty(content, key) {
156
- const match = content.match(new RegExp(`\\b${key}\\b\\s*:\\s*(-?\\d[\\d_]*(?:\\.\\d+)?)`));
157
- if (!match) return void 0;
158
- const value = Number(match[1].replace(/_/g, ""));
159
- return Number.isFinite(value) ? value : void 0;
160
- }
161
- function findBalancedDelimiterEnd(content, start, open, close) {
162
- let depth = 0;
163
- let quote = null;
164
- let escaped = false;
165
- for (let index = start; index < content.length; index += 1) {
166
- const char = content[index];
167
- if (quote) {
168
- if (escaped) escaped = false;
169
- else if (char === "\\") escaped = true;
170
- else if (char === quote) quote = null;
171
- continue;
172
- }
173
- if (char === "\"" || char === "'" || char === "`") {
174
- quote = char;
175
- continue;
176
- }
177
- if (char === open) depth += 1;
178
- if (char !== close) continue;
179
- depth -= 1;
180
- if (depth === 0) return index;
181
- }
182
- return -1;
183
- }
184
- function extractArrayProperty(content, key) {
185
- const keyIndex = content.search(new RegExp(`\\b${key}\\b\\s*:\\s*\\[`));
186
- if (keyIndex === -1) return void 0;
187
- const start = content.indexOf("[", keyIndex);
188
- if (start === -1) return void 0;
189
- const end = findBalancedDelimiterEnd(content, start, "[", "]");
190
- return end === -1 ? void 0 : content.slice(start + 1, end);
191
- }
192
- function readStaticLlmsSections(content) {
193
- const sections = extractArrayProperty(content, "sections");
194
- if (!sections) return void 0;
195
- const result = [];
196
- for (let index = 0; index < sections.length; index += 1) {
197
- if (sections[index] !== "{") continue;
198
- const end = findBalancedDelimiterEnd(sections, index, "{", "}");
199
- if (end === -1) break;
200
- const block = sections.slice(index + 1, end);
201
- const title = readStringProperty(block, "title");
202
- const match = readStringProperty(block, "match") ?? readStringArrayProperty(block, "match");
203
- if (title && (typeof match === "string" || match.length > 0)) {
204
- const maxCharsBlock = extractNestedObjectLiteral(block, ["maxChars"]);
205
- result.push({
206
- title,
207
- description: readStringProperty(block, "description"),
208
- match,
209
- maxChars: maxCharsBlock ? {
210
- mode: readStringProperty(maxCharsBlock, "mode"),
211
- chars: readNumericProperty(maxCharsBlock, "chars")
212
- } : void 0
213
- });
214
- }
215
- index = end;
216
- }
217
- return result.length > 0 ? result : void 0;
218
- }
219
- function readStaticSitemapConfig(content) {
220
- const enabled = readTopLevelBooleanProperty(content, "sitemap");
221
- if (enabled !== void 0) return enabled;
222
- const block = extractNestedObjectLiteral(content, ["sitemap"]);
223
- if (!block) return void 0;
224
- const xmlBoolean = readTopLevelBooleanProperty(block, "xml");
225
- const xmlBlock = extractNestedObjectLiteral(content, ["sitemap", "xml"]);
226
- const markdownBoolean = readTopLevelBooleanProperty(block, "markdown");
227
- const markdownBlock = extractNestedObjectLiteral(content, ["sitemap", "markdown"]);
228
- return {
229
- enabled: readBooleanProperty(block, "enabled") ?? true,
230
- routePrefix: readStringProperty(block, "routePrefix"),
231
- baseUrl: readStringProperty(block, "baseUrl"),
232
- manifestPath: readStringProperty(block, "manifestPath"),
233
- xml: xmlBoolean ?? (xmlBlock ? {
234
- enabled: readBooleanProperty(xmlBlock, "enabled"),
235
- includeLastmod: readBooleanProperty(xmlBlock, "includeLastmod")
236
- } : void 0),
237
- markdown: markdownBoolean ?? (markdownBlock ? {
238
- enabled: readBooleanProperty(markdownBlock, "enabled"),
239
- includeDescriptions: readBooleanProperty(markdownBlock, "includeDescriptions"),
240
- includeLastmod: readBooleanProperty(markdownBlock, "includeLastmod"),
241
- linkTarget: readStringProperty(markdownBlock, "linkTarget")
242
- } : void 0)
243
- };
244
- }
245
- function readStaticRobotsConfig(content) {
246
- const enabled = readTopLevelBooleanProperty(content, "robots");
247
- if (enabled !== void 0) return enabled;
248
- const block = extractNestedObjectLiteral(content, ["robots"]);
249
- if (!block) return void 0;
250
- const ai = readStringProperty(block, "ai");
251
- return {
252
- enabled: readBooleanProperty(block, "enabled") ?? true,
253
- baseUrl: readStringProperty(block, "baseUrl"),
254
- ai: ai === "allow" || ai === "disallow" ? ai : readBooleanProperty(block, "ai")
255
- };
256
- }
257
- function readStringArrayProperty(content, key) {
258
- const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
259
- const match = content.match(new RegExp(`\\b${escaped}\\b\\s*:\\s*\\[([\\s\\S]*?)\\]`));
260
- if (!match) return [];
261
- return [...match[1].matchAll(/["']([^"']+)["']/g)].map((value) => value[1]);
262
- }
263
- function readStaticI18nConfig(content) {
264
- const block = extractNestedObjectLiteral(content, ["i18n"]);
265
- if (!block) return void 0;
266
- const locales = readStringArrayProperty(block, "locales");
267
- if (locales.length === 0) return void 0;
268
- return {
269
- locales,
270
- defaultLocale: readStringProperty(block, "defaultLocale")
271
- };
272
- }
273
- function readStaticMetadataDescription(content) {
274
- const block = extractNestedObjectLiteral(content, ["metadata"]);
275
- return block ? readStringProperty(block, "description") : void 0;
276
- }
277
- function readStaticDocsPath(content) {
278
- const configured = readTopLevelStringProperty(content, "docsPath");
279
- if (configured !== void 0) return configured;
280
- const root = extractTopLevelConfigObject(content) ?? content;
281
- return /\bdocsPath\b\s*:\s*(["'])\1/.test(root) ? "" : void 0;
282
- }
283
- function buildPageUrl(routeEntry, slug, locale) {
284
- const parts = [
285
- routeEntry,
286
- locale,
287
- slug
288
- ].flatMap((value) => value ? [normalizePathSegment(value)] : []);
289
- return parts.length > 0 ? `/${parts.join("/")}` : "/";
290
- }
291
- function staticMarkdownRoute(page, sourceEntry, routeEntry) {
292
- if (!routeEntry && !page.slug) return `/${sourceEntry || "docs"}.md`;
293
- return toDocsMarkdownUrl(page.url);
294
- }
295
- async function loadPages(options) {
296
- const localeInputs = options.i18n ? options.i18n.locales.map((locale) => ({
297
- locale,
298
- directory: path.join(options.contentDir, locale)
299
- })) : [{
300
- locale: void 0,
301
- directory: options.contentDir
302
- }];
303
- const pages = [];
304
- for (const input of localeInputs) {
305
- const source = createFilesystemDocsMcpSource({
306
- rootDir: options.rootDir,
307
- entry: options.routeEntry || "docs",
308
- contentDir: input.directory,
309
- siteTitle: options.siteTitle,
310
- ordering: options.ordering
311
- });
312
- const scanned = await Promise.resolve(source.getPages());
313
- const localeRoute = input.locale && input.locale !== options.i18n?.defaultLocale ? input.locale : void 0;
314
- for (const page of scanned) pages.push({
315
- locale: input.locale,
316
- page: {
317
- ...page,
318
- url: buildPageUrl(options.routeEntry, page.slug, localeRoute)
319
- }
320
- });
321
- }
322
- return pages;
323
- }
324
- function formatDateOnly(value) {
325
- const parsed = new Date(value);
326
- if (Number.isNaN(parsed.getTime())) return void 0;
327
- return parsed.toISOString().slice(0, 10);
328
- }
329
- function pageGitLastmod(rootDir, page) {
330
- if (page.sourcePath) try {
331
- const lastmod = formatDateOnly(execFileSync("git", [
332
- "log",
333
- "-1",
334
- "--format=%cI",
335
- "--",
336
- page.sourcePath
337
- ], {
338
- cwd: rootDir,
339
- encoding: "utf-8",
340
- stdio: [
341
- "ignore",
342
- "pipe",
343
- "ignore"
344
- ]
345
- }).trim());
346
- if (lastmod) return lastmod;
347
- } catch {}
348
- }
349
- function deterministicSitemapManifest(options) {
350
- const manifest = buildDocsSitemapManifest({
351
- pages: options.pages,
352
- entry: options.entry,
353
- siteTitle: options.siteTitle,
354
- baseUrl: options.baseUrl,
355
- generatedAt: "1970-01-01T00:00:00.000Z",
356
- resolveLastmod(page) {
357
- const lastmod = formatDateOnly(page.lastModified ?? "");
358
- return lastmod ? {
359
- lastmod,
360
- lastmodSource: "git"
361
- } : void 0;
362
- }
363
- });
364
- manifest.generatedAt = `${manifest.pages.reduce((current, page) => {
365
- if (!page.lastmod) return current;
366
- return !current || page.lastmod > current ? page.lastmod : current;
367
- }, void 0) ?? "1970-01-01"}T00:00:00.000Z`;
368
- return manifest;
369
- }
370
- function isManagedAgentsContent(content) {
371
- return content.includes(AGENT_EXPORT_AGENTS_MARKER) || content.includes(AGENTS_GENERATE_MARKER);
372
- }
373
- function findPublicAgentsSource(publicDir) {
374
- for (const route of [
375
- DEFAULT_AGENTS_MD_ROUTE,
376
- DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE,
377
- DEFAULT_AGENT_MD_ROUTE,
378
- DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE
379
- ]) {
380
- const content = readExisting(publicFilePath(publicDir, route));
381
- if (content !== void 0 && !isManagedAgentsContent(content)) return normalizeContent(content);
382
- }
383
- }
384
- function addOutput(outputs, publicDir, route, kind, mediaType, content, managed = true) {
385
- const absolutePath = publicFilePath(publicDir, route);
386
- if (absolutePath === publicFilePath(publicDir, AGENT_BUNDLE_MANIFEST_ROUTE)) throw new Error(`Agent Bundle output collision at ${route} (reserved bundle manifest). Change the conflicting docs slug or configured route.`);
387
- const collision = outputs.find((output) => output.absolutePath === absolutePath);
388
- if (collision) throw new Error(`Agent Bundle output collision at ${route} (${collision.kind} and ${kind}). Change the conflicting docs slug or configured route.`);
389
- outputs.push({
390
- absolutePath,
391
- publicPath: publicRelativePath(publicDir, absolutePath),
392
- route,
393
- kind,
394
- mediaType,
395
- content: normalizeContent(content),
396
- managed
397
- });
398
- }
399
- function assertOutputPathsDoNotCollide(options) {
400
- const claimed = new Map([[options.publicManifestPath, "public Agent Bundle manifest"], [options.internalManifestPath, "internal Agent Bundle manifest"]]);
401
- for (const output of options.outputs) {
402
- const owner = claimed.get(output.absolutePath);
403
- if (owner) throw new Error(`Agent Bundle output collision at ${output.route} (${owner} and ${output.kind}). Change the conflicting docs slug or configured route.`);
404
- claimed.set(output.absolutePath, `${output.kind} output`);
405
- }
406
- for (const output of options.internalOutputs) {
407
- const owner = claimed.get(output.absolutePath);
408
- if (owner) throw new Error(`Agent Bundle output collision at ${output.path} (${owner} and internal ${output.kind}). Change the conflicting manifest path.`);
409
- claimed.set(output.absolutePath, `internal ${output.kind} output`);
410
- }
411
- }
412
- function resolveUserOwnedAgentsOutputs(outputs) {
413
- return outputs.map((output) => {
414
- if (output.kind !== "agents") return output;
415
- const current = readExisting(output.absolutePath);
416
- if (current === void 0 || isManagedAgentsContent(current)) return output;
417
- return {
418
- ...output,
419
- content: normalizeContent(current),
420
- managed: false
421
- };
422
- });
423
- }
424
- function resolveUserOwnedOverrides(outputs, previous) {
425
- const preserveKinds = new Set([
426
- "page",
427
- "llms",
428
- "discovery",
429
- "skill"
430
- ]);
431
- const previousByPath = new Map(previous?.files.map((file) => [file.path, file]) ?? []);
432
- return outputs.map((output) => {
433
- if (!preserveKinds.has(output.kind)) return output;
434
- const current = readExisting(output.absolutePath);
435
- if (current === void 0 || current === output.content) return output;
436
- const previousFile = previousByPath.get(output.publicPath);
437
- if (previousFile?.managed && sha256(current) === previousFile.sha256) return output;
438
- return {
439
- ...output,
440
- content: normalizeContent(current),
441
- managed: false
442
- };
443
- });
444
- }
445
- function resolveRobotsOutput(publicDir, entry, sitemap, robots) {
446
- const route = "/robots.txt";
447
- const absolutePath = publicFilePath(publicDir, route);
448
- const existing = readExisting(absolutePath);
449
- const generatedBlock = renderDocsRobotsGeneratedBlock({
450
- entry,
451
- apiCatalog: false,
452
- sitemap,
453
- baseUrl: robots.baseUrl,
454
- robots
455
- });
456
- const hasManagedBlock = existing?.includes(DOCS_ROBOTS_GENERATED_BLOCK_START) === true && existing.includes(DOCS_ROBOTS_GENERATED_BLOCK_END);
457
- if (existing !== void 0 && !hasManagedBlock) return {
458
- absolutePath,
459
- publicPath: publicRelativePath(publicDir, absolutePath),
460
- route,
461
- kind: "robots",
462
- mediaType: "text/plain",
463
- content: normalizeContent(existing),
464
- managed: false
465
- };
466
- return {
467
- absolutePath,
468
- publicPath: publicRelativePath(publicDir, absolutePath),
469
- route,
470
- kind: "robots",
471
- mediaType: "text/plain",
472
- content: normalizeContent(existing && hasManagedBlock ? upsertDocsRobotsGeneratedBlock(existing, generatedBlock) : generatedBlock),
473
- managed: true
474
- };
475
- }
476
- function toManifestFile(output) {
477
- return {
478
- path: output.publicPath,
479
- route: output.route,
480
- kind: output.kind,
481
- mediaType: output.mediaType,
482
- bytes: byteLength(output.content),
483
- sha256: sha256(output.content),
484
- managed: output.managed
485
- };
486
- }
487
- function buildAgentBundleManifest(options) {
488
- const files = [...options.outputs.map(toManifestFile), ...options.orphanedFiles].sort((left, right) => left.path.localeCompare(right.path));
489
- const internalFiles = [...options.internalOutputs.map((output) => ({
490
- path: output.path,
491
- kind: output.kind,
492
- bytes: byteLength(output.content),
493
- sha256: sha256(output.content)
494
- })), ...options.orphanedInternalFiles].sort((left, right) => left.path.localeCompare(right.path));
495
- const contentHash = sha256([...files.map((file) => `public:${file.path}\0${file.sha256}`), ...internalFiles.map((file) => `internal:${file.path}\0${file.sha256}`)].join("\n"));
496
- return {
497
- format: "farming-labs-agent-bundle.v1",
498
- generator: "@farming-labs/docs",
499
- entry: options.entry,
500
- publicDirectory: options.publicDirectory,
501
- baseUrl: options.baseUrl,
502
- contentHash,
503
- files,
504
- internalFiles,
505
- pages: options.pages.map(({ page, locale }) => ({
506
- route: page.url,
507
- markdownRoute: staticMarkdownRoute(page, options.sourceEntry, options.entry),
508
- sourcePath: page.sourcePath,
509
- locale
510
- })).sort((left, right) => left.markdownRoute.localeCompare(right.markdownRoute))
511
- };
512
- }
513
- function readPreviousManifest(manifestPath) {
514
- if (!existsSync(manifestPath)) return void 0;
515
- try {
516
- const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
517
- if (manifest.format !== "farming-labs-agent-bundle.v1" || !Array.isArray(manifest.files) || !Array.isArray(manifest.pages)) return;
518
- return {
519
- ...manifest,
520
- files: manifest.files.filter((file) => file && typeof file.path === "string" && typeof file.sha256 === "string" && typeof file.managed === "boolean"),
521
- internalFiles: Array.isArray(manifest.internalFiles) ? manifest.internalFiles.filter((file) => file && typeof file.path === "string" && typeof file.sha256 === "string") : []
522
- };
523
- } catch {
524
- return;
525
- }
526
- }
527
- function staleManagedPaths(publicDir, previous, outputs) {
528
- if (!previous) return [];
529
- const expected = new Set(outputs.map((output) => output.publicPath));
530
- return previous.files.filter((file) => (file.managed || file.orphaned === true) && !expected.has(file.path)).map((file) => resolvePreviousOutputPath(publicDir, file.path, "public")).filter((filePath) => existsSync(filePath));
531
- }
532
- function staleInternalPaths(rootDir, previous, outputs) {
533
- if (!previous?.internalFiles) return [];
534
- const expected = new Set(outputs.map((output) => output.path));
535
- return previous.internalFiles.filter((file) => !expected.has(file.path)).map((file) => resolvePreviousOutputPath(rootDir, file.path, "internal")).filter((filePath) => existsSync(filePath));
536
- }
537
- function resolvePreviousOutputPath(baseDir, relativePath, kind) {
538
- const resolved = resolveContainedPath(baseDir, relativePath);
539
- if (!resolved) throw new Error(`Previous Agent Bundle manifest contains an unsafe ${kind} output path: ${relativePath}`);
540
- return resolved;
541
- }
542
- function preservedStaleManifestFiles(publicDir, previous, outputs) {
543
- if (!previous) return [];
544
- const expected = new Set(outputs.map((output) => output.publicPath));
545
- return previous.files.flatMap((file) => {
546
- if (!file.managed && file.orphaned !== true || expected.has(file.path)) return [];
547
- const current = readExisting(resolvePreviousOutputPath(publicDir, file.path, "public"));
548
- if (current === void 0) return [];
549
- if (file.orphaned !== true && sha256(current) === file.sha256) return [];
550
- return [{
551
- ...file,
552
- bytes: byteLength(current),
553
- sha256: sha256(current),
554
- managed: false,
555
- orphaned: true
556
- }];
557
- });
558
- }
559
- function preservedStaleInternalManifestFiles(rootDir, previous, outputs) {
560
- if (!previous?.internalFiles) return [];
561
- const expected = new Set(outputs.map((output) => output.path));
562
- return previous.internalFiles.flatMap((file) => {
563
- if (expected.has(file.path)) return [];
564
- const current = readExisting(resolvePreviousOutputPath(rootDir, file.path, "internal"));
565
- if (current === void 0) return [];
566
- if (file.orphaned !== true && sha256(current) === file.sha256) return [];
567
- return [{
568
- ...file,
569
- bytes: byteLength(current),
570
- sha256: sha256(current),
571
- orphaned: true
572
- }];
573
- });
574
- }
575
- function removeStaleManagedFiles(publicDir, previous, stalePaths) {
576
- if (!previous) return [];
577
- const removed = [];
578
- const previousByPath = new Map(previous.files.map((file) => [resolvePreviousOutputPath(publicDir, file.path, "public"), file]));
579
- for (const filePath of stalePaths) {
580
- const previousFile = previousByPath.get(filePath);
581
- const current = readExisting(filePath);
582
- if (!previousFile?.managed || previousFile.orphaned === true || current === void 0 || sha256(current) !== previousFile.sha256) continue;
583
- rmSync(filePath);
584
- removed.push(filePath);
585
- }
586
- return removed;
587
- }
588
- function removeStaleInternalFiles(rootDir, previous, stalePaths) {
589
- if (!previous?.internalFiles) return [];
590
- const previousByPath = new Map(previous.internalFiles.map((file) => [resolvePreviousOutputPath(rootDir, file.path, "internal"), file]));
591
- const removed = [];
592
- for (const filePath of stalePaths) {
593
- const previousFile = previousByPath.get(filePath);
594
- const current = readExisting(filePath);
595
- if (!previousFile || previousFile.orphaned === true || current === void 0 || sha256(current) !== previousFile.sha256) continue;
596
- rmSync(filePath);
597
- removed.push(filePath);
598
- }
599
- return removed;
600
- }
601
- function changedOutputs(outputs) {
602
- return outputs.filter((output) => readExisting(output.absolutePath) !== output.content);
603
- }
604
- async function exportAgentBundle(options = {}) {
605
- if (!options.public && !options.check) throw new Error("Pass --public to write the static Agent Bundle into the framework public directory.");
606
- const rootDir = process.cwd();
607
- const loadedConfigModule = await loadDocsConfigModule(rootDir, options.configPath);
608
- const configContent = readFileSync(loadedConfigModule?.path ?? resolveDocsConfigPath(rootDir, options.configPath), "utf-8");
609
- const config = loadedConfigModule?.config;
610
- const sourceEntry = normalizePathSegment(config?.entry ?? readTopLevelStringProperty(configContent, "entry") ?? "docs");
611
- const routeEntry = normalizePathSegment(config?.docsPath ?? readStaticDocsPath(configContent) ?? sourceEntry);
612
- const contentDir = config?.contentDir ?? resolveDocsContentDir(rootDir, configContent, sourceEntry || "docs");
613
- const siteTitle = typeof config?.nav?.title === "string" ? config.nav.title : readNavTitle(configContent) ?? "Documentation";
614
- const metadataDescription = config?.metadata?.description ?? readStaticMetadataDescription(configContent);
615
- const llmsInput = config?.llmsTxt ?? readStaticLlmsConfig(configContent) ?? true;
616
- const llmsConfig = typeof llmsInput === "object" ? llmsInput : void 0;
617
- const llmsEnabled = llmsInput !== false && !(typeof llmsInput === "object" && llmsInput.enabled === false);
618
- const siteDescription = llmsConfig?.siteDescription ?? metadataDescription;
619
- const resolvedSiteTitle = llmsConfig?.siteTitle ?? siteTitle;
620
- const sitemapInput = config?.sitemap ?? readStaticSitemapConfig(configContent) ?? true;
621
- const robotsInput = config?.robots ?? readStaticRobotsConfig(configContent) ?? true;
622
- const baseUrl = llmsConfig?.baseUrl ?? (typeof sitemapInput === "object" ? sitemapInput.baseUrl : void 0) ?? (typeof robotsInput === "object" ? robotsInput.baseUrl : void 0);
623
- const i18n = resolveDocsI18n(config?.i18n ?? readStaticI18nConfig(configContent));
624
- const publicDirectory = detectFramework(rootDir) === "sveltekit" ? "static" : "public";
625
- const publicDir = resolveContainedPath(rootDir, publicDirectory);
626
- if (!publicDir) throw new Error(`Agent Bundle public directory must resolve inside the project root: ${publicDirectory}`);
627
- const internalManifestPath = resolveContainedPath(rootDir, AGENT_BUNDLE_INTERNAL_MANIFEST);
628
- if (!internalManifestPath) throw new Error(`Agent Bundle internal manifest must resolve inside the project root: ${AGENT_BUNDLE_INTERNAL_MANIFEST}`);
629
- const publicManifestPath = publicFilePath(publicDir, AGENT_BUNDLE_MANIFEST_ROUTE);
630
- const previous = readPreviousManifest(internalManifestPath);
631
- const localizedPages = (await loadPages({
632
- rootDir,
633
- contentDir,
634
- routeEntry,
635
- siteTitle: resolvedSiteTitle,
636
- ordering: config?.ordering,
637
- i18n
638
- })).map(({ page, locale }) => {
639
- const gitLastmod = pageGitLastmod(rootDir, page);
640
- return {
641
- locale,
642
- page: {
643
- ...page,
644
- lastModified: gitLastmod
645
- }
646
- };
647
- });
648
- if (localizedPages.length === 0) throw new Error(`No docs content was found under ${contentDir}.`);
649
- const pages = localizedPages.map(({ page }) => page);
650
- const sitemap = resolveDocsSitemapConfig(sitemapInput, { baseUrl });
651
- const robots = resolveDocsRobotsConfig(robotsInput, { baseUrl: typeof robotsInput === "object" ? robotsInput.baseUrl ?? sitemap.baseUrl : sitemap.baseUrl });
652
- const mcp = resolveDocsMcpConfig(false, { defaultName: resolvedSiteTitle });
653
- const feedbackConfig = resolveDocsAgentFeedbackConfig(false);
654
- const feedback = {
655
- enabled: feedbackConfig.enabled,
656
- route: feedbackConfig.route,
657
- schemaRoute: feedbackConfig.schemaRoute
658
- };
659
- const openapi = { enabled: false };
660
- const llms = {
661
- enabled: llmsEnabled,
662
- apiCatalog: false,
663
- baseUrl,
664
- siteTitle: resolvedSiteTitle,
665
- siteDescription,
666
- maxChars: llmsConfig?.maxChars,
667
- sections: llmsConfig?.sections,
668
- openapi
669
- };
670
- const documentOptions = {
671
- origin: baseUrl ?? "/",
672
- entry: routeEntry || "docs",
673
- apiRoute: config?.cloud?.apiRoute,
674
- apiCatalog: false,
675
- search: false,
676
- mcp,
677
- feedback,
678
- llms,
679
- sitemap: sitemapInput,
680
- robots: robotsInput,
681
- openapi,
682
- markdown: { acceptHeader: false }
683
- };
684
- let outputs = [];
685
- const internalOutputs = [];
686
- for (const { page } of localizedPages) addOutput(outputs, publicDir, staticMarkdownRoute(page, sourceEntry, routeEntry), "page", "text/markdown", renderDocsMarkdownDocument({
687
- ...page,
688
- markdownUrl: staticMarkdownRoute(page, sourceEntry, routeEntry)
689
- }, {
690
- llms,
691
- origin: baseUrl,
692
- sitemap: sitemapInput
693
- }));
694
- if (llmsEnabled) {
695
- const llmsContent = renderDocsLlmsTxt(pages.map((page) => ({
696
- url: page.url,
697
- markdownUrl: staticMarkdownRoute(page, sourceEntry, routeEntry),
698
- title: page.title,
699
- description: page.description,
700
- content: page.content,
701
- rawContent: page.rawContent,
702
- agentContent: page.agentContent,
703
- agentRawContent: page.agentRawContent,
704
- agentFallbackContent: page.agentFallbackContent,
705
- agentFallbackRawContent: page.agentFallbackRawContent
706
- })), llms);
707
- for (const route of [DEFAULT_LLMS_TXT_ROUTE, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE]) addOutput(outputs, publicDir, route, "llms", "text/plain", llmsContent.llmsTxt);
708
- for (const route of [DEFAULT_LLMS_FULL_TXT_ROUTE, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE]) addOutput(outputs, publicDir, route, "llms", "text/plain", llmsContent.llmsFullTxt);
709
- const sectionRoutes = new Set(llmsContent.sections.flatMap((section) => [section.route, section.fullRoute]));
710
- const llmsBaseRoutes = new Set([sourceEntry, routeEntry].filter(Boolean));
711
- for (const llmsBaseRoute of llmsBaseRoutes) {
712
- const entryLlmsRoute = `/${llmsBaseRoute}/llms.txt`;
713
- const entryLlmsFullRoute = `/${llmsBaseRoute}/llms-full.txt`;
714
- if (!sectionRoutes.has(entryLlmsRoute)) addOutput(outputs, publicDir, entryLlmsRoute, "llms", "text/plain", llmsContent.llmsTxt);
715
- if (!sectionRoutes.has(entryLlmsFullRoute)) addOutput(outputs, publicDir, entryLlmsFullRoute, "llms", "text/plain", llmsContent.llmsFullTxt);
716
- }
717
- for (const section of llmsContent.sections) {
718
- addOutput(outputs, publicDir, section.route, "llms", "text/plain", section.llmsTxt);
719
- addOutput(outputs, publicDir, section.fullRoute, "llms", "text/plain", section.llmsFullTxt);
720
- }
721
- }
722
- const discoveryWithBundle = {
723
- ...buildDocsAgentDiscoverySpec({
724
- ...documentOptions,
725
- i18n
726
- }),
727
- staticBundle: {
728
- format: "farming-labs-agent-bundle.v1",
729
- manifest: AGENT_BUNDLE_MANIFEST_ROUTE,
730
- check: "docs agent export --check",
731
- locales: i18n ? {
732
- default: i18n.defaultLocale,
733
- pathPattern: `${routeEntry ? `/${routeEntry}` : ""}/{locale}/{slug}.md`
734
- } : void 0
735
- }
736
- };
737
- const discoveryJson = JSON.stringify(discoveryWithBundle, null, 2);
738
- for (const route of [DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE]) addOutput(outputs, publicDir, route, "discovery", "application/json", discoveryJson);
739
- const generatedSkill = renderDocsSkillDocument(documentOptions);
740
- const rootSkillPath = path.join(rootDir, "skill.md");
741
- const publicSkill = existsSync(rootSkillPath) ? readFileSync(rootSkillPath, "utf-8") : generatedSkill;
742
- for (const route of [DEFAULT_SKILL_MD_ROUTE, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE]) addOutput(outputs, publicDir, route, "skill", "text/markdown", publicSkill);
743
- addOutput(outputs, publicDir, SKILL_CANONICAL_ROUTE, "skill", "text/markdown", generatedSkill);
744
- const generatedAgents = `${AGENT_EXPORT_AGENTS_MARKER}\n${renderDocsAgentsDocument(documentOptions)}`;
745
- const publicAgentsSource = findPublicAgentsSource(publicDir) ?? generatedAgents;
746
- for (const route of [
747
- DEFAULT_AGENTS_MD_ROUTE,
748
- DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE,
749
- DEFAULT_AGENT_MD_ROUTE,
750
- DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE
751
- ]) addOutput(outputs, publicDir, route, "agents", "text/markdown", publicAgentsSource);
752
- outputs = resolveUserOwnedAgentsOutputs(outputs);
753
- if (sitemap.enabled) {
754
- const sitemapManifest = deterministicSitemapManifest({
755
- pages: pages.map((page) => ({
756
- ...page,
757
- markdownUrl: staticMarkdownRoute(page, sourceEntry, routeEntry)
758
- })),
759
- entry: routeEntry || "docs",
760
- siteTitle: resolvedSiteTitle,
761
- baseUrl: sitemap.baseUrl
762
- });
763
- const sitemapManifestPath = resolveContainedPath(rootDir, sitemap.manifestPath);
764
- if (!sitemapManifestPath) throw new Error("sitemap.manifestPath must stay inside the project root for agent export.");
765
- if (sitemapManifestPath === internalManifestPath) throw new Error(`sitemap.manifestPath conflicts with ${AGENT_BUNDLE_INTERNAL_MANIFEST}. Choose a different sitemap manifest path.`);
766
- internalOutputs.push({
767
- absolutePath: sitemapManifestPath,
768
- path: path.relative(rootDir, sitemapManifestPath).replace(/\\/g, "/"),
769
- kind: "sitemap",
770
- content: `${JSON.stringify(sitemapManifest, null, 2)}\n`
771
- });
772
- if (sitemap.xml.enabled) addOutput(outputs, publicDir, sitemap.xml.route, "sitemap", "application/xml", renderDocsSitemapXml(sitemapManifest, {
773
- baseUrl: sitemap.baseUrl,
774
- includeLastmod: sitemap.xml.includeLastmod
775
- }));
776
- if (sitemap.markdown.enabled) {
777
- const sitemapMarkdown = renderDocsSitemapMarkdown(sitemapManifest, {
778
- baseUrl: sitemap.baseUrl,
779
- includeDescriptions: sitemap.markdown.includeDescriptions,
780
- includeLastmod: sitemap.markdown.includeLastmod,
781
- linkTarget: sitemap.markdown.linkTarget
782
- });
783
- for (const route of [
784
- sitemap.markdown.route,
785
- sitemap.markdown.docsRoute,
786
- sitemap.markdown.wellKnownRoute
787
- ]) if (route) addOutput(outputs, publicDir, route, "sitemap", "text/markdown", sitemapMarkdown);
788
- }
789
- }
790
- if (robots.enabled) outputs.push(resolveRobotsOutput(publicDir, routeEntry || "docs", sitemapInput, robots));
791
- outputs = resolveUserOwnedOverrides(outputs, previous);
792
- const publishedAgentSkill = await resolveDocsPublishedAgentSkill({
793
- preferredDocument: outputs.find((output) => output.route === DEFAULT_SKILL_MD_ROUTE)?.content ?? normalizeContent(publicSkill),
794
- fallbackDocument: normalizeContent(generatedSkill)
795
- });
796
- addOutput(outputs, publicDir, publishedAgentSkill.url, "skill", "text/markdown", publishedAgentSkill.content);
797
- addOutput(outputs, publicDir, DEFAULT_AGENT_SKILLS_INDEX_ROUTE, "discovery", "application/json", JSON.stringify(buildDocsAgentSkillsIndex(publishedAgentSkill), null, 2));
798
- assertOutputPathsDoNotCollide({
799
- outputs,
800
- internalOutputs,
801
- publicManifestPath,
802
- internalManifestPath
803
- });
804
- outputs.sort((left, right) => left.publicPath.localeCompare(right.publicPath));
805
- const stalePaths = staleManagedPaths(publicDir, previous, outputs);
806
- const staleInternal = staleInternalPaths(rootDir, previous, internalOutputs);
807
- const orphanedFiles = preservedStaleManifestFiles(publicDir, previous, outputs);
808
- const orphanedInternalFiles = preservedStaleInternalManifestFiles(rootDir, previous, internalOutputs);
809
- const manifest = buildAgentBundleManifest({
810
- sourceEntry,
811
- entry: routeEntry,
812
- publicDirectory,
813
- baseUrl,
814
- outputs,
815
- internalOutputs,
816
- orphanedFiles,
817
- orphanedInternalFiles,
818
- pages: localizedPages
819
- });
820
- const manifestJson = `${JSON.stringify(manifest, null, 2)}\n`;
821
- const changed = changedOutputs(outputs);
822
- const changedInternalOutputs = internalOutputs.filter((output) => readExisting(output.absolutePath) !== output.content);
823
- if (readExisting(publicManifestPath) !== manifestJson) changed.push({
824
- absolutePath: publicManifestPath,
825
- publicPath: publicRelativePath(publicDir, publicManifestPath),
826
- route: AGENT_BUNDLE_MANIFEST_ROUTE,
827
- kind: "discovery",
828
- mediaType: "application/json",
829
- content: manifestJson,
830
- managed: true
831
- });
832
- const internalChanged = readExisting(internalManifestPath) !== manifestJson;
833
- if (options.check && (changed.length > 0 || changedInternalOutputs.length > 0 || internalChanged || stalePaths.length > 0 || staleInternal.length > 0)) throw new Error(`Static Agent Bundle is stale (${changed.length + changedInternalOutputs.length + (internalChanged ? 1 : 0) + stalePaths.length + staleInternal.length} output(s)). Run \`docs agent export --public\` to update it.`);
834
- if (!options.check) {
835
- for (const output of outputs) if (readExisting(output.absolutePath) !== output.content) atomicWriteFile(output.absolutePath, output.content);
836
- for (const output of internalOutputs) if (readExisting(output.absolutePath) !== output.content) atomicWriteFile(output.absolutePath, output.content);
837
- atomicWriteFile(publicManifestPath, manifestJson);
838
- atomicWriteFile(internalManifestPath, manifestJson);
839
- const removed = removeStaleManagedFiles(publicDir, previous, stalePaths);
840
- removed.push(...removeStaleInternalFiles(rootDir, previous, staleInternal));
841
- for (const filePath of removed) console.log(pc.dim(`Removed ${path.relative(rootDir, filePath).replace(/\\/g, "/")}`));
842
- }
843
- const managedCount = manifest.files.filter((file) => file.managed).length;
844
- const customCount = manifest.files.length - managedCount;
845
- const orphanedCount = manifest.files.filter((file) => file.orphaned === true).length + manifest.internalFiles.filter((file) => file.orphaned === true).length;
846
- console.log(pc.green(options.check ? `Static Agent Bundle is current (${manifest.files.length} files, ${manifest.pages.length} pages).` : `Exported Static Agent Bundle (${manifest.files.length} files, ${manifest.pages.length} pages).`));
847
- console.log(pc.dim(`${publicDirectory}/.well-known/agent-bundle.json`));
848
- console.log(pc.dim(AGENT_BUNDLE_INTERNAL_MANIFEST));
849
- if (customCount > 0) console.log(pc.yellow(`Preserved ${customCount} user-owned public file(s).`));
850
- if (orphanedCount > 0) console.log(pc.yellow(`Preserved ${orphanedCount} modified obsolete output(s); remove them manually, then rerun the export.`));
851
- }
852
- function printAgentExportHelp() {
853
- console.log(`
854
- ${pc.bold("docs agent export")} — Export a complete static Agent Bundle.
855
-
856
- ${pc.dim("Usage:")}
857
- pnpm exec docs ${pc.cyan("agent export --public")}
858
- pnpm exec docs ${pc.cyan("agent export --check")}
859
-
860
- ${pc.dim("Options:")}
861
- ${pc.cyan("--public")} Write static agent files to ${pc.dim("public/")} or SvelteKit ${pc.dim("static/")}
862
- ${pc.cyan("--check")} Fail when exported files or their SHA-256 manifest are stale
863
- ${pc.cyan("--config <path>")} Use a custom docs config path instead of ${pc.dim("docs.config.ts[x]")}
864
- ${pc.cyan("-h, --help")} Show this help message
865
- `);
866
- }
867
-
868
- //#endregion
869
- export { exportAgentBundle, parseAgentExportArgs, printAgentExportHelp };