@farming-labs/docs 0.2.52 → 0.2.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/agent-BXvi0uhS.mjs +623 -0
  2. package/dist/{agent-CaOBIVFy.mjs → agent-DXkXi-pS.mjs} +765 -22
  3. package/dist/agent-evals-BD17jOqL.mjs +1166 -0
  4. package/dist/agent-export-n-a0GbeU.mjs +854 -0
  5. package/dist/agent-scope-B8lptqCd.mjs +283 -0
  6. package/dist/agent-surface-drift-LS8zQgbq.mjs +1429 -0
  7. package/dist/{agents-DjhjZaNP.mjs → agents-BJaRQimo.mjs} +7 -5
  8. package/dist/{analytics-BZEwTK-8.mjs → analytics-Bx44lg6d.mjs} +1 -1
  9. package/dist/cli/index.mjs +43 -28
  10. package/dist/client/react.d.mts +1 -1
  11. package/dist/client/react.mjs +1 -1
  12. package/dist/{cloud-C_Ok9rC5.mjs → cloud-HWFlbfLJ.mjs} +4 -4
  13. package/dist/{cloud-ask-ai-Cl-xaV8j.mjs → cloud-ask-ai-1k0q6OAH.mjs} +1 -1
  14. package/dist/{cloud-ask-ai-DcMe6xOf.d.mts → cloud-ask-ai-466g6uAi.d.mts} +1 -1
  15. package/dist/code-blocks-C9awWzEQ.mjs +871 -0
  16. package/dist/codeblocks-BzfkREEC.mjs +250 -0
  17. package/dist/{config-tiQCZ46q.mjs → config-CydaZ5PB.mjs} +52 -11
  18. package/dist/{dev-Tm9Ss4D6.mjs → dev-BA2kRuCn.mjs} +3 -3
  19. package/dist/docs-cloud-server.d.mts +2 -2
  20. package/dist/docs-cloud-server.mjs +2 -2
  21. package/dist/{doctor-O9o9kjN8.mjs → doctor-CQpQ2zZm.mjs} +177 -47
  22. package/dist/{downgrade-CYEaOctn.mjs → downgrade-BStNhyCc.mjs} +2 -2
  23. package/dist/i18n-CAlj1ADU.mjs +40 -0
  24. package/dist/index.d.mts +158 -3
  25. package/dist/index.mjs +7 -6
  26. package/dist/{init-Ch5On0zm.mjs → init-gnHQ_Pz9.mjs} +3 -3
  27. package/dist/{mcp-DuCPNHS-.mjs → mcp-DnxZZWpY.mjs} +10 -5
  28. package/dist/mcp.d.mts +122 -6
  29. package/dist/mcp.mjs +1943 -86
  30. package/dist/{package-version-C8PigBZk.mjs → package-version-DRIc08EU.mjs} +1 -1
  31. package/dist/{reading-time-CPAy1SWO.mjs → reading-time-BrTd3DIh.mjs} +277 -33
  32. package/dist/{review-lm3dt7yy.mjs → review-B6gyEFkD.mjs} +184 -14
  33. package/dist/{robots-DV7u4Ire.mjs → robots-4BUJxlvV.mjs} +4 -4
  34. package/dist/{robots-XVPs9lVz.mjs → robots-DAptQnkx.mjs} +1 -1
  35. package/dist/{search-BWuU70B0.mjs → search-CJIC1Cqo.mjs} +173 -79
  36. package/dist/{search-B6nEkx86.mjs → search-CbPm2x5g.mjs} +6 -4
  37. package/dist/{search-DFEhf9-s.d.mts → search-CfWvmVYA.d.mts} +3 -1
  38. package/dist/server.d.mts +108 -5
  39. package/dist/server.mjs +9 -8
  40. package/dist/{sitemap-BEiKy4Iy.mjs → sitemap-D6nP3J1Q.mjs} +8 -6
  41. package/dist/{sitemap-server-xEHtDUDB.mjs → sitemap-server-wsNLyVkb.mjs} +1 -1
  42. package/dist/{templates-uaauJcTO.mjs → templates-1Cod8KrJ.mjs} +11 -5
  43. package/dist/{types-XqGLsmOD.d.mts → types-BVgucdVm.d.mts} +194 -2
  44. package/dist/{upgrade-DzQtpgJM.mjs → upgrade-CXYRNV0C.mjs} +2 -2
  45. package/package.json +1 -1
  46. package/dist/agent-DXDOMJBw.mjs +0 -9
  47. package/dist/codeblocks-z9iT794h.mjs +0 -1713
  48. package/dist/review-B7goPYUb.mjs +0 -541
  49. /package/dist/{cloud-analytics-Dlk_byos.mjs → cloud-analytics-CSyFE6SS.mjs} +0 -0
  50. /package/dist/{errors-CW1LnxaQ.mjs → errors-BFUtdZfC.mjs} +0 -0
  51. /package/dist/{utils-D-xTRNuh.mjs → utils-DBCCkkJS.mjs} +0 -0
