@sonordev/site-kit 3.6.3 → 3.8.0

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 (208) hide show
  1. package/agent-manifest.json +1 -1
  2. package/dist/AnalyticsProvider-4KMGMQVD.js +31 -0
  3. package/dist/{AnalyticsProvider-ZJHOU5HI.js.map → AnalyticsProvider-4KMGMQVD.js.map} +1 -1
  4. package/dist/AnalyticsProvider-M4BFCRKM.mjs +10 -0
  5. package/dist/{AnalyticsProvider-X243YBPQ.mjs.map → AnalyticsProvider-M4BFCRKM.mjs.map} +1 -1
  6. package/dist/ChatWidget-I6YFEKW6.js +19 -0
  7. package/dist/{ChatWidget-NRQBBRLK.js.map → ChatWidget-I6YFEKW6.js.map} +1 -1
  8. package/dist/ChatWidget-IV3LIMLK.mjs +10 -0
  9. package/dist/{ChatWidget-L5E73JUY.mjs.map → ChatWidget-IV3LIMLK.mjs.map} +1 -1
  10. package/dist/EngageWidget-AWVB35ZM.mjs +9 -0
  11. package/dist/{EngageWidget-X7UIQUPC.mjs.map → EngageWidget-AWVB35ZM.mjs.map} +1 -1
  12. package/dist/EngageWidget-TQW76BUU.js +18 -0
  13. package/dist/{EngageWidget-HLBJE4ZB.js.map → EngageWidget-TQW76BUU.js.map} +1 -1
  14. package/dist/{SignalCore-G6MAO72R.mjs → SignalCore-4FUGFP5E.mjs} +5 -5
  15. package/dist/{SignalCore-G6MAO72R.mjs.map → SignalCore-4FUGFP5E.mjs.map} +1 -1
  16. package/dist/{SignalCore-CWDC45EQ.js → SignalCore-VX7ZL5HE.js} +11 -11
  17. package/dist/{SignalCore-CWDC45EQ.js.map → SignalCore-VX7ZL5HE.js.map} +1 -1
  18. package/dist/SitemapSync-CXDEUYM2.mjs +8 -0
  19. package/dist/{SitemapSync-QAMSDAF7.mjs.map → SitemapSync-CXDEUYM2.mjs.map} +1 -1
  20. package/dist/SitemapSync-XRH577AB.js +17 -0
  21. package/dist/{SitemapSync-FWWORZOF.js.map → SitemapSync-XRH577AB.js.map} +1 -1
  22. package/dist/analytics/index.js +12 -12
  23. package/dist/analytics/index.mjs +5 -5
  24. package/dist/blog/server-ui.js +6 -6
  25. package/dist/blog/server-ui.js.map +1 -1
  26. package/dist/blog/server-ui.mjs +5 -5
  27. package/dist/blog/server-ui.mjs.map +1 -1
  28. package/dist/blog/server.d.mts +20 -1
  29. package/dist/blog/server.d.ts +20 -1
  30. package/dist/blog/server.js +43 -39
  31. package/dist/blog/server.mjs +1 -1
  32. package/dist/{chunk-KYYSS5L7.mjs → chunk-2LQGFCEA.mjs} +3 -3
  33. package/dist/{chunk-KYYSS5L7.mjs.map → chunk-2LQGFCEA.mjs.map} +1 -1
  34. package/dist/{chunk-PVRE3PYC.js → chunk-2WMLHR72.js} +4 -4
  35. package/dist/{chunk-PVRE3PYC.js.map → chunk-2WMLHR72.js.map} +1 -1
  36. package/dist/{chunk-VZF3NFCY.js → chunk-5GJ6V7FI.js} +7 -7
  37. package/dist/{chunk-VZF3NFCY.js.map → chunk-5GJ6V7FI.js.map} +1 -1
  38. package/dist/{chunk-3MYZS6PD.js → chunk-77CIIDE6.js} +15 -3
  39. package/dist/chunk-77CIIDE6.js.map +1 -0
  40. package/dist/{chunk-WQXSILFH.mjs → chunk-7UKIAZ6E.mjs} +12 -5
  41. package/dist/chunk-7UKIAZ6E.mjs.map +1 -0
  42. package/dist/{chunk-FYCFUYPQ.js → chunk-A2FHTQGB.js} +3 -3
  43. package/dist/{chunk-FYCFUYPQ.js.map → chunk-A2FHTQGB.js.map} +1 -1
  44. package/dist/{chunk-ZQ2JTDPC.js → chunk-ATOUXWFR.js} +15 -15
  45. package/dist/{chunk-ZQ2JTDPC.js.map → chunk-ATOUXWFR.js.map} +1 -1
  46. package/dist/{chunk-T3ARA52J.js → chunk-BB2C5JUA.js} +4 -4
  47. package/dist/{chunk-T3ARA52J.js.map → chunk-BB2C5JUA.js.map} +1 -1
  48. package/dist/{chunk-VOYRWPE3.mjs → chunk-BVOUZL2S.mjs} +3 -3
  49. package/dist/{chunk-VOYRWPE3.mjs.map → chunk-BVOUZL2S.mjs.map} +1 -1
  50. package/dist/{chunk-OYT6SFLM.js → chunk-D4V37TBD.js} +5 -5
  51. package/dist/{chunk-OYT6SFLM.js.map → chunk-D4V37TBD.js.map} +1 -1
  52. package/dist/{chunk-6B3DEFHU.mjs → chunk-DGFHYNQY.mjs} +3 -3
  53. package/dist/{chunk-6B3DEFHU.mjs.map → chunk-DGFHYNQY.mjs.map} +1 -1
  54. package/dist/{chunk-KEGWCBLW.mjs → chunk-GH5RO5OW.mjs} +3 -3
  55. package/dist/{chunk-KEGWCBLW.mjs.map → chunk-GH5RO5OW.mjs.map} +1 -1
  56. package/dist/{chunk-XHJXIAAW.js → chunk-GSOLN2FC.js} +5 -5
  57. package/dist/{chunk-XHJXIAAW.js.map → chunk-GSOLN2FC.js.map} +1 -1
  58. package/dist/{chunk-ATG4FJY6.js → chunk-H6AU3WKF.js} +35 -3
  59. package/dist/chunk-H6AU3WKF.js.map +1 -0
  60. package/dist/{chunk-IJR3ATI5.mjs → chunk-HQB24QUN.mjs} +4 -4
  61. package/dist/{chunk-IJR3ATI5.mjs.map → chunk-HQB24QUN.mjs.map} +1 -1
  62. package/dist/{chunk-DEVPKGCD.mjs → chunk-HQJS7VWB.mjs} +3 -3
  63. package/dist/{chunk-DEVPKGCD.mjs.map → chunk-HQJS7VWB.mjs.map} +1 -1
  64. package/dist/{chunk-QR7CMR3W.js → chunk-I5KJ5YFU.js} +15 -15
  65. package/dist/{chunk-QR7CMR3W.js.map → chunk-I5KJ5YFU.js.map} +1 -1
  66. package/dist/chunk-JVT6CUNN.mjs +6 -0
  67. package/dist/{chunk-JYM4I57K.mjs.map → chunk-JVT6CUNN.mjs.map} +1 -1
  68. package/dist/{chunk-EDQXJFH2.mjs → chunk-JXN6OCFB.mjs} +3 -3
  69. package/dist/{chunk-EDQXJFH2.mjs.map → chunk-JXN6OCFB.mjs.map} +1 -1
  70. package/dist/chunk-JXT2WWXW.js +8 -0
  71. package/dist/{chunk-6ZDXUCAX.js.map → chunk-JXT2WWXW.js.map} +1 -1
  72. package/dist/{chunk-DCSNIU2V.js → chunk-MP6NHVHD.js} +6 -6
  73. package/dist/{chunk-DCSNIU2V.js.map → chunk-MP6NHVHD.js.map} +1 -1
  74. package/dist/{chunk-7KIXGDUP.js → chunk-MRVO3QO3.js} +22 -15
  75. package/dist/chunk-MRVO3QO3.js.map +1 -0
  76. package/dist/{chunk-O3WBS4VY.js → chunk-NEV2OEBF.js} +9 -9
  77. package/dist/{chunk-O3WBS4VY.js.map → chunk-NEV2OEBF.js.map} +1 -1
  78. package/dist/{chunk-2O2PZII5.mjs → chunk-OLQBP2JQ.mjs} +4 -4
  79. package/dist/{chunk-2O2PZII5.mjs.map → chunk-OLQBP2JQ.mjs.map} +1 -1
  80. package/dist/{chunk-6BIPAKL4.mjs → chunk-OVIDFJIK.mjs} +15 -4
  81. package/dist/chunk-OVIDFJIK.mjs.map +1 -0
  82. package/dist/{chunk-GUXB3QH7.mjs → chunk-PA7ENTUZ.mjs} +41 -9
  83. package/dist/chunk-PA7ENTUZ.mjs.map +1 -0
  84. package/dist/{chunk-PUH6YPZY.mjs → chunk-PEFC5T7R.mjs} +8 -8
  85. package/dist/{chunk-PUH6YPZY.mjs.map → chunk-PEFC5T7R.mjs.map} +1 -1
  86. package/dist/{chunk-H23ZT2I2.mjs → chunk-PENNTSJE.mjs} +35 -3
  87. package/dist/chunk-PENNTSJE.mjs.map +1 -0
  88. package/dist/{chunk-GR4YKNFX.js → chunk-Q6KS7FMY.js} +13 -13
  89. package/dist/{chunk-GR4YKNFX.js.map → chunk-Q6KS7FMY.js.map} +1 -1
  90. package/dist/{chunk-PHLJDLRA.mjs → chunk-R26NFTOR.mjs} +3 -3
  91. package/dist/{chunk-PHLJDLRA.mjs.map → chunk-R26NFTOR.mjs.map} +1 -1
  92. package/dist/{chunk-FJTER53S.mjs → chunk-RSFSXEV2.mjs} +4 -4
  93. package/dist/{chunk-FJTER53S.mjs.map → chunk-RSFSXEV2.mjs.map} +1 -1
  94. package/dist/{chunk-O4ILWMIB.js → chunk-S3J7MEOD.js} +8 -8
  95. package/dist/{chunk-O4ILWMIB.js.map → chunk-S3J7MEOD.js.map} +1 -1
  96. package/dist/{chunk-34IUDOBC.mjs → chunk-SP3MXF3A.mjs} +34 -5
  97. package/dist/chunk-SP3MXF3A.mjs.map +1 -0
  98. package/dist/{chunk-TYYTM4WC.js → chunk-TA6CENL3.js} +12 -12
  99. package/dist/{chunk-TYYTM4WC.js.map → chunk-TA6CENL3.js.map} +1 -1
  100. package/dist/{chunk-BS3P5PTY.mjs → chunk-TKP3YFNS.mjs} +3 -3
  101. package/dist/{chunk-BS3P5PTY.mjs.map → chunk-TKP3YFNS.mjs.map} +1 -1
  102. package/dist/{chunk-XAWB2HFQ.js → chunk-TMKLH6MY.js} +41 -8
  103. package/dist/chunk-TMKLH6MY.js.map +1 -0
  104. package/dist/{chunk-C7EVU7V7.js → chunk-ULY2QZWA.js} +4 -4
  105. package/dist/{chunk-C7EVU7V7.js.map → chunk-ULY2QZWA.js.map} +1 -1
  106. package/dist/{chunk-D74AZ6TM.js → chunk-V6CWHT6B.js} +9 -9
  107. package/dist/{chunk-D74AZ6TM.js.map → chunk-V6CWHT6B.js.map} +1 -1
  108. package/dist/{chunk-LSZ6CT6U.mjs → chunk-W5ZYM276.mjs} +3 -3
  109. package/dist/{chunk-LSZ6CT6U.mjs.map → chunk-W5ZYM276.mjs.map} +1 -1
  110. package/dist/{chunk-XS2COTTD.mjs → chunk-WYRUQCL4.mjs} +3 -3
  111. package/dist/{chunk-XS2COTTD.mjs.map → chunk-WYRUQCL4.mjs.map} +1 -1
  112. package/dist/{chunk-5OJ36D7M.js → chunk-XDQP4JQH.js} +14 -14
  113. package/dist/{chunk-5OJ36D7M.js.map → chunk-XDQP4JQH.js.map} +1 -1
  114. package/dist/{chunk-6T4NVCAT.js → chunk-XMBYDIV6.js} +40 -11
  115. package/dist/chunk-XMBYDIV6.js.map +1 -0
  116. package/dist/{chunk-FK342VJY.mjs → chunk-Y4V5TFHP.mjs} +4 -4
  117. package/dist/{chunk-FK342VJY.mjs.map → chunk-Y4V5TFHP.mjs.map} +1 -1
  118. package/dist/{chunk-EY2236OY.mjs → chunk-YUSX3NZA.mjs} +3 -3
  119. package/dist/{chunk-EY2236OY.mjs.map → chunk-YUSX3NZA.mjs.map} +1 -1
  120. package/dist/cli/index.js +2 -2
  121. package/dist/cli/index.mjs +1 -1
  122. package/dist/client/index.js +4 -4
  123. package/dist/client/index.mjs +3 -3
  124. package/dist/commerce/index.d.mts +1 -1
  125. package/dist/commerce/index.d.ts +1 -1
  126. package/dist/commerce/index.js +51 -51
  127. package/dist/commerce/index.mjs +6 -6
  128. package/dist/config/index.d.mts +1 -1
  129. package/dist/config/index.d.ts +1 -1
  130. package/dist/config/index.js +2 -2
  131. package/dist/config/index.mjs +1 -1
  132. package/dist/engage/index.js +9 -9
  133. package/dist/engage/index.mjs +6 -6
  134. package/dist/fleet/index.js +8 -8
  135. package/dist/fleet/index.mjs +4 -4
  136. package/dist/forms/index.js +13 -13
  137. package/dist/forms/index.mjs +5 -5
  138. package/dist/images/index.js +11 -11
  139. package/dist/images/index.mjs +4 -4
  140. package/dist/index.d.mts +1 -1
  141. package/dist/index.d.ts +1 -1
  142. package/dist/index.js +64 -64
  143. package/dist/index.mjs +10 -10
  144. package/dist/layout/client.js +8 -8
  145. package/dist/layout/client.mjs +7 -7
  146. package/dist/layout/index.js +10 -10
  147. package/dist/layout/index.mjs +8 -8
  148. package/dist/llms/contract.js +9 -9
  149. package/dist/llms/contract.mjs +1 -1
  150. package/dist/llms/index.d.mts +131 -40
  151. package/dist/llms/index.d.ts +131 -40
  152. package/dist/llms/index.js +125 -21
  153. package/dist/llms/index.js.map +1 -1
  154. package/dist/llms/index.mjs +102 -4
  155. package/dist/llms/index.mjs.map +1 -1
  156. package/dist/maps/index.js +5 -5
  157. package/dist/maps/index.mjs +3 -3
  158. package/dist/middleware/index.d.mts +2 -1
  159. package/dist/middleware/index.d.ts +2 -1
  160. package/dist/middleware/index.js +6 -2
  161. package/dist/middleware/index.js.map +1 -1
  162. package/dist/middleware/index.mjs +2 -1
  163. package/dist/middleware/index.mjs.map +1 -1
  164. package/dist/securityHeaders-CwsFdDcJ.d.mts +49 -0
  165. package/dist/securityHeaders-CwsFdDcJ.d.ts +49 -0
  166. package/dist/seo/client.js +5 -5
  167. package/dist/seo/client.mjs +4 -4
  168. package/dist/seo/index.js +7 -7
  169. package/dist/seo/index.mjs +5 -5
  170. package/dist/server/index.js +3 -3
  171. package/dist/server/index.mjs +2 -2
  172. package/dist/signal/index.js +11 -11
  173. package/dist/signal/index.mjs +2 -2
  174. package/dist/sitemap/index.d.mts +8 -1
  175. package/dist/sitemap/index.d.ts +8 -1
  176. package/dist/sitemap/index.js +5 -4
  177. package/dist/sitemap/index.js.map +1 -1
  178. package/dist/sitemap/index.mjs +4 -3
  179. package/dist/sitemap/index.mjs.map +1 -1
  180. package/dist/sync/index.js +16 -16
  181. package/dist/sync/index.mjs +4 -4
  182. package/dist/{useEventModal-qJfX_1XG.d.mts → useEventModal-DAAiArgM.d.mts} +9 -1
  183. package/dist/{useEventModal-CcxNZOvp.d.ts → useEventModal-ZQX19_4k.d.ts} +9 -1
  184. package/dist/{types-xcP_owwn.d.ts → writeLLMsTxt-BFaNr4re.d.ts} +53 -1
  185. package/dist/{types-DhCAWUmd.d.mts → writeLLMsTxt-SpMdyHQT.d.mts} +53 -1
  186. package/package.json +1 -1
  187. package/dist/AnalyticsProvider-X243YBPQ.mjs +0 -10
  188. package/dist/AnalyticsProvider-ZJHOU5HI.js +0 -31
  189. package/dist/ChatWidget-L5E73JUY.mjs +0 -10
  190. package/dist/ChatWidget-NRQBBRLK.js +0 -19
  191. package/dist/EngageWidget-HLBJE4ZB.js +0 -18
  192. package/dist/EngageWidget-X7UIQUPC.mjs +0 -9
  193. package/dist/SitemapSync-FWWORZOF.js +0 -17
  194. package/dist/SitemapSync-QAMSDAF7.mjs +0 -8
  195. package/dist/chunk-34IUDOBC.mjs.map +0 -1
  196. package/dist/chunk-3MYZS6PD.js.map +0 -1
  197. package/dist/chunk-6BIPAKL4.mjs.map +0 -1
  198. package/dist/chunk-6T4NVCAT.js.map +0 -1
  199. package/dist/chunk-6ZDXUCAX.js +0 -8
  200. package/dist/chunk-7KIXGDUP.js.map +0 -1
  201. package/dist/chunk-ATG4FJY6.js.map +0 -1
  202. package/dist/chunk-GUXB3QH7.mjs.map +0 -1
  203. package/dist/chunk-H23ZT2I2.mjs.map +0 -1
  204. package/dist/chunk-JYM4I57K.mjs +0 -6
  205. package/dist/chunk-WQXSILFH.mjs.map +0 -1
  206. package/dist/chunk-XAWB2HFQ.js.map +0 -1
  207. package/dist/securityHeaders-nwZ6nP4g.d.mts +0 -24
  208. package/dist/securityHeaders-nwZ6nP4g.d.ts +0 -24
