@mlx-node/lm 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -153,10 +153,10 @@ Or set `MLX_PROFILE_DECODE=1` to auto-enable and write a report on exit.
153
153
  | `loadModel()` | Auto-detect and load any supported model from disk |
154
154
  | `loadSession()` | `loadModel()` + `new ChatSession(model)` in one step |
155
155
  | `ChatSession<M>` | Multi-turn chat wrapper — `send()`, `sendStream()`, `sendToolResult()`, `reset()` |
156
- | `Qwen3Model` | Qwen3 inference — `generate()`, paged attention, speculative decoding |
157
- | `Qwen35Model` | Qwen3.5 Dense — `generate()` with compiled C++ forward |
158
- | `Qwen35MoeModel` | Qwen3.5 MoE — `generate()` with compiled C++ forward and expert routing |
159
- | `Gemma4Model` | Gemma4 inference — `generate()` |
156
+ | `Qwen3Model` | Qwen3 inference — `generate()` and paged attention |
157
+ | `Qwen35Model` | Qwen3.5 Dense — compiled forward, VLM, paged attention, native MTP |
158
+ | `Qwen35MoeModel` | Qwen3.5 MoE — compiled forward, expert routing, paged attention, native MTP |
159
+ | `Gemma4Model` | Gemma4 inference — multimodal generation and optional external-draft speculation |
160
160
  | `Lfm2Model` | LFM2.5 hybrid conv+attention inference — `generate()` |
161
161
 
162
162
  ### Streaming Types
