@bendyline/gezel-inference 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (967) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -2
  3. package/dist/cache/adapter.d.ts +115 -0
  4. package/dist/cache/adapter.js +23 -0
  5. package/dist/cache/budget.d.ts +15 -0
  6. package/dist/cache/budget.js +31 -0
  7. package/dist/cache/controller.d.ts +205 -0
  8. package/dist/cache/controller.js +377 -0
  9. package/dist/catalog/LICENSE +21 -0
  10. package/dist/catalog/chat-models/bt/btl4-35b-q4/manifest.json +146 -0
  11. package/dist/catalog/chat-models/bt/btl4-35b-q4/versions/1.0.0/manifest.json +15 -0
  12. package/dist/catalog/chat-models/bt/btl4-35b-q4/versions/1.0.1/manifest.json +15 -0
  13. package/dist/catalog/chat-models/bt/btl4-compact-iq2/manifest.json +146 -0
  14. package/dist/catalog/chat-models/bt/btl4-compact-iq2/versions/1.0.0/manifest.json +15 -0
  15. package/dist/catalog/chat-models/bt/btl4-compact-iq2/versions/1.0.1/manifest.json +15 -0
  16. package/dist/catalog/chat-models/bt/btl4-compact-iq2/versions/1.0.2/manifest.json +15 -0
  17. package/dist/catalog/chat-models/de/deepseek-r1-8b-q4/manifest.json +166 -0
  18. package/dist/catalog/chat-models/de/deepseek-r1-8b-q4/versions/1.1.0/manifest.json +62 -0
  19. package/dist/catalog/chat-models/de/deepseek-r1-8b-q4/versions/1.1.1/manifest.json +61 -0
  20. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-mxfp4/manifest.json +125 -0
  21. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-mxfp4/versions/1.0.0/manifest.json +27 -0
  22. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2/manifest.json +125 -0
  23. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2/versions/1.0.0/manifest.json +27 -0
  24. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2/versions/1.1.0/manifest.json +27 -0
  25. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2q4/manifest.json +126 -0
  26. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2q4/versions/1.0.0/manifest.json +27 -0
  27. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q4/manifest.json +318 -0
  28. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q4/versions/1.0.0/manifest.json +225 -0
  29. package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q4/versions/1.1.0/manifest.json +225 -0
  30. package/dist/catalog/chat-models/ge/gemma4-12b-q4/manifest.json +249 -0
  31. package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.0.0/manifest.json +70 -0
  32. package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.1.0/manifest.json +72 -0
  33. package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.1.2/manifest.json +78 -0
  34. package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.1.3/manifest.json +78 -0
  35. package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.2.0/manifest.json +98 -0
  36. package/dist/catalog/chat-models/ge/gemma4-12b-q8/manifest.json +228 -0
  37. package/dist/catalog/chat-models/ge/gemma4-12b-q8/versions/1.0.0/manifest.json +72 -0
  38. package/dist/catalog/chat-models/ge/gemma4-12b-q8/versions/1.0.2/manifest.json +78 -0
  39. package/dist/catalog/chat-models/ge/gemma4-12b-q8/versions/1.0.3/manifest.json +78 -0
  40. package/dist/catalog/chat-models/ge/gemma4-12b-q8/versions/1.1.0/manifest.json +78 -0
  41. package/dist/catalog/chat-models/ge/gemma4-26b-q4/manifest.json +220 -0
  42. package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.1.0/manifest.json +75 -0
  43. package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.2.0/manifest.json +75 -0
  44. package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.2.1/manifest.json +80 -0
  45. package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.2.2/manifest.json +80 -0
  46. package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.3.0/manifest.json +81 -0
  47. package/dist/catalog/chat-models/ge/gemma4-31b-q4/manifest.json +226 -0
  48. package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.1.0/manifest.json +80 -0
  49. package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.1.1/manifest.json +82 -0
  50. package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.2.0/manifest.json +82 -0
  51. package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.2.1/manifest.json +95 -0
  52. package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.2.2/manifest.json +95 -0
  53. package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.3.0/manifest.json +86 -0
  54. package/dist/catalog/chat-models/ge/gemma4-e2b-q4/manifest.json +213 -0
  55. package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.1.0/manifest.json +67 -0
  56. package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.1.2/manifest.json +75 -0
  57. package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.2.0/manifest.json +71 -0
  58. package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.2.1/manifest.json +71 -0
  59. package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.3.0/manifest.json +71 -0
  60. package/dist/catalog/chat-models/ge/gemma4-e4b-q4/manifest.json +205 -0
  61. package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.1.0/manifest.json +72 -0
  62. package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.1.2/manifest.json +75 -0
  63. package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.2.0/manifest.json +76 -0
  64. package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.2.1/manifest.json +76 -0
  65. package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.3.0/manifest.json +76 -0
  66. package/dist/catalog/chat-models/gl/glm-5.2-754b-q2/manifest.json +127 -0
  67. package/dist/catalog/chat-models/gl/glm-5.2-754b-q2/versions/1.0.0/manifest.json +20 -0
  68. package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/manifest.json +140 -0
  69. package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/versions/1.0.0/manifest.json +23 -0
  70. package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/versions/1.0.1/manifest.json +26 -0
  71. package/dist/catalog/chat-models/gp/gpt-oss-120b-q4/manifest.json +247 -0
  72. package/dist/catalog/chat-models/gp/gpt-oss-120b-q4/versions/1.0.0/manifest.json +137 -0
  73. package/dist/catalog/chat-models/gp/gpt-oss-120b-q4/versions/1.1.0/manifest.json +135 -0
  74. package/dist/catalog/chat-models/gp/gpt-oss-20b-q4/manifest.json +195 -0
  75. package/dist/catalog/chat-models/gp/gpt-oss-20b-q4/versions/1.1.0/manifest.json +72 -0
  76. package/dist/catalog/chat-models/gp/gpt-oss-20b-q4/versions/1.1.1/manifest.json +71 -0
  77. package/dist/catalog/chat-models/gr/granite4.2-30b-q4/manifest.json +200 -0
  78. package/dist/catalog/chat-models/gr/granite4.2-30b-q4/versions/1.0.0/manifest.json +72 -0
  79. package/dist/catalog/chat-models/gr/granite4.2-3b-q4/manifest.json +196 -0
  80. package/dist/catalog/chat-models/gr/granite4.2-3b-q4/versions/1.0.0/manifest.json +57 -0
  81. package/dist/catalog/chat-models/gr/granite4.2-8b-q4/manifest.json +189 -0
  82. package/dist/catalog/chat-models/gr/granite4.2-8b-q4/versions/1.0.0/manifest.json +57 -0
  83. package/dist/catalog/chat-models/index.json +1 -0
  84. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q4/manifest.json +235 -0
  85. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q4/versions/1.0.0/manifest.json +124 -0
  86. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q4/versions/1.0.1/manifest.json +124 -0
  87. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q4/versions/1.0.2/manifest.json +123 -0
  88. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q6/manifest.json +257 -0
  89. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q6/versions/1.0.0/manifest.json +145 -0
  90. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q6/versions/1.0.1/manifest.json +145 -0
  91. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q8/manifest.json +285 -0
  92. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q8/versions/1.0.0/manifest.json +174 -0
  93. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q8/versions/1.0.1/manifest.json +174 -0
  94. package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q8/versions/1.0.2/manifest.json +173 -0
  95. package/dist/catalog/chat-models/lf/lfm2.5-2.6b-q4/manifest.json +162 -0
  96. package/dist/catalog/chat-models/lf/lfm2.5-2.6b-q4/versions/1.0.0/manifest.json +59 -0
  97. package/dist/catalog/chat-models/lf/lfm2.5-2.6b-q4/versions/1.0.1/manifest.json +58 -0
  98. package/dist/catalog/chat-models/ll/llama3.2-3b-q4/manifest.json +134 -0
  99. package/dist/catalog/chat-models/ll/llama3.2-3b-q4/versions/1.1.0/manifest.json +57 -0
  100. package/dist/catalog/chat-models/ll/llama3.2-3b-q4/versions/1.1.1/manifest.json +56 -0
  101. package/dist/catalog/chat-models/mi/minicpm5-1b-q4/manifest.json +156 -0
  102. package/dist/catalog/chat-models/mi/minicpm5-1b-q4/versions/1.0.0/manifest.json +57 -0
  103. package/dist/catalog/chat-models/mi/minicpm5-2b-q4/manifest.json +161 -0
  104. package/dist/catalog/chat-models/mi/minicpm5-2b-q4/versions/1.0.0/manifest.json +57 -0
  105. package/dist/catalog/chat-models/mi/mistral-7b-q4/manifest.json +159 -0
  106. package/dist/catalog/chat-models/mi/mistral-7b-q4/versions/1.1.0/manifest.json +62 -0
  107. package/dist/catalog/chat-models/mi/mistral-7b-q4/versions/1.1.1/manifest.json +61 -0
  108. package/dist/catalog/chat-models/mi/mistral-medium-3.5-128b-q4/manifest.json +275 -0
  109. package/dist/catalog/chat-models/mi/mistral-medium-3.5-128b-q4/versions/1.0.0/manifest.json +154 -0
  110. package/dist/catalog/chat-models/mi/mistral-medium-3.5-128b-q4/versions/1.0.1/manifest.json +153 -0
  111. package/dist/catalog/chat-models/mu/muse-glimmer-30b-q4/manifest.json +135 -0
  112. package/dist/catalog/chat-models/mu/muse-glimmer-30b-q4/versions/1.0.0/manifest.json +20 -0
  113. package/dist/catalog/chat-models/mu/muse-glimmer-30b-q4/versions/1.0.1/manifest.json +20 -0
  114. package/dist/catalog/chat-models/mu/muse-glimmer-30b-q4/versions/1.0.2/manifest.json +20 -0
  115. package/dist/catalog/chat-models/na/nanbeige4.2-3b-q4/manifest.json +138 -0
  116. package/dist/catalog/chat-models/na/nanbeige4.2-3b-q4/versions/1.0.0/manifest.json +14 -0
  117. package/dist/catalog/chat-models/ne/nemotron3-nano-30b-q4/manifest.json +212 -0
  118. package/dist/catalog/chat-models/ne/nemotron3-nano-30b-q4/versions/1.0.0/manifest.json +94 -0
  119. package/dist/catalog/chat-models/ne/nemotron3-nano-30b-q4/versions/1.0.1/manifest.json +94 -0
  120. package/dist/catalog/chat-models/ne/nemotron3-nano-30b-q4/versions/1.0.2/manifest.json +93 -0
  121. package/dist/catalog/chat-models/ne/nemotron3-super-120b-q4/manifest.json +135 -0
  122. package/dist/catalog/chat-models/ne/nemotron3-super-120b-q4/versions/1.0.0/manifest.json +30 -0
  123. package/dist/catalog/chat-models/ne/nemotron3-super-120b-q4/versions/1.0.1/manifest.json +30 -0
  124. package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q4/manifest.json +192 -0
  125. package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q4/versions/1.0.0/manifest.json +74 -0
  126. package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q4/versions/1.0.1/manifest.json +73 -0
  127. package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q8/manifest.json +207 -0
  128. package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q8/versions/1.0.0/manifest.json +89 -0
  129. package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q8/versions/1.0.1/manifest.json +88 -0
  130. package/dist/catalog/chat-models/or/ornith-35b-q4/manifest.json +224 -0
  131. package/dist/catalog/chat-models/or/ornith-35b-q4/versions/1.0.0/manifest.json +94 -0
  132. package/dist/catalog/chat-models/or/ornith-35b-q4/versions/1.0.1/manifest.json +93 -0
  133. package/dist/catalog/chat-models/or/ornith-35b-q8/manifest.json +244 -0
  134. package/dist/catalog/chat-models/or/ornith-35b-q8/versions/1.0.0/manifest.json +114 -0
  135. package/dist/catalog/chat-models/or/ornith-35b-q8/versions/1.0.1/manifest.json +113 -0
  136. package/dist/catalog/chat-models/or/ornith-9b-q4/manifest.json +215 -0
  137. package/dist/catalog/chat-models/or/ornith-9b-q4/versions/1.0.0/manifest.json +84 -0
  138. package/dist/catalog/chat-models/or/ornith-9b-q4/versions/1.0.1/manifest.json +83 -0
  139. package/dist/catalog/chat-models/or/ornith1.5-35b-a3b-q4/manifest.json +208 -0
  140. package/dist/catalog/chat-models/or/ornith1.5-35b-a3b-q4/versions/1.0.0/manifest.json +74 -0
  141. package/dist/catalog/chat-models/or/ornith1.5-35b-a3b-q8/manifest.json +223 -0
  142. package/dist/catalog/chat-models/or/ornith1.5-35b-a3b-q8/versions/1.0.0/manifest.json +89 -0
  143. package/dist/catalog/chat-models/or/ornith1.5-9b-q4/manifest.json +187 -0
  144. package/dist/catalog/chat-models/or/ornith1.5-9b-q4/versions/1.0.0/manifest.json +53 -0
  145. package/dist/catalog/chat-models/or/ornith1.5-9b-q4/versions/1.0.1/manifest.json +77 -0
  146. package/dist/catalog/chat-models/or/ornith1.5-9b-q8/manifest.json +192 -0
  147. package/dist/catalog/chat-models/or/ornith1.5-9b-q8/versions/1.0.0/manifest.json +58 -0
  148. package/dist/catalog/chat-models/or/ornith1.5-9b-q8/versions/1.0.1/manifest.json +82 -0
  149. package/dist/catalog/chat-models/qw/qwen3.5-0.8b-q4/manifest.json +192 -0
  150. package/dist/catalog/chat-models/qw/qwen3.5-0.8b-q4/versions/1.0.0/manifest.json +75 -0
  151. package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/manifest.json +315 -0
  152. package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.0/manifest.json +164 -0
  153. package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.1/manifest.json +164 -0
  154. package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.2/manifest.json +164 -0
  155. package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.3/manifest.json +163 -0
  156. package/dist/catalog/chat-models/qw/qwen3.5-27b-q4/manifest.json +217 -0
  157. package/dist/catalog/chat-models/qw/qwen3.5-27b-q4/versions/1.0.0/manifest.json +90 -0
  158. package/dist/catalog/chat-models/qw/qwen3.5-2b-q4/manifest.json +194 -0
  159. package/dist/catalog/chat-models/qw/qwen3.5-2b-q4/versions/1.1.0/manifest.json +77 -0
  160. package/dist/catalog/chat-models/qw/qwen3.5-2b-q4/versions/1.1.2/manifest.json +76 -0
  161. package/dist/catalog/chat-models/qw/qwen3.5-2b-q4/versions/1.1.3/manifest.json +76 -0
  162. package/dist/catalog/chat-models/qw/qwen3.5-4b-q4/manifest.json +188 -0
  163. package/dist/catalog/chat-models/qw/qwen3.5-4b-q4/versions/1.1.0/manifest.json +77 -0
  164. package/dist/catalog/chat-models/qw/qwen3.5-4b-q4/versions/1.1.2/manifest.json +76 -0
  165. package/dist/catalog/chat-models/qw/qwen3.5-4b-q4/versions/1.1.3/manifest.json +76 -0
  166. package/dist/catalog/chat-models/qw/qwen3.5-9b-q4/manifest.json +205 -0
  167. package/dist/catalog/chat-models/qw/qwen3.5-9b-q4/versions/1.1.0/manifest.json +82 -0
  168. package/dist/catalog/chat-models/qw/qwen3.5-9b-q4/versions/1.1.2/manifest.json +81 -0
  169. package/dist/catalog/chat-models/qw/qwen3.5-9b-q4/versions/1.1.3/manifest.json +81 -0
  170. package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/manifest.json +230 -0
  171. package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/versions/1.1.0/manifest.json +92 -0
  172. package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/versions/1.1.4/manifest.json +91 -0
  173. package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/versions/1.1.5/manifest.json +91 -0
  174. package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/versions/1.1.6/manifest.json +115 -0
  175. package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/manifest.json +240 -0
  176. package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/versions/1.0.0/manifest.json +102 -0
  177. package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/versions/1.0.2/manifest.json +103 -0
  178. package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/versions/1.0.3/manifest.json +103 -0
  179. package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/versions/1.0.4/manifest.json +127 -0
  180. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/manifest.json +233 -0
  181. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.0/manifest.json +92 -0
  182. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.1/manifest.json +93 -0
  183. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.2/manifest.json +93 -0
  184. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.3/manifest.json +117 -0
  185. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/manifest.json +252 -0
  186. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.0/manifest.json +112 -0
  187. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.1/manifest.json +113 -0
  188. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.2/manifest.json +113 -0
  189. package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.3/manifest.json +137 -0
  190. package/dist/catalog/chat-models/qw/qwen3.8-27b-iq1-s/manifest.json +195 -0
  191. package/dist/catalog/chat-models/qw/qwen3.8-27b-iq1-s/versions/1.0.0/manifest.json +19 -0
  192. package/dist/catalog/chat-models/qw/qwen3.8-27b-q2/manifest.json +194 -0
  193. package/dist/catalog/chat-models/qw/qwen3.8-27b-q2/versions/1.0.0/manifest.json +19 -0
  194. package/dist/catalog/chat-models/qw/qwen3.8-27b-q3/manifest.json +194 -0
  195. package/dist/catalog/chat-models/qw/qwen3.8-27b-q3/versions/1.0.0/manifest.json +19 -0
  196. package/dist/catalog/chat-models/qw/qwen3.8-27b-q3/versions/1.0.1/manifest.json +19 -0
  197. package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/manifest.json +291 -0
  198. package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.0/manifest.json +20 -0
  199. package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.1/manifest.json +93 -0
  200. package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.2/manifest.json +92 -0
  201. package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.3/manifest.json +116 -0
  202. package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.4/manifest.json +116 -0
  203. package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.5/manifest.json +116 -0
  204. package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/manifest.json +278 -0
  205. package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/versions/1.0.0/manifest.json +20 -0
  206. package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/versions/1.0.1/manifest.json +104 -0
  207. package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/versions/1.0.2/manifest.json +103 -0
  208. package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/versions/1.0.3/manifest.json +127 -0
  209. package/dist/catalog/chat-models/qw/qwen3.8-27b-q8/manifest.json +278 -0
  210. package/dist/catalog/chat-models/qw/qwen3.8-27b-q8/versions/1.0.0/manifest.json +113 -0
  211. package/dist/catalog/chat-models/qw/qwen3.8-27b-q8/versions/1.0.1/manifest.json +113 -0
  212. package/dist/catalog/chat-models/qw/qwen3.8-27b-q8/versions/1.0.2/manifest.json +137 -0
  213. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq3/manifest.json +221 -0
  214. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq3/versions/1.0.0/manifest.json +36 -0
  215. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq4/manifest.json +429 -0
  216. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq4/versions/1.0.0/manifest.json +36 -0
  217. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq4/versions/1.1.0/manifest.json +205 -0
  218. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq4/versions/1.1.1/manifest.json +244 -0
  219. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-q2/manifest.json +203 -0
  220. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-q2/versions/1.0.0/manifest.json +21 -0
  221. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-q2/versions/1.0.1/manifest.json +31 -0
  222. package/dist/catalog/chat-models/qw/qwen3.8-flash-next-q2/versions/1.0.2/manifest.json +30 -0
  223. package/dist/catalog/chat-models/raw-index.json +1 -0
  224. package/dist/catalog/chat-models/ta/talkie-1930-13b-q4/manifest.json +79 -0
  225. package/dist/catalog/chat-models/ta/talkie-1930-13b-q4/versions/1.0.0/manifest.json +15 -0
  226. package/dist/catalog/chat-models/ta/talkie-1930-13b-q4/versions/1.0.1/manifest.json +15 -0
  227. package/dist/catalog/chat-models/te/ternary-bonsai-27b-q2/manifest.json +204 -0
  228. package/dist/catalog/chat-models/te/ternary-bonsai-27b-q2/versions/1.0.0/manifest.json +70 -0
  229. package/dist/catalog/chat-models/te/ternary-bonsai-27b-q2/versions/1.0.1/manifest.json +70 -0
  230. package/dist/catalog/chat-models/un/underdog-saluki-27b-iq2-mix/manifest.json +164 -0
  231. package/dist/catalog/chat-models/un/underdog-saluki-27b-iq2-mix/versions/1.0.0/manifest.json +14 -0
  232. package/dist/catalog/knowledge-catalogs/be/bendyline-how-to-books/manifest.json +26 -0
  233. package/dist/catalog/knowledge-catalogs/be/bendyline-how-to-books/versions/2026.10.8/manifest.json +8950 -0
  234. package/dist/catalog/knowledge-catalogs/ca/caselaw-alaska-part-0001/manifest.json +24 -0
  235. package/dist/catalog/knowledge-catalogs/ca/caselaw-alaska-part-0001/versions/2026.10.1/manifest.json +658 -0
  236. package/dist/catalog/knowledge-catalogs/ca/caselaw-nevada-part-0001/manifest.json +24 -0
  237. package/dist/catalog/knowledge-catalogs/ca/caselaw-nevada-part-0001/versions/2026.10.1/manifest.json +666 -0
  238. package/dist/catalog/knowledge-catalogs/ca/caselaw-us-300-399-part-0001/manifest.json +24 -0
  239. package/dist/catalog/knowledge-catalogs/ca/caselaw-us-300-399-part-0001/versions/2026.10.2/manifest.json +182 -0
  240. package/dist/catalog/knowledge-catalogs/ca/caselaw-us-347-349/manifest.json +25 -0
  241. package/dist/catalog/knowledge-catalogs/ca/caselaw-us-347-349/versions/2026.10.5/manifest.json +38 -0
  242. package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0001/manifest.json +24 -0
  243. package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0001/versions/2026.10.1/manifest.json +558 -0
  244. package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0002/manifest.json +24 -0
  245. package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0002/versions/2026.10.1/manifest.json +258 -0
  246. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0001/manifest.json +24 -0
  247. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0001/versions/2026.10.1/manifest.json +318 -0
  248. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0002/manifest.json +24 -0
  249. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0002/versions/2026.10.1/manifest.json +266 -0
  250. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0003/manifest.json +24 -0
  251. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0003/versions/2026.10.1/manifest.json +186 -0
  252. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0004/manifest.json +24 -0
  253. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0004/versions/2026.10.1/manifest.json +138 -0
  254. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0005/manifest.json +24 -0
  255. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0005/versions/2026.10.1/manifest.json +138 -0
  256. package/dist/catalog/knowledge-catalogs/ca/caselaw-wyoming-part-0001/manifest.json +24 -0
  257. package/dist/catalog/knowledge-catalogs/ca/caselaw-wyoming-part-0001/versions/2026.10.3/manifest.json +626 -0
  258. package/dist/catalog/knowledge-catalogs/index.json +1 -0
  259. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-aspnet-core-en/manifest.json +22 -0
  260. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-aspnet-core-en/versions/2026.10.16/manifest.json +18270 -0
  261. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-ai-platform-en/manifest.json +23 -0
  262. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-ai-platform-en/versions/2026.10.16/manifest.json +1098 -0
  263. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-apps-compute-en/manifest.json +23 -0
  264. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-apps-compute-en/versions/2026.10.16/manifest.json +722 -0
  265. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-data-aiot-en/manifest.json +23 -0
  266. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-data-aiot-en/versions/2026.10.16/manifest.json +530 -0
  267. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-management-hybrid-en/manifest.json +23 -0
  268. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-management-hybrid-en/versions/2026.10.16/manifest.json +602 -0
  269. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-network-security-en/manifest.json +23 -0
  270. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-network-security-en/versions/2026.10.16/manifest.json +250 -0
  271. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-dotnet-en/manifest.json +22 -0
  272. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-dotnet-en/versions/2026.10.16/manifest.json +16794 -0
  273. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-entity-framework-en/manifest.json +22 -0
  274. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-entity-framework-en/versions/2026.10.16/manifest.json +1106 -0
  275. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-microsoft-365-en/manifest.json +22 -0
  276. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-microsoft-365-en/versions/2026.10.16/manifest.json +234 -0
  277. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-powershell-en/manifest.json +22 -0
  278. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-powershell-en/versions/2026.10.16/manifest.json +522 -0
  279. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-sql-server-en/manifest.json +22 -0
  280. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-sql-server-en/versions/2026.10.16/manifest.json +1850 -0
  281. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-apps-en/manifest.json +22 -0
  282. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-apps-en/versions/2026.10.16/manifest.json +1734 -0
  283. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-server-en/manifest.json +22 -0
  284. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-server-en/versions/2026.10.16/manifest.json +774 -0
  285. package/dist/catalog/knowledge-catalogs/raw-index.json +1 -0
  286. package/dist/catalog/knowledge-catalogs/re/regional-american-south/art.json +12 -0
  287. package/dist/catalog/knowledge-catalogs/re/regional-american-south/logo.webp +0 -0
  288. package/dist/catalog/knowledge-catalogs/re/regional-american-south/manifest.json +48 -0
  289. package/dist/catalog/knowledge-catalogs/re/regional-american-south/versions/2026.10.3/manifest.json +133 -0
  290. package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/art.json +12 -0
  291. package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/logo.webp +0 -0
  292. package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/manifest.json +48 -0
  293. package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/versions/2026.10.3/manifest.json +133 -0
  294. package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/art.json +12 -0
  295. package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/logo.webp +0 -0
  296. package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/manifest.json +48 -0
  297. package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/versions/2026.10.3/manifest.json +133 -0
  298. package/dist/catalog/knowledge-catalogs/re/regional-brazil/art.json +12 -0
  299. package/dist/catalog/knowledge-catalogs/re/regional-brazil/logo.webp +0 -0
  300. package/dist/catalog/knowledge-catalogs/re/regional-brazil/manifest.json +48 -0
  301. package/dist/catalog/knowledge-catalogs/re/regional-brazil/versions/2026.10.3/manifest.json +133 -0
  302. package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/art.json +12 -0
  303. package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/logo.webp +0 -0
  304. package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/manifest.json +48 -0
  305. package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/versions/2026.10.3/manifest.json +133 -0
  306. package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/art.json +12 -0
  307. package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/logo.webp +0 -0
  308. package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/manifest.json +48 -0
  309. package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/versions/2026.10.3/manifest.json +133 -0
  310. package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/art.json +12 -0
  311. package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/logo.webp +0 -0
  312. package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/manifest.json +48 -0
  313. package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/versions/2026.10.3/manifest.json +133 -0
  314. package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/art.json +12 -0
  315. package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/logo.webp +0 -0
  316. package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/manifest.json +48 -0
  317. package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/versions/2026.10.3/manifest.json +133 -0
  318. package/dist/catalog/knowledge-catalogs/re/regional-east-asia/art.json +12 -0
  319. package/dist/catalog/knowledge-catalogs/re/regional-east-asia/logo.webp +0 -0
  320. package/dist/catalog/knowledge-catalogs/re/regional-east-asia/manifest.json +48 -0
  321. package/dist/catalog/knowledge-catalogs/re/regional-east-asia/versions/2026.10.3/manifest.json +133 -0
  322. package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/art.json +12 -0
  323. package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/logo.webp +0 -0
  324. package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/manifest.json +48 -0
  325. package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/versions/2026.10.3/manifest.json +133 -0
  326. package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/art.json +12 -0
  327. package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/logo.webp +0 -0
  328. package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/manifest.json +48 -0
  329. package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/versions/2026.10.3/manifest.json +133 -0
  330. package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/art.json +12 -0
  331. package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/logo.webp +0 -0
  332. package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/manifest.json +48 -0
  333. package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/versions/2026.10.3/manifest.json +133 -0
  334. package/dist/catalog/knowledge-catalogs/re/regional-middle-east/art.json +12 -0
  335. package/dist/catalog/knowledge-catalogs/re/regional-middle-east/logo.webp +0 -0
  336. package/dist/catalog/knowledge-catalogs/re/regional-middle-east/manifest.json +48 -0
  337. package/dist/catalog/knowledge-catalogs/re/regional-middle-east/versions/2026.10.3/manifest.json +133 -0
  338. package/dist/catalog/knowledge-catalogs/re/regional-midwest/art.json +12 -0
  339. package/dist/catalog/knowledge-catalogs/re/regional-midwest/logo.webp +0 -0
  340. package/dist/catalog/knowledge-catalogs/re/regional-midwest/manifest.json +48 -0
  341. package/dist/catalog/knowledge-catalogs/re/regional-midwest/versions/2026.10.3/manifest.json +133 -0
  342. package/dist/catalog/knowledge-catalogs/re/regional-north-africa/art.json +12 -0
  343. package/dist/catalog/knowledge-catalogs/re/regional-north-africa/logo.webp +0 -0
  344. package/dist/catalog/knowledge-catalogs/re/regional-north-africa/manifest.json +48 -0
  345. package/dist/catalog/knowledge-catalogs/re/regional-north-africa/versions/2026.10.3/manifest.json +133 -0
  346. package/dist/catalog/knowledge-catalogs/re/regional-northeast/art.json +12 -0
  347. package/dist/catalog/knowledge-catalogs/re/regional-northeast/logo.webp +0 -0
  348. package/dist/catalog/knowledge-catalogs/re/regional-northeast/manifest.json +48 -0
  349. package/dist/catalog/knowledge-catalogs/re/regional-northeast/versions/2026.10.3/manifest.json +133 -0
  350. package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/art.json +12 -0
  351. package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/logo.webp +0 -0
  352. package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/manifest.json +48 -0
  353. package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/versions/2026.10.3/manifest.json +133 -0
  354. package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/art.json +12 -0
  355. package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/logo.webp +0 -0
  356. package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/manifest.json +48 -0
  357. package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/versions/2026.10.3/manifest.json +133 -0
  358. package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/art.json +12 -0
  359. package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/logo.webp +0 -0
  360. package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/manifest.json +48 -0
  361. package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/versions/2026.10.3/manifest.json +133 -0
  362. package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/art.json +12 -0
  363. package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/logo.webp +0 -0
  364. package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/manifest.json +48 -0
  365. package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/versions/2026.10.3/manifest.json +133 -0
  366. package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/art.json +12 -0
  367. package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/logo.webp +0 -0
  368. package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/manifest.json +48 -0
  369. package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/versions/2026.10.3/manifest.json +133 -0
  370. package/dist/catalog/knowledge-catalogs/re/regional-south-asia/art.json +12 -0
  371. package/dist/catalog/knowledge-catalogs/re/regional-south-asia/logo.webp +0 -0
  372. package/dist/catalog/knowledge-catalogs/re/regional-south-asia/manifest.json +48 -0
  373. package/dist/catalog/knowledge-catalogs/re/regional-south-asia/versions/2026.10.3/manifest.json +133 -0
  374. package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/art.json +12 -0
  375. package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/logo.webp +0 -0
  376. package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/manifest.json +48 -0
  377. package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/versions/2026.10.3/manifest.json +133 -0
  378. package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/art.json +12 -0
  379. package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/logo.webp +0 -0
  380. package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/manifest.json +48 -0
  381. package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/versions/2026.10.3/manifest.json +133 -0
  382. package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/art.json +12 -0
  383. package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/logo.webp +0 -0
  384. package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/manifest.json +48 -0
  385. package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/versions/2026.10.3/manifest.json +133 -0
  386. package/dist/catalog/knowledge-catalogs/re/regional-western-europe/art.json +12 -0
  387. package/dist/catalog/knowledge-catalogs/re/regional-western-europe/logo.webp +0 -0
  388. package/dist/catalog/knowledge-catalogs/re/regional-western-europe/manifest.json +48 -0
  389. package/dist/catalog/knowledge-catalogs/re/regional-western-europe/versions/2026.10.3/manifest.json +133 -0
  390. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/art.json +12 -0
  391. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/logo.webp +0 -0
  392. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/manifest.json +28 -0
  393. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.4.2/manifest.json +53 -0
  394. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.4.3/manifest.json +885 -0
  395. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.4.5/manifest.json +157 -0
  396. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/art.json +11 -0
  397. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/logo.webp +0 -0
  398. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/manifest.json +32 -0
  399. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.4.2/manifest.json +69 -0
  400. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.4.3/manifest.json +741 -0
  401. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.4.5/manifest.json +173 -0
  402. package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/art.json +12 -0
  403. package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/logo.webp +0 -0
  404. package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/manifest.json +69 -0
  405. package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/versions/2026.4.4/manifest.json +217 -0
  406. package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/versions/2026.4.5/manifest.json +217 -0
  407. package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/art.json +12 -0
  408. package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/logo.webp +0 -0
  409. package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/manifest.json +64 -0
  410. package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/versions/2026.4.4/manifest.json +197 -0
  411. package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/versions/2026.4.5/manifest.json +197 -0
  412. package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/art.json +12 -0
  413. package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/logo.webp +0 -0
  414. package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/manifest.json +64 -0
  415. package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/versions/2026.4.5/manifest.json +197 -0
  416. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/art.json +11 -0
  417. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/logo.webp +0 -0
  418. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/manifest.json +29 -0
  419. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.4.2/manifest.json +57 -0
  420. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.4.3/manifest.json +925 -0
  421. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.4.5/manifest.json +185 -0
  422. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/art.json +12 -0
  423. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/logo.webp +0 -0
  424. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/manifest.json +28 -0
  425. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.4.2/manifest.json +53 -0
  426. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.4.3/manifest.json +1665 -0
  427. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.4.5/manifest.json +133 -0
  428. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/art.json +12 -0
  429. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/logo.webp +0 -0
  430. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/manifest.json +29 -0
  431. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.4.2/manifest.json +57 -0
  432. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.4.3/manifest.json +1233 -0
  433. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.4.5/manifest.json +141 -0
  434. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/art.json +11 -0
  435. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/logo.webp +0 -0
  436. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/manifest.json +29 -0
  437. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.4.2/manifest.json +57 -0
  438. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.4.3/manifest.json +493 -0
  439. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.4.5/manifest.json +185 -0
  440. package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/art.json +12 -0
  441. package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/logo.webp +0 -0
  442. package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/manifest.json +63 -0
  443. package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/versions/2026.4.4/manifest.json +193 -0
  444. package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/versions/2026.4.5/manifest.json +193 -0
  445. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/art.json +12 -0
  446. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/logo.webp +0 -0
  447. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/manifest.json +30 -0
  448. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.4.2/manifest.json +61 -0
  449. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.4.3/manifest.json +665 -0
  450. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.4.5/manifest.json +177 -0
  451. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/art.json +12 -0
  452. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/logo.webp +0 -0
  453. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/manifest.json +29 -0
  454. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.4.2/manifest.json +57 -0
  455. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.4.3/manifest.json +745 -0
  456. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.4.5/manifest.json +185 -0
  457. package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/art.json +12 -0
  458. package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/logo.webp +0 -0
  459. package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/manifest.json +62 -0
  460. package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/versions/2026.4.4/manifest.json +189 -0
  461. package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/versions/2026.4.5/manifest.json +189 -0
  462. package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/art.json +12 -0
  463. package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/logo.webp +0 -0
  464. package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/manifest.json +64 -0
  465. package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/versions/2026.4.5/manifest.json +197 -0
  466. package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/art.json +12 -0
  467. package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/logo.webp +0 -0
  468. package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/manifest.json +64 -0
  469. package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/versions/2026.4.4/manifest.json +197 -0
  470. package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/versions/2026.4.5/manifest.json +197 -0
  471. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/art.json +12 -0
  472. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/logo.webp +0 -0
  473. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/manifest.json +30 -0
  474. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.4.2/manifest.json +61 -0
  475. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.4.3/manifest.json +1253 -0
  476. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.4.5/manifest.json +189 -0
  477. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/art.json +12 -0
  478. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/logo.webp +0 -0
  479. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/manifest.json +29 -0
  480. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.4.2/manifest.json +57 -0
  481. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.4.3/manifest.json +1957 -0
  482. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.4.5/manifest.json +185 -0
  483. package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/art.json +12 -0
  484. package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/logo.webp +0 -0
  485. package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/manifest.json +63 -0
  486. package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/versions/2026.4.5/manifest.json +193 -0
  487. package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/art.json +11 -0
  488. package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/logo.webp +0 -0
  489. package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/manifest.json +45 -0
  490. package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/versions/2026.4.4/manifest.json +121 -0
  491. package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/versions/2026.4.5/manifest.json +173 -0
  492. package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/art.json +12 -0
  493. package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/logo.webp +0 -0
  494. package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/manifest.json +62 -0
  495. package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/versions/2026.4.4/manifest.json +189 -0
  496. package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/versions/2026.4.5/manifest.json +189 -0
  497. package/dist/catalog/provenance.json +8 -0
  498. package/dist/chat/catalog-model-lookup.d.ts +21 -0
  499. package/dist/chat/catalog-model-lookup.js +48 -0
  500. package/dist/chat/local-model-tier.d.ts +1 -0
  501. package/dist/chat/local-model-tier.js +2 -0
  502. package/dist/chat/vision-capability.d.ts +1 -0
  503. package/dist/chat/vision-capability.js +3 -0
  504. package/dist/engine-components.d.ts +30 -0
  505. package/dist/engine-components.js +144 -0
  506. package/dist/engines/electron-native-reuse.d.ts +65 -0
  507. package/dist/engines/electron-native-reuse.js +305 -0
  508. package/dist/engines/native-file-manifest.json +1320 -0
  509. package/dist/engines/native-manifest.d.ts +70 -0
  510. package/dist/engines/native-manifest.js +98 -0
  511. package/dist/engines/registry.d.ts +88 -0
  512. package/dist/engines/registry.js +217 -0
  513. package/dist/engines/resolver.d.ts +121 -0
  514. package/dist/engines/resolver.js +894 -0
  515. package/dist/engines/signature.d.ts +85 -0
  516. package/dist/engines/signature.js +231 -0
  517. package/dist/fs/atomic.d.ts +53 -0
  518. package/dist/fs/atomic.js +202 -0
  519. package/dist/fs/config-store.d.ts +14 -0
  520. package/dist/fs/config-store.js +101 -0
  521. package/dist/fs/home-permissions.d.ts +18 -0
  522. package/dist/fs/home-permissions.js +27 -0
  523. package/dist/fs/safe-paths.d.ts +107 -0
  524. package/dist/fs/safe-paths.js +264 -0
  525. package/dist/fs/security-json.d.ts +13 -0
  526. package/dist/fs/security-json.js +67 -0
  527. package/dist/http/auth-context.d.ts +23 -0
  528. package/dist/http/auth-context.js +1 -0
  529. package/dist/http/engine-runtime-context.d.ts +30 -0
  530. package/dist/http/engine-runtime-context.js +1 -0
  531. package/dist/http/external-conversation-contract.d.ts +49 -0
  532. package/dist/http/external-conversation-contract.js +1 -0
  533. package/dist/http/external-conversation-headers.d.ts +11 -0
  534. package/dist/http/external-conversation-headers.js +11 -0
  535. package/dist/http/inference-context.d.ts +36 -0
  536. package/dist/http/inference-context.js +1 -0
  537. package/dist/http/model-inventory-cache.d.ts +8 -0
  538. package/dist/http/model-inventory-cache.js +8 -0
  539. package/dist/http/openai-compat/action-ledger.d.ts +15 -0
  540. package/dist/http/openai-compat/action-ledger.js +119 -0
  541. package/dist/http/openai-compat/apple-model.d.ts +3 -0
  542. package/dist/http/openai-compat/apple-model.js +44 -0
  543. package/dist/http/openai-compat/caller-owned-profile.d.ts +7 -0
  544. package/dist/http/openai-compat/caller-owned-profile.js +18 -0
  545. package/dist/http/openai-compat/chat-progress.d.ts +9 -0
  546. package/dist/http/openai-compat/chat-progress.js +69 -0
  547. package/dist/http/openai-compat/chat-target.d.ts +76 -0
  548. package/dist/http/openai-compat/chat-target.js +97 -0
  549. package/dist/http/openai-compat/embeddings.d.ts +37 -0
  550. package/dist/http/openai-compat/embeddings.js +86 -0
  551. package/dist/http/openai-compat/request-tuning.d.ts +35 -0
  552. package/dist/http/openai-compat/request-tuning.js +87 -0
  553. package/dist/http/openai-compat/responses-streaming.d.ts +351 -0
  554. package/dist/http/openai-compat/responses-streaming.js +717 -0
  555. package/dist/http/openai-compat/responses-translate.d.ts +215 -0
  556. package/dist/http/openai-compat/responses-translate.js +377 -0
  557. package/dist/http/openai-compat/streaming-telemetry.d.ts +30 -0
  558. package/dist/http/openai-compat/streaming-telemetry.js +88 -0
  559. package/dist/http/openai-compat/streaming.d.ts +141 -0
  560. package/dist/http/openai-compat/streaming.js +687 -0
  561. package/dist/http/openai-compat/tool-call-stream-filter.d.ts +33 -0
  562. package/dist/http/openai-compat/tool-call-stream-filter.js +110 -0
  563. package/dist/http/openai-compat/translate.d.ts +254 -0
  564. package/dist/http/openai-compat/translate.js +485 -0
  565. package/dist/http/routes/engines.d.ts +13 -0
  566. package/dist/http/routes/engines.js +366 -0
  567. package/dist/http/routes/machine-engine-proxy.d.ts +26 -0
  568. package/dist/http/routes/machine-engine-proxy.js +43 -0
  569. package/dist/http/routes/model-bundles.d.ts +4 -0
  570. package/dist/http/routes/model-bundles.js +190 -0
  571. package/dist/http/routes/v1-chat.d.ts +72 -0
  572. package/dist/http/routes/v1-chat.js +645 -0
  573. package/dist/http/routes/v1-embeddings.d.ts +3 -0
  574. package/dist/http/routes/v1-embeddings.js +82 -0
  575. package/dist/http/routes/v1-knowledge.d.ts +4 -0
  576. package/dist/http/routes/v1-knowledge.js +304 -0
  577. package/dist/http/routes/v1-models-ensure.d.ts +32 -0
  578. package/dist/http/routes/v1-models-ensure.js +122 -0
  579. package/dist/http/routes/v1-models.d.ts +8 -0
  580. package/dist/http/routes/v1-models.js +189 -0
  581. package/dist/http/routes/v1-responses.d.ts +20 -0
  582. package/dist/http/routes/v1-responses.js +327 -0
  583. package/dist/index.d.ts +2 -0
  584. package/dist/index.js +2 -0
  585. package/dist/inference-service.d.ts +28 -0
  586. package/dist/inference-service.js +275 -0
  587. package/dist/knowledge/admission.d.ts +3 -0
  588. package/dist/knowledge/admission.js +22 -0
  589. package/dist/knowledge/bundled-catalog.d.ts +2 -0
  590. package/dist/knowledge/bundled-catalog.js +2 -0
  591. package/dist/knowledge/catalog-host.d.ts +103 -0
  592. package/dist/knowledge/catalog-host.js +180 -0
  593. package/dist/knowledge/catalog-source.d.ts +22 -0
  594. package/dist/knowledge/catalog-source.js +35 -0
  595. package/dist/knowledge/install.d.ts +55 -0
  596. package/dist/knowledge/install.js +274 -0
  597. package/dist/knowledge/manager.d.ts +287 -0
  598. package/dist/knowledge/manager.js +1540 -0
  599. package/dist/knowledge/registry.d.ts +35 -0
  600. package/dist/knowledge/registry.js +123 -0
  601. package/dist/knowledge/search-worker.d.ts +17 -0
  602. package/dist/knowledge/search-worker.js +36 -0
  603. package/dist/knowledge/shared-install-contract.d.ts +19 -0
  604. package/dist/knowledge/shared-install-contract.js +1 -0
  605. package/dist/knowledge/spatial-query.d.ts +11 -0
  606. package/dist/knowledge/spatial-query.js +33 -0
  607. package/dist/knowledge/trust-anchors.d.ts +11 -0
  608. package/dist/knowledge/trust-anchors.js +51 -0
  609. package/dist/knowledge/vector-floors.d.ts +44 -0
  610. package/dist/knowledge/vector-floors.js +92 -0
  611. package/dist/knowledge/worker-host.d.ts +9 -0
  612. package/dist/knowledge/worker-host.js +179 -0
  613. package/dist/kokoro-lexicon/LICENSE +202 -0
  614. package/dist/kokoro-lexicon/lexicon-gb-en.txt.gz +0 -0
  615. package/dist/kokoro-lexicon/lexicon-us-en.txt.gz +0 -0
  616. package/dist/kokoro-lexicon/manifest.json +23 -0
  617. package/dist/machine-engine/inspect-runtime.d.ts +3 -0
  618. package/dist/machine-engine/inspect-runtime.js +48 -0
  619. package/dist/machine-engine/knowledge-assets.d.ts +79 -0
  620. package/dist/machine-engine/knowledge-assets.js +505 -0
  621. package/dist/memory/embed-core.d.ts +131 -0
  622. package/dist/memory/embed-core.js +398 -0
  623. package/dist/memory/embed-worker.d.ts +23 -0
  624. package/dist/memory/embed-worker.js +49 -0
  625. package/dist/memory/embeddings.d.ts +105 -0
  626. package/dist/memory/embeddings.js +467 -0
  627. package/dist/model-profile/behaviors/tools-mlx-template-fix.d.ts +1 -0
  628. package/dist/model-profile/behaviors/tools-mlx-template-fix.js +2 -0
  629. package/dist/model-profile/behaviors/turn-ramble-detection.d.ts +1 -0
  630. package/dist/model-profile/behaviors/turn-ramble-detection.js +2 -0
  631. package/dist/model-profile/defaults.d.ts +1 -0
  632. package/dist/model-profile/defaults.js +2 -0
  633. package/dist/model-profile/index.d.ts +9 -0
  634. package/dist/model-profile/index.js +7 -0
  635. package/dist/model-profile/registry.d.ts +15 -0
  636. package/dist/model-profile/registry.js +18 -0
  637. package/dist/model-profile/runtime.d.ts +48 -0
  638. package/dist/model-profile/runtime.js +131 -0
  639. package/dist/model-profile/tool-grammar.d.ts +1 -0
  640. package/dist/model-profile/tool-grammar.js +2 -0
  641. package/dist/model-profile/tuning.d.ts +19 -0
  642. package/dist/model-profile/tuning.js +21 -0
  643. package/dist/model-profile/types.d.ts +1 -0
  644. package/dist/model-profile/types.js +2 -0
  645. package/dist/models/bundle-storage.d.ts +28 -0
  646. package/dist/models/bundle-storage.js +80 -0
  647. package/dist/models/catalog-drift.d.ts +48 -0
  648. package/dist/models/catalog-drift.js +94 -0
  649. package/dist/models/catalog-payload-identity.d.ts +107 -0
  650. package/dist/models/catalog-payload-identity.js +254 -0
  651. package/dist/models/ensure.d.ts +125 -0
  652. package/dist/models/ensure.js +205 -0
  653. package/dist/models/gezmodel.d.ts +47 -0
  654. package/dist/models/gezmodel.js +742 -0
  655. package/dist/models/install-registry.d.ts +101 -0
  656. package/dist/models/install-registry.js +216 -0
  657. package/dist/models/model-id.d.ts +22 -0
  658. package/dist/models/model-id.js +40 -0
  659. package/dist/models/storage-roots.d.ts +274 -0
  660. package/dist/models/storage-roots.js +865 -0
  661. package/dist/native-release-entry.d.ts +16 -0
  662. package/dist/native-release-entry.js +16 -0
  663. package/dist/perf/redact-path.d.ts +2 -0
  664. package/dist/perf/redact-path.js +27 -0
  665. package/dist/perf/responsiveness.d.ts +70 -0
  666. package/dist/perf/responsiveness.js +560 -0
  667. package/dist/providers/active-install-message.d.ts +42 -0
  668. package/dist/providers/active-install-message.js +49 -0
  669. package/dist/providers/apple-foundation-models/binary.d.ts +4 -0
  670. package/dist/providers/apple-foundation-models/binary.js +18 -0
  671. package/dist/providers/apple-foundation-models/helper.d.ts +66 -0
  672. package/dist/providers/apple-foundation-models/helper.js +262 -0
  673. package/dist/providers/apple-foundation-models/provider.d.ts +82 -0
  674. package/dist/providers/apple-foundation-models/provider.js +389 -0
  675. package/dist/providers/apple-foundation-models/status.d.ts +9 -0
  676. package/dist/providers/apple-foundation-models/status.js +49 -0
  677. package/dist/providers/audio/kokoro-frontend.d.ts +50 -0
  678. package/dist/providers/audio/kokoro-frontend.js +113 -0
  679. package/dist/providers/audio/managed-speech-model.d.ts +9 -0
  680. package/dist/providers/audio/managed-speech-model.js +86 -0
  681. package/dist/providers/audio/types.d.ts +202 -0
  682. package/dist/providers/audio/types.js +17 -0
  683. package/dist/providers/audio/whisper-cpp.d.ts +99 -0
  684. package/dist/providers/audio/whisper-cpp.js +420 -0
  685. package/dist/providers/audio-persister-contract.d.ts +13 -0
  686. package/dist/providers/audio-persister-contract.js +1 -0
  687. package/dist/providers/catalog-model-config.d.ts +63 -0
  688. package/dist/providers/catalog-model-config.js +95 -0
  689. package/dist/providers/code-block-salvage.d.ts +1 -0
  690. package/dist/providers/code-block-salvage.js +2 -0
  691. package/dist/providers/codex-cli/reasoning.d.ts +8 -0
  692. package/dist/providers/codex-cli/reasoning.js +17 -0
  693. package/dist/providers/complete-tool-call.d.ts +16 -0
  694. package/dist/providers/complete-tool-call.js +25 -0
  695. package/dist/providers/constrained-turn.d.ts +1 -0
  696. package/dist/providers/constrained-turn.js +2 -0
  697. package/dist/providers/deliverable-read-pacing.d.ts +1 -0
  698. package/dist/providers/deliverable-read-pacing.js +2 -0
  699. package/dist/providers/direct-file-work-prompt.d.ts +1 -0
  700. package/dist/providers/direct-file-work-prompt.js +2 -0
  701. package/dist/providers/ds4/build-provider.d.ts +100 -0
  702. package/dist/providers/ds4/build-provider.js +539 -0
  703. package/dist/providers/ds4/cache-adapter.d.ts +42 -0
  704. package/dist/providers/ds4/cache-adapter.js +110 -0
  705. package/dist/providers/ds4/dspark.d.ts +83 -0
  706. package/dist/providers/ds4/dspark.js +107 -0
  707. package/dist/providers/ds4/mtp.d.ts +32 -0
  708. package/dist/providers/ds4/mtp.js +46 -0
  709. package/dist/providers/ds4/provider.d.ts +67 -0
  710. package/dist/providers/ds4/provider.js +104 -0
  711. package/dist/providers/ds4/residency.d.ts +143 -0
  712. package/dist/providers/ds4/residency.js +139 -0
  713. package/dist/providers/ds4/stdout-parser.d.ts +47 -0
  714. package/dist/providers/ds4/stdout-parser.js +134 -0
  715. package/dist/providers/duplicate-tool-calls.d.ts +1 -0
  716. package/dist/providers/duplicate-tool-calls.js +2 -0
  717. package/dist/providers/file-repair-policy.d.ts +1 -0
  718. package/dist/providers/file-repair-policy.js +2 -0
  719. package/dist/providers/gpu-arbiter.d.ts +159 -0
  720. package/dist/providers/gpu-arbiter.js +301 -0
  721. package/dist/providers/image-persister-contract.d.ts +15 -0
  722. package/dist/providers/image-persister-contract.js +1 -0
  723. package/dist/providers/llama-cpp/build-metadata.d.ts +13 -0
  724. package/dist/providers/llama-cpp/build-metadata.js +39 -0
  725. package/dist/providers/llama-cpp/build-provider.d.ts +66 -0
  726. package/dist/providers/llama-cpp/build-provider.js +1491 -0
  727. package/dist/providers/llama-cpp/cache-adapter.d.ts +242 -0
  728. package/dist/providers/llama-cpp/cache-adapter.js +689 -0
  729. package/dist/providers/llama-cpp/devices.d.ts +130 -0
  730. package/dist/providers/llama-cpp/devices.js +256 -0
  731. package/dist/providers/llama-cpp/disk-cache.d.ts +8 -0
  732. package/dist/providers/llama-cpp/disk-cache.js +112 -0
  733. package/dist/providers/llama-cpp/engine-flags.d.ts +181 -0
  734. package/dist/providers/llama-cpp/engine-flags.js +279 -0
  735. package/dist/providers/llama-cpp/gguf-metadata-async.d.ts +11 -0
  736. package/dist/providers/llama-cpp/gguf-metadata-async.js +180 -0
  737. package/dist/providers/llama-cpp/gguf-metadata-worker.d.ts +7 -0
  738. package/dist/providers/llama-cpp/gguf-metadata-worker.js +27 -0
  739. package/dist/providers/llama-cpp/gguf-metadata.d.ts +198 -0
  740. package/dist/providers/llama-cpp/gguf-metadata.js +615 -0
  741. package/dist/providers/llama-cpp/gguf-quantization-backfill.d.ts +32 -0
  742. package/dist/providers/llama-cpp/gguf-quantization-backfill.js +75 -0
  743. package/dist/providers/llama-cpp/index.d.ts +10 -0
  744. package/dist/providers/llama-cpp/index.js +13 -0
  745. package/dist/providers/llama-cpp/kv-cache-type.d.ts +118 -0
  746. package/dist/providers/llama-cpp/kv-cache-type.js +140 -0
  747. package/dist/providers/llama-cpp/log.d.ts +92 -0
  748. package/dist/providers/llama-cpp/log.js +280 -0
  749. package/dist/providers/llama-cpp/models.d.ts +389 -0
  750. package/dist/providers/llama-cpp/models.js +1011 -0
  751. package/dist/providers/llama-cpp/offload-planner.d.ts +339 -0
  752. package/dist/providers/llama-cpp/offload-planner.js +524 -0
  753. package/dist/providers/llama-cpp/provider.d.ts +493 -0
  754. package/dist/providers/llama-cpp/provider.js +862 -0
  755. package/dist/providers/llama-cpp/reasoning-launch.d.ts +7 -0
  756. package/dist/providers/llama-cpp/reasoning-launch.js +14 -0
  757. package/dist/providers/llama-cpp/spec-draft.d.ts +44 -0
  758. package/dist/providers/llama-cpp/spec-draft.js +44 -0
  759. package/dist/providers/llama-cpp/stdout-parser.d.ts +70 -0
  760. package/dist/providers/llama-cpp/stdout-parser.js +197 -0
  761. package/dist/providers/local-tool-call-salvage.d.ts +1 -0
  762. package/dist/providers/local-tool-call-salvage.js +2 -0
  763. package/dist/providers/local-turn-policy.d.ts +1 -0
  764. package/dist/providers/local-turn-policy.js +2 -0
  765. package/dist/providers/mlx/async-file-handoff.d.ts +11 -0
  766. package/dist/providers/mlx/async-file-handoff.js +25 -0
  767. package/dist/providers/mlx/build-provider.d.ts +65 -0
  768. package/dist/providers/mlx/build-provider.js +717 -0
  769. package/dist/providers/mlx/cache-adapter.d.ts +161 -0
  770. package/dist/providers/mlx/cache-adapter.js +445 -0
  771. package/dist/providers/mlx/chat-protocol.d.ts +48 -0
  772. package/dist/providers/mlx/chat-protocol.js +8 -0
  773. package/dist/providers/mlx/config-parser.d.ts +29 -0
  774. package/dist/providers/mlx/config-parser.js +81 -0
  775. package/dist/providers/mlx/engine-gate.d.ts +51 -0
  776. package/dist/providers/mlx/engine-gate.js +207 -0
  777. package/dist/providers/mlx/engine-hold.d.ts +41 -0
  778. package/dist/providers/mlx/engine-hold.js +59 -0
  779. package/dist/providers/mlx/engine-log-router.d.ts +84 -0
  780. package/dist/providers/mlx/engine-log-router.js +137 -0
  781. package/dist/providers/mlx/engine-stats-sampler.d.ts +36 -0
  782. package/dist/providers/mlx/engine-stats-sampler.js +59 -0
  783. package/dist/providers/mlx/index.d.ts +10 -0
  784. package/dist/providers/mlx/index.js +10 -0
  785. package/dist/providers/mlx/log.d.ts +55 -0
  786. package/dist/providers/mlx/log.js +157 -0
  787. package/dist/providers/mlx/model-geometry.d.ts +35 -0
  788. package/dist/providers/mlx/model-geometry.js +118 -0
  789. package/dist/providers/mlx/models.d.ts +289 -0
  790. package/dist/providers/mlx/models.js +1079 -0
  791. package/dist/providers/mlx/provider.d.ts +404 -0
  792. package/dist/providers/mlx/provider.js +3017 -0
  793. package/dist/providers/mlx/python/cache_persist.py +348 -0
  794. package/dist/providers/mlx/python/cache_seed.py +402 -0
  795. package/dist/providers/mlx/python/gezel_mlx_server.py +4491 -0
  796. package/dist/providers/mlx/python/lfm2_compat.py +55 -0
  797. package/dist/providers/mlx/python/qwen3_5_text_compat.py +60 -0
  798. package/dist/providers/mlx/python/qwen4_ple.py +159 -0
  799. package/dist/providers/mlx/python/spec_decode.py +775 -0
  800. package/dist/providers/mlx/python/template_stability.py +133 -0
  801. package/dist/providers/mlx/python/think_budget.py +113 -0
  802. package/dist/providers/mlx/python/tool_args_json.py +297 -0
  803. package/dist/providers/mlx/python/tool_call_stream.py +265 -0
  804. package/dist/providers/mlx/python/tool_grammar.py +794 -0
  805. package/dist/providers/mlx/python/vision_inputs.py +64 -0
  806. package/dist/providers/mlx/python/wave_policy.py +147 -0
  807. package/dist/providers/mlx/reasoning-stream.d.ts +85 -0
  808. package/dist/providers/mlx/reasoning-stream.js +196 -0
  809. package/dist/providers/mlx/request-shape.d.ts +34 -0
  810. package/dist/providers/mlx/request-shape.js +42 -0
  811. package/dist/providers/mlx/runtime-diagnostics.d.ts +29 -0
  812. package/dist/providers/mlx/runtime-diagnostics.js +162 -0
  813. package/dist/providers/mlx/spec-drafter.d.ts +25 -0
  814. package/dist/providers/mlx/spec-drafter.js +73 -0
  815. package/dist/providers/mlx/stdout-parser.d.ts +60 -0
  816. package/dist/providers/mlx/stdout-parser.js +254 -0
  817. package/dist/providers/mlx/textual-tool-call-salvage.d.ts +46 -0
  818. package/dist/providers/mlx/textual-tool-call-salvage.js +396 -0
  819. package/dist/providers/mlx/tool-call-protocol.d.ts +65 -0
  820. package/dist/providers/mlx/tool-call-protocol.js +140 -0
  821. package/dist/providers/mlx/tool-call-stripper.d.ts +68 -0
  822. package/dist/providers/mlx/tool-call-stripper.js +153 -0
  823. package/dist/providers/mlx/tool-image-retention.d.ts +23 -0
  824. package/dist/providers/mlx/tool-image-retention.js +43 -0
  825. package/dist/providers/mlx/turn-telemetry.d.ts +22 -0
  826. package/dist/providers/mlx/turn-telemetry.js +45 -0
  827. package/dist/providers/mlx/venv.d.ts +91 -0
  828. package/dist/providers/mlx/venv.js +111 -0
  829. package/dist/providers/mlx/vision-mode.d.ts +92 -0
  830. package/dist/providers/mlx/vision-mode.js +187 -0
  831. package/dist/providers/mlx/vision.d.ts +2 -0
  832. package/dist/providers/mlx/vision.js +12 -0
  833. package/dist/providers/mlx/wire-transcript.d.ts +14 -0
  834. package/dist/providers/mlx/wire-transcript.js +43 -0
  835. package/dist/providers/native/capacity-broker.d.ts +812 -0
  836. package/dist/providers/native/capacity-broker.js +1058 -0
  837. package/dist/providers/native/capacity-budget.d.ts +133 -0
  838. package/dist/providers/native/capacity-budget.js +265 -0
  839. package/dist/providers/native/device-capacity-ledger.d.ts +31 -0
  840. package/dist/providers/native/device-capacity-ledger.js +196 -0
  841. package/dist/providers/native/device-capacity.d.ts +84 -0
  842. package/dist/providers/native/device-capacity.js +431 -0
  843. package/dist/providers/native/engine-api-key.d.ts +57 -0
  844. package/dist/providers/native/engine-api-key.js +72 -0
  845. package/dist/providers/native/engine-key.d.ts +18 -0
  846. package/dist/providers/native/engine-key.js +41 -0
  847. package/dist/providers/native/engine-router.d.ts +145 -0
  848. package/dist/providers/native/engine-router.js +191 -0
  849. package/dist/providers/native/gpu-panic-guard.d.ts +54 -0
  850. package/dist/providers/native/gpu-panic-guard.js +59 -0
  851. package/dist/providers/native/inference.d.ts +33 -0
  852. package/dist/providers/native/inference.js +49 -0
  853. package/dist/providers/native/local-engine-runtime.d.ts +412 -0
  854. package/dist/providers/native/local-engine-runtime.js +1714 -0
  855. package/dist/providers/native/measured-budget.d.ts +32 -0
  856. package/dist/providers/native/measured-budget.js +54 -0
  857. package/dist/providers/native/port.d.ts +11 -0
  858. package/dist/providers/native/port.js +29 -0
  859. package/dist/providers/native/provider-pool.d.ts +474 -0
  860. package/dist/providers/native/provider-pool.js +1166 -0
  861. package/dist/providers/native/supervisor.d.ts +503 -0
  862. package/dist/providers/native/supervisor.js +1466 -0
  863. package/dist/providers/observation-context.d.ts +16 -0
  864. package/dist/providers/observation-context.js +1 -0
  865. package/dist/providers/openai-compatible/sse.d.ts +1 -0
  866. package/dist/providers/openai-compatible/sse.js +2 -0
  867. package/dist/providers/patient-fetch.d.ts +36 -0
  868. package/dist/providers/patient-fetch.js +44 -0
  869. package/dist/providers/project-macro-loop-bail.d.ts +7 -0
  870. package/dist/providers/project-macro-loop-bail.js +21 -0
  871. package/dist/providers/prose-document-salvage.d.ts +1 -0
  872. package/dist/providers/prose-document-salvage.js +2 -0
  873. package/dist/providers/provider-disposal.d.ts +1 -0
  874. package/dist/providers/provider-disposal.js +2 -0
  875. package/dist/providers/queue.d.ts +15 -0
  876. package/dist/providers/queue.js +23 -0
  877. package/dist/providers/ramble-abort-message.d.ts +1 -0
  878. package/dist/providers/ramble-abort-message.js +2 -0
  879. package/dist/providers/ramble-detector.d.ts +1 -0
  880. package/dist/providers/ramble-detector.js +2 -0
  881. package/dist/providers/reasoning-depth.d.ts +1 -0
  882. package/dist/providers/reasoning-depth.js +2 -0
  883. package/dist/providers/required-input-reads.d.ts +1 -0
  884. package/dist/providers/required-input-reads.js +2 -0
  885. package/dist/providers/session-defaults.d.ts +13 -0
  886. package/dist/providers/session-defaults.js +49 -0
  887. package/dist/providers/session-hooks.d.ts +26 -0
  888. package/dist/providers/session-hooks.js +1 -0
  889. package/dist/providers/streaming-session.d.ts +1 -0
  890. package/dist/providers/streaming-session.js +2 -0
  891. package/dist/providers/terminal-tool-policy.d.ts +1 -0
  892. package/dist/providers/terminal-tool-policy.js +2 -0
  893. package/dist/providers/tool-arg-schema-coercion.d.ts +1 -0
  894. package/dist/providers/tool-arg-schema-coercion.js +2 -0
  895. package/dist/providers/tool-executor.d.ts +12 -0
  896. package/dist/providers/tool-executor.js +20 -0
  897. package/dist/providers/tool-failure-tracker.d.ts +1 -0
  898. package/dist/providers/tool-failure-tracker.js +2 -0
  899. package/dist/providers/tool-repeat-tracker.d.ts +1 -0
  900. package/dist/providers/tool-repeat-tracker.js +2 -0
  901. package/dist/providers/turn-timeout.d.ts +1 -0
  902. package/dist/providers/turn-timeout.js +1 -0
  903. package/dist/providers/types.d.ts +834 -0
  904. package/dist/providers/types.js +42 -0
  905. package/dist/providers/usage-builder.d.ts +1 -0
  906. package/dist/providers/usage-builder.js +2 -0
  907. package/dist/providers/vision-capability.d.ts +109 -0
  908. package/dist/providers/vision-capability.js +137 -0
  909. package/dist/python/mlx-runtime-status-bus.d.ts +39 -0
  910. package/dist/python/mlx-runtime-status-bus.js +27 -0
  911. package/dist/python/uv-runtime.d.ts +176 -0
  912. package/dist/python/uv-runtime.js +492 -0
  913. package/dist/relevance/install.d.ts +28 -0
  914. package/dist/relevance/install.js +114 -0
  915. package/dist/relevance/manager.d.ts +79 -0
  916. package/dist/relevance/manager.js +211 -0
  917. package/dist/relevance/registry.d.ts +11 -0
  918. package/dist/relevance/registry.js +158 -0
  919. package/dist/relevance/relevance-core.d.ts +67 -0
  920. package/dist/relevance/relevance-core.js +189 -0
  921. package/dist/relevance/relevance-model.d.ts +42 -0
  922. package/dist/relevance/relevance-model.js +292 -0
  923. package/dist/relevance/relevance-worker.d.ts +20 -0
  924. package/dist/relevance/relevance-worker.js +57 -0
  925. package/dist/relevance/settings.d.ts +30 -0
  926. package/dist/relevance/settings.js +81 -0
  927. package/dist/remotes/identity.d.ts +121 -0
  928. package/dist/remotes/identity.js +348 -0
  929. package/dist/remotes/pinned-fetch.d.ts +45 -0
  930. package/dist/remotes/pinned-fetch.js +193 -0
  931. package/dist/remotes/types.d.ts +54 -0
  932. package/dist/remotes/types.js +1 -0
  933. package/dist/runtime-lock.d.ts +29 -0
  934. package/dist/runtime-lock.js +85 -0
  935. package/dist/search/relevance-stage.d.ts +81 -0
  936. package/dist/search/relevance-stage.js +177 -0
  937. package/dist/secrets/types.d.ts +63 -0
  938. package/dist/secrets/types.js +64 -0
  939. package/dist/speech.d.ts +1 -0
  940. package/dist/speech.js +1 -0
  941. package/dist/system/darwin-memory.d.ts +26 -0
  942. package/dist/system/darwin-memory.js +81 -0
  943. package/dist/system/gezel-process-memory.d.ts +55 -0
  944. package/dist/system/gezel-process-memory.js +156 -0
  945. package/dist/system/memory.d.ts +154 -0
  946. package/dist/system/memory.js +501 -0
  947. package/dist/transformers-cache.d.ts +112 -0
  948. package/dist/transformers-cache.js +392 -0
  949. package/dist/utils/disk-space.d.ts +55 -0
  950. package/dist/utils/disk-space.js +72 -0
  951. package/dist/utils/download-common.d.ts +138 -0
  952. package/dist/utils/download-common.js +196 -0
  953. package/dist/utils/download-with-retry.d.ts +85 -0
  954. package/dist/utils/download-with-retry.js +522 -0
  955. package/dist/utils/extract-zip.d.ts +22 -0
  956. package/dist/utils/extract-zip.js +103 -0
  957. package/dist/utils/retire-model-worker.d.ts +15 -0
  958. package/dist/utils/retire-model-worker.js +24 -0
  959. package/dist/utils/service-worker-entry.d.ts +59 -0
  960. package/dist/utils/service-worker-entry.js +69 -0
  961. package/dist/utils/xet-download.d.ts +40 -0
  962. package/dist/utils/xet-download.js +526 -0
  963. package/dist/utils/xet.d.ts +86 -0
  964. package/dist/utils/xet.js +201 -0
  965. package/package.json +103 -3
  966. package/scripts/embedding-packaging.cjs +264 -0
  967. package/scripts/embedding-packaging.d.cts +16 -0