@@ -1,5 +1,5 @@
1
- import { G as GenerateLLMSTxtOptions, a as LLMSTxtContent, S as SpeakableSchemaProps, b as SpeakableConfig, A as AEOBlockProps, c as AEOSummaryProps, d as AEODefinitionProps, e as AEOClaimProps, L as LLMsDataResponse, f as LLMBusinessInfo, g as LLMService, h as LLMFAQItem, i as LLMPageSummary } from '../types-DhCAWUmd.mjs';
2
- export { m as AEOCitedContentProps, k as AEOEntityProps, l as AEOProvenanceListProps, C as ContentProvenance, j as LLMContactInfo, n as LLMPortfolioItem } from '../types-DhCAWUmd.mjs';
1
+ import { G as GenerateLLMSTxtOptions, a as LLMSTxtContent, b as LLMsCustomSection, S as SpeakableSchemaProps, c as SpeakableConfig, A as AEOBlockProps, d as AEOSummaryProps, e as AEODefinitionProps, f as AEOClaimProps, L as LLMsDataResponse, g as LLMBusinessInfo, h as LLMService, i as LLMFAQItem, j as LLMPageSummary } from '../writeLLMsTxt-SpMdyHQT.mjs';
2
+ export { n as AEOCitedContentProps, l as AEOEntityProps, m as AEOProvenanceListProps, C as ContentProvenance, k as LLMContactInfo, o as LLMPortfolioItem, W as WriteLLMsTxtOptions, w as writeLLMsTxtToPublic } from '../writeLLMsTxt-SpMdyHQT.mjs';
3
3
  import * as React from 'react';