@@ -218,13 +218,13 @@ function createToolDefinition(
218
218
 
219
219
  Every generative model wrapper exposes the same `ChatSession<M>` surface — `send()`, `sendStream()`, and `sendToolResult()` all work against any of the models below.
220
220
 
221
- | Model | `generate()` | `ChatSession` | Training | Notes |
222
- | ------------- | :----------: | :-----------: | :------: | ------------------------------------- |
223
- | Qwen3 | Yes | Yes | GRPO/SFT | Paged attention, speculative decoding |
224
- | Qwen3.5 Dense | Yes | Yes | GRPO/SFT | Compiled C++ forward, VLM variant |
225
- | Qwen3.5 MoE | Yes | Yes | GRPO/SFT | Compiled C++ forward, expert routing |
226
- | Gemma4 | Yes | Yes | No | Streaming chat via session |
227
- | LFM2.5 | Yes | Yes | No | Hybrid conv + attention architecture |
221
+ | Model | `generate()` | `ChatSession` | Training | Notes |
222
+ | ------------- | :----------: | :-----------: | :------: | ------------------------------------ |
223
+ | Qwen3 | Yes | Yes | GRPO/SFT | Paged attention |
224
+ | Qwen3.5 Dense | Yes | Yes | GRPO/SFT | Compiled forward, VLM, native MTP |
225
+ | Qwen3.5 MoE | Yes | Yes | GRPO/SFT | Expert routing, paged cache, MTP |
226
+ | Gemma4 | Yes | Yes | No | Multimodal, optional external draft |
227
+ | LFM2.5 | Yes | Yes | No | Hybrid conv + attention architecture |
228
228
 
229
229
  ## Performance
230
230
 
@@ -1,90 +1,28 @@
1
+ import type { ChatConfig, ChatMessage, ChatResult, ToolDefinition } from '@mlx-node/core';
2
+ import type { ChatStreamEvent } from './stream.js';
1
3
  /**
2
- * Generic server-side chat session wrapper.
3
- *
4
- * `ChatSession<M>` is the cross-model chat-session wrapper. It works
5
- * against any model that exposes the uniform chat-session NAPI
6
- * surface `chatSessionStart`,
7
- * `chatSessionContinue`, `chatSessionContinueTool`, and their
8
- * streaming variants plus `resetCaches`. See `SessionCapableModel`
9
- * below.
10
- *
11
- * Design notes:
12
- *
13
- * - The session tracks its own `ChatMessage[]` history on the
14
- * TypeScript side. In the common text-continue case the history
15
- * is only appended to and never read back — each `send()` on
16
- * turn >= 1 issues a cheap `chatSessionContinue` delta against
17
- * the live KV cache. The history is kept purely so the
18
- * image-change mid-session path can call `chatSessionStart` with
19
- * the full rebuilt history for a clean re-prefill.
20
- *
21
- * - An image hash (`lastImagesKey`) tracks the images bound to the
22
- * current cache. A `send()` call whose image set has changed
23
- * (different bytes or different ordering) triggers a full
24
- * restart: `resetCaches()` → push the new user message (with
25
- * images) to history → `chatSessionStart(history)`.
26
- *
27
- * - Text-only `send()` on turn >= 1 takes the cheap delta path.
28
- *
29
- * - `sendToolResult` always dispatches `chatSessionContinueTool`,
30
- * since tool turns never change image state. The session enforces
31
- * a strict unresolved-ok-tool-call contract at runtime, driven by
32
- * `unresolvedOkToolCallCount` (derived from `ChatResult.toolCalls`
33
- * after each turn via `countOkToolCalls` /
34
- * `computeTrailingAssistantUnresolvedToolCallCount`):
35
- *
36
- * * `null` — the trailing assistant turn has no outstanding ok
37
- * tool call. Plain `send()` / `sendStream()` are the only
38
- * valid entry points; `sendToolResult*()` throws because
39
- * there is nothing for the result to resolve.
40
- * * `1` — exactly one outstanding ok tool call. Plain `send()` /
41
- * `sendStream()` throw (they would orphan the call);
42
- * `sendToolResult*()` is the sole valid forward step and
43
- * dispatches the tool result through the native session.
44
- * * `>1` — a multi-tool-call fan-out that the chat-session API
45
- * cannot progress incrementally (each `sendToolResult*` would
46
- * re-open the assistant turn and weave new replies between
47
- * the sibling results). Both `send()` / `sendStream()` and
48
- * `sendToolResult*()` throw. The only valid recovery is
49
- * `reset()` or `primeHistory()` + `startFromHistory*()` with
50
- * a fully-resolved conversation — there is no "advance past
51
- * the broken turn" path. This mirrors the native ChatML delta
52
- * format which would otherwise silently corrupt multi-call
53
- * conversations.
54
- *
55
- * - `sawFinal` gates `turnCount` advance on the streaming path, so
56
- * the session refuses to advance when the stream throws
57
- * mid-decode or yields a final chunk with
58
- * `finishReason: 'error'`.
59
- *
60
- * - The `inFlight` guard rejects concurrent `send()` /
61
- * `sendStream()` calls at the class level. The native side
62
- * serializes cache mutation on a single worker thread, so a
63
- * second in-flight call would race the first's cache-save step.
64
- *
65
- * - **Cold-restart primitives.** `primeHistory()` plus
66
- * `startFromHistory()` / `startFromHistoryStream()` let a caller
67
- * seed a fresh session with an externally-reconstructed history
68
- * (e.g. a server `ResponseStore` chain) and replay it through the
69
- * native `chatSessionStart` path without going through `send()`.
70
- * These are intended for server-side `SessionRegistry` cache-miss
71
- * cold-start; normal usage stays on `send` / `sendStream` /
72
- * `sendToolResult` / `reset`.
73
- *
74
- * ## Typical usage
75
- *
76
- * ```typescript
77
- * import { Qwen35Model, ChatSession } from '@mlx-node/lm';
78
- *
79
- * const model = await Qwen35Model.load('./models/qwen3.5-0.8b');
80
- * const session = new ChatSession(model, { system: 'Be concise.' });
81
- * const r1 = await session.send('Say hi in one word.');
82
- * const r2 = await session.send('Another word?');
83
- * await session.reset();
84
- * ```
4
+ * Stable, provider-neutral error raised before native inference when a
5
+ * rendered prompt cannot fit in the model's physically available hot KV
6
+ * window. The marker is intentionally the canonical string recognized by
7
+ * pi's overflow recovery, so managed agent sessions compact and retry while
8
+ * stateless HTTP callers receive a clean request error instead of a native
9
+ * `BlockAllocator exhausted` failure.
85
10
  */
86
- import type { ChatConfig, ChatMessage, ChatResult } from '@mlx-node/core';
87
- import type { ChatStreamEvent } from './stream.js';
11
+ export declare class ContextCapacityError extends Error {
12
+ readonly promptTokens: number;
13
+ readonly effectiveWindowTokens: number;
14
+ readonly code = "context_length_exceeded";
15
+ constructor(promptTokens: number, effectiveWindowTokens: number);
16
+ }
17
+ /** Recognize both the typed JS preflight and the native hard backstop. */
18
+ export declare function isContextCapacityError(error: unknown): boolean;
19
+ /** Physical and trained context limits captured by a native model at load. */
20
+ export interface SessionContextLimits {
21
+ trainedWindowTokens: number;
22
+ effectiveWindowTokens: number;
23
+ pagedBlockCapacity: number;
24
+ pagedBlockSize: number;
25
+ }
88
26
  /**
89
27
  * Structural interface matched by every generative model wrapper
90
28
  * (`Qwen35Model`, `Qwen35MoeModel`, `Lfm2Model`, `Gemma4Model`,
@@ -95,9 +33,38 @@ import type { ChatStreamEvent } from './stream.js';
95
33
  * fully structural.
96
34
  */
97
35
  export interface SessionCapableModel {
36
+ /**
37
+ * Optional non-generating chat-template tokenizer. Exposed by
38
+ * wrappers that can count prompt tokens without running inference
39
+ * (used by Anthropic `/v1/messages/count_tokens`).
40
+ */
41
+ applyChatTemplate?(messages: ChatMessage[], addGenerationPrompt?: boolean | null, tools?: ToolDefinition[] | null, enableThinking?: boolean | null): Promise<Uint32Array> | Uint32Array;
42
+ /**
43
+ * Optional model-native planner for prompt formats whose media placeholders
44
+ * expand after chat-template rendering. It returns the exact token length
45
+ * that inference will prefill, without mutating model/session state.
46
+ *
47
+ * Qwen3.5 dense/MoE implement this with their loaded image processor. Models
48
+ * without post-template expansion omit it and retain raw template counting.
49
+ */
50
+ expandedPromptTokenCount?(promptTokens: Uint32Array, messages: ChatMessage[]): Promise<number> | number;
51
+ /**
52
+ * Optional synchronous load-time snapshot of the model's usable context.
53
+ * Qwen3.5 dense/MoE expose this when adaptive paged-cache sizing is active.
54
+ */
55
+ contextLimits?(): SessionContextLimits;
56
+ /**
57
+ * Whether this loaded model instance has a complete image-input path.
58
+ *
59
+ * Optional so text-only and older wrappers continue to satisfy the
60
+ * structural contract. Supporting native wrappers snapshot this value after
61
+ * load, once the vision encoder/processor and any required cache backend are
62
+ * known to be available.
63
+ */
64
+ supportsImages?(): boolean;
98
65
  chatSessionStart(messages: ChatMessage[], config?: ChatConfig | null): Promise<ChatResult>;
99
- chatSessionContinue(userMessage: string, images: Uint8Array[] | null, config?: ChatConfig | null): Promise<ChatResult>;
100
- chatSessionContinueTool(toolCallId: string, content: string, config?: ChatConfig | null): Promise<ChatResult>;
66
+ chatSessionContinue(userMessage: string, images: Uint8Array[] | null, audio: Uint8Array[] | null, config?: ChatConfig | null): Promise<ChatResult>;
67
+ chatSessionContinueTool(toolCallId: string, content: string, config?: ChatConfig | null, isError?: boolean | null): Promise<ChatResult>;
101
68
  /**
102
69
  * The optional `signal` parameter on every streaming entry point is
103
70
  * plumbed into the `_runChatStream` fast-abort path in the wrapper
@@ -108,9 +75,128 @@ export interface SessionCapableModel {
108
75
  * callers (the common direct-use path) just omit it.
109
76
  */
110
77
  chatStreamSessionStart(messages: ChatMessage[], config?: ChatConfig | null, signal?: AbortSignal): AsyncGenerator<ChatStreamEvent>;
111
- chatStreamSessionContinue(userMessage: string, images: Uint8Array[] | null, config?: ChatConfig | null, signal?: AbortSignal): AsyncGenerator<ChatStreamEvent>;
112
- chatStreamSessionContinueTool(toolCallId: string, content: string, config?: ChatConfig | null, signal?: AbortSignal): AsyncGenerator<ChatStreamEvent>;
78
+ chatStreamSessionContinue(userMessage: string, images: Uint8Array[] | null, audio: Uint8Array[] | null, config?: ChatConfig | null, signal?: AbortSignal): AsyncGenerator<ChatStreamEvent>;
79
+ chatStreamSessionContinueTool(toolCallId: string, content: string, config?: ChatConfig | null, signal?: AbortSignal, isError?: boolean | null): AsyncGenerator<ChatStreamEvent>;
113
80
  resetCaches(): void;
81
+ /**
82
+ * Whether the underlying native model has the block-paged KV cache
83
+ * adapter (`PagedKVCacheAdapter` + `BlockAllocator` + `LayerKVPool`)
84
+ * active.
85
+ *
86
+ * `true` iff the adapter was successfully constructed at load time
87
+ * (driven by the per-model `use_block_paged_cache` config flag, which
88
+ * defaults to ON for Qwen3 + LFM2 after parity verification and OFF
89
+ * for Gemma4 + Qwen3.5 + Qwen3.5 MoE pending parity validation; also
90
+ * always `false` on Qwen3.5 VLM checkpoints where
91
+ * `set_vision_encoder` rejects when the adapter is populated).
92
+ *
93
+ * When `true`, the native cache reuses SYS blocks across requests via
94
+ * content-addressing in the `BlockAllocator`'s prefix-hash table —
95
+ * the JS-side warm slot in
96
+ * `SessionRegistry.getOrCreateWarmAny(requestedSystem)` becomes
97
+ * redundant for stateless `/v1/messages` traffic. The server
98
+ * endpoint reads this getter to decide whether to allocate a fresh
99
+ * `ChatSession` per request (paged-active) or to lease the warm slot
100
+ * (non-paged); see `packages/server/src/endpoints/messages.ts`.
101
+ *
102
+ * Optional on the structural interface so models that pre-date the
103
+ * NAPI getter (notably `QianfanOCRModel` from `@mlx-node/vlm`, which
104
+ * has no paged-adapter wiring) still satisfy the type contract — a
105
+ * missing getter is treated as `false` (not paged) by callers.
106
+ * Surfaced as a synchronous method on every native wrapper that DOES
107
+ * support paged so the routing decision in the server doesn't need a
108
+ * model-thread roundtrip per request — the value is captured at load
109
+ * time and never changes for a given model instance.
110
+ */
111
+ hasBlockPagedCache?(): boolean;
112
+ /**
113
+ * MTP: whether the underlying native model can run speculative
114
+ * decoding. Surfaced by `Qwen3_5Model` / `Qwen3_5MoeModel` (an MTP
115
+ * head shipped in the checkpoint and loaded by persistence) and by
116
+ * `Gemma4Model` (an external draft model — DSpark or Google gemma-4
117
+ * assistant, auto-detected from the draft's config.json — attached
118
+ * via `loadModel` / `loadSession` `draftModelPath`; NOT in-checkpoint
119
+ * MTP heads); all other native wrappers omit the method, in
120
+ * which case callers treat a missing getter as `false` (no MTP).
121
+ *
122
+ * When `true`, {@link ChatSession#mergeConfig} auto-defaults the
123
+ * per-request `enableMtp` flag to `true` — the speculative-decode
124
+ * path takes over unless the caller explicitly opts out by passing
125
+ * `enableMtp: false` in their `ChatConfig` overlay. When `false`
126
+ * (or the method is missing), `enableMtp` is left untouched.
127
+ *
128
+ * Synchronous on every supporting wrapper so the auto-default check
129
+ * doesn't need a model-thread roundtrip per call — the value is
130
+ * captured at load time and never changes for a given model
131
+ * instance.
132
+ *
133
+ * ## Companion `ChatConfig` knobs (only meaningful when `enableMtp` is on)
134
+ *
135
+ * Two related `ChatConfig` fields tune the speculative-decode loop.
136
+ * They are forwarded verbatim to the native side via
137
+ * {@link SendOptions.config} (per-call overlay) or
138
+ * {@link ChatSessionOptions.defaultConfig} (session default), and
139
+ * `mergeConfig` shallow-merges per-call over per-session so an
140
+ * explicit per-send value always wins over the session default for
141
+ * the same field.
142
+ *
143
+ * - **`mtpDepth`** — pins the MTP draft depth per speculative cycle.
144
+ * On Qwen3.5 native MTP heads it is clamped to `[1, 5]` by the
145
+ * verify FFI contract, and when unset native code currently pins
146
+ * depth 1. Setting `mtpDepth` explicitly pins that value unless
147
+ * the caller also passes `mtpAdaptiveDepth: true` to opt into
148
+ * adaptive depth with the supplied maximum/seed. Gemma4 external
149
+ * drafts resolve the field per draft variant instead — see the
150
+ * Gemma4 section below.
151
+ * - **`mtpAdaptiveDepth`** — toggles the adaptive depth policy.
152
+ * Defaults to OFF for native MTP and assistants (Gemma4 DSpark has the
153
+ * family override documented below). When ON, the native-MTP default
154
+ * mode runs a 5-state machine
155
+ * (`Explore` → `Full` → {`NeighborProbe` | `Reduced` → `Probe`})
156
+ * with per-depth EMA tracking of
157
+ * `accepted_tokens / cycle_wall_ns` and picks the depth that
158
+ * maximizes that rate (DFlash-style, EMA decay α=0.3, drop-back
159
+ * threshold 0.75). `MLX_MTP_ADAPTIVE_DEPTH_MODE=expected-value`
160
+ * instead uses the MTPLX-style intra-cycle expected-value gate; by
161
+ * default it stops at its base depth, with deeper expansion kept
162
+ * research-only behind `MLX_MTP_EV_ALLOW_DEEPEN=1`.
163
+ * An explicit `false` always wins, pinning the chosen `mtpDepth` for
164
+ * every cycle. When `enableMtp` is false (or the model has no MTP
165
+ * head) the field is ignored.
166
+ *
167
+ * The defaults for both `mtpDepth` and `mtpAdaptiveDepth` are
168
+ * applied on the native side (see
169
+ * `crates/mlx-core/src/models/qwen3_5/chat_common.rs` MTP runtime
170
+ * flag inventory), so omitting them from `defaultConfig` /
171
+ * `SendOptions.config` is the recommended path for callers that
172
+ * just want speculative decoding "on with sensible defaults".
173
+ *
174
+ * ## Gemma4 external drafts (`draftModelPath`)
175
+ *
176
+ * Gemma4 reinterprets the knobs per draft variant (resolved in
177
+ * `gemma4/model.rs` `resolve_params`, always from the RAW config
178
+ * value — the engine's central `[1, 5]` clamp is an MTP-head
179
+ * contract that does not apply to external drafts):
180
+ *
181
+ * - **DSpark**: with both knobs unset, full draft blocks (the
182
+ * checkpoint's block size — 7 tokens on
183
+ * `dspark_gemma4_12b_block7`) run behind a short per-turn measurement
184
+ * against target-only AR. If DSpark loses on the current host/context,
185
+ * that turn permanently falls back to exact target-only decoding. An
186
+ * insufficiently long generation budget preserves the fixed-block path.
187
+ * An explicit `mtpDepth` acts as a CAP on the block (clamped to
188
+ * `[1, blockSize]`) and pins it unless `mtpAdaptiveDepth: true` opts the
189
+ * guard back in. Explicit `mtpAdaptiveDepth: false` disables the guard.
190
+ * - **Assistant** (Google `gemma-4-*-it-assistant`): chained AR
191
+ * drafting has no checkpoint-pinned block size — an unset
192
+ * `mtpDepth` drafts 3 tokens per cycle (`ASSISTANT_DEFAULT_DEPTH`,
193
+ * a quality/latency tradeoff, not a checkpoint contract), and an
194
+ * explicit `mtpDepth` clamps to `[1, 8]` (`ASSISTANT_MAX_DEPTH`).
195
+ *
196
+ * `mtpAdaptiveDepth` remains ignored for the assistant variant. Qwen3.5
197
+ * native-MTP semantics above are unchanged.
198
+ */
199
+ hasMtpWeights?(): boolean;
114
200
  }
115
201
  /** Per-call options for {@link ChatSession#send} / `sendStream`. */
116
202
  export interface SendOptions {
@@ -120,10 +206,22 @@ export interface SendOptions {
120
206
  * session forcibly restarts via `chatSessionStart`.
121
207
  */
122
208
  images?: Uint8Array[];
209
+ /**
210
+ * Optional audio bytes (encoded WAV) attached to this user turn. When
211
+ * the audio set differs from the session's current `lastAudioKey`, the
212
+ * session forcibly restarts via `chatSessionStart` (mirrors `images`).
213
+ * Only the unified Gemma 4 audio checkpoint consumes this.
214
+ */
215
+ audio?: Uint8Array[];
123
216
  /**
124
217
  * Per-call `ChatConfig` overlay applied on top of the session's
125
218
  * `defaultConfig`. `reuseCache` is always forced on regardless of
126
- * what the caller passes.
219
+ * what the caller passes. The overlay is shallow-merged on top of
220
+ * the session default, so per-call values always win over per-session
221
+ * values for the same field — including the speculative-decode
222
+ * knobs `enableMtp`, `mtpDepth`, and `mtpAdaptiveDepth`. See
223
+ * {@link SessionCapableModel.hasMtpWeights} for the full MTP knob
224
+ * surface and default-resolution rules.
127
225
  */
128
226
  config?: ChatConfig;
129
227
  /**
@@ -155,7 +253,12 @@ export interface ChatSessionOptions {
155
253
  /**
156
254
  * Default `ChatConfig` applied to every `send()` / `sendStream()`
157
255
  * / `sendToolResult()` call. Per-call config is shallow-merged on
158
- * top of this, and `reuseCache` is forced on.
256
+ * top of this, and `reuseCache` is forced on. Speculative-decode
257
+ * knobs (`enableMtp`, `mtpDepth`, `mtpAdaptiveDepth`) can be parked
258
+ * here as session-wide defaults and overridden per call via
259
+ * {@link SendOptions.config}; see
260
+ * {@link SessionCapableModel.hasMtpWeights} for the MTP knob surface
261
+ * and default-resolution rules.
159
262
  */
160
263
  defaultConfig?: ChatConfig;
161
264
  }
@@ -180,13 +283,22 @@ export declare class ChatSession<M extends SessionCapableModel = SessionCapableM
180
283
  private history;
181
284
  /**
182
285
  * Hex-encoded byte-identity key of the image set currently bound
183
- * to the server's KV cache (FNV-1a 64-bit; see `computeImagesKey`).
286
+ * to the server's KV cache (SHA-256; see `computeImagesKey`).
184
287
  * `null` when no images are cached. A `send()` whose new key
185
288
  * differs triggers a full `chatSessionStart` restart.
186
289
  */
187
290
  private lastImagesKey;
291
+ /**
292
+ * Hex-encoded byte-identity key of the audio set currently bound to the
293
+ * server's KV cache (see {@link computeAudioKey}). `null` when no audio is
294
+ * cached. A `send()` whose new key differs triggers a full
295
+ * `chatSessionStart` restart — the audio counterpart of `lastImagesKey`.
296
+ */
297
+ private lastAudioKey;
188
298
  private turnCount;
189
299
  private inFlight;
300
+ /** A failed/abandoned native delta must be followed by a full replay. */
301
+ private needsFullReplay;
190
302
  /**
191
303
  * Count of `ok` tool calls emitted by the prior assistant turn, or
192
304
  * `null` when the prior turn produced none. Gates every continuation
@@ -216,6 +328,32 @@ export declare class ChatSession<M extends SessionCapableModel = SessionCapableM
216
328
  get turns(): number;
217
329
  /** Whether the session currently has images bound to its cache. */
218
330
  get hasImages(): boolean;
331
+ /** Load-time physical context snapshot, when exposed by the model. */
332
+ contextLimits(): SessionContextLimits | undefined;
333
+ /** Authoritative image-input capability of the loaded native model. */
334
+ supportsImages(): boolean;
335
+ /**
336
+ * Render and validate a complete message list against the model's physical
337
+ * context window without starting inference or mutating session/native cache
338
+ * state.
339
+ *
340
+ * HTTP streaming callers use this before committing SSE headers so an
341
+ * oversized prompt can still receive a protocol-shaped 400 response without
342
+ * delaying those headers until image processing, prefill, or the first
343
+ * generated token. The returned config carries the same output-budget clamp
344
+ * applied by the send entry points; those entry points intentionally repeat
345
+ * the check against their own authoritative history before native dispatch.
346
+ */
347
+ preflightContextCapacity(messages: readonly ChatMessage[], config?: ChatConfig): Promise<ChatConfig>;
348
+ /**
349
+ * Capacity-preflight one pending user/tool message against this session's
350
+ * preserved history without starting inference or mutating cache state.
351
+ *
352
+ * This is the exact counterpart of the delta `send*` paths. It matters for
353
+ * server-side prompt-cache hits where the HTTP request contains only the new
354
+ * message while the leased ChatSession owns the earlier conversation.
355
+ */
356
+ preflightPendingContextCapacity(pending: ChatMessage, config?: ChatConfig): Promise<ChatConfig>;
219
357
  /**
220
358
  * Count of `ok` tool calls from the most recent assistant turn, or
221
359
  * `null` when the trailing turn produced none. Non-null means the
@@ -268,16 +406,61 @@ export declare class ChatSession<M extends SessionCapableModel = SessionCapableM
268
406
  * hit this must tighten the prompt / tool spec or reset the
269
407
  * session.
270
408
  *
409
+ * `isError` is the structured tool-error signal. When `true`, the
410
+ * native renderer prepends a short, model-facing error marker to
411
+ * `content` inside the wire-format tool block so the model
412
+ * receives a clear text-level cue that the tool result represents
413
+ * a failure. The structured field is stored verbatim on the
414
+ * appended `{ role: 'tool', ... }` history entry so cold-replay
415
+ * (image-change restart, `startFromHistory*`, server-side
416
+ * `SessionRegistry` cache-miss rebuild) re-renders the marker
417
+ * consistently with the live turn. Defaults to `undefined` (no
418
+ * marker). Pass through verbatim — we do NOT infer error from
419
+ * `content`.
420
+ *
271
421
  * Appends a `{ role: 'tool', ... }` message to history on success.
272
422
  */
273
423
  sendToolResult(toolCallId: string, content: string, opts?: {
424
+ isError?: boolean;
274
425
  config?: ChatConfig;
275
426
  }): Promise<ChatResult>;
276
- /** Streaming variant of {@link ChatSession#sendToolResult}. */
427
+ /**
428
+ * Cold-replay a tool result through the start path: re-render the
429
+ * full preserved history (including the prior media turn and the
430
+ * unresolved tool-call assistant turn) plus this tool message. Used
431
+ * when the native session is cold (turnCount===0 — e.g. after an
432
+ * interrupted media-held replay rolled the cache back) and by the
433
+ * media-held rejection catch. `mediaChanged=true` forces a
434
+ * resetCaches so the prefill always starts from a guaranteed-clean
435
+ * cache; `isFirstTurn=false` because a tool result always follows a
436
+ * prior tool-call turn.
437
+ */
438
+ private replayToolResultThroughStartPath;
439
+ /**
440
+ * Streaming variant of {@link ChatSession#sendToolResult}.
441
+ *
442
+ * `isError` mirrors the non-streaming entry point — when `true`,
443
+ * the native renderer prepends a short, model-facing error marker
444
+ * to `content` inside the wire-format tool block. The structured
445
+ * field is stored verbatim on the appended `{ role: 'tool', ... }`
446
+ * history entry so cold-replay re-renders the marker consistently
447
+ * with the live streaming turn.
448
+ */
277
449
  sendToolResultStream(toolCallId: string, content: string, opts?: {
450
+ isError?: boolean;
278
451
  config?: ChatConfig;
279
452
  signal?: AbortSignal;
280
453
  }): AsyncGenerator<ChatStreamEvent>;
454
+ /**
455
+ * Streaming counterpart of {@link replayToolResultThroughStartPath}:
456
+ * cold-replay a tool result through the start stream. Used by the
457
+ * turn-0 precheck and the media-held rejection catch in
458
+ * {@link sendToolResultStream}. The start stream owns the history
459
+ * push, turnCount increment, and media-key rehydration; callers keep
460
+ * `delegated`/early-return semantics so the commit `finally` stays
461
+ * off.
462
+ */
463
+ private replayToolResultThroughStartStreamPath;
281
464
  /**
282
465
  * Reset the session state.
283
466
  *
@@ -285,6 +468,23 @@ export declare class ChatSession<M extends SessionCapableModel = SessionCapableM
285
468
  * image key, and turn counter so the next `send()` goes through
286
469
  * `chatSessionStart` again.
287
470
  *
471
+ * This is a full wipe — safe default for public callers. It always
472
+ * calls `model.resetCaches()`, which is the ONLY behavior exposed
473
+ * on the public API because the underlying `SessionCapableModel`
474
+ * is shared across every `ChatSession` lifetime via the native
475
+ * `ModelRegistry`: a partial wipe that leaves the shared native
476
+ * KV cache intact would leak a previous (unrelated) request's
477
+ * cached prefix into the next `chat_session_start_sync` call. The
478
+ * server-side warm-lease replay path (where preserving the native
479
+ * cache is correct) uses its own server-private helper gated by
480
+ * the `SessionRegistry` HIT signal — the only authoritative proof
481
+ * that the native cache genuinely belongs to this chain. That
482
+ * helper lives inside `@mlx-node/server`, never touches the
483
+ * `@mlx-node/lm` export map, and is not reachable from downstream
484
+ * consumers. Public consumers of `@mlx-node/lm` have no such HIT
485
+ * signal, so the public API intentionally offers only the full-wipe
486
+ * option.
487
+ *
288
488
  * Returns `Promise<void>` for an async-friendly signature even
289
489
  * though `resetCaches()` is currently synchronous.
290
490
  */
@@ -390,8 +590,31 @@ export declare class ChatSession<M extends SessionCapableModel = SessionCapableM
390
590
  * The session path is a session-reuse operation by construction —
391
591
  * `reuseCache: false` on the continue path would wipe the very
392
592
  * cache the delta depends on.
593
+ *
594
+ * MTP auto-default: if neither `defaultConfig` nor `overlay`
595
+ * sets `enableMtp` AND the underlying model exposes
596
+ * `hasMtpWeights()` returning `true`, set `enableMtp = true` so the
597
+ * speculative-decode path runs out of the box on MTP-capable
598
+ * checkpoints. An explicit `false` from either source wins (the
599
+ * undefined-check below preserves it). This duck-typed check also
600
+ * covers Gemma4 with an external draft attached — DSpark or Google
601
+ * assistant (`hasMtpWeights()` reports the external draft there,
602
+ * not in-checkpoint MTP heads).
393
603
  */
394
604
  private mergeConfig;
605
+ /**
606
+ * Render the exact full prompt and constrain generation to the physical KV
607
+ * window before native code allocates a block. Models that do not expose
608
+ * both the tokenizer seam and a load-time context snapshot retain their
609
+ * existing behavior.
610
+ *
611
+ * The returned config is a copy only when `maxNewTokens` needs clamping.
612
+ * An omitted output budget stays omitted when the native default fits; it is
613
+ * made explicit only when the remaining window is smaller than that default.
614
+ */
615
+ private constrainToContextCapacity;
616
+ /** Full history that a pending user/tool turn would render, without mutation. */
617
+ private historyWithPending;
395
618
  /**
396
619
  * Shared start-path logic for `send()`. Handles both the turn-0
397
620
  * first-ever-send case and the image-change mid-session restart
@@ -400,8 +623,24 @@ export declare class ChatSession<M extends SessionCapableModel = SessionCapableM
400
623
  * image set.
401
624
  */
402
625
  private runStartPath;
626
+ /**
627
+ * Core of {@link runStartPath} that takes a PRE-BUILT pending
628
+ * `ChatMessage` (user or tool) instead of building a user message
629
+ * itself. The cold-restart catch in `sendToolResult()` replays the
630
+ * conversation through this core with a pending `{ role: 'tool', ... }`
631
+ * message so the tool-result turn is re-rendered against the full
632
+ * history without duplicating the start-path bookkeeping.
633
+ */
634
+ private runStartPathWithMessage;
403
635
  /** Streaming counterpart to {@link runStartPath}. */
404
636
  private runStartStreamPath;
637
+ /**
638
+ * Streaming counterpart to {@link runStartPathWithMessage}: replays
639
+ * through the cold start stream from a PRE-BUILT pending
640
+ * `ChatMessage`. The cold-restart catch in `sendToolResultStream()`
641
+ * delegates here with a pending `{ role: 'tool', ... }` message.
642
+ */
643
+ private runStartStreamPathWithMessage;
405
644
  /**
406
645
  * Shared pre-start bookkeeping for both `send()` and `sendStream()`:
407
646
  *
@@ -418,16 +657,22 @@ export declare class ChatSession<M extends SessionCapableModel = SessionCapableM
418
657
  * - On a fresh / reset history, re-inject the system prompt.
419
658
  */
420
659
  private prepareStartPath;
421
- /** Build a user `ChatMessage` with or without attached images. */
660
+ /** Build a user `ChatMessage` with or without attached images/audio. */
422
661
  private buildUserMessage;
423
662
  /**
424
663
  * Walk the history backward to find the most recent user message
425
- * with images and return its FNV-1a key. Used by
664
+ * with images and return its SHA-256 key. Used by
426
665
  * {@link startFromHistory} and {@link startFromHistoryStream} to
427
666
  * hydrate `lastImagesKey` after a cold replay, so subsequent delta
428
667
  * continues correctly detect image changes.
429
668
  */
430
669
  private computeTrailingImagesKey;
670
+ /**
671
+ * Audio counterpart of {@link computeTrailingImagesKey}: walk history
672
+ * backward to the most recent user message carrying audio and return its
673
+ * SHA-256 key, so a cold replay hydrates `lastAudioKey` correctly.
674
+ */
675
+ private computeTrailingAudioKey;
431
676
  /**
432
677
  * Derive the post-prime value of `unresolvedOkToolCallCount` from
433
678
  * the primed history. Walks backward to the most recent assistant
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../src/chat-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../src/chat-session.ts"],"names":[],"mappings":"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"}