@farming-labs/docs 0.2.70 → 0.2.72

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/dist/{agent-MOuft73V.mjs → agent-DbDfIqhe.mjs} +3 -3
  2. package/dist/{agent-evals-BTh28hl-.mjs → agent-evals-CjYzCQMZ.mjs} +90 -10
  3. package/dist/{agent-export-43XUqLf5.mjs → agent-export-CpQhD8eA.mjs} +13 -10
  4. package/dist/{agent-CXkn2ihX.mjs → agent-pS2nNQS3.mjs} +540 -14
  5. package/dist/agent-skills-bundle.d.mts +1 -1
  6. package/dist/{agent-skills-server-DTwblsLu.d.mts → agent-skills-server-DZnNB4_S.d.mts} +2 -2
  7. package/dist/agent-skills-vite.d.mts +3 -3
  8. package/dist/agent-skills-vite.mjs +1 -1
  9. package/dist/{agents-C16sSxHU.mjs → agents-B-1h9Jlm.mjs} +8 -8
  10. package/dist/cli/index.mjs +29 -29
  11. package/dist/client/react.d.mts +1 -1
  12. package/dist/{cloud-pdNC-tyj.mjs → cloud-CyysfDny.mjs} +3 -3
  13. package/dist/{cloud-ask-ai-BfnX18rI.d.mts → cloud-ask-ai-D9gIN4Vr.d.mts} +1 -1
  14. package/dist/{codeblocks-CFuurVIH.mjs → codeblocks-DAj7EAwt.mjs} +2 -2
  15. package/dist/{dev-Cc1cFFj-.mjs → dev-qE7MYEh9.mjs} +2 -2
  16. package/dist/docs-cloud-server.d.mts +2 -2
  17. package/dist/docs-cloud-server.mjs +1 -1
  18. package/dist/{doctor-WjSas47Z.mjs → doctor-CBy8-tPu.mjs} +13 -13
  19. package/dist/{downgrade-w7e6Se0L.mjs → downgrade-DCxezPZI.mjs} +2 -2
  20. package/dist/{golden-evaluations-Cg0braJV.mjs → golden-evaluations-DGg_eHIY.mjs} +23 -3
  21. package/dist/index.d.mts +104 -6
  22. package/dist/index.mjs +6 -6
  23. package/dist/{init-DAkI0Lkf.mjs → init-p1MHf06G.mjs} +3 -3
  24. package/dist/{mcp-BDPfedoh.mjs → mcp-BNK45dzD.mjs} +7 -7
  25. package/dist/mcp.d.mts +7 -2
  26. package/dist/mcp.mjs +122 -18
  27. package/dist/{metadata-BMBvGASC.mjs → metadata-D6qlWDu-.mjs} +1 -1
  28. package/dist/{package-version-n5AFur8a.mjs → package-version-BXHcIm1T.mjs} +1 -1
  29. package/dist/{reading-time-D0s9Osqw.mjs → reading-time-DvTuW2Iy.mjs} +2 -2
  30. package/dist/{review-_0G2gAtx.mjs → review-Cace7A2c.mjs} +8 -8
  31. package/dist/{robots-DOnLGE0l.mjs → robots-C2SindI5.mjs} +1 -1
  32. package/dist/{robots-DLl9Zizg.mjs → robots-DmE_wXvG.mjs} +4 -4
  33. package/dist/{search-CozHzW7v.d.mts → search-1aftosa5.d.mts} +24 -9
  34. package/dist/{search-Boqkxa3T.mjs → search-BbArHODP.mjs} +672 -147
  35. package/dist/{search-B9tkri5i.mjs → search-DB3svkNQ.mjs} +7 -7
  36. package/dist/server.d.mts +13 -5
  37. package/dist/server.mjs +8 -8
  38. package/dist/{sitemap-FgXlxHEO.mjs → sitemap-DPTLh_26.mjs} +8 -8
  39. package/dist/{sitemap-server-Bynukz-j.mjs → sitemap-server-PUoOhplO.mjs} +1 -1
  40. package/dist/{standards-discovery-C0CIC4QI.d.mts → standards-discovery-DRJ10g7B.d.mts} +1 -1
  41. package/dist/{types-BQC05SQm.d.mts → types-B9DNNAdT.d.mts} +49 -1
  42. package/dist/{upgrade-oz-GChgt.mjs → upgrade-DDJQ5l6n.mjs} +2 -2
  43. package/package.json +1 -1
  44. package/dist/agent-scope-C_U--OZ7.mjs +0 -283
  45. /package/dist/{agent-skills-server-B4u3qy-1.mjs → agent-skills-server-BPVv4gMg.mjs} +0 -0
  46. /package/dist/{cloud-ask-ai-sbpjOR2K.mjs → cloud-ask-ai-hnJfj8-X.mjs} +0 -0
  47. /package/dist/{code-blocks-DnNVNK2M.mjs → code-blocks-qe0T8-xe.mjs} +0 -0
  48. /package/dist/{config-Wcdj-D0a.mjs → config-z7_R0f86.mjs} +0 -0
  49. /package/dist/{errors-DbOhkE1h.mjs → errors-Cc_qplZU.mjs} +0 -0
  50. /package/dist/{templates-C6avM0U3.mjs → templates-BJnf6B8l.mjs} +0 -0
  51. /package/dist/{utils-DpiIioYb.mjs → utils-C4RC8Zq_.mjs} +0 -0
@@ -736,6 +736,148 @@ function normalizeInlineText(value) {
736
736
  return value.replace(/\s+/g, " ").trim();
737
737
  }
738
738
 
