@farming-labs/docs 0.2.71 → 0.2.73

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 (42) hide show
  1. package/dist/{agent-bof3qzKZ.mjs → agent-ClRpctMG.mjs} +3 -2
  2. package/dist/{agent-evals-Cr9TAkmB.mjs → agent-evals-BFHGypqh.mjs} +116 -20
  3. package/dist/{agent-export-7Ws4KqDE.mjs → agent-export-B9bah0AV.mjs} +9 -8
  4. package/dist/{agent-FIyl4-Oa.mjs → agent-o9OTadrf.mjs} +607 -769
  5. package/dist/agent-skills-bundle.d.mts +1 -1
  6. package/dist/{agent-skills-server-DTwblsLu.d.mts → agent-skills-server-DCbAx5WU.d.mts} +2 -2
  7. package/dist/{agent-skills-server-B4u3qy-1.mjs → agent-skills-server-noFn1l_p.mjs} +1 -1
  8. package/dist/agent-skills-vite.d.mts +3 -3
  9. package/dist/agent-skills-vite.mjs +2 -2
  10. package/dist/{agents-Be2ntaFr.mjs → agents-CR-Uasbc.mjs} +7 -6
  11. package/dist/cli/index.mjs +14 -14
  12. package/dist/client/react.d.mts +1 -1
  13. package/dist/{cloud-ask-ai-BfnX18rI.d.mts → cloud-ask-ai-yR9vZmSG.d.mts} +1 -1
  14. package/dist/docs-cloud-server.d.mts +2 -2
  15. package/dist/{doctor-DoPAofVP.mjs → doctor-BeyN3Ljh.mjs} +12 -11
  16. package/dist/{golden-evaluations-CPGGnXOV.mjs → golden-evaluations-CloP0pAe.mjs} +23 -2
  17. package/dist/index.d.mts +93 -6
  18. package/dist/index.mjs +9 -8
  19. package/dist/markdown-rendering.d.mts +75 -0
  20. package/dist/markdown-rendering.mjs +618 -0
  21. package/dist/markdown-sections-7OoA7ylx.mjs +1492 -0
  22. package/dist/{mcp-BLynUzE7.mjs → mcp-BLLXvEXB.mjs} +7 -6
  23. package/dist/mcp.d.mts +7 -2
  24. package/dist/mcp.mjs +130 -25
  25. package/dist/{metadata-bw8k-9x-.mjs → metadata-N252j5_a.mjs} +1 -1
  26. package/dist/{reading-time-DtNegNiq.mjs → prompt-references-Cz35rlOa.mjs} +158 -4
  27. package/dist/{review-NFnYbMRI.mjs → review-DaJLdPLh.mjs} +7 -6
  28. package/dist/{robots-DOqBwQw8.mjs → robots-BcuxnZqZ.mjs} +2 -2
  29. package/dist/{robots-B3e-aWPy.mjs → robots-DI-9MZz1.mjs} +4 -3
  30. package/dist/{search-CozHzW7v.d.mts → search-D1n8Sf25.d.mts} +45 -9
  31. package/dist/{search-DOGUUZvs.mjs → search-DeOJiMAy.mjs} +7 -6
  32. package/dist/{search-x5O0-9X3.mjs → search-RfPcG1if.mjs} +742 -42
  33. package/dist/server.d.mts +13 -5
  34. package/dist/server.mjs +8 -7
  35. package/dist/{sitemap-BpMKdDUd.mjs → sitemap-BGGbX_KE.mjs} +7 -6
  36. package/dist/{sitemap-server-D_hayOp6.mjs → sitemap-server-VefDnzEB.mjs} +1 -1
  37. package/dist/{standards-discovery-C0CIC4QI.d.mts → standards-discovery-83lp1lew.d.mts} +5 -4
  38. package/dist/{standards-discovery-CYfiQE13.mjs → standards-discovery-BwL5ffGx.mjs} +4 -3
  39. package/dist/{types-BQC05SQm.d.mts → types-_HCPD4wc.d.mts} +49 -1
  40. package/package.json +9 -1
  41. package/dist/agent-scope-C_U--OZ7.mjs +0 -283
  42. /package/dist/{i18n-CCaFUnAN.mjs → i18n-hHVWcflJ.mjs} +0 -0
@@ -1,4 +1,5 @@
1
- import { F as resolveDocsDiscoveryApiRoute, O as buildDocsApiCatalog, P as isDocsStandardsDiscoveryRequest, S as DOCS_AGENT_MANIFEST_FORMAT, _ as DEFAULT_API_CATALOG_FORMAT, a as DEFAULT_A2A_AGENT_CARD_ROUTE, b as DEFAULT_LEGACY_SKILLS_INDEX_ROUTE, c as DEFAULT_AGENT_SKILLS_ARCHIVE_ROUTE_PATTERN, d as DEFAULT_AGENT_SKILLS_ROUTE_PATTERN, j as createDocsStandardsResponse, l as DEFAULT_AGENT_SKILLS_INDEX_FORMAT, n as API_CATALOG_MEDIA_TYPE, r as API_CATALOG_PROFILE_URI, t as AGENT_SKILLS_DISCOVERY_SCHEMA_URI, u as DEFAULT_AGENT_SKILLS_INDEX_ROUTE, v as DEFAULT_API_CATALOG_ROUTE, w as DOCS_AGENT_MANIFEST_SCHEMA_URI } from "./standards-discovery-CYfiQE13.mjs";
1
+ import { S as upsertPageAgentContractMarkdown, b as renderPageAgentFrontmatterYamlLines, o as findDocsMarkdownSection, p as PAGE_AGENT_CONTRACT_FIELD_SCHEMA, s as parseDocsMarkdownSections } from "./markdown-sections-7OoA7ylx.mjs";
2
+ import { F as isDocsStandardsDiscoveryRequest, I as resolveDocsDiscoveryApiRoute, M as createDocsStandardsResponse, S as DOCS_AGENT_MANIFEST_FORMAT, T as DOCS_AGENT_MANIFEST_VERSION, _ as DEFAULT_API_CATALOG_FORMAT, a as DEFAULT_A2A_AGENT_CARD_ROUTE, b as DEFAULT_LEGACY_SKILLS_INDEX_ROUTE, c as DEFAULT_AGENT_SKILLS_ARCHIVE_ROUTE_PATTERN, d as DEFAULT_AGENT_SKILLS_ROUTE_PATTERN, k as buildDocsApiCatalog, l as DEFAULT_AGENT_SKILLS_INDEX_FORMAT, n as API_CATALOG_MEDIA_TYPE, r as API_CATALOG_PROFILE_URI, t as AGENT_SKILLS_DISCOVERY_SCHEMA_URI, u as DEFAULT_AGENT_SKILLS_INDEX_ROUTE, v as DEFAULT_API_CATALOG_ROUTE, w as DOCS_AGENT_MANIFEST_SCHEMA_URI } from "./standards-discovery-BwL5ffGx.mjs";
2
3
  import { createProcessor } from "@mdx-js/mdx";
3
4
 
4
5
  //#region src/mcp-auth.ts
@@ -98,595 +99,6 @@ function isAbsoluteHttpUrl(value) {
98
99
  }
99
100
  }
100
101
 
