@farming-labs/docs 0.2.103 → 0.2.105

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 (77) hide show
  1. package/dist/{agent-BLHMoVId.mjs → agent-CaCWThBY.mjs} +4 -4
  2. package/dist/{agent-CFqECAG0.mjs → agent-DCTGj6J7.mjs} +212 -19
  3. package/dist/{agent-evals-GpcaCbRb.mjs → agent-evals-D-sPJfXz.mjs} +5 -5
  4. package/dist/{agent-export-oiWxB5aX.mjs → agent-export-GcTZPLfB.mjs} +30 -17
  5. package/dist/agent-feedback-evaluations-DQCTFegz.mjs +240 -0
  6. package/dist/agent-feedback-loop-vaC-M1sx.mjs +196 -0
  7. package/dist/agent-maintenance-CuZ7iAKq.mjs +289 -0
  8. package/dist/agent-skills-bundle.d.mts +1 -1
  9. package/dist/{agent-skills-progressive-disclosure-Da9LKEKv.mjs → agent-skills-progressive-disclosure-DL-q4JZo.mjs} +1 -1
  10. package/dist/{agent-skills-server-CICMh0zv.d.mts → agent-skills-server-D34054x5.d.mts} +2 -2
  11. package/dist/{agent-skills-server-DFqQyO_V.mjs → agent-skills-server-Ddbf15pY.mjs} +1 -1
  12. package/dist/agent-skills-vite.d.mts +3 -3
  13. package/dist/agent-skills-vite.mjs +2 -2
  14. package/dist/{agents-CtqIUW5I.mjs → agents-e1SYT64z.mjs} +11 -10
  15. package/dist/{analytics-Bx44lg6d.mjs → analytics-CqfcIBdg.mjs} +1 -1
  16. package/dist/{analytics-C75BnTEW.d.mts → analytics-aeXwEvQX.d.mts} +1 -1
  17. package/dist/authoring-Do87QzBd.mjs +41 -0
  18. package/dist/authoring-mcp-Be7quE5R.mjs +380 -0
  19. package/dist/browser.d.mts +3 -3
  20. package/dist/browser.mjs +2 -2
  21. package/dist/cli/index.mjs +103 -35
  22. package/dist/client/react.d.mts +1 -1
  23. package/dist/client/react.mjs +1 -1
  24. package/dist/{cloud-FNfcbfli.mjs → cloud-Bvof6mET.mjs} +3 -3
  25. package/dist/{cloud-ask-ai-BmbZVAT5.d.mts → cloud-ask-ai-BqfiQaNZ.d.mts} +1 -1
  26. package/dist/{cloud-ask-ai-CkCYjf2N.mjs → cloud-ask-ai-CK2qlNns.mjs} +1 -1
  27. package/dist/{code-blocks-Bel6vDqI.mjs → code-blocks-D90CCJFs.mjs} +1 -1
  28. package/dist/{codeblocks-jbWuvtJQ.mjs → codeblocks-C911CdyJ.mjs} +2 -2
  29. package/dist/{agent-lWTq6pgr.d.mts → content-change-hydration-CoYRs3pC.d.mts} +707 -675
  30. package/dist/{dev-BvbYmTLz.mjs → dev-Bx0JNglW.mjs} +3 -3
  31. package/dist/docs-cloud-server.d.mts +2 -2
  32. package/dist/docs-cloud-server.mjs +2 -2
  33. package/dist/{doctor-Bmm0uY98.mjs → doctor-CtK1CRPj.mjs} +20 -16
  34. package/dist/{downgrade-Dqm0rJMy.mjs → downgrade-BXmQMkMy.mjs} +2 -2
  35. package/dist/feedback-DWVUMrxy.mjs +72 -0
  36. package/dist/feedback-evals-k0sFDdms.mjs +146 -0
  37. package/dist/{golden-evaluations-K45fcWGW.mjs → golden-evaluations-De4KwoYr.mjs} +3 -3
  38. package/dist/index.d.mts +236 -9
  39. package/dist/index.mjs +14 -11
  40. package/dist/{init-jDQSo-Or.mjs → init-CCV2eRNB.mjs} +3 -3
  41. package/dist/markdown-rendering.mjs +1 -1
  42. package/dist/{markdown-sections-7OoA7ylx.mjs → markdown-sections-BKy4labo.mjs} +110 -2
  43. package/dist/{mcp-CwgKlbIz.mjs → mcp-DsjWxF7g.mjs} +11 -10
  44. package/dist/mcp.d.mts +20 -5
  45. package/dist/mcp.mjs +538 -56
  46. package/dist/{metadata-D4v_R1t5.mjs → metadata-7htr-Xj_.mjs} +1 -1
  47. package/dist/{content-change-hydration-BsbBXAUi.mjs → openapi-mcp-DQ3xptKo.mjs} +182 -4
  48. package/dist/openapi-mcp-node-vO3IXVGI.mjs +43 -0
  49. package/dist/{package-version--oQiHwZj.mjs → package-version-Ci99L0yo.mjs} +1 -1
  50. package/dist/{prompt-references-DW5vG5zs.mjs → prompt-references-1Wce71c7.mjs} +3 -3
  51. package/dist/propose-DJOiHu9Y.mjs +73 -0
  52. package/dist/retrieval-digest-B-SgtXKK.mjs +177 -0
  53. package/dist/retrieval-digest-DyNRD-mt.d.mts +467 -0
  54. package/dist/{review-C_5wB0rR.mjs → review-XI9FXeos.mjs} +12 -12
  55. package/dist/{robots-NQesPX5L.mjs → robots-BOjWB1ky.mjs} +2 -2
  56. package/dist/{robots-BQ42Y84a.mjs → robots-CzKesbdX.mjs} +6 -6
  57. package/dist/{search-B5etKU-v.mjs → search-DwAoC9X7.mjs} +12 -11
  58. package/dist/server.d.mts +47 -264
  59. package/dist/server.mjs +14 -11
  60. package/dist/{sidebar-CwZlgyAz.d.mts → sidebar-CJze8SBi.d.mts} +1 -1
  61. package/dist/{sitemap-DjhxvQP1.mjs → sitemap-DOaJIKJf.mjs} +11 -10
  62. package/dist/{sitemap-server-B0SiREN0.mjs → sitemap-server-NeVu8W38.mjs} +11 -1
  63. package/dist/{skills-BFang8vF.mjs → skills-BILSESek.mjs} +11 -10
  64. package/dist/{standards-discovery-Ckx0tN7B.mjs → standards-discovery-Bpz90VYq.mjs} +2 -177
  65. package/dist/{standards-discovery-D1Ys4J3h.d.mts → standards-discovery-Xm84bS4M.d.mts} +1 -1
  66. package/dist/{types-DLLefoU5.d.mts → types-QhYMnKvb.d.mts} +148 -2
  67. package/dist/{upgrade-kj2crJSk.mjs → upgrade-B92U83xo.mjs} +2 -2
  68. package/package.json +1 -1
  69. package/dist/retrieval-digest-DYEsIeCE.d.mts +0 -164
  70. /package/dist/{audience-exposure-Cw3SA4WE.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/{config-BaTmjDqD.mjs → config-DrZ3fXgf.mjs} +0 -0
  73. /package/dist/{errors-DZiNXv5c.mjs → errors-BDmra6mz.mjs} +0 -0
  74. /package/dist/{i18n-B3BIxShC.mjs → i18n-B1gJ9EW0.mjs} +0 -0
  75. /package/dist/{sidebar-IcpElOVH.mjs → sidebar-3W51s2sF.mjs} +0 -0
  76. /package/dist/{templates-kc7jxspR.mjs → templates-DdB4BBGq.mjs} +0 -0
  77. /package/dist/{utils-DOMeZW9V.mjs → utils-Cc1SrVza.mjs} +0 -0
@@ -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-CFqECAG0.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
@@ -605,4 +605,182 @@ function hydrateDocsContentChanges(options) {
605
605
  }
606
606
 
607
607
  //#endregion
608
- export { getDocsTelemetryFeatures as _, hydrateDocsContentChanges as a, normalizeDocsTelemetryOrigin as b, hashGeneratedAgentContent as c, serializeGeneratedAgentDocument as d, stripGeneratedAgentProvenance as f, emitDocsTelemetryProjectEvent as g, emitDocsTelemetryMcpToolEvent as h, MIN_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as i, normalizeGeneratedAgentContent as l, emitDocsTelemetryEvent as m, DOCS_CONTENT_CHANGE_HYDRATION_FORMAT as n, GENERATED_AGENT_PROVENANCE_MARKER as o, emitDocsTelemetryAgentSurfaceEvent as p, MAX_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as r, GENERATED_AGENT_PROVENANCE_VERSION as s, DEFAULT_DOCS_CONTENT_CHANGE_HYDRATION_TOKEN_BUDGET as t, parseGeneratedAgentDocument as u, inferDocsTelemetryAgentSurface as v, resolveDocsTelemetryConfig as x, isLocalDocsTelemetryOrigin as y };
608
+ //#region src/openapi-mcp.ts
609
+ const HTTP_METHODS = [
610
+ "get",
611
+ "post",
612
+ "put",
613
+ "patch",
614
+ "delete",
615
+ "options",
616
+ "head"
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
+ }
682
+ function asRecord(value) {
683
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
684
+ }
685
+ function selectorFor(method, path) {
686
+ return `${method.toUpperCase()} ${path}`;
687
+ }
688
+ function sanitizeToolName(value) {
689
+ return `api_${value.trim().replace(/[^a-zA-Z0-9_-]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 56) || "operation"}`;
690
+ }
691
+ function operationExtensionEnabled(operation) {
692
+ const extension = operation["x-farming-labs-mcp"];
693
+ return extension === true || asRecord(extension)?.enabled === true;
694
+ }
695
+ function normalizeSecurity(value) {
696
+ if (!Array.isArray(value)) return [];
697
+ return value.flatMap((requirement) => {
698
+ const record = asRecord(requirement);
699
+ if (!record) return [];
700
+ const normalized = {};
701
+ for (const [name, scopes] of Object.entries(record)) normalized[name] = Array.isArray(scopes) ? scopes.filter((scope) => typeof scope === "string") : [];
702
+ return [normalized];
703
+ });
704
+ }
705
+ function normalizeParameters(...values) {
706
+ const parameters = values.flatMap((value) => Array.isArray(value) ? value : []);
707
+ const seen = /* @__PURE__ */ new Set();
708
+ return parameters.flatMap((parameter) => {
709
+ const record = asRecord(parameter);
710
+ if (!record) return [];
711
+ const name = typeof record.name === "string" ? record.name.trim() : "";
712
+ const location = record?.in;
713
+ if (!name || location !== "path" && location !== "query" && location !== "header" && location !== "cookie") return [];
714
+ const key = `${location}:${name}`;
715
+ if (seen.has(key)) return [];
716
+ seen.add(key);
717
+ return [{
718
+ name,
719
+ in: location,
720
+ required: record.required === true || location === "path"
721
+ }];
722
+ });
723
+ }
724
+ function resolveDocsOpenApiMcpOperations(document, config) {
725
+ if (!config || config.enabled === false) return [];
726
+ const allow = new Set((config.operations ?? []).map((value) => value.trim()).filter(Boolean));
727
+ const paths = asRecord(document.paths) ?? {};
728
+ const securitySchemes = asRecord(asRecord(document.components)?.securitySchemes) ?? {};
729
+ const globalSecurity = normalizeSecurity(document.security);
730
+ const operations = [];
731
+ const names = /* @__PURE__ */ new Set();
732
+ for (const [path, rawPathItem] of Object.entries(paths)) {
733
+ const pathItem = asRecord(rawPathItem);
734
+ if (!pathItem) continue;
735
+ for (const method of HTTP_METHODS) {
736
+ const operation = asRecord(pathItem[method]);
737
+ if (!operation) continue;
738
+ const operationId = typeof operation.operationId === "string" && operation.operationId.trim() ? operation.operationId.trim() : `${method}_${path.replace(/[^a-zA-Z0-9]+/g, "_")}`;
739
+ if (!(allow.has(operationId) || allow.has(selectorFor(method, path)) || operationExtensionEnabled(operation))) continue;
740
+ if (![
741
+ "get",
742
+ "head",
743
+ "options"
744
+ ].includes(method) && config.allowMutations !== true) continue;
745
+ const toolName = sanitizeToolName(operationId);
746
+ if (names.has(toolName)) throw new Error(`OpenAPI MCP tool name collision: ${toolName}`);
747
+ names.add(toolName);
748
+ const security = operation.security === void 0 ? globalSecurity : normalizeSecurity(operation.security);
749
+ const usedSchemeNames = new Set(security.flatMap((requirement) => Object.keys(requirement)));
750
+ const usedSecuritySchemes = Object.fromEntries(Object.entries(securitySchemes).filter(([name]) => usedSchemeNames.has(name)));
751
+ operations.push({
752
+ toolName,
753
+ operationId,
754
+ method: method.toUpperCase(),
755
+ path,
756
+ title: typeof operation.summary === "string" && operation.summary.trim() || typeof operation.description === "string" && operation.description.trim() || selectorFor(method, path),
757
+ ...typeof operation.description === "string" && operation.description.trim() ? { description: operation.description.trim() } : {},
758
+ parameters: normalizeParameters(pathItem.parameters, operation.parameters),
759
+ security,
760
+ securitySchemes: usedSecuritySchemes,
761
+ readOnly: method === "get" || method === "head",
762
+ destructive: method === "delete",
763
+ idempotent: [
764
+ "GET",
765
+ "HEAD",
766
+ "PUT",
767
+ "DELETE",
768
+ "OPTIONS"
769
+ ].includes(method.toUpperCase())
770
+ });
771
+ }
772
+ }
773
+ return operations.sort((left, right) => left.toolName.localeCompare(right.toolName));
774
+ }
775
+ function resolveDocsOpenApiMcpBaseUrl(document, config) {
776
+ const configured = config.baseUrl?.trim();
777
+ if (configured) return configured;
778
+ const servers = Array.isArray(document.servers) ? document.servers : [];
779
+ for (const server of servers) {
780
+ const url = asRecord(server)?.url;
781
+ if (typeof url === "string" && url.trim()) return url.trim();
782
+ }
783
+ }
784
+
785
+ //#endregion
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-DOMeZW9V.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
 
@@ -1,7 +1,7 @@
1
- import { At as DEFAULT_SITEMAP_XML_ROUTE, Hn as DEFAULT_MCP_WELL_KNOWN_ROUTE, Ot as DEFAULT_SITEMAP_MD_ROUTE, c as DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, f as DEFAULT_DOCS_CONFIG_ROUTE, h as DEFAULT_LLMS_FULL_TXT_ROUTE, i as DEFAULT_AGENT_FEEDBACK_ROUTE, m as DEFAULT_DOCS_DIAGNOSTICS_ROUTE, t as DEFAULT_AGENTS_MD_ROUTE, v as DEFAULT_LLMS_TXT_ROUTE, x as DEFAULT_SKILL_MD_ROUTE } from "./agent-CFqECAG0.mjs";
2
- import { C as DOCS_AGENT_MANIFEST_SCHEMA_MEDIA_TYPE, S as DOCS_AGENT_MANIFEST_FORMAT, T as DOCS_AGENT_MANIFEST_VERSION, f as DEFAULT_AGENT_SKILLS_ROUTE_PREFIX, n as API_CATALOG_MEDIA_TYPE, r as API_CATALOG_PROFILE_URI, t as AGENT_SKILLS_DISCOVERY_SCHEMA_URI, u as DEFAULT_AGENT_SKILLS_INDEX_ROUTE, v as DEFAULT_API_CATALOG_ROUTE, w as DOCS_AGENT_MANIFEST_SCHEMA_URI } from "./standards-discovery-Ckx0tN7B.mjs";
1
+ import { Un as DEFAULT_MCP_WELL_KNOWN_ROUTE, c as DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, f as DEFAULT_DOCS_CONFIG_ROUTE, h as DEFAULT_LLMS_FULL_TXT_ROUTE, i as DEFAULT_AGENT_FEEDBACK_ROUTE, jt as DEFAULT_SITEMAP_XML_ROUTE, kt as DEFAULT_SITEMAP_MD_ROUTE, m as DEFAULT_DOCS_DIAGNOSTICS_ROUTE, t as DEFAULT_AGENTS_MD_ROUTE, v as DEFAULT_LLMS_TXT_ROUTE, x as DEFAULT_SKILL_MD_ROUTE } from "./agent-DCTGj6J7.mjs";
2
+ import { C as DOCS_AGENT_MANIFEST_SCHEMA_MEDIA_TYPE, S as DOCS_AGENT_MANIFEST_FORMAT, T as DOCS_AGENT_MANIFEST_VERSION, f as DEFAULT_AGENT_SKILLS_ROUTE_PREFIX, n as API_CATALOG_MEDIA_TYPE, r as API_CATALOG_PROFILE_URI, t as AGENT_SKILLS_DISCOVERY_SCHEMA_URI, u as DEFAULT_AGENT_SKILLS_INDEX_ROUTE, v as DEFAULT_API_CATALOG_ROUTE, w as DOCS_AGENT_MANIFEST_SCHEMA_URI } from "./standards-discovery-Bpz90VYq.mjs";
3
3
  import { isDocsAgentSkillName, validateDocsAgentSkillFrontmatter } from "./agent-skills-spec.mjs";
4
- import { n as DEFAULT_ROBOTS_TXT_ROUTE } from "./robots-NQesPX5L.mjs";
4
+ import { n as DEFAULT_ROBOTS_TXT_ROUTE } from "./robots-BOjWB1ky.mjs";
5
5
  import matter from "gray-matter";
6
6
 
7
7
  //#region src/define-docs.ts
@@ -0,0 +1,73 @@
1
+ import { n as analyzeDocsAgentMaintenanceSignals, r as parseDocsAgentMaintenanceSignals } from "./agent-maintenance-CuZ7iAKq.mjs";
2
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
3
+ import path from "node:path";
4
+ import pc from "picocolors";
5
+
6
+ //#region src/cli/propose.ts
7
+ function parseAgentMaintenanceProposeArgs(argv) {
8
+ const options = { inputs: [] };
9
+ for (let index = 0; index < argv.length; index += 1) {
10
+ const argument = argv[index];
11
+ if (argument === "--write") options.write = true;
12
+ else if (argument === "--json") options.json = true;
13
+ else if (argument === "--help" || argument === "-h") options.help = true;
14
+ else if (argument === "--input" || argument === "--output" || argument === "--min-occurrences") {
15
+ const value = argv[index + 1];
16
+ if (!value || value.startsWith("--")) throw new Error(`${argument} requires a value.`);
17
+ index += 1;
18
+ if (argument === "--input") options.inputs.push(value);
19
+ else if (argument === "--output") options.output = value;
20
+ else {
21
+ const parsed = Number(value);
22
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > 100) throw new Error("--min-occurrences must be an integer from 1 through 100.");
23
+ options.minOccurrences = parsed;
24
+ }
25
+ } else throw new Error(`Unknown agent propose flag: ${argument}`);
26
+ }
27
+ return options;
28
+ }
29
+ function resolveProjectPath(rootDir, value) {
30
+ if (path.isAbsolute(value)) throw new Error("Maintenance paths must be project-relative.");
31
+ const candidate = path.resolve(rootDir, value);
32
+ const relative = path.relative(rootDir, candidate);
33
+ if (relative.startsWith("..") || path.isAbsolute(relative)) throw new Error("Maintenance paths must stay inside the project root.");
34
+ return candidate;
35
+ }
36
+ function writeReport(outputPath, report) {
37
+ mkdirSync(path.dirname(outputPath), { recursive: true });
38
+ const temporaryPath = `${outputPath}.${process.pid}.tmp`;
39
+ writeFileSync(temporaryPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
40
+ renameSync(temporaryPath, outputPath);
41
+ }
42
+ async function runAgentMaintenancePropose(options = {}) {
43
+ const rootDir = path.resolve(options.rootDir ?? process.cwd());
44
+ const report = analyzeDocsAgentMaintenanceSignals((options.inputs && options.inputs.length > 0 ? options.inputs : [".farming-labs/agent-feedback-improvements.json"]).flatMap((input) => parseDocsAgentMaintenanceSignals(readFileSync(resolveProjectPath(rootDir, input), "utf8"))), { minOccurrences: options.minOccurrences });
45
+ if (options.write) {
46
+ const outputPath = resolveProjectPath(rootDir, options.output ?? ".farming-labs/agent-maintenance-proposals.json");
47
+ writeReport(outputPath, report);
48
+ if (!options.json) console.log(pc.green(`Wrote ${path.relative(rootDir, outputPath)} with ${report.proposalCount} reviewable proposal${report.proposalCount === 1 ? "" : "s"}.`));
49
+ }
50
+ if (options.json || !options.write) console.log(JSON.stringify(report, null, 2));
51
+ return report;
52
+ }
53
+ function printAgentMaintenanceProposeHelp() {
54
+ console.log(`${pc.bold("docs agent propose")} — turn recurring signals into reviewable maintenance drafts
55
+
56
+ ${pc.dim("Usage:")}
57
+ docs agent propose --input .farming-labs/agent-feedback-improvements.json
58
+ docs agent propose --input search-signals.jsonl --input support-signals.json --write
59
+
60
+ ${pc.dim("Options:")}
61
+ ${pc.cyan("--input <path>")} Repeatable JSON/JSONL signal or feedback report
62
+ ${pc.cyan("--min-occurrences <1-100>")} Proposal threshold (default: 2)
63
+ ${pc.cyan("--write")} Write the draft-only proposal report
64
+ ${pc.cyan("--output <path>")} Output path (default: .farming-labs/agent-maintenance-proposals.json)
65
+ ${pc.cyan("--json")} Print JSON when writing
66
+
67
+ Signal sources: agent-feedback, ask-ai, git, issue, mcp, search, support.
68
+ The command never edits documentation, creates issues, publishes branches, or merges changes.
69
+ `);
70
+ }
71
+
72
+ //#endregion
73
+ export { parseAgentMaintenanceProposeArgs, printAgentMaintenanceProposeHelp, runAgentMaintenancePropose };
@@ -0,0 +1,177 @@
1
+ //#region src/retrieval-digest.ts
2
+ const SHA256_INITIAL_STATE = [
3
+ 1779033703,
4
+ 3144134277,
5
+ 1013904242,
6
+ 2773480762,
7
+ 1359893119,
8
+ 2600822924,
9
+ 528734635,
10
+ 1541459225
11
+ ];
12
+ const SHA256_ROUND_CONSTANTS = [
13
+ 1116352408,
14
+ 1899447441,
15
+ 3049323471,
16
+ 3921009573,
17
+ 961987163,
18
+ 1508970993,
19
+ 2453635748,
20
+ 2870763221,
21
+ 3624381080,
22
+ 310598401,
23
+ 607225278,
24
+ 1426881987,
25
+ 1925078388,
26
+ 2162078206,
27
+ 2614888103,
28
+ 3248222580,
29
+ 3835390401,
30
+ 4022224774,
31
+ 264347078,
32
+ 604807628,
33
+ 770255983,
34
+ 1249150122,
35
+ 1555081692,
36
+ 1996064986,
37
+ 2554220882,
38
+ 2821834349,
39
+ 2952996808,
40
+ 3210313671,
41
+ 3336571891,
42
+ 3584528711,
43
+ 113926993,
44
+ 338241895,
45
+ 666307205,
46
+ 773529912,
47
+ 1294757372,
48
+ 1396182291,
49
+ 1695183700,
50
+ 1986661051,
51
+ 2177026350,
52
+ 2456956037,
53
+ 2730485921,
54
+ 2820302411,
55
+ 3259730800,
56
+ 3345764771,
57
+ 3516065817,
58
+ 3600352804,
59
+ 4094571909,
60
+ 275423344,
61
+ 430227734,
62
+ 506948616,
63
+ 659060556,
64
+ 883997877,
65
+ 958139571,
66
+ 1322822218,
67
+ 1537002063,
68
+ 1747873779,
69
+ 1955562222,
70
+ 2024104815,
71
+ 2227730452,
72
+ 2361852424,
73
+ 2428436474,
74
+ 2756734187,
75
+ 3204031479,
76
+ 3329325298
77
+ ];
78
+ function rotateRight(value, bits) {
79
+ return value >>> bits | value << 32 - bits;
80
+ }
81
+ function normalizeDigestContent(value) {
82
+ return value.replace(/\r\n?/gu, "\n").replace(/^\uFEFF/u, "").trimEnd();
83
+ }
84
+ function toSha256Bytes(value) {
85
+ return typeof value === "string" ? new TextEncoder().encode(value) : value;
86
+ }
87
+ /** Validate the bounded HTTP(S) URL or root-relative URI reference used by provenance. */
88
+ function isDocsRetrievalCanonicalUrl(value) {
89
+ const hasUnsafeCharacter = value.includes("\\") || Array.from(value).some((character) => {
90
+ const codePoint = character.codePointAt(0) ?? 0;
91
+ return codePoint <= 31 || codePoint === 127;
92
+ });
93
+ if (!value || value !== value.trim() || value.length > 4096 || hasUnsafeCharacter) return false;
94
+ if (/^\/(?!\/)/u.test(value)) try {
95
+ new URL(value, "https://docs.local");
96
+ return true;
97
+ } catch {
98
+ return false;
99
+ }
100
+ try {
101
+ const url = new URL(value);
102
+ return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password;
103
+ } catch {
104
+ return false;
105
+ }
106
+ }
107
+ /** Hash exact bytes with portable SHA-256 in Node, edge, and browser runtimes. */
108
+ function sha256DocsContent(value) {
109
+ const input = toSha256Bytes(value);
110
+ const paddedLength = Math.ceil((input.length + 9) / 64) * 64;
111
+ const padded = new Uint8Array(paddedLength);
112
+ padded.set(input);
113
+ padded[input.length] = 128;
114
+ const bitLength = input.length * 8;
115
+ const dataView = new DataView(padded.buffer);
116
+ dataView.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296), false);
117
+ dataView.setUint32(paddedLength - 4, bitLength >>> 0, false);
118
+ const state = Uint32Array.from(SHA256_INITIAL_STATE);
119
+ const words = new Uint32Array(64);
120
+ for (let offset = 0; offset < padded.length; offset += 64) {
121
+ for (let index = 0; index < 16; index += 1) words[index] = dataView.getUint32(offset + index * 4, false);
122
+ for (let index = 16; index < 64; index += 1) {
123
+ const previous15 = words[index - 15];
124
+ const previous2 = words[index - 2];
125
+ const sigma0 = rotateRight(previous15, 7) ^ rotateRight(previous15, 18) ^ previous15 >>> 3;
126
+ const sigma1 = rotateRight(previous2, 17) ^ rotateRight(previous2, 19) ^ previous2 >>> 10;
127
+ words[index] = words[index - 16] + sigma0 + words[index - 7] + sigma1 >>> 0;
128
+ }
129
+ let a = state[0];
130
+ let b = state[1];
131
+ let c = state[2];
132
+ let d = state[3];
133
+ let e = state[4];
134
+ let f = state[5];
135
+ let g = state[6];
136
+ let h = state[7];
137
+ for (let index = 0; index < 64; index += 1) {
138
+ const sum1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
139
+ const choice = e & f ^ ~e & g;
140
+ const temporary1 = h + sum1 + choice + SHA256_ROUND_CONSTANTS[index] + words[index] >>> 0;
141
+ const temporary2 = (rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22)) + (a & b ^ a & c ^ b & c) >>> 0;
142
+ h = g;
143
+ g = f;
144
+ f = e;
145
+ e = d + temporary1 >>> 0;
146
+ d = c;
147
+ c = b;
148
+ b = a;
149
+ a = temporary1 + temporary2 >>> 0;
150
+ }
151
+ state[0] = state[0] + a >>> 0;
152
+ state[1] = state[1] + b >>> 0;
153
+ state[2] = state[2] + c >>> 0;
154
+ state[3] = state[3] + d >>> 0;
155
+ state[4] = state[4] + e >>> 0;
156
+ state[5] = state[5] + f >>> 0;
157
+ state[6] = state[6] + g >>> 0;
158
+ state[7] = state[7] + h >>> 0;
159
+ }
160
+ return Array.from(state, (word) => word.toString(16).padStart(8, "0")).join("");
161
+ }
162
+ /** Hash exact message-content bytes with portable SHA-256. */
163
+ function digestDocsContent(value) {
164
+ return `sha256:${sha256DocsContent(value)}`;
165
+ }
166
+ /**
167
+ * Hash the normalized retrieval projection used by search provenance.
168
+ *
169
+ * The projection removes one leading BOM, normalizes line endings to LF, and trims
170
+ * trailing whitespace. This deliberately differs from HTTP digests over exact bytes.
171
+ */
172
+ function digestDocsRetrievalContent(value) {
173
+ return digestDocsContent(normalizeDigestContent(value));
174
+ }
175
+
176
+ //#endregion
177
+ export { sha256DocsContent as i, digestDocsRetrievalContent as n, isDocsRetrievalCanonicalUrl as r, digestDocsContent as t };