739
+ //#endregion
740
+ //#region src/markdown-sections.ts
741
+ const HTML_ENTITIES = {
742
+ amp: "&",
743
+ apos: "'",
744
+ gt: ">",
745
+ lt: "<",
746
+ nbsp: " ",
747
+ quot: "\""
748
+ };
749
+ /**
750
+ * Reduce inline Markdown in a heading to the visible label used by search and anchors.
751
+ * This intentionally covers the common inline constructs without adding a Markdown parser
752
+ * dependency to the runtime package.
753
+ */
754
+ function cleanDocsMarkdownHeadingLabel(value) {
755
+ return value.replace(/!\[([^\]]*)\]\([^)]*\)/gu, "$1").replace(/\[([^\]]+)\]\([^)]*\)/gu, "$1").replace(/!\[([^\]]*)\]\[[^\]]*\]/gu, "$1").replace(/\[([^\]]+)\]\[[^\]]*\]/gu, "$1").replace(/<((?:https?:\/\/|mailto:)[^>]+)>/giu, "$1").replace(/<[^>]+>/gu, "").replace(/`+([^`]*?)`+/gu, "$1").replace(/\\([!"#$%&'()*+,\-./:;<=>?@[\]^_`{|}~])/gu, "$1").replace(/[*_~]/gu, "").replace(/&(#(?:x[0-9a-f]+|\d+)|[a-z]+);/giu, (_match, entity) => {
756
+ if (entity.startsWith("#x") || entity.startsWith("#X")) {
757
+ const codePoint = Number.parseInt(entity.slice(2), 16);
758
+ return Number.isSafeInteger(codePoint) && codePoint >= 0 && codePoint <= 1114111 ? String.fromCodePoint(codePoint) : _match;
759
+ }
760
+ if (entity.startsWith("#")) {
761
+ const codePoint = Number.parseInt(entity.slice(1), 10);
762
+ return Number.isSafeInteger(codePoint) && codePoint >= 0 && codePoint <= 1114111 ? String.fromCodePoint(codePoint) : _match;
763
+ }
764
+ return HTML_ENTITIES[entity.toLowerCase()] ?? _match;
765
+ }).replace(/\s+/gu, " ").trim();
766
+ }
767
+ /** Keep anchors aligned with the framework's existing ASCII heading-slug behavior. */
768
+ function slugifyDocsMarkdownHeading(value) {
769
+ return cleanDocsMarkdownHeadingLabel(value).toLowerCase().replace(/[`'"‘’“”]/gu, "").replace(/&/gu, " and ").replace(/[^a-z0-9\s-]/gu, "").replace(/\s+/gu, "-").replace(/-+/gu, "-").replace(/^-|-$/gu, "");
770
+ }
771
+ function readOpeningFence(line) {
772
+ const match = line.match(/^ {0,3}(`{3,}|~{3,})/u);
773
+ if (!match) return void 0;
774
+ return {
775
+ marker: match[1][0],
776
+ length: match[1].length
777
+ };
778
+ }
779
+ function isClosingFence(line, fence) {
780
+ const marker = fence.marker === "`" ? "`" : "~";
781
+ const match = line.match(new RegExp(`^ {0,3}(${marker}{${fence.length},})[\\t ]*$`, "u"));
782
+ return Boolean(match);
783
+ }
784
+ function readAtxHeading(line) {
785
+ const match = line.match(/^ {0,3}(#{1,6})(?:[\t ]+|$)(.*)$/u);
786
+ if (!match) return void 0;
787
+ return {
788
+ title: cleanDocsMarkdownHeadingLabel(match[2].replace(/[\t ]+#+[\t ]*$/u, "").trim()),
789
+ level: match[1].length
790
+ };
791
+ }
792
+ function readSetextLevel(line) {
793
+ const match = line.match(/^ {0,3}(=+|-+)[\t ]*$/u);
794
+ if (!match) return void 0;
795
+ return match[1][0] === "=" ? 1 : 2;
796
+ }
797
+ function normalizeDocsSectionSelector(value) {
798
+ let selector = value.trim();
799
+ const hashIndex = selector.lastIndexOf("#");
800
+ if (hashIndex >= 0) selector = selector.slice(hashIndex + 1);
801
+ try {
802
+ selector = decodeURIComponent(selector);
803
+ } catch {}
804
+ return cleanDocsMarkdownHeadingLabel(selector.replace(/^#+/u, "")).toLowerCase();
805
+ }
806
+ /**
807
+ * Parse heading sections once for search, Ask AI hydration, and MCP tools.
808
+ * Supports CommonMark ATX indentation, Setext headings, fenced-code exclusion,
809
+ * visible inline labels, and stable duplicate anchors.
810
+ */
811
+ function parseDocsMarkdownSections(markdown) {
812
+ const lines = markdown.split(/\r?\n/u);
813
+ const headings = [];
814
+ const headingCounts = /* @__PURE__ */ new Map();
815
+ let openFence;
816
+ let setextCandidate;
817
+ const pushHeading = (title, level, start) => {
818
+ const baseAnchor = slugifyDocsMarkdownHeading(title) || `section-${headings.length}`;
819
+ const seen = headingCounts.get(baseAnchor) ?? 0;
820
+ headingCounts.set(baseAnchor, seen + 1);
821
+ headings.push({
822
+ title,
823
+ anchor: seen === 0 ? baseAnchor : `${baseAnchor}-${seen}`,
824
+ level,
825
+ start
826
+ });
827
+ };
828
+ for (let index = 0; index < lines.length; index += 1) {
829
+ const line = lines[index];
830
+ if (openFence) {
831
+ if (isClosingFence(line, openFence)) openFence = void 0;
832
+ setextCandidate = void 0;
833
+ continue;
834
+ }
835
+ const openingFence = readOpeningFence(line);
836
+ if (openingFence) {
837
+ openFence = openingFence;
838
+ setextCandidate = void 0;
839
+ continue;
840
+ }
841
+ const setextLevel = readSetextLevel(line);
842
+ if (setextLevel && setextCandidate?.index === index - 1) {
843
+ const title = cleanDocsMarkdownHeadingLabel(setextCandidate.value.trim());
844
+ if (title) pushHeading(title, setextLevel, setextCandidate.index);
845
+ setextCandidate = void 0;
846
+ continue;
847
+ }
848
+ const atxHeading = readAtxHeading(line);
849
+ if (atxHeading) {
850
+ pushHeading(atxHeading.title, atxHeading.level, index);
851
+ setextCandidate = void 0;
852
+ continue;
853
+ }
854
+ if (!line.trim() || /^ {4}|^\t/u.test(line)) {
855
+ setextCandidate = void 0;
856
+ continue;
857
+ }
858
+ setextCandidate = {
859
+ index,
860
+ value: line
861
+ };
862
+ }
863
+ return headings.map((heading, index) => {
864
+ const end = headings.slice(index + 1).find((candidate) => candidate.level <= heading.level)?.start ?? lines.length;
865
+ return {
866
+ title: heading.title,
867
+ anchor: heading.anchor,
868
+ level: heading.level,
869
+ content: lines.slice(heading.start, end).join("\n").trim(),
870
+ startLine: heading.start + 1,
871
+ endLine: end
872
+ };
873
+ });
874
+ }
875
+ function findDocsMarkdownSection(markdown, requestedSection) {
876
+ const selector = normalizeDocsSectionSelector(requestedSection);
877
+ if (!selector) return void 0;
878
+ return parseDocsMarkdownSections(markdown).find((section) => normalizeDocsSectionSelector(section.title) === selector || section.anchor === selector);
879
+ }
880
+
739
881
  //#endregion
740
882
  //#region src/sitemap.ts
741
883
  const DEFAULT_SITEMAP_XML_ROUTE = "/sitemap.xml";
@@ -2178,6 +2320,7 @@ const DEFAULT_DOCS_DIAGNOSTICS_MCP_TOOLS = {
2178
2320
  getContext: true
2179
2321
  };
2180
2322
  const DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER = "Signature-Agent";
2323
+ const DOCS_MARKDOWN_SECTION_INDEX_FORMAT = "docs-markdown-sections.v1";
2181
2324
  const DOCS_AI_AGENT_USER_AGENT_PATTERNS = [
2182
2325
  "claudebot",
2183
2326
  "claude-searchbot",
@@ -2307,6 +2450,7 @@ const DOCS_CONFIG_MAP_TOP_LEVEL_KEYS = [
2307
2450
  "metadata",
2308
2451
  "og"
2309
2452
  ];
2453
+ const DOCS_MARKDOWN_SECTION_MAX_BUDGET = 1e6;
2310
2454
  function normalizeDocsPathSegment(value) {
2311
2455
  return value.replace(/^\/+|\/+$/g, "");
2312
2456
  }
@@ -2466,12 +2610,22 @@ function buildDocsDiagnostics(config, options = {}) {
2466
2610
  route: search.enabled ? apiQueryRoute("query={query}") : null,
2467
2611
  routes: {
2468
2612
  human: search.enabled ? apiQueryRoute("query={query}") : null,
2469
- agent: search.enabled ? apiQueryRoute("query={query}&audience=agent") : null
2613
+ agent: search.enabled ? apiQueryRoute("query={query}&audience=agent") : null,
2614
+ structuredAgent: search.enabled ? apiQueryRoute("query={query}&audience=agent&response=structured") : null
2470
2615
  },
2471
2616
  agentEndpoint: search.enabled ? apiQueryRoute("query={query}&audience=agent") : null,
2617
+ structuredAgentEndpoint: search.enabled ? apiQueryRoute("query={query}&audience=agent&response=structured") : null,
2472
2618
  audienceParam: "audience",
2473
2619
  defaultAudience: "human",
2474
2620
  supportedAudiences: ["human", "agent"],
2621
+ filterParams: {
2622
+ framework: "framework",
2623
+ version: "version",
2624
+ package: "package",
2625
+ tags: "tags"
2626
+ },
2627
+ responseFormat: "docs-search.v1",
2628
+ warningsField: "warnings",
2475
2629
  provider: search.provider,
2476
2630
  transport: "GET"
2477
2631
  },
@@ -3633,6 +3787,269 @@ function prependDocsMarkdownFrontmatter(markdown, metadata) {
3633
3787
  if (hasDocsMarkdownFrontmatter(markdown)) return markdown;
3634
3788
  return `${renderDocsMarkdownFrontmatter(metadata)}\n\n${markdown.replace(/^\r?\n+/, "")}`;
3635
3789
  }
3790
+ function stripDocsMarkdownFrontmatter(markdown) {
3791
+ const match = markdown.match(/^(---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$))([\s\S]*)$/);
3792
+ if (!match) return {
3793
+ frontmatter: "",
3794
+ body: markdown
3795
+ };
3796
+ return {
3797
+ frontmatter: match[1] ?? "",
3798
+ body: match[2] ?? ""
3799
+ };
3800
+ }
3801
+ function slugifyPublicDocsMarkdownSectionId(value) {
3802
+ return value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/`([^`]+)`/g, "$1").replace(/<[^>]*>/g, "").replace(/[^\p{L}\p{N}\s-]/gu, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
3803
+ }
3804
+ function resolveDocsMarkdownSectionBody(document) {
3805
+ const lines = stripDocsMarkdownFrontmatter(document).body.split(/\r?\n/u);
3806
+ let generatedPreambleStart = 0;
3807
+ while (generatedPreambleStart < lines.length && (lines[generatedPreambleStart] ?? "").trim() === "") generatedPreambleStart += 1;
3808
+ if (/^#(?:\s+|$)/u.test(lines[generatedPreambleStart] ?? "") && /^URL:\s+\S/u.test(lines[generatedPreambleStart + 1] ?? "")) {
3809
+ let metadataEnd = generatedPreambleStart + 2;
3810
+ while (/^(?:LLM index|Description|Related):\s*/u.test(lines[metadataEnd] ?? "")) metadataEnd += 1;
3811
+ for (let index = generatedPreambleStart + 1; index < metadataEnd; index += 1) lines[index] = "";
3812
+ }
3813
+ return {
3814
+ body: lines.join("\n").replace(/\n{2,}## Sitemap\n\n(?:(?:See the (?:full|XML) \[sitemap\]\()|Sitemap discovery is not enabled)[\s\S]*$/u, ""),
3815
+ lineOffset: 0
3816
+ };
3817
+ }
3818
+ function estimateDocsMarkdownTokens(value) {
3819
+ if (!value) return 0;
3820
+ return Math.max(1, Math.ceil(docsMarkdownUtf8Bytes(value) / 4));
3821
+ }
3822
+ function docsMarkdownUtf8Bytes(value) {
3823
+ return new TextEncoder().encode(value).byteLength;
3824
+ }
3825
+ function trimDocsMarkdownToByteBudget(value, byteBudget) {
3826
+ if (docsMarkdownUtf8Bytes(value) <= byteBudget) return value;
3827
+ let output = "";
3828
+ let bytes = 0;
3829
+ const encoder = new TextEncoder();
3830
+ for (const character of value) {
3831
+ const characterBytes = encoder.encode(character).byteLength;
3832
+ if (bytes + characterBytes > byteBudget) break;
3833
+ output += character;
3834
+ bytes += characterBytes;
3835
+ }
3836
+ return output.trimEnd();
3837
+ }
3838
+ function truncateDocsMarkdownSectionContent(content, request) {
3839
+ const budgets = [typeof request.byteBudget === "number" ? request.byteBudget : void 0, typeof request.tokenBudget === "number" ? request.tokenBudget * 4 : void 0].filter((budget) => budget !== void 0 && Number.isSafeInteger(budget) && budget > 0);
3840
+ const byteBudget = budgets.length > 0 ? Math.min(...budgets) : void 0;
3841
+ if (!byteBudget || docsMarkdownUtf8Bytes(content) <= byteBudget) return {
3842
+ document: content,
3843
+ truncated: false
3844
+ };
3845
+ const fullMarker = "\n\n<!-- section truncated: increase tokenBudget or byteBudget for more. -->";
3846
+ const marker = docsMarkdownUtf8Bytes(fullMarker) <= byteBudget ? fullMarker : "\n\n<!-- section truncated -->";
3847
+ if (docsMarkdownUtf8Bytes(marker) > byteBudget) return {
3848
+ document: trimDocsMarkdownToByteBudget(marker.trimStart(), byteBudget),
3849
+ truncated: true
3850
+ };
3851
+ let truncated = trimDocsMarkdownToByteBudget(content, Math.max(0, byteBudget - docsMarkdownUtf8Bytes(marker)));
3852
+ const paragraphBoundary = truncated.lastIndexOf("\n\n");
3853
+ if (paragraphBoundary > 0 && paragraphBoundary > truncated.length * .45) truncated = truncated.slice(0, paragraphBoundary).trimEnd();
3854
+ return {
3855
+ document: `${truncated}${marker}`,
3856
+ truncated: true
3857
+ };
3858
+ }
3859
+ function parsePositiveDocsMarkdownBudget(value) {
3860
+ if (!value) return null;
3861
+ const parsed = Number.parseInt(value.replace(/_/g, ""), 10);
3862
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) return null;
3863
+ return Math.min(parsed, DOCS_MARKDOWN_SECTION_MAX_BUDGET);
3864
+ }
3865
+ function resolveDocsMarkdownSectionRequest(url) {
3866
+ const section = url.searchParams.get("section")?.trim() || null;
3867
+ const tokenBudget = parsePositiveDocsMarkdownBudget(url.searchParams.get("tokenBudget")) ?? parsePositiveDocsMarkdownBudget(url.searchParams.get("tokens"));
3868
+ const byteBudget = parsePositiveDocsMarkdownBudget(url.searchParams.get("byteBudget")) ?? parsePositiveDocsMarkdownBudget(url.searchParams.get("bytes"));
3869
+ if (!section && tokenBudget === null && byteBudget === null) return null;
3870
+ return {
3871
+ section,
3872
+ tokenBudget,
3873
+ byteBudget
3874
+ };
3875
+ }
3876
+ function isDocsMarkdownSectionIndexRequest(url) {
3877
+ if (!url.searchParams.has("sections")) return false;
3878
+ const value = url.searchParams.get("sections")?.trim().toLowerCase();
3879
+ return value === void 0 || ![
3880
+ "0",
3881
+ "false",
3882
+ "no",
3883
+ "off"
3884
+ ].includes(value);
3885
+ }
3886
+ function collectDocsMarkdownSections(document) {
3887
+ const { body, lineOffset } = resolveDocsMarkdownSectionBody(document);
3888
+ const seen = /* @__PURE__ */ new Map();
3889
+ return parseDocsMarkdownSections(body).flatMap((section) => {
3890
+ const baseId = slugifyPublicDocsMarkdownSectionId(section.title);
3891
+ if (!baseId) return [];
3892
+ const count = seen.get(baseId) ?? 0;
3893
+ seen.set(baseId, count + 1);
3894
+ return [{
3895
+ id: count === 0 ? baseId : `${baseId}-${count + 1}`,
3896
+ heading: section.title,
3897
+ level: section.level,
3898
+ content: section.content,
3899
+ startLine: section.startLine + lineOffset,
3900
+ endLine: section.endLine + lineOffset
3901
+ }];
3902
+ });
3903
+ }
3904
+ function updateDocsMarkdownUrl(value, update) {
3905
+ const isAbsolute = /^[a-z][a-z\d+.-]*:/iu.test(value);
3906
+ try {
3907
+ const url = new URL(value, "https://docs.invalid");
3908
+ update(url);
3909
+ return (isAbsolute ? url.toString() : `${url.pathname}${url.search}${url.hash}`).replace(/([?&])sections=(?=&|$)/u, "$1sections");
3910
+ } catch {
3911
+ return value;
3912
+ }
3913
+ }
3914
+ function resolveDocsMarkdownSectionCanonicalUrl(canonicalUrl, sectionId) {
3915
+ return updateDocsMarkdownUrl(canonicalUrl, (url) => {
3916
+ url.hash = sectionId;
3917
+ });
3918
+ }
3919
+ function resolveDocsMarkdownSectionFetchUrl(markdownUrl, sectionId, request) {
3920
+ return updateDocsMarkdownUrl(markdownUrl, (url) => {
3921
+ url.searchParams.delete("sections");
3922
+ url.searchParams.delete("section");
3923
+ url.searchParams.delete("tokens");
3924
+ url.searchParams.delete("bytes");
3925
+ url.searchParams.delete("tokenBudget");
3926
+ url.searchParams.delete("byteBudget");
3927
+ url.searchParams.set("section", sectionId);
3928
+ if (request.tokenBudget) url.searchParams.set("tokenBudget", String(request.tokenBudget));
3929
+ if (request.byteBudget) url.searchParams.set("byteBudget", String(request.byteBudget));
3930
+ });
3931
+ }
3932
+ function resolveDocsMarkdownSectionIndexUrl(markdownUrl, request) {
3933
+ return updateDocsMarkdownUrl(markdownUrl, (url) => {
3934
+ url.searchParams.delete("sections");
3935
+ url.searchParams.delete("section");
3936
+ url.searchParams.delete("tokens");
3937
+ url.searchParams.delete("bytes");
3938
+ url.searchParams.delete("tokenBudget");
3939
+ url.searchParams.delete("byteBudget");
3940
+ url.searchParams.set("sections", "");
3941
+ if (request.tokenBudget) url.searchParams.set("tokenBudget", String(request.tokenBudget));
3942
+ if (request.byteBudget) url.searchParams.set("byteBudget", String(request.byteBudget));
3943
+ });
3944
+ }
3945
+ function buildDocsMarkdownSectionIndex(document, options) {
3946
+ const request = {
3947
+ tokenBudget: options.tokenBudget ?? void 0,
3948
+ byteBudget: options.byteBudget ?? void 0
3949
+ };
3950
+ const sections = collectDocsMarkdownSections(document);
3951
+ const ancestors = [];
3952
+ const metadata = sections.map((section) => {
3953
+ while (ancestors.length > 0 && (ancestors[ancestors.length - 1]?.level ?? Number.NEGATIVE_INFINITY) >= section.level) ancestors.pop();
3954
+ const parentId = ancestors.at(-1)?.id;
3955
+ const item = {
3956
+ id: section.id,
3957
+ heading: section.heading,
3958
+ level: section.level,
3959
+ ...parentId ? { parentId } : {},
3960
+ startLine: section.startLine,
3961
+ endLine: section.endLine,
3962
+ estimatedTokens: estimateDocsMarkdownTokens(section.content),
3963
+ utf8Bytes: docsMarkdownUtf8Bytes(section.content),
3964
+ canonicalUrl: resolveDocsMarkdownSectionCanonicalUrl(options.canonicalUrl, section.id),
3965
+ markdownUrl: resolveDocsMarkdownSectionFetchUrl(options.markdownUrl, section.id, request)
3966
+ };
3967
+ ancestors.push(section);
3968
+ return item;
3969
+ });
3970
+ const fetchBudget = request.tokenBudget || request.byteBudget ? {
3971
+ ...request.tokenBudget ? { tokenBudget: request.tokenBudget } : {},
3972
+ ...request.byteBudget ? { byteBudget: request.byteBudget } : {}
3973
+ } : void 0;
3974
+ return {
3975
+ schemaVersion: 1,
3976
+ format: DOCS_MARKDOWN_SECTION_INDEX_FORMAT,
3977
+ canonicalUrl: options.canonicalUrl,
3978
+ markdownUrl: options.markdownUrl,
3979
+ sectionIndexUrl: options.sectionIndexUrl ?? resolveDocsMarkdownSectionIndexUrl(options.markdownUrl, request),
3980
+ lineNumbering: "body",
3981
+ sectionCount: metadata.length,
3982
+ estimatedTokens: estimateDocsMarkdownTokens(document),
3983
+ utf8Bytes: docsMarkdownUtf8Bytes(document),
3984
+ ...fetchBudget ? { fetchBudget } : {},
3985
+ sections: metadata
3986
+ };
3987
+ }
3988
+ function normalizeRequestedDocsMarkdownSectionId(requestedSection) {
3989
+ let selector = requestedSection.trim();
3990
+ const hashIndex = selector.lastIndexOf("#");
3991
+ if (hashIndex >= 0) selector = selector.slice(hashIndex + 1);
3992
+ try {
3993
+ selector = decodeURIComponent(selector);
3994
+ } catch {}
3995
+ return selector.replace(/^#+/u, "").toLowerCase();
3996
+ }
3997
+ function selectDocsMarkdownSection(document, request) {
3998
+ const availableSections = collectDocsMarkdownSections(document);
3999
+ const requestedSection = request.section?.trim();
4000
+ if (!requestedSection) {
4001
+ const { document: budgetedDocument, truncated } = truncateDocsMarkdownSectionContent(document, request);
4002
+ return {
4003
+ found: true,
4004
+ document: budgetedDocument,
4005
+ truncated,
4006
+ tokenBudget: request.tokenBudget ?? void 0,
4007
+ byteBudget: request.byteBudget ?? void 0,
4008
+ estimatedTokens: estimateDocsMarkdownTokens(budgetedDocument),
4009
+ utf8Bytes: docsMarkdownUtf8Bytes(budgetedDocument),
4010
+ availableSections
4011
+ };
4012
+ }
4013
+ const requestedId = normalizeRequestedDocsMarkdownSectionId(requestedSection);
4014
+ const directSection = availableSections.find((candidate) => candidate.id === requestedId);
4015
+ const { body, lineOffset } = resolveDocsMarkdownSectionBody(document);
4016
+ const selectedSharedSection = directSection ? void 0 : findDocsMarkdownSection(body, requestedSection);
4017
+ const sharedAliasSection = selectedSharedSection ? availableSections.find((candidate) => candidate.startLine === selectedSharedSection.startLine + lineOffset) : void 0;
4018
+ const section = directSection ?? sharedAliasSection;
4019
+ if (!section) {
4020
+ const lines = [
4021
+ "# Markdown Section Not Found",
4022
+ "",
4023
+ requestedSection ? `Could not find section \`${requestedSection}\`.` : "No Markdown sections were available in this page."
4024
+ ];
4025
+ if (availableSections.length > 0) lines.push("", "## Available Sections", "", ...availableSections.map((candidate) => `- ${candidate.heading} (#${candidate.id})`));
4026
+ const notFoundDocument = lines.join("\n");
4027
+ return {
4028
+ found: false,
4029
+ requestedSection,
4030
+ document: notFoundDocument,
4031
+ truncated: false,
4032
+ tokenBudget: request.tokenBudget ?? void 0,
4033
+ byteBudget: request.byteBudget ?? void 0,
4034
+ estimatedTokens: estimateDocsMarkdownTokens(notFoundDocument),
4035
+ utf8Bytes: docsMarkdownUtf8Bytes(notFoundDocument),
4036
+ availableSections
4037
+ };
4038
+ }
4039
+ const { document: selectedDocument, truncated } = truncateDocsMarkdownSectionContent(section.content, request);
4040
+ return {
4041
+ found: true,
4042
+ requestedSection,
4043
+ section,
4044
+ document: selectedDocument,
4045
+ truncated,
4046
+ tokenBudget: request.tokenBudget ?? void 0,
4047
+ byteBudget: request.byteBudget ?? void 0,
4048
+ estimatedTokens: estimateDocsMarkdownTokens(selectedDocument),
4049
+ utf8Bytes: docsMarkdownUtf8Bytes(selectedDocument),
4050
+ availableSections
4051
+ };
4052
+ }
3636
4053
  function resolveDocsMarkdownPageMetadata(page, options) {
3637
4054
  return {
3638
4055
  title: page.title,
@@ -3671,7 +4088,7 @@ function renderDocsMarkdownNotFound({ entry = "docs", apiRoute, requestedPath, o
3671
4088
  lines.push(`- [${match.title}](${match.markdownUrl}) (${confidence} confidence)${match.description ? ` - ${match.description}` : ""}`);
3672
4089
  }
3673
4090
  }
3674
- lines.push("", "## Recovery", "", "- If a closest match looks right, fetch that markdown URL directly.", "- If the match is uncertain, search the docs first and then fetch the smallest page that answers the task.", "- Use the sitemap routes below to browse the full docs index before guessing another slug.", "", "## Discovery Routes", "", "Use these discovery routes to find the right page:", "", `- Agent discovery spec: \`${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}\``, `- Agent discovery fallback: \`${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}\``, `- Agent discovery API: \`${agentSpecApiRoute}\``, `- API catalog: \`${DEFAULT_API_CATALOG_ROUTE}\``, `- Agent Skills index: \`${DEFAULT_AGENT_SKILLS_INDEX_ROUTE}\``, `- Agent instructions: \`${DEFAULT_AGENTS_MD_ROUTE}\``, `- Agent search endpoint: \`${resolvedApiRoute}?query={query}&audience=agent\``, `- Docs index markdown: \`/${normalizedEntry}.md\``, `- Requested markdown API route: \`${requestedApiRoute}\``);
4091
+ lines.push("", "## Recovery", "", "- If a closest match looks right, fetch that markdown URL directly.", "- If the match is uncertain, search the docs first and then fetch the smallest page that answers the task.", "- Use the sitemap routes below to browse the full docs index before guessing another slug.", "", "## Discovery Routes", "", "Use these discovery routes to find the right page:", "", `- Agent discovery spec: \`${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}\``, `- Agent discovery fallback: \`${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}\``, `- Agent discovery API: \`${agentSpecApiRoute}\``, `- API catalog: \`${DEFAULT_API_CATALOG_ROUTE}\``, `- Agent Skills index: \`${DEFAULT_AGENT_SKILLS_INDEX_ROUTE}\``, `- Agent instructions: \`${DEFAULT_AGENTS_MD_ROUTE}\``, `- Structured agent search: \`${resolvedApiRoute}?query={query}&audience=agent&response=structured\` (optionally repeat \`framework\`, \`version\`, \`package\`, or \`tags\`).`, `- Docs index markdown: \`/${normalizedEntry}.md\``, `- Requested markdown API route: \`${requestedApiRoute}\``);
3675
4092
  if (sitemapConfig.enabled) {
3676
4093
  if (sitemapConfig.markdown.enabled) {
3677
4094
  lines.push(`- Semantic sitemap: \`${sitemapConfig.markdown.route}\``);
@@ -3737,6 +4154,17 @@ function resolveDocsMarkdownContentLocation(canonicalUrl) {
3737
4154
  url.pathname = toDocsMarkdownUrl(url.pathname);
3738
4155
  return url.toString();
3739
4156
  }
4157
+ function appendDocsMarkdownSectionQuery(value, sectionRequest) {
4158
+ try {
4159
+ const url = new URL(value);
4160
+ if (sectionRequest.section) url.searchParams.set("section", sectionRequest.section);
4161
+ if (sectionRequest.tokenBudget) url.searchParams.set("tokenBudget", String(sectionRequest.tokenBudget));
4162
+ if (sectionRequest.byteBudget) url.searchParams.set("byteBudget", String(sectionRequest.byteBudget));
4163
+ return url.toString();
4164
+ } catch {
4165
+ return value;
4166
+ }
4167
+ }
3740
4168
  /** Build one standards-aware Markdown response for every framework adapter. */
3741
4169
  function createDocsMarkdownResponse(options) {
3742
4170
  const { request, document, entry = "docs", requestedPath, origin = new URL(request.url).origin, pages, sitemap, locale } = options;
@@ -3748,9 +4176,7 @@ function createDocsMarkdownResponse(options) {
3748
4176
  });
3749
4177
  const contentLocation = options.contentLocation ?? resolveDocsMarkdownContentLocation(canonicalUrl);
3750
4178
  const varyHeader = getDocsMarkdownVaryHeader(request);
3751
- const sharedHeaders = {
3752
- "Content-Location": contentLocation,
3753
- Link: `<${canonicalUrl}>; rel="canonical"`,
4179
+ const baseSharedHeaders = {
3754
4180
  "X-Robots-Tag": "noindex",
3755
4181
  ...locale ? { "Content-Language": locale } : {},
3756
4182
  ...varyHeader ? { Vary: varyHeader } : {}
@@ -3765,7 +4191,9 @@ function createDocsMarkdownResponse(options) {
3765
4191
  if (recovery.redirect) return new Response(null, {
3766
4192
  status: 307,
3767
4193
  headers: {
3768
- ...sharedHeaders,
4194
+ ...baseSharedHeaders,
4195
+ "Content-Location": contentLocation,
4196
+ Link: `<${canonicalUrl}>; rel="canonical"`,
3769
4197
  "Cache-Control": "no-store",
3770
4198
  Location: new URL(recovery.redirect.markdownUrl, request.url).toString()
3771
4199
  }
@@ -3780,19 +4208,81 @@ function createDocsMarkdownResponse(options) {
3780
4208
  }), {
3781
4209
  status: 404,
3782
4210
  headers: {
3783
- ...sharedHeaders,
4211
+ ...baseSharedHeaders,
4212
+ "Content-Location": contentLocation,
4213
+ Link: `<${canonicalUrl}>; rel="canonical"`,
3784
4214
  "Cache-Control": "no-store",
3785
4215
  "Content-Type": "text/markdown; charset=utf-8"
3786
4216
  }
3787
4217
  });
3788
4218
  }
3789
- const etag = createDocsMarkdownEtag(document);
4219
+ const requestUrl = new URL(request.url);
4220
+ const sectionRequest = resolveDocsMarkdownSectionRequest(requestUrl);
4221
+ if (isDocsMarkdownSectionIndexRequest(requestUrl)) {
4222
+ const sectionIndexRequest = sectionRequest ?? {};
4223
+ const sectionIndexContentLocation = resolveDocsMarkdownSectionIndexUrl(contentLocation, sectionIndexRequest);
4224
+ const sectionIndex = buildDocsMarkdownSectionIndex(document, {
4225
+ canonicalUrl,
4226
+ markdownUrl: contentLocation,
4227
+ sectionIndexUrl: sectionIndexContentLocation,
4228
+ tokenBudget: sectionIndexRequest.tokenBudget,
4229
+ byteBudget: sectionIndexRequest.byteBudget
4230
+ });
4231
+ const responseDocument = JSON.stringify(sectionIndex);
4232
+ const etag = createDocsMarkdownEtag(responseDocument);
4233
+ const lastModified = resolveDocsMarkdownHttpDate(options.lastModified ?? extractDocsMarkdownLastModified(document));
4234
+ const responseHeaders = {
4235
+ ...baseSharedHeaders,
4236
+ "Content-Location": sectionIndexContentLocation,
4237
+ Link: `<${canonicalUrl}>; rel="canonical", <${contentLocation}>; rel="alternate"; type="text/markdown"`,
4238
+ "Cache-Control": options.cacheControl ?? "public, max-age=0, s-maxage=3600",
4239
+ "Content-Type": "application/json; charset=utf-8",
4240
+ ETag: etag,
4241
+ "X-Docs-Markdown-Section-Index": DOCS_MARKDOWN_SECTION_INDEX_FORMAT,
4242
+ "X-Docs-Markdown-Section-Count": String(sectionIndex.sectionCount),
4243
+ "X-Docs-Markdown-Source-Estimated-Tokens": String(sectionIndex.estimatedTokens),
4244
+ "X-Docs-Markdown-Source-Utf8-Bytes": String(sectionIndex.utf8Bytes),
4245
+ "X-Docs-Markdown-Estimated-Tokens": String(estimateDocsMarkdownTokens(responseDocument)),
4246
+ "X-Docs-Markdown-Utf8-Bytes": String(docsMarkdownUtf8Bytes(responseDocument)),
4247
+ ...sectionIndexRequest.tokenBudget ? { "X-Docs-Markdown-Token-Budget": String(sectionIndexRequest.tokenBudget) } : {},
4248
+ ...sectionIndexRequest.byteBudget ? { "X-Docs-Markdown-Byte-Budget": String(sectionIndexRequest.byteBudget) } : {},
4249
+ ...lastModified ? { "Last-Modified": lastModified } : {}
4250
+ };
4251
+ if (requestMatchesDocsMarkdownEtag(request, etag) || requestHasFreshDocsMarkdownDate(request, lastModified)) {
4252
+ const { "Content-Type": _contentType, ...notModifiedHeaders } = responseHeaders;
4253
+ return new Response(null, {
4254
+ status: 304,
4255
+ headers: notModifiedHeaders
4256
+ });
4257
+ }
4258
+ return new Response(request.method.toUpperCase() === "HEAD" ? null : responseDocument, {
4259
+ status: 200,
4260
+ headers: responseHeaders
4261
+ });
4262
+ }
4263
+ const sectionResult = sectionRequest ? selectDocsMarkdownSection(document, sectionRequest) : void 0;
4264
+ const responseDocument = sectionResult?.document ?? document;
4265
+ const sectionCanonicalUrl = sectionResult?.found && sectionResult.section ? `${canonicalUrl}#${sectionResult.section.id}` : canonicalUrl;
4266
+ const sectionContentLocation = sectionRequest ? appendDocsMarkdownSectionQuery(contentLocation, sectionRequest) : contentLocation;
4267
+ const sectionHeaders = sectionResult ? {
4268
+ "X-Docs-Markdown-Section": sectionResult.section?.id ?? "",
4269
+ "X-Docs-Markdown-Section-Found": sectionResult.found ? "true" : "false",
4270
+ "X-Docs-Markdown-Section-Truncated": sectionResult.truncated ? "true" : "false",
4271
+ "X-Docs-Markdown-Estimated-Tokens": String(sectionResult.estimatedTokens),
4272
+ "X-Docs-Markdown-Utf8-Bytes": String(sectionResult.utf8Bytes),
4273
+ ...sectionResult.tokenBudget ? { "X-Docs-Markdown-Token-Budget": String(sectionResult.tokenBudget) } : {},
4274
+ ...sectionResult.byteBudget ? { "X-Docs-Markdown-Byte-Budget": String(sectionResult.byteBudget) } : {}
4275
+ } : {};
4276
+ const etag = createDocsMarkdownEtag(responseDocument);
3790
4277
  const lastModified = resolveDocsMarkdownHttpDate(options.lastModified ?? extractDocsMarkdownLastModified(document));
3791
4278
  const responseHeaders = {
3792
- ...sharedHeaders,
3793
- "Cache-Control": options.cacheControl ?? "public, max-age=0, s-maxage=3600",
4279
+ ...baseSharedHeaders,
4280
+ "Content-Location": sectionContentLocation,
4281
+ Link: `<${sectionCanonicalUrl}>; rel="canonical"`,
4282
+ "Cache-Control": sectionResult?.found === false ? "no-store" : options.cacheControl ?? "public, max-age=0, s-maxage=3600",
3794
4283
  "Content-Type": "text/markdown; charset=utf-8",
3795
4284
  ETag: etag,
4285
+ ...sectionHeaders,
3796
4286
  ...lastModified ? { "Last-Modified": lastModified } : {}
3797
4287
  };
3798
4288
  if (requestMatchesDocsMarkdownEtag(request, etag) || requestHasFreshDocsMarkdownDate(request, lastModified)) {
@@ -3802,7 +4292,10 @@ function createDocsMarkdownResponse(options) {
3802
4292
  headers: notModifiedHeaders
3803
4293
  });
3804
4294
  }
3805
- return new Response(document, { headers: responseHeaders });
4295
+ return new Response(responseDocument, {
4296
+ status: sectionResult?.found === false ? 404 : 200,
4297
+ headers: responseHeaders
4298
+ });
3806
4299
  }
3807
4300
  function findDocsMarkdownPage(entry, pages, requestedPath) {
3808
4301
  const normalizedRequest = normalizeRequestedMarkdownPath(entry, requestedPath);
@@ -3840,6 +4333,7 @@ function resolveDocsAgentDocumentContext({ entry = "docs", apiRoute, apiCatalog:
3840
4333
  llmsSections: resolveDocsLlmsTxtSections(llms),
3841
4334
  markdownAcceptHeader: markdown?.acceptHeader === false ? null : "text/markdown",
3842
4335
  markdownSignatureAgentHeader: markdown?.signatureAgentHeader === false ? null : DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER,
4336
+ markdownSectionDiscoveryEnabled: markdown?.sectionDiscovery !== false,
3843
4337
  apiCatalogEnabled: explicitApiCatalog ?? llms?.apiCatalog ?? true
3844
4338
  };
3845
4339
  }
@@ -3849,7 +4343,7 @@ function appendDocsMarkdownNegotiationStartLines(lines, context, variant) {
3849
4343
  }
3850
4344
  function appendDocsSearchStartLine(lines, context, variant) {
3851
4345
  if (!context.searchEnabled) return;
3852
- lines.push(variant === "skill" ? `- Search with ${context.apiRoute}?query={query}&audience=agent when you do not know the page.` : `- Search with ${context.apiRoute}?query={query}&audience=agent when the route is unknown.`);
4346
+ lines.push(variant === "skill" ? `- Search with ${context.apiRoute}?query={query}&audience=agent&response=structured when you do not know the page; optionally repeat framework, version, package, or tags filters.` : `- Search with ${context.apiRoute}?query={query}&audience=agent&response=structured when the route is unknown; optionally repeat framework, version, package, or tags filters.`);
3853
4347
  }
3854
4348
  function appendDocsOpenApiStartLine(lines, context, variant) {
3855
4349
  if (!context.openapiConfig.enabled || !context.openapiConfig.url) return;
@@ -3887,6 +4381,7 @@ function appendDocsAgentStartHereLines(lines, context, variant) {
3887
4381
  lines.push(variant === "skill" ? `- Fetch ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}; fall back to ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE} or ${agentSpecFallback}.` : `- Read ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE} first; fall back to ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE} or ${agentSpecFallback}.`);
3888
4382
  if (context.apiCatalogEnabled) lines.push(variant === "skill" ? `- Use ${DEFAULT_API_CATALOG_ROUTE} for standards-based API discovery.` : `- Use ${DEFAULT_API_CATALOG_ROUTE} for RFC 9727 API discovery.`);
3889
4383
  lines.push(variant === "skill" ? `- Use ${DEFAULT_AGENT_SKILLS_INDEX_ROUTE} for hashed skill discovery.` : `- Use ${DEFAULT_AGENT_SKILLS_INDEX_ROUTE} for integrity-checked skills.`, variant === "skill" ? `- Fetch /${context.normalizedEntry}.md for the root docs page.` : `- Read /${context.normalizedEntry}.md for the root docs page.`, variant === "skill" ? `- Fetch /${context.normalizedEntry}/{slug}.md for page-specific context.` : `- Read /${context.normalizedEntry}/{slug}.md for page-specific context.`);
4384
+ if (context.markdownSectionDiscoveryEnabled) lines.push(variant === "skill" ? `- Fetch /${context.normalizedEntry}/{slug}.md?sections to list section IDs and size estimates before requesting ?section={id}.` : `- Read /${context.normalizedEntry}/{slug}.md?sections before fetching ?section={id} when a full page is larger than needed.`);
3890
4385
  if (variant === "skill") {
3891
4386
  appendDocsMarkdownNegotiationStartLines(lines, context, variant);
3892
4387
  appendDocsSearchStartLine(lines, context, variant);
@@ -3934,6 +4429,7 @@ function appendDocsAgentPublicRouteLines(lines, context, variant) {
3934
4429
  lines.push(`- Agent instructions: ${DEFAULT_AGENTS_MD_ROUTE}`, `- Agent instructions well-known alias: ${DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE}`, `- Agent instructions API format: ${context.apiRoute}?format=agents`, `- Skill document: ${DEFAULT_SKILL_MD_ROUTE}`, `- Skill well-known alias: ${DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE}`, `- Skill API format: ${context.apiRoute}?format=skill`, `- Agent discovery: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}`, `- Agent discovery fallback: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}`);
3935
4430
  if (context.apiCatalogEnabled) lines.push(`- API catalog (RFC 9727): ${DEFAULT_API_CATALOG_ROUTE}`);
3936
4431
  lines.push(`- Agent Skills index: ${DEFAULT_AGENT_SKILLS_INDEX_ROUTE}`, `- Agent Skills artifacts: ${DEFAULT_AGENT_SKILLS_ROUTE_PATTERN}`, `- Markdown root: /${context.normalizedEntry}.md`, `- Markdown pages: /${context.normalizedEntry}/{slug}.md`);
4432
+ if (context.markdownSectionDiscoveryEnabled) lines.push(`- Markdown section index: /${context.normalizedEntry}/{slug}.md?sections`, `- Markdown section fetch: /${context.normalizedEntry}/{slug}.md?section={id}&tokenBudget={tokens}`);
3937
4433
  if (context.robotsEnabled) lines.push(`- Robots policy: ${DEFAULT_AGENT_DISCOVERY_ROBOTS_TXT_ROUTE}`);
3938
4434
  appendDocsLlmsRouteLines(lines, context);
3939
4435
  appendDocsOpenApiRouteLines(lines, context);
@@ -3942,6 +4438,7 @@ function appendDocsAgentPublicRouteLines(lines, context, variant) {
3942
4438
  return;
3943
4439
  }
3944
4440
  lines.push(`- Agent instructions: ${DEFAULT_AGENTS_MD_ROUTE}`, `- Agent instructions well-known alias: ${DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE}`, `- Agent instructions API format: ${context.apiRoute}?format=agents`, `- Agent instructions aliases: ${DEFAULT_AGENT_MD_ROUTE}, ${DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE}`, `- Site skill: ${DEFAULT_SKILL_MD_ROUTE}`, `- Site skill well-known alias: ${DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE}`, `- Site skill API format: ${context.apiRoute}?format=skill`, `- Markdown root: /${context.normalizedEntry}.md`, `- Markdown pages: /${context.normalizedEntry}/{slug}.md`, `- Agent discovery: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}`, `- Agent discovery fallback: ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}`);
4441
+ if (context.markdownSectionDiscoveryEnabled) lines.push(`- Markdown section index: /${context.normalizedEntry}/{slug}.md?sections`, `- Markdown section fetch: /${context.normalizedEntry}/{slug}.md?section={id}&tokenBudget={tokens}`);
3945
4442
  if (context.apiCatalogEnabled) lines.push(`- API catalog (RFC 9727): ${DEFAULT_API_CATALOG_ROUTE}`);
3946
4443
  lines.push(`- Agent Skills index: ${DEFAULT_AGENT_SKILLS_INDEX_ROUTE}`, `- Agent Skills artifacts: ${DEFAULT_AGENT_SKILLS_ROUTE_PATTERN}`);
3947
4444
  appendDocsLlmsRouteLines(lines, context);
@@ -4024,6 +4521,7 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
4024
4521
  const openapiUrl = resolveDocsOpenApiDiscoveryUrl(openapiConfig, resolvedApiRoute);
4025
4522
  const agentContractMcpTools = resolveDocsAgentContractMcpTools(mcp);
4026
4523
  const apiCatalogEnabled = explicitApiCatalog ?? llms?.apiCatalog ?? true;
4524
+ const markdownSectionDiscoveryEnabled = markdown?.sectionDiscovery !== false;
4027
4525
  const protectedResource = mcp.enabled && mcp.security?.authenticate ? mcp.security.protectedResource : void 0;
4028
4526
  const protectedResourceMetadataRoutes = protectedResource ? getDocsMcpProtectedResourceMetadataRoutes(mcp.route) : [];
4029
4527
  return {
@@ -4047,6 +4545,7 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
4047
4545
  },
4048
4546
  capabilities: {
4049
4547
  markdownRoutes: true,
4548
+ markdownSectionDiscovery: markdownSectionDiscoveryEnabled,
4050
4549
  agentMdOverrides: true,
4051
4550
  agentBlocks: true,
4052
4551
  structuredAgentContracts: true,
@@ -4103,6 +4602,16 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
4103
4602
  pagePattern: `/${normalizedEntry}/{slug}.md`,
4104
4603
  rootPage: `/${normalizedEntry}.md`,
4105
4604
  apiPattern: apiQueryRoute("format=markdown&path={slug}"),
4605
+ sectionDiscovery: {
4606
+ enabled: markdownSectionDiscoveryEnabled,
4607
+ ...markdownSectionDiscoveryEnabled ? {
4608
+ format: DOCS_MARKDOWN_SECTION_INDEX_FORMAT,
4609
+ indexParam: "sections",
4610
+ sectionParam: "section",
4611
+ tokenBudgetParam: "tokenBudget",
4612
+ byteBudgetParam: "byteBudget"
4613
+ } : {}
4614
+ },
4106
4615
  resolutionOrder: [
4107
4616
  "agent.md",
4108
4617
  "agent audience projection",
@@ -4190,12 +4699,29 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
4190
4699
  enabled: searchEnabled,
4191
4700
  endpoint: apiQueryRoute("query={query}"),
4192
4701
  agentEndpoint: apiQueryRoute("query={query}&audience=agent"),
4702
+ structuredAgentEndpoint: apiQueryRoute("query={query}&audience=agent&response=structured"),
4193
4703
  method: "GET",
4194
4704
  queryParam: "query",
4195
4705
  localeParam: "lang",
4196
4706
  audienceParam: "audience",
4197
4707
  defaultAudience: "human",
4198
- supportedAudiences: ["human", "agent"]
4708
+ supportedAudiences: ["human", "agent"],
4709
+ responseParam: "response",
4710
+ structuredResponseValue: "structured",
4711
+ responseFormat: "docs-search.v1",
4712
+ filterParams: {
4713
+ framework: "framework",
4714
+ version: "version",
4715
+ package: "package",
4716
+ tags: "tags"
4717
+ },
4718
+ repeatedFilterParams: [
4719
+ "framework",
4720
+ "version",
4721
+ "package",
4722
+ "tags"
4723
+ ],
4724
+ warningsField: "warnings"
4199
4725
  },
4200
4726
  agents: {
4201
4727
  enabled: true,
@@ -4364,4 +4890,4 @@ function toYamlString(value) {
4364
4890
  }
4365
4891
 
4366
4892
  //#endregion
4367
- export { renderDocsAgentsDocument as $, DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE as $t, buildDocsAgentFeedbackSchema as A, buildDocsSitemapManifest as At, getDocsMarkdownVaryHeader as B, renderDocsRelatedMarkdownLines as Bt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as C, resolveDocsAudienceExposure as Ct, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as D, DEFAULT_SITEMAP_MD_ROUTE as Dt, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as E, DEFAULT_SITEMAP_MD_DOCS_ROUTE as Et, createDocsStandardsDiscoveryResponse as F, resolveDocsSitemapConfig as Ft, isDocsDiagnosticsRequest as G, PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS as Gt, isDocsAgentDiscoveryRequest as H, PAGE_AGENT_CONTRACT_FIELDS as Ht, detectDocsMarkdownAgentRequest as I, resolveDocsSitemapPageLastmod as It, isDocsSkillRequest as J, normalizePageAgentFrontmatter as Jt, isDocsLlmsTxtPublicRequest as K, getPageAgentFrontmatterIssues as Kt, findDocsMarkdownPage as L, resolveDocsSitemapRequest as Lt, buildDocsDiagnostics as M, readDocsSitemapManifestFromContentMap as Mt, buildDocsMcpEndpointCandidates as N, renderDocsSitemapMarkdown as Nt, acceptsDocsMarkdown as O, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as Ot, createDocsMarkdownResponse as P, renderDocsSitemapXml as Pt, parseDocsAgentFeedbackData as Q, upsertPageAgentContractMarkdown as Qt, getDocsLlmsTxtMaxCharsIssue as R, toDocsSitemapMarkdownUrl as Rt, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as S, resolveDocsAgentMdxContent as St, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS as T, DEFAULT_SITEMAP_MANIFEST_PATH as Tt, isDocsAgentsRequest as U, PAGE_AGENT_CONTRACT_FIELD_SCHEMA as Ut, hasDocsMarkdownSignatureAgent as V, PAGE_AGENT_CONTRACT_END_MARKER as Vt, isDocsConfigRequest as W, PAGE_AGENT_CONTRACT_START_MARKER as Wt, normalizeDocsPathSegment as X, renderPageAgentFrontmatterYamlLines as Xt, matchesDocsLlmsTxtSection as Y, renderPageAgentContractMarkdown as Yt, normalizeDocsUrlPath as Z, stripGeneratedPageAgentContractMarkdown as Zt, DEFAULT_LLMS_TXT_MAX_CHARS as _, selectDocsLlmsTxtContent as _t, DEFAULT_AGENT_MD_ROUTE as a, getDocsMcpResourcePaths as an, resolveDocsAgentFeedbackConfig as at, DEFAULT_OPENAPI_SCHEMA_ROUTE as b, findDocsAudienceMdxIssues as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, isDocsMcpProtectedResourceMetadataPath as cn, resolveDocsLlmsTxtFormat as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, normalizeDocsMcpAuthorizationServerUrls as dn, resolveDocsMarkdownCanonicalUrl as dt, DEFAULT_MCP_PUBLIC_ROUTE as en, renderDocsLlmsTxt as et, DEFAULT_DOCS_CONFIG_ROUTE as f, normalizeDocsMcpEndpointPath as fn, resolveDocsMarkdownRecovery as ft, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as g, resolveDocsSkillFormat as gt, DEFAULT_LLMS_FULL_TXT_ROUTE as h, resolveDocsRequestApiRoute as ht, DEFAULT_AGENT_FEEDBACK_ROUTE as i, getDocsMcpProtectedResourceMetadataRoutes as in, resolveDocsAgentContractMcpTools as it, buildDocsConfigMap as j, createDocsSitemapResponse as jt, buildDocsAgentDiscoverySpec as k, DEFAULT_SITEMAP_XML_ROUTE as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, isDocsMcpRequest as ln, resolveDocsLlmsTxtRequest as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, resolveDocsMcpResourceLocation as mn, resolveDocsOpenApiDiscoveryConfig as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, DEFAULT_MCP_WELL_KNOWN_ROUTE as nn, renderDocsMarkdownNotFound as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, hasDocsMcpProtectedResourceConfig as on, resolveDocsAgentFeedbackRequest as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, resolveDocsMcpProtectedResourceMetadataLocation as pn, resolveDocsMarkdownRequest as pt, isDocsPublicGetRequest as q, hasStructuredPageAgentContract as qt, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, buildDocsMcpProtectedResourceMetadataRoute as rn, renderDocsSkillDocument as rt, DEFAULT_AGENT_SPEC_ROUTE as s, isDocsMcpOAuthScopeToken as sn, resolveDocsAgentsFormat as st, DEFAULT_AGENTS_MD_ROUTE as t, DEFAULT_MCP_ROUTE as tn, renderDocsMarkdownDocument as tt, DEFAULT_DOCS_API_ROUTE as u, isDocsMcpResourcePath as un, resolveDocsLlmsTxtSections as ut, DEFAULT_LLMS_TXT_ROUTE as v, toDocsMarkdownUrl as vt, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as w, resolveDocsAudienceMdxContent as wt, DEFAULT_SKILL_MD_ROUTE as x, findDocsAudienceMdxTags as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, validateDocsAgentFeedbackPayload as yt, getDocsMarkdownCanonicalLinkHeader as z, normalizeDocsRelated as zt };
4893
+ export { matchesDocsLlmsTxtSection as $, PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS as $t, buildDocsAgentDiscoverySpec as A, resolveDocsAudienceMdxContent as At, findDocsMarkdownPage as B, renderDocsSitemapXml as Bt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as C, selectDocsMarkdownSection as Ct, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as D, findDocsAudienceMdxTags as Dt, DOCS_MARKDOWN_SECTION_INDEX_FORMAT as E, findDocsAudienceMdxIssues as Et, buildDocsMcpEndpointCandidates as F, DEFAULT_SITEMAP_XML_ROUTE as Ft, isDocsAgentDiscoveryRequest as G, findDocsMarkdownSection as Gt, getDocsMarkdownCanonicalLinkHeader as H, resolveDocsSitemapPageLastmod as Ht, collectDocsMarkdownSections as I, buildDocsSitemapManifest as It, isDocsDiagnosticsRequest as J, renderDocsRelatedMarkdownLines as Jt, isDocsAgentsRequest as K, parseDocsMarkdownSections as Kt, createDocsMarkdownResponse as L, createDocsSitemapResponse as Lt, buildDocsConfigMap as M, DEFAULT_SITEMAP_MD_DOCS_ROUTE as Mt, buildDocsDiagnostics as N, DEFAULT_SITEMAP_MD_ROUTE as Nt, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as O, resolveDocsAgentMdxContent as Ot, buildDocsMarkdownSectionIndex as P, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as Pt, isDocsSkillRequest as Q, PAGE_AGENT_CONTRACT_START_MARKER as Qt, createDocsStandardsDiscoveryResponse as R, readDocsSitemapManifestFromContentMap as Rt, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as S, resolveDocsMcpResourceLocation as Sn, selectDocsLlmsTxtContent as St, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS as T, validateDocsAgentFeedbackPayload as Tt, getDocsMarkdownVaryHeader as U, resolveDocsSitemapRequest as Ut, getDocsLlmsTxtMaxCharsIssue as V, resolveDocsSitemapConfig as Vt, hasDocsMarkdownSignatureAgent as W, toDocsSitemapMarkdownUrl as Wt, isDocsMarkdownSectionIndexRequest as X, PAGE_AGENT_CONTRACT_FIELDS as Xt, isDocsLlmsTxtPublicRequest as Y, PAGE_AGENT_CONTRACT_END_MARKER as Yt, isDocsPublicGetRequest as Z, PAGE_AGENT_CONTRACT_FIELD_SCHEMA as Zt, DEFAULT_LLMS_TXT_MAX_CHARS as _, isDocsMcpRequest as _n, resolveDocsMarkdownRequest as _t, DEFAULT_AGENT_MD_ROUTE as a, stripGeneratedPageAgentContractMarkdown as an, renderDocsMarkdownDocument as at, DEFAULT_OPENAPI_SCHEMA_ROUTE as b, normalizeDocsMcpEndpointPath as bn, resolveDocsRequestApiRoute as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, DEFAULT_MCP_PUBLIC_ROUTE as cn, resolveDocsAgentContractMcpTools as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, buildDocsMcpProtectedResourceMetadataRoute as dn, resolveDocsAgentsFormat as dt, getPageAgentFrontmatterIssues as en, normalizeDocsPathSegment as et, DEFAULT_DOCS_CONFIG_ROUTE as f, getDocsMcpProtectedResourceMetadataRoutes as fn, resolveDocsLlmsTxtFormat as ft, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as g, isDocsMcpProtectedResourceMetadataPath as gn, resolveDocsMarkdownRecovery as gt, DEFAULT_LLMS_FULL_TXT_ROUTE as h, isDocsMcpOAuthScopeToken as hn, resolveDocsMarkdownCanonicalUrl as ht, DEFAULT_AGENT_FEEDBACK_ROUTE as i, renderPageAgentFrontmatterYamlLines as in, renderDocsLlmsTxt as it, buildDocsAgentFeedbackSchema as j, DEFAULT_SITEMAP_MANIFEST_PATH as jt, acceptsDocsMarkdown as k, resolveDocsAudienceExposure as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, DEFAULT_MCP_ROUTE as ln, resolveDocsAgentFeedbackConfig as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, hasDocsMcpProtectedResourceConfig as mn, resolveDocsLlmsTxtSections as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, normalizePageAgentFrontmatter as nn, parseDocsAgentFeedbackData as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, upsertPageAgentContractMarkdown as on, renderDocsMarkdownNotFound as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, getDocsMcpResourcePaths as pn, resolveDocsLlmsTxtRequest as pt, isDocsConfigRequest as q, normalizeDocsRelated as qt, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, renderPageAgentContractMarkdown as rn, renderDocsAgentsDocument as rt, DEFAULT_AGENT_SPEC_ROUTE as s, DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE as sn, renderDocsSkillDocument as st, DEFAULT_AGENTS_MD_ROUTE as t, hasStructuredPageAgentContract as tn, normalizeDocsUrlPath as tt, DEFAULT_DOCS_API_ROUTE as u, DEFAULT_MCP_WELL_KNOWN_ROUTE as un, resolveDocsAgentFeedbackRequest as ut, DEFAULT_LLMS_TXT_ROUTE as v, isDocsMcpResourcePath as vn, resolveDocsMarkdownSectionRequest as vt, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as w, toDocsMarkdownUrl as wt, DEFAULT_SKILL_MD_ROUTE as x, resolveDocsMcpProtectedResourceMetadataLocation as xn, resolveDocsSkillFormat as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, normalizeDocsMcpAuthorizationServerUrls as yn, resolveDocsOpenApiDiscoveryConfig as yt, detectDocsMarkdownAgentRequest as z, renderDocsSitemapMarkdown as zt };