@farming-labs/docs 0.2.72 → 0.2.74

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 (55) hide show
  1. package/dist/{agent-pS2nNQS3.mjs → agent-BJ0KXN-A.mjs} +583 -765
  2. package/dist/{agent-DbDfIqhe.mjs → agent-D0LEY2Vy.mjs} +4 -3
  3. package/dist/{agent-evals-CjYzCQMZ.mjs → agent-evals-LIScgQVm.mjs} +86 -43
  4. package/dist/{agent-export-CpQhD8eA.mjs → agent-export-B92pNe6g.mjs} +12 -11
  5. package/dist/agent-skills-bundle.d.mts +1 -1
  6. package/dist/{agent-skills-server-DZnNB4_S.d.mts → agent-skills-server-BqvIGQb1.d.mts} +2 -2
  7. package/dist/{agent-skills-server-BPVv4gMg.mjs → agent-skills-server-noFn1l_p.mjs} +1 -1
  8. package/dist/agent-skills-vite.d.mts +3 -3
  9. package/dist/agent-skills-vite.mjs +2 -2
  10. package/dist/{agents-B-1h9Jlm.mjs → agents-C228QGbp.mjs} +10 -9
  11. package/dist/cli/index.mjs +34 -30
  12. package/dist/client/react.d.mts +1 -1
  13. package/dist/{cloud-ask-ai-D9gIN4Vr.d.mts → cloud-ask-ai-6X9pVjIY.d.mts} +1 -1
  14. package/dist/{cloud-CyysfDny.mjs → cloud-pdNC-tyj.mjs} +3 -3
  15. package/dist/{codeblocks-DAj7EAwt.mjs → codeblocks-CFuurVIH.mjs} +2 -2
  16. package/dist/{dev-qE7MYEh9.mjs → dev-Cc1cFFj-.mjs} +2 -2
  17. package/dist/docs-cloud-server.d.mts +2 -2
  18. package/dist/docs-cloud-server.mjs +1 -1
  19. package/dist/{doctor-CBy8-tPu.mjs → doctor-CgrUZ3tY.mjs} +15 -14
  20. package/dist/{downgrade-DCxezPZI.mjs → downgrade-w7e6Se0L.mjs} +2 -2
  21. package/dist/{golden-evaluations-DGg_eHIY.mjs → golden-evaluations-DTEPZeb0.mjs} +4 -3
  22. package/dist/index.d.mts +72 -6
  23. package/dist/index.mjs +9 -8
  24. package/dist/{init-p1MHf06G.mjs → init-DAkI0Lkf.mjs} +3 -3
  25. package/dist/markdown-rendering.d.mts +75 -0
  26. package/dist/markdown-rendering.mjs +618 -0
  27. package/dist/markdown-sections-7OoA7ylx.mjs +1492 -0
  28. package/dist/{mcp-BNK45dzD.mjs → mcp-YD37HlPY.mjs} +12 -9
  29. package/dist/mcp.d.mts +13 -2
  30. package/dist/mcp.mjs +121 -60
  31. package/dist/{metadata-D6qlWDu-.mjs → metadata-N252j5_a.mjs} +1 -1
  32. package/dist/{package-version-BXHcIm1T.mjs → package-version-n5AFur8a.mjs} +1 -1
  33. package/dist/{reading-time-DvTuW2Iy.mjs → prompt-references-BIS1eXt4.mjs} +158 -4
  34. package/dist/{search-1aftosa5.d.mts → retrieval-digest-9Kp3uSaZ.d.mts} +69 -5
  35. package/dist/{review-Cace7A2c.mjs → review-Dbzkdl6K.mjs} +10 -9
  36. package/dist/{robots-DmE_wXvG.mjs → robots-DUO0r4UI.mjs} +6 -5
  37. package/dist/{robots-C2SindI5.mjs → robots-RbgmSvPH.mjs} +2 -2
  38. package/dist/{search-BbArHODP.mjs → search-DIyIl-tE.mjs} +1288 -149
  39. package/dist/{search-DB3svkNQ.mjs → search-hcqaEZVN.mjs} +66 -27
  40. package/dist/server.d.mts +5 -5
  41. package/dist/server.mjs +10 -9
  42. package/dist/{sitemap-DPTLh_26.mjs → sitemap-jhkS_jYx.mjs} +10 -9
  43. package/dist/{sitemap-server-PUoOhplO.mjs → sitemap-server-BfyBM7_V.mjs} +1 -1
  44. package/dist/{standards-discovery-CYfiQE13.mjs → standards-discovery-BwL5ffGx.mjs} +4 -3
  45. package/dist/{standards-discovery-DRJ10g7B.d.mts → standards-discovery-CdrOE-05.d.mts} +5 -4
  46. package/dist/{types-B9DNNAdT.d.mts → types-clg5J1R4.d.mts} +60 -1
  47. package/dist/{upgrade-DDJQ5l6n.mjs → upgrade-oz-GChgt.mjs} +2 -2
  48. package/package.json +9 -1
  49. /package/dist/{cloud-ask-ai-hnJfj8-X.mjs → cloud-ask-ai-sbpjOR2K.mjs} +0 -0
  50. /package/dist/{code-blocks-qe0T8-xe.mjs → code-blocks-DnNVNK2M.mjs} +0 -0
  51. /package/dist/{config-z7_R0f86.mjs → config-Wcdj-D0a.mjs} +0 -0
  52. /package/dist/{errors-Cc_qplZU.mjs → errors-DbOhkE1h.mjs} +0 -0
  53. /package/dist/{i18n-CCaFUnAN.mjs → i18n-hHVWcflJ.mjs} +0 -0
  54. /package/dist/{templates-BJnf6B8l.mjs → templates-C6avM0U3.mjs} +0 -0
  55. /package/dist/{utils-C4RC8Zq_.mjs → utils-DpiIioYb.mjs} +0 -0
