@farming-labs/docs 0.2.57 → 0.2.59

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 (46) hide show
  1. package/dist/{agent-CxDzPqtl.mjs → agent-BFqyqEnC.mjs} +557 -71
  2. package/dist/{agent-v6R0V3lm.mjs → agent-DlxriaTs.mjs} +3 -3
  3. package/dist/agent-evals-kJs2Y9xR.mjs +2144 -0
  4. package/dist/{agent-export-CZR20g0e.mjs → agent-export-BgUaiW8f.mjs} +20 -10
  5. package/dist/{agents-BPonjolo.mjs → agents-Djh-HXih.mjs} +15 -7
  6. package/dist/cli/index.mjs +29 -29
  7. package/dist/client/react.d.mts +1 -1
  8. package/dist/{cloud-C45jpBtp.mjs → cloud-BH_sHX64.mjs} +3 -3
  9. package/dist/{cloud-ask-ai-CvRVnwdK.d.mts → cloud-ask-ai-B2WnG4fF.d.mts} +1 -1
  10. package/dist/{code-blocks-C9awWzEQ.mjs → code-blocks-qe0T8-xe.mjs} +1 -1
  11. package/dist/{codeblocks-CSqgqbg-.mjs → codeblocks-Bq67u32v.mjs} +2 -2
  12. package/dist/{dev-BA2kRuCn.mjs → dev-CAQlbguk.mjs} +2 -2
  13. package/dist/docs-cloud-server.d.mts +2 -2
  14. package/dist/docs-cloud-server.mjs +1 -1
  15. package/dist/{doctor-svA9Flsx.mjs → doctor-CO1VMcF_.mjs} +208 -41
  16. package/dist/{downgrade-BStNhyCc.mjs → downgrade-BZs86NVr.mjs} +2 -2
  17. package/dist/{agent-surface-drift-rGFS38Ak.mjs → golden-evaluations-BN9u2wxw.mjs} +60 -4
  18. package/dist/index.d.mts +98 -20
  19. package/dist/index.mjs +6 -5
  20. package/dist/{init-Dm0yDz6v.mjs → init-B_9ENq8Z.mjs} +3 -3
  21. package/dist/{mcp-BYIgKsPn.mjs → mcp-BAJr3wC2.mjs} +6 -6
  22. package/dist/mcp.d.mts +1 -1
  23. package/dist/mcp.mjs +149 -7
  24. package/dist/metadata-BDuewuzq.mjs +237 -0
  25. package/dist/{package-version-DRIc08EU.mjs → package-version-qik_4J6C.mjs} +1 -1
  26. package/dist/{reading-time-W_Id2ayC.mjs → reading-time-BkEft6SD.mjs} +307 -250
  27. package/dist/{review-DZ81wm7h.mjs → review-NC-sOdXn.mjs} +44 -32
  28. package/dist/{robots-mSc98PMp.mjs → robots-DskPvGPw.mjs} +4 -4
  29. package/dist/{robots-DRpoiYAV.mjs → robots-ltltiLJF.mjs} +4 -1
  30. package/dist/{search-9uEaC23e.d.mts → search-C1JitPwi.d.mts} +153 -6
  31. package/dist/{search-OHp36znm.mjs → search-D57JXQLj.mjs} +150 -39
  32. package/dist/{search-AMEoabYU.mjs → search-o4Ud6OXv.mjs} +6 -6
  33. package/dist/server.d.mts +108 -6
  34. package/dist/server.mjs +6 -6
  35. package/dist/{sitemap-Cyc0Bbbn.mjs → sitemap-Cq-Yj_iA.mjs} +7 -7
  36. package/dist/{sitemap-server-zFYctvCa.mjs → sitemap-server-C1ibVKOy.mjs} +2 -1
  37. package/dist/{types-R-DN23yw.d.mts → types-XHABMh_f.d.mts} +96 -6
  38. package/dist/{upgrade-CXYRNV0C.mjs → upgrade-BCJTCW3O.mjs} +2 -2
  39. package/package.json +1 -1
  40. package/dist/agent-evals-BD17jOqL.mjs +0 -1166
  41. /package/dist/{agent-scope-B8lptqCd.mjs → agent-scope-CCaIY1aK.mjs} +0 -0
  42. /package/dist/{cloud-ask-ai-1k0q6OAH.mjs → cloud-ask-ai-hnJfj8-X.mjs} +0 -0
  43. /package/dist/{config-DZbZiYEa.mjs → config-DASewQ0x.mjs} +0 -0
  44. /package/dist/{errors-BFUtdZfC.mjs → errors-CVqZ3kOO.mjs} +0 -0
  45. /package/dist/{templates-1Cod8KrJ.mjs → templates-CfQjpDWW.mjs} +0 -0
  46. /package/dist/{utils-DBCCkkJS.mjs → utils-6UCLxv4B.mjs} +0 -0
