@farming-labs/docs 0.2.88 → 0.2.89
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/dist/{agent-FyPQ2AZ4.mjs → agent-Jvn1a78y.mjs} +1 -1
- package/dist/{agent-export-Di1Ofstb.mjs → agent-export-B4Xos6gi.mjs} +1 -1
- package/dist/{agents-DjUz5voa.mjs → agents-DRCl1URL.mjs} +1 -1
- package/dist/cli/index.mjs +30 -28
- package/dist/{cloud-pdNC-tyj.mjs → cloud-DwhH_b_q.mjs} +1 -1
- package/dist/{codeblocks-CPA6Ae5r.mjs → codeblocks-B5lsz3sx.mjs} +1 -1
- package/dist/{config-Wcdj-D0a.mjs → config-BtxaQTPP.mjs} +26 -1
- package/dist/{doctor-DUnOjP9T.mjs → doctor-C3IG5hqb.mjs} +101 -20
- package/dist/{golden-evaluations-CNDwoUOe.mjs → golden-evaluations-DyeYD50F.mjs} +138 -22
- package/dist/{init-c3WAqoI2.mjs → init-CuLodGjP.mjs} +1 -1
- package/dist/{mcp-7bvRe9Da.mjs → mcp-D8Hw2blN.mjs} +1 -1
- package/dist/mcp.mjs +77 -19
- package/dist/{review-DEnzotkg.mjs → review-R39cQsvi.mjs} +2 -2
- package/dist/{robots-DXy1xW3D.mjs → robots-C-Nh0xH6.mjs} +1 -1
- package/dist/{search-DznddPqw.mjs → search-3TUBKtz5.mjs} +1 -1
- package/dist/{sitemap-DCsrVSPf.mjs → sitemap-DrILEtYo.mjs} +1 -1
- package/dist/{skills-CPDwsMq4.mjs → skills-35ecRZtd.mjs} +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { B as findDocsMarkdownPage, at as renderDocsMarkdownDocument } from "./a
|
|
|
2
2
|
import { v as normalizePageAgentFrontmatter, x as stripGeneratedPageAgentContractMarkdown } from "./markdown-sections-7OoA7ylx.mjs";
|
|
3
3
|
import { c as hashGeneratedAgentContent, d as serializeGeneratedAgentDocument, s as GENERATED_AGENT_PROVENANCE_VERSION, u as parseGeneratedAgentDocument } from "./content-change-hydration-DLBinuFR.mjs";
|
|
4
4
|
import { createFilesystemDocsMcpSource } from "./mcp.mjs";
|
|
5
|
-
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-
|
|
5
|
+
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-BtxaQTPP.mjs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import matter from "gray-matter";
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -10,7 +10,7 @@ import "./agent-evals-DCptRrdP.mjs";
|
|
|
10
10
|
import { createFilesystemDocsMcpSource, resolveDocsMcpConfig } from "./mcp.mjs";
|
|
11
11
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
12
12
|
import "./server.mjs";
|
|
13
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, m as readTopLevelBooleanProperty, p as readStringProperty, r as extractTopLevelConfigObject, t as extractNestedObjectLiteral } from "./config-
|
|
13
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, m as readTopLevelBooleanProperty, p as readStringProperty, r as extractTopLevelConfigObject, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
14
14
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
15
15
|
import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
16
16
|
import path from "node:path";
|
|
@@ -8,7 +8,7 @@ import "./agent-evals-DCptRrdP.mjs";
|
|
|
8
8
|
import { resolveDocsMcpConfig } from "./mcp.mjs";
|
|
9
9
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
10
10
|
import "./server.mjs";
|
|
11
|
-
import { a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
11
|
+
import { a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
12
12
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
13
13
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
14
|
import path from "node:path";
|
package/dist/cli/index.mjs
CHANGED
|
@@ -108,43 +108,43 @@ async function main() {
|
|
|
108
108
|
]
|
|
109
109
|
};
|
|
110
110
|
if (!parsedCommand.command || parsedCommand.command === "init") {
|
|
111
|
-
const { init } = await import("../init-
|
|
111
|
+
const { init } = await import("../init-CuLodGjP.mjs");
|
|
112
112
|
await init(initOptions);
|
|
113
113
|
} else if (parsedCommand.command === "dev") {
|
|
114
114
|
const { dev } = await import("../dev-BFBPvjnk.mjs");
|
|
115
115
|
await dev(devOptions);
|
|
116
116
|
} else if (parsedCommand.command === "deploy") {
|
|
117
|
-
const { runCloudDeploy } = await import("../cloud-
|
|
117
|
+
const { runCloudDeploy } = await import("../cloud-DwhH_b_q.mjs");
|
|
118
118
|
await runCloudDeploy(cloudOptions);
|
|
119
119
|
} else if (parsedCommand.command === "preview") {
|
|
120
|
-
const { runCloudPreview } = await import("../cloud-
|
|
120
|
+
const { runCloudPreview } = await import("../cloud-DwhH_b_q.mjs");
|
|
121
121
|
await runCloudPreview(cloudOptions);
|
|
122
122
|
} else if (parsedCommand.command === "cloud" && subcommand === "deploy") {
|
|
123
|
-
const { runCloudDeploy } = await import("../cloud-
|
|
123
|
+
const { runCloudDeploy } = await import("../cloud-DwhH_b_q.mjs");
|
|
124
124
|
await runCloudDeploy(cloudOptions);
|
|
125
125
|
} else if (parsedCommand.command === "cloud" && subcommand === "preview") {
|
|
126
|
-
const { runCloudPreview } = await import("../cloud-
|
|
126
|
+
const { runCloudPreview } = await import("../cloud-DwhH_b_q.mjs");
|
|
127
127
|
await runCloudPreview(cloudOptions);
|
|
128
128
|
} else if (parsedCommand.command === "cloud" && subcommand === "init") {
|
|
129
|
-
const { runCloudInit } = await import("../cloud-
|
|
129
|
+
const { runCloudInit } = await import("../cloud-DwhH_b_q.mjs");
|
|
130
130
|
await runCloudInit(cloudOptions);
|
|
131
131
|
} else if (parsedCommand.command === "cloud" && subcommand === "sync") {
|
|
132
|
-
const { syncCloudConfig } = await import("../cloud-
|
|
132
|
+
const { syncCloudConfig } = await import("../cloud-DwhH_b_q.mjs");
|
|
133
133
|
await syncCloudConfig(cloudOptions);
|
|
134
134
|
} else if (parsedCommand.command === "cloud" && subcommand === "check") {
|
|
135
|
-
const { runCloudCheck } = await import("../cloud-
|
|
135
|
+
const { runCloudCheck } = await import("../cloud-DwhH_b_q.mjs");
|
|
136
136
|
await runCloudCheck(cloudOptions);
|
|
137
137
|
} else if (parsedCommand.command === "cloud") {
|
|
138
138
|
console.error(pc.red(`Unknown cloud subcommand: ${subcommand ?? "(missing)"}`));
|
|
139
139
|
console.error();
|
|
140
|
-
const { printCloudHelp } = await import("../cloud-
|
|
140
|
+
const { printCloudHelp } = await import("../cloud-DwhH_b_q.mjs");
|
|
141
141
|
printCloudHelp();
|
|
142
142
|
process.exit(1);
|
|
143
143
|
} else if (parsedCommand.command === "mcp") {
|
|
144
|
-
const { runMcp } = await import("../mcp-
|
|
144
|
+
const { runMcp } = await import("../mcp-D8Hw2blN.mjs");
|
|
145
145
|
await runMcp(mcpOptions);
|
|
146
146
|
} else if (parsedCommand.command === "agent" && subcommand === "compact") {
|
|
147
|
-
const { compactAgentDocs, parseAgentCompactArgs, printAgentCompactHelp } = await import("../agent-
|
|
147
|
+
const { compactAgentDocs, parseAgentCompactArgs, printAgentCompactHelp } = await import("../agent-Jvn1a78y.mjs").then((n) => n.t);
|
|
148
148
|
const agentCompactOptions = parseAgentCompactArgs(args.slice(2));
|
|
149
149
|
if (agentCompactOptions.help) {
|
|
150
150
|
printAgentCompactHelp();
|
|
@@ -152,7 +152,7 @@ async function main() {
|
|
|
152
152
|
}
|
|
153
153
|
await compactAgentDocs(agentCompactOptions);
|
|
154
154
|
} else if (parsedCommand.command === "agent" && subcommand === "export") {
|
|
155
|
-
const { exportAgentBundle, parseAgentExportArgs, printAgentExportHelp } = await import("../agent-export-
|
|
155
|
+
const { exportAgentBundle, parseAgentExportArgs, printAgentExportHelp } = await import("../agent-export-B4Xos6gi.mjs");
|
|
156
156
|
const agentExportOptions = parseAgentExportArgs(args.slice(2));
|
|
157
157
|
if (agentExportOptions.help) {
|
|
158
158
|
printAgentExportHelp();
|
|
@@ -162,13 +162,13 @@ async function main() {
|
|
|
162
162
|
} else if (parsedCommand.command === "agent") {
|
|
163
163
|
console.error(pc.red(`Unknown agent subcommand: ${subcommand ?? "(missing)"}`));
|
|
164
164
|
console.error();
|
|
165
|
-
const { printAgentCompactHelp } = await import("../agent-
|
|
166
|
-
const { printAgentExportHelp } = await import("../agent-export-
|
|
165
|
+
const { printAgentCompactHelp } = await import("../agent-Jvn1a78y.mjs").then((n) => n.t);
|
|
166
|
+
const { printAgentExportHelp } = await import("../agent-export-B4Xos6gi.mjs");
|
|
167
167
|
printAgentCompactHelp();
|
|
168
168
|
printAgentExportHelp();
|
|
169
169
|
process.exit(1);
|
|
170
170
|
} else if (parsedCommand.command === "agents" && subcommand === "generate") {
|
|
171
|
-
const { generateAgents, parseAgentsGenerateArgs, printAgentsGenerateHelp } = await import("../agents-
|
|
171
|
+
const { generateAgents, parseAgentsGenerateArgs, printAgentsGenerateHelp } = await import("../agents-DRCl1URL.mjs");
|
|
172
172
|
const agentsOptions = parseAgentsGenerateArgs(args.slice(2));
|
|
173
173
|
if (agentsOptions.help) {
|
|
174
174
|
printAgentsGenerateHelp();
|
|
@@ -178,11 +178,11 @@ async function main() {
|
|
|
178
178
|
} else if (parsedCommand.command === "agents") {
|
|
179
179
|
console.error(pc.red(`Unknown agents subcommand: ${subcommand ?? "(missing)"}`));
|
|
180
180
|
console.error();
|
|
181
|
-
const { printAgentsGenerateHelp } = await import("../agents-
|
|
181
|
+
const { printAgentsGenerateHelp } = await import("../agents-DRCl1URL.mjs");
|
|
182
182
|
printAgentsGenerateHelp();
|
|
183
183
|
process.exit(1);
|
|
184
184
|
} else if (parsedCommand.command === "skills" && subcommand === "scaffold") {
|
|
185
|
-
const { parseSkillScaffoldArgs, printSkillScaffoldHelp, scaffoldSkillFromContracts } = await import("../skills-
|
|
185
|
+
const { parseSkillScaffoldArgs, printSkillScaffoldHelp, scaffoldSkillFromContracts } = await import("../skills-35ecRZtd.mjs");
|
|
186
186
|
const skillOptions = parseSkillScaffoldArgs(args.slice(2));
|
|
187
187
|
if (skillOptions.help) {
|
|
188
188
|
printSkillScaffoldHelp();
|
|
@@ -190,16 +190,16 @@ async function main() {
|
|
|
190
190
|
}
|
|
191
191
|
await scaffoldSkillFromContracts(skillOptions);
|
|
192
192
|
} else if (parsedCommand.command === "skills" && (subcommand === "--help" || subcommand === "-h")) {
|
|
193
|
-
const { printSkillScaffoldHelp } = await import("../skills-
|
|
193
|
+
const { printSkillScaffoldHelp } = await import("../skills-35ecRZtd.mjs");
|
|
194
194
|
printSkillScaffoldHelp();
|
|
195
195
|
} else if (parsedCommand.command === "skills") {
|
|
196
196
|
console.error(pc.red(`Unknown skills subcommand: ${subcommand ?? "(missing)"}`));
|
|
197
197
|
console.error();
|
|
198
|
-
const { printSkillScaffoldHelp } = await import("../skills-
|
|
198
|
+
const { printSkillScaffoldHelp } = await import("../skills-35ecRZtd.mjs");
|
|
199
199
|
printSkillScaffoldHelp();
|
|
200
200
|
process.exit(1);
|
|
201
201
|
} else if (parsedCommand.command === "doctor") {
|
|
202
|
-
const { parseDoctorArgs, printDoctorHelp, runDoctor } = await import("../doctor-
|
|
202
|
+
const { parseDoctorArgs, printDoctorHelp, runDoctor } = await import("../doctor-C3IG5hqb.mjs");
|
|
203
203
|
const doctorOptions = parseDoctorArgs(args.slice(1));
|
|
204
204
|
if (doctorOptions.help) {
|
|
205
205
|
printDoctorHelp();
|
|
@@ -207,7 +207,7 @@ async function main() {
|
|
|
207
207
|
}
|
|
208
208
|
await runDoctor(doctorOptions);
|
|
209
209
|
} else if (parsedCommand.command === "review") {
|
|
210
|
-
const { parseReviewArgs, printReviewHelp, runReview } = await import("../review-
|
|
210
|
+
const { parseReviewArgs, printReviewHelp, runReview } = await import("../review-R39cQsvi.mjs");
|
|
211
211
|
const reviewOptions = parseReviewArgs(args.slice(1));
|
|
212
212
|
if (reviewOptions.help) {
|
|
213
213
|
printReviewHelp();
|
|
@@ -215,7 +215,7 @@ async function main() {
|
|
|
215
215
|
}
|
|
216
216
|
await runReview(reviewOptions);
|
|
217
217
|
} else if ((parsedCommand.command === "codeblocks" || parsedCommand.command === "code-blocks") && subcommand === "validate") {
|
|
218
|
-
const { parseCodeBlocksValidateArgs, printCodeBlocksValidateHelp, runCodeBlocksValidate } = await import("../codeblocks-
|
|
218
|
+
const { parseCodeBlocksValidateArgs, printCodeBlocksValidateHelp, runCodeBlocksValidate } = await import("../codeblocks-B5lsz3sx.mjs");
|
|
219
219
|
const codeBlocksOptions = parseCodeBlocksValidateArgs(args.slice(2));
|
|
220
220
|
if (codeBlocksOptions.help) {
|
|
221
221
|
printCodeBlocksValidateHelp();
|
|
@@ -225,11 +225,11 @@ async function main() {
|
|
|
225
225
|
} else if (parsedCommand.command === "codeblocks" || parsedCommand.command === "code-blocks") {
|
|
226
226
|
console.error(pc.red(`Unknown codeblocks subcommand: ${subcommand ?? "(missing)"}`));
|
|
227
227
|
console.error();
|
|
228
|
-
const { printCodeBlocksValidateHelp } = await import("../codeblocks-
|
|
228
|
+
const { printCodeBlocksValidateHelp } = await import("../codeblocks-B5lsz3sx.mjs");
|
|
229
229
|
printCodeBlocksValidateHelp();
|
|
230
230
|
process.exit(1);
|
|
231
231
|
} else if (parsedCommand.command === "search" && subcommand === "sync") {
|
|
232
|
-
const { syncSearch } = await import("../search-
|
|
232
|
+
const { syncSearch } = await import("../search-3TUBKtz5.mjs");
|
|
233
233
|
await syncSearch(searchSyncOptions);
|
|
234
234
|
} else if (parsedCommand.command === "search") {
|
|
235
235
|
console.error(pc.red(`Unknown search subcommand: ${subcommand ?? "(missing)"}`));
|
|
@@ -237,7 +237,7 @@ async function main() {
|
|
|
237
237
|
printHelp();
|
|
238
238
|
process.exit(1);
|
|
239
239
|
} else if (parsedCommand.command === "sitemap" && subcommand === "generate") {
|
|
240
|
-
const { generateSitemap, parseSitemapGenerateArgs, printSitemapGenerateHelp } = await import("../sitemap-
|
|
240
|
+
const { generateSitemap, parseSitemapGenerateArgs, printSitemapGenerateHelp } = await import("../sitemap-DrILEtYo.mjs");
|
|
241
241
|
const sitemapOptions = parseSitemapGenerateArgs(args.slice(2));
|
|
242
242
|
if (sitemapOptions.help) {
|
|
243
243
|
printSitemapGenerateHelp();
|
|
@@ -247,11 +247,11 @@ async function main() {
|
|
|
247
247
|
} else if (parsedCommand.command === "sitemap") {
|
|
248
248
|
console.error(pc.red(`Unknown sitemap subcommand: ${subcommand ?? "(missing)"}`));
|
|
249
249
|
console.error();
|
|
250
|
-
const { printSitemapGenerateHelp } = await import("../sitemap-
|
|
250
|
+
const { printSitemapGenerateHelp } = await import("../sitemap-DrILEtYo.mjs");
|
|
251
251
|
printSitemapGenerateHelp();
|
|
252
252
|
process.exit(1);
|
|
253
253
|
} else if (parsedCommand.command === "robots" && subcommand === "generate") {
|
|
254
|
-
const { generateRobots, parseRobotsGenerateArgs, printRobotsGenerateHelp } = await import("../robots-
|
|
254
|
+
const { generateRobots, parseRobotsGenerateArgs, printRobotsGenerateHelp } = await import("../robots-C-Nh0xH6.mjs");
|
|
255
255
|
const robotsOptions = parseRobotsGenerateArgs(args.slice(2));
|
|
256
256
|
if (robotsOptions.help) {
|
|
257
257
|
printRobotsGenerateHelp();
|
|
@@ -261,7 +261,7 @@ async function main() {
|
|
|
261
261
|
} else if (parsedCommand.command === "robots") {
|
|
262
262
|
console.error(pc.red(`Unknown robots subcommand: ${subcommand ?? "(missing)"}`));
|
|
263
263
|
console.error();
|
|
264
|
-
const { printRobotsGenerateHelp } = await import("../robots-
|
|
264
|
+
const { printRobotsGenerateHelp } = await import("../robots-C-Nh0xH6.mjs");
|
|
265
265
|
printRobotsGenerateHelp();
|
|
266
266
|
process.exit(1);
|
|
267
267
|
} else if (parsedCommand.command === "downgrade") {
|
|
@@ -398,6 +398,8 @@ ${pc.dim("Options for doctor:")}
|
|
|
398
398
|
${pc.cyan("doctor --site")} Score the current docs app for reader-facing docs quality
|
|
399
399
|
${pc.cyan("doctor --human")} Alias for ${pc.cyan("doctor --site")}
|
|
400
400
|
${pc.cyan("doctor --json")} Print the report as JSON for CI, scripts, and automation
|
|
401
|
+
${pc.cyan("doctor --json-output <path>")} Write the JSON report to a file, including alongside ${pc.cyan("--ci")}
|
|
402
|
+
${pc.cyan("doctor --ci")} Emit actionable GitHub annotations in GitHub Actions
|
|
401
403
|
${pc.cyan("doctor --strict")} Exit with failure when any doctor check warns or fails
|
|
402
404
|
${pc.cyan("doctor --agent --fix")} Refresh stale generated ${pc.dim("agent.md")} files and token-budget missing outputs
|
|
403
405
|
${pc.cyan("doctor --agent --fix --dry-run")} Report the fix command without writing generated ${pc.dim("agent.md")} files
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as markCliErrorReported } from "./errors-DbOhkE1h.mjs";
|
|
2
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, c as loadProjectEnv, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, m as readTopLevelBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
2
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, c as loadProjectEnv, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, m as readTopLevelBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
3
3
|
import { i as detectPackageManagerFromProject, t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as validateCodeBlocks, r as resolveDocsCodeBlocksValidateConfig } from "./code-blocks-0wjOsqdJ.mjs";
|
|
2
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, f as readNumberProperty, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
2
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, f as readNumberProperty, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
|
|
@@ -82,6 +82,31 @@ function resolveDocsConfigPath(rootDir, explicitPath) {
|
|
|
82
82
|
}
|
|
83
83
|
throw new Error("Could not find docs.config.ts or docs.config.tsx in the current project. Use --config to point at a custom path.");
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the application root that owns a docs config selected from another
|
|
87
|
+
* working directory. This keeps config-relative paths anchored to a nested
|
|
88
|
+
* workspace package without changing the behavior of configs stored below a
|
|
89
|
+
* project's root (for example, src/lib/docs.config.ts).
|
|
90
|
+
*/
|
|
91
|
+
function resolveDocsProjectRoot(rootDir, configPath) {
|
|
92
|
+
const invocationRoot = resolve(rootDir);
|
|
93
|
+
const configDir = dirname(resolve(configPath));
|
|
94
|
+
const relativeConfigDir = relative(invocationRoot, configDir);
|
|
95
|
+
const configIsInsideInvocationRoot = relativeConfigDir === "" || relativeConfigDir !== ".." && !relativeConfigDir.startsWith(`..${sep}`);
|
|
96
|
+
const fallbackRoot = configIsInsideInvocationRoot ? invocationRoot : configDir;
|
|
97
|
+
let currentDir = configDir;
|
|
98
|
+
while (true) {
|
|
99
|
+
if (existsSync(join(currentDir, "package.json"))) return currentDir;
|
|
100
|
+
if (configIsInsideInvocationRoot && currentDir === invocationRoot) return invocationRoot;
|
|
101
|
+
const parentDir = dirname(currentDir);
|
|
102
|
+
if (parentDir === currentDir) return fallbackRoot;
|
|
103
|
+
if (configIsInsideInvocationRoot) {
|
|
104
|
+
const relativeParent = relative(invocationRoot, parentDir);
|
|
105
|
+
if (relativeParent === ".." || relativeParent.startsWith(`..${sep}`)) return invocationRoot;
|
|
106
|
+
}
|
|
107
|
+
currentDir = parentDir;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
85
110
|
function readStringProperty(content, key) {
|
|
86
111
|
return content.match(createPropertyPattern(key, `["']([^"']+)["']`))?.[1];
|
|
87
112
|
}
|
|
@@ -366,4 +391,4 @@ async function loadDocsConfigModuleResultWithProjectEnv(rootDir, explicitPath, o
|
|
|
366
391
|
}
|
|
367
392
|
|
|
368
393
|
//#endregion
|
|
369
|
-
export { resolveDocsContentDir as _, loadDocsConfigModule as a, loadProjectEnv as c, readNavTitle as d, readNumberProperty as f, resolveDocsConfigPath as g, readTopLevelStringProperty as h, hasTopLevelProperty as i, readBooleanProperty as l, readTopLevelBooleanProperty as m, extractObjectLiteral as n, loadDocsConfigModuleResult as o, readStringProperty as p, extractTopLevelConfigObject as r, loadDocsConfigModuleResultWithProjectEnv as s, extractNestedObjectLiteral as t, readEnvReferenceProperty as u };
|
|
394
|
+
export { resolveDocsContentDir as _, loadDocsConfigModule as a, loadProjectEnv as c, readNavTitle as d, readNumberProperty as f, resolveDocsConfigPath as g, readTopLevelStringProperty as h, hasTopLevelProperty as i, readBooleanProperty as l, readTopLevelBooleanProperty as m, extractObjectLiteral as n, loadDocsConfigModuleResult as o, readStringProperty as p, extractTopLevelConfigObject as r, loadDocsConfigModuleResultWithProjectEnv as s, extractNestedObjectLiteral as t, readEnvReferenceProperty as u, resolveDocsProjectRoot as v };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as scanDocsPageTargets, n as compactAgentDocs, r as inspectAgentCompactionState } from "./agent-
|
|
1
|
+
import { i as scanDocsPageTargets, n as compactAgentDocs, r as inspectAgentCompactionState } from "./agent-Jvn1a78y.mjs";
|
|
2
2
|
import { d as httpLinkHeaderHasTargetRelation, f as AGENT_SKILL_ARCHIVE_MAX_UNCOMPRESSED_BYTES, p as readAgentSkillDocumentFromTar } from "./prompt-references-B6gxePm8.mjs";
|
|
3
3
|
import { A as buildDocsAgentDiscoverySpec, At as DEFAULT_SITEMAP_XML_ROUTE, F as buildDocsMcpEndpointCandidates, Gn as getDocsMcpProtectedResourceMetadataRoutes, It as resolveDocsSitemapConfig, Jn as isDocsMcpOAuthScopeToken, M as buildDocsConfigMap, Ot as DEFAULT_SITEMAP_MD_ROUTE, Qn as normalizeDocsMcpAuthorizationServerUrls, S as DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, T as DOCS_CONFIG_MAP_TOP_LEVEL_KEYS, Un as DEFAULT_MCP_WELL_KNOWN_ROUTE, Vn as DEFAULT_MCP_PUBLIC_ROUTE, c as DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, h as DEFAULT_LLMS_FULL_TXT_ROUTE, i as DEFAULT_AGENT_FEEDBACK_ROUTE, kt as DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, l as DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, n as DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE, pn as resolveAskAISearchRequestConfig, t as DEFAULT_AGENTS_MD_ROUTE, v as DEFAULT_LLMS_TXT_ROUTE, x as DEFAULT_SKILL_MD_ROUTE } from "./agent-CTOUI2BK.mjs";
|
|
4
4
|
import { f as PAGE_AGENT_CONTRACT_FIELDS } from "./markdown-sections-7OoA7ylx.mjs";
|
|
@@ -13,11 +13,11 @@ import { t as runDocsGoldenTasks } from "./agent-evals-DCptRrdP.mjs";
|
|
|
13
13
|
import { createFilesystemDocsMcpSource, getDocsConfigSchema, resolveDocsMcpConfig } from "./mcp.mjs";
|
|
14
14
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
15
15
|
import "./server.mjs";
|
|
16
|
-
import { _ as resolveDocsContentDir, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, r as extractTopLevelConfigObject, s as loadDocsConfigModuleResultWithProjectEnv, t as extractNestedObjectLiteral } from "./config-
|
|
16
|
+
import { _ as resolveDocsContentDir, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, r as extractTopLevelConfigObject, s as loadDocsConfigModuleResultWithProjectEnv, t as extractNestedObjectLiteral, v as resolveDocsProjectRoot } from "./config-BtxaQTPP.mjs";
|
|
17
17
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
18
|
-
import { i as createAgentUsefulnessPagesFromMcp, n as analyzeAgentSurfaceDrift, r as analyzeAgentUsefulness, t as resolveGoldenEvaluationInput } from "./golden-evaluations-
|
|
18
|
+
import { i as createAgentUsefulnessPagesFromMcp, n as analyzeAgentSurfaceDrift, r as analyzeAgentUsefulness, t as resolveGoldenEvaluationInput } from "./golden-evaluations-DyeYD50F.mjs";
|
|
19
19
|
import { t as analyzeConfiguredAgentSkillsProgressiveDisclosure } from "./agent-skills-progressive-disclosure-BVvj7nM8.mjs";
|
|
20
|
-
import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
|
|
20
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
21
21
|
import path from "node:path";
|
|
22
22
|
import { createHash } from "node:crypto";
|
|
23
23
|
import { gunzipSync } from "node:zlib";
|
|
@@ -73,6 +73,23 @@ function parseDoctorArgs(argv) {
|
|
|
73
73
|
parsed.json = true;
|
|
74
74
|
continue;
|
|
75
75
|
}
|
|
76
|
+
if (arg.startsWith("--json-output=")) {
|
|
77
|
+
const value = parseInlineFlag(arg).value;
|
|
78
|
+
if (!value) throw new Error("Missing value for --json-output.");
|
|
79
|
+
parsed.jsonOutputPath = value;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (arg === "--json-output") {
|
|
83
|
+
const value = argv[index + 1];
|
|
84
|
+
if (!value || value.startsWith("--")) throw new Error("Missing value for --json-output.");
|
|
85
|
+
parsed.jsonOutputPath = value;
|
|
86
|
+
index += 1;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (arg === "--ci") {
|
|
90
|
+
parsed.ci = true;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
76
93
|
if (arg === "--strict") {
|
|
77
94
|
parsed.strict = true;
|
|
78
95
|
continue;
|
|
@@ -170,6 +187,8 @@ ${pc.dim("Options:")}
|
|
|
170
187
|
${pc.cyan("--human")} Alias for ${pc.cyan("--site")}
|
|
171
188
|
${pc.cyan("--only <mode>")} Run only one doctor suite: ${pc.cyan("agent")} or ${pc.cyan("site")}
|
|
172
189
|
${pc.cyan("--json")} Print the report as JSON for CI, scripts, and other agents
|
|
190
|
+
${pc.cyan("--json-output <path>")} Write the JSON report to a file; use with ${pc.cyan("--ci")} to keep annotation stdout valid
|
|
191
|
+
${pc.cyan("--ci")} Emit actionable GitHub annotations when running in GitHub Actions
|
|
173
192
|
${pc.cyan("--strict")} Exit with failure when any check warns or fails
|
|
174
193
|
${pc.cyan("--fix")} Refresh stale generated agent.md files and token-budget missing outputs
|
|
175
194
|
${pc.cyan("--dry-run")} With ${pc.cyan("--fix")}, report the compaction command without writing files
|
|
@@ -1631,7 +1650,7 @@ async function buildHostedAgentChecks(url, pages) {
|
|
|
1631
1650
|
checks
|
|
1632
1651
|
};
|
|
1633
1652
|
}
|
|
1634
|
-
function makeCheck(id, title, status, score, maxScore, detail, recommendation) {
|
|
1653
|
+
function makeCheck(id, title, status, score, maxScore, detail, recommendation, findings) {
|
|
1635
1654
|
return {
|
|
1636
1655
|
id,
|
|
1637
1656
|
title,
|
|
@@ -1639,19 +1658,38 @@ function makeCheck(id, title, status, score, maxScore, detail, recommendation) {
|
|
|
1639
1658
|
score,
|
|
1640
1659
|
maxScore,
|
|
1641
1660
|
detail,
|
|
1642
|
-
recommendation
|
|
1643
|
-
|
|
1661
|
+
recommendation,
|
|
1662
|
+
findings
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
function toDoctorCommandFindings(findings) {
|
|
1666
|
+
return findings.filter((finding) => finding.category === "command" && Boolean(finding.command) && Boolean(finding.proposedCorrection)).map((finding) => ({
|
|
1667
|
+
code: finding.code,
|
|
1668
|
+
severity: finding.severity,
|
|
1669
|
+
file: finding.file,
|
|
1670
|
+
line: finding.line,
|
|
1671
|
+
command: finding.command,
|
|
1672
|
+
reason: finding.message,
|
|
1673
|
+
proposedCorrection: finding.proposedCorrection
|
|
1674
|
+
}));
|
|
1644
1675
|
}
|
|
1645
1676
|
async function inspectAgentReadiness(options = {}) {
|
|
1646
|
-
const
|
|
1647
|
-
|
|
1648
|
-
|
|
1677
|
+
const invocationRoot = process.cwd();
|
|
1678
|
+
let rootDir = invocationRoot;
|
|
1679
|
+
let files = [];
|
|
1680
|
+
let framework = "unknown";
|
|
1649
1681
|
const configCheckMax = 10;
|
|
1650
1682
|
let configPath;
|
|
1651
1683
|
try {
|
|
1652
|
-
configPath = resolveDocsConfigPath(
|
|
1684
|
+
configPath = resolveDocsConfigPath(invocationRoot, options.configPath);
|
|
1685
|
+
rootDir = resolveDocsProjectRoot(invocationRoot, configPath);
|
|
1686
|
+
files = listProjectFiles(rootDir);
|
|
1687
|
+
framework = detectFramework(rootDir) ?? detectFrameworkFromFiles(files) ?? "unknown";
|
|
1653
1688
|
} catch (error) {
|
|
1654
|
-
const
|
|
1689
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1690
|
+
const invocationFiles = listProjectFiles(invocationRoot);
|
|
1691
|
+
framework = detectFramework(invocationRoot) ?? detectFrameworkFromFiles(invocationFiles) ?? "unknown";
|
|
1692
|
+
const checks = [makeCheck("config", "Docs config", "fail", 0, configCheckMax, message, "Add docs.config.ts[x] or pass --config so the doctor can inspect the docs app.")];
|
|
1655
1693
|
return {
|
|
1656
1694
|
mode: "agent",
|
|
1657
1695
|
framework,
|
|
@@ -1678,7 +1716,7 @@ async function inspectAgentReadiness(options = {}) {
|
|
|
1678
1716
|
};
|
|
1679
1717
|
}
|
|
1680
1718
|
const configContent = readFileSync(configPath, "utf-8");
|
|
1681
|
-
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir,
|
|
1719
|
+
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir, configPath);
|
|
1682
1720
|
const config = configLoad.status === "evaluated" ? configLoad.config : void 0;
|
|
1683
1721
|
let configuredAgentSkillNames;
|
|
1684
1722
|
let configuredAgentSkillsError;
|
|
@@ -1727,6 +1765,7 @@ async function inspectAgentReadiness(options = {}) {
|
|
|
1727
1765
|
pages: createAgentUsefulnessPagesFromMcp(rootDir, pages),
|
|
1728
1766
|
projectFramework: framework === "unknown" ? void 0 : framework
|
|
1729
1767
|
});
|
|
1768
|
+
const commandFindings = toDoctorCommandFindings(usefulness.findings);
|
|
1730
1769
|
const evaluationInput = config?.agent?.evaluations;
|
|
1731
1770
|
const evaluation = resolveGoldenEvaluationInput(evaluationInput);
|
|
1732
1771
|
const evaluationBaseUrl = config ? resolveDocsMetadataBaseUrl(config) : void 0;
|
|
@@ -1874,7 +1913,7 @@ async function inspectAgentReadiness(options = {}) {
|
|
|
1874
1913
|
checks.push(makeCheck("agent-context-quality", "Agent context usefulness", contextQualityResult.status, contextQualityResult.score, 15, usefulness.metrics.agentBlocks.total > 0 ? `${usefulness.metrics.agentBlocks.useful}/${usefulness.metrics.agentBlocks.total} agent-only blocks are specific and non-repetitive (${usefulness.metrics.agentBlocks.duplicate} duplicate, ${usefulness.metrics.agentBlocks.boilerplate} boilerplate, ${usefulness.metrics.agentBlocks.generic} generic).` : "No embedded agent-only blocks were present; page contracts and sibling agent.md files remain available as alternatives.", usefulness.metrics.agentBlocks.total > 0 && usefulness.metrics.agentBlocks.useful === usefulness.metrics.agentBlocks.total ? void 0 : "Replace repeated agent-only boilerplate with page-specific constraints, commands, files, expected results, and recovery guidance."));
|
|
1875
1914
|
checks.push(makeCheck("agent-task-completeness", "Agent task completeness", taskCompletenessResult.status, taskCompletenessResult.score, 15, `${usefulness.metrics.taskCompleteness.completePages}/${usefulness.metrics.actionablePages} actionable pages include prerequisites, an expected result, and recovery guidance (${usefulness.metrics.taskCompleteness.coverage}% complete).`, usefulness.metrics.actionablePages > 0 && usefulness.metrics.taskCompleteness.coverage >= 80 ? void 0 : "Add prerequisites, observable outcomes or verification expectations, and rollback or resolved failure modes to actionable pages."));
|
|
1876
1915
|
checks.push(makeCheck("agent-applicability", "Framework and version applicability", applicabilityResult.status, applicabilityResult.score, 10, `${usefulness.metrics.applicability.conflictingPages} conflicting, ${usefulness.metrics.applicability.ambiguousPages} ambiguous, and ${usefulness.metrics.applicability.mismatchedPages} project-mismatched actionable pages.`, usefulness.metrics.actionablePages > 0 && applicabilityIssueCount === 0 ? void 0 : "Declare consistent framework/version metadata in page frontmatter and agent.appliesTo so retrieval can select the right variant."));
|
|
1877
|
-
checks.push(makeCheck("command-health", "Documented command health", commandHealthResult.status, commandHealthResult.score, 10, `${usefulness.metrics.commands.healthy}/${usefulness.metrics.commands.total} statically inspected commands are healthy; ${usefulness.metrics.commands.unhealthy} are unhealthy and ${usefulness.metrics.commands.unverified} could not be verified safely.`, usefulness.metrics.commands.total > 0 && usefulness.metrics.commands.unhealthy === 0 && usefulness.metrics.commands.unverified === 0 ? void 0 : "Update broken or stale commands and make workspace selectors resolvable so scripts, working directories, package managers, and docs CLI subcommands can be verified."));
|
|
1916
|
+
checks.push(makeCheck("command-health", "Documented command health", commandHealthResult.status, commandHealthResult.score, 10, `${usefulness.metrics.commands.healthy}/${usefulness.metrics.commands.total} statically inspected commands are healthy; ${usefulness.metrics.commands.unhealthy} are unhealthy and ${usefulness.metrics.commands.unverified} could not be verified safely.`, usefulness.metrics.commands.total > 0 && usefulness.metrics.commands.unhealthy === 0 && usefulness.metrics.commands.unverified === 0 ? void 0 : "Update broken or stale commands and make workspace selectors resolvable so scripts, working directories, package managers, and docs CLI subcommands can be verified.", commandFindings));
|
|
1878
1917
|
checks.push(makeCheck("related-coverage", "Related-page task coverage", relatedCoverageResult.status, relatedCoverageResult.score, 5, `${usefulness.metrics.related.coveredActionablePages}/${usefulness.metrics.actionablePages} actionable pages link to a valid related docs route; ${usefulness.metrics.related.brokenLinks} related links are broken.`, usefulness.metrics.actionablePages > 0 && usefulness.metrics.related.coverage >= 80 && usefulness.metrics.related.brokenLinks === 0 ? void 0 : "Add and validate related routes on actionable pages so agents can expand context without guessing."));
|
|
1879
1918
|
checks.push(makeCheck("compact", "Agent compaction freshness", compactionResult.status, compactionResult.score, 5, `${compactionCoverage.freshGeneratedPages} fresh, ${compactionCoverage.staleGeneratedPages} stale, ${compactionCoverage.modifiedGeneratedPages} modified, ${compactionCoverage.unknownGeneratedPages} unknown, ${compactionCoverage.tokenBudgetMissingPages} token-budget missing, and ${compactionCoverage.otherMissingPages} other missing page${compactionCoverage.otherMissingPages === 1 ? "" : "s"} across compactable docs pages.` + (compactConfigured ? " agent.compact defaults are configured." : " No agent.compact defaults were found in docs config."), compactionResult.recommendation));
|
|
1880
1919
|
const averageMetric = (values) => values.length === 0 ? 0 : Math.round(values.reduce((total, value) => total + value, 0) / values.length * 100) / 100;
|
|
@@ -1902,15 +1941,22 @@ async function inspectAgentReadiness(options = {}) {
|
|
|
1902
1941
|
};
|
|
1903
1942
|
}
|
|
1904
1943
|
async function inspectHumanReadiness(options = {}) {
|
|
1905
|
-
const
|
|
1906
|
-
|
|
1907
|
-
|
|
1944
|
+
const invocationRoot = process.cwd();
|
|
1945
|
+
let rootDir = invocationRoot;
|
|
1946
|
+
let files = [];
|
|
1947
|
+
let framework = "unknown";
|
|
1908
1948
|
const configCheckMax = 10;
|
|
1909
1949
|
let configPath;
|
|
1910
1950
|
try {
|
|
1911
|
-
configPath = resolveDocsConfigPath(
|
|
1951
|
+
configPath = resolveDocsConfigPath(invocationRoot, options.configPath);
|
|
1952
|
+
rootDir = resolveDocsProjectRoot(invocationRoot, configPath);
|
|
1953
|
+
files = listProjectFiles(rootDir);
|
|
1954
|
+
framework = detectFramework(rootDir) ?? detectFrameworkFromFiles(files) ?? "unknown";
|
|
1912
1955
|
} catch (error) {
|
|
1913
|
-
const
|
|
1956
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1957
|
+
const invocationFiles = listProjectFiles(invocationRoot);
|
|
1958
|
+
framework = detectFramework(invocationRoot) ?? detectFrameworkFromFiles(invocationFiles) ?? "unknown";
|
|
1959
|
+
const checks = [makeCheck("config", "Docs config", "fail", 0, configCheckMax, message, "Add docs.config.ts[x] or pass --config so the doctor can inspect the docs app.")];
|
|
1914
1960
|
return {
|
|
1915
1961
|
mode: "human",
|
|
1916
1962
|
framework,
|
|
@@ -1931,7 +1977,7 @@ async function inspectHumanReadiness(options = {}) {
|
|
|
1931
1977
|
};
|
|
1932
1978
|
}
|
|
1933
1979
|
const configContent = readFileSync(configPath, "utf-8");
|
|
1934
|
-
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir,
|
|
1980
|
+
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir, configPath);
|
|
1935
1981
|
const config = configLoad.status === "evaluated" ? configLoad.config : void 0;
|
|
1936
1982
|
const entry = config?.entry ?? readTopLevelStringProperty(configContent, "entry") ?? "docs";
|
|
1937
1983
|
const contentDir = config?.contentDir ?? resolveDocsContentDir(rootDir, configContent, entry);
|
|
@@ -1996,6 +2042,12 @@ function printAgentDoctorReport(report) {
|
|
|
1996
2042
|
for (const check of report.checks) {
|
|
1997
2043
|
console.log(`${formatStatus(check.status)} ${check.title} ${pc.dim(`(${check.score}/${check.maxScore})`)}`);
|
|
1998
2044
|
console.log(` ${check.detail}`);
|
|
2045
|
+
for (const finding of check.findings ?? []) {
|
|
2046
|
+
const location = `${finding.file}${finding.line ? `:${finding.line}` : ""}`;
|
|
2047
|
+
console.log(` ${pc.dim(location)} ${pc.bold("Command:")} ${finding.command}`);
|
|
2048
|
+
console.log(` ${pc.bold("Reason:")} ${finding.reason}`);
|
|
2049
|
+
console.log(` ${pc.bold("Proposed correction:")} ${finding.proposedCorrection}`);
|
|
2050
|
+
}
|
|
1999
2051
|
}
|
|
2000
2052
|
if (report.recommendations.length > 0) {
|
|
2001
2053
|
console.log();
|
|
@@ -2032,6 +2084,30 @@ function serializeDoctorJsonReport(report) {
|
|
|
2032
2084
|
function printDoctorJsonReport(report) {
|
|
2033
2085
|
console.log(JSON.stringify(serializeDoctorJsonReport(report), null, 2));
|
|
2034
2086
|
}
|
|
2087
|
+
function writeDoctorJsonReport(report, outputPath) {
|
|
2088
|
+
const resolvedPath = path.resolve(process.cwd(), outputPath);
|
|
2089
|
+
mkdirSync(path.dirname(resolvedPath), { recursive: true });
|
|
2090
|
+
writeFileSync(resolvedPath, `${JSON.stringify(serializeDoctorJsonReport(report), null, 2)}\n`, "utf-8");
|
|
2091
|
+
}
|
|
2092
|
+
function escapeGitHubAnnotationData(value) {
|
|
2093
|
+
return value.replaceAll("%", "%25").replaceAll("\r", "%0D").replaceAll("\n", "%0A");
|
|
2094
|
+
}
|
|
2095
|
+
function escapeGitHubAnnotationProperty(value) {
|
|
2096
|
+
return escapeGitHubAnnotationData(value).replaceAll(":", "%3A").replaceAll(",", "%2C");
|
|
2097
|
+
}
|
|
2098
|
+
function emitDoctorGitHubAnnotations(report) {
|
|
2099
|
+
if (process.env.GITHUB_ACTIONS !== "true" || report.mode !== "agent") return;
|
|
2100
|
+
for (const check of report.checks) for (const finding of check.findings ?? []) {
|
|
2101
|
+
const command = finding.severity === "error" ? "error" : finding.severity === "warning" ? "warning" : "notice";
|
|
2102
|
+
const location = [
|
|
2103
|
+
`file=${escapeGitHubAnnotationProperty(finding.file)}`,
|
|
2104
|
+
finding.line ? `line=${finding.line}` : void 0,
|
|
2105
|
+
`title=${escapeGitHubAnnotationProperty(check.title)}`
|
|
2106
|
+
].filter(Boolean).join(",");
|
|
2107
|
+
const message = `Command: ${finding.command} Reason: ${finding.reason} Proposed correction: ${finding.proposedCorrection}`;
|
|
2108
|
+
console.log(`::${command} ${location}::${escapeGitHubAnnotationData(message)}`);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2035
2111
|
function hasNonPassingDoctorCheck(report) {
|
|
2036
2112
|
return report.checks.some((check) => check.status !== "pass");
|
|
2037
2113
|
}
|
|
@@ -2093,15 +2169,18 @@ async function runAgentDoctorFixes(report, options) {
|
|
|
2093
2169
|
return fixes;
|
|
2094
2170
|
}
|
|
2095
2171
|
async function runDoctor(options = {}) {
|
|
2172
|
+
if (options.ci && options.json) throw new Error("doctor --ci and --json cannot share stdout. Use --ci --json-output <path> to emit GitHub annotations and persist the JSON report in one run.");
|
|
2096
2173
|
if (options.mode === "human") {
|
|
2097
2174
|
if (options.fix) throw new Error("doctor --fix is currently only supported with --agent.");
|
|
2098
2175
|
const report = await inspectHumanReadiness(options);
|
|
2099
2176
|
applyDoctorExitCode(report, options);
|
|
2177
|
+
if (options.jsonOutputPath) writeDoctorJsonReport(report, options.jsonOutputPath);
|
|
2100
2178
|
if (options.json) {
|
|
2101
2179
|
printDoctorJsonReport(report);
|
|
2102
2180
|
return report;
|
|
2103
2181
|
}
|
|
2104
2182
|
printHumanDoctorReport(report);
|
|
2183
|
+
if (options.ci) emitDoctorGitHubAnnotations(report);
|
|
2105
2184
|
return report;
|
|
2106
2185
|
}
|
|
2107
2186
|
let report = await inspectAgentReadiness(options);
|
|
@@ -2117,11 +2196,13 @@ async function runDoctor(options = {}) {
|
|
|
2117
2196
|
};
|
|
2118
2197
|
}
|
|
2119
2198
|
applyDoctorExitCode(report, options);
|
|
2199
|
+
if (options.jsonOutputPath) writeDoctorJsonReport(report, options.jsonOutputPath);
|
|
2120
2200
|
if (options.json) {
|
|
2121
2201
|
printDoctorJsonReport(report);
|
|
2122
2202
|
return report;
|
|
2123
2203
|
}
|
|
2124
2204
|
printAgentDoctorReport(report);
|
|
2205
|
+
if (options.ci) emitDoctorGitHubAnnotations(report);
|
|
2125
2206
|
return report;
|
|
2126
2207
|
}
|
|
2127
2208
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { An as normalizeAgentFramework, Cn as findDocsAudienceMdxTags, En as resolveDocsAudienceMdxContent, Nn as normalizeAgentVersion, kn as agentVersionConstraintsOverlap } from "./agent-CTOUI2BK.mjs";
|
|
2
2
|
import { _ as hasStructuredPageAgentContract, v as normalizePageAgentFrontmatter } from "./markdown-sections-7OoA7ylx.mjs";
|
|
3
3
|
import { t as extractCodeBlocksFromMarkdown } from "./code-blocks-0wjOsqdJ.mjs";
|
|
4
|
+
import { isMap, isScalar, isSeq, parseDocument } from "yaml";
|
|
4
5
|
import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
|
|
@@ -39,6 +40,7 @@ const DEFAULT_DOCS_COMMANDS = [
|
|
|
39
40
|
"cloud deploy",
|
|
40
41
|
"cloud preview",
|
|
41
42
|
"mcp",
|
|
43
|
+
"skills scaffold",
|
|
42
44
|
"agent compact",
|
|
43
45
|
"agent export",
|
|
44
46
|
"agents generate",
|
|
@@ -519,7 +521,7 @@ function analyzePage(page) {
|
|
|
519
521
|
sourcePath: page.sourcePath,
|
|
520
522
|
route: page.route
|
|
521
523
|
});
|
|
522
|
-
const shellCommands = collectPageCommands(page, agent
|
|
524
|
+
const shellCommands = collectPageCommands(page, agent);
|
|
523
525
|
return {
|
|
524
526
|
page,
|
|
525
527
|
agent,
|
|
@@ -698,7 +700,8 @@ function analyzeCommand(options) {
|
|
|
698
700
|
findings.push(commandFinding(options, {
|
|
699
701
|
code: "command-cwd-outside-root",
|
|
700
702
|
severity: "error",
|
|
701
|
-
message: `Command working directory resolves outside the project root: ${commandCwd}
|
|
703
|
+
message: `Command working directory resolves outside the project root: ${commandCwd}`,
|
|
704
|
+
proposedCorrection: `Set cwd to an existing project-relative directory inside the docs project instead of ${JSON.stringify(commandCwd)}.`
|
|
702
705
|
}));
|
|
703
706
|
return commandAnalysis(findings);
|
|
704
707
|
}
|
|
@@ -706,7 +709,8 @@ function analyzeCommand(options) {
|
|
|
706
709
|
findings.push(commandFinding(options, {
|
|
707
710
|
code: "command-cwd-missing",
|
|
708
711
|
severity: "error",
|
|
709
|
-
message: `Command working directory does not exist: ${commandCwd}
|
|
712
|
+
message: `Command working directory does not exist: ${commandCwd}`,
|
|
713
|
+
proposedCorrection: `Create ${JSON.stringify(commandCwd)} or change cwd to an existing project-relative directory.`
|
|
710
714
|
}));
|
|
711
715
|
return commandAnalysis(findings);
|
|
712
716
|
}
|
|
@@ -714,7 +718,8 @@ function analyzeCommand(options) {
|
|
|
714
718
|
findings.push(commandFinding(options, {
|
|
715
719
|
code: "command-unverified",
|
|
716
720
|
severity: "suggestion",
|
|
717
|
-
message: "Compound commands, redirections, and shell expansions are not executed or inferred; this command is unverified."
|
|
721
|
+
message: "Compound commands, redirections, and shell expansions are not executed or inferred; this command is unverified.",
|
|
722
|
+
proposedCorrection: "Split the shell expression into one independently verifiable command per line and document any redirection or expansion as a separate step."
|
|
718
723
|
}));
|
|
719
724
|
return commandAnalysis(findings);
|
|
720
725
|
}
|
|
@@ -724,7 +729,8 @@ function analyzeCommand(options) {
|
|
|
724
729
|
if (commandPackageManager && expectedPackageManager && commandPackageManager !== expectedPackageManager) findings.push(commandFinding(options, {
|
|
725
730
|
code: "command-package-manager-mismatch",
|
|
726
731
|
severity: "warning",
|
|
727
|
-
message: `Command uses ${commandPackageManager}, but ${expectedPackageManager} is expected for this project or code block
|
|
732
|
+
message: `Command uses ${commandPackageManager}, but ${expectedPackageManager} is expected for this project or code block.`,
|
|
733
|
+
proposedCorrection: `Rewrite this command using ${expectedPackageManager}, or explicitly mark the example as a ${commandPackageManager} alternative when that is intentional.`
|
|
728
734
|
}));
|
|
729
735
|
const workspaceSelection = readWorkspaceSelection(tokens, commandPackageManager);
|
|
730
736
|
const workspaceResolution = resolveWorkspaceSelection(workspaceSelection, options.packageManifests, options.rootDir, options.workspaceRoot);
|
|
@@ -733,7 +739,8 @@ function analyzeCommand(options) {
|
|
|
733
739
|
findings.push(commandFinding(options, {
|
|
734
740
|
code: "command-unverified",
|
|
735
741
|
severity: "suggestion",
|
|
736
|
-
message: `Workspace selector could not be resolved statically (${selectors}); this command is unverified
|
|
742
|
+
message: `Workspace selector could not be resolved statically (${selectors}); this command is unverified.`,
|
|
743
|
+
proposedCorrection: "Replace the selector with an exact workspace package name or path declared by the nearest workspace manifest."
|
|
737
744
|
}));
|
|
738
745
|
}
|
|
739
746
|
const script = readPackageScript(tokens);
|
|
@@ -742,13 +749,15 @@ function analyzeCommand(options) {
|
|
|
742
749
|
if (workspaceResolution.status === "none" && packageJsons.length === 0) findings.push(commandFinding(options, {
|
|
743
750
|
code: "command-unverified",
|
|
744
751
|
severity: "suggestion",
|
|
745
|
-
message: `No package.json could be found for package script "${script}"; this command is unverified
|
|
752
|
+
message: `No package.json could be found for package script "${script}"; this command is unverified.`,
|
|
753
|
+
proposedCorrection: "Set cwd to the package that owns this script, or add a package.json with the documented script."
|
|
746
754
|
}));
|
|
747
755
|
for (const packageJson of packageJsons) if (packageJson.scripts.has(script)) verificationEstablished = true;
|
|
748
756
|
else findings.push(commandFinding(options, {
|
|
749
757
|
code: "command-script-missing",
|
|
750
758
|
severity: "error",
|
|
751
|
-
message: `Command references package script "${script}", but that script is not defined in ${packageJson.relativePath}
|
|
759
|
+
message: `Command references package script "${script}", but that script is not defined in ${packageJson.relativePath}.`,
|
|
760
|
+
proposedCorrection: `Add a ${JSON.stringify(script)} script to ${packageJson.relativePath}, or replace the command with an existing script from that file.`
|
|
752
761
|
}));
|
|
753
762
|
}
|
|
754
763
|
const docsCommand = readDocsCommand(tokens);
|
|
@@ -756,13 +765,15 @@ function analyzeCommand(options) {
|
|
|
756
765
|
else findings.push(commandFinding(options, {
|
|
757
766
|
code: "command-cli-unknown",
|
|
758
767
|
severity: "error",
|
|
759
|
-
message: `Command references an unknown docs CLI command: docs ${docsCommand}
|
|
768
|
+
message: `Command references an unknown docs CLI command: docs ${docsCommand}`,
|
|
769
|
+
proposedCorrection: `Replace "docs ${docsCommand}" with the intended supported command listed by "docs --help".`
|
|
760
770
|
}));
|
|
761
771
|
if (isStaticallyKnownPackageManagerCommand(tokens) || isVersionProbe(tokens) || isStaticallyValidCurlCommand(tokens) || isStaticallyValidShellBuiltin(tokens, resolvedCwd, options.rootDir) || isStaticallyValidAgentToolCommand(tokens)) verificationEstablished = true;
|
|
762
772
|
if (!verificationEstablished && findings.length === 0) findings.push(commandFinding(options, {
|
|
763
773
|
code: "command-unverified",
|
|
764
774
|
severity: "suggestion",
|
|
765
|
-
message: "Command form could not be verified statically; this command is unverified."
|
|
775
|
+
message: "Command form could not be verified statically; this command is unverified.",
|
|
776
|
+
proposedCorrection: "Use a documented package-manager or docs CLI command, or configure explicit executable-example validation for this command."
|
|
766
777
|
}));
|
|
767
778
|
return commandAnalysis(findings);
|
|
768
779
|
}
|
|
@@ -780,16 +791,97 @@ function commandAnalysis(findings) {
|
|
|
780
791
|
status: "healthy"
|
|
781
792
|
};
|
|
782
793
|
}
|
|
783
|
-
function
|
|
794
|
+
function collectContractCommandLocations(source) {
|
|
795
|
+
const empty = () => ({
|
|
796
|
+
commands: [],
|
|
797
|
+
verification: []
|
|
798
|
+
});
|
|
799
|
+
const opening = source.match(/^---[^\S\r\n]*\r?\n/);
|
|
800
|
+
if (!opening) return empty();
|
|
801
|
+
const frontmatterOffset = opening[0].length;
|
|
802
|
+
const remainder = source.slice(frontmatterOffset);
|
|
803
|
+
const closing = /(?:^|\r?\n)---[^\S\r\n]*(?:\r?\n|$)/.exec(remainder);
|
|
804
|
+
if (!closing) return empty();
|
|
805
|
+
try {
|
|
806
|
+
const document = parseDocument(remainder.slice(0, closing.index), { uniqueKeys: true });
|
|
807
|
+
if (document.errors.length > 0 || !isMap(document.contents)) return empty();
|
|
808
|
+
const agent = document.contents.get("agent", true);
|
|
809
|
+
if (!isMap(agent)) return empty();
|
|
810
|
+
return {
|
|
811
|
+
commands: collectContractSequenceLocations(agent.get("commands", true), source, frontmatterOffset),
|
|
812
|
+
verification: collectContractSequenceLocations(agent.get("verification", true), source, frontmatterOffset)
|
|
813
|
+
};
|
|
814
|
+
} catch {
|
|
815
|
+
return empty();
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
function collectContractSequenceLocations(value, source, frontmatterOffset) {
|
|
819
|
+
if (!isSeq(value)) return [];
|
|
820
|
+
const locations = [];
|
|
821
|
+
for (const item of value.items) {
|
|
822
|
+
const run = isScalar(item) ? item : isMap(item) ? item.get("run", true) : void 0;
|
|
823
|
+
if (!isScalar(run) || typeof run.value !== "string") continue;
|
|
824
|
+
const location = contractScalarLocation(run, source, frontmatterOffset);
|
|
825
|
+
if (location) locations.push(location);
|
|
826
|
+
}
|
|
827
|
+
return locations;
|
|
828
|
+
}
|
|
829
|
+
function contractScalarLocation(scalar, source, frontmatterOffset) {
|
|
830
|
+
const relativeOffset = scalar.range?.[0];
|
|
831
|
+
if (typeof scalar.value !== "string" || relativeOffset === void 0) return void 0;
|
|
832
|
+
const absoluteOffset = frontmatterOffset + relativeOffset;
|
|
833
|
+
return {
|
|
834
|
+
run: scalar.value,
|
|
835
|
+
line: source.slice(0, absoluteOffset).split(/\r?\n/).length
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
function claimContractCommandLine(locations, command, claimedLines) {
|
|
839
|
+
const location = locations.find((candidate) => candidate.run === command && !claimedLines.has(candidate.line));
|
|
840
|
+
if (!location) return void 0;
|
|
841
|
+
claimedLines.add(location.line);
|
|
842
|
+
return location.line;
|
|
843
|
+
}
|
|
844
|
+
function preserveLineBreaksOnly(value) {
|
|
845
|
+
return value.replace(/[^\r\n]/g, " ");
|
|
846
|
+
}
|
|
847
|
+
/** Agent projection used for command discovery that keeps original source line numbers stable. */
|
|
848
|
+
function projectAgentCommandSource(source) {
|
|
849
|
+
const tags = findDocsAudienceMdxTags(source);
|
|
850
|
+
if (tags.length === 0) return source;
|
|
851
|
+
const scopes = [];
|
|
852
|
+
let output = "";
|
|
853
|
+
let cursor = 0;
|
|
854
|
+
const visible = () => scopes.every((scope) => scope.only !== "human");
|
|
855
|
+
for (const tag of tags) {
|
|
856
|
+
const activeScope = scopes.at(-1);
|
|
857
|
+
if (tag.closing && activeScope?.name !== tag.name) continue;
|
|
858
|
+
const content = source.slice(cursor, tag.index);
|
|
859
|
+
output += visible() ? content : preserveLineBreaksOnly(content);
|
|
860
|
+
output += preserveLineBreaksOnly(source.slice(tag.index, tag.end));
|
|
861
|
+
cursor = tag.end;
|
|
862
|
+
if (tag.closing) scopes.pop();
|
|
863
|
+
else if (!tag.selfClosing) scopes.push({
|
|
864
|
+
name: tag.name,
|
|
865
|
+
only: tag.only
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
const remaining = source.slice(cursor);
|
|
869
|
+
output += visible() ? remaining : preserveLineBreaksOnly(remaining);
|
|
870
|
+
return output;
|
|
871
|
+
}
|
|
872
|
+
function collectPageCommands(page, agent) {
|
|
784
873
|
const commands = [];
|
|
785
|
-
|
|
874
|
+
const contractLocations = collectContractCommandLocations(page.source);
|
|
875
|
+
const claimedContractLines = /* @__PURE__ */ new Set();
|
|
876
|
+
for (const command of agent?.commands ?? []) commands.push(normalizeAgentCommand(command, page.sourcePath, claimContractCommandLine(contractLocations.commands, typeof command === "string" ? command : command.run, claimedContractLines)));
|
|
786
877
|
for (const verification of agent?.verification ?? []) if (typeof verification !== "string" && verification.run) commands.push({
|
|
787
878
|
run: verification.run,
|
|
879
|
+
line: claimContractCommandLine(contractLocations.verification, verification.run, claimedContractLines),
|
|
788
880
|
sourcePath: page.sourcePath,
|
|
789
881
|
source: "contract"
|
|
790
882
|
});
|
|
791
|
-
collectMarkdownCommands(commands,
|
|
792
|
-
if (page.agentSource) collectMarkdownCommands(commands, page.agentSource, page.agentSourcePath ?? page.sourcePath);
|
|
883
|
+
collectMarkdownCommands(commands, projectAgentCommandSource(page.source), page.sourcePath);
|
|
884
|
+
if (page.agentSource) collectMarkdownCommands(commands, projectAgentCommandSource(page.agentSource), page.agentSourcePath ?? page.sourcePath);
|
|
793
885
|
return dedupeCommands(commands);
|
|
794
886
|
}
|
|
795
887
|
function collectMarkdownCommands(commands, source, sourcePath) {
|
|
@@ -801,30 +893,54 @@ function collectMarkdownCommands(commands, source, sourcePath) {
|
|
|
801
893
|
for (const block of blocks) {
|
|
802
894
|
if (!/^(?:bash|console|sh|shell|zsh)$/i.test(block.language ?? "")) continue;
|
|
803
895
|
for (const command of shellLines(block.code, block.language)) commands.push({
|
|
804
|
-
run: command,
|
|
805
|
-
line: block.lineStart,
|
|
896
|
+
run: command.run,
|
|
897
|
+
line: block.lineStart + 1 + command.lineOffset,
|
|
806
898
|
sourcePath,
|
|
807
899
|
packageManagerHint: block.packageManager,
|
|
808
900
|
source: "fence"
|
|
809
901
|
});
|
|
810
902
|
}
|
|
811
903
|
}
|
|
812
|
-
function normalizeAgentCommand(command, sourcePath) {
|
|
904
|
+
function normalizeAgentCommand(command, sourcePath, line) {
|
|
905
|
+
const run = typeof command === "string" ? command : command.run;
|
|
813
906
|
return typeof command === "string" ? {
|
|
814
|
-
run
|
|
907
|
+
run,
|
|
908
|
+
line,
|
|
815
909
|
sourcePath,
|
|
816
910
|
source: "contract"
|
|
817
911
|
} : {
|
|
818
|
-
run
|
|
912
|
+
run,
|
|
819
913
|
cwd: command.cwd,
|
|
914
|
+
line,
|
|
820
915
|
sourcePath,
|
|
821
916
|
source: "contract"
|
|
822
917
|
};
|
|
823
918
|
}
|
|
824
919
|
function shellLines(code, language) {
|
|
825
|
-
const
|
|
826
|
-
|
|
827
|
-
|
|
920
|
+
const logicalLines = [];
|
|
921
|
+
let pending;
|
|
922
|
+
for (const [lineOffset, physicalLine] of code.split(/\r?\n/).entries()) {
|
|
923
|
+
const trimmed = physicalLine.trim();
|
|
924
|
+
if (!pending) pending = {
|
|
925
|
+
run: "",
|
|
926
|
+
lineOffset
|
|
927
|
+
};
|
|
928
|
+
const continued = /\\\s*$/.test(trimmed);
|
|
929
|
+
const segment = continued ? trimmed.replace(/\\\s*$/, "").trimEnd() : trimmed;
|
|
930
|
+
pending.run = `${pending.run}${pending.run && segment ? " " : ""}${segment}`;
|
|
931
|
+
if (continued) continue;
|
|
932
|
+
logicalLines.push(pending);
|
|
933
|
+
pending = void 0;
|
|
934
|
+
}
|
|
935
|
+
if (pending) logicalLines.push(pending);
|
|
936
|
+
const promptedConsole = language?.toLowerCase() === "console" && logicalLines.some((line) => /^(?:\$|>)\s+/.test(line.run.trim()));
|
|
937
|
+
return logicalLines.map((line) => ({
|
|
938
|
+
...line,
|
|
939
|
+
run: line.run.trim()
|
|
940
|
+
})).filter((line) => !promptedConsole || /^(?:\$|>)\s+/.test(line.run)).map((line) => ({
|
|
941
|
+
...line,
|
|
942
|
+
run: line.run.replace(/^(?:\$|>)\s+/, "")
|
|
943
|
+
})).filter((line) => Boolean(line.run) && !line.run.startsWith("#") && !/^\w+=\S+$/.test(line.run));
|
|
828
944
|
}
|
|
829
945
|
function dedupeCommands(commands) {
|
|
830
946
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -188,7 +188,7 @@ async function configureDocsCloudOnboarding(options) {
|
|
|
188
188
|
enabled = cloudAnswer;
|
|
189
189
|
}
|
|
190
190
|
if (!enabled) return;
|
|
191
|
-
const { initCloudConfig } = await import("./cloud-
|
|
191
|
+
const { initCloudConfig } = await import("./cloud-DwhH_b_q.mjs");
|
|
192
192
|
printDocsCloudOnboardingInstructions(await initCloudConfig({
|
|
193
193
|
rootDir: options.rootDir,
|
|
194
194
|
configPath: getDocsCloudConfigPathForFramework(options.framework)
|
|
@@ -9,7 +9,7 @@ import "./agent-evals-DCptRrdP.mjs";
|
|
|
9
9
|
import { createFilesystemDocsMcpSource, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
|
|
10
10
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
11
11
|
import "./server.mjs";
|
|
12
|
-
import { _ as resolveDocsContentDir, d as readNavTitle, g as resolveDocsConfigPath, i as hasTopLevelProperty, l as readBooleanProperty, n as extractObjectLiteral, o as loadDocsConfigModuleResult, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
12
|
+
import { _ as resolveDocsContentDir, d as readNavTitle, g as resolveDocsConfigPath, i as hasTopLevelProperty, l as readBooleanProperty, n as extractObjectLiteral, o as loadDocsConfigModuleResult, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
13
13
|
import { existsSync, readFileSync } from "node:fs";
|
|
14
14
|
import path from "node:path";
|
|
15
15
|
import pc from "picocolors";
|
package/dist/mcp.mjs
CHANGED
|
@@ -13,6 +13,9 @@ import * as z from "zod/v4";
|
|
|
13
13
|
//#region src/mcp.ts
|
|
14
14
|
const DEFAULT_MCP_VERSION = "0.0.0";
|
|
15
15
|
const DEFAULT_MCP_NAME = "@farming-labs/docs";
|
|
16
|
+
const DOCS_MCP_DISCOVERY_CACHE_TTL_MS = 300 * 1e3;
|
|
17
|
+
const DOCS_MCP_LIST_CACHE_TTL_MS = 300 * 1e3;
|
|
18
|
+
const DOCS_MCP_RESOURCE_CACHE_TTL_MS = 60 * 1e3;
|
|
16
19
|
const DEFAULT_MCP_CONTEXT_TOKEN_BUDGET = 4e3;
|
|
17
20
|
const MIN_MCP_CONTEXT_TOKEN_BUDGET = 256;
|
|
18
21
|
const MAX_MCP_CONTEXT_TOKEN_BUDGET = 32e3;
|
|
@@ -2625,7 +2628,7 @@ function durationMs(startedAt) {
|
|
|
2625
2628
|
}
|
|
2626
2629
|
function createDocsMcpContentChangeMonitor(options) {
|
|
2627
2630
|
let context;
|
|
2628
|
-
let
|
|
2631
|
+
let state;
|
|
2629
2632
|
let timer;
|
|
2630
2633
|
let running = false;
|
|
2631
2634
|
let closed = false;
|
|
@@ -2636,11 +2639,14 @@ function createDocsMcpContentChangeMonitor(options) {
|
|
|
2636
2639
|
if (closed || context === void 0 || options.isActive?.() === false) return;
|
|
2637
2640
|
running = true;
|
|
2638
2641
|
try {
|
|
2639
|
-
const
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2642
|
+
const nextState = await options.readState(context);
|
|
2643
|
+
const previousState = state;
|
|
2644
|
+
state = nextState;
|
|
2645
|
+
if (previousState && nextState.indexGeneration !== previousState.indexGeneration) await options.notify({
|
|
2646
|
+
context,
|
|
2647
|
+
previous: previousState,
|
|
2648
|
+
current: nextState
|
|
2649
|
+
});
|
|
2644
2650
|
} catch {} finally {
|
|
2645
2651
|
running = false;
|
|
2646
2652
|
schedule();
|
|
@@ -2657,9 +2663,9 @@ function createDocsMcpContentChangeMonitor(options) {
|
|
|
2657
2663
|
timer = void 0;
|
|
2658
2664
|
}
|
|
2659
2665
|
try {
|
|
2660
|
-
|
|
2666
|
+
state = await options.readState(nextContext);
|
|
2661
2667
|
} catch {
|
|
2662
|
-
|
|
2668
|
+
state = void 0;
|
|
2663
2669
|
}
|
|
2664
2670
|
schedule();
|
|
2665
2671
|
},
|
|
@@ -2817,10 +2823,36 @@ async function createDocsMcpServer(options) {
|
|
|
2817
2823
|
});
|
|
2818
2824
|
const contentChangesEnabled = resolveDocsContentChangesConfig(options.contentChanges).enabled && resolved.tools.listContentChanges !== false;
|
|
2819
2825
|
const contentChangeHydrationEnabled = contentChangesEnabled && resolved.tools.hydrateContentChanges !== false;
|
|
2826
|
+
const cacheScope = options.requestContext?.auth ? "private" : "public";
|
|
2820
2827
|
const server = new McpServer({
|
|
2821
2828
|
name: resolved.name,
|
|
2822
2829
|
version: resolved.version
|
|
2823
|
-
}
|
|
2830
|
+
}, { cacheHints: {
|
|
2831
|
+
"server/discover": {
|
|
2832
|
+
ttlMs: DOCS_MCP_DISCOVERY_CACHE_TTL_MS,
|
|
2833
|
+
cacheScope
|
|
2834
|
+
},
|
|
2835
|
+
"tools/list": {
|
|
2836
|
+
ttlMs: DOCS_MCP_LIST_CACHE_TTL_MS,
|
|
2837
|
+
cacheScope
|
|
2838
|
+
},
|
|
2839
|
+
"prompts/list": {
|
|
2840
|
+
ttlMs: DOCS_MCP_LIST_CACHE_TTL_MS,
|
|
2841
|
+
cacheScope
|
|
2842
|
+
},
|
|
2843
|
+
"resources/list": {
|
|
2844
|
+
ttlMs: DOCS_MCP_LIST_CACHE_TTL_MS,
|
|
2845
|
+
cacheScope
|
|
2846
|
+
},
|
|
2847
|
+
"resources/templates/list": {
|
|
2848
|
+
ttlMs: DOCS_MCP_LIST_CACHE_TTL_MS,
|
|
2849
|
+
cacheScope
|
|
2850
|
+
},
|
|
2851
|
+
"resources/read": {
|
|
2852
|
+
ttlMs: DOCS_MCP_RESOURCE_CACHE_TTL_MS,
|
|
2853
|
+
cacheScope
|
|
2854
|
+
}
|
|
2855
|
+
} });
|
|
2824
2856
|
installDocsMcpSdkRegistrationPagination(server, protocolScope);
|
|
2825
2857
|
if (contentChangesEnabled) server.server.registerCapabilities({ resources: { subscribe: true } });
|
|
2826
2858
|
const registerResource = (name, uri, metadata, callback) => {
|
|
@@ -4511,22 +4543,35 @@ function createDocsMcpHttpHandler(options) {
|
|
|
4511
4543
|
});
|
|
4512
4544
|
const configuredPollInterval = options.contentChangePollIntervalMs;
|
|
4513
4545
|
const contentChangePollIntervalMs = typeof configuredPollInterval === "number" && Number.isFinite(configuredPollInterval) && configuredPollInterval >= 10 ? Math.floor(configuredPollInterval) : DEFAULT_DOCS_MCP_CONTENT_CHANGE_POLL_INTERVAL_MS;
|
|
4514
|
-
async function
|
|
4546
|
+
async function readMonitoredState(context) {
|
|
4515
4547
|
const locale = options.source.resolveLocale?.(void 0, context);
|
|
4516
4548
|
const pages = dedupePages(await options.source.getPages(locale, context));
|
|
4517
|
-
|
|
4549
|
+
const result = await contentChangeFeed.resolve({
|
|
4518
4550
|
pages: toSearchSourcePages(pages),
|
|
4519
4551
|
search: options.search,
|
|
4520
4552
|
audience: "agent",
|
|
4521
4553
|
locale,
|
|
4522
4554
|
baseUrl: options.source.baseUrl ?? (context.request ? new URL(context.request.url).origin : void 0),
|
|
4523
4555
|
...context.request ? { request: context.request.clone() } : {}
|
|
4524
|
-
})
|
|
4556
|
+
});
|
|
4557
|
+
return {
|
|
4558
|
+
indexGeneration: result.indexGeneration,
|
|
4559
|
+
resourceUris: [
|
|
4560
|
+
"docs://navigation",
|
|
4561
|
+
DOCS_MCP_CONTENT_CHANGES_CURRENT_URI,
|
|
4562
|
+
`docs://changes/${result.indexGeneration}`,
|
|
4563
|
+
...pages.map((page) => toPageResourceUri(page.url))
|
|
4564
|
+
]
|
|
4565
|
+
};
|
|
4525
4566
|
}
|
|
4526
4567
|
const contentChangeMonitor = createDocsMcpContentChangeMonitor({
|
|
4527
4568
|
pollIntervalMs: contentChangePollIntervalMs,
|
|
4528
|
-
|
|
4529
|
-
notify: () =>
|
|
4569
|
+
readState: readMonitoredState,
|
|
4570
|
+
notify: ({ previous, current }) => {
|
|
4571
|
+
mcpHandler.notify.resourcesChanged();
|
|
4572
|
+
const affectedUris = new Set([...previous.resourceUris, ...current.resourceUris]);
|
|
4573
|
+
for (const uri of affectedUris) mcpHandler.notify.resourceUpdated(uri);
|
|
4574
|
+
},
|
|
4530
4575
|
isActive: () => eventBus.listenerCount > 0,
|
|
4531
4576
|
unrefTimer: true
|
|
4532
4577
|
});
|
|
@@ -4659,21 +4704,34 @@ async function runDocsMcpStdio(options) {
|
|
|
4659
4704
|
requestContext
|
|
4660
4705
|
});
|
|
4661
4706
|
if (!contentChangesEnabled) return server;
|
|
4662
|
-
const
|
|
4707
|
+
const readState = async () => {
|
|
4663
4708
|
const locale = options.source.resolveLocale?.(void 0, requestContext);
|
|
4664
4709
|
const pages = dedupePages(await options.source.getPages(locale, requestContext));
|
|
4665
|
-
|
|
4710
|
+
const result = await contentChangeFeed.resolve({
|
|
4666
4711
|
pages: toSearchSourcePages(pages),
|
|
4667
4712
|
search: options.search,
|
|
4668
4713
|
audience: "agent",
|
|
4669
4714
|
locale,
|
|
4670
4715
|
baseUrl: options.source.baseUrl
|
|
4671
|
-
})
|
|
4716
|
+
});
|
|
4717
|
+
return {
|
|
4718
|
+
indexGeneration: result.indexGeneration,
|
|
4719
|
+
resourceUris: [
|
|
4720
|
+
"docs://navigation",
|
|
4721
|
+
DOCS_MCP_CONTENT_CHANGES_CURRENT_URI,
|
|
4722
|
+
`docs://changes/${result.indexGeneration}`,
|
|
4723
|
+
...pages.map((page) => toPageResourceUri(page.url))
|
|
4724
|
+
]
|
|
4725
|
+
};
|
|
4672
4726
|
};
|
|
4673
4727
|
const monitor = createDocsMcpContentChangeMonitor({
|
|
4674
4728
|
pollIntervalMs,
|
|
4675
|
-
|
|
4676
|
-
notify:
|
|
4729
|
+
readState: () => readState(),
|
|
4730
|
+
notify: async ({ previous, current }) => {
|
|
4731
|
+
await server.server.sendResourceListChanged();
|
|
4732
|
+
const affectedUris = new Set([...previous.resourceUris, ...current.resourceUris]);
|
|
4733
|
+
for (const uri of affectedUris) await server.server.sendResourceUpdated({ uri });
|
|
4734
|
+
}
|
|
4677
4735
|
});
|
|
4678
4736
|
await monitor.start(requestContext);
|
|
4679
4737
|
const closeServer = server.close.bind(server);
|
|
@@ -7,9 +7,9 @@ import "./agent-skills-server-CwmzAzf_.mjs";
|
|
|
7
7
|
import { c as resolveDocsReviewConfig, o as ensureDocsReviewWorkflow, s as readDocsReviewConfigFromSource, t as runDocsGoldenTasks } from "./agent-evals-DCptRrdP.mjs";
|
|
8
8
|
import { createFilesystemDocsMcpSource, getDocsConfigSchema, resolveDocsMcpConfig } from "./mcp.mjs";
|
|
9
9
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
10
|
-
import { _ as resolveDocsContentDir, g as resolveDocsConfigPath, h as readTopLevelStringProperty, s as loadDocsConfigModuleResultWithProjectEnv } from "./config-
|
|
10
|
+
import { _ as resolveDocsContentDir, g as resolveDocsConfigPath, h as readTopLevelStringProperty, s as loadDocsConfigModuleResultWithProjectEnv } from "./config-BtxaQTPP.mjs";
|
|
11
11
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
12
|
-
import { a as extractAgentBlocks, i as createAgentUsefulnessPagesFromMcp, n as analyzeAgentSurfaceDrift, r as analyzeAgentUsefulness, t as resolveGoldenEvaluationInput } from "./golden-evaluations-
|
|
12
|
+
import { a as extractAgentBlocks, i as createAgentUsefulnessPagesFromMcp, n as analyzeAgentSurfaceDrift, r as analyzeAgentUsefulness, t as resolveGoldenEvaluationInput } from "./golden-evaluations-DyeYD50F.mjs";
|
|
13
13
|
import { t as analyzeConfiguredAgentSkillsProgressiveDisclosure } from "./agent-skills-progressive-disclosure-BVvj7nM8.mjs";
|
|
14
14
|
import matter from "gray-matter";
|
|
15
15
|
import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
|
|
@@ -2,7 +2,7 @@ import "./agent-CTOUI2BK.mjs";
|
|
|
2
2
|
import "./markdown-sections-7OoA7ylx.mjs";
|
|
3
3
|
import "./standards-discovery-Ckx0tN7B.mjs";
|
|
4
4
|
import { c as renderDocsRobotsGeneratedBlock, f as upsertDocsRobotsGeneratedBlock, i as DOCS_ROBOTS_GENERATED_BLOCK_START, r as DOCS_ROBOTS_GENERATED_BLOCK_END, u as resolveDocsRobotsConfig } from "./robots-DaU38DZw.mjs";
|
|
5
|
-
import { a as loadDocsConfigModule, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, m as readTopLevelBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
5
|
+
import { a as loadDocsConfigModule, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, m as readTopLevelBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
6
6
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
8
|
import path from "node:path";
|
|
@@ -10,7 +10,7 @@ import "./agent-evals-DCptRrdP.mjs";
|
|
|
10
10
|
import { createFilesystemDocsMcpSource } from "./mcp.mjs";
|
|
11
11
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
12
12
|
import "./server.mjs";
|
|
13
|
-
import { _ as resolveDocsContentDir, c as loadProjectEnv, g as resolveDocsConfigPath, h as readTopLevelStringProperty, s as loadDocsConfigModuleResultWithProjectEnv } from "./config-
|
|
13
|
+
import { _ as resolveDocsContentDir, c as loadProjectEnv, g as resolveDocsConfigPath, h as readTopLevelStringProperty, s as loadDocsConfigModuleResultWithProjectEnv } from "./config-BtxaQTPP.mjs";
|
|
14
14
|
import { readFileSync } from "node:fs";
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
import pc from "picocolors";
|
|
@@ -8,7 +8,7 @@ import "./agent-evals-DCptRrdP.mjs";
|
|
|
8
8
|
import { createFilesystemDocsMcpSource } from "./mcp.mjs";
|
|
9
9
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
10
10
|
import "./server.mjs";
|
|
11
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
11
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
12
12
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
13
13
|
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
14
14
|
import path from "node:path";
|
|
@@ -9,7 +9,7 @@ import "./agent-evals-DCptRrdP.mjs";
|
|
|
9
9
|
import { createFilesystemDocsMcpSource } from "./mcp.mjs";
|
|
10
10
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
11
11
|
import "./server.mjs";
|
|
12
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
12
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
13
13
|
import { n as estimateAgentSkillInstructionTokens, r as resolveDocsAgentSkillsProgressiveDisclosureConfig } from "./agent-skills-progressive-disclosure-BVvj7nM8.mjs";
|
|
14
14
|
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
15
15
|
import path from "node:path";
|