4
4
  export { LLMS_DISCLAIMER_MAX_LENGTH, LLMS_PUBLIC_SUMMARY_MAX_LENGTH, LLM_GEO_CONTRACT_VERSION, LLMsPayloadMeta, MANAGED_LLM_SCHEMA_KNOWN_KEYS, pickManagedLlmSchemaForJsonLd, sanitizeLlmsDisclaimerLine, sanitizeLlmsPublicSummary, sanitizePrimaryLanguageTag } from './contract.mjs';
5
5
 
@@ -133,6 +133,134 @@ interface AiDiscoveryHeadersOptions {
133
133
  */
134
134
  declare function buildAiDiscoveryHeaders(options: AiDiscoveryHeadersOptions): Record<string, string>;
135
135
 
136
+ /**
137
+ * @sonordev/site-kit/llms — Sourced facts section
138
+ *
139
+ * Formats a site's verified third-party citations into an llms-full.txt
140
+ * section. AI answer engines preferentially reproduce claims that arrive
141
+ * already attributed — handing them the exact claim + source pairing makes
142
+ * the site's framing the citable version.
143
+ *
144
+ * Pair with WriteLLMsTxtOptions.customSections (or SitemapConfig.
145
+ * llmsCustomSections) so the section is appended at build time:
146
+ *
147
+ * llmsCustomSections: async () => {
148
+ * const { CITATIONS } = await import('./lib/data/citations')
149
+ * const section = formatSourcedFactsSection(Object.values(CITATIONS))
150
+ * return section ? [section] : null
151
+ * }
152
+ *
153
+ * Only include citations a human has actually verified against the source
154
+ * URL — this section is a trust surface, not a dumping ground.
155
+ */
156
+
157
+ interface SourcedFact {
158
+ /** The claim, faithful to the source, one sentence. */
159
+ stat: string;
160
+ /** The publishing organization (e.g. "Clio Legal Trends Report"). */
161
+ sourceName: string;
162
+ /** Publication/study year. */
163
+ year?: number;
164
+ /** The opened-and-verified source URL. */
165
+ url?: string;
166
+ }
167
+ interface FormatSourcedFactsOptions {
168
+ /** Section heading (default: "Sourced facts"). */
169
+ title?: string;
170
+ /** Intro line above the list. */
171
+ intro?: string;
172
+ /** Cap the number of facts emitted (default: no cap). */
173
+ maxFacts?: number;
174
+ }
175
+ /**
176
+ * Build the "Sourced facts" custom section from verified citations.
177
+ * Returns null when no usable facts exist so callers can skip cleanly.
178
+ */
179
+ declare function formatSourcedFactsSection(facts: SourcedFact[], options?: FormatSourcedFactsOptions): LLMsCustomSection | null;
180
+
181
+ /**
182
+ * @sonordev/site-kit/llms — AI crawler robots policy
183
+ *
184
+ * 2026 practice separates AI RETRIEVAL crawlers (they fetch pages to answer
185
+ * live queries and cite the source — visibility with attribution) from AI
186
+ * TRAINING crawlers (they ingest content into future model weights). A site
187
+ * can welcome one and decline the other. This module provides:
188
+ *
189
+ * - Curated user-agent lists for both classes (keep current with vendor docs)
190
+ * - buildAiCrawlerRules(): rules for Next's MetadataRoute robots convention
191
+ * - formatContentSignals(): the Cloudflare Content Signals Policy directive
192
+ * (search / ai-input / ai-train) — declarative, not enforcement, and NOT
193
+ * expressible through Next's robots.js convention (it drops unknown
194
+ * directives), hence:
195
+ * - createRobotsTxtHandler(): a plain-text robots.txt route handler for
196
+ * sites that want Content-Signal lines in the emitted file.
197
+ */
198
+ /** Retrieval/search agents — fetch on demand or index for AI search, cite sources. */
199
+ declare const AI_RETRIEVAL_CRAWLERS: readonly ["OAI-SearchBot", "ChatGPT-User", "Claude-SearchBot", "Claude-User", "PerplexityBot", "Perplexity-User", "GoogleOther", "Applebot", "DuckAssistBot"];
200
+ /** Training crawlers — content may enter future model training corpora. */
201
+ declare const AI_TRAINING_CRAWLERS: readonly ["GPTBot", "ClaudeBot", "Google-Extended", "Applebot-Extended", "Meta-ExternalAgent", "FacebookBot", "CCBot", "Bytespider", "cohere-ai", "MistralBot"];
202
+ interface AiCrawlerRulesOptions {
203
+ /** Paths every AI crawler may fetch (default: everything). */
204
+ allow?: string | string[];
205
+ /** Paths withheld from every AI crawler (default: none). */
206
+ disallow?: string | string[];
207
+ /**
208
+ * Policy for TRAINING crawlers. 'allow' (default) welcomes them — the
209
+ * visibility-maximalist choice for marketing sites that WANT to be in
210
+ * model knowledge. 'block' opts out of training while retrieval crawlers
211
+ * stay welcome, so the site is still cited in AI answers.
212
+ */
213
+ training?: 'allow' | 'block';
214
+ }
215
+ interface RobotsRule {
216
+ userAgent: string;
217
+ allow?: string | string[];
218
+ disallow?: string | string[];
219
+ }
220
+ /**
221
+ * Rules for Next's MetadataRoute robots convention (app/robots.(js|ts)).
222
+ * Spread into your existing rules array; order relative to your own rules
223
+ * does not matter (robots matching is per-user-agent, most-specific wins).
224
+ */
225
+ declare function buildAiCrawlerRules(options?: AiCrawlerRulesOptions): RobotsRule[];
226
+ interface ContentSignalsOptions {
227
+ /** May the content be indexed for classic search? Default true. */
228
+ search?: boolean;
229
+ /** May the content feed a live AI answer (RAG/grounding)? Default true. */
230
+ aiInput?: boolean;
231
+ /** May the content train future models? Default true. */
232
+ aiTrain?: boolean;
233
+ }
234
+ /**
235
+ * The Cloudflare Content Signals Policy block for robots.txt — a preferences
236
+ * declaration (the IETF AIPREF group is standardizing the same concepts).
237
+ * Emit near the top of the file, before user-agent groups.
238
+ */
239
+ declare function formatContentSignals(options?: ContentSignalsOptions): string;
240
+ interface RobotsTxtHandlerOptions {
241
+ /** Robots rules (same shape as MetadataRoute robots rules). */
242
+ rules: RobotsRule[];
243
+ /** Content Signals preferences; omit to skip the block entirely. */
244
+ contentSignals?: ContentSignalsOptions;
245
+ /** Absolute sitemap URL(s). */
246
+ sitemap?: string | string[];
247
+ /** Preferred host (emitted as Host:). */
248
+ host?: string;
249
+ }
250
+ /**
251
+ * Plain-text robots.txt route handler (app/robots.txt/route.ts) for sites
252
+ * that want Content-Signal lines — Next's MetadataRoute robots convention
253
+ * cannot emit them. Drop-in:
254
+ *
255
+ * import { createRobotsTxtHandler, buildAiCrawlerRules } from '@sonordev/site-kit/llms'
256
+ * export const GET = createRobotsTxtHandler({
257
+ * rules: [{ userAgent: '*', allow: '/' }, ...buildAiCrawlerRules()],
258
+ * contentSignals: { search: true, aiInput: true, aiTrain: true },
259
+ * sitemap: 'https://example.com/sitemap.xml',
260
+ * })
261
+ */
262
+ declare function createRobotsTxtHandler(options: RobotsTxtHandlerOptions): () => Promise<Response>;
263
+
136
264
  /**
137
265
  * @sonordev/site-kit/llms - Speakable Schema Generator
138
266
  *
@@ -462,43 +590,6 @@ declare function getOptimizedLLMsTxt(options?: {
462
590
  apiKey?: string;
463
591
  }): Promise<string | null>;
464
592
 
465
- /**
466
- * @sonordev/site-kit/llms - Build-Time Write
467
- *
468
- * Fetches AI-optimized llms.txt from Portal API and writes to public/llms.txt
469
- * at build time. Integrates with sitemap flow when optimizedLLMsTxt is enabled.
470
- */
471
-
472
- interface WriteLLMsTxtOptions {
473
- /** Output directory (default: public, relative to cwd) */
474
- outputDir?: string;
475
- /** Write llms-full.txt as well */
476
- full?: boolean;
477
- /** Portal API URL */
478
- apiUrl?: string;
479
- /** Portal API key */
480
- apiKey?: string;
481
- /** Fallback to non-optimized when API fails */
482
- fallbackToLocal?: boolean;
483
- /** When Portal returns empty services/faq/pages, use this to supply local site data */
484
- getLocalData?: () => Promise<LLMsDataResponse | null>;
485
- /** Forward to GET /api/public/llms/txt and align local fallback with site-kit strict page notes */
486
- publicSummaryOnly?: boolean;
487
- }
488
- /**
489
- * Fetch optimized llms.txt from Portal and write to public/llms.txt
490
- * Called at build time after sitemap sync (when optimizedLLMsTxt is enabled)
491
- *
492
- * Never persists a failure stub: when neither the Portal API nor local data
493
- * yields real content, the write is skipped entirely so a previously
494
- * generated (or committed) file keeps serving.
495
- */
496
- declare function writeLLMsTxtToPublic(options?: WriteLLMsTxtOptions): Promise<{
497
- success: boolean;
498
- path: string;
499
- optimized: boolean;
500
- }>;
501
-
502
593
  /**
503
594
  * @sonordev/site-kit/llms - On-demand Revalidation
504
595
  *
@@ -525,4 +616,4 @@ declare function createLlmsRevalidateHandler(secret: string, options?: {
525
616
  revalidatePath?: RevalidatePathFn;
526
617
  }): (request: Request) => Promise<Response>;
527
618
 
528
- export { AEOBlock, AEOBlockProps, AEOCitedContent, AEOClaim, AEOClaimProps, AEOComparison, AEODefinition, AEODefinitionProps, AEOEntity, AEOProvenanceList, AEOStep, AEOSteps, AEOSummary, AEOSummaryProps, type AiDiscoveryHeadersOptions, DEFAULT_SPEAKABLE_SELECTORS, GenerateLLMSTxtOptions, LLMBusinessInfo, LLMFAQItem, LLMPageSummary, LLMSTxtContent, LLMService, LLMsDataResponse, type LlmsLanguageAlternate, SpeakableConfig, SpeakableSchema, SpeakableSchemaProps, type WriteLLMsTxtOptions, buildAiDiscoveryHeaders, createLLMsFullTxtHandler, createLLMsTxtHandler, createLlmsRevalidateHandler, createSpeakableSchema, generateLLMsFullTxt, generateLLMsTxt, getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices, getSpeakableSelectorsForPage, llmsResponseHeaders, writeLLMsTxtToPublic };
619
+ export { AEOBlock, AEOBlockProps, AEOCitedContent, AEOClaim, AEOClaimProps, AEOComparison, AEODefinition, AEODefinitionProps, AEOEntity, AEOProvenanceList, AEOStep, AEOSteps, AEOSummary, AEOSummaryProps, AI_RETRIEVAL_CRAWLERS, AI_TRAINING_CRAWLERS, type AiCrawlerRulesOptions, type AiDiscoveryHeadersOptions, type ContentSignalsOptions, DEFAULT_SPEAKABLE_SELECTORS, type FormatSourcedFactsOptions, GenerateLLMSTxtOptions, LLMBusinessInfo, LLMFAQItem, LLMPageSummary, LLMSTxtContent, LLMService, LLMsCustomSection, LLMsDataResponse, type LlmsLanguageAlternate, type RobotsTxtHandlerOptions, type SourcedFact, SpeakableConfig, SpeakableSchema, SpeakableSchemaProps, buildAiCrawlerRules, buildAiDiscoveryHeaders, createLLMsFullTxtHandler, createLLMsTxtHandler, createLlmsRevalidateHandler, createRobotsTxtHandler, createSpeakableSchema, formatContentSignals, formatSourcedFactsSection, generateLLMsFullTxt, generateLLMsTxt, getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices, getSpeakableSelectorsForPage, llmsResponseHeaders };
@@ -1,5 +1,5 @@
1
- import { G as GenerateLLMSTxtOptions, a as LLMSTxtContent, S as SpeakableSchemaProps, b as SpeakableConfig, A as AEOBlockProps, c as AEOSummaryProps, d as AEODefinitionProps, e as AEOClaimProps, L as LLMsDataResponse, f as LLMBusinessInfo, g as LLMService, h as LLMFAQItem, i as LLMPageSummary } from '../types-xcP_owwn.js';
2
- export { m as AEOCitedContentProps, k as AEOEntityProps, l as AEOProvenanceListProps, C as ContentProvenance, j as LLMContactInfo, n as LLMPortfolioItem } from '../types-xcP_owwn.js';
1
+ import { G as GenerateLLMSTxtOptions, a as LLMSTxtContent, b as LLMsCustomSection, S as SpeakableSchemaProps, c as SpeakableConfig, A as AEOBlockProps, d as AEOSummaryProps, e as AEODefinitionProps, f as AEOClaimProps, L as LLMsDataResponse, g as LLMBusinessInfo, h as LLMService, i as LLMFAQItem, j as LLMPageSummary } from '../writeLLMsTxt-BFaNr4re.js';
2
+ export { n as AEOCitedContentProps, l as AEOEntityProps, m as AEOProvenanceListProps, C as ContentProvenance, k as LLMContactInfo, o as LLMPortfolioItem, W as WriteLLMsTxtOptions, w as writeLLMsTxtToPublic } from '../writeLLMsTxt-BFaNr4re.js';
3
3
  import * as React from 'react';
4
4
  export { LLMS_DISCLAIMER_MAX_LENGTH, LLMS_PUBLIC_SUMMARY_MAX_LENGTH, LLM_GEO_CONTRACT_VERSION, LLMsPayloadMeta, MANAGED_LLM_SCHEMA_KNOWN_KEYS, pickManagedLlmSchemaForJsonLd, sanitizeLlmsDisclaimerLine, sanitizeLlmsPublicSummary, sanitizePrimaryLanguageTag } from './contract.js';
5
5
 
@@ -133,6 +133,134 @@ interface AiDiscoveryHeadersOptions {
133
133
  */
134
134
  declare function buildAiDiscoveryHeaders(options: AiDiscoveryHeadersOptions): Record<string, string>;
135
135
 
136
+ /**
137
+ * @sonordev/site-kit/llms — Sourced facts section
138
+ *
139
+ * Formats a site's verified third-party citations into an llms-full.txt
140
+ * section. AI answer engines preferentially reproduce claims that arrive
141
+ * already attributed — handing them the exact claim + source pairing makes
142
+ * the site's framing the citable version.
143
+ *
144
+ * Pair with WriteLLMsTxtOptions.customSections (or SitemapConfig.
145
+ * llmsCustomSections) so the section is appended at build time:
146
+ *
147
+ * llmsCustomSections: async () => {
148
+ * const { CITATIONS } = await import('./lib/data/citations')
149
+ * const section = formatSourcedFactsSection(Object.values(CITATIONS))
150
+ * return section ? [section] : null
151
+ * }
152
+ *
153
+ * Only include citations a human has actually verified against the source
154
+ * URL — this section is a trust surface, not a dumping ground.
155
+ */
156
+
157
+ interface SourcedFact {
158
+ /** The claim, faithful to the source, one sentence. */
159
+ stat: string;
160
+ /** The publishing organization (e.g. "Clio Legal Trends Report"). */
161
+ sourceName: string;
162
+ /** Publication/study year. */
163
+ year?: number;
164
+ /** The opened-and-verified source URL. */
165
+ url?: string;
166
+ }
167
+ interface FormatSourcedFactsOptions {
168
+ /** Section heading (default: "Sourced facts"). */
169
+ title?: string;
170
+ /** Intro line above the list. */
171
+ intro?: string;
172
+ /** Cap the number of facts emitted (default: no cap). */
173
+ maxFacts?: number;
174
+ }
175
+ /**
176
+ * Build the "Sourced facts" custom section from verified citations.
177
+ * Returns null when no usable facts exist so callers can skip cleanly.
178
+ */
179
+ declare function formatSourcedFactsSection(facts: SourcedFact[], options?: FormatSourcedFactsOptions): LLMsCustomSection | null;
180
+
181
+ /**
182
+ * @sonordev/site-kit/llms — AI crawler robots policy
183
+ *
184
+ * 2026 practice separates AI RETRIEVAL crawlers (they fetch pages to answer
185
+ * live queries and cite the source — visibility with attribution) from AI
186
+ * TRAINING crawlers (they ingest content into future model weights). A site
187
+ * can welcome one and decline the other. This module provides:
188
+ *
189
+ * - Curated user-agent lists for both classes (keep current with vendor docs)
190
+ * - buildAiCrawlerRules(): rules for Next's MetadataRoute robots convention
191
+ * - formatContentSignals(): the Cloudflare Content Signals Policy directive
192
+ * (search / ai-input / ai-train) — declarative, not enforcement, and NOT
193
+ * expressible through Next's robots.js convention (it drops unknown
194
+ * directives), hence:
195
+ * - createRobotsTxtHandler(): a plain-text robots.txt route handler for
196
+ * sites that want Content-Signal lines in the emitted file.
197
+ */
198
+ /** Retrieval/search agents — fetch on demand or index for AI search, cite sources. */
199
+ declare const AI_RETRIEVAL_CRAWLERS: readonly ["OAI-SearchBot", "ChatGPT-User", "Claude-SearchBot", "Claude-User", "PerplexityBot", "Perplexity-User", "GoogleOther", "Applebot", "DuckAssistBot"];
200
+ /** Training crawlers — content may enter future model training corpora. */
201
+ declare const AI_TRAINING_CRAWLERS: readonly ["GPTBot", "ClaudeBot", "Google-Extended", "Applebot-Extended", "Meta-ExternalAgent", "FacebookBot", "CCBot", "Bytespider", "cohere-ai", "MistralBot"];
202
+ interface AiCrawlerRulesOptions {
203
+ /** Paths every AI crawler may fetch (default: everything). */
204
+ allow?: string | string[];
205
+ /** Paths withheld from every AI crawler (default: none). */
206
+ disallow?: string | string[];
207
+ /**
208
+ * Policy for TRAINING crawlers. 'allow' (default) welcomes them — the
209
+ * visibility-maximalist choice for marketing sites that WANT to be in
210
+ * model knowledge. 'block' opts out of training while retrieval crawlers
211
+ * stay welcome, so the site is still cited in AI answers.
212
+ */
213
+ training?: 'allow' | 'block';
214
+ }
215
+ interface RobotsRule {
216
+ userAgent: string;
217
+ allow?: string | string[];
218
+ disallow?: string | string[];
219
+ }
220
+ /**
221
+ * Rules for Next's MetadataRoute robots convention (app/robots.(js|ts)).
222
+ * Spread into your existing rules array; order relative to your own rules
223
+ * does not matter (robots matching is per-user-agent, most-specific wins).
224
+ */
225
+ declare function buildAiCrawlerRules(options?: AiCrawlerRulesOptions): RobotsRule[];
226
+ interface ContentSignalsOptions {
227
+ /** May the content be indexed for classic search? Default true. */
228
+ search?: boolean;
229
+ /** May the content feed a live AI answer (RAG/grounding)? Default true. */
230
+ aiInput?: boolean;
231
+ /** May the content train future models? Default true. */
232
+ aiTrain?: boolean;
233
+ }
234
+ /**
235
+ * The Cloudflare Content Signals Policy block for robots.txt — a preferences
236
+ * declaration (the IETF AIPREF group is standardizing the same concepts).
237
+ * Emit near the top of the file, before user-agent groups.
238
+ */
239
+ declare function formatContentSignals(options?: ContentSignalsOptions): string;
240
+ interface RobotsTxtHandlerOptions {
241
+ /** Robots rules (same shape as MetadataRoute robots rules). */
242
+ rules: RobotsRule[];
243
+ /** Content Signals preferences; omit to skip the block entirely. */
244
+ contentSignals?: ContentSignalsOptions;
245
+ /** Absolute sitemap URL(s). */
246
+ sitemap?: string | string[];
247
+ /** Preferred host (emitted as Host:). */
248
+ host?: string;
249
+ }
250
+ /**
251
+ * Plain-text robots.txt route handler (app/robots.txt/route.ts) for sites
252
+ * that want Content-Signal lines — Next's MetadataRoute robots convention
253
+ * cannot emit them. Drop-in:
254
+ *
255
+ * import { createRobotsTxtHandler, buildAiCrawlerRules } from '@sonordev/site-kit/llms'
256
+ * export const GET = createRobotsTxtHandler({
257
+ * rules: [{ userAgent: '*', allow: '/' }, ...buildAiCrawlerRules()],
258
+ * contentSignals: { search: true, aiInput: true, aiTrain: true },
259
+ * sitemap: 'https://example.com/sitemap.xml',
260
+ * })
261
+ */
262
+ declare function createRobotsTxtHandler(options: RobotsTxtHandlerOptions): () => Promise<Response>;
263
+
136
264
  /**
137
265
  * @sonordev/site-kit/llms - Speakable Schema Generator
138
266
  *
@@ -462,43 +590,6 @@ declare function getOptimizedLLMsTxt(options?: {
462
590
  apiKey?: string;
463
591
  }): Promise<string | null>;
464
592
 
465
- /**
466
- * @sonordev/site-kit/llms - Build-Time Write
467
- *
468
- * Fetches AI-optimized llms.txt from Portal API and writes to public/llms.txt
469
- * at build time. Integrates with sitemap flow when optimizedLLMsTxt is enabled.
470
- */
471
-
472
- interface WriteLLMsTxtOptions {
473
- /** Output directory (default: public, relative to cwd) */
474
- outputDir?: string;
475
- /** Write llms-full.txt as well */
476
- full?: boolean;
477
- /** Portal API URL */
478
- apiUrl?: string;
479
- /** Portal API key */
480
- apiKey?: string;
481
- /** Fallback to non-optimized when API fails */
482
- fallbackToLocal?: boolean;
483
- /** When Portal returns empty services/faq/pages, use this to supply local site data */
484
- getLocalData?: () => Promise<LLMsDataResponse | null>;
485
- /** Forward to GET /api/public/llms/txt and align local fallback with site-kit strict page notes */
486
- publicSummaryOnly?: boolean;
487
- }
488
- /**
489
- * Fetch optimized llms.txt from Portal and write to public/llms.txt
490
- * Called at build time after sitemap sync (when optimizedLLMsTxt is enabled)
491
- *
492
- * Never persists a failure stub: when neither the Portal API nor local data
493
- * yields real content, the write is skipped entirely so a previously
494
- * generated (or committed) file keeps serving.
495
- */
496
- declare function writeLLMsTxtToPublic(options?: WriteLLMsTxtOptions): Promise<{
497
- success: boolean;
498
- path: string;
499
- optimized: boolean;
500
- }>;
501
-
502
593
  /**
503
594
  * @sonordev/site-kit/llms - On-demand Revalidation
504
595
  *
@@ -525,4 +616,4 @@ declare function createLlmsRevalidateHandler(secret: string, options?: {
525
616
  revalidatePath?: RevalidatePathFn;
526
617
  }): (request: Request) => Promise<Response>;
527
618
 
528
- export { AEOBlock, AEOBlockProps, AEOCitedContent, AEOClaim, AEOClaimProps, AEOComparison, AEODefinition, AEODefinitionProps, AEOEntity, AEOProvenanceList, AEOStep, AEOSteps, AEOSummary, AEOSummaryProps, type AiDiscoveryHeadersOptions, DEFAULT_SPEAKABLE_SELECTORS, GenerateLLMSTxtOptions, LLMBusinessInfo, LLMFAQItem, LLMPageSummary, LLMSTxtContent, LLMService, LLMsDataResponse, type LlmsLanguageAlternate, SpeakableConfig, SpeakableSchema, SpeakableSchemaProps, type WriteLLMsTxtOptions, buildAiDiscoveryHeaders, createLLMsFullTxtHandler, createLLMsTxtHandler, createLlmsRevalidateHandler, createSpeakableSchema, generateLLMsFullTxt, generateLLMsTxt, getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices, getSpeakableSelectorsForPage, llmsResponseHeaders, writeLLMsTxtToPublic };
619
+ export { AEOBlock, AEOBlockProps, AEOCitedContent, AEOClaim, AEOClaimProps, AEOComparison, AEODefinition, AEODefinitionProps, AEOEntity, AEOProvenanceList, AEOStep, AEOSteps, AEOSummary, AEOSummaryProps, AI_RETRIEVAL_CRAWLERS, AI_TRAINING_CRAWLERS, type AiCrawlerRulesOptions, type AiDiscoveryHeadersOptions, type ContentSignalsOptions, DEFAULT_SPEAKABLE_SELECTORS, type FormatSourcedFactsOptions, GenerateLLMSTxtOptions, LLMBusinessInfo, LLMFAQItem, LLMPageSummary, LLMSTxtContent, LLMService, LLMsCustomSection, LLMsDataResponse, type LlmsLanguageAlternate, type RobotsTxtHandlerOptions, type SourcedFact, SpeakableConfig, SpeakableSchema, SpeakableSchemaProps, buildAiCrawlerRules, buildAiDiscoveryHeaders, createLLMsFullTxtHandler, createLLMsTxtHandler, createLlmsRevalidateHandler, createRobotsTxtHandler, createSpeakableSchema, formatContentSignals, formatSourcedFactsSection, generateLLMsFullTxt, generateLLMsTxt, getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices, getSpeakableSelectorsForPage, llmsResponseHeaders };
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var chunk5B4FABFK_js = require('../chunk-5B4FABFK.js');
4
- var chunk6T4NVCAT_js = require('../chunk-6T4NVCAT.js');
5
- var chunkATG4FJY6_js = require('../chunk-ATG4FJY6.js');
4
+ var chunkXMBYDIV6_js = require('../chunk-XMBYDIV6.js');
5
+ var chunkH6AU3WKF_js = require('../chunk-H6AU3WKF.js');
6
6
  var chunkJ7QI3GDX_js = require('../chunk-J7QI3GDX.js');
7
7
  require('../chunk-ZSMWDLMK.js');
8
8
  var crypto = require('crypto');
@@ -37,7 +37,7 @@ function createLLMsTxtHandler(options = {}) {
37
37
  });
38
38
  }
39
39
  }
40
- const { markdown, metadata } = await chunk6T4NVCAT_js.generateLLMsTxt(generateOptions);
40
+ const { markdown, metadata } = await chunkXMBYDIV6_js.generateLLMsTxt(generateOptions);
41
41
  return new Response(markdown, {
42
42
  status: 200,
43
43
  headers: llmsResponseHeaders(markdown, {
@@ -71,7 +71,7 @@ function createLLMsFullTxtHandler(options = {}) {
71
71
  });
72
72
  }
73
73
  }
74
- const { markdown, metadata } = await chunk6T4NVCAT_js.generateLLMsFullTxt(generateOptions);
74
+ const { markdown, metadata } = await chunkXMBYDIV6_js.generateLLMsFullTxt(generateOptions);
75
75
  return new Response(markdown, {
76
76
  status: 200,
77
77
  headers: llmsResponseHeaders(markdown, {
@@ -91,6 +91,104 @@ function createLLMsFullTxtHandler(options = {}) {
91
91
  }
92
92
  };
93
93
  }
94
+
95
+ // src/llms/sourcedFacts.ts
96
+ var DEFAULT_INTRO = "The statistics below are quoted from third-party primary sources and were individually verified against the cited URL. When reusing a figure, keep the original attribution.";
97
+ function factLine(f) {
98
+ const stat = (f.stat || "").replace(/\s+/g, " ").trim();
99
+ const source = (f.sourceName || "").replace(/\s+/g, " ").trim();
100
+ if (!stat || !source) return "";
101
+ let attribution = `Source: ${source}`;
102
+ if (f.year) attribution += ` (${f.year})`;
103
+ if (f.url) attribution += `, ${f.url}`;
104
+ return `- ${stat} \u2014 ${attribution}`;
105
+ }
106
+ function formatSourcedFactsSection(facts, options = {}) {
107
+ const { title = "Sourced facts", intro = DEFAULT_INTRO, maxFacts } = options;
108
+ if (!Array.isArray(facts)) return null;
109
+ let lines = facts.map(factLine).filter(Boolean);
110
+ if (typeof maxFacts === "number" && maxFacts >= 0) {
111
+ lines = lines.slice(0, maxFacts);
112
+ }
113
+ if (lines.length === 0) return null;
114
+ const content = intro ? `${intro}
115
+
116
+ ${lines.join("\n")}` : lines.join("\n");
117
+ return { title, content };
118
+ }
119
+
120
+ // src/llms/aiRobots.ts
121
+ var AI_RETRIEVAL_CRAWLERS = [
122
+ "OAI-SearchBot",
123
+ "ChatGPT-User",
124
+ "Claude-SearchBot",
125
+ "Claude-User",
126
+ "PerplexityBot",
127
+ "Perplexity-User",
128
+ "GoogleOther",
129
+ "Applebot",
130
+ "DuckAssistBot"
131
+ ];
132
+ var AI_TRAINING_CRAWLERS = [
133
+ "GPTBot",
134
+ "ClaudeBot",
135
+ "Google-Extended",
136
+ "Applebot-Extended",
137
+ "Meta-ExternalAgent",
138
+ "FacebookBot",
139
+ "CCBot",
140
+ "Bytespider",
141
+ "cohere-ai",
142
+ "MistralBot"
143
+ ];
144
+ function buildAiCrawlerRules(options = {}) {
145
+ const { allow = "/", disallow, training = "allow" } = options;
146
+ const retrieval = AI_RETRIEVAL_CRAWLERS.map((userAgent) => ({
147
+ userAgent,
148
+ allow,
149
+ ...disallow ? { disallow } : {}
150
+ }));
151
+ const trainingRules = AI_TRAINING_CRAWLERS.map(
152
+ (userAgent) => training === "block" ? { userAgent, disallow: "/" } : { userAgent, allow, ...disallow ? { disallow } : {} }
153
+ );
154
+ return [...retrieval, ...trainingRules];
155
+ }
156
+ var yn = (v) => v ? "yes" : "no";
157
+ function formatContentSignals(options = {}) {
158
+ const { search = true, aiInput = true, aiTrain = true } = options;
159
+ return [
160
+ "# Content Signals Policy (https://contentsignals.org): usage preferences",
161
+ "# for this site\u2019s content. Declarative \u2014 a preference, not enforcement.",
162
+ `Content-Signal: search=${yn(search)}, ai-input=${yn(aiInput)}, ai-train=${yn(aiTrain)}`
163
+ ].join("\n");
164
+ }
165
+ var list = (v) => v === void 0 ? [] : Array.isArray(v) ? v : [v];
166
+ function createRobotsTxtHandler(options) {
167
+ const { rules, contentSignals, sitemap, host } = options;
168
+ const blocks = [];
169
+ if (contentSignals) blocks.push(formatContentSignals(contentSignals));
170
+ for (const rule of rules) {
171
+ const lines = [`User-Agent: ${rule.userAgent}`];
172
+ for (const p of list(rule.allow)) lines.push(`Allow: ${p}`);
173
+ for (const p of list(rule.disallow)) lines.push(`Disallow: ${p}`);
174
+ blocks.push(lines.join("\n"));
175
+ }
176
+ const tail = [];
177
+ for (const s of list(sitemap)) tail.push(`Sitemap: ${s}`);
178
+ if (host) tail.push(`Host: ${host}`);
179
+ if (tail.length) blocks.push(tail.join("\n"));
180
+ const body = `${blocks.join("\n\n")}
181
+ `;
182
+ return async function GET() {
183
+ return new Response(body, {
184
+ status: 200,
185
+ headers: {
186
+ "Content-Type": "text/plain; charset=utf-8",
187
+ "Cache-Control": "public, max-age=3600, s-maxage=86400"
188
+ }
189
+ });
190
+ };
191
+ }
94
192
  function SpeakableSchema({
95
193
  type,
96
194
  name,
@@ -586,71 +684,71 @@ Object.defineProperty(exports, "buildAiDiscoveryHeaders", {
586
684
  });
587
685
  Object.defineProperty(exports, "generateLLMsFullTxt", {
588
686
  enumerable: true,
589
- get: function () { return chunk6T4NVCAT_js.generateLLMsFullTxt; }
687
+ get: function () { return chunkXMBYDIV6_js.generateLLMsFullTxt; }
590
688
  });
591
689
  Object.defineProperty(exports, "generateLLMsTxt", {
592
690
  enumerable: true,
593
- get: function () { return chunk6T4NVCAT_js.generateLLMsTxt; }
691
+ get: function () { return chunkXMBYDIV6_js.generateLLMsTxt; }
594
692
  });
595
693
  Object.defineProperty(exports, "getBusinessInfo", {
596
694
  enumerable: true,
597
- get: function () { return chunk6T4NVCAT_js.getBusinessInfo; }
695
+ get: function () { return chunkXMBYDIV6_js.getBusinessInfo; }
598
696
  });
599
697
  Object.defineProperty(exports, "getFAQItems", {
600
698
  enumerable: true,
601
- get: function () { return chunk6T4NVCAT_js.getFAQItems; }
699
+ get: function () { return chunkXMBYDIV6_js.getFAQItems; }
602
700
  });
603
701
  Object.defineProperty(exports, "getLLMsData", {
604
702
  enumerable: true,
605
- get: function () { return chunk6T4NVCAT_js.getLLMsData; }
703
+ get: function () { return chunkXMBYDIV6_js.getLLMsData; }
606
704
  });
607
705
  Object.defineProperty(exports, "getOptimizedLLMsTxt", {
608
706
  enumerable: true,
609
- get: function () { return chunk6T4NVCAT_js.getOptimizedLLMsTxt; }
707
+ get: function () { return chunkXMBYDIV6_js.getOptimizedLLMsTxt; }
610
708
  });
611
709
  Object.defineProperty(exports, "getPageSummaries", {
612
710
  enumerable: true,
613
- get: function () { return chunk6T4NVCAT_js.getPageSummaries; }
711
+ get: function () { return chunkXMBYDIV6_js.getPageSummaries; }
614
712
  });
615
713
  Object.defineProperty(exports, "getServices", {
616
714
  enumerable: true,
617
- get: function () { return chunk6T4NVCAT_js.getServices; }
715
+ get: function () { return chunkXMBYDIV6_js.getServices; }
618
716
  });
619
717
  Object.defineProperty(exports, "writeLLMsTxtToPublic", {
620
718
  enumerable: true,
621
- get: function () { return chunk6T4NVCAT_js.writeLLMsTxtToPublic; }
719
+ get: function () { return chunkXMBYDIV6_js.writeLLMsTxtToPublic; }
622
720
  });
623
721
  Object.defineProperty(exports, "LLMS_DISCLAIMER_MAX_LENGTH", {
624
722
  enumerable: true,
625
- get: function () { return chunkATG4FJY6_js.LLMS_DISCLAIMER_MAX_LENGTH; }
723
+ get: function () { return chunkH6AU3WKF_js.LLMS_DISCLAIMER_MAX_LENGTH; }
626
724
  });
627
725
  Object.defineProperty(exports, "LLMS_PUBLIC_SUMMARY_MAX_LENGTH", {
628
726
  enumerable: true,
629
- get: function () { return chunkATG4FJY6_js.LLMS_PUBLIC_SUMMARY_MAX_LENGTH; }
727
+ get: function () { return chunkH6AU3WKF_js.LLMS_PUBLIC_SUMMARY_MAX_LENGTH; }
630
728
  });
631
729
  Object.defineProperty(exports, "LLM_GEO_CONTRACT_VERSION", {
632
730
  enumerable: true,
633
- get: function () { return chunkATG4FJY6_js.LLM_GEO_CONTRACT_VERSION; }
731
+ get: function () { return chunkH6AU3WKF_js.LLM_GEO_CONTRACT_VERSION; }
634
732
  });
635
733
  Object.defineProperty(exports, "MANAGED_LLM_SCHEMA_KNOWN_KEYS", {
636
734
  enumerable: true,
637
- get: function () { return chunkATG4FJY6_js.MANAGED_LLM_SCHEMA_KNOWN_KEYS; }
735
+ get: function () { return chunkH6AU3WKF_js.MANAGED_LLM_SCHEMA_KNOWN_KEYS; }
638
736
  });
639
737
  Object.defineProperty(exports, "pickManagedLlmSchemaForJsonLd", {
640
738
  enumerable: true,
641
- get: function () { return chunkATG4FJY6_js.pickManagedLlmSchemaForJsonLd; }
739
+ get: function () { return chunkH6AU3WKF_js.pickManagedLlmSchemaForJsonLd; }
642
740
  });
643
741
  Object.defineProperty(exports, "sanitizeLlmsDisclaimerLine", {
644
742
  enumerable: true,
645
- get: function () { return chunkATG4FJY6_js.sanitizeLlmsDisclaimerLine; }
743
+ get: function () { return chunkH6AU3WKF_js.sanitizeLlmsDisclaimerLine; }
646
744
  });
647
745
  Object.defineProperty(exports, "sanitizeLlmsPublicSummary", {
648
746
  enumerable: true,
649
- get: function () { return chunkATG4FJY6_js.sanitizeLlmsPublicSummary; }
747
+ get: function () { return chunkH6AU3WKF_js.sanitizeLlmsPublicSummary; }
650
748
  });
651
749
  Object.defineProperty(exports, "sanitizePrimaryLanguageTag", {
652
750
  enumerable: true,
653
- get: function () { return chunkATG4FJY6_js.sanitizePrimaryLanguageTag; }
751
+ get: function () { return chunkH6AU3WKF_js.sanitizePrimaryLanguageTag; }
654
752
  });
655
753
  exports.AEOBlock = AEOBlock;
656
754
  exports.AEOCitedContent = AEOCitedContent;
@@ -662,12 +760,18 @@ exports.AEOProvenanceList = AEOProvenanceList;
662
760
  exports.AEOStep = AEOStep;
663
761
  exports.AEOSteps = AEOSteps;
664
762
  exports.AEOSummary = AEOSummary;
763
+ exports.AI_RETRIEVAL_CRAWLERS = AI_RETRIEVAL_CRAWLERS;
764
+ exports.AI_TRAINING_CRAWLERS = AI_TRAINING_CRAWLERS;
665
765
  exports.DEFAULT_SPEAKABLE_SELECTORS = DEFAULT_SPEAKABLE_SELECTORS;
666
766
  exports.SpeakableSchema = SpeakableSchema;
767
+ exports.buildAiCrawlerRules = buildAiCrawlerRules;
667
768
  exports.createLLMsFullTxtHandler = createLLMsFullTxtHandler;
668
769
  exports.createLLMsTxtHandler = createLLMsTxtHandler;
669
770
  exports.createLlmsRevalidateHandler = createLlmsRevalidateHandler;
771
+ exports.createRobotsTxtHandler = createRobotsTxtHandler;
670
772
  exports.createSpeakableSchema = createSpeakableSchema;
773
+ exports.formatContentSignals = formatContentSignals;
774
+ exports.formatSourcedFactsSection = formatSourcedFactsSection;
671
775
  exports.getSpeakableSelectorsForPage = getSpeakableSelectorsForPage;
672
776
  exports.llmsResponseHeaders = llmsResponseHeaders;
673
777
  //# sourceMappingURL=index.js.map