@farming-labs/docs 0.2.120 → 0.2.122
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 +8 -0
- package/dist/access.d.mts +13 -0
- package/dist/access.mjs +56 -0
- package/dist/agent-conformance.d.mts +60 -0
- package/dist/agent-conformance.mjs +538 -0
- package/dist/agent-contract.d.mts +47 -0
- package/dist/agent-contract.mjs +645 -0
- package/dist/agent-detection.d.mts +6 -0
- package/dist/agent-detection.mjs +83 -0
- package/dist/agent-evals.d.mts +224 -0
- package/dist/{agent-evals-BLNLvXbG.mjs → agent-evals.mjs} +7 -565
- package/dist/agent-feedback-evaluations-node.mjs +38 -0
- package/dist/agent-feedback-evaluations.d.mts +91 -0
- package/dist/{agent-feedback-evaluations-CcMGlgsO.mjs → agent-feedback-evaluations.mjs} +2 -2
- package/dist/agent-feedback-loop.d.mts +45 -0
- package/dist/{agent-feedback-loop-CcZL_sb1.mjs → agent-feedback-loop.mjs} +1 -1
- package/dist/agent-maintenance.d.mts +71 -0
- package/dist/{agent-maintenance-CuZ7iAKq.mjs → agent-maintenance.mjs} +1 -1
- package/dist/agent-provenance.d.mts +23 -0
- package/dist/agent-provenance.mjs +77 -0
- package/dist/agent-scope.mjs +321 -0
- package/dist/agent-skills-archive.mjs +86 -0
- package/dist/agent-skills-bundle.d.mts +1 -1
- package/dist/{agent-skills-progressive-disclosure-PjPtTYL-.mjs → agent-skills-progressive-disclosure.mjs} +2 -2
- package/dist/{agent-skills-server-D5IuvwM7.d.mts → agent-skills-server.d.mts} +3 -3
- package/dist/{agent-skills-server-BC7md56k.mjs → agent-skills-server.mjs} +2 -2
- package/dist/agent-skills-vite.d.mts +3 -3
- package/dist/agent-skills-vite.mjs +1 -2
- package/dist/agent-surface-drift.mjs +236 -0
- package/dist/{golden-evaluations-CLUViycJ.mjs → agent-usefulness.mjs} +5 -290
- package/dist/{content-change-hydration-wqXIZHp6.d.mts → agent.d.mts} +10 -411
- package/dist/agent.mjs +2729 -0
- package/dist/{analytics-w3FDOksr.d.mts → analytics.d.mts} +2 -2
- package/dist/{analytics-p8Vhhu2P.mjs → analytics.mjs} +2 -2
- package/dist/{sitemap-server-BUdPBcGs.d.mts → api-reference.d.mts} +2 -6
- package/dist/api-reference.mjs +1481 -0
- package/dist/{audience-exposure-DBrFWULA.d.mts → audience-exposure.d.mts} +1 -1
- package/dist/audience-exposure.mjs +8 -0
- package/dist/audience.d.mts +44 -0
- package/dist/audience.mjs +1654 -0
- package/dist/authoring-mcp.d.mts +44 -0
- package/dist/{authoring-mcp-CiCUQe3o.mjs → authoring-mcp.mjs} +3 -3
- package/dist/browser.d.mts +6 -4
- package/dist/browser.mjs +6 -7
- package/dist/build.d.mts +8 -0
- package/dist/build.mjs +8 -0
- package/dist/changelog.d.mts +20 -0
- package/dist/changelog.mjs +39 -0
- package/dist/{agent-export-CA6IUQ7T.mjs → cli/agent-export.mjs} +19 -45
- package/dist/{agent-CYk2DxY7.mjs → cli/agent.mjs} +6 -35
- package/dist/{agents-BUiVmj8i.mjs → cli/agents.mjs} +5 -18
- package/dist/cli/api-doctor.mjs +206 -0
- package/dist/{authoring-C2ymvYWl.mjs → cli/authoring.mjs} +2 -8
- package/dist/{cloud-6eKrlmKd.mjs → cli/cloud.mjs} +3 -3
- package/dist/{codeblocks-CHpgAwY-.mjs → cli/codeblocks.mjs} +2 -2
- package/dist/cli/config.d.mts +11 -0
- package/dist/{config-BZnKAj_Y.mjs → cli/config.mjs} +1 -1
- package/dist/cli/dev-banner.mjs +58 -0
- package/dist/{dev-Bnn-NUNa.mjs → cli/dev.mjs} +3 -57
- package/dist/{doctor-Bfkrkzad.mjs → cli/doctor.mjs} +41 -226
- package/dist/{downgrade-CHMta85e.mjs → cli/downgrade.mjs} +2 -2
- package/dist/cli/errors.d.mts +4 -0
- package/dist/{errors-BtnVLhNF.mjs → cli/errors.mjs} +1 -1
- package/dist/{feedback-evals-DMilg9pY.mjs → cli/feedback-evals.mjs} +3 -36
- package/dist/{feedback-DL4T5oIO.mjs → cli/feedback.mjs} +1 -1
- package/dist/cli/git-dates.mjs +35 -0
- package/dist/cli/golden-evaluations.mjs +52 -0
- package/dist/cli/index.d.mts +2 -3
- package/dist/cli/index.mjs +38 -38
- package/dist/{init-K0LmXDZ5.mjs → cli/init.mjs} +3 -3
- package/dist/{mcp-iLCmnPJI.mjs → cli/mcp.mjs} +7 -19
- package/dist/{openapi-diff-HcpUNjA-.mjs → cli/openapi-diff.mjs} +2 -7
- package/dist/{openapi-sdk-BQKC6H-_.mjs → cli/openapi-sdk.mjs} +2 -7
- package/dist/{openapi-source-DK6ts_Bk.mjs → cli/openapi-source.mjs} +2 -2
- package/dist/{package-version-HJhYeq4M.mjs → cli/package-version.mjs} +2 -2
- package/dist/{propose-JmUv_BTt.mjs → cli/propose.mjs} +1 -1
- package/dist/{review-C6EmbV0l.mjs → cli/review.mjs} +16 -15
- package/dist/{robots-DteZB8vl.mjs → cli/robots.mjs} +3 -7
- package/dist/{search-Bhuv_YsL.mjs → cli/search.mjs} +7 -20
- package/dist/{sitemap-DW5LDKDa.mjs → cli/sitemap.mjs} +7 -42
- package/dist/{skills-BAPQLSCm.mjs → cli/skills.mjs} +5 -19
- package/dist/{templates-BuQ8YsGv.mjs → cli/templates.mjs} +1 -1
- package/dist/{upgrade-DlQMOFV1.mjs → cli/upgrade.mjs} +2 -2
- package/dist/{utils-C7KDrPpA.mjs → cli/utils.mjs} +1 -1
- package/dist/client/react.d.mts +2 -18
- package/dist/client/react.mjs +1 -157
- package/dist/{cloud-analytics-D14HplI7.mjs → cloud-analytics.mjs} +1 -1
- package/dist/{cloud-ask-ai-BrsTXQf6.d.mts → cloud-ask-ai.d.mts} +2 -2
- package/dist/{cloud-ask-ai-BqKhjpS5.mjs → cloud-ask-ai.mjs} +3 -3
- package/dist/code-blocks.d.mts +51 -0
- package/dist/{code-blocks-GYdvS3BH.mjs → code-blocks.mjs} +2 -2
- package/dist/code-group-mdx.d.mts +11 -0
- package/dist/code-group-mdx.mjs +57 -0
- package/dist/content-change-hydration.d.mts +87 -0
- package/dist/{openapi-mcp-BIOTLiA7.mjs → content-change-hydration.mjs} +5 -210
- package/dist/content-changes.d.mts +47 -0
- package/dist/content-changes.mjs +216 -0
- package/dist/create-theme.d.mts +48 -0
- package/dist/create-theme.mjs +57 -0
- package/dist/date.d.mts +5 -0
- package/dist/date.mjs +17 -0
- package/dist/define-docs.d.mts +9 -0
- package/dist/define-docs.mjs +46 -0
- package/dist/docs-cloud-client.d.mts +18 -0
- package/dist/docs-cloud-client.mjs +161 -0
- package/dist/docs-cloud-server.d.mts +2 -2
- package/dist/docs-cloud-server.mjs +2 -3
- package/dist/heading-toc.d.mts +10 -0
- package/dist/heading-toc.mjs +23 -0
- package/dist/http-body.d.mts +14 -0
- package/dist/{http-body-DkAPk6D5.mjs → http-body.mjs} +1 -1
- package/dist/http-cache.d.mts +25 -0
- package/dist/http-cache.mjs +140 -0
- package/dist/http-link.mjs +81 -0
- package/dist/i18n.d.mts +18 -0
- package/dist/{i18n-B1gJ9EW0.mjs → i18n.mjs} +1 -1
- package/dist/index.d.mts +42 -674
- package/dist/index.mjs +40 -14
- package/dist/markdown-rendering.mjs +1 -1
- package/dist/markdown-section-cache.mjs +49 -0
- package/dist/markdown-sections.d.mts +47 -0
- package/dist/{markdown-sections-9Oxr33b-.mjs → markdown-sections.mjs} +29 -703
- package/dist/mcp-auth.d.mts +14 -0
- package/dist/mcp-auth.mjs +99 -0
- package/dist/mcp.d.mts +5 -3
- package/dist/mcp.mjs +21 -9
- package/dist/mdx.d.mts +6 -0
- package/dist/mdx.mjs +7 -0
- package/dist/metadata.d.mts +60 -0
- package/dist/{metadata-BOHn0Y5K.mjs → metadata.mjs} +2 -2
- package/dist/native-api-reference.mjs +968 -0
- package/dist/okf.d.mts +42 -0
- package/dist/okf.mjs +145 -0
- package/dist/openapi-contract.mjs +154 -0
- package/dist/{openapi-mcp-node-C4jUpZG6.mjs → openapi-mcp-node.mjs} +1 -1
- package/dist/openapi-mcp.d.mts +26 -0
- package/dist/openapi-mcp.mjs +132 -0
- package/dist/openapi-operations.d.mts +71 -0
- package/dist/{openapi-operations-DFpaqOqA.mjs → openapi-operations.mjs} +1 -1
- package/dist/openapi-overlays.mjs +221 -0
- package/dist/openapi-references.mjs +233 -0
- package/dist/pagination.d.mts +7 -0
- package/dist/pagination.mjs +100 -0
- package/dist/prompt-references.d.mts +12 -0
- package/dist/prompt-references.mjs +132 -0
- package/dist/prompt-utils.d.mts +36 -0
- package/dist/{prompt-utils-B5g-bv7o.mjs → prompt-utils.mjs} +1 -57
- package/dist/reading-time.d.mts +23 -0
- package/dist/reading-time.mjs +58 -0
- package/dist/related.d.mts +7 -0
- package/dist/related.mjs +50 -0
- package/dist/retrieval-digest.d.mts +16 -0
- package/dist/{retrieval-digest-CT-eIEcp.mjs → retrieval-digest.mjs} +1 -1
- package/dist/review.d.mts +69 -0
- package/dist/review.mjs +562 -0
- package/dist/robots.d.mts +54 -0
- package/dist/{robots-BYJAVeI6.mjs → robots.mjs} +5 -3
- package/dist/runtime.d.mts +3 -3
- package/dist/runtime.mjs +3 -9
- package/dist/search.d.mts +210 -0
- package/dist/search.mjs +3401 -0
- package/dist/server.d.mts +22 -198
- package/dist/server.mjs +21 -19
- package/dist/sidebar.d.mts +15 -0
- package/dist/sidebar.mjs +73 -0
- package/dist/sitemap-server.d.mts +7 -0
- package/dist/{sitemap-server-Lg3YhUx4.mjs → sitemap-server.mjs} +2 -2
- package/dist/{sitemap-Cl8vrixd.d.mts → sitemap.d.mts} +3 -3
- package/dist/sitemap.mjs +254 -0
- package/dist/{standards-discovery-BHPc7YIX.d.mts → standards-discovery.d.mts} +2 -2
- package/dist/{standards-discovery-sSEojU80.mjs → standards-discovery.mjs} +3 -139
- package/dist/telemetry-runtime.d.mts +42 -0
- package/dist/telemetry-runtime.mjs +238 -0
- package/dist/telemetry.d.mts +15 -0
- package/dist/telemetry.mjs +117 -0
- package/dist/{types-BJFeMXWZ.d.mts → types.d.mts} +3 -2
- package/dist/urls.d.mts +7 -0
- package/dist/urls.mjs +21 -0
- package/dist/utils.d.mts +8 -0
- package/dist/utils.mjs +22 -0
- package/package.json +21 -3
- package/dist/agent-DkAidqtV.mjs +0 -9026
- package/dist/api-reference-BYee4zMo.mjs +0 -3046
- package/dist/prompt-references-DMgbu_dz.mjs +0 -1082
- package/dist/retrieval-digest-AOx2-LbC.d.mts +0 -367
- package/dist/sidebar-CFHBj29f.mjs +0 -421
- package/dist/sidebar-CMPbVfGP.d.mts +0 -63
- /package/dist/{openapi-CfCzX_a1.mjs → cli/openapi.mjs} +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import pc from "picocolors";
|
|
3
|
+
|
|
4
|
+
//#region src/cli/dev-banner.ts
|
|
5
|
+
function createDevLogger() {
|
|
6
|
+
return {
|
|
7
|
+
info(msg) {
|
|
8
|
+
if (msg.includes("VITE") || msg.includes("vite") || msg.includes("ready in") || msg.includes("Local:") || msg.includes("Network:") || msg.includes("➜") || msg.includes("Port") || msg.includes("trying another")) return;
|
|
9
|
+
console.log(msg);
|
|
10
|
+
},
|
|
11
|
+
warn(msg) {
|
|
12
|
+
console.warn(pc.yellow(msg));
|
|
13
|
+
},
|
|
14
|
+
warnOnce(msg) {
|
|
15
|
+
console.warn(pc.yellow(msg));
|
|
16
|
+
},
|
|
17
|
+
error(msg) {
|
|
18
|
+
console.error(pc.red(msg));
|
|
19
|
+
},
|
|
20
|
+
clearScreen() {},
|
|
21
|
+
hasErrorLogged() {
|
|
22
|
+
return false;
|
|
23
|
+
},
|
|
24
|
+
hasWarned: false
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function resolveLocalUrl(protocol, port, localUrl) {
|
|
28
|
+
const resolved = localUrl ?? `${protocol}://localhost:${port}/`;
|
|
29
|
+
return resolved.endsWith("/") ? resolved : `${resolved}/`;
|
|
30
|
+
}
|
|
31
|
+
function resolveNetworkUrl(options) {
|
|
32
|
+
if (!(options.host === true || options.host === "0.0.0.0" || typeof options.host === "string" && options.host !== "localhost" && options.host !== "127.0.0.1")) return null;
|
|
33
|
+
if (options.networkUrl) return options.networkUrl.endsWith("/") ? options.networkUrl : `${options.networkUrl}/`;
|
|
34
|
+
const interfaces = os.networkInterfaces();
|
|
35
|
+
for (const entries of Object.values(interfaces)) for (const iface of entries ?? []) if (iface.family === "IPv4" && !iface.internal) return `${options.protocol}://${iface.address}:${options.port}/`;
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
function printDevBanner({ name = "@farming-labs/docs", version = "v0.0.0", port, host, protocol = "http", startTime, localUrl, networkUrl }) {
|
|
39
|
+
const elapsed = Date.now() - startTime;
|
|
40
|
+
const resolvedLocalUrl = resolveLocalUrl(protocol, port, localUrl);
|
|
41
|
+
const resolvedNetworkUrl = resolveNetworkUrl({
|
|
42
|
+
protocol,
|
|
43
|
+
port,
|
|
44
|
+
host,
|
|
45
|
+
networkUrl
|
|
46
|
+
});
|
|
47
|
+
console.log("");
|
|
48
|
+
console.log(` ${pc.bold(pc.green(name))} ${pc.dim(version)} ${pc.dim(`ready in ${elapsed}ms`)}`);
|
|
49
|
+
console.log("");
|
|
50
|
+
console.log(` ${pc.dim("➜")} ${pc.bold("Local:")} ${pc.cyan(resolvedLocalUrl)}`);
|
|
51
|
+
if (resolvedNetworkUrl === null) console.log(` ${pc.dim("➜")} ${pc.bold("Network:")} ${pc.dim("use --host to expose")}`);
|
|
52
|
+
else if (resolvedNetworkUrl === "") console.log(` ${pc.dim("➜")} ${pc.bold("Network:")} ${pc.dim("no external interface found")}`);
|
|
53
|
+
else console.log(` ${pc.dim("➜")} ${pc.bold("Network:")} ${pc.cyan(resolvedNetworkUrl)}`);
|
|
54
|
+
console.log("");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { createDevLogger, printDevBanner };
|
|
@@ -1,67 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { detectPackageManagerFromProject } from "./utils.mjs";
|
|
2
|
+
import { createDevLogger, printDevBanner } from "./dev-banner.mjs";
|
|
3
|
+
import { docsLayoutTemplate, globalCssTemplate, postcssConfigTemplate, rootLayoutTemplate, tsconfigTemplate } from "./templates.mjs";
|
|
3
4
|
import fs from "node:fs";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
6
7
|
import { spawn } from "node:child_process";
|
|
7
8
|
import { z } from "zod";
|
|
8
|
-
import os from "node:os";
|
|
9
9
|
import pc from "picocolors";
|
|
10
10
|
|
|
11
|
-
//#region src/cli/dev-banner.ts
|
|
12
|
-
function createDevLogger() {
|
|
13
|
-
return {
|
|
14
|
-
info(msg) {
|
|
15
|
-
if (msg.includes("VITE") || msg.includes("vite") || msg.includes("ready in") || msg.includes("Local:") || msg.includes("Network:") || msg.includes("➜") || msg.includes("Port") || msg.includes("trying another")) return;
|
|
16
|
-
console.log(msg);
|
|
17
|
-
},
|
|
18
|
-
warn(msg) {
|
|
19
|
-
console.warn(pc.yellow(msg));
|
|
20
|
-
},
|
|
21
|
-
warnOnce(msg) {
|
|
22
|
-
console.warn(pc.yellow(msg));
|
|
23
|
-
},
|
|
24
|
-
error(msg) {
|
|
25
|
-
console.error(pc.red(msg));
|
|
26
|
-
},
|
|
27
|
-
clearScreen() {},
|
|
28
|
-
hasErrorLogged() {
|
|
29
|
-
return false;
|
|
30
|
-
},
|
|
31
|
-
hasWarned: false
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
function resolveLocalUrl(protocol, port, localUrl) {
|
|
35
|
-
const resolved = localUrl ?? `${protocol}://localhost:${port}/`;
|
|
36
|
-
return resolved.endsWith("/") ? resolved : `${resolved}/`;
|
|
37
|
-
}
|
|
38
|
-
function resolveNetworkUrl(options) {
|
|
39
|
-
if (!(options.host === true || options.host === "0.0.0.0" || typeof options.host === "string" && options.host !== "localhost" && options.host !== "127.0.0.1")) return null;
|
|
40
|
-
if (options.networkUrl) return options.networkUrl.endsWith("/") ? options.networkUrl : `${options.networkUrl}/`;
|
|
41
|
-
const interfaces = os.networkInterfaces();
|
|
42
|
-
for (const entries of Object.values(interfaces)) for (const iface of entries ?? []) if (iface.family === "IPv4" && !iface.internal) return `${options.protocol}://${iface.address}:${options.port}/`;
|
|
43
|
-
return "";
|
|
44
|
-
}
|
|
45
|
-
function printDevBanner({ name = "@farming-labs/docs", version = "v0.0.0", port, host, protocol = "http", startTime, localUrl, networkUrl }) {
|
|
46
|
-
const elapsed = Date.now() - startTime;
|
|
47
|
-
const resolvedLocalUrl = resolveLocalUrl(protocol, port, localUrl);
|
|
48
|
-
const resolvedNetworkUrl = resolveNetworkUrl({
|
|
49
|
-
protocol,
|
|
50
|
-
port,
|
|
51
|
-
host,
|
|
52
|
-
networkUrl
|
|
53
|
-
});
|
|
54
|
-
console.log("");
|
|
55
|
-
console.log(` ${pc.bold(pc.green(name))} ${pc.dim(version)} ${pc.dim(`ready in ${elapsed}ms`)}`);
|
|
56
|
-
console.log("");
|
|
57
|
-
console.log(` ${pc.dim("➜")} ${pc.bold("Local:")} ${pc.cyan(resolvedLocalUrl)}`);
|
|
58
|
-
if (resolvedNetworkUrl === null) console.log(` ${pc.dim("➜")} ${pc.bold("Network:")} ${pc.dim("use --host to expose")}`);
|
|
59
|
-
else if (resolvedNetworkUrl === "") console.log(` ${pc.dim("➜")} ${pc.bold("Network:")} ${pc.dim("no external interface found")}`);
|
|
60
|
-
else console.log(` ${pc.dim("➜")} ${pc.bold("Network:")} ${pc.cyan(resolvedNetworkUrl)}`);
|
|
61
|
-
console.log("");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
//#endregion
|
|
65
11
|
//#region src/cli/dev.ts
|
|
66
12
|
const PRIMARY_MANAGED_CONFIG_FILE = "docs.json";
|
|
67
13
|
const LEGACY_MANAGED_CONFIG_FILE = "docs.cloud.json";
|
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import "
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import "
|
|
12
|
-
import {
|
|
13
|
-
import "
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import "./
|
|
19
|
-
import "
|
|
20
|
-
import "
|
|
21
|
-
import "
|
|
22
|
-
import "./
|
|
23
|
-
import {
|
|
24
|
-
import { t as detectFramework } from "./utils-C7KDrPpA.mjs";
|
|
25
|
-
import { i as createAgentUsefulnessPagesFromMcp, n as analyzeAgentSurfaceDrift, r as analyzeAgentUsefulness, t as resolveGoldenEvaluationInput } from "./golden-evaluations-CLUViycJ.mjs";
|
|
26
|
-
import { t as analyzeConfiguredAgentSkillsProgressiveDisclosure } from "./agent-skills-progressive-disclosure-PjPtTYL-.mjs";
|
|
1
|
+
import { resolveDocsOkfConfig, resolveDocsOkfTrustMetadata } from "../okf.mjs";
|
|
2
|
+
import { DEFAULT_MCP_PUBLIC_ROUTE, DEFAULT_MCP_WELL_KNOWN_ROUTE, getDocsMcpProtectedResourceMetadataRoutes, isDocsMcpOAuthScopeToken, normalizeDocsMcpAuthorizationServerUrls } from "../mcp-auth.mjs";
|
|
3
|
+
import { PAGE_AGENT_CONTRACT_FIELDS } from "../agent-contract.mjs";
|
|
4
|
+
import { resolveAskAISearchRequestConfig } from "../search.mjs";
|
|
5
|
+
import { isDocsAgentSkillName, validateDocsAgentSkillFrontmatter } from "../agent-skills-spec.mjs";
|
|
6
|
+
import { AGENT_SKILLS_DISCOVERY_SCHEMA_URI, API_CATALOG_MEDIA_TYPE, API_CATALOG_PROFILE_URI, DEFAULT_AGENT_SKILLS_INDEX_FORMAT, DEFAULT_AGENT_SKILLS_INDEX_ROUTE, DEFAULT_AGENT_SKILLS_ROUTE_PATTERN, DEFAULT_AGENT_SKILLS_ROUTE_PREFIX, DEFAULT_AGENT_SKILL_FORMAT, DEFAULT_API_CATALOG_FORMAT, DEFAULT_API_CATALOG_ROUTE, resolveDocsDiscoveryApiRoute } from "../standards-discovery.mjs";
|
|
7
|
+
import { DEFAULT_SITEMAP_MD_ROUTE, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, DEFAULT_SITEMAP_XML_ROUTE, resolveDocsSitemapConfig } from "../sitemap.mjs";
|
|
8
|
+
import { DEFAULT_AGENTS_MD_ROUTE, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE, DEFAULT_AGENT_FEEDBACK_ROUTE, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, DEFAULT_LLMS_FULL_TXT_ROUTE, DEFAULT_LLMS_TXT_ROUTE, DEFAULT_SKILL_MD_ROUTE, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS, buildDocsAgentDiscoverySpec, buildDocsConfigMap, buildDocsMcpEndpointCandidates } from "../agent.mjs";
|
|
9
|
+
import { AGENT_SKILL_ARCHIVE_MAX_UNCOMPRESSED_BYTES, readAgentSkillDocumentFromTar } from "../agent-skills-archive.mjs";
|
|
10
|
+
import { httpLinkHeaderHasTargetRelation } from "../http-link.mjs";
|
|
11
|
+
import { DEFAULT_ROBOTS_TXT_ROUTE, analyzeDocsRobotsTxt, resolveDocsRobotsConfig } from "../robots.mjs";
|
|
12
|
+
import { resolveDocsMetadataBaseUrl } from "../metadata.mjs";
|
|
13
|
+
import { resolveConfiguredAgentSkills } from "../agent-skills-server.mjs";
|
|
14
|
+
import { createFilesystemDocsMcpSource, getDocsConfigSchema, resolveDocsMcpConfig } from "../mcp.mjs";
|
|
15
|
+
import { runDocsGoldenTasks } from "../agent-evals.mjs";
|
|
16
|
+
import { extractNestedObjectLiteral, extractTopLevelConfigObject, loadDocsConfigModuleResultWithProjectEnv, readBooleanProperty, readNavTitle, readTopLevelStringProperty, resolveDocsConfigPath, resolveDocsContentDir, resolveDocsProjectRoot } from "./config.mjs";
|
|
17
|
+
import { detectFramework } from "./utils.mjs";
|
|
18
|
+
import { compactAgentDocs, inspectAgentCompactionState, loadAgentCompactionReviews, scanDocsPageTargets } from "./agent.mjs";
|
|
19
|
+
import { analyzeAgentUsefulness, createAgentUsefulnessPagesFromMcp } from "../agent-usefulness.mjs";
|
|
20
|
+
import { analyzeAgentSurfaceDrift } from "../agent-surface-drift.mjs";
|
|
21
|
+
import { analyzeConfiguredAgentSkillsProgressiveDisclosure } from "../agent-skills-progressive-disclosure.mjs";
|
|
22
|
+
import { resolveGoldenEvaluationInput } from "./golden-evaluations.mjs";
|
|
23
|
+
import { inspectApiReferenceHealth } from "./api-doctor.mjs";
|
|
27
24
|
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
28
25
|
import path from "node:path";
|
|
29
26
|
import { createHash } from "node:crypto";
|
|
@@ -32,209 +29,12 @@ import { LATEST_PROTOCOL_VERSION } from "@modelcontextprotocol/server";
|
|
|
32
29
|
import pc from "picocolors";
|
|
33
30
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
34
31
|
|
|
35
|
-
//#region src/cli/api-doctor.ts
|
|
36
|
-
function makeCheck$1(id, title, status, detail, recommendation) {
|
|
37
|
-
return {
|
|
38
|
-
id,
|
|
39
|
-
title,
|
|
40
|
-
status,
|
|
41
|
-
detail,
|
|
42
|
-
recommendation
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function toApiReferenceFramework(framework) {
|
|
46
|
-
return framework === "nextjs" ? "next" : framework;
|
|
47
|
-
}
|
|
48
|
-
function sourceType(source) {
|
|
49
|
-
if (!source) return "generated";
|
|
50
|
-
if (/^https?:/i.test(source) || source.startsWith("/")) return "remote";
|
|
51
|
-
return "local";
|
|
52
|
-
}
|
|
53
|
-
function displaySource(source, routeRoot) {
|
|
54
|
-
if (!source) return `generated:${routeRoot}`;
|
|
55
|
-
if (source.startsWith("/")) return source.split(/[?#]/, 1)[0] || "/";
|
|
56
|
-
if (!/^https?:/i.test(source)) return source;
|
|
57
|
-
try {
|
|
58
|
-
const url = new URL(source);
|
|
59
|
-
url.username = url.username ? "redacted" : "";
|
|
60
|
-
url.password = url.password ? "redacted" : "";
|
|
61
|
-
url.search = "";
|
|
62
|
-
url.hash = "";
|
|
63
|
-
return url.href;
|
|
64
|
-
} catch {
|
|
65
|
-
return "configured remote source";
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function unique(values) {
|
|
69
|
-
return new Set(values).size === values.length;
|
|
70
|
-
}
|
|
71
|
-
function failedReport(framework, detail, recommendation) {
|
|
72
|
-
return {
|
|
73
|
-
mode: "api",
|
|
74
|
-
framework,
|
|
75
|
-
enabled: false,
|
|
76
|
-
sourceCount: 0,
|
|
77
|
-
operationCount: 0,
|
|
78
|
-
checks: [makeCheck$1("config", "API reference config", "fail", detail, recommendation)],
|
|
79
|
-
sources: [],
|
|
80
|
-
recommendations: [recommendation]
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
async function inspectApiReferenceHealth(options = {}) {
|
|
84
|
-
const invocationRoot = process.cwd();
|
|
85
|
-
let configPath;
|
|
86
|
-
let rootDir;
|
|
87
|
-
let framework = "unknown";
|
|
88
|
-
try {
|
|
89
|
-
configPath = resolveDocsConfigPath(invocationRoot, options.configPath);
|
|
90
|
-
rootDir = resolveDocsProjectRoot(invocationRoot, configPath);
|
|
91
|
-
framework = detectFramework(rootDir) ?? "unknown";
|
|
92
|
-
} catch (error) {
|
|
93
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
94
|
-
framework = detectFramework(invocationRoot) ?? "unknown";
|
|
95
|
-
return failedReport(framework, message, "Add docs.config.ts[x] or pass --config so the API doctor can inspect the contract.");
|
|
96
|
-
}
|
|
97
|
-
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir, configPath);
|
|
98
|
-
if (configLoad.status !== "evaluated") return {
|
|
99
|
-
...failedReport(framework, `Could not evaluate ${path.relative(rootDir, configPath).replace(/\\/g, "/")}. ${configLoad.error}`, "Fix docs.config module evaluation so API sources, versions, overlays, and renderer settings can be validated."),
|
|
100
|
-
configPath: path.relative(rootDir, configPath).replace(/\\/g, "/")
|
|
101
|
-
};
|
|
102
|
-
const config = configLoad.config;
|
|
103
|
-
let apiReference;
|
|
104
|
-
try {
|
|
105
|
-
apiReference = resolveApiReferenceConfig(config.apiReference);
|
|
106
|
-
} catch (error) {
|
|
107
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
108
|
-
return {
|
|
109
|
-
...failedReport(framework, message, "Correct the apiReference configuration, then rerun docs doctor --api."),
|
|
110
|
-
configPath: path.relative(rootDir, configPath).replace(/\\/g, "/")
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
const relativeConfigPath = path.relative(rootDir, configPath).replace(/\\/g, "/");
|
|
114
|
-
if (!apiReference.enabled) {
|
|
115
|
-
const recommendation = "Enable apiReference when this project should publish an OpenAPI contract and generated operation documentation.";
|
|
116
|
-
return {
|
|
117
|
-
mode: "api",
|
|
118
|
-
framework,
|
|
119
|
-
configPath: relativeConfigPath,
|
|
120
|
-
enabled: false,
|
|
121
|
-
sourceCount: 0,
|
|
122
|
-
operationCount: 0,
|
|
123
|
-
checks: [makeCheck$1("config", "API reference config", "warn", "apiReference is disabled; there is no API contract to inspect.", recommendation)],
|
|
124
|
-
sources: [],
|
|
125
|
-
recommendations: [recommendation]
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
if (framework === "unknown") return {
|
|
129
|
-
...failedReport(framework, "Could not detect a supported framework from package.json.", "Install or declare Next.js, TanStack Start, Farm.js, SvelteKit, Astro, or Nuxt in the docs app package."),
|
|
130
|
-
configPath: relativeConfigPath,
|
|
131
|
-
enabled: true
|
|
132
|
-
};
|
|
133
|
-
const apiFramework = toApiReferenceFramework(framework);
|
|
134
|
-
const renderer = resolveApiReferenceRenderer(config.apiReference, apiFramework);
|
|
135
|
-
const configuredSources = apiReference.versions.length > 0 ? apiReference.versions.map((version) => ({
|
|
136
|
-
id: version.id,
|
|
137
|
-
label: version.label,
|
|
138
|
-
default: version.default,
|
|
139
|
-
specUrl: version.specUrl,
|
|
140
|
-
overlays: version.overlays
|
|
141
|
-
})) : [{
|
|
142
|
-
id: "default",
|
|
143
|
-
label: "Default",
|
|
144
|
-
default: true,
|
|
145
|
-
specUrl: apiReference.specUrl,
|
|
146
|
-
overlays: apiReference.overlays
|
|
147
|
-
}];
|
|
148
|
-
const loadedSources = await Promise.all(configuredSources.map(async (source) => {
|
|
149
|
-
const baseReport = {
|
|
150
|
-
id: source.id,
|
|
151
|
-
label: source.label,
|
|
152
|
-
default: source.default,
|
|
153
|
-
source: displaySource(source.specUrl, apiReference.routeRoot),
|
|
154
|
-
sourceType: sourceType(source.specUrl),
|
|
155
|
-
overlays: source.overlays.length,
|
|
156
|
-
status: "fail",
|
|
157
|
-
operationCount: 0
|
|
158
|
-
};
|
|
159
|
-
try {
|
|
160
|
-
const document = await loadApiReferenceOpenApiDocumentAsync(config, {
|
|
161
|
-
framework: apiFramework,
|
|
162
|
-
rootDir,
|
|
163
|
-
baseUrl: options.baseUrl,
|
|
164
|
-
version: apiReference.versions.length > 0 ? source.id : void 0
|
|
165
|
-
});
|
|
166
|
-
const validation = validateOpenApiContract(document);
|
|
167
|
-
if (!validation.valid) {
|
|
168
|
-
const first = validation.diagnostics[0];
|
|
169
|
-
throw new Error(first ? `${first.path}: ${first.message}` : "The resolved OpenAPI document is invalid.");
|
|
170
|
-
}
|
|
171
|
-
const model = buildNormalizedOpenApiModel(document);
|
|
172
|
-
return {
|
|
173
|
-
report: {
|
|
174
|
-
...baseReport,
|
|
175
|
-
status: "pass",
|
|
176
|
-
specificationVersion: model.specificationVersion,
|
|
177
|
-
operationCount: model.operationCount
|
|
178
|
-
},
|
|
179
|
-
operationIds: model.operations.map((operation) => operation.operationId),
|
|
180
|
-
operationSlugs: model.operations.map((operation) => operation.slug)
|
|
181
|
-
};
|
|
182
|
-
} catch (error) {
|
|
183
|
-
return {
|
|
184
|
-
report: {
|
|
185
|
-
...baseReport,
|
|
186
|
-
diagnostic: error instanceof Error ? error.message : String(error)
|
|
187
|
-
},
|
|
188
|
-
operationIds: [],
|
|
189
|
-
operationSlugs: []
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
}));
|
|
193
|
-
const sources = loadedSources.map((source) => source.report);
|
|
194
|
-
const failedSources = sources.filter((source) => source.status === "fail");
|
|
195
|
-
const operationCount = sources.reduce((total, source) => total + source.operationCount, 0);
|
|
196
|
-
const checks = [makeCheck$1("config", "API reference config", "pass", `Evaluated ${relativeConfigPath}; API reference is enabled at /${apiReference.path}.`), makeCheck$1("versions", "Versions and default", "pass", apiReference.versions.length > 0 ? `Resolved ${apiReference.versions.length} named versions with ${apiReference.defaultVersion} as the explicit default.` : "Resolved one unversioned API contract.")];
|
|
197
|
-
checks.push(failedSources.length === 0 ? makeCheck$1("sources", "Sources, references, and overlays", "pass", `Loaded ${sources.length} ${sources.length === 1 ? "contract" : "contracts"}, resolved references, and applied ${sources.reduce((total, source) => total + source.overlays, 0)} configured overlays.`) : makeCheck$1("sources", "Sources, references, and overlays", "fail", failedSources.map((source) => `${source.label}: ${source.diagnostic ?? "unknown error"}`).join(" "), "Fix the reported source, parsing, reference, validation, or overlay error and rerun docs doctor --api."));
|
|
198
|
-
const identityFailure = loadedSources.find((source) => !unique(source.operationIds) || !unique(source.operationSlugs));
|
|
199
|
-
checks.push(identityFailure ? makeCheck$1("operation-identities", "Operation IDs and slugs", "fail", `${identityFailure.report.label} produced duplicate normalized operation IDs or slugs.`, "Give every operation a stable, unique operationId and remove normalized slug collisions.") : makeCheck$1("operation-identities", "Operation IDs and slugs", failedSources.length > 0 ? "warn" : "pass", failedSources.length > 0 ? "Operation identities could only be checked for contracts that loaded successfully." : `Validated ${operationCount} unique normalized operation identities across ${sources.length} ${sources.length === 1 ? "contract" : "contracts"}.`));
|
|
200
|
-
const rendererCompatible = renderer !== "fumadocs" || framework === "nextjs";
|
|
201
|
-
checks.push(rendererCompatible ? makeCheck$1("renderer", "Renderer compatibility", "pass", `${renderer} is supported by ${framework}.`) : makeCheck$1("renderer", "Renderer compatibility", "fail", `The fumadocs renderer is only available for Next.js; ${framework} supports the Farming Labs and Scalar renderers.`, "Set apiReference.renderer to \"farming-labs\" or \"scalar\" for this framework."));
|
|
202
|
-
if (failedSources.length === 0 && !identityFailure) try {
|
|
203
|
-
const pages = await buildApiReferenceOperationPagesAsync(config, {
|
|
204
|
-
framework: apiFramework,
|
|
205
|
-
rootDir,
|
|
206
|
-
baseUrl: options.baseUrl
|
|
207
|
-
});
|
|
208
|
-
const pageUrls = pages.map((page) => page.url);
|
|
209
|
-
const completePages = pages.every((page) => page.type === "api" && page.canonicalUrl === page.url && Boolean(page.content));
|
|
210
|
-
const parity = pages.length === operationCount && unique(pageUrls) && completePages;
|
|
211
|
-
checks.push(parity ? makeCheck$1("surface-parity", "Generated surface parity", "pass", `${pages.length} normalized operations produce ${pages.length} unique search, Ask AI, Markdown, and read-only MCP documents.`) : makeCheck$1("surface-parity", "Generated surface parity", "fail", `Normalized contracts contain ${operationCount} operations, but generated projections contain ${pages.length} complete unique documents.`, "Regenerate operation projections from the normalized model and make their URLs and canonical metadata unique."));
|
|
212
|
-
} catch (error) {
|
|
213
|
-
checks.push(makeCheck$1("surface-parity", "Generated surface parity", "fail", error instanceof Error ? error.message : String(error), "Fix operation projection generation and rerun docs doctor --api."));
|
|
214
|
-
}
|
|
215
|
-
else checks.push(makeCheck$1("surface-parity", "Generated surface parity", "warn", "Generated projections were not checked because one or more contracts failed validation."));
|
|
216
|
-
const recommendations = checks.map((check) => check.recommendation).filter((recommendation) => Boolean(recommendation));
|
|
217
|
-
return {
|
|
218
|
-
mode: "api",
|
|
219
|
-
framework,
|
|
220
|
-
configPath: relativeConfigPath,
|
|
221
|
-
enabled: true,
|
|
222
|
-
renderer,
|
|
223
|
-
defaultVersion: apiReference.defaultVersion,
|
|
224
|
-
sourceCount: sources.length,
|
|
225
|
-
operationCount,
|
|
226
|
-
checks,
|
|
227
|
-
sources,
|
|
228
|
-
recommendations
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
//#endregion
|
|
233
32
|
//#region src/cli/doctor.ts
|
|
234
33
|
const DEFAULT_HOSTED_TIMEOUT_MS = 15e3;
|
|
235
34
|
const DEFAULT_HOSTED_RETRIES = 1;
|
|
236
35
|
const hostedProbeOptions = new AsyncLocalStorage();
|
|
237
36
|
const NEXT_CONFIG_PATTERN = /^next\.config\.(?:[cm]?js|[cm]?ts)$/;
|
|
37
|
+
const FARM_CONFIG_PATTERN = /^farm\.config\.(?:[cm]?js|[cm]?ts)$/;
|
|
238
38
|
const ASTRO_CONFIG_PATTERN = /^astro\.config\.(?:[cm]?js|[cm]?ts)$/;
|
|
239
39
|
const CODE_FILE_PATTERN = /\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/;
|
|
240
40
|
const IGNORED_DIRS = new Set([
|
|
@@ -655,12 +455,12 @@ function hasGithubIntegration(config, content) {
|
|
|
655
455
|
function hasReadingTimeSurface(config, content) {
|
|
656
456
|
const current = config?.readingTime;
|
|
657
457
|
if (current === true) return true;
|
|
658
|
-
if (current && typeof current === "object") return current.enabled
|
|
458
|
+
if (current && typeof current === "object") return current.enabled === true;
|
|
659
459
|
const topLevelBoolean = readTopLevelBooleanProperty(content, "readingTime");
|
|
660
460
|
if (typeof topLevelBoolean === "boolean") return topLevelBoolean;
|
|
661
461
|
const block = extractNestedObjectLiteral(content, ["readingTime"]);
|
|
662
462
|
if (!block) return false;
|
|
663
|
-
return readBooleanProperty(block, "enabled")
|
|
463
|
+
return readBooleanProperty(block, "enabled") === true;
|
|
664
464
|
}
|
|
665
465
|
function hasAgentCompactDefaults(config, content) {
|
|
666
466
|
if (config?.agent?.compact) return true;
|
|
@@ -705,6 +505,7 @@ function findCodeFiles(files, predicate) {
|
|
|
705
505
|
}
|
|
706
506
|
function detectFrameworkFromFiles(files) {
|
|
707
507
|
if (files.some((file) => NEXT_CONFIG_PATTERN.test(path.basename(file)))) return "nextjs";
|
|
508
|
+
if (files.some((file) => FARM_CONFIG_PATTERN.test(file))) return "farmjs";
|
|
708
509
|
if (files.some((file) => file.startsWith("src/routes/") && file.includes("api.docs"))) return "tanstack-start";
|
|
709
510
|
if (files.some((file) => file === "src/hooks.server.js" || file === "src/hooks.server.ts")) return "sveltekit";
|
|
710
511
|
if (files.some((file) => ASTRO_CONFIG_PATTERN.test(path.basename(file)))) return "astro";
|
|
@@ -729,6 +530,20 @@ function detectRouteSurface(rootDir, framework, staticExport, files) {
|
|
|
729
530
|
publicDetail: withDocsConfigs.length > 0 ? `Found withDocs() in ${formatPathList(withDocsConfigs)}.` : "Could not find withDocs() in next.config.*, so public docs rewrites are not verified."
|
|
730
531
|
};
|
|
731
532
|
}
|
|
533
|
+
if (framework === "farmjs") {
|
|
534
|
+
const withDocsConfigs = files.filter((file) => {
|
|
535
|
+
if (!FARM_CONFIG_PATTERN.test(file)) return false;
|
|
536
|
+
const source = read(file);
|
|
537
|
+
return source.includes("withDocs(") && source.includes("@farming-labs/farmjs");
|
|
538
|
+
});
|
|
539
|
+
const found = `Found withDocs() from @farming-labs/farmjs in ${formatPathList(withDocsConfigs)}`;
|
|
540
|
+
return {
|
|
541
|
+
apiMounted: withDocsConfigs.length > 0,
|
|
542
|
+
apiDetail: withDocsConfigs.length > 0 ? `${found}; the adapter serves /api/docs.` : "Could not find withDocs() from @farming-labs/farmjs in farm.config.*.",
|
|
543
|
+
publicMounted: withDocsConfigs.length > 0,
|
|
544
|
+
publicDetail: withDocsConfigs.length > 0 ? `${found}; the adapter serves the public docs routes.` : "Could not find withDocs() from @farming-labs/farmjs in farm.config.*, so public docs routes are not verified."
|
|
545
|
+
};
|
|
546
|
+
}
|
|
732
547
|
if (framework === "tanstack-start") {
|
|
733
548
|
const apiRoutes = findCodeFiles(files, (file) => file.startsWith("src/routes/") && read(file).includes("docsServer.GET") && /createFileRoute\((["'])\/api/.test(read(file)));
|
|
734
549
|
const publicHandlers = findCodeFiles(files, (file) => file.startsWith("src/routes/") && read(file).includes("isDocsPublicGetRequest(") && read(file).includes("isDocsMcpRequest("));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { exec, execOutput, fileExists } from "./utils.mjs";
|
|
2
|
+
import { buildDocsPackageInstallCommand, getPackagesForFramework, resolveDocsPackageFramework, resolveDocsPackageManager, validateUpgradeVersion } from "./package-version.mjs";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import pc from "picocolors";
|
|
@@ -17,4 +17,4 @@ function shouldPrintStackTrace(env = process.env) {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
//#endregion
|
|
20
|
-
export {
|
|
20
|
+
export { formatCliError, markCliErrorReported, shouldPrintStackTrace, wasCliErrorReported };
|
|
@@ -1,42 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { buildDocsAgentFeedbackEvaluationCandidates, compareDocsAgentFeedbackEvaluationBaseline, createDocsAgentFeedbackEvaluationBaseline } from "../agent-feedback-evaluations.mjs";
|
|
2
|
+
import { readDocsAgentEvaluationTasksFile, readDocsAgentFeedbackEvaluationBaseline, readDocsAgentFeedbackImprovementReport, readDocsGoldenTasksReportFile } from "../agent-feedback-evaluations-node.mjs";
|
|
3
|
+
import { mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import pc from "picocolors";
|
|
5
6
|
|
|
6
|
-
//#region src/agent-feedback-evaluations-node.ts
|
|
7
|
-
function isRecord(value) {
|
|
8
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9
|
-
}
|
|
10
|
-
function readJsonFile(filePath) {
|
|
11
|
-
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
12
|
-
}
|
|
13
|
-
function readDocsAgentFeedbackImprovementReport(filePath) {
|
|
14
|
-
const value = readJsonFile(filePath);
|
|
15
|
-
if (!isRecord(value) || value.format !== "farming-labs-agent-feedback-improvements.v1" || !Array.isArray(value.clusters) || typeof value.feedbackCount !== "number" || typeof value.recurringClusterCount !== "number") throw new Error("Input is not a supported agent feedback improvement report.");
|
|
16
|
-
return value;
|
|
17
|
-
}
|
|
18
|
-
function readDocsAgentEvaluationTasksFile(filePath) {
|
|
19
|
-
const value = readJsonFile(filePath);
|
|
20
|
-
if (Array.isArray(value)) return value;
|
|
21
|
-
if (!isRecord(value)) throw new Error("Existing evaluation tasks must be a JSON object or array.");
|
|
22
|
-
if (Array.isArray(value.candidates)) return value.candidates.flatMap((candidate) => isRecord(candidate) && isRecord(candidate.task) ? [candidate.task] : []);
|
|
23
|
-
if (Array.isArray(value.tasks)) return value.tasks;
|
|
24
|
-
if (isRecord(value.agent) && isRecord(value.agent.evaluations) && Array.isArray(value.agent.evaluations.tasks)) return value.agent.evaluations.tasks;
|
|
25
|
-
throw new Error("Could not find evaluation tasks in the existing JSON file.");
|
|
26
|
-
}
|
|
27
|
-
function readDocsGoldenTasksReportFile(filePath) {
|
|
28
|
-
const value = readJsonFile(filePath);
|
|
29
|
-
const report = isRecord(value) && isRecord(value.evaluations) ? value.evaluations : value;
|
|
30
|
-
if (!isRecord(report) || !Array.isArray(report.tasks) || typeof report.taskCount !== "number" || !(typeof report.score === "number" || report.score === null)) throw new Error("Input does not contain a golden-task evaluation report.");
|
|
31
|
-
return report;
|
|
32
|
-
}
|
|
33
|
-
function readDocsAgentFeedbackEvaluationBaseline(filePath) {
|
|
34
|
-
const value = readJsonFile(filePath);
|
|
35
|
-
if (!isRecord(value) || value.format !== DOCS_AGENT_FEEDBACK_EVALUATION_BASELINE_FORMAT || typeof value.score !== "number" || !Array.isArray(value.tasks)) throw new Error("Evaluation baseline format is not supported.");
|
|
36
|
-
return value;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
//#endregion
|
|
40
7
|
//#region src/cli/feedback-evals.ts
|
|
41
8
|
function parseAgentFeedbackEvaluationsArgs(argv) {
|
|
42
9
|
const options = { existing: [] };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { analyzeDocsAgentFeedback, readDocsAgentFeedbackFile } from "../agent-feedback-loop.mjs";
|
|
2
2
|
import { mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import pc from "picocolors";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
|
|
4
|
+
//#region src/cli/git-dates.ts
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
/** Preserve per-path Git history semantics while bounding build-time subprocesses. */
|
|
7
|
+
async function readGitLastModifiedDates(rootDir, sourcePaths) {
|
|
8
|
+
const paths = [...new Set([...sourcePaths].filter((value) => Boolean(value)))];
|
|
9
|
+
const dates = /* @__PURE__ */ new Map();
|
|
10
|
+
let next = 0;
|
|
11
|
+
const worker = async () => {
|
|
12
|
+
while (next < paths.length) {
|
|
13
|
+
const sourcePath = paths[next++];
|
|
14
|
+
try {
|
|
15
|
+
const { stdout } = await execFileAsync("git", [
|
|
16
|
+
"log",
|
|
17
|
+
"-1",
|
|
18
|
+
"--format=%cI",
|
|
19
|
+
"--",
|
|
20
|
+
sourcePath
|
|
21
|
+
], {
|
|
22
|
+
cwd: rootDir,
|
|
23
|
+
encoding: "utf-8"
|
|
24
|
+
});
|
|
25
|
+
const parsed = new Date(stdout.trim());
|
|
26
|
+
if (!Number.isNaN(parsed.getTime())) dates.set(sourcePath, parsed.toISOString());
|
|
27
|
+
} catch {}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
await Promise.all(Array.from({ length: Math.min(4, paths.length) }, worker));
|
|
31
|
+
return dates;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { readGitLastModifiedDates };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/cli/golden-evaluations.ts
|
|
2
|
+
function isPlainRecord(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
/** Normalize the runtime docs.config evaluation shape shared by doctor and review. */
|
|
6
|
+
function resolveGoldenEvaluationInput(evaluationInput) {
|
|
7
|
+
if (evaluationInput === void 0 || typeof evaluationInput === "boolean") return {
|
|
8
|
+
tasks: void 0,
|
|
9
|
+
options: {}
|
|
10
|
+
};
|
|
11
|
+
if (!isPlainRecord(evaluationInput)) return {
|
|
12
|
+
tasks: { evaluationConfig: evaluationInput },
|
|
13
|
+
options: {}
|
|
14
|
+
};
|
|
15
|
+
const options = {
|
|
16
|
+
surface: evaluationInput.surface,
|
|
17
|
+
allowNetwork: evaluationInput.allowNetwork,
|
|
18
|
+
searchTimeoutMs: evaluationInput.searchTimeoutMs,
|
|
19
|
+
answer: evaluationInput.answer
|
|
20
|
+
};
|
|
21
|
+
if (evaluationInput.enabled === false) return {
|
|
22
|
+
tasks: void 0,
|
|
23
|
+
options
|
|
24
|
+
};
|
|
25
|
+
if ("enabled" in evaluationInput && typeof evaluationInput.enabled !== "boolean") return {
|
|
26
|
+
tasks: evaluationInput,
|
|
27
|
+
options
|
|
28
|
+
};
|
|
29
|
+
if (!("tasks" in evaluationInput)) return {
|
|
30
|
+
tasks: void 0,
|
|
31
|
+
options
|
|
32
|
+
};
|
|
33
|
+
const runtimeTasks = evaluationInput.tasks;
|
|
34
|
+
if (!Array.isArray(runtimeTasks)) return {
|
|
35
|
+
tasks: runtimeTasks,
|
|
36
|
+
options
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
tasks: runtimeTasks.map((task) => {
|
|
40
|
+
if (!isPlainRecord(task)) return task;
|
|
41
|
+
return {
|
|
42
|
+
...task,
|
|
43
|
+
tokenBudget: task.tokenBudget ?? evaluationInput.tokenBudget,
|
|
44
|
+
topK: task.topK ?? evaluationInput.topK
|
|
45
|
+
};
|
|
46
|
+
}),
|
|
47
|
+
options
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { resolveGoldenEvaluationInput };
|
package/dist/cli/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//#endregion
|
|
1
|
+
import { formatCliError } from "./errors.mjs";
|
|
2
|
+
|
|
4
3
|
//#region src/cli/index.d.ts
|
|
5
4
|
declare const UPGRADE_TAGS: readonly ["latest", "beta"];
|
|
6
5
|
type UpgradeTag = (typeof UPGRADE_TAGS)[number];
|