@bendyline/gezel-inference 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/dist/catalog/chat-models/de/deepseek-v4.1-flash-552b-q2/manifest.json +120 -0
  2. package/dist/catalog/chat-models/de/deepseek-v4.1-flash-552b-q2/versions/1.0.0/manifest.json +21 -0
  3. package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/manifest.json +6 -5
  4. package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/versions/1.0.2/manifest.json +27 -0
  5. package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/versions/1.0.3/manifest.json +27 -0
  6. package/dist/catalog/chat-models/index.json +1 -1
  7. package/dist/catalog/chat-models/ne/nemotron3.5-bolt-74b-iq2/manifest.json +157 -0
  8. package/dist/catalog/chat-models/ne/nemotron3.5-bolt-74b-iq2/versions/1.0.0/manifest.json +30 -0
  9. package/dist/catalog/chat-models/ne/nemotron3.5-super-vl-120b-nvfp4/manifest.json +156 -0
  10. package/dist/catalog/chat-models/ne/nemotron3.5-super-vl-120b-nvfp4/versions/1.0.0/manifest.json +28 -0
  11. package/dist/catalog/chat-models/raw-index.json +1 -1
  12. package/dist/catalog/knowledge-catalogs/be/bendyline-how-to-books/keywords.json +56 -0
  13. package/dist/catalog/knowledge-catalogs/ca/caselaw-alaska-part-0001/keywords.json +12 -0
  14. package/dist/catalog/knowledge-catalogs/ca/caselaw-nevada-part-0001/keywords.json +13 -0
  15. package/dist/catalog/knowledge-catalogs/ca/caselaw-us-300-399-part-0001/keywords.json +14 -0
  16. package/dist/catalog/knowledge-catalogs/ca/caselaw-us-347-349/keywords.json +17 -0
  17. package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0001/keywords.json +12 -0
  18. package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0002/keywords.json +12 -0
  19. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0001/keywords.json +12 -0
  20. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0002/keywords.json +12 -0
  21. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0003/keywords.json +12 -0
  22. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0004/keywords.json +12 -0
  23. package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0005/keywords.json +12 -0
  24. package/dist/catalog/knowledge-catalogs/ca/caselaw-wyoming-part-0001/keywords.json +12 -0
  25. package/dist/catalog/knowledge-catalogs/index.json +1 -1
  26. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-aspnet-core-en/keywords.json +21 -0
  27. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-ai-platform-en/keywords.json +27 -0
  28. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-apps-compute-en/keywords.json +23 -0
  29. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-data-aiot-en/keywords.json +26 -0
  30. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-management-hybrid-en/keywords.json +28 -0
  31. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-network-security-en/keywords.json +29 -0
  32. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-dotnet-en/keywords.json +21 -0
  33. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-entity-framework-en/keywords.json +14 -0
  34. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-microsoft-365-en/keywords.json +20 -0
  35. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-powershell-en/keywords.json +24 -0
  36. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-sql-server-en/keywords.json +27 -0
  37. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-apps-en/keywords.json +18 -0
  38. package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-server-en/keywords.json +28 -0
  39. package/dist/catalog/knowledge-catalogs/raw-index.json +1 -1
  40. package/dist/catalog/knowledge-catalogs/re/regional-american-south/keywords.json +1700 -0
  41. package/dist/catalog/knowledge-catalogs/re/regional-american-south/versions/2026.10.5/manifest.json +133 -0
  42. package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/keywords.json +750 -0
  43. package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/versions/2026.10.5/manifest.json +133 -0
  44. package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/keywords.json +1281 -0
  45. package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/versions/2026.10.5/manifest.json +133 -0
  46. package/dist/catalog/knowledge-catalogs/re/regional-brazil/keywords.json +1125 -0
  47. package/dist/catalog/knowledge-catalogs/re/regional-brazil/versions/2026.10.5/manifest.json +133 -0
  48. package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/keywords.json +3287 -0
  49. package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/versions/2026.10.5/manifest.json +133 -0
  50. package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/keywords.json +1835 -0
  51. package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/versions/2026.10.5/manifest.json +133 -0
  52. package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/keywords.json +1184 -0
  53. package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/versions/2026.10.5/manifest.json +133 -0
  54. package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/keywords.json +1503 -0
  55. package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/versions/2026.10.5/manifest.json +133 -0
  56. package/dist/catalog/knowledge-catalogs/re/regional-east-asia/keywords.json +2836 -0
  57. package/dist/catalog/knowledge-catalogs/re/regional-east-asia/versions/2026.10.5/manifest.json +133 -0
  58. package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/keywords.json +813 -0
  59. package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/versions/2026.10.5/manifest.json +133 -0
  60. package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/keywords.json +2082 -0
  61. package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/versions/2026.10.5/manifest.json +133 -0
  62. package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/keywords.json +1481 -0
  63. package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/versions/2026.10.5/manifest.json +133 -0
  64. package/dist/catalog/knowledge-catalogs/re/regional-middle-east/keywords.json +1272 -0
  65. package/dist/catalog/knowledge-catalogs/re/regional-middle-east/versions/2026.10.5/manifest.json +133 -0
  66. package/dist/catalog/knowledge-catalogs/re/regional-midwest/keywords.json +758 -0
  67. package/dist/catalog/knowledge-catalogs/re/regional-midwest/versions/2026.10.5/manifest.json +133 -0
  68. package/dist/catalog/knowledge-catalogs/re/regional-north-africa/keywords.json +896 -0
  69. package/dist/catalog/knowledge-catalogs/re/regional-north-africa/versions/2026.10.5/manifest.json +133 -0
  70. package/dist/catalog/knowledge-catalogs/re/regional-northeast/keywords.json +1281 -0
  71. package/dist/catalog/knowledge-catalogs/re/regional-northeast/versions/2026.10.5/manifest.json +133 -0
  72. package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/keywords.json +346 -0
  73. package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/versions/2026.10.5/manifest.json +133 -0
  74. package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/keywords.json +2688 -0
  75. package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/versions/2026.10.5/manifest.json +133 -0
  76. package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/keywords.json +973 -0
  77. package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/versions/2026.10.5/manifest.json +133 -0
  78. package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/keywords.json +937 -0
  79. package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/versions/2026.10.5/manifest.json +133 -0
  80. package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/keywords.json +608 -0
  81. package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/versions/2026.10.5/manifest.json +133 -0
  82. package/dist/catalog/knowledge-catalogs/re/regional-south-asia/keywords.json +633 -0
  83. package/dist/catalog/knowledge-catalogs/re/regional-south-asia/versions/2026.10.5/manifest.json +133 -0
  84. package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/keywords.json +2697 -0
  85. package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/versions/2026.10.5/manifest.json +133 -0
  86. package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/keywords.json +606 -0
  87. package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/versions/2026.10.5/manifest.json +133 -0
  88. package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/keywords.json +564 -0
  89. package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/versions/2026.10.5/manifest.json +133 -0
  90. package/dist/catalog/knowledge-catalogs/re/regional-western-europe/keywords.json +3247 -0
  91. package/dist/catalog/knowledge-catalogs/re/regional-western-europe-east/manifest.json +47 -0
  92. package/dist/catalog/knowledge-catalogs/re/regional-western-europe-east/versions/2026.10.5/manifest.json +133 -0
  93. package/dist/catalog/knowledge-catalogs/re/regional-western-europe-west/manifest.json +47 -0
  94. package/dist/catalog/knowledge-catalogs/re/regional-western-europe-west/versions/2026.10.5/manifest.json +133 -0
  95. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/keywords.json +5437 -0
  96. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/manifest.json +1 -1
  97. package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.10.1/manifest.json +181 -0
  98. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/keywords.json +4009 -0
  99. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/manifest.json +1 -1
  100. package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.10.1/manifest.json +181 -0
  101. package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/keywords.json +4009 -0
  102. package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/manifest.json +1 -1
  103. package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/versions/2026.10.1/manifest.json +217 -0
  104. package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/keywords.json +5583 -0
  105. package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/manifest.json +1 -1
  106. package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/versions/2026.10.1/manifest.json +197 -0
  107. package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/keywords.json +6386 -0
  108. package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/manifest.json +2 -2
  109. package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/versions/2026.10.1/manifest.json +197 -0
  110. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/keywords.json +4009 -0
  111. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/manifest.json +1 -1
  112. package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.10.1/manifest.json +185 -0
  113. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/keywords.json +5672 -0
  114. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/manifest.json +1 -1
  115. package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.10.1/manifest.json +137 -0
  116. package/dist/catalog/knowledge-catalogs/wi/wikipedia-geography/manifest.json +68 -0
  117. package/dist/catalog/knowledge-catalogs/wi/wikipedia-geography/versions/2026.10.1/manifest.json +217 -0
  118. package/dist/catalog/knowledge-catalogs/wi/wikipedia-history/manifest.json +68 -0
  119. package/dist/catalog/knowledge-catalogs/wi/wikipedia-history/versions/2026.10.1/manifest.json +217 -0
  120. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/keywords.json +4009 -0
  121. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/manifest.json +1 -1
  122. package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.10.1/manifest.json +141 -0
  123. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/keywords.json +4009 -0
  124. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/manifest.json +1 -1
  125. package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.10.1/manifest.json +185 -0
  126. package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/keywords.json +5719 -0
  127. package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/manifest.json +1 -1
  128. package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/versions/2026.10.1/manifest.json +193 -0
  129. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/keywords.json +4009 -0
  130. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/manifest.json +1 -1
  131. package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.10.1/manifest.json +189 -0
  132. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/keywords.json +16009 -0
  133. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/manifest.json +1 -1
  134. package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.10.1/manifest.json +185 -0
  135. package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/keywords.json +5843 -0
  136. package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/manifest.json +1 -1
  137. package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/versions/2026.10.1/manifest.json +189 -0
  138. package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/keywords.json +6264 -0
  139. package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/manifest.json +1 -1
  140. package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/versions/2026.10.1/manifest.json +197 -0
  141. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-arts/manifest.json +66 -0
  142. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-arts/versions/2026.10.1/manifest.json +209 -0
  143. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-business/manifest.json +61 -0
  144. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-business/versions/2026.10.1/manifest.json +189 -0
  145. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-entertainment/manifest.json +64 -0
  146. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-entertainment/versions/2026.10.1/manifest.json +201 -0
  147. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-military/manifest.json +60 -0
  148. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-military/versions/2026.10.1/manifest.json +185 -0
  149. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-other/manifest.json +55 -0
  150. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-other/versions/2026.10.1/manifest.json +165 -0
  151. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-politics/manifest.json +63 -0
  152. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-politics/versions/2026.10.1/manifest.json +197 -0
  153. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-religion/manifest.json +64 -0
  154. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-religion/versions/2026.10.1/manifest.json +201 -0
  155. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-science/manifest.json +65 -0
  156. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-science/versions/2026.10.1/manifest.json +205 -0
  157. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-sports/manifest.json +73 -0
  158. package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-sports/versions/2026.10.1/manifest.json +237 -0
  159. package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/keywords.json +5447 -0
  160. package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/manifest.json +1 -1
  161. package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/versions/2026.10.1/manifest.json +197 -0
  162. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/keywords.json +4009 -0
  163. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/manifest.json +1 -1
  164. package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.10.1/manifest.json +189 -0
  165. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/keywords.json +4009 -0
  166. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/manifest.json +1 -1
  167. package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.10.1/manifest.json +185 -0
  168. package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/keywords.json +5209 -0
  169. package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/manifest.json +1 -1
  170. package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/versions/2026.10.1/manifest.json +193 -0
  171. package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/keywords.json +6537 -0
  172. package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/manifest.json +1 -1
  173. package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/versions/2026.10.1/manifest.json +185 -0
  174. package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/keywords.json +5989 -0
  175. package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/manifest.json +1 -1
  176. package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/versions/2026.10.1/manifest.json +189 -0
  177. package/dist/catalog/provenance.json +1 -1
  178. package/dist/engines/native-file-manifest.json +483 -413
  179. package/dist/engines/native-manifest.d.ts +4 -4
  180. package/dist/engines/native-manifest.js +36 -34
  181. package/dist/engines/resolver.js +3 -1
  182. package/dist/fs/atomic.d.ts +4 -1
  183. package/dist/fs/atomic.js +7 -1
  184. package/dist/http/openai-compat/chat-target.d.ts +1 -1
  185. package/dist/http/openai-compat/chat-target.js +1 -1
  186. package/dist/http/openai-compat/engine-failure.d.ts +25 -0
  187. package/dist/http/openai-compat/engine-failure.js +76 -0
  188. package/dist/http/openai-compat/responses-streaming.js +2 -1
  189. package/dist/http/openai-compat/responses-translate.d.ts +1 -1
  190. package/dist/http/openai-compat/translate.d.ts +1 -1
  191. package/dist/http/routes/engines.js +35 -0
  192. package/dist/http/routes/v1-chat.js +11 -2
  193. package/dist/http/routes/v1-knowledge.js +4 -0
  194. package/dist/http/routes/v1-models.js +6 -4
  195. package/dist/http/routes/v1-responses.d.ts +1 -1
  196. package/dist/http/routes/v1-responses.js +7 -1
  197. package/dist/inference-service.d.ts +6 -1
  198. package/dist/inference-service.js +20 -9
  199. package/dist/knowledge/catalog-host.d.ts +9 -1
  200. package/dist/knowledge/catalog-host.js +2 -0
  201. package/dist/knowledge/manager.d.ts +21 -0
  202. package/dist/knowledge/manager.js +85 -7
  203. package/dist/knowledge/search-worker.d.ts +1 -1
  204. package/dist/knowledge/spatial-query.d.ts +2 -3
  205. package/dist/knowledge/spatial-query.js +12 -6
  206. package/dist/knowledge/worker-host.js +2 -0
  207. package/dist/memory/embed-core.d.ts +16 -0
  208. package/dist/memory/embed-core.js +31 -0
  209. package/dist/memory/embed-worker.d.ts +7 -3
  210. package/dist/memory/embed-worker.js +13 -4
  211. package/dist/memory/embeddings.d.ts +17 -2
  212. package/dist/memory/embeddings.js +36 -7
  213. package/dist/models/ensure.d.ts +2 -0
  214. package/dist/models/ensure.js +9 -0
  215. package/dist/perf/responsiveness.d.ts +14 -1
  216. package/dist/perf/responsiveness.js +81 -10
  217. package/dist/providers/audio/kokoro-frontend.js +1 -1
  218. package/dist/providers/ds4/build-provider.js +6 -0
  219. package/dist/providers/llama-cpp/backend-health.d.ts +30 -0
  220. package/dist/providers/llama-cpp/backend-health.js +64 -0
  221. package/dist/providers/llama-cpp/backend-quarantine.d.ts +40 -0
  222. package/dist/providers/llama-cpp/backend-quarantine.js +100 -0
  223. package/dist/providers/llama-cpp/build-provider.js +247 -199
  224. package/dist/providers/llama-cpp/cache-adapter.d.ts +7 -1
  225. package/dist/providers/llama-cpp/cache-adapter.js +11 -1
  226. package/dist/providers/llama-cpp/devices.d.ts +22 -2
  227. package/dist/providers/llama-cpp/devices.js +48 -5
  228. package/dist/providers/llama-cpp/engine-flags.d.ts +0 -18
  229. package/dist/providers/llama-cpp/engine-flags.js +12 -18
  230. package/dist/providers/llama-cpp/gguf-metadata.js +20 -3
  231. package/dist/providers/llama-cpp/gpu-startup-watch.d.ts +41 -0
  232. package/dist/providers/llama-cpp/gpu-startup-watch.js +58 -0
  233. package/dist/providers/llama-cpp/models.d.ts +6 -0
  234. package/dist/providers/llama-cpp/models.js +23 -2
  235. package/dist/providers/llama-cpp/offload-planner.d.ts +26 -18
  236. package/dist/providers/llama-cpp/offload-planner.js +30 -14
  237. package/dist/providers/llama-cpp/provider.d.ts +22 -3
  238. package/dist/providers/llama-cpp/provider.js +39 -3
  239. package/dist/providers/mlx/provider.js +5 -6
  240. package/dist/providers/mlx/python/qwen4_ple.py +9 -2
  241. package/dist/providers/mlx/reasoning-stream.d.ts +15 -0
  242. package/dist/providers/mlx/reasoning-stream.js +35 -0
  243. package/dist/providers/native/capacity-broker.d.ts +21 -15
  244. package/dist/providers/native/capacity-broker.js +25 -13
  245. package/dist/providers/native/capacity-budget.d.ts +35 -3
  246. package/dist/providers/native/capacity-budget.js +49 -5
  247. package/dist/providers/native/device-capacity.d.ts +1 -1
  248. package/dist/providers/native/device-capacity.js +23 -5
  249. package/dist/providers/native/local-engine-runtime.js +31 -31
  250. package/dist/providers/native/measured-budget.js +2 -0
  251. package/dist/providers/native/supervisor.d.ts +25 -0
  252. package/dist/providers/native/supervisor.js +62 -8
  253. package/dist/providers/queue.d.ts +9 -2
  254. package/dist/providers/queue.js +17 -2
  255. package/dist/providers/session-hooks.d.ts +4 -1
  256. package/dist/system/amdgpu-adapters.d.ts +18 -0
  257. package/dist/system/amdgpu-adapters.js +55 -0
  258. package/dist/system/gpu-carve-out.d.ts +84 -0
  259. package/dist/system/gpu-carve-out.js +111 -0
  260. package/dist/system/memory.d.ts +17 -1
  261. package/dist/system/memory.js +94 -13
  262. package/dist/transformers-cache.d.ts +2 -0
  263. package/dist/transformers-cache.js +6 -3
  264. package/package.json +5 -5
