polite-crawler 0.1.2 → 0.1.3

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 (40) hide show
  1. package/README.md +533 -8
  2. package/build/cli-daemon--cTmq0Z5.mjs +38 -0
  3. package/build/cli-daemon--cTmq0Z5.mjs.map +1 -0
  4. package/build/cli.mjs +288 -20
  5. package/build/cli.mjs.map +1 -1
  6. package/build/{open-Ca1lcWR3.d.mts → daemon-DP4EqjFL.d.mts} +913 -16
  7. package/build/daemon-fZTE24P5.mjs +515 -0
  8. package/build/daemon-fZTE24P5.mjs.map +1 -0
  9. package/build/{diff-Dk2eSvi-.mjs → diff-NQcQqKe9.mjs} +2 -2
  10. package/build/{diff-Dk2eSvi-.mjs.map → diff-NQcQqKe9.mjs.map} +1 -1
  11. package/build/{extract-DcwNrTK7.mjs → extract-ByFfc8Zk.mjs} +2 -2
  12. package/build/{extract-DcwNrTK7.mjs.map → extract-ByFfc8Zk.mjs.map} +1 -1
  13. package/build/hours.d.mts +26 -0
  14. package/build/hours.mjs +48 -1
  15. package/build/hours.mjs.map +1 -1
  16. package/build/index.d.mts +491 -11
  17. package/build/index.mjs +898 -9
  18. package/build/index.mjs.map +1 -0
  19. package/build/loopback-C_QYowSf.mjs +22 -0
  20. package/build/loopback-C_QYowSf.mjs.map +1 -0
  21. package/build/mcp.d.mts +158 -2
  22. package/build/mcp.mjs +567 -18
  23. package/build/mcp.mjs.map +1 -1
  24. package/build/ollama-BJxkjny4.mjs +160 -0
  25. package/build/ollama-BJxkjny4.mjs.map +1 -0
  26. package/build/{open-DnrWgkC0.mjs → open-C4fhXJgD.mjs} +1404 -21
  27. package/build/open-C4fhXJgD.mjs.map +1 -0
  28. package/build/{runtime-k8mo1_7U.mjs → runtime-JToRO63o.mjs} +3 -3
  29. package/build/{runtime-k8mo1_7U.mjs.map → runtime-JToRO63o.mjs.map} +1 -1
  30. package/build/transformers-BQMlaGj4.mjs +133 -0
  31. package/build/transformers-BQMlaGj4.mjs.map +1 -0
  32. package/build/{duration-iIuMMofi.mjs → version-ntbY-6wh.mjs} +10 -10
  33. package/build/version-ntbY-6wh.mjs.map +1 -0
  34. package/build/{wacz-sfOLT8e9.mjs → wacz-BFNG42Kt.mjs} +3 -3
  35. package/build/{wacz-sfOLT8e9.mjs.map → wacz-BFNG42Kt.mjs.map} +1 -1
  36. package/build/{warc-VIPscWxY.mjs → warc-CVS0t1fW.mjs} +2 -2
  37. package/build/{warc-VIPscWxY.mjs.map → warc-CVS0t1fW.mjs.map} +1 -1
  38. package/package.json +10 -2
  39. package/build/duration-iIuMMofi.mjs.map +0 -1
  40. package/build/open-DnrWgkC0.mjs.map +0 -1
@@ -146,6 +146,16 @@ declare const playwrightRenderer: (options?: {
146
146
  readonly launch?: (() => Promise<object>) | undefined;
147
147
  }) => PlaywrightRenderer;
148
148
  //#endregion
149
+ //#region src/duration.d.ts
150
+ /** A duration is a count of milliseconds, or a text, for example `"30m"`, `"24h"` or `"7d"`. */
151
+ type Duration = number | string;
152
+ /**
153
+ * This function changes a duration into milliseconds. The units are `ms`, `s`, `m` (minutes), `h`,
154
+ * `d` and `w`, in any case. The unit `M` is an error, because a month is not a unit. A bare `0`
155
+ * is zero. The function throws an error for a text that it cannot read.
156
+ */
157
+ declare const durationMs: (duration: Duration) => number;
158
+ //#endregion
149
159
  //#region src/record.d.ts
150
160
  /**
151
161
  * A capture record is one line of the capture log. Each fetch decision makes one record, and a
@@ -806,6 +816,14 @@ interface VersionAt {
806
816
  type RankMode = "exact" | "fast";
807
817
  /** In the mode `fast`, a part is common when more than this share of the documents hold it. */
808
818
  declare const FAST_RANK_SHARE = .2;
819
+ /**
820
+ * This value chooses the ranking of a search of the crawler: a `RankMode` of the index, or
821
+ * `hybrid`. The mode `hybrid` fuses the BM25 ranking with the ranking of the vectors of an
822
+ * embedder (`OpenOptions.embedder`). Without an embedder, it throws an error.
823
+ */
824
+ type SearchRank = RankMode | "hybrid";
825
+ /** The text of the error of hybrid search with no embedder. */
826
+ declare const NO_EMBEDDER = "hybrid search needs an embedder: open the crawler with the option embedder (transformersEmbedder or ollamaEmbedder), or give --embedder transformers or ollama to the command line";
809
827
  /** These are the options of a search of the index. */
