@mlx-node/agent 0.0.10 → 0.0.12
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.d.ts +73 -11
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +88 -16
- package/dist/cold-tier.d.ts +9 -9
- package/dist/cold-tier.d.ts.map +1 -1
- package/dist/cold-tier.js +19 -24
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/provider/chat-config.d.ts +3 -15
- package/dist/provider/chat-config.d.ts.map +1 -1
- package/dist/provider/chat-config.js +15 -38
- package/dist/provider/model-host.d.ts.map +1 -1
- package/dist/provider/model-host.js +7 -1
- package/dist/provider/models.d.ts +19 -15
- package/dist/provider/models.d.ts.map +1 -1
- package/dist/provider/models.js +165 -66
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -8
package/dist/catalog.d.ts
CHANGED
|
@@ -1,41 +1,103 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Curated model catalog for `mlx agent`.
|
|
3
3
|
*
|
|
4
|
-
* The first-run download wizard
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* use them verbatim.
|
|
4
|
+
* The first-run download wizard offers `visibleCatalog()` and feeds the chosen
|
|
5
|
+
* entry's `catalogRepo()` to `mlx download model`. Slugs are verified against the Brooooooklyn
|
|
6
|
+
* HF account — use them verbatim.
|
|
8
7
|
*/
|
|
9
8
|
export interface CatalogEntry {
|
|
10
9
|
/** Wizard display name. */
|
|
11
10
|
label: string;
|
|
12
|
-
/** HF slug for `mlx download model
|
|
11
|
+
/** HF slug for `mlx download model` on Apple Silicon — the MXFP4 build. */
|
|
13
12
|
hfRepo: string;
|
|
13
|
+
/**
|
|
14
|
+
* HF slug on Linux + NVIDIA CUDA — the NVFP4 build.
|
|
15
|
+
*
|
|
16
|
+
* Absent means the entry has no CUDA-specific build and {@link hfRepo}
|
|
17
|
+
* serves both. Resolve with {@link catalogRepo}, never by reading the field.
|
|
18
|
+
*/
|
|
19
|
+
hfRepoCuda?: string;
|
|
14
20
|
/** Approximate download size in GB, for display. */
|
|
15
21
|
sizeGb: number;
|
|
16
22
|
/** One line for the wizard. */
|
|
17
23
|
description: string;
|
|
18
24
|
/** Exactly one entry carries this. */
|
|
19
25
|
isDefault?: boolean;
|
|
20
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* The repo is not published yet, so no UI may offer it as a download.
|
|
28
|
+
*
|
|
29
|
+
* Two consumers honour this: the agent wizard via {@link visibleCatalog},
|
|
30
|
+
* and the dashboard Models page, which filters `!item.hidden` before
|
|
31
|
+
* rendering cards (`packages/dashboard/ui/src/pages/models.tsx`).
|
|
32
|
+
* `catalogWithState()` deliberately keeps hidden entries so the UI, not the
|
|
33
|
+
* dashboard core, decides.
|
|
34
|
+
*
|
|
35
|
+
* Also honoured by the download allowlist: `DownloadManager.start`
|
|
36
|
+
* (`packages/dashboard/src/download.ts`) refuses a hidden repo up front
|
|
37
|
+
* rather than allocating a job that fails mid-download with a 401 from
|
|
38
|
+
* Hugging Face. No UI reaches that path for a hidden entry, but a direct
|
|
39
|
+
* API call does.
|
|
40
|
+
*/
|
|
21
41
|
hidden?: boolean;
|
|
22
42
|
}
|
|
23
43
|
export declare const MODEL_CATALOG: readonly CatalogEntry[];
|
|
44
|
+
/**
|
|
45
|
+
* The repo THIS platform installs for `entry`. Linux is the CUDA preview
|
|
46
|
+
* target (README "Platform Support"); everything else is Apple Silicon.
|
|
47
|
+
*
|
|
48
|
+
* NOT because Metal cannot run NVFP4 — it can. MLX ships the same 234
|
|
49
|
+
* quantized Metal kernels for `nvfp4` as for `mxfp4`, NAX variants included,
|
|
50
|
+
* and only `fp8_e4m3` reconstructs BF16 at load. The MSL 4.1 hardware
|
|
51
|
+
* block-scale format (`metal_fp8_ue8m0_format`) appears nowhere in MLX's Metal
|
|
52
|
+
* backend, so it constrains neither format here.
|
|
53
|
+
*
|
|
54
|
+
* The split is:
|
|
55
|
+
* - CUDA takes NVFP4 through `CublasQQMM` (`nvfp4` -> `CUDA_R_4F_E2M1`), a
|
|
56
|
+
* native path with no MXFP4 equivalent.
|
|
57
|
+
* - Metal has no such native-path advantage either way, so prefer the format
|
|
58
|
+
* that survives quantization better. NVFP4 stores a block scale as `amax/6`
|
|
59
|
+
* in E4M3, and real FFN blocks land in its subnormal band;
|
|
60
|
+
* `apply_nvfp4_pow2_lift` repairs that for dense SwiGLU FFNs but SKIPS MoE
|
|
61
|
+
* experts by design (`NVFP4_LIFT_MOE_MARKERS`, `crates/mlx-core/src/
|
|
62
|
+
* convert.rs`), because the norm there also drives the router and the
|
|
63
|
+
* shared-expert gate, neither scale-invariant. Two of the three visible
|
|
64
|
+
* entries are MoE. MXFP4's E8M0 block scales have no such failure.
|
|
65
|
+
*
|
|
66
|
+
* Unmeasured: whether nvfp4 or mxfp4 decodes faster on Metal. The choice above
|
|
67
|
+
* is made on quantization quality, not throughput.
|
|
68
|
+
*
|
|
69
|
+
* Every consumer that turns a catalog entry into a download, a slug, or an
|
|
70
|
+
* allowlist check must go through here. Reading `entry.hfRepo` directly
|
|
71
|
+
* installs the macOS build on a CUDA box.
|
|
72
|
+
*/
|
|
73
|
+
export declare function catalogRepo(entry: CatalogEntry): string;
|
|
74
|
+
/**
|
|
75
|
+
* {@link catalogRepo} with the platform passed in — the pure half.
|
|
76
|
+
*
|
|
77
|
+
* Exists so both branches can be asserted without touching `process.platform`.
|
|
78
|
+
* Mutating that global leaks across test files sharing a worker: it made
|
|
79
|
+
* `catalogRepo` disagree with a sibling suite's module-level constant and fail
|
|
80
|
+
* a download allowlist check that has nothing to do with the catalog.
|
|
81
|
+
*/
|
|
82
|
+
export declare function catalogRepoFor(entry: CatalogEntry, platform: NodeJS.Platform): string;
|
|
24
83
|
/** Catalog entries the wizard offers (hidden entries filtered out). */
|
|
25
84
|
export declare function visibleCatalog(): CatalogEntry[];
|
|
26
85
|
/**
|
|
27
|
-
* Cold-tier facts, re-exported through this
|
|
86
|
+
* Cold-tier facts and family registration data, re-exported through this
|
|
87
|
+
* subpath.
|
|
28
88
|
*
|
|
29
89
|
* `@mlx-node/agent/catalog` is the agent package's one NATIVE-FREE entry point:
|
|
30
90
|
* the package root re-exports `provider/index.ts`, which value-imports
|
|
31
91
|
* `@mlx-node/core`. The dashboard is a separate viewer process that must never
|
|
32
92
|
* link the addon (docs/dashboard.md: "no Metal init, instant start"), and
|
|
33
93
|
* `mlx agent --help` must print without loading weights — so both reach the
|
|
34
|
-
* cold-tier allowlist
|
|
94
|
+
* cold-tier allowlist, the cache-root canonicalizer, and the family detection
|
|
95
|
+
* data through here.
|
|
35
96
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
97
|
+
* Every module reachable from here must therefore stay free of runtime addon
|
|
98
|
+
* imports. `packages/agent/__test__/catalog-native-free.test.ts` gates that in a
|
|
99
|
+
* real subprocess.
|
|
39
100
|
*/
|
|
40
101
|
export { COLD_TIER_RESTORE_FAMILIES, canonicalCacheRoot, coldTierRestoreFamilyList } from './cold-tier.js';
|
|
102
|
+
export { CHAT_FAMILY_IDS, matchFamily, NON_GENERATIVE_FAMILY_IDS, rawModelTypeToCanonical, } from '@mlx-node/lm/family-data';
|
|
41
103
|
//# sourceMappingURL=catalog.d.ts.map
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,YAAY;IAC3B,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,YAAY,EA0DhD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CAErF;AAED,uEAAuE;AACvE,wBAAgB,cAAc,IAAI,YAAY,EAAE,CAE/C;AAED;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3G,OAAO,EACL,eAAe,EACf,WAAW,EACX,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC"}
|
package/dist/catalog.js
CHANGED
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Curated model catalog for `mlx agent`.
|
|
3
3
|
*
|
|
4
|
-
* The first-run download wizard
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* use them verbatim.
|
|
4
|
+
* The first-run download wizard offers `visibleCatalog()` and feeds the chosen
|
|
5
|
+
* entry's `catalogRepo()` to `mlx download model`. Slugs are verified against the Brooooooklyn
|
|
6
|
+
* HF account — use them verbatim.
|
|
8
7
|
*/
|
|
9
8
|
export const MODEL_CATALOG = [
|
|
10
9
|
{
|
|
11
|
-
label: 'Qwen3.
|
|
12
|
-
hfRepo: 'Brooooooklyn/Qwen3.
|
|
13
|
-
|
|
10
|
+
label: 'Qwen3.8-27B',
|
|
11
|
+
hfRepo: 'Brooooooklyn/Qwen3.8-27B-MXFP4-mlx',
|
|
12
|
+
hfRepoCuda: 'Brooooooklyn/Qwen3.8-27B-NVFP4-mlx',
|
|
13
|
+
sizeGb: 23.3,
|
|
14
14
|
description: 'Best tool use — recommended default',
|
|
15
15
|
isDefault: true,
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
label: 'Qwen-AgentWorld-35B',
|
|
19
|
-
hfRepo: 'Brooooooklyn/Qwen-AgentWorld-35B-A3B-
|
|
20
|
-
|
|
19
|
+
hfRepo: 'Brooooooklyn/Qwen-AgentWorld-35B-A3B-mxfp4-mlx',
|
|
20
|
+
hfRepoCuda: 'Brooooooklyn/Qwen-AgentWorld-35B-A3B-nvfp4-mlx',
|
|
21
|
+
sizeGb: 23.3,
|
|
21
22
|
description: 'Agent-tuned MoE, fast decode',
|
|
22
23
|
},
|
|
23
24
|
{
|
|
24
25
|
label: 'Gemma-4-26B-A4B',
|
|
25
|
-
hfRepo: 'Brooooooklyn/Gemma-4-26B-A4B-
|
|
26
|
-
|
|
26
|
+
hfRepo: 'Brooooooklyn/Gemma-4-26B-A4B-Unsloth-MXFP4-mlx',
|
|
27
|
+
hfRepoCuda: 'Brooooooklyn/Gemma-4-26B-A4B-Unsloth-NVFP4-mlx',
|
|
28
|
+
sizeGb: 16.2,
|
|
27
29
|
description: 'MoE, fast decode',
|
|
28
30
|
},
|
|
29
31
|
{
|
|
@@ -37,23 +39,93 @@ export const MODEL_CATALOG = [
|
|
|
37
39
|
description: 'Compact (mxfp4 MLP + mxfp8 attention), fits smaller machines',
|
|
38
40
|
hidden: true,
|
|
39
41
|
},
|
|
42
|
+
{
|
|
43
|
+
// NOT DOWNLOADABLE. This repo does not exist: the slug below is a
|
|
44
|
+
// placeholder the user has not uploaded to, and Hugging Face answers 401
|
|
45
|
+
// for it. Nothing may offer it as an install until the upload happens and
|
|
46
|
+
// `hidden` is dropped — and do not guess a substitute slug, because a
|
|
47
|
+
// wrong-but-live repo would install the wrong weights silently.
|
|
48
|
+
//
|
|
49
|
+
// The only route to this model today is local conversion from NVIDIA's
|
|
50
|
+
// modelopt checkpoint:
|
|
51
|
+
// mlx convert -m nemotron_h \
|
|
52
|
+
// -i <nvidia/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-NVFP4> \
|
|
53
|
+
// -o <models>/nemotron-3.5-lightning-30b-a3b-nvfp4-mlx
|
|
54
|
+
// (NVFP4 preserved byte-for-byte; the FP8 Mamba-2 projections are
|
|
55
|
+
// re-quantized. See docs/cli.md "modelopt NVFP4 ingest".)
|
|
56
|
+
//
|
|
57
|
+
// The entry is kept — rather than deleted — so the wizard, the dashboard
|
|
58
|
+
// catalog state, and `catalogSlug()` recognize a locally converted
|
|
59
|
+
// checkpoint sitting at the canonical slug.
|
|
60
|
+
label: 'Nemotron-3.5-Lightning-30B-A3B',
|
|
61
|
+
hfRepo: 'Brooooooklyn/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-nvfp4-mlx',
|
|
62
|
+
sizeGb: 23,
|
|
63
|
+
description: 'Hybrid Mamba-2 + MoE, native MTP, 1M context',
|
|
64
|
+
hidden: true,
|
|
65
|
+
},
|
|
40
66
|
];
|
|
67
|
+
/**
|
|
68
|
+
* The repo THIS platform installs for `entry`. Linux is the CUDA preview
|
|
69
|
+
* target (README "Platform Support"); everything else is Apple Silicon.
|
|
70
|
+
*
|
|
71
|
+
* NOT because Metal cannot run NVFP4 — it can. MLX ships the same 234
|
|
72
|
+
* quantized Metal kernels for `nvfp4` as for `mxfp4`, NAX variants included,
|
|
73
|
+
* and only `fp8_e4m3` reconstructs BF16 at load. The MSL 4.1 hardware
|
|
74
|
+
* block-scale format (`metal_fp8_ue8m0_format`) appears nowhere in MLX's Metal
|
|
75
|
+
* backend, so it constrains neither format here.
|
|
76
|
+
*
|
|
77
|
+
* The split is:
|
|
78
|
+
* - CUDA takes NVFP4 through `CublasQQMM` (`nvfp4` -> `CUDA_R_4F_E2M1`), a
|
|
79
|
+
* native path with no MXFP4 equivalent.
|
|
80
|
+
* - Metal has no such native-path advantage either way, so prefer the format
|
|
81
|
+
* that survives quantization better. NVFP4 stores a block scale as `amax/6`
|
|
82
|
+
* in E4M3, and real FFN blocks land in its subnormal band;
|
|
83
|
+
* `apply_nvfp4_pow2_lift` repairs that for dense SwiGLU FFNs but SKIPS MoE
|
|
84
|
+
* experts by design (`NVFP4_LIFT_MOE_MARKERS`, `crates/mlx-core/src/
|
|
85
|
+
* convert.rs`), because the norm there also drives the router and the
|
|
86
|
+
* shared-expert gate, neither scale-invariant. Two of the three visible
|
|
87
|
+
* entries are MoE. MXFP4's E8M0 block scales have no such failure.
|
|
88
|
+
*
|
|
89
|
+
* Unmeasured: whether nvfp4 or mxfp4 decodes faster on Metal. The choice above
|
|
90
|
+
* is made on quantization quality, not throughput.
|
|
91
|
+
*
|
|
92
|
+
* Every consumer that turns a catalog entry into a download, a slug, or an
|
|
93
|
+
* allowlist check must go through here. Reading `entry.hfRepo` directly
|
|
94
|
+
* installs the macOS build on a CUDA box.
|
|
95
|
+
*/
|
|
96
|
+
export function catalogRepo(entry) {
|
|
97
|
+
return catalogRepoFor(entry, process.platform);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* {@link catalogRepo} with the platform passed in — the pure half.
|
|
101
|
+
*
|
|
102
|
+
* Exists so both branches can be asserted without touching `process.platform`.
|
|
103
|
+
* Mutating that global leaks across test files sharing a worker: it made
|
|
104
|
+
* `catalogRepo` disagree with a sibling suite's module-level constant and fail
|
|
105
|
+
* a download allowlist check that has nothing to do with the catalog.
|
|
106
|
+
*/
|
|
107
|
+
export function catalogRepoFor(entry, platform) {
|
|
108
|
+
return platform === 'linux' && entry.hfRepoCuda !== undefined ? entry.hfRepoCuda : entry.hfRepo;
|
|
109
|
+
}
|
|
41
110
|
/** Catalog entries the wizard offers (hidden entries filtered out). */
|
|
42
111
|
export function visibleCatalog() {
|
|
43
112
|
return MODEL_CATALOG.filter((entry) => !entry.hidden);
|
|
44
113
|
}
|
|
45
114
|
/**
|
|
46
|
-
* Cold-tier facts, re-exported through this
|
|
115
|
+
* Cold-tier facts and family registration data, re-exported through this
|
|
116
|
+
* subpath.
|
|
47
117
|
*
|
|
48
118
|
* `@mlx-node/agent/catalog` is the agent package's one NATIVE-FREE entry point:
|
|
49
119
|
* the package root re-exports `provider/index.ts`, which value-imports
|
|
50
120
|
* `@mlx-node/core`. The dashboard is a separate viewer process that must never
|
|
51
121
|
* link the addon (docs/dashboard.md: "no Metal init, instant start"), and
|
|
52
122
|
* `mlx agent --help` must print without loading weights — so both reach the
|
|
53
|
-
* cold-tier allowlist
|
|
123
|
+
* cold-tier allowlist, the cache-root canonicalizer, and the family detection
|
|
124
|
+
* data through here.
|
|
54
125
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
126
|
+
* Every module reachable from here must therefore stay free of runtime addon
|
|
127
|
+
* imports. `packages/agent/__test__/catalog-native-free.test.ts` gates that in a
|
|
128
|
+
* real subprocess.
|
|
58
129
|
*/
|
|
59
130
|
export { COLD_TIER_RESTORE_FAMILIES, canonicalCacheRoot, coldTierRestoreFamilyList } from './cold-tier.js';
|
|
131
|
+
export { CHAT_FAMILY_IDS, matchFamily, NON_GENERATIVE_FAMILY_IDS, rawModelTypeToCanonical, } from '@mlx-node/lm/family-data';
|
package/dist/cold-tier.d.ts
CHANGED
|
@@ -31,10 +31,11 @@
|
|
|
31
31
|
*
|
|
32
32
|
* - `qwen3` (dense) sizes its pool over all layers, so the pool holds the
|
|
33
33
|
* complete KV for the prefix and needs no sidecar.
|
|
34
|
-
* - `gemma4`
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
34
|
+
* - `gemma4` owns full and sliding attention in distinct paged groups. The
|
|
35
|
+
* full-attention chain is authoritative and one grouped sliding sidecar
|
|
36
|
+
* restores every sliding group at the same exact boundary, atomically.
|
|
37
|
+
* - `muse_glimmer` uses the same hybrid contract for its 13 full-attention
|
|
38
|
+
* and 39 sliding-attention layers.
|
|
38
39
|
* - `qwen3_5` (dense) sizes its pool over the full-attention layers only, but
|
|
39
40
|
* persists its out-of-pool GDN recurrent state (conv + recurrent) as a
|
|
40
41
|
* `ColdGroup::GdnState` sidecar, and its `ColdSidecarPolicy` reconciles the
|
|
@@ -43,13 +44,12 @@
|
|
|
43
44
|
* - `qwen3_5_moe` keeps the SAME GDN recurrent state outside the pool — same
|
|
44
45
|
* shapes, same dtype, same layer mapping — so it shares the dense family's
|
|
45
46
|
* sidecar codec and `ColdSidecarPolicy` verbatim. Its restart-parity gate has
|
|
46
|
-
* since been run on `Qwen3.6-
|
|
47
|
+
* since been run on `Qwen3.6-35B-A3B-mxfp4-mlx`: the restore reconciled
|
|
47
48
|
* onto ladder rung 304 of `[16, 64, 304, 1248]` with `hits=42` and
|
|
48
49
|
* `corruptions=0`, and the text matched a no-persist baseline.
|
|
49
|
-
* - `lfm2` / `lfm2_moe` keep
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* persistence on their behalf would restore an incomplete prefix silently.
|
|
50
|
+
* - `lfm2` / `lfm2_moe` keep ShortConv state outside the full-attention pool.
|
|
51
|
+
* A `ColdGroup::ConvState` sidecar persists that state at the same exact
|
|
52
|
+
* boundary; missing or malformed state reconciles down or restarts at zero.
|
|
53
53
|
*
|
|
54
54
|
* Widening this set is a correctness decision, never a perf one, and it is
|
|
55
55
|
* authorized by exactly one thing: the family's native restart-parity gate
|
package/dist/cold-tier.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cold-tier.d.ts","sourceRoot":"","sources":["../src/cold-tier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"cold-tier.d.ts","sourceRoot":"","sources":["../src/cold-tier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,MAAM,CAQzD,CAAC;AAEH,qFAAqF;AACrF,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAEpD;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwBvD"}
|
package/dist/cold-tier.js
CHANGED
|
@@ -34,10 +34,11 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
34
34
|
*
|
|
35
35
|
* - `qwen3` (dense) sizes its pool over all layers, so the pool holds the
|
|
36
36
|
* complete KV for the prefix and needs no sidecar.
|
|
37
|
-
* - `gemma4`
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
37
|
+
* - `gemma4` owns full and sliding attention in distinct paged groups. The
|
|
38
|
+
* full-attention chain is authoritative and one grouped sliding sidecar
|
|
39
|
+
* restores every sliding group at the same exact boundary, atomically.
|
|
40
|
+
* - `muse_glimmer` uses the same hybrid contract for its 13 full-attention
|
|
41
|
+
* and 39 sliding-attention layers.
|
|
41
42
|
* - `qwen3_5` (dense) sizes its pool over the full-attention layers only, but
|
|
42
43
|
* persists its out-of-pool GDN recurrent state (conv + recurrent) as a
|
|
43
44
|
* `ColdGroup::GdnState` sidecar, and its `ColdSidecarPolicy` reconciles the
|
|
@@ -46,13 +47,12 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
46
47
|
* - `qwen3_5_moe` keeps the SAME GDN recurrent state outside the pool — same
|
|
47
48
|
* shapes, same dtype, same layer mapping — so it shares the dense family's
|
|
48
49
|
* sidecar codec and `ColdSidecarPolicy` verbatim. Its restart-parity gate has
|
|
49
|
-
* since been run on `Qwen3.6-
|
|
50
|
+
* since been run on `Qwen3.6-35B-A3B-mxfp4-mlx`: the restore reconciled
|
|
50
51
|
* onto ladder rung 304 of `[16, 64, 304, 1248]` with `hits=42` and
|
|
51
52
|
* `corruptions=0`, and the text matched a no-persist baseline.
|
|
52
|
-
* - `lfm2` / `lfm2_moe` keep
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* persistence on their behalf would restore an incomplete prefix silently.
|
|
53
|
+
* - `lfm2` / `lfm2_moe` keep ShortConv state outside the full-attention pool.
|
|
54
|
+
* A `ColdGroup::ConvState` sidecar persists that state at the same exact
|
|
55
|
+
* boundary; missing or malformed state reconciles down or restarts at zero.
|
|
56
56
|
*
|
|
57
57
|
* Widening this set is a correctness decision, never a perf one, and it is
|
|
58
58
|
* authorized by exactly one thing: the family's native restart-parity gate
|
|
@@ -69,10 +69,13 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
69
69
|
* and asserted by `packages/cli/__test__/agent-cmd.test.ts`.
|
|
70
70
|
*/
|
|
71
71
|
export const COLD_TIER_RESTORE_FAMILIES = new Set([
|
|
72
|
-
'gemma4',
|
|
73
72
|
'qwen3',
|
|
74
73
|
'qwen3_5',
|
|
75
74
|
'qwen3_5_moe',
|
|
75
|
+
'gemma4',
|
|
76
|
+
'muse_glimmer',
|
|
77
|
+
'lfm2',
|
|
78
|
+
'lfm2_moe',
|
|
76
79
|
]);
|
|
77
80
|
/** Allowlisted families in a stable, human-facing order (help text, API payload). */
|
|
78
81
|
export function coldTierRestoreFamilyList() {
|
|
@@ -83,19 +86,6 @@ export function coldTierRestoreFamilyList() {
|
|
|
83
86
|
* prefix that is part of a longer name (`~cache`) is left alone — only the
|
|
84
87
|
* shell's own two spellings are expanded.
|
|
85
88
|
*/
|
|
86
|
-
/**
|
|
87
|
-
* `realpath(3)` rather than Node's JS walk.
|
|
88
|
-
*
|
|
89
|
-
* On a case-insensitive volume — APFS's default, i.e. essentially every Mac —
|
|
90
|
-
* `MLX_COLD_CACHE_DIR=~/CacheDir` and `~/cachedir` name the SAME directory, but
|
|
91
|
-
* `fs.realpathSync` hands back whichever spelling the caller typed. Two join
|
|
92
|
-
* keys for one cache is the F1 symptom inverted: a populated disk scan sitting
|
|
93
|
-
* beside a flat 0/0 trend. `realpathSync.native` folds each existing component
|
|
94
|
-
* to its on-disk spelling, so both env spellings produce one key.
|
|
95
|
-
*/
|
|
96
|
-
function realpathNative(path) {
|
|
97
|
-
return realpathSync.native(path);
|
|
98
|
-
}
|
|
99
89
|
function expandTilde(path) {
|
|
100
90
|
if (path === '~')
|
|
101
91
|
return homedir();
|
|
@@ -139,7 +129,12 @@ export function canonicalCacheRoot(root) {
|
|
|
139
129
|
let cursor = absolute;
|
|
140
130
|
for (;;) {
|
|
141
131
|
try {
|
|
142
|
-
|
|
132
|
+
// `realpathSync.native` (realpath(3)), not Node's JS walk: on a
|
|
133
|
+
// case-insensitive volume — APFS's default — `~/CacheDir` and `~/cachedir`
|
|
134
|
+
// name the SAME directory, but `fs.realpathSync` returns whichever spelling
|
|
135
|
+
// the caller typed. `.native` folds each existing component to its on-disk
|
|
136
|
+
// spelling, so both env spellings produce one join key.
|
|
137
|
+
const resolved = realpathSync.native(cursor);
|
|
143
138
|
return missing.length === 0 ? resolved : join(resolved, ...missing);
|
|
144
139
|
}
|
|
145
140
|
catch {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { DiscoveredModelLike } from './types.js';
|
|
2
|
-
export { type CatalogEntry, MODEL_CATALOG, visibleCatalog } from './catalog.js';
|
|
2
|
+
export { type CatalogEntry, catalogRepo, catalogRepoFor, MODEL_CATALOG, visibleCatalog } from './catalog.js';
|
|
3
3
|
export { createPermissionGateExtension } from './extensions/permission-gate.js';
|
|
4
4
|
export { createSubagentExtension, discoverSubagents, normalizeSubagentMode, type InProcessSubagentSession, type SubagentConfig, type SubagentExtensionOptions, type SubagentMode, type SubagentSessionCreateOptions, } from './extensions/subagent.js';
|
|
5
5
|
export { createTerminalTitleExtension } from './extensions/terminal-title.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAAE,KAAK,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAAE,KAAK,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7G,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,4BAA4B,GAClC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { MODEL_CATALOG, visibleCatalog } from './catalog.js';
|
|
1
|
+
export { catalogRepo, catalogRepoFor, MODEL_CATALOG, visibleCatalog } from './catalog.js';
|
|
2
2
|
export { createPermissionGateExtension } from './extensions/permission-gate.js';
|
|
3
3
|
export { createSubagentExtension, discoverSubagents, normalizeSubagentMode, } from './extensions/subagent.js';
|
|
4
4
|
export { createTerminalTitleExtension } from './extensions/terminal-title.js';
|
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-call `ChatConfig` assembly for the provider bridge.
|
|
3
3
|
*
|
|
4
|
-
* Base sampling + output budget come from
|
|
5
|
-
* `
|
|
6
|
-
* presets/preset types, nothing else) extended by the agent-local
|
|
7
|
-
* {@link AGENT_LAUNCH_PRESETS}, then pi's per-call `SimpleStreamOptions`
|
|
8
|
-
* overlay on top.
|
|
4
|
+
* Base sampling + output budget come from the family-data launch preset
|
|
5
|
+
* (`@mlx-node/lm`), then pi's per-call `SimpleStreamOptions` overlay on top.
|
|
9
6
|
*/
|
|
10
7
|
import type { SimpleStreamOptions, ThinkingLevel } from '@earendil-works/pi-ai';
|
|
11
|
-
import type
|
|
12
|
-
import { type LaunchPreset } from '@mlx-node/server';
|
|
13
|
-
/**
|
|
14
|
-
* Preset lookup — agent-local entries win over `LAUNCH_PRESETS` (they
|
|
15
|
-
* exist precisely because the server table has no correct entry for the
|
|
16
|
-
* type). This is the ONE preset resolution shared by discovery
|
|
17
|
-
* (`models.ts`) and per-call config assembly, so a model can never be
|
|
18
|
-
* discovered without also being streamable (and vice versa).
|
|
19
|
-
*/
|
|
20
|
-
export declare function launchPresetFor(modelType: ModelType): LaunchPreset | undefined;
|
|
8
|
+
import { type ChatConfig, type ModelType, type ToolDefinition } from '@mlx-node/lm';
|
|
21
9
|
export interface ResolvedReasoningMode {
|
|
22
10
|
reasoningEffort: 'none' | 'low' | 'medium' | 'high';
|
|
23
11
|
/** The `enable_thinking` value implied by `reasoningEffort` for templates. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-config.d.ts","sourceRoot":"","sources":["../../src/provider/chat-config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"chat-config.d.ts","sourceRoot":"","sources":["../../src/provider/chat-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAGL,KAAK,UAAU,EAEf,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AA8BtB,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpD,8EAA8E;IAC9E,eAAe,EAAE,OAAO,CAAC;CAC1B;AAMD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,aAAa,GAAG,SAAS,GAAG,qBAAqB,CAMhG;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,mBAAmB,GAAG,SAAS,EACxC,KAAK,EAAE,cAAc,EAAE,GAAG,SAAS,EACnC,gBAAgB,CAAC,EAAE,MAAM,EACzB,iBAAiB,wBAA2C,EAC5D,cAAc,CAAC,EAAE,OAAO,GACvB,UAAU,CAsCZ"}
|
|
@@ -1,46 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-call `ChatConfig` assembly for the provider bridge.
|
|
3
3
|
*
|
|
4
|
-
* Base sampling + output budget come from
|
|
5
|
-
* `
|
|
6
|
-
* presets/preset types, nothing else) extended by the agent-local
|
|
7
|
-
* {@link AGENT_LAUNCH_PRESETS}, then pi's per-call `SimpleStreamOptions`
|
|
8
|
-
* overlay on top.
|
|
4
|
+
* Base sampling + output budget come from the family-data launch preset
|
|
5
|
+
* (`@mlx-node/lm`), then pi's per-call `SimpleStreamOptions` overlay on top.
|
|
9
6
|
*/
|
|
10
|
-
import {
|
|
7
|
+
import { launchPresetFor, MODEL_FAMILY_DATA, } from '@mlx-node/lm';
|
|
11
8
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `lfm2_moe` (LFM2.5-8B-A1B): LiquidAI's HF model card for the MoE
|
|
16
|
-
* checkpoint recommends temperature 0.2 / top_k 80 — deliberately NOT
|
|
17
|
-
* the dense `lfm2` preset (LFM2.5-1.2B guidance: temperature 0.05 /
|
|
18
|
-
* top_k 50). repetitionPenalty 1.05 and the 8192-token output budget
|
|
19
|
-
* match the dense family entry.
|
|
9
|
+
* Model types the no-preset error names: trainable rows, then loadable rows,
|
|
10
|
+
* each in registry order. Pinned byte-exactly by
|
|
11
|
+
* `packages/agent/__test__/chat-config.test.ts`.
|
|
20
12
|
*/
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
repetitionPenalty: 1.05,
|
|
30
|
-
},
|
|
31
|
-
maxOutputTokens: 8192,
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* Preset lookup — agent-local entries win over `LAUNCH_PRESETS` (they
|
|
36
|
-
* exist precisely because the server table has no correct entry for the
|
|
37
|
-
* type). This is the ONE preset resolution shared by discovery
|
|
38
|
-
* (`models.ts`) and per-call config assembly, so a model can never be
|
|
39
|
-
* discovered without also being streamable (and vice versa).
|
|
40
|
-
*/
|
|
41
|
-
export function launchPresetFor(modelType) {
|
|
42
|
-
return AGENT_LAUNCH_PRESETS[modelType] ?? LAUNCH_PRESETS[modelType];
|
|
43
|
-
}
|
|
13
|
+
const KNOWN_PRESET_MODEL_TYPES = (() => {
|
|
14
|
+
const rows = MODEL_FAMILY_DATA;
|
|
15
|
+
const chatRows = rows.filter((row) => row.kind === 'trainable' || row.kind === 'loadable');
|
|
16
|
+
return [
|
|
17
|
+
...chatRows.filter((row) => row.kind === 'trainable'),
|
|
18
|
+
...chatRows.filter((row) => row.kind === 'loadable'),
|
|
19
|
+
].map((row) => row.id);
|
|
20
|
+
})();
|
|
44
21
|
/**
|
|
45
22
|
* pi thinking level → native `reasoningEffort`. pi never delivers 'off'
|
|
46
23
|
* here (the agent loop converts it to `undefined` before the provider
|
|
@@ -73,7 +50,7 @@ export function resolveReasoningMode(reasoning) {
|
|
|
73
50
|
export function buildChatConfig(modelType, options, tools, rootCacheOwnerId, resolvedReasoning = resolveReasoningMode(options?.reasoning), modelMaxTokens) {
|
|
74
51
|
const preset = launchPresetFor(modelType);
|
|
75
52
|
if (!preset) {
|
|
76
|
-
const known =
|
|
53
|
+
const known = KNOWN_PRESET_MODEL_TYPES.join(', ');
|
|
77
54
|
throw new Error(`buildChatConfig: no launch preset for model type "${modelType}" (known types: ${known})`);
|
|
78
55
|
}
|
|
79
56
|
const config = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-host.d.ts","sourceRoot":"","sources":["../../src/provider/model-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAA4B,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD;;;;;;;;GAQG;AACH,OAAO,EAAE,0BAA0B,EAAE,CAAC;AAEtC,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;OAUG;IACH,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,WAAW,CAAC,EAAE,OAAO,SAAS,CAAC;IAC/B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/F;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAmBD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA4E;IAC/G,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IAC5C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IAC5C,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,KAAK,CAAuC;IAEpD,YAAY,MAAM,EAAE,mBAAmB,EAAE,EAAE,IAAI,GAAE,mBAAwB,EAMxE;IAED,IAAI,UAAU,IAAI,MAAM,GAAG,IAAI,CAE9B;IAED;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAE1D;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"model-host.d.ts","sourceRoot":"","sources":["../../src/provider/model-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAA4B,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD;;;;;;;;GAQG;AACH,OAAO,EAAE,0BAA0B,EAAE,CAAC;AAEtC,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;OAUG;IACH,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,WAAW,CAAC,EAAE,OAAO,SAAS,CAAC;IAC/B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/F;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAmBD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA4E;IAC/G,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IAC5C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IAC5C,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,KAAK,CAAuC;IAEpD,YAAY,MAAM,EAAE,mBAAmB,EAAE,EAAE,IAAI,GAAE,mBAAwB,EAMxE;IAED,IAAI,UAAU,IAAI,MAAM,GAAG,IAAI,CAE9B;IAED;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAE1D;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAuD3G;IAED;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAIvC;IAED;;;;;OAKG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAO7C;IAED;;;;OAIG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAIxC;IAED;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAQtB"}
|
|
@@ -99,7 +99,13 @@ export class MlxModelHost {
|
|
|
99
99
|
const resolvedPath = COLD_TIER_RESTORE_FAMILIES.has(entry.modelType)
|
|
100
100
|
? await this.resolveModelPathFn(entry, { persistPagedCache: this.persistPagedCache })
|
|
101
101
|
: await this.resolveModelPathFn(entry);
|
|
102
|
-
|
|
102
|
+
// Preserve the ordinary one-argument call for unpaired checkpoints.
|
|
103
|
+
// A discovered DFlash2 companion is an explicit load option rather
|
|
104
|
+
// than a second advertised model: target and draft become one
|
|
105
|
+
// resident session and the native loader validates their compatibility.
|
|
106
|
+
const model = entry.draftModelPath === undefined
|
|
107
|
+
? await this.loadModelFn(resolvedPath)
|
|
108
|
+
: await this.loadModelFn(resolvedPath, { draftModelPath: entry.draftModelPath });
|
|
103
109
|
const sessionModel = model;
|
|
104
110
|
const gemmaDraftActive = entry.modelType === 'gemma4' && sessionModel.hasMtpWeights?.() === true;
|
|
105
111
|
if (this.requirePagedCache && sessionModel.hasBlockPagedCache?.() !== true && !gemmaDraftActive) {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Local model discovery for the mlx pi provider.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* (`packages/server/src/host/discover.ts
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The same discovery walk as `@mlx-node/server/host`
|
|
5
|
+
* (`packages/server/src/host/discover.ts`), pairing every discovered checkpoint
|
|
6
|
+
* with a pi `ProviderModelConfig` entry ready for
|
|
7
|
+
* `pi.registerProvider('mlx', { models })`.
|
|
8
8
|
*
|
|
9
9
|
* `contextWindow` starts as the checkpoint's trained window, read from the model dir's
|
|
10
10
|
* `config.json` `max_position_embeddings` (root first, then the
|
|
11
11
|
* `text_config` nesting used by qwen3_5 / qwen3_5_moe / gemma4 unified
|
|
12
|
-
* checkpoints). Once a Qwen model loads, the provider narrows
|
|
13
|
-
* model metadata to the physical paged-cache window so pi's later
|
|
14
|
-
* auto-compaction thresholds match reality. When both config fields are
|
|
15
|
-
*
|
|
12
|
+
* checkpoints). Once a Qwen or Muse-Glimmer model loads, the provider narrows
|
|
13
|
+
* this shared model metadata to the physical paged-cache window so pi's later
|
|
14
|
+
* auto-compaction thresholds match reality. When both config fields are absent
|
|
15
|
+
* the per-family fallback documented on `FamilyTraits` (`@mlx-node/lm`
|
|
16
|
+
* family-data) applies.
|
|
16
17
|
*/
|
|
17
18
|
import type { ProviderModelConfig } from '@earendil-works/pi-coding-agent';
|
|
18
19
|
import type { DiscoveredModelLike } from '../types.js';
|
|
@@ -22,13 +23,16 @@ export interface MlxModelInfo {
|
|
|
22
23
|
piModel: ProviderModelConfig;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
|
-
* Scan `modelsDir` for chat-capable model subdirectories and
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
26
|
+
* Scan `modelsDir` for chat-capable model subdirectories and native dense
|
|
27
|
+
* Qwen3.5/Qwen3.8 `Q<number>_K_XL.gguf` files, then build their pi provider
|
|
28
|
+
* entries. XL files may live directly under `modelsDir` or one level inside a
|
|
29
|
+
* downloaded GGUF repository. Each is registered by filename stem so multiple
|
|
30
|
+
* quant variants in one repository remain independently selectable.
|
|
31
|
+
*
|
|
32
|
+
* Same tolerance as the cli discover walk: an unreadable dir yields `[]`;
|
|
33
|
+
* entries with an undetectable config, a non-generative type, or no launch
|
|
34
|
+
* preset are skipped silently (warnings only when `MLX_DEBUG` is set). Cheap
|
|
35
|
+
* by contract — no weights are loaded here. Results are sorted by model name.
|
|
32
36
|
*/
|
|
33
37
|
export declare function discoverMlxModels(modelsDir: string): Promise<MlxModelInfo[]>;
|
|
34
38
|
//# sourceMappingURL=models.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/provider/models.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/provider/models.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAS3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,mBAAmB,CAAC;IAChC,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAyHD;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAsIlF"}
|
package/dist/provider/models.js
CHANGED
|
@@ -1,49 +1,70 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Local model discovery for the mlx pi provider.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* (`packages/server/src/host/discover.ts
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The same discovery walk as `@mlx-node/server/host`
|
|
5
|
+
* (`packages/server/src/host/discover.ts`), pairing every discovered checkpoint
|
|
6
|
+
* with a pi `ProviderModelConfig` entry ready for
|
|
7
|
+
* `pi.registerProvider('mlx', { models })`.
|
|
8
8
|
*
|
|
9
9
|
* `contextWindow` starts as the checkpoint's trained window, read from the model dir's
|
|
10
10
|
* `config.json` `max_position_embeddings` (root first, then the
|
|
11
11
|
* `text_config` nesting used by qwen3_5 / qwen3_5_moe / gemma4 unified
|
|
12
|
-
* checkpoints). Once a Qwen model loads, the provider narrows
|
|
13
|
-
* model metadata to the physical paged-cache window so pi's later
|
|
14
|
-
* auto-compaction thresholds match reality. When both config fields are
|
|
15
|
-
*
|
|
12
|
+
* checkpoints). Once a Qwen or Muse-Glimmer model loads, the provider narrows
|
|
13
|
+
* this shared model metadata to the physical paged-cache window so pi's later
|
|
14
|
+
* auto-compaction thresholds match reality. When both config fields are absent
|
|
15
|
+
* the per-family fallback documented on `FamilyTraits` (`@mlx-node/lm`
|
|
16
|
+
* family-data) applies.
|
|
16
17
|
*/
|
|
17
18
|
import { readdir, readFile } from 'node:fs/promises';
|
|
18
19
|
import { basename, join } from 'node:path';
|
|
19
|
-
import { detectModelType } from '@mlx-node/lm';
|
|
20
|
-
import { launchPresetFor } from './chat-config.js';
|
|
21
|
-
// Non-generative detection results that cannot back a chat endpoint
|
|
22
|
-
// (mirrors the cli discover walk).
|
|
23
|
-
const NON_GENERATIVE = new Set(['harrier', 'qianfan-ocr', 'internvl_chat']);
|
|
20
|
+
import { launchPresetFor, detectModelType, familyTraitsFor, NON_GENERATIVE_FAMILY_IDS, } from '@mlx-node/lm';
|
|
24
21
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* skipped, never guessed.
|
|
22
|
+
* Native direct-GGUF loading currently exists for dense Qwen3.5/Qwen3.8.
|
|
23
|
+
* Match the Unsloth Dynamic XL target names users download, while excluding
|
|
24
|
+
* ordinary Q4_K_M files and companion artifacts such as imatrix/mmproj/draft.
|
|
29
25
|
*/
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
const QWEN35_XL_GGUF = /(?:^|[-_.])Q\d+_K_XL\.gguf$/i;
|
|
27
|
+
const GGUF_COMPANION_NAME = /(?:^|[-_.])(?:imatrix|mmproj|dflash|draft)(?:[-_.]|$)/i;
|
|
28
|
+
function isQwen35XlGguf(name) {
|
|
29
|
+
return QWEN35_XL_GGUF.test(name) && !GGUF_COMPANION_NAME.test(name);
|
|
30
|
+
}
|
|
31
|
+
function ggufModelName(name) {
|
|
32
|
+
return name.slice(0, -'.gguf'.length);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Agent-local convention for pairing a dense Qwen3.5/Qwen3.8 target with an
|
|
36
|
+
* external DFlash2 checkpoint. mlx-vlm accepts an explicit `--draft-model`
|
|
37
|
+
* path and does not define a combined directory layout; the agent needs a
|
|
38
|
+
* deterministic relationship it can discover without another CLI flag.
|
|
39
|
+
*/
|
|
40
|
+
async function embeddedDFlash2Path(modelDir) {
|
|
41
|
+
const draftPath = join(modelDir, 'draft');
|
|
42
|
+
try {
|
|
43
|
+
const raw = await readFile(join(draftPath, 'config.json'), 'utf-8');
|
|
44
|
+
const config = JSON.parse(raw);
|
|
45
|
+
return Array.isArray(config.architectures) && config.architectures.includes('DFlash2DraftModel')
|
|
46
|
+
? draftPath
|
|
47
|
+
: undefined;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function modelFileInventory(modelDir) {
|
|
54
|
+
try {
|
|
55
|
+
const files = (await readdir(modelDir, { withFileTypes: true }))
|
|
56
|
+
.filter((entry) => entry.isFile())
|
|
57
|
+
.map((entry) => entry.name);
|
|
58
|
+
return {
|
|
59
|
+
xlGgufs: files.filter(isQwen35XlGguf).sort(),
|
|
60
|
+
hasGguf: files.some((name) => name.toLowerCase().endsWith('.gguf')),
|
|
61
|
+
hasSafetensors: files.some((name) => name.toLowerCase().endsWith('.safetensors')),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return { xlGgufs: [], hasGguf: false, hasSafetensors: false };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
47
68
|
function positiveInteger(value) {
|
|
48
69
|
return typeof value === 'number' && Number.isFinite(value) && value > 0 ? Math.floor(value) : undefined;
|
|
49
70
|
}
|
|
@@ -82,23 +103,28 @@ async function readDiscoveryMetadata(modelPath, modelType, fallbackContextWindow
|
|
|
82
103
|
const supportsImages = modelType === 'gemma4'
|
|
83
104
|
? hasVisionConfig || nonEmptyRecord(config.unified_vision_config)
|
|
84
105
|
: (modelType === 'qwen3_5' || modelType === 'qwen3_5_moe') && hasVisionConfig;
|
|
106
|
+
const draftOnly = Array.isArray(config.architectures) && config.architectures.includes('DFlash2DraftModel');
|
|
85
107
|
return {
|
|
86
108
|
contextWindow: root ?? nested ?? fallbackContextWindow,
|
|
87
109
|
supportsImages,
|
|
110
|
+
draftOnly,
|
|
88
111
|
};
|
|
89
112
|
}
|
|
90
113
|
catch {
|
|
91
|
-
return { contextWindow: fallbackContextWindow, supportsImages: false };
|
|
114
|
+
return { contextWindow: fallbackContextWindow, supportsImages: false, draftOnly: false };
|
|
92
115
|
}
|
|
93
116
|
}
|
|
94
117
|
/**
|
|
95
|
-
* Scan `modelsDir` for chat-capable model subdirectories and
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
118
|
+
* Scan `modelsDir` for chat-capable model subdirectories and native dense
|
|
119
|
+
* Qwen3.5/Qwen3.8 `Q<number>_K_XL.gguf` files, then build their pi provider
|
|
120
|
+
* entries. XL files may live directly under `modelsDir` or one level inside a
|
|
121
|
+
* downloaded GGUF repository. Each is registered by filename stem so multiple
|
|
122
|
+
* quant variants in one repository remain independently selectable.
|
|
123
|
+
*
|
|
124
|
+
* Same tolerance as the cli discover walk: an unreadable dir yields `[]`;
|
|
125
|
+
* entries with an undetectable config, a non-generative type, or no launch
|
|
126
|
+
* preset are skipped silently (warnings only when `MLX_DEBUG` is set). Cheap
|
|
127
|
+
* by contract — no weights are loaded here. Results are sorted by model name.
|
|
102
128
|
*/
|
|
103
129
|
export async function discoverMlxModels(modelsDir) {
|
|
104
130
|
const debug = Boolean(process.env.MLX_DEBUG);
|
|
@@ -109,8 +135,84 @@ export async function discoverMlxModels(modelsDir) {
|
|
|
109
135
|
catch {
|
|
110
136
|
return [];
|
|
111
137
|
}
|
|
138
|
+
// Collision resolution below gives the first occurrence the bare filename
|
|
139
|
+
// stem. Directory enumeration order is unspecified, so sort before assigning
|
|
140
|
+
// IDs to keep persisted `mlx/<id>` selections stable across filesystems.
|
|
141
|
+
entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
112
142
|
const out = [];
|
|
143
|
+
const usedNames = new Set();
|
|
144
|
+
const append = async (preferredName, path, metadataRoot, modelType, scopeName, draftModelPath) => {
|
|
145
|
+
if (NON_GENERATIVE_FAMILY_IDS.has(modelType))
|
|
146
|
+
return;
|
|
147
|
+
// Fail-closed guards: dead-by-construction for chat families (the
|
|
148
|
+
// family-data row type requires traits + a preset), live for any foreign
|
|
149
|
+
// string that slips through detection.
|
|
150
|
+
const preset = launchPresetFor(modelType);
|
|
151
|
+
if (!preset) {
|
|
152
|
+
if (debug)
|
|
153
|
+
console.warn(`[mlx] skip ${path}: no launch preset for ${modelType}`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const traits = familyTraitsFor(modelType);
|
|
157
|
+
if (!traits) {
|
|
158
|
+
if (debug)
|
|
159
|
+
console.warn(`[mlx] skip ${path}: no FAMILY_TRAITS entry for ${modelType}`);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const metadata = await readDiscoveryMetadata(metadataRoot, modelType, traits.fallbackContextWindow);
|
|
163
|
+
if (metadata.draftOnly) {
|
|
164
|
+
if (debug)
|
|
165
|
+
console.warn(`[mlx] skip ${path}: companion draft checkpoint is not a chat model`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
let name = preferredName;
|
|
169
|
+
if (usedNames.has(name)) {
|
|
170
|
+
name = `${scopeName}-${preferredName}`;
|
|
171
|
+
let suffix = 2;
|
|
172
|
+
while (usedNames.has(name))
|
|
173
|
+
name = `${scopeName}-${preferredName}-${suffix++}`;
|
|
174
|
+
}
|
|
175
|
+
usedNames.add(name);
|
|
176
|
+
const discovered = {
|
|
177
|
+
name,
|
|
178
|
+
path,
|
|
179
|
+
modelType,
|
|
180
|
+
...(draftModelPath === undefined ? {} : { draftModelPath }),
|
|
181
|
+
};
|
|
182
|
+
out.push({
|
|
183
|
+
discovered,
|
|
184
|
+
piModel: {
|
|
185
|
+
id: name,
|
|
186
|
+
name,
|
|
187
|
+
reasoning: traits.reasoning,
|
|
188
|
+
// The structural FamilyThinkingLevelMap must stay assignable to the
|
|
189
|
+
// pi type (pi types are agent-only, so family-data cannot name it).
|
|
190
|
+
thinkingLevelMap: traits.thinkingLevelMap,
|
|
191
|
+
input: metadata.supportsImages ? ['text', 'image'] : ['text'],
|
|
192
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
193
|
+
contextWindow: metadata.contextWindow,
|
|
194
|
+
maxTokens: preset.maxOutputTokens,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
};
|
|
113
198
|
for (const entry of entries) {
|
|
199
|
+
if (entry.isFile() && isQwen35XlGguf(entry.name)) {
|
|
200
|
+
const full = join(modelsDir, entry.name);
|
|
201
|
+
try {
|
|
202
|
+
const modelType = await detectModelType(full);
|
|
203
|
+
if (modelType === 'qwen3_5') {
|
|
204
|
+
await append(ggufModelName(entry.name), full, modelsDir, modelType, basename(modelsDir));
|
|
205
|
+
}
|
|
206
|
+
else if (debug) {
|
|
207
|
+
console.warn(`[mlx] skip ${full}: direct XL GGUF loading is not supported for ${modelType}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
if (debug)
|
|
212
|
+
console.warn(`[mlx] skip ${full}: ${err.message}`);
|
|
213
|
+
}
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
114
216
|
if (!entry.isDirectory())
|
|
115
217
|
continue;
|
|
116
218
|
const full = join(modelsDir, entry.name);
|
|
@@ -123,35 +225,32 @@ export async function discoverMlxModels(modelsDir) {
|
|
|
123
225
|
console.warn(`[mlx] skip ${full}: ${err.message}`);
|
|
124
226
|
continue;
|
|
125
227
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
228
|
+
const inventory = await modelFileInventory(full);
|
|
229
|
+
const { xlGgufs } = inventory;
|
|
230
|
+
if (xlGgufs.length > 0) {
|
|
231
|
+
if (modelType !== 'qwen3_5') {
|
|
232
|
+
if (debug) {
|
|
233
|
+
console.warn(`[mlx] skip ${full}: direct XL GGUF loading is not supported for ${modelType}`);
|
|
234
|
+
}
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const draftModelPath = await embeddedDFlash2Path(full);
|
|
238
|
+
for (const gguf of xlGgufs) {
|
|
239
|
+
await append(ggufModelName(gguf), join(full, gguf), full, modelType, entry.name, draftModelPath);
|
|
240
|
+
}
|
|
132
241
|
continue;
|
|
133
242
|
}
|
|
134
|
-
|
|
135
|
-
|
|
243
|
+
// A raw GGUF repository is not itself a loadable model path. Only the
|
|
244
|
+
// selected native Qwen3.5 XL files above may be handed directly to the
|
|
245
|
+
// loader. Keep converted model directories discoverable when they retain
|
|
246
|
+
// an imatrix/source GGUF beside their actual SafeTensors weights.
|
|
247
|
+
if (inventory.hasGguf && !inventory.hasSafetensors) {
|
|
136
248
|
if (debug)
|
|
137
|
-
console.warn(`[mlx] skip ${full}: no
|
|
249
|
+
console.warn(`[mlx] skip ${full}: no supported direct GGUF target`);
|
|
138
250
|
continue;
|
|
139
251
|
}
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
out.push({
|
|
143
|
-
discovered: { name, path: full, modelType },
|
|
144
|
-
piModel: {
|
|
145
|
-
id: name,
|
|
146
|
-
name,
|
|
147
|
-
reasoning: traits.reasoning,
|
|
148
|
-
thinkingLevelMap: traits.thinkingLevelMap,
|
|
149
|
-
input: supportsImages ? ['text', 'image'] : ['text'],
|
|
150
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
151
|
-
contextWindow,
|
|
152
|
-
maxTokens: preset.maxOutputTokens,
|
|
153
|
-
},
|
|
154
|
-
});
|
|
252
|
+
const draftModelPath = modelType === 'qwen3_5' ? await embeddedDFlash2Path(full) : undefined;
|
|
253
|
+
await append(basename(full), full, full, modelType, entry.name, draftModelPath);
|
|
155
254
|
}
|
|
156
255
|
out.sort((a, b) => (a.discovered.name < b.discovered.name ? -1 : a.discovered.name > b.discovered.name ? 1 : 0));
|
|
157
256
|
return out;
|
package/dist/types.d.ts
CHANGED
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,4FAA4F;AAC5F,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,4FAA4F;AAC5F,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mlx-node/agent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"homepage": "https://github.com/mlx-node/mlx-node",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/mlx-node/mlx-node/issues"
|
|
@@ -31,15 +31,15 @@
|
|
|
31
31
|
"build": "tsc -b"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@earendil-works/pi-ai": "0.
|
|
35
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
36
|
-
"@mlx-node/core": "0.0.
|
|
37
|
-
"@mlx-node/lm": "0.0.
|
|
38
|
-
"@mlx-node/server": "0.0.
|
|
39
|
-
"typebox": "1.3.
|
|
34
|
+
"@earendil-works/pi-ai": "0.84.4",
|
|
35
|
+
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
36
|
+
"@mlx-node/core": "0.0.12",
|
|
37
|
+
"@mlx-node/lm": "0.0.12",
|
|
38
|
+
"@mlx-node/server": "0.0.12",
|
|
39
|
+
"typebox": "1.3.23"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@types/node": "^26.
|
|
42
|
+
"@types/node": "^26.4.0"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=22.19.0"
|