@bendyline/gezel-inference 1.0.0 → 1.0.2
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/README.md +90 -8
- package/dist/cache/adapter.d.ts +7 -0
- package/dist/cache/controller.d.ts +12 -0
- package/dist/cache/controller.js +24 -0
- package/dist/catalog/chat-models/bt/btl4-35b-q4/manifest.json +1 -0
- package/dist/catalog/chat-models/gl/glm-5.2-754b-q2/manifest.json +1 -0
- package/dist/catalog/chat-models/index.json +1 -1
- package/dist/catalog/chat-models/lf/lfm2.5-24b-a2b-q4/manifest.json +122 -0
- package/dist/catalog/chat-models/lf/lfm2.5-24b-a2b-q4/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/chat-models/mi/minicpm-v4.7-35b-a3b-q4/manifest.json +185 -0
- package/dist/catalog/chat-models/mi/minicpm-v4.7-35b-a3b-q4/versions/1.0.0/manifest.json +94 -0
- package/dist/catalog/chat-models/mi/minicpm5-1b-q4/manifest.json +1 -0
- package/dist/catalog/chat-models/mi/minicpm5-2b-q4/manifest.json +1 -0
- package/dist/catalog/chat-models/qw/qwen3.5-0.8b-q4/manifest.json +1 -0
- package/dist/catalog/chat-models/raw-index.json +1 -1
- package/dist/catalog/provenance.json +1 -1
- package/dist/engines/electron-native-reuse.d.ts +9 -0
- package/dist/engines/electron-native-reuse.js +146 -45
- package/dist/engines/native-file-manifest.json +404 -404
- package/dist/engines/native-manifest.d.ts +11 -3
- package/dist/engines/native-manifest.js +48 -18
- package/dist/http/openai-compat/apple-model.d.ts +2 -0
- package/dist/http/openai-compat/apple-model.js +21 -1
- package/dist/http/openai-compat/chat-target.d.ts +12 -0
- package/dist/http/openai-compat/chat-target.js +27 -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 +44 -3
- package/dist/http/routes/v1-chat.js +30 -8
- package/dist/http/routes/v1-models.d.ts +6 -0
- package/dist/http/routes/v1-models.js +137 -30
- package/dist/http/routes/v1-responses.js +16 -3
- package/dist/in-flight-requests.d.ts +19 -0
- package/dist/in-flight-requests.js +34 -0
- package/dist/inference-service.js +3 -3
- package/dist/knowledge/catalog-host.d.ts +9 -1
- package/dist/knowledge/catalog-host.js +2 -0
- package/dist/knowledge/manager.d.ts +14 -0
- package/dist/knowledge/manager.js +53 -6
- 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 +77 -7
- 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 +140 -118
- package/dist/providers/llama-cpp/cache-adapter.d.ts +12 -0
- package/dist/providers/llama-cpp/cache-adapter.js +36 -1
- package/dist/providers/llama-cpp/devices.d.ts +11 -2
- package/dist/providers/llama-cpp/devices.js +10 -4
- 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-async.js +7 -0
- 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 +19 -1
- package/dist/providers/llama-cpp/offload-planner.d.ts +3 -18
- package/dist/providers/llama-cpp/offload-planner.js +3 -14
- package/dist/providers/llama-cpp/provider.d.ts +8 -0
- package/dist/providers/llama-cpp/provider.js +4 -1
- package/dist/providers/mlx/provider.js +14 -11
- package/dist/providers/mlx/python/batch_processors.py +26 -0
- package/dist/providers/mlx/python/gezel_mlx_server.py +88 -20
- package/dist/providers/mlx/python/qwen4_ple.py +9 -2
- package/dist/providers/mlx/python/response_format.py +374 -0
- package/dist/providers/mlx/python/spec_decode.py +5 -0
- package/dist/providers/mlx/python/think_budget.py +35 -1
- package/dist/providers/mlx/python/tool_grammar.py +62 -3
- package/dist/providers/mlx/reasoning-stream.d.ts +20 -2
- package/dist/providers/mlx/reasoning-stream.js +77 -16
- package/dist/providers/mlx/runtime-diagnostics.d.ts +16 -0
- package/dist/providers/mlx/runtime-diagnostics.js +29 -2
- package/dist/providers/native/capacity-broker.d.ts +51 -10
- package/dist/providers/native/capacity-broker.js +80 -9
- 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 +15 -13
- package/dist/providers/native/measured-budget.js +2 -0
- package/dist/providers/native/supervisor.d.ts +25 -0
- package/dist/providers/native/supervisor.js +59 -7
- package/dist/remotes/identity.d.ts +1 -0
- package/dist/remotes/identity.js +6 -0
- package/dist/remotes/pinned-fetch.d.ts +2 -0
- package/dist/remotes/pinned-fetch.js +30 -1
- package/dist/remotes/types.d.ts +14 -0
- package/dist/runtime-lock.js +1 -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 +105 -14
- package/dist/transformers-cache.d.ts +2 -0
- package/dist/transformers-cache.js +6 -3
- package/dist/utils/service-worker-entry.d.ts +4 -0
- package/dist/utils/service-worker-entry.js +4 -0
- package/package.json +14 -10
package/README.md
CHANGED
|
@@ -1,14 +1,96 @@
|
|
|
1
1
|
# @bendyline/gezel-inference
|
|
2
2
|
|
|
3
|
-
The
|
|
3
|
+
The on-device inference runtime shared by [Gezel](https://github.com/bendyline/gezel)
|
|
4
|
+
and by applications that embed it. It runs local AI models on the user's own
|
|
5
|
+
computer and answers them through OpenAI-compatible routes:
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
- **Native engines** — starting, sizing, and stopping llama.cpp, MLX, and the
|
|
8
|
+
other on-device engines, with admission control so models fit in memory.
|
|
9
|
+
- **Model management** — listing, downloading, verifying, and preparing local
|
|
10
|
+
chat models.
|
|
11
|
+
- **Embeddings and knowledge** — the on-device text embedder
|
|
12
|
+
(`model: "gezel:embeddings"`) and search over installed knowledge catalogs,
|
|
13
|
+
each in its own worker.
|
|
14
|
+
- **OpenAI-compatible routes** — `/v1/chat`, `/v1/responses`,
|
|
15
|
+
`/v1/embeddings`, `/v1/models`, `/v1/models/ensure`, `/v1/knowledge`, and
|
|
16
|
+
the engine routes.
|
|
6
17
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- `/internal/*` is the coordinated workspace interface for Gezel's full service; external applications should use the SDK.
|
|
18
|
+
It holds no product state: no gezels, projects, chats, tools, cloud providers,
|
|
19
|
+
or UI. Those belong to the full Gezel service, `@bendyline/gezel-service`,
|
|
20
|
+
which uses this same runtime.
|
|
11
21
|
|
|
12
|
-
|
|
22
|
+
## Install
|
|
13
23
|
|
|
14
|
-
|
|
24
|
+
```bash
|
|
25
|
+
npm install @bendyline/gezel-app-sdk @bendyline/gezel-inference
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Node 24 or newer. On-device text embeddings and the optional relevance model
|
|
29
|
+
also need the `@huggingface/transformers` peer:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @huggingface/transformers@^4.3.1
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Use it through the app SDK
|
|
36
|
+
|
|
37
|
+
Most applications should not import this package directly. Install it beside
|
|
38
|
+
[`@bendyline/gezel-app-sdk`](https://www.npmjs.com/package/@bendyline/gezel-app-sdk)
|
|
39
|
+
and ask the SDK for an inference-only host. The SDK loads this runtime inside
|
|
40
|
+
your process, so there is no second process to supervise, no separate Node
|
|
41
|
+
executable to ship, and no loopback network connection:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { connectOrHost } from '@bendyline/gezel-app-sdk/host';
|
|
45
|
+
|
|
46
|
+
const gezel = await connectOrHost({
|
|
47
|
+
appId: 'acme.editor',
|
|
48
|
+
appName: 'Acme Editor',
|
|
49
|
+
scopes: ['openai'],
|
|
50
|
+
host: { mode: 'in-process', inferenceOnly: true },
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const { chatModel } = await gezel.ensureModel({ model: 'qwen3.5-0.8b-q4' });
|
|
54
|
+
|
|
55
|
+
const reply = await gezel.openai.chat({
|
|
56
|
+
model: chatModel, // 'mlx:qwen3.5-0.8b-q4' on Apple Silicon, 'llama-cpp:…' elsewhere
|
|
57
|
+
messages: [{ role: 'user', content: 'Suggest a title for these notes: …' }],
|
|
58
|
+
});
|
|
59
|
+
console.log(reply.choices[0].message.content);
|
|
60
|
+
|
|
61
|
+
await gezel.close();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The runtime never downloads a model on its own: weights are fetched only when
|
|
65
|
+
your app asks for them, for example with `ensureModel`. See the
|
|
66
|
+
[app SDK README](https://www.npmjs.com/package/@bendyline/gezel-app-sdk) for
|
|
67
|
+
consent, hosting options, shipping engines and models with your app, and
|
|
68
|
+
knowledge catalogs.
|
|
69
|
+
|
|
70
|
+
## Entry points
|
|
71
|
+
|
|
72
|
+
| Import | What it provides |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `@bendyline/gezel-inference` | `startService()`, the in-process host the app SDK calls, and `verifyNativeBinaries()` |
|
|
75
|
+
| `@bendyline/gezel-inference/native-release` | The pinned native engine release and its archive digests, as data. Importing it starts nothing |
|
|
76
|
+
| `@bendyline/gezel-inference/packaging` | Build-time helpers that stage the pinned native engines for an Electron app |
|
|
77
|
+
| `@bendyline/gezel-inference/speech` | The Kokoro text-to-speech frontend and its pronunciation-dictionary lookup |
|
|
78
|
+
|
|
79
|
+
The package also includes chat-model and knowledge-catalog metadata generated
|
|
80
|
+
from the pinned [`@bendyline/gilde`](https://www.npmjs.com/package/@bendyline/gilde)
|
|
81
|
+
catalog. The pronunciation dictionaries' license is at
|
|
82
|
+
`dist/kokoro-lexicon/LICENSE`.
|
|
83
|
+
|
|
84
|
+
## Stability
|
|
85
|
+
|
|
86
|
+
The entry points above are public API under semver.
|
|
87
|
+
`@bendyline/gezel-inference/internal/*` is not: it is how the Gezel service
|
|
88
|
+
reaches the runtime, always installed at exactly the same version, and it can
|
|
89
|
+
change in any release. Do not import it.
|
|
90
|
+
|
|
91
|
+
## Documentation
|
|
92
|
+
|
|
93
|
+
- [Repository and full documentation](https://github.com/bendyline/gezel)
|
|
94
|
+
- [Embedding guide](https://github.com/bendyline/gezel/blob/main/docs/embedding-sdk.md)
|
|
95
|
+
|
|
96
|
+
MIT © Bendyline
|
package/dist/cache/adapter.d.ts
CHANGED
|
@@ -45,6 +45,13 @@ export interface EngineCacheAdapter {
|
|
|
45
45
|
* gone for accounting purposes either way.
|
|
46
46
|
*/
|
|
47
47
|
evict(sessionIds: readonly string[]): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* This session will never be resumed (a one-shot `gezel run`): keep only
|
|
50
|
+
* what helps other sessions, such as a shared prompt-prefix snapshot, and
|
|
51
|
+
* never a resumable snapshot of its own. Optional — an engine that keeps
|
|
52
|
+
* nothing on disk can ignore it. Must not do I/O.
|
|
53
|
+
*/
|
|
54
|
+
markEphemeral?(sessionId: string): void;
|
|
48
55
|
/**
|
|
49
56
|
* Snapshot of what the engine currently has cached. Polled by the
|
|
50
57
|
* controller every few seconds for telemetry; also informs the
|
|
@@ -97,6 +97,12 @@ export declare class SessionCacheController {
|
|
|
97
97
|
* `setBudget` after construction.
|
|
98
98
|
*/
|
|
99
99
|
private readonly pendingBudgets;
|
|
100
|
+
/**
|
|
101
|
+
* One-shot sessions, remembered so an adapter registered after the session
|
|
102
|
+
* was created (engines start lazily, on the first turn) still learns them.
|
|
103
|
+
* Bounded: only a session's own turns need the mark.
|
|
104
|
+
*/
|
|
105
|
+
private readonly ephemeralSessions;
|
|
100
106
|
private readonly now;
|
|
101
107
|
private readonly logger;
|
|
102
108
|
private reconcileTimer?;
|
|
@@ -109,6 +115,12 @@ export declare class SessionCacheController {
|
|
|
109
115
|
* sets a per-engine RAM-aware default via `setBudget`.
|
|
110
116
|
*/
|
|
111
117
|
registerAdapter(adapter: EngineCacheAdapter): void;
|
|
118
|
+
/**
|
|
119
|
+
* A session that will never be resumed keeps no resumable cache of its own
|
|
120
|
+
* on disk. Every one-shot `gezel run` left a ~300 MB llama slot snapshot
|
|
121
|
+
* that nothing ever read (2026-10-15 npm audit).
|
|
122
|
+
*/
|
|
123
|
+
markEphemeral(sessionId: string): void;
|
|
112
124
|
/**
|
|
113
125
|
* Set the memory budget for a provider. Operator-tunable; Phase 3
|
|
114
126
|
* exposes this in the Settings UI. Eviction kicks in immediately if
|
package/dist/cache/controller.js
CHANGED
|
@@ -43,6 +43,7 @@ function emptyHitsBySource() {
|
|
|
43
43
|
return { memory: 0, disk: 0, prefix: 0, fresh: 0 };
|
|
44
44
|
}
|
|
45
45
|
const RECENT_TURN_WINDOW = 50;
|
|
46
|
+
const MAX_REMEMBERED_EPHEMERAL_SESSIONS = 1024;
|
|
46
47
|
export class SessionCacheController {
|
|
47
48
|
providers = new Map();
|
|
48
49
|
/**
|
|
@@ -55,6 +56,12 @@ export class SessionCacheController {
|
|
|
55
56
|
* `setBudget` after construction.
|
|
56
57
|
*/
|
|
57
58
|
pendingBudgets = new Map();
|
|
59
|
+
/**
|
|
60
|
+
* One-shot sessions, remembered so an adapter registered after the session
|
|
61
|
+
* was created (engines start lazily, on the first turn) still learns them.
|
|
62
|
+
* Bounded: only a session's own turns need the mark.
|
|
63
|
+
*/
|
|
64
|
+
ephemeralSessions = new Set();
|
|
58
65
|
now;
|
|
59
66
|
logger;
|
|
60
67
|
reconcileTimer;
|
|
@@ -93,6 +100,23 @@ export class SessionCacheController {
|
|
|
93
100
|
gezelOutcomes: new Map(),
|
|
94
101
|
recentOutcomes: [],
|
|
95
102
|
});
|
|
103
|
+
for (const sessionId of this.ephemeralSessions)
|
|
104
|
+
adapter.markEphemeral?.(sessionId);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* A session that will never be resumed keeps no resumable cache of its own
|
|
108
|
+
* on disk. Every one-shot `gezel run` left a ~300 MB llama slot snapshot
|
|
109
|
+
* that nothing ever read (2026-10-15 npm audit).
|
|
110
|
+
*/
|
|
111
|
+
markEphemeral(sessionId) {
|
|
112
|
+
this.ephemeralSessions.add(sessionId);
|
|
113
|
+
if (this.ephemeralSessions.size > MAX_REMEMBERED_EPHEMERAL_SESSIONS) {
|
|
114
|
+
const oldest = this.ephemeralSessions.values().next().value;
|
|
115
|
+
if (oldest !== undefined)
|
|
116
|
+
this.ephemeralSessions.delete(oldest);
|
|
117
|
+
}
|
|
118
|
+
for (const state of this.providers.values())
|
|
119
|
+
state.adapter.markEphemeral?.(sessionId);
|
|
96
120
|
}
|
|
97
121
|
/**
|
|
98
122
|
* Set the memory budget for a provider. Operator-tunable; Phase 3
|