@@ -1,20 +1,22 @@
1
- import { i as scanDocsPageTargets, n as compactAgentDocs, r as inspectAgentCompactionState } from "./agent-v6R0V3lm.mjs";
2
- import "./reading-time-W_Id2ayC.mjs";
3
- import { At as DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, I as buildDocsMcpEndpointCandidates, Lt as resolveDocsSitemapConfig, M as buildDocsAgentDiscoverySpec, O as DOCS_CONFIG_MAP_TOP_LEVEL_KEYS, P as buildDocsConfigMap, S as DEFAULT_MCP_WELL_KNOWN_ROUTE, T as DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, Wt as PAGE_AGENT_CONTRACT_FIELDS, b as DEFAULT_MCP_PUBLIC_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, l as DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, n as DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE, t as DEFAULT_AGENTS_MD_ROUTE, u as DEFAULT_DOCS_API_ROUTE, v as DEFAULT_LLMS_TXT_ROUTE, w as DEFAULT_SKILL_MD_ROUTE } from "./agent-CxDzPqtl.mjs";
4
- import "./search-OHp36znm.mjs";
5
- import { a as analyzeDocsRobotsTxt, n as DEFAULT_ROBOTS_TXT_ROUTE, u as resolveDocsRobotsConfig } from "./robots-DRpoiYAV.mjs";
6
- import "./sitemap-server-zFYctvCa.mjs";
7
- import { t as runDocsGoldenTasks } from "./agent-evals-BD17jOqL.mjs";
1
+ import { i as scanDocsPageTargets, n as compactAgentDocs, r as inspectAgentCompactionState } from "./agent-DlxriaTs.mjs";
2
+ import { l as httpLinkHeaderHasTargetRelation } from "./reading-time-BkEft6SD.mjs";
3
+ import { Gt as API_CATALOG_PROFILE_URI, I as buildDocsMcpEndpointCandidates, Jt as DEFAULT_AGENT_SKILLS_ROUTE_PATTERN, Kt as DEFAULT_AGENT_SKILLS_INDEX_FORMAT, M as buildDocsAgentDiscoverySpec, Mt as DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, Nt as DEFAULT_SITEMAP_XML_ROUTE, O as DOCS_CONFIG_MAP_TOP_LEVEL_KEYS, P as buildDocsConfigMap, Qt as DEFAULT_API_CATALOG_ROUTE, S as DEFAULT_MCP_WELL_KNOWN_ROUTE, T as DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, Ut as AGENT_SKILLS_DISCOVERY_SCHEMA_URI, Wt as API_CATALOG_MEDIA_TYPE, Xt as DEFAULT_AGENT_SKILL_FORMAT, Zt as DEFAULT_API_CATALOG_FORMAT, an as resolveDocsDiscoveryApiRoute, b as DEFAULT_MCP_PUBLIC_ROUTE, c as DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, fn as PAGE_AGENT_CONTRACT_FIELDS, h as DEFAULT_LLMS_FULL_TXT_ROUTE, i as DEFAULT_AGENT_FEEDBACK_ROUTE, jt as DEFAULT_SITEMAP_MD_ROUTE, l as DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, n as DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE, qt as DEFAULT_AGENT_SKILLS_INDEX_ROUTE, t as DEFAULT_AGENTS_MD_ROUTE, v as DEFAULT_LLMS_TXT_ROUTE, w as DEFAULT_SKILL_MD_ROUTE, zt as resolveDocsSitemapConfig } from "./agent-BFqyqEnC.mjs";
4
+ import { d as resolveAskAISearchRequestConfig } from "./search-D57JXQLj.mjs";
5
+ import { a as analyzeDocsRobotsTxt, n as DEFAULT_ROBOTS_TXT_ROUTE, u as resolveDocsRobotsConfig } from "./robots-ltltiLJF.mjs";
6
+ import { a as resolveDocsMetadataBaseUrl } from "./metadata-BDuewuzq.mjs";
7
+ import "./sitemap-server-C1ibVKOy.mjs";
8
+ import { t as runDocsGoldenTasks } from "./agent-evals-kJs2Y9xR.mjs";
8
9
  import { createFilesystemDocsMcpSource, getDocsConfigSchema, resolveDocsMcpConfig } from "./mcp.mjs";
9
- import "./code-blocks-C9awWzEQ.mjs";
10
+ import "./code-blocks-qe0T8-xe.mjs";
10
11
  import "./server.mjs";
11
- import { a as loadDocsConfigModuleResultWithProjectEnv, h as resolveDocsContentDir, l as readNavTitle, m as resolveDocsConfigPath, p as readTopLevelStringProperty, r as extractTopLevelConfigObject, s as readBooleanProperty, t as extractNestedObjectLiteral } from "./config-DZbZiYEa.mjs";
12
- import { t as detectFramework } from "./utils-DBCCkkJS.mjs";
13
- import { n as analyzeAgentUsefulness, r as createAgentUsefulnessPagesFromMcp, t as analyzeAgentSurfaceDrift } from "./agent-surface-drift-rGFS38Ak.mjs";
12
+ import { a as loadDocsConfigModuleResultWithProjectEnv, h as resolveDocsContentDir, l as readNavTitle, m as resolveDocsConfigPath, p as readTopLevelStringProperty, r as extractTopLevelConfigObject, s as readBooleanProperty, t as extractNestedObjectLiteral } from "./config-DASewQ0x.mjs";
13
+ import { t as detectFramework } from "./utils-6UCLxv4B.mjs";
14
+ import { i as createAgentUsefulnessPagesFromMcp, n as analyzeAgentSurfaceDrift, r as analyzeAgentUsefulness, t as resolveGoldenEvaluationInput } from "./golden-evaluations-BN9u2wxw.mjs";
14
15
  import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
15
16
  import path from "node:path";
16
17
  import { LATEST_PROTOCOL_VERSION } from "@modelcontextprotocol/sdk/types.js";
17
18
  import pc from "picocolors";
19
+ import { createHash } from "node:crypto";
18
20
 
19
21
  //#region src/cli/doctor.ts
20
22
  const NEXT_CONFIG_PATTERN = /^next\.config\.(?:[cm]?js|[cm]?ts)$/;
