@queryrev/ai-readiness 0.0.0-stage → 1.0.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 (66) hide show
  1. package/CITATION.cff +31 -0
  2. package/LICENSE +21 -0
  3. package/README.md +190 -2
  4. package/SECURITY.md +34 -0
  5. package/data/LICENSE +409 -0
  6. package/dist/chunks/cli-BK65ic84.js +56 -0
  7. package/dist/chunks/fetch-text-NUUnM91O.js +866 -0
  8. package/dist/chunks/findings-_twhMw3_.js +2950 -0
  9. package/dist/chunks/main-CJu6SE-W.js +1491 -0
  10. package/dist/cli/args.d.ts +27 -0
  11. package/dist/cli/bin.d.ts +2 -0
  12. package/dist/cli/commands/check.d.ts +4 -0
  13. package/dist/cli/commands/crawlers.d.ts +3 -0
  14. package/dist/cli/commands/llms-generate.d.ts +4 -0
  15. package/dist/cli/commands/llms-validate.d.ts +4 -0
  16. package/dist/cli/commands/robots-test.d.ts +4 -0
  17. package/dist/cli/common.d.ts +27 -0
  18. package/dist/cli/finding.d.ts +3 -0
  19. package/dist/cli/main.d.ts +7 -0
  20. package/dist/cli/node-context.d.ts +3 -0
  21. package/dist/cli/render.d.ts +26 -0
  22. package/dist/cli/run.d.ts +11 -0
  23. package/dist/cli/sanitize.d.ts +8 -0
  24. package/dist/cli/types.d.ts +59 -0
  25. package/dist/cli/usage.d.ts +1 -0
  26. package/dist/cli.js +36 -0
  27. package/dist/crawlers/index.d.ts +79 -0
  28. package/dist/facts/app-shell.d.ts +24 -0
  29. package/dist/facts/check-site.d.ts +13 -0
  30. package/dist/facts/domain.d.ts +15 -0
  31. package/dist/facts/findings.d.ts +5 -0
  32. package/dist/facts/home-page.d.ts +18 -0
  33. package/dist/facts/home-response.d.ts +5 -0
  34. package/dist/facts/html.d.ts +37 -0
  35. package/dist/facts/index.d.ts +16 -0
  36. package/dist/facts/json-ld.d.ts +35 -0
  37. package/dist/facts/marks.d.ts +51 -0
  38. package/dist/facts/organization.d.ts +23 -0
  39. package/dist/facts/origin-robots.d.ts +20 -0
  40. package/dist/facts/profiles.d.ts +13 -0
  41. package/dist/facts/reader.d.ts +2 -0
  42. package/dist/facts/schema-org-organization-types.d.ts +6 -0
  43. package/dist/facts/schema-org-types.d.ts +2 -0
  44. package/dist/facts/sitemap.d.ts +24 -0
  45. package/dist/facts/types.d.ts +214 -0
  46. package/dist/facts/words.d.ts +15 -0
  47. package/dist/generate/generate-llms.d.ts +51 -0
  48. package/dist/generate/index.d.ts +70 -0
  49. package/dist/index.d.ts +10 -0
  50. package/dist/index.js +1023 -0
  51. package/dist/llms/findings.d.ts +7 -0
  52. package/dist/llms/index.d.ts +88 -0
  53. package/dist/llms/links.d.ts +46 -0
  54. package/dist/net/address.d.ts +26 -0
  55. package/dist/net/charset.d.ts +20 -0
  56. package/dist/net/cli.d.ts +13 -0
  57. package/dist/net/fetch-text.d.ts +191 -0
  58. package/dist/net/guard.d.ts +71 -0
  59. package/dist/net/testing/fixture-fetcher.d.ts +15 -0
  60. package/dist/net/testing/fixture-guard.d.ts +20 -0
  61. package/dist/net/testing/index.d.ts +7 -0
  62. package/dist/net-cli.js +1 -0
  63. package/dist/robots/index.d.ts +67 -0
  64. package/dist/run.js +1 -0
  65. package/dist/testing.js +58 -0
  66. package/package.json +80 -6