810
828
  interface FindIndexOptions {
811
829
  /** This value is the maximum number of results. The index gives 1000 or fewer. */
@@ -815,6 +833,14 @@ interface FindIndexOptions {
815
833
  /** This value chooses the ranking. The default is `exact`. */
816
834
  readonly rank?: RankMode | undefined;
817
835
  }
836
+ /** This is the passage of a hit of a hybrid search: the chunk of the text that is closest to the question. */
837
+ interface Passage {
838
+ /** These values are the positions of the chunk in the text of the capture of the hit, in UTF-16 units. */
839
+ readonly start: number;
840
+ readonly end: number;
841
+ /** This value is the cosine of the vectors of the chunk and the question, from -1 to 1. */
842
+ readonly similarity: number;
843
+ }
818
844
  interface Found {
819
845
  readonly doc: string;
820
846
  readonly kind: string;
@@ -829,6 +855,25 @@ interface Found {
829
855
  readonly capture: string;
830
856
  /** This value tells that the document is an archived copy (the kind `archived`), with the archive and the date of the copy. */
831
857
  readonly archived?: Archived | undefined;
858
+ /** This value is the passage that a hybrid search found. A search of the other modes does not give it. */
859
+ readonly passage?: Passage | undefined;
860
+ }
861
+ /** This is the current text of a document in short: its hash, with no text. */
862
+ interface DocDigest {
863
+ readonly doc: string;
864
+ readonly kind: string;
865
+ readonly ai_input: AiInput;
866
+ /** This value is the SHA-256 of the current text of the document, in hex. */
867
+ readonly text_sha: string;
868
+ }
869
+ /** These options choose the documents of `ReadingIndex.digests`. */
870
+ interface DigestOptions {
871
+ /** These documents, in place of a list of each document. A document that is not in the index gives nothing. */
872
+ readonly docs?: readonly string[] | undefined;
873
+ /** In a list of each document, the documents with an id after this id, in the sequence of the ids. */
874
+ readonly after?: string | undefined;
875
+ /** In a list of each document, this number of documents at most. The default is 500. */
876
+ readonly limit?: number | undefined;
832
877
  }
833
878
  /** The variant of a cache entry: the plain response, or the page that the browser rendered. */
834
879
  type Variant = "plain" | "rendered";
@@ -909,6 +954,12 @@ interface ReadingIndex {
909
954
  docsOfCapture(capture: string): Doc[];
910
955
  /** This method tells if a capture gave a version of a document. */
911
956
  hasVersion(capture: string): boolean;
957
+ /**
958
+ * This optional method gives the hash of the current text of documents, with no text. Hybrid
959
+ * search uses it to find the documents whose text has no vectors. An index without it gives the
960
+ * same facts from `get`, more slowly.
961
+ */
962
+ digests?(options: DigestOptions): DocDigest[];
912
963
  find(q: string, options: FindIndexOptions): Found[];
913
964
  rankWithin(q: string, docs: readonly string[], options?: {
914
965
  readonly rank?: RankMode | undefined;
@@ -1013,6 +1064,11 @@ declare class DocIndex implements ReadingIndex {
1013
1064
  }): VersionText[];
1014
1065
  /** This method tells if a capture gave a version of a document. */
1015
1066
  hasVersion(capture: string): boolean;
1067
+ /**
1068
+ * This method gives the hash of the current text of documents, with no text. It gives the
1069
+ * documents of `docs`, or each document after `after` in the sequence of the ids, to `limit`.
1070
+ */
1071
+ digests(options?: DigestOptions): DocDigest[];
1016
1072
  /** This method gives the newest fetch time of the cache entries, or undefined for an empty index. */
1017
1073
  newestFetch(): string | undefined;
1018
1074
  /** This method gives the current documents that a capture gave. */
@@ -1844,16 +1900,6 @@ interface DiffResult {
1844
1900
  */
1845
1901
  declare const diffDocument: (runtime: CrawlRuntime, id: string, options?: DiffOptions) => Promise<DiffResult>;
1846
1902
  //#endregion
1847
- //#region src/duration.d.ts
1848
- /** A duration is a count of milliseconds, or a text, for example `"30m"`, `"24h"` or `"7d"`. */
1849
- type Duration = number | string;
1850
- /**
1851
- * This function changes a duration into milliseconds. The units are `ms`, `s`, `m` (minutes), `h`,
1852
- * `d` and `w`, in any case. The unit `M` is an error, because a month is not a unit. A bare `0`
1853
- * is zero. The function throws an error for a text that it cannot read.
1854
- */
1855
- declare const durationMs: (duration: Duration) => number;
1856
- //#endregion
1857
1903
  //#region src/sitemaps.d.ts
1858
1904
  /**
1859
1905
  * The sitemap reader reads the files that list the pages of a site. These are an XML sitemap, a
@@ -2059,6 +2105,122 @@ interface DiscoverResult {
2059
2105
  */
2060
2106
  declare const discoverSite: (runtime: CrawlRuntime, site: string, options?: DiscoverRunOptions) => Promise<DiscoverResult>;
2061
2107
  //#endregion
2108
+ //#region src/embed.d.ts
2109
+ /**
2110
+ * The parts of hybrid search that need no store: the embedder interface, the chunks of a text, and
2111
+ * the fusion of ranked lists.
2112
+ *
2113
+ * An embedder changes texts into vectors. Two texts with a similar meaning get vectors that point
2114
+ * in a similar direction. Hybrid search ranks the stored documents two times: one time with the
2115
+ * full-text index (BM25), one time by the cosine of the vectors. Reciprocal rank fusion (RRF) then
2116
+ * makes one list of the two.
2117
+ *
2118
+ * `Embedder` is the extension point. `transformersEmbedder` and `ollamaEmbedder` are two adapters,
2119
+ * and an application can give an embedder of its own, as it can give a renderer of its own.
2120
+ */
2121
+ /** These options go to each call of `Embedder.embed`. */
2122
+ interface EmbedCallOptions {
2123
+ /** When this signal aborts, the embedder stops and rejects with the reason of the signal. */
2124
+ readonly signal?: AbortSignal | undefined;
2125
+ /**
2126
+ * This value tells what the texts are: `document` (parts of stored texts, the default) or `query`
2127
+ * (the words of a search). Some models want a different prefix for each.
2128
+ */
2129
+ readonly purpose?: "document" | "query" | undefined;
2130
+ }
2131
+ /**
2132
+ * An embedder changes texts into vectors. The vector store keeps each vector with the `id` of its
2133
+ * embedder, so the vectors of two models do not mix.
2134
+ */
2135
+ interface Embedder {
2136
+ /** This text names the model and its version. Change it when the vectors of the model change. */
2137
+ readonly id: string;
2138
+ /** This value is the length of each vector. The value 0 tells that the embedder learns it from its first answer. */
2139
+ readonly dimensions: number;
2140
+ /** This value is the largest input of the model, in tokens. The chunks of a text fit in it. The default is 256. */
2141
+ readonly maxInputTokens?: number | undefined;
2142
+ /** This method gives one vector for each text, in the same sequence. */
2143
+ embed(texts: readonly string[], options: EmbedCallOptions): Promise<Float32Array[]>;
2144
+ /** This optional method releases the model. A later call of `embed` loads it again. */
2145
+ close?(): Promise<void>;
2146
+ }
2147
+ /** These are the limits of the chunks of a text. */
2148
+ declare const CHUNK_LIMITS: {
2149
+ /** A chunk has this number of tokens at most, also for a model with a larger input. */
2150
+ readonly maxTokens: number;
2151
+ /** A chunk has this number of tokens when the embedder does not give `maxInputTokens`. */
2152
+ readonly defaultTokens: number;
2153
+ /** A chunk fills this share of its limit, because the count of the tokens is an estimate. */
2154
+ readonly fill: number;
2155
+ /** Two chunks next to each other share this share of the tokens of a chunk. */
2156
+ readonly overlap: number;
2157
+ /** A text gives this number of chunks at most. The rest of a longer text gets no vector. */
2158
+ readonly maxChunks: number;
2159
+ };
2160
+ /** This is one chunk of a text: a window of paragraphs, with its position in the text. */
2161
+ interface TextChunk {
2162
+ /** This value is the position of the chunk in the list, from 0. */
2163
+ readonly index: number;
2164
+ /** These values are the positions of the chunk in the text, in UTF-16 units. */
2165
+ readonly start: number;
2166
+ readonly end: number;
2167
+ readonly text: string;
2168
+ }
2169
+ /** These options control the chunks of a text. */
2170
+ interface ChunkOptions {
2171
+ /** This value is the largest number of tokens in a chunk. */
2172
+ readonly maxTokens: number;
2173
+ /** This value is the number of tokens that two chunks next to each other can share. The default is 10 percent of `maxTokens`. */
2174
+ readonly overlapTokens?: number | undefined;
2175
+ /** This value is the largest number of chunks. The default is `CHUNK_LIMITS.maxChunks`. */
2176
+ readonly maxChunks?: number | undefined;
2177
+ }
2178
+ /**
2179
+ * This function estimates the number of tokens of a part of a text. A word is one token for each
2180
+ * six letters. A Chinese, Japanese or Thai character is one token. Each other character that is
2181
+ * not a space is one token. The estimate is a little high for English text, so a chunk fits.
2182
+ */
2183
+ declare const estimateTokens: (text: string, start?: number, end?: number) => number;
2184
+ /**
2185
+ * This function cuts a text into chunks for an embedder. A chunk is a window of whole sentences.
2186
+ * It ends at the end of a paragraph when the paragraph fills half of the window or more. A
2187
+ * sentence that is longer than the window is cut at its spaces. Two chunks next to each other share
2188
+ * a few sentences (`overlapTokens`), so a passage at a cut is in one chunk. Each chunk keeps its
2189
+ * position in the text, so a hit points at a passage.
2190
+ */
2191
+ declare const chunkText: (text: string, options: ChunkOptions) => TextChunk[];
2192
+ /**
2193
+ * This function gives the number of tokens of a chunk for an embedder. It is the input limit with a
2194
+ * margin for the estimate, and `CHUNK_LIMITS.maxTokens` at most.
2195
+ */
2196
+ declare const chunkTokensOf: (embedder: Pick<Embedder, "maxInputTokens">) => number;
2197
+ /** This function gives a copy of a vector with a length of 1. A vector of zeros stays zeros. A value that is not finite throws a `RangeError`. */
2198
+ declare const unitVector: (vector: ArrayLike<number>) => Float32Array;
2199
+ /** These are the defaults of a hybrid search. */
2200
+ declare const HYBRID_DEFAULTS: {
2201
+ /** The full-text search gives this number of candidates. Each candidate gets vectors when it has none. */
2202
+ readonly candidates: number;
2203
+ /** The vector search gives this number of documents: the documents with the closest chunks. */
2204
+ readonly neighbors: number;
2205
+ /** This value is the constant k of reciprocal rank fusion. A larger k gives less weight to the top of each list. */
2206
+ readonly fusionK: number;
2207
+ };
2208
+ /** This is one item of a fused list. */
2209
+ interface FusedRank {
2210
+ readonly id: string;
2211
+ /** This value is the sum of 1 / (k + rank) over the lists that hold the item. */
2212
+ readonly score: number;
2213
+ /** These values are the rank of the item in each list, from 1, or null when a list does not hold it. */
2214
+ readonly ranks: ReadonlyArray<number | null>;
2215
+ }
2216
+ /**
2217
+ * This function fuses ranked lists with reciprocal rank fusion. Each item gets the sum of
2218
+ * 1 / (k + rank) over the lists that hold it, with the rank from 1. The best item is first. A tie goes to
2219
+ * the item with the best rank in a list, then to the earlier list, then to the smaller id. An item
2220
+ * that is two times in one list counts at its first place.
2221
+ */
2222
+ declare const fuseRanks: (lists: ReadonlyArray<readonly string[]>, k?: number) => FusedRank[];
2223
+ //#endregion
2062
2224
  //#region src/extract.d.ts
2063
2225
  /**
2064
2226
  * The field check takes the values that a caller proposes for the fields of a stored page. It finds
@@ -2353,6 +2515,402 @@ interface CrawlRun extends AsyncIterable<CrawlPage> {
2353
2515
  */
2354
2516
  declare const crawlSite: (runtime: CrawlRuntime, seeds: string | readonly string[], options?: CrawlRunOptions) => CrawlRun;
2355
2517
  //#endregion
2518
+ //#region src/vectors.d.ts
2519
+ /**
2520
+ * The vector store keeps the vectors of hybrid search in `vectors.sqlite`, beside the index. It is
2521
+ * a projection, as the index is. Delete the file, and the next hybrid search or `embed` makes the
2522
+ * vectors again from the stored texts.
2523
+ *
2524
+ * - A row is one chunk of one text for one embedder. Its key is the SHA-256 of the text, the
2525
+ * number of the chunk and the id of the embedder. Thus a reindex keeps each vector, and the same
2526
+ * text gets its vectors one time for each model, also when two documents hold it.
2527
+ * - A text is complete when the table `texts` has it, with the plan of its chunks. A text with a
2528
+ * different plan gets new chunks.
2529
+ * - The table `docs` points each document at the text that has its vectors. A search uses only
2530
+ * the texts that a document points at, and the caller checks each document against the index.
2531
+ * - A search compares the vector of the question with each stored vector (a brute-force cosine).
2532
+ * The store keeps the vectors of each embedder in memory after the first search. It reads them
2533
+ * again when a different process writes the file.
2534
+ *
2535
+ * Each connection waits for the lock of a different process (`busy_timeout`), and each write is
2536
+ * one transaction (`BEGIN IMMEDIATE`). The file has a schema version (`VECTORS_SCHEMA`). A file of
2537
+ * a different version opens empty.
2538
+ */
2539
+ /** This value is the version of the schema of the vector file. */
2540
+ declare const VECTORS_SCHEMA = 1;
2541
+ /** This is one chunk of a text with its vector, as the store keeps it. */
2542
+ interface StoredChunk {
2543
+ readonly chunk: number;
2544
+ /** These values are the positions of the chunk in the text, in UTF-16 units. */
2545
+ readonly start: number;
2546
+ readonly end: number;
2547
+ /** This vector has a length of 1, or it is zeros. */
2548
+ readonly vector: Float32Array;
2549
+ }
2550
+ /** This is the best chunk of one text for a question. */
2551
+ interface VectorHit {
2552
+ /** This value is the SHA-256 of the text, in hex. */
2553
+ readonly sha: string;
2554
+ readonly chunk: number;
2555
+ readonly start: number;
2556
+ readonly end: number;
2557
+ /** This value is the cosine of the chunk and the question, from -1 to 1. */
2558
+ readonly similarity: number;
2559
+ /** These documents point at the text. The caller checks each one against the index. */
2560
+ readonly docs: readonly string[];
2561
+ }
2562
+ /** These are the counts of the store, for one embedder or for each embedder. */
2563
+ interface VectorCounts {
2564
+ readonly texts: number;
2565
+ readonly chunks: number;
2566
+ readonly docs: number;
2567
+ /** This value is the size of the vectors in bytes, with no overhead of SQLite. */
2568
+ readonly bytes: number;
2569
+ }
2570
+ /** These options open a vector store. */
2571
+ interface VectorStoreOptions {
2572
+ /** This value is the time in milliseconds that a write waits for the lock of a different process. The default is 10 seconds. */
2573
+ readonly busyTimeoutMs?: number | undefined;
2574
+ }
2575
+ /** These are the parts of one text in a write of the store. */
2576
+ interface VectorWrite {
2577
+ readonly embedder: string;
2578
+ readonly dimensions: number;
2579
+ /** This value is the SHA-256 of the text, in hex. */
2580
+ readonly sha: string;
2581
+ /** This text names the rule of the chunks. A text with a different plan gets new chunks. */
2582
+ readonly plan: string;
2583
+ /** This value is the length of the text. */
2584
+ readonly chars: number;
2585
+ readonly chunks: ReadonlyArray<Omit<StoredChunk, "chunk">>;
2586
+ /** These documents hold the text as their current text. The store points each one at it. */
2587
+ readonly docs: readonly string[];
2588
+ /** This time (ISO 8601) is the time of the write. */
2589
+ readonly at: string;
2590
+ }
2591
+ declare class VectorStore {
2592
+ readonly path: string;
2593
+ private readonly db;
2594
+ private readonly statements;
2595
+ private readonly matrices;
2596
+ private closed;
2597
+ constructor(path: string, options?: VectorStoreOptions);
2598
+ private stmt;
2599
+ private write;
2600
+ private live;
2601
+ /** This method gives the plan of the chunks of a text when the store has each of its vectors, or undefined. */
2602
+ plan(embedder: string, sha: string): string | undefined;
2603
+ /** This method gives the text that a document points at, or undefined. */
2604
+ pointed(embedder: string, doc: string): string | undefined;
2605
+ /** This method gives the dimensions that the store keeps for an embedder, or undefined. */
2606
+ dimensions(embedder: string): number | undefined;
2607
+ /**
2608
+ * This method writes the chunks of one text and points its documents at it, in one transaction.
2609
+ * A vector with a length that is different from the dimensions of the embedder throws an error.
2610
+ */
2611
+ put(input: VectorWrite): void;
2612
+ private pointRow;
2613
+ /** This method points a document at a text that the store has. */
2614
+ point(embedder: string, doc: string, sha: string, at: string): void;
2615
+ /** This method removes the pointer of a document, for example when the document is held back. Its text keeps its vectors. */
2616
+ forget(embedder: string, doc: string): void;
2617
+ /** This method gives the chunks of a text, in their sequence. */
2618
+ chunks(embedder: string, sha: string): StoredChunk[];
2619
+ private pointMatrix;
2620
+ private append;
2621
+ /** This method gives the vectors of an embedder in memory. It reads them again when a different process wrote the file. */
2622
+ private matrix;
2623
+ private load;
2624
+ /** This method gives the best chunk of one text for a question, or undefined when the store has no vector of the text. */
2625
+ best(embedder: string, sha: string, query: Float32Array): VectorHit | undefined;
2626
+ private hitOf;
2627
+ /**
2628
+ * This method compares a question with each stored vector of an embedder (a brute-force cosine).
2629
+ * It gives the best chunk of each text that a document points at, the best first. With `within`,
2630
+ * it compares only the texts of those documents.
2631
+ */
2632
+ search(embedder: string, query: Float32Array, options?: {
2633
+ readonly within?: Iterable<string> | undefined;
2634
+ }): VectorHit[];
2635
+ /** This method gives the counts of the store, for one embedder or for each embedder. */
2636
+ counts(embedder?: string): VectorCounts;
2637
+ /** This method closes the file. A second close does nothing. */
2638
+ close(): void;
2639
+ }
2640
+ //#endregion
2641
+ //#region src/hybrid.d.ts
2642
+ /**
2643
+ * Hybrid search ranks the stored documents two times and fuses the two lists:
2644
+ *
2645
+ * 1. The full-text index gives the BM25 candidates (`candidates`, 50 by default). Each candidate
2646
+ * whose text has no vectors gets them from the embedder first.
2647
+ * 2. The vector store gives the documents with the closest chunks (`neighbors`, 50 by default),
2648
+ * with a brute-force cosine over the vectors of the embedder.
2649
+ * 3. Reciprocal rank fusion (`fusionK`, 60 by default) makes one list of the two.
2650
+ *
2651
+ * The snippet and the `passage` of each hit come from its best chunk. A held-back document gets
2652
+ * no vectors, and no result gives it, exactly as for `find`. The text of a held-back version does not
2653
+ * goes to the embedder.
2654
+ */
2655
+ /** These options change a hybrid search. */
2656
+ interface HybridOptions {
2657
+ /** This value is the number of BM25 candidates. The default is `HYBRID_DEFAULTS.candidates`. */
2658
+ readonly candidates?: number | undefined;
2659
+ /** This value is the number of documents from the vector search. The default is `HYBRID_DEFAULTS.neighbors`. */
2660
+ readonly neighbors?: number | undefined;
2661
+ /** This value is the constant k of reciprocal rank fusion. The default is `HYBRID_DEFAULTS.fusionK`. */
2662
+ readonly fusionK?: number | undefined;
2663
+ /** When this signal aborts, the search stops the embedder and rejects. */
2664
+ readonly signal?: AbortSignal | undefined;
2665
+ }
2666
+ /** These options control a hybrid search of the store. */
2667
+ interface HybridFindOptions extends HybridOptions {
2668
+ /** This value is the maximum number of results. The default is 10, and the maximum is 1000. */
2669
+ readonly limit?: number | undefined;
2670
+ /** This value keeps only the documents of one kind, for example `page` or `pdf`. */
2671
+ readonly kind?: string | null | undefined;
2672
+ }
2673
+ /** This is one document of a ranking of a set of documents (`rankWithin`). */
2674
+ interface Ranked {
2675
+ readonly doc: string;
2676
+ /** This value is the score. A larger score is a better match. In the mode `hybrid`, it is the fused score. */
2677
+ readonly score: number;
2678
+ /** This value is the best chunk of the document, in the mode `hybrid`. */
2679
+ readonly passage?: Passage | undefined;
2680
+ }
2681
+ /** These options control `embed`, which gives vectors to the stored documents that have none. */
2682
+ interface EmbedOptions {
2683
+ /** This value is the longest time of the work, for example `"10m"` (the default). No embedding starts after it. */
2684
+ readonly budget?: Duration | undefined;
2685
+ /** This value is the largest number of texts that get new vectors. The default has no limit. */
2686
+ readonly maxDocs?: number | undefined;
2687
+ /** This value keeps only the documents of one kind, for example `page` or `pdf`. */
2688
+ readonly kind?: string | null | undefined;
2689
+ /** When this signal aborts, the work stops. The result then has `stopped: "signal"`. */
2690
+ readonly signal?: AbortSignal | undefined;
2691
+ }
2692
+ /** The reason of the end of `embed`. */
2693
+ type EmbedStop = "done" | "budget" | "max-docs" | "signal";
2694
+ /** The counts of `embed`. */
2695
+ interface EmbedResult {
2696
+ /** This value is the id of the embedder. */
2697
+ readonly embedder: string;
2698
+ /** This value is the number of documents that the work examined. */
2699
+ readonly docs: number;
2700
+ /** This value is the number of texts that got new vectors. */
2701
+ readonly embedded: number;
2702
+ /** This value is the number of documents whose text had vectors already. */
2703
+ readonly reused: number;
2704
+ /** This value is the number of documents that the work left out, because they are held back. */
2705
+ readonly held_back: number;
2706
+ /** This value is the number of new vectors: one for each chunk. */
2707
+ readonly chunks: number;
2708
+ readonly stopped: EmbedStop;
2709
+ /** This value is the time of the work in milliseconds. */
2710
+ readonly ms: number;
2711
+ }
2712
+ /** Hybrid search over a runtime and a vector store. `openCrawler` makes one when it has an embedder. */
2713
+ interface HybridSearch {
2714
+ readonly embedder: Embedder;
2715
+ /** This method searches the stored documents in the mode `hybrid`. It sends no request to a site. */
2716
+ find(q: string, options?: HybridFindOptions): Promise<Found[]>;
2717
+ /** This method ranks a set of documents in the mode `hybrid`, the best first. */
2718
+ rankWithin(q: string, docs: readonly string[], options?: HybridOptions): Promise<Ranked[]>;
2719
+ /** This method gives vectors to the stored documents that have none, within a budget. */
2720
+ embed(options?: EmbedOptions): Promise<EmbedResult>;
2721
+ }
2722
+ /** These options make a hybrid search. */
2723
+ interface HybridSearchOptions {
2724
+ readonly embedder: Embedder;
2725
+ /** This store keeps the vectors. The caller opens it and closes it. */
2726
+ readonly store: VectorStore;
2727
+ }
2728
+ /** This function makes a hybrid search over a runtime. The vectors go into the store, with the id of the embedder. */
2729
+ declare const createHybridSearch: (runtime: CrawlRuntime, options: HybridSearchOptions) => HybridSearch;
2730
+ //#endregion
2731
+ //#region src/recipe.d.ts
2732
+ /** The capture that an extractor reads: the final URL of the response and its content type. */
2733
+ interface RecipeCapture {
2734
+ readonly url: string;
2735
+ readonly contentType: string | null;
2736
+ }
2737
+ /**
2738
+ * This function reads one captured body into the documents that it holds. It is pure: the same
2739
+ * body and capture always give the same documents. It sends no request. It can answer later.
2740
+ */
2741
+ type RecipeExtract = (body: Uint8Array, capture: RecipeCapture) => ReadonlyArray<ExtractedDoc> | Promise<ReadonlyArray<ExtractedDoc>>;
2742
+ /** The request of a recipe for one input: the URL, and the parts that change with the input. */
2743
+ interface RecipeRequest {
2744
+ readonly url: string;
2745
+ /** This value replaces the `accept` of the recipe for this request. */
2746
+ readonly accept?: string | undefined;
2747
+ /** These headers go with the request. The crawler does not write them into the capture. */
2748
+ readonly headers?: Readonly<Record<string, string>> | undefined;
2749
+ /** These query parameters hold secrets. The capture shows `REDACTED` in their place. */
2750
+ readonly secretParams?: readonly string[] | undefined;
2751
+ }
2752
+ /** These values declare a recipe. Only `name` and `extract` are necessary. */
2753
+ interface RecipeDefinition<Input = string> {
2754
+ /**
2755
+ * This name goes into each capture record of the recipe, so it is part of each capture id.
2756
+ * `reindex` finds the extractor by it. Do not change it after the first capture.
2757
+ */
2758
+ readonly name: string;
2759
+ /** This text tells what the recipe reads. */
2760
+ readonly description?: string | undefined;
2761
+ /**
2762
+ * The value `page` (the default) is a web page: robots.txt applies. The value `api` is a
2763
+ * documented API with terms of its own: robots.txt does not apply, and the pace still does.
2764
+ */
2765
+ readonly mode?: "api" | "page" | undefined;
2766
+ /** This value is the `Accept` header. The defaults are HTML for a page and JSON for an API. */
2767
+ readonly accept?: string | undefined;
2768
+ /** This value is the documented pace of the source: the shortest time between two of its requests. */
2769
+ readonly minInterval?: Duration | undefined;
2770
+ /** A stored copy younger than this age answers with no request. The default is `24h`. */
2771
+ readonly maxAge?: Duration | undefined;
2772
+ /** This value is the most bytes of a body that the crawler keeps. */
2773
+ readonly maxBytes?: number | undefined;
2774
+ /** This function gives the request for an input. With no function, the input is the URL. */
2775
+ readonly fetch?: ((input: Input) => string | RecipeRequest) | undefined;
2776
+ /** This function reads a captured body into documents. It is pure, and it sends no request. */
2777
+ readonly extract: RecipeExtract;
2778
+ }
2779
+ /** These options build the request of a recipe for one input (`Recipe.request`). */
2780
+ interface RecipeRequestOptions {
2781
+ /** This value replaces the `maxAge` of the recipe. The value `0` asks the source again. */
2782
+ readonly maxAge?: Duration | undefined;
2783
+ /** These agents get their robots.txt rules applied too, for a recipe of the mode `page`. */
2784
+ readonly onBehalfOf?: readonly string[] | undefined;
2785
+ /** This name connects the captures to the job that asked for them. */
2786
+ readonly job?: string | undefined;
2787
+ /** When this signal aborts, the crawler stops the fetch. */
2788
+ readonly signal?: AbortSignal | undefined;
2789
+ /** This label goes into each capture record of the request. */
2790
+ readonly scope?: string | undefined;
2791
+ /** These labels go into each capture record of the request. They are not part of the capture id. */
2792
+ readonly labels?: Readonly<Record<string, string>> | undefined;
2793
+ /** No request starts at or after this time (milliseconds since the epoch, on the clock of the crawler). */
2794
+ readonly deadline?: number | undefined;
2795
+ }
2796
+ /** A recipe that `defineRecipe` made. Give it to `runRecipe`, to `registerRecipe` or to `openCrawler`. */
2797
+ interface Recipe<Input = string> {
2798
+ readonly name: string;
2799
+ readonly description: string | null;
2800
+ readonly mode: "api" | "page";
2801
+ readonly accept: string;
2802
+ /** This extractor reads the captures of the recipe. It checks the documents of the definition. */
2803
+ readonly extractor: Extractor;
2804
+ /** This method gives the request of the crawler for one input. A value that is not a URL throws a `TypeError`. */
2805
+ request(input: Input, options?: RecipeRequestOptions): FetchRequest;
2806
+ }
2807
+ /**
2808
+ * This function reads a body as JSON, in the encoding that the response declares. A body that is
2809
+ * not JSON (a page about maintenance, or a login page) throws an error that names the URL and the
2810
+ * content type. In an extractor, the runtime then reports that error.
2811
+ */
2812
+ declare const readJson: (body: Uint8Array, capture: RecipeCapture) => unknown;
2813
+ /**
2814
+ * These recipe names belong to the crawler: the page reader, the archived fallback, robots.txt,
2815
+ * and the sitemaps and feeds of `discover`. A recipe cannot use them.
2816
+ */
2817
+ declare const RESERVED_RECIPES: readonly string[];
2818
+ /** These are the limits of a recipe. */
2819
+ declare const RECIPE_LIMITS: {
2820
+ /** The longest recipe name. */
2821
+ readonly nameChars: number;
2822
+ /** The longest document id. */
2823
+ readonly docIdChars: number;
2824
+ };
2825
+ /**
2826
+ * This function declares a recipe. It checks the definition at once: a name that is not valid, a
2827
+ * reserved name or a duration that it cannot read throws an error. The extractor of the recipe
2828
+ * checks each document of `extract`. A document that is not valid makes the extractor throw, and
2829
+ * the runtime reports it as an error of the extractor.
2830
+ */
2831
+ declare const defineRecipe: <Input = string>(definition: RecipeDefinition<Input>) => Recipe<Input>;
2832
+ /**
2833
+ * This function gives the extractor of a recipe to the extractors of a runtime. A second
2834
+ * registration of the same recipe does nothing. A different extractor with the same name throws
2835
+ * an error, because `reindex` must read each capture with one extractor.
2836
+ */
2837
+ declare const registerRecipe: <Input>(extractors: Extractors, recipe: Recipe<Input>) => void;
2838
+ /** These options control one run of a recipe. */
2839
+ interface RecipeRunOptions extends Omit<RecipeRequestOptions, "deadline"> {
2840
+ /** No request starts after this time from the start of the run, for example `"30s"`. */
2841
+ readonly budget?: Duration | undefined;
2842
+ /** This value is true when a person gave this input directly. It is the only way to see a held-back document. The crawler logs it. */
2843
+ readonly userProvided?: boolean | undefined;
2844
+ /**
2845
+ * The value `archive` gives a copy from a public web archive when the site refuses the page or is
2846
+ * down. Only a recipe of the mode `page` takes it. The page reader reads the copy.
2847
+ */
2848
+ readonly fallback?: "archive" | "none" | undefined;
2849
+ /** The value true also gives an archived copy of a page that the current robots.txt disallows. */
2850
+ readonly archiveDespiteRobots?: boolean | undefined;
2851
+ }
2852
+ /** One document of a run of a recipe: the version of the capture of the run. */
2853
+ interface RecipeDoc {
2854
+ readonly doc: string;
2855
+ readonly kind: string;
2856
+ /** This value is the title. A held-back document shows no title. */
2857
+ readonly title: string;
2858
+ readonly url: string | null;
2859
+ /** This value is the metadata. A held-back document shows only the structural fields. */
2860
+ readonly meta: Readonly<Record<string, unknown>>;
2861
+ /** This value is the length of the text. `read` gives the text. */
2862
+ readonly chars: number;
2863
+ /** This id is the capture of this version. A citation names it. */
2864
+ readonly capture: string;
2865
+ readonly fetched_at: string;
2866
+ readonly held_back: boolean;
2867
+ /** This value tells that the document is an archived copy, with the archive and the date of the copy. */
2868
+ readonly archived?: Archived | undefined;
2869
+ }
2870
+ /** The result of `runRecipe`. */
2871
+ interface RecipeResult {
2872
+ readonly recipe: string;
2873
+ /** This URL is the URL of the capture. Its secrets show as `REDACTED`. */
2874
+ readonly url: string;
2875
+ readonly outcome: string;
2876
+ readonly status: number;
2877
+ /** These documents came from the capture of the run, in the order of the extractor. */
2878
+ readonly docs: readonly RecipeDoc[];
2879
+ /** This id is the capture of the documents. */
2880
+ readonly capture: string | null;
2881
+ readonly fetched_at: string | null;
2882
+ /** This value is true when the stored copy answered, and the crawler sent no request. */
2883
+ readonly from_cache: boolean;
2884
+ /** This value is true when a document is held back. */
2885
+ readonly held_back: boolean;
2886
+ /** This text is the error of the extractor, when it threw for the capture. */
2887
+ readonly error: string | null;
2888
+ /** This value tells that the documents are an archived copy, not a fresh fetch. */
2889
+ readonly archived?: Archived | undefined;
2890
+ readonly note: string | null;
2891
+ }
2892
+ /** A recipe operates on a runtime, or on a crawler that has one (`crawler.runtime`). */
2893
+ type RecipeTarget = CrawlRuntime | {
2894
+ readonly runtime: CrawlRuntime;
2895
+ };
2896
+ /**
2897
+ * This function starts a recipe for one input. It fetches the request through the crawler, and it
2898
+ * reads the capture with the extractor of the recipe. It gives the documents of that capture.
2899
+ * These are its rules:
2900
+ *
2901
+ * - The runtime registers the recipe the first time that it gets it. Give the recipe to
2902
+ * `openCrawler` too, so that `reindex` reads its captures before the first fetch.
2903
+ * - A stored copy younger than `maxAge` answers with no request. When the extractor cannot read a
2904
+ * stored copy, the crawler asks the source one more time.
2905
+ * - An extractor that throws gives no document, and `error` tells why. The fetch still succeeds.
2906
+ * - A document that asked not to be AI input shows no title and only its structural metadata,
2907
+ * unless `userProvided`. The crawler logs each `userProvided` read of a held-back document.
2908
+ * - With `fallback: "archive"`, a page that the site refuses gets an archived copy, with
2909
+ * `archived`. The page reader reads the copy. The extractor of the recipe reads only live
2910
+ * captures. Thus its documents do not mix a live answer and an old copy of a third party.
2911
+ */
2912
+ declare const runRecipe: <Input>(target: RecipeTarget, recipe: Recipe<Input>, input: Input, options?: RecipeRunOptions) => Promise<RecipeResult>;
2913
+ //#endregion
2356
2914
  //#region src/watch.d.ts
2357
2915
  /**
2358
2916
  * A watch list keeps the pages that the crawler checks again on a schedule. `watch.run` fetches the
@@ -2370,7 +2928,7 @@ declare const crawlSite: (runtime: CrawlRuntime, seeds: string | readonly string
2370
2928
  * - The list is in `watch.sqlite` in the store, so it stays after a restart. A run claims each entry
2371
2929
  * with a lease in that file, so two processes do not check one entry two times.
2372
2930
  *
2373
- * The package has no daemon. A scheduler of the operator starts `watch.run`.
2931
+ * A scheduler of the operator starts `watch.run`, or the daemon (`startDaemon`) starts it on a schedule.
2374
2932
  */
2375
2933
  /** This value is the version of the schema of `watch.sqlite`. */
2376
2934
  declare const WATCH_SCHEMA = 1;
@@ -2459,6 +3017,11 @@ interface WatchRunOptions {
2459
3017
  readonly maxPages?: number | undefined;
2460
3018
  /** When this signal aborts, the run stops the checks in progress and ends. */
2461
3019
  readonly signal?: AbortSignal | undefined;
3020
+ /**
3021
+ * When this signal aborts, the run starts no new check. The checks in progress end and write
3022
+ * their state, and the run stops with `cancelled`. The daemon uses it for a clean stop.
3023
+ */
3024
+ readonly drain?: AbortSignal | undefined;
2462
3025
  }
2463
3026
  /** These options control `runWatch`: the options of a run, and the parts of `openCrawler`. */
2464
3027
  interface WatchRunnerOptions extends WatchRunOptions {
@@ -2720,6 +3283,11 @@ interface RuntimeOptions {
2720
3283
  readonly onEvent?: ((event: CrawlEvent) => void) | undefined;
2721
3284
  /** These extractors read the captures of the recipes of an application. The recipes `page` and `archive-copy` are built in. */
2722
3285
  readonly extractors?: Readonly<Record<string, Extractor>> | undefined;
3286
+ /**
3287
+ * These recipes of `defineRecipe` get their extractors at open. Thus `reindex` reads their
3288
+ * captures before the first fetch. A recipe with the name of an entry of `extractors` throws an error.
3289
+ */
3290
+ readonly recipes?: ReadonlyArray<Recipe<never>> | undefined;
2723
3291
  /**
2724
3292
  * This signer signs each request with Web Bot Auth (`CrawlerOptions.signer`). Give the options of
2725
3293
  * `createWebBotAuthSigner`, or a `RequestSigner`. Without it, the crawler signs nothing.
@@ -2746,6 +3314,12 @@ interface OpenOptions extends Omit<RuntimeOptions, "dir" | "log" | "blobs" | "in
2746
3314
  readonly onBehalfOf?: readonly string[] | undefined;
2747
3315
  /** This value is the shortest `every` of a watch. The default is `1h`, so a watch cannot hammer a site. */
2748
3316
  readonly watchFloor?: Duration | undefined;
3317
+ /**
3318
+ * This embedder makes the vectors of hybrid search (`rank: "hybrid"`): `transformersEmbedder`,
3319
+ * `ollamaEmbedder` or an embedder of your own. The vectors go into `vectors.sqlite` in the store.
3320
+ * Without it, `rank: "hybrid"` throws an error. `close` also closes the embedder.
3321
+ */
3322
+ readonly embedder?: Embedder | undefined;
2749
3323
  }
2750
3324
  /** These options control one fetch. */
2751
3325
  interface FetchOptions {
@@ -2787,6 +3361,19 @@ interface FindOptions {
2787
3361
  */
2788
3362
  readonly rank?: RankMode | undefined;
2789
3363
  }
3364
+ /**
3365
+ * These options control a search of `openCrawler`: the options of `find`, and `rank: "hybrid"`
3366
+ * with the options of a hybrid search. The mode `hybrid` needs `OpenOptions.embedder`.
3367
+ */
3368
+ interface SearchOptions extends Omit<FindOptions, "rank">, HybridFindOptions {
3369
+ /** This value chooses the ranking. `hybrid` fuses BM25 with the ranking of the vectors (`SearchRank`). */
3370
+ readonly rank?: SearchRank | undefined;
3371
+ }
3372
+ /** These options control `rankWithin` of a crawler. */
3373
+ interface RankOptions extends HybridOptions {
3374
+ /** This value chooses the ranking. The default is `exact`. */
3375
+ readonly rank?: SearchRank | undefined;
3376
+ }
2790
3377
  /** A polite crawler fetches each source one time, keeps it, and answers the next questions from the disk. */
2791
3378
  interface PoliteCrawler {
2792
3379
  /** The runtime gives the parts to an application that needs more control. */
@@ -2842,8 +3429,14 @@ interface PoliteCrawler {
2842
3429
  * locates each value. It does not make values. It sends no request. `openCrawler` gives it.
2843
3430
  */
2844
3431
  extract?(doc: string, fields: Readonly<Record<string, FieldClaim>>, options?: ExtractOptions): Promise<ExtractResult>;
2845
- }
2846
- /** This crawler is the result of `openCrawler`: a `PoliteCrawler` with `discover`, `crawl`, `diff`, `watch` and `extract`. */
3432
+ /** This optional search ranks with the vectors of an embedder. `openCrawler` gives it when it has an embedder. */
3433
+ readonly hybrid?: HybridSearch | undefined;
3434
+ /** This optional method gives vectors to the stored documents that have none, within a budget. */
3435
+ embed?(options?: EmbedOptions): Promise<EmbedResult>;
3436
+ /** This optional method ranks a set of stored documents against a query, the best first. */
3437
+ rankWithin?(q: string, docs: readonly string[], options?: RankOptions): Promise<Ranked[]>;
3438
+ }
3439
+ /** This crawler is the result of `openCrawler` in version 0.1.2: a `PoliteCrawler` with `discover`, `crawl`, `diff`, `watch` and `extract`. */
2847
3440
  interface OpenedCrawler extends PoliteCrawler {
2848
3441
  /** This method finds the pages of a site from its sitemaps and its feeds. */
2849
3442
  discover(site: string, options?: DiscoverOptions): Promise<DiscoverResult>;
@@ -2859,6 +3452,24 @@ interface OpenedCrawler extends PoliteCrawler {
2859
3452
  */
2860
3453
  extract(doc: string, fields: Readonly<Record<string, FieldClaim>>, options?: ExtractOptions): Promise<ExtractResult>;
2861
3454
  }
3455
+ /**
3456
+ * This crawler is the result of `openCrawler`: an `OpenedCrawler` with hybrid search. Its `find`
3457
+ * takes `rank: "hybrid"`, and it has `hybrid`, `embed` and `rankWithin`. `OpenedCrawler` does not
3458
+ * change, so an object of your own that implements the `OpenedCrawler` of 0.1.2 stays correct.
3459
+ */
3460
+ interface HybridCrawler extends OpenedCrawler {
3461
+ /** This method searches the stored documents. It also takes `rank: "hybrid"`, when the crawler has an embedder. */
3462
+ find(q: string, options?: SearchOptions): Promise<Found[]>;
3463
+ /** This search ranks with the vectors of the embedder, or it is undefined when the crawler has no embedder. */
3464
+ readonly hybrid: HybridSearch | undefined;
3465
+ /** This method gives vectors to the stored documents that have none, within a budget. It rejects when the crawler has no embedder. */
3466
+ embed(options?: EmbedOptions): Promise<EmbedResult>;
3467
+ /**
3468
+ * This method ranks a set of stored documents against a query, the best first. The modes
3469
+ * `exact` and `fast` are `DocIndex.rankWithin`. The mode `hybrid` needs an embedder.
3470
+ */
3471
+ rankWithin(q: string, docs: readonly string[], options?: RankOptions): Promise<Ranked[]>;
3472
+ }
2862
3473
  /**
2863
3474
  * This function opens a crawler on a folder. The folder keeps the capture log (`captures/`), the
2864
3475
  * response bodies (`blobs/`), the search index (`index.sqlite`) and the state of each host
@@ -2869,7 +3480,293 @@ interface OpenedCrawler extends PoliteCrawler {
2869
3480
  * Each method gives a promise, and none throws before its promise. After `close`, each method
2870
3481
  * rejects.
2871
3482
  */
2872
- declare const openCrawler: (options: OpenOptions) => OpenedCrawler;
3483
+ declare const openCrawler: (options: OpenOptions) => HybridCrawler;
3484
+ //#endregion
3485
+ //#region src/daemon.d.ts
3486
+ /** These are the defaults of the daemon. */
3487
+ declare const DAEMON_DEFAULTS: {
3488
+ /** The longest wait between two ticks: 1 minute. A tick comes sooner when an entry is due sooner. */
3489
+ readonly tickMs: 60_000;
3490
+ /** The most random time that the daemon adds to each wait: 10 seconds. */
3491
+ readonly jitterMs: 10_000;
3492
+ /** The budget of the checks of one tick: 10 minutes. No request starts after it. */
3493
+ readonly budgetMs: 600_000;
3494
+ /** The most checks of one tick. */
3495
+ readonly maxPages: 100;
3496
+ /** At a stop, the checks in progress get this time to end: 10 seconds. Then they abort. */
3497
+ readonly graceMs: 10_000;
3498
+ /** The shortest wait between two ticks: 1 second. */
3499
+ readonly minGapMs: 1_000;
3500
+ /** The shortest tick: 1 second. */
3501
+ readonly minTickMs: 1_000;
3502
+ /** The status lists this number of the next due entries. */
3503
+ readonly dueShown: 10;
3504
+ /** An on-change command that runs longer than this time stops: 1 minute. */
3505
+ readonly hookTimeoutMs: 60_000;
3506
+ };
3507
+ /** This value is the version of the format of the state file. */
3508
+ declare const DAEMON_STATE_SCHEMA = 1;
3509
+ /** This is a watch entry that is due soon, as the status shows it. */
3510
+ interface DaemonDue {
3511
+ readonly url: string;
3512
+ /** This time (ISO 8601) is the time when the entry is due. */
3513
+ readonly next_at: string;
3514
+ readonly every_ms: number;
3515
+ /** This value is the kind of the last check, or null before the first check. */
3516
+ readonly last_kind: string | null;
3517
+ }
3518
+ /** This is one tick of the schedule: one run of the watch list. */
3519
+ interface DaemonTick {
3520
+ /** This time (ISO 8601) is the start of the run. */
3521
+ readonly started_at: string;
3522
+ /** This time (ISO 8601) is the end of the run. */
3523
+ readonly ended_at: string;
3524
+ /** This value is the summary of the run, or null when the run failed. */
3525
+ readonly summary: WatchSummary | null;
3526
+ /** This text tells why the run failed, or null. */
3527
+ readonly error: string | null;
3528
+ /** This time (ISO 8601) is the time of the next tick, or null when the schedule stops. */
3529
+ readonly next_at: string | null;
3530
+ /** These entries are the next due entries after the run, the first due first. */
3531
+ readonly due: readonly DaemonDue[];
3532
+ }
3533
+ /** These options control the schedule of the watch list. */
3534
+ interface ScheduleOptions {
3535
+ /** This value is the longest wait between two ticks. The default is `1m`, and the floor is `1s`. */
3536
+ readonly tick?: Duration | undefined;
3537
+ /** This value is the most random time that the schedule adds to each wait. The default is `10s`. */
3538
+ readonly jitter?: Duration | undefined;
3539
+ /** This value is the budget of the checks of one tick. The default is `10m`. */
3540
+ readonly budget?: Duration | undefined;
3541
+ /** This value is the most checks of one tick. The default is 100. */
3542
+ readonly maxPages?: number | undefined;
3543
+ /** This clock gives the time and the waits. Give the clock of the crawler. The default is the real clock. */
3544
+ readonly clock?: Clock | undefined;
3545
+ /** This function gives the random numbers of the jitter. The default is `Math.random`. */
3546
+ readonly random?: (() => number) | undefined;
3547
+ /** This function gets each event of each check. */
3548
+ readonly onEvent?: ((event: WatchEvent) => void) | undefined;
3549
+ /** This function gets each tick when its run ends. */
3550
+ readonly onTick?: ((tick: DaemonTick) => void) | undefined;
3551
+ /** This function gets the error of a run that failed. The schedule goes on at the next tick. */
3552
+ readonly onError?: ((error: Error) => void) | undefined;
3553
+ }
3554
+ /** This is the result of a schedule: the counts so far, and the last tick. */
3555
+ interface ScheduleResult {
3556
+ readonly ticks: number;
3557
+ /** This value counts the checks that gave an event. */
3558
+ readonly checked: number;
3559
+ /** This value counts the confirmed changes. */
3560
+ readonly changes: number;
3561
+ readonly last: DaemonTick | null;
3562
+ }
3563
+ /** A schedule that runs. `stop` ends it, and `done` resolves when it ends. */
3564
+ interface WatchSchedule {
3565
+ /** This promise resolves when the schedule ends. It does not reject. */
3566
+ readonly done: Promise<ScheduleResult>;
3567
+ /**
3568
+ * This method stops the schedule. The run in progress starts no new check. The checks in
3569
+ * progress get `grace` (10 seconds by default) to end and write their state. Then they abort,
3570
+ * and the run releases their leases. A second call with a shorter grace shortens it.
3571
+ */
3572
+ stop(grace?: Duration): Promise<ScheduleResult>;
3573
+ /** This method gives the counts so far. */
3574
+ result(): ScheduleResult;
3575
+ }
3576
+ /**
3577
+ * This function checks a watch list on a schedule. The first tick starts at once. Each tick is one
3578
+ * `watch.run` with the budget and `maxPages` of a tick. Thus each polite rule of the run applies:
3579
+ * one request at a time to each host, the stops of a host, `Retry-After` and robots.txt.
3580
+ *
3581
+ * After a run, the schedule waits for the next tick (`nextTickAt`). An error of a run goes to
3582
+ * `onError`, and the schedule goes on.
3583
+ */
3584
+ declare const scheduleWatches: (watch: WatchList, options?: ScheduleOptions) => WatchSchedule;
3585
+ /** This is a task of the MCP server, as the status shows it. */
3586
+ interface DaemonTask {
3587
+ readonly id: string;
3588
+ /** This value is the name of the tool, for example `crawl_site`. */
3589
+ readonly tool: string;
3590
+ /** This value is `working`, `input_required`, `completed`, `failed` or `cancelled`. */
3591
+ readonly status: string;
3592
+ /** This text tells the progress, for example `3 of 10 done`, or null. */
3593
+ readonly message: string | null;
3594
+ readonly created_at: string;
3595
+ readonly updated_at: string;
3596
+ }
3597
+ /** This is the status of a daemon. The state file (`<store>/daemon/state.json`) holds the same JSON. */
3598
+ interface DaemonStatus {
3599
+ /** This value is the version of the format (`DAEMON_STATE_SCHEMA`). */
3600
+ readonly schema: number;
3601
+ /** This value is the version of polite-crawler. */
3602
+ readonly version: string;
3603
+ /** This value is the id of the process of the daemon. */
3604
+ readonly pid: number;
3605
+ readonly store: string;
3606
+ /** This value is false after the daemon stopped. */
3607
+ readonly running: boolean;
3608
+ readonly started_at: string;
3609
+ readonly updated_at: string;
3610
+ readonly stopped_at: string | null;
3611
+ readonly tick_ms: number;
3612
+ readonly jitter_ms: number;
3613
+ readonly budget_ms: number;
3614
+ readonly max_pages: number;
3615
+ /** This value counts the ticks. */
3616
+ readonly ticks: number;
3617
+ /** This value counts the checks. */
3618
+ readonly checked: number;
3619
+ /** This value counts the confirmed changes. */
3620
+ readonly changes: number;
3621
+ readonly last_tick: DaemonTick | null;
3622
+ /** This time (ISO 8601) is the time of the next tick, or null. */
3623
+ readonly next_tick_at: string | null;
3624
+ /** These entries are the next due entries at the last tick, the first due first. */
3625
+ readonly next_due: readonly DaemonDue[];
3626
+ /** These tasks of the MCP server did not end. */
3627
+ readonly tasks: readonly DaemonTask[];
3628
+ /** This value is the MCP endpoint and the file of its token, or null with no MCP server. */
3629
+ readonly mcp: {
3630
+ readonly url: string;
3631
+ readonly token_file: string | null;
3632
+ } | null;
3633
+ /** This value is the last error: of a tick, of the event log, of an on-change hook or of the MCP server. */
3634
+ readonly last_error: {
3635
+ readonly at: string;
3636
+ readonly message: string;
3637
+ } | null;
3638
+ }
3639
+ /** This is a status that `readDaemonState` read from a state file. */
3640
+ interface DaemonState extends DaemonStatus {
3641
+ /** This value is true when the daemon runs: the state says so, and its process is alive. */
3642
+ readonly alive: boolean;
3643
+ }
3644
+ /** This function gives the path of the state file of a store. */
3645
+ declare const daemonStateFile: (dir: string) => string;
3646
+ /**
3647
+ * This function reads the state file of a daemon. It gives undefined when the file is not there,
3648
+ * or when it is not a state file. `alive` tells if the daemon runs.
3649
+ */
3650
+ declare const readDaemonState: (dir: string, file?: string) => DaemonState | undefined;
3651
+ /** These options start an on-change command. */
3652
+ interface ChangeCommandOptions {
3653
+ /** A command that runs longer than this time stops. The default is `1m`. */
3654
+ readonly timeout?: Duration | undefined;
3655
+ /** This folder is the working folder of the command. The default is the working folder of the daemon. */
3656
+ readonly cwd?: string | undefined;
3657
+ }
3658
+ /**
3659
+ * This function gives an `onChange` hook that starts a command of the operator for each change.
3660
+ * The command operates in the shell of the system, as the user of the daemon. It gets the event as
3661
+ * one JSON line on its standard input, not in its command line. Thus no text of a page goes into
3662
+ * the command line. The output of the command goes nowhere. A command that exits with a code that
3663
+ * is not 0, or that runs too long, rejects with the end of its standard error.
3664
+ *
3665
+ * The command is the decision of the operator. Do not take it from a page or from an assistant.
3666
+ */
3667
+ declare const changeCommand: (command: string, options?: ChangeCommandOptions) => ((event: WatchEvent) => Promise<void>);
3668
+ /** These options serve the MCP tools over HTTP. */
3669
+ interface DaemonMcpOptions {
3670
+ /** This value is the port. The default is 9307. The value 0 takes a free port. */
3671
+ readonly port?: number | undefined;
3672
+ /** This value is the host to bind. The default is `127.0.0.1`. A host that is not loopback needs `allowRemote`. */
3673
+ readonly host?: string | undefined;
3674
+ /** The value true permits a host that is not loopback. Read the warning in the README first. */
3675
+ readonly allowRemote?: boolean | undefined;
3676
+ /** This value is the bearer token. The default makes a new token at each start, in `<store>/daemon/mcp-token`. */
3677
+ readonly token?: string | undefined;
3678
+ /** This file holds the bearer token of the operator. The daemon reads it and writes nothing. */
3679
+ readonly tokenFile?: string | undefined;
3680
+ /** These tokens get their robots.txt rules applied to each fetch of a tool. The default is `["Claude-User"]`. */
3681
+ readonly onBehalfOf?: readonly string[] | undefined;
3682
+ /** The value true lets `user_provided` release held-back text when the client cannot ask the user. */
3683
+ readonly allowUserProvided?: boolean | undefined;
3684
+ /** This text tells why the server renders no page. */
3685
+ readonly renderOff?: string | undefined;
3686
+ }
3687
+ /** These functions connect an MCP host to the daemon. */
3688
+ interface DaemonMcpHooks {
3689
+ /** This function gives the status of the daemon, for the status route. */
3690
+ readonly status: () => DaemonStatus;
3691
+ /** This function operates when a task starts, changes or ends. */
3692
+ readonly onTasks: () => void;
3693
+ /** This function writes a message of the server. */
3694
+ readonly log: (line: string) => void;
3695
+ }
3696
+ /** This is the MCP server of the daemon, as the MCP host gives it. */
3697
+ interface DaemonMcpService {
3698
+ /** This URL is the MCP endpoint. */
3699
+ readonly url: string;
3700
+ /** This method gives the tasks that did not end. */
3701
+ tasks(): readonly DaemonTask[];
3702
+ /** This method stops the server and cancels its tasks. */
3703
+ close(): Promise<void>;
3704
+ }
3705
+ /**
3706
+ * This is the seam between the daemon and its MCP server. The default host (`mcpHttpHost` of
3707
+ * `polite-crawler/mcp`) serves the tools over Streamable HTTP. A different MCP host can replace it.
3708
+ */
3709
+ interface DaemonMcpHost {
3710
+ start(crawler: OpenedCrawler, options: DaemonMcpOptions, hooks: DaemonMcpHooks): Promise<DaemonMcpService>;
3711
+ }
3712
+ /** These options start a daemon on a store. Only `dir` is necessary. */
3713
+ interface DaemonOptions extends OpenOptions {
3714
+ /** This value is the longest wait between two ticks. The default is `1m`, and the floor is `1s`. */
3715
+ readonly tick?: Duration | undefined;
3716
+ /** This value is the most random time that the daemon adds to each wait. The default is `10s`. */
3717
+ readonly jitter?: Duration | undefined;
3718
+ /** This value is the budget of the checks of one tick. The default is `10m`. */
3719
+ readonly budget?: Duration | undefined;
3720
+ /** This value is the most checks of one tick. The default is 100. */
3721
+ readonly maxPages?: number | undefined;
3722
+ /** At a stop, the checks in progress get this time to end. The default is `10s`. */
3723
+ readonly grace?: Duration | undefined;
3724
+ /**
3725
+ * The daemon writes each change event as one JSON line here: a file, a function, or the standard
3726
+ * output (the default). The value false writes no line. A change is an event with `confirmed: true`.
3727
+ */
3728
+ readonly events?: string | ((line: string) => void) | false | undefined;
3729
+ /** This function gets each change event. The daemon starts it in order, one at a time, and logs its error. */
3730
+ readonly onChange?: ((event: WatchEvent) => void | Promise<void>) | undefined;
3731
+ /** These options serve the MCP tools over HTTP. Without them, the daemon serves no MCP. */
3732
+ readonly mcp?: DaemonMcpOptions | undefined;
3733
+ /** This host serves the MCP tools. The default serves them over Streamable HTTP. */
3734
+ readonly mcpHost?: DaemonMcpHost | undefined;
3735
+ /** The value false installs no handler of `SIGINT` and `SIGTERM`. The default is true. */
3736
+ readonly signals?: boolean | undefined;
3737
+ /** This file keeps the state of the daemon. The default is `<store>/daemon/state.json`. */
3738
+ readonly stateFile?: string | undefined;
3739
+ /** This function writes the messages of the daemon. The default writes them to the standard error. */
3740
+ readonly log?: ((line: string) => void) | undefined;
3741
+ }
3742
+ /** This is a daemon that runs. */
3743
+ interface Daemon {
3744
+ /** This crawler is the crawler of the daemon. The daemon closes it when it stops. */
3745
+ readonly crawler: OpenedCrawler;
3746
+ /** This file keeps the state of the daemon. */
3747
+ readonly stateFile: string;
3748
+ /** This value is the MCP server, or undefined. */
3749
+ readonly mcp: DaemonMcpService | undefined;
3750
+ /** This method gives the status at this time. */
3751
+ status(): DaemonStatus;
3752
+ /**
3753
+ * This method stops the daemon. The checks in progress get the grace time to end, then they
3754
+ * abort and the run releases their leases. The MCP server stops and cancels its tasks. A second
3755
+ * call with `0` aborts the checks at once.
3756
+ */
3757
+ stop(grace?: Duration): Promise<DaemonStatus>;
3758
+ /** This promise resolves with the last status when the daemon stopped. */
3759
+ readonly done: Promise<DaemonStatus>;
3760
+ }
3761
+ /**
3762
+ * This function starts a daemon on a store. It opens the crawler, serves MCP when `mcp` is given,
3763
+ * and checks the watch list on a schedule (`scheduleWatches`). It writes each change event as one
3764
+ * JSON line, and it gives each change to `onChange`. The state file tells `daemon status` what runs.
3765
+ *
3766
+ * Only one daemon operates on a store: a second start rejects. At `SIGINT` or `SIGTERM`, the daemon
3767
+ * stops cleanly (`stop`). A second signal aborts the checks at once.
3768
+ */
3769
+ declare const startDaemon: (options: DaemonOptions) => Promise<Daemon>;
2873
3770
  //#endregion
2874
- export { DiscoverOptions as $, verifyQuote as $n, SignedRequest as $t, CrawlPage as A, Extractors as An, diffTexts as At, ExtractSummary as B, catchUpIndex as Bn, FetchOutcome as Bt, WatchStop as C, WebArchive as Cn, DiffSide as Ct, runWatch as D, CatchUpResult as Dn, VersionChoice as Dt, WatchSummary as E, CapturePayload as En, TextDiff as Et, UrlPattern as F, ReadOptions as Fn, CrawlEvent as Ft, FieldKind as G, isHeldBack as Gn, DirectoryKey as Gt, FieldCandidate as H, fetchPage as Hn, Fetched as Ht, crawlSite as I, ReadResult as In, Crawler as It, FieldStatus as J, pageExtractor as Jn, KeyDirectory as Jt, FieldResult as K, isoTime as Kn, KEY_DIRECTORY_PATH as Kt, ExtractOptions as L, ReindexResult as Ln, CrawlerOptions as Lt, CrawlRunOptions as M, Indexed as Mn, CacheEntry as Mt, CrawlStop as N, PageOptions as Nn, CacheIndex as Nt, CRAWL_LIMITS as O, CrawlRuntime as On, WordPart as Ot, CrawlSummary as P, PageResult as Pn, CaptureWriter as Pt, DISCOVER_LIMITS as Q, renderAndIndex as Qn, SignatureCheck as Qt, ExtractResult as R, VerifyOptions as Rn, DEADLINE_NOTE as Rt, WatchRunnerOptions as S, Archived as Sn, DiffResult as St, WatchStoreOptions as T, archivedDocId as Tn, MetaChange as Tt, FieldCheck as U, findDocuments as Un, RenderRequest as Ut, FIELD_KINDS as V, fetchAndIndex as Vn, FetchRequest as Vt, FieldClaim as W, heldBackMeta as Wn, renderedKey as Wt, checkFields as X, recordOverride as Xn, RequestSigner as Xt, FieldsChecked as Y, readDocument as Yn, KeyInput as Yt, extractDocument as Z, reindex as Zn, SignatureAgentType as Zt, WatchList as _, RankMode as _n, BlobStore as _r, DiffHunk as _t, PoliteCrawler as a, EgressOptions as an, ScanOptions as ar, discoverSite as at, WatchRun as b, VersionAt as bn, DiffLine as bt, createRuntime as c, Doc as cn, makeRecord as cr, SitemapEntry as ct, openCrawler as d, DocVersion as dn, RefusedReason as dr, SitemapRead as dt, WebBotAuthOptions as en, versionAtTime as er, DiscoverResult as et, WATCH_LIMITS as f, ExtractedDoc as fn, RenderOptions as fr, feedDate as ft, WatchKind as g, Latest as gn, playwrightRenderer as gr, DIFF_LIMITS as gt, WatchEvent as h, Found as hn, Renderer as hr, durationMs as ht, OpenedCrawler as i, verifySignature as in, DamagedLine as ir, DiscoveredUrl as it, CrawlRun as j, HELD_BACK as jn, CAPTURE_SCHEMA as jt, CrawlOptions as k, Extractor as kn, diffDocument as kt, defaultUserAgent as l, DocIndex as ln, NO_PLAYWRIGHT as lr, SitemapKind as lt, WatchEntry as m, FindIndexOptions as mn, Rendered as mr, Duration as mt, FindOptions as n, createWebBotAuthSigner as nn, CaptureLog as nr, DiscoverSource as nt, RuntimeOptions as o, EgressRefused as on, CaptureRecord as or, Changefreq as ot, WATCH_SCHEMA as p, FAST_RANK_SHARE as pn, RenderRefused as pr, readSitemap as pt, FieldSpan as q, pageDocId as qn, KEY_DIRECTORY_TYPE as qt, OpenOptions as r, keyDirectory as rn, CaptureReader as rr, DiscoverStop as rt, StoreRuntime as s, egressLookup as sn, RecordInput as sr, SITEMAP_LIMITS as st, FetchOptions as t, WebBotAuthSigner as tn, CaptureFilter as tr, DiscoverRunOptions as tt, isMailbox as u, DocInput as un, PlaywrightRenderer as ur, SitemapLimits as ut, WatchOptions as v, ReadingIndex as vn, FileBlobStore as vr, DiffInput as vt, WatchStore as w, archiveExtractor as wn, DiffSummary as wt, WatchRunOptions as x, VersionText as xn, DiffOptions as xt, WatchPending as y, Variant as yn, DiffLimits as yt, ExtractSource as z, VerifyResult as zn, DEFAULT_SECRET_PARAMS as zt };
2875
- //# sourceMappingURL=open-Ca1lcWR3.d.mts.map
3771
+ export { RECIPE_LIMITS as $, FetchOutcome as $n, ReadOptions as $r, checkFields as $t, RuntimeOptions as A, PlaywrightRenderer as Ai, DiffHunk as An, Found as Ar, VectorWrite as At, WatchEvent as B, VersionChoice as Bn, Archived as Br, ExtractOptions as Bt, FetchOptions as C, ScanOptions as Ci, SitemapEntry as Cn, DocDigest as Cr, createHybridSearch as Ct, OpenedCrawler as D, Duration as Di, feedDate as Dn, ExtractedDoc as Dr, VectorHit as Dt, OpenOptions as E, makeRecord as Ei, SitemapRead as En, DocVersion as Er, VectorCounts as Et, isMailbox as F, Renderer as Fi, DiffResult as Fn, ReadingIndex as Fr, CrawlRunOptions as Ft, WatchRun as G, CacheEntry as Gn, CatchUpResult as Gr, FieldCandidate as Gt, WatchList as H, diffDocument as Hn, archiveExtractor as Hr, ExtractSource as Ht, openCrawler as I, playwrightRenderer as Ii, DiffSide as In, SearchRank as Ir, CrawlStop as It, WatchStop as J, CrawlEvent as Jn, Extractors as Jr, FieldKind as Jt, WatchRunOptions as K, CacheIndex as Kn, CrawlRuntime as Kr, FieldCheck as Kt, WATCH_LIMITS as L, BlobStore as Li, DiffSummary as Ln, Variant as Lr, CrawlSummary as Lt, StoreRuntime as M, RenderOptions as Mi, DiffLimits as Mn, NO_EMBEDDER as Mr, CrawlOptions as Mt, createRuntime as N, RenderRefused as Ni, DiffLine as Nn, Passage as Nr, CrawlPage as Nt, PoliteCrawler as O, durationMs as Oi, readSitemap as On, FAST_RANK_SHARE as Or, VectorStore as Ot, defaultUserAgent as P, Rendered as Pi, DiffOptions as Pn, RankMode as Pr, CrawlRun as Pt, runWatch as Q, DEFAULT_SECRET_PARAMS as Qn, PageResult as Qr, FieldsChecked as Qt, WATCH_SCHEMA as R, FileBlobStore as Ri, MetaChange as Rn, VersionAt as Rr, UrlPattern as Rt, startDaemon as S, DamagedLine as Si, SITEMAP_LIMITS as Sn, Doc as Sr, Ranked as St, HybridCrawler as T, RecordInput as Ti, SitemapLimits as Tn, DocInput as Tr, VECTORS_SCHEMA as Tt, WatchOptions as U, diffTexts as Un, archivedDocId as Ur, ExtractSummary as Ut, WatchKind as V, WordPart as Vn, WebArchive as Vr, ExtractResult as Vt, WatchPending as W, CAPTURE_SCHEMA as Wn, CapturePayload as Wr, FIELD_KINDS as Wt, WatchStoreOptions as X, CrawlerOptions as Xn, Indexed as Xr, FieldSpan as Xt, WatchStore as Y, Crawler as Yn, HELD_BACK as Yr, FieldResult as Yt, WatchSummary as Z, DEADLINE_NOTE as Zn, PageOptions as Zr, FieldStatus as Zt, WatchSchedule as _, verifyQuote as _i, DiscoverSource as _n, verifySignature as _r, EmbedStop as _t, DaemonDue as a, fetchAndIndex as ai, FusedRank as an, KEY_DIRECTORY_PATH as ar, RecipeExtract as at, readDaemonState as b, CaptureLog as bi, discoverSite as bn, egressLookup as br, HybridSearch as bt, DaemonMcpOptions as c, heldBackMeta as ci, chunkText as cn, KeyInput as cr, RecipeResult as ct, DaemonState as d, pageDocId as di, fuseRanks as dn, SignatureCheck as dr, defineRecipe as dt, ReadResult as ei, extractDocument as en, FetchRequest as er, RESERVED_RECIPES as et, DaemonStatus as f, pageExtractor as fi, unitVector as fn, SignedRequest as fr, readJson as ft, ScheduleResult as g, renderAndIndex as gi, DiscoverRunOptions as gn, keyDirectory as gr, EmbedResult as gt, ScheduleOptions as h, reindex as hi, DiscoverResult as hn, createWebBotAuthSigner as hr, EmbedOptions as ht, Daemon as i, catchUpIndex as ii, Embedder as in, DirectoryKey as ir, RecipeDoc as it, SearchOptions as j, RefusedReason as ji, DiffInput as jn, Latest as jr, CRAWL_LIMITS as jt, RankOptions as k, NO_PLAYWRIGHT as ki, DIFF_LIMITS as kn, FindIndexOptions as kr, VectorStoreOptions as kt, DaemonMcpService as l, isHeldBack as li, chunkTokensOf as ln, RequestSigner as lr, RecipeRunOptions as lt, DaemonTick as m, recordOverride as mi, DiscoverOptions as mn, WebBotAuthSigner as mr, runRecipe as mt, DAEMON_DEFAULTS as n, VerifyOptions as ni, ChunkOptions as nn, RenderRequest as nr, RecipeCapture as nt, DaemonMcpHooks as o, fetchPage as oi, HYBRID_DEFAULTS as on, KEY_DIRECTORY_TYPE as or, RecipeRequest as ot, DaemonTask as p, readDocument as pi, DISCOVER_LIMITS as pn, WebBotAuthOptions as pr, registerRecipe as pt, WatchRunnerOptions as q, CaptureWriter as qn, Extractor as qr, FieldClaim as qt, DAEMON_STATE_SCHEMA as r, VerifyResult as ri, EmbedCallOptions as rn, renderedKey as rr, RecipeDefinition as rt, DaemonMcpHost as s, findDocuments as si, TextChunk as sn, KeyDirectory as sr, RecipeRequestOptions as st, ChangeCommandOptions as t, ReindexResult as ti, CHUNK_LIMITS as tn, Fetched as tr, Recipe as tt, DaemonOptions as u, isoTime as ui, estimateTokens as un, SignatureAgentType as ur, RecipeTarget as ut, changeCommand as v, versionAtTime as vi, DiscoverStop as vn, EgressOptions as vr, HybridFindOptions as vt, FindOptions as w, CaptureRecord as wi, SitemapKind as wn, DocIndex as wr, StoredChunk as wt, scheduleWatches as x, CaptureReader as xi, Changefreq as xn, DigestOptions as xr, HybridSearchOptions as xt, daemonStateFile as y, CaptureFilter as yi, DiscoveredUrl as yn, EgressRefused as yr, HybridOptions as yt, WatchEntry as z, TextDiff as zn, VersionText as zr, crawlSite as zt };
3772
+ //# sourceMappingURL=daemon-DP4EqjFL.d.mts.map