101
- //#endregion
102
- //#region src/agent-contract.ts
103
- const PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS = [
104
- "task",
105
- "outcome",
106
- "appliesTo",
107
- "prerequisites",
108
- "files",
109
- "commands",
110
- "sideEffects",
111
- "verification",
112
- "rollback",
113
- "failureModes"
114
- ];
115
- const PAGE_AGENT_CONTRACT_FIELDS = ["tokenBudget", ...PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS];
116
- const PAGE_AGENT_CONTRACT_FIELD_SCHEMA = {
117
- tokenBudget: "number",
118
- task: "string",
119
- outcome: "string",
120
- appliesTo: {
121
- framework: "string|string[]",
122
- version: "string|string[]",
123
- package: "string|string[]"
124
- },
125
- prerequisites: "string[]",
126
- files: "string[]",
127
- commands: "Array<string|{run,cwd?,description?}>",
128
- sideEffects: "string[]",
129
- verification: "Array<string|{description?,run?,expect?}>",
130
- rollback: "string[]",
131
- failureModes: "Array<string|{symptom,resolution?}>"
132
- };
133
- const APPLIES_TO_FIELDS = [
134
- "framework",
135
- "version",
136
- "package"
137
- ];
138
- const COMMAND_FIELDS = [
139
- "run",
140
- "cwd",
141
- "description"
142
- ];
143
- const VERIFICATION_FIELDS = [
144
- "description",
145
- "run",
146
- "expect"
147
- ];
148
- const FAILURE_MODE_FIELDS = ["symptom", "resolution"];
149
- const PAGE_AGENT_CONTRACT_START_MARKER = "<!-- farming-labs:agent-contract:start -->";
150
- const PAGE_AGENT_CONTRACT_END_MARKER = "<!-- farming-labs:agent-contract:end -->";
151
- function isRecord(value) {
152
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
153
- }
154
- function normalizeString(value) {
155
- if (typeof value !== "string") return void 0;
156
- return value.trim() || void 0;
157
- }
158
- function normalizeStringList(value) {
159
- if (!Array.isArray(value)) return void 0;
160
- const seen = /* @__PURE__ */ new Set();
161
- const normalized = [];
162
- for (const item of value) {
163
- const text = normalizeString(item);
164
- if (!text || seen.has(text)) continue;
165
- seen.add(text);
166
- normalized.push(text);
167
- }
168
- return normalized.length > 0 ? normalized : void 0;
169
- }
170
- function normalizeStringOrList(value) {
171
- const single = normalizeString(value);
172
- if (single) return [single];
173
- return normalizeStringList(value);
174
- }
175
- function normalizeAppliesTo(value) {
176
- if (!isRecord(value)) return void 0;
177
- const framework = normalizeStringOrList(value.framework);
178
- const version = normalizeStringOrList(value.version);
179
- const packageNames = normalizeStringOrList(value.package);
180
- if (!framework && !version && !packageNames) return void 0;
181
- return {
182
- ...framework ? { framework } : {},
183
- ...version ? { version } : {},
184
- ...packageNames ? { package: packageNames } : {}
185
- };
186
- }
187
- function normalizeCommands(value) {
188
- if (!Array.isArray(value)) return void 0;
189
- const commands = [];
190
- for (const item of value) {
191
- const shorthand = normalizeString(item);
192
- if (shorthand) {
193
- commands.push(shorthand);
194
- continue;
195
- }
196
- if (!isRecord(item)) continue;
197
- const run = normalizeString(item.run);
198
- if (!run) continue;
199
- const cwd = normalizeString(item.cwd);
200
- const description = normalizeString(item.description);
201
- commands.push({
202
- run,
203
- ...cwd ? { cwd } : {},
204
- ...description ? { description } : {}
205
- });
206
- }
207
- return commands.length > 0 ? commands : void 0;
208
- }
209
- function normalizeVerification(value) {
210
- if (!Array.isArray(value)) return void 0;
211
- const verification = [];
212
- for (const item of value) {
213
- const shorthand = normalizeString(item);
214
- if (shorthand) {
215
- verification.push(shorthand);
216
- continue;
217
- }
218
- if (!isRecord(item)) continue;
219
- const description = normalizeString(item.description);
220
- const run = normalizeString(item.run);
221
- const expect = normalizeString(item.expect);
222
- if (!description && !run && !expect) continue;
223
- verification.push({
224
- ...description ? { description } : {},
225
- ...run ? { run } : {},
226
- ...expect ? { expect } : {}
227
- });
228
- }
229
- return verification.length > 0 ? verification : void 0;
230
- }
231
- function normalizeFailureModes(value) {
232
- if (!Array.isArray(value)) return void 0;
233
- const failureModes = [];
234
- for (const item of value) {
235
- const shorthand = normalizeString(item);
236
- if (shorthand) {
237
- failureModes.push(shorthand);
238
- continue;
239
- }
240
- if (!isRecord(item)) continue;
241
- const symptom = normalizeString(item.symptom);
242
- if (!symptom) continue;
243
- const resolution = normalizeString(item.resolution);
244
- failureModes.push({
245
- symptom,
246
- ...resolution ? { resolution } : {}
247
- });
248
- }
249
- return failureModes.length > 0 ? failureModes : void 0;
250
- }
251
- function normalizeTokenBudget(value) {
252
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return void 0;
253
- return Math.ceil(value);
254
- }
255
- /**
256
- * Normalize untrusted page frontmatter into the stable agent contract shape.
257
- * Invalid fields are omitted so malformed author input cannot break page delivery.
258
- */
259
- function normalizePageAgentFrontmatter(value) {
260
- if (!isRecord(value)) return void 0;
261
- const tokenBudget = normalizeTokenBudget(value.tokenBudget);
262
- const task = normalizeString(value.task);
263
- const outcome = normalizeString(value.outcome);
264
- const appliesTo = normalizeAppliesTo(value.appliesTo);
265
- const prerequisites = normalizeStringList(value.prerequisites);
266
- const files = normalizeStringList(value.files);
267
- const commands = normalizeCommands(value.commands);
268
- const sideEffects = normalizeStringList(value.sideEffects);
269
- const verification = normalizeVerification(value.verification);
270
- const rollback = normalizeStringList(value.rollback);
271
- const failureModes = normalizeFailureModes(value.failureModes);
272
- const normalized = {
273
- ...tokenBudget !== void 0 ? { tokenBudget } : {},
274
- ...task ? { task } : {},
275
- ...outcome ? { outcome } : {},
276
- ...appliesTo ? { appliesTo } : {},
277
- ...prerequisites ? { prerequisites } : {},
278
- ...files ? { files } : {},
279
- ...commands ? { commands } : {},
280
- ...sideEffects ? { sideEffects } : {},
281
- ...verification ? { verification } : {},
282
- ...rollback ? { rollback } : {},
283
- ...failureModes ? { failureModes } : {}
284
- };
285
- return Object.keys(normalized).length > 0 ? normalized : void 0;
286
- }
287
- function hasStructuredPageAgentContract(value) {
288
- const normalized = normalizePageAgentFrontmatter(value);
289
- if (!normalized) return false;
290
- return PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS.some((field) => normalized[field] !== void 0);
291
- }
292
- function addStringIssue(issues, object, field) {
293
- if (!(field in object)) return;
294
- if (!normalizeString(object[field])) issues.push({
295
- path: `agent.${field}`,
296
- message: "must be a non-empty string"
297
- });
298
- }
299
- function addStringListIssues(issues, object, field) {
300
- if (!(field in object)) return;
301
- const value = object[field];
302
- if (!Array.isArray(value) || value.length === 0) {
303
- issues.push({
304
- path: `agent.${field}`,
305
- message: "must be a non-empty string array"
306
- });
307
- return;
308
- }
309
- value.forEach((item, index) => {
310
- if (!normalizeString(item)) issues.push({
311
- path: `agent.${field}[${index}]`,
312
- message: "must be a non-empty string"
313
- });
314
- });
315
- }
316
- function editDistance(left, right) {
317
- const previous = Array.from({ length: right.length + 1 }, (_, index) => index);
318
- for (let leftIndex = 1; leftIndex <= left.length; leftIndex += 1) {
319
- const current = [leftIndex];
320
- 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));
321
- previous.splice(0, previous.length, ...current);
322
- }
323
- return previous[right.length] ?? 0;
324
- }
325
- function closestKnownField(field, allowed) {
326
- const closest = allowed.map((candidate) => ({
327
- candidate,
328
- distance: editDistance(field, candidate)
329
- })).sort((left, right) => left.distance - right.distance || left.candidate.localeCompare(right.candidate))[0];
330
- if (!closest) return void 0;
331
- const threshold = Math.max(1, Math.min(3, Math.floor(closest.candidate.length / 3)));
332
- return closest.distance <= threshold ? closest.candidate : void 0;
333
- }
334
- function addUnknownKeyIssues(issues, object, allowed, path) {
335
- for (const field of Object.keys(object)) {
336
- if (allowed.includes(field)) continue;
337
- const suggestion = closestKnownField(field, allowed);
338
- issues.push({
339
- path: `${path}.${field}`,
340
- message: suggestion ? `is not recognized; did you mean "${path}.${suggestion}"?` : "is not recognized"
341
- });
342
- }
343
- }
344
- /** Return author-facing validation issues without throwing. */
345
- function getPageAgentFrontmatterIssues(value) {
346
- if (value === void 0) return [];
347
- if (!isRecord(value)) return [{
348
- path: "agent",
349
- message: "must be an object"
350
- }];
351
- const issues = [];
352
- addUnknownKeyIssues(issues, value, PAGE_AGENT_CONTRACT_FIELDS, "agent");
353
- if ("tokenBudget" in value && (typeof value.tokenBudget !== "number" || !Number.isFinite(value.tokenBudget) || value.tokenBudget <= 0)) issues.push({
354
- path: "agent.tokenBudget",
355
- message: "must be a positive finite number"
356
- });
357
- addStringIssue(issues, value, "task");
358
- addStringIssue(issues, value, "outcome");
359
- if ("appliesTo" in value) if (!isRecord(value.appliesTo)) issues.push({
360
- path: "agent.appliesTo",
361
- message: "must be an object"
362
- });
363
- else {
364
- addUnknownKeyIssues(issues, value.appliesTo, APPLIES_TO_FIELDS, "agent.appliesTo");
365
- for (const field of [
366
- "framework",
367
- "version",
368
- "package"
369
- ]) {
370
- if (!(field in value.appliesTo)) continue;
371
- const fieldValue = value.appliesTo[field];
372
- if (!normalizeStringOrList(fieldValue)) {
373
- issues.push({
374
- path: `agent.appliesTo.${field}`,
375
- message: "must be a non-empty string or string array"
376
- });
377
- continue;
378
- }
379
- if (Array.isArray(fieldValue)) fieldValue.forEach((item, index) => {
380
- if (!normalizeString(item)) issues.push({
381
- path: `agent.appliesTo.${field}[${index}]`,
382
- message: "must be a non-empty string"
383
- });
384
- });
385
- }
386
- if (!normalizeAppliesTo(value.appliesTo)) issues.push({
387
- path: "agent.appliesTo",
388
- message: "must include framework, version, or package"
389
- });
390
- }
391
- for (const field of [
392
- "prerequisites",
393
- "files",
394
- "sideEffects",
395
- "rollback"
396
- ]) addStringListIssues(issues, value, field);
397
- if ("commands" in value) if (!Array.isArray(value.commands) || value.commands.length === 0) issues.push({
398
- path: "agent.commands",
399
- message: "must be a non-empty array"
400
- });
401
- else value.commands.forEach((command, index) => {
402
- if (normalizeString(command)) return;
403
- if (!isRecord(command)) {
404
- issues.push({
405
- path: `agent.commands[${index}]`,
406
- message: "must be a command string or an object with a non-empty run field"
407
- });
408
- return;
409
- }
410
- addUnknownKeyIssues(issues, command, COMMAND_FIELDS, `agent.commands[${index}]`);
411
- if (!normalizeString(command.run)) {
412
- issues.push({
413
- path: `agent.commands[${index}]`,
414
- message: "must be a command string or an object with a non-empty run field"
415
- });
416
- return;
417
- }
418
- for (const field of ["cwd", "description"]) if (field in command && !normalizeString(command[field])) issues.push({
419
- path: `agent.commands[${index}].${field}`,
420
- message: "must be a non-empty string"
421
- });
422
- });
423
- if ("verification" in value) if (!Array.isArray(value.verification) || value.verification.length === 0) issues.push({
424
- path: "agent.verification",
425
- message: "must be a non-empty array"
426
- });
427
- else value.verification.forEach((step, index) => {
428
- if (normalizeString(step)) return;
429
- if (!isRecord(step)) {
430
- issues.push({
431
- path: `agent.verification[${index}]`,
432
- message: "must be a string or an object with description, run, or expect"
433
- });
434
- return;
435
- }
436
- addUnknownKeyIssues(issues, step, VERIFICATION_FIELDS, `agent.verification[${index}]`);
437
- if (!normalizeVerification([step])) {
438
- issues.push({
439
- path: `agent.verification[${index}]`,
440
- message: "must be a string or an object with description, run, or expect"
441
- });
442
- return;
443
- }
444
- for (const field of [
445
- "description",
446
- "run",
447
- "expect"
448
- ]) if (field in step && !normalizeString(step[field])) issues.push({
449
- path: `agent.verification[${index}].${field}`,
450
- message: "must be a non-empty string"
451
- });
452
- });
453
- if ("failureModes" in value) if (!Array.isArray(value.failureModes) || value.failureModes.length === 0) issues.push({
454
- path: "agent.failureModes",
455
- message: "must be a non-empty array"
456
- });
457
- else value.failureModes.forEach((mode, index) => {
458
- if (normalizeString(mode)) return;
459
- if (!isRecord(mode)) {
460
- issues.push({
461
- path: `agent.failureModes[${index}]`,
462
- message: "must be a string or an object with a non-empty symptom field"
463
- });
464
- return;
465
- }
466
- addUnknownKeyIssues(issues, mode, FAILURE_MODE_FIELDS, `agent.failureModes[${index}]`);
467
- if (!normalizeString(mode.symptom)) {
468
- issues.push({
469
- path: `agent.failureModes[${index}]`,
470
- message: "must be a string or an object with a non-empty symptom field"
471
- });
472
- return;
473
- }
474
- if ("resolution" in mode && !normalizeString(mode.resolution)) issues.push({
475
- path: `agent.failureModes[${index}].resolution`,
476
- message: "must be a non-empty string"
477
- });
478
- });
479
- return issues;
480
- }
481
- function yamlString(value) {
482
- return JSON.stringify(value);
483
- }
484
- function renderYamlStringList(lines, indent, key, values) {
485
- lines.push(`${indent}${key}:`);
486
- for (const value of values) lines.push(`${indent} - ${yamlString(value)}`);
487
- }
488
- function renderYamlObjectList(lines, indent, key, values, fields) {
489
- lines.push(`${indent}${key}:`);
490
- for (const value of values) {
491
- if (typeof value === "string") {
492
- lines.push(`${indent} - ${yamlString(value)}`);
493
- continue;
494
- }
495
- const record = value;
496
- const firstField = fields.find((field) => normalizeString(record[field]));
497
- if (!firstField) continue;
498
- lines.push(`${indent} - ${firstField}: ${yamlString(normalizeString(record[firstField]))}`);
499
- for (const field of fields) {
500
- const fieldValue = normalizeString(record[field]);
501
- if (field === firstField || !fieldValue) continue;
502
- lines.push(`${indent} ${field}: ${yamlString(fieldValue)}`);
503
- }
504
- }
505
- }
506
- /** Render normalized `agent` YAML in a stable field order. */
507
- function renderPageAgentFrontmatterYamlLines(value, indentation = 0) {
508
- const agent = normalizePageAgentFrontmatter(value);
509
- if (!agent) return [];
510
- const indent = " ".repeat(Math.max(0, indentation));
511
- const child = `${indent} `;
512
- const lines = [`${indent}agent:`];
513
- if (agent.tokenBudget !== void 0) lines.push(`${child}tokenBudget: ${agent.tokenBudget}`);
514
- if (agent.task) lines.push(`${child}task: ${yamlString(agent.task)}`);
515
- if (agent.outcome) lines.push(`${child}outcome: ${yamlString(agent.outcome)}`);
516
- if (agent.appliesTo) {
517
- lines.push(`${child}appliesTo:`);
518
- const appliesIndent = `${child} `;
519
- for (const field of [
520
- "framework",
521
- "version",
522
- "package"
523
- ]) {
524
- const values = normalizeStringOrList(agent.appliesTo[field]);
525
- if (values) renderYamlStringList(lines, appliesIndent, field, values);
526
- }
527
- }
528
- if (agent.prerequisites) renderYamlStringList(lines, child, "prerequisites", agent.prerequisites);
529
- if (agent.files) renderYamlStringList(lines, child, "files", agent.files);
530
- if (agent.commands) renderYamlObjectList(lines, child, "commands", agent.commands, [
531
- "run",
532
- "cwd",
533
- "description"
534
- ]);
535
- if (agent.sideEffects) renderYamlStringList(lines, child, "sideEffects", agent.sideEffects);
536
- if (agent.verification) renderYamlObjectList(lines, child, "verification", agent.verification, [
537
- "description",
538
- "run",
539
- "expect"
540
- ]);
541
- if (agent.rollback) renderYamlStringList(lines, child, "rollback", agent.rollback);
542
- if (agent.failureModes) renderYamlObjectList(lines, child, "failureModes", agent.failureModes, ["symptom", "resolution"]);
543
- return lines;
544
- }
545
- function inlineCode(value) {
546
- const longestRun = Math.max(0, ...[...value.matchAll(/`+/g)].map((match) => match[0].length));
547
- const fence = "`".repeat(longestRun + 1);
548
- const padding = value.startsWith("`") || value.endsWith("`") ? " " : "";
549
- return `${fence}${padding}${value}${padding}${fence}`;
550
- }
551
- function renderTextList(lines, title, values, code = false) {
552
- lines.push("", `### ${title}`, "");
553
- for (const value of values) lines.push(`- ${code ? inlineCode(value) : value}`);
554
- }
555
- /** Render the structured contract as deterministic, compact machine-readable Markdown. */
556
- function renderPageAgentContractMarkdown(value) {
557
- const agent = normalizePageAgentFrontmatter(value);
558
- if (!agent || !hasStructuredPageAgentContract(agent)) return "";
559
- const lines = [PAGE_AGENT_CONTRACT_START_MARKER, "## Agent Contract"];
560
- if (agent.task) lines.push("", `Task: ${agent.task}`);
561
- if (agent.outcome) lines.push(`Outcome: ${agent.outcome}`);
562
- if (agent.appliesTo) {
563
- lines.push("", "### Applies To", "");
564
- for (const [label, field] of [
565
- ["Framework", "framework"],
566
- ["Version", "version"],
567
- ["Package", "package"]
568
- ]) {
569
- const values = normalizeStringOrList(agent.appliesTo[field]);
570
- if (values) lines.push(`- ${label}: ${values.map(inlineCode).join(", ")}`);
571
- }
572
- }
573
- if (agent.prerequisites) renderTextList(lines, "Prerequisites", agent.prerequisites);
574
- if (agent.files) renderTextList(lines, "Files", agent.files, true);
575
- if (agent.commands) {
576
- lines.push("", "### Commands", "");
577
- for (const command of agent.commands) {
578
- if (typeof command === "string") {
579
- lines.push(`- ${inlineCode(command)}`);
580
- continue;
581
- }
582
- const details = [command.cwd ? `cwd ${inlineCode(command.cwd)}` : void 0, command.description].filter(Boolean);
583
- lines.push(`- ${inlineCode(command.run)}${details.length ? ` — ${details.join("; ")}` : ""}`);
584
- }
585
- }
586
- if (agent.sideEffects) renderTextList(lines, "Side Effects", agent.sideEffects);
587
- if (agent.verification) {
588
- lines.push("", "### Verification", "");
589
- for (const step of agent.verification) {
590
- if (typeof step === "string") {
591
- lines.push(`- ${step}`);
592
- continue;
593
- }
594
- const summary = step.description ?? (step.run ? `Run ${inlineCode(step.run)}` : step.expect ?? "Verification step");
595
- lines.push(`- ${summary}`);
596
- if (step.run && step.description) lines.push(` - Run: ${inlineCode(step.run)}`);
597
- if (step.expect && step.expect !== summary) lines.push(` - Expected: ${step.expect}`);
598
- }
599
- }
600
- if (agent.rollback) renderTextList(lines, "Rollback", agent.rollback);
601
- if (agent.failureModes) {
602
- lines.push("", "### Failure Modes", "");
603
- for (const mode of agent.failureModes) {
604
- if (typeof mode === "string") {
605
- lines.push(`- ${mode}`);
606
- continue;
607
- }
608
- lines.push(`- ${mode.symptom}${mode.resolution ? ` — Recovery: ${mode.resolution}` : ""}`);
609
- }
610
- }
611
- lines.push(PAGE_AGENT_CONTRACT_END_MARKER);
612
- return lines.join("\n");
613
- }
614
- /** Remove generated contract blocks while preserving handwritten guidance. */
615
- function stripGeneratedPageAgentContractMarkdown(markdown) {
616
- const newline = markdown.includes("\r\n") ? "\r\n" : "\n";
617
- const output = [];
618
- let fence;
619
- let pendingBlock;
620
- let skipEmptySeparator = false;
621
- for (const line of markdown.split(/\r?\n/)) {
622
- if (pendingBlock) {
623
- pendingBlock.push(line);
624
- if (isGeneratedAgentContractMarker(line, PAGE_AGENT_CONTRACT_END_MARKER)) {
625
- pendingBlock = void 0;
626
- skipEmptySeparator = true;
627
- }
628
- continue;
629
- }
630
- if (!fence && isGeneratedAgentContractMarker(line, PAGE_AGENT_CONTRACT_START_MARKER)) {
631
- pendingBlock = [line];
632
- continue;
633
- }
634
- if (skipEmptySeparator && line.length === 0) continue;
635
- skipEmptySeparator = false;
636
- output.push(line);
637
- fence = advanceMarkdownFence(line, fence);
638
- }
639
- if (pendingBlock) output.push(...pendingBlock);
640
- while (output[0] === "") output.shift();
641
- return output.join(newline);
642
- }
643
- function isGeneratedAgentContractMarker(line, marker) {
644
- if (line.trim() !== marker) return false;
645
- const markerIndex = line.indexOf(marker);
646
- return markerIndex <= 3 && /^ *$/.test(line.slice(0, markerIndex));
647
- }
648
- function advanceMarkdownFence(line, fence) {
649
- if (fence) {
650
- const closing = /^ {0,3}(`+|~+)[\t ]*$/.exec(line)?.[1];
651
- if (closing?.[0] === fence.character && closing.length >= fence.length) return;
652
- return fence;
653
- }
654
- const opening = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line);
655
- if (!opening?.[1]) return void 0;
656
- if (opening[1][0] === "`" && opening[2]?.includes("`")) return void 0;
657
- return {
658
- character: opening[1][0],
659
- length: opening[1].length
660
- };
661
- }
662
- function isAgentContractHeadingText(value) {
663
- return value.trim().toLowerCase() === "agent contract";
664
- }
665
- function hasPageAgentContractHeading(markdown) {
666
- let fence;
667
- let previousLine;
668
- for (const line of markdown.split(/\r?\n/)) {
669
- const nextFence = advanceMarkdownFence(line, fence);
670
- if (fence || nextFence) {
671
- fence = nextFence;
672
- previousLine = void 0;
673
- continue;
674
- }
675
- const atxText = /^ {0,3}#{1,6}(?:[\t ]+|$)(.*)$/.exec(line)?.[1]?.replace(/[\t ]+#+[\t ]*$/, "").trim();
676
- if (atxText && isAgentContractHeadingText(atxText)) return true;
677
- if (previousLine && /^ {0,3}(?:=+|-+)[\t ]*$/.test(line) && isAgentContractHeadingText(previousLine)) return true;
678
- previousLine = line.trim().length > 0 && !/^ {4}/.test(line) && !/^ {0,3}\t/.test(line) ? line : void 0;
679
- }
680
- return false;
681
- }
682
- /** Insert one generated contract unless the document already has handwritten contract guidance. */
683
- function upsertPageAgentContractMarkdown(markdown, value) {
684
- const cleaned = stripGeneratedPageAgentContractMarkdown(markdown);
685
- const contract = renderPageAgentContractMarkdown(value);
686
- if (!contract || hasPageAgentContractHeading(cleaned)) return cleaned;
687
- return cleaned ? `${contract}\n\n${cleaned.replace(/^\r?\n+/, "")}` : contract;
688
- }
689
-
690
102
  //#endregion
691
103
  //#region src/related.ts
692
104
  function normalizeDocsRelated(value) {
@@ -736,148 +148,6 @@ function normalizeInlineText(value) {
736
148
  return value.replace(/\s+/g, " ").trim();
737
149
  }
738
150
 
739
- //#endregion
740
- //#region src/markdown-sections.ts
741
- const HTML_ENTITIES = {
742
- amp: "&",
743
- apos: "'",
744
- gt: ">",
745
- lt: "<",
746
- nbsp: " ",
747
- quot: "\""
748
- };
749
- /**
750
- * Reduce inline Markdown in a heading to the visible label used by search and anchors.
751
- * This intentionally covers the common inline constructs without adding a Markdown parser
752
- * dependency to the runtime package.
753
- */
754
- function cleanDocsMarkdownHeadingLabel(value) {
755
- return value.replace(/!\[([^\]]*)\]\([^)]*\)/gu, "$1").replace(/\[([^\]]+)\]\([^)]*\)/gu, "$1").replace(/!\[([^\]]*)\]\[[^\]]*\]/gu, "$1").replace(/\[([^\]]+)\]\[[^\]]*\]/gu, "$1").replace(/<((?:https?:\/\/|mailto:)[^>]+)>/giu, "$1").replace(/<[^>]+>/gu, "").replace(/`+([^`]*?)`+/gu, "$1").replace(/\\([!"#$%&'()*+,\-./:;<=>?@[\]^_`{|}~])/gu, "$1").replace(/[*_~]/gu, "").replace(/&(#(?:x[0-9a-f]+|\d+)|[a-z]+);/giu, (_match, entity) => {
756
- if (entity.startsWith("#x") || entity.startsWith("#X")) {
757
- const codePoint = Number.parseInt(entity.slice(2), 16);
758
- return Number.isSafeInteger(codePoint) && codePoint >= 0 && codePoint <= 1114111 ? String.fromCodePoint(codePoint) : _match;
759
- }
760
- if (entity.startsWith("#")) {
761
- const codePoint = Number.parseInt(entity.slice(1), 10);
762
- return Number.isSafeInteger(codePoint) && codePoint >= 0 && codePoint <= 1114111 ? String.fromCodePoint(codePoint) : _match;
763
- }
764
- return HTML_ENTITIES[entity.toLowerCase()] ?? _match;
765
- }).replace(/\s+/gu, " ").trim();
766
- }
767
- /** Keep anchors aligned with the framework's existing ASCII heading-slug behavior. */
768
- function slugifyDocsMarkdownHeading(value) {
769
- return cleanDocsMarkdownHeadingLabel(value).toLowerCase().replace(/[`'"‘’“”]/gu, "").replace(/&/gu, " and ").replace(/[^a-z0-9\s-]/gu, "").replace(/\s+/gu, "-").replace(/-+/gu, "-").replace(/^-|-$/gu, "");
770
- }
771
- function readOpeningFence(line) {
772
- const match = line.match(/^ {0,3}(`{3,}|~{3,})/u);
773
- if (!match) return void 0;
774
- return {
775
- marker: match[1][0],
776
- length: match[1].length
777
- };
778
- }
779
- function isClosingFence(line, fence) {
780
- const marker = fence.marker === "`" ? "`" : "~";
781
- const match = line.match(new RegExp(`^ {0,3}(${marker}{${fence.length},})[\\t ]*$`, "u"));
782
- return Boolean(match);
783
- }
784
- function readAtxHeading(line) {
785
- const match = line.match(/^ {0,3}(#{1,6})(?:[\t ]+|$)(.*)$/u);
786
- if (!match) return void 0;
787
- return {
788
- title: cleanDocsMarkdownHeadingLabel(match[2].replace(/[\t ]+#+[\t ]*$/u, "").trim()),
789
- level: match[1].length
790
- };
791
- }
792
- function readSetextLevel(line) {
793
- const match = line.match(/^ {0,3}(=+|-+)[\t ]*$/u);
794
- if (!match) return void 0;
795
- return match[1][0] === "=" ? 1 : 2;
796
- }
797
- function normalizeDocsSectionSelector(value) {
798
- let selector = value.trim();
799
- const hashIndex = selector.lastIndexOf("#");
800
- if (hashIndex >= 0) selector = selector.slice(hashIndex + 1);
801
- try {
802
- selector = decodeURIComponent(selector);
803
- } catch {}
804
- return cleanDocsMarkdownHeadingLabel(selector.replace(/^#+/u, "")).toLowerCase();
805
- }
806
- /**
807
- * Parse heading sections once for search, Ask AI hydration, and MCP tools.
808
- * Supports CommonMark ATX indentation, Setext headings, fenced-code exclusion,
809
- * visible inline labels, and stable duplicate anchors.
810
- */
811
- function parseDocsMarkdownSections(markdown) {
812
- const lines = markdown.split(/\r?\n/u);
813
- const headings = [];
814
- const headingCounts = /* @__PURE__ */ new Map();
815
- let openFence;
816
- let setextCandidate;
817
- const pushHeading = (title, level, start) => {
818
- const baseAnchor = slugifyDocsMarkdownHeading(title) || `section-${headings.length}`;
819
- const seen = headingCounts.get(baseAnchor) ?? 0;
820
- headingCounts.set(baseAnchor, seen + 1);
821
- headings.push({
822
- title,
823
- anchor: seen === 0 ? baseAnchor : `${baseAnchor}-${seen}`,
824
- level,
825
- start
826
- });
827
- };
828
- for (let index = 0; index < lines.length; index += 1) {
829
- const line = lines[index];
830
- if (openFence) {
831
- if (isClosingFence(line, openFence)) openFence = void 0;
832
- setextCandidate = void 0;
833
- continue;
834
- }
835
- const openingFence = readOpeningFence(line);
836
- if (openingFence) {
837
- openFence = openingFence;
838
- setextCandidate = void 0;
839
- continue;
840
- }
841
- const setextLevel = readSetextLevel(line);
842
- if (setextLevel && setextCandidate?.index === index - 1) {
843
- const title = cleanDocsMarkdownHeadingLabel(setextCandidate.value.trim());
844
- if (title) pushHeading(title, setextLevel, setextCandidate.index);
845
- setextCandidate = void 0;
846
- continue;
847
- }
848
- const atxHeading = readAtxHeading(line);
849
- if (atxHeading) {
850
- pushHeading(atxHeading.title, atxHeading.level, index);
851
- setextCandidate = void 0;
852
- continue;
853
- }
854
- if (!line.trim() || /^ {4}|^\t/u.test(line)) {
855
- setextCandidate = void 0;
856
- continue;
857
- }
858
- setextCandidate = {
859
- index,
860
- value: line
861
- };
862
- }
863
- return headings.map((heading, index) => {
864
- const end = headings.slice(index + 1).find((candidate) => candidate.level <= heading.level)?.start ?? lines.length;
865
- return {
866
- title: heading.title,
867
- anchor: heading.anchor,
868
- level: heading.level,
869
- content: lines.slice(heading.start, end).join("\n").trim(),
870
- startLine: heading.start + 1,
871
- endLine: end
872
- };
873
- });
874
- }
875
- function findDocsMarkdownSection(markdown, requestedSection) {
876
- const selector = normalizeDocsSectionSelector(requestedSection);
877
- if (!selector) return void 0;
878
- return parseDocsMarkdownSections(markdown).find((section) => normalizeDocsSectionSelector(section.title) === selector || section.anchor === selector);
879
- }
880
-
881
151
  //#endregion
882
152
  //#region src/sitemap.ts
883
153
  const DEFAULT_SITEMAP_XML_ROUTE = "/sitemap.xml";
@@ -2146,6 +1416,543 @@ function findProtectedRanges(content) {
2146
1416
  const htmlLiterals = findHtmlLiteralRanges(content, excludedRanges);
2147
1417
  return mergeProtectedRanges([...excludedRanges, ...htmlLiterals]);
2148
1418
  }
1419
+ function findMarkdownLinkLiteralRanges(content) {
1420
+ try {
1421
+ const offsetAdjustment = content.startsWith("") ? 1 : 0;
1422
+ const tree = docsAudienceMarkdownProcessor.parse(offsetAdjustment > 0 ? content.slice(offsetAdjustment) : content);
1423
+ const ranges = [];
1424
+ const visit = (node) => {
1425
+ const rawStart = getOffset(node.position, "start");
1426
+ const rawEnd = getOffset(node.position, "end");
1427
+ const start = rawStart === void 0 ? void 0 : rawStart + offsetAdjustment;
1428
+ const end = rawEnd === void 0 ? void 0 : rawEnd + offsetAdjustment;
1429
+ if (start !== void 0 && end !== void 0 && (node.type === "link" || node.type === "image" || node.type === "linkReference" || node.type === "imageReference")) {
1430
+ ranges.push({
1431
+ start,
1432
+ end
1433
+ });
1434
+ return;
1435
+ }
1436
+ for (const child of node.children ?? []) visit(child);
1437
+ };
1438
+ visit(tree);
1439
+ return ranges;
1440
+ } catch {
1441
+ return [];
1442
+ }
1443
+ }
1444
+ function findDocsMarkdownPromptBracketLiteralRanges(content, protectedRanges) {
1445
+ const ranges = [];
1446
+ let cursor = 0;
1447
+ while (cursor < content.length) {
1448
+ const index = content.indexOf("[", cursor);
1449
+ if (index === -1 || isEscapedAt(content, index) || isInsideRange(index, protectedRanges)) {
1450
+ if (index === -1) break;
1451
+ cursor = index + 1;
1452
+ continue;
1453
+ }
1454
+ let depth = 1;
1455
+ let end = index + 1;
1456
+ while (end < content.length && depth > 0) {
1457
+ if (content[end] === "\\") {
1458
+ end += 2;
1459
+ continue;
1460
+ }
1461
+ if (content[end] === "[") depth += 1;
1462
+ if (content[end] === "]") depth -= 1;
1463
+ end += 1;
1464
+ }
1465
+ if (depth !== 0) {
1466
+ cursor = index + 1;
1467
+ continue;
1468
+ }
1469
+ const label = content.slice(index + 1, end - 1);
1470
+ if (/<Prompt(?=[\s/>])/.test(label) && /<\/Prompt\s*>/.test(label)) {
1471
+ let rangeEnd = end;
1472
+ if (content[rangeEnd] === "[") {
1473
+ let referenceEnd = rangeEnd + 1;
1474
+ while (referenceEnd < content.length) {
1475
+ if (content[referenceEnd] === "\\") {
1476
+ referenceEnd += 2;
1477
+ continue;
1478
+ }
1479
+ if (content[referenceEnd] === "]") {
1480
+ referenceEnd += 1;
1481
+ break;
1482
+ }
1483
+ referenceEnd += 1;
1484
+ }
1485
+ if (content[referenceEnd - 1] === "]") rangeEnd = referenceEnd;
1486
+ }
1487
+ ranges.push({
1488
+ start: content[index - 1] === "!" ? index - 1 : index,
1489
+ end: rangeEnd
1490
+ });
1491
+ }
1492
+ cursor = end;
1493
+ }
1494
+ return ranges;
1495
+ }
1496
+ const DOCS_MARKDOWN_INTRINSIC_CONTAINER_NAMES = new Set([
1497
+ "a",
1498
+ "abbr",
1499
+ "address",
1500
+ "article",
1501
+ "aside",
1502
+ "audio",
1503
+ "b",
1504
+ "bdi",
1505
+ "bdo",
1506
+ "blockquote",
1507
+ "body",
1508
+ "button",
1509
+ "canvas",
1510
+ "caption",
1511
+ "cite",
1512
+ "code",
1513
+ "colgroup",
1514
+ "data",
1515
+ "datalist",
1516
+ "dd",
1517
+ "del",
1518
+ "details",
1519
+ "dfn",
1520
+ "dialog",
1521
+ "div",
1522
+ "dl",
1523
+ "dt",
1524
+ "em",
1525
+ "fieldset",
1526
+ "figcaption",
1527
+ "figure",
1528
+ "footer",
1529
+ "form",
1530
+ "h1",
1531
+ "h2",
1532
+ "h3",
1533
+ "h4",
1534
+ "h5",
1535
+ "h6",
1536
+ "head",
1537
+ "header",
1538
+ "hgroup",
1539
+ "html",
1540
+ "i",
1541
+ "iframe",
1542
+ "ins",
1543
+ "kbd",
1544
+ "label",
1545
+ "legend",
1546
+ "li",
1547
+ "main",
1548
+ "map",
1549
+ "mark",
1550
+ "math",
1551
+ "menu",
1552
+ "meter",
1553
+ "nav",
1554
+ "noembed",
1555
+ "noframes",
1556
+ "noscript",
1557
+ "object",
1558
+ "ol",
1559
+ "optgroup",
1560
+ "option",
1561
+ "output",
1562
+ "p",
1563
+ "picture",
1564
+ "pre",
1565
+ "progress",
1566
+ "q",
1567
+ "rp",
1568
+ "rt",
1569
+ "ruby",
1570
+ "s",
1571
+ "samp",
1572
+ "script",
1573
+ "search",
1574
+ "section",
1575
+ "select",
1576
+ "slot",
1577
+ "small",
1578
+ "span",
1579
+ "strong",
1580
+ "style",
1581
+ "sub",
1582
+ "summary",
1583
+ "sup",
1584
+ "svg",
1585
+ "table",
1586
+ "tbody",
1587
+ "td",
1588
+ "template",
1589
+ "textarea",
1590
+ "tfoot",
1591
+ "th",
1592
+ "thead",
1593
+ "time",
1594
+ "title",
1595
+ "tr",
1596
+ "u",
1597
+ "ul",
1598
+ "var",
1599
+ "video",
1600
+ "xmp"
1601
+ ]);
1602
+ function normalizeDocsMarkdownIntrinsicContainerName(name) {
1603
+ const normalized = name.toLowerCase();
1604
+ if (!DOCS_MARKDOWN_INTRINSIC_CONTAINER_NAMES.has(normalized)) return void 0;
1605
+ const isLowercase = name === normalized;
1606
+ const isUppercase = name === name.toUpperCase() && /[A-Z]/.test(name);
1607
+ return isLowercase || isUppercase ? normalized : void 0;
1608
+ }
1609
+ function readDocsMarkdownPromptTagAt(content, index) {
1610
+ const closing = content[index + 1] === "/";
1611
+ const nameStart = index + (closing ? 2 : 1);
1612
+ if (!content.startsWith("Prompt", nameStart) || !/[\s/>]/.test(content[nameStart + 6] ?? "")) return;
1613
+ const tag = readGenericMdxJsxTag(content, index);
1614
+ if (!tag) return void 0;
1615
+ const attributesStart = nameStart + 6;
1616
+ let attributesEnd = tag.end - 1;
1617
+ while (attributesEnd > attributesStart && /\s/.test(content[attributesEnd - 1] ?? "")) attributesEnd -= 1;
1618
+ if (content[attributesEnd - 1] === "/") attributesEnd -= 1;
1619
+ return {
1620
+ attributes: closing ? "" : content.slice(attributesStart, attributesEnd),
1621
+ closing,
1622
+ end: tag.end,
1623
+ index,
1624
+ selfClosing: tag.selfClosing
1625
+ };
1626
+ }
1627
+ function findDocsMarkdownHtmlContainerLiteralRanges(content, protectedRanges) {
1628
+ const ranges = [];
1629
+ const openings = [];
1630
+ let cursor = 0;
1631
+ while (cursor < content.length) {
1632
+ const index = content.indexOf("<", cursor);
1633
+ if (index === -1) break;
1634
+ if (isEscapedAt(content, index) || isInsideRange(index, protectedRanges)) {
1635
+ cursor = index + 1;
1636
+ continue;
1637
+ }
1638
+ const closing = content[index + 1] === "/";
1639
+ const nameStart = index + (closing ? 2 : 1);
1640
+ let nameEnd = nameStart;
1641
+ while (/[\w:.-]/.test(content[nameEnd] ?? "")) nameEnd += 1;
1642
+ const name = normalizeDocsMarkdownIntrinsicContainerName(content.slice(nameStart, nameEnd));
1643
+ if (!name) {
1644
+ cursor = index + 1;
1645
+ continue;
1646
+ }
1647
+ const tag = readGenericMdxJsxTag(content, index);
1648
+ if (!tag) {
1649
+ cursor = index + 1;
1650
+ continue;
1651
+ }
1652
+ cursor = tag.end;
1653
+ if (!closing) {
1654
+ if (!tag.selfClosing) openings.push({
1655
+ name,
1656
+ start: index
1657
+ });
1658
+ continue;
1659
+ }
1660
+ let openingIndex = openings.length - 1;
1661
+ while (openingIndex >= 0 && openings[openingIndex].name !== name) openingIndex -= 1;
1662
+ if (openingIndex < 0) continue;
1663
+ const [opening] = openings.splice(openingIndex);
1664
+ ranges.push({
1665
+ start: opening.start,
1666
+ end: tag.end
1667
+ });
1668
+ }
1669
+ return ranges;
1670
+ }
1671
+ function isStandaloneDocsMarkdownPromptHtmlRange(content, start, end) {
1672
+ while (start < end && /\s/.test(content[start] ?? "")) start += 1;
1673
+ while (end > start && /\s/.test(content[end - 1] ?? "")) end -= 1;
1674
+ return readDocsMarkdownPromptTagAt(content, start) !== void 0;
1675
+ }
1676
+ function findDocsMarkdownRawHtmlLiteralRanges(content) {
1677
+ try {
1678
+ const offsetAdjustment = content.startsWith("") ? 1 : 0;
1679
+ const tree = docsAudienceMarkdownProcessor.parse(offsetAdjustment > 0 ? content.slice(offsetAdjustment) : content);
1680
+ const ranges = [];
1681
+ const visit = (node) => {
1682
+ const rawStart = getOffset(node.position, "start");
1683
+ const rawEnd = getOffset(node.position, "end");
1684
+ const start = rawStart === void 0 ? void 0 : rawStart + offsetAdjustment;
1685
+ const end = rawEnd === void 0 ? void 0 : rawEnd + offsetAdjustment;
1686
+ if (node.type === "html" && start !== void 0 && end !== void 0) {
1687
+ if (isStandaloneDocsMarkdownPromptHtmlRange(content, start, end)) return;
1688
+ const elementName = content.slice(start, end).trimStart().match(/^<\/?([A-Za-z][\w:.-]*)(?=[\s/>])/)?.[1];
1689
+ if (elementName && !normalizeDocsMarkdownIntrinsicContainerName(elementName)) return;
1690
+ let cursor = start;
1691
+ let promptDepth = 0;
1692
+ let trailingClosingPrompt;
1693
+ while (cursor < end) {
1694
+ const index = content.indexOf("<", cursor);
1695
+ if (index === -1 || index >= end) break;
1696
+ const tag = readDocsMarkdownPromptTagAt(content, index);
1697
+ if (!tag || tag.end > end) {
1698
+ cursor = index + 1;
1699
+ continue;
1700
+ }
1701
+ if (!tag.closing && !tag.selfClosing) promptDepth += 1;
1702
+ else if (tag.closing && promptDepth > 0) promptDepth -= 1;
1703
+ else if (tag.closing && content.slice(tag.end, end).trim().length === 0) trailingClosingPrompt = tag.index;
1704
+ cursor = tag.end;
1705
+ }
1706
+ const literalEnd = trailingClosingPrompt ?? end;
1707
+ if (literalEnd > start) ranges.push({
1708
+ start,
1709
+ end: literalEnd
1710
+ });
1711
+ return;
1712
+ }
1713
+ for (const child of node.children ?? []) visit(child);
1714
+ };
1715
+ visit(tree);
1716
+ return ranges;
1717
+ } catch {
1718
+ return [];
1719
+ }
1720
+ }
1721
+ function findDocsMarkdownPromptAstInfo(content) {
1722
+ try {
1723
+ const prepared = prepareMdxParserSource(content);
1724
+ const offsetAdjustment = prepared.startsWith("") ? 1 : 0;
1725
+ const tree = docsAudienceMdxProcessor.parse(offsetAdjustment > 0 ? prepared.slice(offsetAdjustment) : prepared);
1726
+ const flowStarts = /* @__PURE__ */ new Set();
1727
+ const starts = /* @__PURE__ */ new Set();
1728
+ const visit = (node) => {
1729
+ if (node.name === "Prompt" && (node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") && getOffset(node.position, "start") !== void 0) {
1730
+ const start = getOffset(node.position, "start") + offsetAdjustment;
1731
+ starts.add(start);
1732
+ if (node.type === "mdxJsxFlowElement") flowStarts.add(start);
1733
+ }
1734
+ for (const child of node.children ?? []) visit(child);
1735
+ };
1736
+ visit(tree);
1737
+ return {
1738
+ flowStarts,
1739
+ starts
1740
+ };
1741
+ } catch {
1742
+ return;
1743
+ }
1744
+ }
1745
+ function findDocsMarkdownPromptExpressionRanges(content, protectedRanges) {
1746
+ const ranges = [];
1747
+ let protectedIndex = 0;
1748
+ let cursor = 0;
1749
+ while (cursor < content.length) {
1750
+ const start = content.indexOf("{", cursor);
1751
+ if (start === -1) break;
1752
+ if (isEscapedAt(content, start) || isInsideRange(start, protectedRanges)) {
1753
+ cursor = start + 1;
1754
+ continue;
1755
+ }
1756
+ let depth = 1;
1757
+ let end = start + 1;
1758
+ while (end < content.length && depth > 0) {
1759
+ while (protectedIndex < protectedRanges.length && protectedRanges[protectedIndex].end <= end) protectedIndex += 1;
1760
+ const candidate = protectedRanges[protectedIndex];
1761
+ const protectedRange = candidate && end >= candidate.start && end < candidate.end ? candidate : void 0;
1762
+ if (protectedRange) {
1763
+ end = protectedRange.end;
1764
+ continue;
1765
+ }
1766
+ if (content[end] === "{") depth += 1;
1767
+ if (content[end] === "}") depth -= 1;
1768
+ end += 1;
1769
+ }
1770
+ ranges.push({
1771
+ start,
1772
+ end: depth === 0 ? end : content.length
1773
+ });
1774
+ if (depth !== 0) break;
1775
+ cursor = end;
1776
+ }
1777
+ return ranges;
1778
+ }
1779
+ function createDocsMarkdownPromptToken(content, used, startAt) {
1780
+ let index = startAt;
1781
+ let token = "";
1782
+ do {
1783
+ token = `%%PROMPT_${index}%%`;
1784
+ index += 1;
1785
+ } while (content.includes(token) || used.has(token));
1786
+ return token;
1787
+ }
1788
+ function isFallbackDocsMarkdownPromptFlow(content, opening, closing) {
1789
+ const lineStart = Math.max(0, content.lastIndexOf("\n", opening.index - 1) + 1);
1790
+ const prefix = content.slice(lineStart, opening.index);
1791
+ if (!/^[\t ]{0,3}$/.test(prefix)) return false;
1792
+ const lineEnd = content.indexOf("\n", closing.end);
1793
+ const suffix = content.slice(closing.end, lineEnd === -1 ? content.length : lineEnd);
1794
+ return content.slice(opening.end, closing.index).includes("\n") || /^[\t\r ]*$/.test(suffix);
1795
+ }
1796
+ function resolveDocsMarkdownPromptContainer(content, opening) {
1797
+ const lineStart = Math.max(0, content.lastIndexOf("\n", opening.index - 1) + 1);
1798
+ let prefix = content.slice(lineStart, opening.index);
1799
+ let blockquoteDepth = 0;
1800
+ let listIndent = 0;
1801
+ while (true) {
1802
+ const blockquote = /^ {0,3}>[\t ]?/.exec(prefix);
1803
+ if (!blockquote) break;
1804
+ blockquoteDepth += 1;
1805
+ prefix = prefix.slice(blockquote[0].length);
1806
+ }
1807
+ while (true) {
1808
+ const list = /^ {0,3}(?:[-+*]|\d{1,9}[.)])[\t ]+/.exec(prefix);
1809
+ if (!list) break;
1810
+ listIndent += list[0].length;
1811
+ prefix = prefix.slice(list[0].length);
1812
+ }
1813
+ if (listIndent === 0 && /^[\t ]+$/.test(prefix)) {
1814
+ let previousLineEnd = Math.max(0, lineStart - 1);
1815
+ while (previousLineEnd > 0) {
1816
+ const previousLineStart = Math.max(0, content.lastIndexOf("\n", previousLineEnd - 1) + 1);
1817
+ let previousLine = content.slice(previousLineStart, previousLineEnd).replace(/\r$/, "");
1818
+ for (let depth = 0; depth < blockquoteDepth; depth += 1) {
1819
+ const blockquote = /^ {0,3}>[\t ]?/.exec(previousLine);
1820
+ if (!blockquote) {
1821
+ previousLine = "";
1822
+ break;
1823
+ }
1824
+ previousLine = previousLine.slice(blockquote[0].length);
1825
+ }
1826
+ const list = /^ {0,3}(?:[-+*]|\d{1,9}[.)])[\t ]+/.exec(previousLine);
1827
+ if (list && prefix.length >= list[0].length) {
1828
+ listIndent = list[0].length;
1829
+ break;
1830
+ }
1831
+ if (previousLine.trim().length === 0) break;
1832
+ previousLineEnd = Math.max(0, previousLineStart - 1);
1833
+ }
1834
+ }
1835
+ if (blockquoteDepth === 0 && listIndent === 0 || !/^[\t ]*$/.test(prefix)) return;
1836
+ return {
1837
+ blockquoteDepth,
1838
+ listIndent
1839
+ };
1840
+ }
1841
+ function stripDocsMarkdownPromptContainer(children, container) {
1842
+ if (!container) return children;
1843
+ return children.split(/(\r?\n)/).map((segment, index) => {
1844
+ if (index % 2 === 1) return segment;
1845
+ let line = segment;
1846
+ for (let depth = 0; depth < container.blockquoteDepth; depth += 1) {
1847
+ const blockquote = /^ {0,3}>[\t ]?/.exec(line);
1848
+ if (!blockquote) break;
1849
+ line = line.slice(blockquote[0].length);
1850
+ }
1851
+ let remainingIndent = container.listIndent;
1852
+ while (remainingIndent > 0 && /^[\t ]/.test(line)) {
1853
+ line = line.slice(1);
1854
+ remainingIndent -= 1;
1855
+ }
1856
+ return line;
1857
+ }).join("");
1858
+ }
1859
+ function createDocsMarkdownPromptReplacement(content, start, end, token, flow, container, adjacentFlowBefore = false, adjacentFlowAfter = false) {
1860
+ if (!flow || container) return token;
1861
+ const newline = content.includes("\r\n") ? "\r\n" : "\n";
1862
+ const before = content.slice(0, start);
1863
+ const after = content.slice(end);
1864
+ const leading = adjacentFlowBefore || before.length === 0 || /(?:\r?\n){2}$/.test(before) ? "" : /\r?\n$/.test(before) ? newline : newline + newline;
1865
+ const trailing = adjacentFlowAfter || after.length === 0 || /^(?:\r?\n){2}/.test(after) ? "" : /^\r?\n/.test(after) ? newline : newline + newline;
1866
+ return leading + token + trailing;
1867
+ }
1868
+ /**
1869
+ * Extract live MDX Prompt blocks while leaving Markdown literals untouched.
1870
+ *
1871
+ * Prompt bodies are copyable source, so callers can safely run audience,
1872
+ * reference-definition, and heading passes over `markdown`, then restore each
1873
+ * block from its token. Fences (including container fences), inline code, links,
1874
+ * comments, raw elements, and other literal contexts are never extracted.
1875
+ */
1876
+ function extractDocsMarkdownPromptBlocks(content) {
1877
+ if (!/<Prompt(?=[\s/>])/.test(content)) return {
1878
+ blocks: [],
1879
+ markdown: content
1880
+ };
1881
+ const syntaxProtectedRanges = mergeProtectedRanges([...findProtectedRanges(content), ...findMarkdownLinkLiteralRanges(content)]);
1882
+ const expressionRanges = findDocsMarkdownPromptExpressionRanges(content, syntaxProtectedRanges);
1883
+ const baseProtectedRanges = mergeProtectedRanges([
1884
+ ...syntaxProtectedRanges,
1885
+ ...expressionRanges,
1886
+ ...findDocsMarkdownRawHtmlLiteralRanges(content),
1887
+ ...findDocsMarkdownHtmlContainerLiteralRanges(content, syntaxProtectedRanges)
1888
+ ]);
1889
+ const protectedRanges = mergeProtectedRanges([...baseProtectedRanges, ...findDocsMarkdownPromptBracketLiteralRanges(content, baseProtectedRanges)]);
1890
+ const promptAst = findDocsMarkdownPromptAstInfo(content);
1891
+ const pairs = [];
1892
+ const openings = [];
1893
+ let cursor = 0;
1894
+ while (cursor < content.length) {
1895
+ const index = content.indexOf("<", cursor);
1896
+ if (index === -1) break;
1897
+ if (isEscapedAt(content, index) || isInsideRange(index, protectedRanges)) {
1898
+ cursor = index + 1;
1899
+ continue;
1900
+ }
1901
+ const tag = readDocsMarkdownPromptTagAt(content, index);
1902
+ if (!tag) {
1903
+ cursor = index + 1;
1904
+ continue;
1905
+ }
1906
+ cursor = tag.end;
1907
+ if (!tag.closing) {
1908
+ if (promptAst && !promptAst.starts.has(tag.index)) continue;
1909
+ if (!tag.selfClosing) openings.push({
1910
+ completedChildren: [],
1911
+ tag
1912
+ });
1913
+ continue;
1914
+ }
1915
+ const frame = openings.pop();
1916
+ if (!frame) continue;
1917
+ const container = resolveDocsMarkdownPromptContainer(content, frame.tag);
1918
+ const pair = {
1919
+ attributes: frame.tag.attributes,
1920
+ children: stripDocsMarkdownPromptContainer(content.slice(frame.tag.end, tag.index), container),
1921
+ container,
1922
+ end: tag.end,
1923
+ flow: promptAst?.flowStarts.has(frame.tag.index) === true || isFallbackDocsMarkdownPromptFlow(content, frame.tag, tag),
1924
+ start: frame.tag.index
1925
+ };
1926
+ const parent = openings.at(-1);
1927
+ if (parent) parent.completedChildren.push(pair);
1928
+ else pairs.push(pair);
1929
+ }
1930
+ for (const frame of openings) pairs.push(...frame.completedChildren);
1931
+ pairs.sort((left, right) => left.start - right.start);
1932
+ if (pairs.length === 0) return {
1933
+ blocks: [],
1934
+ markdown: content
1935
+ };
1936
+ const usedTokens = /* @__PURE__ */ new Set();
1937
+ const blocks = pairs.map((pair, index) => {
1938
+ const token = createDocsMarkdownPromptToken(content, usedTokens, index);
1939
+ usedTokens.add(token);
1940
+ return {
1941
+ attributes: pair.attributes,
1942
+ children: pair.children,
1943
+ token
1944
+ };
1945
+ });
1946
+ let markdown = content;
1947
+ for (let index = pairs.length - 1; index >= 0; index -= 1) {
1948
+ const replacement = createDocsMarkdownPromptReplacement(content, pairs[index].start, pairs[index].end, blocks[index].token, pairs[index].flow, pairs[index].container, index > 0 && pairs[index - 1].flow && /^[\t \r\n]*$/.test(content.slice(pairs[index - 1].end, pairs[index].start)), index + 1 < pairs.length && pairs[index + 1].flow && /^[\t \r\n]*$/.test(content.slice(pairs[index].end, pairs[index + 1].start)));
1949
+ markdown = markdown.slice(0, pairs[index].start) + replacement + markdown.slice(pairs[index].end);
1950
+ }
1951
+ return {
1952
+ blocks,
1953
+ markdown
1954
+ };
1955
+ }
2149
1956
  function normalizeProjectedWhitespace(content) {
2150
1957
  const protectedRanges = findProtectedRanges(content);
2151
1958
  return content.replace(/\n{3,}/g, (newlines, offset) => {
@@ -2320,7 +2127,7 @@ const DEFAULT_DOCS_DIAGNOSTICS_MCP_TOOLS = {
2320
2127
  getContext: true
2321
2128
  };
2322
2129
  const DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER = "Signature-Agent";
2323
- const DOCS_MARKDOWN_SECTION_INDEX_FORMAT = "docs-markdown-sections.v1";
2130
+ const DOCS_MARKDOWN_SECTION_INDEX_FORMAT = "docs-markdown-sections.v2";
2324
2131
  const DOCS_AI_AGENT_USER_AGENT_PATTERNS = [
2325
2132
  "claudebot",
2326
2133
  "claude-searchbot",
@@ -2389,6 +2196,7 @@ const DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN = buildDocsUserAgentHeaderPattern(
2389
2196
  const DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN = buildDocsUserAgentHeaderPattern(DOCS_TRADITIONAL_BOT_USER_AGENT_PATTERNS);
2390
2197
  const DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN = buildDocsUserAgentHeaderPattern(DOCS_BOT_LIKE_USER_AGENT_TERMS);
2391
2198
  const DOCS_LLMS_TXT_DIRECTIVE_LINE = "LLM index: /llms.txt";
2199
+ const DOCS_MARKDOWN_GENERATED_PREAMBLE_FIELD = "x_farming_labs_generated_preamble";
2392
2200
  const DOCS_MCP_SERVICE_SUBDOMAIN_LABELS = new Set([
2393
2201
  "api",
2394
2202
  "developer",
@@ -2610,12 +2418,22 @@ function buildDocsDiagnostics(config, options = {}) {
2610
2418
  route: search.enabled ? apiQueryRoute("query={query}") : null,
2611
2419
  routes: {
2612
2420
  human: search.enabled ? apiQueryRoute("query={query}") : null,
2613
- agent: search.enabled ? apiQueryRoute("query={query}&audience=agent") : null
2421
+ agent: search.enabled ? apiQueryRoute("query={query}&audience=agent") : null,
2422
+ structuredAgent: search.enabled ? apiQueryRoute("query={query}&audience=agent&response=structured") : null
2614
2423
  },
2615
2424
  agentEndpoint: search.enabled ? apiQueryRoute("query={query}&audience=agent") : null,
2425
+ structuredAgentEndpoint: search.enabled ? apiQueryRoute("query={query}&audience=agent&response=structured") : null,
2616
2426
  audienceParam: "audience",
2617
2427
  defaultAudience: "human",
2618
2428
  supportedAudiences: ["human", "agent"],
2429
+ filterParams: {
2430
+ framework: "framework",
2431
+ version: "version",
2432
+ package: "package",
2433
+ tags: "tags"
2434
+ },
2435
+ responseFormat: "docs-search.v1",
2436
+ warningsField: "warnings",
2619
2437
  provider: search.provider,
2620
2438
  transport: "GET"
2621
2439
  },
@@ -3127,7 +2945,9 @@ function validateDocsAgentFeedbackPayload(value, schema, valuePath = "payload")
3127
2945
  }
3128
2946
  }
3129
2947
  function toDocsMarkdownUrl(url, options = {}) {
3130
- const [withoutHash, hash = ""] = url.split("#", 2);
2948
+ const hashIndex = url.indexOf("#");
2949
+ const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
2950
+ const hash = hashIndex >= 0 ? url.slice(hashIndex + 1) : "";
3131
2951
  const [pathname, query = ""] = withoutHash.split("?", 2);
3132
2952
  const normalizedPath = normalizeDocsUrlPath(pathname || "/");
3133
2953
  const markdownPath = normalizedPath.endsWith(".md") ? normalizedPath : `${normalizedPath}.md`;
@@ -3758,7 +3578,7 @@ function resolveDocsMarkdownMetadataUrl(value, origin) {
3758
3578
  return value;
3759
3579
  }
3760
3580
  }
3761
- function renderDocsMarkdownFrontmatter({ title, description, canonicalUrl, markdownUrl, lastUpdated, agent }) {
3581
+ function renderDocsMarkdownFrontmatter({ title, description, canonicalUrl, markdownUrl, lastUpdated, agent, generatedPreamble }) {
3762
3582
  return [
3763
3583
  "---",
3764
3584
  `title: ${toYamlString(title)}`,
@@ -3766,6 +3586,7 @@ function renderDocsMarkdownFrontmatter({ title, description, canonicalUrl, markd
3766
3586
  `canonical_url: ${toYamlString(canonicalUrl)}`,
3767
3587
  `markdown_url: ${toYamlString(markdownUrl)}`,
3768
3588
  ...lastUpdated ? [`last_updated: ${toYamlString(lastUpdated)}`] : [],
3589
+ ...generatedPreamble ? [`${DOCS_MARKDOWN_GENERATED_PREAMBLE_FIELD}: true`] : [],
3769
3590
  ...renderPageAgentFrontmatterYamlLines(agent),
3770
3591
  "---"
3771
3592
  ].join("\n");
@@ -3788,14 +3609,14 @@ function stripDocsMarkdownFrontmatter(markdown) {
3788
3609
  body: match[2] ?? ""
3789
3610
  };
3790
3611
  }
3791
- function slugifyPublicDocsMarkdownSectionId(value) {
3792
- return value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/`([^`]+)`/g, "$1").replace(/<[^>]*>/g, "").replace(/[^\p{L}\p{N}\s-]/gu, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
3793
- }
3794
3612
  function resolveDocsMarkdownSectionBody(document) {
3795
- const lines = stripDocsMarkdownFrontmatter(document).body.split(/\r?\n/u);
3613
+ const stripped = stripDocsMarkdownFrontmatter(document);
3614
+ const hasGeneratedPreamble = stripped.frontmatter.split(/\r?\n/u).some((line) => line.trim() === `${DOCS_MARKDOWN_GENERATED_PREAMBLE_FIELD}: true`);
3615
+ const lines = stripped.body.split(/\r?\n/u);
3796
3616
  let generatedPreambleStart = 0;
3797
3617
  while (generatedPreambleStart < lines.length && (lines[generatedPreambleStart] ?? "").trim() === "") generatedPreambleStart += 1;
3798
- if (/^#(?:\s+|$)/u.test(lines[generatedPreambleStart] ?? "") && /^URL:\s+\S/u.test(lines[generatedPreambleStart + 1] ?? "")) {
3618
+ if (hasGeneratedPreamble && /^#(?:\s+|$)/u.test(lines[generatedPreambleStart] ?? "") && /^URL:\s+\S/u.test(lines[generatedPreambleStart + 1] ?? "")) {
3619
+ lines[generatedPreambleStart] = "";
3799
3620
  let metadataEnd = generatedPreambleStart + 2;
3800
3621
  while (/^(?:LLM index|Description|Related):\s*/u.test(lines[metadataEnd] ?? "")) metadataEnd += 1;
3801
3622
  for (let index = generatedPreambleStart + 1; index < metadataEnd; index += 1) lines[index] = "";
@@ -3875,21 +3696,14 @@ function isDocsMarkdownSectionIndexRequest(url) {
3875
3696
  }
3876
3697
  function collectDocsMarkdownSections(document) {
3877
3698
  const { body, lineOffset } = resolveDocsMarkdownSectionBody(document);
3878
- const seen = /* @__PURE__ */ new Map();
3879
- return parseDocsMarkdownSections(body).flatMap((section) => {
3880
- const baseId = slugifyPublicDocsMarkdownSectionId(section.title);
3881
- if (!baseId) return [];
3882
- const count = seen.get(baseId) ?? 0;
3883
- seen.set(baseId, count + 1);
3884
- return [{
3885
- id: count === 0 ? baseId : `${baseId}-${count + 1}`,
3886
- heading: section.title,
3887
- level: section.level,
3888
- content: section.content,
3889
- startLine: section.startLine + lineOffset,
3890
- endLine: section.endLine + lineOffset
3891
- }];
3892
- });
3699
+ return parseDocsMarkdownSections(body).map((section) => ({
3700
+ id: section.anchor,
3701
+ heading: section.title,
3702
+ level: section.level,
3703
+ content: section.content,
3704
+ startLine: section.startLine + lineOffset,
3705
+ endLine: section.endLine + lineOffset
3706
+ }));
3893
3707
  }
3894
3708
  function updateDocsMarkdownUrl(value, update) {
3895
3709
  const isAbsolute = /^[a-z][a-z\d+.-]*:/iu.test(value);
@@ -3903,7 +3717,7 @@ function updateDocsMarkdownUrl(value, update) {
3903
3717
  }
3904
3718
  function resolveDocsMarkdownSectionCanonicalUrl(canonicalUrl, sectionId) {
3905
3719
  return updateDocsMarkdownUrl(canonicalUrl, (url) => {
3906
- url.hash = sectionId;
3720
+ url.hash = encodeURIComponent(sectionId);
3907
3721
  });
3908
3722
  }
3909
3723
  function resolveDocsMarkdownSectionFetchUrl(markdownUrl, sectionId, request) {
@@ -3962,7 +3776,7 @@ function buildDocsMarkdownSectionIndex(document, options) {
3962
3776
  ...request.byteBudget ? { byteBudget: request.byteBudget } : {}
3963
3777
  } : void 0;
3964
3778
  return {
3965
- schemaVersion: 1,
3779
+ schemaVersion: 2,
3966
3780
  format: DOCS_MARKDOWN_SECTION_INDEX_FORMAT,
3967
3781
  canonicalUrl: options.canonicalUrl,
3968
3782
  markdownUrl: options.markdownUrl,
@@ -3977,12 +3791,12 @@ function buildDocsMarkdownSectionIndex(document, options) {
3977
3791
  }
3978
3792
  function normalizeRequestedDocsMarkdownSectionId(requestedSection) {
3979
3793
  let selector = requestedSection.trim();
3980
- const hashIndex = selector.lastIndexOf("#");
3794
+ const hashIndex = selector.indexOf("#");
3981
3795
  if (hashIndex >= 0) selector = selector.slice(hashIndex + 1);
3982
3796
  try {
3983
3797
  selector = decodeURIComponent(selector);
3984
3798
  } catch {}
3985
- return selector.replace(/^#+/u, "").toLowerCase();
3799
+ return selector;
3986
3800
  }
3987
3801
  function selectDocsMarkdownSection(document, request) {
3988
3802
  const availableSections = collectDocsMarkdownSections(document);
@@ -4000,8 +3814,12 @@ function selectDocsMarkdownSection(document, request) {
4000
3814
  availableSections
4001
3815
  };
4002
3816
  }
3817
+ const rawRequestedId = requestedSection.trim();
3818
+ const rawExactSection = availableSections.find((candidate) => candidate.id === rawRequestedId);
4003
3819
  const requestedId = normalizeRequestedDocsMarkdownSectionId(requestedSection);
4004
- const directSection = availableSections.find((candidate) => candidate.id === requestedId);
3820
+ const exactSection = rawExactSection ?? availableSections.find((candidate) => candidate.id === requestedId);
3821
+ const caseInsensitiveSections = exactSection ? [] : availableSections.filter((candidate) => candidate.id.toLowerCase() === requestedId.toLowerCase());
3822
+ const directSection = exactSection ?? (caseInsensitiveSections.length === 1 ? caseInsensitiveSections[0] : void 0);
4005
3823
  const { body, lineOffset } = resolveDocsMarkdownSectionBody(document);
4006
3824
  const selectedSharedSection = directSection ? void 0 : findDocsMarkdownSection(body, requestedSection);
4007
3825
  const sharedAliasSection = selectedSharedSection ? availableSections.find((candidate) => candidate.startLine === selectedSharedSection.startLine + lineOffset) : void 0;
@@ -4078,7 +3896,7 @@ function renderDocsMarkdownNotFound({ entry = "docs", apiRoute, requestedPath, o
4078
3896
  lines.push(`- [${match.title}](${match.markdownUrl}) (${confidence} confidence)${match.description ? ` - ${match.description}` : ""}`);
4079
3897
  }
4080
3898
  }
4081
- lines.push("", "## Recovery", "", "- If a closest match looks right, fetch that markdown URL directly.", "- If the match is uncertain, search the docs first and then fetch the smallest page that answers the task.", "- Use the sitemap routes below to browse the full docs index before guessing another slug.", "", "## Discovery Routes", "", "Use these discovery routes to find the right page:", "", `- Agent discovery spec: \`${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}\``, `- Agent discovery fallback: \`${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}\``, `- Agent discovery API: \`${agentSpecApiRoute}\``, `- API catalog: \`${DEFAULT_API_CATALOG_ROUTE}\``, `- Agent Skills index: \`${DEFAULT_AGENT_SKILLS_INDEX_ROUTE}\``, `- Agent instructions: \`${DEFAULT_AGENTS_MD_ROUTE}\``, `- Agent search endpoint: \`${resolvedApiRoute}?query={query}&audience=agent\``, `- Docs index markdown: \`/${normalizedEntry}.md\``, `- Requested markdown API route: \`${requestedApiRoute}\``);
3899
+ lines.push("", "## Recovery", "", "- If a closest match looks right, fetch that markdown URL directly.", "- If the match is uncertain, search the docs first and then fetch the smallest page that answers the task.", "- Use the sitemap routes below to browse the full docs index before guessing another slug.", "", "## Discovery Routes", "", "Use these discovery routes to find the right page:", "", `- Agent discovery spec: \`${DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE}\``, `- Agent discovery fallback: \`${DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE}\``, `- Agent discovery API: \`${agentSpecApiRoute}\``, `- API catalog: \`${DEFAULT_API_CATALOG_ROUTE}\``, `- Agent Skills index: \`${DEFAULT_AGENT_SKILLS_INDEX_ROUTE}\``, `- Agent instructions: \`${DEFAULT_AGENTS_MD_ROUTE}\``, `- Structured agent search: \`${resolvedApiRoute}?query={query}&audience=agent&response=structured\` (optionally repeat \`framework\`, \`version\`, \`package\`, or \`tags\`).`, `- Docs index markdown: \`/${normalizedEntry}.md\``, `- Requested markdown API route: \`${requestedApiRoute}\``);
4082
3900
  if (sitemapConfig.enabled) {
4083
3901
  if (sitemapConfig.markdown.enabled) {
4084
3902
  lines.push(`- Semantic sitemap: \`${sitemapConfig.markdown.route}\``);
@@ -4252,10 +4070,10 @@ function createDocsMarkdownResponse(options) {
4252
4070
  }
4253
4071
  const sectionResult = sectionRequest ? selectDocsMarkdownSection(document, sectionRequest) : void 0;
4254
4072
  const responseDocument = sectionResult?.document ?? document;
4255
- const sectionCanonicalUrl = sectionResult?.found && sectionResult.section ? `${canonicalUrl}#${sectionResult.section.id}` : canonicalUrl;
4073
+ const sectionCanonicalUrl = sectionResult?.found && sectionResult.section ? resolveDocsMarkdownSectionCanonicalUrl(canonicalUrl, sectionResult.section.id) : canonicalUrl;
4256
4074
  const sectionContentLocation = sectionRequest ? appendDocsMarkdownSectionQuery(contentLocation, sectionRequest) : contentLocation;
4257
4075
  const sectionHeaders = sectionResult ? {
4258
- "X-Docs-Markdown-Section": sectionResult.section?.id ?? "",
4076
+ "X-Docs-Markdown-Section": sectionResult.section ? encodeURIComponent(sectionResult.section.id) : "",
4259
4077
  "X-Docs-Markdown-Section-Found": sectionResult.found ? "true" : "false",
4260
4078
  "X-Docs-Markdown-Section-Truncated": sectionResult.truncated ? "true" : "false",
4261
4079
  "X-Docs-Markdown-Estimated-Tokens": String(sectionResult.estimatedTokens),
@@ -4333,7 +4151,7 @@ function appendDocsMarkdownNegotiationStartLines(lines, context, variant) {
4333
4151
  }
4334
4152
  function appendDocsSearchStartLine(lines, context, variant) {
4335
4153
  if (!context.searchEnabled) return;
4336
- lines.push(variant === "skill" ? `- Search with ${context.apiRoute}?query={query}&audience=agent when you do not know the page.` : `- Search with ${context.apiRoute}?query={query}&audience=agent when the route is unknown.`);
4154
+ lines.push(variant === "skill" ? `- Search with ${context.apiRoute}?query={query}&audience=agent&response=structured when you do not know the page; optionally repeat framework, version, package, or tags filters.` : `- Search with ${context.apiRoute}?query={query}&audience=agent&response=structured when the route is unknown; optionally repeat framework, version, package, or tags filters.`);
4337
4155
  }
4338
4156
  function appendDocsOpenApiStartLine(lines, context, variant) {
4339
4157
  if (!context.openapiConfig.enabled || !context.openapiConfig.url) return;
@@ -4446,7 +4264,10 @@ function renderDocsMarkdownDocument(page, options) {
4446
4264
  if (page.description) lines.push(`Description: ${page.description}`);
4447
4265
  lines.push(...relatedLines);
4448
4266
  lines.push("", upsertPageAgentContractMarkdown(page.agentFallbackRawContent ?? page.agentFallbackContent ?? page.rawContent ?? page.content, page.agent));
4449
- return appendDocsMarkdownSitemapFooter(prependDocsMarkdownFrontmatter(lines.join("\n"), resolveDocsMarkdownPageMetadata(page, options)), options?.sitemap);
4267
+ return appendDocsMarkdownSitemapFooter(prependDocsMarkdownFrontmatter(lines.join("\n"), {
4268
+ ...resolveDocsMarkdownPageMetadata(page, options),
4269
+ generatedPreamble: true
4270
+ }), options?.sitemap);
4450
4271
  }
4451
4272
  function renderDocsSkillDocument(options) {
4452
4273
  const { origin } = options;
@@ -4517,7 +4338,7 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
4517
4338
  return {
4518
4339
  $schema: DOCS_AGENT_MANIFEST_SCHEMA_URI,
4519
4340
  format: DOCS_AGENT_MANIFEST_FORMAT,
4520
- version: "1",
4341
+ version: DOCS_AGENT_MANIFEST_VERSION,
4521
4342
  name: "@farming-labs/docs",
4522
4343
  baseUrl: origin,
4523
4344
  site: {
@@ -4689,12 +4510,29 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
4689
4510
  enabled: searchEnabled,
4690
4511
  endpoint: apiQueryRoute("query={query}"),
4691
4512
  agentEndpoint: apiQueryRoute("query={query}&audience=agent"),
4513
+ structuredAgentEndpoint: apiQueryRoute("query={query}&audience=agent&response=structured"),
4692
4514
  method: "GET",
4693
4515
  queryParam: "query",
4694
4516
  localeParam: "lang",
4695
4517
  audienceParam: "audience",
4696
4518
  defaultAudience: "human",
4697
- supportedAudiences: ["human", "agent"]
4519
+ supportedAudiences: ["human", "agent"],
4520
+ responseParam: "response",
4521
+ structuredResponseValue: "structured",
4522
+ responseFormat: "docs-search.v1",
4523
+ filterParams: {
4524
+ framework: "framework",
4525
+ version: "version",
4526
+ package: "package",
4527
+ tags: "tags"
4528
+ },
4529
+ repeatedFilterParams: [
4530
+ "framework",
4531
+ "version",
4532
+ "package",
4533
+ "tags"
4534
+ ],
4535
+ warningsField: "warnings"
4698
4536
  },
4699
4537
  agents: {
4700
4538
  enabled: true,
@@ -4863,4 +4701,4 @@ function toYamlString(value) {
4863
4701
  }
4864
4702
 
4865
4703
  //#endregion
4866
- export { matchesDocsLlmsTxtSection as $, PAGE_AGENT_STRUCTURED_CONTRACT_FIELDS as $t, buildDocsAgentDiscoverySpec as A, resolveDocsAudienceMdxContent as At, findDocsMarkdownPage as B, renderDocsSitemapXml as Bt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as C, selectDocsMarkdownSection as Ct, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as D, findDocsAudienceMdxTags as Dt, DOCS_MARKDOWN_SECTION_INDEX_FORMAT as E, findDocsAudienceMdxIssues as Et, buildDocsMcpEndpointCandidates as F, DEFAULT_SITEMAP_XML_ROUTE as Ft, isDocsAgentDiscoveryRequest as G, findDocsMarkdownSection as Gt, getDocsMarkdownCanonicalLinkHeader as H, resolveDocsSitemapPageLastmod as Ht, collectDocsMarkdownSections as I, buildDocsSitemapManifest as It, isDocsDiagnosticsRequest as J, renderDocsRelatedMarkdownLines as Jt, isDocsAgentsRequest as K, parseDocsMarkdownSections as Kt, createDocsMarkdownResponse as L, createDocsSitemapResponse as Lt, buildDocsConfigMap as M, DEFAULT_SITEMAP_MD_DOCS_ROUTE as Mt, buildDocsDiagnostics as N, DEFAULT_SITEMAP_MD_ROUTE as Nt, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as O, resolveDocsAgentMdxContent as Ot, buildDocsMarkdownSectionIndex as P, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as Pt, isDocsSkillRequest as Q, PAGE_AGENT_CONTRACT_START_MARKER as Qt, createDocsStandardsDiscoveryResponse as R, readDocsSitemapManifestFromContentMap as Rt, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as S, resolveDocsMcpResourceLocation as Sn, selectDocsLlmsTxtContent as St, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS as T, validateDocsAgentFeedbackPayload as Tt, getDocsMarkdownVaryHeader as U, resolveDocsSitemapRequest as Ut, getDocsLlmsTxtMaxCharsIssue as V, resolveDocsSitemapConfig as Vt, hasDocsMarkdownSignatureAgent as W, toDocsSitemapMarkdownUrl as Wt, isDocsMarkdownSectionIndexRequest as X, PAGE_AGENT_CONTRACT_FIELDS as Xt, isDocsLlmsTxtPublicRequest as Y, PAGE_AGENT_CONTRACT_END_MARKER as Yt, isDocsPublicGetRequest as Z, PAGE_AGENT_CONTRACT_FIELD_SCHEMA as Zt, DEFAULT_LLMS_TXT_MAX_CHARS as _, isDocsMcpRequest as _n, resolveDocsMarkdownRequest as _t, DEFAULT_AGENT_MD_ROUTE as a, stripGeneratedPageAgentContractMarkdown as an, renderDocsMarkdownDocument as at, DEFAULT_OPENAPI_SCHEMA_ROUTE as b, normalizeDocsMcpEndpointPath as bn, resolveDocsRequestApiRoute as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, DEFAULT_MCP_PUBLIC_ROUTE as cn, resolveDocsAgentContractMcpTools as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, buildDocsMcpProtectedResourceMetadataRoute as dn, resolveDocsAgentsFormat as dt, getPageAgentFrontmatterIssues as en, normalizeDocsPathSegment as et, DEFAULT_DOCS_CONFIG_ROUTE as f, getDocsMcpProtectedResourceMetadataRoutes as fn, resolveDocsLlmsTxtFormat as ft, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as g, isDocsMcpProtectedResourceMetadataPath as gn, resolveDocsMarkdownRecovery as gt, DEFAULT_LLMS_FULL_TXT_ROUTE as h, isDocsMcpOAuthScopeToken as hn, resolveDocsMarkdownCanonicalUrl as ht, DEFAULT_AGENT_FEEDBACK_ROUTE as i, renderPageAgentFrontmatterYamlLines as in, renderDocsLlmsTxt as it, buildDocsAgentFeedbackSchema as j, DEFAULT_SITEMAP_MANIFEST_PATH as jt, acceptsDocsMarkdown as k, resolveDocsAudienceExposure as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, DEFAULT_MCP_ROUTE as ln, resolveDocsAgentFeedbackConfig as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, hasDocsMcpProtectedResourceConfig as mn, resolveDocsLlmsTxtSections as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, normalizePageAgentFrontmatter as nn, parseDocsAgentFeedbackData as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, upsertPageAgentContractMarkdown as on, renderDocsMarkdownNotFound as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, getDocsMcpResourcePaths as pn, resolveDocsLlmsTxtRequest as pt, isDocsConfigRequest as q, normalizeDocsRelated as qt, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, renderPageAgentContractMarkdown as rn, renderDocsAgentsDocument as rt, DEFAULT_AGENT_SPEC_ROUTE as s, DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE as sn, renderDocsSkillDocument as st, DEFAULT_AGENTS_MD_ROUTE as t, hasStructuredPageAgentContract as tn, normalizeDocsUrlPath as tt, DEFAULT_DOCS_API_ROUTE as u, DEFAULT_MCP_WELL_KNOWN_ROUTE as un, resolveDocsAgentFeedbackRequest as ut, DEFAULT_LLMS_TXT_ROUTE as v, isDocsMcpResourcePath as vn, resolveDocsMarkdownSectionRequest as vt, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as w, toDocsMarkdownUrl as wt, DEFAULT_SKILL_MD_ROUTE as x, resolveDocsMcpProtectedResourceMetadataLocation as xn, resolveDocsSkillFormat as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, normalizeDocsMcpAuthorizationServerUrls as yn, resolveDocsOpenApiDiscoveryConfig as yt, detectDocsMarkdownAgentRequest as z, renderDocsSitemapMarkdown as zt };
4704
+ export { matchesDocsLlmsTxtSection as $, getDocsMcpProtectedResourceMetadataRoutes as $t, buildDocsAgentDiscoverySpec as A, resolveDocsAudienceExposure as At, findDocsMarkdownPage as B, renderDocsSitemapMarkdown as Bt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as C, selectDocsMarkdownSection as Ct, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as D, findDocsAudienceMdxIssues as Dt, DOCS_MARKDOWN_SECTION_INDEX_FORMAT as E, extractDocsMarkdownPromptBlocks as Et, buildDocsMcpEndpointCandidates as F, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as Ft, isDocsAgentDiscoveryRequest as G, toDocsSitemapMarkdownUrl as Gt, getDocsMarkdownCanonicalLinkHeader as H, resolveDocsSitemapConfig as Ht, collectDocsMarkdownSections as I, DEFAULT_SITEMAP_XML_ROUTE as It, isDocsDiagnosticsRequest as J, DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE as Jt, isDocsAgentsRequest as K, normalizeDocsRelated as Kt, createDocsMarkdownResponse as L, buildDocsSitemapManifest as Lt, buildDocsConfigMap as M, DEFAULT_SITEMAP_MANIFEST_PATH as Mt, buildDocsDiagnostics as N, DEFAULT_SITEMAP_MD_DOCS_ROUTE as Nt, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as O, findDocsAudienceMdxTags as Ot, buildDocsMarkdownSectionIndex as P, DEFAULT_SITEMAP_MD_ROUTE as Pt, isDocsSkillRequest as Q, buildDocsMcpProtectedResourceMetadataRoute as Qt, createDocsStandardsDiscoveryResponse as R, createDocsSitemapResponse as Rt, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as S, selectDocsLlmsTxtContent as St, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS as T, validateDocsAgentFeedbackPayload as Tt, getDocsMarkdownVaryHeader as U, resolveDocsSitemapPageLastmod as Ut, getDocsLlmsTxtMaxCharsIssue as V, renderDocsSitemapXml as Vt, hasDocsMarkdownSignatureAgent as W, resolveDocsSitemapRequest as Wt, isDocsMarkdownSectionIndexRequest as X, DEFAULT_MCP_ROUTE as Xt, isDocsLlmsTxtPublicRequest as Y, DEFAULT_MCP_PUBLIC_ROUTE as Yt, isDocsPublicGetRequest as Z, DEFAULT_MCP_WELL_KNOWN_ROUTE as Zt, DEFAULT_LLMS_TXT_MAX_CHARS as _, resolveDocsMarkdownRequest as _t, DEFAULT_AGENT_MD_ROUTE as a, isDocsMcpResourcePath as an, renderDocsMarkdownDocument as at, DEFAULT_OPENAPI_SCHEMA_ROUTE as b, resolveDocsRequestApiRoute as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, resolveDocsMcpProtectedResourceMetadataLocation as cn, resolveDocsAgentContractMcpTools as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, resolveDocsAgentsFormat as dt, getDocsMcpResourcePaths as en, normalizeDocsPathSegment 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, isDocsMcpRequest as in, renderDocsLlmsTxt as it, buildDocsAgentFeedbackSchema as j, resolveDocsAudienceMdxContent as jt, acceptsDocsMarkdown as k, resolveDocsAgentMdxContent as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, resolveDocsMcpResourceLocation as ln, resolveDocsAgentFeedbackConfig as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, resolveDocsLlmsTxtSections as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, isDocsMcpOAuthScopeToken as nn, parseDocsAgentFeedbackData as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, normalizeDocsMcpAuthorizationServerUrls as on, renderDocsMarkdownNotFound as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, resolveDocsLlmsTxtRequest as pt, isDocsConfigRequest as q, renderDocsRelatedMarkdownLines as qt, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, isDocsMcpProtectedResourceMetadataPath as rn, renderDocsAgentsDocument as rt, DEFAULT_AGENT_SPEC_ROUTE as s, normalizeDocsMcpEndpointPath as sn, renderDocsSkillDocument as st, DEFAULT_AGENTS_MD_ROUTE as t, hasDocsMcpProtectedResourceConfig as tn, normalizeDocsUrlPath as tt, DEFAULT_DOCS_API_ROUTE as u, resolveDocsAgentFeedbackRequest as ut, DEFAULT_LLMS_TXT_ROUTE as v, resolveDocsMarkdownSectionRequest as vt, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as w, toDocsMarkdownUrl as wt, DEFAULT_SKILL_MD_ROUTE as x, resolveDocsSkillFormat as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, resolveDocsOpenApiDiscoveryConfig as yt, detectDocsMarkdownAgentRequest as z, readDocsSitemapManifestFromContentMap as zt };