@farming-labs/docs 0.2.104 → 0.2.106

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 (78) hide show
  1. package/dist/{agent-NerpHcQB.mjs → agent-CaCWThBY.mjs} +4 -4
  2. package/dist/{agent-PSrgiJD8.mjs → agent-DCTGj6J7.mjs} +48 -12
  3. package/dist/{agent-evals-U9d_db2u.mjs → agent-evals-D-sPJfXz.mjs} +5 -5
  4. package/dist/{agent-export-DlBUKkTt.mjs → agent-export-GcTZPLfB.mjs} +19 -17
  5. package/dist/agent-feedback-evaluations-DQCTFegz.mjs +240 -0
  6. package/dist/agent-maintenance-CuZ7iAKq.mjs +289 -0
  7. package/dist/agent-skills-bundle.d.mts +1 -1
  8. package/dist/{agent-skills-progressive-disclosure-CfIsq4Ew.mjs → agent-skills-progressive-disclosure-DL-q4JZo.mjs} +1 -1
  9. package/dist/{agent-skills-server-CIoL58X7.d.mts → agent-skills-server-D34054x5.d.mts} +2 -2
  10. package/dist/{agent-skills-server-DFqQyO_V.mjs → agent-skills-server-Ddbf15pY.mjs} +1 -1
  11. package/dist/agent-skills-vite.d.mts +3 -3
  12. package/dist/agent-skills-vite.mjs +2 -2
  13. package/dist/{agents-D3SLnQet.mjs → agents-e1SYT64z.mjs} +11 -11
  14. package/dist/{analytics-Bx44lg6d.mjs → analytics-CqfcIBdg.mjs} +1 -1
  15. package/dist/{analytics-B-jz7re8.d.mts → analytics-aeXwEvQX.d.mts} +1 -1
  16. package/dist/{authoring-BsWXMH43.mjs → authoring-Do87QzBd.mjs} +6 -6
  17. package/dist/{authoring-mcp-BCM5CJbJ.mjs → authoring-mcp-Be7quE5R.mjs} +2 -2
  18. package/dist/browser.d.mts +3 -3
  19. package/dist/browser.mjs +2 -2
  20. package/dist/cli/index.mjs +71 -35
  21. package/dist/client/react.d.mts +1 -1
  22. package/dist/client/react.mjs +1 -1
  23. package/dist/{cloud-BLxt_HYO.mjs → cloud-Bvof6mET.mjs} +3 -3
  24. package/dist/{cloud-ask-ai-19G2HJ62.d.mts → cloud-ask-ai-BqfiQaNZ.d.mts} +1 -1
  25. package/dist/{cloud-ask-ai-DeojA5lB.mjs → cloud-ask-ai-CK2qlNns.mjs} +1 -1
  26. package/dist/{codeblocks-qHdKGVaE.mjs → codeblocks-C911CdyJ.mjs} +2 -2
  27. package/dist/{agent-C9IdC__R.d.mts → content-change-hydration-CoYRs3pC.d.mts} +704 -678
  28. package/dist/{dev-B0iHJjTz.mjs → dev-Bx0JNglW.mjs} +2 -2
  29. package/dist/docs-cloud-server.d.mts +2 -2
  30. package/dist/docs-cloud-server.mjs +2 -2
  31. package/dist/{doctor-x3k6aE2I.mjs → doctor-CtK1CRPj.mjs} +17 -17
  32. package/dist/{downgrade-Dd3vvVdD.mjs → downgrade-BXmQMkMy.mjs} +2 -2
  33. package/dist/{feedback-DdWc33oO.mjs → feedback-DWVUMrxy.mjs} +1 -1
  34. package/dist/feedback-evals-k0sFDdms.mjs +146 -0
  35. package/dist/{golden-evaluations-7k7Akp3R.mjs → golden-evaluations-De4KwoYr.mjs} +3 -3
  36. package/dist/index.d.mts +174 -9
  37. package/dist/index.mjs +14 -11
  38. package/dist/{init-DKukQdOQ.mjs → init-CCV2eRNB.mjs} +3 -3
  39. package/dist/markdown-rendering.mjs +1 -1
  40. package/dist/{markdown-sections-7OoA7ylx.mjs → markdown-sections-BKy4labo.mjs} +110 -2
  41. package/dist/{mcp-B6ZZdp6F.mjs → mcp-DsjWxF7g.mjs} +11 -11
  42. package/dist/mcp.d.mts +5 -3
  43. package/dist/mcp.mjs +92 -29
  44. package/dist/{metadata-D4v_R1t5.mjs → metadata-7htr-Xj_.mjs} +1 -1
  45. package/dist/{openapi-mcp-B7u7Y0gB.mjs → openapi-mcp-DQ3xptKo.mjs} +68 -4
  46. package/dist/openapi-mcp-node-vO3IXVGI.mjs +43 -0
  47. package/dist/{package-version-P4TT_9IO.mjs → package-version-Ci99L0yo.mjs} +1 -1
  48. package/dist/{prompt-references-Ca2Rcrpw.mjs → prompt-references-1Wce71c7.mjs} +3 -3
  49. package/dist/propose-DJOiHu9Y.mjs +73 -0
  50. package/dist/retrieval-digest-B-SgtXKK.mjs +177 -0
  51. package/dist/retrieval-digest-DyNRD-mt.d.mts +467 -0
  52. package/dist/{review-DgaNTtP0.mjs → review-XI9FXeos.mjs} +12 -12
  53. package/dist/{robots-DNod0XKB.mjs → robots-BOjWB1ky.mjs} +2 -2
  54. package/dist/{robots-msD1xoH5.mjs → robots-CzKesbdX.mjs} +6 -6
  55. package/dist/{search-CNzq9S5S.mjs → search-DwAoC9X7.mjs} +12 -12
  56. package/dist/server.d.mts +6 -308
  57. package/dist/server.mjs +13 -12
  58. package/dist/{sidebar-DmXRpAAK.d.mts → sidebar-CJze8SBi.d.mts} +1 -1
  59. package/dist/{sitemap-CHvips7o.mjs → sitemap-DOaJIKJf.mjs} +11 -11
  60. package/dist/{sitemap-server-C2TauhKa.mjs → sitemap-server-NeVu8W38.mjs} +1 -1
  61. package/dist/{skills-aaE5L1go.mjs → skills-BILSESek.mjs} +11 -11
  62. package/dist/{standards-discovery-Ckx0tN7B.mjs → standards-discovery-Bpz90VYq.mjs} +2 -177
  63. package/dist/{standards-discovery-Cqq8QmlH.d.mts → standards-discovery-Xm84bS4M.d.mts} +1 -1
  64. package/dist/{types-BthCiAD9.d.mts → types-QhYMnKvb.d.mts} +35 -2
  65. package/dist/{upgrade-B0OA_7jE.mjs → upgrade-B92U83xo.mjs} +2 -2
  66. package/package.json +1 -1
  67. package/styles/themes/shadcn.css +232 -38
  68. package/dist/retrieval-digest-DT9Ktc4C.d.mts +0 -164
  69. /package/dist/{agent-feedback-loop-CGrc-gDW.mjs → agent-feedback-loop-vaC-M1sx.mjs} +0 -0
  70. /package/dist/{audience-exposure-BW13cI2O.d.mts → audience-exposure-CkNZNeVX.d.mts} +0 -0
  71. /package/dist/{cloud-analytics-CSyFE6SS.mjs → cloud-analytics-Ci1yiwD8.mjs} +0 -0
  72. /package/dist/{code-blocks-c3nIrWOM.mjs → code-blocks-D90CCJFs.mjs} +0 -0
  73. /package/dist/{config-BhF6J2N4.mjs → config-DrZ3fXgf.mjs} +0 -0
  74. /package/dist/{errors-B5KTe1Xo.mjs → errors-BDmra6mz.mjs} +0 -0
  75. /package/dist/{i18n-B3BIxShC.mjs → i18n-B1gJ9EW0.mjs} +0 -0
  76. /package/dist/{sidebar-IcpElOVH.mjs → sidebar-3W51s2sF.mjs} +0 -0
  77. /package/dist/{templates-m_j4ARnu.mjs → templates-DdB4BBGq.mjs} +0 -0
  78. /package/dist/{utils-DcCUwxqS.mjs → utils-Cc1SrVza.mjs} +0 -0
