@farming-labs/docs 0.2.83 → 0.2.85

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 (37) hide show
  1. package/dist/{agent-WS4GXGh6.d.mts → agent-2MWvWpJf.d.mts} +18 -3
  2. package/dist/{agent-Dze2Cy5B.mjs → agent-CTOUI2BK.mjs} +338 -296
  3. package/dist/{agent-Biyd8A98.mjs → agent-FyPQ2AZ4.mjs} +2 -2
  4. package/dist/{agent-evals-Burrzyam.mjs → agent-evals-DCptRrdP.mjs} +2 -2
  5. package/dist/{agent-export-whKAZQUI.mjs → agent-export-Di1Ofstb.mjs} +41 -25
  6. package/dist/agent-skills-bundle.d.mts +1 -1
  7. package/dist/{agent-skills-server-D5qYU19g.mjs → agent-skills-server-CwmzAzf_.mjs} +1 -1
  8. package/dist/{agent-skills-server-q4B9kRGg.d.mts → agent-skills-server-DNtmvTkv.d.mts} +2 -2
  9. package/dist/agent-skills-vite.d.mts +3 -3
  10. package/dist/agent-skills-vite.mjs +2 -2
  11. package/dist/{agents-B_980VCs.mjs → agents-DjUz5voa.mjs} +6 -6
  12. package/dist/cli/index.mjs +14 -14
  13. package/dist/client/react.d.mts +1 -1
  14. package/dist/{cloud-ask-ai-BQAeHkpZ.d.mts → cloud-ask-ai-Bx-qtqHL.d.mts} +1 -1
  15. package/dist/{content-change-hydration-DpQ0KdAD.mjs → content-change-hydration-DLBinuFR.mjs} +2 -1
  16. package/dist/docs-cloud-server.d.mts +2 -2
  17. package/dist/{doctor-WjuyRWYT.mjs → doctor-BPx6iAzQ.mjs} +10 -10
  18. package/dist/{golden-evaluations-B2GHnoFa.mjs → golden-evaluations-CQuiglEv.mjs} +8 -2
  19. package/dist/index.d.mts +29 -5
  20. package/dist/index.mjs +6 -6
  21. package/dist/{mcp-bhIsgqxy.mjs → mcp-lSrFDtwr.mjs} +6 -6
  22. package/dist/mcp.d.mts +3 -3
  23. package/dist/mcp.mjs +96 -6
  24. package/dist/{prompt-references-embiJdYt.mjs → prompt-references-B6gxePm8.mjs} +3 -3
  25. package/dist/{retrieval-digest-DRRHA1B3.d.mts → retrieval-digest-CfNbL70a.d.mts} +10 -7
  26. package/dist/{review-2e4TXoGS.mjs → review-CG2UApoQ.mjs} +6 -6
  27. package/dist/{robots-BIySk2gE.mjs → robots-BsOTGWiY.mjs} +3 -3
  28. package/dist/{robots-D96X6eVX.mjs → robots-DaU38DZw.mjs} +2 -2
  29. package/dist/{search-DfB3LQ4s.mjs → search-DEz_28y1.mjs} +6 -6
  30. package/dist/server.d.mts +6 -6
  31. package/dist/server.mjs +6 -6
  32. package/dist/{sitemap-server-BefXEox6.mjs → sitemap-server-Ds5z4WQB.mjs} +1 -1
  33. package/dist/{sitemap-AcwP8jIo.mjs → sitemap-vQbO76Vo.mjs} +6 -6
  34. package/dist/{standards-discovery-BKlEnK_H.mjs → standards-discovery-Ckx0tN7B.mjs} +342 -41
  35. package/dist/{standards-discovery-DPUEcUmb.d.mts → standards-discovery-CthpcXx2.d.mts} +5 -2
  36. package/dist/{types-lGEHcx_6.d.mts → types-DQl2dvDl.d.mts} +66 -1
  37. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { S as upsertPageAgentContractMarkdown, a as findDocsGeneratedAgentContractRanges, b as renderPageAgentFrontmatterYamlLines, d as PAGE_AGENT_CONTRACT_END_MARKER, l as stripDocsGeneratedAgentContractMarkers, m as PAGE_AGENT_CONTRACT_START_MARKER, o as findDocsMarkdownSection, p as PAGE_AGENT_CONTRACT_FIELD_SCHEMA, s as parseDocsMarkdownSections, y as renderPageAgentContractMarkdown } 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-BKlEnK_H.mjs";
2
+ import { B as createDocsCacheableResponse, F as isDocsStandardsDiscoveryRequest, I as resolveDocsDiscoveryApiRoute, K as digestDocsRetrievalContent, M as createDocsStandardsResponse, S as DOCS_AGENT_MANIFEST_FORMAT, T as DOCS_AGENT_MANIFEST_VERSION, W as resolveDocsHttpDate, _ 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, q as isDocsRetrievalCanonicalUrl, 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-Ckx0tN7B.mjs";
3
3
  import { createProcessor } from "@mdx-js/mdx";
4
4
 
5
5
  //#region src/mcp-auth.ts
@@ -148,172 +148,6 @@ function normalizeInlineText(value) {
148
148
  return value.replace(/\s+/g, " ").trim();
149
149
  }
150
150
 
151
- //#endregion
152
- //#region src/retrieval-digest.ts
153
- const SHA256_INITIAL_STATE = [
154
- 1779033703,
155
- 3144134277,
156
- 1013904242,
157
- 2773480762,
158
- 1359893119,
159
- 2600822924,
160
- 528734635,
161
- 1541459225
162
- ];
163
- const SHA256_ROUND_CONSTANTS = [
164
- 1116352408,
165
- 1899447441,
166
- 3049323471,
167
- 3921009573,
168
- 961987163,
169
- 1508970993,
170
- 2453635748,
171
- 2870763221,
172
- 3624381080,
173
- 310598401,
174
- 607225278,
175
- 1426881987,
176
- 1925078388,
177
- 2162078206,
178
- 2614888103,
179
- 3248222580,
180
- 3835390401,
181
- 4022224774,
182
- 264347078,
183
- 604807628,
184
- 770255983,
185
- 1249150122,
186
- 1555081692,
187
- 1996064986,
188
- 2554220882,
189
- 2821834349,
190
- 2952996808,
191
- 3210313671,
192
- 3336571891,
193
- 3584528711,
194
- 113926993,
195
- 338241895,
196
- 666307205,
197
- 773529912,
198
- 1294757372,
199
- 1396182291,
200
- 1695183700,
201
- 1986661051,
202
- 2177026350,
203
- 2456956037,
204
- 2730485921,
205
- 2820302411,
206
- 3259730800,
207
- 3345764771,
208
- 3516065817,
209
- 3600352804,
210
- 4094571909,
211
- 275423344,
212
- 430227734,
213
- 506948616,
214
- 659060556,
215
- 883997877,
216
- 958139571,
217
- 1322822218,
218
- 1537002063,
219
- 1747873779,
220
- 1955562222,
221
- 2024104815,
222
- 2227730452,
223
- 2361852424,
224
- 2428436474,
225
- 2756734187,
226
- 3204031479,
227
- 3329325298
228
- ];
229
- function rotateRight(value, bits) {
230
- return value >>> bits | value << 32 - bits;
231
- }
232
- function normalizeDigestContent(value) {
233
- return value.replace(/\r\n?/gu, "\n").replace(/^\uFEFF/u, "").trimEnd();
234
- }
235
- /** Validate the bounded HTTP(S) URL or root-relative URI reference used by provenance. */
236
- function isDocsRetrievalCanonicalUrl(value) {
237
- const hasUnsafeCharacter = value.includes("\\") || Array.from(value).some((character) => {
238
- const codePoint = character.codePointAt(0) ?? 0;
239
- return codePoint <= 31 || codePoint === 127;
240
- });
241
- if (!value || value !== value.trim() || value.length > 4096 || hasUnsafeCharacter) return false;
242
- if (/^\/(?!\/)/u.test(value)) try {
243
- new URL(value, "https://docs.local");
244
- return true;
245
- } catch {
246
- return false;
247
- }
248
- try {
249
- const url = new URL(value);
250
- return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password;
251
- } catch {
252
- return false;
253
- }
254
- }
255
- /**
256
- * Hash a retrieval source projection with portable SHA-256.
257
- *
258
- * The projection is normalized by removing one leading BOM, converting CRLF/CR
259
- * line endings to LF, and trimming trailing whitespace. The helper is exported so
260
- * agents can independently verify provenance in Node, edge, and browser runtimes.
261
- */
262
- function digestDocsRetrievalContent(value) {
263
- const input = new TextEncoder().encode(normalizeDigestContent(value));
264
- const paddedLength = Math.ceil((input.length + 9) / 64) * 64;
265
- const padded = new Uint8Array(paddedLength);
266
- padded.set(input);
267
- padded[input.length] = 128;
268
- const bitLength = input.length * 8;
269
- const dataView = new DataView(padded.buffer);
270
- dataView.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296), false);
271
- dataView.setUint32(paddedLength - 4, bitLength >>> 0, false);
272
- const state = Uint32Array.from(SHA256_INITIAL_STATE);
273
- const words = new Uint32Array(64);
274
- for (let offset = 0; offset < padded.length; offset += 64) {
275
- for (let index = 0; index < 16; index += 1) words[index] = dataView.getUint32(offset + index * 4, false);
276
- for (let index = 16; index < 64; index += 1) {
277
- const previous15 = words[index - 15];
278
- const previous2 = words[index - 2];
279
- const sigma0 = rotateRight(previous15, 7) ^ rotateRight(previous15, 18) ^ previous15 >>> 3;
280
- const sigma1 = rotateRight(previous2, 17) ^ rotateRight(previous2, 19) ^ previous2 >>> 10;
281
- words[index] = words[index - 16] + sigma0 + words[index - 7] + sigma1 >>> 0;
282
- }
283
- let a = state[0];
284
- let b = state[1];
285
- let c = state[2];
286
- let d = state[3];
287
- let e = state[4];
288
- let f = state[5];
289
- let g = state[6];
290
- let h = state[7];
291
- for (let index = 0; index < 64; index += 1) {
292
- const sum1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
293
- const choice = e & f ^ ~e & g;
294
- const temporary1 = h + sum1 + choice + SHA256_ROUND_CONSTANTS[index] + words[index] >>> 0;
295
- const temporary2 = (rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22)) + (a & b ^ a & c ^ b & c) >>> 0;
296
- h = g;
297
- g = f;
298
- f = e;
299
- e = d + temporary1 >>> 0;
300
- d = c;
301
- c = b;
302
- b = a;
303
- a = temporary1 + temporary2 >>> 0;
304
- }
305
- state[0] = state[0] + a >>> 0;
306
- state[1] = state[1] + b >>> 0;
307
- state[2] = state[2] + c >>> 0;
308
- state[3] = state[3] + d >>> 0;
309
- state[4] = state[4] + e >>> 0;
310
- state[5] = state[5] + f >>> 0;
311
- state[6] = state[6] + g >>> 0;
312
- state[7] = state[7] + h >>> 0;
313
- }
314
- return `sha256:${Array.from(state, (word) => word.toString(16).padStart(8, "0")).join("")}`;
315
- }
316
-
317
151
  //#endregion
