@bendyline/gezel-inference 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog/chat-models/de/deepseek-v4.1-flash-552b-q2/manifest.json +120 -0
- package/dist/catalog/chat-models/de/deepseek-v4.1-flash-552b-q2/versions/1.0.0/manifest.json +21 -0
- package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/manifest.json +6 -5
- package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/versions/1.0.2/manifest.json +27 -0
- package/dist/catalog/chat-models/gl/glm-5.3-flash-320b-q2/versions/1.0.3/manifest.json +27 -0
- package/dist/catalog/chat-models/index.json +1 -1
- package/dist/catalog/chat-models/ne/nemotron3.5-bolt-74b-iq2/manifest.json +157 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-bolt-74b-iq2/versions/1.0.0/manifest.json +30 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-super-vl-120b-nvfp4/manifest.json +156 -0
- package/dist/catalog/chat-models/ne/nemotron3.5-super-vl-120b-nvfp4/versions/1.0.0/manifest.json +28 -0
- package/dist/catalog/chat-models/raw-index.json +1 -1
- package/dist/catalog/knowledge-catalogs/be/bendyline-how-to-books/keywords.json +56 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-alaska-part-0001/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-nevada-part-0001/keywords.json +13 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-us-300-399-part-0001/keywords.json +14 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-us-347-349/keywords.json +17 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0001/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-utah-part-0002/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0001/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0002/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0003/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0004/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-washington-part-0005/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/ca/caselaw-wyoming-part-0001/keywords.json +12 -0
- package/dist/catalog/knowledge-catalogs/index.json +1 -1
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-aspnet-core-en/keywords.json +21 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-ai-platform-en/keywords.json +27 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-apps-compute-en/keywords.json +23 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-data-aiot-en/keywords.json +26 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-management-hybrid-en/keywords.json +28 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-azure-network-security-en/keywords.json +29 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-dotnet-en/keywords.json +21 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-entity-framework-en/keywords.json +14 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-microsoft-365-en/keywords.json +20 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-powershell-en/keywords.json +24 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-sql-server-en/keywords.json +27 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-apps-en/keywords.json +18 -0
- package/dist/catalog/knowledge-catalogs/mi/microsoftdocs-windows-server-en/keywords.json +28 -0
- package/dist/catalog/knowledge-catalogs/raw-index.json +1 -1
- package/dist/catalog/knowledge-catalogs/re/regional-american-south/keywords.json +1700 -0
- package/dist/catalog/knowledge-catalogs/re/regional-american-south/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/keywords.json +750 -0
- package/dist/catalog/knowledge-catalogs/re/regional-andes-amazon/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/keywords.json +1281 -0
- package/dist/catalog/knowledge-catalogs/re/regional-australia-nz/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-brazil/keywords.json +1125 -0
- package/dist/catalog/knowledge-catalogs/re/regional-brazil/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/keywords.json +3287 -0
- package/dist/catalog/knowledge-catalogs/re/regional-britain-ireland/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/keywords.json +1835 -0
- package/dist/catalog/knowledge-catalogs/re/regional-california-southwest/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/keywords.json +1184 -0
- package/dist/catalog/knowledge-catalogs/re/regional-canada-alaska/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/keywords.json +1503 -0
- package/dist/catalog/knowledge-catalogs/re/regional-central-eastern-europe/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-asia/keywords.json +2836 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-asia/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/keywords.json +813 -0
- package/dist/catalog/knowledge-catalogs/re/regional-east-southern-africa/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/keywords.json +2082 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mediterranean/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/keywords.json +1481 -0
- package/dist/catalog/knowledge-catalogs/re/regional-mexico-central-america/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-middle-east/keywords.json +1272 -0
- package/dist/catalog/knowledge-catalogs/re/regional-middle-east/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-midwest/keywords.json +758 -0
- package/dist/catalog/knowledge-catalogs/re/regional-midwest/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-north-africa/keywords.json +896 -0
- package/dist/catalog/knowledge-catalogs/re/regional-north-africa/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northeast/keywords.json +1281 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northeast/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/keywords.json +346 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-eurasia/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/keywords.json +2688 -0
- package/dist/catalog/knowledge-catalogs/re/regional-northern-europe/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/keywords.json +973 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-islands/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/keywords.json +937 -0
- package/dist/catalog/knowledge-catalogs/re/regional-pacific-northwest/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/keywords.json +608 -0
- package/dist/catalog/knowledge-catalogs/re/regional-rockies-plains/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-south-asia/keywords.json +633 -0
- package/dist/catalog/knowledge-catalogs/re/regional-south-asia/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/keywords.json +2697 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southeast-asia/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/keywords.json +606 -0
- package/dist/catalog/knowledge-catalogs/re/regional-southern-cone/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/keywords.json +564 -0
- package/dist/catalog/knowledge-catalogs/re/regional-west-central-africa/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe/keywords.json +3247 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe-east/manifest.json +47 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe-east/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe-west/manifest.json +47 -0
- package/dist/catalog/knowledge-catalogs/re/regional-western-europe-west/versions/2026.10.5/manifest.json +133 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/keywords.json +5437 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.10.1/manifest.json +181 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/keywords.json +4009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.10.1/manifest.json +181 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/keywords.json +4009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/versions/2026.10.1/manifest.json +217 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/keywords.json +5583 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/versions/2026.10.1/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/keywords.json +6386 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/manifest.json +2 -2
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/versions/2026.10.1/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/keywords.json +4009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.10.1/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/keywords.json +5672 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.10.1/manifest.json +137 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-geography/manifest.json +68 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-geography/versions/2026.10.1/manifest.json +217 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-history/manifest.json +68 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-history/versions/2026.10.1/manifest.json +217 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/keywords.json +4009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.10.1/manifest.json +141 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/keywords.json +4009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.10.1/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/keywords.json +5719 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/versions/2026.10.1/manifest.json +193 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/keywords.json +4009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.10.1/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/keywords.json +16009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.10.1/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/keywords.json +5843 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/versions/2026.10.1/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/keywords.json +6264 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/versions/2026.10.1/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-arts/manifest.json +66 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-arts/versions/2026.10.1/manifest.json +209 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-business/manifest.json +61 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-business/versions/2026.10.1/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-entertainment/manifest.json +64 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-entertainment/versions/2026.10.1/manifest.json +201 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-military/manifest.json +60 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-military/versions/2026.10.1/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-other/manifest.json +55 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-other/versions/2026.10.1/manifest.json +165 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-politics/manifest.json +63 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-politics/versions/2026.10.1/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-religion/manifest.json +64 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-religion/versions/2026.10.1/manifest.json +201 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-science/manifest.json +65 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-science/versions/2026.10.1/manifest.json +205 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-sports/manifest.json +73 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-sports/versions/2026.10.1/manifest.json +237 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/keywords.json +5447 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/versions/2026.10.1/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/keywords.json +4009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.10.1/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/keywords.json +4009 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.10.1/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/keywords.json +5209 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/versions/2026.10.1/manifest.json +193 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/keywords.json +6537 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/versions/2026.10.1/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/keywords.json +5989 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/manifest.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/versions/2026.10.1/manifest.json +189 -0
- package/dist/catalog/provenance.json +1 -1
- package/dist/engines/native-file-manifest.json +483 -413
- package/dist/engines/native-manifest.d.ts +4 -4
- package/dist/engines/native-manifest.js +36 -34
- package/dist/engines/resolver.js +3 -1
- package/dist/fs/atomic.d.ts +4 -1
- package/dist/fs/atomic.js +7 -1
- package/dist/http/openai-compat/chat-target.d.ts +1 -1
- package/dist/http/openai-compat/chat-target.js +1 -1
- package/dist/http/openai-compat/engine-failure.d.ts +25 -0
- package/dist/http/openai-compat/engine-failure.js +76 -0
- package/dist/http/openai-compat/responses-streaming.js +2 -1
- package/dist/http/openai-compat/responses-translate.d.ts +1 -1
- package/dist/http/openai-compat/translate.d.ts +1 -1
- package/dist/http/routes/engines.js +35 -0
- package/dist/http/routes/v1-chat.js +11 -2
- package/dist/http/routes/v1-knowledge.js +4 -0
- package/dist/http/routes/v1-models.js +6 -4
- package/dist/http/routes/v1-responses.d.ts +1 -1
- package/dist/http/routes/v1-responses.js +7 -1
- package/dist/inference-service.d.ts +6 -1
- package/dist/inference-service.js +20 -9
- package/dist/knowledge/catalog-host.d.ts +9 -1
- package/dist/knowledge/catalog-host.js +2 -0
- package/dist/knowledge/manager.d.ts +21 -0
- package/dist/knowledge/manager.js +85 -7
- package/dist/knowledge/search-worker.d.ts +1 -1
- package/dist/knowledge/spatial-query.d.ts +2 -3
- package/dist/knowledge/spatial-query.js +12 -6
- package/dist/knowledge/worker-host.js +2 -0
- package/dist/memory/embed-core.d.ts +16 -0
- package/dist/memory/embed-core.js +31 -0
- package/dist/memory/embed-worker.d.ts +7 -3
- package/dist/memory/embed-worker.js +13 -4
- package/dist/memory/embeddings.d.ts +17 -2
- package/dist/memory/embeddings.js +36 -7
- package/dist/models/ensure.d.ts +2 -0
- package/dist/models/ensure.js +9 -0
- package/dist/perf/responsiveness.d.ts +14 -1
- package/dist/perf/responsiveness.js +81 -10
- package/dist/providers/audio/kokoro-frontend.js +1 -1
- package/dist/providers/ds4/build-provider.js +6 -0
- package/dist/providers/llama-cpp/backend-health.d.ts +30 -0
- package/dist/providers/llama-cpp/backend-health.js +64 -0
- package/dist/providers/llama-cpp/backend-quarantine.d.ts +40 -0
- package/dist/providers/llama-cpp/backend-quarantine.js +100 -0
- package/dist/providers/llama-cpp/build-provider.js +247 -199
- package/dist/providers/llama-cpp/cache-adapter.d.ts +7 -1
- package/dist/providers/llama-cpp/cache-adapter.js +11 -1
- package/dist/providers/llama-cpp/devices.d.ts +22 -2
- package/dist/providers/llama-cpp/devices.js +48 -5
- package/dist/providers/llama-cpp/engine-flags.d.ts +0 -18
- package/dist/providers/llama-cpp/engine-flags.js +12 -18
- package/dist/providers/llama-cpp/gguf-metadata.js +20 -3
- package/dist/providers/llama-cpp/gpu-startup-watch.d.ts +41 -0
- package/dist/providers/llama-cpp/gpu-startup-watch.js +58 -0
- package/dist/providers/llama-cpp/models.d.ts +6 -0
- package/dist/providers/llama-cpp/models.js +23 -2
- package/dist/providers/llama-cpp/offload-planner.d.ts +26 -18
- package/dist/providers/llama-cpp/offload-planner.js +30 -14
- package/dist/providers/llama-cpp/provider.d.ts +22 -3
- package/dist/providers/llama-cpp/provider.js +39 -3
- package/dist/providers/mlx/provider.js +5 -6
- package/dist/providers/mlx/python/qwen4_ple.py +9 -2
- package/dist/providers/mlx/reasoning-stream.d.ts +15 -0
- package/dist/providers/mlx/reasoning-stream.js +35 -0
- package/dist/providers/native/capacity-broker.d.ts +21 -15
- package/dist/providers/native/capacity-broker.js +25 -13
- package/dist/providers/native/capacity-budget.d.ts +35 -3
- package/dist/providers/native/capacity-budget.js +49 -5
- package/dist/providers/native/device-capacity.d.ts +1 -1
- package/dist/providers/native/device-capacity.js +23 -5
- package/dist/providers/native/local-engine-runtime.js +31 -31
- package/dist/providers/native/measured-budget.js +2 -0
- package/dist/providers/native/supervisor.d.ts +25 -0
- package/dist/providers/native/supervisor.js +62 -8
- package/dist/providers/queue.d.ts +9 -2
- package/dist/providers/queue.js +17 -2
- package/dist/providers/session-hooks.d.ts +4 -1
- package/dist/system/amdgpu-adapters.d.ts +18 -0
- package/dist/system/amdgpu-adapters.js +55 -0
- package/dist/system/gpu-carve-out.d.ts +84 -0
- package/dist/system/gpu-carve-out.js +111 -0
- package/dist/system/memory.d.ts +17 -1
- package/dist/system/memory.js +94 -13
- package/dist/transformers-cache.d.ts +2 -0
- package/dist/transformers-cache.js +6 -3
- package/package.json +5 -5
|
@@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { readdir, stat } from 'node:fs/promises';
|
|
3
3
|
import { homedir, totalmem } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
-
import { GEZEL_VERSION, NativeCapacityCommandSchema, NativeCapacityReplySchema, awakeNow, createLogger, isUnstampedDevBuild, } from '@bendyline/gezel';
|
|
5
|
+
import { DS4_FULL_RESIDENCY_HEADROOM_BYTES, GEZEL_VERSION, NativeCapacityCommandSchema, NativeCapacityReplySchema, awakeNow, createLogger, isUnstampedDevBuild, } from '@bendyline/gezel';
|
|
6
6
|
import { readSystemServiceRuntime, systemServiceHome } from '@bendyline/gezel-client/node';
|
|
7
7
|
import { ConfigStore } from '../../fs/config-store.js';
|
|
8
8
|
import { createPinnedFetch } from '../../remotes/pinned-fetch.js';
|
|
@@ -119,21 +119,39 @@ export function configuredEngineMemoryBytes(config) {
|
|
|
119
119
|
? config.localEngineMemoryGb * GIB
|
|
120
120
|
: undefined;
|
|
121
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* GPU bytes a unified host may commit to one launch. macOS keeps 0.75 × RAM,
|
|
124
|
+
* near where Metal's recommended GPU working set sits. Linux unified hosts
|
|
125
|
+
* (DGX Spark GB10) have no such limit, so a large one may commit all but the
|
|
126
|
+
* OS reserve ds4's residency gate keeps: on a 121.6 GiB Spark, 0.75 × RAM
|
|
127
|
+
* (91.2 GiB) refused a GLM 5.3 Q2 launch that runs at 105 GiB with ~9 GiB to
|
|
128
|
+
* spare. Smaller Linux hosts stay on the 0.75 curve, which is the larger one there.
|
|
129
|
+
*/
|
|
130
|
+
function unifiedGpuCeilingBytes(ramBytes, platform) {
|
|
131
|
+
const curve = ramBytes * 0.75;
|
|
132
|
+
return platform === 'linux'
|
|
133
|
+
? Math.max(curve, ramBytes - DS4_FULL_RESIDENCY_HEADROOM_BYTES)
|
|
134
|
+
: curve;
|
|
135
|
+
}
|
|
122
136
|
/**
|
|
123
137
|
* The ledger's static ceilings: a request above either is refused at acquire,
|
|
124
138
|
* whatever else is running. Shared with the media fit check so a model the
|
|
125
139
|
* download pages hide is exactly one the launch path refuses. Omit
|
|
126
140
|
* `configuredBytes` for the machine's automatic ceilings.
|
|
127
141
|
*/
|
|
128
|
-
export function staticCapacityCeilings(budget, ramBytes, configuredBytes) {
|
|
142
|
+
export function staticCapacityCeilings(budget, ramBytes, configuredBytes, platform = process.platform) {
|
|
129
143
|
const budgetBytes = configuredBytes === undefined
|
|
130
144
|
? budget.budgetBytes
|
|
131
145
|
: Math.min(configuredBytes, budget.budgetBytes);
|
|
132
146
|
return {
|
|
133
147
|
budgetBytes,
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
|
|
148
|
+
// Non-reclaimable accelerator commitments get their own ceiling: a larger
|
|
149
|
+
// RAM budget is not permission to wire the whole machine. An integrated
|
|
150
|
+
// GPU's carve-out (`vramBytes` on a unified host) is already the GPU's,
|
|
151
|
+
// and sits outside `ramBytes`.
|
|
152
|
+
gpuBudgetBytes: Math.min(budgetBytes, budget.kind === 'unified'
|
|
153
|
+
? Math.min(budget.fastBytes, unifiedGpuCeilingBytes(ramBytes, platform) + budget.vramBytes)
|
|
154
|
+
: budget.fastBytes),
|
|
137
155
|
};
|
|
138
156
|
}
|
|
139
157
|
export async function sampleDeviceCapacity(home) {
|
|
@@ -223,11 +223,19 @@ export class LocalEngineRuntime {
|
|
|
223
223
|
return null;
|
|
224
224
|
if (this.engineRouterInitPromise)
|
|
225
225
|
return this.engineRouterInitPromise;
|
|
226
|
-
|
|
226
|
+
const pending = this.buildEngineRouter().then((r) => {
|
|
227
227
|
this.engineRouterCache = r;
|
|
228
228
|
return r;
|
|
229
|
+
}, (err) => {
|
|
230
|
+
// A failed build must not be cached. One that ran while a dev rebuild
|
|
231
|
+
// had emptied dist/ failed every later local turn with "Cannot find
|
|
232
|
+
// module …engine-router.js" until the app restarted (2026-10-19).
|
|
233
|
+
if (this.engineRouterInitPromise === pending)
|
|
234
|
+
this.engineRouterInitPromise = null;
|
|
235
|
+
throw err;
|
|
229
236
|
});
|
|
230
|
-
|
|
237
|
+
this.engineRouterInitPromise = pending;
|
|
238
|
+
return pending;
|
|
231
239
|
}
|
|
232
240
|
async buildEngineRouter() {
|
|
233
241
|
const { EngineRouter } = await import('./engine-router.js');
|
|
@@ -260,6 +268,8 @@ export class LocalEngineRuntime {
|
|
|
260
268
|
? {
|
|
261
269
|
unifiedMemory: memoryProfile.gpuMemoryKind === 'integrated' ||
|
|
262
270
|
memoryProfile.gpuMemoryKind === 'unified',
|
|
271
|
+
reservedGpuBytes: memoryProfile.gpuReservedBytes ?? null,
|
|
272
|
+
gpuAddressableBytes: memoryProfile.gpuAddressableBytes ?? null,
|
|
263
273
|
}
|
|
264
274
|
: {}),
|
|
265
275
|
allowRamSpillover: config.allowRamSpillover ?? null,
|
|
@@ -1134,17 +1144,12 @@ export class LocalEngineRuntime {
|
|
|
1134
1144
|
const manifestEngineConfig = await resolveCatalogLlamaCppEngineConfig(this.catalog, modelId);
|
|
1135
1145
|
const perModelCtxOverride = config.modelContextOverrides?.[`llama-cpp:${modelId}`];
|
|
1136
1146
|
const explicitContextWindow = envNumCtx ?? perModelCtxOverride ?? config.llamaCppNumCtx;
|
|
1137
|
-
//
|
|
1138
|
-
//
|
|
1139
|
-
// the request back to 64K. Env / machine-wide values keep their
|
|
1140
|
-
// historical floor semantics. Mirrors buildLlamaCppProvider.
|
|
1147
|
+
// The shared resolver honors every explicit numeric context below the
|
|
1148
|
+
// host floor. Keep per-model override state for the Settings auto marker.
|
|
1141
1149
|
const overrideActive = perModelCtxOverride !== undefined && explicitContextWindow === perModelCtxOverride;
|
|
1142
|
-
const minViableTokens = overrideActive
|
|
1143
|
-
? Math.min(contextFloor, perModelCtxOverride)
|
|
1144
|
-
: contextFloor;
|
|
1145
1150
|
const contextRequirement = resolveLlamaCppContextRequirement({
|
|
1146
1151
|
modelContextWindow: installed.contextWindow,
|
|
1147
|
-
minViableContextTokens:
|
|
1152
|
+
minViableContextTokens: contextFloor,
|
|
1148
1153
|
...(explicitContextWindow !== undefined ? { explicitContextWindow } : {}),
|
|
1149
1154
|
...(manifestEngineConfig?.contextSize !== undefined
|
|
1150
1155
|
? {
|
|
@@ -1160,8 +1165,8 @@ export class LocalEngineRuntime {
|
|
|
1160
1165
|
// per-model override deliberately does NOT short-circuit on a resident
|
|
1161
1166
|
// engine: the full plan must run so a stale resident window surfaces as
|
|
1162
1167
|
// restart-required instead of masquerading as the applied setting.
|
|
1163
|
-
const shortCircuit =
|
|
1164
|
-
const {
|
|
1168
|
+
const shortCircuit = residentContextWindow !== undefined && !overrideActive;
|
|
1169
|
+
const { defaultLocalEngineSlots, estimatePerSlotKvBytes, kvQuantScale, llamaCppSlotCeiling, planAdaptiveContextGrowth, planCtxTokensForMemory, plannedLocalEngineSlots, } = await import('./capacity-broker.js');
|
|
1165
1170
|
const capacity = await this.previewCapacityInputs('llama-cpp', modelId, capacityOpts);
|
|
1166
1171
|
const { budgetBytes: admissionBudgetBytes, fastBudgetBytes, committedOtherBytes } = capacity;
|
|
1167
1172
|
const configuredSlots = config.providerConcurrency?.['llama-cpp'];
|
|
@@ -1481,27 +1486,18 @@ export class LocalEngineRuntime {
|
|
|
1481
1486
|
vramBytes: capacity.vramBytes,
|
|
1482
1487
|
});
|
|
1483
1488
|
// Mirror the launch path's windowed-cache admission (see
|
|
1484
|
-
// buildLlamaCppProvider):
|
|
1485
|
-
//
|
|
1486
|
-
// full-attention plan above overstates
|
|
1487
|
-
//
|
|
1488
|
-
//
|
|
1489
|
+
// buildLlamaCppProvider): unless `swaFull` is pinned, a
|
|
1490
|
+
// sliding-window model runs the windowed cache, which the
|
|
1491
|
+
// full-attention plan above overstates — re-plan with the windowed
|
|
1492
|
+
// linearization so the previewed window matches what the engine will
|
|
1493
|
+
// actually grant.
|
|
1489
1494
|
// Strict model-max deliberately does NOT gate this: for SWA models
|
|
1490
1495
|
// the windowed cache is the only layout whose native-window KV can
|
|
1491
1496
|
// fit real machines, and the strict minimum rides inside
|
|
1492
1497
|
// `requirement.minimumPerTurnCtxTokens`, so the windowed
|
|
1493
1498
|
// re-plan sheds slots or denies but never shortens the window.
|
|
1494
1499
|
const explicitSwaFull = config.llamaCppSwaFull ?? manifestEngineConfig?.swaFull;
|
|
1495
|
-
|
|
1496
|
-
(exactKvAtReference / referenceCtx) * grantedCtx * slots > autoKvCacheMaxBytes();
|
|
1497
|
-
const windowedCacheWillRun = (!admission.minimumSatisfied ||
|
|
1498
|
-
admission.clamped ||
|
|
1499
|
-
admission.slots < slots ||
|
|
1500
|
-
fullCacheOverCeiling) &&
|
|
1501
|
-
(explicitSwaFull === false ||
|
|
1502
|
-
(explicitSwaFull === undefined &&
|
|
1503
|
-
isGemmaModel({ architecture: installed.architecture, modelId })));
|
|
1504
|
-
if (windowedCacheWillRun) {
|
|
1500
|
+
if (explicitSwaFull !== true) {
|
|
1505
1501
|
const windowed = estimateWindowedKvLinearization({
|
|
1506
1502
|
blockCount: summary.blockCount,
|
|
1507
1503
|
embeddingLength: summary.embeddingLength,
|
|
@@ -1541,9 +1537,13 @@ export class LocalEngineRuntime {
|
|
|
1541
1537
|
fixedPerSlotBytes: windowed.fixedBytes,
|
|
1542
1538
|
};
|
|
1543
1539
|
}
|
|
1544
|
-
else if ((
|
|
1545
|
-
|
|
1546
|
-
|
|
1540
|
+
else if ((!admission.minimumSatisfied || admission.clamped || admission.slots < slots) &&
|
|
1541
|
+
(explicitSwaFull === false
|
|
1542
|
+
? (summary.slidingWindow ?? 0) > 0
|
|
1543
|
+
: isGemmaModel({ architecture: installed.architecture, modelId }))) {
|
|
1544
|
+
// SWA model without a readable layout, over budget on full
|
|
1545
|
+
// math: the launch path leaves such a launch untouched — preview
|
|
1546
|
+
// the requested window.
|
|
1547
1547
|
return { grantedCtx, slots, kvCacheType: kv, plannedFieldsOk: false };
|
|
1548
1548
|
}
|
|
1549
1549
|
}
|
|
@@ -1590,7 +1590,7 @@ export class LocalEngineRuntime {
|
|
|
1590
1590
|
}
|
|
1591
1591
|
return { grantedCtx, slots, kvCacheType: kv, plannedFieldsOk: true };
|
|
1592
1592
|
};
|
|
1593
|
-
const plan = llamaPlanPass(explicitContextWindow,
|
|
1593
|
+
const plan = llamaPlanPass(explicitContextWindow, contextFloor);
|
|
1594
1594
|
let autoContextWindow;
|
|
1595
1595
|
if (overrideActive) {
|
|
1596
1596
|
try {
|
|
@@ -50,5 +50,7 @@ export async function measuredCapacityBudget() {
|
|
|
50
50
|
systemRamBytes: profile.totalRamBytes,
|
|
51
51
|
gpuVramBytes: profile.gpuVramBytes,
|
|
52
52
|
unifiedMemory: profile.gpuMemoryKind === 'integrated' || profile.gpuMemoryKind === 'unified',
|
|
53
|
+
reservedGpuBytes: profile.gpuReservedBytes ?? null,
|
|
54
|
+
gpuAddressableBytes: profile.gpuAddressableBytes ?? null,
|
|
53
55
|
});
|
|
54
56
|
}
|
|
@@ -158,6 +158,11 @@ export interface NativeEngineSupervisorOptions {
|
|
|
158
158
|
onLog?: (line: string) => void;
|
|
159
159
|
/** Called for both expected and unexpected exits after a snapshot is sealed. */
|
|
160
160
|
onExit?: (snapshot: NativeEngineExitSnapshot) => void | Promise<void>;
|
|
161
|
+
/**
|
|
162
|
+
* Called each time a start reaches readiness. Errors are caught and logged;
|
|
163
|
+
* a failing hook never fails the start.
|
|
164
|
+
*/
|
|
165
|
+
onReady?: (launch: NativeEngineLaunch) => void;
|
|
161
166
|
/**
|
|
162
167
|
* Consulted after a start attempt fails (child died or never became
|
|
163
168
|
* ready — not spawn errors, and not crashes after readiness). Return
|
|
@@ -214,6 +219,13 @@ export interface NativeEngineSupervisorOptions {
|
|
|
214
219
|
psRunner?: () => Promise<NativeProcessSnapshot[]>;
|
|
215
220
|
/** Platform seam for Windows owner-liveness semantics in orphan tests. */
|
|
216
221
|
platform?: NodeJS.Platform;
|
|
222
|
+
/**
|
|
223
|
+
* The kernel's running count of out-of-memory kills, or null when it
|
|
224
|
+
* cannot be read. Compared across a child's life to tell Linux's
|
|
225
|
+
* out-of-memory killer from any other SIGKILL. Defaults to `oom_kill` in
|
|
226
|
+
* `/proc/vmstat` on Linux (any account can read it) and null elsewhere.
|
|
227
|
+
*/
|
|
228
|
+
readOomKillCount?: () => number | null;
|
|
217
229
|
/**
|
|
218
230
|
* Test seam paired with `psRunner` — invoked instead of
|
|
219
231
|
* `process.kill(pid, 'SIGKILL')`. Lets unit tests assert which pids
|
|
@@ -263,6 +275,7 @@ export declare class NativeEngineSupervisor {
|
|
|
263
275
|
private readonly fetchImpl;
|
|
264
276
|
private readonly onLog;
|
|
265
277
|
private readonly onExit?;
|
|
278
|
+
private readonly onReady?;
|
|
266
279
|
private readonly recoverStartup?;
|
|
267
280
|
private readonly onRawLine?;
|
|
268
281
|
private readonly logPrefix;
|
|
@@ -271,6 +284,9 @@ export declare class NativeEngineSupervisor {
|
|
|
271
284
|
private readonly psRunner;
|
|
272
285
|
private readonly killProcess;
|
|
273
286
|
private readonly platform;
|
|
287
|
+
private readonly readOomKillCount;
|
|
288
|
+
/** `oom_kill` when the current child spawned; null where it cannot be read. */
|
|
289
|
+
private currentOomKills;
|
|
274
290
|
private readonly logListeners;
|
|
275
291
|
private recentStarts;
|
|
276
292
|
private lastUsedAt;
|
|
@@ -482,6 +498,13 @@ export declare class NativeEngineSupervisor {
|
|
|
482
498
|
*/
|
|
483
499
|
private runFreeze;
|
|
484
500
|
private clearIdleTimer;
|
|
501
|
+
/**
|
|
502
|
+
* The counter's movement since `before`, when it rose. Another process
|
|
503
|
+
* killed in the same window would also move it, but a child that died by a
|
|
504
|
+
* SIGKILL this supervisor did not send while the counter rose is, in
|
|
505
|
+
* practice, the one the killer chose.
|
|
506
|
+
*/
|
|
507
|
+
private oomKillsSince;
|
|
485
508
|
private clearFreezeTimer;
|
|
486
509
|
private clearHealthTimer;
|
|
487
510
|
}
|
|
@@ -490,6 +513,8 @@ export declare function classifyNativeEnginePanic(line: string): {
|
|
|
490
513
|
kind: NativeEnginePanicKind;
|
|
491
514
|
line: string;
|
|
492
515
|
} | undefined;
|
|
516
|
+
/** `oom_kill` from `/proc/vmstat` (Linux 4.13+), or null when it cannot be read. */
|
|
517
|
+
export declare function readLinuxOomKillCount(): number | null;
|
|
493
518
|
/** Parse the portable `ps -axo pid=,ppid=,command=` shape. */
|
|
494
519
|
export declare function parseNativeProcessSnapshot(stdout: string): NativeProcessSnapshot[];
|
|
495
520
|
/** `code` stamped on every engine-launch failure. See {@link isEngineLaunchError}. */
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* so we can drive the lifecycle without a real binary.
|
|
22
22
|
*/
|
|
23
23
|
import { spawn as nodeSpawn } from 'node:child_process';
|
|
24
|
+
import { readFileSync } from 'node:fs';
|
|
24
25
|
import { basename } from 'node:path';
|
|
25
26
|
import { awakeNow, createLogger } from '@bendyline/gezel';
|
|
26
27
|
import { listProcessSnapshots } from '@bendyline/gezel-client/node';
|
|
@@ -54,7 +55,9 @@ const RESTART_WINDOW_MS = 60_000;
|
|
|
54
55
|
/**
|
|
55
56
|
* Ceiling on `recoverStartup` retries within one start. Two covers the
|
|
56
57
|
* full MoE degradation ladder (partial split → all experts to RAM →
|
|
57
|
-
* engine-owned fit); a hook that keeps
|
|
58
|
+
* engine-owned fit), or one slot and one offload rung; a hook that keeps
|
|
59
|
+
* asking past that is looping. Every failed start also spends the restart
|
|
60
|
+
* budget, which refuses a fourth start inside its window anyway.
|
|
58
61
|
*/
|
|
59
62
|
const MAX_STARTUP_RECOVERIES = 2;
|
|
60
63
|
const HEALTH_FAIL_THRESHOLD = 3;
|
|
@@ -179,6 +182,7 @@ export class NativeEngineSupervisor {
|
|
|
179
182
|
fetchImpl;
|
|
180
183
|
onLog;
|
|
181
184
|
onExit;
|
|
185
|
+
onReady;
|
|
182
186
|
recoverStartup;
|
|
183
187
|
onRawLine;
|
|
184
188
|
logPrefix;
|
|
@@ -187,6 +191,9 @@ export class NativeEngineSupervisor {
|
|
|
187
191
|
psRunner;
|
|
188
192
|
killProcess;
|
|
189
193
|
platform;
|
|
194
|
+
readOomKillCount;
|
|
195
|
+
/** `oom_kill` when the current child spawned; null where it cannot be read. */
|
|
196
|
+
currentOomKills = null;
|
|
190
197
|
// Ad-hoc log listeners attached at runtime (vs. the construction-time
|
|
191
198
|
// `onLog` / `onRawLine` hooks). Used by the owning provider to
|
|
192
199
|
// subscribe to engine log lines for the duration of a single request
|
|
@@ -274,6 +281,8 @@ export class NativeEngineSupervisor {
|
|
|
274
281
|
this.onLog = opts.onLog ?? ((line) => log.info(line));
|
|
275
282
|
if (opts.onExit)
|
|
276
283
|
this.onExit = opts.onExit;
|
|
284
|
+
if (opts.onReady)
|
|
285
|
+
this.onReady = opts.onReady;
|
|
277
286
|
if (opts.recoverStartup)
|
|
278
287
|
this.recoverStartup = opts.recoverStartup;
|
|
279
288
|
if (opts.onRawLine)
|
|
@@ -282,6 +291,8 @@ export class NativeEngineSupervisor {
|
|
|
282
291
|
this.readinessPath = opts.readinessPath ?? '/health';
|
|
283
292
|
this.readyOnAnyResponse = opts.readyOnAnyResponse ?? false;
|
|
284
293
|
this.platform = opts.platform ?? process.platform;
|
|
294
|
+
this.readOomKillCount =
|
|
295
|
+
opts.readOomKillCount ?? (this.platform === 'linux' ? readLinuxOomKillCount : () => null);
|
|
285
296
|
this.psRunner = opts.psRunner ?? (() => defaultPsRunner(this.platform));
|
|
286
297
|
this.killProcess = opts.killProcess ?? ((pid, sig) => process.kill(pid, sig));
|
|
287
298
|
}
|
|
@@ -600,6 +611,7 @@ export class NativeEngineSupervisor {
|
|
|
600
611
|
this.currentDiagnostics = launch.diagnostics ? { ...launch.diagnostics } : undefined;
|
|
601
612
|
this.currentOutput = '';
|
|
602
613
|
this.currentPanic = undefined;
|
|
614
|
+
this.currentOomKills = this.readOomKillCount();
|
|
603
615
|
this.expectedExitReason = undefined;
|
|
604
616
|
this.onLog(`${this.logPrefix} launch ${JSON.stringify({
|
|
605
617
|
pid: this.currentPid ?? null,
|
|
@@ -698,6 +710,12 @@ export class NativeEngineSupervisor {
|
|
|
698
710
|
this.state = { kind: 'running', launch, child, healthFails: 0 };
|
|
699
711
|
this.resetIdleTimer();
|
|
700
712
|
this.startHealthWatch();
|
|
713
|
+
try {
|
|
714
|
+
this.onReady?.(launch);
|
|
715
|
+
}
|
|
716
|
+
catch (hookErr) {
|
|
717
|
+
this.onLog(`${this.logPrefix} onReady hook threw: ${hookErr instanceof Error ? hookErr.message : hookErr}`);
|
|
718
|
+
}
|
|
701
719
|
}
|
|
702
720
|
catch (err) {
|
|
703
721
|
// The panic classifier state is cleared by handleExit — read it now,
|
|
@@ -998,13 +1016,23 @@ export class NativeEngineSupervisor {
|
|
|
998
1016
|
// the output didn't already explain the death more precisely: an
|
|
999
1017
|
// engine that printed `CUDA error: …` and then took SIGILL on the
|
|
1000
1018
|
// way down is a CUDA fault, not an unrunnable build.
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1019
|
+
// An out-of-memory kill outranks anything the engine printed: a CUDA or
|
|
1020
|
+
// Vulkan allocation line on the way there is a symptom of the same
|
|
1021
|
+
// shortage, and the GPU-to-RAM ladder those lines trigger cannot help
|
|
1022
|
+
// when RAM is what ran out.
|
|
1023
|
+
const oomKilled = signal === 'SIGKILL' && !expected ? this.oomKillsSince(this.currentOomKills) : null;
|
|
1024
|
+
const panic = oomKilled
|
|
1025
|
+
? {
|
|
1026
|
+
kind: 'host-out-of-memory',
|
|
1027
|
+
line: `engine killed by the Linux out-of-memory killer (oom_kill ${oomKilled.before} -> ${oomKilled.after})`,
|
|
1028
|
+
}
|
|
1029
|
+
: (this.currentPanic ??
|
|
1030
|
+
(signal === 'SIGILL'
|
|
1031
|
+
? {
|
|
1032
|
+
kind: 'illegal-instruction',
|
|
1033
|
+
line: 'engine terminated by SIGILL (illegal instruction) with no diagnostic output',
|
|
1034
|
+
}
|
|
1035
|
+
: undefined));
|
|
1008
1036
|
const snapshot = {
|
|
1009
1037
|
incidentId: `native-${pid ?? 'unknown'}-${exitedAt}`,
|
|
1010
1038
|
...(pid !== undefined ? { pid } : {}),
|
|
@@ -1062,6 +1090,7 @@ export class NativeEngineSupervisor {
|
|
|
1062
1090
|
this.currentDiagnostics = undefined;
|
|
1063
1091
|
this.currentOutput = '';
|
|
1064
1092
|
this.currentPanic = undefined;
|
|
1093
|
+
this.currentOomKills = null;
|
|
1065
1094
|
this.expectedExitReason = undefined;
|
|
1066
1095
|
if (priorState.kind === 'stopped')
|
|
1067
1096
|
return;
|
|
@@ -1313,6 +1342,18 @@ export class NativeEngineSupervisor {
|
|
|
1313
1342
|
this.idleTimer = undefined;
|
|
1314
1343
|
}
|
|
1315
1344
|
}
|
|
1345
|
+
/**
|
|
1346
|
+
* The counter's movement since `before`, when it rose. Another process
|
|
1347
|
+
* killed in the same window would also move it, but a child that died by a
|
|
1348
|
+
* SIGKILL this supervisor did not send while the counter rose is, in
|
|
1349
|
+
* practice, the one the killer chose.
|
|
1350
|
+
*/
|
|
1351
|
+
oomKillsSince(before) {
|
|
1352
|
+
if (before === null)
|
|
1353
|
+
return null;
|
|
1354
|
+
const after = this.readOomKillCount();
|
|
1355
|
+
return after !== null && after > before ? { before, after } : null;
|
|
1356
|
+
}
|
|
1316
1357
|
clearFreezeTimer() {
|
|
1317
1358
|
if (this.freezeTimer) {
|
|
1318
1359
|
clearTimeout(this.freezeTimer);
|
|
@@ -1346,6 +1387,9 @@ export function classifyNativeEnginePanic(line) {
|
|
|
1346
1387
|
if (/CUDA error:.*device-side assert/i.test(line)) {
|
|
1347
1388
|
return { kind: 'cuda-device-assert', line: clipped };
|
|
1348
1389
|
}
|
|
1390
|
+
if (/CUDA error:\s*(?:no kernel image is available|the provided PTX was compiled with an unsupported toolchain)/i.test(line)) {
|
|
1391
|
+
return { kind: 'cuda-unsupported-device', line: clipped };
|
|
1392
|
+
}
|
|
1349
1393
|
if (/CUDA error:/i.test(line))
|
|
1350
1394
|
return { kind: 'cuda-error', line: clipped };
|
|
1351
1395
|
if (/assert(?:ion)? failed|GGML_ASSERT/i.test(line)) {
|
|
@@ -1353,6 +1397,16 @@ export function classifyNativeEnginePanic(line) {
|
|
|
1353
1397
|
}
|
|
1354
1398
|
return undefined;
|
|
1355
1399
|
}
|
|
1400
|
+
/** `oom_kill` from `/proc/vmstat` (Linux 4.13+), or null when it cannot be read. */
|
|
1401
|
+
export function readLinuxOomKillCount() {
|
|
1402
|
+
try {
|
|
1403
|
+
const match = /^oom_kill (\d+)$/m.exec(readFileSync('/proc/vmstat', 'utf8'));
|
|
1404
|
+
return match?.[1] ? Number(match[1]) : null;
|
|
1405
|
+
}
|
|
1406
|
+
catch {
|
|
1407
|
+
return null;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1356
1410
|
function panicPriority(kind) {
|
|
1357
1411
|
if (kind === 'cuda-error')
|
|
1358
1412
|
return 1;
|
|
@@ -5,11 +5,18 @@
|
|
|
5
5
|
* service's import point and keeps the one piece that reads the process
|
|
6
6
|
* environment.
|
|
7
7
|
*/
|
|
8
|
-
export { AbortedWhileQueuedError, DEFAULT_AMBIENT_QUIET_MS, ProviderQueue, QUEUE_WAIT_NOTICE_DELAY_MS, QUEUE_WAIT_NOTICE_REPEAT_MS, backgroundLaneCap, runInQueue, } from '@bendyline/gezel/runtime';
|
|
9
|
-
export type { EnqueueRequest, Lane, ProviderQueueOptions, QueueSnapshot, QueueWaitOpts, } from '@bendyline/gezel/runtime';
|
|
8
|
+
export { AbortedWhileQueuedError, DEFAULT_AMBIENT_QUIET_MS, DEFAULT_LOCAL_YIELD_QUANTUM_MS, ProviderQueue, QUEUE_WAIT_NOTICE_DELAY_MS, QUEUE_WAIT_NOTICE_REPEAT_MS, backgroundLaneCap, runInQueue, } from '@bendyline/gezel/runtime';
|
|
9
|
+
export type { EnqueueRequest, Lane, ProviderQueueOptions, QueueLease, QueueSnapshot, QueueWaitOpts, } from '@bendyline/gezel/runtime';
|
|
10
10
|
/**
|
|
11
11
|
* Ambient quiet window for local engine queues. Override with
|
|
12
12
|
* `GEZEL_AMBIENT_QUIET_MS` (milliseconds; `0` disables ambient gating
|
|
13
13
|
* entirely).
|
|
14
14
|
*/
|
|
15
15
|
export declare function defaultAmbientQuietMs(): number;
|
|
16
|
+
/**
|
|
17
|
+
* How long a local turn holds its queue slot before it hands the slot to
|
|
18
|
+
* another conversation that is waiting. Override with
|
|
19
|
+
* `GEZEL_QUEUE_YIELD_QUANTUM_MS` (milliseconds; `0` keeps a slot for the
|
|
20
|
+
* whole turn).
|
|
21
|
+
*/
|
|
22
|
+
export declare function defaultQueueYieldQuantumMs(): number;
|
package/dist/providers/queue.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* service's import point and keeps the one piece that reads the process
|
|
6
6
|
* environment.
|
|
7
7
|
*/
|
|
8
|
-
import { DEFAULT_AMBIENT_QUIET_MS } from '@bendyline/gezel/runtime';
|
|
9
|
-
export { AbortedWhileQueuedError, DEFAULT_AMBIENT_QUIET_MS, ProviderQueue, QUEUE_WAIT_NOTICE_DELAY_MS, QUEUE_WAIT_NOTICE_REPEAT_MS, backgroundLaneCap, runInQueue, } from '@bendyline/gezel/runtime';
|
|
8
|
+
import { DEFAULT_AMBIENT_QUIET_MS, DEFAULT_LOCAL_YIELD_QUANTUM_MS } from '@bendyline/gezel/runtime';
|
|
9
|
+
export { AbortedWhileQueuedError, DEFAULT_AMBIENT_QUIET_MS, DEFAULT_LOCAL_YIELD_QUANTUM_MS, ProviderQueue, QUEUE_WAIT_NOTICE_DELAY_MS, QUEUE_WAIT_NOTICE_REPEAT_MS, backgroundLaneCap, runInQueue, } from '@bendyline/gezel/runtime';
|
|
10
10
|
/**
|
|
11
11
|
* Ambient quiet window for local engine queues. Override with
|
|
12
12
|
* `GEZEL_AMBIENT_QUIET_MS` (milliseconds; `0` disables ambient gating
|
|
@@ -21,3 +21,18 @@ export function defaultAmbientQuietMs() {
|
|
|
21
21
|
}
|
|
22
22
|
return DEFAULT_AMBIENT_QUIET_MS;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* How long a local turn holds its queue slot before it hands the slot to
|
|
26
|
+
* another conversation that is waiting. Override with
|
|
27
|
+
* `GEZEL_QUEUE_YIELD_QUANTUM_MS` (milliseconds; `0` keeps a slot for the
|
|
28
|
+
* whole turn).
|
|
29
|
+
*/
|
|
30
|
+
export function defaultQueueYieldQuantumMs() {
|
|
31
|
+
const raw = process.env.GEZEL_QUEUE_YIELD_QUANTUM_MS;
|
|
32
|
+
if (raw !== undefined) {
|
|
33
|
+
const parsed = Number.parseInt(raw, 10);
|
|
34
|
+
if (Number.isFinite(parsed) && parsed >= 0)
|
|
35
|
+
return parsed;
|
|
36
|
+
}
|
|
37
|
+
return DEFAULT_LOCAL_YIELD_QUANTUM_MS;
|
|
38
|
+
}
|
|
@@ -22,5 +22,8 @@ export interface ToolGroundingHooks {
|
|
|
22
22
|
kind: 'allow';
|
|
23
23
|
args: Record<string, unknown>;
|
|
24
24
|
} | null;
|
|
25
|
-
|
|
25
|
+
/** `source.thirdParty` is true for a tool served by any server but gezel's own. */
|
|
26
|
+
labelEvidence(toolName: string, args: Record<string, unknown>, text: string, source?: {
|
|
27
|
+
thirdParty: boolean;
|
|
28
|
+
}): string | null;
|
|
26
29
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The amdgpu devices Linux describes in sysfs, for the carve-out decision in
|
|
3
|
+
* gpu-carve-out.ts — the Linux counterpart of the DXCore adapter listing the
|
|
4
|
+
* device-health helper reads on Windows. Everything read here is
|
|
5
|
+
* world-readable, so the machine service's unprivileged account sees it too.
|
|
6
|
+
*/
|
|
7
|
+
import type { GpuAdapterFacts } from './gpu-carve-out.js';
|
|
8
|
+
export interface SysfsIo {
|
|
9
|
+
readFile?: (path: string) => string;
|
|
10
|
+
readDir?: (path: string) => string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* One entry per amdgpu device: `dedicatedBytes` from `mem_info_vram_total`,
|
|
14
|
+
* `sharedSystemBytes` from `mem_info_gtt_total` (the system RAM the kernel
|
|
15
|
+
* lets it map). Connector entries (`card0-HDMI-A-1`) and render nodes are
|
|
16
|
+
* skipped. Empty off Linux, without amdgpu, or when sysfs cannot be read.
|
|
17
|
+
*/
|
|
18
|
+
export declare function readAmdgpuAdapters(io?: SysfsIo): GpuAdapterFacts[];
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The amdgpu devices Linux describes in sysfs, for the carve-out decision in
|
|
3
|
+
* gpu-carve-out.ts — the Linux counterpart of the DXCore adapter listing the
|
|
4
|
+
* device-health helper reads on Windows. Everything read here is
|
|
5
|
+
* world-readable, so the machine service's unprivileged account sees it too.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
const DRM_ROOT = '/sys/class/drm';
|
|
10
|
+
const AMD_PCI_VENDOR = 0x1002;
|
|
11
|
+
/**
|
|
12
|
+
* One entry per amdgpu device: `dedicatedBytes` from `mem_info_vram_total`,
|
|
13
|
+
* `sharedSystemBytes` from `mem_info_gtt_total` (the system RAM the kernel
|
|
14
|
+
* lets it map). Connector entries (`card0-HDMI-A-1`) and render nodes are
|
|
15
|
+
* skipped. Empty off Linux, without amdgpu, or when sysfs cannot be read.
|
|
16
|
+
*/
|
|
17
|
+
export function readAmdgpuAdapters(io = {}) {
|
|
18
|
+
const readFile = io.readFile ?? ((path) => readFileSync(path, 'utf8'));
|
|
19
|
+
const readDir = io.readDir ?? ((path) => readdirSync(path));
|
|
20
|
+
const read = (path) => {
|
|
21
|
+
try {
|
|
22
|
+
return readFile(path).trim();
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
let cards;
|
|
29
|
+
try {
|
|
30
|
+
cards = readDir(DRM_ROOT).filter((entry) => /^card\d+$/.test(entry));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
const adapters = [];
|
|
36
|
+
for (const card of cards) {
|
|
37
|
+
const device = join(DRM_ROOT, card, 'device');
|
|
38
|
+
if (Number.parseInt(read(join(device, 'vendor')) ?? '', 16) !== AMD_PCI_VENDOR)
|
|
39
|
+
continue;
|
|
40
|
+
const vram = byteCount(read(join(device, 'mem_info_vram_total')));
|
|
41
|
+
if (vram === undefined)
|
|
42
|
+
continue;
|
|
43
|
+
const gtt = byteCount(read(join(device, 'mem_info_gtt_total')));
|
|
44
|
+
adapters.push({
|
|
45
|
+
vendorId: AMD_PCI_VENDOR,
|
|
46
|
+
dedicatedBytes: vram,
|
|
47
|
+
...(gtt !== undefined ? { sharedSystemBytes: gtt } : {}),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return adapters;
|
|
51
|
+
}
|
|
52
|
+
function byteCount(raw) {
|
|
53
|
+
const value = raw ? Number(raw) : Number.NaN;
|
|
54
|
+
return Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
55
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How much memory firmware set aside for an integrated GPU, if any.
|
|
3
|
+
*
|
|
4
|
+
* Two kinds of integrated GPU report "VRAM" through Vulkan, and they mean
|
|
5
|
+
* opposite things:
|
|
6
|
+
*
|
|
7
|
+
* - A **shared view** (Intel, Snapdragon, most iGPUs): the number is a slice
|
|
8
|
+
* of the same RAM the OS already counts. Adding it double-counts, which is
|
|
9
|
+
* why integrated hosts budget from system RAM alone.
|
|
10
|
+
* - A **carve-out** (an AMD APU's "UMA frame buffer", set in firmware or by
|
|
11
|
+
* AMD's Variable Graphics Memory): memory removed before the OS ever counts
|
|
12
|
+
* RAM. It sits in neither `os.totalmem()` nor any free-RAM reading, and only
|
|
13
|
+
* the GPU can use it. Budgeting from system RAM alone loses it entirely, so
|
|
14
|
+
* on a 16 GB laptop raising the carve-out from 3 GB to 8 GB cut the budget
|
|
15
|
+
* from ~9 GB to ~4 GB.
|
|
16
|
+
*
|
|
17
|
+
* Windows answers directly when the device-health helper can list adapters
|
|
18
|
+
* (DXCore): an integrated adapter's dedicated memory IS its carve-out. Where
|
|
19
|
+
* installed RAM is known too, the two must agree — the carve-out has to fit
|
|
20
|
+
* in the memory that is installed but missing from the OS's count — so one
|
|
21
|
+
* odd driver figure cannot inflate the budget.
|
|
22
|
+
*
|
|
23
|
+
* Without an adapter listing, the GPU's Vulkan-reported memory stands in: a
|
|
24
|
+
* carve-out fits inside that same gap, a shared view is far larger than it
|
|
25
|
+
* (a few hundred MB of firmware reservations is the usual gap without one).
|
|
26
|
+
*
|
|
27
|
+
* Linux answers through the amdgpu driver instead (see
|
|
28
|
+
* {@link linuxGpuCarveOutBytes}). Installed RAM is not readable there without
|
|
29
|
+
* root, and the Vulkan figure cannot stand in: llama.cpp sums every heap of an
|
|
30
|
+
* integrated GPU, and RADV reports an APU's GTT — borrowed system RAM — beside
|
|
31
|
+
* the carve-out.
|
|
32
|
+
*
|
|
33
|
+
* Anything uncertain answers null — integrated GPUs budgeted from system RAM
|
|
34
|
+
* alone, as before.
|
|
35
|
+
*/
|
|
36
|
+
export declare function gpuCarveOutBytes(input: {
|
|
37
|
+
/** Physically installed RAM, or null when it could not be read. */
|
|
38
|
+
installedRamBytes: number | null;
|
|
39
|
+
/** RAM the OS reports (`os.totalmem()`). */
|
|
40
|
+
visibleRamBytes: number;
|
|
41
|
+
/** Memory the integrated GPU reports for itself through Vulkan. */
|
|
42
|
+
deviceBytes: number;
|
|
43
|
+
/** Windows' figure for the integrated adapter's own memory, when listed. */
|
|
44
|
+
adapterDedicatedBytes?: number | null;
|
|
45
|
+
}): number | null;
|
|
46
|
+
/**
|
|
47
|
+
* An AMD APU's carve-out on Linux: amdgpu's `mem_info_vram_total`, which on an
|
|
48
|
+
* APU is the frame buffer firmware reserved before the kernel counted RAM, so
|
|
49
|
+
* it is absent from MemTotal. Read only for the one amdgpu device there is —
|
|
50
|
+
* sysfs does not say which of two is integrated — and only when it fits in
|
|
51
|
+
* what Vulkan reports, which for an integrated GPU is the carve-out plus GTT.
|
|
52
|
+
* The caller has already decided the GPU llama.cpp picked is integrated.
|
|
53
|
+
*/
|
|
54
|
+
export declare function linuxGpuCarveOutBytes(input: {
|
|
55
|
+
/** amdgpu devices from sysfs (`readAmdgpuAdapters`). */
|
|
56
|
+
adapters: readonly GpuAdapterFacts[];
|
|
57
|
+
visibleRamBytes: number;
|
|
58
|
+
/** Memory the integrated GPU reports for itself through Vulkan. */
|
|
59
|
+
deviceBytes: number;
|
|
60
|
+
}): number | null;
|
|
61
|
+
/**
|
|
62
|
+
* Everything an AMD APU can reach on Linux: its carve-out plus GTT, the
|
|
63
|
+
* window of system RAM amdgpu lets it map (half of RAM on recent kernels
|
|
64
|
+
* unless `ttm.pages_limit` raises it). Past that, allocations fail however
|
|
65
|
+
* much RAM is free. Null without both figures for the one amdgpu device.
|
|
66
|
+
*/
|
|
67
|
+
export declare function linuxGpuAddressableBytes(adapters: readonly GpuAdapterFacts[]): number | null;
|
|
68
|
+
/** The part of a helper adapter record (`DeviceGpuAdapter`) this module reads. */
|
|
69
|
+
export interface GpuAdapterFacts {
|
|
70
|
+
name?: string;
|
|
71
|
+
vendorId: number;
|
|
72
|
+
integrated?: boolean;
|
|
73
|
+
dedicatedBytes?: number;
|
|
74
|
+
/** System RAM the adapter may borrow on top of its own (Linux: GTT). */
|
|
75
|
+
sharedSystemBytes?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The adapter Windows lists for the GPU llama.cpp picked: the one with the
|
|
79
|
+
* same name, else the only adapter there is. Null when that is ambiguous —
|
|
80
|
+
* the name-based guesses then stand.
|
|
81
|
+
*/
|
|
82
|
+
export declare function matchGpuAdapter<T extends GpuAdapterFacts>(adapters: readonly T[], deviceName: string): T | null;
|
|
83
|
+
/** GPU maker from its PCI vendor id. */
|
|
84
|
+
export declare function gpuVendorFromPciId(vendorId: number): 'amd' | 'intel' | 'nvidia' | undefined;
|