@mlx-node/core 0.0.9 → 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.
Files changed (3) hide show
  1. package/index.cjs +195 -80
  2. package/index.d.cts +1009 -79
  3. package/package.json +5 -4
package/index.d.cts CHANGED
@@ -26,6 +26,34 @@ export declare class BatchGenerationResult {
26
26
  get groupSize(): number;
27
27
  }
28
28
 
29
+ /**
30
+ * In-flight non-streaming chat turn returned by the internal
31
+ * `begin_chat_session_*` operation entry points (H2).
32
+ *
33
+ * The dispatching NAPI method resolves with this object IMMEDIATELY
34
+ * after the command is queued (mirroring how the streaming methods
35
+ * return their [`ChatStreamHandle`] before the turn runs); the turn's
36
+ * reply arrives later through [`Self::result`]. `cancel()` flips the
37
+ * same `Arc<AtomicBool>` the command carries, so it
38
+ * reaches the model thread's chunk-boundary / per-step polls exactly
39
+ * like a streaming cancel.
40
+ *
41
+ * Reply contract: a cancelled turn REJECTS the `result()` promise with
42
+ * the exact string `"chat session cancelled"`
43
+ * ([`crate::engine::session::CHAT_SESSION_CANCELLED`]).
44
+ */
45
+ export declare class ChatSessionCall {
46
+ /** Cooperatively cancel this queued or running turn. */
47
+ cancel(): void;
48
+ /**
49
+ * Await the turn's reply. Resolves with the [`ChatResult`] on a
50
+ * completed turn; rejects with `"chat session cancelled"` when the
51
+ * turn was cancelled, or with the turn's native error otherwise.
52
+ * Single-shot: a second call rejects.
53
+ */
54
+ result(): Promise<ChatResult>;
55
+ }
56
+
29
57
  /**
30
58
  * Handle returned by the streaming chat-session entry points
31
59
  * (`chat_stream_session_start`, `chat_stream_session_continue`,
@@ -125,11 +153,8 @@ export declare class Gemma4Model {
125
153
  * **Prefer [`Gemma4Model::load`]** for any real usage — `new(config)`
126
154
  * is a config-only stub that matches the OCR-model pattern
127
155
  * (`VLModel::new(config)`, `QianfanOCRModel::new(config)`) and is
128
- * intentionally NOT runnable. It was introduced in the cache-limit
129
- * coordinator work so that the coordinator's per-model delta is
130
- * registered exclusively on the `load()` path, eliminating a
131
- * baseline-registration gap where a no-op `new(config)` would have
132
- * leaked an empty guard into the coordinator.
156
+ * intentionally NOT runnable: the cache-limit coordinator's per-model delta is
157
+ * registered exclusively on the `load()` path.
133
158
  *
134
159
  * This path does NOT spawn a model thread, NOT materialize any
135
160
  * weights, and NOT register with the cache-limit coordinator. The
@@ -139,14 +164,12 @@ export declare class Gemma4Model {
139
164
  * with a `napi::Error` whose message is exactly
140
165
  * `"Model not initialized. Call Gemma4Model.load() first."` until
141
166
  * `load()` runs and installs the underlying model thread. The
142
- * synchronous `resetCaches()` call is a silent no-op on the stub
143
- * to keep `ChatSession.reset()` idempotent across both runnable
144
- * and stub instances.
167
+ * async `resetCaches()` call resolves as a silent no-op on the
168
+ * stub to keep `ChatSession.reset()` idempotent across both
169
+ * runnable and stub instances.
145
170
  *
146
- * A runnable model requires `await Gemma4Model.load(path)`. The
147
- * constructor signature is fixed by NAPI-RS; the stub-only behavior is
148
- * covered by the regression tests in
149
- * `__test__/models/model-loader-gemma4.test.ts`.
171
+ * A runnable model requires `await Gemma4Model.load(path)`. The constructor
172
+ * signature is fixed by NAPI-RS.
150
173
  */
151
174
  constructor(config: Gemma4Config);
152
175
  /** Returns true if weights have been loaded via `load()`. */
@@ -157,14 +180,14 @@ export declare class Gemma4Model {
157
180
  *
158
181
  * `true` iff `Gemma4Inner::paged_adapter` was successfully
159
182
  * constructed at load time (driven by
160
- * `Gemma4Config::use_block_paged_cache`). The
161
- * `gemma4_paged_vs_flat_parity` integration test pins greedy
162
- * byte-equal at BF16 against real Gemma-4-E2B-IT weights. Stubs
163
- * constructed via `new(config)` always return `false`. Surfaced
183
+ * `Gemma4Config::use_block_paged_cache`). Stubs constructed via
184
+ * `new(config)` always return `false`. Surfaced
164
185
  * through this NAPI method so server endpoints can branch on it
165
186
  * without a model-thread roundtrip.
166
187
  */
167
188
  hasBlockPagedCache(): boolean;
189
+ maxConcurrentSequences(): number;
190
+ schedulerStats(): Promise<SchedulerStats>;
168
191
  /**
169
192
  * Whether this loaded instance can execute image-bearing chat turns.
170
193
  * Config-only stubs and incomplete/non-paged physical paths return false.
@@ -187,11 +210,16 @@ export declare class Gemma4Model {
187
210
  /** Load a Gemma4 model from a directory. */
188
211
  static load(modelPath: string, options?: Gemma4LoadOptions | undefined | null): Promise<Gemma4Model>;
189
212
  /**
190
- * Reset all caches and clear cached token history. Exposed
191
- * so tests and session-management code can start from a
192
- * known clean state between turns.
213
+ * Reset all caches and clear cached token history. Async so a reset
214
+ * queued behind an in-flight turn parks a tokio future, never the
215
+ * Node event loop (H1: a dead prefill used to freeze all HTTP traffic).
193
216
  */
194
- resetCaches(): void;
217
+ resetCaches(): Promise<void>;
218
+ /**
219
+ * Release scheduler-owned KV/history state for one logical
220
+ * session owner without purging content-addressed prefix blocks.
221
+ */
222
+ releaseCacheOwner(ownerId: string): Promise<void>;
195
223
  /**
196
224
  * Start a new chat session.
197
225
  *
@@ -200,6 +228,16 @@ export declare class Gemma4Model {
200
228
  * preserves the resulting KV state for exact-prefix reuse.
201
229
  */
202
230
  chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
231
+ /**
232
+ * Internal operation bridge for `chatSessionStart` (H2). Resolves
233
+ * IMMEDIATELY with a `ChatSessionCall` whose `cancel()`
234
+ * can cancel the queued/running turn; the reply arrives via
235
+ * `call.result()`. A cancelled turn rejects `result()` with
236
+ * the exact string `"chat session cancelled"`. The LM wrapper
237
+ * keeps this two-phase operation private and exposes cancellation
238
+ * through the ordinary method's `AbortSignal` argument.
239
+ */
240
+ beginChatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatSessionCall>;
203
241
  /**
204
242
  * Continue an existing chat session from the complete
205
243
  * structured conversation. The loaded model template is the
@@ -208,11 +246,27 @@ export declare class Gemma4Model {
208
246
  * against the saved token history.
209
247
  */
210
248
  chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
249
+ /**
250
+ * Internal operation bridge for `chatSessionContinue` (H2). Same
251
+ * contract as `beginChatSessionStart`.
252
+ */
253
+ beginChatSessionContinue(
254
+ messages: Array<ChatMessage>,
255
+ config?: ChatConfig | undefined | null,
256
+ ): Promise<ChatSessionCall>;
211
257
  /**
212
258
  * Continue an existing chat session from a complete
213
259
  * structured conversation ending in a tool-role message.
214
260
  */
215
261
  chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
262
+ /**
263
+ * Internal operation bridge for `chatSessionContinueTool` (H2). Same
264
+ * contract as `beginChatSessionStart`.
265
+ */
266
+ beginChatSessionContinueTool(
267
+ messages: Array<ChatMessage>,
268
+ config?: ChatConfig | undefined | null,
269
+ ): Promise<ChatSessionCall>;
216
270
  /** Streaming variant of `chatSessionStart`. */