@@ -1068,26 +1070,6 @@ async function probeMcpRouteCandidates(baseUrl, routes, expectedTools) {
1068
1070
  function asRecord(value) {
1069
1071
  return value && typeof value === "object" ? value : void 0;
1070
1072
  }
1071
- function isPlainRecord(value) {
1072
- return Boolean(asRecord(value)) && !Array.isArray(value);
1073
- }
1074
- function resolveGoldenEvaluationTasks(evaluationInput) {
1075
- if (evaluationInput === void 0 || typeof evaluationInput === "boolean") return void 0;
1076
- if (!isPlainRecord(evaluationInput)) return { evaluationConfig: evaluationInput };
1077
- if (evaluationInput.enabled === false) return void 0;
1078
- if ("enabled" in evaluationInput && typeof evaluationInput.enabled !== "boolean") return evaluationInput;
1079
- if (!("tasks" in evaluationInput)) return void 0;
1080
- const runtimeTasks = evaluationInput.tasks;
1081
- if (!Array.isArray(runtimeTasks)) return runtimeTasks;
1082
- return runtimeTasks.map((task) => {
1083
- if (!isPlainRecord(task)) return task;
1084
- return {
1085
- ...task,
1086
- tokenBudget: task.tokenBudget ?? evaluationInput.tokenBudget,
1087
- topK: task.topK ?? evaluationInput.topK
1088
- };
1089
- });
1090
- }
1091
1073
  function isNonEmptyString(value) {
1092
1074
  return typeof value === "string" && value.trim().length > 0;
1093
1075
  }
@@ -1100,11 +1082,160 @@ function isHostedAgentDiscoveryManifest(value) {
1100
1082
  const site = asRecord(root?.site);
1101
1083
  const capabilities = asRecord(root?.capabilities);
1102
1084
  const api = asRecord(root?.api);
1085
+ const apiCatalog = asRecord(root?.apiCatalog);
1103
1086
  const config = asRecord(root?.config);
1104
1087
  const search = asRecord(root?.search);
1088
+ const skillsDiscovery = asRecord(asRecord(root?.skills)?.discovery);
1105
1089
  const mcp = asRecord(root?.mcp);
1106
1090
  const agentContractFields = asRecord(asRecord(root?.agentContract)?.fields);
1107
- return Boolean(root && isNonEmptyString(root.version) && isNonEmptyString(root.name) && isNonEmptyString(root.baseUrl) && isNonEmptyString(site?.entry) && typeof capabilities?.search === "boolean" && typeof capabilities?.mcp === "boolean" && isNonEmptyString(api?.docs) && isNonEmptyString(api?.config) && isNonEmptyString(config?.endpoint) && typeof search?.enabled === "boolean" && isNonEmptyString(search?.endpoint) && typeof mcp?.enabled === "boolean" && isNonEmptyString(mcp?.endpoint) && isBooleanRecord(mcp?.tools) && agentContractFields && Object.keys(agentContractFields).length > 0);
1091
+ const apiRoute = isNonEmptyString(api?.docs) ? resolveDocsDiscoveryApiRoute(api.docs) : void 0;
1092
+ return Boolean(root && isNonEmptyString(root.version) && isNonEmptyString(root.name) && isNonEmptyString(root.baseUrl) && isNonEmptyString(site?.entry) && typeof capabilities?.search === "boolean" && typeof capabilities?.mcp === "boolean" && capabilities?.apiCatalog === true && capabilities?.agentSkillsDiscovery === true && apiRoute && api?.docs === apiRoute && api?.config === `${apiRoute}?format=config` && api?.apiCatalog === DEFAULT_API_CATALOG_ROUTE && api?.apiCatalogQuery === `${apiRoute}?format=${DEFAULT_API_CATALOG_FORMAT}` && api?.agentSkillsIndex === DEFAULT_AGENT_SKILLS_INDEX_ROUTE && apiCatalog?.enabled === true && apiCatalog?.route === DEFAULT_API_CATALOG_ROUTE && apiCatalog?.api === `${apiRoute}?format=${DEFAULT_API_CATALOG_FORMAT}` && apiCatalog?.mediaType === API_CATALOG_MEDIA_TYPE && apiCatalog?.profile === API_CATALOG_PROFILE_URI && skillsDiscovery?.schema === AGENT_SKILLS_DISCOVERY_SCHEMA_URI && skillsDiscovery?.index === DEFAULT_AGENT_SKILLS_INDEX_ROUTE && skillsDiscovery?.artifact === DEFAULT_AGENT_SKILLS_ROUTE_PATTERN && skillsDiscovery?.apiIndex === `${apiRoute}?format=${DEFAULT_AGENT_SKILLS_INDEX_FORMAT}` && skillsDiscovery?.apiArtifact === `${apiRoute}?format=${DEFAULT_AGENT_SKILL_FORMAT}&name={name}` && skillsDiscovery?.digest === "sha256" && config?.endpoint === `${apiRoute}?format=config` && typeof search?.enabled === "boolean" && isNonEmptyString(search?.endpoint) && typeof mcp?.enabled === "boolean" && isNonEmptyString(mcp?.endpoint) && isBooleanRecord(mcp?.tools) && agentContractFields && Object.keys(agentContractFields).length > 0);
1093
+ }
1094
+ function responseMediaType(contentType) {
1095
+ return contentType?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
1096
+ }
1097
+ function contentTypeParameter(contentType, name) {
1098
+ if (!contentType) return void 0;
1099
+ const parameterPattern = new RegExp(`(?:^|;)\\s*${name.replace(/[.*+?^${}()|[\\]\\]/g, "\\$&")}\\s*=\\s*(?:"([^"]*)"|([^;\\s]+))`, "i");
1100
+ const match = contentType.match(parameterPattern);
1101
+ return match?.[1] ?? match?.[2];
1102
+ }
1103
+ function isApiCatalogLinkset(value) {
1104
+ const root = asRecord(value);
1105
+ if (!Array.isArray(root?.linkset) || root.linkset.length === 0) return false;
1106
+ let apiLinks = 0;
1107
+ for (const rawContext of root.linkset) {
1108
+ const context = asRecord(rawContext);
1109
+ if (!isNonEmptyString(context?.anchor)) return false;
1110
+ if (!Array.isArray(context.item)) continue;
1111
+ for (const rawItem of context.item) {
1112
+ if (!isNonEmptyString(asRecord(rawItem)?.href)) return false;
1113
+ apiLinks += 1;
1114
+ }
1115
+ }
1116
+ return apiLinks > 0;
1117
+ }
1118
+ async function probeApiCatalogRoute(baseUrl) {
1119
+ const route = DEFAULT_API_CATALOG_ROUTE;
1120
+ const url = joinDoctorUrl(baseUrl, route);
1121
+ try {
1122
+ const [getResponse, headResponse] = await Promise.all([fetchWithTimeout(url, { headers: { Accept: API_CATALOG_MEDIA_TYPE } }), fetchWithTimeout(url, {
1123
+ method: "HEAD",
1124
+ headers: { Accept: API_CATALOG_MEDIA_TYPE }
1125
+ })]);
1126
+ const text = await getResponse.text().catch(() => "");
1127
+ let body;
1128
+ try {
1129
+ body = JSON.parse(text);
1130
+ } catch {
1131
+ body = void 0;
1132
+ }
1133
+ const failures = [];
1134
+ if (!getResponse.ok) failures.push(`GET returned HTTP ${getResponse.status}`);
1135
+ if (!headResponse.ok) failures.push(`HEAD returned HTTP ${headResponse.status}`);
1136
+ for (const [method, response] of [["GET", getResponse], ["HEAD", headResponse]]) {
1137
+ const contentType = response.headers.get("content-type");
1138
+ if (responseMediaType(contentType) !== API_CATALOG_MEDIA_TYPE) failures.push(`${method} Content-Type is ${JSON.stringify(contentType ?? "<missing>")}`);
1139
+ else if (contentTypeParameter(contentType, "profile") !== API_CATALOG_PROFILE_URI) failures.push(`${method} Content-Type is missing the RFC 9727 profile`);
1140
+ if (!httpLinkHeaderHasTargetRelation(response.headers.get("link"), DEFAULT_API_CATALOG_ROUTE, "api-catalog", url)) failures.push(`${method} is missing an ${DEFAULT_API_CATALOG_ROUTE} rel="api-catalog" Link value`);
1141
+ }
1142
+ if (!isApiCatalogLinkset(body)) failures.push("GET did not return a JSON Linkset with at least one API item");
1143
+ return failures.length === 0 ? {
1144
+ ok: true,
1145
+ detail: `${route} passed RFC 9727 GET and HEAD checks with a profiled JSON Linkset and api-catalog Link headers.`
1146
+ } : {
1147
+ ok: false,
1148
+ detail: `${route} failed standards validation: ${failures.join("; ")}.`
1149
+ };
1150
+ } catch (error) {
1151
+ return {
1152
+ ok: false,
1153
+ detail: `${route} failed: ${error instanceof Error ? error.message : String(error)}.`
1154
+ };
1155
+ }
1156
+ }
1157
+ function isValidAgentSkillEntry(value) {
1158
+ const entry = asRecord(value);
1159
+ return Boolean(entry && typeof entry.name === "string" && /^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(entry.name) && entry.name.length <= 64 && entry.type === "skill-md" && isNonEmptyString(entry.description) && entry.description.length <= 1024 && isNonEmptyString(entry.url) && typeof entry.digest === "string" && /^sha256:[0-9a-f]{64}$/u.test(entry.digest));
1160
+ }
1161
+ async function probeAgentSkillsDiscovery(baseUrl) {
1162
+ const route = DEFAULT_AGENT_SKILLS_INDEX_ROUTE;
1163
+ const indexUrl = joinDoctorUrl(baseUrl, route);
1164
+ try {
1165
+ const [indexResponse, indexHeadResponse] = await Promise.all([fetchWithTimeout(indexUrl, { headers: { Accept: "application/json" } }), fetchWithTimeout(indexUrl, {
1166
+ method: "HEAD",
1167
+ headers: { Accept: "application/json" }
1168
+ })]);
1169
+ const text = await indexResponse.text().catch(() => "");
1170
+ const failures = [];
1171
+ let body;
1172
+ try {
1173
+ body = JSON.parse(text);
1174
+ } catch {
1175
+ body = void 0;
1176
+ }
1177
+ if (!indexResponse.ok) failures.push(`index returned HTTP ${indexResponse.status}`);
1178
+ if (!indexHeadResponse.ok) failures.push(`index HEAD returned HTTP ${indexHeadResponse.status}`);
1179
+ if (responseMediaType(indexResponse.headers.get("content-type")) !== "application/json") failures.push("index Content-Type is not application/json");
1180
+ if (responseMediaType(indexHeadResponse.headers.get("content-type")) !== "application/json") failures.push("index HEAD Content-Type is not application/json");
1181
+ const root = asRecord(body);
1182
+ if (root?.$schema !== AGENT_SKILLS_DISCOVERY_SCHEMA_URI) failures.push("index $schema is not the Agent Skills discovery 0.2.0 schema");
1183
+ const skills = Array.isArray(root?.skills) ? root.skills : [];
1184
+ if (skills.length === 0) failures.push("index does not publish any skills");
1185
+ if (skills.length > 100) failures.push("index publishes more than 100 skills");
1186
+ const validSkills = skills.filter(isValidAgentSkillEntry);
1187
+ if (validSkills.length !== skills.length) failures.push("one or more index entries have invalid name, type, description, URL, or digest fields");
1188
+ if (new Set(validSkills.map((skill) => skill.name)).size !== validSkills.length) failures.push("index contains duplicate skill names");
1189
+ const baseOrigin = new URL(baseUrl).origin;
1190
+ const artifactDetails = [];
1191
+ if (skills.length <= 100) for (const skill of validSkills) {
1192
+ let artifactUrl;
1193
+ try {
1194
+ artifactUrl = new URL(skill.url, indexUrl);
1195
+ } catch {
1196
+ failures.push(`${skill.name} has an invalid artifact URL`);
1197
+ continue;
1198
+ }
1199
+ const expectedPath = DEFAULT_AGENT_SKILLS_ROUTE_PATTERN.replace("{name}", skill.name);
1200
+ if (artifactUrl.origin !== baseOrigin) {
1201
+ failures.push(`${skill.name} artifact is not same-origin`);
1202
+ continue;
1203
+ }
1204
+ if (!artifactUrl.pathname.endsWith(expectedPath)) {
1205
+ failures.push(`${skill.name} artifact URL does not match ${expectedPath}`);
1206
+ continue;
1207
+ }
1208
+ try {
1209
+ const [artifactResponse, artifactHeadResponse] = await Promise.all([fetchWithTimeout(artifactUrl.toString(), { headers: { Accept: "text/markdown" } }), fetchWithTimeout(artifactUrl.toString(), {
1210
+ method: "HEAD",
1211
+ headers: { Accept: "text/markdown" }
1212
+ })]);
1213
+ const content = Buffer.from(await artifactResponse.arrayBuffer());
1214
+ const computedDigest = `sha256:${createHash("sha256").update(content).digest("hex")}`;
1215
+ if (!artifactResponse.ok) failures.push(`${skill.name} artifact returned HTTP ${artifactResponse.status}`);
1216
+ else if (!artifactHeadResponse.ok) failures.push(`${skill.name} artifact HEAD returned HTTP ${artifactHeadResponse.status}`);
1217
+ else if (responseMediaType(artifactResponse.headers.get("content-type")) !== "text/markdown") failures.push(`${skill.name} artifact Content-Type is not text/markdown`);
1218
+ else if (responseMediaType(artifactHeadResponse.headers.get("content-type")) !== "text/markdown") failures.push(`${skill.name} artifact HEAD Content-Type is not text/markdown`);
1219
+ else if (content.length === 0) failures.push(`${skill.name} artifact is empty`);
1220
+ else if (computedDigest !== skill.digest) failures.push(`${skill.name} artifact digest does not match the index`);
1221
+ else artifactDetails.push(`${skill.name} digest verified`);
1222
+ } catch (error) {
1223
+ failures.push(`${skill.name} artifact failed: ${error instanceof Error ? error.message : String(error)}`);
1224
+ }
1225
+ }
1226
+ return failures.length === 0 ? {
1227
+ ok: true,
1228
+ detail: `${route} returned a valid Agent Skills index; ${artifactDetails.join(", ")}.`
1229
+ } : {
1230
+ ok: false,
1231
+ detail: `${route} failed standards validation: ${failures.join("; ")}.`
1232
+ };
1233
+ } catch (error) {
1234
+ return {
1235
+ ok: false,
1236
+ detail: `${route} failed: ${error instanceof Error ? error.message : String(error)}.`
1237
+ };
1238
+ }
1108
1239
  }
1109
1240
  function readDiscoveryRoute(value) {
1110
1241
  return typeof value === "string" && value.startsWith("/") ? value : void 0;
@@ -1256,6 +1387,9 @@ async function buildHostedAgentChecks(url, pages) {
1256
1387
  const discovery = await probeJsonRoute(baseUrl, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE);
1257
1388
  const discoveryManifestValid = discovery.ok && isHostedAgentDiscoveryManifest(discovery.body);
1258
1389
  checks.push(makeCheck("hosted-agent-discovery", "Hosted agent discovery", discoveryManifestValid ? "pass" : "fail", discoveryManifestValid ? 5 : 0, 5, `${baseUrl}: ${discovery.ok && !discoveryManifestValid ? `${discovery.detail} The payload is not a complete agent discovery manifest.` : discovery.detail}`, discoveryManifestValid ? void 0 : `Make sure ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE} returns the complete agent discovery manifest from the shared docs API.`));
1390
+ const [apiCatalog, agentSkills] = await Promise.all([probeApiCatalogRoute(baseUrl), probeAgentSkillsDiscovery(baseUrl)]);
1391
+ checks.push(makeCheck("hosted-api-catalog", "Hosted RFC 9727 API catalog", apiCatalog.ok ? "pass" : "fail", apiCatalog.ok ? 5 : 0, 5, apiCatalog.detail, apiCatalog.ok ? void 0 : `Publish ${DEFAULT_API_CATALOG_ROUTE} with GET and HEAD support, the profiled ${API_CATALOG_MEDIA_TYPE} content type, a rel="api-catalog" Link header, and API links.`));
1392
+ checks.push(makeCheck("hosted-agent-skills", "Hosted Agent Skills discovery", agentSkills.ok ? "pass" : "fail", agentSkills.ok ? 5 : 0, 5, agentSkills.detail, agentSkills.ok ? void 0 : `Publish ${DEFAULT_AGENT_SKILLS_INDEX_ROUTE} and make every indexed SKILL.md artifact match its declared SHA-256 digest.`));
1259
1393
  const llms = await Promise.all([probeTextRoute(baseUrl, DEFAULT_LLMS_TXT_ROUTE), probeTextRoute(baseUrl, DEFAULT_LLMS_FULL_TXT_ROUTE)]);
1260
1394
  const llmsPassed = llms.filter((result) => result.ok).length;
1261
1395
  checks.push(makeCheck("hosted-llms", "Hosted llms.txt", llmsPassed === llms.length ? "pass" : llmsPassed > 0 ? "warn" : "fail", llmsPassed === llms.length ? 5 : llmsPassed > 0 ? 3 : 0, 5, llms.map((result) => result.detail).join(" "), llmsPassed === llms.length ? void 0 : "Verify deployed /llms.txt and /llms-full.txt routes return non-empty text."));
@@ -1388,7 +1522,26 @@ async function inspectAgentReadiness(options = {}) {
1388
1522
  projectFramework: framework === "unknown" ? void 0 : framework
1389
1523
  });
1390
1524
  const evaluationInput = config?.agent?.evaluations;
1391
- const evaluations = await runDocsGoldenTasks(pages, resolveGoldenEvaluationTasks(evaluationInput));
1525
+ const evaluation = resolveGoldenEvaluationInput(evaluationInput);
1526
+ const evaluationBaseUrl = config ? resolveDocsMetadataBaseUrl(config) : void 0;
1527
+ const evaluationMcp = resolveDocsMcpConfig(config?.mcp, { defaultName: siteTitle });
1528
+ const askAISearch = resolveAskAISearchRequestConfig({
1529
+ search: config?.search,
1530
+ useMcp: config?.ai?.useMcp,
1531
+ mcpEndpoint: evaluationMcp.route,
1532
+ mcpEnabled: evaluationMcp.enabled,
1533
+ mcpSearchEnabled: evaluationMcp.tools.searchDocs,
1534
+ requestUrl: evaluationBaseUrl
1535
+ });
1536
+ const evaluations = await runDocsGoldenTasks(pages, evaluation.tasks, {
1537
+ ...evaluation.options,
1538
+ search: config?.search,
1539
+ askAISearch,
1540
+ siteTitle,
1541
+ baseUrl: evaluationBaseUrl,
1542
+ rootDir,
1543
+ codeBlocksValidate: config?.codeBlocks?.validate
1544
+ });
1392
1545
  const compactionCoverage = buildCompactionCoverage(rootDir, contentDir, entry, pages, config?.agent?.compact ?? {});
1393
1546
  coverage.compaction = compactionCoverage;
1394
1547
  const metadataCoverage = buildMetadataCoverage(pages);
@@ -1408,9 +1561,11 @@ async function inspectAgentReadiness(options = {}) {
1408
1561
  const robotsPath = resolveRobotsFilePath(rootDir, framework, typeof robotsInput === "object" ? robotsInput : void 0);
1409
1562
  const feedbackRoute = DEFAULT_AGENT_FEEDBACK_ROUTE;
1410
1563
  const feedbackSchemaRoute = `${feedbackRoute}/schema`;
1564
+ const apiRoute = resolveDocsDiscoveryApiRoute(config?.cloud?.apiRoute);
1411
1565
  const discovery = buildDocsAgentDiscoverySpec({
1412
1566
  origin: "http://localhost",
1413
1567
  entry,
1568
+ apiRoute,
1414
1569
  search: searchEnabled,
1415
1570
  mcp: mcpConfig,
1416
1571
  feedback: {
@@ -1429,7 +1584,7 @@ async function inspectAgentReadiness(options = {}) {
1429
1584
  entry,
1430
1585
  search: {
1431
1586
  enabled: searchEnabled,
1432
- endpoint: `${DEFAULT_DOCS_API_ROUTE}?query={query}`
1587
+ endpoint: `${apiRoute}?query={query}`
1433
1588
  },
1434
1589
  mcp: {
1435
1590
  enabled: mcpConfig.enabled,
@@ -1437,23 +1592,32 @@ async function inspectAgentReadiness(options = {}) {
1437
1592
  tools: mcpConfig.tools
1438
1593
  },
1439
1594
  routes: {
1440
- "api.docs": DEFAULT_DOCS_API_ROUTE,
1441
- "api.config": DEFAULT_DOCS_CONFIG_ROUTE,
1442
- "config.endpoint": DEFAULT_DOCS_CONFIG_ROUTE
1595
+ "api.docs": apiRoute,
1596
+ "api.config": `${apiRoute}?format=config`,
1597
+ "api.apiCatalog": DEFAULT_API_CATALOG_ROUTE,
1598
+ "api.apiCatalogQuery": `${apiRoute}?format=${DEFAULT_API_CATALOG_FORMAT}`,
1599
+ "api.agentSkillsIndex": DEFAULT_AGENT_SKILLS_INDEX_ROUTE,
1600
+ "apiCatalog.route": DEFAULT_API_CATALOG_ROUTE,
1601
+ "apiCatalog.api": `${apiRoute}?format=${DEFAULT_API_CATALOG_FORMAT}`,
1602
+ "config.endpoint": `${apiRoute}?format=config`,
1603
+ "skills.discovery.index": DEFAULT_AGENT_SKILLS_INDEX_ROUTE,
1604
+ "skills.discovery.artifact": DEFAULT_AGENT_SKILLS_ROUTE_PATTERN,
1605
+ "skills.discovery.apiIndex": `${apiRoute}?format=${DEFAULT_AGENT_SKILLS_INDEX_FORMAT}`,
1606
+ "skills.discovery.apiArtifact": `${apiRoute}?format=${DEFAULT_AGENT_SKILL_FORMAT}&name={name}`
1443
1607
  }
1444
1608
  }
1445
1609
  });
1446
1610
  const checks = [];
1447
1611
  checks.push(makeCheck("config", "Docs config", configLoad.status === "evaluated" ? "pass" : "warn", configLoad.status === "evaluated" ? 10 : 2, configCheckMax, configLoad.status === "evaluated" ? `Resolved ${path.relative(rootDir, configLoad.path).replace(/\\/g, "/")} and evaluated the config module.` : `Resolved ${path.relative(rootDir, configPath).replace(/\\/g, "/")} using static parsing fallback.`, configLoad.status === "evaluated" ? void 0 : "Fix docs.config module evaluation before relying on resolved diagnostic scores."));
1448
1612
  const canScoreSurfaceDrift = configLoad.status === "evaluated";
1449
- checks.push(makeCheck("surface-drift", "Discovery/config/schema consistency", !canScoreSurfaceDrift ? "warn" : surfaceDrift.length === 0 ? "pass" : "fail", !canScoreSurfaceDrift ? 0 : surfaceDrift.length === 0 ? 10 : Math.max(0, 10 - surfaceDrift.length * 2), 10, !canScoreSurfaceDrift ? "Not scored because docs.config could not be evaluated; static parsing cannot prove discovery/config/schema consistency." : surfaceDrift.length === 0 ? "Resolved config, discovery metadata, MCP tool flags, config schema, and agent contract fields agree." : surfaceDrift.slice(0, 3).map((issue) => issue.message).join(" "), canScoreSurfaceDrift && surfaceDrift.length === 0 ? void 0 : canScoreSurfaceDrift ? "Align docs config, agent discovery, MCP tools, config schema, and the canonical page agent contract before publishing." : "Fix docs.config module evaluation so doctor can compare resolved config with discovery and schema surfaces."));
1613
+ checks.push(makeCheck("surface-drift", "Discovery/config/schema consistency", !canScoreSurfaceDrift ? "warn" : surfaceDrift.length === 0 ? "pass" : "fail", !canScoreSurfaceDrift ? 0 : surfaceDrift.length === 0 ? 10 : Math.max(0, 10 - surfaceDrift.length * 2), 10, !canScoreSurfaceDrift ? "Not scored because docs.config could not be evaluated; static parsing cannot prove discovery/config/schema consistency." : surfaceDrift.length === 0 ? "Resolved config, discovery metadata, MCP tool flags, config schema, and agent contract fields agree." : surfaceDrift.slice(0, 3).map((issue) => issue.message).join(" "), canScoreSurfaceDrift && surfaceDrift.length === 0 ? void 0 : canScoreSurfaceDrift ? "Align docs config, agent discovery (including API catalog and Agent Skills routes), MCP tools, config schema, and the canonical page agent contract before publishing." : "Fix docs.config module evaluation so doctor can compare resolved config with discovery and schema surfaces."));
1450
1614
  const dynamicStaticFallback = configLoad.status === "static-fallback" && /(?:\.\.\.|process\.env|import\.meta\.env|\[[^\]]+\]\s*:|:\s*[A-Za-z_$][\w$]*\s*[,}])/u.test(configContent);
1451
1615
  checks.push(configLoad.status === "evaluated" ? makeCheck("config-confidence", "Config loading confidence", "pass", 5, 5, "High confidence: docs.config was evaluated with project-local environment values.") : makeCheck("config-confidence", "Config loading confidence", "warn", dynamicStaticFallback ? 1 : 2, 5, `${dynamicStaticFallback ? "Low" : "Partial"} confidence: only static config parsing succeeded. ${configLoad.error}`, "Fix docs.config module evaluation so doctor and review can inspect dynamic values, golden tasks, and resolved feature settings."));
1452
1616
  const contentDirAbs = path.resolve(rootDir, contentDir);
1453
1617
  checks.push(coverage.totalPages > 0 ? makeCheck("content", "Docs content", "pass", 10, 10, `Found ${coverage.totalPages} docs page${coverage.totalPages === 1 ? "" : "s"} in ${path.relative(rootDir, contentDirAbs).replace(/\\/g, "/")}.`) : makeCheck("content", "Docs content", "fail", 0, 10, `No folder-based docs pages were found in ${path.relative(rootDir, contentDirAbs).replace(/\\/g, "/")}.`, "Add index/page MDX files under the configured contentDir so the machine-readable surfaces have pages to serve."));
1454
1618
  checks.push(makeCheck("api-route", "Docs API route", routeSurface.apiMounted ? "pass" : "fail", routeSurface.apiMounted ? 10 : 0, 10, routeSurface.apiDetail, routeSurface.apiMounted ? void 0 : "Wire the framework docs API route so /api/docs can serve markdown, llms.txt, sitemap, AGENTS.md, skill.md, and discovery responses."));
1455
- checks.push(makeCheck("public-routes", "Public agent routes", routeSurface.publicMounted ? "pass" : "fail", routeSurface.publicMounted ? 10 : 0, 10, routeSurface.publicDetail, routeSurface.publicMounted ? void 0 : "Add the framework public forwarder so /.well-known/*, /llms.txt, /sitemap.xml, /sitemap.md, /docs/sitemap.md, /AGENTS.md, /skill.md, /mcp, and .md routes resolve from the shared docs API."));
1456
- checks.push(makeCheck("agent-discovery", "Agent discovery spec", routeSurface.apiMounted && routeSurface.publicMounted ? "pass" : "fail", routeSurface.apiMounted && routeSurface.publicMounted ? 5 : 0, 5, routeSurface.apiMounted && routeSurface.publicMounted ? `Expected discovery endpoints are available through ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}, ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}, and /api/docs?agent=spec.` : "Could not verify the shared agent discovery spec endpoints because docs API/public route wiring is incomplete.", routeSurface.apiMounted && routeSurface.publicMounted ? void 0 : "Make sure both the docs API handler and the public docs forwarder are mounted so agents can discover the site through the well-known agent spec."));
1619
+ checks.push(makeCheck("public-routes", "Public agent routes", routeSurface.publicMounted ? "pass" : "fail", routeSurface.publicMounted ? 10 : 0, 10, routeSurface.publicDetail, routeSurface.publicMounted ? void 0 : "Add the framework public forwarder so /.well-known/api-catalog, /.well-known/agent-skills/*, the other /.well-known/* resources, /llms.txt, /sitemap.xml, /sitemap.md, /docs/sitemap.md, /AGENTS.md, /skill.md, /mcp, and .md routes resolve from the shared docs API."));
1620
+ checks.push(makeCheck("agent-discovery", "Agent discovery spec", routeSurface.apiMounted && routeSurface.publicMounted ? "pass" : "fail", routeSurface.apiMounted && routeSurface.publicMounted ? 5 : 0, 5, routeSurface.apiMounted && routeSurface.publicMounted ? `Expected discovery endpoints are available through ${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}, ${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}, ${DEFAULT_API_CATALOG_ROUTE}, ${DEFAULT_AGENT_SKILLS_INDEX_ROUTE}, and /api/docs?agent=spec.` : "Could not verify the shared agent discovery spec endpoints because docs API/public route wiring is incomplete.", routeSurface.apiMounted && routeSurface.publicMounted ? void 0 : "Make sure both the docs API handler and public docs forwarder expose the custom agent manifest, RFC 9727 API catalog, and Agent Skills discovery routes."));
1457
1621
  checks.push(llmsEnabled ? makeCheck("llms", "llms.txt discovery", "pass", 5, 5, `Enabled via ${DEFAULT_LLMS_TXT_ROUTE} and ${DEFAULT_LLMS_FULL_TXT_ROUTE}.`) : makeCheck("llms", "llms.txt discovery", "warn", 0, 5, `${DEFAULT_LLMS_TXT_ROUTE} and ${DEFAULT_LLMS_FULL_TXT_ROUTE} are disabled in docs config.`, "Enable llmsTxt so agents and GEO crawlers can discover the docs index and full context surfaces."));
1458
1622
  checks.push(sitemapConfig.enabled ? makeCheck("sitemap", "Sitemap discovery", "pass", 5, 5, `Enabled via ${[
1459
1623
  sitemapConfig.xml.route,
@@ -1721,9 +1885,12 @@ async function runDoctor(options = {}) {
1721
1885
  let fixes;
1722
1886
  if (options.fix) {
1723
1887
  fixes = await runAgentDoctorFixes(report, options);
1724
- report = {
1888
+ report = fixes.some((fix) => fix.status === "applied") ? {
1725
1889
  ...await inspectAgentReadiness(options),
1726
1890
  fixes
1891
+ } : {
1892
+ ...report,
1893
+ fixes
1727
1894
  };
1728
1895
  }
1729
1896
  applyDoctorExitCode(report, options);
@@ -1,5 +1,5 @@
1
- import { c as fileExists, o as exec, s as execOutput } from "./utils-DBCCkkJS.mjs";
2
- import { a as getPackagesForFramework, c as resolveDocsPackageManager, l as validateUpgradeVersion, r as buildDocsPackageInstallCommand, s as resolveDocsPackageFramework } from "./package-version-DRIc08EU.mjs";
1
+ import { c as fileExists, o as exec, s as execOutput } from "./utils-6UCLxv4B.mjs";
2
+ import { a as getPackagesForFramework, c as resolveDocsPackageManager, l as validateUpgradeVersion, r as buildDocsPackageInstallCommand, s as resolveDocsPackageFramework } from "./package-version-qik_4J6C.mjs";
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import pc from "picocolors";
@@ -1,6 +1,6 @@
1
- import { Ct as findDocsAudienceMdxTags, Et as resolveDocsAudienceMdxContent, Xt as normalizePageAgentFrontmatter, Yt as hasStructuredPageAgentContract } from "./agent-CxDzPqtl.mjs";
2
- import { n as agentVersionConstraintsOverlap, o as normalizeAgentVersion, r as normalizeAgentFramework } from "./agent-scope-B8lptqCd.mjs";
3
- import { t as extractCodeBlocksFromMarkdown } from "./code-blocks-C9awWzEQ.mjs";
1
+ import { Ot as resolveDocsAudienceMdxContent, Tt as findDocsAudienceMdxTags, _n as hasStructuredPageAgentContract, vn as normalizePageAgentFrontmatter } from "./agent-BFqyqEnC.mjs";
2
+ import { n as agentVersionConstraintsOverlap, o as normalizeAgentVersion, r as normalizeAgentFramework } from "./agent-scope-CCaIY1aK.mjs";
3
+ import { t as extractCodeBlocksFromMarkdown } from "./code-blocks-qe0T8-xe.mjs";
4
4
  import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
5
5
  import path from "node:path";
6
6
 
@@ -1282,6 +1282,11 @@ function collectSchemaPaths(options) {
1282
1282
  function schemaCoversConfigPath(schemaPaths, configPath) {
1283
1283
  if (schemaPaths.has(configPath)) return true;
1284
1284
  if (configPath.endsWith("[]") && schemaPaths.has(configPath.slice(0, -2))) return true;
1285
+ for (const schemaPath of schemaPaths) {
1286
+ if (!schemaPath.endsWith(".*")) continue;
1287
+ const prefix = schemaPath.slice(0, -1);
1288
+ if (configPath.startsWith(prefix) && configPath.length > prefix.length) return true;
1289
+ }
1285
1290
  return false;
1286
1291
  }
1287
1292
  function readPath(root, dotPath) {
@@ -1424,4 +1429,55 @@ function analyzeAgentSurfaceDrift(options) {
1424
1429
  }
1425
1430
 
1426
1431
  //#endregion
1427
- export { extractAgentBlocks as i, analyzeAgentUsefulness as n, createAgentUsefulnessPagesFromMcp as r, analyzeAgentSurfaceDrift as t };
1432
+ //#region src/cli/golden-evaluations.ts
1433
+ function isPlainRecord(value) {
1434
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1435
+ }
1436
+ /** Normalize the runtime docs.config evaluation shape shared by doctor and review. */
1437
+ function resolveGoldenEvaluationInput(evaluationInput) {
1438
+ if (evaluationInput === void 0 || typeof evaluationInput === "boolean") return {
1439
+ tasks: void 0,
1440
+ options: {}
1441
+ };
1442
+ if (!isPlainRecord(evaluationInput)) return {
1443
+ tasks: { evaluationConfig: evaluationInput },
1444
+ options: {}
1445
+ };
1446
+ const options = {
1447
+ surface: evaluationInput.surface,
1448
+ allowNetwork: evaluationInput.allowNetwork,
1449
+ searchTimeoutMs: evaluationInput.searchTimeoutMs,
1450
+ answer: evaluationInput.answer
1451
+ };
1452
+ if (evaluationInput.enabled === false) return {
1453
+ tasks: void 0,
1454
+ options
1455
+ };
1456
+ if ("enabled" in evaluationInput && typeof evaluationInput.enabled !== "boolean") return {
1457
+ tasks: evaluationInput,
1458
+ options
1459
+ };
1460
+ if (!("tasks" in evaluationInput)) return {
1461
+ tasks: void 0,
1462
+ options
1463
+ };
1464
+ const runtimeTasks = evaluationInput.tasks;
1465
+ if (!Array.isArray(runtimeTasks)) return {
1466
+ tasks: runtimeTasks,
1467
+ options
1468
+ };
1469
+ return {
1470
+ tasks: runtimeTasks.map((task) => {
1471
+ if (!isPlainRecord(task)) return task;
1472
+ return {
1473
+ ...task,
1474
+ tokenBudget: task.tokenBudget ?? evaluationInput.tokenBudget,
1475
+ topK: task.topK ?? evaluationInput.topK
1476
+ };
1477
+ }),
1478
+ options
1479
+ };
1480
+ }
1481
+
1482
+ //#endregion
1483
+ export { extractAgentBlocks as a, createAgentUsefulnessPagesFromMcp as i, analyzeAgentSurfaceDrift as n, analyzeAgentUsefulness as r, resolveGoldenEvaluationInput as t };