@@ -0,0 +1,2 @@
1
+ /** The product token this reader uses when it matches robots.txt rules (its user agent's product). */
2
+ export declare const READER_TOKEN = "QueryRev-AIReadiness";
@@ -0,0 +1,6 @@
1
+ /** The schema.org release the list below was read from. */
2
+ export declare const SCHEMA_ORG_VERSION = "30.1";
3
+ /** SHA-256 of that release's vocabulary file (schemaorg-current-https.jsonld). */
4
+ export declare const SCHEMA_ORG_SHA256 = "0a4b8c4c910fc831ec8695196510973390906a5ee34dc6b862dfec4d21a12f74";
5
+ /** `Organization` and every schema.org type that is a subtype of it, sorted. */
6
+ export declare const ORGANIZATION_TYPES: readonly string[];
@@ -0,0 +1,2 @@
1
+ /** Every type of schema.org 30.1 (classes and data types), sorted. */
2
+ export declare const SCHEMA_ORG_TYPES: readonly string[];
@@ -0,0 +1,24 @@
1
+ import type { SitemapFacts } from './types.js';
2
+ /** A sitemap is read to this many bytes after decompression (the fetch cap for a sitemap). */
3
+ export declare const SITEMAP_MAX_BYTES: number;
4
+ /** `<loc>` entries or text lines counted at most. */
5
+ export declare const MAX_LOCS_COUNTED = 100000;
6
+ export interface ReadSitemapOptions {
7
+ /** The bytes were already cut at the fetch cap. */
8
+ readonly truncated?: boolean;
9
+ readonly registrableDomain?: (host: string) => string;
10
+ }
11
+ /**
12
+ * The sitemap rules on text that is already decoded and inflated. `truncated` says the text was
13
+ * cut at the cap: it is then read as far as it goes.
14
+ */
15
+ export declare function readSitemapText(text: string, contentType: string | null, siteUrl: string, options?: ReadSitemapOptions & {
16
+ readonly gzip?: boolean;
17
+ }): SitemapFacts;
18
+ /**
19
+ * Reads a sitemap file from its bytes as served. A gzip file (the `.gz` sitemap, found by its
20
+ * two first bytes) is inflated to at most `SITEMAP_MAX_BYTES`; a file that goes past the cap is
21
+ * cut there and reported as `truncated`, and valid as far as it was read. `siteUrl` is the
22
+ * site's own address: only `<loc>` entries on its registrable domain count.
23
+ */
24
+ export declare function readSitemap(bytes: Uint8Array, contentType: string | null, siteUrl: string, options?: ReadSitemapOptions): Promise<SitemapFacts>;
@@ -0,0 +1,214 @@
1
+ import type { TextFetcher } from '../net/fetch-text.js';
2
+ /**
3
+ * The result types of the readers and of `checkSite`. They are plain data (no classes, no
4
+ * functions), so a result can be written to JSON and read back: the study runner, the check
5
+ * pages and the command line all build on these shapes.
6
+ *
7
+ * Nothing here is a score. A check returns findings with evidence; counts and shares are for
8
+ * whoever collects many of them.
9
+ */
10
+ /** One result of a check, stable enough to be matched by `id` across versions. */
11
+ export type FindingLevel = 'pass' | 'warn' | 'fail' | 'info';
12
+ export interface Finding {
13
+ /** Stable name of the check (`organization-schema`, `sitemap-valid`). Never reused. */
14
+ readonly id: string;
15
+ readonly level: FindingLevel;
16
+ /** One plain sentence about this site. */
17
+ readonly message: string;
18
+ /** Where the check is explained. */
19
+ readonly docUrl: string;
20
+ /** The evidence: the line, value or text the finding rests on, cut short. */
21
+ readonly snippet?: string;
22
+ }
23
+ /** How much of the home page's text is in the HTML as served. */
24
+ export type HomeContent = 'text_in_html' | 'little_text' | 'app_shell';
25
+ /** Where a profile in `sameAs` points, by host. */
26
+ export type ProfileKind = 'wikidata' | 'wikipedia' | 'linkedin' | 'x' | 'facebook' | 'instagram' | 'youtube' | 'tiktok' | 'github' | 'crunchbase' | 'pinterest' | 'other';
27
+ /** Where the organization was found. JSON-LD wins over microdata. */
28
+ export type OrganizationSource = 'json_ld' | 'microdata' | 'none';
29
+ /** A limit of the JSON-LD reader that was reached; the rest of the data was not read. */
30
+ export type JsonLdBound = 'blocks' | 'block_size' | 'total_size' | 'depth' | 'nodes';
31
+ /** What the page says about its primary Organization node. */
32
+ export interface OrganizationFacts {
33
+ /** The node's `@type` that names Organization or one of its subtypes. */
34
+ readonly type: string;
35
+ /** The node's `name`, as written, cut to 200 characters; null without a usable one. */
36
+ readonly name: string | null;
37
+ /** The node's `url` when it is an absolute http(s) URL, else null. */
38
+ readonly url: string | null;
39
+ /** A non-empty `name` and an absolute http(s) `url`. */
40
+ readonly nameAndUrl: boolean;
41
+ /** `logo` is a URL, or an ImageObject with a `url`. */
42
+ readonly logo: boolean;
43
+ /**
44
+ * The distinct `sameAs` URLs (absolute http(s), not on the site's own registrable domain),
45
+ * at most 100, in the order written.
46
+ */
47
+ readonly sameAs: readonly string[];
48
+ /** The kinds of `sameAs`, each once, in a fixed order. */
49
+ readonly sameAsKinds: readonly ProfileKind[];
50
+ }
51
+ /** What the `<script type="application/ld+json">` blocks of the page held. */
52
+ export interface JsonLdFacts {
53
+ /** ld+json scripts read (at most 50). */
54
+ readonly scripts: number;
55
+ /** Scripts that parse as JSON. */
56
+ readonly parsed: number;
57
+ /** Scripts that parse and whose top-level `@context` names schema.org. */
58
+ readonly schemaOrgBlocks: number;
59
+ /** Scripts that do not parse. */
60
+ readonly errors: number;
61
+ /** The limits that were reached, each once. Empty when the whole page was read. */
62
+ readonly bounds: readonly JsonLdBound[];
63
+ }
64
+ /** Everything `readHomePage` reads from one page. */
65
+ export interface HomePageFacts {
66
+ /** The address the page was read at (the final one, after redirects). */
67
+ readonly url: string;
68
+ readonly host: string;
69
+ /** Size of the HTML in bytes (UTF-8). */
70
+ readonly bytes: number;
71
+ /** The scan stopped at its limit, so the end of a very large page was not read. */
72
+ readonly scanTruncated: boolean;
73
+ /** Words of main text; a lower bound when `wordsCapped`. */
74
+ readonly mainWords: number;
75
+ /** Counting stopped at its word limit or its character limit, so `mainWords` is a lower bound. */
76
+ readonly wordsCapped: boolean;
77
+ /** Whether the words are those of `<main>` / `[role=main]` or of the body less its chrome. */
78
+ readonly mainSource: 'main' | 'body';
79
+ readonly content: HomeContent;
80
+ /** An application root element is present (`#root`, `#__next`, `app-root`, and the rest). */
81
+ readonly appRoot: boolean;
82
+ /** The page asks the reader to enable JavaScript. */
83
+ readonly jsNotice: boolean;
84
+ /** A small page whose title or visible text is that of a bot check (a 202 is decided apart). */
85
+ readonly botCheck: boolean;
86
+ readonly noindex: boolean;
87
+ readonly noindexSource: 'meta' | 'header' | 'both' | null;
88
+ readonly jsonLd: JsonLdFacts;
89
+ /** schema.org type names found in JSON-LD and microdata, each once, at most 200. */
90
+ readonly types: readonly string[];
91
+ /** The `itemtype` values of the microdata, as type names, each once. */
92
+ readonly microdataTypes: readonly string[];
93
+ readonly organization: OrganizationSource;
94
+ /** Type of the primary node, or the first Organization type seen in microdata. */
95
+ readonly organizationType: string | null;
96
+ /** The primary Organization node of the JSON-LD; null without one. */
97
+ readonly primary: OrganizationFacts | null;
98
+ /** A `WebSite` node. */
99
+ readonly website: boolean;
100
+ /** A `WebSite` node with a `potentialAction` of type `SearchAction`. */
101
+ readonly searchAction: boolean;
102
+ /** A `FAQPage` node (JSON-LD or microdata). */
103
+ readonly faqPage: boolean;
104
+ }
105
+ export type SitemapOutcome = 'valid' | 'not_a_sitemap' | 'malformed';
106
+ /** Why a file is not a valid sitemap. */
107
+ export type SitemapReason = 'html' | 'empty' | 'doctype' | 'bad_root' | 'no_loc' | 'off_site' | 'not_closed' | 'text_lines' | 'gzip_failed';
108
+ /** What `readSitemap` found in one file. */
109
+ export interface SitemapFacts {
110
+ readonly outcome: SitemapOutcome;
111
+ /** `urlset` and `index` are XML (sitemaps.org); `text` is one URL per line. */
112
+ readonly kind: 'urlset' | 'index' | 'text' | null;
113
+ readonly reason: SitemapReason | null;
114
+ /** `<loc>` entries (or text lines) counted, up to 100,000. */
115
+ readonly locs: number;
116
+ /** The file was gzip and was inflated. */
117
+ readonly gzip: boolean;
118
+ /** The file was cut at the size cap: it is valid as far as it was read. */
119
+ readonly truncated: boolean;
120
+ /** Bytes read after decompression. */
121
+ readonly bytes: number;
122
+ }
123
+ /** Why the home page counts as read or not. */
124
+ export type HomeOutcome = 'read'
125
+ /** robots.txt keeps this reader from `/`. */
126
+ | 'not_allowed' | 'forbidden' | 'challenge' | 'placeholder' | 'not_html' | 'error_status' | 'off_site' | 'redirect_error' | 'network';
127
+ /** The robots.txt of a site as a check read it. */
128
+ export type RobotsOutcome =
129
+ /** A file, parsed. */
130
+ 'file'
131
+ /** A 4xx (not 401, 403, 429): there is no file, and nothing is closed. */
132
+ | 'missing'
133
+ /** Not read: 401, 403, 429, 5xx, a bot check, or no answer. Nothing more is asked. */
134
+ | 'not_read';
135
+ export interface RobotsRead {
136
+ readonly outcome: RobotsOutcome;
137
+ readonly url: string;
138
+ readonly status: number | null;
139
+ readonly bytes: number;
140
+ readonly truncated: boolean;
141
+ /** `Sitemap:` lines, as written. */
142
+ readonly sitemaps: readonly string[];
143
+ /** Whether this reader's own token may fetch `/`. True without a file. */
144
+ readonly allowsThisReader: boolean;
145
+ }
146
+ export interface HomeRead {
147
+ readonly outcome: HomeOutcome;
148
+ readonly requestedUrl: string;
149
+ /** The last URL requested; the page was read there. */
150
+ readonly finalUrl: string;
151
+ readonly status: number | null;
152
+ readonly redirects: number;
153
+ readonly truncated: boolean;
154
+ /** Present when the outcome is `read`. */
155
+ readonly facts: HomePageFacts | null;
156
+ }
157
+ export interface LlmsRead {
158
+ /** False when robots.txt keeps this reader from the file. */
159
+ readonly asked: boolean;
160
+ readonly present: boolean;
161
+ /** The verdict of `validateLlmsTxt`; null when not asked. */
162
+ readonly verdict: string | null;
163
+ readonly bytes: number;
164
+ readonly truncated: boolean;
165
+ readonly h1: string | null;
166
+ readonly sections: number;
167
+ readonly links: number;
168
+ }
169
+ export type SitemapSource = 'robots' | 'well_known';
170
+ export interface SitemapRead {
171
+ /** False when robots.txt keeps this reader from the file, or the robots.txt was not read. */
172
+ readonly asked: boolean;
173
+ readonly source: SitemapSource | null;
174
+ readonly url: string | null;
175
+ readonly status: number | null;
176
+ /** Null when the file was not read or the answer was not 2xx. */
177
+ readonly facts: SitemapFacts | null;
178
+ }
179
+ /** Access of one covered crawler to `/`, from the site's robots.txt. */
180
+ export interface CrawlerRootAccess {
181
+ readonly token: string;
182
+ readonly purpose: 'training' | 'search' | 'user';
183
+ readonly access: 'allowed' | 'partial' | 'blocked';
184
+ /** The crawler may fetch `/`. */
185
+ readonly root: boolean;
186
+ }
187
+ /** The result of `checkSite`: facts gathered from files, and the findings drawn from them. */
188
+ export interface SiteCheck {
189
+ readonly schemaVersion: 1;
190
+ /** The site as asked: scheme and host. */
191
+ readonly origin: string;
192
+ readonly host: string;
193
+ /** The crawlers-covered line every report carries. */
194
+ readonly crawlersCovered: string;
195
+ readonly robots: RobotsRead;
196
+ /** The covered crawlers' access; empty when robots.txt was not read. */
197
+ readonly crawlerAccess: readonly CrawlerRootAccess[];
198
+ /** Null when no request was made (robots.txt not read, or `/` not allowed). */
199
+ readonly home: HomeRead | null;
200
+ readonly llms: LlmsRead;
201
+ readonly sitemap: SitemapRead;
202
+ readonly findings: readonly Finding[];
203
+ }
204
+ export interface CheckOptions {
205
+ /** Reads files over the guarded network layer. By default one is made and closed per check. */
206
+ readonly fetcher?: TextFetcher;
207
+ /** The caller's overall budget; by default 30 seconds. */
208
+ readonly signal?: AbortSignal;
209
+ /**
210
+ * Maps a host name to its registrable domain. The built-in rule knows the common two-label
211
+ * suffixes only; pass a full public-suffix lookup to be exact.
212
+ */
213
+ readonly registrableDomain?: (host: string) => string;
214
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Word counting by the Unicode word-break rules (`Intl.Segmenter`, word-like segments), so
3
+ * a page in Chinese or Japanese is counted too, where splitting on spaces would find one word.
4
+ */
5
+ /** Counting stops here: no rule of the library looks past it, and a page cannot make it slow. */
6
+ export declare const MAX_WORDS_COUNTED = 100000;
7
+ /** Characters given to the word-break rules at most (text that is not plain ASCII). */
8
+ export declare const MAX_SEGMENTED_CHARS: number;
9
+ export interface WordCount {
10
+ readonly words: number;
11
+ /** The count is a lower bound: counting stopped at the word limit or the character limit. */
12
+ readonly capped: boolean;
13
+ }
14
+ /** Words in `text`, counted up to `limit`. Linear in the length of the text. */
15
+ export declare function countWords(text: string, limit?: number): WordCount;
@@ -0,0 +1,51 @@
1
+ import { type TextFetcher } from '../net/fetch-text.js';
2
+ import { type LlmsPage, type LlmsSite } from './index.js';
3
+ /** Pages listed when the caller does not say. */
4
+ export declare const GENERATE_DEFAULT_PAGES = 30;
5
+ /** The most pages one run lists. */
6
+ export declare const GENERATE_MAX_PAGES = 100;
7
+ /** Sitemap files read in one run. */
8
+ export declare const GENERATE_MAX_SITEMAPS = 5;
9
+ /** Bytes of each page that are read: the part `pageMeta` looks at. */
10
+ export declare const GENERATE_PAGE_BYTES: number;
11
+ export type SkippedReason = 'robots' | 'noindex' | 'not_html' | 'status' | 'off_site' | 'unreachable' | 'duplicate';
12
+ export interface SkippedPage {
13
+ readonly url: string;
14
+ readonly reason: SkippedReason;
15
+ }
16
+ export type GenerateOutcome =
17
+ /** A file was built. */
18
+ 'generated'
19
+ /** The address cannot be checked (not a web site name). */
20
+ | 'refused'
21
+ /** robots.txt could not be read, so nothing else was requested. */
22
+ | 'robots_unreadable'
23
+ /** No page could be read: robots.txt keeps this reader out, or nothing answered. */
24
+ | 'nothing_found';
25
+ export interface GeneratedLlms {
26
+ readonly schemaVersion: 1;
27
+ readonly outcome: GenerateOutcome;
28
+ readonly origin: string;
29
+ readonly host: string;
30
+ /** The file; null unless the outcome is `generated`. */
31
+ readonly text: string | null;
32
+ readonly site: LlmsSite | null;
33
+ readonly pages: readonly LlmsPage[];
34
+ /** Where the page addresses came from. */
35
+ readonly source: 'sitemap' | 'home_links' | 'none';
36
+ readonly skipped: readonly SkippedPage[];
37
+ /** The run ran out of time and listed what it had. */
38
+ readonly budgetReached: boolean;
39
+ /** One plain sentence about anything the reader should know. */
40
+ readonly notes: readonly string[];
41
+ }
42
+ export interface GenerateOptions {
43
+ /** Pages to list: 30 by default, at most 100. */
44
+ readonly maxPages?: number;
45
+ readonly fetcher?: TextFetcher;
46
+ readonly signal?: AbortSignal;
47
+ readonly registrableDomain?: (host: string) => string;
48
+ }
49
+ /** The addresses of the `<a href>` links of a page, resolved against `base`; at most `max`. */
50
+ export declare function homeLinks(html: string, base: string, max?: number): string[];
51
+ export declare function generateLlmsTxt(input: string, options?: GenerateOptions): Promise<GeneratedLlms>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * llms.txt generation, as pure functions of text: what a page says about itself (its title,
3
+ * first H1 and meta description, as written), the addresses a sitemap lists, and the file
4
+ * built from them. Nothing here fetches; a caller reads the files with `fetchText` and passes
5
+ * the text in.
6
+ */
7
+ /** What a page says about itself. */
8
+ export interface PageMeta {
9
+ /** The `<title>`, as written (entities decoded, whitespace collapsed); null without one. */
10
+ readonly title: string | null;
11
+ /** The first `<h1>`'s text; null without one. */
12
+ readonly h1: string | null;
13
+ /** `<meta name="description">`; null without one. */
14
+ readonly description: string | null;
15
+ /** A `<meta name="robots">` that says `noindex`. */
16
+ readonly noindex: boolean;
17
+ }
18
+ export declare function decodeEntities(text: string): string;
19
+ /** Text from a site made safe to show: control and reordering characters removed. */
20
+ export declare function stripUnsafeCharacters(text: string): string;
21
+ /** Characters of a page read for its title, H1 and meta tags: its head and the start of its body. */
22
+ export declare const PAGE_SCAN_MAX_CHARS: number;
23
+ /** Characters of a sitemap scanned: its whole size cap (5 MiB), in one linear pass. */
24
+ export declare const SITEMAP_SCAN_MAX_CHARS: number;
25
+ /**
26
+ * `<loc>` tags looked at in one sitemap, empty or unusable ones included, before the scan
27
+ * stops: enough for any list the tools take addresses from, and a bound on the work a file of
28
+ * millions of empty tags can cause.
29
+ */
30
+ export declare const MAX_LOC_TAGS_SCANNED = 10000;
31
+ /** A sitemap address longer than this is left out. */
32
+ export declare const MAX_LOCATION_LENGTH = 2048;
33
+ export declare function isSpace(char: string | undefined): boolean;
34
+ /** The attributes of one tag's text (between its name and its `>`), in one pass. */
35
+ export declare function attributes(tag: string): Map<string, string>;
36
+ /** Reads a page's title, first H1, meta description and robots meta from its HTML. */
37
+ export declare function pageMeta(input: string): PageMeta;
38
+ /** The addresses a sitemap file lists. */
39
+ export interface SitemapLocations {
40
+ /** `urlset` lists pages; `index` lists other sitemaps; `unknown` is neither. */
41
+ readonly kind: 'urlset' | 'index' | 'unknown';
42
+ /** The `<loc>` values in order, entities decoded, at most `max`; none over 2,048 characters. */
43
+ readonly locations: readonly string[];
44
+ }
45
+ /** Reads the `<loc>` addresses of a sitemap (sitemaps.org), up to `max` of them. */
46
+ export declare function sitemapLocations(input: string, max: number): SitemapLocations;
47
+ /** The site an llms.txt is about. */
48
+ export interface LlmsSite {
49
+ /** Its name: the file's H1. */
50
+ readonly name: string;
51
+ /** One or two sentences about it: the summary blockquote. Null leaves it out. */
52
+ readonly summary: string | null;
53
+ }
54
+ /** One page to list. */
55
+ export interface LlmsPage {
56
+ /** Its absolute address. */
57
+ readonly url: string;
58
+ readonly title: string;
59
+ readonly description: string | null;
60
+ }
61
+ /** The section of pages that sit at the top of the site (no first path segment). */
62
+ export declare const MAIN_SECTION = "Main pages";
63
+ /**
64
+ * The llms.txt for a site and its pages (llmstxt.org): the site's name as the H1, its summary
65
+ * as a blockquote, then one H2 section per folder (first path segment with pages under it), in
66
+ * the order the pages come, the other pages first under "Main pages". Each page is a list item
67
+ * `- [title](url): description`, the description left out when there is none. Titles and
68
+ * descriptions are used as written, on one line.
69
+ */
70
+ export declare function renderLlmsTxt(site: LlmsSite, pages: readonly LlmsPage[]): string;
@@ -0,0 +1,10 @@
1
+ export { crawlDelayFor, isAllowedByRobots, matchRobots, parseRobots, ROBOTS_MAX_AGE_MS, ROBOTS_MAX_BYTES, ROBOTS_MAX_REDIRECTS, type RobotsGroup, type RobotsRule, type RobotsTxt, type RuleMatch, } from './robots/index.js';
2
+ export { agentVerdict, AI_AGENTS, CRAWLER_PURPOSES, CRAWLERS, crawlerAccess, crawlersCoveredLine, STUDY_AGENTS, verdictsFor, type AgentAccess, type AgentVerdict, type AiAgent, type CrawlerAccess, type CrawlerInfo, type CrawlerPurpose, type StudyAgent, } from './crawlers/index.js';
3
+ export { llmsStructure, looksLikeHtml, looksLikeLlmsTxt, looksLikeRobotsTxt, LLMS_H1_MAX, validateLlmsTxt, type LlmsReport, type LlmsStructure, type LlmsVerdict, } from './llms/index.js';
4
+ export { llmsFindings, LLMS_FINDING_IDS } from './llms/findings.js';
5
+ export { MAIN_SECTION, MAX_LOC_TAGS_SCANNED, pageMeta, renderLlmsTxt, sitemapLocations, stripUnsafeCharacters, type LlmsPage, type LlmsSite, type PageMeta, type SitemapLocations, } from './generate/index.js';
6
+ export { decodeHtml, detectCharset, type DecodedText } from './net/charset.js';
7
+ export { classifyAddress, type AddressClass, type AddressRefusal } from './net/address.js';
8
+ export { CRAWL_PORTS, createNetworkGuard, DNS_TIMEOUT_MS, guardedConnector, NetworkGuardError, systemResolver, type GuardErrorCode, type HostResolver, type NetworkGuard, } from './net/guard.js';
9
+ export { AI_READINESS_USER_AGENT, CHECK_BUDGET_MS, CONNECT_TIMEOUT_MS, createTextFetcher, FETCH_LIMITS, GENERATE_BUDGET_MS, HOST_INTERVAL_MS, KEPT_HEADERS, MAX_CRAWL_DELAY_SECONDS, MAX_HOST_LENGTH, MAX_REDIRECTS, REQUEST_TIMEOUT_MS, type FetchKind, type FetchTextOptions, type KeptHeader, type RedirectHop, type TextFetcher, type TextFetcherOptions, type TextFetchOutcome, type TextFetchResult, type UrlRefusal, } from './net/fetch-text.js';
10
+ export * from './facts/index.js';