@@ -123,7 +123,7 @@ export declare class LlamaCppCacheAdapter implements EngineCacheAdapter {
123
123
  */
124
124
  private allocationTail;
125
125
  private engineGeneration;
126
- private readonly slotCount;
126
+ private slotCount;
127
127
  private readonly resolveBaseUrl;
128
128
  private readonly resolveAuthToken;
129
129
  private readonly fetchImpl;
@@ -168,6 +168,12 @@ export declare class LlamaCppCacheAdapter implements EngineCacheAdapter {
168
168
  */
169
169
  private slotActionsUnsupported;
170
170
  constructor(opts: LlamaCppCacheAdapterOptions);
171
+ /**
172
+ * Follow an engine relaunched with a different `--parallel` count. Every
173
+ * binding goes with it: a session pinned to a slot the new engine lacks
174
+ * would send an `id_slot` the server rejects.
175
+ */
176
+ setSlotCount(slotCount: number): void;
171
177
  /** The provider survives engine restarts, but its resident slot contents do not. */
172
178
  resetEngineState(): void;
173
179
  /**
@@ -181,6 +181,15 @@ export class LlamaCppCacheAdapter {
181
181
  throw new Error('Invalid llama disk cache budget');
182
182
  this.diskCacheBudgetBytes = budget * 1024 * 1024;
183
183
  }
184
+ /**
185
+ * Follow an engine relaunched with a different `--parallel` count. Every
186
+ * binding goes with it: a session pinned to a slot the new engine lacks
187
+ * would send an `id_slot` the server rejects.
188
+ */
189
+ setSlotCount(slotCount) {
190
+ this.slotCount = Math.max(1, Math.floor(slotCount));
191
+ this.resetEngineState();
192
+ }
184
193
  /** The provider survives engine restarts, but its resident slot contents do not. */
185
194
  resetEngineState() {
186
195
  this.engineGeneration++;
@@ -306,7 +315,8 @@ export class LlamaCppCacheAdapter {
306
315
  if (!entry || typeof entry !== 'object')
307
316
  continue;
308
317
  const slot = entry.id;
309
- const cachedTokens = entry.n_cache_tokens;
318
+ // The slot's resident tokens (prompt plus generated); there is no `n_cache_tokens`.
319
+ const cachedTokens = entry.n_prompt_tokens;
310
320
  if (typeof slot !== 'number' || typeof cachedTokens !== 'number' || cachedTokens <= 0) {
311
321
  continue;
312
322
  }
@@ -31,6 +31,14 @@ export interface LlamaDeviceProbe {
31
31
  probedAt: string;
32
32
  /** True when returned from the on-disk cache rather than a fresh spawn. */
33
33
  cached: boolean;
34
+ /**
35
+ * The RAM the OS reported when the probe ran. Changing an integrated GPU's
36
+ * firmware carve-out changes this figure and the GPU's own, so a mismatch
37
+ * means the cached devices describe a machine that no longer exists.
38
+ */
39
+ systemRamBytes?: number;
40
+ /** {@link llamaBinaryFingerprint} of the build that answered. */
41
+ binary?: string;
34
42
  }
35
43
  export interface NvidiaRuntimeDevice {
36
44
  index: number;
@@ -69,19 +77,31 @@ export declare function maxGpuVramBytes(devices: LlamaDevice[]): number;
69
77
  * (e.g. "AMD Radeon RX 7900 XTX") in a tier rationale. Pure — unit-tested.
70
78
  */
71
79
  export declare function pickBestGpuDevice(devices: LlamaDevice[]): LlamaDevice | null;
80
+ /**
81
+ * Which build a cached listing came from: its path (the backend) and its
82
+ * size and mtime (the release, since a native update rewrites the files).
83
+ * A listing taken from the CPU build, or from the build an update replaced,
84
+ * said "no GPU" about a 32 GB Radeon and was served for the rest of the day
85
+ * (2026-10-19).
86
+ */
87
+ export declare function llamaBinaryFingerprint(binaryPath: string): string;
72
88
  /**
73
89
  * Probe device memory by running `<binaryPath> --list-devices`, caching
74
90
  * the result. Reads the cache when present (VRAM capacity is stable per
75
- * machine); pass `force` to re-probe. Any failure (spawn error, no
91
+ * machine), the OS still reports the RAM it was probed with, and the same
92
+ * build answered it; an empty listing is re-asked hourly. Pass `force` to
93
+ * re-probe. Any failure (spawn error, no
76
94
  * cache, unparseable output) resolves to an empty device list — the
77
95
  * planner then simply does nothing and the engine's own `--fit`/`-ngl
78
- * auto` takes over. `nowIso` is injectable for deterministic tests.
96
+ * auto` takes over. `nowIso` and `systemRamBytes` are injectable for
97
+ * deterministic tests.
79
98
  */
80
99
  export declare function probeLlamaDevices(opts: {
81
100
  binaryPath: string;
82
101
  home: string;
83
102
  force?: boolean;
84
103
  nowIso?: () => string;
104
+ systemRamBytes?: number;
85
105
  }): Promise<LlamaDeviceProbe>;
86
106
  /**
87
107
  * Best-effort VRAM for a non-NVIDIA GPU (AMD Radeon, Intel Arc, any Vulkan
@@ -16,7 +16,8 @@
16
16
  * `backend.json` pattern in `core/native/llama-backend.ts`.
17
17
  */
18
18
  import { execFile } from 'node:child_process';
19
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
19
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
20
+ import { totalmem } from 'node:os';
20
21
  import { delimiter, dirname, join } from 'node:path';
21
22
  import { promisify } from 'node:util';
22
23
  import { windowsHeadlessSpawnOptions } from '@bendyline/gezel/native';
@@ -121,23 +122,59 @@ export function pickBestGpuDevice(devices) {
121
122
  function cachePath(home) {
122
123
  return join(home, 'engines', 'llama-cpp', 'devices.json');
123
124
  }
125
+ /**
126
+ * An empty listing is re-asked after this long. A CPU build always answers
127
+ * "(none)", but so can a GPU build whose driver was mid-update, and a cached
128
+ * "no GPU" sizes every model against system RAM.
129
+ */
130
+ const EMPTY_DEVICES_RETRY_MS = 60 * 60 * 1000;
131
+ /**
132
+ * Which build a cached listing came from: its path (the backend) and its
133
+ * size and mtime (the release, since a native update rewrites the files).
134
+ * A listing taken from the CPU build, or from the build an update replaced,
135
+ * said "no GPU" about a 32 GB Radeon and was served for the rest of the day
136
+ * (2026-10-19).
137
+ */
138
+ export function llamaBinaryFingerprint(binaryPath) {
139
+ try {
140
+ const { size, mtimeMs } = statSync(binaryPath);
141
+ return `${binaryPath}|${size}|${Math.floor(mtimeMs)}`;
142
+ }
143
+ catch {
144
+ return binaryPath;
145
+ }
146
+ }
124
147
  /**
125
148
  * Probe device memory by running `<binaryPath> --list-devices`, caching
126
149
  * the result. Reads the cache when present (VRAM capacity is stable per
127
- * machine); pass `force` to re-probe. Any failure (spawn error, no
150
+ * machine), the OS still reports the RAM it was probed with, and the same
151
+ * build answered it; an empty listing is re-asked hourly. Pass `force` to
152
+ * re-probe. Any failure (spawn error, no
128
153
  * cache, unparseable output) resolves to an empty device list — the
129
154
  * planner then simply does nothing and the engine's own `--fit`/`-ngl
130
- * auto` takes over. `nowIso` is injectable for deterministic tests.
155
+ * auto` takes over. `nowIso` and `systemRamBytes` are injectable for
156
+ * deterministic tests.
131
157
  */
132
158
  export async function probeLlamaDevices(opts) {
133
159
  const { binaryPath, home, force } = opts;
134
160
  const now = opts.nowIso ?? (() => new Date().toISOString());
161
+ const systemRamBytes = opts.systemRamBytes ?? totalmem();
135
162
  const path = cachePath(home);
163
+ const binary = llamaBinaryFingerprint(binaryPath);
136
164
  if (!force && existsSync(path)) {
137
165
  try {
138
166
  const cached = JSON.parse(readFileSync(path, 'utf8'));
139
- if (Array.isArray(cached.devices))
167
+ // A cache without the RAM figure or the binary predates that check and
168
+ // re-probes once.
169
+ const emptyExpired = Array.isArray(cached.devices) &&
170
+ cached.devices.length === 0 &&
171
+ !(Date.parse(now()) - Date.parse(cached.probedAt) < EMPTY_DEVICES_RETRY_MS);
172
+ if (Array.isArray(cached.devices) &&
173
+ cached.systemRamBytes === systemRamBytes &&
174
+ cached.binary === binary &&
175
+ !emptyExpired) {
140
176
  return { ...cached, cached: true };
177
+ }
141
178
  }
142
179
  catch {
143
180
  // fall through to a fresh probe
@@ -165,7 +202,13 @@ export async function probeLlamaDevices(opts) {
165
202
  // Leave devices empty — caller treats "no devices" as "no offload target".
166
203
  return { devices, probedAt: now(), cached: false };
167
204
  }
168
- const probe = { devices, probedAt: now(), cached: false };
205
+ const probe = {
206
+ devices,
207
+ probedAt: now(),
208
+ cached: false,
209
+ systemRamBytes,
210
+ binary,
211
+ };
169
212
  try {
170
213
  mkdirSync(dirname(path), { recursive: true });
171
214
  writeFileSync(path, JSON.stringify(probe, null, 2), 'utf8');
@@ -126,24 +126,6 @@ export interface EngineFlagInput {
126
126
  * when the client also replays `reasoning_content`.
127
127
  */
128
128
  reasoningPreserve?: boolean | undefined;
129
- /**
130
- * The model's GGUF `general.architecture`, for the Gemma-family auto
131
- * defaults (sliding-window full cache). Undefined disables the arch
132
- * heuristic; an explicit config/manifest `swaFull` still applies.
133
- */
134
- architecture?: string | undefined;
135
- /** The resolved model id, a fallback for `architecture` (see isGemmaModel). */
136
- modelId?: string | undefined;
137
- /**
138
- * Whether resident weights plus the full SWA KV cache fit the host's
139
- * fast-memory pool (VRAM on a discrete GPU). The exact estimate honors
140
- * per-layer SWA dimensions and shared-KV layers. `false` declines the
141
- * auto-default so a low-memory device keeps the model's full context on
142
- * the windowed cache instead of spilling or OOMing. `undefined` (unknown
143
- * host/metadata) and `true` retain the compatibility default. An explicit
144
- * config/manifest `swaFull` wins regardless.
145
- */
146
- swaFullAutoFits?: boolean | undefined;
147
129
  /**
148
130
  * The llama-server build's backend (`cuda`, `vulkan`, `metal`, `cpu`).
149
131
  * Only a GPU backend can receive the GPU-resident thread default.
@@ -21,7 +21,6 @@
21
21
  * dependency; the real `GezelConfig` / `LlamaCppEngineConfig` satisfy
22
22
  * these shapes by construction.
23
23
  */
24
- import { isGemmaModel } from './kv-cache-type.js';
25
24
  /** Default `--cache-reuse` chunk when neither config nor manifest set it. */
26
25
  export const DEFAULT_CACHE_REUSE = 256;
27
26
  /**
@@ -101,7 +100,7 @@ function normalizeFlagKey(key) {
101
100
  * `args` array.
102
101
  */
103
102
  export function buildLlamaCppEngineArgs(input) {
104
- const { config, perModel, planner, kvCacheType, slots, ggufHasMtp, installedDraftModelPath, reasoningFormat, reasoningPreserve, architecture, modelId, swaFullAutoFits, backend, hostCpuCount, } = input;
103
+ const { config, perModel, planner, kvCacheType, slots, ggufHasMtp, installedDraftModelPath, reasoningFormat, reasoningPreserve, backend, hostCpuCount, } = input;
105
104
  const args = [];
106
105
  // ── GPU-layer offload (`--n-gpu-layers`) ──────────────────────────
107
106
  const nGpuLayers = config.llamaCppNGpuLayers ?? perModel?.nGpuLayers ?? planner?.nGpuLayers;
@@ -176,26 +175,20 @@ export function buildLlamaCppEngineArgs(input) {
176
175
  //
177
176
  // So the engine already declines it precisely when it cannot honour it,
178
177
  // which is what the warning is for. Withholding the flag ourselves only
179
- // cost reuse on multi-slot dense engines. Note the coupling this exposes:
180
- // the memory-driven `--swa-full` decision below also silently decides
181
- // whether Gemma gets any cross-request prefix reuse at all.
178
+ // cost reuse on multi-slot dense engines. Gemma therefore gets it only
179
+ // with a pinned `--swa-full` below.
182
180
  const explicitCacheReuse = config.llamaCppCacheReuse ?? perModel?.cacheReuse;
183
181
  const cacheReuse = explicitCacheReuse ?? DEFAULT_CACHE_REUSE;
184
182
  if (cacheReuse > 0)
185
183
  args.push('--cache-reuse', String(cacheReuse));
186
184
  // ── SWA full cache (`--swa-full`) ─────────────────────────────────
187
- // Tri-state: explicit config/manifest `true`/`false` wins; `undefined`
188
- // at both layers falls through to the Gemma-family auto-default. Gemma's
189
- // sliding-window attention refuses cross-request prefix reuse under the
190
- // memory-efficient windowed cache; the full cache preserves old SWA KV
191
- // for cache operations by allocating full-context storage on every
192
- // cache-owning layer. The cost varies sharply with model geometry, so
193
- // Auto is gated on `swaFullAutoFits`: when weights + full KV do not fit
194
- // fast memory, Gemma launches with the windowed cache instead.
195
- const swaFull = config.llamaCppSwaFull ??
196
- perModel?.swaFull ??
197
- (swaFullAutoFits !== false && isGemmaModel({ architecture, modelId }));
198
- if (swaFull)
185
+ // Opt-in only: an explicit config/manifest `swaFull`. Gemma used to get
186
+ // it by default for cross-request prefix reuse, until a paired A/B on
187
+ // gemma4-31b (2026-10-15) showed the full cache decodes 17-25% slower at
188
+ // every context depth, because decode reads each sliding-window layer's
189
+ // whole cache, and costs 51 GB more at 64K. Trials ran 19% longer in
190
+ // total despite the better reuse.
191
+ if (config.llamaCppSwaFull ?? perModel?.swaFull)
199
192
  args.push('--swa-full');
200
193
  // ── Thread / batch overrides ──────────────────────────────────────
201
194
  // The GPU-resident default needs positive evidence that no model compute
@@ -248,7 +241,8 @@ export function buildLlamaCppEngineArgs(input) {
248
241
  const nMax = config.llamaCppSpecDraftNMax ?? perModel?.spec?.nMax;
249
242
  if (typeof nMax === 'number')
250
243
  args.push('--spec-draft-n-max', String(nMax));
251
- // v0.6.0 supports probabilistic selection only for MTP/simple drafts.
244
+ // v0.7.0 supports probabilistic selection only for MTP/simple drafts
245
+ // (DFlash/LiLiCorr ignore it).
252
246
  // Leave the upstream greedy default untouched unless explicitly set.
253
247
  if ((safeSpecType === 'draft-mtp' || safeSpecType === 'draft-simple') &&
254
248
  config.llamaCppSpecDraftSampling) {
@@ -32,8 +32,9 @@ const GgufValueType = {
32
32
  INT64: 11,
33
33
  FLOAT64: 12,
34
34
  };
35
- // `general.file_type` enum from llama.cpp/src/llama.h. Only the
36
- // common values — the enum has ~30 entries and upstream adds more.
35
+ // `general.file_type` enum (`llama_ftype`) from llama.cpp's include/llama.h.
36
+ // Copy new values from upstream rather than guessing: this table once mapped
37
+ // 30 to BF16 (upstream 30 is IQ4_XS, BF16 is 32) and had no NVFP4 at all.
37
38
  // Anything unrecognised is reported by number.
38
39
  const FILE_TYPE_NAMES = {
39
40
  0: 'ALL_F32',
@@ -54,8 +55,24 @@ const FILE_TYPE_NAMES = {
54
55
  18: 'MOSTLY_Q6_K',
55
56
  19: 'MOSTLY_IQ2_XXS',
56
57
  20: 'MOSTLY_IQ2_XS',
58
+ 21: 'MOSTLY_Q2_K_S',
59
+ 22: 'MOSTLY_IQ3_XS',
57
60
  23: 'MOSTLY_IQ3_XXS',
58
- 30: 'MOSTLY_BF16',
61
+ 24: 'MOSTLY_IQ1_S',
62
+ 25: 'MOSTLY_IQ4_NL',
63
+ 26: 'MOSTLY_IQ3_S',
64
+ 27: 'MOSTLY_IQ3_M',
65
+ 28: 'MOSTLY_IQ2_S',
66
+ 29: 'MOSTLY_IQ2_M',
67
+ 30: 'MOSTLY_IQ4_XS',
68
+ 31: 'MOSTLY_IQ1_M',
69
+ 32: 'MOSTLY_BF16',
70
+ 36: 'MOSTLY_TQ1_0',
71
+ 37: 'MOSTLY_TQ2_0',
72
+ 38: 'MOSTLY_MXFP4_MOE',
73
+ 39: 'MOSTLY_NVFP4',
74
+ 40: 'MOSTLY_Q1_0',
75
+ 41: 'MOSTLY_Q2_0',
59
76
  };
60
77
  /**
61
78
  * The quantization tag a GGUF declares about itself, in the shape the model
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Did a GPU build of llama-server actually get its GPU? Read from the
3
+ * engine's own startup output, because nothing else says.
4
+ *
5
+ * The bundled builds load their GPU backend with dlopen (`GGML_BACKEND_DL`),
6
+ * and in a release build ggml skips a backend that fails to load without a
7
+ * word. A CUDA backend that loads but cannot initialize prints one error line
8
+ * and registers no devices. Either way the engine starts, answers, and runs
9
+ * every token on the CPU — at a fraction of the speed the person's hardware
10
+ * and Settings promise — while gezel reports the CUDA or Vulkan build it
11
+ * launched.
12
+ *
13
+ * llama.cpp names every GPU it will use while loading a model
14
+ * (`using device CUDA0 (NVIDIA GB10) …`), integrated GPUs included. A GPU
15
+ * build that reached readiness after loading a model without that line ran
16
+ * without its GPU. The explicit lines say why when there is a why to say.
17
+ */
18
+ export type GpuUnusedReason =
19
+ /** The CUDA runtime loaded and refused to start: `failed to initialize CUDA`. */
20
+ 'init-failed'
21
+ /** The backend loaded and found no device it could use. */
22
+ | 'no-devices'
23
+ /** No sign of the GPU backend at all: it failed to load, silently. */
24
+ | 'not-loaded';
25
+ export interface GpuUnused {
26
+ backend: 'cuda' | 'vulkan';
27
+ reason: GpuUnusedReason;
28
+ /** The engine's own words, when it gave any. */
29
+ detail?: string;
30
+ }
31
+ export declare class GpuStartupWatch {
32
+ private readonly backend;
33
+ private usingGpu;
34
+ private sawModelLoad;
35
+ private initFailure;
36
+ private noDevices;
37
+ constructor(backend: string | undefined);
38
+ observe(line: string): void;
39
+ /** At readiness: what kept the GPU out, or null when it is in use or this is no GPU build. */
40
+ verdict(): GpuUnused | null;
41
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Did a GPU build of llama-server actually get its GPU? Read from the
3
+ * engine's own startup output, because nothing else says.
4
+ *
5
+ * The bundled builds load their GPU backend with dlopen (`GGML_BACKEND_DL`),
6
+ * and in a release build ggml skips a backend that fails to load without a
7
+ * word. A CUDA backend that loads but cannot initialize prints one error line
8
+ * and registers no devices. Either way the engine starts, answers, and runs
9
+ * every token on the CPU — at a fraction of the speed the person's hardware
10
+ * and Settings promise — while gezel reports the CUDA or Vulkan build it
11
+ * launched.
12
+ *
13
+ * llama.cpp names every GPU it will use while loading a model
14
+ * (`using device CUDA0 (NVIDIA GB10) …`), integrated GPUs included. A GPU
15
+ * build that reached readiness after loading a model without that line ran
16
+ * without its GPU. The explicit lines say why when there is a why to say.
17
+ */
18
+ const USING_GPU = /\busing device (?:CUDA|Vulkan|ROCm|SYCL|MTL)\d+\b/;
19
+ const CUDA_INIT_FAILED = /ggml_cuda_init: failed to initialize CUDA:\s*(.+?)\s*$/;
20
+ const VULKAN_NO_DEVICES = /ggml_vulkan: No devices found/;
21
+ /**
22
+ * Lines llama.cpp prints at the same verbosity as `using device`, while
23
+ * loading a model. Without one the output is too quiet to conclude anything.
24
+ */
25
+ const MODEL_LOAD = /\b(?:llama_model_loader:|load_tensors:|print_info:|llama_model_load_from_file_impl:)/;
26
+ export class GpuStartupWatch {
27
+ backend;
28
+ usingGpu = false;
29
+ sawModelLoad = false;
30
+ initFailure;
31
+ noDevices = false;
32
+ constructor(backend) {
33
+ this.backend = backend;
34
+ }
35
+ observe(line) {
36
+ if (USING_GPU.test(line))
37
+ this.usingGpu = true;
38
+ if (MODEL_LOAD.test(line))
39
+ this.sawModelLoad = true;
40
+ const failure = CUDA_INIT_FAILED.exec(line);
41
+ if (failure?.[1])
42
+ this.initFailure = failure[1];
43
+ if (VULKAN_NO_DEVICES.test(line))
44
+ this.noDevices = true;
45
+ }
46
+ /** At readiness: what kept the GPU out, or null when it is in use or this is no GPU build. */
47
+ verdict() {
48
+ const backend = this.backend;
49
+ if ((backend !== 'cuda' && backend !== 'vulkan') || this.usingGpu)
50
+ return null;
51
+ if (backend === 'cuda' && this.initFailure) {
52
+ return { backend, reason: 'init-failed', detail: this.initFailure };
53
+ }
54
+ if (backend === 'vulkan' && this.noDevices)
55
+ return { backend, reason: 'no-devices' };
56
+ return this.sawModelLoad ? { backend, reason: 'not-loaded' } : null;
57
+ }
58
+ }
@@ -236,6 +236,11 @@ export interface LlamaCppModelManagerOptions {
236
236
  engine: 'llama-cpp' | 'ds4';
237
237
  id: string;
238
238
  }) => void;
239
+ /**
240
+ * The llama-server backend installs are judged against for a catalog
241
+ * source's `excludeBackends`. Test seam — defaults to the process's own.
242
+ */
243
+ resolveBackend?: () => string | undefined;
239
244
  }
240
245
  export declare class LlamaCppModelManager {
241
246
  private readonly modelsRoot;
@@ -244,6 +249,7 @@ export declare class LlamaCppModelManager {
244
249
  private readonly fetchImpl;
245
250
  private readonly engine;
246
251
  private readonly onInstalled?;
252
+ private readonly resolveBackend;
247
253
  /**
248
254
  * In-flight installs. `install()` registers an entry on first yield
249
255
  * and clears it in the iterator's `finally` block, so consumers
@@ -35,13 +35,14 @@ import { createHash } from 'node:crypto';
35
35
  import { createReadStream } from 'node:fs';
36
36
  import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from 'node:fs/promises';
37
37
  import { basename, join, resolve } from 'node:path';
38
- import { createLogger } from '@bendyline/gezel';
38
+ import { createLogger, llamaCppBackendExclusion, llamaCppBackendLabel } from '@bendyline/gezel';
39
39
  import { listBundleModelFiles, publishStagedModel, safeBundleModelPath, } from '../../models/bundle-storage.js';
40
40
  import { evaluateCatalogDrift } from '../../models/catalog-drift.js';
41
41
  import { catalogPayloadFingerprint, describeCatalogPayload, } from '../../models/catalog-payload-identity.js';
42
42
  import { MODEL_HASH_READ_BUFFER_BYTES, assertModelStorePathSafe, findModelRoot, findRenamedModelId, hashModelPayloadFiles, inspectModelDirectory, listIncompleteModelDownloads, listOverlayModelIds, makeSharedModelReadable, modelExistsOnlyReadOnly, modelStorageRoots, pruneModelPayloadFiles, readOnlyModelError, removeModelDir, verifyReadOnlyModelPayload, } from '../../models/storage-roots.js';
43
43
  import { checkDiskSpace, describeDiskShortfall } from '../../utils/disk-space.js';
44
44
  import { downloadWithRetry } from '../../utils/download-with-retry.js';
45
+ import { currentLlamaCppBackend } from './backend-health.js';
45
46
  import { ggufQuantizationTag, readGgufSummary } from './gguf-metadata.js';
46
47
  import { backfillGgufQuantization } from './gguf-quantization-backfill.js';
47
48
  /**
@@ -58,6 +59,7 @@ export class LlamaCppModelManager {
58
59
  fetchImpl;
59
60
  engine;
60
61
  onInstalled;
62
+ resolveBackend;
61
63
  /**
62
64
  * In-flight installs. `install()` registers an entry on first yield
63
65
  * and clears it in the iterator's `finally` block, so consumers
@@ -78,6 +80,7 @@ export class LlamaCppModelManager {
78
80
  this.catalog = opts.catalog;
79
81
  this.fetchImpl = opts.fetchImpl ?? fetch;
80
82
  this.onInstalled = opts.onInstalled;
83
+ this.resolveBackend = opts.resolveBackend ?? currentLlamaCppBackend;
81
84
  }
82
85
  /**
83
86
  * The catalog source block this manager downloads from — `ds4` for the
@@ -435,6 +438,17 @@ export class LlamaCppModelManager {
435
438
  };
436
439
  return;
437
440
  }
441
+ if (this.engine === 'llama-cpp') {
442
+ const backend = this.resolveBackend();
443
+ const excluded = llamaCppBackendExclusion(manifest.llamaCpp, backend);
444
+ if (excluded && backend) {
445
+ yield {
446
+ type: 'error',
447
+ error: `chat-model "${catalogId}" is not available on the ${llamaCppBackendLabel(backend)} llama.cpp engine: ${excluded}`,
448
+ };
449
+ return;
450
+ }
451
+ }
438
452
  tracked.totalBytes = installSrc.approxSizeBytes;
439
453
  yield* this.runInstall(catalogId, manifest, tracked, skipSha, includeMmproj);
440
454
  }
@@ -734,7 +748,10 @@ export class LlamaCppModelManager {
734
748
  installed.fileSha256 = await hashModelPayloadFiles(itemDir, verifiedDigests);
735
749
  await writeFile(join(itemDir, 'manifest.json'), JSON.stringify(installed, null, 2), 'utf8');
736
750
  await makeSharedModelReadable(itemDir);
737
- const warning = summary.chatTemplateMissing
751
+ // ds4-server renders each family's prompt itself and never reads
752
+ // tokenizer.chat_template; DeepSeek V4.1 ships no Jinja template at all,
753
+ // and its first install warned that replies "may be incoherent".
754
+ const warning = summary.chatTemplateMissing && this.engine === 'llama-cpp'
738
755
  ? 'Model has no embedded chat template (tokenizer.chat_template is missing). llama-server will fall back to a generic template that may not match this model — replies may be incoherent. Consider a different quant of the same model.'
739
756
  : undefined;
740
757
  try {
@@ -964,6 +981,10 @@ includeMmproj = true) {
964
981
  // after install without a second download.
965
982
  if (src.draftModel) {
966
983
  out.push({
984
+ ...(src.draftModel.huggingfaceRepo
985
+ ? { huggingfaceRepo: src.draftModel.huggingfaceRepo }
986
+ : {}),
987
+ ...(src.draftModel.revision ? { revision: src.draftModel.revision } : {}),
967
988
  repoPath: src.draftModel.filename,
968
989
  destFilename: basename(src.draftModel.filename),
969
990
  sha256: src.draftModel.sha256,
@@ -166,6 +166,29 @@ export declare function planMoeOffload(input: MoeOffloadInput): MoeOffloadDecisi
166
166
  export declare function degradeMoeOffloadDecision(decision: MoeOffloadDecision | undefined): MoeOffloadDecision | null;
167
167
  /** Dense counterpart of {@link degradeMoeOffloadDecision}. */
168
168
  export declare function degradeDenseFfnOffloadDecision(decision: MoeOffloadDecision | undefined, blockCount: number | undefined): MoeOffloadDecision | null;
169
+ /**
170
+ * Room an extra engine slot must leave on the card. Other programs' graphics
171
+ * memory moves while a model runs (a browser, a video, the desktop), and a
172
+ * two-slot launch planned to within a gigabyte or two died with a Vulkan
173
+ * out-of-memory when they took more (2026-10-19, a 32 GB card).
174
+ */
175
+ export declare const EXTRA_SLOT_GPU_CUSHION_BYTES: number;
176
+ /**
177
+ * Fewer slots before system RAM. Keep `slots` only when the model stays
178
+ * fully on the GPU with {@link EXTRA_SLOT_GPU_CUSHION_BYTES} to spare;
179
+ * otherwise drop to one slot when that alone keeps it fully on the GPU. A
180
+ * model that needs system RAM even at one slot keeps its slots and the
181
+ * planner's split. `plan` prices one slot count against one VRAM pool.
182
+ */
183
+ export declare function shedSlotsForGpuResidency(input: {
184
+ slots: number;
185
+ vramBytes: number;
186
+ plan: (slots: number, vramBytes: number) => MoeOffloadDecision;
187
+ }): {
188
+ slots: number;
189
+ decision: MoeOffloadDecision;
190
+ shed: boolean;
191
+ };
169
192
  export interface KvReserveInput {
170
193
  blockCount?: number | undefined;
171
194
  embeddingLength?: number | undefined;
@@ -286,10 +309,9 @@ export interface WindowedKvLinearization {
286
309
  * than the layer ratio — global layers carry fewer KV heads at wider head
287
310
  * dims (31b: 10 layers × 4 heads × 512+512 vs 50 layers × 16 heads ×
288
311
  * 256+256) — so full-attention math overstates the windowed cache ~14×
289
- * and using it for admission over-clamps or over-denies exactly the
290
- * launches the `--swa-full` decline is trying to keep whole (the
291
- * 2026-08-04 gemma4-26b sweep shipped 19–56K windows on a 65536 request
292
- * this way).
312
+ * and using it for admission over-clamps or over-denies launches the
313
+ * windowed cache holds easily (the 2026-08-04 gemma4-26b sweep shipped
314
+ * 19–56K windows on a 65536 request this way).
293
315
  *
294
316
  * Returns undefined when the header lacks the SWA layout (no window, no
295
317
  * pattern, length mismatches) so callers fall back to their conservative
@@ -323,17 +345,3 @@ export declare function estimateExactPerSlotKvBytesF16(input: Omit<WindowedKvInp
323
345
  */
324
346
  export declare function estimateLinearHybridKvLinearization(input: WindowedKvInput): WindowedKvLinearization | undefined;
325
347
  export declare function estimateWindowedKvLinearization(input: WindowedKvInput): WindowedKvLinearization | undefined;
326
- export interface SwaFullFastMemoryFitInput {
327
- residentWeightsBytes: number;
328
- fullKvBytes: number;
329
- /** Already safety-discounted fast-memory budget (VRAM on a discrete GPU). */
330
- fastBudgetBytes: number;
331
- /** Fast-memory reservations held by models that are already resident. */
332
- committedOtherBytes?: number | undefined;
333
- }
334
- /**
335
- * Whether Auto may keep `--swa-full` without spilling the model or KV cache
336
- * out of the fast pool. The capacity budget already reserves driver/OS
337
- * headroom, so this comparison must not discount it a second time.
338
- */
339
- export declare function fitsSwaFullInFastMemory(input: SwaFullFastMemoryFitInput): boolean;
@@ -272,6 +272,33 @@ export function degradeDenseFfnOffloadDecision(decision, blockCount) {
272
272
  }
273
273
  return null;
274
274
  }
275
+ /**
276
+ * Room an extra engine slot must leave on the card. Other programs' graphics
277
+ * memory moves while a model runs (a browser, a video, the desktop), and a
278
+ * two-slot launch planned to within a gigabyte or two died with a Vulkan
279
+ * out-of-memory when they took more (2026-10-19, a 32 GB card).
280
+ */
281
+ export const EXTRA_SLOT_GPU_CUSHION_BYTES = 2 * 1024 ** 3;
282
+ /**
283
+ * Fewer slots before system RAM. Keep `slots` only when the model stays
284
+ * fully on the GPU with {@link EXTRA_SLOT_GPU_CUSHION_BYTES} to spare;
285
+ * otherwise drop to one slot when that alone keeps it fully on the GPU. A
286
+ * model that needs system RAM even at one slot keeps its slots and the
287
+ * planner's split. `plan` prices one slot count against one VRAM pool.
288
+ */
289
+ export function shedSlotsForGpuResidency(input) {
290
+ const decision = input.plan(input.slots, input.vramBytes);
291
+ const keep = { slots: input.slots, decision, shed: false };
292
+ if (input.slots <= 1 || input.vramBytes <= 0)
293
+ return keep;
294
+ const roomy = input.plan(input.slots, Math.max(0, input.vramBytes - EXTRA_SLOT_GPU_CUSHION_BYTES));
295
+ if (roomy.fullGpuResidency)
296
+ return keep;
297
+ const single = input.plan(1, input.vramBytes);
298
+ if (!single.fullGpuResidency)
299
+ return keep;
300
+ return { slots: 1, decision: single, shed: true };
301
+ }
275
302
  /** Bytes per KV element for llama-server's `--cache-type-k/v` values. */
276
303
  const KV_BYTES_PER_ELEMENT = {
277
304
  f32: 4,
@@ -406,10 +433,9 @@ const SWA_UBATCH_MARGIN_TOKENS = 2048;
406
433
  * than the layer ratio — global layers carry fewer KV heads at wider head
407
434
  * dims (31b: 10 layers × 4 heads × 512+512 vs 50 layers × 16 heads ×
408
435
  * 256+256) — so full-attention math overstates the windowed cache ~14×
409
- * and using it for admission over-clamps or over-denies exactly the
410
- * launches the `--swa-full` decline is trying to keep whole (the
411
- * 2026-08-04 gemma4-26b sweep shipped 19–56K windows on a 65536 request
412
- * this way).
436
+ * and using it for admission over-clamps or over-denies launches the
437
+ * windowed cache holds easily (the 2026-08-04 gemma4-26b sweep shipped
438
+ * 19–56K windows on a 65536 request this way).
413
439
  *
414
440
  * Returns undefined when the header lacks the SWA layout (no window, no
415
441
  * pattern, length mismatches) so callers fall back to their conservative
@@ -512,13 +538,3 @@ export function estimateWindowedKvLinearization(input) {
512
538
  fixedBytes: Math.round(swaElemsPerToken * bytesPerElement * (slidingWindow + SWA_UBATCH_MARGIN_TOKENS) * loops),
513
539
  };
514
540
  }
515
- /**
516
- * Whether Auto may keep `--swa-full` without spilling the model or KV cache
517
- * out of the fast pool. The capacity budget already reserves driver/OS
518
- * headroom, so this comparison must not discount it a second time.
519
- */
520
- export function fitsSwaFullInFastMemory(input) {
521
- const required = Math.max(0, input.residentWeightsBytes) + Math.max(0, input.fullKvBytes);
522
- const available = Math.max(0, input.fastBudgetBytes - Math.max(0, input.committedOtherBytes ?? 0));
523
- return Number.isFinite(required) && Number.isFinite(available) && required <= available;
524
- }