318
152
  //#region src/pagination.ts
319
153
  const DOCS_PAGINATION_CURSOR_VERSION = 1;
@@ -2408,6 +2242,8 @@ const MAX_SEARCH_WARNINGS = 16;
2408
2242
  const MAX_SEARCH_WARNING_VALUES = 16;
2409
2243
  const MAX_SEARCH_WARNING_PAGE_URLS = 8;
2410
2244
  const MAX_SEARCH_FACET_VALUES = 100;
2245
+ const MAX_SEARCH_EXPLANATION_TERMS = 32;
2246
+ const MAX_SEARCH_EXPLANATION_TERM_CHARS = 128;
2411
2247
  const RETRIEVAL_INDEX_FORMAT = "docs-retrieval-index.v1";
2412
2248
  const MAX_RETRIEVAL_SOURCE_URL_CHARS = 4096;
2413
2249
  const MAX_RETRIEVAL_SOURCE_VALUE_CHARS = 256;
@@ -2522,6 +2358,9 @@ function resolveDocsSearchRequest(searchParams) {
2522
2358
  const response = searchParams.get("response");
2523
2359
  const structured = response === "structured";
2524
2360
  const facets = response === "facets";
2361
+ const rawExplain = searchParams.get("explain");
2362
+ if (rawExplain !== null && rawExplain !== "true" && rawExplain !== "false") throw new DocsSearchRequestError("Search explain must be `true` or `false`.");
2363
+ const explain = rawExplain === "true";
2525
2364
  const rawFacet = searchParams.get("facet");
2526
2365
  let facet;
2527
2366
  if (rawFacet !== null) {
@@ -2543,6 +2382,7 @@ function resolveDocsSearchRequest(searchParams) {
2543
2382
  return {
2544
2383
  filters: resolveDocsSearchFilters(searchParams),
2545
2384
  structured,
2385
+ ...explain ? { explain: true } : {},
2546
2386
  ...facets ? { facets: true } : {},
2547
2387
  ...facet !== void 0 ? { facet } : {},
2548
2388
  ...cursor !== void 0 ? { cursor } : {},
@@ -3703,9 +3543,14 @@ function buildDocsSearchDocuments(pages, chunking = {}, audience = "human") {
3703
3543
  return [...base.content ? [base] : [], ...sections];
3704
3544
  });
3705
3545
  }
3706
- function scoreDocument(query, document) {
3546
+ function analyzeDocsSearchDocument(query, document, explain = false) {
3707
3547
  const q = normalizeSearchPhrase(query);
3708
- if (!q) return 0;
3548
+ if (!q) return {
3549
+ score: 0,
3550
+ matchedTerms: [],
3551
+ matchedTermsTruncated: false,
3552
+ rankingReasons: []
3553
+ };
3709
3554
  const words = tokenizeSearchQuery(q);
3710
3555
  const title = normalizeSearchPhrase(document.title);
3711
3556
  const section = document.section ? normalizeSearchPhrase(document.section) : "";
@@ -3718,65 +3563,248 @@ function scoreDocument(query, document) {
3718
3563
  const titleTokens = tokenizeSearchQuery(title);
3719
3564
  const sectionTokens = tokenizeSearchQuery(section);
3720
3565
  let score = 0;
3566
+ const reasonContributions = explain ? /* @__PURE__ */ new Map() : void 0;
3567
+ const addScore = (contribution, code, description) => {
3568
+ score += contribution;
3569
+ if (!reasonContributions) return;
3570
+ const current = reasonContributions.get(code);
3571
+ reasonContributions.set(code, {
3572
+ contribution: (current?.contribution ?? 0) + contribution,
3573
+ description: current?.description ?? description
3574
+ });
3575
+ };
3721
3576
  const insideLiteralPriority = document.type !== "page" && hasDistinctSection && isLiteralLookupQuery(q) ? Math.max(literalMatchPriority(q, section), literalMatchPriority(q, description), literalMatchPriority(q, content)) : 0;
3722
- if (insideLiteralPriority > 0) score += insideLiteralPriority * 2250;
3723
- if (title === q) score += 1120;
3724
- else if (title.startsWith(q)) score += 70;
3725
- else if (title.includes(q)) score += 45;
3577
+ if (insideLiteralPriority > 0) addScore(insideLiteralPriority * 2250, "literal_match", "A short literal lookup matched this section or its searchable text.");
3578
+ if (title === q) addScore(1120, "title_phrase", "The normalized query exactly matches the page title.");
3579
+ else if (title.startsWith(q)) addScore(70, "title_phrase", "The page title starts with the normalized query.");
3580
+ else if (title.includes(q)) addScore(45, "title_phrase", "The page title contains the normalized query.");
3726
3581
  if (hasDistinctSection) {
3727
- if (section === q) score += 1080;
3728
- else if (section.startsWith(q)) score += 55;
3729
- else if (section.includes(q)) score += 30;
3730
- if (titleSection === q) score += 1e3;
3731
- else if (titleSection.startsWith(q)) score += 50;
3732
- else if (titleSection.includes(q)) score += 28;
3733
- }
3734
- if (urlSegments.includes(q)) score += 950;
3735
- if (url.includes(q)) score += 12;
3736
- if (description.includes(q)) score += 18;
3737
- if (content.includes(q)) score += 12;
3582
+ if (section === q) addScore(1080, "section_phrase", "The normalized query exactly matches the section title.");
3583
+ else if (section.startsWith(q)) addScore(55, "section_phrase", "The section title starts with the normalized query.");
3584
+ else if (section.includes(q)) addScore(30, "section_phrase", "The section title contains the normalized query.");
3585
+ if (titleSection === q) addScore(1e3, "title_section_phrase", "The normalized query exactly matches the combined page and section title.");
3586
+ else if (titleSection.startsWith(q)) addScore(50, "title_section_phrase", "The combined page and section title starts with the normalized query.");
3587
+ else if (titleSection.includes(q)) addScore(28, "title_section_phrase", "The combined page and section title contains the normalized query.");
3588
+ }
3589
+ if (urlSegments.includes(q)) addScore(950, "url_phrase", "The normalized query exactly matches a URL segment.");
3590
+ if (url.includes(q)) addScore(12, "url_phrase", "The result URL contains the normalized query.");
3591
+ if (description.includes(q)) addScore(18, "description_phrase", "The page description contains the normalized query.");
3592
+ if (content.includes(q)) addScore(12, "content_phrase", "The searchable content contains the normalized query.");
3738
3593
  let matchedWords = 0;
3739
3594
  for (const word of words) {
3740
3595
  let matched = false;
3741
3596
  if (title === word) {
3742
- score += 28;
3597
+ addScore(28, "title_terms", "Normalized query terms match the page title.");
3743
3598
  matched = true;
3744
3599
  } else if (title.startsWith(word)) {
3745
- score += 20;
3600
+ addScore(20, "title_terms", "Normalized query terms match the page title.");
3746
3601
  matched = true;
3747
3602
  } else if (title.includes(word)) {
3748
- score += 12;
3603
+ addScore(12, "title_terms", "Normalized query terms match the page title.");
3749
3604
  matched = true;
3750
3605
  }
3751
3606
  if (hasDistinctSection) {
3752
3607
  if (section === word) {
3753
- score += 22;
3608
+ addScore(22, "section_terms", "Normalized query terms match the section title.");
3754
3609
  matched = true;
3755
3610
  } else if (section.startsWith(word)) {
3756
- score += 16;
3611
+ addScore(16, "section_terms", "Normalized query terms match the section title.");
3757
3612
  matched = true;
3758
3613
  } else if (section.includes(word)) {
3759
- score += 10;
3614
+ addScore(10, "section_terms", "Normalized query terms match the section title.");
3760
3615
  matched = true;
3761
3616
  }
3762
3617
  }
3763
3618
  if (description.includes(word)) {
3764
- score += 6;
3619
+ addScore(6, "description_terms", "Normalized query terms match the page description.");
3765
3620
  matched = true;
3766
3621
  }
3767
3622
  if (content.includes(word)) {
3768
- score += 4;
3623
+ addScore(4, "content_terms", "Normalized query terms match the searchable content.");
3769
3624
  matched = true;
3770
3625
  }
3771
3626
  if (matched) matchedWords += 1;
3772
3627
  }
3773
3628
  if (words.length > 1) {
3774
- if (hasDistinctSection && sectionTokens.length > 0 && words.every((word) => sectionTokens.includes(word))) score += 30;
3775
- if (document.type === "page" && titleTokens.length > 0 && words.every((word) => titleTokens.includes(word))) score += 24;
3629
+ if (hasDistinctSection && sectionTokens.length > 0 && words.every((word) => sectionTokens.includes(word))) addScore(30, "all_terms_in_section", "Every normalized query term occurs in the section title.");
3630
+ if (document.type === "page" && titleTokens.length > 0 && words.every((word) => titleTokens.includes(word))) addScore(24, "all_terms_in_title", "Every normalized query term occurs in the page title.");
3631
+ }
3632
+ if (matchedWords === words.length && words.length > 1) addScore(20, "all_query_terms", "Every normalized query term matched a searchable field.");
3633
+ if (score > 0 && document.type === "heading" && hasDistinctSection) addScore(6, "heading_boost", "A distinct matching section is preferred over a page-only hit.");
3634
+ const matchedTerms = [];
3635
+ let matchedTermCount = 0;
3636
+ let matchedTermCharactersTruncated = false;
3637
+ if (explain) {
3638
+ const candidateTerms = words.length > 0 ? words : [q];
3639
+ const fields = [
3640
+ ["title", title],
3641
+ ["section", section],
3642
+ ["description", description],
3643
+ ["content", content],
3644
+ ["url", url]
3645
+ ];
3646
+ for (const term of candidateTerms) {
3647
+ const matchingFields = fields.flatMap(([field, value]) => value.includes(term) ? [field] : []);
3648
+ if (matchingFields.length === 0) continue;
3649
+ matchedTermCount += 1;
3650
+ if (matchedTerms.length < MAX_SEARCH_EXPLANATION_TERMS) {
3651
+ matchedTermCharactersTruncated ||= term.length > MAX_SEARCH_EXPLANATION_TERM_CHARS;
3652
+ matchedTerms.push({
3653
+ term: term.slice(0, MAX_SEARCH_EXPLANATION_TERM_CHARS),
3654
+ fields: matchingFields
3655
+ });
3656
+ }
3657
+ }
3776
3658
  }
3777
- if (matchedWords === words.length && words.length > 1) score += 20;
3778
- if (score > 0 && document.type === "heading" && hasDistinctSection) score += 6;
3779
- return score;
3659
+ return {
3660
+ score,
3661
+ matchedTerms,
3662
+ matchedTermsTruncated: matchedTermCount > matchedTerms.length || matchedTermCharactersTruncated,
3663
+ rankingReasons: reasonContributions ? [...reasonContributions.entries()].map(([code, value]) => ({
3664
+ code,
3665
+ ...value
3666
+ })).sort((left, right) => right.contribution - left.contribution || left.code.localeCompare(right.code)) : []
3667
+ };
3668
+ }
3669
+ function scoreDocument(query, document) {
3670
+ return analyzeDocsSearchDocument(query, document).score;
3671
+ }
3672
+ function getDocsSearchExplanationResultIdentity(result) {
3673
+ return JSON.stringify([
3674
+ result.id,
3675
+ result.url,
3676
+ result.section ?? null
3677
+ ]);
3678
+ }
3679
+ function getDocsSearchExplanationDocumentIdentity(document) {
3680
+ return getSearchResultKey({
3681
+ id: document.id,
3682
+ url: document.url,
3683
+ content: document.title,
3684
+ type: document.type,
3685
+ section: document.section
3686
+ });
3687
+ }
3688
+ function resolveDocsSearchExplanationDocument(result, documentsById, documentsByResultKey) {
3689
+ const local = documentsById.get(result.id) ?? documentsByResultKey.get(getSearchResultKey(result));
3690
+ if (local) return local;
3691
+ return {
3692
+ id: result.id,
3693
+ url: result.url,
3694
+ title: inferResultTitle(result),
3695
+ content: result.content,
3696
+ description: result.description,
3697
+ section: result.section,
3698
+ type: result.type
3699
+ };
3700
+ }
3701
+ function buildDocsSearchFilterDecisions(filters, scope) {
3702
+ return SEARCH_FILTER_FIELDS.map((field) => {
3703
+ const requestedValues = filters[field] ?? [];
3704
+ const selectedValues = scope?.[field] ?? [];
3705
+ if (requestedValues.length === 0) return {
3706
+ field,
3707
+ requestedValues: [],
3708
+ selectedValues: [...selectedValues],
3709
+ matchedValues: [],
3710
+ outcome: "not_requested"
3711
+ };
3712
+ const matchedValues = requestedValues.filter((requested) => selectedValues.some((selected) => docsSearchScopeValueMatches(field, requested, selected)));
3713
+ const versionGroupsMatch = field !== "version" || !scope?.versionGroups?.length || agentVersionConstraintGroupsOverlap([requestedValues, ...scope.versionGroups]);
3714
+ const verifiable = Boolean(scope) && !scope?.conflicts?.includes(field) && !scope?.truncated?.includes(field) && selectedValues.length > 0;
3715
+ return {
3716
+ field,
3717
+ requestedValues: [...requestedValues],
3718
+ selectedValues: [...selectedValues],
3719
+ matchedValues,
3720
+ outcome: verifiable && matchedValues.length > 0 && versionGroupsMatch ? "matched" : "not_verifiable"
3721
+ };
3722
+ });
3723
+ }
3724
+ function buildDocsSearchAmbiguityResolution(filters, scope, warnings, unverifiableFields) {
3725
+ const decisions = SEARCH_AMBIGUITY_FIELDS.map((field) => {
3726
+ const selectedValues = [...scope?.[field] ?? []];
3727
+ const requestedValues = filters[field];
3728
+ if (requestedValues?.length) return {
3729
+ field,
3730
+ status: "resolved_by_filter",
3731
+ selectedValues,
3732
+ candidateValues: [...requestedValues],
3733
+ reason: `The explicit ${field} filter constrained the result set.`
3734
+ };
3735
+ const warning = warnings.find((candidate) => candidate.code === "ambiguous_scope" && candidate.field === field);
3736
+ if (warning) return {
3737
+ field,
3738
+ status: "requires_filter",
3739
+ selectedValues,
3740
+ ...warning.values ? { candidateValues: [...warning.values] } : {},
3741
+ reason: `Results span multiple ${field} scopes; select a ${field} filter before acting on scope-specific guidance.`
3742
+ };
3743
+ const hasConflictingMetadata = warnings.some((candidate) => candidate.code === "conflicting_scope_metadata" && candidate.field === field);
3744
+ if (selectedValues.length === 0 || unverifiableFields.has(field) || hasConflictingMetadata) return {
3745
+ field,
3746
+ status: "not_verifiable",
3747
+ selectedValues,
3748
+ reason: `No trusted ${field} scope is available for this result.`
3749
+ };
3750
+ return {
3751
+ field,
3752
+ status: "unambiguous",
3753
+ selectedValues,
3754
+ reason: `The matching result set does not contain conflicting ${field} choices.`
3755
+ };
3756
+ });
3757
+ const hasUnresolved = decisions.some((decision) => decision.status === "requires_filter");
3758
+ const isNotVerifiable = decisions.some((decision) => decision.status === "not_verifiable");
3759
+ const hasResolved = decisions.some((decision) => decision.status === "resolved_by_filter");
3760
+ return {
3761
+ status: hasUnresolved ? "unresolved" : isNotVerifiable ? "not_verifiable" : hasResolved ? "resolved" : "unambiguous",
3762
+ decisions
3763
+ };
3764
+ }
3765
+ function explainDocsSearchResults(options) {
3766
+ const documentsById = new Map(options.documents.map((document) => [document.id, document]));
3767
+ const documentsByResultKey = new Map(options.documents.map((document) => [getDocsSearchExplanationDocumentIdentity(document), document]));
3768
+ return options.results.map((result, index, results) => {
3769
+ const document = resolveDocsSearchExplanationDocument(result, documentsById, documentsByResultKey);
3770
+ const analysis = analyzeDocsSearchDocument(options.query, document, true);
3771
+ const rankingStrategy = options.resolveRankingStrategy(result);
3772
+ const rankingReasons = rankingStrategy === "provider" ? [{
3773
+ code: "provider_order",
3774
+ description: `The ${options.provider} search adapter supplied this result order; provider-internal ranking details are not available to the shared pipeline.`
3775
+ }] : [...analysis.rankingReasons];
3776
+ if (rankingStrategy === "exact") rankingReasons.unshift({
3777
+ code: "exact_page_boost",
3778
+ contribution: 2e3,
3779
+ description: "An exact normalized page-title or URL-segment match was promoted."
3780
+ });
3781
+ if (rankingStrategy === "provider" && insideLiteralResultPriority(options.query, result) > 0) rankingReasons.push({
3782
+ code: "literal_result_priority",
3783
+ description: "The shared pipeline promoted this distinct section because it matched a short literal lookup."
3784
+ });
3785
+ const resultScore = result.score;
3786
+ const previousScore = index > 0 ? results[index - 1]?.score : void 0;
3787
+ const nextScore = index + 1 < results.length ? results[index + 1]?.score : void 0;
3788
+ if (rankingStrategy !== "provider" && resultScore !== void 0 && (resultScore === previousScore || resultScore === nextScore)) rankingReasons.push({
3789
+ code: "stable_url_tiebreak",
3790
+ description: "A stable URL comparison resolved an equal lexical score."
3791
+ });
3792
+ const selectedScope = result.source?.scope;
3793
+ return {
3794
+ ...result,
3795
+ explanation: {
3796
+ format: "docs-search-explanation.v1",
3797
+ rank: options.rankOffset + index + 1,
3798
+ rankingStrategy,
3799
+ matchedTerms: analysis.matchedTerms,
3800
+ matchedTermsTruncated: analysis.matchedTermsTruncated,
3801
+ selectedScope: selectedScope ? { ...selectedScope } : null,
3802
+ filterDecisions: buildDocsSearchFilterDecisions(options.filters, selectedScope),
3803
+ ambiguityResolution: buildDocsSearchAmbiguityResolution(options.filters, selectedScope, options.warnings, options.unverifiableAmbiguityFields),
3804
+ rankingReasons
3805
+ }
3806
+ };
3807
+ });
3780
3808
  }
3781
3809
  function buildSnippet(document, query) {
3782
3810
  const q = query.trim().toLowerCase();
@@ -4568,6 +4596,7 @@ function createMcpSearchAdapter(config) {
4568
4596
  query: query.query,
4569
4597
  limit: pageSize,
4570
4598
  locale: query.locale,
4599
+ ...query.explain ? { explain: true } : {},
4571
4600
  ...providerCursor !== void 0 ? { cursor: providerCursor } : {},
4572
4601
  ...forwardAudience ? { audience } : {},
4573
4602
  ...query.filters?.framework ? { framework: query.filters.framework } : {},
@@ -4994,7 +5023,8 @@ async function performDocsSearchInternal(options) {
4994
5023
  locale: options.locale,
4995
5024
  pathname: options.pathname,
4996
5025
  audience,
4997
- ...hasFilters ? { filters } : {}
5026
+ ...hasFilters ? { filters } : {},
5027
+ ...options.explain ? { explain: true } : {}
4998
5028
  };
4999
5029
  let currentIndexGeneration;
5000
5030
  const getCurrentIndexGeneration = () => {
@@ -5017,24 +5047,64 @@ async function performDocsSearchInternal(options) {
5017
5047
  });
5018
5048
  return hostedIndexGeneration;
5019
5049
  };
5020
- const finalizeResults = async (results) => enrichDocsSearchResultsWithSources({
5021
- results,
5022
- pages: scopedPages,
5023
- generationPages: options.generationPages ?? options.pages,
5024
- audience,
5025
- chunking: search.chunking,
5026
- locale: options.locale,
5027
- baseUrl: options.baseUrl,
5028
- indexGeneration: options.indexGeneration,
5029
- strictExternalOrigins: options.strictExternalOrigins,
5030
- filters,
5031
- requireCurrentIndexGeneration
5032
- });
5050
+ let explanationWarnings;
5051
+ const getExplanationWarnings = () => {
5052
+ explanationWarnings ??= buildDocsSearchWarnings({
5053
+ pages: corpusPages,
5054
+ results: [],
5055
+ filters,
5056
+ query: options.query,
5057
+ audience,
5058
+ baseUrl: options.baseUrl,
5059
+ completeResultSet: true
5060
+ });
5061
+ return explanationWarnings;
5062
+ };
5063
+ let explanationUnverifiableAmbiguityFields;
5064
+ const getExplanationUnverifiableAmbiguityFields = () => {
5065
+ explanationUnverifiableAmbiguityFields ??= new Set(SEARCH_AMBIGUITY_FIELDS.filter((field) => corpusPages.some((page) => {
5066
+ if (scoreDocument(options.query, pageToSearchDocument(page, audience)) <= 0) return false;
5067
+ const scope = resolveDocsSearchPageScope(page);
5068
+ if (hasFilters && !docsSearchPageMatchesFilters(scope, filters)) return false;
5069
+ return scope.conflicts.includes(field) || scope.declarations[field].length === 0;
5070
+ })));
5071
+ return explanationUnverifiableAmbiguityFields;
5072
+ };
5073
+ const finalizeResults = async (results, ranking = "lexical") => {
5074
+ const enriched = await enrichDocsSearchResultsWithSources({
5075
+ results,
5076
+ pages: scopedPages,
5077
+ generationPages: options.generationPages ?? options.pages,
5078
+ audience,
5079
+ chunking: search.chunking,
5080
+ locale: options.locale,
5081
+ baseUrl: options.baseUrl,
5082
+ indexGeneration: options.indexGeneration,
5083
+ strictExternalOrigins: options.strictExternalOrigins,
5084
+ filters,
5085
+ requireCurrentIndexGeneration
5086
+ });
5087
+ if (!options.explain) return enriched.map((result) => {
5088
+ const { explanation: _explanation, ...resultWithoutExplanation } = result;
5089
+ return resultWithoutExplanation;
5090
+ });
5091
+ return explainDocsSearchResults({
5092
+ results: enriched,
5093
+ documents: getDocuments(),
5094
+ query: options.query,
5095
+ filters,
5096
+ warnings: getExplanationWarnings(),
5097
+ unverifiableAmbiguityFields: getExplanationUnverifiableAmbiguityFields(),
5098
+ provider: search.provider,
5099
+ rankOffset: options.offset ?? 0,
5100
+ resolveRankingStrategy: typeof ranking === "function" ? ranking : () => ranking
5101
+ });
5102
+ };
5033
5103
  const createLocalPage = async () => {
5034
5104
  const fallback = options.paginated ? await createSimpleSearchAdapter().searchPage(query, context) : normalizeDocsSearchAdapterPage(await createSimpleSearchAdapter().search(query, context));
5035
5105
  if (options.expectedTotal !== void 0 && fallback.total !== options.expectedTotal) throw new DocsPaginationCursorError();
5036
5106
  return {
5037
- results: await finalizeResults(fallback.results),
5107
+ results: await finalizeResults(fallback.results, "lexical"),
5038
5108
  total: options.paginated ? fallback.total : fallback.results.length,
5039
5109
  paginationMode: "local"
5040
5110
  };
@@ -5084,7 +5154,7 @@ async function performDocsSearchInternal(options) {
5084
5154
  if (search.provider === "simple") {
5085
5155
  if (options.expectedTotal !== void 0 && adapterPage.total !== options.expectedTotal) throw new DocsPaginationCursorError();
5086
5156
  return {
5087
- results: await finalizeResults(results),
5157
+ results: await finalizeResults(results, "lexical"),
5088
5158
  total: options.paginated ? adapterPage.total : results.length,
5089
5159
  paginationMode: "local"
5090
5160
  };
@@ -5116,7 +5186,7 @@ async function performDocsSearchInternal(options) {
5116
5186
  const endOffset = (query.offset ?? 0) + safeAdapterResults.length;
5117
5187
  if (safeAdapterResults.length !== results.length || safeAdapterResults.length > (query.limit ?? search.maxResults) || endOffset > adapterPage.total || requireCurrentIndexGeneration && adapterPage.total === 0 && localAudienceProjectionResults.length > 0 || endOffset < adapterPage.total && safeAdapterResults.length === 0 || adapterPage.nextCursor !== void 0 && options.providerCursor !== void 0 && adapterPage.nextCursor === options.providerCursor || adapterPage.nextCursor !== void 0 && endOffset >= adapterPage.total || options.expectedTotal !== void 0 && adapterPage.total !== options.expectedTotal) return fallBackFromProvider();
5118
5188
  return {
5119
- results: await finalizeResults(safeAdapterResults),
5189
+ results: await finalizeResults(safeAdapterResults, "provider"),
5120
5190
  total: adapterPage.total,
5121
5191
  ...adapterPage.nextCursor !== void 0 ? { nextCursor: adapterPage.nextCursor } : {},
5122
5192
  paginationMode: "provider"
@@ -5125,20 +5195,30 @@ async function performDocsSearchInternal(options) {
5125
5195
  if (options.supplementExternalResults === false) {
5126
5196
  const bounded = safeAdapterResults.slice(0, query.limit ?? search.maxResults ?? DEFAULT_SEARCH_LIMIT);
5127
5197
  return {
5128
- results: await finalizeResults(bounded),
5198
+ results: await finalizeResults(bounded, "provider"),
5129
5199
  total: bounded.length,
5130
5200
  paginationMode: "provider"
5131
5201
  };
5132
5202
  }
5133
5203
  const simpleAudienceResults = audience === "agent" || results.length === 0 || safeAdapterResults.length < results.length ? await createSimpleSearchAdapter().search(query, context) : [];
5204
+ const exactPageResults = buildExactPageSearchResults(options.query, scopedPages, audience);
5205
+ const rankingStrategyByResult = /* @__PURE__ */ new Map();
5206
+ for (const [group, strategy] of [
5207
+ [exactPageResults, "exact"],
5208
+ [safeAdapterResults, "provider"],
5209
+ [simpleAudienceResults, "lexical"]
5210
+ ]) for (const result of group) {
5211
+ const identity = getDocsSearchExplanationResultIdentity(result);
5212
+ if (!rankingStrategyByResult.has(identity)) rankingStrategyByResult.set(identity, strategy);
5213
+ }
5134
5214
  const combinedResults = mergeSearchResults([
5135
- buildExactPageSearchResults(options.query, scopedPages, audience),
5215
+ exactPageResults,
5136
5216
  safeAdapterResults,
5137
5217
  simpleAudienceResults
5138
5218
  ], audience === "agent" ? (result) => getAskAIResultKey(result, options.baseUrl, options.strictExternalOrigins) : void 0);
5139
5219
  const bounded = prioritizeLiteralInsideResults(options.query, combinedResults).slice(0, query.limit ?? search.maxResults ?? DEFAULT_SEARCH_LIMIT);
5140
5220
  return {
5141
- results: await finalizeResults(bounded),
5221
+ results: await finalizeResults(bounded, (result) => rankingStrategyByResult.get(getDocsSearchExplanationResultIdentity(result)) ?? "provider"),
5142
5222
  total: bounded.length,
5143
5223
  paginationMode: "provider"
5144
5224
  };
@@ -6350,10 +6430,12 @@ function buildDocsDiagnostics(config, options = {}) {
6350
6430
  human: search.enabled ? apiQueryRoute("query={query}") : null,
6351
6431
  agent: search.enabled ? apiQueryRoute("query={query}&audience=agent") : null,
6352
6432
  structuredAgent: search.enabled ? apiQueryRoute("query={query}&audience=agent&response=structured") : null,
6433
+ explainedAgent: search.enabled ? apiQueryRoute("query={query}&audience=agent&response=structured&explain=true") : null,
6353
6434
  facets: search.enabled ? apiQueryRoute("audience=agent&response=facets") : null
6354
6435
  },
6355
6436
  agentEndpoint: search.enabled ? apiQueryRoute("query={query}&audience=agent") : null,
6356
6437
  structuredAgentEndpoint: search.enabled ? apiQueryRoute("query={query}&audience=agent&response=structured") : null,
6438
+ explainedAgentEndpoint: search.enabled ? apiQueryRoute("query={query}&audience=agent&response=structured&explain=true") : null,
6357
6439
  facetsEndpoint: search.enabled ? apiQueryRoute("audience=agent&response=facets") : null,
6358
6440
  audienceParam: "audience",
6359
6441
  defaultAudience: "human",
@@ -6365,6 +6447,10 @@ function buildDocsDiagnostics(config, options = {}) {
6365
6447
  tags: "tags"
6366
6448
  },
6367
6449
  responseFormat: "docs-search.v1",
6450
+ explainParam: "explain",
6451
+ explainValue: "true",
6452
+ explanationField: "explanation",
6453
+ explanationFormat: "docs-search-explanation.v1",
6368
6454
  facetsResponseFormat: "docs-search-facets.v1",
6369
6455
  warningsField: "warnings",
6370
6456
  facetParam: "facet",
@@ -7170,7 +7256,7 @@ function resolveDocsStandardsOrigin(preferred, fallback) {
7170
7256
  return new URL(fallback).origin;
7171
7257
  }
7172
7258
  /** Build and serve standards-based discovery without replacing the custom agent manifest. */
7173
- async function createDocsStandardsDiscoveryResponse({ request, preferredSkillDocument, fallbackSkillDocument, origin, entry = "docs", docsPath, apiCatalog: explicitApiCatalog, apiRoute, i18n: _i18n, search: _search, mcp, feedback, llms, sitemap, robots, openapi, markdown: _markdown, publishedSkills, agentCard }) {
7259
+ async function createDocsStandardsDiscoveryResponse({ request, preferredSkillDocument, fallbackSkillDocument, origin, entry = "docs", docsPath, apiCatalog: explicitApiCatalog, apiRoute, i18n: _i18n, search: _search, mcp, feedback, llms, sitemap, robots, openapi, markdown: _markdown, publishedSkills, agentCard, lastModified }) {
7174
7260
  const url = new URL(request.url);
7175
7261
  const resolvedApiRoute = resolveDocsDiscoveryApiRoute(apiRoute);
7176
7262
  if (!isDocsStandardsDiscoveryRequest(url, { apiRoute: resolvedApiRoute })) return null;
@@ -7207,6 +7293,7 @@ async function createDocsStandardsDiscoveryResponse({ request, preferredSkillDoc
7207
7293
  fallbackSkillDocument,
7208
7294
  publishedSkills,
7209
7295
  agentCard,
7296
+ lastModified,
7210
7297
  apiCatalog: apiCatalogEnabled ? buildDocsApiCatalog({
7211
7298
  origin: catalogOrigin,
7212
7299
  docsRoute: normalizedDocsPath ? `/${normalizedDocsPath}` : "/",
@@ -7879,34 +7966,6 @@ function renderDocsMarkdownNotFound({ entry = "docs", apiRoute, requestedPath, o
7879
7966
  markdownUrl: resolveDocsMarkdownMetadataUrl(requestedMarkdownRoute, origin)
7880
7967
  }), sitemap);
7881
7968
  }
7882
- function hashDocsMarkdownRepresentation(value) {
7883
- let hash = 2166136261;
7884
- for (let index = 0; index < value.length; index += 1) {
7885
- hash ^= value.charCodeAt(index);
7886
- hash = Math.imul(hash, 16777619);
7887
- }
7888
- return (hash >>> 0).toString(16).padStart(8, "0");
7889
- }
7890
- function createDocsMarkdownEtag(document) {
7891
- return `W/"${document.length.toString(16)}-${hashDocsMarkdownRepresentation(document)}"`;
7892
- }
7893
- function normalizeDocsMarkdownEtag(value) {
7894
- return value.trim().replace(/^W\//i, "");
7895
- }
7896
- function requestMatchesDocsMarkdownEtag(request, etag) {
7897
- const header = request.headers.get("if-none-match");
7898
- if (!header) return false;
7899
- if (header.trim() === "*") return true;
7900
- const expected = normalizeDocsMarkdownEtag(etag);
7901
- return header.split(",").some((candidate) => normalizeDocsMarkdownEtag(candidate) === expected);
7902
- }
7903
- function resolveDocsMarkdownHttpDate(value) {
7904
- if (!value) return void 0;
7905
- if (typeof value === "string" && !/(?:T|\s)\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?/.test(value.trim())) return;
7906
- const date = value instanceof Date ? value : new Date(value);
7907
- if (Number.isNaN(date.getTime())) return void 0;
7908
- return date.toUTCString();
7909
- }
7910
7969
  function extractDocsMarkdownLastModified(document) {
7911
7970
  const frontmatter = document.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1];
7912
7971
  if (!frontmatter) return void 0;
@@ -7915,14 +7974,6 @@ function extractDocsMarkdownLastModified(document) {
7915
7974
  if (raw.startsWith("\"") && raw.endsWith("\"") || raw.startsWith("'") && raw.endsWith("'")) return raw.slice(1, -1);
7916
7975
  return raw;
7917
7976
  }
7918
- function requestHasFreshDocsMarkdownDate(request, lastModified) {
7919
- if (!lastModified || request.headers.has("if-none-match")) return false;
7920
- const ifModifiedSince = request.headers.get("if-modified-since");
7921
- if (!ifModifiedSince) return false;
7922
- const resourceTime = Date.parse(lastModified);
7923
- const requestTime = Date.parse(ifModifiedSince);
7924
- return Number.isFinite(resourceTime) && Number.isFinite(requestTime) && Math.floor(resourceTime / 1e3) <= Math.floor(requestTime / 1e3);
7925
- }
7926
7977
  function resolveDocsMarkdownContentLocation(canonicalUrl) {
7927
7978
  const url = new URL(canonicalUrl);
7928
7979
  url.pathname = toDocsMarkdownUrl(url.pathname);
@@ -8003,35 +8054,27 @@ function createDocsMarkdownResponse(options) {
8003
8054
  byteBudget: sectionIndexRequest.byteBudget
8004
8055
  });
8005
8056
  const responseDocument = JSON.stringify(sectionIndex);
8006
- const etag = createDocsMarkdownEtag(responseDocument);
8007
- const lastModified = resolveDocsMarkdownHttpDate(options.lastModified ?? extractDocsMarkdownLastModified(document));
8008
- const responseHeaders = {
8009
- ...baseSharedHeaders,
8010
- "Content-Location": sectionIndexContentLocation,
8011
- Link: `<${canonicalUrl}>; rel="canonical", <${contentLocation}>; rel="alternate"; type="text/markdown"`,
8012
- "Cache-Control": options.cacheControl ?? "public, max-age=0, s-maxage=3600",
8013
- "Content-Type": "application/json; charset=utf-8",
8014
- ETag: etag,
8015
- "X-Docs-Markdown-Section-Index": DOCS_MARKDOWN_SECTION_INDEX_FORMAT,
8016
- "X-Docs-Markdown-Section-Count": String(sectionIndex.sectionCount),
8017
- "X-Docs-Markdown-Source-Estimated-Tokens": String(sectionIndex.estimatedTokens),
8018
- "X-Docs-Markdown-Source-Utf8-Bytes": String(sectionIndex.utf8Bytes),
8019
- "X-Docs-Markdown-Estimated-Tokens": String(estimateDocsMarkdownTokens(responseDocument)),
8020
- "X-Docs-Markdown-Utf8-Bytes": String(docsMarkdownUtf8Bytes(responseDocument)),
8021
- ...sectionIndexRequest.tokenBudget ? { "X-Docs-Markdown-Token-Budget": String(sectionIndexRequest.tokenBudget) } : {},
8022
- ...sectionIndexRequest.byteBudget ? { "X-Docs-Markdown-Byte-Budget": String(sectionIndexRequest.byteBudget) } : {},
8023
- ...lastModified ? { "Last-Modified": lastModified } : {}
8024
- };
8025
- if (requestMatchesDocsMarkdownEtag(request, etag) || requestHasFreshDocsMarkdownDate(request, lastModified)) {
8026
- const { "Content-Type": _contentType, ...notModifiedHeaders } = responseHeaders;
8027
- return new Response(null, {
8028
- status: 304,
8029
- headers: notModifiedHeaders
8030
- });
8031
- }
8032
- return new Response(request.method.toUpperCase() === "HEAD" ? null : responseDocument, {
8033
- status: 200,
8034
- headers: responseHeaders
8057
+ const lastModified = resolveDocsHttpDate(options.lastModified ?? extractDocsMarkdownLastModified(document));
8058
+ return createDocsCacheableResponse({
8059
+ request,
8060
+ content: responseDocument,
8061
+ lastModified,
8062
+ headers: {
8063
+ ...baseSharedHeaders,
8064
+ "Content-Location": sectionIndexContentLocation,
8065
+ Link: `<${canonicalUrl}>; rel="canonical", <${contentLocation}>; rel="alternate"; type="text/markdown"`,
8066
+ "Cache-Control": options.cacheControl ?? "public, max-age=0, s-maxage=3600",
8067
+ "Content-Type": "application/json; charset=utf-8",
8068
+ "X-Docs-Markdown-Section-Index": DOCS_MARKDOWN_SECTION_INDEX_FORMAT,
8069
+ "X-Docs-Markdown-Section-Count": String(sectionIndex.sectionCount),
8070
+ "X-Docs-Markdown-Source-Estimated-Tokens": String(sectionIndex.estimatedTokens),
8071
+ "X-Docs-Markdown-Source-Utf8-Bytes": String(sectionIndex.utf8Bytes),
8072
+ "X-Docs-Markdown-Estimated-Tokens": String(estimateDocsMarkdownTokens(responseDocument)),
8073
+ "X-Docs-Markdown-Utf8-Bytes": String(docsMarkdownUtf8Bytes(responseDocument)),
8074
+ ...sectionIndexRequest.tokenBudget ? { "X-Docs-Markdown-Token-Budget": String(sectionIndexRequest.tokenBudget) } : {},
8075
+ ...sectionIndexRequest.byteBudget ? { "X-Docs-Markdown-Byte-Budget": String(sectionIndexRequest.byteBudget) } : {},
8076
+ ...lastModified ? { "Last-Modified": lastModified } : {}
8077
+ }
8035
8078
  });
8036
8079
  }
8037
8080
  const sectionResult = sectionRequest ? selectDocsMarkdownSection(document, sectionRequest) : void 0;
@@ -8047,27 +8090,21 @@ function createDocsMarkdownResponse(options) {
8047
8090
  ...sectionResult.tokenBudget ? { "X-Docs-Markdown-Token-Budget": String(sectionResult.tokenBudget) } : {},
8048
8091
  ...sectionResult.byteBudget ? { "X-Docs-Markdown-Byte-Budget": String(sectionResult.byteBudget) } : {}
8049
8092
  } : {};
8050
- const etag = createDocsMarkdownEtag(responseDocument);
8051
- const lastModified = resolveDocsMarkdownHttpDate(options.lastModified ?? extractDocsMarkdownLastModified(document));
8093
+ const lastModified = resolveDocsHttpDate(options.lastModified ?? extractDocsMarkdownLastModified(document));
8052
8094
  const responseHeaders = {
8053
8095
  ...baseSharedHeaders,
8054
8096
  "Content-Location": sectionContentLocation,
8055
8097
  Link: `<${sectionCanonicalUrl}>; rel="canonical"`,
8056
8098
  "Cache-Control": sectionResult?.found === false ? "no-store" : options.cacheControl ?? "public, max-age=0, s-maxage=3600",
8057
8099
  "Content-Type": "text/markdown; charset=utf-8",
8058
- ETag: etag,
8059
8100
  ...sectionHeaders,
8060
8101
  ...lastModified ? { "Last-Modified": lastModified } : {}
8061
8102
  };
8062
- if (requestMatchesDocsMarkdownEtag(request, etag) || requestHasFreshDocsMarkdownDate(request, lastModified)) {
8063
- const { "Content-Type": _contentType, ...notModifiedHeaders } = responseHeaders;
8064
- return new Response(null, {
8065
- status: 304,
8066
- headers: notModifiedHeaders
8067
- });
8068
- }
8069
- return new Response(responseDocument, {
8103
+ return createDocsCacheableResponse({
8104
+ request,
8105
+ content: responseDocument,
8070
8106
  status: sectionResult?.found === false ? 404 : 200,
8107
+ lastModified,
8071
8108
  headers: responseHeaders
8072
8109
  });
8073
8110
  }
@@ -8118,7 +8155,7 @@ function appendDocsMarkdownNegotiationStartLines(lines, context, variant) {
8118
8155
  }
8119
8156
  function appendDocsSearchStartLine(lines, context, variant) {
8120
8157
  if (!context.searchEnabled) return;
8121
- lines.push(`- Discover valid search filters with ${context.apiRoute}?audience=agent&response=facets before choosing framework, version, package, or tags values; continue a large field with facet={field}, limit={limit}, and its nextCursor.`, 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.`);
8158
+ lines.push(`- Discover valid search filters with ${context.apiRoute}?audience=agent&response=facets before choosing framework, version, package, or tags values; continue a large field with facet={field}, limit={limit}, and its nextCursor.`, 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 and add explain=true for retrieval evidence.` : `- Search with ${context.apiRoute}?query={query}&audience=agent&response=structured when the route is unknown; optionally repeat framework, version, package, or tags filters and add explain=true for retrieval evidence.`);
8122
8159
  }
8123
8160
  function appendDocsContentChangesStartLine(lines, context) {
8124
8161
  if (!context.contentChangesEnabled) return;
@@ -8489,6 +8526,7 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
8489
8526
  endpoint: apiQueryRoute("query={query}"),
8490
8527
  agentEndpoint: apiQueryRoute("query={query}&audience=agent"),
8491
8528
  structuredAgentEndpoint: apiQueryRoute("query={query}&audience=agent&response=structured"),
8529
+ explainedAgentEndpoint: apiQueryRoute("query={query}&audience=agent&response=structured&explain=true"),
8492
8530
  facetsEndpoint: apiQueryRoute("audience=agent&response=facets"),
8493
8531
  method: "GET",
8494
8532
  queryParam: "query",
@@ -8500,6 +8538,10 @@ function buildDocsAgentDiscoverySpec({ origin, entry = "docs", apiRoute, apiCata
8500
8538
  structuredResponseValue: "structured",
8501
8539
  facetsResponseValue: "facets",
8502
8540
  responseFormat: "docs-search.v1",
8541
+ explainParam: "explain",
8542
+ explainValue: "true",
8543
+ explanationField: "explanation",
8544
+ explanationFormat: "docs-search-explanation.v1",
8503
8545
  facetsResponseFormat: "docs-search-facets.v1",
8504
8546
  filterParams: {
8505
8547
  framework: "framework",
@@ -8715,4 +8757,4 @@ function toYamlString(value) {
8715
8757
  }
8716
8758
 
8717
8759
  //#endregion
8718
- export { matchesDocsLlmsTxtSection as $, isDocsMcpResourcePath as $n, buildDocsRetrievalDigestProjection as $t, buildDocsAgentDiscoverySpec as A, normalizeAgentFramework as An, DEFAULT_SITEMAP_XML_ROUTE as At, findDocsMarkdownPage as B, normalizeDocsRelated as Bn, DOCS_CONTENT_CHANGES_FORMAT as Bt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as C, findDocsAudienceMdxTags as Cn, selectDocsMarkdownSection as Ct, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as D, agentVersionConstraintGroupsOverlap as Dn, DEFAULT_SITEMAP_MD_DOCS_ROUTE as Dt, DOCS_MARKDOWN_SECTION_INDEX_FORMAT as E, resolveDocsAudienceMdxContent as En, DEFAULT_SITEMAP_MANIFEST_PATH as Et, buildDocsMcpEndpointCandidates as F, createDocsPaginationCursor as Fn, renderDocsSitemapXml as Ft, isDocsAgentDiscoveryRequest as G, DEFAULT_MCP_WELL_KNOWN_ROUTE as Gn, createDocsContentChangesHttpResponse as Gt, getDocsMarkdownCanonicalLinkHeader as H, DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE as Hn, DOCS_CONTENT_SNAPSHOT_FORMAT as Ht, collectDocsMarkdownSections as I, paginateDocsItems as In, resolveDocsSitemapConfig as It, isDocsDiagnosticsRequest as J, getDocsMcpResourcePaths as Jn, resolveDocsContentChangesConfig as Jt, isDocsAgentsRequest as K, buildDocsMcpProtectedResourceMetadataRoute as Kn, isDocsContentChangeGeneration as Kt, createDocsMarkdownResponse as L, resolveDocsPaginationOffset as Ln, resolveDocsSitemapPageLastmod as Lt, buildDocsConfigMap as M, normalizeAgentScopeValues as Mn, createDocsSitemapResponse as Mt, buildDocsDiagnostics as N, normalizeAgentVersion as Nn, readDocsSitemapManifestFromContentMap as Nt, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as O, agentVersionConstraintMatches as On, DEFAULT_SITEMAP_MD_ROUTE as Ot, buildDocsMarkdownSectionIndex as P, DocsPaginationCursorError as Pn, renderDocsSitemapMarkdown as Pt, isDocsSkillRequest as Q, isDocsMcpRequest as Qn, buildDocsContentSnapshot as Qt, createDocsStandardsDiscoveryResponse as R, digestDocsRetrievalContent as Rn, resolveDocsSitemapRequest as Rt, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as S, findDocsAudienceMdxIssues as Sn, selectDocsLlmsTxtContent as St, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS as T, resolveDocsAudienceExposure as Tn, validateDocsAgentFeedbackPayload as Tt, getDocsMarkdownVaryHeader as U, DEFAULT_MCP_PUBLIC_ROUTE as Un, DocsContentChangesRequestError as Ut, getDocsLlmsTxtMaxCharsIssue as V, renderDocsRelatedMarkdownLines as Vn, DOCS_CONTENT_CHANGES_RESPONSE_VALUE as Vt, hasDocsMarkdownSignatureAgent as W, DEFAULT_MCP_ROUTE as Wn, createDocsContentChangeFeed as Wt, isDocsMarkdownSectionIndexRequest as X, isDocsMcpOAuthScopeToken as Xn, DocsSearchRequestError as Xt, isDocsLlmsTxtPublicRequest as Y, hasDocsMcpProtectedResourceConfig as Yn, resolveDocsContentChangesRequest as Yt, isDocsPublicGetRequest as Z, isDocsMcpProtectedResourceMetadataPath as Zn, buildDocsAskAIContext as Zt, DEFAULT_LLMS_TXT_MAX_CHARS as _, resolveDocsSearchFilters as _n, resolveDocsMarkdownRequest as _t, DEFAULT_AGENT_MD_ROUTE as a, createSimpleSearchAdapter as an, renderDocsMarkdownDocument as at, DEFAULT_OPENAPI_SCHEMA_ROUTE as b, resolveSearchRequestConfig as bn, resolveDocsRequestApiRoute as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, formatDocsAskAIPackageHints as cn, resolveDocsAgentContractMcpTools as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, performDocsSearch as dn, resolveDocsAgentsFormat as dt, buildDocsSearchDocuments as en, normalizeDocsMcpAuthorizationServerUrls as er, normalizeDocsPathSegment as et, DEFAULT_DOCS_CONFIG_ROUTE as f, performDocsSearchWithMetadata as fn, resolveDocsLlmsTxtFormat as ft, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as g, resolveDocsSearchError as gn, resolveDocsMarkdownRecovery as gt, DEFAULT_LLMS_FULL_TXT_ROUTE as h, resolveDocsSearchAudience as hn, resolveDocsMarkdownCanonicalUrl as ht, DEFAULT_AGENT_FEEDBACK_ROUTE as i, createMcpSearchAdapter as in, renderDocsLlmsTxt as it, buildDocsAgentFeedbackSchema as j, normalizeAgentLocale as jn, buildDocsSitemapManifest as jt, acceptsDocsMarkdown as k, agentVersionConstraintsOverlap as kn, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, inferDocsAskAIPackageHints as ln, resolveDocsAgentFeedbackConfig as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, resolveDocsRetrievalLastModified as mn, resolveDocsLlmsTxtSections as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, createAlgoliaSearchAdapter as nn, resolveDocsMcpProtectedResourceMetadataLocation as nr, parseDocsAgentFeedbackData as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, createTypesenseSearchAdapter as on, renderDocsMarkdownNotFound as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, resolveAskAISearchRequestConfig as pn, resolveDocsLlmsTxtRequest as pt, isDocsConfigRequest as q, getDocsMcpProtectedResourceMetadataRoutes as qn, isDocsContentChangesRequest as qt, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, createCustomSearchAdapter as rn, resolveDocsMcpResourceLocation as rr, renderDocsAgentsDocument as rt, DEFAULT_AGENT_SPEC_ROUTE as s, enrichDocsSearchDocumentsWithProvenance as sn, renderDocsSkillDocument as st, DEFAULT_AGENTS_MD_ROUTE as t, buildDocsSearchFacets as tn, normalizeDocsMcpEndpointPath as tr, normalizeDocsUrlPath as tt, DEFAULT_DOCS_API_ROUTE as u, normalizeDocsSearchFilters as un, resolveDocsAgentFeedbackRequest as ut, DEFAULT_LLMS_TXT_ROUTE as v, resolveDocsSearchRequest as vn, resolveDocsMarkdownSectionRequest as vt, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as w, resolveDocsAgentMdxContent as wn, toDocsMarkdownUrl as wt, DEFAULT_SKILL_MD_ROUTE as x, extractDocsMarkdownPromptBlocks as xn, resolveDocsSkillFormat as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, resolveLocalDocsMcpSearchConfig as yn, resolveDocsOpenApiDiscoveryConfig as yt, detectDocsMarkdownAgentRequest as z, isDocsRetrievalCanonicalUrl as zn, toDocsSitemapMarkdownUrl as zt };
8760
+ export { matchesDocsLlmsTxtSection as $, normalizeDocsMcpEndpointPath as $n, buildDocsRetrievalDigestProjection as $t, buildDocsAgentDiscoverySpec as A, normalizeAgentFramework as An, DEFAULT_SITEMAP_XML_ROUTE as At, findDocsMarkdownPage as B, DEFAULT_MCP_PROTECTED_RESOURCE_METADATA_ROUTE as Bn, DOCS_CONTENT_CHANGES_FORMAT as Bt, DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN as C, findDocsAudienceMdxTags as Cn, selectDocsMarkdownSection as Ct, DOCS_MARKDOWN_SIGNATURE_AGENT_HEADER as D, agentVersionConstraintGroupsOverlap as Dn, DEFAULT_SITEMAP_MD_DOCS_ROUTE as Dt, DOCS_MARKDOWN_SECTION_INDEX_FORMAT as E, resolveDocsAudienceMdxContent as En, DEFAULT_SITEMAP_MANIFEST_PATH as Et, buildDocsMcpEndpointCandidates as F, createDocsPaginationCursor as Fn, renderDocsSitemapXml as Ft, isDocsAgentDiscoveryRequest as G, getDocsMcpProtectedResourceMetadataRoutes as Gn, createDocsContentChangesHttpResponse as Gt, getDocsMarkdownCanonicalLinkHeader as H, DEFAULT_MCP_ROUTE as Hn, DOCS_CONTENT_SNAPSHOT_FORMAT as Ht, collectDocsMarkdownSections as I, paginateDocsItems as In, resolveDocsSitemapConfig as It, isDocsDiagnosticsRequest as J, isDocsMcpOAuthScopeToken as Jn, resolveDocsContentChangesConfig as Jt, isDocsAgentsRequest as K, getDocsMcpResourcePaths as Kn, isDocsContentChangeGeneration as Kt, createDocsMarkdownResponse as L, resolveDocsPaginationOffset as Ln, resolveDocsSitemapPageLastmod as Lt, buildDocsConfigMap as M, normalizeAgentScopeValues as Mn, createDocsSitemapResponse as Mt, buildDocsDiagnostics as N, normalizeAgentVersion as Nn, readDocsSitemapManifestFromContentMap as Nt, DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN as O, agentVersionConstraintMatches as On, DEFAULT_SITEMAP_MD_ROUTE as Ot, buildDocsMarkdownSectionIndex as P, DocsPaginationCursorError as Pn, renderDocsSitemapMarkdown as Pt, isDocsSkillRequest as Q, normalizeDocsMcpAuthorizationServerUrls as Qn, buildDocsContentSnapshot as Qt, createDocsStandardsDiscoveryResponse as R, normalizeDocsRelated as Rn, resolveDocsSitemapRequest as Rt, DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE as S, findDocsAudienceMdxIssues as Sn, selectDocsLlmsTxtContent as St, DOCS_CONFIG_MAP_TOP_LEVEL_KEYS as T, resolveDocsAudienceExposure as Tn, validateDocsAgentFeedbackPayload as Tt, getDocsMarkdownVaryHeader as U, DEFAULT_MCP_WELL_KNOWN_ROUTE as Un, DocsContentChangesRequestError as Ut, getDocsLlmsTxtMaxCharsIssue as V, DEFAULT_MCP_PUBLIC_ROUTE as Vn, DOCS_CONTENT_CHANGES_RESPONSE_VALUE as Vt, hasDocsMarkdownSignatureAgent as W, buildDocsMcpProtectedResourceMetadataRoute as Wn, createDocsContentChangeFeed as Wt, isDocsMarkdownSectionIndexRequest as X, isDocsMcpRequest as Xn, DocsSearchRequestError as Xt, isDocsLlmsTxtPublicRequest as Y, isDocsMcpProtectedResourceMetadataPath as Yn, resolveDocsContentChangesRequest as Yt, isDocsPublicGetRequest as Z, isDocsMcpResourcePath as Zn, buildDocsAskAIContext as Zt, DEFAULT_LLMS_TXT_MAX_CHARS as _, resolveDocsSearchFilters as _n, resolveDocsMarkdownRequest as _t, DEFAULT_AGENT_MD_ROUTE as a, createSimpleSearchAdapter as an, renderDocsMarkdownDocument as at, DEFAULT_OPENAPI_SCHEMA_ROUTE as b, resolveSearchRequestConfig as bn, resolveDocsRequestApiRoute as bt, DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE as c, formatDocsAskAIPackageHints as cn, resolveDocsAgentContractMcpTools as ct, DEFAULT_DOCS_CONFIG_FORMAT as d, performDocsSearch as dn, resolveDocsAgentsFormat as dt, buildDocsSearchDocuments as en, resolveDocsMcpProtectedResourceMetadataLocation as er, normalizeDocsPathSegment as et, DEFAULT_DOCS_CONFIG_ROUTE as f, performDocsSearchWithMetadata as fn, resolveDocsLlmsTxtFormat as ft, DEFAULT_LLMS_FULL_TXT_WELL_KNOWN_ROUTE as g, resolveDocsSearchError as gn, resolveDocsMarkdownRecovery as gt, DEFAULT_LLMS_FULL_TXT_ROUTE as h, resolveDocsSearchAudience as hn, resolveDocsMarkdownCanonicalUrl as ht, DEFAULT_AGENT_FEEDBACK_ROUTE as i, createMcpSearchAdapter as in, renderDocsLlmsTxt as it, buildDocsAgentFeedbackSchema as j, normalizeAgentLocale as jn, buildDocsSitemapManifest as jt, acceptsDocsMarkdown as k, agentVersionConstraintsOverlap as kn, DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE as kt, DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE as l, inferDocsAskAIPackageHints as ln, resolveDocsAgentFeedbackConfig as lt, DEFAULT_DOCS_DIAGNOSTICS_ROUTE as m, resolveDocsRetrievalLastModified as mn, resolveDocsLlmsTxtSections as mt, DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE as n, createAlgoliaSearchAdapter as nn, parseDocsAgentFeedbackData as nt, DEFAULT_AGENT_MD_WELL_KNOWN_ROUTE as o, createTypesenseSearchAdapter as on, renderDocsMarkdownNotFound as ot, DEFAULT_DOCS_DIAGNOSTICS_FORMAT as p, resolveAskAISearchRequestConfig as pn, resolveDocsLlmsTxtRequest as pt, isDocsConfigRequest as q, hasDocsMcpProtectedResourceConfig as qn, isDocsContentChangesRequest as qt, DEFAULT_AGENT_FEEDBACK_PAYLOAD_SCHEMA as r, createCustomSearchAdapter as rn, renderDocsAgentsDocument as rt, DEFAULT_AGENT_SPEC_ROUTE as s, enrichDocsSearchDocumentsWithProvenance as sn, renderDocsSkillDocument as st, DEFAULT_AGENTS_MD_ROUTE as t, buildDocsSearchFacets as tn, resolveDocsMcpResourceLocation as tr, normalizeDocsUrlPath as tt, DEFAULT_DOCS_API_ROUTE as u, normalizeDocsSearchFilters as un, resolveDocsAgentFeedbackRequest as ut, DEFAULT_LLMS_TXT_ROUTE as v, resolveDocsSearchRequest as vn, resolveDocsMarkdownSectionRequest as vt, DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN as w, resolveDocsAgentMdxContent as wn, toDocsMarkdownUrl as wt, DEFAULT_SKILL_MD_ROUTE as x, extractDocsMarkdownPromptBlocks as xn, resolveDocsSkillFormat as xt, DEFAULT_LLMS_TXT_WELL_KNOWN_ROUTE as y, resolveLocalDocsMcpSearchConfig as yn, resolveDocsOpenApiDiscoveryConfig as yt, detectDocsMarkdownAgentRequest as z, renderDocsRelatedMarkdownLines as zn, toDocsSitemapMarkdownUrl as zt };