@bendyline/gezel-inference 0.0.0-stage → 1.0.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.
- package/LICENSE +21 -0
- package/README.md +13 -2
- package/dist/cache/adapter.d.ts +115 -0
- package/dist/cache/adapter.js +23 -0
- package/dist/cache/budget.d.ts +15 -0
- package/dist/cache/budget.js +31 -0
- package/dist/cache/controller.d.ts +205 -0
- package/dist/cache/controller.js +377 -0
- package/dist/catalog/LICENSE +21 -0
- package/dist/catalog/chat-models/bt/btl4-35b-q4/manifest.json +146 -0
- package/dist/catalog/chat-models/bt/btl4-35b-q4/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/chat-models/bt/btl4-35b-q4/versions/1.0.1/manifest.json +15 -0
- package/dist/catalog/chat-models/bt/btl4-compact-iq2/manifest.json +146 -0
- package/dist/catalog/chat-models/bt/btl4-compact-iq2/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/chat-models/bt/btl4-compact-iq2/versions/1.0.1/manifest.json +15 -0
- package/dist/catalog/chat-models/bt/btl4-compact-iq2/versions/1.0.2/manifest.json +15 -0
- package/dist/catalog/chat-models/de/deepseek-r1-8b-q4/manifest.json +166 -0
- package/dist/catalog/chat-models/de/deepseek-r1-8b-q4/versions/1.1.0/manifest.json +62 -0
- package/dist/catalog/chat-models/de/deepseek-r1-8b-q4/versions/1.1.1/manifest.json +61 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-mxfp4/manifest.json +125 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-mxfp4/versions/1.0.0/manifest.json +27 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2/manifest.json +125 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2/versions/1.0.0/manifest.json +27 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2/versions/1.1.0/manifest.json +27 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2q4/manifest.json +126 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q2q4/versions/1.0.0/manifest.json +27 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q4/manifest.json +318 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q4/versions/1.0.0/manifest.json +225 -0
- package/dist/catalog/chat-models/de/deepseek-v4-flash-284b-q4/versions/1.1.0/manifest.json +225 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q4/manifest.json +249 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.0.0/manifest.json +70 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.1.0/manifest.json +72 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.1.2/manifest.json +78 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.1.3/manifest.json +78 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q4/versions/1.2.0/manifest.json +98 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q8/manifest.json +228 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q8/versions/1.0.0/manifest.json +72 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q8/versions/1.0.2/manifest.json +78 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q8/versions/1.0.3/manifest.json +78 -0
- package/dist/catalog/chat-models/ge/gemma4-12b-q8/versions/1.1.0/manifest.json +78 -0
- package/dist/catalog/chat-models/ge/gemma4-26b-q4/manifest.json +220 -0
- package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.1.0/manifest.json +75 -0
- package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.2.0/manifest.json +75 -0
- package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.2.1/manifest.json +80 -0
- package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.2.2/manifest.json +80 -0
- package/dist/catalog/chat-models/ge/gemma4-26b-q4/versions/1.3.0/manifest.json +81 -0
- package/dist/catalog/chat-models/ge/gemma4-31b-q4/manifest.json +226 -0
- package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.1.0/manifest.json +80 -0
- package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.1.1/manifest.json +82 -0
- package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.2.0/manifest.json +82 -0
- package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.2.1/manifest.json +95 -0
- package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.2.2/manifest.json +95 -0
- package/dist/catalog/chat-models/ge/gemma4-31b-q4/versions/1.3.0/manifest.json +86 -0
- package/dist/catalog/chat-models/ge/gemma4-e2b-q4/manifest.json +213 -0
- package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.1.0/manifest.json +67 -0
- package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.1.2/manifest.json +75 -0
- package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.2.0/manifest.json +71 -0
- package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.2.1/manifest.json +71 -0
- package/dist/catalog/chat-models/ge/gemma4-e2b-q4/versions/1.3.0/manifest.json +71 -0
- package/dist/catalog/chat-models/ge/gemma4-e4b-q4/manifest.json +205 -0
- package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.1.0/manifest.json +72 -0
- package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.1.2/manifest.json +75 -0
- package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.2.0/manifest.json +76 -0
- package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.2.1/manifest.json +76 -0
- package/dist/catalog/chat-models/ge/gemma4-e4b-q4/versions/1.3.0/manifest.json +76 -0
- package/dist/catalog/chat-models/gl/glm-5.2-754b-q2/manifest.json +127 -0
- package/dist/catalog/chat-models/gl/glm-5.2-754b-q2/versions/1.0.0/manifest.json +20 -0
- package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/manifest.json +140 -0
- package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/versions/1.0.0/manifest.json +23 -0
- package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/versions/1.0.1/manifest.json +26 -0
- package/dist/catalog/chat-models/gp/gpt-oss-120b-q4/manifest.json +247 -0
- package/dist/catalog/chat-models/gp/gpt-oss-120b-q4/versions/1.0.0/manifest.json +137 -0
- package/dist/catalog/chat-models/gp/gpt-oss-120b-q4/versions/1.1.0/manifest.json +135 -0
- package/dist/catalog/chat-models/gp/gpt-oss-20b-q4/manifest.json +195 -0
- package/dist/catalog/chat-models/gp/gpt-oss-20b-q4/versions/1.1.0/manifest.json +72 -0
- package/dist/catalog/chat-models/gp/gpt-oss-20b-q4/versions/1.1.1/manifest.json +71 -0
- package/dist/catalog/chat-models/gr/granite4.2-30b-q4/manifest.json +200 -0
- package/dist/catalog/chat-models/gr/granite4.2-30b-q4/versions/1.0.0/manifest.json +72 -0
- package/dist/catalog/chat-models/gr/granite4.2-3b-q4/manifest.json +196 -0
- package/dist/catalog/chat-models/gr/granite4.2-3b-q4/versions/1.0.0/manifest.json +57 -0
- package/dist/catalog/chat-models/gr/granite4.2-8b-q4/manifest.json +189 -0
- package/dist/catalog/chat-models/gr/granite4.2-8b-q4/versions/1.0.0/manifest.json +57 -0
- package/dist/catalog/chat-models/index.json +1 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q4/manifest.json +235 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q4/versions/1.0.0/manifest.json +124 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q4/versions/1.0.1/manifest.json +124 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q4/versions/1.0.2/manifest.json +123 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q6/manifest.json +257 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q6/versions/1.0.0/manifest.json +145 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q6/versions/1.0.1/manifest.json +145 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q8/manifest.json +285 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q8/versions/1.0.0/manifest.json +174 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q8/versions/1.0.1/manifest.json +174 -0
- package/dist/catalog/chat-models/la/laguna-s-2.1-118b-q8/versions/1.0.2/manifest.json +173 -0
- package/dist/catalog/chat-models/lf/lfm2.5-2.6b-q4/manifest.json +162 -0
- package/dist/catalog/chat-models/lf/lfm2.5-2.6b-q4/versions/1.0.0/manifest.json +59 -0
- package/dist/catalog/chat-models/lf/lfm2.5-2.6b-q4/versions/1.0.1/manifest.json +58 -0
- package/dist/catalog/chat-models/ll/llama3.2-3b-q4/manifest.json +134 -0
- package/dist/catalog/chat-models/ll/llama3.2-3b-q4/versions/1.1.0/manifest.json +57 -0
- package/dist/catalog/chat-models/ll/llama3.2-3b-q4/versions/1.1.1/manifest.json +56 -0
- package/dist/catalog/chat-models/mi/minicpm5-1b-q4/manifest.json +156 -0
- package/dist/catalog/chat-models/mi/minicpm5-1b-q4/versions/1.0.0/manifest.json +57 -0
- package/dist/catalog/chat-models/mi/minicpm5-2b-q4/manifest.json +161 -0
- package/dist/catalog/chat-models/mi/minicpm5-2b-q4/versions/1.0.0/manifest.json +57 -0
- package/dist/catalog/chat-models/mi/mistral-7b-q4/manifest.json +159 -0
- package/dist/catalog/chat-models/mi/mistral-7b-q4/versions/1.1.0/manifest.json +62 -0
- package/dist/catalog/chat-models/mi/mistral-7b-q4/versions/1.1.1/manifest.json +61 -0
- package/dist/catalog/chat-models/mi/mistral-medium-3.5-128b-q4/manifest.json +275 -0
- package/dist/catalog/chat-models/mi/mistral-medium-3.5-128b-q4/versions/1.0.0/manifest.json +154 -0
- package/dist/catalog/chat-models/mi/mistral-medium-3.5-128b-q4/versions/1.0.1/manifest.json +153 -0
- package/dist/catalog/chat-models/mu/muse-glimmer-30b-q4/manifest.json +135 -0
- package/dist/catalog/chat-models/mu/muse-glimmer-30b-q4/versions/1.0.0/manifest.json +20 -0
- package/dist/catalog/chat-models/mu/muse-glimmer-30b-q4/versions/1.0.1/manifest.json +20 -0
- package/dist/catalog/chat-models/mu/muse-glimmer-30b-q4/versions/1.0.2/manifest.json +20 -0
- package/dist/catalog/chat-models/na/nanbeige4.2-3b-q4/manifest.json +138 -0
- package/dist/catalog/chat-models/na/nanbeige4.2-3b-q4/versions/1.0.0/manifest.json +14 -0
- package/dist/catalog/chat-models/ne/nemotron3-nano-30b-q4/manifest.json +212 -0
- package/dist/catalog/chat-models/ne/nemotron3-nano-30b-q4/versions/1.0.0/manifest.json +94 -0
- package/dist/catalog/chat-models/ne/nemotron3-nano-30b-q4/versions/1.0.1/manifest.json +94 -0
- package/dist/catalog/chat-models/ne/nemotron3-nano-30b-q4/versions/1.0.2/manifest.json +93 -0
- package/dist/catalog/chat-models/ne/nemotron3-super-120b-q4/manifest.json +135 -0
- package/dist/catalog/chat-models/ne/nemotron3-super-120b-q4/versions/1.0.0/manifest.json +30 -0
- package/dist/catalog/chat-models/ne/nemotron3-super-120b-q4/versions/1.0.1/manifest.json +30 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q4/manifest.json +192 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q4/versions/1.0.0/manifest.json +74 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q4/versions/1.0.1/manifest.json +73 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q8/manifest.json +207 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q8/versions/1.0.0/manifest.json +89 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-lightning-30b-q8/versions/1.0.1/manifest.json +88 -0
- package/dist/catalog/chat-models/or/ornith-35b-q4/manifest.json +224 -0
- package/dist/catalog/chat-models/or/ornith-35b-q4/versions/1.0.0/manifest.json +94 -0
- package/dist/catalog/chat-models/or/ornith-35b-q4/versions/1.0.1/manifest.json +93 -0
- package/dist/catalog/chat-models/or/ornith-35b-q8/manifest.json +244 -0
- package/dist/catalog/chat-models/or/ornith-35b-q8/versions/1.0.0/manifest.json +114 -0
- package/dist/catalog/chat-models/or/ornith-35b-q8/versions/1.0.1/manifest.json +113 -0
- package/dist/catalog/chat-models/or/ornith-9b-q4/manifest.json +215 -0
- package/dist/catalog/chat-models/or/ornith-9b-q4/versions/1.0.0/manifest.json +84 -0
- package/dist/catalog/chat-models/or/ornith-9b-q4/versions/1.0.1/manifest.json +83 -0
- package/dist/catalog/chat-models/or/ornith1.5-35b-a3b-q4/manifest.json +208 -0
- package/dist/catalog/chat-models/or/ornith1.5-35b-a3b-q4/versions/1.0.0/manifest.json +74 -0
- package/dist/catalog/chat-models/or/ornith1.5-35b-a3b-q8/manifest.json +223 -0
- package/dist/catalog/chat-models/or/ornith1.5-35b-a3b-q8/versions/1.0.0/manifest.json +89 -0
- package/dist/catalog/chat-models/or/ornith1.5-9b-q4/manifest.json +187 -0
- package/dist/catalog/chat-models/or/ornith1.5-9b-q4/versions/1.0.0/manifest.json +53 -0
- package/dist/catalog/chat-models/or/ornith1.5-9b-q4/versions/1.0.1/manifest.json +77 -0
- package/dist/catalog/chat-models/or/ornith1.5-9b-q8/manifest.json +192 -0
- package/dist/catalog/chat-models/or/ornith1.5-9b-q8/versions/1.0.0/manifest.json +58 -0
- package/dist/catalog/chat-models/or/ornith1.5-9b-q8/versions/1.0.1/manifest.json +82 -0
- package/dist/catalog/chat-models/qw/qwen3.5-0.8b-q4/manifest.json +192 -0
- package/dist/catalog/chat-models/qw/qwen3.5-0.8b-q4/versions/1.0.0/manifest.json +75 -0
- package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/manifest.json +315 -0
- package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.0/manifest.json +164 -0
- package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.1/manifest.json +164 -0
- package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.2/manifest.json +164 -0
- package/dist/catalog/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.3/manifest.json +163 -0
- package/dist/catalog/chat-models/qw/qwen3.5-27b-q4/manifest.json +217 -0
- package/dist/catalog/chat-models/qw/qwen3.5-27b-q4/versions/1.0.0/manifest.json +90 -0
- package/dist/catalog/chat-models/qw/qwen3.5-2b-q4/manifest.json +194 -0
- package/dist/catalog/chat-models/qw/qwen3.5-2b-q4/versions/1.1.0/manifest.json +77 -0
- package/dist/catalog/chat-models/qw/qwen3.5-2b-q4/versions/1.1.2/manifest.json +76 -0
- package/dist/catalog/chat-models/qw/qwen3.5-2b-q4/versions/1.1.3/manifest.json +76 -0
- package/dist/catalog/chat-models/qw/qwen3.5-4b-q4/manifest.json +188 -0
- package/dist/catalog/chat-models/qw/qwen3.5-4b-q4/versions/1.1.0/manifest.json +77 -0
- package/dist/catalog/chat-models/qw/qwen3.5-4b-q4/versions/1.1.2/manifest.json +76 -0
- package/dist/catalog/chat-models/qw/qwen3.5-4b-q4/versions/1.1.3/manifest.json +76 -0
- package/dist/catalog/chat-models/qw/qwen3.5-9b-q4/manifest.json +205 -0
- package/dist/catalog/chat-models/qw/qwen3.5-9b-q4/versions/1.1.0/manifest.json +82 -0
- package/dist/catalog/chat-models/qw/qwen3.5-9b-q4/versions/1.1.2/manifest.json +81 -0
- package/dist/catalog/chat-models/qw/qwen3.5-9b-q4/versions/1.1.3/manifest.json +81 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/manifest.json +230 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/versions/1.1.0/manifest.json +92 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/versions/1.1.4/manifest.json +91 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/versions/1.1.5/manifest.json +91 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q4/versions/1.1.6/manifest.json +115 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/manifest.json +240 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/versions/1.0.0/manifest.json +102 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/versions/1.0.2/manifest.json +103 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/versions/1.0.3/manifest.json +103 -0
- package/dist/catalog/chat-models/qw/qwen3.6-27b-q8/versions/1.0.4/manifest.json +127 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/manifest.json +233 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.0/manifest.json +92 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.1/manifest.json +93 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.2/manifest.json +93 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.3/manifest.json +117 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/manifest.json +252 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.0/manifest.json +112 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.1/manifest.json +113 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.2/manifest.json +113 -0
- package/dist/catalog/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.3/manifest.json +137 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-iq1-s/manifest.json +195 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-iq1-s/versions/1.0.0/manifest.json +19 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q2/manifest.json +194 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q2/versions/1.0.0/manifest.json +19 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q3/manifest.json +194 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q3/versions/1.0.0/manifest.json +19 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q3/versions/1.0.1/manifest.json +19 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/manifest.json +291 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.0/manifest.json +20 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.1/manifest.json +93 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.2/manifest.json +92 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.3/manifest.json +116 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.4/manifest.json +116 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q4/versions/1.0.5/manifest.json +116 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/manifest.json +278 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/versions/1.0.0/manifest.json +20 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/versions/1.0.1/manifest.json +104 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/versions/1.0.2/manifest.json +103 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q6/versions/1.0.3/manifest.json +127 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q8/manifest.json +278 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q8/versions/1.0.0/manifest.json +113 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q8/versions/1.0.1/manifest.json +113 -0
- package/dist/catalog/chat-models/qw/qwen3.8-27b-q8/versions/1.0.2/manifest.json +137 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq3/manifest.json +221 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq3/versions/1.0.0/manifest.json +36 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq4/manifest.json +429 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq4/versions/1.0.0/manifest.json +36 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq4/versions/1.1.0/manifest.json +205 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-iq4/versions/1.1.1/manifest.json +244 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-q2/manifest.json +203 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-q2/versions/1.0.0/manifest.json +21 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-q2/versions/1.0.1/manifest.json +31 -0
- package/dist/catalog/chat-models/qw/qwen3.8-flash-next-q2/versions/1.0.2/manifest.json +30 -0
- package/dist/catalog/chat-models/raw-index.json +1 -0
- package/dist/catalog/chat-models/ta/talkie-1930-13b-q4/manifest.json +79 -0
- package/dist/catalog/chat-models/ta/talkie-1930-13b-q4/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/chat-models/ta/talkie-1930-13b-q4/versions/1.0.1/manifest.json +15 -0
- package/dist/catalog/chat-models/te/ternary-bonsai-27b-q2/manifest.json +204 -0
- package/dist/catalog/chat-models/te/ternary-bonsai-27b-q2/versions/1.0.0/manifest.json +70 -0
- package/dist/catalog/chat-models/te/ternary-bonsai-27b-q2/versions/1.0.1/manifest.json +70 -0
- package/dist/catalog/chat-models/un/underdog-saluki-27b-iq2-mix/manifest.json +164 -0
- package/dist/catalog/chat-models/un/underdog-saluki-27b-iq2-mix/versions/1.0.0/manifest.json +14 -0
- package/dist/catalog/knowledge-catalogs/be/bendyline-how-to-books/manifest.json +26 -0
- package/dist/catalog/knowledge-catalogs/be/bendyline-how-to-books/versions/2026.10.8/manifest.json +8950 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-alaska-part-0001/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-alaska-part-0001/versions/2026.10.1/manifest.json +658 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-nevada-part-0001/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-nevada-part-0001/versions/2026.10.1/manifest.json +666 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-us-300-399-part-0001/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-us-300-399-part-0001/versions/2026.10.2/manifest.json +182 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-us-347-349/manifest.json +25 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-us-347-349/versions/2026.10.5/manifest.json +38 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0001/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0001/versions/2026.10.1/manifest.json +558 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0002/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0002/versions/2026.10.1/manifest.json +258 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0001/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0001/versions/2026.10.1/manifest.json +318 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0002/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0002/versions/2026.10.1/manifest.json +266 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0003/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0003/versions/2026.10.1/manifest.json +186 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0004/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0004/versions/2026.10.1/manifest.json +138 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0005/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0005/versions/2026.10.1/manifest.json +138 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-wyoming-part-0001/manifest.json +24 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-wyoming-part-0001/versions/2026.10.3/manifest.json +626 -0
- package/dist/catalog/knowledge-catalogs/index.json +1 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-aspnet-core-en/manifest.json +22 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-aspnet-core-en/versions/2026.10.16/manifest.json +18270 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-ai-platform-en/manifest.json +23 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-ai-platform-en/versions/2026.10.16/manifest.json +1098 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-apps-compute-en/manifest.json +23 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-apps-compute-en/versions/2026.10.16/manifest.json +722 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-data-aiot-en/manifest.json +23 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-data-aiot-en/versions/2026.10.16/manifest.json +530 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-management-hybrid-en/manifest.json +23 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-management-hybrid-en/versions/2026.10.16/manifest.json +602 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-network-security-en/manifest.json +23 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-network-security-en/versions/2026.10.16/manifest.json +250 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-dotnet-en/manifest.json +22 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-dotnet-en/versions/2026.10.16/manifest.json +16794 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-entity-framework-en/manifest.json +22 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-entity-framework-en/versions/2026.10.16/manifest.json +1106 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-microsoft-365-en/manifest.json +22 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-microsoft-365-en/versions/2026.10.16/manifest.json +234 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-powershell-en/manifest.json +22 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-powershell-en/versions/2026.10.16/manifest.json +522 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-sql-server-en/manifest.json +22 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-sql-server-en/versions/2026.10.16/manifest.json +1850 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-apps-en/manifest.json +22 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-apps-en/versions/2026.10.16/manifest.json +1734 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-server-en/manifest.json +22 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-server-en/versions/2026.10.16/manifest.json +774 -0
- package/dist/catalog/knowledge-catalogs/raw-index.json +1 -0
- package/dist/catalog/knowledge-catalogs/re/regional-american-south/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-american-south/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-american-south/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-american-south/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-brazil/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-brazil/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-brazil/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-brazil/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-asia/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-asia/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-asia/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-asia/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-middle-east/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-middle-east/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-middle-east/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-middle-east/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-midwest/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-midwest/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-midwest/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-midwest/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-north-africa/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-north-africa/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-north-africa/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-north-africa/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northeast/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northeast/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northeast/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northeast/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-south-asia/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-south-asia/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-south-asia/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-south-asia/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe/manifest.json +48 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe/versions/2026.10.3/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/manifest.json +28 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.4.2/manifest.json +53 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.4.3/manifest.json +885 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.4.5/manifest.json +157 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/art.json +11 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/manifest.json +32 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.4.2/manifest.json +69 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.4.3/manifest.json +741 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.4.5/manifest.json +173 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/manifest.json +69 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/versions/2026.4.4/manifest.json +217 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/versions/2026.4.5/manifest.json +217 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/manifest.json +64 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/versions/2026.4.4/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/versions/2026.4.5/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/manifest.json +64 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/versions/2026.4.5/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/art.json +11 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/manifest.json +29 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.4.2/manifest.json +57 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.4.3/manifest.json +925 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.4.5/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/manifest.json +28 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.4.2/manifest.json +53 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.4.3/manifest.json +1665 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.4.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/manifest.json +29 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.4.2/manifest.json +57 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.4.3/manifest.json +1233 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.4.5/manifest.json +141 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/art.json +11 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/manifest.json +29 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.4.2/manifest.json +57 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.4.3/manifest.json +493 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.4.5/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/manifest.json +63 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/versions/2026.4.4/manifest.json +193 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/versions/2026.4.5/manifest.json +193 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/manifest.json +30 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.4.2/manifest.json +61 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.4.3/manifest.json +665 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.4.5/manifest.json +177 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/manifest.json +29 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.4.2/manifest.json +57 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.4.3/manifest.json +745 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.4.5/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/manifest.json +62 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/versions/2026.4.4/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/versions/2026.4.5/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/manifest.json +64 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/versions/2026.4.5/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/manifest.json +64 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/versions/2026.4.4/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/versions/2026.4.5/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/manifest.json +30 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.4.2/manifest.json +61 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.4.3/manifest.json +1253 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.4.5/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/manifest.json +29 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.4.2/manifest.json +57 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.4.3/manifest.json +1957 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.4.5/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/manifest.json +63 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/versions/2026.4.5/manifest.json +193 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/art.json +11 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/manifest.json +45 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/versions/2026.4.4/manifest.json +121 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/versions/2026.4.5/manifest.json +173 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/art.json +12 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/logo.webp +0 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/manifest.json +62 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/versions/2026.4.4/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/versions/2026.4.5/manifest.json +189 -0
- package/dist/catalog/provenance.json +8 -0
- package/dist/chat/catalog-model-lookup.d.ts +21 -0
- package/dist/chat/catalog-model-lookup.js +48 -0
- package/dist/chat/local-model-tier.d.ts +1 -0
- package/dist/chat/local-model-tier.js +2 -0
- package/dist/chat/vision-capability.d.ts +1 -0
- package/dist/chat/vision-capability.js +3 -0
- package/dist/engine-components.d.ts +30 -0
- package/dist/engine-components.js +144 -0
- package/dist/engines/electron-native-reuse.d.ts +65 -0
- package/dist/engines/electron-native-reuse.js +305 -0
- package/dist/engines/native-file-manifest.json +1320 -0
- package/dist/engines/native-manifest.d.ts +70 -0
- package/dist/engines/native-manifest.js +98 -0
- package/dist/engines/registry.d.ts +88 -0
- package/dist/engines/registry.js +217 -0
- package/dist/engines/resolver.d.ts +121 -0
- package/dist/engines/resolver.js +894 -0
- package/dist/engines/signature.d.ts +85 -0
- package/dist/engines/signature.js +231 -0
- package/dist/fs/atomic.d.ts +53 -0
- package/dist/fs/atomic.js +202 -0
- package/dist/fs/config-store.d.ts +14 -0
- package/dist/fs/config-store.js +101 -0
- package/dist/fs/home-permissions.d.ts +18 -0
- package/dist/fs/home-permissions.js +27 -0
- package/dist/fs/safe-paths.d.ts +107 -0
- package/dist/fs/safe-paths.js +264 -0
- package/dist/fs/security-json.d.ts +13 -0
- package/dist/fs/security-json.js +67 -0
- package/dist/http/auth-context.d.ts +23 -0
- package/dist/http/auth-context.js +1 -0
- package/dist/http/engine-runtime-context.d.ts +30 -0
- package/dist/http/engine-runtime-context.js +1 -0
- package/dist/http/external-conversation-contract.d.ts +49 -0
- package/dist/http/external-conversation-contract.js +1 -0
- package/dist/http/external-conversation-headers.d.ts +11 -0
- package/dist/http/external-conversation-headers.js +11 -0
- package/dist/http/inference-context.d.ts +36 -0
- package/dist/http/inference-context.js +1 -0
- package/dist/http/model-inventory-cache.d.ts +8 -0
- package/dist/http/model-inventory-cache.js +8 -0
- package/dist/http/openai-compat/action-ledger.d.ts +15 -0
- package/dist/http/openai-compat/action-ledger.js +119 -0
- package/dist/http/openai-compat/apple-model.d.ts +3 -0
- package/dist/http/openai-compat/apple-model.js +44 -0
- package/dist/http/openai-compat/caller-owned-profile.d.ts +7 -0
- package/dist/http/openai-compat/caller-owned-profile.js +18 -0
- package/dist/http/openai-compat/chat-progress.d.ts +9 -0
- package/dist/http/openai-compat/chat-progress.js +69 -0
- package/dist/http/openai-compat/chat-target.d.ts +76 -0
- package/dist/http/openai-compat/chat-target.js +97 -0
- package/dist/http/openai-compat/embeddings.d.ts +37 -0
- package/dist/http/openai-compat/embeddings.js +86 -0
- package/dist/http/openai-compat/request-tuning.d.ts +35 -0
- package/dist/http/openai-compat/request-tuning.js +87 -0
- package/dist/http/openai-compat/responses-streaming.d.ts +351 -0
- package/dist/http/openai-compat/responses-streaming.js +717 -0
- package/dist/http/openai-compat/responses-translate.d.ts +215 -0
- package/dist/http/openai-compat/responses-translate.js +377 -0
- package/dist/http/openai-compat/streaming-telemetry.d.ts +30 -0
- package/dist/http/openai-compat/streaming-telemetry.js +88 -0
- package/dist/http/openai-compat/streaming.d.ts +141 -0
- package/dist/http/openai-compat/streaming.js +687 -0
- package/dist/http/openai-compat/tool-call-stream-filter.d.ts +33 -0
- package/dist/http/openai-compat/tool-call-stream-filter.js +110 -0
- package/dist/http/openai-compat/translate.d.ts +254 -0
- package/dist/http/openai-compat/translate.js +485 -0
- package/dist/http/routes/engines.d.ts +13 -0
- package/dist/http/routes/engines.js +366 -0
- package/dist/http/routes/machine-engine-proxy.d.ts +26 -0
- package/dist/http/routes/machine-engine-proxy.js +43 -0
- package/dist/http/routes/model-bundles.d.ts +4 -0
- package/dist/http/routes/model-bundles.js +190 -0
- package/dist/http/routes/v1-chat.d.ts +72 -0
- package/dist/http/routes/v1-chat.js +645 -0
- package/dist/http/routes/v1-embeddings.d.ts +3 -0
- package/dist/http/routes/v1-embeddings.js +82 -0
- package/dist/http/routes/v1-knowledge.d.ts +4 -0
- package/dist/http/routes/v1-knowledge.js +304 -0
- package/dist/http/routes/v1-models-ensure.d.ts +32 -0
- package/dist/http/routes/v1-models-ensure.js +122 -0
- package/dist/http/routes/v1-models.d.ts +8 -0
- package/dist/http/routes/v1-models.js +189 -0
- package/dist/http/routes/v1-responses.d.ts +20 -0
- package/dist/http/routes/v1-responses.js +327 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/inference-service.d.ts +28 -0
- package/dist/inference-service.js +275 -0
- package/dist/knowledge/admission.d.ts +3 -0
- package/dist/knowledge/admission.js +22 -0
- package/dist/knowledge/bundled-catalog.d.ts +2 -0
- package/dist/knowledge/bundled-catalog.js +2 -0
- package/dist/knowledge/catalog-host.d.ts +103 -0
- package/dist/knowledge/catalog-host.js +180 -0
- package/dist/knowledge/catalog-source.d.ts +22 -0
- package/dist/knowledge/catalog-source.js +35 -0
- package/dist/knowledge/install.d.ts +55 -0
- package/dist/knowledge/install.js +274 -0
- package/dist/knowledge/manager.d.ts +287 -0
- package/dist/knowledge/manager.js +1540 -0
- package/dist/knowledge/registry.d.ts +35 -0
- package/dist/knowledge/registry.js +123 -0
- package/dist/knowledge/search-worker.d.ts +17 -0
- package/dist/knowledge/search-worker.js +36 -0
- package/dist/knowledge/shared-install-contract.d.ts +19 -0
- package/dist/knowledge/shared-install-contract.js +1 -0
- package/dist/knowledge/spatial-query.d.ts +11 -0
- package/dist/knowledge/spatial-query.js +33 -0
- package/dist/knowledge/trust-anchors.d.ts +11 -0
- package/dist/knowledge/trust-anchors.js +51 -0
- package/dist/knowledge/vector-floors.d.ts +44 -0
- package/dist/knowledge/vector-floors.js +92 -0
- package/dist/knowledge/worker-host.d.ts +9 -0
- package/dist/knowledge/worker-host.js +179 -0
- package/dist/kokoro-lexicon/LICENSE +202 -0
- package/dist/kokoro-lexicon/lexicon-gb-en.txt.gz +0 -0
- package/dist/kokoro-lexicon/lexicon-us-en.txt.gz +0 -0
- package/dist/kokoro-lexicon/manifest.json +23 -0
- package/dist/machine-engine/inspect-runtime.d.ts +3 -0
- package/dist/machine-engine/inspect-runtime.js +48 -0
- package/dist/machine-engine/knowledge-assets.d.ts +79 -0
- package/dist/machine-engine/knowledge-assets.js +505 -0
- package/dist/memory/embed-core.d.ts +131 -0
- package/dist/memory/embed-core.js +398 -0
- package/dist/memory/embed-worker.d.ts +23 -0
- package/dist/memory/embed-worker.js +49 -0
- package/dist/memory/embeddings.d.ts +105 -0
- package/dist/memory/embeddings.js +467 -0
- package/dist/model-profile/behaviors/tools-mlx-template-fix.d.ts +1 -0
- package/dist/model-profile/behaviors/tools-mlx-template-fix.js +2 -0
- package/dist/model-profile/behaviors/turn-ramble-detection.d.ts +1 -0
- package/dist/model-profile/behaviors/turn-ramble-detection.js +2 -0
- package/dist/model-profile/defaults.d.ts +1 -0
- package/dist/model-profile/defaults.js +2 -0
- package/dist/model-profile/index.d.ts +9 -0
- package/dist/model-profile/index.js +7 -0
- package/dist/model-profile/registry.d.ts +15 -0
- package/dist/model-profile/registry.js +18 -0
- package/dist/model-profile/runtime.d.ts +48 -0
- package/dist/model-profile/runtime.js +131 -0
- package/dist/model-profile/tool-grammar.d.ts +1 -0
- package/dist/model-profile/tool-grammar.js +2 -0
- package/dist/model-profile/tuning.d.ts +19 -0
- package/dist/model-profile/tuning.js +21 -0
- package/dist/model-profile/types.d.ts +1 -0
- package/dist/model-profile/types.js +2 -0
- package/dist/models/bundle-storage.d.ts +28 -0
- package/dist/models/bundle-storage.js +80 -0
- package/dist/models/catalog-drift.d.ts +48 -0
- package/dist/models/catalog-drift.js +94 -0
- package/dist/models/catalog-payload-identity.d.ts +107 -0
- package/dist/models/catalog-payload-identity.js +254 -0
- package/dist/models/ensure.d.ts +125 -0
- package/dist/models/ensure.js +205 -0
- package/dist/models/gezmodel.d.ts +47 -0
- package/dist/models/gezmodel.js +742 -0
- package/dist/models/install-registry.d.ts +101 -0
- package/dist/models/install-registry.js +216 -0
- package/dist/models/model-id.d.ts +22 -0
- package/dist/models/model-id.js +40 -0
- package/dist/models/storage-roots.d.ts +274 -0
- package/dist/models/storage-roots.js +865 -0
- package/dist/native-release-entry.d.ts +16 -0
- package/dist/native-release-entry.js +16 -0
- package/dist/perf/redact-path.d.ts +2 -0
- package/dist/perf/redact-path.js +27 -0
- package/dist/perf/responsiveness.d.ts +70 -0
- package/dist/perf/responsiveness.js +560 -0
- package/dist/providers/active-install-message.d.ts +42 -0
- package/dist/providers/active-install-message.js +49 -0
- package/dist/providers/apple-foundation-models/binary.d.ts +4 -0
- package/dist/providers/apple-foundation-models/binary.js +18 -0
- package/dist/providers/apple-foundation-models/helper.d.ts +66 -0
- package/dist/providers/apple-foundation-models/helper.js +262 -0
- package/dist/providers/apple-foundation-models/provider.d.ts +82 -0
- package/dist/providers/apple-foundation-models/provider.js +389 -0
- package/dist/providers/apple-foundation-models/status.d.ts +9 -0
- package/dist/providers/apple-foundation-models/status.js +49 -0
- package/dist/providers/audio/kokoro-frontend.d.ts +50 -0
- package/dist/providers/audio/kokoro-frontend.js +113 -0
- package/dist/providers/audio/managed-speech-model.d.ts +9 -0
- package/dist/providers/audio/managed-speech-model.js +86 -0
- package/dist/providers/audio/types.d.ts +202 -0
- package/dist/providers/audio/types.js +17 -0
- package/dist/providers/audio/whisper-cpp.d.ts +99 -0
- package/dist/providers/audio/whisper-cpp.js +420 -0
- package/dist/providers/audio-persister-contract.d.ts +13 -0
- package/dist/providers/audio-persister-contract.js +1 -0
- package/dist/providers/catalog-model-config.d.ts +63 -0
- package/dist/providers/catalog-model-config.js +95 -0
- package/dist/providers/code-block-salvage.d.ts +1 -0
- package/dist/providers/code-block-salvage.js +2 -0
- package/dist/providers/codex-cli/reasoning.d.ts +8 -0
- package/dist/providers/codex-cli/reasoning.js +17 -0
- package/dist/providers/complete-tool-call.d.ts +16 -0
- package/dist/providers/complete-tool-call.js +25 -0
- package/dist/providers/constrained-turn.d.ts +1 -0
- package/dist/providers/constrained-turn.js +2 -0
- package/dist/providers/deliverable-read-pacing.d.ts +1 -0
- package/dist/providers/deliverable-read-pacing.js +2 -0
- package/dist/providers/direct-file-work-prompt.d.ts +1 -0
- package/dist/providers/direct-file-work-prompt.js +2 -0
- package/dist/providers/ds4/build-provider.d.ts +100 -0
- package/dist/providers/ds4/build-provider.js +539 -0
- package/dist/providers/ds4/cache-adapter.d.ts +42 -0
- package/dist/providers/ds4/cache-adapter.js +110 -0
- package/dist/providers/ds4/dspark.d.ts +83 -0
- package/dist/providers/ds4/dspark.js +107 -0
- package/dist/providers/ds4/mtp.d.ts +32 -0
- package/dist/providers/ds4/mtp.js +46 -0
- package/dist/providers/ds4/provider.d.ts +67 -0
- package/dist/providers/ds4/provider.js +104 -0
- package/dist/providers/ds4/residency.d.ts +143 -0
- package/dist/providers/ds4/residency.js +139 -0
- package/dist/providers/ds4/stdout-parser.d.ts +47 -0
- package/dist/providers/ds4/stdout-parser.js +134 -0
- package/dist/providers/duplicate-tool-calls.d.ts +1 -0
- package/dist/providers/duplicate-tool-calls.js +2 -0
- package/dist/providers/file-repair-policy.d.ts +1 -0
- package/dist/providers/file-repair-policy.js +2 -0
- package/dist/providers/gpu-arbiter.d.ts +159 -0
- package/dist/providers/gpu-arbiter.js +301 -0
- package/dist/providers/image-persister-contract.d.ts +15 -0
- package/dist/providers/image-persister-contract.js +1 -0
- package/dist/providers/llama-cpp/build-metadata.d.ts +13 -0
- package/dist/providers/llama-cpp/build-metadata.js +39 -0
- package/dist/providers/llama-cpp/build-provider.d.ts +66 -0
- package/dist/providers/llama-cpp/build-provider.js +1491 -0
- package/dist/providers/llama-cpp/cache-adapter.d.ts +242 -0
- package/dist/providers/llama-cpp/cache-adapter.js +689 -0
- package/dist/providers/llama-cpp/devices.d.ts +130 -0
- package/dist/providers/llama-cpp/devices.js +256 -0
- package/dist/providers/llama-cpp/disk-cache.d.ts +8 -0
- package/dist/providers/llama-cpp/disk-cache.js +112 -0
- package/dist/providers/llama-cpp/engine-flags.d.ts +181 -0
- package/dist/providers/llama-cpp/engine-flags.js +279 -0
- package/dist/providers/llama-cpp/gguf-metadata-async.d.ts +11 -0
- package/dist/providers/llama-cpp/gguf-metadata-async.js +180 -0
- package/dist/providers/llama-cpp/gguf-metadata-worker.d.ts +7 -0
- package/dist/providers/llama-cpp/gguf-metadata-worker.js +27 -0
- package/dist/providers/llama-cpp/gguf-metadata.d.ts +198 -0
- package/dist/providers/llama-cpp/gguf-metadata.js +615 -0
- package/dist/providers/llama-cpp/gguf-quantization-backfill.d.ts +32 -0
- package/dist/providers/llama-cpp/gguf-quantization-backfill.js +75 -0
- package/dist/providers/llama-cpp/index.d.ts +10 -0
- package/dist/providers/llama-cpp/index.js +13 -0
- package/dist/providers/llama-cpp/kv-cache-type.d.ts +118 -0
- package/dist/providers/llama-cpp/kv-cache-type.js +140 -0
- package/dist/providers/llama-cpp/log.d.ts +92 -0
- package/dist/providers/llama-cpp/log.js +280 -0
- package/dist/providers/llama-cpp/models.d.ts +389 -0
- package/dist/providers/llama-cpp/models.js +1011 -0
- package/dist/providers/llama-cpp/offload-planner.d.ts +339 -0
- package/dist/providers/llama-cpp/offload-planner.js +524 -0
- package/dist/providers/llama-cpp/provider.d.ts +493 -0
- package/dist/providers/llama-cpp/provider.js +862 -0
- package/dist/providers/llama-cpp/reasoning-launch.d.ts +7 -0
- package/dist/providers/llama-cpp/reasoning-launch.js +14 -0
- package/dist/providers/llama-cpp/spec-draft.d.ts +44 -0
- package/dist/providers/llama-cpp/spec-draft.js +44 -0
- package/dist/providers/llama-cpp/stdout-parser.d.ts +70 -0
- package/dist/providers/llama-cpp/stdout-parser.js +197 -0
- package/dist/providers/local-tool-call-salvage.d.ts +1 -0
- package/dist/providers/local-tool-call-salvage.js +2 -0
- package/dist/providers/local-turn-policy.d.ts +1 -0
- package/dist/providers/local-turn-policy.js +2 -0
- package/dist/providers/mlx/async-file-handoff.d.ts +11 -0
- package/dist/providers/mlx/async-file-handoff.js +25 -0
- package/dist/providers/mlx/build-provider.d.ts +65 -0
- package/dist/providers/mlx/build-provider.js +717 -0
- package/dist/providers/mlx/cache-adapter.d.ts +161 -0
- package/dist/providers/mlx/cache-adapter.js +445 -0
- package/dist/providers/mlx/chat-protocol.d.ts +48 -0
- package/dist/providers/mlx/chat-protocol.js +8 -0
- package/dist/providers/mlx/config-parser.d.ts +29 -0
- package/dist/providers/mlx/config-parser.js +81 -0
- package/dist/providers/mlx/engine-gate.d.ts +51 -0
- package/dist/providers/mlx/engine-gate.js +207 -0
- package/dist/providers/mlx/engine-hold.d.ts +41 -0
- package/dist/providers/mlx/engine-hold.js +59 -0
- package/dist/providers/mlx/engine-log-router.d.ts +84 -0
- package/dist/providers/mlx/engine-log-router.js +137 -0
- package/dist/providers/mlx/engine-stats-sampler.d.ts +36 -0
- package/dist/providers/mlx/engine-stats-sampler.js +59 -0
- package/dist/providers/mlx/index.d.ts +10 -0
- package/dist/providers/mlx/index.js +10 -0
- package/dist/providers/mlx/log.d.ts +55 -0
- package/dist/providers/mlx/log.js +157 -0
- package/dist/providers/mlx/model-geometry.d.ts +35 -0
- package/dist/providers/mlx/model-geometry.js +118 -0
- package/dist/providers/mlx/models.d.ts +289 -0
- package/dist/providers/mlx/models.js +1079 -0
- package/dist/providers/mlx/provider.d.ts +404 -0
- package/dist/providers/mlx/provider.js +3017 -0
- package/dist/providers/mlx/python/cache_persist.py +348 -0
- package/dist/providers/mlx/python/cache_seed.py +402 -0
- package/dist/providers/mlx/python/gezel_mlx_server.py +4491 -0
- package/dist/providers/mlx/python/lfm2_compat.py +55 -0
- package/dist/providers/mlx/python/qwen3_5_text_compat.py +60 -0
- package/dist/providers/mlx/python/qwen4_ple.py +159 -0
- package/dist/providers/mlx/python/spec_decode.py +775 -0
- package/dist/providers/mlx/python/template_stability.py +133 -0
- package/dist/providers/mlx/python/think_budget.py +113 -0
- package/dist/providers/mlx/python/tool_args_json.py +297 -0
- package/dist/providers/mlx/python/tool_call_stream.py +265 -0
- package/dist/providers/mlx/python/tool_grammar.py +794 -0
- package/dist/providers/mlx/python/vision_inputs.py +64 -0
- package/dist/providers/mlx/python/wave_policy.py +147 -0
- package/dist/providers/mlx/reasoning-stream.d.ts +85 -0
- package/dist/providers/mlx/reasoning-stream.js +196 -0
- package/dist/providers/mlx/request-shape.d.ts +34 -0
- package/dist/providers/mlx/request-shape.js +42 -0
- package/dist/providers/mlx/runtime-diagnostics.d.ts +29 -0
- package/dist/providers/mlx/runtime-diagnostics.js +162 -0
- package/dist/providers/mlx/spec-drafter.d.ts +25 -0
- package/dist/providers/mlx/spec-drafter.js +73 -0
- package/dist/providers/mlx/stdout-parser.d.ts +60 -0
- package/dist/providers/mlx/stdout-parser.js +254 -0
- package/dist/providers/mlx/textual-tool-call-salvage.d.ts +46 -0
- package/dist/providers/mlx/textual-tool-call-salvage.js +396 -0
- package/dist/providers/mlx/tool-call-protocol.d.ts +65 -0
- package/dist/providers/mlx/tool-call-protocol.js +140 -0
- package/dist/providers/mlx/tool-call-stripper.d.ts +68 -0
- package/dist/providers/mlx/tool-call-stripper.js +153 -0
- package/dist/providers/mlx/tool-image-retention.d.ts +23 -0
- package/dist/providers/mlx/tool-image-retention.js +43 -0
- package/dist/providers/mlx/turn-telemetry.d.ts +22 -0
- package/dist/providers/mlx/turn-telemetry.js +45 -0
- package/dist/providers/mlx/venv.d.ts +91 -0
- package/dist/providers/mlx/venv.js +111 -0
- package/dist/providers/mlx/vision-mode.d.ts +92 -0
- package/dist/providers/mlx/vision-mode.js +187 -0
- package/dist/providers/mlx/vision.d.ts +2 -0
- package/dist/providers/mlx/vision.js +12 -0
- package/dist/providers/mlx/wire-transcript.d.ts +14 -0
- package/dist/providers/mlx/wire-transcript.js +43 -0
- package/dist/providers/native/capacity-broker.d.ts +812 -0
- package/dist/providers/native/capacity-broker.js +1058 -0
- package/dist/providers/native/capacity-budget.d.ts +133 -0
- package/dist/providers/native/capacity-budget.js +265 -0
- package/dist/providers/native/device-capacity-ledger.d.ts +31 -0
- package/dist/providers/native/device-capacity-ledger.js +196 -0
- package/dist/providers/native/device-capacity.d.ts +84 -0
- package/dist/providers/native/device-capacity.js +431 -0
- package/dist/providers/native/engine-api-key.d.ts +57 -0
- package/dist/providers/native/engine-api-key.js +72 -0
- package/dist/providers/native/engine-key.d.ts +18 -0
- package/dist/providers/native/engine-key.js +41 -0
- package/dist/providers/native/engine-router.d.ts +145 -0
- package/dist/providers/native/engine-router.js +191 -0
- package/dist/providers/native/gpu-panic-guard.d.ts +54 -0
- package/dist/providers/native/gpu-panic-guard.js +59 -0
- package/dist/providers/native/inference.d.ts +33 -0
- package/dist/providers/native/inference.js +49 -0
- package/dist/providers/native/local-engine-runtime.d.ts +412 -0
- package/dist/providers/native/local-engine-runtime.js +1714 -0
- package/dist/providers/native/measured-budget.d.ts +32 -0
- package/dist/providers/native/measured-budget.js +54 -0
- package/dist/providers/native/port.d.ts +11 -0
- package/dist/providers/native/port.js +29 -0
- package/dist/providers/native/provider-pool.d.ts +474 -0
- package/dist/providers/native/provider-pool.js +1166 -0
- package/dist/providers/native/supervisor.d.ts +503 -0
- package/dist/providers/native/supervisor.js +1466 -0
- package/dist/providers/observation-context.d.ts +16 -0
- package/dist/providers/observation-context.js +1 -0
- package/dist/providers/openai-compatible/sse.d.ts +1 -0
- package/dist/providers/openai-compatible/sse.js +2 -0
- package/dist/providers/patient-fetch.d.ts +36 -0
- package/dist/providers/patient-fetch.js +44 -0
- package/dist/providers/project-macro-loop-bail.d.ts +7 -0
- package/dist/providers/project-macro-loop-bail.js +21 -0
- package/dist/providers/prose-document-salvage.d.ts +1 -0
- package/dist/providers/prose-document-salvage.js +2 -0
- package/dist/providers/provider-disposal.d.ts +1 -0
- package/dist/providers/provider-disposal.js +2 -0
- package/dist/providers/queue.d.ts +15 -0
- package/dist/providers/queue.js +23 -0
- package/dist/providers/ramble-abort-message.d.ts +1 -0
- package/dist/providers/ramble-abort-message.js +2 -0
- package/dist/providers/ramble-detector.d.ts +1 -0
- package/dist/providers/ramble-detector.js +2 -0
- package/dist/providers/reasoning-depth.d.ts +1 -0
- package/dist/providers/reasoning-depth.js +2 -0
- package/dist/providers/required-input-reads.d.ts +1 -0
- package/dist/providers/required-input-reads.js +2 -0
- package/dist/providers/session-defaults.d.ts +13 -0
- package/dist/providers/session-defaults.js +49 -0
- package/dist/providers/session-hooks.d.ts +26 -0
- package/dist/providers/session-hooks.js +1 -0
- package/dist/providers/streaming-session.d.ts +1 -0
- package/dist/providers/streaming-session.js +2 -0
- package/dist/providers/terminal-tool-policy.d.ts +1 -0
- package/dist/providers/terminal-tool-policy.js +2 -0
- package/dist/providers/tool-arg-schema-coercion.d.ts +1 -0
- package/dist/providers/tool-arg-schema-coercion.js +2 -0
- package/dist/providers/tool-executor.d.ts +12 -0
- package/dist/providers/tool-executor.js +20 -0
- package/dist/providers/tool-failure-tracker.d.ts +1 -0
- package/dist/providers/tool-failure-tracker.js +2 -0
- package/dist/providers/tool-repeat-tracker.d.ts +1 -0
- package/dist/providers/tool-repeat-tracker.js +2 -0
- package/dist/providers/turn-timeout.d.ts +1 -0
- package/dist/providers/turn-timeout.js +1 -0
- package/dist/providers/types.d.ts +834 -0
- package/dist/providers/types.js +42 -0
- package/dist/providers/usage-builder.d.ts +1 -0
- package/dist/providers/usage-builder.js +2 -0
- package/dist/providers/vision-capability.d.ts +109 -0
- package/dist/providers/vision-capability.js +137 -0
- package/dist/python/mlx-runtime-status-bus.d.ts +39 -0
- package/dist/python/mlx-runtime-status-bus.js +27 -0
- package/dist/python/uv-runtime.d.ts +176 -0
- package/dist/python/uv-runtime.js +492 -0
- package/dist/relevance/install.d.ts +28 -0
- package/dist/relevance/install.js +114 -0
- package/dist/relevance/manager.d.ts +79 -0
- package/dist/relevance/manager.js +211 -0
- package/dist/relevance/registry.d.ts +11 -0
- package/dist/relevance/registry.js +158 -0
- package/dist/relevance/relevance-core.d.ts +67 -0
- package/dist/relevance/relevance-core.js +189 -0
- package/dist/relevance/relevance-model.d.ts +42 -0
- package/dist/relevance/relevance-model.js +292 -0
- package/dist/relevance/relevance-worker.d.ts +20 -0
- package/dist/relevance/relevance-worker.js +57 -0
- package/dist/relevance/settings.d.ts +30 -0
- package/dist/relevance/settings.js +81 -0
- package/dist/remotes/identity.d.ts +121 -0
- package/dist/remotes/identity.js +348 -0
- package/dist/remotes/pinned-fetch.d.ts +45 -0
- package/dist/remotes/pinned-fetch.js +193 -0
- package/dist/remotes/types.d.ts +54 -0
- package/dist/remotes/types.js +1 -0
- package/dist/runtime-lock.d.ts +29 -0
- package/dist/runtime-lock.js +85 -0
- package/dist/search/relevance-stage.d.ts +81 -0
- package/dist/search/relevance-stage.js +177 -0
- package/dist/secrets/types.d.ts +63 -0
- package/dist/secrets/types.js +64 -0
- package/dist/speech.d.ts +1 -0
- package/dist/speech.js +1 -0
- package/dist/system/darwin-memory.d.ts +26 -0
- package/dist/system/darwin-memory.js +81 -0
- package/dist/system/gezel-process-memory.d.ts +55 -0
- package/dist/system/gezel-process-memory.js +156 -0
- package/dist/system/memory.d.ts +154 -0
- package/dist/system/memory.js +501 -0
- package/dist/transformers-cache.d.ts +112 -0
- package/dist/transformers-cache.js +392 -0
- package/dist/utils/disk-space.d.ts +55 -0
- package/dist/utils/disk-space.js +72 -0
- package/dist/utils/download-common.d.ts +138 -0
- package/dist/utils/download-common.js +196 -0
- package/dist/utils/download-with-retry.d.ts +85 -0
- package/dist/utils/download-with-retry.js +522 -0
- package/dist/utils/extract-zip.d.ts +22 -0
- package/dist/utils/extract-zip.js +103 -0
- package/dist/utils/retire-model-worker.d.ts +15 -0
- package/dist/utils/retire-model-worker.js +24 -0
- package/dist/utils/service-worker-entry.d.ts +59 -0
- package/dist/utils/service-worker-entry.js +69 -0
- package/dist/utils/xet-download.d.ts +40 -0
- package/dist/utils/xet-download.js +526 -0
- package/dist/utils/xet.d.ts +86 -0
- package/dist/utils/xet.js +201 -0
- package/package.json +103 -3
- package/scripts/embedding-packaging.cjs +264 -0
- package/scripts/embedding-packaging.d.cts +16 -0
|
@@ -0,0 +1,1166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProviderPool — owns the lifecycle of every local-engine
|
|
3
|
+
* {@link LLMProvider} instance, keyed by `{provider, modelId,
|
|
4
|
+
* replicaIdx}`. Replaces the singleton "one supervisor per provider"
|
|
5
|
+
* model with a fleet so different gezels can run different models
|
|
6
|
+
* without cold-reload between turns.
|
|
7
|
+
*
|
|
8
|
+
* Capacity is enforced through {@link CapacityBroker}: every `ensure`
|
|
9
|
+
* reserves the model's `residentBytes`; when the budget is exhausted
|
|
10
|
+
* the pool LRU-evicts entries (shutting them down, releasing
|
|
11
|
+
* capacity, flushing any disk-cache work in the provider's
|
|
12
|
+
* `shutdown`) until the new entry fits.
|
|
13
|
+
*
|
|
14
|
+
* The pool is intentionally provider-agnostic — it doesn't know how
|
|
15
|
+
* to launch a llama-server or a Python MLX runtime. Callers inject a
|
|
16
|
+
* builder per `LocalProviderName`; tests inject a `MockProviderBuilder`
|
|
17
|
+
* that produces no-op LLMProviders.
|
|
18
|
+
*/
|
|
19
|
+
import { createLogger } from '@bendyline/gezel';
|
|
20
|
+
import { AbortedWhileQueuedError } from '../queue.js';
|
|
21
|
+
import { CapacityDeniedError, EngineBusyError, formatCapacityDenial, } from './capacity-broker.js';
|
|
22
|
+
import { makeEngineKey, parseEngineKey, } from './engine-key.js';
|
|
23
|
+
const log = createLogger('provider-pool');
|
|
24
|
+
/**
|
|
25
|
+
* The stable, machine-shaped denial log line. Its shape is a contract
|
|
26
|
+
* with the eval harness — evals/src/failure-class.ts:118,
|
|
27
|
+
* evals/src/preflight.ts:196, and evals/src/runner.ts:981 all grep the
|
|
28
|
+
* daemon log for `capacity broker denied <key>: budget exhausted: …`
|
|
29
|
+
* to classify capacity denials as infra (not model) failures. Do not
|
|
30
|
+
* reword either side without updating the other.
|
|
31
|
+
*/
|
|
32
|
+
export function capacityDenialLogLine(key, reason) {
|
|
33
|
+
return `capacity broker denied ${key}: ${reason}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Slack allowed between the card's measured free memory and what a new engine
|
|
37
|
+
* needs on it. Covers the display framebuffer, driver allocations, and the lag
|
|
38
|
+
* between a `shutdown()` returning and the driver actually handing the memory
|
|
39
|
+
* back — all of which make a fresh reading pessimistic by a fraction of a GB.
|
|
40
|
+
* Large enough that only an unambiguous shortfall denies.
|
|
41
|
+
*/
|
|
42
|
+
const MEASURED_VRAM_TOLERANCE_BYTES = 1024 ** 3;
|
|
43
|
+
/**
|
|
44
|
+
* A native child can be gone before a discrete-GPU driver publishes the
|
|
45
|
+
* released allocation as free again. Only pay this bounded wait after this
|
|
46
|
+
* pool actually evicted one of its own engines; a genuinely foreign tenant
|
|
47
|
+
* must still fail fast instead of adding latency to every denial.
|
|
48
|
+
*/
|
|
49
|
+
const MEASURED_VRAM_RECLAIM_POLL_MS = 1_000;
|
|
50
|
+
const MEASURED_VRAM_RECLAIM_WAIT_MS = 5_000;
|
|
51
|
+
function gb(bytes) {
|
|
52
|
+
return `${(bytes / 1024 ** 3).toFixed(1)} GB`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Raw reason for a denial the device reading made, not the ledger. Keeps the
|
|
56
|
+
* `budget exhausted: would commit N against M` shape {@link capacityDenialLogLine}
|
|
57
|
+
* carries into the eval harness — this IS a capacity denial, measured rather
|
|
58
|
+
* than reserved, and any other shape would be reported as a model failure.
|
|
59
|
+
*/
|
|
60
|
+
export function measuredVramDenialReason(requiredBytes, freeBytes) {
|
|
61
|
+
const required = Math.round(requiredBytes);
|
|
62
|
+
const free = Math.round(freeBytes);
|
|
63
|
+
return `budget exhausted: would commit ${required} against ${free} (measured free graphics memory)`;
|
|
64
|
+
}
|
|
65
|
+
function emptyPooledQueueSummary() {
|
|
66
|
+
return {
|
|
67
|
+
running: 0,
|
|
68
|
+
runningInteractive: 0,
|
|
69
|
+
runningBackground: 0,
|
|
70
|
+
queuedInteractive: 0,
|
|
71
|
+
queuedBackground: 0,
|
|
72
|
+
ambientHeld: 0,
|
|
73
|
+
concurrency: 0,
|
|
74
|
+
interactiveConcurrency: 0,
|
|
75
|
+
backgroundConcurrency: 0,
|
|
76
|
+
maxConcurrency: 0,
|
|
77
|
+
active: [],
|
|
78
|
+
pending: [],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function positiveConcurrency(value) {
|
|
82
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < 1)
|
|
83
|
+
return undefined;
|
|
84
|
+
return Math.floor(value);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Concurrent generation width the provider can serve right now.
|
|
88
|
+
*
|
|
89
|
+
* A supervised native launch is the strongest source: its retained `slots`
|
|
90
|
+
* diagnostic is the exact `--parallel` / server-width value of the live
|
|
91
|
+
* process. Older or wrapper providers may expose only `batch` or the queue's
|
|
92
|
+
* interactive cap, so use the widest of those compatible signals as the
|
|
93
|
+
* fallback. Never use total queue concurrency here — local queues carry an
|
|
94
|
+
* extra logical background lease that is not a native generation slot.
|
|
95
|
+
*/
|
|
96
|
+
export function liveProviderConcurrency(provider) {
|
|
97
|
+
const launchedSlots = positiveConcurrency(provider.engineLaunchSnapshot?.()?.diagnostics?.slots);
|
|
98
|
+
if (launchedSlots !== undefined)
|
|
99
|
+
return launchedSlots;
|
|
100
|
+
return Math.max(1, positiveConcurrency(provider.batch?.maxConcurrency) ?? 0, positiveConcurrency(provider.queue?.interactiveConcurrency) ?? 0);
|
|
101
|
+
}
|
|
102
|
+
/** Window over which {@link PoolEntry.recentHits} counts toward demand. */
|
|
103
|
+
const DEMAND_WINDOW_MS = 60_000;
|
|
104
|
+
const DEFAULT_DRAIN_WAIT_MS = 30_000;
|
|
105
|
+
const DRAIN_POLL_MS = 500;
|
|
106
|
+
/** Matches the provider queue's wait-notice cadence. */
|
|
107
|
+
const DRAIN_NOTICE_REPEAT_MS = 5_000;
|
|
108
|
+
/**
|
|
109
|
+
* In-flight work check, via the provider's own queue. A provider
|
|
110
|
+
* without a queue (cloud providers, test fakes) is treated as idle.
|
|
111
|
+
* Known blind spot: turns sent with `bypassQueue: true` (ask-specialist
|
|
112
|
+
* sub-sessions) never appear in the snapshot, so a drain can complete
|
|
113
|
+
* while one of those is still streaming — bounded harm, since those
|
|
114
|
+
* turns are short consultations with their own timeouts.
|
|
115
|
+
*/
|
|
116
|
+
function isBusy(entry) {
|
|
117
|
+
const snap = entry.provider.queue?.snapshot();
|
|
118
|
+
if (!snap)
|
|
119
|
+
return false;
|
|
120
|
+
return snap.running + snap.queuedInteractive + snap.queuedBackground > 0;
|
|
121
|
+
}
|
|
122
|
+
function throwIfAborted(signal) {
|
|
123
|
+
if (signal?.aborted)
|
|
124
|
+
throw new AbortedWhileQueuedError();
|
|
125
|
+
}
|
|
126
|
+
function drainWaitInfo(key, entry) {
|
|
127
|
+
const queue = entry.provider.queue;
|
|
128
|
+
const active = typeof queue?.describe === 'function' ? queue.describe().active : [];
|
|
129
|
+
return {
|
|
130
|
+
engineKey: key,
|
|
131
|
+
modelId: entry.parsed.modelId,
|
|
132
|
+
holders: active.map((a) => ({
|
|
133
|
+
...(a.sessionId !== undefined ? { sessionId: a.sessionId } : {}),
|
|
134
|
+
...(a.gezelId !== undefined ? { gezelId: a.gezelId } : {}),
|
|
135
|
+
...(a.job !== undefined ? { job: a.job } : {}),
|
|
136
|
+
...(a.actorLabel !== undefined ? { actorLabel: a.actorLabel } : {}),
|
|
137
|
+
})),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/** Native-child state for providers backed by a supervised local engine. */
|
|
141
|
+
function engineLifecycle(entry) {
|
|
142
|
+
return entry.provider.engineLifecycleSnapshot?.();
|
|
143
|
+
}
|
|
144
|
+
/** Drop recent-hit timestamps older than the demand window. */
|
|
145
|
+
function pruneHits(entry, now) {
|
|
146
|
+
const cutoff = now - DEMAND_WINDOW_MS;
|
|
147
|
+
if (entry.recentHits.length === 0 || entry.recentHits[0] >= cutoff)
|
|
148
|
+
return;
|
|
149
|
+
entry.recentHits = entry.recentHits.filter((t) => t >= cutoff);
|
|
150
|
+
}
|
|
151
|
+
export class ProviderPool {
|
|
152
|
+
broker;
|
|
153
|
+
builders;
|
|
154
|
+
now;
|
|
155
|
+
onChange;
|
|
156
|
+
drainWaitMs;
|
|
157
|
+
sleep;
|
|
158
|
+
gpuPanicGuard;
|
|
159
|
+
vramHeadroom;
|
|
160
|
+
serializeGpuLoads;
|
|
161
|
+
/** Tail of the serialized-load chain; each load awaits the previous. */
|
|
162
|
+
gpuLoadChain = Promise.resolve();
|
|
163
|
+
entries = new Map();
|
|
164
|
+
// Lock per key so two parallel `ensure` calls don't race to build
|
|
165
|
+
// the same engine. Hit path stays lock-free (Map.get).
|
|
166
|
+
buildLocks = new Map();
|
|
167
|
+
// In-flight evictions per key — parallel evict() calls join the
|
|
168
|
+
// same teardown instead of double-shutting-down the provider.
|
|
169
|
+
evicting = new Map();
|
|
170
|
+
/** Closed permanently once this user daemon adopts the machine broker. */
|
|
171
|
+
retiring = false;
|
|
172
|
+
retirementPromise = null;
|
|
173
|
+
constructor(opts) {
|
|
174
|
+
this.broker = opts.broker;
|
|
175
|
+
this.builders = opts.builders;
|
|
176
|
+
this.now = opts.now ?? Date.now;
|
|
177
|
+
if (opts.onChange)
|
|
178
|
+
this.onChange = opts.onChange;
|
|
179
|
+
this.drainWaitMs = opts.drainWaitMs ?? DEFAULT_DRAIN_WAIT_MS;
|
|
180
|
+
this.sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
181
|
+
if (opts.gpuPanicGuard)
|
|
182
|
+
this.gpuPanicGuard = opts.gpuPanicGuard;
|
|
183
|
+
if (opts.vramHeadroom)
|
|
184
|
+
this.vramHeadroom = opts.vramHeadroom;
|
|
185
|
+
this.serializeGpuLoads =
|
|
186
|
+
opts.serializeGpuLoads ??
|
|
187
|
+
(process.platform === 'darwin' && process.env.GEZEL_SERIALIZE_GPU_LOADS !== 'off');
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Run a model-LOAD (a `builder()` call, which maps weights onto the GPU)
|
|
191
|
+
* either immediately or serialized behind any in-flight load, per
|
|
192
|
+
* {@link ProviderPoolOptions.serializeGpuLoads}. Deadlock-free: the chain
|
|
193
|
+
* only ever waits for a load to finish, never for a turn or an eviction, and
|
|
194
|
+
* a load's failure doesn't wedge the chain (prior errors are swallowed).
|
|
195
|
+
*/
|
|
196
|
+
async withGpuLoadSlot(load) {
|
|
197
|
+
if (!this.serializeGpuLoads)
|
|
198
|
+
return load();
|
|
199
|
+
const prior = this.gpuLoadChain;
|
|
200
|
+
let release;
|
|
201
|
+
this.gpuLoadChain = new Promise((r) => {
|
|
202
|
+
release = r;
|
|
203
|
+
});
|
|
204
|
+
await prior.catch(() => { });
|
|
205
|
+
try {
|
|
206
|
+
return await load();
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
release();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Resolve an engine key to a live, initialized provider. Hits the
|
|
214
|
+
* cache; on miss, evicts LRU as needed to clear `residentBytes`,
|
|
215
|
+
* then builds via the injected builder. The cost of eviction
|
|
216
|
+
* (provider.shutdown) is awaited so the caller never returns to a
|
|
217
|
+
* partially-spawned state.
|
|
218
|
+
*/
|
|
219
|
+
async ensure(provider, modelId, replicaIdx, residentBytes, opts = {}) {
|
|
220
|
+
if (this.retiring) {
|
|
221
|
+
throw new Error('local engine pool retired after machine engine adoption');
|
|
222
|
+
}
|
|
223
|
+
await this.sweepFailedStarts();
|
|
224
|
+
const key = makeEngineKey(provider, modelId, replicaIdx);
|
|
225
|
+
const hit = this.entries.get(key);
|
|
226
|
+
if (hit && !hit.draining) {
|
|
227
|
+
hit.lastUsedAt = this.now();
|
|
228
|
+
return hit.provider;
|
|
229
|
+
}
|
|
230
|
+
if (hit?.draining) {
|
|
231
|
+
// The entry is being torn down to make room elsewhere. Handing
|
|
232
|
+
// it out would keep it busy forever (starvation); instead wait,
|
|
233
|
+
// on this caller's terms, for the eviction to settle, then
|
|
234
|
+
// rebuild below. If every drain gave up, or this caller's own
|
|
235
|
+
// wait ran out first, the entry survives — return it rather
|
|
236
|
+
// than double-building over a still-reserved key.
|
|
237
|
+
await this.waitForDrainToSettle(key, hit, opts);
|
|
238
|
+
const survived = this.entries.get(key);
|
|
239
|
+
if (survived) {
|
|
240
|
+
survived.lastUsedAt = this.now();
|
|
241
|
+
return survived.provider;
|
|
242
|
+
}
|
|
243
|
+
// Retirement may have started while this ensure was parked behind the
|
|
244
|
+
// drain. Never resurrect a user-owned engine after broker adoption.
|
|
245
|
+
if (this.retiring) {
|
|
246
|
+
throw new Error('local engine pool retired after machine engine adoption');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (this.retiring) {
|
|
250
|
+
throw new Error('local engine pool retired after machine engine adoption');
|
|
251
|
+
}
|
|
252
|
+
const pending = this.buildLocks.get(key);
|
|
253
|
+
if (pending)
|
|
254
|
+
return pending;
|
|
255
|
+
const build = this.buildEntry(provider, modelId, replicaIdx, residentBytes, opts).finally(() => {
|
|
256
|
+
// Identity-guarded like `evicting` below: a retry build started after
|
|
257
|
+
// this one settled must not be evicted by this one's cleanup.
|
|
258
|
+
if (this.buildLocks.get(key) === build)
|
|
259
|
+
this.buildLocks.delete(key);
|
|
260
|
+
});
|
|
261
|
+
this.buildLocks.set(key, build);
|
|
262
|
+
return build;
|
|
263
|
+
}
|
|
264
|
+
async buildEntry(provider, modelId, replicaIdx, residentBytes, opts) {
|
|
265
|
+
const builder = this.builders[provider];
|
|
266
|
+
if (!builder) {
|
|
267
|
+
throw new Error(`no ProviderBuilder registered for '${provider}'`);
|
|
268
|
+
}
|
|
269
|
+
// GPU-panic guard: refuse to spawn a fresh local GPU engine right after a
|
|
270
|
+
// macOS GPU-driver kernel panic so we don't re-trigger the crash loop.
|
|
271
|
+
// Denied the same way as a capacity denial (throw a user-readable reason);
|
|
272
|
+
// no-op off macOS / when no guard is wired. See gpu-panic-guard.ts.
|
|
273
|
+
const panicDecision = this.gpuPanicGuard?.check(provider);
|
|
274
|
+
if (panicDecision?.blocked) {
|
|
275
|
+
throw new Error(panicDecision.reason ?? 'Local models are paused after a recent GPU kernel panic.');
|
|
276
|
+
}
|
|
277
|
+
const evictedOwnEngine = await this.makeRoom(residentBytes, opts);
|
|
278
|
+
// A caller may wait a whole turn for room; the service can begin
|
|
279
|
+
// shutting down in that time, and must not get a new engine for it.
|
|
280
|
+
if (this.retiring) {
|
|
281
|
+
throw new Error('local engine pool retired after machine engine adoption');
|
|
282
|
+
}
|
|
283
|
+
const key = makeEngineKey(provider, modelId, replicaIdx);
|
|
284
|
+
// Pre-flight: makeRoom evicts what it can, but on a memory-tight
|
|
285
|
+
// machine a model larger than the whole budget can never fit (no
|
|
286
|
+
// amount of eviction helps). Deny BEFORE spawning so we don't load
|
|
287
|
+
// gigabytes of weights only to immediately tear them down — and
|
|
288
|
+
// surface a human-readable reason instead of a raw byte comparison.
|
|
289
|
+
if (!this.broker.canReserve(residentBytes)) {
|
|
290
|
+
const c = this.broker.committed();
|
|
291
|
+
log.error(capacityDenialLogLine(key, this.broker.denialReason(residentBytes)));
|
|
292
|
+
throw new CapacityDeniedError(formatCapacityDenial({
|
|
293
|
+
modelLabel: modelId,
|
|
294
|
+
requestedBytes: residentBytes,
|
|
295
|
+
budgetBytes: c.budgetBytes,
|
|
296
|
+
committedBytes: c.committedBytes,
|
|
297
|
+
systemRamBytes: c.systemRamBytes,
|
|
298
|
+
pools: c.pools,
|
|
299
|
+
coResidencyBytes: c.ramSpillover.coResidencyBytes,
|
|
300
|
+
}));
|
|
301
|
+
}
|
|
302
|
+
// A model larger than the card streams part of itself from system RAM,
|
|
303
|
+
// and how much stays on the card is the build's plan. Checked against
|
|
304
|
+
// the whole card instead, it was refused whenever anything else used the
|
|
305
|
+
// GPU, so it is checked after the build, against the plan.
|
|
306
|
+
const pools = this.broker.committed().pools;
|
|
307
|
+
const largerThanCard = pools.kind === 'discrete-gpu' && residentBytes > pools.fastBytes;
|
|
308
|
+
if (!largerThanCard) {
|
|
309
|
+
const measured = await this.measuredVramDenial(modelId, residentBytes, evictedOwnEngine);
|
|
310
|
+
if (measured) {
|
|
311
|
+
log.error(capacityDenialLogLine(key, measured.reason));
|
|
312
|
+
throw new CapacityDeniedError(measured.message);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
let built;
|
|
316
|
+
try {
|
|
317
|
+
built = await this.withGpuLoadSlot(() => builder({ modelId, replicaIdx }));
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
if (!(err instanceof CapacityDeniedError))
|
|
321
|
+
throw err;
|
|
322
|
+
// A supervised child may have released its physical memory while its
|
|
323
|
+
// provider entry deliberately retained a worst-case reservation for a
|
|
324
|
+
// lazy restart. Usually that paper guarantee is harmless. It must not,
|
|
325
|
+
// however, make a NEW model's context planner conclude the machine is
|
|
326
|
+
// full before ProviderPool gets the builder's context-inclusive byte
|
|
327
|
+
// estimate and can run its ordinary makeRoom pass.
|
|
328
|
+
//
|
|
329
|
+
// Reclaim stopped, idle entries only after a real capacity denial, then
|
|
330
|
+
// retry the non-binding build once. Running/warm engines stay intact;
|
|
331
|
+
// an intrinsically too-large target simply returns the retried denial.
|
|
332
|
+
const reclaimed = await this.reclaimReleasedReservations();
|
|
333
|
+
if (reclaimed <= 0)
|
|
334
|
+
throw err;
|
|
335
|
+
log.info(`reclaimed ${gb(reclaimed)} of released model reservations for ${key}; retrying admission`);
|
|
336
|
+
built = await this.withGpuLoadSlot(() => builder({ modelId, replicaIdx }));
|
|
337
|
+
}
|
|
338
|
+
if (largerThanCard) {
|
|
339
|
+
const gpuNeed = built.provider.plannedGpuBytes?.() ?? residentBytes;
|
|
340
|
+
const measured = await this.measuredVramDenial(modelId, gpuNeed, evictedOwnEngine);
|
|
341
|
+
if (measured) {
|
|
342
|
+
await built.provider.shutdown().catch((err) => {
|
|
343
|
+
log.warn(`shutdown after a graphics-memory denial for ${key}: ${err}`);
|
|
344
|
+
});
|
|
345
|
+
log.error(capacityDenialLogLine(key, measured.reason));
|
|
346
|
+
throw new CapacityDeniedError(measured.message);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// The builder's actual residentBytes wins if it differs from the
|
|
350
|
+
// pre-flight estimate (e.g. catalog override). Reserve the truth.
|
|
351
|
+
const finalBytes = built.residentBytes;
|
|
352
|
+
const r = this.broker.reserve(key, finalBytes);
|
|
353
|
+
if (!r.granted) {
|
|
354
|
+
// Reservation race: another concurrent build consumed budget
|
|
355
|
+
// between our makeRoom and reserve. Shut down what we just
|
|
356
|
+
// built, retry one more makeRoom + reserve loop.
|
|
357
|
+
await built.provider.shutdown().catch((err) => {
|
|
358
|
+
log.warn(`shutdown after failed reserve for ${key}: ${err}`);
|
|
359
|
+
});
|
|
360
|
+
await this.makeRoom(finalBytes, opts);
|
|
361
|
+
const r2 = this.broker.reserve(key, finalBytes);
|
|
362
|
+
if (!r2.granted) {
|
|
363
|
+
const c = this.broker.committed();
|
|
364
|
+
log.error(capacityDenialLogLine(key, r2.reason ?? this.broker.denialReason(finalBytes)));
|
|
365
|
+
throw new CapacityDeniedError(formatCapacityDenial({
|
|
366
|
+
modelLabel: modelId,
|
|
367
|
+
requestedBytes: finalBytes,
|
|
368
|
+
budgetBytes: c.budgetBytes,
|
|
369
|
+
committedBytes: c.committedBytes,
|
|
370
|
+
systemRamBytes: c.systemRamBytes,
|
|
371
|
+
pools: c.pools,
|
|
372
|
+
coResidencyBytes: c.ramSpillover.coResidencyBytes,
|
|
373
|
+
}));
|
|
374
|
+
}
|
|
375
|
+
// Re-build under the now-clear budget.
|
|
376
|
+
const rebuilt = await this.withGpuLoadSlot(() => builder({ modelId, replicaIdx }));
|
|
377
|
+
this.installEntry(key, provider, modelId, replicaIdx, rebuilt.provider, rebuilt.residentBytes, rebuilt.modelWeightsBytes);
|
|
378
|
+
return rebuilt.provider;
|
|
379
|
+
}
|
|
380
|
+
this.installEntry(key, provider, modelId, replicaIdx, built.provider, finalBytes, built.modelWeightsBytes);
|
|
381
|
+
return built.provider;
|
|
382
|
+
}
|
|
383
|
+
installEntry(key, provider, modelId, replicaIdx, instance, residentBytes, modelWeightsBytes) {
|
|
384
|
+
const at = this.now();
|
|
385
|
+
this.entries.set(key, {
|
|
386
|
+
parsed: { provider, modelId, replicaIdx },
|
|
387
|
+
provider: instance,
|
|
388
|
+
residentBytes,
|
|
389
|
+
...(typeof modelWeightsBytes === 'number' && Number.isFinite(modelWeightsBytes)
|
|
390
|
+
? { modelWeightsBytes: Math.max(0, modelWeightsBytes) }
|
|
391
|
+
: {}),
|
|
392
|
+
lastUsedAt: at,
|
|
393
|
+
createdAt: at,
|
|
394
|
+
draining: false,
|
|
395
|
+
drainClaims: 0,
|
|
396
|
+
recentHits: [at],
|
|
397
|
+
});
|
|
398
|
+
// Registration is lazy: most providers do not launch their native child
|
|
399
|
+
// until the first request. Calling this "spawned" made preflight logs
|
|
400
|
+
// claim an engine existed when only a pool entry had been installed.
|
|
401
|
+
log.info(`registered provider ${key} (${residentBytes} bytes)`);
|
|
402
|
+
this.fireChange();
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Mark a key as touched. Called by ChatManager after each turn
|
|
406
|
+
* so the LRU evictor doesn't kill the engine the user is
|
|
407
|
+
* actively using.
|
|
408
|
+
*/
|
|
409
|
+
touch(key) {
|
|
410
|
+
const entry = this.entries.get(key);
|
|
411
|
+
if (!entry)
|
|
412
|
+
return;
|
|
413
|
+
const now = this.now();
|
|
414
|
+
entry.lastUsedAt = now;
|
|
415
|
+
entry.recentHits.push(now);
|
|
416
|
+
pruneHits(entry, now);
|
|
417
|
+
}
|
|
418
|
+
/** Returns true if the pool currently holds an entry for `key`. */
|
|
419
|
+
has(key) {
|
|
420
|
+
return this.entries.has(key);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* True while a waiting request is draining `key` so another model can
|
|
424
|
+
* load. A turn bound to it that can rebind should step aside rather than
|
|
425
|
+
* start — see `SendAndWaitOpts.queue.yieldToSwap`.
|
|
426
|
+
*/
|
|
427
|
+
isDraining(key) {
|
|
428
|
+
return this.entries.get(key)?.draining === true;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Drop entries whose engine failed to start, releasing the budget they hold.
|
|
432
|
+
*
|
|
433
|
+
* The reservation is taken when the builder returns — before the engine
|
|
434
|
+
* process exists, because the engine starts lazily on the first turn. A
|
|
435
|
+
* start that then fails (memory admission refused, spawn error, panic
|
|
436
|
+
* guard) leaves an entry that owns its whole `residentBytes` while running
|
|
437
|
+
* nothing, and it is never reclaimed on its own: the idle timer that would
|
|
438
|
+
* eventually release it is only ever armed by an engine that reached
|
|
439
|
+
* `running`. Observed as a 9.7 GB reservation on a machine whose engine
|
|
440
|
+
* process count was zero, against an 11.2 GB budget.
|
|
441
|
+
*
|
|
442
|
+
* Eviction is the whole repair. The next `ensure` rebuilds, which re-plans
|
|
443
|
+
* the context window against memory as it stands then rather than handing
|
|
444
|
+
* back a provider that will fail the same way.
|
|
445
|
+
*/
|
|
446
|
+
async sweepFailedStarts() {
|
|
447
|
+
const dead = [];
|
|
448
|
+
for (const [key, entry] of this.entries) {
|
|
449
|
+
if (entry.draining || isBusy(entry))
|
|
450
|
+
continue;
|
|
451
|
+
const lifecycle = engineLifecycle(entry);
|
|
452
|
+
if (lifecycle?.startFailedAt !== undefined && !lifecycle.running)
|
|
453
|
+
dead.push(key);
|
|
454
|
+
}
|
|
455
|
+
for (const key of dead) {
|
|
456
|
+
try {
|
|
457
|
+
log.info(`releasing ${key}: engine never started`);
|
|
458
|
+
await this.evict(key);
|
|
459
|
+
}
|
|
460
|
+
catch (err) {
|
|
461
|
+
// A racing turn made it busy — the next sweep gets it.
|
|
462
|
+
log.warn(`sweepFailedStarts: ${key} not released: ${err instanceof Error ? err.message : String(err)}`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Evict pool entries whose supervised native child has already stopped.
|
|
468
|
+
* Their bytes are capacity guarantees, not physical residency. Keeping the
|
|
469
|
+
* wrapper cached is useful until another model actually needs that promise;
|
|
470
|
+
* a capacity denial is the pressure signal that makes the released entries
|
|
471
|
+
* expendable.
|
|
472
|
+
*/
|
|
473
|
+
async reclaimReleasedReservations() {
|
|
474
|
+
const candidates = [];
|
|
475
|
+
for (const [key, entry] of this.entries) {
|
|
476
|
+
if (entry.draining || isBusy(entry))
|
|
477
|
+
continue;
|
|
478
|
+
const lifecycle = engineLifecycle(entry);
|
|
479
|
+
if (lifecycle && !lifecycle.running) {
|
|
480
|
+
candidates.push({ key, bytes: entry.residentBytes });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (candidates.length === 0)
|
|
484
|
+
return 0;
|
|
485
|
+
const reclaimed = await Promise.all(candidates.map(async ({ key, bytes }) => {
|
|
486
|
+
try {
|
|
487
|
+
return (await this.unloadIdle(key)) ? bytes : 0;
|
|
488
|
+
}
|
|
489
|
+
catch (err) {
|
|
490
|
+
// A new turn may have claimed the provider after the lifecycle
|
|
491
|
+
// sample. Never drain that racing work merely to repair accounting;
|
|
492
|
+
// leave the entry resident and let the retried denial describe what
|
|
493
|
+
// is still unavailable.
|
|
494
|
+
log.warn(`released reservation ${key} could not be reclaimed: ${err instanceof Error ? err.message : String(err)}`);
|
|
495
|
+
return 0;
|
|
496
|
+
}
|
|
497
|
+
}));
|
|
498
|
+
return reclaimed.reduce((sum, bytes) => sum + bytes, 0);
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Immediately unload one resident engine, but only while it is idle.
|
|
502
|
+
*
|
|
503
|
+
* This is the user-triggered counterpart to the idle-retention timer. It
|
|
504
|
+
* deliberately refuses a busy engine instead of entering the ordinary
|
|
505
|
+
* bounded drain path: an "Unload now" click must never turn into a delayed
|
|
506
|
+
* teardown of work that started just after the status surface was sampled.
|
|
507
|
+
* Returns false when the engine has already gone away.
|
|
508
|
+
*/
|
|
509
|
+
async unloadIdle(key) {
|
|
510
|
+
const existingEviction = this.evicting.get(key);
|
|
511
|
+
if (existingEviction) {
|
|
512
|
+
await existingEviction;
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
const entry = this.entries.get(key);
|
|
516
|
+
if (!entry)
|
|
517
|
+
return false;
|
|
518
|
+
if (isBusy(entry)) {
|
|
519
|
+
throw new EngineBusyError(`engine ${key} is currently serving requests and cannot be unloaded yet. Wait for current turns to finish.`);
|
|
520
|
+
}
|
|
521
|
+
await this.evict(key);
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Unload every resident engine that is idle right now, leaving busy ones
|
|
526
|
+
* running. Returns the keys that stayed resident because they were serving
|
|
527
|
+
* a turn — the caller reports them; the ordinary LRU / idle-retention path
|
|
528
|
+
* collects them once they go quiet.
|
|
529
|
+
*
|
|
530
|
+
* This is what a live config reset uses. {@link shutdown} is the other
|
|
531
|
+
* shape — it force-evicts busy engines too — and is only correct when the
|
|
532
|
+
* process is going away (service shutdown, emergency stop), because a
|
|
533
|
+
* forced eviction kills whatever turn is streaming.
|
|
534
|
+
*/
|
|
535
|
+
async releaseIdle() {
|
|
536
|
+
const busy = [];
|
|
537
|
+
for (const key of [...this.entries.keys()]) {
|
|
538
|
+
try {
|
|
539
|
+
await this.unloadIdle(key);
|
|
540
|
+
}
|
|
541
|
+
catch (err) {
|
|
542
|
+
if (err instanceof EngineBusyError) {
|
|
543
|
+
busy.push(key);
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
log.warn(`releaseIdle: ${key} failed to unload: ${err instanceof Error ? err.message : String(err)}`);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return busy;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Evict a specific entry. Awaits the provider's `shutdown` so the
|
|
553
|
+
* disk-cache flush (Tier 1 prior plan) completes before the broker
|
|
554
|
+
* releases capacity.
|
|
555
|
+
*
|
|
556
|
+
* When the engine has in-flight or queued turns and `force` is not
|
|
557
|
+
* set, the entry is marked `draining` (no new `ensure` hits, no new
|
|
558
|
+
* binds) and the eviction waits up to the caller's `drainWaitMs` for
|
|
559
|
+
* the queue to empty. On timeout it throws a "model is busy" error
|
|
560
|
+
* instead of killing live work — the caller (typically `makeRoom` on
|
|
561
|
+
* behalf of a request for a *different* model) surfaces that as a
|
|
562
|
+
* clear temporary-failure to its own caller. `force: true` (service
|
|
563
|
+
* shutdown) skips the wait entirely.
|
|
564
|
+
*
|
|
565
|
+
* Parallel `evict` calls for the same key wait independently, each
|
|
566
|
+
* with its own deadline and signal, and join the same teardown.
|
|
567
|
+
*/
|
|
568
|
+
async evict(key, opts = {}) {
|
|
569
|
+
if (opts.force) {
|
|
570
|
+
const entry = this.entries.get(key);
|
|
571
|
+
return entry ? this.teardown(key, entry) : this.evicting.get(key);
|
|
572
|
+
}
|
|
573
|
+
const waitMs = opts.drainWaitMs ?? this.drainWaitMs;
|
|
574
|
+
const deadline = this.now() + waitMs;
|
|
575
|
+
for (;;) {
|
|
576
|
+
const entry = this.entries.get(key);
|
|
577
|
+
if (!entry) {
|
|
578
|
+
await this.evicting.get(key);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
// Idle check and teardown share a tick, so no turn can start between them.
|
|
582
|
+
if (!isBusy(entry))
|
|
583
|
+
return this.teardown(key, entry);
|
|
584
|
+
await this.drainFor(key, entry, waitMs, deadline, opts);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Hold `entry` draining until its queue empties, the entry is replaced,
|
|
589
|
+
* or this caller's deadline or signal ends the wait. The last caller to
|
|
590
|
+
* give up clears `draining`, so the engine serves hits again; a caller
|
|
591
|
+
* that saw it drain leaves the flag set for the teardown that follows.
|
|
592
|
+
*/
|
|
593
|
+
async drainFor(key, entry, waitMs, deadline, opts) {
|
|
594
|
+
entry.drainClaims += 1;
|
|
595
|
+
if (!entry.draining) {
|
|
596
|
+
entry.draining = true;
|
|
597
|
+
this.fireChange();
|
|
598
|
+
}
|
|
599
|
+
log.info(`evict ${key}: engine busy — draining (${Number.isFinite(waitMs) ? `cap ${waitMs}ms` : 'until idle'})`);
|
|
600
|
+
const notice = this.drainNotifier(key, entry, opts);
|
|
601
|
+
let drained = false;
|
|
602
|
+
try {
|
|
603
|
+
while (isBusy(entry)) {
|
|
604
|
+
// A force-evict (service shutdown) may have torn the entry
|
|
605
|
+
// down underneath this drain — if our entry is no longer the
|
|
606
|
+
// resident one, the eviction is done.
|
|
607
|
+
if (this.entries.get(key) !== entry)
|
|
608
|
+
return;
|
|
609
|
+
throwIfAborted(opts.signal);
|
|
610
|
+
if (this.now() >= deadline) {
|
|
611
|
+
throw new EngineBusyError(`engine ${key} is busy serving requests and did not drain within ${Math.round(waitMs / 1000)}s — not evicting. Retry shortly, or wait for current turns to finish.`);
|
|
612
|
+
}
|
|
613
|
+
notice();
|
|
614
|
+
await this.sleep(DRAIN_POLL_MS);
|
|
615
|
+
}
|
|
616
|
+
drained = true;
|
|
617
|
+
}
|
|
618
|
+
finally {
|
|
619
|
+
entry.drainClaims -= 1;
|
|
620
|
+
if (!drained && entry.drainClaims === 0 && this.entries.get(key) === entry) {
|
|
621
|
+
entry.draining = false;
|
|
622
|
+
this.fireChange();
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Wait for someone else's drain of `entry` to end — evicted, or given
|
|
628
|
+
* up — within this caller's own deadline and signal. Returning while
|
|
629
|
+
* the entry is still draining is the deadline: the caller takes the
|
|
630
|
+
* resident engine as it is.
|
|
631
|
+
*/
|
|
632
|
+
async waitForDrainToSettle(key, entry, opts) {
|
|
633
|
+
const deadline = this.now() + (opts.drainWaitMs ?? this.drainWaitMs);
|
|
634
|
+
const notice = this.drainNotifier(key, entry, opts);
|
|
635
|
+
while (this.entries.get(key) === entry && entry.draining) {
|
|
636
|
+
throwIfAborted(opts.signal);
|
|
637
|
+
if (this.now() >= deadline)
|
|
638
|
+
return;
|
|
639
|
+
notice();
|
|
640
|
+
await this.sleep(DRAIN_POLL_MS);
|
|
641
|
+
}
|
|
642
|
+
await this.evicting.get(key);
|
|
643
|
+
}
|
|
644
|
+
/** Rate-limited {@link EngineWaitOpts.onDrainWait}: once at the start, then every few seconds. */
|
|
645
|
+
drainNotifier(key, entry, opts) {
|
|
646
|
+
const notify = opts.onDrainWait;
|
|
647
|
+
if (!notify)
|
|
648
|
+
return () => { };
|
|
649
|
+
let lastAt = Number.NEGATIVE_INFINITY;
|
|
650
|
+
return () => {
|
|
651
|
+
const now = this.now();
|
|
652
|
+
if (now - lastAt < DRAIN_NOTICE_REPEAT_MS)
|
|
653
|
+
return;
|
|
654
|
+
lastAt = now;
|
|
655
|
+
try {
|
|
656
|
+
notify(drainWaitInfo(key, entry));
|
|
657
|
+
}
|
|
658
|
+
catch (err) {
|
|
659
|
+
log.warn(`onDrainWait threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Remove `entry` and shut its provider down. The removal is synchronous,
|
|
665
|
+
* so nothing can bind to it once this is called; the shutdown is shared
|
|
666
|
+
* by every caller evicting the same entry.
|
|
667
|
+
*/
|
|
668
|
+
teardown(key, entry) {
|
|
669
|
+
if (this.entries.get(key) !== entry)
|
|
670
|
+
return this.evicting.get(key) ?? Promise.resolve();
|
|
671
|
+
this.entries.delete(key);
|
|
672
|
+
const prior = this.evicting.get(key);
|
|
673
|
+
const run = (async () => {
|
|
674
|
+
await prior;
|
|
675
|
+
try {
|
|
676
|
+
await entry.provider.shutdown();
|
|
677
|
+
}
|
|
678
|
+
catch (err) {
|
|
679
|
+
log.warn(`shutdown threw for ${key}: ${err instanceof Error ? err.message : String(err)}`);
|
|
680
|
+
}
|
|
681
|
+
this.broker.release(key);
|
|
682
|
+
log.info(`evicted ${key}`);
|
|
683
|
+
this.fireChange();
|
|
684
|
+
})().finally(() => {
|
|
685
|
+
if (this.evicting.get(key) === run)
|
|
686
|
+
this.evicting.delete(key);
|
|
687
|
+
});
|
|
688
|
+
this.evicting.set(key, run);
|
|
689
|
+
return run;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Deny a spawn the card cannot physically take, whatever the ledger says.
|
|
693
|
+
*
|
|
694
|
+
* Runs after `makeRoom`, so everything this daemon was willing to release is
|
|
695
|
+
* already gone and the reading reflects what is genuinely left. Discrete
|
|
696
|
+
* cards only: on a unified host there is one pool, the RAM share already
|
|
697
|
+
* governs it, and the OS pages normally rather than falling off a cliff.
|
|
698
|
+
*
|
|
699
|
+
* A model larger than the card is deliberately streamed from system RAM, so
|
|
700
|
+
* the requirement is capped at the fast pool — otherwise this would refuse
|
|
701
|
+
* exactly the big-MoE case the two-pool budget was built to allow.
|
|
702
|
+
*/
|
|
703
|
+
async measuredVramDenial(modelId, residentBytes, waitForOwnedReclaim) {
|
|
704
|
+
const vramHeadroom = this.vramHeadroom;
|
|
705
|
+
if (!vramHeadroom)
|
|
706
|
+
return null;
|
|
707
|
+
const committed = this.broker.committed();
|
|
708
|
+
if (!committed.enforced || committed.pools.kind !== 'discrete-gpu')
|
|
709
|
+
return null;
|
|
710
|
+
const required = Math.min(residentBytes, committed.pools.fastBytes);
|
|
711
|
+
if (required <= 0)
|
|
712
|
+
return null;
|
|
713
|
+
const probe = async () => await vramHeadroom().catch((err) => {
|
|
714
|
+
log.debug(`vram headroom probe failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
715
|
+
return null;
|
|
716
|
+
});
|
|
717
|
+
let reading = await probe();
|
|
718
|
+
let freeBytes = reading?.freeBytes;
|
|
719
|
+
if (typeof freeBytes !== 'number' || !Number.isFinite(freeBytes))
|
|
720
|
+
return null;
|
|
721
|
+
if (freeBytes + MEASURED_VRAM_TOLERANCE_BYTES >= required)
|
|
722
|
+
return null;
|
|
723
|
+
if (waitForOwnedReclaim) {
|
|
724
|
+
const attempts = Math.ceil(MEASURED_VRAM_RECLAIM_WAIT_MS / MEASURED_VRAM_RECLAIM_POLL_MS);
|
|
725
|
+
log.info(`graphics memory still reports ${gb(freeBytes)} free after an owned engine eviction; ` +
|
|
726
|
+
`waiting up to ${MEASURED_VRAM_RECLAIM_WAIT_MS / 1_000}s for driver reclamation`);
|
|
727
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
728
|
+
await this.sleep(MEASURED_VRAM_RECLAIM_POLL_MS);
|
|
729
|
+
reading = await probe();
|
|
730
|
+
freeBytes = reading?.freeBytes;
|
|
731
|
+
// Preserve the guard's fail-open behavior when the device probe stops
|
|
732
|
+
// producing a usable reading during the reclaim window.
|
|
733
|
+
if (typeof freeBytes !== 'number' || !Number.isFinite(freeBytes))
|
|
734
|
+
return null;
|
|
735
|
+
if (freeBytes + MEASURED_VRAM_TOLERANCE_BYTES >= required) {
|
|
736
|
+
log.info(`graphics memory reclaimed after ${attempt * MEASURED_VRAM_RECLAIM_POLL_MS}ms ` +
|
|
737
|
+
`(${gb(freeBytes)} free)`);
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
const total = reading?.totalBytes;
|
|
743
|
+
const reason = measuredVramDenialReason(required, freeBytes);
|
|
744
|
+
const capacity = [
|
|
745
|
+
`Not enough graphics memory to load ${modelId} (about ${gb(required)} on the card). `,
|
|
746
|
+
`The graphics card has ${gb(freeBytes)} free`,
|
|
747
|
+
typeof total === 'number' && Number.isFinite(total) ? ` of ${gb(total)}` : '',
|
|
748
|
+
'. ',
|
|
749
|
+
].join('');
|
|
750
|
+
const message = waitForOwnedReclaim
|
|
751
|
+
? [
|
|
752
|
+
capacity,
|
|
753
|
+
`Gezel unloaded its previous model and waited ${MEASURED_VRAM_RECLAIM_WAIT_MS / 1_000} seconds, `,
|
|
754
|
+
'but the graphics driver has not made enough memory available yet. Wait a few seconds ',
|
|
755
|
+
'and try again. If this keeps happening, another program or a second Gezel engine may ',
|
|
756
|
+
'also be using the graphics card.',
|
|
757
|
+
].join('')
|
|
758
|
+
: [
|
|
759
|
+
capacity,
|
|
760
|
+
'Gezel has no other idle model in this engine left to unload, so another program, a ',
|
|
761
|
+
'second Gezel engine, or the graphics driver may be holding that memory. Close the other ',
|
|
762
|
+
'graphics-card workload, or wait a few seconds and try again.',
|
|
763
|
+
].join('');
|
|
764
|
+
return { reason, message };
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Evict entries until the broker reports headroom for `needed`
|
|
768
|
+
* bytes (or the pool is empty). Victim order: oldest *idle* entries
|
|
769
|
+
* first; only when every candidate is busy does it pick a busy one —
|
|
770
|
+
* one already draining for another caller first — whose eviction
|
|
771
|
+
* then drains on this caller's terms rather than killing in-flight
|
|
772
|
+
* turns. Pool-internal; callers never invoke directly.
|
|
773
|
+
*
|
|
774
|
+
* Idle victims are evicted *concurrently* (a model switch on a
|
|
775
|
+
* memory-tight box often has to clear several idle resident models
|
|
776
|
+
* to fit the incoming one): idle `shutdown()` doesn't drain, so the
|
|
777
|
+
* per-engine disk-cache flush of N victims runs in parallel instead
|
|
778
|
+
* of paying each one serially before the new model can spawn. The
|
|
779
|
+
* busy path stays serial to preserve the bounded-drain semantics.
|
|
780
|
+
*/
|
|
781
|
+
async makeRoom(needed, opts = {}) {
|
|
782
|
+
let evictedOwnEngine = false;
|
|
783
|
+
while (!this.broker.canReserve(needed) && this.entries.size > 0) {
|
|
784
|
+
const idleBatch = this.idleVictimsFor(needed);
|
|
785
|
+
if (idleBatch.length > 0) {
|
|
786
|
+
const evicted = await Promise.all(idleBatch.map(async (k) => {
|
|
787
|
+
try {
|
|
788
|
+
await this.evict(k);
|
|
789
|
+
return true;
|
|
790
|
+
}
|
|
791
|
+
catch (err) {
|
|
792
|
+
// Idle evictions shouldn't throw (no drain wait), but a
|
|
793
|
+
// shutdown() rejection must not abort the sibling evicts
|
|
794
|
+
// or the whole makeRoom — log and let the loop re-check.
|
|
795
|
+
log.warn(`makeRoom: idle evict ${k} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
796
|
+
return false;
|
|
797
|
+
}
|
|
798
|
+
}));
|
|
799
|
+
evictedOwnEngine ||= evicted.some(Boolean);
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
// No idle candidates — evict a single busy/draining victim. This
|
|
803
|
+
// path waits on the caller's terms (and may throw on a busy engine
|
|
804
|
+
// that won't drain in time, which propagates to the caller).
|
|
805
|
+
const victim = this.lruKey();
|
|
806
|
+
if (!victim) {
|
|
807
|
+
// Only teardowns are left in flight — wait for one to release
|
|
808
|
+
// its memory and re-check the budget.
|
|
809
|
+
if (this.evicting.size === 0)
|
|
810
|
+
break;
|
|
811
|
+
await Promise.race([...this.evicting.values()]).catch(() => { });
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
814
|
+
await this.evict(victim, opts);
|
|
815
|
+
evictedOwnEngine = true;
|
|
816
|
+
}
|
|
817
|
+
return evictedOwnEngine;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* The idle (non-busy, non-draining) eviction victims — oldest-first —
|
|
821
|
+
* whose combined `residentBytes`, once released, would give `needed`
|
|
822
|
+
* room to fit under the budget. Returns `[]` when there are no idle
|
|
823
|
+
* candidates (the caller then falls back to a single busy eviction)
|
|
824
|
+
* or when no eviction is required. Lets {@link makeRoom} batch idle
|
|
825
|
+
* evictions in parallel instead of one-at-a-time.
|
|
826
|
+
*/
|
|
827
|
+
idleVictimsFor(needed) {
|
|
828
|
+
// The broker owns the arithmetic: two constraints bind here (the total
|
|
829
|
+
// budget and, when RAM spillover is off, the co-residency ceiling) and
|
|
830
|
+
// sizing the batch against only the first left this returning no victims
|
|
831
|
+
// while `canReserve` stayed false — makeRoom would then fall through to
|
|
832
|
+
// evicting a BUSY engine instead of the idle ones sitting right there.
|
|
833
|
+
let deficit = this.broker.shortfallFor(needed);
|
|
834
|
+
if (deficit <= 0)
|
|
835
|
+
return [];
|
|
836
|
+
const now = this.now();
|
|
837
|
+
const idle = [];
|
|
838
|
+
for (const [key, entry] of this.entries) {
|
|
839
|
+
if (entry.draining)
|
|
840
|
+
continue;
|
|
841
|
+
if (isBusy(entry))
|
|
842
|
+
continue;
|
|
843
|
+
pruneHits(entry, now);
|
|
844
|
+
idle.push({
|
|
845
|
+
key,
|
|
846
|
+
at: entry.lastUsedAt,
|
|
847
|
+
bytes: entry.residentBytes,
|
|
848
|
+
demand: entry.recentHits.length,
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
// Demand-weighted LRU: evict the LEAST-recently-DEMANDED idle model first
|
|
852
|
+
// (fewest hits in the window), breaking ties by oldest `lastUsedAt`. Keeps
|
|
853
|
+
// a model that several tenants hit intermittently resident instead of
|
|
854
|
+
// dropping it just because one caller idled. Falls back to pure-oldest
|
|
855
|
+
// when demand is uniform (e.g. all single-hit), preserving prior behavior.
|
|
856
|
+
idle.sort((a, b) => a.demand - b.demand || a.at - b.at);
|
|
857
|
+
const out = [];
|
|
858
|
+
for (const v of idle) {
|
|
859
|
+
if (deficit <= 0)
|
|
860
|
+
break;
|
|
861
|
+
out.push(v.key);
|
|
862
|
+
deficit -= v.bytes;
|
|
863
|
+
}
|
|
864
|
+
return out;
|
|
865
|
+
}
|
|
866
|
+
lruKey() {
|
|
867
|
+
let oldestIdle = null;
|
|
868
|
+
let draining = null;
|
|
869
|
+
let oldestBusy = null;
|
|
870
|
+
for (const [key, entry] of this.entries) {
|
|
871
|
+
// Joining a drain already under way frees memory that is leaving
|
|
872
|
+
// anyway; starting a second one would unload more than needed.
|
|
873
|
+
if (entry.draining) {
|
|
874
|
+
draining ??= key;
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
877
|
+
if (isBusy(entry)) {
|
|
878
|
+
if (oldestBusy === null || entry.lastUsedAt < oldestBusy.at) {
|
|
879
|
+
oldestBusy = { key, at: entry.lastUsedAt };
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
else if (oldestIdle === null || entry.lastUsedAt < oldestIdle.at) {
|
|
883
|
+
oldestIdle = { key, at: entry.lastUsedAt };
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
return oldestIdle?.key ?? draining ?? oldestBusy?.key ?? null;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Shut down everything the pool owns. Used at service shutdown —
|
|
890
|
+
* forces eviction without waiting for busy engines to drain.
|
|
891
|
+
*/
|
|
892
|
+
async shutdown() {
|
|
893
|
+
this.retiring = true;
|
|
894
|
+
const keys = [...this.entries.keys()];
|
|
895
|
+
await Promise.all(keys.map((k) => this.evict(k, { force: true })));
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Permanently close the pool to new work, wait for builds already admitted,
|
|
899
|
+
* then drain every interactive and background queue before shutdown. Unlike
|
|
900
|
+
* service shutdown this never force-kills a turn and has no turn-length cap.
|
|
901
|
+
*/
|
|
902
|
+
async retire() {
|
|
903
|
+
if (this.retirementPromise)
|
|
904
|
+
return this.retirementPromise;
|
|
905
|
+
this.retiring = true;
|
|
906
|
+
const run = (async () => {
|
|
907
|
+
while (this.buildLocks.size > 0) {
|
|
908
|
+
await Promise.allSettled(Array.from(this.buildLocks.values()));
|
|
909
|
+
}
|
|
910
|
+
while (this.entries.size > 0) {
|
|
911
|
+
const keys = [...this.entries.keys()];
|
|
912
|
+
await Promise.all(keys.map((key) => this.evict(key, { drainWaitMs: Number.POSITIVE_INFINITY })));
|
|
913
|
+
}
|
|
914
|
+
})();
|
|
915
|
+
this.retirementPromise = run;
|
|
916
|
+
try {
|
|
917
|
+
await run;
|
|
918
|
+
}
|
|
919
|
+
catch (error) {
|
|
920
|
+
if (this.retirementPromise === run)
|
|
921
|
+
this.retirementPromise = null;
|
|
922
|
+
throw error;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Reconcile the resident set toward `target` — a map of
|
|
927
|
+
* `(provider, modelId) → desiredReplicaCount`. Spawns missing
|
|
928
|
+
* replicas (subject to capacity) and evicts replicas at indices
|
|
929
|
+
* `>= count`. Used by the UX layer when the user changes the
|
|
930
|
+
* clone-count picker.
|
|
931
|
+
*
|
|
932
|
+
* `ensureRes` resolves residentBytes for `(provider, modelId)`;
|
|
933
|
+
* typically a closure over the catalog.
|
|
934
|
+
*/
|
|
935
|
+
async reconcile(target, ensureRes) {
|
|
936
|
+
// 1. Evict replicas at indices >= desired clone count.
|
|
937
|
+
const wanted = new Set();
|
|
938
|
+
for (const { provider, modelId, clones } of target) {
|
|
939
|
+
for (let i = 0; i < clones; i++) {
|
|
940
|
+
wanted.add(makeEngineKey(provider, modelId, i));
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
// Be careful: only evict entries whose (provider, modelId)
|
|
944
|
+
// appears in `target` at all. Entries the caller didn't enumerate
|
|
945
|
+
// are pre-existing and left alone (typical chat-driven spawns).
|
|
946
|
+
const namedSet = new Set(target.map((t) => `${t.provider}:${t.modelId}`));
|
|
947
|
+
const toEvict = [];
|
|
948
|
+
for (const [key, entry] of this.entries) {
|
|
949
|
+
const fp = `${entry.parsed.provider}:${entry.parsed.modelId}`;
|
|
950
|
+
if (namedSet.has(fp) && !wanted.has(key))
|
|
951
|
+
toEvict.push(key);
|
|
952
|
+
}
|
|
953
|
+
for (const key of toEvict) {
|
|
954
|
+
try {
|
|
955
|
+
await this.evict(key);
|
|
956
|
+
}
|
|
957
|
+
catch (err) {
|
|
958
|
+
// Busy engine that didn't drain in time — leave it resident
|
|
959
|
+
// and carry on; the user can re-apply the clone change once
|
|
960
|
+
// its turns finish.
|
|
961
|
+
log.warn(`reconcile: could not evict ${key}: ${err instanceof Error ? err.message : String(err)}`);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
// 2. Spawn missing replicas (best-effort under capacity).
|
|
965
|
+
for (const { provider, modelId, clones } of target) {
|
|
966
|
+
for (let i = 0; i < clones; i++) {
|
|
967
|
+
const key = makeEngineKey(provider, modelId, i);
|
|
968
|
+
if (this.entries.has(key))
|
|
969
|
+
continue;
|
|
970
|
+
try {
|
|
971
|
+
await this.ensure(provider, modelId, i, ensureRes(provider, modelId));
|
|
972
|
+
}
|
|
973
|
+
catch (err) {
|
|
974
|
+
log.warn(`reconcile: failed to spawn ${key}: ${err instanceof Error ? err.message : String(err)}`);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* Pick a replica index to bind a new session to. Returns the
|
|
981
|
+
* least-loaded existing replica of `(provider, modelId)` based on
|
|
982
|
+
* an external `sessionsPerKey` map (the chat manager owns the
|
|
983
|
+
* tally; the pool stays state-free about sessions). If no replica
|
|
984
|
+
* exists, returns 0 so the caller spawns the first one.
|
|
985
|
+
*/
|
|
986
|
+
pickReplicaForBind(provider, modelId, sessionsPerKey) {
|
|
987
|
+
let bestIdx = -1;
|
|
988
|
+
let bestLoad = Number.POSITIVE_INFINITY;
|
|
989
|
+
for (const [key, entry] of this.entries) {
|
|
990
|
+
if (entry.parsed.provider !== provider)
|
|
991
|
+
continue;
|
|
992
|
+
if (entry.parsed.modelId !== modelId)
|
|
993
|
+
continue;
|
|
994
|
+
if (entry.draining)
|
|
995
|
+
continue; // being evicted — don't bind new sessions to it
|
|
996
|
+
const load = sessionsPerKey.get(key) ?? 0;
|
|
997
|
+
if (load < bestLoad) {
|
|
998
|
+
bestLoad = load;
|
|
999
|
+
bestIdx = entry.parsed.replicaIdx;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
return bestIdx >= 0 ? bestIdx : 0;
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Enumerate `(provider, modelId, replicaIdx)` triples currently
|
|
1006
|
+
* resident. The chat layer uses this to validate a session's
|
|
1007
|
+
* persisted `engineKey` after restart.
|
|
1008
|
+
*/
|
|
1009
|
+
resolveExisting(key) {
|
|
1010
|
+
const entry = this.entries.get(key);
|
|
1011
|
+
if (entry)
|
|
1012
|
+
return entry.parsed;
|
|
1013
|
+
return parseEngineKey(key);
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Existing replica indices for a `(provider, modelId)` pair,
|
|
1017
|
+
* sorted ascending. Used to discover "is replica 1 already
|
|
1018
|
+
* resident?" without scanning the whole pool from the outside.
|
|
1019
|
+
*/
|
|
1020
|
+
existingReplicas(provider, modelId) {
|
|
1021
|
+
const out = [];
|
|
1022
|
+
for (const entry of this.entries.values()) {
|
|
1023
|
+
if (entry.parsed.provider === provider && entry.parsed.modelId === modelId) {
|
|
1024
|
+
out.push(entry.parsed.replicaIdx);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
return out.sort((a, b) => a - b);
|
|
1028
|
+
}
|
|
1029
|
+
snapshot() {
|
|
1030
|
+
const committed = this.broker.committed();
|
|
1031
|
+
const entries = [];
|
|
1032
|
+
for (const [key, e] of this.entries) {
|
|
1033
|
+
const lifecycle = engineLifecycle(e);
|
|
1034
|
+
entries.push({
|
|
1035
|
+
key,
|
|
1036
|
+
provider: e.parsed.provider,
|
|
1037
|
+
modelId: e.parsed.modelId,
|
|
1038
|
+
replicaIdx: e.parsed.replicaIdx,
|
|
1039
|
+
residentBytes: e.residentBytes,
|
|
1040
|
+
...(e.modelWeightsBytes !== undefined ? { modelWeightsBytes: e.modelWeightsBytes } : {}),
|
|
1041
|
+
lastUsedAt: e.lastUsedAt,
|
|
1042
|
+
createdAt: e.createdAt,
|
|
1043
|
+
draining: e.draining,
|
|
1044
|
+
...(lifecycle ? { lifecycle } : {}),
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
return {
|
|
1048
|
+
entries: entries.sort((a, b) => a.key.localeCompare(b.key)),
|
|
1049
|
+
committedBytes: committed.committedBytes,
|
|
1050
|
+
budgetBytes: committed.budgetBytes,
|
|
1051
|
+
enforced: committed.enforced,
|
|
1052
|
+
systemRamBytes: committed.systemRamBytes,
|
|
1053
|
+
autoBudgetBytes: committed.autoBudgetBytes,
|
|
1054
|
+
overridden: committed.overridden,
|
|
1055
|
+
pools: committed.pools,
|
|
1056
|
+
ramSpillover: committed.ramSpillover,
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Return already-created replicas for one exact model without allocating,
|
|
1061
|
+
* initializing, touching LRU state, or evicting anything. Cache warming and
|
|
1062
|
+
* telemetry use this peek so a read-like request cannot cold-start an engine.
|
|
1063
|
+
*/
|
|
1064
|
+
peekProvidersForModel(provider, modelId) {
|
|
1065
|
+
return [...this.entries.values()]
|
|
1066
|
+
.filter((entry) => !entry.draining && entry.parsed.provider === provider && entry.parsed.modelId === modelId)
|
|
1067
|
+
.sort((a, b) => b.lastUsedAt - a.lastUsedAt)
|
|
1068
|
+
.map((entry) => entry.provider);
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* Fold every resident replica's live queue into one summary per
|
|
1072
|
+
* {@link LocalProviderName}. Under the pool architecture local
|
|
1073
|
+
* providers aren't seeded as singletons in `ChatManager.providers`, so
|
|
1074
|
+
* `/api/queues` — which reads only `getProviderIfReady(name).queue` —
|
|
1075
|
+
* otherwise misses ALL pooled work: chat turns and background one-shots
|
|
1076
|
+
* alike (weekly digest, about.md drafts, memory extraction). That blind
|
|
1077
|
+
* spot is what made the engine pill read "Idle" while a one-shot decoded
|
|
1078
|
+
* on the GPU.
|
|
1079
|
+
*
|
|
1080
|
+
* Counts sum across a provider's replicas; `active` / `pending` (with
|
|
1081
|
+
* their job labels) concatenate. Draining replicas are included — they
|
|
1082
|
+
* can still be finishing in-flight turns. Replicas whose provider
|
|
1083
|
+
* exposes no queue (cloud, test fakes) contribute nothing.
|
|
1084
|
+
*/
|
|
1085
|
+
/**
|
|
1086
|
+
* Launch provenance of every pooled provider whose engine process is
|
|
1087
|
+
* live right now — provider + model attribution from the pool key, the
|
|
1088
|
+
* snapshot (pid, start time, granted context) from the provider's
|
|
1089
|
+
* supervisor. Providers without a supervised engine contribute nothing.
|
|
1090
|
+
*/
|
|
1091
|
+
engineLaunchSnapshots() {
|
|
1092
|
+
const out = [];
|
|
1093
|
+
for (const entry of this.entries.values()) {
|
|
1094
|
+
const snapshot = entry.provider.engineLaunchSnapshot?.();
|
|
1095
|
+
if (!snapshot)
|
|
1096
|
+
continue;
|
|
1097
|
+
out.push({ provider: entry.parsed.provider, modelId: entry.parsed.modelId, snapshot });
|
|
1098
|
+
}
|
|
1099
|
+
return out;
|
|
1100
|
+
}
|
|
1101
|
+
queueSummaries() {
|
|
1102
|
+
const out = new Map();
|
|
1103
|
+
for (const entry of this.entries.values()) {
|
|
1104
|
+
const q = entry.provider.queue;
|
|
1105
|
+
if (!q)
|
|
1106
|
+
continue;
|
|
1107
|
+
const d = q.describe();
|
|
1108
|
+
const name = entry.parsed.provider;
|
|
1109
|
+
const cur = out.get(name) ?? emptyPooledQueueSummary();
|
|
1110
|
+
cur.running += d.running;
|
|
1111
|
+
cur.runningInteractive += d.runningInteractive;
|
|
1112
|
+
cur.runningBackground += d.runningBackground;
|
|
1113
|
+
cur.queuedInteractive += d.queuedInteractive;
|
|
1114
|
+
cur.queuedBackground += d.queuedBackground;
|
|
1115
|
+
cur.ambientHeld += d.ambientHeld;
|
|
1116
|
+
cur.concurrency += d.concurrency;
|
|
1117
|
+
cur.interactiveConcurrency += d.interactiveConcurrency;
|
|
1118
|
+
cur.backgroundConcurrency += d.backgroundConcurrency;
|
|
1119
|
+
cur.maxConcurrency += liveProviderConcurrency(entry.provider);
|
|
1120
|
+
cur.active.push(...d.active);
|
|
1121
|
+
cur.pending.push(...d.pending);
|
|
1122
|
+
out.set(name, cur);
|
|
1123
|
+
}
|
|
1124
|
+
return out;
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Cancel a pending queue entry on whichever resident replica of
|
|
1128
|
+
* `provider` holds it — the write side of {@link queueSummaries},
|
|
1129
|
+
* which the singleton `getProviderIfReady` path can't reach for
|
|
1130
|
+
* pool-routed local engines. Queue ids are replica-local (each
|
|
1131
|
+
* {@link ProviderQueue} counts from 1), so we cancel on the first
|
|
1132
|
+
* replica of this provider whose queue knows the id; in the common
|
|
1133
|
+
* single-replica case that is unambiguous, and a stale id simply
|
|
1134
|
+
* matches nothing. Returns true when an entry was removed.
|
|
1135
|
+
*/
|
|
1136
|
+
cancelPendingQueueItem(provider, id) {
|
|
1137
|
+
for (const entry of this.entries.values()) {
|
|
1138
|
+
if (entry.parsed.provider !== provider)
|
|
1139
|
+
continue;
|
|
1140
|
+
if (entry.provider.queue?.cancelPending(id))
|
|
1141
|
+
return true;
|
|
1142
|
+
}
|
|
1143
|
+
return false;
|
|
1144
|
+
}
|
|
1145
|
+
/** Reorder a pending queue entry across this provider's replicas. See
|
|
1146
|
+
* {@link cancelPendingQueueItem} for the id-matching contract. */
|
|
1147
|
+
movePendingQueueItem(provider, id, direction) {
|
|
1148
|
+
for (const entry of this.entries.values()) {
|
|
1149
|
+
if (entry.parsed.provider !== provider)
|
|
1150
|
+
continue;
|
|
1151
|
+
if (entry.provider.queue?.movePending(id, direction))
|
|
1152
|
+
return true;
|
|
1153
|
+
}
|
|
1154
|
+
return false;
|
|
1155
|
+
}
|
|
1156
|
+
fireChange() {
|
|
1157
|
+
if (!this.onChange)
|
|
1158
|
+
return;
|
|
1159
|
+
try {
|
|
1160
|
+
this.onChange(this.snapshot());
|
|
1161
|
+
}
|
|
1162
|
+
catch (err) {
|
|
1163
|
+
log.warn(`onChange listener threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|