217
271
  chatStreamSessionStart(
218
272
  messages: ChatMessage[],
@@ -505,14 +559,23 @@ export declare class Lfm2Model {
505
559
  hasBlockPagedCache(): boolean;
506
560
  /** Get the model configuration. */
507
561
  getConfig(): Lfm2Config;
562
+ /** Native admission capacity for the server's per-model semaphore. */
563
+ maxConcurrentSequences(): number;
564
+ /** Snapshot scheduler occupancy and paged-pool admission telemetry. */
565
+ schedulerStats(): Promise<SchedulerStats>;
508
566
  /** Estimated number of model parameters. */
509
567
  numParameters(): number;
510
568
  /**
511
- * Reset all caches and clear cached token history. Exposed
512
- * so tests and session-management code can start from a
513
- * known clean state between turns.
569
+ * Reset all caches and clear cached token history. Async so a reset
570
+ * queued behind an in-flight turn parks a tokio future, never the
571
+ * Node event loop (H1: a dead prefill used to freeze all HTTP traffic).
572
+ */
573
+ resetCaches(): Promise<void>;
574
+ /**
575
+ * Release scheduler-owned KV/history state for one logical
576
+ * session owner without purging content-addressed prefix blocks.
514
577
  */
515
- resetCaches(): void;
578
+ releaseCacheOwner(ownerId: string): Promise<void>;
516
579
  /**
517
580
  * Start a new chat session.
518
581
  *
@@ -521,6 +584,16 @@ export declare class Lfm2Model {
521
584
  * preserves the resulting KV state for exact-prefix reuse.
522
585
  */
523
586
  chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
587
+ /**
588
+ * Internal operation bridge for `chatSessionStart` (H2). Resolves
589
+ * IMMEDIATELY with a `ChatSessionCall` whose `cancel()`
590
+ * can cancel the queued/running turn; the reply arrives via
591
+ * `call.result()`. A cancelled turn rejects `result()` with
592
+ * the exact string `"chat session cancelled"`. The LM wrapper
593
+ * keeps this two-phase operation private and exposes cancellation
594
+ * through the ordinary method's `AbortSignal` argument.
595
+ */
596
+ beginChatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatSessionCall>;
524
597
  /**
525
598
  * Continue an existing chat session from the complete
526
599
  * structured conversation. The loaded model template is the
@@ -529,11 +602,117 @@ export declare class Lfm2Model {
529
602
  * against the saved token history.
530
603
  */
531
604
  chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
605
+ /**
606
+ * Internal operation bridge for `chatSessionContinue` (H2). Same
607
+ * contract as `beginChatSessionStart`.
608
+ */
609
+ beginChatSessionContinue(
610
+ messages: Array<ChatMessage>,
611
+ config?: ChatConfig | undefined | null,
612
+ ): Promise<ChatSessionCall>;
532
613
  /**
533
614
  * Continue an existing chat session from a complete
534
615
  * structured conversation ending in a tool-role message.
535
616
  */
536
617
  chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
618
+ /**
619
+ * Internal operation bridge for `chatSessionContinueTool` (H2). Same
620
+ * contract as `beginChatSessionStart`.
621
+ */
622
+ beginChatSessionContinueTool(
623
+ messages: Array<ChatMessage>,
624
+ config?: ChatConfig | undefined | null,
625
+ ): Promise<ChatSessionCall>;
626
+ /** Streaming variant of `chatSessionStart`. */
627
+ chatStreamSessionStart(
628
+ messages: ChatMessage[],
629
+ config: ChatConfig | null,
630
+ callback: (err: Error | null, chunk: ChatStreamChunk) => void,
631
+ ): Promise<ChatStreamHandle>;
632
+ /** Streaming variant of `chatSessionContinue`. */
633
+ chatStreamSessionContinue(
634
+ messages: ChatMessage[],
635
+ config: ChatConfig | null,
636
+ callback: (err: Error | null, chunk: ChatStreamChunk) => void,
637
+ ): Promise<ChatStreamHandle>;
638
+ /** Streaming variant of `chatSessionContinueTool`. */
639
+ chatStreamSessionContinueTool(
640
+ messages: ChatMessage[],
641
+ config: ChatConfig | null,
642
+ callback: (err: Error | null, chunk: ChatStreamChunk) => void,
643
+ ): Promise<ChatStreamHandle>;
644
+ }
645
+
646
+ export declare class MuseGlimmerModel {
647
+ static load(modelPath: string): Promise<MuseGlimmerModel>;
648
+ hasMtpWeights(): boolean;
649
+ autoEnablesMtp(): boolean;
650
+ hasBlockPagedCache(): boolean;
651
+ maxConcurrentSequences(): number;
652
+ /**
653
+ * Model-wide context snapshot used by higher layers for compaction.
654
+ * `effective_window_tokens` is min(trained, live pool).
655
+ */
656
+ contextLimits(): MuseGlimmerContextLimits;
657
+ schedulerStats(): Promise<SchedulerStats>;
658
+ /**
659
+ * Reset all caches and clear cached token history. Async so a reset
660
+ * queued behind an in-flight turn parks a tokio future, never the
661
+ * Node event loop (H1: a dead prefill used to freeze all HTTP traffic).
662
+ */
663
+ resetCaches(): Promise<void>;
664
+ /**
665
+ * Release scheduler-owned KV/history state for one logical
666
+ * session owner without purging content-addressed prefix blocks.
667
+ */
668
+ releaseCacheOwner(ownerId: string): Promise<void>;
669
+ /**
670
+ * Start a new chat session.
671
+ *
672
+ * Renders the complete conversation through the loaded chat
673
+ * template, decodes until the family's session stop token, and
674
+ * preserves the resulting KV state for exact-prefix reuse.
675
+ */
676
+ chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
677
+ /**
678
+ * Internal operation bridge for `chatSessionStart` (H2). Resolves
679
+ * IMMEDIATELY with a `ChatSessionCall` whose `cancel()`
680
+ * can cancel the queued/running turn; the reply arrives via
681
+ * `call.result()`. A cancelled turn rejects `result()` with
682
+ * the exact string `"chat session cancelled"`. The LM wrapper
683
+ * keeps this two-phase operation private and exposes cancellation
684
+ * through the ordinary method's `AbortSignal` argument.
685
+ */
686
+ beginChatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatSessionCall>;
687
+ /**
688
+ * Continue an existing chat session from the complete
689
+ * structured conversation. The loaded model template is the
690
+ * sole authority for the rendered suffix; native cache reuse
691
+ * occurs only after the completed structured history is verified
692
+ * against the saved token history.
693
+ */
694
+ chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
695
+ /**
696
+ * Internal operation bridge for `chatSessionContinue` (H2). Same
697
+ * contract as `beginChatSessionStart`.
698
+ */
699
+ beginChatSessionContinue(
700
+ messages: Array<ChatMessage>,
701
+ config?: ChatConfig | undefined | null,
702
+ ): Promise<ChatSessionCall>;
703
+ /**
704
+ * Continue an existing chat session from a complete
705
+ * structured conversation ending in a tool-role message.
706
+ */
707
+ chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
708
+ /**
709
+ * Internal operation bridge for `chatSessionContinueTool` (H2). Same
710
+ * contract as `beginChatSessionStart`.
711
+ */
712
+ beginChatSessionContinueTool(
713
+ messages: Array<ChatMessage>,
714
+ config?: ChatConfig | undefined | null,
715
+ ): Promise<ChatSessionCall>;
537
716
  /** Streaming variant of `chatSessionStart`. */
538
717
  chatStreamSessionStart(
539
718
  messages: ChatMessage[],
@@ -821,6 +1000,131 @@ export declare class NativeRewardRegistry {
821
1000
  setNormalize(normalize: boolean): void;
822
1001
  }
823
1002
 
1003
+ /**
1004
+ * NVIDIA Nemotron 3.5 Lightning language model: hybrid Mamba-2 SSM + GQA + MoE-FFN
1005
+ * with an optional in-checkpoint MTP head. All model state lives on a dedicated OS
1006
+ * thread; NAPI methods dispatch commands via channels.
1007
+ */
1008
+ export declare class NemotronHModel {
1009
+ /**
1010
+ * Load a NemotronH model from a directory containing safetensors and
1011
+ * config.json.
1012
+ */
1013
+ static load(modelPath: string): Promise<NemotronHModel>;
1014
+ /**
1015
+ * Whether this checkpoint shipped a complete MTP head (speculative
1016
+ * decoding is available when enableMtp is set on the request).
1017
+ */
1018
+ hasMtpWeights(): boolean;
1019
+ /**
1020
+ * Whether `ChatSession` should turn MTP ON when the caller sets nothing. FALSE
1021
+ * deliberately, about SCHEDULING not speed: this family's flat MTP core has no
1022
+ * streaming arm, so `enable_mtp == Some(true)` costs a SYNC turn its scheduled
1023
+ * slot — `chat_requires_barrier` routes it to the EXCLUSIVE lane and out of
1024
+ * continuous batching. A streaming turn plans plain autoregressive and keeps its
1025
+ * slot. `MLX_NEMOTRON_MTP_DEFAULT=1` flips the default.
1026
+ */
1027
+ mtpAutoEnabled(): boolean;
1028
+ /**
1029
+ * Whether the block-paged KV cache adapter is active on this model
1030
+ * instance (default-on unless `use_block_paged_cache: false`).
1031
+ */
1032
+ hasBlockPagedCache(): boolean;
1033
+ /**
1034
+ * Physical/trained context limits captured at load, so the ChatSession preflight
1035
+ * rejects long conversations instead of failing inside paged-cache allocation.
1036
+ */
1037
+ contextLimits(): NemotronHContextLimits;
1038
+ /** Get the model configuration. */
1039
+ getConfig(): NemotronHConfig;
1040
+ /**
1041
+ * Native admission capacity for the server's per-model semaphore.
1042
+ * Paged models advertise the scheduler lane (up to 8 default); flat
1043
+ * models and forced-serial processes report 1.
1044
+ */
1045
+ maxConcurrentSequences(): number;
1046
+ /** Snapshot scheduler occupancy and paged-pool admission telemetry. */
1047
+ schedulerStats(): Promise<SchedulerStats>;
1048
+ /** Estimated number of model parameters. */
1049
+ numParameters(): number;
1050
+ /**
1051
+ * Reset all caches and clear cached token history. Async so a reset
1052
+ * queued behind an in-flight turn parks a tokio future, never the
1053
+ * Node event loop (H1: a dead prefill used to freeze all HTTP traffic).
1054
+ */
1055
+ resetCaches(): Promise<void>;
1056
+ /**
1057
+ * Release scheduler-owned KV/history state for one logical
1058
+ * session owner without purging content-addressed prefix blocks.
1059
+ */
1060
+ releaseCacheOwner(ownerId: string): Promise<void>;
1061
+ /**
1062
+ * Start a new chat session.
1063
+ *
1064
+ * Renders the complete conversation through the loaded chat
1065
+ * template, decodes until the family's session stop token, and
1066
+ * preserves the resulting KV state for exact-prefix reuse.
1067
+ */
1068
+ chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1069
+ /**
1070
+ * Internal operation bridge for `chatSessionStart` (H2). Resolves
1071
+ * IMMEDIATELY with a `ChatSessionCall` whose `cancel()`
1072
+ * can cancel the queued/running turn; the reply arrives via
1073
+ * `call.result()`. A cancelled turn rejects `result()` with
1074
+ * the exact string `"chat session cancelled"`. The LM wrapper
1075
+ * keeps this two-phase operation private and exposes cancellation
1076
+ * through the ordinary method's `AbortSignal` argument.
1077
+ */
1078
+ beginChatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatSessionCall>;
1079
+ /**
1080
+ * Continue an existing chat session from the complete
1081
+ * structured conversation. The loaded model template is the
1082
+ * sole authority for the rendered suffix; native cache reuse
1083
+ * occurs only after the completed structured history is verified
1084
+ * against the saved token history.
1085
+ */
1086
+ chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1087
+ /**
1088
+ * Internal operation bridge for `chatSessionContinue` (H2). Same
1089
+ * contract as `beginChatSessionStart`.
1090
+ */
1091
+ beginChatSessionContinue(
1092
+ messages: Array<ChatMessage>,
1093
+ config?: ChatConfig | undefined | null,
1094
+ ): Promise<ChatSessionCall>;
1095
+ /**
1096
+ * Continue an existing chat session from a complete
1097
+ * structured conversation ending in a tool-role message.
1098
+ */
1099
+ chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1100
+ /**
1101
+ * Internal operation bridge for `chatSessionContinueTool` (H2). Same
1102
+ * contract as `beginChatSessionStart`.
1103
+ */
1104
+ beginChatSessionContinueTool(
1105
+ messages: Array<ChatMessage>,
1106
+ config?: ChatConfig | undefined | null,
1107
+ ): Promise<ChatSessionCall>;
1108
+ /** Streaming variant of `chatSessionStart`. */
1109
+ chatStreamSessionStart(
1110
+ messages: ChatMessage[],
1111
+ config: ChatConfig | null,
1112
+ callback: (err: Error | null, chunk: ChatStreamChunk) => void,
1113
+ ): Promise<ChatStreamHandle>;
1114
+ /** Streaming variant of `chatSessionContinue`. */
1115
+ chatStreamSessionContinue(
1116
+ messages: ChatMessage[],
1117
+ config: ChatConfig | null,
1118
+ callback: (err: Error | null, chunk: ChatStreamChunk) => void,
1119
+ ): Promise<ChatStreamHandle>;
1120
+ /** Streaming variant of `chatSessionContinueTool`. */
1121
+ chatStreamSessionContinueTool(
1122
+ messages: ChatMessage[],
1123
+ config: ChatConfig | null,
1124
+ callback: (err: Error | null, chunk: ChatStreamChunk) => void,
1125
+ ): Promise<ChatStreamHandle>;
1126
+ }
1127
+
824
1128
  /**
825
1129
  * OutputStore - Persistence layer for training outputs
826
1130
  *
@@ -1029,8 +1333,13 @@ export declare class QianfanOCRModel {
1029
1333
  maxNewTokens?: number | undefined | null,
1030
1334
  temperature?: number | undefined | null,
1031
1335
  ): Promise<Array<number>>;
1032
- /** Reset KV caches and token history. */
1033
- resetCaches(): void;
1336
+ /**
1337
+ * Reset KV caches and token history. Async so a reset queued behind
1338
+ * an in-flight turn parks a tokio future, never the Node event loop
1339
+ * (H1a — same contract as the `chat_napi_surface!` families). Callers
1340
+ * requiring reset-before-next-turn ordering must await this Promise.
1341
+ */
1342
+ resetCaches(): Promise<void>;
1034
1343
  /**
1035
1344
  * Start a new chat session.
1036
1345
  *
@@ -1043,17 +1352,33 @@ export declare class QianfanOCRModel {
1043
1352
  * fast-fail used by plain language models.
1044
1353
  */
1045
1354
  chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1355
+ /**
1356
+ * Internal operation for `chatSessionStart`. The returned call exposes an
1357
+ * idempotent `cancel()` immediately; `result()` resolves or rejects with the
1358
+ * exact `chat session cancelled` sentinel.
1359
+ */
1360
+ beginChatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatSessionCall>;
1046
1361
  /**
1047
1362
  * Continue from the caller's complete conversation history. The
1048
1363
  * checkpoint's chat template is rendered again and exact prefix matching
1049
1364
  * decides whether the live cache can be reused.
1050
1365
  */
1051
1366
  chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1367
+ /** Internal operation for `chatSessionContinue`. */
1368
+ beginChatSessionContinue(
1369
+ messages: Array<ChatMessage>,
1370
+ config?: ChatConfig | undefined | null,
1371
+ ): Promise<ChatSessionCall>;
1052
1372
  /**
1053
1373
  * Tool-result continuation over a full history. Tool representation is
1054
1374
  * owned entirely by the model-provided template.
1055
1375
  */
1056
1376
  chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1377
+ /** Internal operation for `chatSessionContinueTool`. */
1378
+ beginChatSessionContinueTool(
1379
+ messages: Array<ChatMessage>,
1380
+ config?: ChatConfig | undefined | null,
1381
+ ): Promise<ChatSessionCall>;
1057
1382
  /** Streaming variant of `chatSessionStart`. */
1058
1383
  chatStreamSessionStart(
1059
1384
  messages: ChatMessage[],
@@ -1082,27 +1407,39 @@ export declare class QianfanOCRModel {
1082
1407
  * routed through `TrainingDispatch` to the model thread.
1083
1408
  */
1084
1409
  export declare class Qwen35Model {
1410
+ /**
1411
+ * Resolved directory containing this model's tokenizer/config assets.
1412
+ * Streaming wrappers use it after a direct GGUF load so chat templating
1413
+ * reads the reconstructed sidecars from the native-packed cache.
1414
+ */
1415
+ modelAssetsPath(): string;
1085
1416
  /**
1086
1417
  * Whether the block-paged KV cache adapter is active on this model
1087
1418
  * instance.
1088
1419
  *
1089
1420
  * `true` iff `Qwen35Inner::paged_adapter` was successfully
1090
1421
  * constructed at load time (driven by
1091
- * `Qwen3_5Config::use_block_paged_cache`, default-OFF for text-only
1092
- * checkpoints because parity is pending real-weights validation, and
1093
- * default-ON for VLM checkpoints). On VLM checkpoints dense image turns
1094
- * ONLY run on the paged-vision core; a vision turn that reaches a None
1095
- * adapter errors at dispatch. Surfaced through this NAPI method so
1422
+ * `Qwen3_5Config::use_block_paged_cache`, default-ON for every compatible
1423
+ * checkpoint). On VLM checkpoints dense image turns ONLY run on the
1424
+ * paged-vision core; a vision turn that reaches a None adapter errors at
1425
+ * dispatch. Surfaced through this NAPI method so
1096
1426
  * server endpoints can branch on it without round-tripping through
1097
1427
  * the model thread.
1098
1428
  */
1099
1429
  hasBlockPagedCache(): boolean;
1100
1430
  /**
1101
- * Whether this checkpoint shipped an MTP head (module loaded by
1102
- * `persistence::apply_weights_inner`). Snapshotted at load time from
1103
- * `Qwen35Inner::has_mtp_weights()` so the TS `ChatSession` can
1104
- * auto-default `enableMtp = true` for MTP-capable checkpoints without
1105
- * dispatching a command into the model thread.
1431
+ * Native admission width for plain text AR turns. Installed vision and
1432
+ * MTP modules do not disable text batching: requests that actually carry
1433
+ * media or set `enable_mtp=true` are routed through the ordered exclusive
1434
+ * lane by the scheduler.
1435
+ */
1436
+ maxConcurrentSequences(): number;
1437
+ /** Snapshot scheduler occupancy plus unified block/recurrent admission. */
1438
+ schedulerStats(): Promise<SchedulerStats>;
1439
+ /**
1440
+ * Whether this instance has an inline MTP head or external DFlash2
1441
+ * companion. Snapshotted at load time so `ChatSession` can auto-default
1442
+ * `enableMtp = true` without dispatching into the model thread.
1106
1443
  *
1107
1444
  * Note: this only reports weight availability. Whether the
1108
1445
  * speculative-decode path actually runs on a given call also requires the
@@ -1139,7 +1476,7 @@ export declare class Qwen35Model {
1139
1476
  * - model.safetensors (or model-*.safetensors)
1140
1477
  * - tokenizer.json + tokenizer_config.json
1141
1478
  */
1142
- static load(path: string): Promise<Qwen35Model>;
1479
+ static load(path: string, options?: Qwen35LoadOptions | undefined | null): Promise<Qwen35Model>;
1143
1480
  /** Generate text from a prompt token sequence. */
1144
1481
  generate(promptTokens: MxArray, config: Qwen35GenerationConfig): Promise<Qwen35GenerationResult>;
1145
1482
  /**
@@ -1155,11 +1492,16 @@ export declare class Qwen35Model {
1155
1492
  */
1156
1493
  saveModel(savePath: string): Promise<undefined>;
1157
1494
  /**
1158
- * Reset all caches and clear cached token history. Exposed
1159
- * so tests and session-management code can start from a
1160
- * known clean state between turns.
1495
+ * Reset all caches and clear cached token history. Async so a reset
1496
+ * queued behind an in-flight turn parks a tokio future, never the
1497
+ * Node event loop (H1: a dead prefill used to freeze all HTTP traffic).
1161
1498
  */
1162
- resetCaches(): void;
1499
+ resetCaches(): Promise<void>;
1500
+ /**
1501
+ * Release scheduler-owned KV/history state for one logical
1502
+ * session owner without purging content-addressed prefix blocks.
1503
+ */
1504
+ releaseCacheOwner(ownerId: string): Promise<void>;
1163
1505
  /**
1164
1506
  * Start a new chat session.
1165
1507
  *
@@ -1168,6 +1510,16 @@ export declare class Qwen35Model {
1168
1510
  * preserves the resulting KV state for exact-prefix reuse.
1169
1511
  */
1170
1512
  chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1513
+ /**
1514
+ * Internal operation bridge for `chatSessionStart` (H2). Resolves
1515
+ * IMMEDIATELY with a `ChatSessionCall` whose `cancel()`
1516
+ * can cancel the queued/running turn; the reply arrives via
1517
+ * `call.result()`. A cancelled turn rejects `result()` with
1518
+ * the exact string `"chat session cancelled"`. The LM wrapper
1519
+ * keeps this two-phase operation private and exposes cancellation
1520
+ * through the ordinary method's `AbortSignal` argument.
1521
+ */
1522
+ beginChatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatSessionCall>;
1171
1523
  /**
1172
1524
  * Continue an existing chat session from the complete
1173
1525
  * structured conversation. The loaded model template is the
@@ -1176,11 +1528,27 @@ export declare class Qwen35Model {
1176
1528
  * against the saved token history.
1177
1529
  */
1178
1530
  chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1531
+ /**
1532
+ * Internal operation bridge for `chatSessionContinue` (H2). Same
1533
+ * contract as `beginChatSessionStart`.
1534
+ */
1535
+ beginChatSessionContinue(
1536
+ messages: Array<ChatMessage>,
1537
+ config?: ChatConfig | undefined | null,
1538
+ ): Promise<ChatSessionCall>;
1179
1539
  /**
1180
1540
  * Continue an existing chat session from a complete
1181
1541
  * structured conversation ending in a tool-role message.
1182
1542
  */
1183
1543
  chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1544
+ /**
1545
+ * Internal operation bridge for `chatSessionContinueTool` (H2). Same
1546
+ * contract as `beginChatSessionStart`.
1547
+ */
1548
+ beginChatSessionContinueTool(
1549
+ messages: Array<ChatMessage>,
1550
+ config?: ChatConfig | undefined | null,
1551
+ ): Promise<ChatSessionCall>;
1184
1552
  /** Streaming variant of `chatSessionStart`. */
1185
1553
  chatStreamSessionStart(
1186
1554
  messages: ChatMessage[],
@@ -1216,15 +1584,22 @@ export declare class Qwen35MoeModel {
1216
1584
  *
1217
1585
  * `true` iff `Qwen35MoeInner::paged_adapter` was successfully
1218
1586
  * constructed at load time (driven by
1219
- * `Qwen3_5MoeConfig::use_block_paged_cache`, currently default-OFF
1220
- * because parity is pending real-weights validation). On VLM
1221
- * checkpoints the adapter can still be active for text-only
1587
+ * `Qwen3_5MoeConfig::use_block_paged_cache`, default-ON for compatible
1588
+ * checkpoints). On VLM checkpoints the adapter can still be active for text-only
1222
1589
  * inference; image-bearing chat turns are rejected at runtime by
1223
1590
  * the chat-entry sites. Surfaced through this NAPI method so
1224
1591
  * server endpoints can branch on it without round-tripping through
1225
1592
  * the model thread.
1226
1593
  */
1227
1594
  hasBlockPagedCache(): boolean;
1595
+ /**
1596
+ * Native admission width for plain text autoregressive turns. MTP and
1597
+ * multimodal turns remain ordered barriers and do not enter the batched
1598
+ * decode lane.
1599
+ */
1600
+ maxConcurrentSequences(): number;
1601
+ /** Snapshot scheduler occupancy plus unified block/recurrent admission. */
1602
+ schedulerStats(): Promise<SchedulerStats>;
1228
1603
  /**
1229
1604
  * Whether this checkpoint shipped an MTP head (module loaded by
1230
1605
  * `persistence::apply_weights_moe_inner`). Snapshotted at load time from
@@ -1270,11 +1645,16 @@ export declare class Qwen35MoeModel {
1270
1645
  */
1271
1646
  saveModel(savePath: string): Promise<undefined>;
1272
1647
  /**
1273
- * Reset all caches and clear cached token history. Exposed
1274
- * so tests and session-management code can start from a
1275
- * known clean state between turns.
1648
+ * Reset all caches and clear cached token history. Async so a reset
1649
+ * queued behind an in-flight turn parks a tokio future, never the
1650
+ * Node event loop (H1: a dead prefill used to freeze all HTTP traffic).
1651
+ */
1652
+ resetCaches(): Promise<void>;
1653
+ /**
1654
+ * Release scheduler-owned KV/history state for one logical
1655
+ * session owner without purging content-addressed prefix blocks.
1276
1656
  */
1277
- resetCaches(): void;
1657
+ releaseCacheOwner(ownerId: string): Promise<void>;
1278
1658
  /**
1279
1659
  * Start a new chat session.
1280
1660
  *
@@ -1283,6 +1663,16 @@ export declare class Qwen35MoeModel {
1283
1663
  * preserves the resulting KV state for exact-prefix reuse.
1284
1664
  */
1285
1665
  chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1666
+ /**
1667
+ * Internal operation bridge for `chatSessionStart` (H2). Resolves
1668
+ * IMMEDIATELY with a `ChatSessionCall` whose `cancel()`
1669
+ * can cancel the queued/running turn; the reply arrives via
1670
+ * `call.result()`. A cancelled turn rejects `result()` with
1671
+ * the exact string `"chat session cancelled"`. The LM wrapper
1672
+ * keeps this two-phase operation private and exposes cancellation
1673
+ * through the ordinary method's `AbortSignal` argument.
1674
+ */
1675
+ beginChatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatSessionCall>;
1286
1676
  /**
1287
1677
  * Continue an existing chat session from the complete
1288
1678
  * structured conversation. The loaded model template is the
@@ -1291,11 +1681,27 @@ export declare class Qwen35MoeModel {
1291
1681
  * against the saved token history.
1292
1682
  */
1293
1683
  chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1684
+ /**
1685
+ * Internal operation bridge for `chatSessionContinue` (H2). Same
1686
+ * contract as `beginChatSessionStart`.
1687
+ */
1688
+ beginChatSessionContinue(
1689
+ messages: Array<ChatMessage>,
1690
+ config?: ChatConfig | undefined | null,
1691
+ ): Promise<ChatSessionCall>;
1294
1692
  /**
1295
1693
  * Continue an existing chat session from a complete
1296
1694
  * structured conversation ending in a tool-role message.
1297
1695
  */
1298
1696
  chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1697
+ /**
1698
+ * Internal operation bridge for `chatSessionContinueTool` (H2). Same
1699
+ * contract as `beginChatSessionStart`.
1700
+ */
1701
+ beginChatSessionContinueTool(
1702
+ messages: Array<ChatMessage>,
1703
+ config?: ChatConfig | undefined | null,
1704
+ ): Promise<ChatSessionCall>;
1299
1705
  /** Streaming variant of `chatSessionStart`. */
1300
1706
  chatStreamSessionStart(
1301
1707
  messages: ChatMessage[],
@@ -1317,6 +1723,36 @@ export declare class Qwen35MoeModel {
1317
1723
  }
1318
1724
  export type Qwen3_5MoeModel = Qwen35MoeModel;
1319
1725
 
1726
+ export declare class Qwen3AsrCapture {
1727
+ get source(): Qwen3AsrCaptureSource;
1728
+ get deviceName(): string;
1729
+ get sampleRate(): number;
1730
+ get channels(): number;
1731
+ pause(): void;
1732
+ resume(): void;
1733
+ stop(): Promise<Qwen3AsrCaptureStats>;
1734
+ }
1735
+
1736
+ export declare class Qwen3AsrModel {
1737
+ static load(modelPath: string): Promise<Qwen3AsrModel>;
1738
+ transcribe(audio: Float32Array, options?: Qwen3AsrTranscribeOptions | undefined | null): Promise<Qwen3AsrResult>;
1739
+ createStream(options?: Qwen3AsrStreamOptions | undefined | null): Promise<Qwen3AsrStream>;
1740
+ }
1741
+
1742
+ export declare class Qwen3AsrStream {
1743
+ feed(samples: Float32Array): Promise<Qwen3AsrResult | undefined | null>;
1744
+ finish(): Promise<Qwen3AsrResult>;
1745
+ /**
1746
+ * Start real-time microphone or system-output capture through Core Audio.
1747
+ * The realtime callback only writes mono float PCM into a bounded lock-free
1748
+ * ring; a separate worker drains it and feeds this streaming session.
1749
+ */
1750
+ startCapture(
1751
+ options: Qwen3AsrCaptureOptions | undefined | null,
1752
+ callback: (err: Error | null, arg: Qwen3AsrResult) => void,
1753
+ ): Qwen3AsrCapture;
1754
+ }
1755
+
1320
1756
  /**
1321
1757
  * Qwen3 Model with automatic differentiation support
1322
1758
  *
@@ -1340,6 +1776,17 @@ export declare class Qwen3Model {
1340
1776
  * runtime-routing decision.
1341
1777
  */
1342
1778
  hasBlockPagedCache(): boolean;
1779
+ /**
1780
+ * Maximum number of independent sequences admitted to the continuous
1781
+ * batching scheduler. Flat-cache and forced-serial instances deliberately
1782
+ * report one so the server retains its exclusive dispatch lane.
1783
+ */
1784
+ maxConcurrentSequences(): number;
1785
+ /**
1786
+ * Snapshot continuous-batching scheduler counters after all commands
1787
+ * already ahead of this query have drained.
1788
+ */
1789
+ schedulerStats(): Promise<SchedulerStats>;
1343
1790
  /** Get model configuration */
1344
1791
  getConfig(): Qwen3Config;
1345
1792
  /**
@@ -1434,11 +1881,16 @@ export declare class Qwen3Model {
1434
1881
  enableThinking?: boolean | undefined | null,
1435
1882
  ): Promise<Uint32Array>;
1436
1883
  /**
1437
- * Reset all caches and clear cached token history. Exposed
1438
- * so tests and session-management code can start from a
1439
- * known clean state between turns.
1884
+ * Reset all caches and clear cached token history. Async so a reset
1885
+ * queued behind an in-flight turn parks a tokio future, never the
1886
+ * Node event loop (H1: a dead prefill used to freeze all HTTP traffic).
1440
1887
  */
1441
- resetCaches(): void;
1888
+ resetCaches(): Promise<void>;
1889
+ /**
1890
+ * Release scheduler-owned KV/history state for one logical
1891
+ * session owner without purging content-addressed prefix blocks.
1892
+ */
1893
+ releaseCacheOwner(ownerId: string): Promise<void>;
1442
1894
  /**
1443
1895
  * Start a new chat session.
1444
1896
  *
@@ -1447,6 +1899,16 @@ export declare class Qwen3Model {
1447
1899
  * preserves the resulting KV state for exact-prefix reuse.
1448
1900
  */
1449
1901
  chatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1902
+ /**
1903
+ * Internal operation bridge for `chatSessionStart` (H2). Resolves
1904
+ * IMMEDIATELY with a `ChatSessionCall` whose `cancel()`
1905
+ * can cancel the queued/running turn; the reply arrives via
1906
+ * `call.result()`. A cancelled turn rejects `result()` with
1907
+ * the exact string `"chat session cancelled"`. The LM wrapper
1908
+ * keeps this two-phase operation private and exposes cancellation
1909
+ * through the ordinary method's `AbortSignal` argument.
1910
+ */
1911
+ beginChatSessionStart(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatSessionCall>;
1450
1912
  /**
1451
1913
  * Continue an existing chat session from the complete
1452
1914
  * structured conversation. The loaded model template is the
@@ -1455,11 +1917,27 @@ export declare class Qwen3Model {
1455
1917
  * against the saved token history.
1456
1918
  */
1457
1919
  chatSessionContinue(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1920
+ /**
1921
+ * Internal operation bridge for `chatSessionContinue` (H2). Same
1922
+ * contract as `beginChatSessionStart`.
1923
+ */
1924
+ beginChatSessionContinue(
1925
+ messages: Array<ChatMessage>,
1926
+ config?: ChatConfig | undefined | null,
1927
+ ): Promise<ChatSessionCall>;
1458
1928
  /**
1459
1929
  * Continue an existing chat session from a complete
1460
1930
  * structured conversation ending in a tool-role message.
1461
1931
  */
1462
1932
  chatSessionContinueTool(messages: Array<ChatMessage>, config?: ChatConfig | undefined | null): Promise<ChatResult>;
1933
+ /**
1934
+ * Internal operation bridge for `chatSessionContinueTool` (H2). Same
1935
+ * contract as `beginChatSessionStart`.
1936
+ */
1937
+ beginChatSessionContinueTool(
1938
+ messages: Array<ChatMessage>,
1939
+ config?: ChatConfig | undefined | null,
1940
+ ): Promise<ChatSessionCall>;
1463
1941
  /** Streaming variant of `chatSessionStart`. */
1464
1942
  chatStreamSessionStart(
1465
1943
  messages: ChatMessage[],
@@ -1483,8 +1961,8 @@ export declare class Qwen3Model {
1483
1961
  *
1484
1962
  * This loads a model from a directory containing:
1485
1963
  * - config.json: Model configuration
1486
- * - weights.mlx (optional): MLX format weights with data arrays
1487
- * - weights.safetensors (optional): SafeTensors format (not yet supported)
1964
+ * - weights.safetensors or model.safetensors (single-file SafeTensors)
1965
+ * - model-*-of-*.safetensors (sharded SafeTensors)
1488
1966
  *
1489
1967
  * # Arguments
1490
1968
  * * `model_path` - Path to the model directory
@@ -2123,8 +2601,45 @@ export declare function calibrateActivationAmaxRaw(
2123
2601
  calibSeq: number,
2124
2602
  ): Promise<number>;
2125
2603
 
2604
+ /**
2605
+ * Run the teacher over `texts` and write its top-`top_k` next-token
2606
+ * distribution into `cache_dir`. Returns the number of rows written.
2607
+ *
2608
+ * Each row is tokenized RAW (no chat template, no BOS), truncated to `seq_len`
2609
+ * tokens, and prefilled on fresh caches. The head is projected over positions
2610
+ * in `logit_chunk`-sized chunks so the full-vocabulary logits never
2611
+ * materialize for the whole sequence at once.
2612
+ *
2613
+ * `seq_len` is raised to 2 when lower: the first token primes the forward and
2614
+ * has no target of its own, so a shorter row scores nothing. `top_k` is
2615
+ * clamped to the teacher's vocabulary, so a wider request degrades to an exact
2616
+ * full-vocab KL. The cache records both EFFECTIVE values, not the requested
2617
+ * ones — the support width is what says how far a top-K KL can be trusted.
2618
+ *
2619
+ * A quantized teacher is accepted — anchoring on a released quantized
2620
+ * checkpoint is a real comparison — but it is warned about and recorded in the
2621
+ * cache, because every number then measures divergence from that checkpoint
2622
+ * rather than from the bf16 model.
2623
+ */
2624
+ export declare function captureTeacherLogits(
2625
+ teacherPath: string,
2626
+ texts: Array<string>,
2627
+ seqLen: number,
2628
+ topK: number,
2629
+ logitChunk: number,
2630
+ cacheDir: string,
2631
+ ): Promise<number>;
2632
+
2126
2633
  /** Unified chat configuration shared by all model variants (Qwen3, Qwen3.5, Qwen3.5 MoE). */
2127
2634
  export interface ChatConfig {
2635
+ /**
2636
+ * Security domain for content-addressed paged-KV prefix reuse.
2637
+ * Requests with different values cannot reuse each other's cached
2638
+ * prefixes even when their token sequences are identical. This is
2639
+ * deliberately separate from `cache_owner_id`, which controls logical
2640
+ * session/recurrent-state ownership rather than physical KV sharing.
2641
+ */
2642
+ cacheSalt?: string | undefined;
2128
2643
  /**
2129
2644
  * Internal logical cache owner. The agent provider forwards Pi's stable
2130
2645
  * session id so model-global GDN sidecars can retain parent and child
@@ -2204,6 +2719,20 @@ export interface ChatConfig {
2204
2719
  * loop (pure-Rust eager; qwen3.5 dense and MoE). Requires the model
2205
2720
  * checkpoint to carry an MTP head (otherwise silently ignored). Default:
2206
2721
  * `false`.
2722
+ *
2723
+ * The MTP acceptance gate (`MLX_MTP_ACCEPT_GATE`, default ON) also
2724
+ * applies to explicit requests at fixed depth 1: the model aggregates
2725
+ * first-draft acceptance counts across completed depth-1 turns (history
2726
+ * bounded to roughly the most recent ~512 attempts) and silently runs
2727
+ * plain autoregressive decoding for the next depth-1 turn when an
2728
+ * exact-binomial test at the 5% level shows the aggregate is
2729
+ * inconsistent with the ~0.6 break-even acceptance rate. After 3
2730
+ * consecutive gated turns the gate re-probes with speculation on, and
2731
+ * `resetCaches()` clears the per-model (not per-session) history. The
2732
+ * gate is depth-1-scoped and exempts adaptive-depth turns
2733
+ * (`mtpAdaptiveDepth` and explicit depth > 1 turns are never gated).
2734
+ * Set the env var to `0` / `false` / `off` to bypass the gate and
2735
+ * always run MTP when requested.
2207
2736
  */
2208
2737
  enableMtp?: boolean | undefined;
2209
2738
  /**
@@ -2216,10 +2745,14 @@ export interface ChatConfig {
2216
2745
  * Adaptive depth is opt-in; set `mtpAdaptiveDepth: true` explicitly to
2217
2746
  * enable it.
2218
2747
  *
2219
- * Gemma4 external drafts (`draftModelPath`) resolve the field per draft
2220
- * variant instead (`gemma4/model.rs` `resolve_params`, always from the
2221
- * RAW config value — the engine's central `[1, 5]` clamp is an MTP-head
2222
- * contract that does not apply to external drafts):
2748
+ * External drafts (`draftModelPath`) resolve the field against their
2749
+ * checkpoint width instead (always from the RAW config value — the
2750
+ * engine's central `[1, 5]` clamp is an MTP-head contract that does not
2751
+ * apply to external drafts):
2752
+ * - Qwen3.8 DFlash2: checkpoint `block_size = 8` contains one target
2753
+ * anchor plus seven proposals. Unset uses all seven; an explicit value
2754
+ * clamps to `[1, 7]` and pins that depth unless
2755
+ * `mtpAdaptiveDepth: true` explicitly enables the break-even guard.
2223
2756
  * - DSpark: with both knobs unset, full draft blocks (the checkpoint's
2224
2757
  * block size — 7 tokens on `dspark_gemma4_12b_block7`) run behind a
2225
2758
  * short target-AR/DSpark break-even calibration. A short generation
@@ -2230,6 +2763,10 @@ export interface ChatConfig {
2230
2763
  * - Assistant (Google `gemma-4-*-it-assistant`): an unset `mtpDepth`
2231
2764
  * drafts 3 tokens per cycle (`ASSISTANT_DEFAULT_DEPTH`), and an
2232
2765
  * explicit `mtpDepth` clamps to `[1, 8]` (`ASSISTANT_MAX_DEPTH`).
2766
+ * - Muse-Glimmer DFlash follows DSpark's external-draft rules: unset
2767
+ * uses the checkpoint block size (16 for Muse-Glimmer-30B), while an
2768
+ * explicit value clamps to `[1, block_size]` and pins that depth unless
2769
+ * `mtpAdaptiveDepth: true` explicitly enables the break-even guard.
2233
2770
  *
2234
2771
  * `mtpAdaptiveDepth` is ignored for the Gemma4 assistant variant.
2235
2772
  */
@@ -2244,9 +2781,10 @@ export interface ChatConfig {
2244
2781
  * `MLX_MTP_EV_ALLOW_DEEPEN=0` to pin the base depth.
2245
2782
  * When false, the loop pins `mtpDepth` for every cycle.
2246
2783
  *
2247
- * Default: false, except Gemma4 DSpark enables its measured break-even
2248
- * guard when both this field and `mtpDepth` are unset. An explicit value
2249
- * always wins over the family default.
2784
+ * Default: false, except Gemma4 DSpark and Muse-Glimmer DFlash enable the
2785
+ * measured break-even guard when both this field and `mtpDepth` are unset.
2786
+ * Qwen3.8 DFlash2 remains fixed-width by default. An explicit value always
2787
+ * wins over the family default.
2250
2788
  */
2251
2789
  mtpAdaptiveDepth?: boolean | undefined;
2252
2790
  }
@@ -2672,6 +3210,15 @@ export declare function convertForeignWeights(options: ForeignConversionOptions)
2672
3210
 
2673
3211
  export declare function convertGgufToSafetensors(options: GgufConversionOptions): Promise<GgufConversionResult>;
2674
3212
 
3213
+ /**
3214
+ * Every convertible `model_type` the converter registry accepts, in dispatch
3215
+ * order — the native half of the CLI detect-table parity gate (same pattern
3216
+ * as `cold_restore_families`): a family with a conversion recipe but no CLI
3217
+ * detect row would otherwise convert generically and produce unloadable
3218
+ * output.
3219
+ */
3220
+ export declare function convertibleModelTypes(): Array<string>;
3221
+
2675
3222
  /**
2676
3223
  * Convert a HuggingFace SafeTensors model to MLX format
2677
3224
  *
@@ -2747,6 +3294,11 @@ export declare function createRandomQwen35MoeCheckpoint(config: Qwen35MoeConfig,
2747
3294
  */
2748
3295
  export declare function createRandomQwen3Checkpoint(config: Qwen3Config, savePath: string): Promise<undefined>;
2749
3296
 
3297
+ export interface DecodeBatchOccupancyBucket {
3298
+ occupancy: number;
3299
+ steps: number;
3300
+ }
3301
+
2750
3302
  /** Document element - either a table or paragraph */
2751
3303
  export interface DocumentElement {
2752
3304
  elementType: ElementType;
@@ -2835,6 +3387,34 @@ export interface EngineStepMetrics {
2835
3387
  activeMemoryMb: number;
2836
3388
  }
2837
3389
 
3390
+ /**
3391
+ * Teacher-forced quality of one checkpoint against a cached reference.
3392
+ *
3393
+ * `mean_nll`, `perplexity` and `top1_agreement` are EXACT full-vocab numbers.
3394
+ * `mean_kl_topk` is exact only over the teacher's cached support — read it
3395
+ * together with `teacher_tail_mass`, which is the probability mass that support
3396
+ * leaves out.
3397
+ */
3398
+ export interface EvalReport {
3399
+ rows: number;
3400
+ positions: number;
3401
+ topK: number;
3402
+ /** Teacher the cache was captured from, carried through from its metadata. */
3403
+ teacherPath: string;
3404
+ /**
3405
+ * That teacher was itself quantized, so every number below measures
3406
+ * divergence from it rather than from the bf16 model.
3407
+ */
3408
+ teacherQuantized: boolean;
3409
+ meanNll: number;
3410
+ perplexity: number;
3411
+ teacherMeanNll: number;
3412
+ teacherPerplexity: number;
3413
+ meanKlTopk: number;
3414
+ teacherTailMass: number;
3415
+ top1Agreement: number;
3416
+ }
3417
+
2838
3418
  export interface ForeignConversionOptions {
2839
3419
  /** Path to the input weights file (.pdparams, .pkl, .pt, .pth) */
2840
3420
  inputPath: string;
@@ -3046,10 +3626,9 @@ export interface Gemma4LoadOptions {
3046
3626
  * alongside the target model for speculative decoding — either a
3047
3627
  * DSpark draft or a Google assistant draft; the kind is probed from
3048
3628
  * the draft config.json. When omitted, `<model_path>/draft/` is loaded
3049
- * automatically when present. Draft decoding runs only on the flat
3050
- * KV-cache path: setting this while the model config explicitly enables
3051
- * `use_block_paged_cache` is a hard load error, and an unset
3052
- * `use_block_paged_cache` is forced to `false`.
3629
+ * automatically when present. Draft decoding uses a request-local flat
3630
+ * target-cache lane. The resident target retains its grouped paged pools,
3631
+ * so loading an optional proposer does not disable ordinary batching.
3053
3632
  */
3054
3633
  draftModelPath?: string;
3055
3634
  }
@@ -3224,6 +3803,13 @@ export declare function getMemorySnapshot(): GpuMemorySnapshot;
3224
3803
  /** Retrieve all collected profiling data as a `ProfilingSession`. */
3225
3804
  export declare function getProfilingData(): ProfilingSession;
3226
3805
 
3806
+ /**
3807
+ * Read the architecture declared by a GGUF header without loading any tensor
3808
+ * payloads. This is the model-family detection seam for standalone GGUF files
3809
+ * that intentionally do not ship a sibling `config.json`.
3810
+ */
3811
+ export declare function ggufArchitecture(inputPath: string): string;
3812
+
3227
3813
  export interface GgufConversionOptions {
3228
3814
  /** Path to the GGUF file */
3229
3815
  inputPath: string;
@@ -3281,13 +3867,20 @@ export interface GgufConversionOptions {
3281
3867
  */
3282
3868
  quantMxfp?: boolean;
3283
3869
  /**
3284
- * Import ggml Q4_K / Q5_K / Q6_K tensors as MLX K-quant arrays instead of
3870
+ * Import supported ggml K/IQ tensors as native MLX packed arrays instead of
3285
3871
  * rejecting them (default: false). The blocks are repacked, never
3286
- * dequantized, so the output keeps the source file's weights and byte size.
3872
+ * dequantized, so the output preserves the source quantized values. IQ3_S
3873
+ * expands only its integer grid/sign encoding to signed 8-bit codes.
3287
3874
  * With this off, Q6_K remains the Gemma4 token-embedding BF16 fallback and
3288
3875
  * Q4_K / Q5_K are an error.
3289
3876
  */
3290
3877
  importKQuants?: boolean;
3878
+ /**
3879
+ * Preserve Qwen3.5/3.8 GGUF GDN tensors in llama.cpp's tiled value-head
3880
+ * order. The runtime consumes this layout directly and avoids any packed
3881
+ * weight permutation. Intended for native GGUF execution.
3882
+ */
3883
+ nativeQwen35Layout?: boolean;
3291
3884
  }
3292
3885
 
3293
3886
  export interface GgufConversionResult {
@@ -3624,6 +4217,12 @@ export interface Lfm2Config {
3624
4217
  * fully flat `Lfm2LayerCache` path on all layers.
3625
4218
  */
3626
4219
  useBlockPagedCache?: boolean | undefined;
4220
+ /**
4221
+ * Persist block-paged attention state and the co-keyed short-convolution
4222
+ * sidecar to the SSD cold tier. Explicit config overrides the process-wide
4223
+ * `MLX_PERSIST_PAGED_CACHE` default.
4224
+ */
4225
+ persistPagedCache?: boolean | undefined;
3627
4226
  /**
3628
4227
  * MLP intermediate size for the DENSE-in-MoE layers (`layer_idx <
3629
4228
  * num_dense_layers`). Used DIRECTLY (no 2/3 `computed_ff_dim()` shrink).
@@ -3715,6 +4314,104 @@ export declare const enum MultimodalContentOrder {
3715
4314
  ImagesThenText = 'imagesThenText',
3716
4315
  }
3717
4316
 
4317
+ /**
4318
+ * Trained and physically available active-context limits for one loaded
4319
+ * Muse-Glimmer model. Values are snapshots because the physical pool is fixed
4320
+ * for the lifetime of the resident model.
4321
+ */
4322
+ export interface MuseGlimmerContextLimits {
4323
+ trainedWindowTokens: number;
4324
+ effectiveWindowTokens: number;
4325
+ pagedBlockCapacity: number;
4326
+ pagedBlockSize: number;
4327
+ }
4328
+
4329
+ /**
4330
+ * NVIDIA Nemotron 3.5 Lightning ("nemotron_h") model configuration.
4331
+ *
4332
+ * Hybrid MoE: every layer is one pre-RMSNorm + ONE mixer + a residual, closed
4333
+ * by `norm_f` and an untied `lm_head`. Parsed fail-closed — unknown block
4334
+ * types, missing fields and unsupported features are rejected at load.
4335
+ */
4336
+ export interface NemotronHConfig {
4337
+ vocabSize: number;
4338
+ hiddenSize: number;
4339
+ numHiddenLayers: number;
4340
+ numAttentionHeads: number;
4341
+ numKeyValueHeads: number;
4342
+ headDim: number;
4343
+ maxPositionEmbeddings: number;
4344
+ layerNormEpsilon: number;
4345
+ /**
4346
+ * Per-layer mixer kind, remapped from the checkpoint's
4347
+ * `layers_block_type` to the HF `MIXER_TYPES` names.
4348
+ */
4349
+ layersBlockType: Array<string>;
4350
+ mambaNumHeads: number;
4351
+ mambaHeadDim: number;
4352
+ /** SSM state size, per head per group. */
4353
+ ssmStateSize: number;
4354
+ /** Number of SSM groups; head `h` belongs to group `h / (H / G)`. */
4355
+ nGroups: number;
4356
+ /** Depthwise causal conv1d kernel size. */
4357
+ convKernel: number;
4358
+ chunkSize: number;
4359
+ /**
4360
+ * Declared minimum discretized time step.
4361
+ *
4362
+ * UNUSED BY THE RUNTIME. No served reference clamps dt to it - only HF's
4363
+ * torch fallback does. `time_step_limit_pair()` is the real clamp.
4364
+ */
4365
+ timeStepMin: number;
4366
+ /**
4367
+ * Optional `[min, max]` bounds for the discretized time step. `None` is
4368
+ * the reference default `(0.0, +inf)`, i.e. no clamp.
4369
+ */
4370
+ timeStepLimit?: number[];
4371
+ nRoutedExperts: number;
4372
+ numExpertsPerTok: number;
4373
+ /** Routing weight scale, applied after normalization. */
4374
+ routedScalingFactor: number;
4375
+ /** Renormalize the gathered top-k weights to sum to 1 before scaling. */
4376
+ normTopkProb: boolean;
4377
+ /** Per-expert MLP intermediate size (non-gated up -> relu2 -> down). */
4378
+ intermediateSize: number;
4379
+ /** Shared-expert MLP intermediate size; it runs on ALL tokens. */
4380
+ moeSharedExpertIntermediateSize: number;
4381
+ /** EOS token ids, from the config.json scalar or array. */
4382
+ eosTokenIds: number[];
4383
+ /** MTP layer kinds, remapped like `layers_block_type`. */
4384
+ mtpLayersBlockType: string[];
4385
+ /** Number of MTP predictor steps (`num_nextn_predict_layers`). */
4386
+ nMtpLayers: number;
4387
+ /**
4388
+ * Optional block-paged KV cache memory cap in MiB. `None` requests one
4389
+ * `max_position_embeddings` sequence (6 GiB on Lightning 30B-A3B) then
4390
+ * clips with load-time Metal/RAM sizing after weights. Explicit values
4391
+ * skip the auto-sizer.
4392
+ */
4393
+ pagedCacheMemoryMb?: number;
4394
+ /** Optional paged block size in tokens (default 16). */
4395
+ pagedBlockSize?: number;
4396
+ /**
4397
+ * Opt in/out of the block-paged KV adapter. `None` enables the paged pool
4398
+ * and the continuous-batching lane; `Some(false)` reverts to whole-turn.
4399
+ */
4400
+ useBlockPagedCache?: boolean;
4401
+ }
4402
+
4403
+ /**
4404
+ * Physical and trained context limits captured at load time, surfaced through
4405
+ * `context_limits()` so the ChatSession preflight can compact or reject against
4406
+ * the paged pool's ACTUAL capacity instead of the trained window.
4407
+ */
4408
+ export interface NemotronHContextLimits {
4409
+ trainedWindowTokens: number;
4410
+ effectiveWindowTokens: number;
4411
+ pagedBlockCapacity: number;
4412
+ pagedBlockSize: number;
4413
+ }
4414
+
3718
4415
  /** Result from document orientation classification. */
3719
4416
  export interface OrientationResult {
3720
4417
  /** Detected rotation angle (0, 90, 180, or 270 degrees) */
@@ -3885,6 +4582,12 @@ export interface PhaseProfile {
3885
4582
  count: number;
3886
4583
  }
3887
4584
 
4585
+ /**
4586
+ * Header-only DFlash validation for the CLI's transactional ordering. This
4587
+ * runs before the primary conversion touches its output directory.
4588
+ */
4589
+ export declare function preflightMuseDflashGguf(inputPath: string, targetConfigDir: string): void;
4590
+
3888
4591
  /**
3889
4592
  * Per-call Viterbi calibration overrides.
3890
4593
  *
@@ -4062,6 +4765,15 @@ export interface Qwen35Config {
4062
4765
  * Default: automatically sized for one full-context sequence.
4063
4766
  */
4064
4767
  pagedCacheMemoryMb?: number | undefined;
4768
+ /**
4769
+ * Initial paged KV pool size in MiB for the grow-on-demand pool: the
4770
+ * pool starts at this size and grows toward the max budget
4771
+ * (`paged_cache_memory_mb` or the auto one-full-context default) on
4772
+ * exhaustion. Unset (default) makes the initial pool equal the max —
4773
+ * the historical fixed-pool behavior. `MLX_PAGED_CACHE_INITIAL_MB` wins
4774
+ * over this field at load time.
4775
+ */
4776
+ pagedCacheInitialMemoryMb?: number | undefined;
4065
4777
  /**
4066
4778
  * Block size for paged attention (tokens per block).
4067
4779
  * Only used when `use_block_paged_cache` is true.
@@ -4072,7 +4784,7 @@ export interface Qwen35Config {
4072
4784
  * Use the block-paged KV cache adapter (`PagedKVCacheAdapter`) for
4073
4785
  * full-attention layers.
4074
4786
  *
4075
- * **OPT-IN experimental.** When `Some(true)`, `Qwen35Inner`
4787
+ * When enabled (the default), `Qwen35Inner`
4076
4788
  * allocates a `BlockAllocator` + `LayerKVPool` pair sized for the
4077
4789
  * model's full-attention layer count and constructs a
4078
4790
  * `PagedKVCacheAdapter`. The chat-session forward dispatch routes
@@ -4083,12 +4795,12 @@ export interface Qwen35Config {
4083
4795
  * prefix reuse for recurrent layers" stance.
4084
4796
  *
4085
4797
  * **Paged vs flat eager**: this flag selects the eager paged decode
4086
- * over the eager flat decode. When `Some(true)`, full-attention
4798
+ * over the eager flat decode. When enabled, full-attention
4087
4799
  * layers run through the paged adapter (cross-request prefix reuse);
4088
- * when unset, they run the eager flat decode. Either way the forward
4089
- * is pure-Rust eager.
4800
+ * an explicit false runs eager flat decode. Either way the forward is
4801
+ * pure-Rust eager.
4090
4802
  *
4091
- * **VLM under paged**: a VLM checkpoint defaults this flag ON at load, so
4803
+ * **VLM under paged**: VLM checkpoints also default this flag ON, so
4092
4804
  * dense image turns ONLY run on the paged-vision core. A fresh single-turn
4093
4805
  * image-bearing prompt prefills through the paged adapter (M-RoPE positions
4094
4806
  * feed the rotary; the merged vision embeddings feed the forward) and
@@ -4098,8 +4810,9 @@ export interface Qwen35Config {
4098
4810
  * that reaches a None adapter (explicit `Some(false)`, non-Metal build, or
4099
4811
  * a sym8 checkpoint) errors at dispatch.
4100
4812
  *
4101
- * Default: `None` for text-only checkpoints (eager flat decode);
4102
- * `Some(true)` for VLM checkpoints (block-paged, set in `parse_config`).
4813
+ * Load default: `Some(true)` for compatible text and VLM checkpoints.
4814
+ * Explicit false remains available for flat-path diagnostics; sym8 is
4815
+ * forced flat by persistence after its storage mode is known.
4103
4816
  */
4104
4817
  useBlockPagedCache?: boolean | undefined;
4105
4818
  /**
@@ -4117,12 +4830,20 @@ export interface Qwen35Config {
4117
4830
  * unavailable.
4118
4831
  */
4119
4832
  nMtpLayers: number;
4833
+ /**
4834
+ * Internal layout marker written by native Qwen3.5/3.8 GGUF conversion.
4835
+ * `Some("tiled")` keeps llama.cpp's value-head order and lets GDN map
4836
+ * value head h to key head h % Hk without permuting packed weights.
4837
+ */
4838
+ qwen35GgufGdnLayout?: string | undefined;
4120
4839
  }
4121
4840
 
4122
4841
  /**
4123
4842
  * Trained and physically available active-context limits for one loaded
4124
- * Qwen3.5 model. Values are snapshots because the physical pool is fixed for
4125
- * the lifetime of the resident model.
4843
+ * Qwen3.5 model. Values are snapshots taken at load: `effective_window`
4844
+ * derives from the pool's MAX capacity (grow-on-demand pools are preflighted
4845
+ * against the ceiling they grow toward), while `paged_block_capacity` is the
4846
+ * physical pool size actually allocated at load and may lag after a grow.
4126
4847
  */
4127
4848
  export interface Qwen35ContextLimits {
4128
4849
  trainedWindowTokens: number;
@@ -4148,6 +4869,11 @@ export interface Qwen35GenerationResult {
4148
4869
  finishReason: string;
4149
4870
  }
4150
4871
 
4872
+ export interface Qwen35LoadOptions {
4873
+ /** External z-lab DFlash2 checkpoint directory. */
4874
+ draftModelPath?: string;
4875
+ }
4876
+
4151
4877
  /**
4152
4878
  * Qwen3.5 MoE model configuration.
4153
4879
  *
@@ -4189,6 +4915,15 @@ export interface Qwen35MoeConfig {
4189
4915
  * Default: automatically sized for one full-context sequence.
4190
4916
  */
4191
4917
  pagedCacheMemoryMb?: number | undefined;
4918
+ /**
4919
+ * Initial paged KV pool size in MiB for the grow-on-demand pool: the
4920
+ * pool starts at this size and grows toward the max budget
4921
+ * (`paged_cache_memory_mb` or the auto one-full-context default) on
4922
+ * exhaustion. Unset (default) makes the initial pool equal the max —
4923
+ * the historical fixed-pool behavior. `MLX_PAGED_CACHE_INITIAL_MB` wins
4924
+ * over this field at load time.
4925
+ */
4926
+ pagedCacheInitialMemoryMb?: number | undefined;
4192
4927
  /**
4193
4928
  * Block size for paged attention (tokens per block).
4194
4929
  * Only used when `use_block_paged_cache` is true.
@@ -4198,8 +4933,8 @@ export interface Qwen35MoeConfig {
4198
4933
  /**
4199
4934
  * Use the block-paged KV cache adapter for full-attention layers.
4200
4935
  *
4201
- * **OPT-IN — experimental.** Same semantics as the dense
4202
- * `Qwen3_5Config::use_block_paged_cache` field. Selects the eager
4936
+ * Same semantics as the dense `Qwen3_5Config::use_block_paged_cache`
4937
+ * field. Selects the eager
4203
4938
  * paged decode over the eager flat decode: routes full-attention
4204
4939
  * layers through `PagedKVCacheAdapter` (cross-request prefix reuse);
4205
4940
  * GDN linear-attention layers stay on `Qwen3_5LayerCache::Linear`
@@ -4213,7 +4948,8 @@ export interface Qwen35MoeConfig {
4213
4948
  * runtime; warm image-bearing session continues / cache-hit reuse are
4214
4949
  * cold-started (no warm GDN two-pass prefix).
4215
4950
  *
4216
- * Default: `None` / `false`.
4951
+ * Default: enabled for compatible Metal checkpoints. Explicit `false`
4952
+ * and `MLX_QWEN35_PAGED_OVERRIDE=0` retain the flat rollback path.
4217
4953
  */
4218
4954
  useBlockPagedCache?: boolean | undefined;
4219
4955
  /**
@@ -4232,6 +4968,13 @@ export interface Qwen35MoeConfig {
4232
4968
  * unavailable.
4233
4969
  */
4234
4970
  nMtpLayers: number;
4971
+ /**
4972
+ * Internal layout marker written by native Qwen3.5/3.8 GGUF conversion.
4973
+ * `Some("tiled")` keeps llama.cpp's value-head order and lets the shared
4974
+ * GDN runtime map value head h to key head h % Hk without permuting
4975
+ * packed weights.
4976
+ */
4977
+ qwen35GgufGdnLayout?: string | undefined;
4235
4978
  }
4236
4979
 
4237
4980
  /** Generation configuration for Qwen3.5 MoE */
@@ -4251,6 +4994,145 @@ export interface Qwen35MoeGenerationResult {
4251
4994
  finishReason: string;
4252
4995
  }
4253
4996
 
4997
+ export interface Qwen3AsrAudioDevice {
4998
+ id: string;
4999
+ name: string;
5000
+ source: Qwen3AsrCaptureSource;
5001
+ isDefault: boolean;
5002
+ sampleRate: number;
5003
+ channels: number;
5004
+ }
5005
+
5006
+ export declare function qwen3AsrAudioDevices(): Array<Qwen3AsrAudioDevice>;
5007
+
5008
+ export interface Qwen3AsrCaptureOptions {
5009
+ /** Audio source. Omit to capture the microphone. */
5010
+ source?: Qwen3AsrCaptureSource;
5011
+ /**
5012
+ * Stable Core Audio device UID returned by `qwen3AsrAudioDevices()` or
5013
+ * `qwen3AsrInputDevices()`.
5014
+ */
5015
+ deviceId?: string;
5016
+ /**
5017
+ * Device name. Omit to use the default input or output device for the
5018
+ * selected source.
5019
+ */
5020
+ deviceName?: string;
5021
+ /**
5022
+ * For system audio, optionally capture only processes with these bundle
5023
+ * identifiers. Empty or omitted captures all audio sent to the device.
5024
+ */
5025
+ applicationBundleIds?: Array<string>;
5026
+ /** Lock-free callback ring capacity in seconds (default 10). */
5027
+ ringSeconds?: number;
5028
+ /** Amount drained from the ring into each model feed (default 100 ms). */
5029
+ feedMilliseconds?: number;
5030
+ }
5031
+
5032
+ export declare const enum Qwen3AsrCaptureSource {
5033
+ Microphone = 'microphone',
5034
+ SystemAudio = 'systemAudio',
5035
+ }
5036
+
5037
+ export interface Qwen3AsrCaptureStats {
5038
+ capturedFrames: number;
5039
+ droppedFrames: number;
5040
+ }
5041
+
5042
+ export interface Qwen3AsrInputDevice {
5043
+ id: string;
5044
+ name: string;
5045
+ isDefault: boolean;
5046
+ sampleRate: number;
5047
+ channels: number;
5048
+ sampleFormat: string;
5049
+ }
5050
+
5051
+ export declare function qwen3AsrInputDevices(): Array<Qwen3AsrInputDevice>;
5052
+
5053
+ export interface Qwen3AsrResult {
5054
+ /**
5055
+ * Complete transcription for the latest rolling revision. The trailing
5056
+ * provisional region may be replaced by the next revision.
5057
+ */
5058
+ text: string;
5059
+ /**
5060
+ * Prefix that survived the stream's provisional-token rollback window.
5061
+ * Equals `text` for a final or one-shot result.
5062
+ */
5063
+ stableText: string;
5064
+ /**
5065
+ * Trailing text that may be replaced by the next rolling revision.
5066
+ * Empty for a final or one-shot result.
5067
+ */
5068
+ provisionalText: string;
5069
+ language?: string;
5070
+ tokenIds: Array<number>;
5071
+ /**
5072
+ * True when generation used the entire configured token budget without
5073
+ * reaching an end token. The revision may contain incomplete or repeated
5074
+ * text and callers may choose to flag it for review.
5075
+ */
5076
+ reachedMaxTokens: boolean;
5077
+ /** Total audio committed by this stream, or the full one-shot duration. */
5078
+ audioSeconds: number;
5079
+ /** Newly consumed audio duration for this update. */
5080
+ segmentAudioSeconds: number;
5081
+ featureMs: number;
5082
+ encoderMs: number;
5083
+ prefillMs: number;
5084
+ decodeMs: number;
5085
+ totalMs: number;
5086
+ tokensPerSecond: number;
5087
+ realTimeFactor: number;
5088
+ /**
5089
+ * Streaming revisions increment whenever a rolling decode replaces
5090
+ * previously provisional text. Zero for one-shot transcription.
5091
+ */
5092
+ revision: number;
5093
+ isFinal: boolean;
5094
+ }
5095
+
5096
+ export interface Qwen3AsrStreamOptions {
5097
+ sampleRate?: number;
5098
+ prompt?: string;
5099
+ language?: string;
5100
+ /**
5101
+ * Maximum continuation tokens generated per revision (default 32).
5102
+ * Keeping this bounded is essential for realtime latency.
5103
+ */
5104
+ maxTokens?: number;
5105
+ /** Minimum newly buffered audio before a rolling decode (default 2 s). */
5106
+ chunkSeconds?: number;
5107
+ /**
5108
+ * Number of trailing raw decoder tokens rolled back and regenerated on
5109
+ * the next revision (default 5).
5110
+ */
5111
+ provisionalTokens?: number;
5112
+ /**
5113
+ * Number of initial chunks decoded without transcript conditioning
5114
+ * (default 2), matching Qwen's official streaming policy.
5115
+ */
5116
+ unfixedChunks?: number;
5117
+ }
5118
+
5119
+ export interface Qwen3AsrTranscribeOptions {
5120
+ /**
5121
+ * Sampling rate of `audio`. Inputs are resampled to the checkpoint's
5122
+ * native 16 kHz rate before feature extraction.
5123
+ */
5124
+ sampleRate?: number;
5125
+ /** Optional domain/context prompt placed in the system turn. */
5126
+ prompt?: string;
5127
+ /**
5128
+ * Language code (`en`, `zh`, ...) or canonical language name. Omit for
5129
+ * automatic language detection.
5130
+ */
5131
+ language?: string;
5132
+ /** Maximum number of newly generated tokens (default 256). */
5133
+ maxTokens?: number;
5134
+ }
5135
+
4254
5136
  /** Qwen3 model configuration */
4255
5137
  export interface Qwen3Config {
4256
5138
  vocabSize: number;
@@ -4419,6 +5301,54 @@ export interface SamplingConfig {
4419
5301
  */
4420
5302
  export declare function saveToXlsx(text: string, filePath: string): void;
4421
5303
 
5304
+ /**
5305
+ * Read-only NAPI/dashboard mirror. Counters use `f64`, matching the other
5306
+ * native metrics snapshots and avoiding BigInt round-trips in JavaScript.
5307
+ */
5308
+ export interface SchedulerStats {
5309
+ globalSteps: number;
5310
+ maxBatchOccupancy: number;
5311
+ decodeBatchOccupancyHist: Array<DecodeBatchOccupancyBucket>;
5312
+ fusedGreedyEpilogueSteps: number;
5313
+ admitted: number;
5314
+ completed: number;
5315
+ admissionDeferredBlocks: number;
5316
+ rowsAllocEvicted: number;
5317
+ blockCapacity: number;
5318
+ freeBlocks: number;
5319
+ reclaimableBlocks: number;
5320
+ allocatedBlocks: number;
5321
+ watermarkBlocks: number;
5322
+ reservedBlocks: number;
5323
+ memoryCapacityBytes: number;
5324
+ memoryWatermarkBytes: number;
5325
+ reservedBlockBytes: number;
5326
+ reservedStateBytes: number;
5327
+ admissionDeferredState: number;
5328
+ ssdRestoreWaiting: number;
5329
+ ssdRestoreBytes: number;
5330
+ ssdRestoreWaitMs: number;
5331
+ preemptions: number;
5332
+ preemptionsRecompute: number;
5333
+ preemptionsSsd: number;
5334
+ }
5335
+
5336
+ /**
5337
+ * Teacher-force `model_path` over the token ids cached in `cache_dir` and
5338
+ * report its NLL, perplexity, top-1 agreement and KL against the teacher.
5339
+ *
5340
+ * The candidate is refused when it cannot answer for the cached rows: a
5341
+ * different `model_type`, a different tokenizer, or a different vocabulary
5342
+ * width. Score reads its token ids FROM THE CACHE, so a tokenizer mismatch
5343
+ * would otherwise report a finite, plausible number measured on the wrong
5344
+ * text.
5345
+ */
5346
+ export declare function scoreAgainstTeacher(
5347
+ modelPath: string,
5348
+ cacheDir: string,
5349
+ logitChunk: number,
5350
+ ): Promise<EvalReport>;
5351
+
4422
5352
  /** Enable or disable profiling globally. */
4423
5353
  export declare function setProfilingEnabled(enabled: boolean): void;
4424
5354