@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.
- package/dist/{agent-bof3qzKZ.mjs → agent-ClRpctMG.mjs} +3 -2
- package/dist/{agent-evals-Cr9TAkmB.mjs → agent-evals-BFHGypqh.mjs} +116 -20
- package/dist/{agent-export-7Ws4KqDE.mjs → agent-export-B9bah0AV.mjs} +9 -8
- package/dist/{agent-FIyl4-Oa.mjs → agent-o9OTadrf.mjs} +607 -769
- package/dist/agent-skills-bundle.d.mts +1 -1
- package/dist/{agent-skills-server-DTwblsLu.d.mts → agent-skills-server-DCbAx5WU.d.mts} +2 -2
- package/dist/{agent-skills-server-B4u3qy-1.mjs → agent-skills-server-noFn1l_p.mjs} +1 -1
- package/dist/agent-skills-vite.d.mts +3 -3
- package/dist/agent-skills-vite.mjs +2 -2
- package/dist/{agents-Be2ntaFr.mjs → agents-CR-Uasbc.mjs} +7 -6
- package/dist/cli/index.mjs +14 -14
- package/dist/client/react.d.mts +1 -1
- package/dist/{cloud-ask-ai-BfnX18rI.d.mts → cloud-ask-ai-yR9vZmSG.d.mts} +1 -1
- package/dist/docs-cloud-server.d.mts +2 -2
- package/dist/{doctor-DoPAofVP.mjs → doctor-BeyN3Ljh.mjs} +12 -11
- package/dist/{golden-evaluations-CPGGnXOV.mjs → golden-evaluations-CloP0pAe.mjs} +23 -2
- package/dist/index.d.mts +93 -6
- package/dist/index.mjs +9 -8
- package/dist/markdown-rendering.d.mts +75 -0
- package/dist/markdown-rendering.mjs +618 -0
- package/dist/markdown-sections-7OoA7ylx.mjs +1492 -0
- package/dist/{mcp-BLynUzE7.mjs → mcp-BLLXvEXB.mjs} +7 -6
- package/dist/mcp.d.mts +7 -2
- package/dist/mcp.mjs +130 -25
- package/dist/{metadata-bw8k-9x-.mjs → metadata-N252j5_a.mjs} +1 -1
- package/dist/{reading-time-DtNegNiq.mjs → prompt-references-Cz35rlOa.mjs} +158 -4
- package/dist/{review-NFnYbMRI.mjs → review-DaJLdPLh.mjs} +7 -6
- package/dist/{robots-DOqBwQw8.mjs → robots-BcuxnZqZ.mjs} +2 -2
- package/dist/{robots-B3e-aWPy.mjs → robots-DI-9MZz1.mjs} +4 -3
- package/dist/{search-CozHzW7v.d.mts → search-D1n8Sf25.d.mts} +45 -9
- package/dist/{search-DOGUUZvs.mjs → search-DeOJiMAy.mjs} +7 -6
- package/dist/{search-x5O0-9X3.mjs → search-RfPcG1if.mjs} +742 -42
- package/dist/server.d.mts +13 -5
- package/dist/server.mjs +8 -7
- package/dist/{sitemap-BpMKdDUd.mjs → sitemap-BGGbX_KE.mjs} +7 -6
- package/dist/{sitemap-server-D_hayOp6.mjs → sitemap-server-VefDnzEB.mjs} +1 -1
- package/dist/{standards-discovery-C0CIC4QI.d.mts → standards-discovery-83lp1lew.d.mts} +5 -4
- package/dist/{standards-discovery-CYfiQE13.mjs → standards-discovery-BwL5ffGx.mjs} +4 -3
- package/dist/{types-BQC05SQm.d.mts → types-_HCPD4wc.d.mts} +49 -1
- package/package.json +9 -1
- package/dist/agent-scope-C_U--OZ7.mjs +0 -283
- /package/dist/{i18n-CCaFUnAN.mjs → i18n-hHVWcflJ.mjs} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
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:
|
|
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.
|
|
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
|
|
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
|
|
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}\``, `-
|
|
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 ?
|
|
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
|
|
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"),
|
|
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:
|
|
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 $,
|
|
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 };
|