wiki-graph-core 0.3.1

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 (576) hide show
  1. package/LICENSE +201 -0
  2. package/data/editor/clue_reviewer.jinja +410 -0
  3. package/data/editor/clue_reviewer_generator.jinja +428 -0
  4. package/data/editor/revision_feedback.jinja +5 -0
  5. package/data/editor/text_compressor.jinja +127 -0
  6. package/data/guaranteed/response_intent_classifier.jinja +8 -0
  7. package/data/help/commands/archive/next.jinja +29 -0
  8. package/data/help/commands/gc.jinja +38 -0
  9. package/data/help/commands/legacy/migrate.jinja +20 -0
  10. package/data/help/commands/legacy.jinja +19 -0
  11. package/data/help/commands/maintenance/chapter/add.jinja +41 -0
  12. package/data/help/commands/maintenance/chapter/list.jinja +33 -0
  13. package/data/help/commands/maintenance/chapter/move.jinja +36 -0
  14. package/data/help/commands/maintenance/chapter/remove.jinja +26 -0
  15. package/data/help/commands/maintenance/chapter/reset.jinja +29 -0
  16. package/data/help/commands/maintenance/chapter/set-source.jinja +34 -0
  17. package/data/help/commands/maintenance/chapter/set-summary.jinja +31 -0
  18. package/data/help/commands/maintenance/chapter/set-title.jinja +29 -0
  19. package/data/help/commands/maintenance/chapter/tree.jinja +58 -0
  20. package/data/help/commands/maintenance/chapter.jinja +59 -0
  21. package/data/help/commands/maintenance/cover.jinja +28 -0
  22. package/data/help/commands/maintenance/meta.jinja +55 -0
  23. package/data/help/commands/predicate.jinja +460 -0
  24. package/data/help/commands/root.jinja +83 -0
  25. package/data/help/commands/transform.jinja +34 -0
  26. package/data/help/commands/uri.jinja +274 -0
  27. package/data/help/topics/config.jinja +88 -0
  28. package/data/help/topics/format.jinja +72 -0
  29. package/data/help/topics/readiness.jinja +99 -0
  30. package/data/help/topics/recipe.jinja +151 -0
  31. package/data/help/topics/runtime.jinja +62 -0
  32. package/data/help/topics/uri.jinja +178 -0
  33. package/data/output/epub/cover.xhtml.jinja +13 -0
  34. package/data/output/epub/nav.xhtml.jinja +12 -0
  35. package/data/output/epub/package.opf.xml.jinja +39 -0
  36. package/data/output/epub/section.xhtml.jinja +12 -0
  37. package/data/topologization/book_coherence_extraction.jinja +223 -0
  38. package/data/topologization/chunk_extraction.jinja +233 -0
  39. package/data/topologization/evidence_choice.jinja +38 -0
  40. package/data/topologization/translate_chunks.jinja +138 -0
  41. package/data/topologization/user_focused_extraction.jinja +378 -0
  42. package/dist/archive/query/archive-view.d.ts +26 -0
  43. package/dist/archive/query/archive-view.js +4540 -0
  44. package/dist/archive/query/archive-view.js.map +1 -0
  45. package/dist/archive/query/continuation-cursor.d.ts +61 -0
  46. package/dist/archive/query/continuation-cursor.js +363 -0
  47. package/dist/archive/query/continuation-cursor.js.map +1 -0
  48. package/dist/archive/query/index.d.ts +29 -0
  49. package/dist/archive/query/index.js +63 -0
  50. package/dist/archive/query/index.js.map +1 -0
  51. package/dist/archive/query/lexical-search.d.ts +22 -0
  52. package/dist/archive/query/lexical-search.js +137 -0
  53. package/dist/archive/query/lexical-search.js.map +1 -0
  54. package/dist/archive/query/search-cache.d.ts +192 -0
  55. package/dist/archive/query/search-cache.js +1248 -0
  56. package/dist/archive/query/search-cache.js.map +1 -0
  57. package/dist/archive/search-index/index.d.ts +26 -0
  58. package/dist/archive/search-index/index.js +29 -0
  59. package/dist/archive/search-index/index.js.map +1 -0
  60. package/dist/archive/search-index/search-index.d.ts +26 -0
  61. package/dist/archive/search-index/search-index.js +555 -0
  62. package/dist/archive/search-index/search-index.js.map +1 -0
  63. package/dist/archive/search-index/search-tokenizer.d.ts +16 -0
  64. package/dist/archive/search-index/search-tokenizer.js +225 -0
  65. package/dist/archive/search-index/search-tokenizer.js.map +1 -0
  66. package/dist/common/cli-command.d.ts +4 -0
  67. package/dist/common/cli-command.js +7 -0
  68. package/dist/common/cli-command.js.map +1 -0
  69. package/dist/common/data-dir.d.ts +3 -0
  70. package/dist/common/data-dir.js +48 -0
  71. package/dist/common/data-dir.js.map +1 -0
  72. package/dist/common/language.d.ts +55 -0
  73. package/dist/common/language.js +208 -0
  74. package/dist/common/language.js.map +1 -0
  75. package/dist/common/llm-scope.d.ts +19 -0
  76. package/dist/common/llm-scope.js +31 -0
  77. package/dist/common/llm-scope.js.map +1 -0
  78. package/dist/common/logging.d.ts +22 -0
  79. package/dist/common/logging.js +141 -0
  80. package/dist/common/logging.js.map +1 -0
  81. package/dist/common/template.d.ts +8 -0
  82. package/dist/common/template.js +54 -0
  83. package/dist/common/template.js.map +1 -0
  84. package/dist/common/tinyld-language.d.ts +6 -0
  85. package/dist/common/tinyld-language.js +34 -0
  86. package/dist/common/tinyld-language.js.map +1 -0
  87. package/dist/common/wiki-graph-dir.d.ts +10 -0
  88. package/dist/common/wiki-graph-dir.js +41 -0
  89. package/dist/common/wiki-graph-dir.js.map +1 -0
  90. package/dist/common/wiki-graph-temp.d.ts +6 -0
  91. package/dist/common/wiki-graph-temp.js +21 -0
  92. package/dist/common/wiki-graph-temp.js.map +1 -0
  93. package/dist/common/wiki-graph-uri.d.ts +28 -0
  94. package/dist/common/wiki-graph-uri.js +171 -0
  95. package/dist/common/wiki-graph-uri.js.map +1 -0
  96. package/dist/context/index.d.ts +1 -0
  97. package/dist/context/index.js +13 -0
  98. package/dist/context/index.js.map +1 -0
  99. package/dist/context/task-context.d.ts +41 -0
  100. package/dist/context/task-context.js +111 -0
  101. package/dist/context/task-context.js.map +1 -0
  102. package/dist/document/database.d.ts +30 -0
  103. package/dist/document/database.js +273 -0
  104. package/dist/document/database.js.map +1 -0
  105. package/dist/document/document.d.ts +153 -0
  106. package/dist/document/document.js +615 -0
  107. package/dist/document/document.js.map +1 -0
  108. package/dist/document/fragments.d.ts +63 -0
  109. package/dist/document/fragments.js +371 -0
  110. package/dist/document/fragments.js.map +1 -0
  111. package/dist/document/index.d.ts +13 -0
  112. package/dist/document/index.js +62 -0
  113. package/dist/document/index.js.map +1 -0
  114. package/dist/document/schema.d.ts +8 -0
  115. package/dist/document/schema.js +472 -0
  116. package/dist/document/schema.js.map +1 -0
  117. package/dist/document/shared-state-database.d.ts +9 -0
  118. package/dist/document/shared-state-database.js +193 -0
  119. package/dist/document/shared-state-database.js.map +1 -0
  120. package/dist/document/stores.d.ts +203 -0
  121. package/dist/document/stores.js +1678 -0
  122. package/dist/document/stores.js.map +1 -0
  123. package/dist/document/text-streams.d.ts +86 -0
  124. package/dist/document/text-streams.js +515 -0
  125. package/dist/document/text-streams.js.map +1 -0
  126. package/dist/document/types.d.ts +148 -0
  127. package/dist/document/types.js +69 -0
  128. package/dist/document/types.js.map +1 -0
  129. package/dist/editor/clue.d.ts +27 -0
  130. package/dist/editor/clue.js +158 -0
  131. package/dist/editor/clue.js.map +1 -0
  132. package/dist/editor/compressor.d.ts +18 -0
  133. package/dist/editor/compressor.js +68 -0
  134. package/dist/editor/compressor.js.map +1 -0
  135. package/dist/editor/editor.d.ts +39 -0
  136. package/dist/editor/editor.js +253 -0
  137. package/dist/editor/editor.js.map +1 -0
  138. package/dist/editor/feedback.d.ts +16 -0
  139. package/dist/editor/feedback.js +104 -0
  140. package/dist/editor/feedback.js.map +1 -0
  141. package/dist/editor/index.d.ts +17 -0
  142. package/dist/editor/index.js +5 -0
  143. package/dist/editor/index.js.map +1 -0
  144. package/dist/editor/language-review.d.ts +14 -0
  145. package/dist/editor/language-review.js +35 -0
  146. package/dist/editor/language-review.js.map +1 -0
  147. package/dist/editor/log.d.ts +37 -0
  148. package/dist/editor/log.js +202 -0
  149. package/dist/editor/log.js.map +1 -0
  150. package/dist/editor/markup.d.ts +20 -0
  151. package/dist/editor/markup.js +294 -0
  152. package/dist/editor/markup.js.map +1 -0
  153. package/dist/editor/prompt-templates.d.ts +6 -0
  154. package/dist/editor/prompt-templates.js +11 -0
  155. package/dist/editor/prompt-templates.js.map +1 -0
  156. package/dist/editor/response.d.ts +5 -0
  157. package/dist/editor/response.js +31 -0
  158. package/dist/editor/response.js.map +1 -0
  159. package/dist/editor/review.d.ts +34 -0
  160. package/dist/editor/review.js +189 -0
  161. package/dist/editor/review.js.map +1 -0
  162. package/dist/editor/types.d.ts +31 -0
  163. package/dist/editor/types.js +21 -0
  164. package/dist/editor/types.js.map +1 -0
  165. package/dist/evidence-selection/anchor-resolver.d.ts +43 -0
  166. package/dist/evidence-selection/anchor-resolver.js +783 -0
  167. package/dist/evidence-selection/anchor-resolver.js.map +1 -0
  168. package/dist/evidence-selection/anchor-types.d.ts +27 -0
  169. package/dist/evidence-selection/anchor-types.js +1 -0
  170. package/dist/evidence-selection/anchor-types.js.map +1 -0
  171. package/dist/evidence-selection/index.d.ts +8 -0
  172. package/dist/evidence-selection/index.js +32 -0
  173. package/dist/evidence-selection/index.js.map +1 -0
  174. package/dist/evidence-selection/prompt.d.ts +18 -0
  175. package/dist/evidence-selection/prompt.js +54 -0
  176. package/dist/evidence-selection/prompt.js.map +1 -0
  177. package/dist/evidence-selection/quote-score.d.ts +29 -0
  178. package/dist/evidence-selection/quote-score.js +331 -0
  179. package/dist/evidence-selection/quote-score.js.map +1 -0
  180. package/dist/evidence-selection/selection-resolver.d.ts +19 -0
  181. package/dist/evidence-selection/selection-resolver.js +303 -0
  182. package/dist/evidence-selection/selection-resolver.js.map +1 -0
  183. package/dist/evidence-selection/text.d.ts +4 -0
  184. package/dist/evidence-selection/text.js +66 -0
  185. package/dist/evidence-selection/text.js.map +1 -0
  186. package/dist/evidence-selection/types.d.ts +36 -0
  187. package/dist/evidence-selection/types.js +1 -0
  188. package/dist/evidence-selection/types.js.map +1 -0
  189. package/dist/facade/app.d.ts +75 -0
  190. package/dist/facade/app.js +141 -0
  191. package/dist/facade/app.js.map +1 -0
  192. package/dist/facade/build-queue.d.ts +181 -0
  193. package/dist/facade/build-queue.js +1442 -0
  194. package/dist/facade/build-queue.js.map +1 -0
  195. package/dist/facade/chapter-build.d.ts +60 -0
  196. package/dist/facade/chapter-build.js +1020 -0
  197. package/dist/facade/chapter-build.js.map +1 -0
  198. package/dist/facade/chapter.d.ts +168 -0
  199. package/dist/facade/chapter.js +944 -0
  200. package/dist/facade/chapter.js.map +1 -0
  201. package/dist/facade/digest.d.ts +55 -0
  202. package/dist/facade/digest.js +168 -0
  203. package/dist/facade/digest.js.map +1 -0
  204. package/dist/facade/graph.d.ts +60 -0
  205. package/dist/facade/graph.js +203 -0
  206. package/dist/facade/graph.js.map +1 -0
  207. package/dist/facade/import.d.ts +49 -0
  208. package/dist/facade/import.js +262 -0
  209. package/dist/facade/import.js.map +1 -0
  210. package/dist/facade/index.d.ts +39 -0
  211. package/dist/facade/index.js +171 -0
  212. package/dist/facade/index.js.map +1 -0
  213. package/dist/facade/knowledge-graph-build.d.ts +75 -0
  214. package/dist/facade/knowledge-graph-build.js +897 -0
  215. package/dist/facade/knowledge-graph-build.js.map +1 -0
  216. package/dist/facade/llm-sampling.d.ts +11 -0
  217. package/dist/facade/llm-sampling.js +58 -0
  218. package/dist/facade/llm-sampling.js.map +1 -0
  219. package/dist/facade/types.d.ts +8 -0
  220. package/dist/facade/types.js +1 -0
  221. package/dist/facade/types.js.map +1 -0
  222. package/dist/facade/wiki-graph-archive.d.ts +41 -0
  223. package/dist/facade/wiki-graph-archive.js +130 -0
  224. package/dist/facade/wiki-graph-archive.js.map +1 -0
  225. package/dist/gc/files.d.ts +15 -0
  226. package/dist/gc/files.js +141 -0
  227. package/dist/gc/files.js.map +1 -0
  228. package/dist/gc/index.d.ts +2 -0
  229. package/dist/gc/index.js +5 -0
  230. package/dist/gc/index.js.map +1 -0
  231. package/dist/gc/lock.d.ts +3 -0
  232. package/dist/gc/lock.js +137 -0
  233. package/dist/gc/lock.js.map +1 -0
  234. package/dist/gc/runner.d.ts +9 -0
  235. package/dist/gc/runner.js +129 -0
  236. package/dist/gc/runner.js.map +1 -0
  237. package/dist/gc/tmp-gc.d.ts +5 -0
  238. package/dist/gc/tmp-gc.js +57 -0
  239. package/dist/gc/tmp-gc.js.map +1 -0
  240. package/dist/gc/types.d.ts +24 -0
  241. package/dist/gc/types.js +1 -0
  242. package/dist/gc/types.js.map +1 -0
  243. package/dist/gc.cjs +10041 -0
  244. package/dist/gc.cjs.map +1 -0
  245. package/dist/gc.d.cts +10 -0
  246. package/dist/gc.d.ts +2 -0
  247. package/dist/gc.js +5 -0
  248. package/dist/gc.js.map +1 -0
  249. package/dist/guaranteed/classifier.d.ts +10 -0
  250. package/dist/guaranteed/classifier.js +88 -0
  251. package/dist/guaranteed/classifier.js.map +1 -0
  252. package/dist/guaranteed/errors.d.ts +38 -0
  253. package/dist/guaranteed/errors.js +73 -0
  254. package/dist/guaranteed/errors.js.map +1 -0
  255. package/dist/guaranteed/index.d.ts +7 -0
  256. package/dist/guaranteed/index.js +21 -0
  257. package/dist/guaranteed/index.js.map +1 -0
  258. package/dist/guaranteed/request.d.ts +8 -0
  259. package/dist/guaranteed/request.js +206 -0
  260. package/dist/guaranteed/request.js.map +1 -0
  261. package/dist/guaranteed/response.d.ts +12 -0
  262. package/dist/guaranteed/response.js +98 -0
  263. package/dist/guaranteed/response.js.map +1 -0
  264. package/dist/guaranteed/types.d.ts +20 -0
  265. package/dist/guaranteed/types.js +1 -0
  266. package/dist/guaranteed/types.js.map +1 -0
  267. package/dist/index-B8NNnQ8P.d.ts +424 -0
  268. package/dist/index.cjs +34774 -0
  269. package/dist/index.cjs.map +1 -0
  270. package/dist/index.d.cts +2462 -0
  271. package/dist/index.d.ts +79 -0
  272. package/dist/index.js +168 -0
  273. package/dist/index.js.map +1 -0
  274. package/dist/legacy-sdpub/upgrade.d.ts +7 -0
  275. package/dist/legacy-sdpub/upgrade.js +795 -0
  276. package/dist/legacy-sdpub/upgrade.js.map +1 -0
  277. package/dist/llm/cache.d.ts +13 -0
  278. package/dist/llm/cache.js +35 -0
  279. package/dist/llm/cache.js.map +1 -0
  280. package/dist/llm/client.d.ts +26 -0
  281. package/dist/llm/client.js +572 -0
  282. package/dist/llm/client.js.map +1 -0
  283. package/dist/llm/context.d.ts +22 -0
  284. package/dist/llm/context.js +78 -0
  285. package/dist/llm/context.js.map +1 -0
  286. package/dist/llm/errors.d.ts +7 -0
  287. package/dist/llm/errors.js +12 -0
  288. package/dist/llm/errors.js.map +1 -0
  289. package/dist/llm/index.d.ts +7 -0
  290. package/dist/llm/index.js +17 -0
  291. package/dist/llm/index.js.map +1 -0
  292. package/dist/llm/request-log.d.ts +9 -0
  293. package/dist/llm/request-log.js +35 -0
  294. package/dist/llm/request-log.js.map +1 -0
  295. package/dist/llm/sampling.d.ts +11 -0
  296. package/dist/llm/sampling.js +67 -0
  297. package/dist/llm/sampling.js.map +1 -0
  298. package/dist/llm/types.d.ts +50 -0
  299. package/dist/llm/types.js +1 -0
  300. package/dist/llm/types.js.map +1 -0
  301. package/dist/output/epub/archive.d.ts +9 -0
  302. package/dist/output/epub/archive.js +81 -0
  303. package/dist/output/epub/archive.js.map +1 -0
  304. package/dist/output/epub/book.d.ts +15 -0
  305. package/dist/output/epub/book.js +76 -0
  306. package/dist/output/epub/book.js.map +1 -0
  307. package/dist/output/epub/content.d.ts +9 -0
  308. package/dist/output/epub/content.js +35 -0
  309. package/dist/output/epub/content.js.map +1 -0
  310. package/dist/output/epub/index.d.ts +20 -0
  311. package/dist/output/epub/index.js +14 -0
  312. package/dist/output/epub/index.js.map +1 -0
  313. package/dist/output/epub/model.d.ts +24 -0
  314. package/dist/output/epub/model.js +1 -0
  315. package/dist/output/epub/model.js.map +1 -0
  316. package/dist/output/epub/navigation.d.ts +10 -0
  317. package/dist/output/epub/navigation.js +39 -0
  318. package/dist/output/epub/navigation.js.map +1 -0
  319. package/dist/output/epub/package.d.ts +17 -0
  320. package/dist/output/epub/package.js +29 -0
  321. package/dist/output/epub/package.js.map +1 -0
  322. package/dist/output/epub/shared.d.ts +4 -0
  323. package/dist/output/epub/shared.js +12 -0
  324. package/dist/output/epub/shared.js.map +1 -0
  325. package/dist/output/epub/templates.d.ts +35 -0
  326. package/dist/output/epub/templates.js +26 -0
  327. package/dist/output/epub/templates.js.map +1 -0
  328. package/dist/output/index.d.ts +14 -0
  329. package/dist/output/index.js +11 -0
  330. package/dist/output/index.js.map +1 -0
  331. package/dist/output/plain-text.d.ts +18 -0
  332. package/dist/output/plain-text.js +56 -0
  333. package/dist/output/plain-text.js.map +1 -0
  334. package/dist/progress/index.d.ts +3 -0
  335. package/dist/progress/index.js +14 -0
  336. package/dist/progress/index.js.map +1 -0
  337. package/dist/progress/reporter.d.ts +10 -0
  338. package/dist/progress/reporter.js +79 -0
  339. package/dist/progress/reporter.js.map +1 -0
  340. package/dist/progress/tracker.d.ts +37 -0
  341. package/dist/progress/tracker.js +119 -0
  342. package/dist/progress/tracker.js.map +1 -0
  343. package/dist/progress/types.d.ts +28 -0
  344. package/dist/progress/types.js +1 -0
  345. package/dist/progress/types.js.map +1 -0
  346. package/dist/reader/attention/attention.d.ts +39 -0
  347. package/dist/reader/attention/attention.js +123 -0
  348. package/dist/reader/attention/attention.js.map +1 -0
  349. package/dist/reader/attention/index.d.ts +9 -0
  350. package/dist/reader/attention/index.js +5 -0
  351. package/dist/reader/attention/index.js.map +1 -0
  352. package/dist/reader/attention/wave-reflection.d.ts +21 -0
  353. package/dist/reader/attention/wave-reflection.js +153 -0
  354. package/dist/reader/attention/wave-reflection.js.map +1 -0
  355. package/dist/reader/attention/working-memory.d.ts +28 -0
  356. package/dist/reader/attention/working-memory.js +62 -0
  357. package/dist/reader/attention/working-memory.js.map +1 -0
  358. package/dist/reader/chunk-batch/extract.d.ts +13 -0
  359. package/dist/reader/chunk-batch/extract.js +14 -0
  360. package/dist/reader/chunk-batch/extract.js.map +1 -0
  361. package/dist/reader/chunk-batch/extractor.d.ts +17 -0
  362. package/dist/reader/chunk-batch/extractor.js +337 -0
  363. package/dist/reader/chunk-batch/extractor.js.map +1 -0
  364. package/dist/reader/chunk-batch/fragment-projection.d.ts +34 -0
  365. package/dist/reader/chunk-batch/fragment-projection.js +94 -0
  366. package/dist/reader/chunk-batch/fragment-projection.js.map +1 -0
  367. package/dist/reader/chunk-batch/index.d.ts +12 -0
  368. package/dist/reader/chunk-batch/index.js +13 -0
  369. package/dist/reader/chunk-batch/index.js.map +1 -0
  370. package/dist/reader/chunk-batch/language.d.ts +9 -0
  371. package/dist/reader/chunk-batch/language.js +23 -0
  372. package/dist/reader/chunk-batch/language.js.map +1 -0
  373. package/dist/reader/chunk-batch/parser.d.ts +94 -0
  374. package/dist/reader/chunk-batch/parser.js +640 -0
  375. package/dist/reader/chunk-batch/parser.js.map +1 -0
  376. package/dist/reader/chunk-batch/prompt-templates.d.ts +6 -0
  377. package/dist/reader/chunk-batch/prompt-templates.js +11 -0
  378. package/dist/reader/chunk-batch/prompt-templates.js.map +1 -0
  379. package/dist/reader/chunk-batch/types.d.ts +85 -0
  380. package/dist/reader/chunk-batch/types.js +1 -0
  381. package/dist/reader/chunk-batch/types.js.map +1 -0
  382. package/dist/reader/index.d.ts +13 -0
  383. package/dist/reader/index.js +7 -0
  384. package/dist/reader/index.js.map +1 -0
  385. package/dist/reader/reader.d.ts +37 -0
  386. package/dist/reader/reader.js +82 -0
  387. package/dist/reader/reader.js.map +1 -0
  388. package/dist/reader/segment/index.d.ts +2 -0
  389. package/dist/reader/segment/index.js +5 -0
  390. package/dist/reader/segment/index.js.map +1 -0
  391. package/dist/reader/segment/intl-segmenter.d.ts +5 -0
  392. package/dist/reader/segment/intl-segmenter.js +102 -0
  393. package/dist/reader/segment/intl-segmenter.js.map +1 -0
  394. package/dist/reader/segment/segment.d.ts +5 -0
  395. package/dist/reader/segment/segment.js +9 -0
  396. package/dist/reader/segment/segment.js.map +1 -0
  397. package/dist/reader/segment/types.d.ts +14 -0
  398. package/dist/reader/segment/types.js +1 -0
  399. package/dist/reader/segment/types.js.map +1 -0
  400. package/dist/reader/types.d.ts +29 -0
  401. package/dist/reader/types.js +1 -0
  402. package/dist/reader/types.js.map +1 -0
  403. package/dist/serial.d.ts +89 -0
  404. package/dist/serial.js +476 -0
  405. package/dist/serial.js.map +1 -0
  406. package/dist/source/adapter.d.ts +15 -0
  407. package/dist/source/adapter.js +1 -0
  408. package/dist/source/adapter.js.map +1 -0
  409. package/dist/source/epub/archive.d.ts +27 -0
  410. package/dist/source/epub/archive.js +189 -0
  411. package/dist/source/epub/archive.js.map +1 -0
  412. package/dist/source/epub/content.d.ts +22 -0
  413. package/dist/source/epub/content.js +183 -0
  414. package/dist/source/epub/content.js.map +1 -0
  415. package/dist/source/epub/document.d.ts +55 -0
  416. package/dist/source/epub/document.js +179 -0
  417. package/dist/source/epub/document.js.map +1 -0
  418. package/dist/source/epub/index.d.ts +10 -0
  419. package/dist/source/epub/index.js +6 -0
  420. package/dist/source/epub/index.js.map +1 -0
  421. package/dist/source/epub/navigation.d.ts +16 -0
  422. package/dist/source/epub/navigation.js +215 -0
  423. package/dist/source/epub/navigation.js.map +1 -0
  424. package/dist/source/epub/package.d.ts +33 -0
  425. package/dist/source/epub/package.js +237 -0
  426. package/dist/source/epub/package.js.map +1 -0
  427. package/dist/source/epub/xml.d.ts +16 -0
  428. package/dist/source/epub/xml.js +111 -0
  429. package/dist/source/epub/xml.js.map +1 -0
  430. package/dist/source/index.d.ts +12 -0
  431. package/dist/source/index.js +32 -0
  432. package/dist/source/index.js.map +1 -0
  433. package/dist/source/meta.d.ts +30 -0
  434. package/dist/source/meta.js +22 -0
  435. package/dist/source/meta.js.map +1 -0
  436. package/dist/source/plain-text.d.ts +16 -0
  437. package/dist/source/plain-text.js +86 -0
  438. package/dist/source/plain-text.js.map +1 -0
  439. package/dist/source/toc.d.ts +16 -0
  440. package/dist/source/toc.js +17 -0
  441. package/dist/source/toc.js.map +1 -0
  442. package/dist/source/types.d.ts +16 -0
  443. package/dist/source/types.js +1 -0
  444. package/dist/source/types.js.map +1 -0
  445. package/dist/topology/grouping.d.ts +15 -0
  446. package/dist/topology/grouping.js +18 -0
  447. package/dist/topology/grouping.js.map +1 -0
  448. package/dist/topology/index.d.ts +21 -0
  449. package/dist/topology/index.js +5 -0
  450. package/dist/topology/index.js.map +1 -0
  451. package/dist/topology/resource-segmentation.d.ts +13 -0
  452. package/dist/topology/resource-segmentation.js +111 -0
  453. package/dist/topology/resource-segmentation.js.map +1 -0
  454. package/dist/topology/segment-incision.d.ts +18 -0
  455. package/dist/topology/segment-incision.js +197 -0
  456. package/dist/topology/segment-incision.js.map +1 -0
  457. package/dist/topology/snake-detector.d.ts +13 -0
  458. package/dist/topology/snake-detector.js +520 -0
  459. package/dist/topology/snake-detector.js.map +1 -0
  460. package/dist/topology/snake-graph-builder.d.ts +14 -0
  461. package/dist/topology/snake-graph-builder.js +76 -0
  462. package/dist/topology/snake-graph-builder.js.map +1 -0
  463. package/dist/topology/topology.d.ts +29 -0
  464. package/dist/topology/topology.js +348 -0
  465. package/dist/topology/topology.js.map +1 -0
  466. package/dist/topology/weights.d.ts +10 -0
  467. package/dist/topology/weights.js +84 -0
  468. package/dist/topology/weights.js.map +1 -0
  469. package/dist/types-FVIqiLC9.d.cts +24 -0
  470. package/dist/utils/async-semaphore.d.ts +7 -0
  471. package/dist/utils/async-semaphore.js +40 -0
  472. package/dist/utils/async-semaphore.js.map +1 -0
  473. package/dist/utils/enum.d.ts +5 -0
  474. package/dist/utils/enum.js +18 -0
  475. package/dist/utils/enum.js.map +1 -0
  476. package/dist/utils/hash.d.ts +3 -0
  477. package/dist/utils/hash.js +132 -0
  478. package/dist/utils/hash.js.map +1 -0
  479. package/dist/utils/node-error.d.ts +4 -0
  480. package/dist/utils/node-error.js +59 -0
  481. package/dist/utils/node-error.js.map +1 -0
  482. package/dist/wikg/archive-uri.d.ts +1 -0
  483. package/dist/wikg/archive-uri.js +37 -0
  484. package/dist/wikg/archive-uri.js.map +1 -0
  485. package/dist/wikg/archive.d.ts +28 -0
  486. package/dist/wikg/archive.js +496 -0
  487. package/dist/wikg/archive.js.map +1 -0
  488. package/dist/wikg/index.d.ts +31 -0
  489. package/dist/wikg/index.js +60 -0
  490. package/dist/wikg/index.js.map +1 -0
  491. package/dist/wikg/wikg-coordinator.d.ts +45 -0
  492. package/dist/wikg/wikg-coordinator.js +1687 -0
  493. package/dist/wikg/wikg-coordinator.js.map +1 -0
  494. package/dist/wikg/wiki-graph-archive-file.d.ts +42 -0
  495. package/dist/wikg/wiki-graph-archive-file.js +78 -0
  496. package/dist/wikg/wiki-graph-archive-file.js.map +1 -0
  497. package/dist/wikilink/index.d.ts +10 -0
  498. package/dist/wikilink/index.js +7 -0
  499. package/dist/wikilink/index.js.map +1 -0
  500. package/dist/wikilink/relation-discovery.d.ts +31 -0
  501. package/dist/wikilink/relation-discovery.js +477 -0
  502. package/dist/wikilink/relation-discovery.js.map +1 -0
  503. package/dist/wikilink/types.d.ts +23 -0
  504. package/dist/wikilink/types.js +1 -0
  505. package/dist/wikilink/types.js.map +1 -0
  506. package/dist/wikilink/window.d.ts +7 -0
  507. package/dist/wikilink/window.js +53 -0
  508. package/dist/wikilink/window.js.map +1 -0
  509. package/dist/wikimatch/enrichment.d.ts +10 -0
  510. package/dist/wikimatch/enrichment.js +55 -0
  511. package/dist/wikimatch/enrichment.js.map +1 -0
  512. package/dist/wikimatch/index.d.ts +16 -0
  513. package/dist/wikimatch/index.js +66 -0
  514. package/dist/wikimatch/index.js.map +1 -0
  515. package/dist/wikimatch/option-narrowing.d.ts +17 -0
  516. package/dist/wikimatch/option-narrowing.js +208 -0
  517. package/dist/wikimatch/option-narrowing.js.map +1 -0
  518. package/dist/wikimatch/options.d.ts +14 -0
  519. package/dist/wikimatch/options.js +155 -0
  520. package/dist/wikimatch/options.js.map +1 -0
  521. package/dist/wikimatch/policy-judge.d.ts +17 -0
  522. package/dist/wikimatch/policy-judge.js +430 -0
  523. package/dist/wikimatch/policy-judge.js.map +1 -0
  524. package/dist/wikimatch/range-suppression.d.ts +9 -0
  525. package/dist/wikimatch/range-suppression.js +27 -0
  526. package/dist/wikimatch/range-suppression.js.map +1 -0
  527. package/dist/wikimatch/surface-screening.d.ts +16 -0
  528. package/dist/wikimatch/surface-screening.js +168 -0
  529. package/dist/wikimatch/surface-screening.js.map +1 -0
  530. package/dist/wikimatch/surface-window.d.ts +6 -0
  531. package/dist/wikimatch/surface-window.js +44 -0
  532. package/dist/wikimatch/surface-window.js.map +1 -0
  533. package/dist/wikimatch/types.d.ts +151 -0
  534. package/dist/wikimatch/types.js +1 -0
  535. package/dist/wikimatch/types.js.map +1 -0
  536. package/dist/wikimatch/wikispine.d.ts +43 -0
  537. package/dist/wikimatch/wikispine.js +399 -0
  538. package/dist/wikimatch/wikispine.js.map +1 -0
  539. package/dist/wikimatch/window.d.ts +6 -0
  540. package/dist/wikimatch/window.js +83 -0
  541. package/dist/wikimatch/window.js.map +1 -0
  542. package/dist/wikimatch/words.d.ts +16 -0
  543. package/dist/wikimatch/words.js +66 -0
  544. package/dist/wikimatch/words.js.map +1 -0
  545. package/dist/wikipage/cache.d.ts +18 -0
  546. package/dist/wikipage/cache.js +404 -0
  547. package/dist/wikipage/cache.js.map +1 -0
  548. package/dist/wikipage/fetch-log.d.ts +17 -0
  549. package/dist/wikipage/fetch-log.js +143 -0
  550. package/dist/wikipage/fetch-log.js.map +1 -0
  551. package/dist/wikipage/index.d.ts +14 -0
  552. package/dist/wikipage/index.js +17 -0
  553. package/dist/wikipage/index.js.map +1 -0
  554. package/dist/wikipage/normalizer.d.ts +14 -0
  555. package/dist/wikipage/normalizer.js +147 -0
  556. package/dist/wikipage/normalizer.js.map +1 -0
  557. package/dist/wikipage/rate-limiter.d.ts +13 -0
  558. package/dist/wikipage/rate-limiter.js +84 -0
  559. package/dist/wikipage/rate-limiter.js.map +1 -0
  560. package/dist/wikipage/resolver.d.ts +26 -0
  561. package/dist/wikipage/resolver.js +325 -0
  562. package/dist/wikipage/resolver.js.map +1 -0
  563. package/dist/wikipage/types.d.ts +96 -0
  564. package/dist/wikipage/types.js +1 -0
  565. package/dist/wikipage/types.js.map +1 -0
  566. package/dist/wikipage/wikimedia-client.d.ts +48 -0
  567. package/dist/wikipage/wikimedia-client.js +397 -0
  568. package/dist/wikipage/wikimedia-client.js.map +1 -0
  569. package/dist/worker-BgQ0Xl8T.d.cts +181 -0
  570. package/dist/worker.cjs +5259 -0
  571. package/dist/worker.cjs.map +1 -0
  572. package/dist/worker.d.cts +2 -0
  573. package/dist/worker.d.ts +2 -0
  574. package/dist/worker.js +5 -0
  575. package/dist/worker.js.map +1 -0
  576. package/package.json +78 -0
