@mlx-node/lm 0.0.7 → 0.0.9
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 +56 -38
- package/dist/chat-session.d.ts +372 -104
- package/dist/chat-session.d.ts.map +1 -1
- package/dist/chat-session.js +891 -187
- package/dist/index.d.ts +12 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -7
- package/dist/interfaces.d.ts +2 -17
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/models/lfm2-configs.d.ts.map +1 -1
- package/dist/models/lfm2-configs.js +59 -0
- package/dist/models/model-loader.d.ts +175 -4
- package/dist/models/model-loader.d.ts.map +1 -1
- package/dist/models/model-loader.js +226 -49
- package/dist/models/paged-config-override.d.ts +72 -0
- package/dist/models/paged-config-override.d.ts.map +1 -0
- package/dist/models/paged-config-override.js +291 -0
- package/dist/models/qwen3_5-configs.d.ts.map +1 -1
- package/dist/models/qwen3_5-configs.js +5 -0
- package/dist/stream.d.ts +216 -103
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +192 -229
- package/package.json +3 -3
|
@@ -5,44 +5,215 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { readFile } from 'node:fs/promises';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
|
-
import { HarrierModel, QianfanOCRModel } from '@mlx-node/core';
|
|
8
|
+
import { Gemma4Model as NativeGemma4Model, HarrierModel, Lfm2Model as NativeLfm2Model, QianfanOCRModel, Qwen3Model as NativeQwen3Model, Qwen35Model as NativeQwen35Model, Qwen35MoeModel as NativeQwen35MoeModel, } from '@mlx-node/core';
|
|
9
9
|
import { ChatSession } from '../chat-session.js';
|
|
10
10
|
import { Gemma4Model, Lfm2Model, Qwen3Model, Qwen35Model, Qwen35MoeModel } from '../stream.js';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Ordered source of truth for every supported model family. Each entry owns
|
|
13
|
+
* its canonical `ModelType`, raw config aliases / architecture probes, loader,
|
|
14
|
+
* and `ChatSession` eligibility:
|
|
15
|
+
*
|
|
16
|
+
* - `'trainable'` — GRPO/SFT-capable LM (Qwen3 family); chat-capable.
|
|
17
|
+
* - `'loadable'` — chat-capable LM with no trainer engine (Gemma4, LFM2).
|
|
18
|
+
* - `'embedding'` — no chat surface (Harrier); rejected by `loadSession`.
|
|
19
|
+
* - `'vlm'` — VLM whose AsyncGenerator wrapper lives in
|
|
20
|
+
* `@mlx-node/vlm` (importing it here would create a
|
|
21
|
+
* circular package dependency), so `loadSession`
|
|
22
|
+
* rejects it and routes callers to `@mlx-node/vlm`.
|
|
23
|
+
*
|
|
24
|
+
* A base family is selected from an explicit alias or the single declarative
|
|
25
|
+
* nullish-model_type default, then architecture probes refine it in declaration
|
|
26
|
+
* order. Gemma's unified architecture is authoritative (matching the native
|
|
27
|
+
* loader); Harrier refines a Qwen3 base. Adding a family means adding one
|
|
28
|
+
* descriptor here, without a second normalization or dispatch branch.
|
|
29
|
+
*/
|
|
30
|
+
const MODEL_FAMILY_REGISTRY = [
|
|
31
|
+
{
|
|
32
|
+
modelType: 'gemma4',
|
|
33
|
+
kind: 'loadable',
|
|
34
|
+
match: {
|
|
35
|
+
rawModelTypes: ['gemma4', 'gemma4_text', 'gemma4_unified'],
|
|
36
|
+
architectureProbe: ({ architectures }) => architectures.has('Gemma4UnifiedForConditionalGeneration'),
|
|
37
|
+
},
|
|
38
|
+
load: (modelPath, options) => Gemma4Model.load(modelPath, options?.draftModelPath === undefined ? null : { draftModelPath: options.draftModelPath }),
|
|
39
|
+
nativeModelClass: NativeGemma4Model,
|
|
40
|
+
acceptsDraftModel: true,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
modelType: 'harrier',
|
|
44
|
+
kind: 'embedding',
|
|
45
|
+
match: {
|
|
46
|
+
rawModelTypes: ['harrier'],
|
|
47
|
+
architectureProbe: ({ modelType, architectures }) => modelType === 'qwen3' && architectures.has('Qwen3Model') && !architectures.has('Qwen3ForCausalLM'),
|
|
48
|
+
},
|
|
49
|
+
load: (modelPath) => HarrierModel.load(modelPath),
|
|
50
|
+
nativeModelClass: HarrierModel,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
modelType: 'qwen3',
|
|
54
|
+
kind: 'trainable',
|
|
55
|
+
match: { rawModelTypes: ['qwen3'] },
|
|
56
|
+
load: (modelPath) => Qwen3Model.load(modelPath),
|
|
57
|
+
nativeModelClass: NativeQwen3Model,
|
|
58
|
+
defaultForNullishModelType: true,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
modelType: 'qwen3_5',
|
|
62
|
+
kind: 'trainable',
|
|
63
|
+
match: { rawModelTypes: ['qwen3_5'] },
|
|
64
|
+
load: (modelPath) => Qwen35Model.load(modelPath),
|
|
65
|
+
nativeModelClass: NativeQwen35Model,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
modelType: 'qwen3_5_moe',
|
|
69
|
+
kind: 'trainable',
|
|
70
|
+
match: { rawModelTypes: ['qwen3_5_moe'] },
|
|
71
|
+
load: (modelPath) => Qwen35MoeModel.load(modelPath),
|
|
72
|
+
nativeModelClass: NativeQwen35MoeModel,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
modelType: 'lfm2',
|
|
76
|
+
kind: 'loadable',
|
|
77
|
+
match: { rawModelTypes: ['lfm2'] },
|
|
78
|
+
load: (modelPath) => Lfm2Model.load(modelPath),
|
|
79
|
+
nativeModelClass: NativeLfm2Model,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
modelType: 'lfm2_moe',
|
|
83
|
+
kind: 'loadable',
|
|
84
|
+
match: { rawModelTypes: ['lfm2_moe'] },
|
|
85
|
+
load: (modelPath) => Lfm2Model.load(modelPath),
|
|
86
|
+
nativeModelClass: NativeLfm2Model,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
modelType: 'internvl_chat',
|
|
90
|
+
kind: 'vlm',
|
|
91
|
+
match: { rawModelTypes: ['internvl_chat'] },
|
|
92
|
+
load: (modelPath) => QianfanOCRModel.load(modelPath),
|
|
93
|
+
nativeModelClass: QianfanOCRModel,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
modelType: 'qianfan-ocr',
|
|
97
|
+
kind: 'vlm',
|
|
98
|
+
match: { rawModelTypes: ['qianfan-ocr'] },
|
|
99
|
+
load: (modelPath) => QianfanOCRModel.load(modelPath),
|
|
100
|
+
nativeModelClass: QianfanOCRModel,
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
function buildModelFamilyIndex(registry) {
|
|
104
|
+
const byModelType = new Map();
|
|
105
|
+
const byRawModelType = new Map();
|
|
106
|
+
let defaultForNullishModelType;
|
|
107
|
+
for (const family of registry) {
|
|
108
|
+
const previousFamily = byModelType.get(family.modelType);
|
|
109
|
+
if (previousFamily !== undefined) {
|
|
110
|
+
throw new Error(`Duplicate canonical model type "${family.modelType}" in model family registry`);
|
|
111
|
+
}
|
|
112
|
+
byModelType.set(family.modelType, family);
|
|
113
|
+
for (const rawModelType of family.match.rawModelTypes) {
|
|
114
|
+
const previous = byRawModelType.get(rawModelType);
|
|
115
|
+
if (previous !== undefined) {
|
|
116
|
+
throw new Error(`Duplicate model_type alias "${rawModelType}" for "${previous.modelType}" and "${family.modelType}"`);
|
|
117
|
+
}
|
|
118
|
+
byRawModelType.set(rawModelType, family);
|
|
119
|
+
}
|
|
120
|
+
if (family.defaultForNullishModelType === true) {
|
|
121
|
+
if (defaultForNullishModelType !== undefined) {
|
|
122
|
+
throw new Error(`Duplicate nullish-model_type defaults for "${defaultForNullishModelType.modelType}" and "${family.modelType}"`);
|
|
123
|
+
}
|
|
124
|
+
defaultForNullishModelType = family;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (defaultForNullishModelType === undefined) {
|
|
128
|
+
throw new Error('Model family registry must declare exactly one nullish-model_type default');
|
|
129
|
+
}
|
|
130
|
+
return { byModelType, byRawModelType, defaultForNullishModelType };
|
|
131
|
+
}
|
|
132
|
+
const MODEL_FAMILY_INDEX = buildModelFamilyIndex(MODEL_FAMILY_REGISTRY);
|
|
133
|
+
function findFamily(modelType) {
|
|
134
|
+
const family = MODEL_FAMILY_INDEX.byModelType.get(modelType);
|
|
135
|
+
if (family === undefined) {
|
|
136
|
+
throw new Error(`Internal error: missing model family descriptor for "${modelType}"`);
|
|
137
|
+
}
|
|
138
|
+
return family;
|
|
139
|
+
}
|
|
140
|
+
function matchesArchitectureProbe(family, config) {
|
|
141
|
+
return family.match.architectureProbe?.(config) === true;
|
|
142
|
+
}
|
|
143
|
+
class MalformedModelConfigError extends Error {
|
|
144
|
+
constructor(modelPath, reason) {
|
|
145
|
+
super(`Malformed config.json in ${modelPath}: ${reason}`);
|
|
146
|
+
this.name = 'MalformedModelConfigError';
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Fail-closed validation: a config.json whose root is not a plain object,
|
|
151
|
+
* or whose `architectures` is neither an array nor a string, is rejected
|
|
152
|
+
* instead of coerced (coercion would fall through to the qwen3
|
|
153
|
+
* nullish-model_type default and silently misroute the checkpoint).
|
|
154
|
+
* Blessed lenient shapes stay accepted: `{}` root (qwen3 default),
|
|
155
|
+
* missing/`null` `architectures` (empty set), bare-string `architectures`
|
|
156
|
+
* (single-element set), and non-string array entries (filtered out).
|
|
157
|
+
*/
|
|
158
|
+
function normalizeConfig(modelPath, config) {
|
|
159
|
+
if (typeof config !== 'object' || config === null || Array.isArray(config)) {
|
|
160
|
+
throw new MalformedModelConfigError(modelPath, 'root must be a JSON object');
|
|
161
|
+
}
|
|
162
|
+
const object = config;
|
|
163
|
+
const hasModelType = Object.hasOwn(object, 'model_type');
|
|
164
|
+
const rawModelTypeValue = hasModelType ? object.model_type : undefined;
|
|
165
|
+
const usesDefaultModelType = !hasModelType || rawModelTypeValue === null;
|
|
166
|
+
const rawModelType = typeof rawModelTypeValue === 'string' ? rawModelTypeValue : undefined;
|
|
167
|
+
const rawModelTypeLabel = hasModelType ? String(rawModelTypeValue) : '<missing>';
|
|
168
|
+
const rawArchitectures = 'architectures' in object ? object.architectures : undefined;
|
|
169
|
+
if (rawArchitectures !== undefined &&
|
|
170
|
+
rawArchitectures !== null &&
|
|
171
|
+
!Array.isArray(rawArchitectures) &&
|
|
172
|
+
typeof rawArchitectures !== 'string') {
|
|
173
|
+
throw new MalformedModelConfigError(modelPath, '"architectures" must be an array or a string');
|
|
174
|
+
}
|
|
175
|
+
const architectures = Array.isArray(rawArchitectures)
|
|
176
|
+
? rawArchitectures.filter((architecture) => typeof architecture === 'string')
|
|
177
|
+
: typeof rawArchitectures === 'string'
|
|
178
|
+
? [rawArchitectures]
|
|
179
|
+
: [];
|
|
180
|
+
return { usesDefaultModelType, rawModelType, rawModelTypeLabel, architectures: new Set(architectures) };
|
|
181
|
+
}
|
|
182
|
+
class UnsupportedModelTypeError extends Error {
|
|
183
|
+
constructor(modelPath, rawModelTypeLabel) {
|
|
184
|
+
super(`Unsupported model_type "${rawModelTypeLabel}" in ${modelPath}/config.json`);
|
|
185
|
+
this.name = 'UnsupportedModelTypeError';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Dispatch a load through the registry, validating gemma4-only options.
|
|
190
|
+
* `draftModelPath` reaches ONLY the gemma4 row; every other family rejects
|
|
191
|
+
* it loudly instead of silently ignoring a caller's speculative-decode
|
|
192
|
+
* intent.
|
|
193
|
+
*/
|
|
194
|
+
function dispatchLoad(modelType, modelPath, options) {
|
|
195
|
+
const family = findFamily(modelType);
|
|
196
|
+
if (options?.draftModelPath !== undefined && family.acceptsDraftModel !== true) {
|
|
197
|
+
throw new Error(`draftModelPath (speculative-decoding draft) is only supported by gemma4 models; ` +
|
|
198
|
+
`${modelPath} has model_type "${modelType}"`);
|
|
199
|
+
}
|
|
200
|
+
return family.load(modelPath, options);
|
|
201
|
+
}
|
|
21
202
|
/**
|
|
22
203
|
* Load a model from disk, auto-detecting architecture from config.json.
|
|
23
204
|
*
|
|
24
205
|
* Supports both language models (Qwen3, Qwen3.5) and vision-language models
|
|
25
206
|
* (Qianfan-OCR / InternVL). Use `instanceof` to narrow the returned type.
|
|
207
|
+
*
|
|
208
|
+
* `options.draftModelPath` attaches an external draft checkpoint (DSpark or
|
|
209
|
+
* Google gemma-4 assistant, auto-detected from the draft's config.json) for
|
|
210
|
+
* speculative decoding — gemma4 only; any other detected family rejects it.
|
|
211
|
+
* Without the option, Gemma4 loads `<modelPath>/draft/` automatically when
|
|
212
|
+
* that embedded checkpoint is present.
|
|
26
213
|
*/
|
|
27
|
-
export async function loadModel(modelPath) {
|
|
214
|
+
export async function loadModel(modelPath, options) {
|
|
28
215
|
const modelType = await detectModelType(modelPath);
|
|
29
|
-
|
|
30
|
-
case 'qwen3_5_moe':
|
|
31
|
-
return Qwen35MoeModel.load(modelPath);
|
|
32
|
-
case 'qwen3_5':
|
|
33
|
-
return Qwen35Model.load(modelPath);
|
|
34
|
-
case 'qwen3':
|
|
35
|
-
return Qwen3Model.load(modelPath);
|
|
36
|
-
case 'harrier':
|
|
37
|
-
return HarrierModel.load(modelPath);
|
|
38
|
-
case 'internvl_chat':
|
|
39
|
-
case 'qianfan-ocr':
|
|
40
|
-
return QianfanOCRModel.load(modelPath);
|
|
41
|
-
case 'gemma4':
|
|
42
|
-
return Gemma4Model.load(modelPath);
|
|
43
|
-
case 'lfm2':
|
|
44
|
-
return Lfm2Model.load(modelPath);
|
|
45
|
-
}
|
|
216
|
+
return dispatchLoad(modelType, modelPath, options);
|
|
46
217
|
}
|
|
47
218
|
/**
|
|
48
219
|
* Load a model and wrap it in a {@link ChatSession} for multi-turn chat.
|
|
@@ -59,38 +230,44 @@ export async function loadModel(modelPath) {
|
|
|
59
230
|
* package dependency), so callers who want a Qianfan-OCR session
|
|
60
231
|
* must import `QianfanOCRModel` from `@mlx-node/vlm` and construct
|
|
61
232
|
* `new ChatSession(model)` directly.
|
|
233
|
+
*
|
|
234
|
+
* `options.draftModelPath` attaches an external draft checkpoint (DSpark or
|
|
235
|
+
* Google gemma-4 assistant, auto-detected from the draft's config.json) for
|
|
236
|
+
* speculative decoding — gemma4 only; any other detected family rejects it.
|
|
237
|
+
* Without the option, Gemma4 loads `<modelPath>/draft/` automatically when
|
|
238
|
+
* that embedded checkpoint is present.
|
|
239
|
+
* The resulting session auto-enables the speculative path (the model
|
|
240
|
+
* reports `hasMtpWeights()`); pass `enableMtp: false` per call to opt out.
|
|
62
241
|
*/
|
|
63
|
-
export async function loadSession(modelPath) {
|
|
64
|
-
const
|
|
65
|
-
|
|
242
|
+
export async function loadSession(modelPath, options) {
|
|
243
|
+
const modelType = await detectModelType(modelPath);
|
|
244
|
+
const kind = findFamily(modelType).kind;
|
|
245
|
+
if (kind === 'embedding') {
|
|
66
246
|
throw new Error('loadSession: embedding models (Harrier) cannot be wrapped in a ChatSession');
|
|
67
247
|
}
|
|
68
|
-
if (
|
|
248
|
+
if (kind === 'vlm') {
|
|
69
249
|
throw new Error('loadSession: Qianfan-OCR / InternVL session support lives in @mlx-node/vlm. Import QianfanOCRModel from @mlx-node/vlm and construct ChatSession(model) directly.');
|
|
70
250
|
}
|
|
251
|
+
const m = await dispatchLoad(modelType, modelPath, options);
|
|
71
252
|
return new ChatSession(m);
|
|
72
253
|
}
|
|
73
254
|
export async function detectModelType(modelPath) {
|
|
74
255
|
try {
|
|
75
256
|
const raw = await readFile(join(modelPath, 'config.json'), 'utf-8');
|
|
76
|
-
const config = JSON.parse(raw);
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (!SUPPORTED_MODEL_TYPES.has(modelType)) {
|
|
88
|
-
throw new Error(`Unsupported model_type "${modelType}" in ${modelPath}/config.json`);
|
|
89
|
-
}
|
|
90
|
-
return modelType;
|
|
257
|
+
const config = normalizeConfig(modelPath, JSON.parse(raw));
|
|
258
|
+
const baseFamily = config.usesDefaultModelType
|
|
259
|
+
? MODEL_FAMILY_INDEX.defaultForNullishModelType
|
|
260
|
+
: config.rawModelType === undefined
|
|
261
|
+
? undefined
|
|
262
|
+
: MODEL_FAMILY_INDEX.byRawModelType.get(config.rawModelType);
|
|
263
|
+
const matchContext = { ...config, modelType: baseFamily?.modelType };
|
|
264
|
+
const family = MODEL_FAMILY_REGISTRY.find((candidate) => matchesArchitectureProbe(candidate, matchContext)) ?? baseFamily;
|
|
265
|
+
if (family === undefined)
|
|
266
|
+
throw new UnsupportedModelTypeError(modelPath, config.rawModelTypeLabel);
|
|
267
|
+
return family.modelType;
|
|
91
268
|
}
|
|
92
269
|
catch (e) {
|
|
93
|
-
if (e instanceof
|
|
270
|
+
if (e instanceof UnsupportedModelTypeError || e instanceof MalformedModelConfigError)
|
|
94
271
|
throw e;
|
|
95
272
|
throw new Error(`Cannot detect model type: config.json not found in ${modelPath}`);
|
|
96
273
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-local model-directory overrides for forcing block-paged KV caches.
|
|
3
|
+
*
|
|
4
|
+
* Native model loaders accept a directory path and read paging policy from
|
|
5
|
+
* `config.json`. This manager creates an isolated temporary clone containing a
|
|
6
|
+
* patched config plus symlinks to the source files, so callers can opt models
|
|
7
|
+
* into paging without mutating downloaded checkpoints. Loader-known Qwen3.5
|
|
8
|
+
* MTP sidecars are preserved explicitly; unrelated directories (including a
|
|
9
|
+
* Gemma4 `draft/`) remain hidden unless a caller explicitly preserves the
|
|
10
|
+
* Gemma draft for flat speculative decoding.
|
|
11
|
+
*/
|
|
12
|
+
/** Every chat-capable family currently discovered by `@mlx-node/agent`. */
|
|
13
|
+
export declare const AGENT_PAGED_MODEL_TYPES: readonly ['qwen3', 'qwen3_5', 'qwen3_5_moe', 'gemma4', 'lfm2', 'lfm2_moe'];
|
|
14
|
+
/** Families historically forced paged by `mlx launch claude`. */
|
|
15
|
+
export declare const QWEN35_PAGED_MODEL_TYPES: readonly ['qwen3_5', 'qwen3_5_moe'];
|
|
16
|
+
export interface PagedConfigOverrideManagerOptions {
|
|
17
|
+
/** Model types to force onto the paged path. Defaults to all agent chat families. */
|
|
18
|
+
modelTypes?: readonly string[];
|
|
19
|
+
/** Temporary-directory prefix. Primarily useful for diagnostics/tests. */
|
|
20
|
+
tempDirPrefix?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Pass Gemma4 checkpoints with an embedded `draft/` through unchanged.
|
|
23
|
+
* This keeps native draft auto-discovery, which currently requires flat KV
|
|
24
|
+
* caches. Defaults to false so a paged override remains a paged contract.
|
|
25
|
+
*/
|
|
26
|
+
preserveEmbeddedGemmaDraft?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Owns one isolated set of temporary paged-config overrides.
|
|
30
|
+
*
|
|
31
|
+
* A manager is intentionally single-lifecycle: repeated resolution of one
|
|
32
|
+
* source returns the same override, and `cleanup()` permanently disposes the
|
|
33
|
+
* manager. Separate managers never share directories, so one launch cannot
|
|
34
|
+
* remove another launch's live override.
|
|
35
|
+
*/
|
|
36
|
+
export declare class PagedConfigOverrideManager {
|
|
37
|
+
private readonly modelTypes;
|
|
38
|
+
private readonly tempDirPrefix;
|
|
39
|
+
private readonly preserveEmbeddedGemmaDraft;
|
|
40
|
+
private readonly overrides;
|
|
41
|
+
private readonly activeResolves;
|
|
42
|
+
private rootPromise;
|
|
43
|
+
private cleanupPromise;
|
|
44
|
+
private disposed;
|
|
45
|
+
constructor(options?: PagedConfigOverrideManagerOptions);
|
|
46
|
+
/**
|
|
47
|
+
* Resolve `modelPath` to a paged-aware clone when its model type is managed.
|
|
48
|
+
* A caller-supplied canonical family takes precedence over the raw config
|
|
49
|
+
* type (for example, `gemma4` for a `gemma4_unified` checkpoint).
|
|
50
|
+
* Unmanaged, unreadable, or malformed checkpoints pass through unchanged.
|
|
51
|
+
*
|
|
52
|
+
* `persistPagedCache` is a tri-state cold-tier directive. `undefined` leaves
|
|
53
|
+
* the field untouched (families with no cold-tier opt-in). A boolean is
|
|
54
|
+
* AUTHORITATIVE: it writes `persist_paged_cache: <value>` into the cloned
|
|
55
|
+
* config, overriding whatever the source config.json carries (either alias),
|
|
56
|
+
* and forces a clone whenever the source's value disagrees so the directive
|
|
57
|
+
* actually reaches the loader. Callers gate the boolean to the families whose
|
|
58
|
+
* paged cold restore is sound — the allowlist in
|
|
59
|
+
* `packages/agent/src/cold-tier.ts`, mirrored by `COLD_RESTORE_FAMILIES` in
|
|
60
|
+
* `crates/mlx-core/src/cold_tier.rs`. It is a SET, not one family, and it is
|
|
61
|
+
* deliberately not repeated here: `MlxModelHost` calls this for every
|
|
62
|
+
* allowlisted family, and a second copy of the list would drift.
|
|
63
|
+
*/
|
|
64
|
+
resolve(modelPath: string, canonicalModelType?: string, persistPagedCache?: boolean): Promise<string>;
|
|
65
|
+
private resolveInternal;
|
|
66
|
+
/** Remove this manager's temporary root without affecting other managers. */
|
|
67
|
+
cleanup(): Promise<void>;
|
|
68
|
+
private performCleanup;
|
|
69
|
+
private createOverride;
|
|
70
|
+
private getRoot;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=paged-config-override.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paged-config-override.d.ts","sourceRoot":"","sources":["../../src/models/paged-config-override.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB,YAAI,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAU,CAAC;AAElH,iEAAiE;AACjE,eAAO,MAAM,wBAAwB,YAAI,SAAS,EAAE,aAAa,CAAU,CAAC;AAO5E,MAAM,WAAW,iCAAiC;IAChD,qFAAqF;IACrF,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAED;;;;;;;GAOG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAU;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA8B;IAC7D,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,QAAQ,CAAS;IAEzB,YAAY,OAAO,GAAE,iCAAsC,EAI1D;IAED;;;;;;;;;;;;;;;;;OAiBG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,kBAAkB,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAY1G;YAEa,eAAe;IAuE7B,6EAA6E;IAC7E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAKvB;YAEa,cAAc;YAad,cAAc;IAsD5B,OAAO,CAAC,OAAO;CAIhB"}
|