@farming-labs/docs 0.2.60 → 0.2.61
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.
- package/README.md +1 -1
- package/dist/{agent-DlxriaTs.mjs → agent-DFHlw_JC.mjs} +3 -3
- package/dist/{agent-BFqyqEnC.mjs → agent-Fl0pjVNF.mjs} +136 -331
- package/dist/{agent-evals-kJs2Y9xR.mjs → agent-evals-f4_OL10T.mjs} +3 -3
- package/dist/{agent-export-BgUaiW8f.mjs → agent-export-D0zQhasD.mjs} +87 -46
- package/dist/agent-skills-bundle.d.mts +13 -0
- package/dist/agent-skills-bundle.mjs +12 -0
- package/dist/agent-skills-server-CIeBszxp.mjs +263 -0
- package/dist/agent-skills-server-CKq3_jMj.d.mts +12 -0
- package/dist/agent-skills-vite.d.mts +31 -0
- package/dist/agent-skills-vite.mjs +70 -0
- package/dist/{agents-Djh-HXih.mjs → agents-ibnXrWyp.mjs} +9 -7
- package/dist/cli/index.mjs +29 -29
- package/dist/client/react.d.mts +1 -1
- package/dist/{cloud-ask-ai-B2WnG4fF.d.mts → cloud-ask-ai-D7ZgF47y.d.mts} +1 -1
- package/dist/{cloud-BH_sHX64.mjs → cloud-pdNC-tyj.mjs} +3 -3
- package/dist/{codeblocks-Bq67u32v.mjs → codeblocks-CFuurVIH.mjs} +2 -2
- package/dist/{config-DASewQ0x.mjs → config-Wcdj-D0a.mjs} +7 -1
- package/dist/{dev-DgY5xGl9.mjs → dev-Cmy6DtdF.mjs} +2 -2
- package/dist/docs-cloud-server.d.mts +2 -2
- package/dist/docs-cloud-server.mjs +1 -1
- package/dist/{doctor-CO1VMcF_.mjs → doctor-CXostbsI.mjs} +151 -21
- package/dist/{downgrade-BZs86NVr.mjs → downgrade-w7e6Se0L.mjs} +2 -2
- package/dist/{golden-evaluations-BN9u2wxw.mjs → golden-evaluations-CBZ_JZjf.mjs} +19 -4
- package/dist/index.d.mts +52 -10
- package/dist/index.mjs +8 -7
- package/dist/{init-Bd_k06bR.mjs → init-CQY0Woe3.mjs} +36 -5
- package/dist/{mcp-B_yXL5G5.mjs → mcp-DyPcoLwm.mjs} +33 -14
- package/dist/mcp.d.mts +13 -2
- package/dist/mcp.mjs +699 -408
- package/dist/{metadata-BDuewuzq.mjs → metadata-Dv1ah0Aj.mjs} +1 -1
- package/dist/{package-version-qik_4J6C.mjs → package-version-n5AFur8a.mjs} +1 -1
- package/dist/{reading-time-BkEft6SD.mjs → reading-time-C-SAhQT9.mjs} +10 -9
- package/dist/{review-NC-sOdXn.mjs → review-D2UBrxFq.mjs} +18 -10
- package/dist/{robots-DskPvGPw.mjs → robots-5Yqz9mz7.mjs} +5 -4
- package/dist/{robots-ltltiLJF.mjs → robots-C08kDLsz.mjs} +6 -2
- package/dist/{search-D57JXQLj.mjs → search-9OnMGMvt.mjs} +1 -1
- package/dist/{search-C1JitPwi.d.mts → search-C6heDO8h.d.mts} +3 -126
- package/dist/{search-o4Ud6OXv.mjs → search-CNsRpz90.mjs} +8 -6
- package/dist/server.d.mts +6 -5
- package/dist/server.mjs +9 -7
- package/dist/{sitemap-Cq-Yj_iA.mjs → sitemap-BpYnSsfJ.mjs} +9 -7
- package/dist/{sitemap-server-C1ibVKOy.mjs → sitemap-server-D_0Kzanj.mjs} +1 -1
- package/dist/standards-discovery-C4HUqMd2.d.mts +227 -0
- package/dist/standards-discovery-C54V_aJH.mjs +510 -0
- package/dist/{templates-DNw15P-x.mjs → templates-Bq_P7ctv.mjs} +101 -9
- package/dist/{types-XHABMh_f.d.mts → types-EhFhYGfr.d.mts} +58 -1
- package/dist/{upgrade-BCJTCW3O.mjs → upgrade-oz-GChgt.mjs} +2 -2
- package/package.json +11 -1
- /package/dist/{agent-scope-CCaIY1aK.mjs → agent-scope-C_U--OZ7.mjs} +0 -0
- /package/dist/{cloud-ask-ai-hnJfj8-X.mjs → cloud-ask-ai-sbpjOR2K.mjs} +0 -0
- /package/dist/{code-blocks-qe0T8-xe.mjs → code-blocks-DnNVNK2M.mjs} +0 -0
- /package/dist/{errors-CVqZ3kOO.mjs → errors-DbOhkE1h.mjs} +0 -0
- /package/dist/{i18n-CAlj1ADU.mjs → i18n-CCaFUnAN.mjs} +0 -0
- /package/dist/{utils-6UCLxv4B.mjs → utils-DpiIioYb.mjs} +0 -0
package/README.md
CHANGED
|
@@ -102,7 +102,7 @@ Farming Labs can expose the same docs in machine-readable forms, including:
|
|
|
102
102
|
|
|
103
103
|
- `llms.txt` and full-document feeds
|
|
104
104
|
- Markdown routes for individual pages
|
|
105
|
-
- `skill.md`, `AGENTS.md`, and agent discovery endpoints
|
|
105
|
+
- `skill.md`, multi-skill discovery with hashed companion assets, `AGENTS.md`, and agent discovery endpoints
|
|
106
106
|
- A built-in Model Context Protocol (MCP) server
|
|
107
107
|
- Schema.org JSON-LD, sitemaps, and generated `robots.txt`
|
|
108
108
|
- Agent-focused health checks with `docs doctor --agent`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as hashGeneratedAgentContent, b as serializeGeneratedAgentDocument, g as GENERATED_AGENT_PROVENANCE_VERSION, y as parseGeneratedAgentDocument } from "./search-
|
|
1
|
+
import { Jt as normalizePageAgentFrontmatter, L as findDocsMarkdownPage, Zt as stripGeneratedPageAgentContractMarkdown, tt as renderDocsMarkdownDocument } from "./agent-Fl0pjVNF.mjs";
|
|
2
|
+
import { _ as hashGeneratedAgentContent, b as serializeGeneratedAgentDocument, g as GENERATED_AGENT_PROVENANCE_VERSION, y as parseGeneratedAgentDocument } from "./search-9OnMGMvt.mjs";
|
|
3
3
|
import { createFilesystemDocsMcpSource } from "./mcp.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, c as loadProjectEnv, d as readNavTitle, f as readNumberProperty, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral, u as readEnvReferenceProperty } from "./config-Wcdj-D0a.mjs";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import matter from "gray-matter";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -1,5 +1,104 @@
|
|
|
1
|
+
import { C as buildDocsApiCatalog, D as isDocsStandardsDiscoveryRequest, O as resolveDocsDiscoveryApiRoute, T as createDocsStandardsResponse, a as DEFAULT_A2A_AGENT_CARD_ROUTE, c as DEFAULT_AGENT_SKILLS_INDEX_ROUTE, g as DEFAULT_API_CATALOG_ROUTE, h as DEFAULT_API_CATALOG_FORMAT, l as DEFAULT_AGENT_SKILLS_ROUTE_PATTERN, n as API_CATALOG_MEDIA_TYPE, o as DEFAULT_AGENT_SKILLS_ARCHIVE_ROUTE_PATTERN, r as API_CATALOG_PROFILE_URI, s as DEFAULT_AGENT_SKILLS_INDEX_FORMAT, t as AGENT_SKILLS_DISCOVERY_SCHEMA_URI, v as DEFAULT_LEGACY_SKILLS_INDEX_ROUTE } from "./standards-discovery-C54V_aJH.mjs";
|
|
1
2
|
import { createProcessor } from "@mdx-js/mdx";
|
|
2
3
|
|
|
4
|
+
//#region src/mcp-auth.ts
|
|
5
|
+
const DEFAULT_MCP_ROUTE = "/api/docs/mcp";
|
|
6
|
+
const DEFAULT_MCP_PUBLIC_ROUTE = "/mcp";
|
|
7
|
+
const DEFAULT_MCP_WELL_KNOWN_ROUTE = "/.well-known/mcp";
|
|
8
|
+
const DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE = "/.well-known/oauth-protected-resource";
|
|
9
|
+
function normalizeDocsMcpEndpointPath(route, fallback = DEFAULT_MCP_ROUTE) {
|
|
10
|
+
const normalized = `/${route?.trim().split(/[?#]/, 1)[0] || fallback}`.replace(/\/+/g, "/");
|
|
11
|
+
return normalized !== "/" ? normalized.replace(/\/+$/, "") : fallback;
|
|
12
|
+
}
|
|
13
|
+
function getDocsMcpResourcePaths(route) {
|
|
14
|
+
return Array.from(new Set([
|
|
15
|
+
normalizeDocsMcpEndpointPath(route),
|
|
16
|
+
DEFAULT_MCP_PUBLIC_ROUTE,
|
|
17
|
+
DEFAULT_MCP_WELL_KNOWN_ROUTE
|
|
18
|
+
]));
|
|
19
|
+
}
|
|
20
|
+
function buildDocsMcpProtectedResourceMetadataRoute(resourcePath) {
|
|
21
|
+
const candidate = resourcePath.trim().split(/[?#]/, 1)[0] || "/";
|
|
22
|
+
const trailingSlash = candidate.length > 1 && candidate.endsWith("/");
|
|
23
|
+
const normalized = candidate === "/" ? "/" : normalizeDocsMcpEndpointPath(candidate);
|
|
24
|
+
return normalized === "/" ? DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE : `${DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE}${normalized}${trailingSlash ? "/" : ""}`;
|
|
25
|
+
}
|
|
26
|
+
function getDocsMcpProtectedResourceMetadataRoutes(route) {
|
|
27
|
+
return getDocsMcpResourcePaths(route).map(buildDocsMcpProtectedResourceMetadataRoute);
|
|
28
|
+
}
|
|
29
|
+
function hasDocsMcpProtectedResourceConfig(mcp) {
|
|
30
|
+
if (!mcp || typeof mcp !== "object" || mcp.enabled === false || typeof mcp.security?.authenticate !== "function") return false;
|
|
31
|
+
return normalizeDocsMcpAuthorizationServerUrls(mcp.security?.protectedResource?.authorizationServers).length > 0;
|
|
32
|
+
}
|
|
33
|
+
function normalizeDocsMcpAuthorizationServerUrls(values) {
|
|
34
|
+
if (!Array.isArray(values)) return [];
|
|
35
|
+
return Array.from(new Set(values.filter((value) => typeof value === "string").map((value) => value.trim()).filter(isAbsoluteHttpUrl)));
|
|
36
|
+
}
|
|
37
|
+
function isDocsMcpOAuthScopeToken(value) {
|
|
38
|
+
return typeof value === "string" && /^[\x21\x23-\x5B\x5D-\x7E]+$/u.test(value);
|
|
39
|
+
}
|
|
40
|
+
function isDocsMcpRequest(url, mcp) {
|
|
41
|
+
const route = typeof mcp === "object" ? mcp.route : void 0;
|
|
42
|
+
if (isDocsMcpResourcePath(url.pathname, route)) return true;
|
|
43
|
+
return hasDocsMcpProtectedResourceConfig(mcp) && isDocsMcpProtectedResourceMetadataRequestPath(url.pathname, route);
|
|
44
|
+
}
|
|
45
|
+
function isDocsMcpResourcePath(pathname, route) {
|
|
46
|
+
return isCanonicalResourcePath(pathname, getDocsMcpResourcePaths(route));
|
|
47
|
+
}
|
|
48
|
+
function resolveDocsMcpResourceLocation(request, route) {
|
|
49
|
+
const requestUrl = new URL(request.url);
|
|
50
|
+
const allowedPaths = getDocsMcpResourcePaths(route);
|
|
51
|
+
const normalizedRequestPath = normalizeRequestPath(requestUrl.pathname);
|
|
52
|
+
const resourcePath = isCanonicalResourcePath(requestUrl.pathname, allowedPaths) ? requestUrl.pathname : normalizedRequestPath;
|
|
53
|
+
const resourceUrl = new URL(requestUrl);
|
|
54
|
+
resourceUrl.pathname = resourcePath;
|
|
55
|
+
const metadataUrl = new URL(resourceUrl);
|
|
56
|
+
metadataUrl.pathname = buildDocsMcpProtectedResourceMetadataRoute(resourcePath);
|
|
57
|
+
return {
|
|
58
|
+
resourceUrl,
|
|
59
|
+
metadataUrl
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function resolveDocsMcpProtectedResourceMetadataLocation(request, route) {
|
|
63
|
+
const rawUrl = new URL(request.url);
|
|
64
|
+
const allowedPaths = getDocsMcpResourcePaths(route);
|
|
65
|
+
if (!rawUrl.pathname.startsWith(`${DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE}/`)) return;
|
|
66
|
+
const requestedResourcePath = rawUrl.pathname.slice(37);
|
|
67
|
+
if (!isCanonicalResourcePath(requestedResourcePath, allowedPaths)) return void 0;
|
|
68
|
+
const metadataUrl = new URL(rawUrl);
|
|
69
|
+
const resourceUrl = new URL(metadataUrl);
|
|
70
|
+
resourceUrl.pathname = requestedResourcePath;
|
|
71
|
+
return {
|
|
72
|
+
resourceUrl,
|
|
73
|
+
metadataUrl
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function isDocsMcpProtectedResourceMetadataPath(pathname) {
|
|
77
|
+
const normalized = normalizeRequestPath(pathname);
|
|
78
|
+
return normalized === DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE || normalized.startsWith(`${DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE}/`);
|
|
79
|
+
}
|
|
80
|
+
function normalizeRequestPath(pathname) {
|
|
81
|
+
const normalized = `/${pathname}`.replace(/\/+/g, "/");
|
|
82
|
+
return normalized === "/" ? normalized : normalized.replace(/\/+$/, "");
|
|
83
|
+
}
|
|
84
|
+
function isCanonicalResourcePath(pathname, resourcePaths) {
|
|
85
|
+
return resourcePaths.some((resourcePath) => pathname === resourcePath || resourcePath !== "/" && pathname === `${resourcePath}/`);
|
|
86
|
+
}
|
|
87
|
+
function isDocsMcpProtectedResourceMetadataRequestPath(pathname, route) {
|
|
88
|
+
if (!pathname.startsWith(`${DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE}/`)) return false;
|
|
89
|
+
return isCanonicalResourcePath(pathname.slice(37), getDocsMcpResourcePaths(route));
|
|
90
|
+
}
|
|
91
|
+
function isAbsoluteHttpUrl(value) {
|
|
92
|
+
try {
|
|
93
|
+
const url = new URL(value);
|
|
94
|
+
const loopbackHttp = url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]");
|
|
95
|
+
return (url.protocol === "https:" || loopbackHttp) && !url.username && !url.password && !url.search && !url.hash;
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
3
102
|
//#region src/agent-contract.ts
|
|
4
103
|
const PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS = [
|
|
5
104
|
"task",
|
|
@@ -637,325 +736,6 @@ function normalizeInlineText(value) {
|
|
|
637
736
|
return value.replace(/\s+/g, " ").trim();
|
|
638
737
|
}
|
|
639
738
|
|
|
640
|
-
//#endregion
|
|
641
|
-
//#region src/standards-discovery.ts
|
|
642
|
-
const DEFAULT_API_CATALOG_ROUTE = "/.well-known/api-catalog";
|
|
643
|
-
const DEFAULT_API_CATALOG_FORMAT = "api-catalog";
|
|
644
|
-
const API_CATALOG_PROFILE_URI = "https://www.rfc-editor.org/info/rfc9727";
|
|
645
|
-
const API_CATALOG_MEDIA_TYPE = "application/linkset+json";
|
|
646
|
-
const DEFAULT_AGENT_SKILLS_INDEX_ROUTE = "/.well-known/agent-skills/index.json";
|
|
647
|
-
const DEFAULT_AGENT_SKILLS_ROUTE_PREFIX = "/.well-known/agent-skills";
|
|
648
|
-
const DEFAULT_AGENT_SKILLS_ROUTE_PATTERN = `${DEFAULT_AGENT_SKILLS_ROUTE_PREFIX}/{name}/SKILL.md`;
|
|
649
|
-
const DEFAULT_AGENT_SKILLS_INDEX_FORMAT = "agent-skills";
|
|
650
|
-
const DEFAULT_AGENT_SKILL_FORMAT = "agent-skill";
|
|
651
|
-
const AGENT_SKILLS_DISCOVERY_SCHEMA_URI = "https://schemas.agentskills.io/discovery/0.2.0/schema.json";
|
|
652
|
-
const DEFAULT_DOCS_API_ROUTE$1 = "/api/docs";
|
|
653
|
-
const DEFAULT_AGENT_MANIFEST_ROUTE = "/.well-known/agent.json";
|
|
654
|
-
const AGENT_SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
655
|
-
const AGENT_SKILL_NAME_MAX_LENGTH = 64;
|
|
656
|
-
const AGENT_SKILL_DESCRIPTION_MAX_LENGTH = 1024;
|
|
657
|
-
const DISCOVERY_CACHE_CONTROL = "public, max-age=0, s-maxage=3600";
|
|
658
|
-
function normalizeDocsRoute(value) {
|
|
659
|
-
const normalized = `/${value.trim()}`.replace(/\/{2,}/g, "/");
|
|
660
|
-
return normalized === "/" ? normalized : normalized.replace(/\/+$/, "");
|
|
661
|
-
}
|
|
662
|
-
/** Resolve the same-origin Docs API pathname used by query-form discovery routes. */
|
|
663
|
-
function resolveDocsDiscoveryApiRoute(apiRoute) {
|
|
664
|
-
const candidate = apiRoute?.trim().split(/[?#]/, 1)[0];
|
|
665
|
-
return normalizeDocsRoute(candidate || DEFAULT_DOCS_API_ROUTE$1);
|
|
666
|
-
}
|
|
667
|
-
function resolveHttpUrl(value, origin) {
|
|
668
|
-
if (!value) return null;
|
|
669
|
-
try {
|
|
670
|
-
const base = new URL(origin);
|
|
671
|
-
const resolved = new URL(value, `${base.origin}/`);
|
|
672
|
-
if (resolved.protocol !== "http:" && resolved.protocol !== "https:") return null;
|
|
673
|
-
return resolved.toString();
|
|
674
|
-
} catch {
|
|
675
|
-
return null;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
function compactUniqueTargets(targets) {
|
|
679
|
-
const seen = /* @__PURE__ */ new Set();
|
|
680
|
-
return targets.filter((target) => {
|
|
681
|
-
if (!target) return false;
|
|
682
|
-
const key = `${target.href}\u0000${target.type ?? ""}\u0000${target.title ?? ""}`;
|
|
683
|
-
if (seen.has(key)) return false;
|
|
684
|
-
seen.add(key);
|
|
685
|
-
return true;
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
function toTarget(route, origin, type, title) {
|
|
689
|
-
const href = resolveHttpUrl(route, origin);
|
|
690
|
-
return href ? {
|
|
691
|
-
href,
|
|
692
|
-
...type ? { type } : {},
|
|
693
|
-
...title ? { title } : {}
|
|
694
|
-
} : null;
|
|
695
|
-
}
|
|
696
|
-
/** Build an RFC 9727 API Catalog using the RFC 9264 JSON Linkset representation. */
|
|
697
|
-
function buildDocsApiCatalog(options) {
|
|
698
|
-
const catalogUrl = resolveHttpUrl(DEFAULT_API_CATALOG_ROUTE, options.origin);
|
|
699
|
-
if (!catalogUrl) throw new Error(`Invalid HTTP(S) docs origin for API catalog: ${options.origin}`);
|
|
700
|
-
const apiRoute = options.apiRoute === null ? null : resolveDocsDiscoveryApiRoute(options.apiRoute);
|
|
701
|
-
const agentManifestRoute = options.agentManifestRoute === void 0 ? DEFAULT_AGENT_MANIFEST_ROUTE : options.agentManifestRoute;
|
|
702
|
-
const agentSkillsIndexRoute = options.agentSkillsIndexRoute === void 0 ? DEFAULT_AGENT_SKILLS_INDEX_ROUTE : options.agentSkillsIndexRoute;
|
|
703
|
-
const apiTargets = compactUniqueTargets([
|
|
704
|
-
toTarget(apiRoute, options.origin, "application/json", "Documentation API"),
|
|
705
|
-
...(options.apiRoutes ?? []).map((target) => toTarget(target.route, options.origin, target.type, target.title)),
|
|
706
|
-
toTarget(options.mcpRoute, options.origin, "application/json", "Documentation MCP endpoint"),
|
|
707
|
-
...(options.feedbackRoutes ?? []).map((route, index) => toTarget(route, options.origin, index === 0 ? "application/json" : "application/schema+json", index === 0 ? "Agent feedback endpoint" : "Agent feedback schema"))
|
|
708
|
-
]);
|
|
709
|
-
const serviceDocs = compactUniqueTargets([
|
|
710
|
-
toTarget(options.docsRoute ?? "/docs", options.origin, "text/html", "Documentation"),
|
|
711
|
-
toTarget(options.markdownRootRoute, options.origin, "text/markdown", "Documentation Markdown"),
|
|
712
|
-
toTarget(options.agentsRoute, options.origin, "text/markdown", "Agent instructions"),
|
|
713
|
-
toTarget(options.skillRoute, options.origin, "text/markdown", "Site skill"),
|
|
714
|
-
...(options.llmsRoutes ?? []).map((route) => toTarget(route, options.origin, "text/plain", "LLM documentation index")),
|
|
715
|
-
...(options.sitemapRoutes ?? []).map((route) => toTarget(route, options.origin, route.endsWith(".xml") ? "application/xml" : "text/markdown", "Documentation sitemap")),
|
|
716
|
-
toTarget(options.apiReferenceRoute, options.origin, "text/html", "API reference")
|
|
717
|
-
]);
|
|
718
|
-
const serviceMetadata = compactUniqueTargets([
|
|
719
|
-
toTarget(agentManifestRoute, options.origin, "application/json", "Agent discovery manifest"),
|
|
720
|
-
toTarget(agentSkillsIndexRoute, options.origin, "application/json", "Agent Skills discovery index"),
|
|
721
|
-
toTarget(options.configRoute, options.origin, "application/json", "Docs configuration map"),
|
|
722
|
-
toTarget(options.diagnosticsRoute, options.origin, "application/json", "Docs diagnostics"),
|
|
723
|
-
toTarget(options.robotsRoute, options.origin, "text/plain", "Robots policy")
|
|
724
|
-
]);
|
|
725
|
-
const serviceDescriptions = compactUniqueTargets([toTarget(options.openapiRoute, options.origin, "application/vnd.oai.openapi+json;version=3.1", "OpenAPI schema")]);
|
|
726
|
-
const catalogContext = {
|
|
727
|
-
anchor: catalogUrl,
|
|
728
|
-
"api-catalog": [{
|
|
729
|
-
href: catalogUrl,
|
|
730
|
-
type: API_CATALOG_MEDIA_TYPE,
|
|
731
|
-
title: "API catalog"
|
|
732
|
-
}]
|
|
733
|
-
};
|
|
734
|
-
if (apiTargets.length > 0) catalogContext.item = apiTargets;
|
|
735
|
-
if (serviceDocs.length > 0) catalogContext["service-doc"] = serviceDocs;
|
|
736
|
-
if (serviceMetadata.length > 0) catalogContext["service-meta"] = serviceMetadata;
|
|
737
|
-
if (serviceDescriptions.length > 0) catalogContext["service-desc"] = serviceDescriptions;
|
|
738
|
-
const linkset = [catalogContext];
|
|
739
|
-
for (const target of apiTargets) {
|
|
740
|
-
const context = { anchor: target.href };
|
|
741
|
-
if (serviceDocs.length > 0) context["service-doc"] = serviceDocs;
|
|
742
|
-
if (serviceMetadata.length > 0) context["service-meta"] = serviceMetadata;
|
|
743
|
-
if (serviceDescriptions.length > 0 && target.href === resolveHttpUrl(apiRoute, options.origin)) context["service-desc"] = serviceDescriptions;
|
|
744
|
-
linkset.push(context);
|
|
745
|
-
}
|
|
746
|
-
return { linkset };
|
|
747
|
-
}
|
|
748
|
-
function unquoteFrontmatterScalar(value) {
|
|
749
|
-
const trimmed = value.trim();
|
|
750
|
-
if (!trimmed || trimmed === ">" || trimmed === "|" || trimmed.startsWith("[") || trimmed.startsWith("{")) return null;
|
|
751
|
-
if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) try {
|
|
752
|
-
const parsed = JSON.parse(trimmed);
|
|
753
|
-
return typeof parsed === "string" ? parsed.trim() : null;
|
|
754
|
-
} catch {
|
|
755
|
-
return null;
|
|
756
|
-
}
|
|
757
|
-
if (trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed.slice(1, -1).replace(/''/g, "'").trim();
|
|
758
|
-
return trimmed.replace(/\s+#.*$/, "").trim();
|
|
759
|
-
}
|
|
760
|
-
function readAgentSkillFrontmatter(document) {
|
|
761
|
-
const match = (document.startsWith("") ? document.slice(1) : document).match(/^---[\t ]*\r?\n([\s\S]*?)\r?\n---(?:[\t ]*\r?\n|$)/);
|
|
762
|
-
if (!match) return null;
|
|
763
|
-
const values = /* @__PURE__ */ new Map();
|
|
764
|
-
for (const line of match[1].split(/\r?\n/)) {
|
|
765
|
-
const field = line.match(/^([A-Za-z][A-Za-z0-9_-]*):\s*(.*?)\s*$/);
|
|
766
|
-
if (!field) continue;
|
|
767
|
-
const value = unquoteFrontmatterScalar(field[2]);
|
|
768
|
-
if (value !== null) values.set(field[1], value);
|
|
769
|
-
}
|
|
770
|
-
const name = values.get("name") ?? "";
|
|
771
|
-
const description = values.get("description") ?? "";
|
|
772
|
-
if (!name || name.length > AGENT_SKILL_NAME_MAX_LENGTH || !AGENT_SKILL_NAME_PATTERN.test(name) || !description || description.length > AGENT_SKILL_DESCRIPTION_MAX_LENGTH) return null;
|
|
773
|
-
return {
|
|
774
|
-
name,
|
|
775
|
-
description
|
|
776
|
-
};
|
|
777
|
-
}
|
|
778
|
-
async function sha256DocsDiscoveryContent(content) {
|
|
779
|
-
const subtle = globalThis.crypto?.subtle;
|
|
780
|
-
if (!subtle) throw new Error("Web Crypto SHA-256 support is required for Agent Skills discovery.");
|
|
781
|
-
const digest = await subtle.digest("SHA-256", new TextEncoder().encode(content));
|
|
782
|
-
return [...new Uint8Array(digest)].map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
783
|
-
}
|
|
784
|
-
/** Select a valid public skill and hash the exact bytes returned by its standards route. */
|
|
785
|
-
async function resolveDocsPublishedAgentSkill({ preferredDocument, fallbackDocument }) {
|
|
786
|
-
const preferredMetadata = preferredDocument ? readAgentSkillFrontmatter(preferredDocument) : null;
|
|
787
|
-
const fallbackMetadata = readAgentSkillFrontmatter(fallbackDocument);
|
|
788
|
-
const content = preferredMetadata ? preferredDocument : fallbackDocument;
|
|
789
|
-
const metadata = preferredMetadata ?? fallbackMetadata;
|
|
790
|
-
if (!metadata) throw new Error("The generated Agent Skills fallback must contain valid name and description frontmatter.");
|
|
791
|
-
const sha256 = await sha256DocsDiscoveryContent(content);
|
|
792
|
-
return {
|
|
793
|
-
name: metadata.name,
|
|
794
|
-
type: "skill-md",
|
|
795
|
-
description: metadata.description,
|
|
796
|
-
url: `${DEFAULT_AGENT_SKILLS_ROUTE_PREFIX}/${metadata.name}/SKILL.md`,
|
|
797
|
-
digest: `sha256:${sha256}`,
|
|
798
|
-
content,
|
|
799
|
-
sha256
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
function buildDocsAgentSkillsIndex(skills) {
|
|
803
|
-
return {
|
|
804
|
-
$schema: AGENT_SKILLS_DISCOVERY_SCHEMA_URI,
|
|
805
|
-
skills: (Array.isArray(skills) ? skills : [skills]).map(({ name, type, description, url, digest }) => ({
|
|
806
|
-
name,
|
|
807
|
-
type,
|
|
808
|
-
description,
|
|
809
|
-
url,
|
|
810
|
-
digest
|
|
811
|
-
})).sort((left, right) => left.name.localeCompare(right.name))
|
|
812
|
-
};
|
|
813
|
-
}
|
|
814
|
-
function resolveDocsStandardsDiscoveryRequest(url, options = {}) {
|
|
815
|
-
const pathname = normalizeDocsRoute(url.pathname);
|
|
816
|
-
if (pathname === DEFAULT_API_CATALOG_ROUTE) return { kind: "api-catalog" };
|
|
817
|
-
if (pathname === DEFAULT_AGENT_SKILLS_INDEX_ROUTE) return { kind: "agent-skills-index" };
|
|
818
|
-
const artifactMatch = pathname.match(/^\/\.well-known\/agent-skills\/([^/]+)\/SKILL\.md$/);
|
|
819
|
-
if (artifactMatch) try {
|
|
820
|
-
return {
|
|
821
|
-
kind: "agent-skill",
|
|
822
|
-
name: decodeURIComponent(artifactMatch[1])
|
|
823
|
-
};
|
|
824
|
-
} catch {
|
|
825
|
-
return {
|
|
826
|
-
kind: "agent-skill",
|
|
827
|
-
name: ""
|
|
828
|
-
};
|
|
829
|
-
}
|
|
830
|
-
if (pathname !== resolveDocsDiscoveryApiRoute(options.apiRoute)) return null;
|
|
831
|
-
const format = url.searchParams.get("format")?.trim();
|
|
832
|
-
if (format === DEFAULT_API_CATALOG_FORMAT) return { kind: "api-catalog" };
|
|
833
|
-
if (format === DEFAULT_AGENT_SKILLS_INDEX_FORMAT) return { kind: "agent-skills-index" };
|
|
834
|
-
if (format === DEFAULT_AGENT_SKILL_FORMAT) return {
|
|
835
|
-
kind: "agent-skill",
|
|
836
|
-
name: url.searchParams.get("name")?.trim() ?? ""
|
|
837
|
-
};
|
|
838
|
-
return null;
|
|
839
|
-
}
|
|
840
|
-
function isDocsStandardsDiscoveryRequest(url, options = {}) {
|
|
841
|
-
return resolveDocsStandardsDiscoveryRequest(url, options) !== null;
|
|
842
|
-
}
|
|
843
|
-
function formatLinkTarget(href, relation, options = {}) {
|
|
844
|
-
return [
|
|
845
|
-
`<${href}>`,
|
|
846
|
-
`rel="${relation}"`,
|
|
847
|
-
...options.type ? [`type="${options.type}"`] : [],
|
|
848
|
-
...options.profile ? [`profile="${options.profile}"`] : []
|
|
849
|
-
].join("; ");
|
|
850
|
-
}
|
|
851
|
-
/** Cross-link the standards endpoints without replacing an existing canonical Link value. */
|
|
852
|
-
function getDocsDiscoveryLinkHeader(options = {}) {
|
|
853
|
-
return [
|
|
854
|
-
...options.includeApiCatalog === false ? [] : [formatLinkTarget(DEFAULT_API_CATALOG_ROUTE, "api-catalog", {
|
|
855
|
-
type: API_CATALOG_MEDIA_TYPE,
|
|
856
|
-
profile: API_CATALOG_PROFILE_URI
|
|
857
|
-
})],
|
|
858
|
-
...options.includeManifest === false ? [] : [formatLinkTarget(DEFAULT_AGENT_MANIFEST_ROUTE, "service-meta", { type: "application/json" })],
|
|
859
|
-
...options.includeSkills === false ? [] : [formatLinkTarget(DEFAULT_AGENT_SKILLS_INDEX_ROUTE, "service-meta", { type: "application/json" })]
|
|
860
|
-
].join(", ");
|
|
861
|
-
}
|
|
862
|
-
function appendDocsDiscoveryLinkHeader(headers, value) {
|
|
863
|
-
const next = new Headers(headers);
|
|
864
|
-
const discoveryLinks = value ?? getDocsDiscoveryLinkHeader();
|
|
865
|
-
const existing = next.get("Link");
|
|
866
|
-
next.set("Link", existing ? `${existing}, ${discoveryLinks}` : discoveryLinks);
|
|
867
|
-
return next;
|
|
868
|
-
}
|
|
869
|
-
function requestMatchesEtag(request, etag) {
|
|
870
|
-
const value = request.headers.get("if-none-match");
|
|
871
|
-
if (!value) return false;
|
|
872
|
-
if (value.trim() === "*") return true;
|
|
873
|
-
return value.split(",").some((candidate) => candidate.trim().replace(/^W\//i, "") === etag);
|
|
874
|
-
}
|
|
875
|
-
async function createHashedDiscoveryResponse(options) {
|
|
876
|
-
const etag = `"${options.sha256 ?? await sha256DocsDiscoveryContent(options.content)}"`;
|
|
877
|
-
const headers = {
|
|
878
|
-
"Access-Control-Allow-Origin": "*",
|
|
879
|
-
"Access-Control-Expose-Headers": "ETag, Link",
|
|
880
|
-
Allow: "GET, HEAD",
|
|
881
|
-
"Cache-Control": DISCOVERY_CACHE_CONTROL,
|
|
882
|
-
"Content-Type": options.contentType,
|
|
883
|
-
ETag: etag,
|
|
884
|
-
Link: options.linkHeader,
|
|
885
|
-
"X-Robots-Tag": "noindex"
|
|
886
|
-
};
|
|
887
|
-
if (requestMatchesEtag(options.request, etag)) {
|
|
888
|
-
const { "Content-Type": _contentType, ...notModifiedHeaders } = headers;
|
|
889
|
-
return new Response(null, {
|
|
890
|
-
status: 304,
|
|
891
|
-
headers: notModifiedHeaders
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
return new Response(options.request.method.toUpperCase() === "HEAD" ? null : options.content, { headers });
|
|
895
|
-
}
|
|
896
|
-
function standardsNotFoundResponse(request, linkHeader) {
|
|
897
|
-
return new Response(request.method.toUpperCase() === "HEAD" ? null : "Not Found", {
|
|
898
|
-
status: 404,
|
|
899
|
-
headers: {
|
|
900
|
-
"Access-Control-Allow-Origin": "*",
|
|
901
|
-
"Access-Control-Expose-Headers": "Link",
|
|
902
|
-
"Cache-Control": "no-store",
|
|
903
|
-
"Content-Type": "text/plain; charset=utf-8",
|
|
904
|
-
Link: linkHeader,
|
|
905
|
-
"X-Robots-Tag": "noindex"
|
|
906
|
-
}
|
|
907
|
-
});
|
|
908
|
-
}
|
|
909
|
-
function standardsMethodNotAllowedResponse(linkHeader) {
|
|
910
|
-
return new Response("Method Not Allowed", {
|
|
911
|
-
status: 405,
|
|
912
|
-
headers: {
|
|
913
|
-
"Access-Control-Allow-Origin": "*",
|
|
914
|
-
"Access-Control-Expose-Headers": "Link",
|
|
915
|
-
Allow: "GET, HEAD",
|
|
916
|
-
"Cache-Control": "no-store",
|
|
917
|
-
"Content-Type": "text/plain; charset=utf-8",
|
|
918
|
-
Link: linkHeader,
|
|
919
|
-
"X-Robots-Tag": "noindex"
|
|
920
|
-
}
|
|
921
|
-
});
|
|
922
|
-
}
|
|
923
|
-
/** Return one RFC 9727 or Agent Skills discovery response, or null for unrelated requests. */
|
|
924
|
-
async function createDocsStandardsResponse({ request, apiCatalog, apiCatalogEnabled = true, apiRoute, preferredSkillDocument, fallbackSkillDocument }) {
|
|
925
|
-
const resolved = resolveDocsStandardsDiscoveryRequest(new URL(request.url), { apiRoute });
|
|
926
|
-
if (!resolved) return null;
|
|
927
|
-
const linkHeader = getDocsDiscoveryLinkHeader({ includeApiCatalog: apiCatalogEnabled });
|
|
928
|
-
if (resolved.kind === "api-catalog" && (!apiCatalogEnabled || !apiCatalog)) return standardsNotFoundResponse(request, linkHeader);
|
|
929
|
-
const method = request.method.toUpperCase();
|
|
930
|
-
if (method !== "GET" && method !== "HEAD") return standardsMethodNotAllowedResponse(linkHeader);
|
|
931
|
-
if (resolved.kind === "api-catalog") return createHashedDiscoveryResponse({
|
|
932
|
-
request,
|
|
933
|
-
content: `${JSON.stringify(apiCatalog, null, 2)}\n`,
|
|
934
|
-
contentType: `${API_CATALOG_MEDIA_TYPE}; profile="${API_CATALOG_PROFILE_URI}"; charset=utf-8`,
|
|
935
|
-
linkHeader
|
|
936
|
-
});
|
|
937
|
-
const skill = await resolveDocsPublishedAgentSkill({
|
|
938
|
-
preferredDocument: preferredSkillDocument,
|
|
939
|
-
fallbackDocument: fallbackSkillDocument
|
|
940
|
-
});
|
|
941
|
-
if (resolved.kind === "agent-skill") {
|
|
942
|
-
if (resolved.name !== skill.name) return standardsNotFoundResponse(request, linkHeader);
|
|
943
|
-
return createHashedDiscoveryResponse({
|
|
944
|
-
request,
|
|
945
|
-
content: skill.content,
|
|
946
|
-
contentType: "text/markdown; charset=utf-8",
|
|
947
|
-
sha256: skill.sha256,
|
|
948
|
-
linkHeader: [linkHeader, formatLinkTarget(DEFAULT_AGENT_SKILLS_INDEX_ROUTE, "collection", { type: "application/json" })].join(", ")
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
return createHashedDiscoveryResponse({
|
|
952
|
-
request,
|
|
953
|
-
content: `${JSON.stringify(buildDocsAgentSkillsIndex(skill), null, 2)}\n`,
|
|
954
|
-
contentType: "application/json; charset=utf-8",
|
|
955
|
-
linkHeader: [linkHeader, formatLinkTarget(skill.url, "item", { type: "text/markdown" })].join(", ")
|
|
956
|
-
});
|
|
957
|
-
}
|
|
958
|
-
|
|
959
739
|
//#endregion
|
|
960
740
|
//#region src/sitemap.ts
|
|
961
741
|
const DEFAULT_SITEMAP_XML_ROUTE = "/sitemap.xml";
|
|
@@ -2329,9 +2109,6 @@ const DEFAULT_OPENAPI_SCHEMA_ROUTE = `${DEFAULT_DOCS_API_ROUTE}?format=openapi`;
|
|
|
2329
2109
|
const DEFAULT_AGENT_SPEC_ROUTE = "/api/docs/agent/spec";
|
|
2330
2110
|
const DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE = "/.well-known/agent";
|
|
2331
2111
|
const DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE = "/.well-known/agent.json";
|
|
2332
|
-
const DEFAULT_MCP_ROUTE = "/api/docs/mcp";
|
|
2333
|
-
const DEFAULT_MCP_PUBLIC_ROUTE = "/mcp";
|
|
2334
|
-
const DEFAULT_MCP_WELL_KNOWN_ROUTE = "/.well-known/mcp";
|
|
2335
2112
|
const DEFAULT_LLMS_TXT_ROUTE = "/llms.txt";
|
|
2336
2113
|
const DEFAULT_LLMS_FULL_TXT_ROUTE = "/llms-full.txt";
|
|
2337
2114
|
const DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE = "/.well-known/llms.txt";
|
|
@@ -3460,7 +3237,7 @@ function resolveDocsStandardsOrigin(preferred, fallback) {
|
|
|
3460
3237
|
return new URL(fallback).origin;
|
|
3461
3238
|
}
|
|
3462
3239
|
/** Build and serve standards-based discovery without replacing the custom agent manifest. */
|
|
3463
|
-
async function createDocsStandardsDiscoveryResponse({ request, preferredSkillDocument, fallbackSkillDocument, origin, entry = "docs", docsPath, apiCatalog: explicitApiCatalog, apiRoute, i18n: _i18n, search: _search, mcp, feedback, llms, sitemap, robots, openapi, markdown: _markdown }) {
|
|
3240
|
+
async function createDocsStandardsDiscoveryResponse({ request, preferredSkillDocument, fallbackSkillDocument, origin, entry = "docs", docsPath, apiCatalog: explicitApiCatalog, apiRoute, i18n: _i18n, search: _search, mcp, feedback, llms, sitemap, robots, openapi, markdown: _markdown, publishedSkills, agentCard }) {
|
|
3464
3241
|
const url = new URL(request.url);
|
|
3465
3242
|
const resolvedApiRoute = resolveDocsDiscoveryApiRoute(apiRoute);
|
|
3466
3243
|
if (!isDocsStandardsDiscoveryRequest(url, { apiRoute: resolvedApiRoute })) return null;
|
|
@@ -3488,12 +3265,15 @@ async function createDocsStandardsDiscoveryResponse({ request, preferredSkillDoc
|
|
|
3488
3265
|
sitemapConfig.markdown.docsRoute,
|
|
3489
3266
|
sitemapConfig.markdown.wellKnownRoute
|
|
3490
3267
|
].filter((route) => Boolean(route)) : []] : [];
|
|
3268
|
+
const protectedResourceMetadataRoutes = mcp.enabled && mcp.security?.authenticate && mcp.security.protectedResource ? getDocsMcpProtectedResourceMetadataRoutes(mcp.route) : [];
|
|
3491
3269
|
return createDocsStandardsResponse({
|
|
3492
3270
|
request,
|
|
3493
3271
|
apiCatalogEnabled,
|
|
3494
3272
|
apiRoute: resolvedApiRoute,
|
|
3495
3273
|
preferredSkillDocument,
|
|
3496
3274
|
fallbackSkillDocument,
|
|
3275
|
+
publishedSkills,
|
|
3276
|
+
agentCard,
|
|
3497
3277
|
apiCatalog: apiCatalogEnabled ? buildDocsApiCatalog({
|
|
3498
3278
|
origin: catalogOrigin,
|
|
3499
3279
|
docsRoute: normalizedDocsPath ? `/${normalizedDocsPath}` : "/",
|
|
@@ -3502,6 +3282,8 @@ async function createDocsStandardsDiscoveryResponse({ request, preferredSkillDoc
|
|
|
3502
3282
|
diagnosticsRoute: `${resolvedApiRoute}?format=diagnostics`,
|
|
3503
3283
|
agentManifestRoute: DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE,
|
|
3504
3284
|
agentSkillsIndexRoute: DEFAULT_AGENT_SKILLS_INDEX_ROUTE,
|
|
3285
|
+
legacySkillsIndexRoute: DEFAULT_LEGACY_SKILLS_INDEX_ROUTE,
|
|
3286
|
+
agentCardRoute: agentCard ? DEFAULT_A2A_AGENT_CARD_ROUTE : null,
|
|
3505
3287
|
agentsRoute: DEFAULT_AGENTS_MD_ROUTE,
|
|
3506
3288
|
skillRoute: DEFAULT_SKILL_MD_ROUTE,
|
|
3507
3289
|
markdownRootRoute: `/${normalizedEntry}.md`,
|
|
@@ -3509,6 +3291,7 @@ async function createDocsStandardsDiscoveryResponse({ request, preferredSkillDoc
|
|
|
3509
3291
|
sitemapRoutes,
|
|
3510
3292
|
robotsRoute: robotsEnabled ? DEFAULT_AGENT_DISCOVERY_ROBOTS_TXT_ROUTE : null,
|
|
3511
3293
|
mcpRoute: mcp.enabled ? mcp.route : null,
|
|
3294
|
+
protectedResourceMetadataRoutes,
|
|
3512
3295
|
feedbackRoutes: feedback?.enabled ? [feedbackRoute, feedbackSchemaRoute] : [],
|
|
3513
3296
|
openapiRoute: openapiConfig.enabled ? openapiUrl ?? `${resolvedApiRoute}?format=openapi` : null,
|
|
3514
3297
|
apiReferenceRoute: openapiConfig.enabled && openapiConfig.apiReferencePath ? openapiConfig.apiReferencePath : null
|
|
@@ -3520,10 +3303,6 @@ function isDocsAgentDiscoveryRequest(url, options = {}) {
|
|
|
3520
3303
|
if (pathname === resolveDocsDiscoveryApiRoute(options.apiRoute) && url.searchParams.get("agent")?.trim() === "spec") return true;
|
|
3521
3304
|
return pathname === DEFAULT_AGENT_SPEC_ROUTE || pathname === DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE || pathname === DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE;
|
|
3522
3305
|
}
|
|
3523
|
-
function isDocsMcpRequest(url) {
|
|
3524
|
-
const pathname = normalizeDocsUrlPath(url.pathname);
|
|
3525
|
-
return pathname === DEFAULT_MCP_ROUTE || pathname === DEFAULT_MCP_PUBLIC_ROUTE || pathname === DEFAULT_MCP_WELL_KNOWN_ROUTE;
|
|
3526
|
-
}
|
|
3527
3306
|
function buildDocsMcpEndpointCandidates(baseUrl, routes = [DEFAULT_MCP_PUBLIC_ROUTE, DEFAULT_MCP_WELL_KNOWN_ROUTE], options = {}) {
|
|
3528
3307
|
const includeOriginFallback = options.includeOriginFallback !== false;
|
|
3529
3308
|
const includeRootDomainFallback = options.includeRootDomainFallback !== false;
|
|
@@ -4219,7 +3998,7 @@ function resolveDocsAgentContractMcpTools(mcp) {
|
|
|
4219
3998
|
if (mcp.tools.readTask !== false) tools.read = "read_task";
|
|
4220
3999
|
return tools.list || tools.read ? tools : void 0;
|
|
4221
4000
|
}
|
|
4222
|
-
function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCatalog: explicitApiCatalog, i18n = null, search, mcp, feedback, llms, sitemap, robots, openapi, markdown }) {
|
|
4001
|
+
function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCatalog: explicitApiCatalog, i18n = null, search, mcp, feedback, llms, sitemap, robots, openapi, markdown, publishedSkills = [], agentCard }) {
|
|
4223
4002
|
const normalizedEntry = normalizeDocsPathSegment(entry) || "docs";
|
|
4224
4003
|
const resolvedApiRoute = resolveDocsDiscoveryApiRoute(apiRoute);
|
|
4225
4004
|
const apiQueryRoute = (query) => `${resolvedApiRoute}?${query}`;
|
|
@@ -4236,6 +4015,8 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
|
|
|
4236
4015
|
const openapiUrl = resolveDocsOpenApiDiscoveryUrl(openapiConfig, resolvedApiRoute);
|
|
4237
4016
|
const agentContractMcpTools = resolveDocsAgentContractMcpTools(mcp);
|
|
4238
4017
|
const apiCatalogEnabled = explicitApiCatalog ?? llms?.apiCatalog ?? true;
|
|
4018
|
+
const protectedResource = mcp.enabled && mcp.security?.authenticate ? mcp.security.protectedResource : void 0;
|
|
4019
|
+
const protectedResourceMetadataRoutes = protectedResource ? getDocsMcpProtectedResourceMetadataRoutes(mcp.route) : [];
|
|
4239
4020
|
return {
|
|
4240
4021
|
version: "1",
|
|
4241
4022
|
name: "@farming-labs/docs",
|
|
@@ -4289,6 +4070,8 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
|
|
|
4289
4070
|
apiCatalogQuery: apiQueryRoute(`format=${DEFAULT_API_CATALOG_FORMAT}`)
|
|
4290
4071
|
} : {},
|
|
4291
4072
|
agentSkillsIndex: DEFAULT_AGENT_SKILLS_INDEX_ROUTE,
|
|
4073
|
+
legacySkillsIndex: DEFAULT_LEGACY_SKILLS_INDEX_ROUTE,
|
|
4074
|
+
...agentCard ? { agentCard: DEFAULT_A2A_AGENT_CARD_ROUTE } : {},
|
|
4292
4075
|
openapi: defaultOpenapiRoute
|
|
4293
4076
|
},
|
|
4294
4077
|
apiCatalog: {
|
|
@@ -4421,10 +4204,26 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
|
|
|
4421
4204
|
schema: AGENT_SKILLS_DISCOVERY_SCHEMA_URI,
|
|
4422
4205
|
index: DEFAULT_AGENT_SKILLS_INDEX_ROUTE,
|
|
4423
4206
|
artifact: DEFAULT_AGENT_SKILLS_ROUTE_PATTERN,
|
|
4207
|
+
archive: DEFAULT_AGENT_SKILLS_ARCHIVE_ROUTE_PATTERN,
|
|
4208
|
+
file: `${DEFAULT_AGENT_SKILLS_ROUTE_PATTERN.replace("/SKILL.md", "/{path}")}`,
|
|
4209
|
+
legacyIndex: DEFAULT_LEGACY_SKILLS_INDEX_ROUTE,
|
|
4424
4210
|
apiIndex: apiQueryRoute(`format=${DEFAULT_AGENT_SKILLS_INDEX_FORMAT}`),
|
|
4425
4211
|
apiArtifact: apiQueryRoute("format=agent-skill&name={name}"),
|
|
4212
|
+
apiFile: apiQueryRoute("format=agent-skill-file&name={name}&path={path}"),
|
|
4426
4213
|
digest: "sha256"
|
|
4427
4214
|
},
|
|
4215
|
+
published: publishedSkills.map((skill) => ({
|
|
4216
|
+
name: skill.name,
|
|
4217
|
+
description: skill.description,
|
|
4218
|
+
type: skill.type,
|
|
4219
|
+
url: skill.url,
|
|
4220
|
+
digest: skill.digest,
|
|
4221
|
+
files: skill.files.map((file) => ({
|
|
4222
|
+
path: file.path,
|
|
4223
|
+
url: file.url,
|
|
4224
|
+
digest: file.digest
|
|
4225
|
+
}))
|
|
4226
|
+
})),
|
|
4428
4227
|
recommended: [{
|
|
4429
4228
|
name: "getting-started",
|
|
4430
4229
|
description: "Use for installation, init, framework setup, theme CSS, and first docs.config wiring."
|
|
@@ -4437,10 +4236,16 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
|
|
|
4437
4236
|
publicEndpoint: DEFAULT_MCP_PUBLIC_ROUTE,
|
|
4438
4237
|
wellKnownEndpoint: DEFAULT_MCP_WELL_KNOWN_ROUTE,
|
|
4439
4238
|
publicEndpoints: [DEFAULT_MCP_PUBLIC_ROUTE, DEFAULT_MCP_WELL_KNOWN_ROUTE],
|
|
4440
|
-
canonicalEndpoint:
|
|
4239
|
+
canonicalEndpoint: mcp.route,
|
|
4441
4240
|
name: mcp.name,
|
|
4442
4241
|
version: mcp.version,
|
|
4443
|
-
tools: mcp.tools
|
|
4242
|
+
tools: mcp.tools,
|
|
4243
|
+
...protectedResource ? { protectedResource: {
|
|
4244
|
+
metadataEndpoints: protectedResourceMetadataRoutes,
|
|
4245
|
+
authorizationServers: protectedResource.authorizationServers,
|
|
4246
|
+
scopesSupported: protectedResource.scopesSupported,
|
|
4247
|
+
requiredScopes: protectedResource.requiredScopes
|
|
4248
|
+
} } : {}
|
|
4444
4249
|
},
|
|
4445
4250
|
feedback: {
|
|
4446
4251
|
enabled: feedback?.enabled ?? false,
|
|
@@ -4544,4 +4349,4 @@ function toYamlString(value) {
|
|
|
4544
4349
|
}
|
|
4545
4350
|
|
|
4546
4351
|
//#endregion
|
|
4547
|
-
export {
|
|
4352
|
+
export { renderDocsAgentsDocument as $, DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE as $t, buildDocsAgentFeedbackSchema as A, buildDocsSitemapManifest as At, getDocsMarkdownVaryHeader as B, renderDocsRelatedMarkdownLines as Bt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as C, resolveDocsAudienceExposure as Ct, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as D, DEFAULT_SITEMAP_MD_ROUTE as Dt, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as E, DEFAULT_SITEMAP_MD_DOCS_ROUTE as Et, createDocsStandardsDiscoveryResponse as F, resolveDocsSitemapConfig as Ft, isDocsDiagnosticsRequest as G, PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS as Gt, isDocsAgentDiscoveryRequest as H, PAGE_AGENT_CONTRACT_FIELDS as Ht, detectDocsMarkdownAgentRequest as I, resolveDocsSitemapPageLastmod as It, isDocsSkillRequest as J, normalizePageAgentFrontmatter as Jt, isDocsLlmsTxtPublicRequest as K, getPageAgentFrontmatterIssues as Kt, findDocsMarkdownPage as L, resolveDocsSitemapRequest as Lt, buildDocsDiagnostics as M, readDocsSitemapManifestFromContentMap as Mt, buildDocsMcpEndpointCandidates as N, renderDocsSitemapMarkdown as Nt, acceptsDocsMarkdown as O, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as Ot, createDocsMarkdownResponse as P, renderDocsSitemapXml as Pt, parseDocsAgentFeedbackData as Q, upsertPageAgentContractMarkdown as Qt, getDocsLlmsTxtMaxCharsIssue as R, toDocsSitemapMarkdownUrl as Rt, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as S, resolveDocsAgentMdxContent as St, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS as T, DEFAULT_SITEMAP_MANIFEST_PATH as Tt, isDocsAgentsRequest as U, PAGE_AGENT_CONTRACT_FIELD_SCHEMA as Ut, hasDocsMarkdownSignatureAgent as V, PAGE_AGENT_CONTRACT_END_MARKER as Vt, isDocsConfigRequest as W, PAGE_AGENT_CONTRACT_START_MARKER as Wt, normalizeDocsPathSegment as X, renderPageAgentFrontmatterYamlLines as Xt, matchesDocsLlmsTxtSection as Y, renderPageAgentContractMarkdown as Yt, normalizeDocsUrlPath as Z, stripGeneratedPageAgentContractMarkdown as Zt, DEFAULT_LLMS_TXT_MAX_CHARS as _, selectDocsLlmsTxtContent as _t, DEFAULT_AGENT_MD_ROUTE as a, getDocsMcpResourcePaths as an, resolveDocsAgentFeedbackConfig as at, DEFAULT_OPENAPI_SCHEMA_ROUTE as b, findDocsAudienceMdxIssues as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, isDocsMcpProtectedResourceMetadataPath as cn, resolveDocsLlmsTxtFormat as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, normalizeDocsMcpAuthorizationServerUrls as dn, resolveDocsMarkdownCanonicalUrl as dt, DEFAULT_MCP_PUBLIC_ROUTE as en, renderDocsLlmsTxt as et, DEFAULT_DOCS_CONFIG_ROUTE as f, normalizeDocsMcpEndpointPath as fn, resolveDocsMarkdownRecovery as ft, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as g, resolveDocsSkillFormat as gt, DEFAULT_LLMS_FULL_TXT_ROUTE as h, resolveDocsRequestApiRoute as ht, DEFAULT_AGENT_FEEDBACK_ROUTE as i, getDocsMcpProtectedResourceMetadataRoutes as in, resolveDocsAgentContractMcpTools as it, buildDocsConfigMap as j, createDocsSitemapResponse as jt, buildDocsAgentDiscoverySpec as k, DEFAULT_SITEMAP_XML_ROUTE as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, isDocsMcpRequest as ln, resolveDocsLlmsTxtRequest as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, resolveDocsMcpResourceLocation as mn, resolveDocsOpenApiDiscoveryConfig as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, DEFAULT_MCP_WELL_KNOWN_ROUTE as nn, renderDocsMarkdownNotFound as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, hasDocsMcpProtectedResourceConfig as on, resolveDocsAgentFeedbackRequest as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, resolveDocsMcpProtectedResourceMetadataLocation as pn, resolveDocsMarkdownRequest as pt, isDocsPublicGetRequest as q, hasStructuredPageAgentContract as qt, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, buildDocsMcpProtectedResourceMetadataRoute as rn, renderDocsSkillDocument as rt, DEFAULT_AGENT_SPEC_ROUTE as s, isDocsMcpOAuthScopeToken as sn, resolveDocsAgentsFormat as st, DEFAULT_AGENTS_MD_ROUTE as t, DEFAULT_MCP_ROUTE as tn, renderDocsMarkdownDocument as tt, DEFAULT_DOCS_API_ROUTE as u, isDocsMcpResourcePath as un, resolveDocsLlmsTxtSections as ut, DEFAULT_LLMS_TXT_ROUTE as v, toDocsMarkdownUrl as vt, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as w, resolveDocsAudienceMdxContent as wt, DEFAULT_SKILL_MD_ROUTE as x, findDocsAudienceMdxTags as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, validateDocsAgentFeedbackPayload as yt, getDocsMarkdownCanonicalLinkHeader as z, normalizeDocsRelated as zt };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { f as resolveSearchRequestConfig, p as findDocsMarkdownSection, t as buildDocsAskAIContext, u as performDocsSearch } from "./search-
|
|
2
|
-
import { a as normalizeAgentScopeValues, i as normalizeAgentLocale, n as agentVersionConstraintsOverlap, o as normalizeAgentVersion, r as normalizeAgentFramework, t as agentVersionConstraintMatches } from "./agent-scope-
|
|
1
|
+
import { f as resolveSearchRequestConfig, p as findDocsMarkdownSection, t as buildDocsAskAIContext, u as performDocsSearch } from "./search-9OnMGMvt.mjs";
|
|
2
|
+
import { a as normalizeAgentScopeValues, i as normalizeAgentLocale, n as agentVersionConstraintsOverlap, o as normalizeAgentVersion, r as normalizeAgentFramework, t as agentVersionConstraintMatches } from "./agent-scope-C_U--OZ7.mjs";
|
|
3
3
|
import { buildDocsMcpContext } from "./mcp.mjs";
|
|
4
|
-
import { i as validateCodeBlockPlans, n as planCodeBlockTargets, r as resolveDocsCodeBlocksValidateConfig, t as extractCodeBlocksFromMarkdown } from "./code-blocks-
|
|
4
|
+
import { i as validateCodeBlockPlans, n as planCodeBlockTargets, r as resolveDocsCodeBlocksValidateConfig, t as extractCodeBlocksFromMarkdown } from "./code-blocks-DnNVNK2M.mjs";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
7
7
|
import { createJiti } from "jiti";
|