@@ -0,0 +1,555 @@
1
+ import { createHash } from "crypto";
2
+ import {
3
+ getNumber
4
+ } from "../../document/database.js";
5
+ import {
6
+ createSearchTokenPlan,
7
+ hasSearchTokens,
8
+ listSearchPlanTerms,
9
+ normalizeSearchText
10
+ } from "./search-tokenizer.js";
11
+ const TEXT_SENTENCE_KIND = {
12
+ source: 1,
13
+ summary: 2
14
+ };
15
+ const SEARCH_OBJECT_PROPERTY_OWNER_KIND = {
16
+ chapter: 1,
17
+ chunk: 2,
18
+ entity: 3
19
+ };
20
+ const SEARCH_OBJECT_PROPERTY_KIND = {
21
+ title: 1,
22
+ label: 1,
23
+ content: 2,
24
+ surface: 1
25
+ };
26
+ const SEARCH_INDEX_VERSION = "3";
27
+ const SEARCH_INDEX_FTS_HIT_LIMIT = 32e3;
28
+ const FTS5_RANK_SCORE_SCALE = 1e6;
29
+ const TIER_WEIGHTS = [1, 0.45, 0.08];
30
+ async function readArchiveIndexSettings(document) {
31
+ return await document.readDatabase(async (database) => {
32
+ const row = await database.queryOne(
33
+ `
34
+ SELECT fts_embedded
35
+ FROM archive_index_settings
36
+ WHERE id = 1
37
+ `,
38
+ void 0,
39
+ (value) => ({
40
+ ftsEmbedded: getNumber(value, "fts_embedded") !== 0
41
+ })
42
+ );
43
+ return row ?? { ftsEmbedded: false };
44
+ });
45
+ }
46
+ async function setFtsIndexEmbedded(document, embedded) {
47
+ await document.readDatabase(async (database) => {
48
+ await database.run(
49
+ `
50
+ INSERT INTO archive_index_settings(id, fts_embedded)
51
+ VALUES (1, ?)
52
+ ON CONFLICT(id)
53
+ DO UPDATE SET fts_embedded = excluded.fts_embedded
54
+ `,
55
+ [embedded ? 1 : 0]
56
+ );
57
+ });
58
+ }
59
+ async function isSearchIndexCurrent(document, input) {
60
+ return await readSearchIndexStatus(document, input) === "current";
61
+ }
62
+ async function readSearchIndexStatus(document, input) {
63
+ const fingerprint = input === void 0 ? void 0 : createSearchIndexFingerprint(input);
64
+ try {
65
+ return await document.readSearchIndexDatabase(async (database) => {
66
+ const indexedFingerprint = await readSearchIndexFingerprintFromDatabase(database);
67
+ if (indexedFingerprint === void 0) {
68
+ return "dirty";
69
+ }
70
+ return fingerprint === void 0 || indexedFingerprint === fingerprint ? "current" : "dirty";
71
+ });
72
+ } catch (error) {
73
+ if (isMissingSearchIndexError(error)) {
74
+ return "missing";
75
+ }
76
+ throw error;
77
+ }
78
+ }
79
+ async function ensureSearchIndex(document, input, progress) {
80
+ const chaptersRevision = await document.serials.getChaptersRevision();
81
+ await document.writeSearchIndexDatabase(async (database) => {
82
+ const fingerprint = createSearchIndexFingerprint(input);
83
+ const indexedFingerprint = await readSearchIndexFingerprintFromDatabase(database);
84
+ if (indexedFingerprint === fingerprint) {
85
+ return;
86
+ }
87
+ await database.transaction(async () => {
88
+ await progress?.({ phase: "clearing" });
89
+ await database.run("DELETE FROM text_sentence_fts");
90
+ await database.run("DELETE FROM search_object_properties_fts");
91
+ await database.run("DELETE FROM search_object_properties_records");
92
+ await database.run("DELETE FROM search_index_state");
93
+ let textDone = 0;
94
+ for (const record of input.textSentences) {
95
+ const plan = createSearchTokenPlan(record.text);
96
+ const rowId = await insertTextSentenceRecord(database, record);
97
+ await insertFtsRecord(database, "text_sentence_fts", rowId, plan);
98
+ textDone += 1;
99
+ await progress?.({
100
+ done: textDone,
101
+ phase: "indexing-text",
102
+ total: input.textSentences.length,
103
+ unit: "sentence"
104
+ });
105
+ }
106
+ let objectDone = 0;
107
+ for (const record of input.objectProperties) {
108
+ const plan = createSearchTokenPlan(record.text);
109
+ const rowId = await insertSearchObjectPropertyRecord(database, record);
110
+ await insertFtsRecord(
111
+ database,
112
+ "search_object_properties_fts",
113
+ rowId,
114
+ plan
115
+ );
116
+ objectDone += 1;
117
+ await progress?.({
118
+ done: objectDone,
119
+ phase: "indexing-objects",
120
+ total: input.objectProperties.length,
121
+ unit: "object"
122
+ });
123
+ }
124
+ await progress?.({ phase: "finalizing" });
125
+ await database.run(
126
+ `
127
+ INSERT INTO search_index_state(key, value)
128
+ VALUES ('version', ?)
129
+ `,
130
+ [SEARCH_INDEX_VERSION]
131
+ );
132
+ await database.run(
133
+ `
134
+ INSERT INTO search_index_state(key, value)
135
+ VALUES ('fingerprint', ?)
136
+ `,
137
+ [fingerprint]
138
+ );
139
+ await database.run(
140
+ `
141
+ INSERT INTO search_index_state(key, value)
142
+ VALUES ('chaptersRevision', ?)
143
+ `,
144
+ [String(chaptersRevision)]
145
+ );
146
+ });
147
+ });
148
+ }
149
+ async function querySearchIndex(document, query, options = {}) {
150
+ const plan = createSearchTokenPlan(query);
151
+ if (!hasSearchTokens(plan)) {
152
+ return void 0;
153
+ }
154
+ const terms = listSearchPlanTerms(plan);
155
+ return await document.readSearchIndexDatabase(async (database) => {
156
+ const tierQueries = createTierQueries(query, plan, options.match ?? "any");
157
+ const objectHitLimit = options.objectHitLimit ?? SEARCH_INDEX_FTS_HIT_LIMIT;
158
+ const textHitLimit = options.textHitLimit ?? SEARCH_INDEX_FTS_HIT_LIMIT;
159
+ const queriesObjects = shouldQueryObjects(options.types);
160
+ const queriesText = createTextKindFilter(options.types).length > 0;
161
+ const objectHitsByKey = /* @__PURE__ */ new Map();
162
+ const textHitsByKey = /* @__PURE__ */ new Map();
163
+ for (const tierQuery of tierQueries) {
164
+ if (tierQuery.matchExpression === "") {
165
+ continue;
166
+ }
167
+ const objectHitRemaining = Math.max(
168
+ 0,
169
+ objectHitLimit - objectHitsByKey.size
170
+ );
171
+ const textHitRemaining = Math.max(0, textHitLimit - textHitsByKey.size);
172
+ if ((!queriesObjects || objectHitRemaining <= 0) && (!queriesText || textHitRemaining <= 0)) {
173
+ break;
174
+ }
175
+ const [objectRows, textRows] = await Promise.all([
176
+ queryObjectRows(database, tierQuery.matchExpression, {
177
+ ...options,
178
+ objectHitLimit: objectHitRemaining
179
+ }),
180
+ queryTextRows(database, tierQuery.matchExpression, {
181
+ ...options,
182
+ textHitLimit: textHitRemaining
183
+ })
184
+ ]);
185
+ for (const hit of objectRows) {
186
+ const key = createObjectHitKey(hit);
187
+ if (!objectHitsByKey.has(key)) {
188
+ objectHitsByKey.set(key, hit);
189
+ }
190
+ }
191
+ for (const hit of textRows) {
192
+ const key = createTextHitKey(hit);
193
+ if (!textHitsByKey.has(key)) {
194
+ textHitsByKey.set(key, hit);
195
+ }
196
+ }
197
+ if ((!queriesObjects || objectHitsByKey.size >= objectHitLimit) && (!queriesText || textHitsByKey.size >= textHitLimit)) {
198
+ break;
199
+ }
200
+ }
201
+ return {
202
+ objectHits: [...objectHitsByKey.values()],
203
+ terms,
204
+ textHits: [...textHitsByKey.values()]
205
+ };
206
+ });
207
+ }
208
+ async function queryObjectRows(database, matchExpression, options) {
209
+ if (!shouldQueryObjects(options.types) || options.objectHitLimit === 0) {
210
+ return [];
211
+ }
212
+ return await database.queryAll(
213
+ `
214
+ SELECT
215
+ r.owner_kind AS owner_kind,
216
+ r.owner_id AS owner_id,
217
+ r.property_kind AS property_kind,
218
+ r.chapter_id AS chapter_id,
219
+ bm25(search_object_properties_fts, ?, ?, ?) AS rank
220
+ FROM search_object_properties_fts
221
+ JOIN search_object_properties_records AS r
222
+ ON r.id = search_object_properties_fts.rowid
223
+ WHERE search_object_properties_fts MATCH ?
224
+ ${createChapterSql(options.chapters)}
225
+ ORDER BY rank ASC, r.chapter_id, r.owner_kind, r.owner_id, r.property_kind
226
+ ${createLimitSql(options.objectHitLimit)}
227
+ `,
228
+ [
229
+ ...TIER_WEIGHTS,
230
+ matchExpression,
231
+ ...createChapterParams(options.chapters),
232
+ ...createLimitParams(options.objectHitLimit)
233
+ ],
234
+ (row) => ({
235
+ ownerId: String(row.owner_id),
236
+ ownerKind: getNumber(row, "owner_kind"),
237
+ propertyKind: getNumber(row, "property_kind"),
238
+ score: rankToScore(getNumber(row, "rank")),
239
+ ...row.chapter_id === null ? {} : { chapterId: getNumber(row, "chapter_id") }
240
+ })
241
+ );
242
+ }
243
+ async function queryTextRows(database, matchExpression, options) {
244
+ const kinds = createTextKindFilter(options.types);
245
+ if (kinds.length === 0) {
246
+ return [];
247
+ }
248
+ if (options.textHitLimit === 0) {
249
+ return [];
250
+ }
251
+ const after = options.textAfter;
252
+ return await database.queryAll(
253
+ `
254
+ SELECT
255
+ kind,
256
+ chapter_id,
257
+ sentence_index,
258
+ words_count,
259
+ rank
260
+ FROM (
261
+ SELECT
262
+ r.kind AS kind,
263
+ r.chapter_id AS chapter_id,
264
+ r.sentence_index AS sentence_index,
265
+ r.words_count AS words_count,
266
+ bm25(text_sentence_fts, ?, ?, ?) AS rank
267
+ FROM text_sentence_fts
268
+ JOIN text_sentence_records AS r
269
+ ON r.id = text_sentence_fts.rowid
270
+ WHERE text_sentence_fts MATCH ?
271
+ AND r.kind IN (${kinds.map(() => "?").join(", ")})
272
+ ${createChapterSql(options.chapters)}
273
+ )
274
+ ${after === void 0 ? "" : `
275
+ WHERE (
276
+ rank > ?
277
+ OR (rank = ? AND chapter_id > ?)
278
+ OR (rank = ? AND chapter_id = ? AND sentence_index > ?)
279
+ OR (
280
+ rank = ?
281
+ AND chapter_id = ?
282
+ AND sentence_index = ?
283
+ AND kind > ?
284
+ )
285
+ )
286
+ `}
287
+ ORDER BY rank ASC, chapter_id, sentence_index, kind
288
+ ${createLimitSql(options.textHitLimit)}
289
+ `,
290
+ [
291
+ ...TIER_WEIGHTS,
292
+ matchExpression,
293
+ ...kinds,
294
+ ...createChapterParams(options.chapters),
295
+ ...after === void 0 ? [] : [
296
+ after.rank,
297
+ after.rank,
298
+ after.chapterId,
299
+ after.rank,
300
+ after.chapterId,
301
+ after.sentenceIndex,
302
+ after.rank,
303
+ after.chapterId,
304
+ after.sentenceIndex,
305
+ after.kind
306
+ ],
307
+ ...createLimitParams(options.textHitLimit)
308
+ ],
309
+ (row) => {
310
+ const rank = getNumber(row, "rank");
311
+ return {
312
+ chapterId: getNumber(row, "chapter_id"),
313
+ kind: getNumber(row, "kind"),
314
+ rank,
315
+ score: rankToScore(rank),
316
+ sentenceIndex: getNumber(row, "sentence_index"),
317
+ wordsCount: getNumber(row, "words_count")
318
+ };
319
+ }
320
+ );
321
+ }
322
+ function createTierQueries(query, plan, match) {
323
+ if (match === "all") {
324
+ return createAllMatchTierQueries(query);
325
+ }
326
+ return [
327
+ {
328
+ matchExpression: createMatchExpression([
329
+ { column: "tier1", tokens: plan.tier1.map((token) => token.encoded) }
330
+ ])
331
+ },
332
+ {
333
+ matchExpression: createMatchExpression([
334
+ { column: "tier1", tokens: plan.tier1.map((token) => token.encoded) },
335
+ { column: "tier2", tokens: plan.tier2.map((token) => token.encoded) }
336
+ ])
337
+ },
338
+ {
339
+ matchExpression: createMatchExpression([
340
+ { column: "tier1", tokens: plan.tier1.map((token) => token.encoded) },
341
+ { column: "tier2", tokens: plan.tier2.map((token) => token.encoded) },
342
+ { column: "tier3", tokens: plan.tier3.map((token) => token.encoded) }
343
+ ])
344
+ }
345
+ ];
346
+ }
347
+ function createAllMatchTierQueries(query) {
348
+ const termPlans = normalizeSearchText(query).split(/\s+/u).map((term) => createSearchTokenPlan(term)).filter(hasSearchTokens);
349
+ const createExpression = (selectTokens) => termPlans.map((termPlan) => {
350
+ const tokens = [...new Set(selectTokens(termPlan))];
351
+ return tokens.length === 0 ? "" : `(${tokens.join(" OR ")})`;
352
+ }).filter((term) => term !== "").join(" AND ");
353
+ return [
354
+ {
355
+ matchExpression: createExpression(
356
+ (termPlan) => termPlan.tier1.map((token) => `tier1:${escapeFtsToken(token.encoded)}`)
357
+ )
358
+ },
359
+ {
360
+ matchExpression: createExpression((termPlan) => [
361
+ ...termPlan.tier1.map(
362
+ (token) => `tier1:${escapeFtsToken(token.encoded)}`
363
+ ),
364
+ ...termPlan.tier2.map(
365
+ (token) => `tier2:${escapeFtsToken(token.encoded)}`
366
+ )
367
+ ])
368
+ },
369
+ {
370
+ matchExpression: createExpression((termPlan) => [
371
+ ...termPlan.tier1.map(
372
+ (token) => `tier1:${escapeFtsToken(token.encoded)}`
373
+ ),
374
+ ...termPlan.tier2.map(
375
+ (token) => `tier2:${escapeFtsToken(token.encoded)}`
376
+ ),
377
+ ...termPlan.tier3.map(
378
+ (token) => `tier3:${escapeFtsToken(token.encoded)}`
379
+ )
380
+ ])
381
+ }
382
+ ];
383
+ }
384
+ function createMatchExpression(groups) {
385
+ return groups.map((group) => ({
386
+ ...group,
387
+ tokens: [...new Set(group.tokens)]
388
+ })).filter((group) => group.tokens.length > 0).map(
389
+ (group) => `${group.column}:(${group.tokens.map(escapeFtsToken).join(" OR ")})`
390
+ ).join(" OR ");
391
+ }
392
+ function escapeFtsToken(token) {
393
+ return `"${token.replaceAll('"', '""')}"`;
394
+ }
395
+ async function insertTextSentenceRecord(database, record) {
396
+ const rowId = await database.queryOne(
397
+ `
398
+ SELECT id
399
+ FROM text_sentence_records
400
+ WHERE kind = ? AND chapter_id = ? AND sentence_index = ?
401
+ `,
402
+ [record.kind, record.chapterId, record.sentenceIndex],
403
+ (row) => getNumber(row, "id")
404
+ );
405
+ if (rowId !== void 0) {
406
+ return rowId;
407
+ }
408
+ await database.run(
409
+ `
410
+ INSERT INTO text_sentence_records (
411
+ kind, chapter_id, sentence_index, words_count, byte_offset, byte_length
412
+ )
413
+ VALUES (?, ?, ?, ?, 0, 0)
414
+ `,
415
+ [record.kind, record.chapterId, record.sentenceIndex, record.wordsCount]
416
+ );
417
+ return await database.getLastInsertRowId();
418
+ }
419
+ async function insertSearchObjectPropertyRecord(database, record) {
420
+ await database.run(
421
+ `
422
+ INSERT INTO search_object_properties_records (
423
+ owner_kind, owner_id, property_kind, chapter_id
424
+ )
425
+ VALUES (?, ?, ?, ?)
426
+ `,
427
+ [
428
+ record.ownerKind,
429
+ record.ownerId,
430
+ record.propertyKind,
431
+ record.chapterId ?? null
432
+ ]
433
+ );
434
+ return await database.getLastInsertRowId();
435
+ }
436
+ async function insertFtsRecord(database, table, rowId, plan) {
437
+ await database.run(
438
+ `
439
+ INSERT INTO ${table}(rowid, tier1, tier2, tier3)
440
+ VALUES (?, ?, ?, ?)
441
+ `,
442
+ [
443
+ rowId,
444
+ serializeTokens(plan.tier1),
445
+ serializeTokens(plan.tier2),
446
+ serializeTokens(plan.tier3)
447
+ ]
448
+ );
449
+ }
450
+ function createSearchIndexFingerprint(input) {
451
+ const hash = createHash("sha256");
452
+ for (const record of input.textSentences) {
453
+ hash.update("text");
454
+ hash.update("\0");
455
+ hash.update(String(record.kind));
456
+ hash.update("\0");
457
+ hash.update(String(record.chapterId));
458
+ hash.update("\0");
459
+ hash.update(String(record.sentenceIndex));
460
+ hash.update("\0");
461
+ hash.update(record.text);
462
+ hash.update("\0");
463
+ }
464
+ for (const record of input.objectProperties) {
465
+ hash.update("object-property");
466
+ hash.update("\0");
467
+ hash.update(String(record.ownerKind));
468
+ hash.update("\0");
469
+ hash.update(record.ownerId);
470
+ hash.update("\0");
471
+ hash.update(String(record.propertyKind));
472
+ hash.update("\0");
473
+ hash.update(String(record.chapterId ?? ""));
474
+ hash.update("\0");
475
+ hash.update(record.text);
476
+ hash.update("\0");
477
+ }
478
+ return hash.digest("hex");
479
+ }
480
+ async function readSearchIndexFingerprintFromDatabase(database) {
481
+ return await database.queryOne(
482
+ `
483
+ SELECT value
484
+ FROM search_index_state
485
+ WHERE key = 'fingerprint'
486
+ `,
487
+ void 0,
488
+ (row) => String(row.value)
489
+ );
490
+ }
491
+ function isMissingSearchIndexError(error) {
492
+ const code = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
493
+ return code === "SQLITE_CANTOPEN" || error instanceof Error && (error.message.includes("Archive SQLite entry is missing: fts.db") || error.message.includes("no such table: search_index_state"));
494
+ }
495
+ function serializeTokens(tokens) {
496
+ return tokens.map((token) => token.encoded).join(" ");
497
+ }
498
+ function createChapterSql(chapters) {
499
+ return chapters === void 0 || chapters.length === 0 ? "" : `AND r.chapter_id IN (${chapters.map(() => "?").join(", ")})`;
500
+ }
501
+ function createChapterParams(chapters) {
502
+ return chapters === void 0 ? [] : [...chapters];
503
+ }
504
+ function createLimitSql(limit) {
505
+ return limit === void 0 ? "" : "LIMIT ?";
506
+ }
507
+ function createLimitParams(limit) {
508
+ return limit === void 0 ? [] : [limit];
509
+ }
510
+ function shouldQueryObjects(types) {
511
+ return types === void 0 || types === null || types.includes("chapter") || types.includes("chapter-title") || types.includes("node") || types.includes("entity");
512
+ }
513
+ function createTextKindFilter(types) {
514
+ if (types === void 0 || types === null) {
515
+ return [TEXT_SENTENCE_KIND.summary, TEXT_SENTENCE_KIND.source];
516
+ }
517
+ const kinds = [];
518
+ if (types.includes("summary")) {
519
+ kinds.push(TEXT_SENTENCE_KIND.summary);
520
+ }
521
+ if (types.includes("source")) {
522
+ kinds.push(TEXT_SENTENCE_KIND.source);
523
+ }
524
+ return kinds;
525
+ }
526
+ function rankToScore(rank) {
527
+ const relevance = Math.max(0, -rank) * FTS5_RANK_SCORE_SCALE;
528
+ return relevance / (1 + relevance);
529
+ }
530
+ function createObjectHitKey(hit) {
531
+ return [
532
+ hit.ownerKind,
533
+ hit.ownerId,
534
+ hit.propertyKind,
535
+ hit.chapterId ?? ""
536
+ ].join(":");
537
+ }
538
+ function createTextHitKey(hit) {
539
+ return [hit.kind, hit.chapterId, hit.sentenceIndex].join(":");
540
+ }
541
+ export {
542
+ SEARCH_INDEX_FTS_HIT_LIMIT,
543
+ SEARCH_OBJECT_PROPERTY_KIND,
544
+ SEARCH_OBJECT_PROPERTY_OWNER_KIND,
545
+ TEXT_SENTENCE_KIND,
546
+ createSearchIndexFingerprint,
547
+ ensureSearchIndex,
548
+ isSearchIndexCurrent,
549
+ querySearchIndex,
550
+ readArchiveIndexSettings,
551
+ readSearchIndexFingerprintFromDatabase,
552
+ readSearchIndexStatus,
553
+ setFtsIndexEmbedded
554
+ };
555
+ //# sourceMappingURL=search-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/archive/search-index/search-index.ts"],"sourcesContent":["import { createHash } from \"crypto\";\n\nimport {\n getNumber,\n type Database,\n type SqlBindValue,\n} from \"../../document/database.js\";\nimport type { Document, ReadonlyDocument } from \"../../document/index.js\";\n\nimport {\n createSearchTokenPlan,\n hasSearchTokens,\n listSearchPlanTerms,\n normalizeSearchText,\n type SearchTokenPlan,\n} from \"./search-tokenizer.js\";\nimport type {\n ArchiveFindMatch,\n ArchiveFindObjectType,\n} from \"../query/archive-view.js\";\n\nexport const TEXT_SENTENCE_KIND = {\n source: 1,\n summary: 2,\n} as const;\n\nexport type TextSentenceKind =\n (typeof TEXT_SENTENCE_KIND)[keyof typeof TEXT_SENTENCE_KIND];\n\nexport const SEARCH_OBJECT_PROPERTY_OWNER_KIND = {\n chapter: 1,\n chunk: 2,\n entity: 3,\n} as const;\n\nexport type SearchObjectPropertyOwnerKind =\n (typeof SEARCH_OBJECT_PROPERTY_OWNER_KIND)[keyof typeof SEARCH_OBJECT_PROPERTY_OWNER_KIND];\n\nexport const SEARCH_OBJECT_PROPERTY_KIND = {\n title: 1,\n label: 1,\n content: 2,\n surface: 1,\n} as const;\n\nexport type SearchObjectPropertyKind =\n (typeof SEARCH_OBJECT_PROPERTY_KIND)[keyof typeof SEARCH_OBJECT_PROPERTY_KIND];\n\nexport interface TextSentenceRecordInput {\n readonly chapterId: number;\n readonly kind: TextSentenceKind;\n readonly sentenceIndex: number;\n readonly text: string;\n readonly wordsCount: number;\n}\n\nexport interface SearchObjectPropertyRecordInput {\n readonly chapterId?: number;\n readonly ownerId: string;\n readonly ownerKind: SearchObjectPropertyOwnerKind;\n readonly propertyKind: SearchObjectPropertyKind;\n readonly text: string;\n}\n\nexport interface SearchIndexInput {\n readonly objectProperties: readonly SearchObjectPropertyRecordInput[];\n readonly textSentences: readonly TextSentenceRecordInput[];\n}\n\nexport type SearchIndexProgressPhase =\n | \"checking\"\n | \"clearing\"\n | \"collecting\"\n | \"finalizing\"\n | \"indexing-objects\"\n | \"indexing-text\";\n\nexport interface SearchIndexProgressEvent {\n readonly done?: number;\n readonly phase: SearchIndexProgressPhase;\n readonly total?: number;\n readonly unit?: \"chapter\" | \"object\" | \"sentence\";\n}\n\nexport type SearchIndexProgressReporter = (\n event: SearchIndexProgressEvent,\n) => void | Promise<void>;\n\nexport type SearchIndexStatus = \"current\" | \"dirty\" | \"missing\";\n\nexport interface SearchIndexTextHit {\n readonly chapterId: number;\n readonly kind: TextSentenceKind;\n readonly rank: number;\n readonly score: number;\n readonly sentenceIndex: number;\n readonly wordsCount: number;\n}\n\nexport interface SearchIndexObjectHit {\n readonly chapterId?: number;\n readonly ownerId: string;\n readonly ownerKind: SearchObjectPropertyOwnerKind;\n readonly propertyKind: SearchObjectPropertyKind;\n readonly score: number;\n}\n\nexport interface SearchIndexQueryResult {\n readonly objectHits: readonly SearchIndexObjectHit[];\n readonly terms: readonly string[];\n readonly textHits: readonly SearchIndexTextHit[];\n}\n\nconst SEARCH_INDEX_VERSION = \"3\";\nexport const SEARCH_INDEX_FTS_HIT_LIMIT = 32_000;\nconst FTS5_RANK_SCORE_SCALE = 1_000_000;\nconst TIER_WEIGHTS = [1, 0.45, 0.08] as const;\n\nexport interface ArchiveIndexSettings {\n readonly ftsEmbedded: boolean;\n}\n\nexport async function readArchiveIndexSettings(\n document: ReadonlyDocument,\n): Promise<ArchiveIndexSettings> {\n return await document.readDatabase(async (database) => {\n const row = await database.queryOne(\n `\n SELECT fts_embedded\n FROM archive_index_settings\n WHERE id = 1\n `,\n undefined,\n (value) => ({\n ftsEmbedded: getNumber(value, \"fts_embedded\") !== 0,\n }),\n );\n\n return row ?? { ftsEmbedded: false };\n });\n}\n\nexport async function setFtsIndexEmbedded(\n document: Document,\n embedded: boolean,\n): Promise<void> {\n await document.readDatabase(async (database) => {\n await database.run(\n `\n INSERT INTO archive_index_settings(id, fts_embedded)\n VALUES (1, ?)\n ON CONFLICT(id)\n DO UPDATE SET fts_embedded = excluded.fts_embedded\n `,\n [embedded ? 1 : 0],\n );\n });\n}\n\nexport async function isSearchIndexCurrent(\n document: ReadonlyDocument,\n input?: SearchIndexInput,\n): Promise<boolean> {\n return (await readSearchIndexStatus(document, input)) === \"current\";\n}\n\nexport async function readSearchIndexStatus(\n document: ReadonlyDocument,\n input?: SearchIndexInput,\n): Promise<SearchIndexStatus> {\n const fingerprint =\n input === undefined ? undefined : createSearchIndexFingerprint(input);\n\n try {\n return await document.readSearchIndexDatabase(async (database) => {\n const indexedFingerprint =\n await readSearchIndexFingerprintFromDatabase(database);\n\n if (indexedFingerprint === undefined) {\n return \"dirty\";\n }\n\n return fingerprint === undefined || indexedFingerprint === fingerprint\n ? \"current\"\n : \"dirty\";\n });\n } catch (error) {\n if (isMissingSearchIndexError(error)) {\n return \"missing\";\n }\n\n throw error;\n }\n}\n\nexport async function ensureSearchIndex(\n document: Document,\n input: SearchIndexInput,\n progress?: SearchIndexProgressReporter,\n): Promise<void> {\n const chaptersRevision = await document.serials.getChaptersRevision();\n\n await document.writeSearchIndexDatabase(async (database) => {\n const fingerprint = createSearchIndexFingerprint(input);\n const indexedFingerprint =\n await readSearchIndexFingerprintFromDatabase(database);\n\n if (indexedFingerprint === fingerprint) {\n return;\n }\n\n await database.transaction(async () => {\n await progress?.({ phase: \"clearing\" });\n await database.run(\"DELETE FROM text_sentence_fts\");\n await database.run(\"DELETE FROM search_object_properties_fts\");\n await database.run(\"DELETE FROM search_object_properties_records\");\n await database.run(\"DELETE FROM search_index_state\");\n\n let textDone = 0;\n for (const record of input.textSentences) {\n const plan = createSearchTokenPlan(record.text);\n const rowId = await insertTextSentenceRecord(database, record);\n\n await insertFtsRecord(database, \"text_sentence_fts\", rowId, plan);\n textDone += 1;\n await progress?.({\n done: textDone,\n phase: \"indexing-text\",\n total: input.textSentences.length,\n unit: \"sentence\",\n });\n }\n\n let objectDone = 0;\n for (const record of input.objectProperties) {\n const plan = createSearchTokenPlan(record.text);\n const rowId = await insertSearchObjectPropertyRecord(database, record);\n\n await insertFtsRecord(\n database,\n \"search_object_properties_fts\",\n rowId,\n plan,\n );\n objectDone += 1;\n await progress?.({\n done: objectDone,\n phase: \"indexing-objects\",\n total: input.objectProperties.length,\n unit: \"object\",\n });\n }\n\n await progress?.({ phase: \"finalizing\" });\n await database.run(\n `\n INSERT INTO search_index_state(key, value)\n VALUES ('version', ?)\n `,\n [SEARCH_INDEX_VERSION],\n );\n await database.run(\n `\n INSERT INTO search_index_state(key, value)\n VALUES ('fingerprint', ?)\n `,\n [fingerprint],\n );\n await database.run(\n `\n INSERT INTO search_index_state(key, value)\n VALUES ('chaptersRevision', ?)\n `,\n [String(chaptersRevision)],\n );\n });\n });\n}\n\nexport async function querySearchIndex(\n document: ReadonlyDocument,\n query: string,\n options: {\n readonly chapters?: readonly number[];\n readonly match?: ArchiveFindMatch;\n readonly objectHitLimit?: number;\n readonly textAfter?: {\n readonly chapterId: number;\n readonly kind: TextSentenceKind;\n readonly rank: number;\n readonly sentenceIndex: number;\n };\n readonly textHitLimit?: number;\n readonly types?: readonly ArchiveFindObjectType[] | null;\n } = {},\n): Promise<SearchIndexQueryResult | undefined> {\n const plan = createSearchTokenPlan(query);\n\n if (!hasSearchTokens(plan)) {\n return undefined;\n }\n\n const terms = listSearchPlanTerms(plan);\n\n return await document.readSearchIndexDatabase(async (database) => {\n const tierQueries = createTierQueries(query, plan, options.match ?? \"any\");\n const objectHitLimit = options.objectHitLimit ?? SEARCH_INDEX_FTS_HIT_LIMIT;\n const textHitLimit = options.textHitLimit ?? SEARCH_INDEX_FTS_HIT_LIMIT;\n const queriesObjects = shouldQueryObjects(options.types);\n const queriesText = createTextKindFilter(options.types).length > 0;\n const objectHitsByKey = new Map<string, SearchIndexObjectHit>();\n const textHitsByKey = new Map<string, SearchIndexTextHit>();\n\n for (const tierQuery of tierQueries) {\n if (tierQuery.matchExpression === \"\") {\n continue;\n }\n\n const objectHitRemaining = Math.max(\n 0,\n objectHitLimit - objectHitsByKey.size,\n );\n const textHitRemaining = Math.max(0, textHitLimit - textHitsByKey.size);\n\n if (\n (!queriesObjects || objectHitRemaining <= 0) &&\n (!queriesText || textHitRemaining <= 0)\n ) {\n break;\n }\n\n const [objectRows, textRows] = await Promise.all([\n queryObjectRows(database, tierQuery.matchExpression, {\n ...options,\n objectHitLimit: objectHitRemaining,\n }),\n queryTextRows(database, tierQuery.matchExpression, {\n ...options,\n textHitLimit: textHitRemaining,\n }),\n ]);\n\n for (const hit of objectRows) {\n const key = createObjectHitKey(hit);\n\n if (!objectHitsByKey.has(key)) {\n objectHitsByKey.set(key, hit);\n }\n }\n for (const hit of textRows) {\n const key = createTextHitKey(hit);\n\n if (!textHitsByKey.has(key)) {\n textHitsByKey.set(key, hit);\n }\n }\n if (\n (!queriesObjects || objectHitsByKey.size >= objectHitLimit) &&\n (!queriesText || textHitsByKey.size >= textHitLimit)\n ) {\n break;\n }\n }\n\n return {\n objectHits: [...objectHitsByKey.values()],\n terms,\n textHits: [...textHitsByKey.values()],\n };\n });\n}\n\nasync function queryObjectRows(\n database: Database,\n matchExpression: string,\n options: {\n readonly chapters?: readonly number[];\n readonly objectHitLimit?: number;\n readonly types?: readonly ArchiveFindObjectType[] | null;\n },\n): Promise<readonly SearchIndexObjectHit[]> {\n if (!shouldQueryObjects(options.types) || options.objectHitLimit === 0) {\n return [];\n }\n\n return await database.queryAll(\n `\n SELECT\n r.owner_kind AS owner_kind,\n r.owner_id AS owner_id,\n r.property_kind AS property_kind,\n r.chapter_id AS chapter_id,\n bm25(search_object_properties_fts, ?, ?, ?) AS rank\n FROM search_object_properties_fts\n JOIN search_object_properties_records AS r\n ON r.id = search_object_properties_fts.rowid\n WHERE search_object_properties_fts MATCH ?\n ${createChapterSql(options.chapters)}\n ORDER BY rank ASC, r.chapter_id, r.owner_kind, r.owner_id, r.property_kind\n ${createLimitSql(options.objectHitLimit)}\n `,\n [\n ...TIER_WEIGHTS,\n matchExpression,\n ...createChapterParams(options.chapters),\n ...createLimitParams(options.objectHitLimit),\n ],\n (row) => ({\n ownerId: String(row.owner_id),\n ownerKind: getNumber(row, \"owner_kind\") as SearchObjectPropertyOwnerKind,\n propertyKind: getNumber(row, \"property_kind\") as SearchObjectPropertyKind,\n score: rankToScore(getNumber(row, \"rank\")),\n ...(row.chapter_id === null\n ? {}\n : { chapterId: getNumber(row, \"chapter_id\") }),\n }),\n );\n}\n\nasync function queryTextRows(\n database: Database,\n matchExpression: string,\n options: {\n readonly chapters?: readonly number[];\n readonly textAfter?: {\n readonly chapterId: number;\n readonly kind: TextSentenceKind;\n readonly rank: number;\n readonly sentenceIndex: number;\n };\n readonly textHitLimit?: number;\n readonly types?: readonly ArchiveFindObjectType[] | null;\n },\n): Promise<readonly SearchIndexTextHit[]> {\n const kinds = createTextKindFilter(options.types);\n\n if (kinds.length === 0) {\n return [];\n }\n if (options.textHitLimit === 0) {\n return [];\n }\n\n const after = options.textAfter;\n\n return await database.queryAll(\n `\n SELECT\n kind,\n chapter_id,\n sentence_index,\n words_count,\n rank\n FROM (\n SELECT\n r.kind AS kind,\n r.chapter_id AS chapter_id,\n r.sentence_index AS sentence_index,\n r.words_count AS words_count,\n bm25(text_sentence_fts, ?, ?, ?) AS rank\n FROM text_sentence_fts\n JOIN text_sentence_records AS r\n ON r.id = text_sentence_fts.rowid\n WHERE text_sentence_fts MATCH ?\n AND r.kind IN (${kinds.map(() => \"?\").join(\", \")})\n ${createChapterSql(options.chapters)}\n )\n ${\n after === undefined\n ? \"\"\n : `\n WHERE (\n rank > ?\n OR (rank = ? AND chapter_id > ?)\n OR (rank = ? AND chapter_id = ? AND sentence_index > ?)\n OR (\n rank = ?\n AND chapter_id = ?\n AND sentence_index = ?\n AND kind > ?\n )\n )\n `\n }\n ORDER BY rank ASC, chapter_id, sentence_index, kind\n ${createLimitSql(options.textHitLimit)}\n `,\n [\n ...TIER_WEIGHTS,\n matchExpression,\n ...kinds,\n ...createChapterParams(options.chapters),\n ...(after === undefined\n ? []\n : [\n after.rank,\n after.rank,\n after.chapterId,\n after.rank,\n after.chapterId,\n after.sentenceIndex,\n after.rank,\n after.chapterId,\n after.sentenceIndex,\n after.kind,\n ]),\n ...createLimitParams(options.textHitLimit),\n ],\n (row) => {\n const rank = getNumber(row, \"rank\");\n\n return {\n chapterId: getNumber(row, \"chapter_id\"),\n kind: getNumber(row, \"kind\") as TextSentenceKind,\n rank,\n score: rankToScore(rank),\n sentenceIndex: getNumber(row, \"sentence_index\"),\n wordsCount: getNumber(row, \"words_count\"),\n };\n },\n );\n}\n\nfunction createTierQueries(\n query: string,\n plan: SearchTokenPlan,\n match: ArchiveFindMatch,\n): readonly {\n readonly matchExpression: string;\n}[] {\n if (match === \"all\") {\n return createAllMatchTierQueries(query);\n }\n\n return [\n {\n matchExpression: createMatchExpression([\n { column: \"tier1\", tokens: plan.tier1.map((token) => token.encoded) },\n ]),\n },\n {\n matchExpression: createMatchExpression([\n { column: \"tier1\", tokens: plan.tier1.map((token) => token.encoded) },\n { column: \"tier2\", tokens: plan.tier2.map((token) => token.encoded) },\n ]),\n },\n {\n matchExpression: createMatchExpression([\n { column: \"tier1\", tokens: plan.tier1.map((token) => token.encoded) },\n { column: \"tier2\", tokens: plan.tier2.map((token) => token.encoded) },\n { column: \"tier3\", tokens: plan.tier3.map((token) => token.encoded) },\n ]),\n },\n ];\n}\n\nfunction createAllMatchTierQueries(query: string): readonly {\n readonly matchExpression: string;\n}[] {\n const termPlans = normalizeSearchText(query)\n .split(/\\s+/u)\n .map((term) => createSearchTokenPlan(term))\n .filter(hasSearchTokens);\n\n const createExpression = (\n selectTokens: (plan: SearchTokenPlan) => readonly string[],\n ): string =>\n termPlans\n .map((termPlan) => {\n const tokens = [...new Set(selectTokens(termPlan))];\n\n return tokens.length === 0 ? \"\" : `(${tokens.join(\" OR \")})`;\n })\n .filter((term) => term !== \"\")\n .join(\" AND \");\n\n return [\n {\n matchExpression: createExpression((termPlan) =>\n termPlan.tier1.map((token) => `tier1:${escapeFtsToken(token.encoded)}`),\n ),\n },\n {\n matchExpression: createExpression((termPlan) => [\n ...termPlan.tier1.map(\n (token) => `tier1:${escapeFtsToken(token.encoded)}`,\n ),\n ...termPlan.tier2.map(\n (token) => `tier2:${escapeFtsToken(token.encoded)}`,\n ),\n ]),\n },\n {\n matchExpression: createExpression((termPlan) => [\n ...termPlan.tier1.map(\n (token) => `tier1:${escapeFtsToken(token.encoded)}`,\n ),\n ...termPlan.tier2.map(\n (token) => `tier2:${escapeFtsToken(token.encoded)}`,\n ),\n ...termPlan.tier3.map(\n (token) => `tier3:${escapeFtsToken(token.encoded)}`,\n ),\n ]),\n },\n ];\n}\n\nfunction createMatchExpression(\n groups: readonly {\n readonly column: string;\n readonly tokens: readonly string[];\n }[],\n): string {\n return groups\n .map((group) => ({\n ...group,\n tokens: [...new Set(group.tokens)],\n }))\n .filter((group) => group.tokens.length > 0)\n .map(\n (group) =>\n `${group.column}:(${group.tokens.map(escapeFtsToken).join(\" OR \")})`,\n )\n .join(\" OR \");\n}\n\nfunction escapeFtsToken(token: string): string {\n return `\"${token.replaceAll('\"', '\"\"')}\"`;\n}\n\nasync function insertTextSentenceRecord(\n database: Database,\n record: TextSentenceRecordInput,\n): Promise<number> {\n const rowId = await database.queryOne(\n `\n SELECT id\n FROM text_sentence_records\n WHERE kind = ? AND chapter_id = ? AND sentence_index = ?\n `,\n [record.kind, record.chapterId, record.sentenceIndex],\n (row) => getNumber(row, \"id\"),\n );\n\n if (rowId !== undefined) {\n return rowId;\n }\n\n await database.run(\n `\n INSERT INTO text_sentence_records (\n kind, chapter_id, sentence_index, words_count, byte_offset, byte_length\n )\n VALUES (?, ?, ?, ?, 0, 0)\n `,\n [record.kind, record.chapterId, record.sentenceIndex, record.wordsCount],\n );\n\n return await database.getLastInsertRowId();\n}\n\nasync function insertSearchObjectPropertyRecord(\n database: Database,\n record: SearchObjectPropertyRecordInput,\n): Promise<number> {\n await database.run(\n `\n INSERT INTO search_object_properties_records (\n owner_kind, owner_id, property_kind, chapter_id\n )\n VALUES (?, ?, ?, ?)\n `,\n [\n record.ownerKind,\n record.ownerId,\n record.propertyKind,\n record.chapterId ?? null,\n ],\n );\n\n return await database.getLastInsertRowId();\n}\n\nasync function insertFtsRecord(\n database: Database,\n table: \"search_object_properties_fts\" | \"text_sentence_fts\",\n rowId: number,\n plan: SearchTokenPlan,\n): Promise<void> {\n await database.run(\n `\n INSERT INTO ${table}(rowid, tier1, tier2, tier3)\n VALUES (?, ?, ?, ?)\n `,\n [\n rowId,\n serializeTokens(plan.tier1),\n serializeTokens(plan.tier2),\n serializeTokens(plan.tier3),\n ],\n );\n}\n\nexport function createSearchIndexFingerprint(input: SearchIndexInput): string {\n const hash = createHash(\"sha256\");\n\n for (const record of input.textSentences) {\n hash.update(\"text\");\n hash.update(\"\\0\");\n hash.update(String(record.kind));\n hash.update(\"\\0\");\n hash.update(String(record.chapterId));\n hash.update(\"\\0\");\n hash.update(String(record.sentenceIndex));\n hash.update(\"\\0\");\n hash.update(record.text);\n hash.update(\"\\0\");\n }\n\n for (const record of input.objectProperties) {\n hash.update(\"object-property\");\n hash.update(\"\\0\");\n hash.update(String(record.ownerKind));\n hash.update(\"\\0\");\n hash.update(record.ownerId);\n hash.update(\"\\0\");\n hash.update(String(record.propertyKind));\n hash.update(\"\\0\");\n hash.update(String(record.chapterId ?? \"\"));\n hash.update(\"\\0\");\n hash.update(record.text);\n hash.update(\"\\0\");\n }\n\n return hash.digest(\"hex\");\n}\n\nexport async function readSearchIndexFingerprintFromDatabase(\n database: Database,\n): Promise<string | undefined> {\n return await database.queryOne(\n `\n SELECT value\n FROM search_index_state\n WHERE key = 'fingerprint'\n `,\n undefined,\n (row) => String(row.value),\n );\n}\n\nfunction isMissingSearchIndexError(error: unknown): boolean {\n const code =\n typeof error === \"object\" && error !== null && \"code\" in error\n ? error.code\n : undefined;\n\n return (\n code === \"SQLITE_CANTOPEN\" ||\n (error instanceof Error &&\n (error.message.includes(\"Archive SQLite entry is missing: fts.db\") ||\n error.message.includes(\"no such table: search_index_state\")))\n );\n}\n\nfunction serializeTokens(\n tokens: readonly {\n readonly encoded: string;\n }[],\n): string {\n return tokens.map((token) => token.encoded).join(\" \");\n}\n\nfunction createChapterSql(chapters: readonly number[] | undefined): string {\n return chapters === undefined || chapters.length === 0\n ? \"\"\n : `AND r.chapter_id IN (${chapters.map(() => \"?\").join(\", \")})`;\n}\n\nfunction createChapterParams(\n chapters: readonly number[] | undefined,\n): readonly SqlBindValue[] {\n return chapters === undefined ? [] : [...chapters];\n}\n\nfunction createLimitSql(limit: number | undefined): string {\n return limit === undefined ? \"\" : \"LIMIT ?\";\n}\n\nfunction createLimitParams(limit: number | undefined): readonly SqlBindValue[] {\n return limit === undefined ? [] : [limit];\n}\n\nfunction shouldQueryObjects(\n types: readonly ArchiveFindObjectType[] | null | undefined,\n): boolean {\n return (\n types === undefined ||\n types === null ||\n types.includes(\"chapter\") ||\n types.includes(\"chapter-title\") ||\n types.includes(\"node\") ||\n types.includes(\"entity\")\n );\n}\n\nfunction createTextKindFilter(\n types: readonly ArchiveFindObjectType[] | null | undefined,\n): readonly TextSentenceKind[] {\n if (types === undefined || types === null) {\n return [TEXT_SENTENCE_KIND.summary, TEXT_SENTENCE_KIND.source];\n }\n\n const kinds: TextSentenceKind[] = [];\n\n if (types.includes(\"summary\")) {\n kinds.push(TEXT_SENTENCE_KIND.summary);\n }\n if (types.includes(\"source\")) {\n kinds.push(TEXT_SENTENCE_KIND.source);\n }\n\n return kinds;\n}\n\nfunction rankToScore(rank: number): number {\n const relevance = Math.max(0, -rank) * FTS5_RANK_SCORE_SCALE;\n\n return relevance / (1 + relevance);\n}\n\nfunction createObjectHitKey(hit: SearchIndexObjectHit): string {\n return [\n hit.ownerKind,\n hit.ownerId,\n hit.propertyKind,\n hit.chapterId ?? \"\",\n ].join(\":\");\n}\n\nfunction createTextHitKey(hit: SearchIndexTextHit): string {\n return [hit.kind, hit.chapterId, hit.sentenceIndex].join(\":\");\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,16 @@
1
+ interface SearchToken {
2
+ readonly encoded: string;
3
+ readonly raw: string;
4
+ readonly tier: 1 | 2 | 3;
5
+ }
6
+ interface SearchTokenPlan {
7
+ readonly tier1: readonly SearchToken[];
8
+ readonly tier2: readonly SearchToken[];
9
+ readonly tier3: readonly SearchToken[];
10
+ }
11
+ declare function normalizeSearchText(value: string): string;
12
+ declare function createSearchTokenPlan(value: string): SearchTokenPlan;
13
+ declare function listSearchPlanTerms(plan: SearchTokenPlan): readonly string[];
14
+ declare function hasSearchTokens(plan: SearchTokenPlan): boolean;
15
+
16
+ export { type SearchToken, type SearchTokenPlan, createSearchTokenPlan, hasSearchTokens, listSearchPlanTerms, normalizeSearchText };