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,399 @@
1
+ import { spawn } from "child_process";
2
+ const WIKISPINE_RUNTIME_GUIDE_URL = "https://raw.githubusercontent.com/oomol-lab/wiki-graph/refs/heads/main/docs/wikispine-runtime.md";
3
+ const DEFAULT_WIKISPINE_FETCH_ENDPOINT = "https://wikispi-service-cxbfjlteab.cn-hangzhou.fcapp.run";
4
+ async function matchWikispineSentenceCandidates(options) {
5
+ const candidates = [];
6
+ let candidateIndex = 1;
7
+ for (const sentence of options.sentences) {
8
+ for (const matched of await matchSentence(sentence, options)) {
9
+ const surface = sentence.text.slice(matched.start, matched.end);
10
+ candidates.push({
11
+ id: `c${candidateIndex}`,
12
+ qidOptions: matched.qids.map(toQidOption),
13
+ range: {
14
+ end: sentence.range.start + matched.end,
15
+ start: sentence.range.start + matched.start
16
+ },
17
+ surface
18
+ });
19
+ candidateIndex += 1;
20
+ }
21
+ await options.onProgress?.({ coveredRangeEnd: sentence.range.end });
22
+ }
23
+ return candidates;
24
+ }
25
+ async function matchSentence(sentence, options) {
26
+ return resolveProvider(options) === "fetch" ? await fetchWikispineMatch(options, sentence) : await runWikispineMatch(
27
+ options.command ?? "wikispine",
28
+ buildMatchArgs(options),
29
+ sentence,
30
+ options
31
+ );
32
+ }
33
+ async function testWikispineRuntime(options) {
34
+ const provider = resolveProvider(options);
35
+ const startedAt = Date.now();
36
+ if (provider === "fetch") {
37
+ const endpoint = requireEndpoint(options.endpoint);
38
+ const metadata = await fetchWikispineMetadata(endpoint, options.fetch);
39
+ await fetchWikispineMatch(
40
+ {
41
+ ...options,
42
+ endpoint,
43
+ maxCandidatesPerSurface: 1
44
+ },
45
+ {
46
+ id: "test",
47
+ range: { end: 7, start: 0 },
48
+ text: "\u5317\u4EAC\u5927\u5B66\u4F4D\u4E8E\u5317\u4EAC\u3002"
49
+ }
50
+ );
51
+ return {
52
+ durationMs: Date.now() - startedAt,
53
+ metadata,
54
+ ok: true,
55
+ provider
56
+ };
57
+ }
58
+ await runWikispineMatch(
59
+ options.command ?? "wikispine",
60
+ buildMatchArgs({
61
+ ...options,
62
+ maxCandidatesPerSurface: 1
63
+ }),
64
+ {
65
+ id: "test",
66
+ range: { end: 7, start: 0 },
67
+ text: "\u5317\u4EAC\u5927\u5B66\u4F4D\u4E8E\u5317\u4EAC\u3002"
68
+ },
69
+ {}
70
+ );
71
+ return {
72
+ durationMs: Date.now() - startedAt,
73
+ ok: true,
74
+ provider
75
+ };
76
+ }
77
+ async function runWikispineMatch(command, args, sentence, options) {
78
+ return await new Promise((resolve, reject) => {
79
+ const child = spawn(command, args, {
80
+ stdio: ["pipe", "pipe", "pipe"]
81
+ });
82
+ const progress = createWikispineProgressReporter(options.onProgress, {
83
+ onFailure: (error) => {
84
+ reject(error);
85
+ child.kill();
86
+ }
87
+ });
88
+ const parser = createWikispineNdjsonParser({
89
+ onMatch: (match) => {
90
+ progress.report({
91
+ coveredRangeEnd: sentence.range.start + match.end
92
+ });
93
+ }
94
+ });
95
+ const stderr = [];
96
+ child.stdout.setEncoding("utf8");
97
+ child.stdout.on("data", (chunk) => {
98
+ try {
99
+ parser.push(chunk);
100
+ } catch (error) {
101
+ reject(toError(error));
102
+ child.kill();
103
+ }
104
+ });
105
+ child.stderr.on("data", (chunk) => {
106
+ stderr.push(chunk);
107
+ });
108
+ child.on("error", (error) => {
109
+ reject(
110
+ new Error(
111
+ formatWikispineRuntimeError(
112
+ `Failed to start wikispine command: ${error.message}`
113
+ )
114
+ )
115
+ );
116
+ });
117
+ child.on("close", (code) => {
118
+ if (code !== 0) {
119
+ reject(
120
+ new Error(
121
+ formatWikispineRuntimeError(
122
+ `wikispine match failed with exit code ${code}: ${Buffer.concat(stderr).toString("utf8")}`
123
+ )
124
+ )
125
+ );
126
+ return;
127
+ }
128
+ void (async () => {
129
+ try {
130
+ const matches = parser.finish();
131
+ await progress.wait();
132
+ resolve(matches);
133
+ } catch (error) {
134
+ reject(toError(error));
135
+ }
136
+ })();
137
+ });
138
+ child.stdin.end(sentence.text);
139
+ });
140
+ }
141
+ function buildMatchArgs(options) {
142
+ const args = ["match"];
143
+ if (options.dataDir !== void 0) {
144
+ args.push("--data-dir", options.dataDir);
145
+ }
146
+ if (options.includeDisambiguation === false) {
147
+ args.push("--exclude-disambiguation");
148
+ }
149
+ if (options.maxCandidatesPerSurface !== void 0) {
150
+ args.push(
151
+ "--max-candidates-per-surface",
152
+ String(options.maxCandidatesPerSurface)
153
+ );
154
+ }
155
+ return args;
156
+ }
157
+ async function fetchWikispineMatch(options, sentence) {
158
+ const endpoint = requireEndpoint(options.endpoint);
159
+ const response = await (options.fetch ?? fetch)(`${endpoint}/match`, {
160
+ body: JSON.stringify({
161
+ options: {
162
+ ...options.includeDisambiguation === void 0 ? {} : { include_disambiguation: options.includeDisambiguation },
163
+ ...options.maxCandidatesPerSurface === void 0 ? {} : {
164
+ max_candidates_per_surface: options.maxCandidatesPerSurface
165
+ }
166
+ },
167
+ text: sentence.text
168
+ }),
169
+ headers: {
170
+ accept: "application/x-ndjson",
171
+ "content-type": "application/json"
172
+ },
173
+ method: "POST"
174
+ });
175
+ if (!response.ok) {
176
+ throw new Error(
177
+ formatWikispineRuntimeError(
178
+ `WikiSpine fetch provider failed with HTTP ${response.status}: ${await response.text()}`
179
+ )
180
+ );
181
+ }
182
+ const progress = createWikispineProgressReporter(options.onProgress);
183
+ const parser = createWikispineNdjsonParser({
184
+ onMatch: (match) => {
185
+ progress.report({
186
+ coveredRangeEnd: sentence.range.start + match.end
187
+ });
188
+ }
189
+ });
190
+ if (response.body === null) {
191
+ parser.push(await response.text());
192
+ const matches2 = parser.finish();
193
+ await progress.wait();
194
+ return matches2;
195
+ }
196
+ const reader = response.body.getReader();
197
+ const decoder = new TextDecoder();
198
+ while (true) {
199
+ const { done, value } = await reader.read();
200
+ if (done) {
201
+ break;
202
+ }
203
+ parser.push(decoder.decode(value, { stream: true }));
204
+ progress.throwIfFailed();
205
+ }
206
+ parser.push(decoder.decode());
207
+ const matches = parser.finish();
208
+ await progress.wait();
209
+ return matches;
210
+ }
211
+ function createWikispineProgressReporter(onProgress, options) {
212
+ const tasks = [];
213
+ let failure;
214
+ function fail(error) {
215
+ if (failure !== void 0) {
216
+ return;
217
+ }
218
+ failure = toError(error);
219
+ options?.onFailure?.(failure);
220
+ }
221
+ return {
222
+ report: (progress) => {
223
+ if (onProgress === void 0 || failure !== void 0) {
224
+ return;
225
+ }
226
+ try {
227
+ tasks.push(Promise.resolve(onProgress(progress)).catch(fail));
228
+ } catch (error) {
229
+ fail(error);
230
+ }
231
+ },
232
+ throwIfFailed: () => {
233
+ if (failure !== void 0) {
234
+ throw failure;
235
+ }
236
+ },
237
+ wait: async () => {
238
+ await Promise.all(tasks);
239
+ if (failure !== void 0) {
240
+ throw failure;
241
+ }
242
+ }
243
+ };
244
+ }
245
+ async function fetchWikispineMetadata(endpoint, fetchFn = fetch) {
246
+ const ready = await fetchFn(`${endpoint}/readyz`);
247
+ if (!ready.ok) {
248
+ throw new Error(
249
+ formatWikispineRuntimeError(
250
+ `WikiSpine fetch provider is not ready: HTTP ${ready.status}.`
251
+ )
252
+ );
253
+ }
254
+ const response = await fetchFn(`${endpoint}/metadata`);
255
+ if (!response.ok) {
256
+ throw new Error(
257
+ formatWikispineRuntimeError(
258
+ `WikiSpine metadata request failed with HTTP ${response.status}.`
259
+ )
260
+ );
261
+ }
262
+ try {
263
+ return parseWikispineMetadata(await response.json());
264
+ } catch (error) {
265
+ if (error instanceof Error && error.message.includes("setup guide")) {
266
+ throw error;
267
+ }
268
+ throw new Error(
269
+ formatWikispineRuntimeError(
270
+ `Invalid WikiSpine metadata response: ${error instanceof Error ? error.message : String(error)}`
271
+ )
272
+ );
273
+ }
274
+ }
275
+ function createWikispineNdjsonParser(input) {
276
+ const matches = [];
277
+ let buffer = "";
278
+ function parseLine(line) {
279
+ if (line.trim() === "") {
280
+ return;
281
+ }
282
+ const event = parseWikispineEvent(JSON.parse(line));
283
+ if (event.type === "match") {
284
+ matches.push(event.match);
285
+ input?.onMatch?.(event.match);
286
+ }
287
+ }
288
+ function wrapParseError(error) {
289
+ return new Error(
290
+ formatWikispineRuntimeError(
291
+ `Invalid WikiSpine match response: ${error instanceof Error ? error.message : String(error)}`
292
+ )
293
+ );
294
+ }
295
+ return {
296
+ finish: () => {
297
+ try {
298
+ parseLine(buffer);
299
+ buffer = "";
300
+ return matches;
301
+ } catch (error) {
302
+ throw wrapParseError(error);
303
+ }
304
+ },
305
+ push: (chunk) => {
306
+ try {
307
+ buffer += chunk;
308
+ const lines = buffer.split(/\r?\n/u);
309
+ buffer = lines.pop() ?? "";
310
+ for (const line of lines) {
311
+ parseLine(line);
312
+ }
313
+ } catch (error) {
314
+ throw wrapParseError(error);
315
+ }
316
+ }
317
+ };
318
+ }
319
+ function parseWikispineEvent(value) {
320
+ if (typeof value !== "object" || value === null) {
321
+ throw new Error("Expected wikispine event to be an object.");
322
+ }
323
+ const record = value;
324
+ if (record.type === "done") {
325
+ return { type: "done" };
326
+ }
327
+ if (record.type === "match" && isWikispineMatchRecord(record.match)) {
328
+ return {
329
+ match: record.match,
330
+ type: "match"
331
+ };
332
+ }
333
+ throw new Error(`Unexpected wikispine event: ${JSON.stringify(value)}`);
334
+ }
335
+ function toError(error) {
336
+ return error instanceof Error ? error : new Error(String(error));
337
+ }
338
+ function parseWikispineMetadata(value) {
339
+ if (typeof value !== "object" || value === null) {
340
+ throw new Error(
341
+ formatWikispineRuntimeError("Expected WikiSpine metadata.")
342
+ );
343
+ }
344
+ const record = value;
345
+ if (typeof record.automaton_shard_count !== "number" || typeof record.format !== "string" || typeof record.qid_count !== "number" || typeof record.surface_count !== "number" || typeof record.surface_normalization !== "string") {
346
+ throw new Error(formatWikispineRuntimeError("Invalid WikiSpine metadata."));
347
+ }
348
+ return {
349
+ automaton_shard_count: record.automaton_shard_count,
350
+ format: record.format,
351
+ qid_count: record.qid_count,
352
+ surface_count: record.surface_count,
353
+ surface_normalization: record.surface_normalization
354
+ };
355
+ }
356
+ function isWikispineMatchRecord(value) {
357
+ if (typeof value !== "object" || value === null) {
358
+ return false;
359
+ }
360
+ const record = value;
361
+ return typeof record.end === "number" && Array.isArray(record.qids) && record.qids.every(isWikispineQidCandidate) && typeof record.start === "number" && typeof record.surface_id === "number";
362
+ }
363
+ function isWikispineQidCandidate(value) {
364
+ if (typeof value !== "object" || value === null) {
365
+ return false;
366
+ }
367
+ const record = value;
368
+ return (!("disambiguation" in record) || typeof record.disambiguation === "boolean") && typeof record.qid === "string" && /^Q[1-9]\d*$/u.test(record.qid);
369
+ }
370
+ function toQidOption(candidate) {
371
+ return {
372
+ isDisambiguation: candidate.disambiguation === true,
373
+ qid: candidate.qid
374
+ };
375
+ }
376
+ function resolveProvider(options) {
377
+ return options.provider ?? "cli";
378
+ }
379
+ function requireEndpoint(endpoint) {
380
+ const normalized = (endpoint ?? DEFAULT_WIKISPINE_FETCH_ENDPOINT).trim().replace(/\/+$/u, "");
381
+ if (normalized === "") {
382
+ throw new Error(
383
+ formatWikispineRuntimeError(
384
+ "WikiSpine fetch provider has no default endpoint."
385
+ )
386
+ );
387
+ }
388
+ return normalized;
389
+ }
390
+ function formatWikispineRuntimeError(message) {
391
+ return `${message}
392
+ WikiSpine setup guide: ${WIKISPINE_RUNTIME_GUIDE_URL}`;
393
+ }
394
+ export {
395
+ DEFAULT_WIKISPINE_FETCH_ENDPOINT,
396
+ matchWikispineSentenceCandidates,
397
+ testWikispineRuntime
398
+ };
399
+ //# sourceMappingURL=wikispine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/wikimatch/wikispine.ts"],"sourcesContent":["import { spawn } from \"child_process\";\n\nimport type {\n WikimatchCandidate,\n WikimatchQidOption,\n WikimatchSentence,\n} from \"./types.js\";\n\nexport interface MatchWikispineSentenceCandidatesOptions {\n readonly command?: string;\n readonly dataDir?: string;\n readonly endpoint?: string;\n readonly fetch?: typeof fetch;\n readonly includeDisambiguation?: boolean;\n readonly maxCandidatesPerSurface?: number;\n readonly onProgress?: (\n progress: WikispineMatchProgress,\n ) => Promise<void> | void;\n readonly provider?: WikispineProvider;\n readonly sentences: readonly WikimatchSentence[];\n}\n\nexport type WikispineProvider = \"cli\" | \"fetch\";\n\nexport interface WikispineMatchProgress {\n readonly coveredRangeEnd: number;\n}\n\nexport interface TestWikispineRuntimeOptions {\n readonly command?: string;\n readonly dataDir?: string;\n readonly endpoint?: string;\n readonly fetch?: typeof fetch;\n readonly provider?: WikispineProvider;\n}\n\nexport interface WikispineRuntimeTestResult {\n readonly durationMs: number;\n readonly metadata?: WikispineMetadata;\n readonly ok: true;\n readonly provider: WikispineProvider;\n}\n\ninterface WikispineMatchEvent {\n readonly match: WikispineMatchRecord;\n readonly type: \"match\";\n}\n\ninterface WikispineDoneEvent {\n readonly stats?: unknown;\n readonly type: \"done\";\n}\n\ntype WikispineEvent = WikispineDoneEvent | WikispineMatchEvent;\n\ninterface WikispineMatchRecord {\n readonly end: number;\n readonly qids: readonly WikispineQidCandidate[];\n readonly start: number;\n readonly surface_id: number;\n}\n\ninterface WikispineQidCandidate {\n readonly disambiguation?: boolean;\n readonly qid: string;\n}\n\ninterface WikispineMetadata {\n readonly automaton_shard_count: number;\n readonly format: string;\n readonly qid_count: number;\n readonly surface_count: number;\n readonly surface_normalization: string;\n}\n\nconst WIKISPINE_RUNTIME_GUIDE_URL =\n \"https://raw.githubusercontent.com/oomol-lab/wiki-graph/refs/heads/main/docs/wikispine-runtime.md\";\nexport const DEFAULT_WIKISPINE_FETCH_ENDPOINT =\n \"https://wikispi-service-cxbfjlteab.cn-hangzhou.fcapp.run\";\n\nexport async function matchWikispineSentenceCandidates(\n options: MatchWikispineSentenceCandidatesOptions,\n): Promise<readonly WikimatchCandidate[]> {\n const candidates: WikimatchCandidate[] = [];\n let candidateIndex = 1;\n\n for (const sentence of options.sentences) {\n for (const matched of await matchSentence(sentence, options)) {\n const surface = sentence.text.slice(matched.start, matched.end);\n\n candidates.push({\n id: `c${candidateIndex}`,\n qidOptions: matched.qids.map(toQidOption),\n range: {\n end: sentence.range.start + matched.end,\n start: sentence.range.start + matched.start,\n },\n surface,\n });\n candidateIndex += 1;\n }\n await options.onProgress?.({ coveredRangeEnd: sentence.range.end });\n }\n\n return candidates;\n}\n\nasync function matchSentence(\n sentence: WikimatchSentence,\n options: MatchWikispineSentenceCandidatesOptions,\n): Promise<readonly WikispineMatchRecord[]> {\n return resolveProvider(options) === \"fetch\"\n ? await fetchWikispineMatch(options, sentence)\n : await runWikispineMatch(\n options.command ?? \"wikispine\",\n buildMatchArgs(options),\n sentence,\n options,\n );\n}\n\nexport async function testWikispineRuntime(\n options: TestWikispineRuntimeOptions,\n): Promise<WikispineRuntimeTestResult> {\n const provider = resolveProvider(options);\n const startedAt = Date.now();\n\n if (provider === \"fetch\") {\n const endpoint = requireEndpoint(options.endpoint);\n const metadata = await fetchWikispineMetadata(endpoint, options.fetch);\n\n await fetchWikispineMatch(\n {\n ...options,\n endpoint,\n maxCandidatesPerSurface: 1,\n },\n {\n id: \"test\",\n range: { end: 7, start: 0 },\n text: \"北京大学位于北京。\",\n },\n );\n\n return {\n durationMs: Date.now() - startedAt,\n metadata,\n ok: true,\n provider,\n };\n }\n\n await runWikispineMatch(\n options.command ?? \"wikispine\",\n buildMatchArgs({\n ...options,\n maxCandidatesPerSurface: 1,\n }),\n {\n id: \"test\",\n range: { end: 7, start: 0 },\n text: \"北京大学位于北京。\",\n },\n {},\n );\n\n return {\n durationMs: Date.now() - startedAt,\n ok: true,\n provider,\n };\n}\n\nasync function runWikispineMatch(\n command: string,\n args: readonly string[],\n sentence: WikimatchSentence,\n options: Pick<MatchWikispineSentenceCandidatesOptions, \"onProgress\">,\n): Promise<readonly WikispineMatchRecord[]> {\n return await new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n const progress = createWikispineProgressReporter(options.onProgress, {\n onFailure: (error) => {\n reject(error);\n child.kill();\n },\n });\n const parser = createWikispineNdjsonParser({\n onMatch: (match) => {\n progress.report({\n coveredRangeEnd: sentence.range.start + match.end,\n });\n },\n });\n const stderr: Buffer[] = [];\n\n child.stdout.setEncoding(\"utf8\");\n child.stdout.on(\"data\", (chunk: string) => {\n try {\n parser.push(chunk);\n } catch (error) {\n reject(toError(error));\n child.kill();\n }\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderr.push(chunk);\n });\n child.on(\"error\", (error) => {\n reject(\n new Error(\n formatWikispineRuntimeError(\n `Failed to start wikispine command: ${error.message}`,\n ),\n ),\n );\n });\n child.on(\"close\", (code) => {\n if (code !== 0) {\n reject(\n new Error(\n formatWikispineRuntimeError(\n `wikispine match failed with exit code ${code}: ${Buffer.concat(stderr).toString(\"utf8\")}`,\n ),\n ),\n );\n return;\n }\n\n void (async () => {\n try {\n const matches = parser.finish();\n await progress.wait();\n resolve(matches);\n } catch (error) {\n reject(toError(error));\n }\n })();\n });\n\n child.stdin.end(sentence.text);\n });\n}\n\nfunction buildMatchArgs(\n options: Pick<\n MatchWikispineSentenceCandidatesOptions,\n \"dataDir\" | \"includeDisambiguation\" | \"maxCandidatesPerSurface\"\n >,\n): string[] {\n const args = [\"match\"];\n\n if (options.dataDir !== undefined) {\n args.push(\"--data-dir\", options.dataDir);\n }\n if (options.includeDisambiguation === false) {\n args.push(\"--exclude-disambiguation\");\n }\n if (options.maxCandidatesPerSurface !== undefined) {\n args.push(\n \"--max-candidates-per-surface\",\n String(options.maxCandidatesPerSurface),\n );\n }\n\n return args;\n}\n\nasync function fetchWikispineMatch(\n options: Pick<\n MatchWikispineSentenceCandidatesOptions,\n | \"endpoint\"\n | \"fetch\"\n | \"includeDisambiguation\"\n | \"maxCandidatesPerSurface\"\n | \"onProgress\"\n >,\n sentence: WikimatchSentence,\n): Promise<readonly WikispineMatchRecord[]> {\n const endpoint = requireEndpoint(options.endpoint);\n const response = await (options.fetch ?? fetch)(`${endpoint}/match`, {\n body: JSON.stringify({\n options: {\n ...(options.includeDisambiguation === undefined\n ? {}\n : { include_disambiguation: options.includeDisambiguation }),\n ...(options.maxCandidatesPerSurface === undefined\n ? {}\n : {\n max_candidates_per_surface: options.maxCandidatesPerSurface,\n }),\n },\n text: sentence.text,\n }),\n headers: {\n accept: \"application/x-ndjson\",\n \"content-type\": \"application/json\",\n },\n method: \"POST\",\n });\n\n if (!response.ok) {\n throw new Error(\n formatWikispineRuntimeError(\n `WikiSpine fetch provider failed with HTTP ${response.status}: ${await response.text()}`,\n ),\n );\n }\n\n const progress = createWikispineProgressReporter(options.onProgress);\n const parser = createWikispineNdjsonParser({\n onMatch: (match) => {\n progress.report({\n coveredRangeEnd: sentence.range.start + match.end,\n });\n },\n });\n\n if (response.body === null) {\n parser.push(await response.text());\n const matches = parser.finish();\n await progress.wait();\n return matches;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n parser.push(decoder.decode(value, { stream: true }));\n progress.throwIfFailed();\n }\n\n parser.push(decoder.decode());\n const matches = parser.finish();\n await progress.wait();\n return matches;\n}\n\nfunction createWikispineProgressReporter(\n onProgress:\n | ((progress: WikispineMatchProgress) => Promise<void> | void)\n | undefined,\n options?: {\n readonly onFailure?: (error: Error) => void;\n },\n): {\n readonly report: (progress: WikispineMatchProgress) => void;\n readonly throwIfFailed: () => void;\n readonly wait: () => Promise<void>;\n} {\n const tasks: Promise<void>[] = [];\n let failure: Error | undefined;\n\n function fail(error: unknown): void {\n if (failure !== undefined) {\n return;\n }\n failure = toError(error);\n options?.onFailure?.(failure);\n }\n\n return {\n report: (progress) => {\n if (onProgress === undefined || failure !== undefined) {\n return;\n }\n\n try {\n tasks.push(Promise.resolve(onProgress(progress)).catch(fail));\n } catch (error) {\n fail(error);\n }\n },\n throwIfFailed: () => {\n if (failure !== undefined) {\n throw failure;\n }\n },\n wait: async () => {\n await Promise.all(tasks);\n if (failure !== undefined) {\n throw failure;\n }\n },\n };\n}\n\nasync function fetchWikispineMetadata(\n endpoint: string,\n fetchFn: typeof fetch = fetch,\n): Promise<WikispineMetadata> {\n const ready = await fetchFn(`${endpoint}/readyz`);\n\n if (!ready.ok) {\n throw new Error(\n formatWikispineRuntimeError(\n `WikiSpine fetch provider is not ready: HTTP ${ready.status}.`,\n ),\n );\n }\n\n const response = await fetchFn(`${endpoint}/metadata`);\n\n if (!response.ok) {\n throw new Error(\n formatWikispineRuntimeError(\n `WikiSpine metadata request failed with HTTP ${response.status}.`,\n ),\n );\n }\n\n try {\n return parseWikispineMetadata(await response.json());\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"setup guide\")) {\n throw error;\n }\n\n throw new Error(\n formatWikispineRuntimeError(\n `Invalid WikiSpine metadata response: ${error instanceof Error ? error.message : String(error)}`,\n ),\n );\n }\n}\n\nfunction createWikispineNdjsonParser(input?: {\n readonly onMatch?: (match: WikispineMatchRecord) => void;\n}): {\n readonly finish: () => readonly WikispineMatchRecord[];\n readonly push: (chunk: string) => void;\n} {\n const matches: WikispineMatchRecord[] = [];\n let buffer = \"\";\n\n function parseLine(line: string): void {\n if (line.trim() === \"\") {\n return;\n }\n\n const event = parseWikispineEvent(JSON.parse(line));\n\n if (event.type === \"match\") {\n matches.push(event.match);\n input?.onMatch?.(event.match);\n }\n }\n\n function wrapParseError(error: unknown): Error {\n return new Error(\n formatWikispineRuntimeError(\n `Invalid WikiSpine match response: ${error instanceof Error ? error.message : String(error)}`,\n ),\n );\n }\n\n return {\n finish: () => {\n try {\n parseLine(buffer);\n buffer = \"\";\n return matches;\n } catch (error) {\n throw wrapParseError(error);\n }\n },\n push: (chunk) => {\n try {\n buffer += chunk;\n const lines = buffer.split(/\\r?\\n/u);\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n parseLine(line);\n }\n } catch (error) {\n throw wrapParseError(error);\n }\n },\n };\n}\n\nfunction parseWikispineEvent(value: unknown): WikispineEvent {\n if (typeof value !== \"object\" || value === null) {\n throw new Error(\"Expected wikispine event to be an object.\");\n }\n\n const record = value as Record<string, unknown>;\n\n if (record.type === \"done\") {\n return { type: \"done\" };\n }\n if (record.type === \"match\" && isWikispineMatchRecord(record.match)) {\n return {\n match: record.match,\n type: \"match\",\n };\n }\n\n throw new Error(`Unexpected wikispine event: ${JSON.stringify(value)}`);\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction parseWikispineMetadata(value: unknown): WikispineMetadata {\n if (typeof value !== \"object\" || value === null) {\n throw new Error(\n formatWikispineRuntimeError(\"Expected WikiSpine metadata.\"),\n );\n }\n\n const record = value as Record<string, unknown>;\n\n if (\n typeof record.automaton_shard_count !== \"number\" ||\n typeof record.format !== \"string\" ||\n typeof record.qid_count !== \"number\" ||\n typeof record.surface_count !== \"number\" ||\n typeof record.surface_normalization !== \"string\"\n ) {\n throw new Error(formatWikispineRuntimeError(\"Invalid WikiSpine metadata.\"));\n }\n\n return {\n automaton_shard_count: record.automaton_shard_count,\n format: record.format,\n qid_count: record.qid_count,\n surface_count: record.surface_count,\n surface_normalization: record.surface_normalization,\n };\n}\n\nfunction isWikispineMatchRecord(value: unknown): value is WikispineMatchRecord {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const record = value as Record<string, unknown>;\n\n return (\n typeof record.end === \"number\" &&\n Array.isArray(record.qids) &&\n record.qids.every(isWikispineQidCandidate) &&\n typeof record.start === \"number\" &&\n typeof record.surface_id === \"number\"\n );\n}\n\nfunction isWikispineQidCandidate(\n value: unknown,\n): value is WikispineQidCandidate {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const record = value as Record<string, unknown>;\n\n return (\n (!(\"disambiguation\" in record) ||\n typeof record.disambiguation === \"boolean\") &&\n typeof record.qid === \"string\" &&\n /^Q[1-9]\\d*$/u.test(record.qid)\n );\n}\n\nfunction toQidOption(candidate: WikispineQidCandidate): WikimatchQidOption {\n return {\n isDisambiguation: candidate.disambiguation === true,\n qid: candidate.qid,\n };\n}\n\nfunction resolveProvider(options: {\n readonly provider?: WikispineProvider;\n}): WikispineProvider {\n return options.provider ?? \"cli\";\n}\n\nfunction requireEndpoint(endpoint: string | undefined): string {\n const normalized = (endpoint ?? DEFAULT_WIKISPINE_FETCH_ENDPOINT)\n .trim()\n .replace(/\\/+$/u, \"\");\n\n if (normalized === \"\") {\n throw new Error(\n formatWikispineRuntimeError(\n \"WikiSpine fetch provider has no default endpoint.\",\n ),\n );\n }\n\n return normalized;\n}\n\nfunction formatWikispineRuntimeError(message: string): string {\n return `${message}\\nWikiSpine setup guide: ${WIKISPINE_RUNTIME_GUIDE_URL}`;\n}\n"],"mappings":"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","names":["matches"]}
@@ -0,0 +1,6 @@
1
+ import { BuildWikimatchWindowsOptions, WikimatchWindow } from './types.js';
2
+ import '../wikipage/types.js';
3
+
4
+ declare function buildWikimatchWindows(options: BuildWikimatchWindowsOptions): readonly WikimatchWindow[];
5
+
6
+ export { buildWikimatchWindows };
@@ -0,0 +1,83 @@
1
+ import { expandRangeByWords } from "./words.js";
2
+ import { countWikimatchCandidateOptions } from "./options.js";
3
+ function buildWikimatchWindows(options) {
4
+ const groups = groupOverlappingCandidates(
5
+ normalizeCandidates(options.candidates ?? [])
6
+ );
7
+ const windows = [];
8
+ let pendingGroups = [];
9
+ let pendingOptionCount = 0;
10
+ for (const group of groups) {
11
+ const groupOptionCount = countGroupOptions(group);
12
+ if (pendingGroups.length > 0 && pendingOptionCount + groupOptionCount > options.optionBudget) {
13
+ windows.push(createWindow(options.text, pendingGroups, options));
14
+ pendingGroups = [];
15
+ pendingOptionCount = 0;
16
+ }
17
+ pendingGroups.push(group);
18
+ pendingOptionCount += groupOptionCount;
19
+ }
20
+ if (pendingGroups.length > 0) {
21
+ windows.push(createWindow(options.text, pendingGroups, options));
22
+ }
23
+ return windows;
24
+ }
25
+ function countGroupOptions(group) {
26
+ return group.candidates.reduce(
27
+ (total, candidate) => total + countWikimatchCandidateOptions(candidate),
28
+ 0
29
+ );
30
+ }
31
+ function createWindow(text, groups, options) {
32
+ const groupStart = Math.min(...groups.map((group) => group.range.start));
33
+ const groupEnd = Math.max(...groups.map((group) => group.range.end));
34
+ const expandedRange = expandRangeByWords({
35
+ rangeEnd: groupEnd,
36
+ rangeStart: groupStart,
37
+ text,
38
+ words: options.contextWords
39
+ });
40
+ return {
41
+ baseOffset: expandedRange.start,
42
+ candidates: groups.flatMap((group) => group.candidates),
43
+ groups: groups.map((group, index) => ({
44
+ candidateIds: group.candidates.map((candidate) => candidate.id),
45
+ id: `g${index + 1}`,
46
+ range: group.range
47
+ })),
48
+ text: text.slice(expandedRange.start, expandedRange.end)
49
+ };
50
+ }
51
+ function groupOverlappingCandidates(candidates) {
52
+ const groups = [];
53
+ let current;
54
+ for (const candidate of candidates) {
55
+ if (current === void 0 || candidate.range.start >= current.range.end) {
56
+ current = {
57
+ candidates: [candidate],
58
+ range: candidate.range
59
+ };
60
+ groups.push(current);
61
+ continue;
62
+ }
63
+ current = {
64
+ candidates: [...current.candidates, candidate],
65
+ range: {
66
+ end: Math.max(current.range.end, candidate.range.end),
67
+ start: Math.min(current.range.start, candidate.range.start)
68
+ }
69
+ };
70
+ groups[groups.length - 1] = current;
71
+ }
72
+ return groups;
73
+ }
74
+ function normalizeCandidates(candidates) {
75
+ return candidates.filter((candidate) => candidate.range.start < candidate.range.end).sort(compareCandidate);
76
+ }
77
+ function compareCandidate(left, right) {
78
+ return left.range.start - right.range.start || right.range.end - left.range.end || left.id.localeCompare(right.id);
79
+ }
80
+ export {
81
+ buildWikimatchWindows
82
+ };
83
+ //# sourceMappingURL=window.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/wikimatch/window.ts"],"sourcesContent":["import { expandRangeByWords } from \"./words.js\";\nimport { countWikimatchCandidateOptions } from \"./options.js\";\nimport type {\n BuildWikimatchWindowsOptions,\n WikimatchCandidate,\n WikimatchWindow,\n} from \"./types.js\";\n\ninterface CandidateGroup {\n readonly candidates: readonly WikimatchCandidate[];\n readonly range: {\n readonly end: number;\n readonly start: number;\n };\n}\n\nexport function buildWikimatchWindows(\n options: BuildWikimatchWindowsOptions,\n): readonly WikimatchWindow[] {\n const groups = groupOverlappingCandidates(\n normalizeCandidates(options.candidates ?? []),\n );\n const windows: WikimatchWindow[] = [];\n let pendingGroups: CandidateGroup[] = [];\n let pendingOptionCount = 0;\n\n for (const group of groups) {\n const groupOptionCount = countGroupOptions(group);\n\n if (\n pendingGroups.length > 0 &&\n pendingOptionCount + groupOptionCount > options.optionBudget\n ) {\n windows.push(createWindow(options.text, pendingGroups, options));\n pendingGroups = [];\n pendingOptionCount = 0;\n }\n\n pendingGroups.push(group);\n pendingOptionCount += groupOptionCount;\n }\n\n if (pendingGroups.length > 0) {\n windows.push(createWindow(options.text, pendingGroups, options));\n }\n\n return windows;\n}\n\nfunction countGroupOptions(group: CandidateGroup): number {\n return group.candidates.reduce(\n (total, candidate) => total + countWikimatchCandidateOptions(candidate),\n 0,\n );\n}\n\nfunction createWindow(\n text: string,\n groups: readonly CandidateGroup[],\n options: BuildWikimatchWindowsOptions,\n): WikimatchWindow {\n const groupStart = Math.min(...groups.map((group) => group.range.start));\n const groupEnd = Math.max(...groups.map((group) => group.range.end));\n const expandedRange = expandRangeByWords({\n rangeEnd: groupEnd,\n rangeStart: groupStart,\n text,\n words: options.contextWords,\n });\n\n return {\n baseOffset: expandedRange.start,\n candidates: groups.flatMap((group) => group.candidates),\n groups: groups.map((group, index) => ({\n candidateIds: group.candidates.map((candidate) => candidate.id),\n id: `g${index + 1}`,\n range: group.range,\n })),\n text: text.slice(expandedRange.start, expandedRange.end),\n };\n}\n\nfunction groupOverlappingCandidates(\n candidates: readonly WikimatchCandidate[],\n): readonly CandidateGroup[] {\n const groups: CandidateGroup[] = [];\n let current: CandidateGroup | undefined;\n\n for (const candidate of candidates) {\n if (current === undefined || candidate.range.start >= current.range.end) {\n current = {\n candidates: [candidate],\n range: candidate.range,\n };\n groups.push(current);\n continue;\n }\n\n current = {\n candidates: [...current.candidates, candidate],\n range: {\n end: Math.max(current.range.end, candidate.range.end),\n start: Math.min(current.range.start, candidate.range.start),\n },\n };\n groups[groups.length - 1] = current;\n }\n\n return groups;\n}\n\nfunction normalizeCandidates(\n candidates: readonly WikimatchCandidate[],\n): readonly WikimatchCandidate[] {\n return candidates\n .filter((candidate) => candidate.range.start < candidate.range.end)\n .sort(compareCandidate);\n}\n\nfunction compareCandidate(\n left: WikimatchCandidate,\n right: WikimatchCandidate,\n): number {\n return (\n left.range.start - right.range.start ||\n right.range.end - left.range.end ||\n left.id.localeCompare(right.id)\n );\n}\n"],"mappings":"AAAA,SAAS,0BAA0B;AACnC,SAAS,sCAAsC;AAexC,SAAS,sBACd,SAC4B;AAC5B,QAAM,SAAS;AAAA,IACb,oBAAoB,QAAQ,cAAc,CAAC,CAAC;AAAA,EAC9C;AACA,QAAM,UAA6B,CAAC;AACpC,MAAI,gBAAkC,CAAC;AACvC,MAAI,qBAAqB;AAEzB,aAAW,SAAS,QAAQ;AAC1B,UAAM,mBAAmB,kBAAkB,KAAK;AAEhD,QACE,cAAc,SAAS,KACvB,qBAAqB,mBAAmB,QAAQ,cAChD;AACA,cAAQ,KAAK,aAAa,QAAQ,MAAM,eAAe,OAAO,CAAC;AAC/D,sBAAgB,CAAC;AACjB,2BAAqB;AAAA,IACvB;AAEA,kBAAc,KAAK,KAAK;AACxB,0BAAsB;AAAA,EACxB;AAEA,MAAI,cAAc,SAAS,GAAG;AAC5B,YAAQ,KAAK,aAAa,QAAQ,MAAM,eAAe,OAAO,CAAC;AAAA,EACjE;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,OAA+B;AACxD,SAAO,MAAM,WAAW;AAAA,IACtB,CAAC,OAAO,cAAc,QAAQ,+BAA+B,SAAS;AAAA,IACtE;AAAA,EACF;AACF;AAEA,SAAS,aACP,MACA,QACA,SACiB;AACjB,QAAM,aAAa,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,MAAM,KAAK,CAAC;AACvE,QAAM,WAAW,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,MAAM,GAAG,CAAC;AACnE,QAAM,gBAAgB,mBAAmB;AAAA,IACvC,UAAU;AAAA,IACV,YAAY;AAAA,IACZ;AAAA,IACA,OAAO,QAAQ;AAAA,EACjB,CAAC;AAED,SAAO;AAAA,IACL,YAAY,cAAc;AAAA,IAC1B,YAAY,OAAO,QAAQ,CAAC,UAAU,MAAM,UAAU;AAAA,IACtD,QAAQ,OAAO,IAAI,CAAC,OAAO,WAAW;AAAA,MACpC,cAAc,MAAM,WAAW,IAAI,CAAC,cAAc,UAAU,EAAE;AAAA,MAC9D,IAAI,IAAI,QAAQ,CAAC;AAAA,MACjB,OAAO,MAAM;AAAA,IACf,EAAE;AAAA,IACF,MAAM,KAAK,MAAM,cAAc,OAAO,cAAc,GAAG;AAAA,EACzD;AACF;AAEA,SAAS,2BACP,YAC2B;AAC3B,QAAM,SAA2B,CAAC;AAClC,MAAI;AAEJ,aAAW,aAAa,YAAY;AAClC,QAAI,YAAY,UAAa,UAAU,MAAM,SAAS,QAAQ,MAAM,KAAK;AACvE,gBAAU;AAAA,QACR,YAAY,CAAC,SAAS;AAAA,QACtB,OAAO,UAAU;AAAA,MACnB;AACA,aAAO,KAAK,OAAO;AACnB;AAAA,IACF;AAEA,cAAU;AAAA,MACR,YAAY,CAAC,GAAG,QAAQ,YAAY,SAAS;AAAA,MAC7C,OAAO;AAAA,QACL,KAAK,KAAK,IAAI,QAAQ,MAAM,KAAK,UAAU,MAAM,GAAG;AAAA,QACpD,OAAO,KAAK,IAAI,QAAQ,MAAM,OAAO,UAAU,MAAM,KAAK;AAAA,MAC5D;AAAA,IACF;AACA,WAAO,OAAO,SAAS,CAAC,IAAI;AAAA,EAC9B;AAEA,SAAO;AACT;AAEA,SAAS,oBACP,YAC+B;AAC/B,SAAO,WACJ,OAAO,CAAC,cAAc,UAAU,MAAM,QAAQ,UAAU,MAAM,GAAG,EACjE,KAAK,gBAAgB;AAC1B;AAEA,SAAS,iBACP,MACA,OACQ;AACR,SACE,KAAK,MAAM,QAAQ,MAAM,MAAM,SAC/B,MAAM,MAAM,MAAM,KAAK,MAAM,OAC7B,KAAK,GAAG,cAAc,MAAM,EAAE;AAElC;","names":[]}
@@ -0,0 +1,16 @@
1
+ interface WordBoundary {
2
+ readonly end: number;
3
+ readonly start: number;
4
+ }
5
+ declare function listWordBoundaries(text: string): readonly WordBoundary[];
6
+ declare function expandRangeByWords(input: {
7
+ readonly rangeEnd: number;
8
+ readonly rangeStart: number;
9
+ readonly text: string;
10
+ readonly words: number;
11
+ }): {
12
+ readonly end: number;
13
+ readonly start: number;
14
+ };
15
+
16
+ export { type WordBoundary, expandRangeByWords, listWordBoundaries };
@@ -0,0 +1,66 @@
1
+ function listWordBoundaries(text) {
2
+ const segmenter = new Intl.Segmenter(void 0, {
3
+ granularity: "word"
4
+ });
5
+ const graphemeSegmenter = new Intl.Segmenter(void 0, {
6
+ granularity: "grapheme"
7
+ });
8
+ const words = [];
9
+ for (const segment of segmenter.segment(text)) {
10
+ if ("isWordLike" in segment && segment.isWordLike) {
11
+ words.push({
12
+ end: segment.index + segment.segment.length,
13
+ start: segment.index
14
+ });
15
+ }
16
+ }
17
+ if (words.length > 0) {
18
+ return words;
19
+ }
20
+ return [...graphemeSegmenter.segment(text)].filter((segment) => segment.segment.trim() !== "").map((segment) => ({
21
+ end: segment.index + segment.segment.length,
22
+ start: segment.index
23
+ }));
24
+ }
25
+ function expandRangeByWords(input) {
26
+ const wordBoundaries = listWordBoundaries(input.text);
27
+ if (wordBoundaries.length === 0) {
28
+ return {
29
+ end: input.text.length,
30
+ start: 0
31
+ };
32
+ }
33
+ const firstWordIndex = findWordIndexAtOrAfter(
34
+ wordBoundaries,
35
+ input.rangeStart
36
+ );
37
+ const lastWordIndex = findWordIndexBeforeOrAt(wordBoundaries, input.rangeEnd);
38
+ const halfBudget = Math.max(0, Math.floor(input.words / 2));
39
+ const startIndex = Math.max(0, firstWordIndex - halfBudget);
40
+ const endIndex = Math.min(
41
+ wordBoundaries.length - 1,
42
+ lastWordIndex + halfBudget
43
+ );
44
+ return {
45
+ end: wordBoundaries[endIndex]?.end ?? input.text.length,
46
+ start: wordBoundaries[startIndex]?.start ?? 0
47
+ };
48
+ }
49
+ function findWordIndexAtOrAfter(words, offset) {
50
+ const matched = words.findIndex((word) => word.end > offset);
51
+ return matched === -1 ? words.length - 1 : matched;
52
+ }
53
+ function findWordIndexBeforeOrAt(words, offset) {
54
+ for (let index = words.length - 1; index >= 0; index -= 1) {
55
+ const word = words[index];
56
+ if (word !== void 0 && word.start < offset) {
57
+ return index;
58
+ }
59
+ }
60
+ return 0;
61
+ }
62
+ export {
63
+ expandRangeByWords,
64
+ listWordBoundaries
65
+ };
66
+ //# sourceMappingURL=words.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/wikimatch/words.ts"],"sourcesContent":["export interface WordBoundary {\n readonly end: number;\n readonly start: number;\n}\n\nexport function listWordBoundaries(text: string): readonly WordBoundary[] {\n const segmenter = new Intl.Segmenter(undefined, {\n granularity: \"word\",\n });\n const graphemeSegmenter = new Intl.Segmenter(undefined, {\n granularity: \"grapheme\",\n });\n const words: WordBoundary[] = [];\n\n for (const segment of segmenter.segment(text)) {\n if (\"isWordLike\" in segment && segment.isWordLike) {\n words.push({\n end: segment.index + segment.segment.length,\n start: segment.index,\n });\n }\n }\n\n if (words.length > 0) {\n return words;\n }\n\n return [...graphemeSegmenter.segment(text)]\n .filter((segment) => segment.segment.trim() !== \"\")\n .map((segment) => ({\n end: segment.index + segment.segment.length,\n start: segment.index,\n }));\n}\n\nexport function expandRangeByWords(input: {\n readonly rangeEnd: number;\n readonly rangeStart: number;\n readonly text: string;\n readonly words: number;\n}): { readonly end: number; readonly start: number } {\n const wordBoundaries = listWordBoundaries(input.text);\n\n if (wordBoundaries.length === 0) {\n return {\n end: input.text.length,\n start: 0,\n };\n }\n\n const firstWordIndex = findWordIndexAtOrAfter(\n wordBoundaries,\n input.rangeStart,\n );\n const lastWordIndex = findWordIndexBeforeOrAt(wordBoundaries, input.rangeEnd);\n const halfBudget = Math.max(0, Math.floor(input.words / 2));\n const startIndex = Math.max(0, firstWordIndex - halfBudget);\n const endIndex = Math.min(\n wordBoundaries.length - 1,\n lastWordIndex + halfBudget,\n );\n\n return {\n end: wordBoundaries[endIndex]?.end ?? input.text.length,\n start: wordBoundaries[startIndex]?.start ?? 0,\n };\n}\n\nfunction findWordIndexAtOrAfter(\n words: readonly WordBoundary[],\n offset: number,\n): number {\n const matched = words.findIndex((word) => word.end > offset);\n\n return matched === -1 ? words.length - 1 : matched;\n}\n\nfunction findWordIndexBeforeOrAt(\n words: readonly WordBoundary[],\n offset: number,\n): number {\n for (let index = words.length - 1; index >= 0; index -= 1) {\n const word = words[index];\n\n if (word !== undefined && word.start < offset) {\n return index;\n }\n }\n\n return 0;\n}\n"],"mappings":"AAKO,SAAS,mBAAmB,MAAuC;AACxE,QAAM,YAAY,IAAI,KAAK,UAAU,QAAW;AAAA,IAC9C,aAAa;AAAA,EACf,CAAC;AACD,QAAM,oBAAoB,IAAI,KAAK,UAAU,QAAW;AAAA,IACtD,aAAa;AAAA,EACf,CAAC;AACD,QAAM,QAAwB,CAAC;AAE/B,aAAW,WAAW,UAAU,QAAQ,IAAI,GAAG;AAC7C,QAAI,gBAAgB,WAAW,QAAQ,YAAY;AACjD,YAAM,KAAK;AAAA,QACT,KAAK,QAAQ,QAAQ,QAAQ,QAAQ;AAAA,QACrC,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,GAAG,kBAAkB,QAAQ,IAAI,CAAC,EACvC,OAAO,CAAC,YAAY,QAAQ,QAAQ,KAAK,MAAM,EAAE,EACjD,IAAI,CAAC,aAAa;AAAA,IACjB,KAAK,QAAQ,QAAQ,QAAQ,QAAQ;AAAA,IACrC,OAAO,QAAQ;AAAA,EACjB,EAAE;AACN;AAEO,SAAS,mBAAmB,OAKkB;AACnD,QAAM,iBAAiB,mBAAmB,MAAM,IAAI;AAEpD,MAAI,eAAe,WAAW,GAAG;AAC/B,WAAO;AAAA,MACL,KAAK,MAAM,KAAK;AAAA,MAChB,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA,MAAM;AAAA,EACR;AACA,QAAM,gBAAgB,wBAAwB,gBAAgB,MAAM,QAAQ;AAC5E,QAAM,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,QAAQ,CAAC,CAAC;AAC1D,QAAM,aAAa,KAAK,IAAI,GAAG,iBAAiB,UAAU;AAC1D,QAAM,WAAW,KAAK;AAAA,IACpB,eAAe,SAAS;AAAA,IACxB,gBAAgB;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,KAAK,eAAe,QAAQ,GAAG,OAAO,MAAM,KAAK;AAAA,IACjD,OAAO,eAAe,UAAU,GAAG,SAAS;AAAA,EAC9C;AACF;AAEA,SAAS,uBACP,OACA,QACQ;AACR,QAAM,UAAU,MAAM,UAAU,CAAC,SAAS,KAAK,MAAM,MAAM;AAE3D,SAAO,YAAY,KAAK,MAAM,SAAS,IAAI;AAC7C;AAEA,SAAS,wBACP,OACA,QACQ;AACR,WAAS,QAAQ,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AACzD,UAAM,OAAO,MAAM,KAAK;AAExB,QAAI,SAAS,UAAa,KAAK,QAAQ,QAAQ;AAC7C,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
@@ -0,0 +1,18 @@
1
+ import { Database } from '../document/database.js';
2
+ import { GcContext, GcJobResult } from '../gc/types.js';
3
+ import { CachedQidRecord, CachedDisambiguationRecord } from './types.js';
4
+ import 'sqlite3';
5
+
6
+ declare class WikipageCache {
7
+ #private;
8
+ constructor(database: Database);
9
+ static open(path?: string): Promise<WikipageCache>;
10
+ close(): Promise<void>;
11
+ getQids(qids: readonly string[], language: string): Promise<ReadonlyMap<string, CachedQidRecord>>;
12
+ putQids(records: readonly CachedQidRecord[], language: string): Promise<void>;
13
+ getDisambiguations(qids: readonly string[], wiki: string): Promise<ReadonlyMap<string, CachedDisambiguationRecord>>;
14
+ putDisambiguations(records: readonly CachedDisambiguationRecord[], wiki: string): Promise<void>;
15
+ }
16
+ declare function runWikipageCacheGc(context: GcContext): Promise<GcJobResult>;
17
+
18
+ export { WikipageCache, runWikipageCacheGc };