@@ -3,6 +3,61 @@ import { slug } from "github-slugger";
3
3
  import { parseEntities } from "parse-entities";
4
4
  import remarkGfm from "remark-gfm";
5
5
 
6
+ //#region src/access.ts
7
+ function isRecord$1(value) {
8
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
9
+ }
10
+ function normalizeStrings(value) {
11
+ if (!Array.isArray(value)) return void 0;
12
+ const strings = Array.from(new Set(value.flatMap((item) => typeof item === "string" && item.trim() ? [item.trim()] : [])));
13
+ return strings.length > 0 ? strings : void 0;
14
+ }
15
+ function normalizeClaimValue(value) {
16
+ if (typeof value === "string") return value.trim() || void 0;
17
+ if (typeof value === "number" && Number.isFinite(value)) return value;
18
+ if (typeof value === "boolean") return value;
19
+ return normalizeStrings(value);
20
+ }
21
+ function normalizeDocsPageAccessPolicy(value) {
22
+ if (!isRecord$1(value)) return void 0;
23
+ const visibility = value.visibility === "public" || value.visibility === "authenticated" ? value.visibility : void 0;
24
+ const scopes = normalizeStrings(value.scopes);
25
+ const rawClaims = isRecord$1(value.claims) ? value.claims : void 0;
26
+ const claims = rawClaims ? Object.fromEntries(Object.entries(rawClaims).flatMap(([name, rawValue]) => {
27
+ const normalizedName = name.trim();
28
+ const normalizedValue = normalizeClaimValue(rawValue);
29
+ return normalizedName && normalizedValue !== void 0 ? [[normalizedName, normalizedValue]] : [];
30
+ })) : void 0;
31
+ const normalizedClaims = claims && Object.keys(claims).length > 0 ? claims : void 0;
32
+ if (!visibility && !scopes && !normalizedClaims) return void 0;
33
+ return {
34
+ ...visibility ? { visibility } : {},
35
+ ...scopes ? { scopes } : {},
36
+ ...normalizedClaims ? { claims: normalizedClaims } : {}
37
+ };
38
+ }
39
+ function claimMatches(expected, actual) {
40
+ const expectedValues = Array.isArray(expected) ? expected : [expected];
41
+ const actualValues = Array.isArray(actual) ? actual : [actual];
42
+ return expectedValues.some((expectedValue) => actualValues.some((actualValue) => actualValue === expectedValue));
43
+ }
44
+ function isDocsPageAccessAllowed(policy, principal) {
45
+ if (!policy) return true;
46
+ if (!(policy.visibility !== "public" || Boolean(policy.scopes?.length) || Boolean(policy.claims && Object.keys(policy.claims).length > 0))) return true;
47
+ if (!principal) return false;
48
+ const scopes = new Set(principal.scopes ?? []);
49
+ if (policy.scopes?.some((scope) => !scopes.has(scope))) return false;
50
+ for (const [name, expected] of Object.entries(policy.claims ?? {})) if (!claimMatches(expected, principal.claims?.[name])) return false;
51
+ return true;
52
+ }
53
+ function isDocsAgentPageAccessible(page, principal) {
54
+ return isDocsPageAccessAllowed(page.agent?.access, principal);
55
+ }
56
+ function filterDocsPagesByAccess(pages, principal) {
57
+ return pages.filter((page) => isDocsAgentPageAccessible(page, principal));
58
+ }
59
+
60
+ //#endregion
6
61
  //#region src/agent-contract.ts