@@ -1,13 +1,15 @@
1
- import "./agent-pS2nNQS3.mjs";
2
- import { I as resolveDocsPublishedAgentSkill } from "./standards-discovery-CYfiQE13.mjs";
3
- import "./search-BbArHODP.mjs";
4
- import "./sitemap-server-PUoOhplO.mjs";
5
- import "./agent-evals-CjYzCQMZ.mjs";
1
+ import "./agent-BJ0KXN-A.mjs";
2
+ import "./markdown-sections-7OoA7ylx.mjs";
3
+ import { L as resolveDocsPublishedAgentSkill } from "./standards-discovery-BwL5ffGx.mjs";
4
+ import "./search-DIyIl-tE.mjs";
5
+ import { a as resolveDocsMetadataBaseUrl } from "./metadata-N252j5_a.mjs";
6
+ import "./sitemap-server-BfyBM7_V.mjs";
7
+ import "./agent-evals-LIScgQVm.mjs";
6
8
  import { createFilesystemDocsMcpSource, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
7
- import "./code-blocks-qe0T8-xe.mjs";
8
- import { t as resolveConfiguredAgentSkills } from "./agent-skills-server-BPVv4gMg.mjs";
9
+ import "./code-blocks-DnNVNK2M.mjs";
10
+ import { t as resolveConfiguredAgentSkills } from "./agent-skills-server-noFn1l_p.mjs";
9
11
  import "./server.mjs";
10
- import { _ as resolveDocsContentDir, d as readNavTitle, g as resolveDocsConfigPath, i as hasTopLevelProperty, l as readBooleanProperty, n as extractObjectLiteral, o as loadDocsConfigModuleResult, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-z7_R0f86.mjs";
12
+ import { _ as resolveDocsContentDir, d as readNavTitle, g as resolveDocsConfigPath, i as hasTopLevelProperty, l as readBooleanProperty, n as extractObjectLiteral, o as loadDocsConfigModuleResult, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-Wcdj-D0a.mjs";
11
13
  import { existsSync, readFileSync } from "node:fs";
12
14
  import path from "node:path";
13
15
  import pc from "picocolors";
@@ -42,7 +44,8 @@ async function runMcp(options = {}) {
42
44
  rootDir,
43
45
  entry,
44
46
  contentDir,
45
- siteTitle: navTitle ?? "Documentation"
47
+ siteTitle: navTitle ?? "Documentation",
48
+ baseUrl: loadedConfig ? resolveDocsMetadataBaseUrl(loadedConfig) : void 0
46
49
  });
47
50
  const resolvedMcp = resolveDocsMcpConfig(mcp ?? true, { defaultName: navTitle ?? "@farming-labs/docs" });
48
51
  await runDocsMcpStdio({
package/dist/mcp.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { Ft as DocsMcpAuthenticate, Kt as DocsObservabilityConfig, Nt as DocsMcpAllowedOrigins, Pt as DocsMcpAuthPrincipal, Qn as PageAgentFrontmatter, Rt as DocsMcpConfig, cn as DocsSearchConfig, kn as DocsTelemetryFramework, qn as OrderingItem, rt as DocsAnalyticsConfig, wn as DocsTelemetryConfig, yn as DocsSearchSourcePage } from "./types-B9DNNAdT.mjs";
2
- import { I as DocsPublishedAgentSkill } from "./standards-discovery-DRJ10g7B.mjs";
1
+ import { En as DocsTelemetryConfig, Ft as DocsMcpAuthenticate, Kt as DocsObservabilityConfig, Nt as DocsMcpAllowedOrigins, Pt as DocsMcpAuthPrincipal, Rt as DocsMcpConfig, Xt as DocsRetrievalSourceProvenance, Yn as OrderingItem, er as PageAgentFrontmatter, jn as DocsTelemetryFramework, rt as DocsAnalyticsConfig, un as DocsSearchConfig, xn as DocsSearchSourcePage } from "./types-clg5J1R4.mjs";
2
+ import { L as DocsPublishedAgentSkill } from "./standards-discovery-CdrOE-05.mjs";
3
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
 
5
5
  //#region src/mcp.d.ts
@@ -12,6 +12,7 @@ interface DocsMcpPage {
12
12
  agent?: PageAgentFrontmatter;
13
13
  icon?: string;
14
14
  sourcePath?: string;
15
+ lastmod?: string;
15
16
  lastModified?: string;
16
17
  locale?: string;
17
18
  framework?: string;
@@ -21,6 +22,7 @@ interface DocsMcpPage {
21
22
  rawContent?: string;
22
23
  agentContent?: string;
23
24
  agentRawContent?: string;
25
+ agentLastModified?: string;
24
26
  agentFallbackContent?: string;
25
27
  agentFallbackRawContent?: string;
26
28
  }
@@ -126,6 +128,8 @@ interface DocsMcpContextSource {
126
128
  version?: string;
127
129
  package?: string[];
128
130
  tags?: string[];
131
+ /** Canonical, scope-aware provenance for this retrieved source. */
132
+ source?: DocsRetrievalSourceProvenance;
129
133
  score?: number;
130
134
  content: string;
131
135
  /** JavaScript string length for this source's content only. */
@@ -168,6 +172,8 @@ interface DocsMcpContextOptions {
168
172
  tokenBudget: number;
169
173
  entry?: string;
170
174
  siteTitle?: string;
175
+ /** Public docs origin used to resolve canonical source URLs. */
176
+ baseUrl?: string;
171
177
  /** Maximum number of ranked, deduplicated candidates to render. Defaults to 50. */
172
178
  maxResults?: number;
173
179
  }
@@ -193,6 +199,10 @@ interface DocsMcpNavigationTree {
193
199
  interface DocsMcpSource {
194
200
  entry?: string;
195
201
  siteTitle?: string;
202
+ /** Canonical public docs origin used for retrieval source URLs. */
203
+ baseUrl?: string;
204
+ /** Resolve a requested locale to the locale whose pages will actually be returned. */
205
+ resolveLocale?(locale?: string, context?: DocsMcpRequestContext): string | undefined;
196
206
  getPages(locale?: string, context?: DocsMcpRequestContext): DocsMcpPage[] | Promise<DocsMcpPage[]>;
197
207
  getNavigation(locale?: string, context?: DocsMcpRequestContext): DocsMcpNavigationTree | Promise<DocsMcpNavigationTree>;
198
208
  /** Reusable Agent Skills exposed as progressive-disclosure MCP resources. */
@@ -277,6 +287,7 @@ interface CreateFilesystemDocsMcpSourceOptions {
277
287
  entry?: string;
278
288
  contentDir?: string;
279
289
  siteTitle?: string;
290
+ baseUrl?: string;
280
291
  ordering?: "alphabetical" | "numeric" | OrderingItem[];
281
292
  }
282
293
  declare const DEFAULT_DOCS_MCP_MAX_BODY_BYTES: number;
package/dist/mcp.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { a as emitDocsAnalyticsEvent, i as emitDocsAgentTraceEvent, n as createDocsAgentTraceContext, r as createDocsAgentTraceId } from "./analytics-Bx44lg6d.mjs";
2
- import { At as resolveDocsAudienceMdxContent, Gt as findDocsMarkdownSection, Jt as renderDocsRelatedMarkdownLines, Kt as parseDocsMarkdownSections, Sn as resolveDocsMcpResourceLocation, bn as normalizeDocsMcpEndpointPath, gn as isDocsMcpProtectedResourceMetadataPath, hn as isDocsMcpOAuthScopeToken, nn as normalizePageAgentFrontmatter, on as upsertPageAgentContractMarkdown, qt as normalizeDocsRelated, tn as hasStructuredPageAgentContract, vn as isDocsMcpResourcePath, xn as resolveDocsMcpProtectedResourceMetadataLocation, yn as normalizeDocsMcpAuthorizationServerUrls } from "./agent-pS2nNQS3.mjs";
3
- import "./standards-discovery-CYfiQE13.mjs";
4
- import { A as stripGeneratedAgentProvenance, F as emitDocsTelemetryAgentSurfaceEvent, L as emitDocsTelemetryMcpToolEvent, M as resolvePageSidebarFolderIndexBehavior, R as emitDocsTelemetryProjectEvent, S as normalizeAgentScopeValues, b as normalizeAgentFramework, d as performDocsSearch, f as performDocsSearchWithMetadata, u as normalizeDocsSearchFilters, v as agentVersionConstraintMatches, x as normalizeAgentLocale, y as agentVersionConstraintsOverlap } from "./search-BbArHODP.mjs";
2
+ import { Kt as normalizeDocsRelated, an as isDocsMcpResourcePath, cn as resolveDocsMcpProtectedResourceMetadataLocation, jt as resolveDocsAudienceMdxContent, ln as resolveDocsMcpResourceLocation, nn as isDocsMcpOAuthScopeToken, on as normalizeDocsMcpAuthorizationServerUrls, qt as renderDocsRelatedMarkdownLines, rn as isDocsMcpProtectedResourceMetadataPath, sn as normalizeDocsMcpEndpointPath } from "./agent-BJ0KXN-A.mjs";
3
+ import { S as upsertPageAgentContractMarkdown, _ as hasStructuredPageAgentContract, o as findDocsMarkdownSection, s as parseDocsMarkdownSections, v as normalizePageAgentFrontmatter } from "./markdown-sections-7OoA7ylx.mjs";
4
+ import "./standards-discovery-BwL5ffGx.mjs";
5
+ import { C as agentVersionConstraintsOverlap, E as normalizeAgentScopeValues, I as stripGeneratedAgentProvenance, R as resolvePageSidebarFolderIndexBehavior, S as agentVersionConstraintMatches, T as normalizeAgentLocale, U as emitDocsTelemetryMcpToolEvent, V as emitDocsTelemetryAgentSurfaceEvent, W as emitDocsTelemetryProjectEvent, f as normalizeDocsSearchFilters, k as isDocsRetrievalCanonicalUrl, m as performDocsSearchWithMetadata, p as performDocsSearch, w as normalizeAgentFramework } from "./search-DIyIl-tE.mjs";
5
6
  import matter from "gray-matter";
6
7
  import fs from "node:fs";
7
8
  import path from "node:path";
@@ -1253,18 +1254,27 @@ const DOCS_CONFIG_SCHEMA_OPTIONS_TEMPLATE = [
1253
1254
  default: true,
1254
1255
  description: "Built-in simple search, Typesense, Algolia, MCP, or a custom adapter.",
1255
1256
  docs: "/docs/customization/search",
1256
- children: [{
1257
- path: "search.provider",
1258
- name: "provider",
1259
- type: "\"simple\" | \"typesense\" | \"algolia\" | \"mcp\" | \"custom\"",
1260
- default: "simple",
1261
- description: "Search backend used by the docs UI and MCP search tool."
1262
- }, {
1263
- path: "search.maxResults",
1264
- name: "maxResults",
1265
- type: "number",
1266
- description: "Maximum result count returned by search requests."
1267
- }]
1257
+ children: [
1258
+ {
1259
+ path: "search.provider",
1260
+ name: "provider",
1261
+ type: "\"simple\" | \"typesense\" | \"algolia\" | \"mcp\" | \"custom\"",
1262
+ default: "simple",
1263
+ description: "Search backend used by the docs UI and MCP search tool."
1264
+ },
1265
+ {
1266
+ path: "search.maxResults",
1267
+ name: "maxResults",
1268
+ type: "number",
1269
+ description: "Maximum result count returned by search requests."
1270
+ },
1271
+ {
1272
+ path: "search.syncNamespace",
1273
+ name: "syncNamespace",
1274
+ type: "string",
1275
+ description: "Stable ownership namespace used to isolate and safely prune this corpus in a shared hosted index."
1276
+ }
1277
+ ]
1268
1278
  },
1269
1279
  {
1270
1280
  path: "cloud",
@@ -1690,7 +1700,7 @@ const searchFilterValueSchema = z.union([z.string().trim().min(1).max(128), z.ar
1690
1700
  const searchDocsInputSchema = z.object({
1691
1701
  query: z.string().trim().min(1),
1692
1702
  limit: z.number().int().min(1).max(25).optional(),
1693
- locale: z.string().min(1).optional(),
1703
+ locale: z.string().trim().min(1).max(128).optional(),
1694
1704
  audience: z.enum(["human", "agent"]).optional(),
1695
1705
  framework: searchFilterValueSchema.optional(),
1696
1706
  version: searchFilterValueSchema.optional(),
@@ -1699,7 +1709,7 @@ const searchDocsInputSchema = z.object({
1699
1709
  });
1700
1710
  const readPageInputSchema = z.object({
1701
1711
  path: z.string().min(1),
1702
- locale: z.string().min(1).optional(),
1712
+ locale: z.string().trim().min(1).max(128).optional(),
1703
1713
  section: z.string().trim().min(1).optional(),
1704
1714
  maxChars: z.number().int().min(256).max(1e6).optional()
1705
1715
  });
@@ -1708,7 +1718,7 @@ const listTasksInputSchema = z.object({
1708
1718
  framework: z.string().trim().min(1).optional(),
1709
1719
  version: z.string().trim().min(1).optional(),
1710
1720
  package: z.string().trim().min(1).optional(),
1711
- locale: z.string().min(1).optional()
1721
+ locale: z.string().trim().min(1).max(128).optional()
1712
1722
  });
1713
1723
  const readTaskInputSchema = readPageInputSchema;
1714
1724
  const pageAgentAppliesToOutputSchema = z.object({
@@ -1767,12 +1777,12 @@ const readTaskOutputSchema = z.object({
1767
1777
  }),
1768
1778
  contract: pageAgentContractOutputSchema
1769
1779
  });
1770
- const listPagesInputSchema = z.object({ locale: z.string().min(1).optional() });
1780
+ const listPagesInputSchema = z.object({ locale: z.string().trim().min(1).max(128).optional() });
1771
1781
  const listDocsInputSchema = z.object({
1772
1782
  section: z.string().trim().min(1).optional(),
1773
- locale: z.string().min(1).optional()
1783
+ locale: z.string().trim().min(1).max(128).optional()
1774
1784
  });
1775
- const getNavigationInputSchema = z.object({ locale: z.string().min(1).optional() });
1785
+ const getNavigationInputSchema = z.object({ locale: z.string().trim().min(1).max(128).optional() });
1776
1786
  const getConfigSchemaInputSchema = z.object({
1777
1787
  option: z.string().trim().min(1).optional(),
1778
1788
  query: z.string().trim().min(1).optional()
@@ -1785,7 +1795,7 @@ const getCodeExamplesInputSchema = z.object({
1785
1795
  language: z.string().trim().min(1).optional(),
1786
1796
  runnable: z.boolean().optional(),
1787
1797
  limit: z.number().int().min(1).max(50).optional(),
1788
- locale: z.string().min(1).optional()
1798
+ locale: z.string().trim().min(1).max(128).optional()
1789
1799
  });
1790
1800
  const getContextInputSchema = z.object({
1791
1801
  query: z.string().trim().min(1),
@@ -1793,7 +1803,7 @@ const getContextInputSchema = z.object({
1793
1803
  version: z.string().trim().min(1).optional(),
1794
1804
  package: searchFilterValueSchema.optional(),
1795
1805
  tags: searchFilterValueSchema.optional(),
1796
- locale: z.string().trim().min(1).optional(),
1806
+ locale: z.string().trim().min(1).max(128).optional(),
1797
1807
  tokenBudget: z.number().int().min(MIN_MCP_CONTEXT_TOKEN_BUDGET).max(MAX_MCP_CONTEXT_TOKEN_BUDGET).default(DEFAULT_MCP_CONTEXT_TOKEN_BUDGET)
1798
1808
  });
1799
1809
  const relatedLinkOutputSchema = z.object({ href: z.string() });
@@ -1853,6 +1863,37 @@ const navigationOutputSchema = z.object({
1853
1863
  }),
1854
1864
  markdown: z.string()
1855
1865
  });
1866
+ const retrievalSourceValueOutputSchema = z.string().max(128);
1867
+ const retrievalSourceValuesOutputSchema = z.array(retrievalSourceValueOutputSchema).max(16);
1868
+ const retrievalSourceScopeOutputSchema = z.object({
1869
+ audience: z.enum(["human", "agent"]),
1870
+ locale: retrievalSourceValuesOutputSchema.optional(),
1871
+ framework: retrievalSourceValuesOutputSchema.optional(),
1872
+ version: retrievalSourceValuesOutputSchema.optional(),
1873
+ versionGroups: z.array(retrievalSourceValuesOutputSchema).max(16).optional(),
1874
+ package: retrievalSourceValuesOutputSchema.optional(),
1875
+ tags: retrievalSourceValuesOutputSchema.optional(),
1876
+ truncated: z.array(z.enum([
1877
+ "framework",
1878
+ "version",
1879
+ "package",
1880
+ "tags"
1881
+ ])).max(4).optional(),
1882
+ conflicts: z.array(z.enum([
1883
+ "framework",
1884
+ "version",
1885
+ "package",
1886
+ "tags"
1887
+ ])).max(4).optional()
1888
+ });
1889
+ const retrievalSourceDigestOutputSchema = z.string().regex(/^sha256:[a-f\d]{64}$/iu);
1890
+ const retrievalSourceOutputSchema = z.object({
1891
+ canonicalUrl: z.string().max(4096).refine(isDocsRetrievalCanonicalUrl, "Expected a safe HTTP(S) URL or root-relative path"),
1892
+ scope: retrievalSourceScopeOutputSchema,
1893
+ lastModified: z.string().max(256).refine((value) => Number.isFinite(Date.parse(value)), "Expected a parseable modified time").optional(),
1894
+ digest: retrievalSourceDigestOutputSchema,
1895
+ indexGeneration: retrievalSourceDigestOutputSchema
1896
+ });
1856
1897
  const searchResultOutputSchema = z.object({
1857
1898
  id: z.string(),
1858
1899
  url: z.string(),
@@ -1864,7 +1905,8 @@ const searchResultOutputSchema = z.object({
1864
1905
  "text"
1865
1906
  ]),
1866
1907
  score: z.number().optional(),
1867
- section: z.string().optional()
1908
+ section: z.string().optional(),
1909
+ source: retrievalSourceOutputSchema.optional()
1868
1910
  });
1869
1911
  const searchFiltersOutputSchema = z.object({
1870
1912
  framework: z.array(z.string()).optional(),
@@ -1895,6 +1937,7 @@ const searchDocsOutputSchema = z.object({
1895
1937
  query: z.string(),
1896
1938
  audience: z.enum(["human", "agent"]),
1897
1939
  filters: searchFiltersOutputSchema,
1940
+ indexGeneration: retrievalSourceDigestOutputSchema,
1898
1941
  resultCount: z.number().int().nonnegative(),
1899
1942
  results: z.array(searchResultOutputSchema),
1900
1943
  warnings: z.array(searchWarningOutputSchema)
@@ -1984,6 +2027,7 @@ const contextSourceOutputSchema = z.object({
1984
2027
  version: z.string().optional(),
1985
2028
  package: z.array(z.string()).optional(),
1986
2029
  tags: z.array(z.string()).optional(),
2030
+ source: retrievalSourceOutputSchema.optional(),
1987
2031
  score: z.number().optional(),
1988
2032
  content: z.string(),
1989
2033
  chars: z.number().int().nonnegative(),
@@ -2155,6 +2199,8 @@ function createFilesystemDocsMcpSource(options = {}) {
2155
2199
  return {
2156
2200
  entry,
2157
2201
  siteTitle: options.siteTitle ?? "Documentation",
2202
+ baseUrl: options.baseUrl,
2203
+ resolveLocale: () => void 0,
2158
2204
  getPages,
2159
2205
  getNavigation
2160
2206
  };
@@ -2191,10 +2237,13 @@ async function createDocsMcpServer(options) {
2191
2237
  };
2192
2238
  const telemetryFramework = options.telemetryFramework ?? "mcp";
2193
2239
  function getSourcePages(locale) {
2194
- return options.source.getPages(locale, options.requestContext);
2240
+ return options.source.getPages(resolveSourceLocale(locale), options.requestContext);
2195
2241
  }
2196
2242
  function getSourceNavigation(locale) {
2197
- return options.source.getNavigation(locale, options.requestContext);
2243
+ return options.source.getNavigation(resolveSourceLocale(locale), options.requestContext);
2244
+ }
2245
+ function resolveSourceLocale(locale) {
2246
+ return options.source.resolveLocale ? options.source.resolveLocale(locale, options.requestContext) : locale;
2198
2247
  }
2199
2248
  function getSourceSkills() {
2200
2249
  return options.source.getSkills?.(options.requestContext) ?? [];
@@ -2810,6 +2859,7 @@ async function createDocsMcpServer(options) {
2810
2859
  const startedAt = nowMs();
2811
2860
  const resolvedLimit = limit ?? 10;
2812
2861
  const resolvedAudience = audience ?? "agent";
2862
+ const resolvedLocale = resolveSourceLocale(locale);
2813
2863
  const filters = {
2814
2864
  framework,
2815
2865
  version,
@@ -2838,13 +2888,15 @@ async function createDocsMcpServer(options) {
2838
2888
  });
2839
2889
  try {
2840
2890
  const searchResponse = await performDocsSearchWithMetadata({
2841
- pages: toSearchSourcePages(dedupePages(await getSourcePages(locale))),
2891
+ pages: toSearchSourcePages(dedupePages(await options.source.getPages(resolvedLocale, options.requestContext))),
2842
2892
  query,
2843
2893
  search: toolSearchConfig ?? true,
2844
2894
  audience: resolvedAudience,
2845
2895
  filters,
2846
- locale,
2896
+ locale: resolvedLocale,
2847
2897
  siteTitle: options.source.siteTitle,
2898
+ baseUrl: options.source.baseUrl ?? (options.requestContext?.request ? new URL(options.requestContext.request.url).origin : void 0),
2899
+ syncBaseUrl: options.source.baseUrl ?? null,
2848
2900
  limit: resolvedLimit
2849
2901
  });
2850
2902
  const elapsed = durationMs(startedAt);
@@ -3011,6 +3063,7 @@ async function createDocsMcpServer(options) {
3011
3063
  annotations: { readOnlyHint: true }
3012
3064
  }, async ({ query, framework, version, package: packageName, tags, locale, tokenBudget }) => {
3013
3065
  const startedAt = nowMs();
3066
+ const resolvedLocale = resolveSourceLocale(locale);
3014
3067
  const trace = createDocsAgentTraceContext("mcp.tool.get_context");
3015
3068
  const callSpanId = createDocsAgentTraceId("span");
3016
3069
  await emitDocsAgentTraceEvent(options.observability, {
@@ -3035,16 +3088,17 @@ async function createDocsMcpServer(options) {
3035
3088
  });
3036
3089
  try {
3037
3090
  const result = await buildDocsMcpContext({
3038
- pages: dedupePages(await getSourcePages(locale)),
3091
+ pages: dedupePages(await options.source.getPages(resolvedLocale, options.requestContext)),
3039
3092
  query,
3040
3093
  framework,
3041
3094
  version,
3042
3095
  package: packageName,
3043
3096
  tags,
3044
- locale,
3097
+ locale: resolvedLocale,
3045
3098
  tokenBudget,
3046
3099
  entry: options.source.entry,
3047
- siteTitle: options.source.siteTitle
3100
+ siteTitle: options.source.siteTitle,
3101
+ baseUrl: options.source.baseUrl ?? (options.requestContext?.request ? new URL(options.requestContext.request.url).origin : void 0)
3048
3102
  });
3049
3103
  const elapsed = durationMs(startedAt);
3050
3104
  await emitDocsAnalyticsEvent(options.analytics, {
@@ -3198,11 +3252,10 @@ async function createDocsMcpServer(options) {
3198
3252
  };
3199
3253
  }
3200
3254
  const fullDocument = renderPageDocument(page);
3201
- const sectionDocument = getDocsMcpSourceMarkdown(page);
3202
- const selectedSection = section ? findDocsMarkdownSection(sectionDocument, section) ?? (sectionDocument !== fullDocument ? findDocsMarkdownSection(fullDocument, section) : void 0) : void 0;
3255
+ const sectionDocument = upsertPageAgentContractMarkdown(getDocsMcpSourceMarkdown(page), page.agent);
3256
+ const selectedSection = section ? findDocsMarkdownSection(sectionDocument, section) : void 0;
3203
3257
  if (section && !selectedSection) {
3204
- const sourceSections = parseDocsMarkdownSections(sectionDocument);
3205
- const availableSections = (sourceSections.length > 0 ? sourceSections : parseDocsMarkdownSections(fullDocument)).map((item) => ({
3258
+ const availableSections = parseDocsMarkdownSections(sectionDocument).map((item) => ({
3206
3259
  title: item.title,
3207
3260
  anchor: item.anchor
3208
3261
  }));
@@ -3831,6 +3884,10 @@ function hasVisibleDescendantFilesystemDocsPage(dir) {
3831
3884
  }
3832
3885
  return false;
3833
3886
  }
3887
+ function normalizeFrontmatterLastmod(value) {
3888
+ if (typeof value === "string") return value;
3889
+ return value instanceof Date && Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
3890
+ }
3834
3891
  function scanFilesystemDocsPages(contentDirAbs, entry, rootDir) {
3835
3892
  const pages = [];
3836
3893
  function scan(dir, slugParts) {
@@ -3865,6 +3922,7 @@ function scanFilesystemDocsPages(contentDirAbs, entry, rootDir) {
3865
3922
  agent: normalizePageAgentFrontmatter(data.agent),
3866
3923
  icon: data.icon,
3867
3924
  sourcePath: path.relative(rootDir, full).replace(/\\/g, "/"),
3925
+ lastmod: normalizeFrontmatterLastmod(data.lastmod),
3868
3926
  lastModified: stat.mtime.toISOString(),
3869
3927
  locale: typeof data.locale === "string" ? data.locale : void 0,
3870
3928
  framework: typeof data.framework === "string" ? data.framework : void 0,
@@ -3889,7 +3947,8 @@ function readFilesystemAgentDoc(dir) {
3889
3947
  const agentContent = resolveDocsAudienceMdxContent(content, "agent");
3890
3948
  return {
3891
3949
  agentContent: stripMarkdownForMcp(agentContent),
3892
- agentRawContent: agentContent
3950
+ agentRawContent: agentContent,
3951
+ agentLastModified: fs.statSync(agentPath).mtime.toISOString()
3893
3952
  };
3894
3953
  }
3895
3954
  function resolveRelatedForMcpPages(pages) {
@@ -4005,25 +4064,7 @@ function dedupePages(pages) {
4005
4064
  return [...seen.values()];
4006
4065
  }
4007
4066
  function toSearchSourcePages(pages) {
4008
- return pages.map((page) => ({
4009
- title: page.title,
4010
- url: page.url,
4011
- content: page.content,
4012
- rawContent: page.rawContent,
4013
- sourcePath: page.sourcePath,
4014
- lastModified: page.lastModified,
4015
- locale: page.locale,
4016
- framework: page.framework,
4017
- version: page.version,
4018
- tags: page.tags,
4019
- agentContent: page.agentContent,
4020
- agentRawContent: page.agentRawContent,
4021
- agentFallbackContent: page.agentFallbackContent,
4022
- agentFallbackRawContent: page.agentFallbackRawContent,
4023
- description: page.description,
4024
- related: page.related,
4025
- agent: page.agent
4026
- }));
4067
+ return pages;
4027
4068
  }
4028
4069
  function getDocsConfigSchema(filters = {}) {
4029
4070
  const option = filters.option?.trim();
@@ -4613,7 +4654,8 @@ function getDocsMcpResultPageUrl(value) {
4613
4654
  return value.split("#", 1)[0] ?? value;
4614
4655
  }
4615
4656
  function getDocsMcpResultAnchor(value) {
4616
- const anchor = value.split("#", 2)[1];
4657
+ const hashIndex = value.indexOf("#");
4658
+ const anchor = hashIndex >= 0 ? value.slice(hashIndex + 1) : "";
4617
4659
  if (!anchor) return void 0;
4618
4660
  try {
4619
4661
  return decodeURIComponent(anchor);
@@ -4636,10 +4678,13 @@ async function buildDocsMcpContext(options) {
4636
4678
  }] : [];
4637
4679
  });
4638
4680
  const scopedPages = scopedPageEntries.map(({ page }) => page);
4681
+ const allSearchPages = toSearchSourcePages([...options.pages]);
4682
+ const searchPageBySource = new Map(options.pages.map((page, index) => [page, allSearchPages[index]]));
4639
4683
  const scopeByPage = new Map(scopedPageEntries.map(({ page, scope }) => [page, scope]));
4640
4684
  const maxResults = typeof options.maxResults === "number" && Number.isFinite(options.maxResults) ? Math.max(1, Math.min(50, Math.floor(options.maxResults))) : 50;
4641
4685
  const orderedResults = [...await performDocsSearch({
4642
- pages: toSearchSourcePages(scopedPages),
4686
+ pages: scopedPages.map((page) => searchPageBySource.get(page)),
4687
+ generationPages: allSearchPages,
4643
4688
  query: options.query,
4644
4689
  search: {
4645
4690
  enabled: true,
@@ -4650,6 +4695,7 @@ async function buildDocsMcpContext(options) {
4650
4695
  audience: "agent",
4651
4696
  locale: options.locale,
4652
4697
  siteTitle: options.siteTitle,
4698
+ baseUrl: options.baseUrl,
4653
4699
  limit: 50
4654
4700
  })].sort((left, right) => {
4655
4701
  const scoreDelta = (right.score ?? 0) - (left.score ?? 0);
@@ -4695,7 +4741,7 @@ async function buildDocsMcpContext(options) {
4695
4741
  let usedUtf8Bytes = 0;
4696
4742
  for (const { result, page, scope, selectedSection, rawContent } of resolvedCandidates) {
4697
4743
  const anchor = selectedSection?.anchor;
4698
- const sourceUrl = anchor ? `${page.url}#${anchor}` : page.url;
4744
+ const sourceUrl = result.source?.canonicalUrl ?? (anchor ? `${page.url.split("#", 1)[0]}#${encodeURIComponent(anchor)}` : page.url);
4699
4745
  const headerLines = [`## ${page.title}`, `Source: ${sourceUrl}`];
4700
4746
  if (selectedSection?.title) headerLines.push(`Section: ${selectedSection.title}`);
4701
4747
  if (scope.framework) headerLines.push(`Framework: ${scope.framework}`);
@@ -4722,12 +4768,13 @@ async function buildDocsMcpContext(options) {
4722
4768
  section: selectedSection?.title,
4723
4769
  anchor,
4724
4770
  sourcePath: page.sourcePath,
4725
- lastModified: page.lastModified,
4771
+ lastModified: result.source?.lastModified ?? page.lastModified,
4726
4772
  locale: scope.locale,
4727
4773
  framework: scope.framework,
4728
4774
  version: scope.version,
4729
4775
  package: scope.package.length > 0 ? [...scope.package] : void 0,
4730
4776
  tags: scope.tags.length > 0 ? [...scope.tags] : void 0,
4777
+ source: result.source,
4731
4778
  score: result.score,
4732
4779
  content: limited.text,
4733
4780
  chars: limited.text.length,
@@ -4770,11 +4817,25 @@ async function buildDocsMcpContext(options) {
4770
4817
  }
4771
4818
  function findDocsPage(pages, requestedPath, entry) {
4772
4819
  const normalizedRequest = normalizeRequestedPath(requestedPath, entry);
4773
- for (const page of pages) if (normalizeUrlPath(page.url) === normalizedRequest) return page;
4820
+ const normalizedRequestWithoutLocale = normalizeRequestedPath(removeDocsLocaleQuery(requestedPath), entry);
4821
+ for (const page of pages) {
4822
+ const normalizedPageUrl = normalizeUrlPath(page.url);
4823
+ if (normalizedPageUrl === normalizedRequest || normalizedPageUrl === normalizedRequestWithoutLocale) return page;
4824
+ }
4774
4825
  const normalizedSlug = normalizePathSegment(requestedPath.replace(/^\//, ""));
4775
4826
  for (const page of pages) if (normalizePathSegment(page.slug) === normalizedSlug) return page;
4776
4827
  return null;
4777
4828
  }
4829
+ function removeDocsLocaleQuery(value) {
4830
+ try {
4831
+ const absolute = /^[a-z][a-z\d+.-]*:/iu.test(value);
4832
+ const url = new URL(value, "https://docs.local");
4833
+ url.searchParams.delete("lang");
4834
+ return absolute ? url.toString() : `${url.pathname}${url.search}${url.hash}`;
4835
+ } catch {
4836
+ return value;
4837
+ }
4838
+ }
4778
4839
  function normalizeRequestedPath(requestedPath, entry) {
4779
4840
  const trimmed = requestedPath.trim();
4780
4841
  if (!trimmed) return "/";
@@ -1,4 +1,4 @@
1
- import { nn as normalizePageAgentFrontmatter, tn as hasStructuredPageAgentContract } from "./agent-pS2nNQS3.mjs";
1
+ import { _ as hasStructuredPageAgentContract, v as normalizePageAgentFrontmatter } from "./markdown-sections-7OoA7ylx.mjs";
2
2
 
3
3
  //#region src/metadata.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { i as detectPackageManagerFromProject, l as formatPackageManagerDetection, t as detectFramework, u as installCommand } from "./utils-C4RC8Zq_.mjs";
1
+ import { i as detectPackageManagerFromProject, l as formatPackageManagerDetection, t as detectFramework, u as installCommand } from "./utils-DpiIioYb.mjs";
2
2
  import pc from "picocolors";
3
3
  import * as p from "@clack/prompts";
4
4