@@ -1,3 +1,592 @@
1
+ //#region src/agent-contract.ts
2
+ const PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS = [
3
+ "task",
4
+ "outcome",
5
+ "appliesTo",
6
+ "prerequisites",
7
+ "files",
8
+ "commands",
9
+ "sideEffects",
10
+ "verification",
11
+ "rollback",
12
+ "failureModes"
13
+ ];
14
+ const PAGE_AGENT_CONTRACT_FIELDS = ["tokenBudget", ...PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS];
15
+ const PAGE_AGENT_CONTRACT_FIELD_SCHEMA = {
16
+ tokenBudget: "number",
17
+ task: "string",
18
+ outcome: "string",
19
+ appliesTo: {
20
+ framework: "string|string[]",
21
+ version: "string|string[]",
22
+ package: "string|string[]"
23
+ },
24
+ prerequisites: "string[]",
25
+ files: "string[]",
26
+ commands: "Array<string|{run,cwd?,description?}>",
27
+ sideEffects: "string[]",
28
+ verification: "Array<string|{description?,run?,expect?}>",
29
+ rollback: "string[]",
30
+ failureModes: "Array<string|{symptom,resolution?}>"
31
+ };
32
+ const APPLIES_TO_FIELDS = [
33
+ "framework",
34
+ "version",
35
+ "package"
36
+ ];
37
+ const COMMAND_FIELDS = [
38
+ "run",
39
+ "cwd",
40
+ "description"
41
+ ];
42
+ const VERIFICATION_FIELDS = [
43
+ "description",
44
+ "run",
45
+ "expect"
46
+ ];
47
+ const FAILURE_MODE_FIELDS = ["symptom", "resolution"];
48
+ const PAGE_AGENT_CONTRACT_START_MARKER = "<!-- farming-labs:agent-contract:start -->";
49
+ const PAGE_AGENT_CONTRACT_END_MARKER = "<!-- farming-labs:agent-contract:end -->";
50
+ function isRecord(value) {
51
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
52
+ }
53
+ function normalizeString(value) {
54
+ if (typeof value !== "string") return void 0;
55
+ return value.trim() || void 0;
56
+ }
57
+ function normalizeStringList(value) {
58
+ if (!Array.isArray(value)) return void 0;
59
+ const seen = /* @__PURE__ */ new Set();
60
+ const normalized = [];
61
+ for (const item of value) {
62
+ const text = normalizeString(item);
63
+ if (!text || seen.has(text)) continue;
64
+ seen.add(text);
65
+ normalized.push(text);
66
+ }
67
+ return normalized.length > 0 ? normalized : void 0;
68
+ }
69
+ function normalizeStringOrList(value) {
70
+ const single = normalizeString(value);
71
+ if (single) return [single];
72
+ return normalizeStringList(value);
73
+ }
74
+ function normalizeAppliesTo(value) {
75
+ if (!isRecord(value)) return void 0;
76
+ const framework = normalizeStringOrList(value.framework);
77
+ const version = normalizeStringOrList(value.version);
78
+ const packageNames = normalizeStringOrList(value.package);
79
+ if (!framework && !version && !packageNames) return void 0;
80
+ return {
81
+ ...framework ? { framework } : {},
82
+ ...version ? { version } : {},
83
+ ...packageNames ? { package: packageNames } : {}
84
+ };
85
+ }
86
+ function normalizeCommands(value) {
87
+ if (!Array.isArray(value)) return void 0;
88
+ const commands = [];
89
+ for (const item of value) {
90
+ const shorthand = normalizeString(item);
91
+ if (shorthand) {
92
+ commands.push(shorthand);
93
+ continue;
94
+ }
95
+ if (!isRecord(item)) continue;
96
+ const run = normalizeString(item.run);
97
+ if (!run) continue;
98
+ const cwd = normalizeString(item.cwd);
99
+ const description = normalizeString(item.description);
100
+ commands.push({
101
+ run,
102
+ ...cwd ? { cwd } : {},
103
+ ...description ? { description } : {}
104
+ });
105
+ }
106
+ return commands.length > 0 ? commands : void 0;
107
+ }
108
+ function normalizeVerification(value) {
109
+ if (!Array.isArray(value)) return void 0;
110
+ const verification = [];
111
+ for (const item of value) {
112
+ const shorthand = normalizeString(item);
113
+ if (shorthand) {
114
+ verification.push(shorthand);
115
+ continue;
116
+ }
117
+ if (!isRecord(item)) continue;
118
+ const description = normalizeString(item.description);
119
+ const run = normalizeString(item.run);
120
+ const expect = normalizeString(item.expect);
121
+ if (!description && !run && !expect) continue;
122
+ verification.push({
123
+ ...description ? { description } : {},
124
+ ...run ? { run } : {},
125
+ ...expect ? { expect } : {}
126
+ });
127
+ }
128
+ return verification.length > 0 ? verification : void 0;
129
+ }
130
+ function normalizeFailureModes(value) {
131
+ if (!Array.isArray(value)) return void 0;
132
+ const failureModes = [];
133
+ for (const item of value) {
134
+ const shorthand = normalizeString(item);
135
+ if (shorthand) {
136
+ failureModes.push(shorthand);
137
+ continue;
138
+ }
139
+ if (!isRecord(item)) continue;
140
+ const symptom = normalizeString(item.symptom);
141
+ if (!symptom) continue;
142
+ const resolution = normalizeString(item.resolution);
143
+ failureModes.push({
144
+ symptom,
145
+ ...resolution ? { resolution } : {}
146
+ });
147
+ }
148
+ return failureModes.length > 0 ? failureModes : void 0;
149
+ }
150
+ function normalizeTokenBudget(value) {
151
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return void 0;
152
+ return Math.ceil(value);
153
+ }
154
+ /**
155
+ * Normalize untrusted page frontmatter into the stable agent contract shape.
156
+ * Invalid fields are omitted so malformed author input cannot break page delivery.
157
+ */
158
+ function normalizePageAgentFrontmatter(value) {
159
+ if (!isRecord(value)) return void 0;
160
+ const tokenBudget = normalizeTokenBudget(value.tokenBudget);
161
+ const task = normalizeString(value.task);
162
+ const outcome = normalizeString(value.outcome);
163
+ const appliesTo = normalizeAppliesTo(value.appliesTo);
164
+ const prerequisites = normalizeStringList(value.prerequisites);
165
+ const files = normalizeStringList(value.files);
166
+ const commands = normalizeCommands(value.commands);
167
+ const sideEffects = normalizeStringList(value.sideEffects);
168
+ const verification = normalizeVerification(value.verification);
169
+ const rollback = normalizeStringList(value.rollback);
170
+ const failureModes = normalizeFailureModes(value.failureModes);
171
+ const normalized = {
172
+ ...tokenBudget !== void 0 ? { tokenBudget } : {},
173
+ ...task ? { task } : {},
174
+ ...outcome ? { outcome } : {},
175
+ ...appliesTo ? { appliesTo } : {},
176
+ ...prerequisites ? { prerequisites } : {},
177
+ ...files ? { files } : {},
178
+ ...commands ? { commands } : {},
179
+ ...sideEffects ? { sideEffects } : {},
180
+ ...verification ? { verification } : {},
181
+ ...rollback ? { rollback } : {},
182
+ ...failureModes ? { failureModes } : {}
183
+ };
184
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
185
+ }
186
+ function hasStructuredPageAgentContract(value) {
187
+ const normalized = normalizePageAgentFrontmatter(value);
188
+ if (!normalized) return false;
189
+ return PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS.some((field) => normalized[field] !== void 0);
190
+ }
191
+ function addStringIssue(issues, object, field) {
192
+ if (!(field in object)) return;
193
+ if (!normalizeString(object[field])) issues.push({
194
+ path: `agent.${field}`,
195
+ message: "must be a non-empty string"
196
+ });
197
+ }
198
+ function addStringListIssues(issues, object, field) {
199
+ if (!(field in object)) return;
200
+ const value = object[field];
201
+ if (!Array.isArray(value) || value.length === 0) {
202
+ issues.push({
203
+ path: `agent.${field}`,
204
+ message: "must be a non-empty string array"
205
+ });
206
+ return;
207
+ }
208
+ value.forEach((item, index) => {
209
+ if (!normalizeString(item)) issues.push({
210
+ path: `agent.${field}[${index}]`,
211
+ message: "must be a non-empty string"
212
+ });
213
+ });
214
+ }
215
+ function editDistance(left, right) {
216
+ const previous = Array.from({ length: right.length + 1 }, (_, index) => index);
217
+ for (let leftIndex = 1; leftIndex <= left.length; leftIndex += 1) {
218
+ const current = [leftIndex];
219
+ for (let rightIndex = 1; rightIndex <= right.length; rightIndex += 1) current[rightIndex] = Math.min((current[rightIndex - 1] ?? 0) + 1, (previous[rightIndex] ?? 0) + 1, (previous[rightIndex - 1] ?? 0) + (left[leftIndex - 1] === right[rightIndex - 1] ? 0 : 1));
220
+ previous.splice(0, previous.length, ...current);
221
+ }
222
+ return previous[right.length] ?? 0;
223
+ }
224
+ function closestKnownField(field, allowed) {
225
+ const closest = allowed.map((candidate) => ({
226
+ candidate,
227
+ distance: editDistance(field, candidate)
228
+ })).sort((left, right) => left.distance - right.distance || left.candidate.localeCompare(right.candidate))[0];
229
+ if (!closest) return void 0;
230
+ const threshold = Math.max(1, Math.min(3, Math.floor(closest.candidate.length / 3)));
231
+ return closest.distance <= threshold ? closest.candidate : void 0;
232
+ }
233
+ function addUnknownKeyIssues(issues, object, allowed, path) {
234
+ for (const field of Object.keys(object)) {
235
+ if (allowed.includes(field)) continue;
236
+ const suggestion = closestKnownField(field, allowed);
237
+ issues.push({
238
+ path: `${path}.${field}`,
239
+ message: suggestion ? `is not recognized; did you mean "${path}.${suggestion}"?` : "is not recognized"
240
+ });
241
+ }
242
+ }
243
+ /** Return author-facing validation issues without throwing. */
244
+ function getPageAgentFrontmatterIssues(value) {
245
+ if (value === void 0) return [];
246
+ if (!isRecord(value)) return [{
247
+ path: "agent",
248
+ message: "must be an object"
249
+ }];
250
+ const issues = [];
251
+ addUnknownKeyIssues(issues, value, PAGE_AGENT_CONTRACT_FIELDS, "agent");
252
+ if ("tokenBudget" in value && (typeof value.tokenBudget !== "number" || !Number.isFinite(value.tokenBudget) || value.tokenBudget <= 0)) issues.push({
253
+ path: "agent.tokenBudget",
254
+ message: "must be a positive finite number"
255
+ });
256
+ addStringIssue(issues, value, "task");
257
+ addStringIssue(issues, value, "outcome");
258
+ if ("appliesTo" in value) if (!isRecord(value.appliesTo)) issues.push({
259
+ path: "agent.appliesTo",
260
+ message: "must be an object"
261
+ });
262
+ else {
263
+ addUnknownKeyIssues(issues, value.appliesTo, APPLIES_TO_FIELDS, "agent.appliesTo");
264
+ for (const field of [
265
+ "framework",
266
+ "version",
267
+ "package"
268
+ ]) {
269
+ if (!(field in value.appliesTo)) continue;
270
+ const fieldValue = value.appliesTo[field];
271
+ if (!normalizeStringOrList(fieldValue)) {
272
+ issues.push({
273
+ path: `agent.appliesTo.${field}`,
274
+ message: "must be a non-empty string or string array"
275
+ });
276
+ continue;
277
+ }
278
+ if (Array.isArray(fieldValue)) fieldValue.forEach((item, index) => {
279
+ if (!normalizeString(item)) issues.push({
280
+ path: `agent.appliesTo.${field}[${index}]`,
281
+ message: "must be a non-empty string"
282
+ });
283
+ });
284
+ }
285
+ if (!normalizeAppliesTo(value.appliesTo)) issues.push({
286
+ path: "agent.appliesTo",
287
+ message: "must include framework, version, or package"
288
+ });
289
+ }
290
+ for (const field of [
291
+ "prerequisites",
292
+ "files",
293
+ "sideEffects",
294
+ "rollback"
295
+ ]) addStringListIssues(issues, value, field);
296
+ if ("commands" in value) if (!Array.isArray(value.commands) || value.commands.length === 0) issues.push({
297
+ path: "agent.commands",
298
+ message: "must be a non-empty array"
299
+ });
300
+ else value.commands.forEach((command, index) => {
301
+ if (normalizeString(command)) return;
302
+ if (!isRecord(command)) {
303
+ issues.push({
304
+ path: `agent.commands[${index}]`,
305
+ message: "must be a command string or an object with a non-empty run field"
306
+ });
307
+ return;
308
+ }
309
+ addUnknownKeyIssues(issues, command, COMMAND_FIELDS, `agent.commands[${index}]`);
310
+ if (!normalizeString(command.run)) {
311
+ issues.push({
312
+ path: `agent.commands[${index}]`,
313
+ message: "must be a command string or an object with a non-empty run field"
314
+ });
315
+ return;
316
+ }
317
+ for (const field of ["cwd", "description"]) if (field in command && !normalizeString(command[field])) issues.push({
318
+ path: `agent.commands[${index}].${field}`,
319
+ message: "must be a non-empty string"
320
+ });
321
+ });
322
+ if ("verification" in value) if (!Array.isArray(value.verification) || value.verification.length === 0) issues.push({
323
+ path: "agent.verification",
324
+ message: "must be a non-empty array"
325
+ });
326
+ else value.verification.forEach((step, index) => {
327
+ if (normalizeString(step)) return;
328
+ if (!isRecord(step)) {
329
+ issues.push({
330
+ path: `agent.verification[${index}]`,
331
+ message: "must be a string or an object with description, run, or expect"
332
+ });
333
+ return;
334
+ }
335
+ addUnknownKeyIssues(issues, step, VERIFICATION_FIELDS, `agent.verification[${index}]`);
336
+ if (!normalizeVerification([step])) {
337
+ issues.push({
338
+ path: `agent.verification[${index}]`,
339
+ message: "must be a string or an object with description, run, or expect"
340
+ });
341
+ return;
342
+ }
343
+ for (const field of [
344
+ "description",
345
+ "run",
346
+ "expect"
347
+ ]) if (field in step && !normalizeString(step[field])) issues.push({
348
+ path: `agent.verification[${index}].${field}`,
349
+ message: "must be a non-empty string"
350
+ });
351
+ });
352
+ if ("failureModes" in value) if (!Array.isArray(value.failureModes) || value.failureModes.length === 0) issues.push({
353
+ path: "agent.failureModes",
354
+ message: "must be a non-empty array"
355
+ });
356
+ else value.failureModes.forEach((mode, index) => {
357
+ if (normalizeString(mode)) return;
358
+ if (!isRecord(mode)) {
359
+ issues.push({
360
+ path: `agent.failureModes[${index}]`,
361
+ message: "must be a string or an object with a non-empty symptom field"
362
+ });
363
+ return;
364
+ }
365
+ addUnknownKeyIssues(issues, mode, FAILURE_MODE_FIELDS, `agent.failureModes[${index}]`);
366
+ if (!normalizeString(mode.symptom)) {
367
+ issues.push({
368
+ path: `agent.failureModes[${index}]`,
369
+ message: "must be a string or an object with a non-empty symptom field"
370
+ });
371
+ return;
372
+ }
373
+ if ("resolution" in mode && !normalizeString(mode.resolution)) issues.push({
374
+ path: `agent.failureModes[${index}].resolution`,
375
+ message: "must be a non-empty string"
376
+ });
377
+ });
378
+ return issues;
379
+ }
380
+ function yamlString(value) {
381
+ return JSON.stringify(value);
382
+ }
383
+ function renderYamlStringList(lines, indent, key, values) {
384
+ lines.push(`${indent}${key}:`);
385
+ for (const value of values) lines.push(`${indent} - ${yamlString(value)}`);
386
+ }
387
+ function renderYamlObjectList(lines, indent, key, values, fields) {
388
+ lines.push(`${indent}${key}:`);
389
+ for (const value of values) {
390
+ if (typeof value === "string") {
391
+ lines.push(`${indent} - ${yamlString(value)}`);
392
+ continue;
393
+ }
394
+ const record = value;
395
+ const firstField = fields.find((field) => normalizeString(record[field]));
396
+ if (!firstField) continue;
397
+ lines.push(`${indent} - ${firstField}: ${yamlString(normalizeString(record[firstField]))}`);
398
+ for (const field of fields) {
399
+ const fieldValue = normalizeString(record[field]);
400
+ if (field === firstField || !fieldValue) continue;
401
+ lines.push(`${indent} ${field}: ${yamlString(fieldValue)}`);
402
+ }
403
+ }
404
+ }
405
+ /** Render normalized `agent` YAML in a stable field order. */
406
+ function renderPageAgentFrontmatterYamlLines(value, indentation = 0) {
407
+ const agent = normalizePageAgentFrontmatter(value);
408
+ if (!agent) return [];
409
+ const indent = " ".repeat(Math.max(0, indentation));
410
+ const child = `${indent} `;
411
+ const lines = [`${indent}agent:`];
412
+ if (agent.tokenBudget !== void 0) lines.push(`${child}tokenBudget: ${agent.tokenBudget}`);
413
+ if (agent.task) lines.push(`${child}task: ${yamlString(agent.task)}`);
414
+ if (agent.outcome) lines.push(`${child}outcome: ${yamlString(agent.outcome)}`);
415
+ if (agent.appliesTo) {
416
+ lines.push(`${child}appliesTo:`);
417
+ const appliesIndent = `${child} `;
418
+ for (const field of [
419
+ "framework",
420
+ "version",
421
+ "package"
422
+ ]) {
423
+ const values = normalizeStringOrList(agent.appliesTo[field]);
424
+ if (values) renderYamlStringList(lines, appliesIndent, field, values);
425
+ }
426
+ }
427
+ if (agent.prerequisites) renderYamlStringList(lines, child, "prerequisites", agent.prerequisites);
428
+ if (agent.files) renderYamlStringList(lines, child, "files", agent.files);
429
+ if (agent.commands) renderYamlObjectList(lines, child, "commands", agent.commands, [
430
+ "run",
431
+ "cwd",
432
+ "description"
433
+ ]);
434
+ if (agent.sideEffects) renderYamlStringList(lines, child, "sideEffects", agent.sideEffects);
435
+ if (agent.verification) renderYamlObjectList(lines, child, "verification", agent.verification, [
436
+ "description",
437
+ "run",
438
+ "expect"
439
+ ]);
440
+ if (agent.rollback) renderYamlStringList(lines, child, "rollback", agent.rollback);
441
+ if (agent.failureModes) renderYamlObjectList(lines, child, "failureModes", agent.failureModes, ["symptom", "resolution"]);
442
+ return lines;
443
+ }
444
+ function inlineCode(value) {
445
+ const longestRun = Math.max(0, ...[...value.matchAll(/`+/g)].map((match) => match[0].length));
446
+ const fence = "`".repeat(longestRun + 1);
447
+ const padding = value.startsWith("`") || value.endsWith("`") ? " " : "";
448
+ return `${fence}${padding}${value}${padding}${fence}`;
449
+ }
450
+ function renderTextList(lines, title, values, code = false) {
451
+ lines.push("", `### ${title}`, "");
452
+ for (const value of values) lines.push(`- ${code ? inlineCode(value) : value}`);
453
+ }
454
+ /** Render the structured contract as deterministic, compact machine-readable Markdown. */
455
+ function renderPageAgentContractMarkdown(value) {
456
+ const agent = normalizePageAgentFrontmatter(value);
457
+ if (!agent || !hasStructuredPageAgentContract(agent)) return "";
458
+ const lines = [PAGE_AGENT_CONTRACT_START_MARKER, "## Agent Contract"];
459
+ if (agent.task) lines.push("", `Task: ${agent.task}`);
460
+ if (agent.outcome) lines.push(`Outcome: ${agent.outcome}`);
461
+ if (agent.appliesTo) {
462
+ lines.push("", "### Applies To", "");
463
+ for (const [label, field] of [
464
+ ["Framework", "framework"],
465
+ ["Version", "version"],
466
+ ["Package", "package"]
467
+ ]) {
468
+ const values = normalizeStringOrList(agent.appliesTo[field]);
469
+ if (values) lines.push(`- ${label}: ${values.map(inlineCode).join(", ")}`);
470
+ }
471
+ }
472
+ if (agent.prerequisites) renderTextList(lines, "Prerequisites", agent.prerequisites);
473
+ if (agent.files) renderTextList(lines, "Files", agent.files, true);
474
+ if (agent.commands) {
475
+ lines.push("", "### Commands", "");
476
+ for (const command of agent.commands) {
477
+ if (typeof command === "string") {
478
+ lines.push(`- ${inlineCode(command)}`);
479
+ continue;
480
+ }
481
+ const details = [command.cwd ? `cwd ${inlineCode(command.cwd)}` : void 0, command.description].filter(Boolean);
482
+ lines.push(`- ${inlineCode(command.run)}${details.length ? ` — ${details.join("; ")}` : ""}`);
483
+ }
484
+ }
485
+ if (agent.sideEffects) renderTextList(lines, "Side Effects", agent.sideEffects);
486
+ if (agent.verification) {
487
+ lines.push("", "### Verification", "");
488
+ for (const step of agent.verification) {
489
+ if (typeof step === "string") {
490
+ lines.push(`- ${step}`);
491
+ continue;
492
+ }
493
+ const summary = step.description ?? (step.run ? `Run ${inlineCode(step.run)}` : step.expect ?? "Verification step");
494
+ lines.push(`- ${summary}`);
495
+ if (step.run && step.description) lines.push(` - Run: ${inlineCode(step.run)}`);
496
+ if (step.expect && step.expect !== summary) lines.push(` - Expected: ${step.expect}`);
497
+ }
498
+ }
499
+ if (agent.rollback) renderTextList(lines, "Rollback", agent.rollback);
500
+ if (agent.failureModes) {
501
+ lines.push("", "### Failure Modes", "");
502
+ for (const mode of agent.failureModes) {
503
+ if (typeof mode === "string") {
504
+ lines.push(`- ${mode}`);
505
+ continue;
506
+ }
507
+ lines.push(`- ${mode.symptom}${mode.resolution ? ` — Recovery: ${mode.resolution}` : ""}`);
508
+ }
509
+ }
510
+ lines.push(PAGE_AGENT_CONTRACT_END_MARKER);
511
+ return lines.join("\n");
512
+ }
513
+ /** Remove generated contract blocks while preserving handwritten guidance. */
514
+ function stripGeneratedPageAgentContractMarkdown(markdown) {
515
+ const newline = markdown.includes("\r\n") ? "\r\n" : "\n";
516
+ const output = [];
517
+ let fence;
518
+ let pendingBlock;
519
+ let skipEmptySeparator = false;
520
+ for (const line of markdown.split(/\r?\n/)) {
521
+ if (pendingBlock) {
522
+ pendingBlock.push(line);
523
+ if (isGeneratedAgentContractMarker(line, PAGE_AGENT_CONTRACT_END_MARKER)) {
524
+ pendingBlock = void 0;
525
+ skipEmptySeparator = true;
526
+ }
527
+ continue;
528
+ }
529
+ if (!fence && isGeneratedAgentContractMarker(line, PAGE_AGENT_CONTRACT_START_MARKER)) {
530
+ pendingBlock = [line];
531
+ continue;
532
+ }
533
+ if (skipEmptySeparator && line.length === 0) continue;
534
+ skipEmptySeparator = false;
535
+ output.push(line);
536
+ fence = advanceMarkdownFence(line, fence);
537
+ }
538
+ if (pendingBlock) output.push(...pendingBlock);
539
+ while (output[0] === "") output.shift();
540
+ return output.join(newline);
541
+ }
542
+ function isGeneratedAgentContractMarker(line, marker) {
543
+ if (line.trim() !== marker) return false;
544
+ const markerIndex = line.indexOf(marker);
545
+ return markerIndex <= 3 && /^ *$/.test(line.slice(0, markerIndex));
546
+ }
547
+ function advanceMarkdownFence(line, fence) {
548
+ if (fence) {
549
+ const closing = /^ {0,3}(`+|~+)[\t ]*$/.exec(line)?.[1];
550
+ if (closing?.[0] === fence.character && closing.length >= fence.length) return;
551
+ return fence;
552
+ }
553
+ const opening = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
554
+ if (!opening?.[1]) return void 0;
555
+ if (opening[1][0] === "`" && opening[2]?.includes("`")) return void 0;
556
+ return {
557
+ character: opening[1][0],
558
+ length: opening[1].length
559
+ };
560
+ }
561
+ function isAgentContractHeadingText(value) {
562
+ return value.trim().toLowerCase() === "agent contract";
563
+ }
564
+ function hasPageAgentContractHeading(markdown) {
565
+ let fence;
566
+ let previousLine;
567
+ for (const line of markdown.split(/\r?\n/)) {
568
+ const nextFence = advanceMarkdownFence(line, fence);
569
+ if (fence || nextFence) {
570
+ fence = nextFence;
571
+ previousLine = void 0;
572
+ continue;
573
+ }
574
+ const atxText = /^ {0,3}#{1,6}(?:[\t ]+|$)(.*)$/.exec(line)?.[1]?.replace(/[\t ]+#+[\t ]*$/, "").trim();
575
+ if (atxText && isAgentContractHeadingText(atxText)) return true;
576
+ if (previousLine && /^ {0,3}(?:=+|-+)[\t ]*$/.test(line) && isAgentContractHeadingText(previousLine)) return true;
577
+ previousLine = line.trim().length > 0 && !/^ {4}/.test(line) && !/^ {0,3}\t/.test(line) ? line : void 0;
578
+ }
579
+ return false;
580
+ }
581
+ /** Insert one generated contract unless the document already has handwritten contract guidance. */
582
+ function upsertPageAgentContractMarkdown(markdown, value) {
583
+ const cleaned = stripGeneratedPageAgentContractMarkdown(markdown);
584
+ const contract = renderPageAgentContractMarkdown(value);
585
+ if (!contract || hasPageAgentContractHeading(cleaned)) return cleaned;
586
+ return cleaned ? `${contract}\n\n${cleaned.replace(/^\r?\n+/, "")}` : contract;
587
+ }
588
+
589
+ //#endregion
1
590
  //#region src/related.ts
2
591
  function normalizeDocsRelated(value) {
3
592
  if (!Array.isArray(value)) return [];
@@ -181,7 +770,7 @@ function buildDocsSitemapManifest(options) {
181
770
  pages.push({
182
771
  url,
183
772
  absoluteUrl: absolutizeUrl(baseUrl, url),
184
- markdownUrl: toDocsSitemapMarkdownUrl(url),
773
+ markdownUrl: page.markdownUrl ?? toDocsSitemapMarkdownUrl(url),
185
774
  title: page.title,
186
775
  description: page.description,
187
776
  sourcePath: page.sourcePath,
@@ -371,10 +960,13 @@ const DEFAULT_DOCS_DIAGNOSTICS_MCP_TOOLS = {
371
960
  listDocs: true,
372
961
  listPages: true,
373
962
  readPage: true,
963
+ listTasks: true,
964
+ readTask: true,
374
965
  searchDocs: true,
375
966
  getNavigation: true,
376
967
  getCodeExamples: true,
377
- getConfigSchema: true
968
+ getConfigSchema: true,
969
+ getContext: true
378
970
  };
379
971
  const DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER = "Signature-Agent";
380
972
  const DOCS_AI_AGENT_USER_AGENT_PATTERNS = [
@@ -927,10 +1519,13 @@ function resolveDocsDiagnosticsMcp(mcp) {
927
1519
  listDocs: tools.listDocs !== false,
928
1520
  listPages: tools.listPages !== false,
929
1521
  readPage: tools.readPage !== false,
1522
+ listTasks: tools.listTasks !== false,
1523
+ readTask: tools.readTask !== false,
930
1524
  searchDocs: tools.searchDocs !== false,
931
1525
  getNavigation: tools.getNavigation !== false,
932
1526
  getCodeExamples: tools.getCodeExamples !== false,
933
- getConfigSchema: tools.getConfigSchema !== false
1527
+ getConfigSchema: tools.getConfigSchema !== false,
1528
+ getContext: tools.getContext !== false
934
1529
  }
935
1530
  };
936
1531
  }
@@ -1262,7 +1857,7 @@ function resolveDocsLlmsTxtRequest(url, llms, basePath) {
1262
1857
  function renderLlmsTxtPageList(pages, baseUrl) {
1263
1858
  let content = "";
1264
1859
  for (const page of pages) {
1265
- content += `- [${page.title}](${baseUrl}${toDocsMarkdownUrl(page.url)})`;
1860
+ content += `- [${page.title}](${baseUrl}${page.markdownUrl ?? toDocsMarkdownUrl(page.url)})`;
1266
1861
  if (page.description) content += `: ${page.description}`;
1267
1862
  content += "\n";
1268
1863
  }
@@ -1498,7 +2093,7 @@ function resolveDocsMarkdownRequest(entry, url, request) {
1498
2093
  if (pathname === `${normalizedEntry}.md`) return { requestedPath: "" };
1499
2094
  const slugPrefix = `${normalizedEntry}/`;
1500
2095
  if (pathname.startsWith(slugPrefix) && pathname.endsWith(".md")) return { requestedPath: pathname.slice(slugPrefix.length, -3) };
1501
- if (acceptsMarkdown(request) || hasDocsMarkdownSignatureAgent(request) || detectDocsMarkdownAgentRequest(request).detected) {
2096
+ if (acceptsDocsMarkdown(request) || hasDocsMarkdownSignatureAgent(request) || detectDocsMarkdownAgentRequest(request).detected) {
1502
2097
  if (pathname === normalizedEntry) return { requestedPath: "" };
1503
2098
  if (pathname.startsWith(slugPrefix)) return { requestedPath: pathname.slice(slugPrefix.length) };
1504
2099
  }
@@ -1534,7 +2129,7 @@ function detectDocsMarkdownAgentRequest(request) {
1534
2129
  }
1535
2130
  function getDocsMarkdownVaryHeader(request) {
1536
2131
  const values = /* @__PURE__ */ new Set();
1537
- if (acceptsMarkdown(request)) values.add("Accept");
2132
+ if (acceptsDocsMarkdown(request)) values.add("Accept");
1538
2133
  if (hasDocsMarkdownSignatureAgent(request)) {
1539
2134
  values.add("Accept");
1540
2135
  values.add(DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER);
@@ -1680,7 +2275,7 @@ function resolveDocsMarkdownMetadataUrl(value, origin) {
1680
2275
  return value;
1681
2276
  }
1682
2277
  }
1683
- function renderDocsMarkdownFrontmatter({ title, description, canonicalUrl, markdownUrl, lastUpdated }) {
2278
+ function renderDocsMarkdownFrontmatter({ title, description, canonicalUrl, markdownUrl, lastUpdated, agent }) {
1684
2279
  return [
1685
2280
  "---",
1686
2281
  `title: ${toYamlString(title)}`,
@@ -1688,6 +2283,7 @@ function renderDocsMarkdownFrontmatter({ title, description, canonicalUrl, markd
1688
2283
  `canonical_url: ${toYamlString(canonicalUrl)}`,
1689
2284
  `markdown_url: ${toYamlString(markdownUrl)}`,
1690
2285
  ...lastUpdated ? [`last_updated: ${toYamlString(lastUpdated)}`] : [],
2286
+ ...renderPageAgentFrontmatterYamlLines(agent),
1691
2287
  "---"
1692
2288
  ].join("\n");
1693
2289
  }
@@ -1703,8 +2299,9 @@ function resolveDocsMarkdownPageMetadata(page, options) {
1703
2299
  title: page.title,
1704
2300
  description: page.description,
1705
2301
  canonicalUrl: resolveDocsMarkdownMetadataUrl(page.url, options?.origin),
1706
- markdownUrl: resolveDocsMarkdownMetadataUrl(toDocsMarkdownUrl(page.url), options?.origin),
1707
- lastUpdated: normalizeDocsMarkdownLastUpdated(page.lastmod ?? page.lastModified)
2302
+ markdownUrl: resolveDocsMarkdownMetadataUrl(page.markdownUrl ?? toDocsMarkdownUrl(page.url), options?.origin),
2303
+ lastUpdated: normalizeDocsMarkdownLastUpdated(page.lastmod ?? page.lastModified),
2304
+ agent: page.agent
1708
2305
  };
1709
2306
  }
1710
2307
  function renderDocsMarkdownNotFound({ entry = "docs", requestedPath, origin, pages, sitemap }) {
@@ -1750,6 +2347,121 @@ function renderDocsMarkdownNotFound({ entry = "docs", requestedPath, origin, pag
1750
2347
  markdownUrl: resolveDocsMarkdownMetadataUrl(requestedMarkdownRoute, origin)
1751
2348
  }), sitemap);
1752
2349
  }
2350
+ function hashDocsMarkdownRepresentation(value) {
2351
+ let hash = 2166136261;
2352
+ for (let index = 0; index < value.length; index += 1) {
2353
+ hash ^= value.charCodeAt(index);
2354
+ hash = Math.imul(hash, 16777619);
2355
+ }
2356
+ return (hash >>> 0).toString(16).padStart(8, "0");
2357
+ }
2358
+ function createDocsMarkdownEtag(document) {
2359
+ return `W/"${document.length.toString(16)}-${hashDocsMarkdownRepresentation(document)}"`;
2360
+ }
2361
+ function normalizeDocsMarkdownEtag(value) {
2362
+ return value.trim().replace(/^W\//i, "");
2363
+ }
2364
+ function requestMatchesDocsMarkdownEtag(request, etag) {
2365
+ const header = request.headers.get("if-none-match");
2366
+ if (!header) return false;
2367
+ if (header.trim() === "*") return true;
2368
+ const expected = normalizeDocsMarkdownEtag(etag);
2369
+ return header.split(",").some((candidate) => normalizeDocsMarkdownEtag(candidate) === expected);
2370
+ }
2371
+ function resolveDocsMarkdownHttpDate(value) {
2372
+ if (!value) return void 0;
2373
+ if (typeof value === "string" && !/(?:T|\s)\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?/.test(value.trim())) return;
2374
+ const date = value instanceof Date ? value : new Date(value);
2375
+ if (Number.isNaN(date.getTime())) return void 0;
2376
+ return date.toUTCString();
2377
+ }
2378
+ function extractDocsMarkdownLastModified(document) {
2379
+ const frontmatter = document.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1];
2380
+ if (!frontmatter) return void 0;
2381
+ const raw = frontmatter.match(/^last_updated:\s*(.+?)\s*$/m)?.[1]?.trim();
2382
+ if (!raw) return void 0;
2383
+ if (raw.startsWith("\"") && raw.endsWith("\"") || raw.startsWith("'") && raw.endsWith("'")) return raw.slice(1, -1);
2384
+ return raw;
2385
+ }
2386
+ function requestHasFreshDocsMarkdownDate(request, lastModified) {
2387
+ if (!lastModified || request.headers.has("if-none-match")) return false;
2388
+ const ifModifiedSince = request.headers.get("if-modified-since");
2389
+ if (!ifModifiedSince) return false;
2390
+ const resourceTime = Date.parse(lastModified);
2391
+ const requestTime = Date.parse(ifModifiedSince);
2392
+ return Number.isFinite(resourceTime) && Number.isFinite(requestTime) && Math.floor(resourceTime / 1e3) <= Math.floor(requestTime / 1e3);
2393
+ }
2394
+ function resolveDocsMarkdownContentLocation(canonicalUrl) {
2395
+ const url = new URL(canonicalUrl);
2396
+ url.pathname = toDocsMarkdownUrl(url.pathname);
2397
+ return url.toString();
2398
+ }
2399
+ /** Build one standards-aware Markdown response for every framework adapter. */
2400
+ function createDocsMarkdownResponse(options) {
2401
+ const { request, document, entry = "docs", requestedPath, origin = new URL(request.url).origin, pages, sitemap, locale } = options;
2402
+ const canonicalUrl = options.canonicalUrl ?? resolveDocsMarkdownCanonicalUrl({
2403
+ origin,
2404
+ entry,
2405
+ requestedPath,
2406
+ locale
2407
+ });
2408
+ const contentLocation = options.contentLocation ?? resolveDocsMarkdownContentLocation(canonicalUrl);
2409
+ const varyHeader = getDocsMarkdownVaryHeader(request);
2410
+ const sharedHeaders = {
2411
+ "Content-Location": contentLocation,
2412
+ Link: `<${canonicalUrl}>; rel="canonical"`,
2413
+ "X-Robots-Tag": "noindex",
2414
+ ...locale ? { "Content-Language": locale } : {},
2415
+ ...varyHeader ? { Vary: varyHeader } : {}
2416
+ };
2417
+ if (!document) {
2418
+ const recovery = resolveDocsMarkdownRecovery({
2419
+ entry,
2420
+ requestedPath,
2421
+ pages,
2422
+ sitemap
2423
+ });
2424
+ if (recovery.redirect) return new Response(null, {
2425
+ status: 307,
2426
+ headers: {
2427
+ ...sharedHeaders,
2428
+ "Cache-Control": "no-store",
2429
+ Location: new URL(recovery.redirect.markdownUrl, request.url).toString()
2430
+ }
2431
+ });
2432
+ return new Response(renderDocsMarkdownNotFound({
2433
+ entry,
2434
+ requestedPath,
2435
+ origin,
2436
+ pages,
2437
+ sitemap
2438
+ }), {
2439
+ status: 404,
2440
+ headers: {
2441
+ ...sharedHeaders,
2442
+ "Cache-Control": "no-store",
2443
+ "Content-Type": "text/markdown; charset=utf-8"
2444
+ }
2445
+ });
2446
+ }
2447
+ const etag = createDocsMarkdownEtag(document);
2448
+ const lastModified = resolveDocsMarkdownHttpDate(options.lastModified ?? extractDocsMarkdownLastModified(document));
2449
+ const responseHeaders = {
2450
+ ...sharedHeaders,
2451
+ "Cache-Control": options.cacheControl ?? "public, max-age=0, s-maxage=3600",
2452
+ "Content-Type": "text/markdown; charset=utf-8",
2453
+ ETag: etag,
2454
+ ...lastModified ? { "Last-Modified": lastModified } : {}
2455
+ };
2456
+ if (requestMatchesDocsMarkdownEtag(request, etag) || requestHasFreshDocsMarkdownDate(request, lastModified)) {
2457
+ const { "Content-Type": _contentType, ...notModifiedHeaders } = responseHeaders;
2458
+ return new Response(null, {
2459
+ status: 304,
2460
+ headers: notModifiedHeaders
2461
+ });
2462
+ }
2463
+ return new Response(document, { headers: responseHeaders });
2464
+ }
1753
2465
  function findDocsMarkdownPage(entry, pages, requestedPath) {
1754
2466
  const normalizedRequest = normalizeRequestedMarkdownPath(entry, requestedPath);
1755
2467
  for (const page of pages) if (normalizeDocsUrlPath(page.url) === normalizedRequest) return page;
@@ -1883,13 +2595,13 @@ function appendDocsAgentPublicRouteLines(lines, context, variant) {
1883
2595
  appendDocsMcpRouteLines(lines, context);
1884
2596
  }
1885
2597
  function renderDocsMarkdownDocument(page, options) {
1886
- if (page.agentRawContent !== void 0) return appendDocsMarkdownSitemapFooter(prependDocsMarkdownFrontmatter(page.agentRawContent, resolveDocsMarkdownPageMetadata(page, options)), options?.sitemap);
2598
+ if (page.agentRawContent !== void 0) return appendDocsMarkdownSitemapFooter(prependDocsMarkdownFrontmatter(upsertPageAgentContractMarkdown(page.agentRawContent, page.agent), resolveDocsMarkdownPageMetadata(page, options)), options?.sitemap);
1887
2599
  const relatedLines = renderDocsRelatedMarkdownLines(page.related);
1888
2600
  const lines = [`# ${page.title}`, `URL: ${page.url}`];
1889
2601
  if (shouldRenderLlmsDirective(options)) lines.push(DOCS_LLMS_TXT_DIRECTIVE_LINE);
1890
2602
  if (page.description) lines.push(`Description: ${page.description}`);
1891
2603
  lines.push(...relatedLines);
1892
- lines.push("", page.agentFallbackRawContent ?? page.rawContent ?? page.content);
2604
+ lines.push("", upsertPageAgentContractMarkdown(page.agentFallbackRawContent ?? page.rawContent ?? page.content, page.agent));
1893
2605
  return appendDocsMarkdownSitemapFooter(prependDocsMarkdownFrontmatter(lines.join("\n"), resolveDocsMarkdownPageMetadata(page, options)), options?.sitemap);
1894
2606
  }
1895
2607
  function renderDocsSkillDocument(options) {
@@ -1977,6 +2689,14 @@ function resolveDocsAgentMdxContent(content, audience) {
1977
2689
  }
1978
2690
  return output.join("\n").replace(/\n{3,}/g, "\n\n").trim();
1979
2691
  }
2692
+ /** Resolve only the task tools that the advertised MCP endpoint actually exposes. */
2693
+ function resolveDocsAgentContractMcpTools(mcp) {
2694
+ if (!mcp.enabled) return void 0;
2695
+ const tools = {};
2696
+ if (mcp.tools.listTasks !== false) tools.list = "list_tasks";
2697
+ if (mcp.tools.readTask !== false) tools.read = "read_task";
2698
+ return tools.list || tools.read ? tools : void 0;
2699
+ }
1980
2700
  function buildDocsAgentDiscoverySpec({ origin, entry = "docs", i18n = null, search, mcp, feedback, llms, sitemap, robots, openapi, markdown }) {
1981
2701
  const normalizedEntry = normalizeDocsPathSegment(entry) || "docs";
1982
2702
  const localesEnabled = i18n !== null;
@@ -1988,6 +2708,7 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", i18n = null, sear
1988
2708
  const sitemapConfig = resolveDocsSitemapConfig(sitemap, { baseUrl: llms?.baseUrl });
1989
2709
  const robotsEnabled = isRobotsDiscoveryEnabled(robots);
1990
2710
  const openapiConfig = resolveDocsOpenApiDiscoveryConfig(openapi);
2711
+ const agentContractMcpTools = resolveDocsAgentContractMcpTools(mcp);
1991
2712
  return {
1992
2713
  version: "1",
1993
2714
  name: "@farming-labs/docs",
@@ -2009,6 +2730,7 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", i18n = null, sear
2009
2730
  markdownRoutes: true,
2010
2731
  agentMdOverrides: true,
2011
2732
  agentBlocks: true,
2733
+ structuredAgentContracts: true,
2012
2734
  agents: true,
2013
2735
  llms: llmsEnabled,
2014
2736
  skills: true,
@@ -2052,6 +2774,17 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", i18n = null, sear
2052
2774
  "page markdown"
2053
2775
  ]
2054
2776
  },
2777
+ agentContract: {
2778
+ enabled: true,
2779
+ schemaVersion: "page-agent-contract.v1",
2780
+ source: "page-frontmatter",
2781
+ frontmatterPath: "agent",
2782
+ markdownSection: "Agent Contract",
2783
+ mcpField: "agent",
2784
+ ...agentContractMcpTools ? { mcpTools: agentContractMcpTools } : {},
2785
+ usefulContractFields: ["task", "outcome"],
2786
+ fields: PAGE_AGENT_CONTRACT_FIELD_SCHEMA
2787
+ },
2055
2788
  llms: {
2056
2789
  enabled: llmsEnabled,
2057
2790
  defaultTxt: DEFAULT_LLMS_TXT_ROUTE,
@@ -2103,10 +2836,12 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", i18n = null, sear
2103
2836
  "description",
2104
2837
  "url",
2105
2838
  "dateModified",
2106
- "breadcrumb"
2839
+ "breadcrumb",
2840
+ "mainEntity"
2107
2841
  ],
2108
2842
  canonicalUrlField: "url",
2109
- breadcrumbType: "BreadcrumbList"
2843
+ breadcrumbType: "BreadcrumbList",
2844
+ agentContractType: "HowTo"
2110
2845
  },
2111
2846
  openapi: {
2112
2847
  enabled: openapiConfig.enabled,
@@ -2174,18 +2909,26 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", i18n = null, sear
2174
2909
  }
2175
2910
  };
2176
2911
  }
2177
- function acceptsMarkdown(request) {
2912
+ function acceptsDocsMarkdown(request) {
2178
2913
  const accept = request.headers.get("accept");
2179
2914
  if (!accept) return false;
2180
- return accept.split(",").map((value) => value.trim()).some((value) => {
2181
- const [mediaType, ...params] = value.split(";").map((part) => part.trim().toLowerCase());
2182
- if (mediaType !== "text/markdown") return false;
2915
+ const ranges = accept.split(",").map((value) => {
2916
+ const [rawMediaType = "", ...params] = value.split(";").map((part) => part.trim().toLowerCase());
2183
2917
  const qualityParam = params.find((param) => param.split("=", 1)[0]?.trim() === "q");
2184
- if (!qualityParam) return true;
2185
- const qualityValue = qualityParam.slice(qualityParam.indexOf("=") + 1).trim();
2186
- const quality = Number.parseFloat(qualityValue);
2187
- return Number.isFinite(quality) ? quality > 0 : true;
2918
+ const parsedQuality = qualityParam ? Number.parseFloat(qualityParam.slice(qualityParam.indexOf("=") + 1).trim()) : 1;
2919
+ return {
2920
+ mediaType: rawMediaType,
2921
+ quality: Number.isFinite(parsedQuality) ? Math.min(1, Math.max(0, parsedQuality)) : 0
2922
+ };
2188
2923
  });
2924
+ const qualityFor = (mediaType) => {
2925
+ const matches = ranges.filter((range) => range.mediaType === mediaType);
2926
+ return matches.length > 0 ? Math.max(...matches.map((range) => range.quality)) : void 0;
2927
+ };
2928
+ const markdownQuality = qualityFor("text/markdown");
2929
+ if (!markdownQuality || markdownQuality <= 0) return false;
2930
+ const htmlQuality = qualityFor("text/html") ?? qualityFor("text/*") ?? qualityFor("*/*");
2931
+ return htmlQuality === void 0 || htmlQuality <= markdownQuality;
2189
2932
  }
2190
2933
  function buildDocsUserAgentHeaderPattern(patterns) {
2191
2934
  return `.*(?:${patterns.map(toCaseInsensitiveHeaderPattern).join("|")}).*`;
@@ -2247,4 +2990,4 @@ function toYamlString(value) {
2247
2990
  }
2248
2991
 
2249
2992
  //#endregion
2250
- export { renderDocsAgentsDocument as $, buildDocsAgentDiscoverySpec as A, resolveDocsSitemapPageLastmod as At, hasDocsMarkdownSignatureAgent as B, DEFAULT_OPENAPI_SCHEMA_ROUTE as C, DEFAULT_SITEMAP_XML_ROUTE as Ct, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as D, renderDocsSitemapMarkdown as Dt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as E, readDocsSitemapManifestFromContentMap as Et, detectDocsMarkdownAgentRequest as F, isDocsLlmsTxtPublicRequest as G, isDocsAgentsRequest as H, findDocsMarkdownPage as I, isDocsSkillRequest as J, isDocsMcpRequest as K, getDocsLlmsTxtMaxCharsIssue as L, buildDocsConfigMap as M, toDocsSitemapMarkdownUrl as Mt, buildDocsDiagnostics as N, normalizeDocsRelated as Nt, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as O, renderDocsSitemapXml as Ot, buildDocsMcpEndpointCandidates as P, renderDocsRelatedMarkdownLines as Pt, parseDocsAgentFeedbackData as Q, getDocsMarkdownCanonicalLinkHeader as R, DEFAULT_MCP_WELL_KNOWN_ROUTE as S, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as St, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as T, createDocsSitemapResponse as Tt, isDocsConfigRequest as U, isDocsAgentDiscoveryRequest as V, isDocsDiagnosticsRequest as W, normalizeDocsPathSegment as X, matchesDocsLlmsTxtSection as Y, normalizeDocsUrlPath as Z, DEFAULT_LLMS_TXT_MAX_CHARS as _, toDocsMarkdownUrl as _t, DEFAULT_AGENT_MD_ROUTE as a, resolveDocsAgentFeedbackRequest as at, DEFAULT_MCP_PUBLIC_ROUTE as b, DEFAULT_SITEMAP_MD_DOCS_ROUTE as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, resolveDocsLlmsTxtFormat as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, resolveDocsMarkdownCanonicalUrl as dt, renderDocsLlmsTxt as et, DEFAULT_DOCS_CONFIG_ROUTE as f, resolveDocsMarkdownRecovery as ft, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as g, selectDocsLlmsTxtContent as gt, DEFAULT_LLMS_FULL_TXT_ROUTE as h, resolveDocsSkillFormat as ht, DEFAULT_AGENT_FEEDBACK_ROUTE as i, resolveDocsAgentFeedbackConfig as it, buildDocsAgentFeedbackSchema as j, resolveDocsSitemapRequest as jt, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as k, resolveDocsSitemapConfig as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, resolveDocsLlmsTxtRequest as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, resolveDocsOpenApiDiscoveryConfig as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, renderDocsMarkdownNotFound as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, resolveDocsAgentMdxContent as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, resolveDocsMarkdownRequest as pt, isDocsPublicGetRequest as q, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, renderDocsSkillDocument as rt, DEFAULT_AGENT_SPEC_ROUTE as s, resolveDocsAgentsFormat as st, DEFAULT_AGENTS_MD_ROUTE as t, renderDocsMarkdownDocument as tt, DEFAULT_DOCS_API_ROUTE as u, resolveDocsLlmsTxtSections as ut, DEFAULT_LLMS_TXT_ROUTE as v, validateDocsAgentFeedbackPayload as vt, DEFAULT_SKILL_MD_ROUTE as w, buildDocsSitemapManifest as wt, DEFAULT_MCP_ROUTE as x, DEFAULT_SITEMAP_MD_ROUTE as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, DEFAULT_SITEMAP_MANIFEST_PATH as yt, getDocsMarkdownVaryHeader as z };
2993
+ export { normalizeDocsPathSegment as $, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as A, readDocsSitemapManifestFromContentMap as At, getDocsLlmsTxtMaxCharsIssue as B, PAGE_AGENT_CONTRACT_FIELDS as Bt, DEFAULT_OPENAPI_SCHEMA_ROUTE as C, DEFAULT_SITEMAP_MANIFEST_PATH as Ct, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as D, DEFAULT_SITEMAP_XML_ROUTE as Dt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as E, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as Et, buildDocsDiagnostics as F, resolveDocsSitemapRequest as Ft, isDocsAgentsRequest as G, hasStructuredPageAgentContract as Gt, getDocsMarkdownVaryHeader as H, PAGE_AGENT_CONTRACT_START_MARKER as Ht, buildDocsMcpEndpointCandidates as I, toDocsSitemapMarkdownUrl as It, isDocsLlmsTxtPublicRequest as J, renderPageAgentFrontmatterYamlLines as Jt, isDocsConfigRequest as K, normalizePageAgentFrontmatter as Kt, createDocsMarkdownResponse as L, normalizeDocsRelated as Lt, buildDocsAgentDiscoverySpec as M, renderDocsSitemapXml as Mt, buildDocsAgentFeedbackSchema as N, resolveDocsSitemapConfig as Nt, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS as O, buildDocsSitemapManifest as Ot, buildDocsConfigMap as P, resolveDocsSitemapPageLastmod as Pt, matchesDocsLlmsTxtSection as Q, detectDocsMarkdownAgentRequest as R, renderDocsRelatedMarkdownLines as Rt, DEFAULT_MCP_WELL_KNOWN_ROUTE as S, validateDocsAgentFeedbackPayload as St, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as T, DEFAULT_SITEMAP_MD_ROUTE as Tt, hasDocsMarkdownSignatureAgent as U, PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS as Ut, getDocsMarkdownCanonicalLinkHeader as V, PAGE_AGENT_CONTRACT_FIELD_SCHEMA as Vt, isDocsAgentDiscoveryRequest as W, getPageAgentFrontmatterIssues as Wt, isDocsPublicGetRequest as X, upsertPageAgentContractMarkdown as Xt, isDocsMcpRequest as Y, stripGeneratedPageAgentContractMarkdown as Yt, isDocsSkillRequest as Z, DEFAULT_LLMS_TXT_MAX_CHARS as _, resolveDocsMarkdownRequest as _t, DEFAULT_AGENT_MD_ROUTE as a, renderDocsMarkdownNotFound as at, DEFAULT_MCP_PUBLIC_ROUTE as b, selectDocsLlmsTxtContent as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, resolveDocsAgentFeedbackConfig as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, resolveDocsAgentsFormat as dt, normalizeDocsUrlPath as et, DEFAULT_DOCS_CONFIG_ROUTE as f, resolveDocsLlmsTxtFormat as ft, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as g, resolveDocsMarkdownRecovery as gt, DEFAULT_LLMS_FULL_TXT_ROUTE as h, resolveDocsMarkdownCanonicalUrl as ht, DEFAULT_AGENT_FEEDBACK_ROUTE as i, renderDocsMarkdownDocument as it, acceptsDocsMarkdown as j, renderDocsSitemapMarkdown as jt, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as k, createDocsSitemapResponse as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, resolveDocsAgentFeedbackRequest as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, resolveDocsLlmsTxtSections as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, renderDocsAgentsDocument as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, renderDocsSkillDocument as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, resolveDocsLlmsTxtRequest as pt, isDocsDiagnosticsRequest as q, renderPageAgentContractMarkdown as qt, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, renderDocsLlmsTxt as rt, DEFAULT_AGENT_SPEC_ROUTE as s, resolveDocsAgentContractMcpTools as st, DEFAULT_AGENTS_MD_ROUTE as t, parseDocsAgentFeedbackData as tt, DEFAULT_DOCS_API_ROUTE as u, resolveDocsAgentMdxContent as ut, DEFAULT_LLMS_TXT_ROUTE as v, resolveDocsOpenApiDiscoveryConfig as vt, DEFAULT_SKILL_MD_ROUTE as w, DEFAULT_SITEMAP_MD_DOCS_ROUTE as wt, DEFAULT_MCP_ROUTE as x, toDocsMarkdownUrl as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, resolveDocsSkillFormat as yt, findDocsMarkdownPage as z, PAGE_AGENT_CONTRACT_END_MARKER as zt };