7
62
  const PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS = [
8
63
  "task",
@@ -16,9 +71,14 @@ const PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS = [
16
71
  "rollback",
17
72
  "failureModes"
18
73
  ];
19
- const PAGE_AGENT_CONTRACT_FIELDS = ["tokenBudget", ...PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS];
74
+ const PAGE_AGENT_CONTRACT_FIELDS = [
75
+ "tokenBudget",
76
+ "access",
77
+ ...PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS
78
+ ];
20
79
  const PAGE_AGENT_CONTRACT_FIELD_SCHEMA = {
21
80
  tokenBudget: "number",
81
+ access: "{visibility?,scopes?,claims?}",
22
82
  task: "string",
23
83
  outcome: "string",
24
84
  appliesTo: {
@@ -50,6 +110,11 @@ const VERIFICATION_FIELDS = [
50
110
  "expect"
51
111
  ];
52
112
  const FAILURE_MODE_FIELDS = ["symptom", "resolution"];
113
+ const ACCESS_FIELDS = [
114
+ "visibility",
115
+ "scopes",
116
+ "claims"
117
+ ];
53
118
  const PAGE_AGENT_CONTRACT_START_MARKER = "<!-- farming-labs:agent-contract:start -->";
54
119
  const PAGE_AGENT_CONTRACT_END_MARKER = "<!-- farming-labs:agent-contract:end -->";
55
120
  function isRecord(value) {
@@ -163,6 +228,7 @@ function normalizeTokenBudget(value) {
163
228
  function normalizePageAgentFrontmatter(value) {
164
229
  if (!isRecord(value)) return void 0;
165
230
  const tokenBudget = normalizeTokenBudget(value.tokenBudget);
231
+ const access = "access" in value ? normalizeDocsPageAccessPolicy(value.access) ?? { visibility: "authenticated" } : void 0;
166
232
  const task = normalizeString(value.task);
167
233
  const outcome = normalizeString(value.outcome);
168
234
  const appliesTo = normalizeAppliesTo(value.appliesTo);
@@ -175,6 +241,7 @@ function normalizePageAgentFrontmatter(value) {
175
241
  const failureModes = normalizeFailureModes(value.failureModes);
176
242
  const normalized = {
177
243
  ...tokenBudget !== void 0 ? { tokenBudget } : {},
244
+ ...access ? { access } : {},
178
245
  ...task ? { task } : {},
179
246
  ...outcome ? { outcome } : {},
180
247
  ...appliesTo ? { appliesTo } : {},
@@ -258,6 +325,35 @@ function getPageAgentFrontmatterIssues(value) {
258
325
  path: "agent.tokenBudget",
259
326
  message: "must be a positive finite number"
260
327
  });
328
+ if ("access" in value) if (!isRecord(value.access)) issues.push({
329
+ path: "agent.access",
330
+ message: "must be an object"
331
+ });
332
+ else {
333
+ addUnknownKeyIssues(issues, value.access, ACCESS_FIELDS, "agent.access");
334
+ if ("visibility" in value.access && value.access.visibility !== "public" && value.access.visibility !== "authenticated") issues.push({
335
+ path: "agent.access.visibility",
336
+ message: "must be \"public\" or \"authenticated\""
337
+ });
338
+ if ("scopes" in value.access && !normalizeStringList(value.access.scopes)) issues.push({
339
+ path: "agent.access.scopes",
340
+ message: "must be a non-empty string array"
341
+ });
342
+ if ("claims" in value.access) {
343
+ if (!isRecord(value.access.claims) || Object.keys(value.access.claims).length === 0) issues.push({
344
+ path: "agent.access.claims",
345
+ message: "must be a non-empty object"
346
+ });
347
+ else for (const [name, claim] of Object.entries(value.access.claims)) if (!name.trim() || normalizeDocsPageAccessPolicy({ claims: { [name]: claim } }) === void 0) issues.push({
348
+ path: `agent.access.claims.${name || "<empty>"}`,
349
+ message: "must be a string, number, boolean, or non-empty string array"
350
+ });
351
+ }
352
+ if (!normalizeDocsPageAccessPolicy(value.access)) issues.push({
353
+ path: "agent.access",
354
+ message: "must include a valid visibility, scope, or claim"
355
+ });
356
+ }
261
357
  addStringIssue(issues, value, "task");
262
358
  addStringIssue(issues, value, "outcome");
263
359
  if ("appliesTo" in value) if (!isRecord(value.appliesTo)) issues.push({
@@ -415,6 +511,18 @@ function renderPageAgentFrontmatterYamlLines(value, indentation = 0) {
415
511
  const child = `${indent} `;
416
512
  const lines = [`${indent}agent:`];
417
513
  if (agent.tokenBudget !== void 0) lines.push(`${child}tokenBudget: ${agent.tokenBudget}`);
514
+ if (agent.access) {
515
+ lines.push(`${child}access:`);
516
+ const accessIndent = `${child} `;
517
+ if (agent.access.visibility) lines.push(`${accessIndent}visibility: ${agent.access.visibility}`);
518
+ if (agent.access.scopes) renderYamlStringList(lines, accessIndent, "scopes", [...agent.access.scopes]);
519
+ if (agent.access.claims) {
520
+ lines.push(`${accessIndent}claims:`);
521
+ const claimsIndent = `${accessIndent} `;
522
+ for (const [name, claim] of Object.entries(agent.access.claims).sort(([left], [right]) => left.localeCompare(right))) if (Array.isArray(claim)) renderYamlStringList(lines, claimsIndent, yamlString(name), [...claim]);
523
+ else lines.push(`${claimsIndent}${yamlString(name)}: ${typeof claim === "string" ? yamlString(claim) : claim}`);
524
+ }
525
+ }
418
526
  if (agent.task) lines.push(`${child}task: ${yamlString(agent.task)}`);
419
527
  if (agent.outcome) lines.push(`${child}outcome: ${yamlString(agent.outcome)}`);
420
528
  if (agent.appliesTo) {
@@ -1489,4 +1597,4 @@ function findDocsMarkdownSection(markdown, requestedSection) {
1489
1597
  }
1490
1598
 
1491
1599
  //#endregion
1492
- export { upsertPageAgentContractMarkdown as S, hasStructuredPageAgentContract as _, findDocsGeneratedAgentContractRanges as a, renderPageAgentFrontmatterYamlLines as b, slugifyDocsMarkdownHeading as c, PAGE_AGENT_CONTRACT_END_MARKER as d, PAGE_AGENT_CONTRACT_FIELDS as f, getPageAgentFrontmatterIssues as g, PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS as h, createDocsRenderedHeadingAnchorResolver as i, stripDocsGeneratedAgentContractMarkers as l, PAGE_AGENT_CONTRACT_START_MARKER as m, cleanDocsRenderedHeadingLabel as n, findDocsMarkdownSection as o, PAGE_AGENT_CONTRACT_FIELD_SCHEMA as p, createDocsMarkdownHeadingAnchorResolver as r, parseDocsMarkdownSections as s, applyDocsMarkdownHeadingAnchors as t, withDocsMarkdownRenderableHeadings as u, normalizePageAgentFrontmatter as v, stripGeneratedPageAgentContractMarkdown as x, renderPageAgentContractMarkdown as y };
1600
+ export { filterDocsPagesByAccess as C, normalizeDocsPageAccessPolicy as E, upsertPageAgentContractMarkdown as S, isDocsPageAccessAllowed as T, hasStructuredPageAgentContract as _, findDocsGeneratedAgentContractRanges as a, renderPageAgentFrontmatterYamlLines as b, slugifyDocsMarkdownHeading as c, PAGE_AGENT_CONTRACT_END_MARKER as d, PAGE_AGENT_CONTRACT_FIELDS as f, getPageAgentFrontmatterIssues as g, PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS as h, createDocsRenderedHeadingAnchorResolver as i, stripDocsGeneratedAgentContractMarkers as l, PAGE_AGENT_CONTRACT_START_MARKER as m, cleanDocsRenderedHeadingLabel as n, findDocsMarkdownSection as o, PAGE_AGENT_CONTRACT_FIELD_SCHEMA as p, createDocsMarkdownHeadingAnchorResolver as r, parseDocsMarkdownSections as s, applyDocsMarkdownHeadingAnchors as t, withDocsMarkdownRenderableHeadings as u, normalizePageAgentFrontmatter as v, isDocsAgentPageAccessible as w, stripGeneratedPageAgentContractMarkdown as x, renderPageAgentContractMarkdown as y };
@@ -1,16 +1,16 @@
1
- import "./agent-PSrgiJD8.mjs";
2
- import "./markdown-sections-7OoA7ylx.mjs";
3
- import { L as resolveDocsPublishedAgentSkill } from "./standards-discovery-Ckx0tN7B.mjs";
4
- import "./openapi-mcp-B7u7Y0gB.mjs";
5
- import { a as resolveDocsMetadataBaseUrl } from "./metadata-D4v_R1t5.mjs";
6
- import "./sitemap-server-C2TauhKa.mjs";
7
- import { r as resolveConfiguredAgentSkills } from "./agent-skills-server-DFqQyO_V.mjs";
8
- import "./agent-evals-U9d_db2u.mjs";
1
+ import "./markdown-sections-BKy4labo.mjs";
2
+ import "./agent-DCTGj6J7.mjs";
3
+ import { L as resolveDocsPublishedAgentSkill } from "./standards-discovery-Bpz90VYq.mjs";
4
+ import "./openapi-mcp-DQ3xptKo.mjs";
5
+ import { a as resolveDocsMetadataBaseUrl } from "./metadata-7htr-Xj_.mjs";
6
+ import "./sitemap-server-NeVu8W38.mjs";
7
+ import { r as resolveConfiguredAgentSkills } from "./agent-skills-server-Ddbf15pY.mjs";
8
+ import "./agent-evals-D-sPJfXz.mjs";
9
9
  import { createFilesystemDocsMcpSource, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
10
- import "./authoring-mcp-BCM5CJbJ.mjs";
11
- import "./code-blocks-c3nIrWOM.mjs";
10
+ import "./authoring-mcp-Be7quE5R.mjs";
11
+ import "./code-blocks-D90CCJFs.mjs";
12
12
  import "./server.mjs";
13
- 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-BhF6J2N4.mjs";
13
+ 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-DrZ3fXgf.mjs";
14
14
  import { existsSync, readFileSync } from "node:fs";
15
15
  import path from "node:path";
16
16
  import pc from "picocolors";
package/dist/mcp.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { Cr as FeedbackConfig, F as DocsAgentContentChangesConfig, Qt as DocsMcpAuthenticate, Tn as DocsRetrievalSourceProvenance, Un as DocsSearchConfig, W as DocsAgentEvaluationsConfig, Xt as DocsMcpAllowedOrigins, Zt as DocsMcpAuthPrincipal, bn as DocsOpenApiMcpConfig, dr as DocsSearchSourcePage, ft as DocsAnalyticsConfig, gr as DocsTelemetryConfig, mn as DocsOkfConfig, qr as PageAgentFrontmatter, tn as DocsMcpConfig, un as DocsObservabilityConfig, vn as DocsOkfTrustMetadataInput, xr as DocsTelemetryFramework, zr as OrderingItem } from "./types-BthCiAD9.mjs";
2
- import { z as DocsPublishedAgentSkill } from "./standards-discovery-Cqq8QmlH.mjs";
3
- import { An as MIN_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, Cn as DocsContentChangeHydrationBudget, Dn as DocsContentChangeHydrationTombstone, En as DocsContentChangeHydrationSection, Fn as DocsContentChangeFeed, On as HydrateDocsContentChangesOptions, Sn as DOCS_CONTENT_CHANGE_HYDRATION_FORMAT, Tn as DocsContentChangeHydrationResponse, it as DocsMarkdownSectionIndex, jn as hydrateDocsContentChanges, kn as MAX_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, wn as DocsContentChangeHydrationContent, xn as DEFAULT_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET } from "./agent-C9IdC__R.mjs";
1
+ import { $t as DocsMcpAuthPrincipal, Er as FeedbackConfig, Hr as OrderingItem, K as DocsAgentEvaluationsConfig, Kn as DocsSearchConfig, L as DocsAgentContentChangesConfig, On as DocsRetrievalSourceProvenance, Qt as DocsMcpAllowedOrigins, Sn as DocsOpenApiMcpConfig, Xr as PageAgentFrontmatter, bn as DocsOkfTrustMetadataInput, en as DocsMcpAuthenticate, fn as DocsObservabilityConfig, gn as DocsOkfConfig, mr as DocsSearchSourcePage, mt as DocsAnalyticsConfig, rn as DocsMcpConfig, wr as DocsTelemetryFramework, yr as DocsTelemetryConfig } from "./types-QhYMnKvb.mjs";
2
+ import { z as DocsPublishedAgentSkill } from "./standards-discovery-Xm84bS4M.mjs";
3
+ import { a as DocsContentChangeHydrationResponse, c as HydrateDocsContentChangesOptions, d as hydrateDocsContentChanges, h as DocsContentChangeFeed, i as DocsContentChangeHydrationContent, l as MAX_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, n as DOCS_CONTENT_CHANGE_HYDRATION_FORMAT, o as DocsContentChangeHydrationSection, r as DocsContentChangeHydrationBudget, s as DocsContentChangeHydrationTombstone, sn as DocsMarkdownSectionIndex, t as DEFAULT_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, u as MIN_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET } from "./content-change-hydration-CoYRs3pC.mjs";
4
4
  import { McpServer } from "@modelcontextprotocol/server";
5
5
 
6
6
  //#region src/mcp.d.ts
@@ -188,6 +188,8 @@ interface DocsMcpContextResult {
188
188
  }
189
189
  interface DocsMcpContextOptions {
190
190
  pages: readonly DocsMcpPage[];
191
+ /** Authenticated identity used to retain authorized pages during retrieval. */
192
+ principal?: DocsMcpAuthPrincipal;
191
193
  query: string;
192
194
  framework?: string;
193
195
  version?: string;
package/dist/mcp.mjs CHANGED
@@ -1,9 +1,11 @@
1
- import { a as emitDocsAnalyticsEvent, i as emitDocsAgentTraceEvent, n as createDocsAgentTraceContext, r as createDocsAgentTraceId } from "./analytics-Bx44lg6d.mjs";
2
- import { $n as resolveDocsMcpProtectedResourceMetadataLocation, An as normalizeAgentLocale, Dn as agentVersionConstraintMatches, E as DOCS_MARKDOWN_SECTION_INDEX_FORMAT, Fn as paginateDocsItems, Jn as isDocsMcpProtectedResourceMetadataPath, Jt as resolveDocsContentChangesConfig, Kt as isDocsContentChangeGeneration, Ln as normalizeDocsRelated, Nn as DocsPaginationCursorError, On as agentVersionConstraintsOverlap, P as buildDocsMarkdownSectionIndex, Qn as normalizeDocsMcpEndpointPath, Rn as renderDocsRelatedMarkdownLines, Tn as resolveDocsAudienceMdxContent, Tt as validateDocsAgentFeedbackPayload, Ut as DocsContentChangesRequestError, Wt as createDocsContentChangeFeed, Xn as isDocsMcpResourcePath, Zn as normalizeDocsMcpAuthorizationServerUrls, ar as normalizeDocsOkfTrustMetadataInput, dn as performDocsSearch, er as resolveDocsMcpResourceLocation, fn as performDocsSearchWithMetadata, ir as buildDocsOkfBundle, jn as normalizeAgentScopeValues, kn as normalizeAgentFramework, lt as resolveDocsAgentFeedbackConfig, or as resolveDocsOkfConfig, qn as isDocsMcpOAuthScopeToken, tn as buildDocsSearchFacets, un as normalizeDocsSearchFilters, wt as toDocsMarkdownUrl, yn as resolveLocalDocsMcpSearchConfig } from "./agent-PSrgiJD8.mjs";
3
- import { S as upsertPageAgentContractMarkdown, _ as hasStructuredPageAgentContract, o as findDocsMarkdownSection, s as parseDocsMarkdownSections, v as normalizePageAgentFrontmatter, y as renderPageAgentContractMarkdown } from "./markdown-sections-7OoA7ylx.mjs";
4
- import { q as isDocsRetrievalCanonicalUrl } from "./standards-discovery-Ckx0tN7B.mjs";
5
- import { _ as emitDocsTelemetryMcpToolEvent, a as MAX_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, h as emitDocsTelemetryAgentSurfaceEvent, i as DOCS_CONTENT_CHANGE_HYDRATION_FORMAT, m as stripGeneratedAgentProvenance, n as resolveDocsOpenApiMcpOperations, o as MIN_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, r as DEFAULT_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, s as hydrateDocsContentChanges, t as resolveDocsOpenApiMcpBaseUrl, v as emitDocsTelemetryProjectEvent } from "./openapi-mcp-B7u7Y0gB.mjs";
6
- import { n as resolvePageSidebarFolderIndexBehavior } from "./sidebar-IcpElOVH.mjs";
1
+ import { C as filterDocsPagesByAccess, S as upsertPageAgentContractMarkdown, _ as hasStructuredPageAgentContract, o as findDocsMarkdownSection, s as parseDocsMarkdownSections, v as normalizePageAgentFrontmatter, y as renderPageAgentContractMarkdown } from "./markdown-sections-BKy4labo.mjs";
2
+ import { a as emitDocsAnalyticsEvent, i as emitDocsAgentTraceEvent, n as createDocsAgentTraceContext, r as createDocsAgentTraceId } from "./analytics-CqfcIBdg.mjs";
3
+ import { $n as normalizeDocsMcpEndpointPath, An as normalizeAgentFramework, E as DOCS_MARKDOWN_SECTION_INDEX_FORMAT, En as resolveDocsAudienceMdxContent, Et as validateDocsAgentFeedbackPayload, Gt as createDocsContentChangeFeed, In as paginateDocsItems, Jn as isDocsMcpOAuthScopeToken, Mn as normalizeAgentScopeValues, On as agentVersionConstraintMatches, P as buildDocsMarkdownSectionIndex, Pn as DocsPaginationCursorError, Qn as normalizeDocsMcpAuthorizationServerUrls, Rn as normalizeDocsRelated, Tt as toDocsMarkdownUrl, Wt as DocsContentChangesRequestError, Yn as isDocsMcpProtectedResourceMetadataPath, Yt as resolveDocsContentChangesConfig, Zn as isDocsMcpResourcePath, ar as buildDocsOkfBundle, bn as resolveLocalDocsMcpSearchConfig, dn as normalizeDocsSearchFilters, er as resolveDocsMcpProtectedResourceMetadataLocation, fn as performDocsSearch, jn as normalizeAgentLocale, kn as agentVersionConstraintsOverlap, nn as buildDocsSearchFacets, or as normalizeDocsOkfTrustMetadataInput, pn as performDocsSearchWithMetadata, qt as isDocsContentChangeGeneration, sr as resolveDocsOkfConfig, tr as resolveDocsMcpResourceLocation, ut as resolveDocsAgentFeedbackConfig, zn as renderDocsRelatedMarkdownLines } from "./agent-DCTGj6J7.mjs";
4
+ import { r as isDocsRetrievalCanonicalUrl } from "./retrieval-digest-B-SgtXKK.mjs";
5
+ import "./standards-discovery-Bpz90VYq.mjs";
6
+ import { _ as emitDocsTelemetryAgentSurfaceEvent, a as DEFAULT_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, b as emitDocsTelemetryProjectEvent, c as MIN_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, g as stripGeneratedAgentProvenance, i as resolveDocsOpenApiMcpOperations, l as hydrateDocsContentChanges, n as readDocsOpenApiMcpResponse, o as DOCS_CONTENT_CHANGE_HYDRATION_FORMAT, r as resolveDocsOpenApiMcpBaseUrl, s as MAX_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET, t as acquireDocsOpenApiMcpBudget, y as emitDocsTelemetryMcpToolEvent } from "./openapi-mcp-DQ3xptKo.mjs";
7
+ import { n as resolvePageSidebarFolderIndexBehavior } from "./sidebar-3W51s2sF.mjs";
8
+ import { t as validateDocsOpenApiMcpUrl } from "./openapi-mcp-node-vO3IXVGI.mjs";
7
9
  import matter from "gray-matter";
8
10
  import fs from "node:fs";
9
11
  import path from "node:path";
@@ -12,6 +14,23 @@ import { InMemoryServerEventBus, McpServer, ProtocolError, ProtocolErrorCode, Re
12
14
  import * as z from "zod/v4";
13
15
 
14
16
  //#region src/mcp.ts
17
+ function filterDocsMcpNavigation(tree, allowedUrls) {
18
+ const filterNodes = (nodes) => nodes.flatMap((node) => {
19
+ if (node.type === "page") return allowedUrls.has(node.url) ? [node] : [];
20
+ const children = filterNodes(node.children);
21
+ const index = node.index && allowedUrls.has(node.index.url) ? node.index : void 0;
22
+ const { index: _unfilteredIndex, ...folder } = node;
23
+ return children.length > 0 || index ? [{
24
+ ...folder,
25
+ ...index ? { index } : {},
26
+ children
27
+ }] : [];
28
+ });
29
+ return {
30
+ ...tree,
31
+ children: filterNodes(tree.children)
32
+ };
33
+ }
15
34
  const DEFAULT_MCP_VERSION = "0.0.0";
16
35
  const DEFAULT_MCP_NAME = "@farming-labs/docs";
17
36
  const DOCS_MCP_DISCOVERY_CACHE_TTL_MS = 300 * 1e3;
@@ -2687,6 +2706,7 @@ const openApiOperationOutputSchema = z.object({
2687
2706
  status: z.number().int(),
2688
2707
  ok: z.boolean(),
2689
2708
  contentType: z.string().optional(),
2709
+ responseTruncated: z.boolean().optional(),
2690
2710
  body: z.unknown()
2691
2711
  });
2692
2712
  const readPagesOutputSchema = z.object({
@@ -3319,11 +3339,16 @@ async function createDocsMcpServer(options) {
3319
3339
  search: options.search
3320
3340
  };
3321
3341
  const telemetryFramework = options.telemetryFramework ?? "mcp";
3322
- function getSourcePages(locale) {
3323
- return options.source.getPages(resolveSourceLocale(locale), options.requestContext);
3342
+ async function getSourcePages(locale) {
3343
+ return getResolvedSourcePages(resolveSourceLocale(locale));
3324
3344
  }
3325
- function getSourceNavigation(locale) {
3326
- return options.source.getNavigation(resolveSourceLocale(locale), options.requestContext);
3345
+ async function getResolvedSourcePages(locale) {
3346
+ return filterDocsPagesByAccess(await options.source.getPages(locale, options.requestContext), options.requestContext?.auth);
3347
+ }
3348
+ async function getSourceNavigation(locale) {
3349
+ const resolvedLocale = resolveSourceLocale(locale);
3350
+ const [tree, pages] = await Promise.all([options.source.getNavigation(resolvedLocale, options.requestContext), getResolvedSourcePages(resolvedLocale)]);
3351
+ return filterDocsMcpNavigation(tree, new Set(pages.map((page) => page.url)));
3327
3352
  }
3328
3353
  function resolveSourceLocale(locale) {
3329
3354
  return options.source.resolveLocale ? options.source.resolveLocale(locale, options.requestContext) : locale;
@@ -3420,7 +3445,11 @@ async function createDocsMcpServer(options) {
3420
3445
  }
3421
3446
  const requestUrl = new URL(requestPath.replace(/^\/+/, ""), `${baseUrl.replace(/\/+$/u, "")}/`);
3422
3447
  for (const [name, value] of query) requestUrl.searchParams.append(name, value);
3423
- if (requestUrl.protocol !== "https:" && requestUrl.protocol !== "http:") throw new ProtocolError(ProtocolErrorCode.InvalidParams, "OpenAPI MCP server URLs must use HTTP or HTTPS.");
3448
+ try {
3449
+ await validateDocsOpenApiMcpUrl(requestUrl, openapiConfig);
3450
+ } catch (error) {
3451
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, error instanceof Error ? error.message : "OpenAPI MCP destination was blocked.");
3452
+ }
3424
3453
  const configuredHeaders = typeof openapiConfig.headers === "function" ? await openapiConfig.headers({
3425
3454
  operationId: operation.operationId,
3426
3455
  method: operation.method,
@@ -3432,17 +3461,42 @@ async function createDocsMcpServer(options) {
3432
3461
  if (body !== void 0) requestHeaders.set("Content-Type", "application/json");
3433
3462
  const controller = new AbortController();
3434
3463
  const timeout = setTimeout(() => controller.abort(), openapiConfig.timeoutMs ?? 1e4);
3464
+ const budgetKey = `${options.requestContext?.auth?.id ?? "anonymous"}:${operation.operationId}`;
3465
+ let releaseBudget;
3435
3466
  try {
3436
- const response = await fetch(requestUrl, {
3437
- method: operation.method,
3438
- headers: requestHeaders,
3439
- ...body !== void 0 ? { body: JSON.stringify(body) } : {},
3440
- signal: controller.signal
3441
- });
3467
+ releaseBudget = acquireDocsOpenApiMcpBudget(budgetKey, openapiConfig);
3468
+ let response;
3469
+ let destination = requestUrl;
3470
+ const maxRedirects = Math.max(0, openapiConfig.maxRedirects ?? 0);
3471
+ for (let redirectCount = 0; redirectCount <= maxRedirects; redirectCount += 1) {
3472
+ response = await fetch(destination, {
3473
+ method: operation.method,
3474
+ headers: requestHeaders,
3475
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {},
3476
+ redirect: "manual",
3477
+ signal: controller.signal
3478
+ });
3479
+ if (![
3480
+ 301,
3481
+ 302,
3482
+ 303,
3483
+ 307,
3484
+ 308
3485
+ ].includes(response.status)) break;
3486
+ const location = response.headers.get("location");
3487
+ if (!location || redirectCount >= maxRedirects) throw new ProtocolError(ProtocolErrorCode.InvalidRequest, "OpenAPI MCP redirect blocked. Increase maxRedirects to follow validated redirects.");
3488
+ destination = new URL(location, destination);
3489
+ try {
3490
+ await validateDocsOpenApiMcpUrl(destination, openapiConfig);
3491
+ } catch (error) {
3492
+ throw new ProtocolError(ProtocolErrorCode.InvalidRequest, error instanceof Error ? error.message : "OpenAPI MCP redirect was blocked.");
3493
+ }
3494
+ }
3495
+ if (!response) throw new ProtocolError(ProtocolErrorCode.InternalError, "No API response.");
3442
3496
  const contentType = response.headers.get("content-type") ?? void 0;
3443
- const text = (await response.text()).slice(0, 1e6);
3497
+ const { text, truncated } = await readDocsOpenApiMcpResponse(response, openapiConfig.maxResponseBytes);
3444
3498
  let responseBody = text;
3445
- if (contentType?.includes("json") && text) try {
3499
+ if (contentType?.includes("json") && text && !truncated) try {
3446
3500
  responseBody = JSON.parse(text);
3447
3501
  } catch {
3448
3502
  responseBody = text;
@@ -3452,6 +3506,7 @@ async function createDocsMcpServer(options) {
3452
3506
  status: response.status,
3453
3507
  ok: response.ok,
3454
3508
  ...contentType ? { contentType } : {},
3509
+ ...truncated ? { responseTruncated: true } : {},
3455
3510
  body: responseBody
3456
3511
  };
3457
3512
  trackMcpTool(operation.toolName, { resultCount: 1 });
@@ -3460,6 +3515,7 @@ async function createDocsMcpServer(options) {
3460
3515
  ...response.ok ? {} : { isError: true }
3461
3516
  };
3462
3517
  } finally {
3518
+ releaseBudget?.();
3463
3519
  clearTimeout(timeout);
3464
3520
  }
3465
3521
  });
@@ -3521,11 +3577,12 @@ async function createDocsMcpServer(options) {
3521
3577
  if (!contentChangesEnabled) throw new ProtocolError(ProtocolErrorCode.MethodNotFound, "Content changes are disabled.");
3522
3578
  if (since && !isDocsContentChangeGeneration(since)) throw new ProtocolError(ProtocolErrorCode.InvalidParams, "Content-change `since` must be a SHA-256 index generation.");
3523
3579
  const resolvedLocale = resolveSourceLocale(locale);
3524
- const pages = dedupePages(await options.source.getPages(resolvedLocale, options.requestContext));
3580
+ const pages = dedupePages(await getResolvedSourcePages(resolvedLocale));
3525
3581
  try {
3526
3582
  return {
3527
3583
  result: await contentChangeFeed.resolve({
3528
3584
  pages: toSearchSourcePages(pages),
3585
+ principal: options.requestContext?.auth,
3529
3586
  search: options.search,
3530
3587
  audience: "agent",
3531
3588
  locale: resolvedLocale,
@@ -3713,7 +3770,7 @@ async function createDocsMcpServer(options) {
3713
3770
  metadata: { tool: "list_pages" }
3714
3771
  });
3715
3772
  try {
3716
- const page = paginateDocsMcpItems(toPageSummaries(dedupePages(await options.source.getPages(resolvedLocale, options.requestContext))).sort(compareDocsMcpPageSummaries), {
3773
+ const page = paginateDocsMcpItems(toPageSummaries(dedupePages(await getResolvedSourcePages(resolvedLocale))).sort(compareDocsMcpPageSummaries), {
3717
3774
  kind: "mcp.tool/list_pages",
3718
3775
  scope: stableDocsMcpPaginationScope({ locale: resolvedLocale ?? null }),
3719
3776
  cursor
@@ -3808,7 +3865,7 @@ async function createDocsMcpServer(options) {
3808
3865
  metadata: { tool: "list_docs" }
3809
3866
  });
3810
3867
  try {
3811
- const docs = paginateDocsMcpDocsList(listDocsBySection(dedupePages(await options.source.getPages(resolvedLocale, options.requestContext)), {
3868
+ const docs = paginateDocsMcpDocsList(listDocsBySection(dedupePages(await getResolvedSourcePages(resolvedLocale)), {
3812
3869
  section,
3813
3870
  entry: options.source.entry
3814
3871
  }), {
@@ -3906,7 +3963,7 @@ async function createDocsMcpServer(options) {
3906
3963
  metadata: { tool: "list_tasks" }
3907
3964
  });
3908
3965
  try {
3909
- const page = paginateDocsMcpItems(listDocsTasks(dedupePages(await options.source.getPages(resolvedLocale, options.requestContext)), {
3966
+ const page = paginateDocsMcpItems(listDocsTasks(dedupePages(await getResolvedSourcePages(resolvedLocale)), {
3910
3967
  query,
3911
3968
  framework,
3912
3969
  version,
@@ -4330,7 +4387,8 @@ async function createDocsMcpServer(options) {
4330
4387
  });
4331
4388
  try {
4332
4389
  const facets = await buildDocsSearchFacets({
4333
- pages: toSearchSourcePages(dedupePages(await options.source.getPages(resolvedLocale, options.requestContext))),
4390
+ pages: toSearchSourcePages(dedupePages(await getResolvedSourcePages(resolvedLocale))),
4391
+ principal: options.requestContext?.auth,
4334
4392
  search: toolSearchConfig ?? true,
4335
4393
  audience: resolvedAudience,
4336
4394
  filters,
@@ -4438,7 +4496,8 @@ async function createDocsMcpServer(options) {
4438
4496
  });
4439
4497
  try {
4440
4498
  const searchResponse = await performDocsSearchWithMetadata({
4441
- pages: toSearchSourcePages(dedupePages(await options.source.getPages(resolvedLocale, options.requestContext))),
4499
+ pages: toSearchSourcePages(dedupePages(await getResolvedSourcePages(resolvedLocale))),
4500
+ principal: options.requestContext?.auth,
4442
4501
  query,
4443
4502
  search: toolSearchConfig ?? true,
4444
4503
  audience: resolvedAudience,
@@ -4644,7 +4703,8 @@ async function createDocsMcpServer(options) {
4644
4703
  });
4645
4704
  try {
4646
4705
  const result = await buildDocsMcpContext({
4647
- pages: dedupePages(await options.source.getPages(resolvedLocale, options.requestContext)),
4706
+ pages: dedupePages(await getResolvedSourcePages(resolvedLocale)),
4707
+ principal: options.requestContext?.auth,
4648
4708
  query,
4649
4709
  framework,
4650
4710
  version,
@@ -4752,7 +4812,7 @@ async function createDocsMcpServer(options) {
4752
4812
  metadata: { tool: "list_page_sections" }
4753
4813
  });
4754
4814
  try {
4755
- const page = findDocsPage(dedupePages(await options.source.getPages(resolvedLocale, options.requestContext)), requestedPath, options.source.entry);
4815
+ const page = findDocsPage(dedupePages(await getResolvedSourcePages(resolvedLocale)), requestedPath, options.source.entry);
4756
4816
  if (!page) {
4757
4817
  const elapsed = durationMs(startedAt);
4758
4818
  await emitDocsAnalyticsEvent(options.analytics, {
@@ -5275,9 +5335,10 @@ function createDocsMcpHttpHandler(options) {
5275
5335
  const contentChangePollIntervalMs = typeof configuredPollInterval === "number" && Number.isFinite(configuredPollInterval) && configuredPollInterval >= 10 ? Math.floor(configuredPollInterval) : DEFAULT_DOCS_MCP_CONTENT_CHANGE_POLL_INTERVAL_MS;
5276
5336
  async function readMonitoredState(context) {
5277
5337
  const locale = options.source.resolveLocale?.(void 0, context);
5278
- const pages = dedupePages(await options.source.getPages(locale, context));
5338
+ const pages = dedupePages(filterDocsPagesByAccess(await options.source.getPages(locale, context), context.auth));
5279
5339
  const result = await contentChangeFeed.resolve({
5280
5340
  pages: toSearchSourcePages(pages),
5341
+ principal: context.auth,
5281
5342
  search: options.search,
5282
5343
  audience: "agent",
5283
5344
  locale,
@@ -5436,9 +5497,10 @@ async function runDocsMcpStdio(options) {
5436
5497
  if (!contentChangesEnabled) return server;
5437
5498
  const readState = async () => {
5438
5499
  const locale = options.source.resolveLocale?.(void 0, requestContext);
5439
- const pages = dedupePages(await options.source.getPages(locale, requestContext));
5500
+ const pages = dedupePages(filterDocsPagesByAccess(await options.source.getPages(locale, requestContext), requestContext.auth));
5440
5501
  const result = await contentChangeFeed.resolve({
5441
5502
  pages: toSearchSourcePages(pages),
5503
+ principal: requestContext.auth,
5442
5504
  search: options.search,
5443
5505
  audience: "agent",
5444
5506
  locale,
@@ -6689,6 +6751,7 @@ async function buildDocsMcpContext(options) {
6689
6751
  const orderedResults = [...await performDocsSearch({
6690
6752
  pages: scopedPages.map((page) => searchPageBySource.get(page)),
6691
6753
  generationPages: allSearchPages,
6754
+ principal: options.principal,
6692
6755
  query: options.query,
6693
6756
  search: {
6694
6757
  enabled: true,
@@ -1,4 +1,4 @@
1
- import { _ as hasStructuredPageAgentContract, v as normalizePageAgentFrontmatter } from "./markdown-sections-7OoA7ylx.mjs";
1
+ import { _ as hasStructuredPageAgentContract, v as normalizePageAgentFrontmatter } from "./markdown-sections-BKy4labo.mjs";
2
2
 
3
3
  //#region src/metadata.ts
4
4
  /**
@@ -1,6 +1,6 @@
1
- import { $t as buildDocsRetrievalDigestProjection, G as isDocsAgentDiscoveryRequest, In as resolveDocsPaginationOffset, Jt as resolveDocsContentChangesConfig, K as isDocsAgentsRequest, Nn as DocsPaginationCursorError, Pn as createDocsPaginationCursor, Q as isDocsSkillRequest, _t as resolveDocsMarkdownRequest, dt as resolveDocsAgentsFormat, lt as resolveDocsAgentFeedbackConfig, pt as resolveDocsLlmsTxtRequest, qt as isDocsContentChangesRequest, ut as resolveDocsAgentFeedbackRequest, xt as resolveDocsSkillFormat } from "./agent-PSrgiJD8.mjs";
2
- import { s as parseDocsMarkdownSections } from "./markdown-sections-7OoA7ylx.mjs";
3
- import { K as digestDocsRetrievalContent } from "./standards-discovery-Ckx0tN7B.mjs";
1
+ import { s as parseDocsMarkdownSections } from "./markdown-sections-BKy4labo.mjs";
2
+ import { $ as isDocsSkillRequest, Fn as createDocsPaginationCursor, Jt as isDocsContentChangesRequest, K as isDocsAgentDiscoveryRequest, Ln as resolveDocsPaginationOffset, Pn as DocsPaginationCursorError, St as resolveDocsSkillFormat, Yt as resolveDocsContentChangesConfig, dt as resolveDocsAgentFeedbackRequest, en as buildDocsRetrievalDigestProjection, ft as resolveDocsAgentsFormat, mt as resolveDocsLlmsTxtRequest, q as isDocsAgentsRequest, ut as resolveDocsAgentFeedbackConfig, vt as resolveDocsMarkdownRequest } from "./agent-DCTGj6J7.mjs";
3
+ import { n as digestDocsRetrievalContent } from "./retrieval-digest-B-SgtXKK.mjs";
4
4
  import matter from "gray-matter";
5
5
 
6
6
  //#region src/telemetry.ts
@@ -615,6 +615,70 @@ const HTTP_METHODS = [
615
615
  "options",
616
616
  "head"
617
617
  ];
618
+ const OPENAPI_RATE_WINDOW_MS = 6e4;
619
+ const openApiRateWindows = /* @__PURE__ */ new Map();
620
+ function acquireDocsOpenApiMcpBudget(key, config, now = Date.now()) {
621
+ const requestsPerMinute = Math.max(1, config.requestsPerMinute ?? 60);
622
+ const maxConcurrentRequests = Math.max(1, config.maxConcurrentRequests ?? 4);
623
+ let window = openApiRateWindows.get(key);
624
+ if (!window || now - window.startedAt >= OPENAPI_RATE_WINDOW_MS) {
625
+ window = {
626
+ startedAt: now,
627
+ count: 0,
628
+ active: window?.active ?? 0
629
+ };
630
+ openApiRateWindows.set(key, window);
631
+ }
632
+ if (window.count >= requestsPerMinute) throw new Error("OpenAPI MCP rate limit exceeded for this principal and operation.");
633
+ if (window.active >= maxConcurrentRequests) throw new Error("OpenAPI MCP concurrency limit exceeded for this principal and operation.");
634
+ window.count += 1;
635
+ window.active += 1;
636
+ let released = false;
637
+ return () => {
638
+ if (released) return;
639
+ released = true;
640
+ window.active = Math.max(0, window.active - 1);
641
+ };
642
+ }
643
+ async function readDocsOpenApiMcpResponse(response, maxBytes = 1e6) {
644
+ const limit = Math.max(1, maxBytes);
645
+ if (!response.body) return {
646
+ text: "",
647
+ truncated: false
648
+ };
649
+ const reader = response.body.getReader();
650
+ const chunks = [];
651
+ let used = 0;
652
+ let truncated = false;
653
+ try {
654
+ while (true) {
655
+ const { done, value } = await reader.read();
656
+ if (done) break;
657
+ if (used + value.byteLength > limit) {
658
+ const remaining = limit - used;
659
+ if (remaining > 0) chunks.push(value.subarray(0, remaining));
660
+ used = limit;
661
+ truncated = true;
662
+ await reader.cancel("OpenAPI MCP response byte limit reached");
663
+ break;
664
+ }
665
+ chunks.push(value);
666
+ used += value.byteLength;
667
+ }
668
+ } finally {
669
+ reader.releaseLock();
670
+ }
671
+ const bytes = new Uint8Array(used);
672
+ let offset = 0;
673
+ for (const chunk of chunks) {
674
+ bytes.set(chunk, offset);
675
+ offset += chunk.byteLength;
676
+ }
677
+ return {
678
+ text: new TextDecoder().decode(bytes),
679
+ truncated
680
+ };
681
+ }
618
682
  function asRecord(value) {
619
683
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
620
684
  }
@@ -719,4 +783,4 @@ function resolveDocsOpenApiMcpBaseUrl(document, config) {
719
783
  }
720
784
 
721
785
  //#endregion
722
- export { resolveDocsTelemetryConfig as C, normalizeDocsTelemetryOrigin as S, emitDocsTelemetryMcpToolEvent as _, MAX_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as a, inferDocsTelemetryAgentSurface as b, GENERATED_AGENT_PROVENANCE_MARKER as c, normalizeGeneratedAgentContent as d, parseGeneratedAgentDocument as f, emitDocsTelemetryEvent as g, emitDocsTelemetryAgentSurfaceEvent as h, DOCS_CONTENT_CHANGE_HYDRATION_FORMAT as i, GENERATED_AGENT_PROVENANCE_VERSION as l, stripGeneratedAgentProvenance as m, resolveDocsOpenApiMcpOperations as n, MIN_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as o, serializeGeneratedAgentDocument as p, DEFAULT_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as r, hydrateDocsContentChanges as s, resolveDocsOpenApiMcpBaseUrl as t, hashGeneratedAgentContent as u, emitDocsTelemetryProjectEvent as v, isLocalDocsTelemetryOrigin as x, getDocsTelemetryFeatures as y };
786
+ export { isLocalDocsTelemetryOrigin as C, inferDocsTelemetryAgentSurface as S, resolveDocsTelemetryConfig as T, emitDocsTelemetryAgentSurfaceEvent as _, DEFAULT_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as a, emitDocsTelemetryProjectEvent as b, MIN_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as c, GENERATED_AGENT_PROVENANCE_VERSION as d, hashGeneratedAgentContent as f, stripGeneratedAgentProvenance as g, serializeGeneratedAgentDocument as h, resolveDocsOpenApiMcpOperations as i, hydrateDocsContentChanges as l, parseGeneratedAgentDocument as m, readDocsOpenApiMcpResponse as n, DOCS_CONTENT_CHANGE_HYDRATION_FORMAT as o, normalizeGeneratedAgentContent as p, resolveDocsOpenApiMcpBaseUrl as r, MAX_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as s, acquireDocsOpenApiMcpBudget as t, GENERATED_AGENT_PROVENANCE_MARKER as u, emitDocsTelemetryEvent as v, normalizeDocsTelemetryOrigin as w, getDocsTelemetryFeatures as x, emitDocsTelemetryMcpToolEvent as y };
@@ -0,0 +1,43 @@
1
+ import { lookup } from "node:dns/promises";
2
+ import { isIP } from "node:net";
3
+
4
+ //#region src/openapi-mcp-node.ts
5
+ function isPrivateIpv4(address) {
6
+ const octets = address.split(".").map(Number);
7
+ if (octets.length !== 4 || octets.some((octet) => !Number.isInteger(octet))) return true;
8
+ const [a, b] = octets;
9
+ return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && (b === 0 || b === 168) || a === 198 && (b === 18 || b === 19) || a >= 224;
10
+ }
11
+ function isDocsOpenApiMcpPrivateAddress(address) {
12
+ const normalized = address.trim().toLowerCase().replace(/^\[|\]$/gu, "");
13
+ const family = isIP(normalized);
14
+ if (family === 4) return isPrivateIpv4(normalized);
15
+ if (family !== 6) return true;
16
+ const mappedIpv4 = normalized.match(/^(?:::ffff:)(\d+\.\d+\.\d+\.\d+)$/u)?.[1];
17
+ if (mappedIpv4) return isPrivateIpv4(mappedIpv4);
18
+ return normalized === "::" || normalized === "::1" || normalized.startsWith("fc") || normalized.startsWith("fd") || /^fe[89ab]/u.test(normalized) || normalized.startsWith("ff");
19
+ }
20
+ async function defaultResolveHost(hostname) {
21
+ if (isIP(hostname)) return [hostname];
22
+ return (await lookup(hostname, {
23
+ all: true,
24
+ verbatim: true
25
+ })).map((entry) => entry.address);
26
+ }
27
+ async function validateDocsOpenApiMcpUrl(url, config) {
28
+ if (url.protocol !== "https:" && !(url.protocol === "http:" && config.allowInsecureHttp)) throw new Error("OpenAPI MCP destinations must use HTTPS unless allowInsecureHttp is enabled.");
29
+ if (url.username || url.password) throw new Error("OpenAPI MCP destinations cannot contain URL credentials.");
30
+ if (config.allowPrivateNetwork) return;
31
+ const hostname = url.hostname.toLowerCase().replace(/^\[|\]$/gu, "");
32
+ if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname.endsWith(".local") || hostname.endsWith(".internal") || hostname === "metadata.google.internal") throw new Error(`OpenAPI MCP blocked private destination: ${hostname}`);
33
+ let addresses;
34
+ try {
35
+ addresses = await (config.resolveHost ?? defaultResolveHost)(hostname);
36
+ } catch {
37
+ throw new Error(`OpenAPI MCP could not safely resolve destination: ${hostname}`);
38
+ }
39
+ if (addresses.length === 0 || addresses.some(isDocsOpenApiMcpPrivateAddress)) throw new Error(`OpenAPI MCP blocked private or unresolved destination: ${hostname}`);
40
+ }
41
+
42
+ //#endregion
43
+ export { validateDocsOpenApiMcpUrl as t };
@@ -1,4 +1,4 @@
1
- import { i as detectPackageManagerFromProject, l as formatPackageManagerDetection, t as detectFramework, u as installCommand } from "./utils-DcCUwxqS.mjs";
1
+ import { i as detectPackageManagerFromProject, l as formatPackageManagerDetection, t as detectFramework, u as installCommand } from "./utils-Cc1SrVza.mjs";
2
2
  import pc from "picocolors";
3
3
  import * as p from "@clack/prompts";
4
4