@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,1714 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { join } from 'node:path';
3
+ import { createLogger } from '@bendyline/gezel';
4
+ import { estimateLlamaCppResidentBytes } from '@bendyline/gezel';
5
+ import { resolveCatalogLlamaCppEngineConfig } from '../catalog-model-config.js';
6
+ import { buildDs4Provider, resolveDs4LaunchCtx, resolveDs4VisionLaunch, } from '../ds4/build-provider.js';
7
+ import { ds4VisionResidentBytes } from '../ds4/residency.js';
8
+ import { buildLlamaCppProvider, ensureLlamaEngineStatus } from '../llama-cpp/build-provider.js';
9
+ import { readGgufSummaryAsync } from '../llama-cpp/gguf-metadata-async.js';
10
+ import { effectiveLazyTensorBytes } from '../llama-cpp/gguf-metadata.js';
11
+ import { isGemmaModel, planLlamaCppKv, resolveLlamaCppKvCacheType, } from '../llama-cpp/kv-cache-type.js';
12
+ import { estimateExactPerSlotKvBytesF16, estimateKvReserveBytes, estimateWindowedKvLinearization, } from '../llama-cpp/offload-planner.js';
13
+ import { buildMlxProvider, resolveMlxEffectiveNumCtx } from '../mlx/build-provider.js';
14
+ import { readMlxModelGeometry } from '../mlx/model-geometry.js';
15
+ import { ModelNotInstalledError } from '../types.js';
16
+ import { mmprojBudgetBytes, nativeVisionEnabledFor } from '../vision-capability.js';
17
+ import { CapacityDeniedError, NOT_ENOUGH_MEMORY_MESSAGE, availableSystemRamBytes, minViableLocalContextTokens, resolveLlamaCppContextRequirement, } from './capacity-broker.js';
18
+ import { engineApiKey } from './engine-api-key.js';
19
+ import { isLocalProvider, makeEngineKey, parseEngineKey, } from './engine-key.js';
20
+ const log = createLogger('engines');
21
+ /** Native engine lifetime, admission, and cache control. No product sessions or tools. */
22
+ export class LocalEngineRuntime {
23
+ store;
24
+ constructor(opts) {
25
+ this.store = opts.store;
26
+ this.catalog = opts.catalog;
27
+ this.llamaCppModels = opts.llamaCppModels;
28
+ this.ds4Models = opts.ds4Models;
29
+ this.mlxModels = opts.mlxModels;
30
+ this.uvRuntime = opts.uvRuntime;
31
+ this.mlxRuntimeStatus = opts.mlxRuntimeStatus;
32
+ this.home = opts.home;
33
+ this.cacheController = opts.cacheController;
34
+ this.gpuArbiter = opts.gpuArbiter;
35
+ this.engineBinaries = opts.engineBinaries;
36
+ this.engineRouter = opts.engineRouter;
37
+ }
38
+ /** Product chat may prefill its own sessions; the engine runtime never resolves them. */
39
+ async prefillCacheSession(_sessionId) {
40
+ return false;
41
+ }
42
+ /** Cached provider instances keyed by provider name. */
43
+ providers = new Map();
44
+ catalog;
45
+ llamaCppModels;
46
+ ds4Models;
47
+ mlxModels;
48
+ uvRuntime;
49
+ mlxRuntimeStatus;
50
+ home;
51
+ cacheController;
52
+ gpuArbiter;
53
+ engineBinaries;
54
+ engineRouter;
55
+ /**
56
+ * Snapshot of every provider's prompt-cache state. Empty array when
57
+ * no controller is wired (cloud-only install, tests). Polled by the
58
+ * EngineStatusPill alongside `/api/queues` for the popover stats
59
+ * rows. Cheap — pure read of in-memory state.
60
+ */
61
+ getCacheStats() {
62
+ return this.cacheController?.getAllStats() ?? [];
63
+ }
64
+ /**
65
+ * Operator-driven invalidation hook. The /api/cache/evict route
66
+ * calls this to drop a single session's cache; same path the
67
+ * compaction / archive / delete hooks already use internally.
68
+ */
69
+ invalidateSessionCache(sessionId) {
70
+ this.cacheController?.invalidate(sessionId);
71
+ }
72
+ /**
73
+ * Operator-driven full-provider eviction. Same hook the resetClient
74
+ * path uses; surfaced on /api/cache/clear so an operator can punt
75
+ * stale state without waiting for credential rotation.
76
+ */
77
+ invalidateProviderCache(providerName) {
78
+ this.cacheController?.invalidateProvider(providerName);
79
+ }
80
+ /**
81
+ * Live-update the controller's per-provider budget. Called from the
82
+ * config PUT handler when the operator changes `cacheBudgetMb` —
83
+ * eviction kicks in immediately if the new budget is below current
84
+ * usage. No-op if no controller is wired.
85
+ */
86
+ setCacheBudget(providerName, bytes) {
87
+ this.cacheController?.setBudget(providerName, bytes);
88
+ }
89
+ /**
90
+ * Live-update the capacity broker's total budget for resident local
91
+ * engines. Called from the config PUT handler when the operator moves the
92
+ * memory slider (`localEngineMemoryGb`); `null` reverts to the host's
93
+ * auto-derived value.
94
+ *
95
+ * No-op when no router exists yet — {@link buildEngineRouter} reads the
96
+ * config itself, so a router built later already picks the new value up.
97
+ * The in-flight case is the one that needs care: a build that read the
98
+ * config *before* this write would otherwise install the stale budget and
99
+ * keep it until shutdown, so chain onto the pending promise rather than
100
+ * only checking the resolved cache.
101
+ */
102
+ async setLocalEngineMemoryBudget(bytes) {
103
+ const live = this.engineRouter ?? this.engineRouterCache;
104
+ if (live) {
105
+ live.broker.setBudgetBytes(bytes);
106
+ return;
107
+ }
108
+ const pending = this.engineRouterInitPromise;
109
+ if (!pending)
110
+ return;
111
+ const router = await pending.catch(() => null);
112
+ router?.broker.setBudgetBytes(bytes);
113
+ }
114
+ /**
115
+ * Live-update whether co-resident local models may spill into system RAM.
116
+ * `null` reverts to the host's auto choice. Same in-flight care as
117
+ * {@link setLocalEngineMemoryBudget}, and the same non-eviction contract:
118
+ * turning spillover off doesn't unload anything, it changes what the next
119
+ * spawn is allowed to add.
120
+ */
121
+ async setAllowRamSpillover(allow) {
122
+ const live = this.engineRouter ?? this.engineRouterCache;
123
+ if (live) {
124
+ live.broker.setAllowRamSpillover(allow);
125
+ return;
126
+ }
127
+ const pending = this.engineRouterInitPromise;
128
+ if (!pending)
129
+ return;
130
+ const router = await pending.catch(() => null);
131
+ router?.broker.setAllowRamSpillover(allow);
132
+ }
133
+ /** Return the provider if it has already been initialized; never creates one. */
134
+ getProviderIfReady(name) {
135
+ return this.providers.get(name) ?? null;
136
+ }
137
+ /**
138
+ * Lazily construct the multi-engine router using the engine runtime’s
139
+ * already-resolved deps (store, catalog, llamaCppModels, ds4Models, mlxModels,
140
+ * uvRuntime). Once built, the router owns the {@link ProviderPool}
141
+ * and {@link CapacityBroker}; subsequent calls return the cached
142
+ * instance.
143
+ *
144
+ * Returns `null` when {@link LocalEngineRuntimeOptions.engineRouter} was
145
+ * explicitly injected — that path is owned by the caller (typically
146
+ * tests). The lazy build is only for production wiring through
147
+ * `service.ts`.
148
+ */
149
+ engineRouterCache = null;
150
+ engineRouterInitPromise = null;
151
+ /**
152
+ * Shut down the production-owned lazy engine router, including a router
153
+ * whose construction is still in flight. Pooled local providers do not live
154
+ * in {@link providers}, so omitting this step lets their native children
155
+ * outlive gezeld and become PPID-1 orphans.
156
+ *
157
+ * An explicitly injected {@link engineRouter} remains caller-owned (mostly
158
+ * a test seam) and is deliberately left alone.
159
+ */
160
+ async shutdownOwnedEngineRouter() {
161
+ let router = this.engineRouterCache;
162
+ const pending = this.engineRouterInitPromise;
163
+ if (!router && pending) {
164
+ try {
165
+ router = await pending;
166
+ }
167
+ catch {
168
+ // A failed construction owns no resident providers, but clear the
169
+ // rejected one-flight so a live hard reset can try again later.
170
+ }
171
+ }
172
+ this.engineRouterCache = null;
173
+ this.engineRouterInitPromise = null;
174
+ if (!router)
175
+ return;
176
+ try {
177
+ await router.shutdown();
178
+ }
179
+ catch (err) {
180
+ log.warn(`engine router shutdown failed: ${err instanceof Error ? err.message : String(err)}`);
181
+ }
182
+ }
183
+ /**
184
+ * Free the memory a live reset can free without severing anything: evict
185
+ * every resident engine that is idle right now and leave the rest to the
186
+ * pool's ordinary lifecycle. The router itself stays — dropping it while an
187
+ * engine is still serving a turn would orphan that process outside the
188
+ * broker's accounting, which is the reason the old path force-killed
189
+ * everything instead.
190
+ *
191
+ * An explicitly injected {@link engineRouter} remains caller-owned and is
192
+ * left alone, same rule as {@link shutdownOwnedEngineRouter}. A router
193
+ * whose construction is still in flight owns no resident engines yet, so
194
+ * this deliberately does not await it.
195
+ */
196
+ async releaseIdleOwnedEngines() {
197
+ const router = this.engineRouterCache;
198
+ if (!router)
199
+ return;
200
+ try {
201
+ const busy = await router.releaseIdle();
202
+ if (busy.length > 0) {
203
+ log.info(`[chat] reset kept ${busy.length} busy engine(s) resident (${busy.join(', ')}) — they unload when their turns finish`);
204
+ }
205
+ }
206
+ catch (err) {
207
+ log.warn(`engine release-idle failed: ${err instanceof Error ? err.message : String(err)}`);
208
+ }
209
+ }
210
+ /**
211
+ * Resolve (or build) the router. Returns `null` only when no local
212
+ * provider is wired up at all (cloud-only installs); production
213
+ * installs with `llamaCppModels`, `ds4Models`, or `mlxModels` set always get a
214
+ * router. Callers MUST tolerate a `null` return — the legacy
215
+ * singleton path takes over.
216
+ */
217
+ async getEngineRouter() {
218
+ if (this.engineRouter)
219
+ return this.engineRouter;
220
+ if (this.engineRouterCache)
221
+ return this.engineRouterCache;
222
+ if (!this.llamaCppModels && !this.ds4Models && !this.mlxModels)
223
+ return null;
224
+ if (this.engineRouterInitPromise)
225
+ return this.engineRouterInitPromise;
226
+ this.engineRouterInitPromise = this.buildEngineRouter().then((r) => {
227
+ this.engineRouterCache = r;
228
+ return r;
229
+ });
230
+ return this.engineRouterInitPromise;
231
+ }
232
+ async buildEngineRouter() {
233
+ const { EngineRouter } = await import('./engine-router.js');
234
+ const { CapacityBroker } = await import('./capacity-broker.js');
235
+ const { ProviderPool } = await import('./provider-pool.js');
236
+ const { GpuPanicGuard } = await import('./gpu-panic-guard.js');
237
+ const gpuPanicGuard = new GpuPanicGuard();
238
+ const config = await this.store.readConfig();
239
+ const budgetBytes = typeof config.localEngineMemoryGb === 'number'
240
+ ? Math.round(config.localEngineMemoryGb * 1024 ** 3)
241
+ : undefined;
242
+ // Measure the accelerator before deriving the budget. Without this the
243
+ // broker sizes a discrete-GPU host off system RAM alone — the shape that
244
+ // told a 64 GB / 24 GB-VRAM box its models get "60% of your 63.9 GB
245
+ // machine" and then refused a model that fit the card plus offload.
246
+ // The probe caches, and a failure degrades to the RAM-only curve.
247
+ const memoryProfile = await (async () => {
248
+ try {
249
+ const { detectMemoryProfileCached } = await import('../../system/memory.js');
250
+ return await detectMemoryProfileCached();
251
+ }
252
+ catch {
253
+ return null;
254
+ }
255
+ })();
256
+ const broker = new CapacityBroker({
257
+ ...(budgetBytes !== undefined ? { budgetBytes } : {}),
258
+ gpuVramBytes: memoryProfile?.gpuVramBytes ?? null,
259
+ ...(memoryProfile
260
+ ? {
261
+ unifiedMemory: memoryProfile.gpuMemoryKind === 'integrated' ||
262
+ memoryProfile.gpuMemoryKind === 'unified',
263
+ }
264
+ : {}),
265
+ allowRamSpillover: config.allowRamSpillover ?? null,
266
+ });
267
+ const pool = new ProviderPool({ broker, builders: {} });
268
+ // Builders close over `this` so they can re-read config and use the
269
+ // already-resolved model managers / runtimes. Each replica goes
270
+ // through the same factories as the singleton path, with
271
+ // `modelOverride` set to pin the modelId + replicaIdx.
272
+ const llamaBuilder = async ({ modelId, replicaIdx, }) => {
273
+ const cfg = await this.store.readConfig();
274
+ const affinity = cfg.providerQueue?.affinity;
275
+ const eb = this.engineBinaries;
276
+ const provider = await buildLlamaCppProvider({
277
+ config: cfg,
278
+ affinity,
279
+ home: this.home,
280
+ ...(this.llamaCppModels ? { llamaCppModels: this.llamaCppModels } : {}),
281
+ ...(this.gpuArbiter ? { arbiter: this.gpuArbiter } : {}),
282
+ ...(eb ? { ensureEngine: () => ensureLlamaEngineStatus(eb, cfg) } : {}),
283
+ catalog: this.catalog,
284
+ modelOverride: { modelId, replicaIdx },
285
+ // Pool path: lets the slot ceiling see co-resident reservations.
286
+ broker,
287
+ });
288
+ await this.initLocalProvider('llama-cpp', provider, cfg);
289
+ // Prefer the launch admission's own reservation (weights + KV at the
290
+ // granted window) over the catalog/weights-multiplier estimate — the
291
+ // ledger otherwise carries zero KV and under-reserves dense models
292
+ // whose KV rivals their weights (M1).
293
+ const bytes = provider.plannedReservationBytes?.() ??
294
+ (await this.resolveResidentBytes('llama-cpp', modelId));
295
+ const installed = await this.llamaCppModels?.resolveModel(modelId).catch(() => null);
296
+ return {
297
+ provider,
298
+ residentBytes: bytes,
299
+ ...(installed?.approxSizeBytes ? { modelWeightsBytes: installed.approxSizeBytes } : {}),
300
+ };
301
+ };
302
+ const mlxBuilder = async ({ modelId, replicaIdx, }) => {
303
+ const cfg = await this.store.readConfig();
304
+ const affinity = cfg.providerQueue?.affinity;
305
+ const provider = await buildMlxProvider({
306
+ config: cfg,
307
+ affinity,
308
+ store: this.store,
309
+ ...(this.mlxModels ? { mlxModels: this.mlxModels } : {}),
310
+ ...(this.uvRuntime ? { uvRuntime: this.uvRuntime } : {}),
311
+ ...(this.mlxRuntimeStatus ? { mlxRuntimeStatus: this.mlxRuntimeStatus } : {}),
312
+ ...(this.gpuArbiter ? { arbiter: this.gpuArbiter } : {}),
313
+ modelOverride: { modelId, replicaIdx },
314
+ broker,
315
+ });
316
+ await this.initLocalProvider('mlx', provider, cfg);
317
+ // Same M1 preference as the llama-cpp builder: the launch admission's
318
+ // weights+KV reservation over the catalog/weights-multiplier fallback.
319
+ const bytes = provider.plannedReservationBytes?.() ?? (await this.resolveResidentBytes('mlx', modelId));
320
+ const installed = await this.mlxModels?.resolveModel(modelId).catch(() => null);
321
+ return {
322
+ provider,
323
+ residentBytes: bytes,
324
+ ...(installed?.approxSizeBytes ? { modelWeightsBytes: installed.approxSizeBytes } : {}),
325
+ };
326
+ };
327
+ const ds4Builder = async ({ modelId, replicaIdx, }) => {
328
+ const cfg = await this.store.readConfig();
329
+ const affinity = cfg.providerQueue?.affinity;
330
+ const provider = await buildDs4Provider({
331
+ config: cfg,
332
+ affinity,
333
+ home: this.home,
334
+ ...(this.ds4Models ? { ds4Models: this.ds4Models } : {}),
335
+ ...(this.gpuArbiter ? { arbiter: this.gpuArbiter } : {}),
336
+ catalog: this.catalog,
337
+ modelOverride: { modelId, replicaIdx },
338
+ broker,
339
+ });
340
+ await this.initLocalProvider('ds4', provider, cfg);
341
+ const bytes = await this.resolveResidentBytes('ds4', modelId);
342
+ const installed = await this.ds4Models?.resolveModel(modelId).catch(() => null);
343
+ return {
344
+ provider,
345
+ residentBytes: bytes,
346
+ ...(installed?.approxSizeBytes ? { modelWeightsBytes: installed.approxSizeBytes } : {}),
347
+ };
348
+ };
349
+ const builders = {};
350
+ if (this.llamaCppModels)
351
+ builders['llama-cpp'] = llamaBuilder;
352
+ if (this.mlxModels)
353
+ builders.mlx = mlxBuilder;
354
+ // ds4 has no model-manager gate (v1 resolves its GGUF from an explicit
355
+ // path / external URL, not the catalog dir) — always register it; the
356
+ // builder throws an actionable error when neither a ds4-server binary
357
+ // nor an external URL is configured, and the M5 availability probe hides
358
+ // ds4 in the UI on unsupported platforms.
359
+ builders.ds4 = ds4Builder;
360
+ // Replace the empty pool with one that holds the actual builders.
361
+ const realPool = new ProviderPool({
362
+ broker,
363
+ builders,
364
+ gpuPanicGuard,
365
+ // The arbiter already reads device-wide accelerator memory for the idle
366
+ // release hint; the pool needs the same number to refuse a spawn onto a
367
+ // card another process has filled.
368
+ ...(this.gpuArbiter
369
+ ? { vramHeadroom: () => this.gpuArbiter.getMemoryPressureStatus() }
370
+ : {}),
371
+ });
372
+ return new EngineRouter({
373
+ broker,
374
+ pool: realPool,
375
+ builders,
376
+ resolveResidentBytes: (provider, modelId) => {
377
+ // Synchronous lookup; we cache the catalog read inside
378
+ // `resolveResidentBytesCache` populated lazily on first
379
+ // builder call. Falls through to broker estimator on miss.
380
+ const cached = this.resolveResidentBytesCache.get(`${provider}:${modelId}`);
381
+ return cached;
382
+ },
383
+ });
384
+ }
385
+ /**
386
+ * Per-replica provider initialization + cache-controller wiring.
387
+ * Mirrors the singleton-path post-construction work inside
388
+ * {@link ensureProvider}, factored out so the pool's builder
389
+ * closures can share it. Cache-controller registration is gated
390
+ * on replica index — only replica 0 registers, because the
391
+ * controller is keyed by provider name and N adapters would
392
+ * collide.
393
+ */
394
+ async initLocalProvider(name, provider, config) {
395
+ try {
396
+ await provider.initialize();
397
+ }
398
+ catch (err) {
399
+ const message = err instanceof Error ? err.message : String(err);
400
+ const actionable = err instanceof Error && err.isActionable === true;
401
+ throw new Error(actionable
402
+ ? message
403
+ : `${name} provider failed to start: ${message}. Go to Settings and check your credentials.`);
404
+ }
405
+ // Wire the engine's prompt-cache adapter. Without this, pool-built
406
+ // providers (the default path for local engines) have
407
+ // `cacheAdapter = null` — every send re-attaches cache_id to the
408
+ // request body, the wrapped engine clears its KV cache on stream
409
+ // end, and each tool-loop iteration pays the full prefill cost
410
+ // again. Wild-caught on a gemma4-26b/MLX Meester loop:
411
+ // 11+ tool-loop iterations, ~10s of prefill per turn, no cache
412
+ // hits in Python logs because the request body never carried
413
+ // `cache_id`. `ensureProvider` already had this wiring inline;
414
+ // pulling it out so both call sites share one source of truth.
415
+ await this.wireLocalProviderCacheAdapter(name, provider, config);
416
+ }
417
+ /**
418
+ * Construct the engine's `EngineCacheAdapter`, register it with the
419
+ * shared `cacheController`, and attach it to the provider so every
420
+ * subsequent send carries cache extras. Idempotent at the controller
421
+ * level — `registerAdapter` overwrites by `providerName`, so calling
422
+ * this for two replicas of the same provider just keeps the
423
+ * most-recently-registered adapter in the controller's tracking.
424
+ * Each provider still gets its own per-replica adapter via
425
+ * `setCacheAdapter`. Returns early when no controller is wired
426
+ * (test paths) or the provider isn't a local engine.
427
+ */
428
+ async wireLocalProviderCacheAdapter(name, provider, config) {
429
+ if (!this.cacheController)
430
+ return;
431
+ // ds4 manages its own KV persistence (`--kv-disk-dir`, token-text
432
+ // keyed), so its adapter attaches nothing per request and can't evict
433
+ // or inspect — its one real capability is `warm`: a prefill-only
434
+ // request that runs the (minutes-long, SSD-streamed) conversation
435
+ // prefill while the user is still reading, so the next real turn
436
+ // lands on hot KV. Wired to the OUTER Ds4Provider only — the inner
437
+ // llama provider's send path expects the llama-specific slot adapter.
438
+ if (name === 'ds4') {
439
+ const ds4Provider = provider;
440
+ const { Ds4CacheAdapter } = await import('../ds4/cache-adapter.js');
441
+ const innerLlama = ds4Provider.llamaCpp;
442
+ const adapter = new Ds4CacheAdapter({
443
+ resolveBaseUrl: async () => innerLlama.currentBaseUrl(),
444
+ isBusy: () => {
445
+ const snap = ds4Provider.queue?.snapshot();
446
+ if (!snap)
447
+ return false;
448
+ return snap.running > 0 || snap.queuedInteractive > 0;
449
+ },
450
+ // Route the warm through the session's OWN request assembly so
451
+ // the warmed prefix is byte-identical to the next real turn's
452
+ // prompt (ds4 KV is prefix-keyed from token 0 — a hand-built
453
+ // transcript request stores a key no real turn can hit). The
454
+ // ensureState here also pre-builds the MCP bridge + provider
455
+ // session — work the real turn needs anyway, done early.
456
+ prefillSession: async (sessionId) => {
457
+ return this.prefillCacheSession(sessionId);
458
+ },
459
+ });
460
+ this.cacheController.registerAdapter(adapter);
461
+ ds4Provider.setCacheAdapter(adapter);
462
+ }
463
+ else if (name === 'llama-cpp') {
464
+ const llamaProvider = provider;
465
+ const { LlamaCppCacheAdapter } = await import('../llama-cpp/cache-adapter.js');
466
+ const llamaSlotSavePath = llamaProvider.getSlotSavePath();
467
+ const adapter = new LlamaCppCacheAdapter({
468
+ resolveBaseUrl: async () => llamaProvider.currentBaseUrl(),
469
+ // `/slots` is an AUTHENTICATED endpoint — only `/health` answers
470
+ // without the key (see engine-api-key.ts). The provider authenticates
471
+ // because `build-provider` wraps its fetch in `withEngineApiKey`, but
472
+ // the adapter is constructed here with a bare `fetch`, so without this
473
+ // it sent no Authorization header and every call 401'd: the `/slots`
474
+ // usage poll AND both `?action=save|restore` calls, i.e. the whole
475
+ // disk KV persistence layer, silently dead. It failed quietly because
476
+ // each call site degrades on error by design (no cache entry, `disk
477
+ // save: MISSED`) — the only symptom was cold prefills and a 5-second
478
+ // drip of `unauthorized: Invalid API Key` in the engine log, ~300 per
479
+ // trial. Resolved per call, not captured: the key is generated lazily.
480
+ resolveAuthToken: () => engineApiKey(),
481
+ // The ENGINE slot count (`--parallel N`), not `queue.concurrency`:
482
+ // the queue reserves a background lane above the engine slots, so
483
+ // on a single-slot launch it reads 2 and the adapter would bind
484
+ // sessions to slot ids the server doesn't have (wild-caught
485
+ // 2026-08-03 — save/restore against the phantom slot 400s
486
+ // silently).
487
+ slotCount: llamaProvider.getLaunchedSlots(),
488
+ diskCacheRoot: join(this.home, 'engines', 'llama-cpp', 'slots'),
489
+ diskCacheBudgetMb: config.llamaCppDiskCacheBudgetMb,
490
+ ...(llamaSlotSavePath ? { slotSavePath: llamaSlotSavePath } : {}),
491
+ });
492
+ this.cacheController.registerAdapter(adapter);
493
+ llamaProvider.setCacheAdapter(adapter);
494
+ }
495
+ else if (name === 'mlx') {
496
+ const mlxProvider = provider;
497
+ const { MlxCacheAdapter } = await import('../mlx/cache-adapter.js');
498
+ const adapter = new MlxCacheAdapter({
499
+ resolveBaseUrl: async () => mlxProvider.currentBaseUrl(),
500
+ runExclusive: (label, work) => mlxProvider.runExclusiveEngineRequest(label, work),
501
+ });
502
+ this.cacheController.registerAdapter(adapter);
503
+ mlxProvider.setCacheAdapter(adapter);
504
+ }
505
+ }
506
+ /**
507
+ * Cache of catalog `residentBytes` per `(provider:modelId)`.
508
+ * Populated synchronously by `prefetchResidentBytes` so the
509
+ * router's sync resolver works. Falls back to the broker estimator
510
+ * on miss.
511
+ */
512
+ resolveResidentBytesCache = new Map();
513
+ /**
514
+ * Drop cached reservations so the next admission re-reads the catalog and
515
+ * config. ds4 prices its footprint at the launch context, so a per-model
516
+ * context override changes what the broker must reserve — leaving the old
517
+ * entry cached would keep billing the pre-override number for the life of
518
+ * the process. Call from any route that mutates context sizing.
519
+ */
520
+ invalidateResidentBytesCache(provider, modelId) {
521
+ if (!provider) {
522
+ this.resolveResidentBytesCache.clear();
523
+ return;
524
+ }
525
+ if (modelId) {
526
+ this.resolveResidentBytesCache.delete(`${provider}:${modelId}`);
527
+ return;
528
+ }
529
+ for (const key of this.resolveResidentBytesCache.keys()) {
530
+ if (key.startsWith(`${provider}:`))
531
+ this.resolveResidentBytesCache.delete(key);
532
+ }
533
+ }
534
+ /** Extra fixed reservation for the exact ds4 vision encoder this launch uses. */
535
+ async resolveDs4VisionResidentBytes(config, modelId, installed, source) {
536
+ const explicitModelPath = process.env.GEZEL_DS4_MODEL ?? config.ds4ModelPath;
537
+ const explicitVisionEncoderPath = process.env.GEZEL_DS4_VISION_ENCODER ?? config.ds4VisionEncoderPath;
538
+ const externalBaseUrl = process.env.GEZEL_DS4_SERVER_URL ?? config.ds4BaseUrl;
539
+ const vision = resolveDs4VisionLaunch({
540
+ modelId,
541
+ ...(config.nativeVision ? { nativeVision: config.nativeVision } : {}),
542
+ ...(installed?.visionEncoderPath
543
+ ? { installedVisionEncoderPath: installed.visionEncoderPath }
544
+ : {}),
545
+ ...(explicitModelPath ? { explicitModelPath } : {}),
546
+ ...(explicitVisionEncoderPath ? { explicitVisionEncoderPath } : {}),
547
+ ...(externalBaseUrl ? { externalBaseUrl } : {}),
548
+ });
549
+ if (!vision.enabled || !vision.visionEncoderPath)
550
+ return 0;
551
+ let sizeBytes = vision.visionEncoderPath === installed?.visionEncoderPath
552
+ ? (installed?.visionEncoderSizeBytes ?? source?.visionEncoder?.sizeBytes)
553
+ : undefined;
554
+ if (!sizeBytes) {
555
+ const { stat } = await import('node:fs/promises');
556
+ sizeBytes = await stat(vision.visionEncoderPath)
557
+ .then((entry) => entry.size)
558
+ .catch(() => undefined);
559
+ }
560
+ return ds4VisionResidentBytes(sizeBytes);
561
+ }
562
+ async resolveResidentBytes(provider, modelId) {
563
+ const cacheKey = `${provider}:${modelId}`;
564
+ const cached = this.resolveResidentBytesCache.get(cacheKey);
565
+ if (cached !== undefined)
566
+ return cached;
567
+ // Read from the catalog. The chat-model manifest carries
568
+ // residentBytes per source block (llamaCpp / ds4 / mlx); fall back to
569
+ // approxSizeBytes * tier multiplier when missing.
570
+ let bytes;
571
+ try {
572
+ const items = await this.catalog.list('chat-model');
573
+ const match = items.find((m) => m.manifest.id === modelId);
574
+ // The discriminated `manifest` union narrows to a chat-model
575
+ // shape via `kind`. Cast through `unknown` because we've
576
+ // already filtered by id from the chat-model list — the kind
577
+ // check would be redundant.
578
+ const cm = match?.manifest;
579
+ if (cm) {
580
+ const block = provider === 'mlx' ? cm.mlx : provider === 'ds4' ? cm.ds4 : cm.llamaCpp;
581
+ if (block?.residentBytes) {
582
+ bytes = block.residentBytes;
583
+ if (provider === 'ds4') {
584
+ const config = await this.store.readConfig();
585
+ const externalBaseUrl = process.env.GEZEL_DS4_SERVER_URL ?? config.ds4BaseUrl;
586
+ if (!externalBaseUrl) {
587
+ const { ds4ProjectedResidentBytes, ds4ResidentBytesForMode, ds4ResidentLine, shouldUseDs4SsdStreaming, } = await import('../ds4/residency.js');
588
+ // Bill the window this model will actually launch with. The
589
+ // authored footprint is a measurement at `residentCtxTokens`, so
590
+ // without this a raised context reserves the old number and the
591
+ // broker admits a model whose KV no longer fits — the exact
592
+ // memory-pressure event the residency rules exist to prevent.
593
+ const ds4Block = cm.ds4;
594
+ const installed = await this.ds4Models?.resolveModel(modelId).catch(() => null);
595
+ const visionResidentBytes = await this.resolveDs4VisionResidentBytes(config, modelId, installed, ds4Block);
596
+ const line = ds4ResidentLine({
597
+ residentBytes: bytes,
598
+ kvBytesPerToken: ds4Block?.kvBytesPerToken,
599
+ residentCtxTokens: ds4Block?.residentCtxTokens,
600
+ });
601
+ if (line) {
602
+ const { totalmem } = await import('node:os');
603
+ bytes = ds4ProjectedResidentBytes(line, resolveDs4LaunchCtx({
604
+ configured: config.modelContextOverrides?.[`ds4:${modelId}`] ?? config.ds4NumCtx,
605
+ ramTieredCtx: totalmem() / 1024 ** 3 >= 192 ? 262_144 : 131_072,
606
+ catalogMaxCtx: ds4Block?.maxLaunchCtx,
607
+ minViableContextTokens: minViableLocalContextTokens(),
608
+ }));
609
+ }
610
+ bytes = ds4ResidentBytesForMode(bytes, shouldUseDs4SsdStreaming({
611
+ configured: config.ds4SsdStreaming,
612
+ ...(ds4Block?.ssdStreamingSupported !== undefined
613
+ ? { ssdStreamingSupported: ds4Block.ssdStreamingSupported }
614
+ : {}),
615
+ modelSizeBytes: ds4Block?.residentWeightBytes ?? block.approxSizeBytes,
616
+ ...(visionResidentBytes > 0 ? { companionBytes: visionResidentBytes } : {}),
617
+ }), ds4Block?.ssdStreamingSupported);
618
+ bytes += visionResidentBytes;
619
+ }
620
+ }
621
+ }
622
+ else if (block?.approxSizeBytes) {
623
+ const { CapacityBroker } = await import('./capacity-broker.js');
624
+ // `approxSizeBytes` is the weights alone; a multimodal entry also
625
+ // loads its projector, which the catalog sizes separately.
626
+ const mmprojBytes = provider === 'llama-cpp' ? (cm.llamaCpp?.mmproj?.sizeBytes ?? 0) : 0;
627
+ let residentWeightFileBytes = block.approxSizeBytes;
628
+ if (provider === 'llama-cpp') {
629
+ // v0.4 can leave architecture-marked row-addressable embeddings
630
+ // file-backed (notably Qwen 3.8 Flash Next's 51B-parameter
631
+ // PLE/engram table). Inspect the installed split GGUF before the pool's
632
+ // preflight reservation; otherwise it rejects the model before
633
+ // buildLlamaCppProvider gets a chance to make the same deduction.
634
+ const installed = await this.llamaCppModels?.resolveModel(modelId).catch(() => null);
635
+ if (installed?.weightsPath) {
636
+ const [summary, config, perModel] = await Promise.all([
637
+ readGgufSummaryAsync(installed.weightsPath, { includeTensorSizes: true }).catch(() => null),
638
+ this.store.readConfig(),
639
+ resolveCatalogLlamaCppEngineConfig(this.catalog, modelId),
640
+ ]);
641
+ if (summary) {
642
+ residentWeightFileBytes = Math.max(0, residentWeightFileBytes -
643
+ effectiveLazyTensorBytes(summary, config.llamaCppLazyMode ?? perModel?.lazyMode ?? 'auto'));
644
+ }
645
+ }
646
+ }
647
+ bytes = CapacityBroker.estimateResidentBytes(provider, residentWeightFileBytes, {
648
+ mmprojBytes,
649
+ });
650
+ }
651
+ }
652
+ }
653
+ catch {
654
+ /* fall through to default */
655
+ }
656
+ if (bytes === undefined) {
657
+ const { CapacityBroker } = await import('./capacity-broker.js');
658
+ bytes = CapacityBroker.estimateResidentBytes(provider, 8 * 1024 ** 3);
659
+ }
660
+ this.resolveResidentBytesCache.set(cacheKey, bytes);
661
+ return bytes;
662
+ }
663
+ /**
664
+ * Reconcile the pool's resident set to match a target clone-count
665
+ * map. Surfaces the Settings → Local Models picker's intent to the
666
+ * runtime: spawn missing replicas (up to capacity) and evict
667
+ * excess. No-op when no router is configured.
668
+ */
669
+ async reconcileEnginePool(provider, target) {
670
+ const router = await this.getEngineRouter();
671
+ if (!router)
672
+ return;
673
+ await router.reconcileClones(provider, target);
674
+ }
675
+ /**
676
+ * Unload one already-resident local model replica without constructing the
677
+ * engine router as a side effect. The pool rejects the request if the model
678
+ * became busy after the UI's last lifecycle sample.
679
+ */
680
+ async unloadIdleEngine(provider, modelId, replicaIdx) {
681
+ const router = this.engineRouter ?? this.engineRouterCache;
682
+ if (!router || !router.pool.has(makeEngineKey(provider, modelId, replicaIdx)))
683
+ return false;
684
+ return router.unloadIdle(provider, modelId, replicaIdx);
685
+ }
686
+ /**
687
+ * Snapshot of the live pool — committed bytes, budget, per-key
688
+ * resident set. Surfaced via `GET /api/engines/status`. Returns
689
+ * `null` for installs without a pool wired.
690
+ */
691
+ async engineStatus() {
692
+ const router = await this.getEngineRouter();
693
+ if (!router)
694
+ return null;
695
+ return router.snapshot();
696
+ }
697
+ /**
698
+ * Read the already-live local-engine pool without constructing the router.
699
+ * Hot status endpoints use this path so opening a telemetry popover never
700
+ * initializes local inference as a side effect.
701
+ */
702
+ peekEngineStatus() {
703
+ const router = this.engineRouter ?? this.engineRouterCache;
704
+ return router?.snapshot() ?? null;
705
+ }
706
+ /**
707
+ * Live provider-queue summaries for pool-resident local engines, keyed
708
+ * by provider name — the data `/api/queues` needs to reflect pooled
709
+ * work the singleton {@link getProviderIfReady} path can't see (chat
710
+ * turns AND background one-shots). See
711
+ * {@link ProviderPool.queueSummaries} for why the blind spot existed.
712
+ *
713
+ * Synchronous, non-building peek: reads the already-resolved router and
714
+ * returns an empty map when none exists yet. A poll before any local
715
+ * work has run has nothing resident to report anyway — and a status
716
+ * endpoint must never spin the router up as a side effect.
717
+ */
718
+ localEngineQueueSummaries() {
719
+ const router = this.engineRouter ?? this.engineRouterCache;
720
+ if (!router)
721
+ return new Map();
722
+ return router.pool.queueSummaries();
723
+ }
724
+ /**
725
+ * Launch provenance of every live local engine — the granted context
726
+ * window, slots, and KV dtype each engine ACTUALLY started with, from
727
+ * the supervisors' retained launch payloads. Non-building and cheap:
728
+ * walks resident providers only, never starts an engine. Feeds
729
+ * `/api/system/diagnostics` `localEngines` (Settings → About), so a
730
+ * "model is looping" report carries the grant without log spelunking.
731
+ */
732
+ localEngineLaunchSummaries() {
733
+ const router = this.engineRouter ?? this.engineRouterCache;
734
+ const out = router?.pool.engineLaunchSnapshots() ?? [];
735
+ // The singleton map can hold the same provider object (and therefore
736
+ // the same engine process) a pool entry already reported — dedupe by
737
+ // pid, the process identity the snapshot is about.
738
+ const seenPids = new Set(out.map((entry) => entry.snapshot.pid).filter((pid) => pid !== undefined));
739
+ for (const name of ['llama-cpp', 'mlx', 'ds4']) {
740
+ const singleton = this.providers.get(name);
741
+ const snapshot = singleton?.engineLaunchSnapshot?.();
742
+ if (!snapshot)
743
+ continue;
744
+ if (snapshot.pid !== undefined && seenPids.has(snapshot.pid))
745
+ continue;
746
+ const modelId = singleton?.getEffectiveModelId?.();
747
+ out.push({ provider: name, ...(modelId !== undefined ? { modelId } : {}), snapshot });
748
+ }
749
+ return out;
750
+ }
751
+ /**
752
+ * Non-building lookup for an already-created native provider. Unlike
753
+ * `getProviderForModel`, this cannot allocate a replica, evict another model,
754
+ * or start an engine. The caller still checks the provider's live base URL
755
+ * because a retained provider object may currently have no resident process.
756
+ */
757
+ peekResidentLocalProviders(name, modelId) {
758
+ if (!isLocalProvider(name) || !modelId)
759
+ return [];
760
+ const singleton = this.providers.get(name);
761
+ const router = this.engineRouter ?? this.engineRouterCache;
762
+ const pooled = router?.pool.peekProvidersForModel(name, modelId) ?? [];
763
+ return singleton ? [singleton, ...pooled.filter((provider) => provider !== singleton)] : pooled;
764
+ }
765
+ /**
766
+ * Resolve the context window a native model would receive without binding a
767
+ * pool replica. This is the broker-side half of remote admission: focusing a
768
+ * chat needs the live memory clamp so the user daemon can size its prompt,
769
+ * but it must not load the model or evict somebody else's resident engine.
770
+ *
771
+ * `standalone` prices the target as the eventual sole resident: inventory
772
+ * callers use it for stable device fitness, while remote admission combines
773
+ * it with `liveSystemPressure` because a competing Gezel engine is
774
+ * evictable/queueable but memory held by other applications is not. See
775
+ * {@link previewLocalEnginePlan}'s `standalone` note.
776
+ */
777
+ async previewContextWindowForModel(name, modelId, opts = {}) {
778
+ return (await this.previewLocalEnginePlan(name, modelId, opts)).contextWindow;
779
+ }
780
+ /**
781
+ * Reservations held by models OTHER than the one being previewed.
782
+ *
783
+ * `committed()` totals every replica, the previewed model's own included.
784
+ * Feeding that back as `committedOtherBytes` prices the launch as if a
785
+ * second copy had to load beside the resident one, so the model currently
786
+ * serving chats reports "won't fit" against its own reservation — and on a
787
+ * host where one big model fills most of the budget, every OTHER row is
788
+ * denied by a reservation that eviction would release. Every consumer of
789
+ * `committedOtherBytes` means co-resident models, so subtract our own
790
+ * replicas here. A key the parser doesn't recognise stays counted: an
791
+ * unattributable reservation is real memory, and over-counting only makes
792
+ * the preview conservative.
793
+ */
794
+ committedOtherBytesFor(snapshot, provider, modelId) {
795
+ if (!snapshot?.enforced)
796
+ return 0;
797
+ const own = snapshot.byKey.reduce((sum, entry) => {
798
+ const parsed = parseEngineKey(entry.key);
799
+ return parsed?.provider === provider && parsed.modelId === modelId ? sum + entry.bytes : sum;
800
+ }, 0);
801
+ return Math.max(0, snapshot.committedBytes - own);
802
+ }
803
+ /**
804
+ * The memory picture every engine's launch preview prices against.
805
+ *
806
+ * One derivation because each engine branch below used to rebuild it, and
807
+ * they drifted: the llama.cpp branch pinned its admission clamp to usable
808
+ * VRAM alone on discrete hosts, so a 21 GB MoE the broker would gladly
809
+ * admit against a 30 GB budget reported "won't fit" — while the MLX branch,
810
+ * which never passed live RAM, priced the same question correctly. A 4.7 GB
811
+ * model was denied the same way. Adding an engine must not re-open that.
812
+ *
813
+ * Policy previews deliberately carry no `freeSystemRamBytes`: live free RAM
814
+ * is self-referential there — a warm engine can depress it and make every
815
+ * inventory row, itself included, fluctuate. Imminent placement callers may
816
+ * opt into `liveSystemPressure`; that is the broker `/admit` path and must
817
+ * use the same reclaimable-aware clamp as provider construction. Confining
818
+ * grown KV to fast memory is not lost for policy previews —
819
+ * `planAdaptiveContextGrowth` applies that clamp itself from `budgetKind` +
820
+ * `vramBytes`.
821
+ */
822
+ async previewCapacityInputs(provider, modelId, opts) {
823
+ const { computeCapacityBudget } = await import('./capacity-broker.js');
824
+ const { measuredCapacityBudget } = await import('./measured-budget.js');
825
+ const router = this.engineRouter ?? this.engineRouterCache;
826
+ const snapshot = router?.broker.committed();
827
+ // An unenforced budget carries no usable numbers — fall back wholesale
828
+ // rather than per-field, so a snapshot never contributes half a picture.
829
+ const enforced = snapshot?.enforced ? snapshot : undefined;
830
+ // No broker yet means no engine has ever been placed in this process, so
831
+ // the ambient GPU probe may still be unpublished — measure rather than
832
+ // read it. See measured-budget.ts for what a missing card costs here.
833
+ const live = enforced ? computeCapacityBudget() : await measuredCapacityBudget();
834
+ const committedOtherBytes = this.committedOtherBytesFor(snapshot, provider, modelId);
835
+ return {
836
+ budgetBytes: enforced?.budgetBytes ?? live.budgetBytes,
837
+ fastBudgetBytes: enforced === undefined
838
+ ? live.fastBytes
839
+ : (router?.broker.fastBudgetBytes() ?? enforced.pools.fastBytes),
840
+ concurrencySizingBytes: enforced?.pools.concurrencySizingBytes ?? live.concurrencySizingBytes,
841
+ vramBytes: enforced?.pools.vramBytes ?? live.vramBytes,
842
+ budgetKind: enforced?.pools.kind ?? live.kind,
843
+ committedOtherBytes: opts.standalone ? 0 : committedOtherBytes,
844
+ // A standalone imminent placement treats other Gezel engines as
845
+ // evictable: if one is busy, /infer queues until it drains. Its current
846
+ // process footprint is therefore not an intrinsic device-capacity
847
+ // denial. With no competing reservation, live pressure represents
848
+ // external applications / real system load and must match launch.
849
+ ...(opts.liveSystemPressure && !(opts.standalone && committedOtherBytes > 0)
850
+ ? { freeSystemRamBytes: availableSystemRamBytes() }
851
+ : {}),
852
+ };
853
+ }
854
+ /**
855
+ * Full non-binding launch preview: the context window a native model
856
+ * would receive AND the resident footprint at that window. Powers the
857
+ * models-list "size in memory" column alongside
858
+ * {@link previewContextWindowForModel}.
859
+ *
860
+ * Two footprints, deliberately: `plannedResidentBytes` is weights plus
861
+ * ONE slot's KV — what serving a single chat costs, and the only figure
862
+ * that tracks measured peak RSS. `reservedResidentBytes` is weights plus
863
+ * `plannedSlots` slots' KV — what the broker actually holds. Quoting the
864
+ * fleet as "size in memory" reads as the cost of using the model at all,
865
+ * which overstates a multi-slot host by the slot count.
866
+ */
867
+ async previewLocalEnginePlan(name, modelId,
868
+ /**
869
+ * ds4 only: price a catalog entry that is NOT downloaded yet. The ds4 plan
870
+ * needs the catalog block and this device's RAM tier, never the GGUF, so
871
+ * the browse list can quote the window and footprint a download would land
872
+ * on — which is when the fit decision is actually made. Other engines keep
873
+ * throwing {@link ModelNotInstalledError}: their plans read the real
874
+ * header.
875
+ */
876
+ opts = {}) {
877
+ let residentContextWindow;
878
+ for (const resident of this.peekResidentLocalProviders(name, modelId)) {
879
+ const residentModel = resident.getEffectiveModelId?.();
880
+ if (residentModel && residentModel !== modelId)
881
+ continue;
882
+ const prepared = await resident.prepareContextWindow?.(modelId);
883
+ const live = prepared ?? resident.getContextWindow?.();
884
+ if (live && Number.isFinite(live) && live > 0) {
885
+ residentContextWindow = Math.floor(live);
886
+ break;
887
+ }
888
+ }
889
+ const useResidentOr = (planned, minimum) => {
890
+ if (residentContextWindow === undefined)
891
+ return planned;
892
+ if (residentContextWindow < minimum) {
893
+ throw new CapacityDeniedError(`${modelId} is already running with only ${residentContextWindow.toLocaleString('en-US')} context tokens per turn, below its required ${minimum.toLocaleString('en-US')}-token working window. Restart the local engine so Gezel can re-admit it at the current context policy.`, { reason: 'resident-below-minimum' });
894
+ }
895
+ return residentContextWindow;
896
+ };
897
+ // Reusing an already-running target does not allocate its weights again,
898
+ // so current free RAM (which that same process depressed) is not a launch
899
+ // input. Keep the policy checks below — including resident-below-minimum
900
+ // and changed overrides — while skipping only the self-referential clamp.
901
+ const capacityOpts = residentContextWindow !== undefined && opts.liveSystemPressure
902
+ ? { ...opts, liveSystemPressure: false }
903
+ : opts;
904
+ const config = await this.store.readConfig();
905
+ // The floor this host is held to — 64K, or 32K where memory forces the
906
+ // trade. Read once so every branch of the preview prices the same window
907
+ // the launch path will ask for.
908
+ const contextFloor = minViableLocalContextTokens();
909
+ if (name === 'mlx') {
910
+ const installed = await this.mlxModels?.resolveModel(modelId);
911
+ if (!installed)
912
+ throw new ModelNotInstalledError(name, modelId);
913
+ const mlxOverride = config.modelContextOverrides?.[`mlx:${modelId}`];
914
+ // An override below the host floor is deliberate user intent — lower
915
+ // the floor to the override instead of raising the request back up.
916
+ const mlxFloor = mlxOverride !== undefined ? Math.min(contextFloor, mlxOverride) : contextFloor;
917
+ const geometry = installed.modelDir ? readMlxModelGeometry(installed.modelDir) : undefined;
918
+ const { CapacityBroker, defaultLocalEngineSlots, kvQuantScale, localEngineSlotCeiling, planCtxTokensForMemory, plannedLocalEngineSlots, } = await import('./capacity-broker.js');
919
+ const capacity = await this.previewCapacityInputs('mlx', modelId, capacityOpts);
920
+ const { budgetBytes, fastBudgetBytes: fastBudget, committedOtherBytes, concurrencySizingBytes: concurrencySizingBudget, } = capacity;
921
+ const kvBits = config.mlxKvBits ?? 0;
922
+ const kvCacheType = kvBits === 4 ? 'q4_0' : kvBits === 8 ? 'q8_0' : 'f16';
923
+ const weightsResident = CapacityBroker.estimateResidentBytes('mlx', installed.approxSizeBytes);
924
+ // One planning pass — request resolution + memory-priced admission
925
+ // (M4: mirror buildMlxProvider so the advertised window is what memory
926
+ // admits, not the native max — before this an MLX 26B on a 16 GB Mac
927
+ // previewed 256K). Runs a second time with the override ignored to
928
+ // mark where "Automatic" lands on the slider.
929
+ const planPass = (configuredLimit, floor) => {
930
+ let effective = resolveMlxEffectiveNumCtx({
931
+ ...(installed.contextWindow ? { modelContextWindow: installed.contextWindow } : {}),
932
+ ...(configuredLimit !== undefined ? { configuredLimit } : {}),
933
+ minViableContextTokens: floor,
934
+ });
935
+ const minimum = Math.min(installed.contextWindow ?? floor, floor);
936
+ const exactPerSlotKvF16 = geometry
937
+ ? estimateExactPerSlotKvBytesF16(geometry, effective)
938
+ : undefined;
939
+ if (!geometry || exactPerSlotKvF16 === undefined)
940
+ return { grantedCtx: effective, minimum };
941
+ const kvBytesPerToken = (exactPerSlotKvF16 / Math.max(1, effective)) * kvQuantScale(kvCacheType);
942
+ const configured = config.providerConcurrency?.mlx;
943
+ const ceiling = localEngineSlotCeiling({
944
+ engine: 'mlx',
945
+ budgetBytes: fastBudget,
946
+ sizingBudgetBytes: concurrencySizingBudget,
947
+ weightsBytes: installed.approxSizeBytes,
948
+ perTurnCtxTokens: effective,
949
+ kvCacheType,
950
+ committedOtherBytes,
951
+ exactPerSlotKvBytesF16: exactPerSlotKvF16,
952
+ });
953
+ let slots = plannedLocalEngineSlots({
954
+ configuredSlots: configured,
955
+ ceiling,
956
+ tierDefault: defaultLocalEngineSlots(fastBudget),
957
+ });
958
+ const admission = planCtxTokensForMemory({
959
+ requestedPerTurnCtxTokens: effective,
960
+ slots,
961
+ minimumPerTurnCtxTokens: minimum,
962
+ kvBytesPerToken,
963
+ weightsResidentBytes: weightsResident,
964
+ budgetBytes,
965
+ committedOtherBytes,
966
+ ...(capacity.freeSystemRamBytes !== undefined
967
+ ? { freeSystemRamBytes: capacity.freeSystemRamBytes }
968
+ : {}),
969
+ vramBytes: capacity.vramBytes,
970
+ });
971
+ if (!admission.minimumSatisfied) {
972
+ throw new CapacityDeniedError(NOT_ENOUGH_MEMORY_MESSAGE);
973
+ }
974
+ slots = admission.slots;
975
+ effective = admission.perTurnCtxTokens;
976
+ return { grantedCtx: effective, slots, kvBytesPerToken, minimum };
977
+ };
978
+ const plan = planPass(mlxOverride ?? config.mlxNumCtx, mlxFloor);
979
+ let autoContextWindow;
980
+ if (mlxOverride !== undefined) {
981
+ try {
982
+ autoContextWindow = planPass(config.mlxNumCtx, contextFloor).grantedCtx;
983
+ }
984
+ catch {
985
+ // Automatic sizing may not fit where a smaller override does — no marker.
986
+ }
987
+ }
988
+ // A resident engine below (or above) a freshly-set override keeps its
989
+ // launch window until restart; surface that as restart-required
990
+ // instead of quietly showing the stale window as if it were current.
991
+ if (mlxOverride !== undefined &&
992
+ residentContextWindow !== undefined &&
993
+ residentContextWindow !== plan.grantedCtx) {
994
+ throw new CapacityDeniedError(`${modelId} is running with ${residentContextWindow.toLocaleString('en-US')} context tokens per turn, but its custom context setting now resolves to ${plan.grantedCtx.toLocaleString('en-US')}. Restart the local engine to apply it.`, { reason: 'resident-below-minimum' });
995
+ }
996
+ const kvLin = geometry !== undefined
997
+ ? (() => {
998
+ const a = estimateExactPerSlotKvBytesF16(geometry, 8_192);
999
+ const b = estimateExactPerSlotKvBytesF16(geometry, 65_536);
1000
+ if (a === undefined || b === undefined)
1001
+ return undefined;
1002
+ const scale = kvQuantScale(kvCacheType);
1003
+ const bytesPerToken = ((b - a) / (65_536 - 8_192)) * scale;
1004
+ return { bytesPerToken, fixedBytes: Math.max(0, a * scale - bytesPerToken * 8_192) };
1005
+ })()
1006
+ : undefined;
1007
+ return {
1008
+ contextWindow: useResidentOr(plan.grantedCtx, plan.minimum),
1009
+ ...(plan.slots !== undefined && plan.kvBytesPerToken !== undefined
1010
+ ? {
1011
+ plannedResidentBytes: Math.round(weightsResident + plan.kvBytesPerToken * plan.grantedCtx),
1012
+ reservedResidentBytes: Math.round(weightsResident + plan.kvBytesPerToken * plan.grantedCtx * plan.slots),
1013
+ plannedSlots: plan.slots,
1014
+ weightsResidentBytes: weightsResident,
1015
+ }
1016
+ : {}),
1017
+ ...(installed.contextWindow ? { nativeContextWindow: installed.contextWindow } : {}),
1018
+ ...(mlxOverride !== undefined ? { overrideContextTokens: mlxOverride } : {}),
1019
+ ...(autoContextWindow !== undefined ? { autoContextWindow } : {}),
1020
+ ...(kvLin !== undefined
1021
+ ? { kvBytesPerTokenPerSlot: kvLin.bytesPerToken, kvFixedBytesPerSlot: kvLin.fixedBytes }
1022
+ : {}),
1023
+ };
1024
+ }
1025
+ if (name === 'ds4') {
1026
+ const installed = await this.ds4Models?.resolveModel(modelId);
1027
+ const hasExplicitSource = Boolean(process.env.GEZEL_DS4_MODEL ||
1028
+ process.env.GEZEL_DS4_SERVER_URL ||
1029
+ config.ds4ModelPath ||
1030
+ config.ds4BaseUrl);
1031
+ const detail = await this.catalog.get('chat-model', modelId).catch(() => null);
1032
+ const ds4Manifest = detail?.manifest.kind === 'chat-model' ? detail.manifest : undefined;
1033
+ const ds4Source = ds4Manifest?.ds4;
1034
+ // A catalog entry with a ds4 block is plannable before download; only a
1035
+ // model we know nothing about is genuinely absent.
1036
+ if (!installed && !hasExplicitSource && !(opts.allowUninstalled && ds4Source)) {
1037
+ throw new ModelNotInstalledError(name, modelId);
1038
+ }
1039
+ const { totalmem } = await import('node:os');
1040
+ const ramTieredCtx = totalmem() / 1024 ** 3 >= 192 ? 262_144 : 131_072;
1041
+ const ds4Override = config.modelContextOverrides?.[`ds4:${modelId}`];
1042
+ const ds4Floor = ds4Override !== undefined ? Math.min(contextFloor, ds4Override) : contextFloor;
1043
+ const effective = resolveDs4LaunchCtx({
1044
+ configured: ds4Override ?? config.ds4NumCtx,
1045
+ ramTieredCtx,
1046
+ catalogMaxCtx: ds4Source?.maxLaunchCtx,
1047
+ minViableContextTokens: ds4Floor,
1048
+ });
1049
+ if (ds4Override !== undefined &&
1050
+ residentContextWindow !== undefined &&
1051
+ residentContextWindow !== effective) {
1052
+ throw new CapacityDeniedError(`${modelId} is running with ${residentContextWindow.toLocaleString('en-US')} context tokens per turn, but its custom context setting now resolves to ${effective.toLocaleString('en-US')}. Restart the local engine to apply it.`, { reason: 'resident-below-minimum' });
1053
+ }
1054
+ // The slider's max for ds4: the authored catalog launch ceiling wins
1055
+ // over the advertised native window because ds4 has no ctx-vs-memory
1056
+ // admission to catch a window the engine cannot actually serve. The
1057
+ // manifest's window stands in before download, when there is no GGUF
1058
+ // header to read.
1059
+ const nativeWindow = installed?.contextWindow ?? ds4Manifest?.contextWindow;
1060
+ const ceilingTokens = ds4Source?.maxLaunchCtx !== undefined || nativeWindow !== undefined
1061
+ ? Math.min(ds4Source?.maxLaunchCtx ?? Number.POSITIVE_INFINITY, nativeWindow ?? Number.POSITIVE_INFINITY)
1062
+ : undefined;
1063
+ let ds4AutoContextWindow;
1064
+ if (ds4Override !== undefined) {
1065
+ ds4AutoContextWindow = resolveDs4LaunchCtx({
1066
+ configured: config.ds4NumCtx,
1067
+ ramTieredCtx,
1068
+ catalogMaxCtx: ds4Source?.maxLaunchCtx,
1069
+ minViableContextTokens: contextFloor,
1070
+ });
1071
+ }
1072
+ // ds4's catalog residentBytes is an authored working set (resident
1073
+ // weights or expert cache + fixed weights + KV) measured at ONE window. Where
1074
+ // the entry also authors the per-token slope, re-base it onto the window
1075
+ // this device actually launches with and hand the UI the same
1076
+ // `fixed + slope × ctx` line llama.cpp/MLX rows carry, so the slider
1077
+ // prices a drag instead of claiming the footprint never moves. Entries
1078
+ // without a measured slope keep the flat number and say so.
1079
+ const { ds4ProjectedResidentBytes, ds4ResidentBytesForMode, ds4ResidentLine, shouldUseDs4SsdStreaming, } = await import('../ds4/residency.js');
1080
+ const ds4Line = ds4ResidentLine({
1081
+ residentBytes: ds4Source?.residentBytes,
1082
+ kvBytesPerToken: ds4Source?.kvBytesPerToken,
1083
+ residentCtxTokens: ds4Source?.residentCtxTokens,
1084
+ });
1085
+ const visionResidentBytes = await this.resolveDs4VisionResidentBytes(config, modelId, installed, ds4Source);
1086
+ const ssdStreaming = shouldUseDs4SsdStreaming({
1087
+ configured: config.ds4SsdStreaming,
1088
+ ...(ds4Source?.ssdStreamingSupported !== undefined
1089
+ ? { ssdStreamingSupported: ds4Source.ssdStreamingSupported }
1090
+ : {}),
1091
+ modelSizeBytes: ds4Source?.residentWeightBytes ??
1092
+ ds4Source?.approxSizeBytes ??
1093
+ installed?.approxSizeBytes,
1094
+ ...(visionResidentBytes > 0 ? { companionBytes: visionResidentBytes } : {}),
1095
+ });
1096
+ const plannedResidentBytes = ds4Line
1097
+ ? ds4ResidentBytesForMode(ds4ProjectedResidentBytes(ds4Line, effective), ssdStreaming, ds4Source?.ssdStreamingSupported) + visionResidentBytes
1098
+ : await this.resolveResidentBytes('ds4', modelId);
1099
+ return {
1100
+ contextWindow: useResidentOr(effective, Math.min(effective, ds4Floor)),
1101
+ plannedResidentBytes,
1102
+ ...(ds4Line
1103
+ ? {
1104
+ weightsResidentBytes: ds4ResidentBytesForMode(ds4Line.contextFreeBytes, ssdStreaming, ds4Source?.ssdStreamingSupported) + visionResidentBytes,
1105
+ kvFixedBytesPerSlot: 0,
1106
+ kvBytesPerTokenPerSlot: ds4Line.kvBytesPerToken,
1107
+ }
1108
+ : {}),
1109
+ ...(nativeWindow ? { nativeContextWindow: nativeWindow } : {}),
1110
+ ...(ds4Override !== undefined ? { overrideContextTokens: ds4Override } : {}),
1111
+ ...(ds4AutoContextWindow !== undefined ? { autoContextWindow: ds4AutoContextWindow } : {}),
1112
+ ...(ceilingTokens !== undefined && Number.isFinite(ceilingTokens)
1113
+ ? { contextCeilingTokens: ceilingTokens }
1114
+ : {}),
1115
+ };
1116
+ }
1117
+ const installed = await this.llamaCppModels?.resolveModel(modelId);
1118
+ if (!installed)
1119
+ throw new ModelNotInstalledError(name, modelId);
1120
+ // Charge the projector against memory only when the launch will actually
1121
+ // load it. Every estimate below used to pass `installed.mmprojSizeBytes`
1122
+ // unconditionally, which was harmless while the file only existed for
1123
+ // models that had opted in — but the projector now ships with the model,
1124
+ // so an unconditional charge would quietly tax every multimodal model
1125
+ // (~900MB on a 27B) including the ones deliberately running text-only.
1126
+ const visionBudgetBytes = mmprojBudgetBytes(installed.mmprojSizeBytes, !!installed.mmprojPath && nativeVisionEnabledFor(config.nativeVision, modelId));
1127
+ const envNumCtx = (() => {
1128
+ const raw = process.env.GEZEL_LLAMA_NUM_CTX;
1129
+ if (!raw)
1130
+ return undefined;
1131
+ const parsed = Number.parseInt(raw, 10);
1132
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
1133
+ })();
1134
+ const manifestEngineConfig = await resolveCatalogLlamaCppEngineConfig(this.catalog, modelId);
1135
+ const perModelCtxOverride = config.modelContextOverrides?.[`llama-cpp:${modelId}`];
1136
+ const explicitContextWindow = envNumCtx ?? perModelCtxOverride ?? config.llamaCppNumCtx;
1137
+ // A per-model override below the host floor is deliberate user intent —
1138
+ // lower the admission floor to the override instead of silently raising
1139
+ // the request back to 64K. Env / machine-wide values keep their
1140
+ // historical floor semantics. Mirrors buildLlamaCppProvider.
1141
+ const overrideActive = perModelCtxOverride !== undefined && explicitContextWindow === perModelCtxOverride;
1142
+ const minViableTokens = overrideActive
1143
+ ? Math.min(contextFloor, perModelCtxOverride)
1144
+ : contextFloor;
1145
+ const contextRequirement = resolveLlamaCppContextRequirement({
1146
+ modelContextWindow: installed.contextWindow,
1147
+ minViableContextTokens: minViableTokens,
1148
+ ...(explicitContextWindow !== undefined ? { explicitContextWindow } : {}),
1149
+ ...(manifestEngineConfig?.contextSize !== undefined
1150
+ ? {
1151
+ adaptiveContextWindow: manifestEngineConfig.contextSize,
1152
+ manifestContextSize: manifestEngineConfig.contextSize,
1153
+ }
1154
+ : {}),
1155
+ contextSizing: config.llamaCppContextSizing ?? 'adaptive',
1156
+ });
1157
+ const effectiveNumCtx = contextRequirement.requestedPerTurnCtxTokens;
1158
+ // Resident/env short-circuits still want a footprint estimate, which
1159
+ // needs the header read below — the return moves after it. An active
1160
+ // per-model override deliberately does NOT short-circuit on a resident
1161
+ // engine: the full plan must run so a stale resident window surfaces as
1162
+ // restart-required instead of masquerading as the applied setting.
1163
+ const shortCircuit = (residentContextWindow !== undefined && !overrideActive) || envNumCtx !== undefined;
1164
+ const { defaultLocalEngineSlots, estimatePerSlotKvBytes, kvQuantScale, llamaCppSlotCeiling, planAdaptiveContextGrowth, planCtxTokensForMemory, plannedLocalEngineSlots, } = await import('./capacity-broker.js');
1165
+ const capacity = await this.previewCapacityInputs('llama-cpp', modelId, capacityOpts);
1166
+ const { budgetBytes: admissionBudgetBytes, fastBudgetBytes, committedOtherBytes } = capacity;
1167
+ const configuredSlots = config.providerConcurrency?.['llama-cpp'];
1168
+ const kvCacheType = resolveLlamaCppKvCacheType({
1169
+ architecture: installed.architecture,
1170
+ modelId,
1171
+ override: config.llamaCppKvCacheType,
1172
+ });
1173
+ // Header-exact per-slot KV for the slot ceiling (M2); the
1174
+ // weights-scaled heuristic only when the GGUF is unreadable. Tensor sizes
1175
+ // also expose Qwen/Gemma's v0.4 lazy embedding range, which must not be
1176
+ // advertised as resident RAM/VRAM in the Settings preview.
1177
+ let summary = null;
1178
+ try {
1179
+ summary = await readGgufSummaryAsync(installed.weightsPath, { includeTensorSizes: true });
1180
+ }
1181
+ catch {
1182
+ summary = null;
1183
+ }
1184
+ const lazyTensorBytes = summary
1185
+ ? effectiveLazyTensorBytes(summary, config.llamaCppLazyMode ?? manifestEngineConfig?.lazyMode ?? 'auto')
1186
+ : 0;
1187
+ const residentWeightFileBytes = Math.max(0, installed.approxSizeBytes - lazyTensorBytes);
1188
+ const residentWeightsBytes = estimateLlamaCppResidentBytes(residentWeightFileBytes, {
1189
+ mmprojBytes: visionBudgetBytes,
1190
+ });
1191
+ const exactPerSlotKvF16 = summary
1192
+ ? estimateExactPerSlotKvBytesF16({
1193
+ blockCount: summary.blockCount,
1194
+ embeddingLength: summary.embeddingLength,
1195
+ headCount: summary.headCount,
1196
+ headCountKv: summary.headCountKv,
1197
+ headCountKvPerLayer: summary.headCountKvPerLayer,
1198
+ slidingWindow: summary.slidingWindow,
1199
+ slidingWindowPattern: summary.slidingWindowPattern,
1200
+ sharedKvLayers: summary.sharedKvLayers,
1201
+ loopCount: summary.loopCount,
1202
+ keyLength: summary.keyLength,
1203
+ valueLength: summary.valueLength,
1204
+ keyLengthSwa: summary.keyLengthSwa,
1205
+ valueLengthSwa: summary.valueLengthSwa,
1206
+ fullAttentionInterval: summary.fullAttentionInterval,
1207
+ ssmInnerSize: summary.ssmInnerSize,
1208
+ ssmStateSize: summary.ssmStateSize,
1209
+ ssmConvKernel: summary.ssmConvKernel,
1210
+ }, effectiveNumCtx)
1211
+ : undefined;
1212
+ // Weights + KV at a given window/slot count. Two figures, because they
1213
+ // answer different questions: `single` is what one chat costs (the
1214
+ // models-list headline), `reserved` is what the broker holds for the
1215
+ // whole slot fleet (the launch path's reservation math).
1216
+ const plannedFor = (ctx, slotCount, kv) => {
1217
+ if (!summary)
1218
+ return undefined;
1219
+ const perSlotF16 = estimateExactPerSlotKvBytesF16({
1220
+ blockCount: summary.blockCount,
1221
+ embeddingLength: summary.embeddingLength,
1222
+ headCount: summary.headCount,
1223
+ headCountKv: summary.headCountKv,
1224
+ headCountKvPerLayer: summary.headCountKvPerLayer,
1225
+ slidingWindow: summary.slidingWindow,
1226
+ slidingWindowPattern: summary.slidingWindowPattern,
1227
+ sharedKvLayers: summary.sharedKvLayers,
1228
+ loopCount: summary.loopCount,
1229
+ keyLength: summary.keyLength,
1230
+ valueLength: summary.valueLength,
1231
+ keyLengthSwa: summary.keyLengthSwa,
1232
+ valueLengthSwa: summary.valueLengthSwa,
1233
+ fullAttentionInterval: summary.fullAttentionInterval,
1234
+ ssmInnerSize: summary.ssmInnerSize,
1235
+ ssmStateSize: summary.ssmStateSize,
1236
+ ssmConvKernel: summary.ssmConvKernel,
1237
+ }, ctx);
1238
+ if (perSlotF16 === undefined)
1239
+ return undefined;
1240
+ const perSlotBytes = perSlotF16 * kvQuantScale(kv);
1241
+ return {
1242
+ single: Math.round(residentWeightsBytes + perSlotBytes),
1243
+ reserved: Math.round(residentWeightsBytes + perSlotBytes * slotCount),
1244
+ slots: slotCount,
1245
+ };
1246
+ };
1247
+ // Post-quant single-slot KV linearization for the UI's live slider
1248
+ // estimate. Two-point sampling stays exact for full-attention models
1249
+ // and matches the windowed/hybrid piecewise slope everywhere above the
1250
+ // sliding window — the slider's 32K floor clears every real window.
1251
+ const kvLinearizationFor = (kv) => {
1252
+ if (!summary)
1253
+ return undefined;
1254
+ const geometry = {
1255
+ blockCount: summary.blockCount,
1256
+ embeddingLength: summary.embeddingLength,
1257
+ headCount: summary.headCount,
1258
+ headCountKv: summary.headCountKv,
1259
+ headCountKvPerLayer: summary.headCountKvPerLayer,
1260
+ slidingWindow: summary.slidingWindow,
1261
+ slidingWindowPattern: summary.slidingWindowPattern,
1262
+ sharedKvLayers: summary.sharedKvLayers,
1263
+ loopCount: summary.loopCount,
1264
+ keyLength: summary.keyLength,
1265
+ valueLength: summary.valueLength,
1266
+ keyLengthSwa: summary.keyLengthSwa,
1267
+ valueLengthSwa: summary.valueLengthSwa,
1268
+ fullAttentionInterval: summary.fullAttentionInterval,
1269
+ ssmInnerSize: summary.ssmInnerSize,
1270
+ ssmStateSize: summary.ssmStateSize,
1271
+ ssmConvKernel: summary.ssmConvKernel,
1272
+ };
1273
+ const a = estimateExactPerSlotKvBytesF16(geometry, 8_192);
1274
+ const b = estimateExactPerSlotKvBytesF16(geometry, 65_536);
1275
+ if (a === undefined || b === undefined)
1276
+ return undefined;
1277
+ const scale = kvQuantScale(kv);
1278
+ const bytesPerToken = ((b - a) / (65_536 - 8_192)) * scale;
1279
+ return { bytesPerToken, fixedBytes: Math.max(0, a * scale - bytesPerToken * 8_192) };
1280
+ };
1281
+ const ceilingAt = (ctx, kv) => llamaCppSlotCeiling({
1282
+ budgetBytes: fastBudgetBytes,
1283
+ sizingBudgetBytes: capacity.concurrencySizingBytes,
1284
+ weightsBytes: residentWeightFileBytes,
1285
+ perTurnCtxTokens: ctx,
1286
+ kvCacheType: kv,
1287
+ committedOtherBytes,
1288
+ ...(exactPerSlotKvF16 !== undefined ? { exactPerSlotKvBytesF16: exactPerSlotKvF16 } : {}),
1289
+ });
1290
+ if (shortCircuit) {
1291
+ const contextWindow = useResidentOr(effectiveNumCtx, contextRequirement.minimumPerTurnCtxTokens);
1292
+ // Memory-aware slot count, same as the main path below. The raw tier
1293
+ // default is what a launch would *like*; on a constrained host the
1294
+ // ceiling is what it can actually have, and quoting the former made
1295
+ // this branch advertise reservations the broker would never admit.
1296
+ const planned = plannedFor(contextWindow, plannedLocalEngineSlots({
1297
+ configuredSlots,
1298
+ ceiling: ceilingAt(contextWindow, kvCacheType),
1299
+ tierDefault: defaultLocalEngineSlots(fastBudgetBytes),
1300
+ }), kvCacheType);
1301
+ const lin = kvLinearizationFor(kvCacheType);
1302
+ return {
1303
+ contextWindow,
1304
+ ...(planned !== undefined
1305
+ ? {
1306
+ plannedResidentBytes: planned.single,
1307
+ reservedResidentBytes: planned.reserved,
1308
+ plannedSlots: planned.slots,
1309
+ weightsResidentBytes: residentWeightsBytes,
1310
+ }
1311
+ : {}),
1312
+ ...(installed.contextWindow ? { nativeContextWindow: installed.contextWindow } : {}),
1313
+ ...(perModelCtxOverride !== undefined
1314
+ ? { overrideContextTokens: perModelCtxOverride }
1315
+ : {}),
1316
+ ...(lin !== undefined
1317
+ ? { kvBytesPerTokenPerSlot: lin.bytesPerToken, kvFixedBytesPerSlot: lin.fixedBytes }
1318
+ : {}),
1319
+ };
1320
+ }
1321
+ // One planning pass: policy resolution → KV/slot plan → admission
1322
+ // ladder → windowed re-plan → adaptive growth, mirroring
1323
+ // buildLlamaCppProvider. Runs once for the live preview and — while a
1324
+ // per-model override is active — a second time with the override
1325
+ // ignored, so the slider can mark where "Automatic" lands right now.
1326
+ const llamaPlanPass = (explicitArg, minViableArg) => {
1327
+ const requirement = resolveLlamaCppContextRequirement({
1328
+ modelContextWindow: installed.contextWindow,
1329
+ minViableContextTokens: minViableArg,
1330
+ ...(explicitArg !== undefined ? { explicitContextWindow: explicitArg } : {}),
1331
+ ...(manifestEngineConfig?.contextSize !== undefined
1332
+ ? {
1333
+ adaptiveContextWindow: manifestEngineConfig.contextSize,
1334
+ manifestContextSize: manifestEngineConfig.contextSize,
1335
+ }
1336
+ : {}),
1337
+ contextSizing: config.llamaCppContextSizing ?? 'adaptive',
1338
+ });
1339
+ let grantedCtx = requirement.requestedPerTurnCtxTokens;
1340
+ let kv = resolveLlamaCppKvCacheType({
1341
+ architecture: installed.architecture,
1342
+ modelId,
1343
+ override: config.llamaCppKvCacheType,
1344
+ });
1345
+ // Per-pass exact KV at this pass's requested window — the auto pass
1346
+ // may request a different window than the primary one, and a slot
1347
+ // ceiling fed with the other pass's bytes skews the marker.
1348
+ const exactAtRequested = summary
1349
+ ? estimateExactPerSlotKvBytesF16({
1350
+ blockCount: summary.blockCount,
1351
+ embeddingLength: summary.embeddingLength,
1352
+ headCount: summary.headCount,
1353
+ headCountKv: summary.headCountKv,
1354
+ headCountKvPerLayer: summary.headCountKvPerLayer,
1355
+ slidingWindow: summary.slidingWindow,
1356
+ slidingWindowPattern: summary.slidingWindowPattern,
1357
+ sharedKvLayers: summary.sharedKvLayers,
1358
+ loopCount: summary.loopCount,
1359
+ keyLength: summary.keyLength,
1360
+ valueLength: summary.valueLength,
1361
+ keyLengthSwa: summary.keyLengthSwa,
1362
+ valueLengthSwa: summary.valueLengthSwa,
1363
+ fullAttentionInterval: summary.fullAttentionInterval,
1364
+ ssmInnerSize: summary.ssmInnerSize,
1365
+ ssmStateSize: summary.ssmStateSize,
1366
+ ssmConvKernel: summary.ssmConvKernel,
1367
+ }, grantedCtx)
1368
+ : undefined;
1369
+ const passPlanCtx = grantedCtx;
1370
+ const passCeiling = (kvType, ctxTokens) => llamaCppSlotCeiling({
1371
+ budgetBytes: fastBudgetBytes,
1372
+ sizingBudgetBytes: capacity.concurrencySizingBytes,
1373
+ weightsBytes: residentWeightFileBytes,
1374
+ perTurnCtxTokens: ctxTokens,
1375
+ kvCacheType: kvType,
1376
+ committedOtherBytes,
1377
+ ...(exactAtRequested !== undefined
1378
+ ? { exactPerSlotKvBytesF16: (exactAtRequested * ctxTokens) / passPlanCtx }
1379
+ : {}),
1380
+ });
1381
+ // One pricing for a candidate KV dtype, shared by the plan's fit gate
1382
+ // and by the admission below — a second copy is how a preview starts
1383
+ // promising a window the launch then denies.
1384
+ const referenceCtx = 4096;
1385
+ const exactKvAtReferenceFor = (kvType) => summary
1386
+ ? estimateKvReserveBytes({
1387
+ blockCount: summary.blockCount,
1388
+ embeddingLength: summary.embeddingLength,
1389
+ headCount: summary.headCount,
1390
+ headCountKv: summary.headCountKv,
1391
+ headCountKvPerLayer: summary.headCountKvPerLayer,
1392
+ slidingWindowPattern: summary.slidingWindowPattern,
1393
+ sharedKvLayers: summary.sharedKvLayers,
1394
+ loopCount: summary.loopCount,
1395
+ keyLength: summary.keyLength,
1396
+ valueLength: summary.valueLength,
1397
+ keyLengthSwa: summary.keyLengthSwa,
1398
+ valueLengthSwa: summary.valueLengthSwa,
1399
+ fullAttentionInterval: summary.fullAttentionInterval,
1400
+ ssmInnerSize: summary.ssmInnerSize,
1401
+ ssmStateSize: summary.ssmStateSize,
1402
+ ssmConvKernel: summary.ssmConvKernel,
1403
+ ctxTokens: referenceCtx,
1404
+ kvCacheType: kvType,
1405
+ })
1406
+ : undefined;
1407
+ const kvBytesPerTokenFor = (kvType) => {
1408
+ const exact = exactKvAtReferenceFor(kvType);
1409
+ return exact !== undefined
1410
+ ? exact / referenceCtx
1411
+ : estimatePerSlotKvBytes({
1412
+ perTurnCtxTokens: referenceCtx,
1413
+ weightsBytes: residentWeightFileBytes,
1414
+ kvCacheType: kvType,
1415
+ }) / referenceCtx;
1416
+ };
1417
+ const planFitsAt = (kvType, ctxTokens, slotCount) => {
1418
+ // `minimumPerTurnCtxTokens: ctxTokens` makes this ask for the WHOLE
1419
+ // window — a plan admission would only accept by clamping does not
1420
+ // count as a fit, which is exactly the case q8_0 has to rescue.
1421
+ const probe = planCtxTokensForMemory({
1422
+ requestedPerTurnCtxTokens: ctxTokens,
1423
+ slots: slotCount,
1424
+ minimumPerTurnCtxTokens: ctxTokens,
1425
+ kvBytesPerToken: kvBytesPerTokenFor(kvType),
1426
+ weightsResidentBytes: residentWeightsBytes,
1427
+ budgetBytes: admissionBudgetBytes,
1428
+ committedOtherBytes,
1429
+ ...(capacity.freeSystemRamBytes !== undefined
1430
+ ? { freeSystemRamBytes: capacity.freeSystemRamBytes }
1431
+ : {}),
1432
+ vramBytes: capacity.vramBytes,
1433
+ });
1434
+ return probe.minimumSatisfied && probe.slots >= slotCount;
1435
+ };
1436
+ const kvPlan = planLlamaCppKv({
1437
+ architecture: installed.architecture,
1438
+ modelId,
1439
+ override: config.llamaCppKvCacheType,
1440
+ slotsConfigured: configuredSlots !== undefined,
1441
+ ...(configuredSlots !== undefined ? { configuredSlots } : {}),
1442
+ requestedCtxTokens: grantedCtx,
1443
+ minimumCtxTokens: requirement.minimumPerTurnCtxTokens,
1444
+ ctxConfigured: explicitArg !== undefined || (config.llamaCppContextSizing ?? 'adaptive') === 'model-max',
1445
+ ceilingFor: passCeiling,
1446
+ fitsAt: planFitsAt,
1447
+ maxSlots: defaultLocalEngineSlots(fastBudgetBytes),
1448
+ });
1449
+ kv = kvPlan.kvCacheType;
1450
+ // Mirror the launch: the f16-by-context-cap trade shrinks the granted
1451
+ // window here too, so the settings preview shows what will really run.
1452
+ if (kvPlan.ctxCapTokens !== undefined && kvPlan.ctxCapTokens < grantedCtx) {
1453
+ grantedCtx = kvPlan.ctxCapTokens;
1454
+ }
1455
+ let slots = plannedLocalEngineSlots({
1456
+ configuredSlots,
1457
+ ceiling: passCeiling(kv, grantedCtx),
1458
+ tierDefault: defaultLocalEngineSlots(fastBudgetBytes),
1459
+ });
1460
+ if ((config.llamaCppSpecType ?? manifestEngineConfig?.spec?.type) === 'draft-mtp')
1461
+ slots = 1;
1462
+ try {
1463
+ if (!summary)
1464
+ throw new Error('GGUF header unreadable');
1465
+ const exactKvAtReference = exactKvAtReferenceFor(kv);
1466
+ const kvBytesPerToken = kvBytesPerTokenFor(kv);
1467
+ // The linearization the accepted plan priced with, so the growth
1468
+ // pass cannot disagree with admission about the same launch.
1469
+ let ladderKvLinearization = { bytesPerToken: kvBytesPerToken, fixedPerSlotBytes: 0 };
1470
+ let admission = planCtxTokensForMemory({
1471
+ requestedPerTurnCtxTokens: grantedCtx,
1472
+ slots,
1473
+ minimumPerTurnCtxTokens: requirement.minimumPerTurnCtxTokens,
1474
+ kvBytesPerToken,
1475
+ weightsResidentBytes: residentWeightsBytes,
1476
+ budgetBytes: admissionBudgetBytes,
1477
+ committedOtherBytes,
1478
+ ...(capacity.freeSystemRamBytes !== undefined
1479
+ ? { freeSystemRamBytes: capacity.freeSystemRamBytes }
1480
+ : {}),
1481
+ vramBytes: capacity.vramBytes,
1482
+ });
1483
+ // Mirror the launch path's windowed-cache admission (see
1484
+ // buildLlamaCppProvider): when the launch will decline the Gemma
1485
+ // `--swa-full` auto-default (or the windowed cache is pinned), the
1486
+ // full-attention plan above overstates the real allocation — re-plan
1487
+ // with the windowed linearization so the previewed window matches
1488
+ // what the engine will actually grant.
1489
+ // Strict model-max deliberately does NOT gate this: for SWA models
1490
+ // the windowed cache is the only layout whose native-window KV can
1491
+ // fit real machines, and the strict minimum rides inside
1492
+ // `requirement.minimumPerTurnCtxTokens`, so the windowed
1493
+ // re-plan sheds slots or denies but never shortens the window.
1494
+ const explicitSwaFull = config.llamaCppSwaFull ?? manifestEngineConfig?.swaFull;
1495
+ const windowedCacheWillRun = (!admission.minimumSatisfied || admission.clamped || admission.slots < slots) &&
1496
+ (explicitSwaFull === false ||
1497
+ (explicitSwaFull === undefined &&
1498
+ isGemmaModel({ architecture: installed.architecture, modelId })));
1499
+ if (windowedCacheWillRun) {
1500
+ const windowed = estimateWindowedKvLinearization({
1501
+ blockCount: summary.blockCount,
1502
+ embeddingLength: summary.embeddingLength,
1503
+ headCount: summary.headCount,
1504
+ headCountKv: summary.headCountKv,
1505
+ headCountKvPerLayer: summary.headCountKvPerLayer,
1506
+ slidingWindow: summary.slidingWindow,
1507
+ slidingWindowPattern: summary.slidingWindowPattern,
1508
+ sharedKvLayers: summary.sharedKvLayers,
1509
+ loopCount: summary.loopCount,
1510
+ keyLength: summary.keyLength,
1511
+ valueLength: summary.valueLength,
1512
+ keyLengthSwa: summary.keyLengthSwa,
1513
+ valueLengthSwa: summary.valueLengthSwa,
1514
+ fullAttentionInterval: summary.fullAttentionInterval,
1515
+ ssmInnerSize: summary.ssmInnerSize,
1516
+ ssmStateSize: summary.ssmStateSize,
1517
+ ssmConvKernel: summary.ssmConvKernel,
1518
+ kvCacheType: kv,
1519
+ });
1520
+ if (windowed) {
1521
+ admission = planCtxTokensForMemory({
1522
+ requestedPerTurnCtxTokens: grantedCtx,
1523
+ slots,
1524
+ minimumPerTurnCtxTokens: requirement.minimumPerTurnCtxTokens,
1525
+ kvBytesPerToken: windowed.bytesPerToken,
1526
+ weightsResidentBytes: residentWeightsBytes + windowed.fixedBytes * slots,
1527
+ budgetBytes: admissionBudgetBytes,
1528
+ committedOtherBytes,
1529
+ ...(capacity.freeSystemRamBytes !== undefined
1530
+ ? { freeSystemRamBytes: capacity.freeSystemRamBytes }
1531
+ : {}),
1532
+ vramBytes: capacity.vramBytes,
1533
+ });
1534
+ ladderKvLinearization = {
1535
+ bytesPerToken: windowed.bytesPerToken,
1536
+ fixedPerSlotBytes: windowed.fixedBytes,
1537
+ };
1538
+ }
1539
+ else if ((summary.slidingWindow ?? 0) > 0 || explicitSwaFull === undefined) {
1540
+ // SWA model without a readable layout: the launch path leaves
1541
+ // such a launch untouched — preview the requested window.
1542
+ return { grantedCtx, slots, kvCacheType: kv, plannedFieldsOk: false };
1543
+ }
1544
+ }
1545
+ if (!admission.minimumSatisfied) {
1546
+ throw new CapacityDeniedError(NOT_ENOUGH_MEMORY_MESSAGE);
1547
+ }
1548
+ slots = admission.slots;
1549
+ grantedCtx = admission.perTurnCtxTokens;
1550
+ // ── Adaptive context growth ── mirror of buildLlamaCppProvider:
1551
+ // slots and the base grant are settled; spend leftover FAST memory
1552
+ // on a longer window up to the resolver's target. Exact GGUF
1553
+ // geometry only.
1554
+ if (requirement.growthTargetTokens !== undefined &&
1555
+ ladderKvLinearization !== null &&
1556
+ exactKvAtReference !== undefined) {
1557
+ const growth = planAdaptiveContextGrowth({
1558
+ basePerTurnCtxTokens: grantedCtx,
1559
+ targetPerTurnCtxTokens: requirement.growthTargetTokens,
1560
+ slots,
1561
+ kvBytesPerToken: ladderKvLinearization.bytesPerToken,
1562
+ kvFixedPerSlotBytes: ladderKvLinearization.fixedPerSlotBytes,
1563
+ weightsResidentBytes: residentWeightsBytes,
1564
+ fastBudgetBytes,
1565
+ committedOtherBytes,
1566
+ budgetKind: capacity.budgetKind,
1567
+ vramBytes: capacity.vramBytes,
1568
+ ...(capacity.freeSystemRamBytes !== undefined
1569
+ ? { freeSystemRamBytes: capacity.freeSystemRamBytes }
1570
+ : {}),
1571
+ isMoE: (summary.expertCount ?? 0) > 1,
1572
+ // A user-chosen lane count is not growth's to spend.
1573
+ allowSlotTrade: configuredSlots === undefined,
1574
+ });
1575
+ if (growth.grown) {
1576
+ grantedCtx = growth.perTurnCtxTokens;
1577
+ slots = growth.slots;
1578
+ }
1579
+ }
1580
+ }
1581
+ catch (error) {
1582
+ if (error instanceof CapacityDeniedError)
1583
+ throw error;
1584
+ log.warn(`[llama-cpp] could not inspect ${modelId} while previewing admission: ${error instanceof Error ? error.message : String(error)}`);
1585
+ }
1586
+ return { grantedCtx, slots, kvCacheType: kv, plannedFieldsOk: true };
1587
+ };
1588
+ const plan = llamaPlanPass(explicitContextWindow, minViableTokens);
1589
+ let autoContextWindow;
1590
+ if (overrideActive) {
1591
+ try {
1592
+ autoContextWindow = llamaPlanPass(config.llamaCppNumCtx, contextFloor).grantedCtx;
1593
+ }
1594
+ catch {
1595
+ // Automatic sizing may not fit where a smaller override does — no marker.
1596
+ }
1597
+ }
1598
+ // A resident engine holding a different window than a freshly-set
1599
+ // override keeps its launch window until restart; surface that as
1600
+ // restart-required instead of quietly showing the stale window as if
1601
+ // the setting had applied.
1602
+ if (overrideActive &&
1603
+ residentContextWindow !== undefined &&
1604
+ residentContextWindow !== plan.grantedCtx) {
1605
+ throw new CapacityDeniedError(`${modelId} is running with ${residentContextWindow.toLocaleString('en-US')} context tokens per turn, but its custom context setting now resolves to ${plan.grantedCtx.toLocaleString('en-US')}. Restart the local engine to apply it.`, { reason: 'resident-below-minimum' });
1606
+ }
1607
+ const planned = plan.plannedFieldsOk
1608
+ ? plannedFor(plan.grantedCtx, plan.slots, plan.kvCacheType)
1609
+ : undefined;
1610
+ const lin = plan.plannedFieldsOk ? kvLinearizationFor(plan.kvCacheType) : undefined;
1611
+ return {
1612
+ contextWindow: plan.grantedCtx,
1613
+ ...(planned !== undefined
1614
+ ? {
1615
+ plannedResidentBytes: planned.single,
1616
+ reservedResidentBytes: planned.reserved,
1617
+ plannedSlots: planned.slots,
1618
+ weightsResidentBytes: residentWeightsBytes,
1619
+ }
1620
+ : {}),
1621
+ ...(installed.contextWindow ? { nativeContextWindow: installed.contextWindow } : {}),
1622
+ ...(perModelCtxOverride !== undefined ? { overrideContextTokens: perModelCtxOverride } : {}),
1623
+ ...(autoContextWindow !== undefined ? { autoContextWindow } : {}),
1624
+ ...(lin !== undefined
1625
+ ? { kvBytesPerTokenPerSlot: lin.bytesPerToken, kvFixedBytesPerSlot: lin.fixedBytes }
1626
+ : {}),
1627
+ };
1628
+ }
1629
+ /**
1630
+ * Cancel a pending provider-queue entry by (provider, id). Resolves
1631
+ * the queue the SAME two ways {@link localEngineQueueSummaries} +
1632
+ * `/api/queues` surface it: the singleton `providers` map first
1633
+ * (cloud providers, seeded test mocks), then the engine pool for
1634
+ * pool-routed local engines whose queue the singleton never sees.
1635
+ * Returns true when an entry was removed, false when the id is
1636
+ * unknown (already running, already cancelled, or no such provider).
1637
+ */
1638
+ cancelProviderQueueItem(name, id) {
1639
+ if (this.getProviderIfReady(name)?.queue?.cancelPending(id))
1640
+ return true;
1641
+ const router = this.engineRouter ?? this.engineRouterCache;
1642
+ return router ? router.pool.cancelPendingQueueItem(name, id) : false;
1643
+ }
1644
+ /** Reorder a pending provider-queue entry. Same singleton-then-pool
1645
+ * resolution as {@link cancelProviderQueueItem}. */
1646
+ moveProviderQueueItem(name, id, direction) {
1647
+ if (this.getProviderIfReady(name)?.queue?.movePending(id, direction))
1648
+ return true;
1649
+ const router = this.engineRouter ?? this.engineRouterCache;
1650
+ return router ? router.pool.movePendingQueueItem(name, id, direction) : false;
1651
+ }
1652
+ sessionsPerEngineKey() {
1653
+ return new Map();
1654
+ }
1655
+ async bindLocalReplica(router, name, modelId, opts) {
1656
+ // Pre-populate the bytes cache so the router's sync resolver
1657
+ // hits on the first ensure.
1658
+ await this.resolveResidentBytes(name, modelId);
1659
+ // Tally active sessions per engine key for load-balanced bind.
1660
+ const sessionsPerKey = this.sessionsPerEngineKey();
1661
+ return router.bindForSession(name, modelId, {
1662
+ sessionId: opts.sessionId,
1663
+ sessionsPerKey,
1664
+ ...(opts.engineDrainWaitMs !== undefined ? { drainWaitMs: opts.engineDrainWaitMs } : {}),
1665
+ ...(opts.signal ? { signal: opts.signal } : {}),
1666
+ ...(opts.onDrainWait ? { onDrainWait: opts.onDrainWait } : {}),
1667
+ }, opts.priorEngineKey);
1668
+ }
1669
+ async getLocalProviderForModel(name, modelId, opts, fallback) {
1670
+ const seeded = this.providers.get(name);
1671
+ if (seeded)
1672
+ return seeded;
1673
+ const router = await this.getEngineRouter();
1674
+ if (!router)
1675
+ return fallback();
1676
+ const config = await this.store.readConfig();
1677
+ const resolved = modelId ?? config.defaultModel?.[name];
1678
+ if (!resolved)
1679
+ return fallback();
1680
+ const installed = name === 'llama-cpp'
1681
+ ? await this.llamaCppModels?.resolveModel(resolved)
1682
+ : name === 'ds4'
1683
+ ? // ds4 v1 also resolves weights OUTSIDE the model manager — an
1684
+ // explicit gguf path (GEZEL_DS4_MODEL / config.ds4ModelPath) or
1685
+ // an external server (GEZEL_DS4_SERVER_URL / config.ds4BaseUrl).
1686
+ // `buildDs4Provider` handles those directly, so don't gate the
1687
+ // pool on the store: falling back to the singleton here spawns
1688
+ // a SECOND supervisor for a server that's already running, and
1689
+ // ds4-server's single-instance lock refuses it — every ds4
1690
+ // one-shot (summaries, meester-status, extraction) then fails
1691
+ // with "another ds4 process is already running" (wild-caught
1692
+ // by validate-ambient-gate on an env-path daemon).
1693
+ ((await this.ds4Models?.resolveModel(resolved)) ??
1694
+ (process.env.GEZEL_DS4_MODEL ||
1695
+ process.env.GEZEL_DS4_SERVER_URL ||
1696
+ config.ds4ModelPath ||
1697
+ config.ds4BaseUrl
1698
+ ? { explicitSource: true }
1699
+ : undefined))
1700
+ : await this.mlxModels?.resolveModel(resolved);
1701
+ if (!installed) {
1702
+ throw new ModelNotInstalledError(name, resolved);
1703
+ }
1704
+ const { provider } = await this.bindLocalReplica(router, name, resolved, {
1705
+ // Synthetic id — one-shot requests have no session record; the
1706
+ // bind still load-balances across resident replicas.
1707
+ sessionId: `v1:${randomUUID()}`,
1708
+ ...(opts.engineDrainWaitMs !== undefined
1709
+ ? { engineDrainWaitMs: opts.engineDrainWaitMs }
1710
+ : {}),
1711
+ });
1712
+ return provider;
1713
+ }
1714
+ }