@@ -0,0 +1,1540 @@
1
+ /**
2
+ * KnowledgeManager — the daemon-side owner of installed `.gezk` catalogs:
3
+ * registry + mount lifecycle (verify-before-mount → quarantine-with-reason),
4
+ * background install jobs (a client disconnect never abandons a download),
5
+ * the gilde join (what is available, what has a newer version), browse APIs
6
+ * for the routes, and the SearchService knowledge arm. Every SQLite touch
7
+ * goes through the KnowledgeCatalogHost (worker thread in production); this
8
+ * class never opens a catalog database itself.
9
+ */
10
+ import { createHash } from 'node:crypto';
11
+ import { existsSync } from 'node:fs';
12
+ import { readFile, readdir, rm, stat } from 'node:fs/promises';
13
+ import { dirname, join, resolve } from 'node:path';
14
+ import { fileURLToPath } from 'node:url';
15
+ import { KnowledgeMachineInventorySchema, KnowledgeNearbyRequestSchema, createLogger, formatKnowledgeUri, parseKnowledgeUri, resolveSecurityPolicy, sameVectorSpace, } from '@bendyline/gezel';
16
+ import { compareCatalogVersions, knowledgeEmbeddingProfile, readGezkManifest, } from '@bendyline/gezel-knowledge';
17
+ import { knowledgeCatalogVersionDir, knowledgeCatalogsDir, knowledgeDownloadsDir, } from '@bendyline/gezel/paths';
18
+ import { HANDBOEK_KNOWLEDGE_CATALOG, HANDBOEK_KNOWLEDGE_PUBLISHER } from './bundled-catalog.js';
19
+ import { scoreResult } from '@bendyline/gezel';
20
+ import { sharedKnowledgeRoot, sharedKnowledgeVersionDir, } from '../machine-engine/knowledge-assets.js';
21
+ import { embedKnowledgeQuery, sharesDaemonEmbedder } from '../memory/embeddings.js';
22
+ import { ChatModelInstallRegistry } from '../models/install-registry.js';
23
+ import { beginPerfWork } from '../perf/responsiveness.js';
24
+ import { resolveKnowledgeCatalogSource } from './catalog-source.js';
25
+ import { KNOWLEDGE_DOWNLOAD_KEY_PATTERN, installKnowledgeCatalog, knowledgeDownloadKey, pruneOtherKnowledgeCatalogVersions, } from './install.js';
26
+ import { KnowledgeRegistry } from './registry.js';
27
+ import { KnowledgeSpatialCursorError, encodeNearbyCursor, nearbyCursorOffset, regionalDocumentIdentity, } from './spatial-query.js';
28
+ import { resolveKnowledgeVectorFloors } from './vector-floors.js';
29
+ const log = createLogger('knowledge');
30
+ /** Explicit-search shard budget (S) across every active catalog (§3.4). */
31
+ const ROUTE_BUDGET_EXPLICIT = 6;
32
+ /**
33
+ * Shards added beyond that budget for pages the query names by title (the
34
+ * catalog host's title-assisted routing): the centroids alone left the ABBA
35
+ * article unscanned for "Who were the members of ABBA?". Two, not one per
36
+ * catalog, so twenty mounted catalogs cannot add twenty scans.
37
+ */
38
+ const TITLE_ROUTE_EXPLICIT = 2;
39
+ const FINAL_K = 24;
40
+ /** Same cadence as the catalog download's own progress (download-with-retry). */
41
+ const EMBEDDER_PROGRESS_INTERVAL_MS = 250;
42
+ const DEFAULT_EMBEDDER_PREWARM_TIMEOUT_MS = 5 * 60_000;
43
+ /** Finished jobs stay pollable for a minute: the CLI and older cards poll `/jobs/:id`. */
44
+ const JOB_TTL_MS = 60_000;
45
+ const AUTO_UPDATE_STARTUP_DELAY_MS = 10 * 60_000;
46
+ const AUTO_UPDATE_INTERVAL_MS = 24 * 60 * 60_000;
47
+ /**
48
+ * A catalog's semantic mode. `shared` reuses the daemon's own query vectors,
49
+ * `profile` loads the registered profile's pinned model on demand, and a
50
+ * profile that matches neither — including a registered id whose pinned
51
+ * files or precision differ — is searched by keyword only rather than with
52
+ * vectors from another space.
53
+ */
54
+ function semanticSearchModeFor(profile) {
55
+ if (sharesDaemonEmbedder(profile))
56
+ return 'shared';
57
+ const registered = knowledgeEmbeddingProfile(profile.id);
58
+ if (registered && sameVectorSpace(registered, profile))
59
+ return 'profile';
60
+ return 'keyword-only';
61
+ }
62
+ /**
63
+ * Explicit search fuses three arms per catalog by reciprocal rank (k = 60):
64
+ * the vector chunks (best chunk per document, by rerank cosine), the
65
+ * doc-title FTS hits, and the chunk-body FTS hits. Rank fusion instead of
66
+ * score comparison because the arms' scores are not commensurable — e5
67
+ * cosines sit in a narrow 0.7–0.9 band for everything, so a cosine-first
68
+ * ordering buried an exact title match under any vaguely related passage
69
+ * ("Who painted the Mona Lisa?" listed three other Mona Lisa copies above
70
+ * the article whose title the question names). Two lexical arms agreeing
71
+ * on a document now outrank one vector arm; a document every arm names
72
+ * comes first.
73
+ */
74
+ const RRF_K = 60;
75
+ const ARM_WEIGHTS = { vector: 1, docFts: 1, chunkFts: 0.5 };
76
+ /**
77
+ * Media rows fuse per row, not per document: a document's own text chunk
78
+ * (cosine ≈ 0.9) would otherwise always stand in for its image (≈ 0.7). Each
79
+ * modality is ranked on its own scale, past its own measured floor.
80
+ */
81
+ const MEDIA_ARM_WEIGHTS = { vector: 0.5, chunkFts: 0.25 };
82
+ /** Media rows asked of each catalog, per modality, on an explicit search. */
83
+ const MEDIA_K = 2;
84
+ /** Media results one search returns at most, and per document. */
85
+ const MEDIA_RESULT_CAP = 4;
86
+ const MEDIA_PER_DOCUMENT = 1;
87
+ /**
88
+ * Fused documents per catalog when several are in scope: keeps one catalog
89
+ * from monopolizing the merged list. A search scoped to one catalog has
90
+ * nothing to share the list with, and the cap cut the Knowledge browser's
91
+ * search for "blob" in an Azure-docs catalog — 348 matching titles — to six.
92
+ */
93
+ const PER_CATALOG_CAP = 6;
94
+ /** Lexical candidates fetched per arm before fusion, at the least. */
95
+ const DOC_FTS_MIN = 6;
96
+ const CHUNK_FTS_MIN = 8;
97
+ /** Rank-anchored relevance for a fused knowledge result: the best hit is a strong 1.0, decaying RRF-style. */
98
+ function fusedRankRelevance(rank) {
99
+ return 11 / (11 + rank);
100
+ }
101
+ /**
102
+ * The first prose paragraph of a document body, for a hit that no chunk
103
+ * carries (a title-only match): the model gets something to read, not just
104
+ * a summary line. Skips the title heading and a key-facts list.
105
+ */
106
+ function leadExcerpt(markdown, max = 600) {
107
+ const body = markdown.replace(/^#\s[^\n]*\n+/, '');
108
+ const paragraph = body
109
+ .split(/\n\s*\n/)
110
+ .map((part) => part.trim())
111
+ .find((part) => part.length > 0 && !part.startsWith('#') && !part.startsWith('- ')) ??
112
+ body.trim();
113
+ return paragraph.length > max ? `${paragraph.slice(0, max - 1)}…` : paragraph;
114
+ }
115
+ function errorMessage(err) {
116
+ return err instanceof Error ? err.message : String(err);
117
+ }
118
+ export class KnowledgeManager {
119
+ opts;
120
+ registry;
121
+ mountedByKey = new Map();
122
+ installs;
123
+ /** What each running job was asked to install, for the active-install listing. */
124
+ jobRequests = new Map();
125
+ /** Download temp keys of running jobs, so the incomplete listing skips live transfers. */
126
+ jobDownloadKeys = new Map();
127
+ autoUpdateTimers = [];
128
+ jobCounter = 0;
129
+ vectorFloors;
130
+ constructor(opts) {
131
+ this.opts = opts;
132
+ this.registry = new KnowledgeRegistry(opts.home);
133
+ this.vectorFloors = opts.vectorFloors ?? resolveKnowledgeVectorFloors(opts.env ?? process.env);
134
+ this.installs = new ChatModelInstallRegistry({
135
+ engine: 'knowledge',
136
+ run: (jobId, start) => this.runInstall(jobId, start.request),
137
+ finishedTtlMs: JOB_TTL_MS,
138
+ });
139
+ }
140
+ get host() {
141
+ return this.opts.host;
142
+ }
143
+ /** The job registry, for the SSE subscriber shared with the model install routes. */
144
+ get installRegistry() {
145
+ return this.installs;
146
+ }
147
+ keyFor(ref) {
148
+ return `${ref.publisherId}/${ref.catalogId}`;
149
+ }
150
+ dirFor(ref) {
151
+ if (ref.storageScope === 'machine-shared') {
152
+ const root = sharedKnowledgeRoot(this.opts.env);
153
+ if (!root) {
154
+ throw new Error('catalog is stored in the machine-shared asset store, which is not configured on this device');
155
+ }
156
+ // Mounted read-only from the shared store; verify-before-mount runs
157
+ // the same per-file hash reconciliation as the private tier.
158
+ return sharedKnowledgeVersionDir(root, {
159
+ publisherId: ref.publisherId,
160
+ catalogId: ref.catalogId,
161
+ version: ref.version,
162
+ expectedDigest: ref.contentDigest,
163
+ });
164
+ }
165
+ return knowledgeCatalogVersionDir(this.opts.home, ref.publisherId, ref.catalogId, ref.version, ref.contentDigest);
166
+ }
167
+ /** Mount every enabled registry entry. Failures quarantine, never throw. */
168
+ async start() {
169
+ await this.ensureBundledHandboek().catch((err) => {
170
+ log.warn(`bundled Handboek catalog unavailable: ${errorMessage(err)}`);
171
+ });
172
+ for (const entry of this.registry.read().catalogs) {
173
+ if (!entry.enabled)
174
+ continue;
175
+ await this.mountEntry(entry, { deferPrewarm: true }).catch((err) => {
176
+ const reason = errorMessage(err);
177
+ log.warn(`catalog ${entry.ref.catalogId} failed to mount: ${reason}`);
178
+ this.registry.quarantine(entry.ref.publisherId, entry.ref.catalogId, reason);
179
+ });
180
+ }
181
+ // After every mount, not between them: the worker runs one op at a time,
182
+ // and boot awaits start(), so a warm-up queued per mount would hold the
183
+ // next catalog's validation — and the service — behind it.
184
+ for (const key of this.mountedByKey.keys())
185
+ this.prewarmVectors(key);
186
+ }
187
+ async ensureBundledHandboek() {
188
+ const archive = this.opts.bundledHandboekArchive ?? null;
189
+ if (!archive)
190
+ return;
191
+ const bytes = await readFile(archive);
192
+ const digest = createHash('sha256').update(bytes).digest('hex');
193
+ const existing = this.registry.find(HANDBOEK_KNOWLEDGE_PUBLISHER, HANDBOEK_KNOWLEDGE_CATALOG);
194
+ if (existing && existing.source !== 'bundled') {
195
+ log.warn('Handboek catalog id is already used by a user-installed catalog; leaving it intact');
196
+ return;
197
+ }
198
+ if (existing?.ref.contentDigest === digest)
199
+ return;
200
+ const enabled = existing?.enabled ?? true;
201
+ const manifest = await readGezkManifest(archive);
202
+ for await (const event of installKnowledgeCatalog({
203
+ home: this.opts.home,
204
+ source: { kind: 'file', path: archive },
205
+ origin: 'bundled',
206
+ expectedIdentity: {
207
+ publisherId: HANDBOEK_KNOWLEDGE_PUBLISHER,
208
+ catalogId: HANDBOEK_KNOWLEDGE_CATALOG,
209
+ version: manifest.version,
210
+ },
211
+ registry: this.registry,
212
+ validateCatalog: (rootDir, deep) => this.opts.host.validate(rootDir, deep),
213
+ })) {
214
+ if (event.type === 'error')
215
+ throw new Error(event.error);
216
+ if (event.type === 'done') {
217
+ if (!enabled)
218
+ this.registry.setEnabled(event.ref.publisherId, event.ref.catalogId, false);
219
+ await pruneOtherKnowledgeCatalogVersions(this.opts.home, event.ref);
220
+ }
221
+ }
222
+ }
223
+ async mountEntry(entry, opts = {}) {
224
+ const ref = entry.ref;
225
+ const key = this.keyFor(ref);
226
+ if (this.mountedByKey.has(key))
227
+ return;
228
+ const rootDir = this.dirFor(ref);
229
+ // Full verify before mount, including SQLite quick_check, vector-table
230
+ // alignment, self-KNN, and publisher smoke queries. This runs in the
231
+ // dedicated knowledge worker in production. An install that deep-validated
232
+ // these bytes moments ago re-checks hashes and counts only: repeating the
233
+ // deep pass doubled the tail of every update, during which the worker
234
+ // answered no other knowledge query.
235
+ const report = await this.opts.host.validate(rootDir, opts.justVerified !== true);
236
+ if (!report.ok || !report.manifest) {
237
+ const failed = report.checks.filter((c) => !c.ok);
238
+ throw new Error(failed.length > 0
239
+ ? `verification failed: ${failed[0]?.name}${failed[0]?.detail ? ` (${failed[0]?.detail})` : ''}`
240
+ : 'verification failed');
241
+ }
242
+ const manifest = report.manifest;
243
+ if (manifest.id !== ref.catalogId || manifest.version !== ref.version) {
244
+ throw new Error(`on-disk catalog is ${manifest.id}@${manifest.version}, registry expects ${ref.catalogId}@${ref.version}`);
245
+ }
246
+ await this.opts.host.mount({ key, rootDir, catalogId: ref.catalogId, version: ref.version });
247
+ const topics = await this.opts.host.topics(key);
248
+ // Queries must be embedded in the catalog's own space. A profile the
249
+ // daemon's model already implements shares its vectors; a registered
250
+ // profile gets its own model loaded on demand; anything else is keyword-only.
251
+ const semanticSearch = semanticSearchModeFor(manifest.embedding);
252
+ const vectorCompatible = semanticSearch !== 'keyword-only';
253
+ this.mountedByKey.set(key, {
254
+ ref,
255
+ key,
256
+ rootDir,
257
+ name: manifest.name,
258
+ ...(manifest.description ? { description: manifest.description } : {}),
259
+ language: manifest.language,
260
+ license: manifest.license.name,
261
+ documents: manifest.counts.documents,
262
+ chunks: manifest.counts.chunks,
263
+ sizeBytes: manifest.files.reduce((sum, f) => sum + f.sizeBytes, 0),
264
+ vectorCompatible,
265
+ semanticSearch,
266
+ embedding: manifest.embedding,
267
+ topicNames: new Map(topics.map((t) => [t.id, t.name])),
268
+ sourceUrlByDoc: new Map(),
269
+ });
270
+ log.info(`mounted ${ref.catalogId}@${ref.version} (${manifest.counts.documents} documents, semantic search: ${semanticSearch})`);
271
+ if (!opts.deferPrewarm)
272
+ this.prewarmVectors(key);
273
+ }
274
+ /**
275
+ * Load a catalog's vector bits in the worker now, in the background. The
276
+ * first semantic search otherwise loads them itself — ~300 ms for a
277
+ * 200k-chunk shard — inside its 600 ms scope budget, times out, and the
278
+ * knowledge arm answers nothing, keyword hits included. A failure here
279
+ * costs only that first search.
280
+ */
281
+ prewarmVectors(key) {
282
+ const info = this.mountedByKey.get(key);
283
+ if (!info?.vectorCompatible)
284
+ return;
285
+ const started = performance.now();
286
+ this.opts.host.prewarm(key).then((shards) => {
287
+ if (shards === 0)
288
+ return;
289
+ log.info(`prewarmed ${info.ref.catalogId} vectors: ${shards} shard(s) in ${Math.round(performance.now() - started)}ms`);
290
+ }, (err) => log.warn(`vector prewarm for ${info.ref.catalogId} failed: ${errorMessage(err)}`));
291
+ }
292
+ async stop() {
293
+ for (const timer of this.autoUpdateTimers.splice(0))
294
+ clearTimeout(timer);
295
+ this.installs.clear();
296
+ await this.opts.host.dispose();
297
+ this.mountedByKey.clear();
298
+ }
299
+ // ── the gilde join ────────────────────────────────────────────────────────
300
+ /**
301
+ * Every gilde `knowledge-catalog` entry (newest version), keyed by
302
+ * publisher/id, with the catalog route URL of its Reference Mark artwork.
303
+ */
304
+ async gildeEntries() {
305
+ const out = new Map();
306
+ if (!this.opts.catalog)
307
+ return out;
308
+ try {
309
+ for (const item of await this.opts.catalog.list('knowledge-catalog')) {
310
+ if (item.manifest.kind !== 'knowledge-catalog')
311
+ continue;
312
+ out.set(this.keyFor({ publisherId: item.manifest.publisherId, catalogId: item.manifest.id }), { manifest: item.manifest, ...(item.logoUrl ? { logoUrl: item.logoUrl } : {}) });
313
+ }
314
+ }
315
+ catch (err) {
316
+ log.debug(`knowledge catalog listing unavailable: ${errorMessage(err)}`);
317
+ }
318
+ return out;
319
+ }
320
+ /** Every gilde `knowledge-catalog` manifest (newest version), keyed by publisher/id. */
321
+ async gildeItems() {
322
+ const out = new Map();
323
+ for (const [key, entry] of await this.gildeEntries())
324
+ out.set(key, entry.manifest);
325
+ return out;
326
+ }
327
+ /** Coordinates present in the machine-shared asset store (public inventory, read-only). */
328
+ async sharedInventoryKeys() {
329
+ const root = sharedKnowledgeRoot(this.opts.env);
330
+ if (!root)
331
+ return new Set();
332
+ try {
333
+ const inventory = KnowledgeMachineInventorySchema.parse(JSON.parse(await readFile(join(root, 'inventory.json'), 'utf8')));
334
+ return new Set(inventory.catalogs.map((c) => `${c.publisherId}/${c.catalogId}/${c.version}/${c.contentDigest}`));
335
+ }
336
+ catch {
337
+ return new Set();
338
+ }
339
+ }
340
+ // ── listing ───────────────────────────────────────────────────────────────
341
+ async list() {
342
+ const gilde = await this.gildeEntries();
343
+ return this.registry.read().catalogs.map((entry) => {
344
+ const key = this.keyFor(entry.ref);
345
+ const mounted = this.mountedByKey.get(key);
346
+ const listed = gilde.get(key);
347
+ const item = listed?.manifest;
348
+ const availableVersion = item && compareCatalogVersions(item.version, entry.ref.version) > 0
349
+ ? item.version
350
+ : undefined;
351
+ return {
352
+ ref: entry.ref,
353
+ enabled: entry.enabled,
354
+ addedAt: entry.addedAt,
355
+ ...(entry.disabledReason ? { disabledReason: entry.disabledReason } : {}),
356
+ mounted: Boolean(mounted),
357
+ ...(mounted
358
+ ? {
359
+ name: mounted.name,
360
+ ...(mounted.description ? { description: mounted.description } : {}),
361
+ language: mounted.language,
362
+ license: mounted.license,
363
+ documents: mounted.documents,
364
+ chunks: mounted.chunks,
365
+ sizeBytes: mounted.sizeBytes,
366
+ vectorCompatible: mounted.vectorCompatible,
367
+ semanticSearch: mounted.semanticSearch,
368
+ }
369
+ : {}),
370
+ source: entry.source ?? (item ? 'gilde' : 'file'),
371
+ updateAvailable: availableVersion !== undefined,
372
+ ...(availableVersion ? { availableVersion } : {}),
373
+ ...(listed?.logoUrl ? { logoUrl: listed.logoUrl } : {}),
374
+ };
375
+ });
376
+ }
377
+ /** Installed catalogs for which the shipped gilde content carries a strictly newer version. */
378
+ async updates() {
379
+ const gilde = await this.gildeItems();
380
+ const out = [];
381
+ for (const entry of this.registry.read().catalogs) {
382
+ const item = gilde.get(this.keyFor(entry.ref));
383
+ if (!item || compareCatalogVersions(item.version, entry.ref.version) <= 0)
384
+ continue;
385
+ out.push({
386
+ publisherId: item.publisherId,
387
+ catalogId: item.id,
388
+ name: item.name,
389
+ installedVersion: entry.ref.version,
390
+ availableVersion: item.version,
391
+ releasedAt: item.releasedAt,
392
+ archiveBytes: item.archiveBytes,
393
+ contentDigest: item.sha256,
394
+ huggingface: item.huggingface,
395
+ });
396
+ }
397
+ return out;
398
+ }
399
+ /**
400
+ * Every gilde `knowledge-catalog` entry joined with this user's registry,
401
+ * the machine-shared inventory, running installs and partial downloads —
402
+ * what the Knowledge screen's browser renders. Offline-safe: gilde is local.
403
+ */
404
+ async available() {
405
+ const gilde = await this.gildeItems();
406
+ if (gilde.size === 0)
407
+ return [];
408
+ const registry = this.registry.read().catalogs;
409
+ const shared = await this.sharedInventoryKeys();
410
+ const activeIds = new Set(this.installs.active().map((a) => a.id));
411
+ const partials = await this.partialDownloadKeys();
412
+ return [...gilde.values()]
413
+ .sort((a, b) => a.name.localeCompare(b.name))
414
+ .map((item) => {
415
+ const entry = registry.find((c) => c.ref.publisherId === item.publisherId && c.ref.catalogId === item.id);
416
+ return {
417
+ id: item.id,
418
+ publisherId: item.publisherId,
419
+ name: item.name,
420
+ description: item.description,
421
+ tags: item.tags,
422
+ language: item.language,
423
+ ...(item.category ? { category: item.category } : {}),
424
+ ...(item.license ? { license: item.license } : {}),
425
+ ...(item.licenseUrl ? { licenseUrl: item.licenseUrl } : {}),
426
+ version: item.version,
427
+ releasedAt: item.releasedAt,
428
+ formatVersion: item.formatVersion,
429
+ huggingface: item.huggingface,
430
+ ...(item.upstream ? { upstream: item.upstream } : {}),
431
+ ...(item.parquet ? { parquet: item.parquet } : {}),
432
+ sha256: item.sha256,
433
+ archiveBytes: item.archiveBytes,
434
+ uncompressedBytes: item.uncompressedBytes,
435
+ documents: item.documents,
436
+ chunks: item.chunks,
437
+ embeddingProfile: item.embeddingProfile,
438
+ topics: item.topics,
439
+ ...(item.minGezelVersion ? { minGezelVersion: item.minGezelVersion } : {}),
440
+ ...(entry
441
+ ? {
442
+ installed: {
443
+ version: entry.ref.version,
444
+ contentDigest: entry.ref.contentDigest,
445
+ storageScope: entry.ref.storageScope,
446
+ enabled: entry.enabled,
447
+ updateAvailable: compareCatalogVersions(item.version, entry.ref.version) > 0,
448
+ },
449
+ }
450
+ : {}),
451
+ sharedOnDevice: shared.has(`${item.publisherId}/${item.id}/${item.version}/${item.sha256}`),
452
+ installing: activeIds.has(item.id),
453
+ incompleteDownload: partials.has(item.sha256.slice(0, 16)),
454
+ };
455
+ });
456
+ }
457
+ /** Resolve a catalogId (URI authority) to its mounted info, or null. */
458
+ mountedCatalog(catalogId) {
459
+ for (const info of this.mountedByKey.values()) {
460
+ if (info.ref.catalogId === catalogId)
461
+ return info;
462
+ }
463
+ return null;
464
+ }
465
+ // ── install jobs ──────────────────────────────────────────────────────────
466
+ /**
467
+ * Start an install, or attach to the one already running. A catalog
468
+ * install's job id is the catalog id, so a second click, the auto-updater
469
+ * and a reconnecting client all land on the same job.
470
+ */
471
+ startInstall(request) {
472
+ const jobId = request.kind === 'catalog'
473
+ ? request.id
474
+ : `knowledge-install-${++this.jobCounter}-${Date.now().toString(36)}`;
475
+ const { alreadyRunning } = this.installs.start(jobId, { request });
476
+ if (!alreadyRunning)
477
+ this.jobRequests.set(jobId, request);
478
+ return { jobId, alreadyRunning };
479
+ }
480
+ async planInstall(request) {
481
+ if (request.kind !== 'catalog') {
482
+ return { source: request, origin: request.kind, placement: 'user' };
483
+ }
484
+ if (!this.opts.catalog)
485
+ return { error: 'the catalog is not available in this daemon' };
486
+ const resolved = await resolveKnowledgeCatalogSource(this.opts.catalog, request.id, request.version);
487
+ if (!resolved) {
488
+ return {
489
+ error: `no knowledge catalog '${request.id}'${request.version ? `@${request.version}` : ''} in the catalog`,
490
+ };
491
+ }
492
+ return {
493
+ source: { kind: 'url', url: resolved.url, expectedSha256: resolved.sha256 },
494
+ origin: 'gilde',
495
+ archiveBytes: resolved.archiveBytes,
496
+ expectedIdentity: {
497
+ publisherId: resolved.coordinate.publisherId,
498
+ catalogId: resolved.coordinate.catalogId,
499
+ version: resolved.coordinate.version,
500
+ },
501
+ coordinate: resolved.coordinate,
502
+ placement: request.placement ?? 'auto',
503
+ };
504
+ }
505
+ /**
506
+ * Ask the machine broker to ensure the coordinate in the shared store,
507
+ * relaying its progress. Cancelling this job cancels the broker's too:
508
+ * this daemon asked for the download, so its cancel is the honest signal.
509
+ */
510
+ async *installShared(coordinate, installer, signal) {
511
+ const queue = [];
512
+ let result = null;
513
+ let wake = null;
514
+ const notify = () => {
515
+ wake?.();
516
+ wake = null;
517
+ };
518
+ const run = installer
519
+ .ensure(coordinate, (event) => {
520
+ queue.push(event);
521
+ notify();
522
+ }, signal)
523
+ .then((outcome) => {
524
+ result = outcome;
525
+ }, (err) => {
526
+ result = { status: 'unavailable', reason: errorMessage(err) };
527
+ })
528
+ .finally(notify);
529
+ try {
530
+ while (true) {
531
+ const next = queue.shift();
532
+ if (next) {
533
+ yield next;
534
+ continue;
535
+ }
536
+ if (result)
537
+ break;
538
+ await new Promise((resolveWake) => {
539
+ wake = resolveWake;
540
+ });
541
+ }
542
+ }
543
+ finally {
544
+ if (signal.aborted)
545
+ void installer.cancel(coordinate);
546
+ }
547
+ await run;
548
+ return result ?? { status: 'unavailable', reason: 'the shared installer returned nothing' };
549
+ }
550
+ /** Bytes a private install of this catalog left behind, once a shared copy replaces it. */
551
+ async deletePrivateBytes(ref) {
552
+ const catalogDir = join(knowledgeCatalogsDir(this.opts.home), ref.publisherId, ref.catalogId);
553
+ await rm(catalogDir, {
554
+ recursive: true,
555
+ force: true,
556
+ maxRetries: 5,
557
+ retryDelay: 100,
558
+ }).catch((err) => {
559
+ log.warn(`could not delete ${catalogDir}: ${err}`);
560
+ });
561
+ }
562
+ async *runInstall(jobId, request) {
563
+ // The registry cancels by unwinding this generator; the inner download
564
+ // only stops when its signal fires, so abort in `finally` rather than
565
+ // relying on the unwind alone.
566
+ const abort = new AbortController();
567
+ const installedBefore = new Map(this.registry.read().catalogs.map((c) => [this.keyFor(c.ref), c.ref.version]));
568
+ const catalogId = request.kind === 'catalog' ? request.id : undefined;
569
+ const endPerfWork = beginPerfWork(`knowledge install ${catalogId ?? request.kind}`);
570
+ try {
571
+ const plan = await this.planInstall(request);
572
+ if ('error' in plan) {
573
+ await this.recordInstallFailure(jobId, catalogId, plan.error);
574
+ yield { type: 'error', error: plan.error };
575
+ return;
576
+ }
577
+ const installer = this.opts.sharedInstaller;
578
+ if (plan.coordinate && plan.placement === 'auto' && installer?.available()) {
579
+ const shared = yield* this.installShared(plan.coordinate, installer, abort.signal);
580
+ if (shared.status === 'ready') {
581
+ const ref = {
582
+ publisherId: plan.coordinate.publisherId,
583
+ catalogId: plan.coordinate.catalogId,
584
+ version: plan.coordinate.version,
585
+ contentDigest: plan.coordinate.expectedDigest,
586
+ storageScope: 'machine-shared',
587
+ };
588
+ const previous = this.registry.find(ref.publisherId, ref.catalogId);
589
+ this.registry.upsert(ref, { enabled: true, source: plan.origin });
590
+ yield* this.finishInstall({ type: 'done', ref, rootDir: this.dirFor(ref), storageScope: 'machine-shared' }, installedBefore, plan.origin, previous?.ref.storageScope === 'user');
591
+ return;
592
+ }
593
+ if (shared.status === 'failed') {
594
+ await this.recordInstallFailure(jobId, catalogId, shared.error);
595
+ yield { type: 'error', error: shared.error, mismatch: shared.mismatch };
596
+ return;
597
+ }
598
+ if (abort.signal.aborted)
599
+ return;
600
+ log.info(`shared placement unavailable for ${plan.coordinate.catalogId}@${plan.coordinate.version} (${shared.reason}); installing privately`);
601
+ }
602
+ if (plan.source.kind === 'url') {
603
+ this.jobDownloadKeys.set(jobId, knowledgeDownloadKey(plan.source));
604
+ }
605
+ const run = installKnowledgeCatalog({
606
+ home: this.opts.home,
607
+ source: plan.source,
608
+ origin: plan.origin,
609
+ ...(plan.archiveBytes !== undefined ? { archiveBytes: plan.archiveBytes } : {}),
610
+ ...(plan.expectedIdentity ? { expectedIdentity: plan.expectedIdentity } : {}),
611
+ registry: this.registry,
612
+ ...(this.opts.fetchImpl ? { fetchImpl: this.opts.fetchImpl } : {}),
613
+ signal: abort.signal,
614
+ validateCatalog: (rootDir, deep) => this.opts.host.validate(rootDir, deep),
615
+ });
616
+ for await (const event of run) {
617
+ if (event.type === 'done') {
618
+ yield* this.finishInstall(event, installedBefore, plan.origin);
619
+ return;
620
+ }
621
+ if (event.type === 'error')
622
+ await this.recordInstallFailure(jobId, catalogId, event.error);
623
+ yield event;
624
+ }
625
+ }
626
+ finally {
627
+ endPerfWork();
628
+ abort.abort();
629
+ this.jobDownloadKeys.delete(jobId);
630
+ this.jobRequests.delete(jobId);
631
+ }
632
+ }
633
+ /** Mount the fresh version, record it, and warm the query embedder before `done`. */
634
+ async *finishInstall(event, installedBefore, origin, deletePrivateBytes = false) {
635
+ const key = this.keyFor(event.ref);
636
+ await this.opts.host.unmount(key).catch(() => { });
637
+ this.mountedByKey.delete(key);
638
+ if (deletePrivateBytes) {
639
+ await this.deletePrivateBytes(event.ref);
640
+ }
641
+ else if (event.ref.storageScope === 'user') {
642
+ await pruneOtherKnowledgeCatalogVersions(this.opts.home, event.ref);
643
+ }
644
+ const entry = this.registry.find(event.ref.publisherId, event.ref.catalogId);
645
+ if (entry) {
646
+ try {
647
+ await this.mountEntry(entry, { justVerified: true });
648
+ }
649
+ catch (err) {
650
+ const reason = errorMessage(err);
651
+ this.registry.quarantine(event.ref.publisherId, event.ref.catalogId, reason);
652
+ await this.logHistory('knowledge.catalog.install_failed', `Knowledge catalog ${event.ref.catalogId}@${event.ref.version} installed but failed to mount`, {
653
+ publisherId: event.ref.publisherId,
654
+ catalogId: event.ref.catalogId,
655
+ version: event.ref.version,
656
+ source: origin,
657
+ storageScope: event.ref.storageScope,
658
+ error: reason,
659
+ });
660
+ yield { type: 'error', error: `installed but failed to mount: ${reason}` };
661
+ return;
662
+ }
663
+ }
664
+ const previousVersion = installedBefore.get(key);
665
+ const updated = previousVersion !== undefined && previousVersion !== event.ref.version;
666
+ await this.logHistory(updated ? 'knowledge.catalog.updated' : 'knowledge.catalog.installed', updated
667
+ ? `Knowledge catalog ${event.ref.catalogId} updated ${previousVersion} → ${event.ref.version}`
668
+ : `Knowledge catalog ${event.ref.catalogId}@${event.ref.version} installed`, {
669
+ publisherId: event.ref.publisherId,
670
+ catalogId: event.ref.catalogId,
671
+ version: event.ref.version,
672
+ source: origin,
673
+ storageScope: event.ref.storageScope,
674
+ ...(updated ? { previousVersion } : {}),
675
+ });
676
+ let warning;
677
+ const mounted = this.mountedByKey.get(key);
678
+ if (mounted?.semanticSearch === 'profile') {
679
+ yield { type: 'progress', phase: 'embedder', bytesDone: 0, bytesTotal: 0 };
680
+ warning = yield* this.prewarmProfile(mounted.embedding);
681
+ }
682
+ yield { ...event, ...(warning ? { warning } : {}) };
683
+ }
684
+ /**
685
+ * Pull the catalog's query model now, while the user is watching the
686
+ * install, instead of on the first search. Never an install failure: the
687
+ * catalog is on disk and keyword search works without the model. The model
688
+ * can outweigh the catalog — multilingual-e5-small's full-precision graph
689
+ * is ~470 MB against a 160 MB Wikipedia catalog — so its download reports
690
+ * bytes the way the catalog's own does.
691
+ *
692
+ * Not gated on `allowAppNetwork`: every install is either a person's own
693
+ * download or an auto-update `checkAutoUpdates` already gated, and skipping
694
+ * the model here would leave an offline machine without semantic search.
695
+ */
696
+ async *prewarmProfile(profile) {
697
+ const progress = { latest: null, reported: null };
698
+ let lastReportAt = 0;
699
+ let outcome = null;
700
+ let wake = null;
701
+ let finished = false;
702
+ const notify = () => {
703
+ wake?.();
704
+ wake = null;
705
+ };
706
+ const configuredTimeout = Number.parseInt(this.opts.env?.GEZEL_KNOWLEDGE_PREWARM_TIMEOUT_MS ??
707
+ process.env.GEZEL_KNOWLEDGE_PREWARM_TIMEOUT_MS ??
708
+ '', 10);
709
+ const timeoutMs = this.opts.profilePrewarmTimeoutMs ??
710
+ (Number.isFinite(configuredTimeout) && configuredTimeout > 0
711
+ ? configuredTimeout
712
+ : DEFAULT_EMBEDDER_PREWARM_TIMEOUT_MS);
713
+ const timeout = setTimeout(() => {
714
+ if (finished)
715
+ return;
716
+ outcome = {
717
+ warning: `semantic search starts once the embedding model ${profile.model.repo} is available; prewarm exceeded ${timeoutMs}ms`,
718
+ };
719
+ notify();
720
+ }, timeoutMs);
721
+ void (this.opts.embedQueryForProfile ?? embedKnowledgeQuery)('knowledge catalog warm-up', profile, {
722
+ onDownloadProgress: (next) => {
723
+ progress.latest = next;
724
+ if (Date.now() - lastReportAt >= EMBEDDER_PROGRESS_INTERVAL_MS)
725
+ notify();
726
+ },
727
+ }).then(() => {
728
+ if (finished)
729
+ return;
730
+ outcome = { warning: undefined };
731
+ notify();
732
+ }, (err) => {
733
+ if (finished)
734
+ return;
735
+ outcome = {
736
+ warning: `semantic search starts once the embedding model ${profile.model.repo} is available: ${errorMessage(err)}`,
737
+ };
738
+ notify();
739
+ });
740
+ try {
741
+ while (true) {
742
+ const settled = outcome;
743
+ const latest = progress.latest;
744
+ if (latest &&
745
+ latest !== progress.reported &&
746
+ (settled || Date.now() - lastReportAt >= EMBEDDER_PROGRESS_INTERVAL_MS)) {
747
+ progress.reported = latest;
748
+ lastReportAt = Date.now();
749
+ yield { type: 'progress', phase: 'embedder', ...latest };
750
+ continue;
751
+ }
752
+ if (settled)
753
+ return settled.warning;
754
+ await new Promise((resolveWake) => {
755
+ wake = resolveWake;
756
+ });
757
+ }
758
+ }
759
+ finally {
760
+ finished = true;
761
+ clearTimeout(timeout);
762
+ }
763
+ }
764
+ async recordInstallFailure(jobId, catalogId, error) {
765
+ await this.logHistory('knowledge.catalog.install_failed', `Knowledge catalog install ${catalogId ?? jobId} failed`, { jobId, ...(catalogId ? { catalogId } : {}), error });
766
+ }
767
+ getJob(jobId) {
768
+ const described = this.installs.describe(jobId);
769
+ if (!described)
770
+ return null;
771
+ const events = [described.lastEvent, described.terminalEvent].filter((event) => event !== null);
772
+ return {
773
+ id: described.id,
774
+ startedAt: described.startedAt,
775
+ finished: described.finished,
776
+ ...(described.error ? { error: described.error } : {}),
777
+ events,
778
+ };
779
+ }
780
+ /** Live events for a job; replays the latest progress (and the terminal event) first. */
781
+ subscribeJob(jobId, listener) {
782
+ return this.installs.subscribe(jobId, listener);
783
+ }
784
+ cancelJob(jobId) {
785
+ return this.installs.cancel(jobId);
786
+ }
787
+ /** Every running install with its latest progress (the polled twin of the SSE). */
788
+ activeInstalls() {
789
+ return this.installs.active().map(({ id, startedAt, lastEvent }) => {
790
+ const request = this.jobRequests.get(id);
791
+ const phase = lastEvent?.type === 'progress'
792
+ ? lastEvent.phase
793
+ : lastEvent?.type === 'verifying'
794
+ ? 'verifying'
795
+ : lastEvent?.type === 'retrying'
796
+ ? 'retrying'
797
+ : 'download';
798
+ return {
799
+ jobId: id,
800
+ ...(request?.kind === 'catalog' ? { catalogId: request.id } : {}),
801
+ startedAt,
802
+ phase,
803
+ bytesDone: lastEvent?.type === 'progress' ? lastEvent.bytesDone : 0,
804
+ bytesTotal: lastEvent?.type === 'progress' ? lastEvent.bytesTotal : 0,
805
+ };
806
+ });
807
+ }
808
+ // ── incomplete downloads ──────────────────────────────────────────────────
809
+ async partialDownloadKeys() {
810
+ const keys = new Set();
811
+ let names;
812
+ try {
813
+ names = await readdir(knowledgeDownloadsDir(this.opts.home));
814
+ }
815
+ catch {
816
+ return keys;
817
+ }
818
+ const live = new Set(this.jobDownloadKeys.values());
819
+ for (const name of names) {
820
+ if (!name.endsWith('.gezk.partial'))
821
+ continue;
822
+ const key = name.slice(0, -'.gezk.partial'.length);
823
+ if (KNOWLEDGE_DOWNLOAD_KEY_PATTERN.test(key) && !live.has(key))
824
+ keys.add(key);
825
+ }
826
+ return keys;
827
+ }
828
+ /**
829
+ * Partial archives no job is writing. A key that still matches a gilde
830
+ * pin resumes on the next install of that catalog; anything else can only
831
+ * be deleted. Largest first: the most disk to reclaim.
832
+ */
833
+ async listIncompleteDownloads() {
834
+ const keys = await this.partialDownloadKeys();
835
+ if (keys.size === 0)
836
+ return [];
837
+ const downloads = knowledgeDownloadsDir(this.opts.home);
838
+ const byDigestPrefix = new Map();
839
+ for (const item of (await this.gildeItems()).values()) {
840
+ byDigestPrefix.set(item.sha256.slice(0, 16), item);
841
+ }
842
+ const out = [];
843
+ for (const key of keys) {
844
+ const info = await stat(join(downloads, `${key}.gezk.partial`)).catch(() => null);
845
+ if (!info)
846
+ continue;
847
+ const item = byDigestPrefix.get(key);
848
+ out.push({
849
+ key,
850
+ bytes: info.size,
851
+ updatedAt: info.mtime.toISOString(),
852
+ resumable: Boolean(item),
853
+ ...(item ? { catalogId: item.id, name: item.name, archiveBytes: item.archiveBytes } : {}),
854
+ });
855
+ }
856
+ return out.sort((a, b) => b.bytes - a.bytes);
857
+ }
858
+ /** Delete a partial download by key. Refuses a key a running job is writing. */
859
+ async deleteIncompleteDownload(key) {
860
+ if (!KNOWLEDGE_DOWNLOAD_KEY_PATTERN.test(key))
861
+ return false;
862
+ if (new Set(this.jobDownloadKeys.values()).has(key))
863
+ return false;
864
+ const downloads = knowledgeDownloadsDir(this.opts.home);
865
+ let removed = false;
866
+ for (const name of [`${key}.gezk.partial`, `${key}.gezk`]) {
867
+ const path = join(downloads, name);
868
+ if (!(await stat(path).catch(() => null)))
869
+ continue;
870
+ await rm(path, { force: true });
871
+ removed = true;
872
+ }
873
+ return removed;
874
+ }
875
+ // ── auto-update ───────────────────────────────────────────────────────────
876
+ /**
877
+ * Start installs for catalogs whose registry entry (or the install-wide
878
+ * `config.knowledge.autoUpdate` default) opted into automatic updates.
879
+ * Returns the `catalog@version` pairs it started.
880
+ */
881
+ async checkAutoUpdates() {
882
+ if (!(await this.networkAllowed()))
883
+ return [];
884
+ const config = await this.readConfig();
885
+ const defaultAutoUpdate = config?.knowledge?.autoUpdate ?? false;
886
+ const started = [];
887
+ for (const update of await this.updates()) {
888
+ const entry = this.registry.find(update.publisherId, update.catalogId);
889
+ if (!(entry?.autoUpdate ?? defaultAutoUpdate))
890
+ continue;
891
+ const { alreadyRunning } = this.startInstall({
892
+ kind: 'catalog',
893
+ id: update.catalogId,
894
+ version: update.availableVersion,
895
+ });
896
+ if (!alreadyRunning)
897
+ started.push(`${update.catalogId}@${update.availableVersion}`);
898
+ }
899
+ if (started.length > 0)
900
+ log.info(`auto-updating knowledge catalogs: ${started.join(', ')}`);
901
+ return started;
902
+ }
903
+ /** Arm the daily auto-update check (a quiet start, then every 24 h); `stop()` disarms. */
904
+ startAutoUpdateTimer() {
905
+ const run = () => {
906
+ void this.checkAutoUpdates().catch((err) => {
907
+ log.warn(`knowledge auto-update check failed: ${errorMessage(err)}`);
908
+ });
909
+ };
910
+ const startup = setTimeout(run, AUTO_UPDATE_STARTUP_DELAY_MS);
911
+ startup.unref?.();
912
+ const interval = setInterval(run, AUTO_UPDATE_INTERVAL_MS);
913
+ interval.unref?.();
914
+ this.autoUpdateTimers.push(startup, interval);
915
+ }
916
+ async readConfig() {
917
+ if (!this.opts.readConfig)
918
+ return null;
919
+ try {
920
+ return await this.opts.readConfig();
921
+ }
922
+ catch {
923
+ return null;
924
+ }
925
+ }
926
+ async networkAllowed() {
927
+ const config = await this.readConfig();
928
+ return config ? resolveSecurityPolicy(config).allowAppNetwork : true;
929
+ }
930
+ async logHistory(kind, summary, details) {
931
+ if (!this.opts.history)
932
+ return;
933
+ try {
934
+ await this.opts.history.log({ kind, summary, details });
935
+ }
936
+ catch (err) {
937
+ log.warn(`history write failed for ${kind}: ${errorMessage(err)}`);
938
+ }
939
+ }
940
+ // ── lifecycle mutations ───────────────────────────────────────────────────
941
+ async setEnabled(catalogId, enabled) {
942
+ const entry = this.registry.read().catalogs.find((c) => c.ref.catalogId === catalogId);
943
+ if (!entry)
944
+ return false;
945
+ const changed = this.registry.setEnabled(entry.ref.publisherId, catalogId, enabled);
946
+ if (!changed)
947
+ return false;
948
+ const key = this.keyFor(entry.ref);
949
+ if (enabled) {
950
+ const fresh = this.registry.find(entry.ref.publisherId, catalogId);
951
+ if (fresh) {
952
+ await this.mountEntry(fresh).catch((err) => {
953
+ const reason = errorMessage(err);
954
+ this.registry.quarantine(entry.ref.publisherId, catalogId, reason);
955
+ });
956
+ }
957
+ }
958
+ else {
959
+ await this.opts.host.unmount(key).catch(() => { });
960
+ this.mountedByKey.delete(key);
961
+ }
962
+ await this.logHistory(enabled ? 'knowledge.catalog.enabled' : 'knowledge.catalog.disabled', `Knowledge catalog ${catalogId} ${enabled ? 'enabled' : 'disabled'}`, {
963
+ publisherId: entry.ref.publisherId,
964
+ catalogId,
965
+ version: entry.ref.version,
966
+ storageScope: entry.ref.storageScope,
967
+ });
968
+ return true;
969
+ }
970
+ /**
971
+ * Adopt a catalog that already exists in the machine-shared asset store:
972
+ * add this user's ref and mount read-only. The shared bytes belong to the
973
+ * machine installer — adoption and removal never touch them.
974
+ */
975
+ async adoptSharedCatalog(coordinate) {
976
+ const ref = {
977
+ publisherId: coordinate.publisherId,
978
+ catalogId: coordinate.catalogId,
979
+ version: coordinate.version,
980
+ contentDigest: coordinate.expectedDigest,
981
+ storageScope: 'machine-shared',
982
+ };
983
+ this.registry.upsert(ref, { enabled: true, source: 'gilde' });
984
+ const entry = this.registry.find(ref.publisherId, ref.catalogId);
985
+ if (!entry)
986
+ return false;
987
+ try {
988
+ const key = this.keyFor(ref);
989
+ await this.opts.host.unmount(key).catch(() => { });
990
+ this.mountedByKey.delete(key);
991
+ await this.mountEntry(entry);
992
+ return true;
993
+ }
994
+ catch (err) {
995
+ const reason = errorMessage(err);
996
+ this.registry.quarantine(ref.publisherId, ref.catalogId, reason);
997
+ return false;
998
+ }
999
+ }
1000
+ /** Remove the ref and (for the private tier) delete the bytes. */
1001
+ async remove(catalogId) {
1002
+ const entry = this.registry.read().catalogs.find((c) => c.ref.catalogId === catalogId);
1003
+ if (!entry)
1004
+ return false;
1005
+ if (entry.source === 'bundled')
1006
+ return false;
1007
+ const key = this.keyFor(entry.ref);
1008
+ await this.opts.host.unmount(key).catch(() => { });
1009
+ this.mountedByKey.delete(key);
1010
+ this.registry.remove(entry.ref.publisherId, catalogId);
1011
+ if (entry.ref.storageScope === 'user') {
1012
+ const catalogDir = join(knowledgeCatalogsDir(this.opts.home), entry.ref.publisherId, entry.ref.catalogId);
1013
+ await rm(catalogDir, { recursive: true, force: true }).catch((err) => {
1014
+ log.warn(`could not delete ${catalogDir}: ${err}`);
1015
+ });
1016
+ }
1017
+ await this.logHistory('knowledge.catalog.removed', `Knowledge catalog ${catalogId}@${entry.ref.version} removed`, {
1018
+ publisherId: entry.ref.publisherId,
1019
+ catalogId,
1020
+ version: entry.ref.version,
1021
+ storageScope: entry.ref.storageScope,
1022
+ });
1023
+ return true;
1024
+ }
1025
+ // ── browsing (routes) ─────────────────────────────────────────────────────
1026
+ requireMounted(catalogId) {
1027
+ const info = this.mountedCatalog(catalogId);
1028
+ if (!info)
1029
+ throw new KnowledgeNotFoundError(`catalog not installed or not enabled: ${catalogId}`);
1030
+ return info;
1031
+ }
1032
+ async topics(catalogId) {
1033
+ return this.opts.host.topics(this.requireMounted(catalogId).key);
1034
+ }
1035
+ async documentsPage(catalogId, opts) {
1036
+ return this.opts.host.documentsPage(this.requireMounted(catalogId).key, opts);
1037
+ }
1038
+ async getDocument(catalogId, documentId) {
1039
+ return this.opts.host.getDocument(this.requireMounted(catalogId).key, documentId);
1040
+ }
1041
+ /** One passage by its citation id, with the document's title and origin. */
1042
+ async getPassage(catalogId, documentId, chunkUid) {
1043
+ const info = this.requireMounted(catalogId);
1044
+ const chunk = await this.opts.host.getChunk(info.key, documentId, chunkUid);
1045
+ if (!chunk)
1046
+ return null;
1047
+ const doc = await this.opts.host.getDocument(info.key, documentId).catch(() => null);
1048
+ return {
1049
+ catalogId,
1050
+ catalogVersion: info.ref.version,
1051
+ documentId,
1052
+ chunkUid,
1053
+ title: doc?.title ?? chunk.title,
1054
+ headingPath: chunk.headingPath,
1055
+ lineStart: chunk.lineStart,
1056
+ lineEnd: chunk.lineEnd,
1057
+ text: chunk.text,
1058
+ ...(doc?.sourceUrl ? { sourceUrl: doc.sourceUrl } : {}),
1059
+ ...(doc?.sourceUpdatedAt ? { sourceUpdatedAt: doc.sourceUpdatedAt } : {}),
1060
+ };
1061
+ }
1062
+ /**
1063
+ * Resolve a `knowledge://` citation: the catalog (publisher included) is
1064
+ * installed and enabled, the document exists, and a `#chunk=` passage is in
1065
+ * it. A citation is only evidence when it resolves; a model can write a
1066
+ * well-formed URI for a passage that does not exist.
1067
+ */
1068
+ async resolveCitation(raw) {
1069
+ const uri = parseKnowledgeUri(raw.trim());
1070
+ if (!uri)
1071
+ return { ok: false, reason: 'malformed' };
1072
+ const info = this.mountedCatalog(uri.catalogId);
1073
+ if (!info || info.ref.publisherId !== uri.publisherId)
1074
+ return { ok: false, reason: 'catalog-not-installed' };
1075
+ const doc = await this.opts.host.getDocument(info.key, uri.documentId).catch(() => null);
1076
+ if (!doc)
1077
+ return { ok: false, reason: 'no-document' };
1078
+ const base = {
1079
+ ok: true,
1080
+ uri,
1081
+ title: doc.title,
1082
+ catalogVersion: info.ref.version,
1083
+ ...(doc.sourceUrl ? { sourceUrl: doc.sourceUrl } : {}),
1084
+ };
1085
+ if (uri.fragment && 'chunk' in uri.fragment) {
1086
+ const chunk = await this.opts.host
1087
+ .getChunk(info.key, uri.documentId, uri.fragment.chunk)
1088
+ .catch(() => null);
1089
+ if (!chunk)
1090
+ return { ok: false, reason: 'no-passage' };
1091
+ return { ...base, chunk };
1092
+ }
1093
+ return { ...base, markdown: doc.markdown };
1094
+ }
1095
+ async assets(catalogId) {
1096
+ return this.opts.host.assets(this.requireMounted(catalogId).key);
1097
+ }
1098
+ async readAsset(catalogId, path) {
1099
+ return this.opts.host.readAsset(this.requireMounted(catalogId).key, path);
1100
+ }
1101
+ async assetFile(catalogId, path) {
1102
+ return this.opts.host.assetFile(this.requireMounted(catalogId).key, path);
1103
+ }
1104
+ /** The mounted version of a catalog — what an asset URL binds to for caching. */
1105
+ mountedVersion(catalogId) {
1106
+ return this.requireMounted(catalogId).ref.version;
1107
+ }
1108
+ // ── the SearchService knowledge arm ───────────────────────────────────────
1109
+ /**
1110
+ * Discover subject articles under the active catalog policy. Source replicas
1111
+ * deduplicate before counts and cursor pages, and scope is checked again
1112
+ * before returning the response if catalogs changed during worker scans.
1113
+ */
1114
+ async nearby(request, projectId) {
1115
+ const body = KnowledgeNearbyRequestSchema.parse(request);
1116
+ const keys = (await this.activeCatalogKeys(projectId, true))
1117
+ .filter((key) => !body.catalogs || body.catalogs.includes(this.mountedByKey.get(key).ref.catalogId))
1118
+ .sort();
1119
+ const snapshot = createHash('sha256')
1120
+ .update(JSON.stringify({
1121
+ spatial: body.spatial,
1122
+ projectId,
1123
+ refs: keys.map((key) => this.mountedByKey.get(key).ref),
1124
+ }))
1125
+ .digest('hex');
1126
+ const offset = nearbyCursorOffset(body.cursor, snapshot);
1127
+ const unique = new Map();
1128
+ for (const key of keys) {
1129
+ const info = this.mountedByKey.get(key);
1130
+ let start = 0;
1131
+ for (;;) {
1132
+ const page = await this.opts.host.nearbyDocuments(key, body.spatial, {
1133
+ offset: start,
1134
+ limit: 500,
1135
+ });
1136
+ for (const document of page.documents) {
1137
+ const result = {
1138
+ ...document,
1139
+ publisherId: info.ref.publisherId,
1140
+ catalogId: info.ref.catalogId,
1141
+ catalogVersion: info.ref.version,
1142
+ uri: formatKnowledgeUri({
1143
+ publisherId: info.ref.publisherId,
1144
+ catalogId: info.ref.catalogId,
1145
+ documentId: document.id,
1146
+ }),
1147
+ };
1148
+ const identity = regionalDocumentIdentity(info.ref.publisherId, info.ref.catalogId, document.id);
1149
+ const previous = unique.get(identity);
1150
+ if (!previous || result.distanceMeters < previous.distanceMeters)
1151
+ unique.set(identity, result);
1152
+ }
1153
+ start += page.documents.length;
1154
+ if (start >= page.total || !page.documents.length)
1155
+ break;
1156
+ }
1157
+ }
1158
+ const ordered = [...unique.values()].sort((a, b) => a.distanceMeters - b.distanceMeters ||
1159
+ a.publisherId.localeCompare(b.publisherId) ||
1160
+ a.catalogId.localeCompare(b.catalogId) ||
1161
+ a.id.localeCompare(b.id));
1162
+ const currentKeys = (await this.activeCatalogKeys(projectId, true))
1163
+ .filter((key) => this.mountedByKey.has(key) &&
1164
+ (!body.catalogs || body.catalogs.includes(this.mountedByKey.get(key).ref.catalogId)))
1165
+ .sort();
1166
+ const currentSnapshot = createHash('sha256')
1167
+ .update(JSON.stringify({
1168
+ spatial: body.spatial,
1169
+ projectId,
1170
+ refs: currentKeys.map((key) => this.mountedByKey.get(key).ref),
1171
+ }))
1172
+ .digest('hex');
1173
+ if (currentSnapshot !== snapshot)
1174
+ throw new KnowledgeSpatialCursorError('Catalog scope changed during nearby query; restart the query.');
1175
+ const documents = ordered.slice(offset, offset + body.limit);
1176
+ const next = offset + documents.length;
1177
+ return {
1178
+ documents,
1179
+ total: ordered.length,
1180
+ ...(next < ordered.length ? { nextCursor: encodeNearbyCursor(snapshot, next) } : {}),
1181
+ };
1182
+ }
1183
+ /**
1184
+ * Search each catalog in its embedding space and fuse lexical/vector ranks.
1185
+ * Spatial eligibility applies inside workers before candidate selection.
1186
+ */
1187
+ async searchUnified(query, opts) {
1188
+ const active = (await this.activeCatalogKeys(opts.projectId, Boolean(opts.spatial))).filter((key) => !opts.catalogs || opts.catalogs.includes(this.mountedByKey.get(key).ref.catalogId));
1189
+ if (active.length === 0)
1190
+ return [];
1191
+ const groups = [];
1192
+ const shared = [];
1193
+ const keyword = [];
1194
+ const byProfile = new Map();
1195
+ for (const key of active) {
1196
+ const info = this.mountedByKey.get(key);
1197
+ if (!info)
1198
+ continue;
1199
+ if (info.semanticSearch === 'shared' && !opts.localModelsOnly)
1200
+ shared.push(key);
1201
+ else if (info.semanticSearch === 'profile' || info.semanticSearch === 'shared') {
1202
+ const group = byProfile.get(info.embedding.id) ?? { profile: info.embedding, keys: [] };
1203
+ group.keys.push(key);
1204
+ byProfile.set(info.embedding.id, group);
1205
+ }
1206
+ else
1207
+ keyword.push(key);
1208
+ }
1209
+ if (shared.length > 0) {
1210
+ groups.push({
1211
+ keys: shared,
1212
+ ...(opts.vector ? { vector: Float32Array.from(opts.vector) } : {}),
1213
+ });
1214
+ }
1215
+ for (const group of byProfile.values()) {
1216
+ const vector = await this.embedForProfile(query, group.profile, opts.queryEmbedBudgetMs, opts.localModelsOnly);
1217
+ groups.push({ keys: group.keys, ...(vector ? { vector } : {}) });
1218
+ }
1219
+ if (keyword.length > 0)
1220
+ groups.push({ keys: keyword });
1221
+ const response = {
1222
+ chunks: [],
1223
+ documents: [],
1224
+ };
1225
+ for (const group of groups) {
1226
+ const request = {
1227
+ query,
1228
+ shardBudget: ROUTE_BUDGET_EXPLICIT,
1229
+ titleRouteShards: TITLE_ROUTE_EXPLICIT,
1230
+ finalK: FINAL_K,
1231
+ includeChunkFts: true,
1232
+ catalogKeys: group.keys,
1233
+ // A pool no deeper than the page asked for: six title hits could
1234
+ // never fill a twenty-result browse search.
1235
+ docFtsLimit: Math.max(DOC_FTS_MIN, opts.maxResults),
1236
+ chunkFtsLimit: Math.max(CHUNK_FTS_MIN, opts.maxResults),
1237
+ spatial: opts.spatial,
1238
+ };
1239
+ let part;
1240
+ try {
1241
+ part = await this.opts.host.search(group.vector
1242
+ ? { ...request, vector: group.vector, ...(opts.media ? { mediaK: MEDIA_K } : {}) }
1243
+ : request);
1244
+ }
1245
+ catch (error) {
1246
+ // A catalog that refuses the query vector (a width the catalog does
1247
+ // not store, say) is an embedding failure, not a search failure: the
1248
+ // worker forwards only the message, so any vector-arm error falls
1249
+ // back to the keyword arms for this group.
1250
+ if (!group.vector)
1251
+ throw error;
1252
+ log.warn(`[knowledge] semantic search failed for ${group.keys.join(', ')}; keyword-only: ${error instanceof Error ? error.message : String(error)}`);
1253
+ part = await this.opts.host.search(request);
1254
+ }
1255
+ response.chunks.push(...part.chunks);
1256
+ response.documents.push(...part.documents);
1257
+ }
1258
+ // ── fuse the arms per document ──────────────────────────────────────
1259
+ const fused = new Map();
1260
+ const bump = (catalogKey, documentId, weight, rank, chunk) => {
1261
+ const key = `${catalogKey}\u0000${documentId}`;
1262
+ const entry = fused.get(key) ?? { catalogKey, documentId, score: 0 };
1263
+ entry.score += weight / (RRF_K + rank);
1264
+ // The document's representative chunk: its best vector chunk, else
1265
+ // whichever chunk-FTS row named it.
1266
+ if (chunk && (!entry.chunk || (chunk.cosine ?? -1) > (entry.chunk.cosine ?? -1))) {
1267
+ entry.chunk = chunk;
1268
+ }
1269
+ fused.set(key, entry);
1270
+ };
1271
+ // Vector arm: one rank per document, in rerank-cosine order. A hit under
1272
+ // its profile's floor is not evidence at all — KNN always returns its
1273
+ // nearest rows, and a rank-0 row fuses to relevance 1.0 however far away
1274
+ // it is (see vector-floors.ts).
1275
+ const textChunks = response.chunks.filter((h) => !h.media);
1276
+ const mediaChunks = response.chunks.filter((h) => h.media);
1277
+ const seenVector = new Set();
1278
+ let vectorRank = 0;
1279
+ for (const hit of textChunks
1280
+ .filter((h) => h.cosine !== undefined)
1281
+ .sort((a, b) => (b.cosine ?? 0) - (a.cosine ?? 0))) {
1282
+ const key = `${hit.catalogKey}\u0000${hit.documentId}`;
1283
+ if (seenVector.has(key))
1284
+ continue;
1285
+ const cosine = hit.cosine ?? 0;
1286
+ const floor = this.vectorFloorFor(hit.catalogKey);
1287
+ if (floor !== null && cosine < floor)
1288
+ continue;
1289
+ seenVector.add(key);
1290
+ bump(hit.catalogKey, hit.documentId, ARM_WEIGHTS.vector, vectorRank++, hit);
1291
+ const entry = fused.get(key);
1292
+ if (entry && floor !== null && cosine > (entry.similarity ?? Number.NEGATIVE_INFINITY)) {
1293
+ entry.similarity = cosine;
1294
+ }
1295
+ }
1296
+ // Chunk-body FTS arm: BM25 order as the shards returned it, ranked per catalog.
1297
+ const chunkFtsRank = new Map();
1298
+ const seenChunkFts = new Set();
1299
+ for (const hit of textChunks.filter((h) => h.cosine === undefined)) {
1300
+ const key = `${hit.catalogKey}\u0000${hit.documentId}`;
1301
+ if (seenChunkFts.has(key))
1302
+ continue;
1303
+ seenChunkFts.add(key);
1304
+ const rank = chunkFtsRank.get(hit.catalogKey) ?? 0;
1305
+ chunkFtsRank.set(hit.catalogKey, rank + 1);
1306
+ bump(hit.catalogKey, hit.documentId, ARM_WEIGHTS.chunkFts, rank, hit);
1307
+ }
1308
+ // Doc-title FTS arm: exact-name evidence, ranked per catalog by the host.
1309
+ for (const doc of response.documents) {
1310
+ bump(doc.catalogKey, doc.documentId, ARM_WEIGHTS.docFts, doc.rank);
1311
+ }
1312
+ // Media rows: their own vector arm per modality (a modality with no
1313
+ // measured floor gives no vector evidence — nearest-neighbour search
1314
+ // always returns some image, and a media row has no query words to be
1315
+ // grounded in) and a caption FTS arm.
1316
+ const mediaFused = new Map();
1317
+ const bumpMedia = (hit, weight, rank) => {
1318
+ const key = `${hit.catalogKey}\u0000${hit.chunkUid}`;
1319
+ const entry = mediaFused.get(key) ?? {
1320
+ catalogKey: hit.catalogKey,
1321
+ documentId: hit.documentId,
1322
+ score: 0,
1323
+ chunk: hit,
1324
+ };
1325
+ entry.score += weight / (RRF_K + rank);
1326
+ if ((hit.cosine ?? -1) > (entry.chunk?.cosine ?? -1))
1327
+ entry.chunk = hit;
1328
+ mediaFused.set(key, entry);
1329
+ };
1330
+ const mediaVectorRank = new Map();
1331
+ for (const hit of mediaChunks
1332
+ .filter((h) => h.cosine !== undefined)
1333
+ .sort((a, b) => (b.cosine ?? 0) - (a.cosine ?? 0))) {
1334
+ const modality = hit.media?.modality;
1335
+ const floor = this.vectorFloorFor(hit.catalogKey, modality);
1336
+ if (floor === null || (hit.cosine ?? 0) < floor)
1337
+ continue;
1338
+ const rank = mediaVectorRank.get(modality) ?? 0;
1339
+ mediaVectorRank.set(modality, rank + 1);
1340
+ bumpMedia(hit, MEDIA_ARM_WEIGHTS.vector, rank);
1341
+ const entry = mediaFused.get(`${hit.catalogKey}\u0000${hit.chunkUid}`);
1342
+ if (entry)
1343
+ entry.similarity = Math.max(entry.similarity ?? -1, hit.cosine ?? 0);
1344
+ }
1345
+ let mediaFtsRank = 0;
1346
+ for (const hit of mediaChunks.filter((h) => h.cosine === undefined)) {
1347
+ bumpMedia(hit, MEDIA_ARM_WEIGHTS.chunkFts, mediaFtsRank++);
1348
+ }
1349
+ const ordered = [...fused.values(), ...mediaFused.values()].sort((a, b) => b.score - a.score ||
1350
+ (b.chunk?.cosine ?? -1) - (a.chunk?.cosine ?? -1) ||
1351
+ a.documentId.localeCompare(b.documentId));
1352
+ const matches = new Map([...response.documents, ...response.chunks]
1353
+ .filter((hit) => hit.matchedLocation)
1354
+ .map((hit) => [
1355
+ `${hit.catalogKey}\u0000${hit.documentId}`,
1356
+ { distanceMeters: hit.distanceMeters, matchedLocation: hit.matchedLocation },
1357
+ ]));
1358
+ const seenSpatial = new Set();
1359
+ const out = [];
1360
+ const perCatalogCount = new Map();
1361
+ const capPerCatalog = !opts.spatial && active.length > 1;
1362
+ const mediaPerDocument = new Map();
1363
+ let mediaResults = 0;
1364
+ for (const entry of ordered) {
1365
+ const info = this.mountedByKey.get(entry.catalogKey);
1366
+ if (!info)
1367
+ continue;
1368
+ if (entry.chunk?.media) {
1369
+ const docKey = `${entry.catalogKey}\u0000${entry.documentId}`;
1370
+ const forDocument = mediaPerDocument.get(docKey) ?? 0;
1371
+ if (mediaResults >= MEDIA_RESULT_CAP || forDocument >= MEDIA_PER_DOCUMENT)
1372
+ continue;
1373
+ const evidence = entry.similarity !== undefined
1374
+ ? { arm: 'vector', similarity: entry.similarity }
1375
+ : { arm: 'fts' };
1376
+ mediaPerDocument.set(docKey, forDocument + 1);
1377
+ mediaResults++;
1378
+ out.push(this.toResult(info, entry.chunk, fusedRankRelevance(out.length), evidence));
1379
+ if (out.length >= Math.max(10, opts.maxResults))
1380
+ break;
1381
+ continue;
1382
+ }
1383
+ const count = perCatalogCount.get(entry.catalogKey) ?? 0;
1384
+ if (capPerCatalog && count >= PER_CATALOG_CAP)
1385
+ continue;
1386
+ const spatialIdentity = regionalDocumentIdentity(info.ref.publisherId, info.ref.catalogId, entry.documentId);
1387
+ if (opts.spatial && seenSpatial.has(spatialIdentity))
1388
+ continue;
1389
+ const relevance = fusedRankRelevance(out.length);
1390
+ // `vector` only when the hit cleared a measured floor; everything else
1391
+ // is lexical evidence, which proactive injection asks to be grounded.
1392
+ const evidence = entry.similarity !== undefined
1393
+ ? { arm: 'vector', similarity: entry.similarity }
1394
+ : { arm: 'fts' };
1395
+ const result = entry.chunk
1396
+ ? this.toResult(info, entry.chunk, relevance, evidence)
1397
+ : await this.toDocumentResult(info, entry.documentId, relevance, evidence);
1398
+ if (!result)
1399
+ continue;
1400
+ perCatalogCount.set(entry.catalogKey, count + 1);
1401
+ seenSpatial.add(spatialIdentity);
1402
+ out.push({ ...result, ...matches.get(`${entry.catalogKey}\u0000${entry.documentId}`) });
1403
+ if (out.length >= Math.max(10, opts.maxResults))
1404
+ break;
1405
+ }
1406
+ return out;
1407
+ }
1408
+ /** A document the lexical arms named but no chunk carries: cite it with its lead paragraph. */
1409
+ async toDocumentResult(info, documentId, relevance, evidence) {
1410
+ const doc = await this.opts.host.getDocument(info.key, documentId).catch(() => null);
1411
+ if (!doc)
1412
+ return null;
1413
+ const snippet = leadExcerpt(doc.markdown) || doc.summary || '';
1414
+ return {
1415
+ kind: 'knowledge',
1416
+ id: `knowledge:${info.ref.catalogId}:doc:${documentId}`,
1417
+ title: doc.title,
1418
+ subtitle: `${info.name} · ${info.topicNames.get(doc.topicId) ?? doc.topicId}`,
1419
+ ...(snippet ? { snippet } : {}),
1420
+ retrievalSource: 'knowledge',
1421
+ catalogId: info.ref.catalogId,
1422
+ catalogVersion: info.ref.version,
1423
+ documentId,
1424
+ topicPath: [info.topicNames.get(doc.topicId) ?? doc.topicId],
1425
+ uri: formatKnowledgeUri({
1426
+ publisherId: info.ref.publisherId,
1427
+ catalogId: info.ref.catalogId,
1428
+ documentId,
1429
+ }),
1430
+ ...(doc.sourceUrl ? { sourceUrl: doc.sourceUrl } : {}),
1431
+ ...evidence,
1432
+ ...scoreResult('knowledge', relevance),
1433
+ };
1434
+ }
1435
+ /** A catalog's vector floor, or null when its hits are keyword-only or its scale unmeasured. */
1436
+ vectorFloorFor(catalogKey, modality) {
1437
+ const info = this.mountedByKey.get(catalogKey);
1438
+ if (!info)
1439
+ return null;
1440
+ return this.vectorFloors.floorFor({
1441
+ catalogKey,
1442
+ profileId: info.embedding.id,
1443
+ ...(modality ? { modality } : {}),
1444
+ });
1445
+ }
1446
+ /**
1447
+ * Load every mounted catalog's own query model now. A search waits for
1448
+ * these only briefly, so a caller that needs the semantic path measured
1449
+ * (the retrieval preview's `warm`) loads them first.
1450
+ */
1451
+ async warmQueryModels() {
1452
+ const profiles = new Map();
1453
+ for (const info of this.mountedByKey.values()) {
1454
+ if (info.semanticSearch === 'profile')
1455
+ profiles.set(info.embedding.id, info.embedding);
1456
+ }
1457
+ for (const profile of profiles.values())
1458
+ await this.embedForProfile('warm', profile);
1459
+ }
1460
+ /**
1461
+ * A profile's query vector, or undefined when its model is unavailable or
1462
+ * not ready within `budgetMs` (that group searches FTS). A load that misses
1463
+ * the budget keeps running — loads are single-flight per profile — so the
1464
+ * next query gets vectors.
1465
+ */
1466
+ async embedForProfile(query, profile, budgetMs, localFilesOnly = false) {
1467
+ const pending = (this.opts.embedQueryForProfile ?? embedKnowledgeQuery)(query, profile, {
1468
+ localFilesOnly,
1469
+ });
1470
+ let timer;
1471
+ try {
1472
+ const vector = budgetMs === undefined
1473
+ ? await pending
1474
+ : await Promise.race([
1475
+ pending,
1476
+ new Promise((resolveBudget) => {
1477
+ timer = setTimeout(() => resolveBudget(null), budgetMs);
1478
+ }),
1479
+ ]);
1480
+ if (vector === null) {
1481
+ log.debug(`knowledge query model for profile ${profile.id} not ready within ${budgetMs}ms; searching FTS only`);
1482
+ return undefined;
1483
+ }
1484
+ return vector.length > 0 ? Float32Array.from(vector) : undefined;
1485
+ }
1486
+ catch (err) {
1487
+ log.debug(`knowledge query embedding unavailable for profile ${profile.id}; searching FTS only: ${errorMessage(err)}`);
1488
+ return undefined;
1489
+ }
1490
+ finally {
1491
+ if (timer)
1492
+ clearTimeout(timer);
1493
+ }
1494
+ }
1495
+ toResult(info, hit, relevance, evidence) {
1496
+ return {
1497
+ kind: 'knowledge',
1498
+ id: `knowledge:${info.ref.catalogId}:${hit.chunkUid}`,
1499
+ title: hit.headingPath.length > 0 ? `${hit.title} › ${hit.headingPath.join(' › ')}` : hit.title,
1500
+ subtitle: info.name,
1501
+ snippet: hit.text,
1502
+ retrievalSource: 'knowledge',
1503
+ catalogId: info.ref.catalogId,
1504
+ catalogVersion: info.ref.version,
1505
+ documentId: hit.documentId,
1506
+ uri: formatKnowledgeUri({
1507
+ publisherId: info.ref.publisherId,
1508
+ catalogId: info.ref.catalogId,
1509
+ documentId: hit.documentId,
1510
+ fragment: { chunk: hit.chunkUid },
1511
+ }),
1512
+ line: hit.lineStart,
1513
+ lineEnd: hit.lineEnd,
1514
+ ...(hit.media ? { media: hit.media } : {}),
1515
+ ...evidence,
1516
+ ...scoreResult('knowledge', relevance),
1517
+ };
1518
+ }
1519
+ /** Enabled+mounted catalogs, intersected with the project policy. */
1520
+ async activeCatalogKeys(projectId, failClosed = false) {
1521
+ const mounted = [...this.mountedByKey.values()];
1522
+ if (!projectId || !this.opts.projectPolicy)
1523
+ return mounted.map((m) => m.key);
1524
+ const policy = await this.opts
1525
+ .projectPolicy(projectId)
1526
+ .catch(() => (failClosed ? { mode: 'off' } : null));
1527
+ if (!policy || policy.mode === 'inherit')
1528
+ return mounted.map((m) => m.key);
1529
+ if (policy.mode === 'off')
1530
+ return [];
1531
+ const selected = new Set((policy.refs ?? []).map((r) => `${r.publisherId}/${r.catalogId}`));
1532
+ return mounted.filter((m) => selected.has(m.key)).map((m) => m.key);
1533
+ }
1534
+ }
1535
+ export class KnowledgeNotFoundError extends Error {
1536
+ constructor(message) {
1537
+ super(message);
1538
+ this.name = 'KnowledgeNotFoundError';
1539
+ }
1540
+ }