@mlx-bun/inference 0.0.0-stage → 1.0.0

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 (467) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1475 -2
  3. package/THIRD_PARTY_NOTICES.md +3404 -0
  4. package/dist/native/libmlx_bun_ane.dylib +0 -0
  5. package/dist/native/libmlx_bun_expert_io.dylib +0 -0
  6. package/dist/native/mlx-bun-frame-extract +0 -0
  7. package/examples/fit-model.ts +25 -0
  8. package/examples/qwen3-forward.ts +42 -0
  9. package/examples/qwen3-generate.ts +28 -0
  10. package/examples/trellis-expand.ts +23 -0
  11. package/package.json +129 -4
  12. package/src/adapters/available.ts +110 -0
  13. package/src/adapters/index.ts +3 -0
  14. package/src/adapters/manager.ts +316 -0
  15. package/src/artifacts/auxiliary-files.ts +45 -0
  16. package/src/artifacts/config-dialects.ts +94 -0
  17. package/src/artifacts/config.ts +341 -0
  18. package/src/artifacts/draft-vocabulary.ts +30 -0
  19. package/src/artifacts/expert-offload-build.ts +75 -0
  20. package/src/artifacts/expert-offload.ts +89 -0
  21. package/src/artifacts/experts/index.ts +3 -0
  22. package/src/artifacts/experts/io.ts +386 -0
  23. package/src/artifacts/experts/residency.ts +1134 -0
  24. package/src/artifacts/experts/usage.ts +415 -0
  25. package/src/artifacts/fingerprint.ts +44 -0
  26. package/src/artifacts/glm52/container.ts +305 -0
  27. package/src/artifacts/glm52/expert-layout.ts +249 -0
  28. package/src/artifacts/glm52/index.ts +7 -0
  29. package/src/artifacts/glm52/kernel-layout.ts +124 -0
  30. package/src/artifacts/glm52/layout.ts +152 -0
  31. package/src/artifacts/glm52/memory.ts +500 -0
  32. package/src/artifacts/glm52/resident-weights.ts +135 -0
  33. package/src/artifacts/glm52/weights.ts +503 -0
  34. package/src/artifacts/glm52-config.ts +262 -0
  35. package/src/artifacts/identity.ts +94 -0
  36. package/src/artifacts/index.ts +15 -0
  37. package/src/artifacts/mmap.ts +90 -0
  38. package/src/artifacts/safetensors-writer.ts +249 -0
  39. package/src/artifacts/safetensors.ts +164 -0
  40. package/src/artifacts/turboquant-fold.ts +42 -0
  41. package/src/artifacts/weight-audit.ts +43 -0
  42. package/src/artifacts/weights.ts +255 -0
  43. package/src/contracts/index.ts +2 -0
  44. package/src/contracts/mlx/attention.ts +8 -0
  45. package/src/contracts/mlx/cache.ts +510 -0
  46. package/src/contracts/mlx/checkpoint.ts +10 -0
  47. package/src/contracts/mlx/draft-checkpoint.ts +14 -0
  48. package/src/contracts/mlx/draft-projection.ts +27 -0
  49. package/src/contracts/mlx/draft-target.ts +84 -0
  50. package/src/contracts/mlx/drafter.ts +176 -0
  51. package/src/contracts/mlx/forward-work.ts +23 -0
  52. package/src/contracts/mlx/glm52-weights.ts +25 -0
  53. package/src/contracts/mlx/graph.ts +309 -0
  54. package/src/contracts/mlx/head.ts +6 -0
  55. package/src/contracts/mlx/index.ts +15 -0
  56. package/src/contracts/mlx/kv-codec.ts +9 -0
  57. package/src/contracts/mlx/media.ts +113 -0
  58. package/src/contracts/mlx/positions.ts +16 -0
  59. package/src/contracts/mlx/row-table.ts +2 -0
  60. package/src/contracts/mlx/trainable.ts +103 -0
  61. package/src/contracts/mlx/whisper.ts +96 -0
  62. package/src/contracts/portable/composition.ts +106 -0
  63. package/src/contracts/portable/denoising.ts +17 -0
  64. package/src/contracts/portable/execution.ts +79 -0
  65. package/src/contracts/portable/generation.ts +103 -0
  66. package/src/contracts/portable/graph.ts +80 -0
  67. package/src/contracts/portable/index.ts +15 -0
  68. package/src/contracts/portable/memory-plan.ts +26 -0
  69. package/src/contracts/portable/object-cache.ts +8 -0
  70. package/src/contracts/portable/prefill.ts +63 -0
  71. package/src/contracts/portable/prefix-cache.ts +33 -0
  72. package/src/contracts/portable/prompt.ts +2 -0
  73. package/src/contracts/portable/resources.ts +25 -0
  74. package/src/contracts/portable/rollback.ts +7 -0
  75. package/src/contracts/portable/sampling.ts +44 -0
  76. package/src/contracts/portable/scheduling.ts +54 -0
  77. package/src/contracts/portable/token-delivery.ts +4 -0
  78. package/src/contracts/portable/tsconfig.json +14 -0
  79. package/src/embeddings/index.ts +1 -0
  80. package/src/embeddings/text.ts +85 -0
  81. package/src/execution/admission.ts +59 -0
  82. package/src/execution/batch-group.ts +1240 -0
  83. package/src/execution/batch-types.ts +225 -0
  84. package/src/execution/cancellation.ts +38 -0
  85. package/src/execution/continuation-request.ts +45 -0
  86. package/src/execution/continuation-types.ts +10 -0
  87. package/src/execution/coordinator.ts +70 -0
  88. package/src/execution/denoising-group.ts +180 -0
  89. package/src/execution/engine.ts +56 -0
  90. package/src/execution/fill-group.ts +505 -0
  91. package/src/execution/fit.ts +184 -0
  92. package/src/execution/gateway-binding.ts +178 -0
  93. package/src/execution/grammar-group.ts +224 -0
  94. package/src/execution/index.ts +18 -0
  95. package/src/execution/methods.ts +75 -0
  96. package/src/execution/mixed-iteration.ts +96 -0
  97. package/src/execution/plan.ts +65 -0
  98. package/src/execution/prefill-cohort.ts +100 -0
  99. package/src/execution/prefill-rows.ts +263 -0
  100. package/src/execution/request-policy.ts +19 -0
  101. package/src/execution/row-sampling.ts +49 -0
  102. package/src/execution/scheduler.ts +92 -0
  103. package/src/execution/session.ts +247 -0
  104. package/src/execution/speculative-group.ts +797 -0
  105. package/src/execution/tasks.ts +44 -0
  106. package/src/generation/autoregressive.ts +840 -0
  107. package/src/generation/bindings/autoregressive.ts +104 -0
  108. package/src/generation/bindings/denoising.ts +60 -0
  109. package/src/generation/bindings/prefill-policy.ts +36 -0
  110. package/src/generation/checkpoint-identity.ts +60 -0
  111. package/src/generation/denoising.ts +85 -0
  112. package/src/generation/diffusion.ts +583 -0
  113. package/src/generation/fill/echo-index.ts +188 -0
  114. package/src/generation/fill/index.ts +3 -0
  115. package/src/generation/fill/proposal.ts +69 -0
  116. package/src/generation/fill/schema-rows.ts +506 -0
  117. package/src/generation/fill/session.ts +464 -0
  118. package/src/generation/fill/tool-boundary.ts +103 -0
  119. package/src/generation/fill-append.ts +58 -0
  120. package/src/generation/generate.ts +44 -0
  121. package/src/generation/grammar-step.ts +39 -0
  122. package/src/generation/index.ts +14 -0
  123. package/src/generation/phase-dispatch.ts +115 -0
  124. package/src/generation/prefill.ts +33 -0
  125. package/src/generation/result.ts +49 -0
  126. package/src/generation/scopes.ts +157 -0
  127. package/src/generation/speculative/acceptance.ts +41 -0
  128. package/src/generation/speculative/adaptive-draft-gate.ts +166 -0
  129. package/src/generation/speculative/bindings/assistant-rows.ts +102 -0
  130. package/src/generation/speculative/bindings/autoregressive-rows.ts +124 -0
  131. package/src/generation/speculative/bindings/binding.ts +106 -0
  132. package/src/generation/speculative/bindings/deepspec-rows.ts +33 -0
  133. package/src/generation/speculative/bindings/draft-target.ts +10 -0
  134. package/src/generation/speculative/bindings/glm52-mtp-rows.ts +128 -0
  135. package/src/generation/speculative/bindings/projected-context-rows.ts +78 -0
  136. package/src/generation/speculative/bindings/projected-draft-rows.ts +95 -0
  137. package/src/generation/speculative/bindings/qwen-mtp-rows.ts +336 -0
  138. package/src/generation/speculative/bindings/two-model-rows.ts +63 -0
  139. package/src/generation/speculative/cache-identity.ts +16 -0
  140. package/src/generation/speculative/draft-kind.ts +149 -0
  141. package/src/generation/speculative/draft-policy.ts +41 -0
  142. package/src/generation/speculative/draft-registry.ts +118 -0
  143. package/src/generation/speculative/draft-vocab.ts +110 -0
  144. package/src/generation/speculative/index.ts +17 -0
  145. package/src/generation/speculative/output.ts +49 -0
  146. package/src/generation/speculative/round.ts +307 -0
  147. package/src/generation/speculative/source.ts +144 -0
  148. package/src/generation/speculative/sources/assistant-source.ts +64 -0
  149. package/src/generation/speculative/sources/deepspec-source.ts +70 -0
  150. package/src/generation/speculative/sources/dflash-source.ts +84 -0
  151. package/src/generation/speculative/sources/dflash2-source.ts +86 -0
  152. package/src/generation/speculative/sources/glm52-mtp-source.ts +66 -0
  153. package/src/generation/speculative/sources/ngram-source.ts +165 -0
  154. package/src/generation/speculative/sources/qwen-mtp-source.ts +154 -0
  155. package/src/generation/speculative/sources/two-model.ts +75 -0
  156. package/src/generation/types.ts +194 -0
  157. package/src/index.ts +20 -0
  158. package/src/input/audio/audiotoolbox.ts +112 -0
  159. package/src/input/audio/decode.ts +133 -0
  160. package/src/input/audio/features.ts +202 -0
  161. package/src/input/audio/index.ts +6 -0
  162. package/src/input/audio/transcode.ts +67 -0
  163. package/src/input/audio/whisper-mel.ts +185 -0
  164. package/src/input/audio/whisper-tokenizer.ts +238 -0
  165. package/src/input/chat-template.ts +389 -0
  166. package/src/input/index.ts +6 -0
  167. package/src/input/media-fetch.ts +439 -0
  168. package/src/input/packed-mixed.ts +43 -0
  169. package/src/input/special-tokens.ts +75 -0
  170. package/src/input/token-groups.ts +49 -0
  171. package/src/input/tokenizer.ts +336 -0
  172. package/src/input/tool-call.ts +689 -0
  173. package/src/input/vision/index.ts +3 -0
  174. package/src/input/vision/preprocess.ts +247 -0
  175. package/src/input/vision/prompt.ts +398 -0
  176. package/src/input/vision/qwen3vl-preprocess.ts +409 -0
  177. package/src/input/vision/qwen3vl-prompt.ts +237 -0
  178. package/src/input/vision/video-frames.ts +100 -0
  179. package/src/kernels/ane/fill.ts +101 -0
  180. package/src/kernels/ane/linear.ts +416 -0
  181. package/src/kernels/attention/flash.ts +694 -0
  182. package/src/kernels/attention/kvq4-decode.ts +155 -0
  183. package/src/kernels/attention/masks.ts +40 -0
  184. package/src/kernels/attention/multi-query.ts +193 -0
  185. package/src/kernels/attention/paged.ts +130 -0
  186. package/src/kernels/delta/gated.ts +306 -0
  187. package/src/kernels/delta/index.ts +3 -0
  188. package/src/kernels/delta/silu-rms-heads.ts +69 -0
  189. package/src/kernels/delta/state.ts +74 -0
  190. package/src/kernels/gated-rms-norm.ts +64 -0
  191. package/src/kernels/glm52/layout.ts +37 -0
  192. package/src/kernels/glm52/streamed-experts.ts +360 -0
  193. package/src/kernels/logits.ts +38 -0
  194. package/src/kernels/quantization/affine-row.ts +154 -0
  195. package/src/kernels/quantization/affine-rows.ts +36 -0
  196. package/src/kernels/quantization/affine-split-mma.ts +144 -0
  197. package/src/kernels/quantization/affine3-mma.ts +117 -0
  198. package/src/kernels/quantization/affine3-rows.ts +103 -0
  199. package/src/kernels/quantization/affine4-mma.ts +113 -0
  200. package/src/kernels/quantization/affine4-rows.ts +102 -0
  201. package/src/kernels/residual-rms-norm.ts +65 -0
  202. package/src/kernels/sampling/index.ts +2 -0
  203. package/src/kernels/sampling/normalized-argmax.ts +116 -0
  204. package/src/kernels/sampling/token-bitmask.ts +52 -0
  205. package/src/kernels/softcap.ts +35 -0
  206. package/src/kernels/trellis/codebook.ts +123 -0
  207. package/src/kernels/trellis/down-codebook.ts +184 -0
  208. package/src/kernels/trellis/down-factored.ts +180 -0
  209. package/src/kernels/trellis/down-k3-interleaved-factored.ts +146 -0
  210. package/src/kernels/trellis/down-mma-wide.ts +195 -0
  211. package/src/kernels/trellis/down-mma.ts +145 -0
  212. package/src/kernels/trellis/expand.ts +42 -0
  213. package/src/kernels/trellis/gate-up-codebook-mma.ts +141 -0
  214. package/src/kernels/trellis/gate-up-codebook.ts +137 -0
  215. package/src/kernels/trellis/gate-up-factored.ts +197 -0
  216. package/src/kernels/trellis/gate-up-mma-wide.ts +147 -0
  217. package/src/kernels/trellis/gate-up-mma.ts +148 -0
  218. package/src/kernels/trellis/gate-up.ts +248 -0
  219. package/src/kernels/trellis/geometry.ts +22 -0
  220. package/src/kernels/trellis/index.ts +103 -0
  221. package/src/kernels/trellis/launch.ts +12 -0
  222. package/src/kernels/trellis/mixed-gate-up-factored.ts +119 -0
  223. package/src/kernels/trellis/mixed-gate-up.ts +146 -0
  224. package/src/kernels/trellis/qualified.ts +34 -0
  225. package/src/kernels/trellis/reduce.ts +150 -0
  226. package/src/kernels/trellis/scatter.ts +407 -0
  227. package/src/kernels/trellis/splitk-prefill.ts +152 -0
  228. package/src/kernels/trellis/tiled-prefill.ts +131 -0
  229. package/src/kernels/trellis/vector-expand.ts +58 -0
  230. package/src/kernels/trellis/wide-prefill.ts +89 -0
  231. package/src/kernels/turboquant/decode.ts +82 -0
  232. package/src/kernels/turboquant/index.ts +5 -0
  233. package/src/kernels/turboquant/inverse.ts +122 -0
  234. package/src/kernels/turboquant/ops.ts +860 -0
  235. package/src/kernels/turboquant/signs.ts +130 -0
  236. package/src/kernels/turboquant/tables.ts +124 -0
  237. package/src/layers/affine-verify-linear.ts +75 -0
  238. package/src/layers/ane-prefill-split.ts +283 -0
  239. package/src/layers/compiled-normalization.ts +41 -0
  240. package/src/layers/delta-heads.ts +23 -0
  241. package/src/layers/dense-embedding.ts +29 -0
  242. package/src/layers/dense-linear.ts +32 -0
  243. package/src/layers/dequantized-linear.ts +72 -0
  244. package/src/layers/folded-attention.ts +42 -0
  245. package/src/layers/geglu.ts +130 -0
  246. package/src/layers/helpers.ts +7 -0
  247. package/src/layers/index.ts +36 -0
  248. package/src/layers/kv4-decode-attention.ts +15 -0
  249. package/src/layers/layer-norm.ts +24 -0
  250. package/src/layers/loading.ts +92 -0
  251. package/src/layers/lora.ts +150 -0
  252. package/src/layers/normalization.ts +9 -0
  253. package/src/layers/prefix-layout.ts +33 -0
  254. package/src/layers/quantized-append-attention.ts +32 -0
  255. package/src/layers/quantized-attention.ts +353 -0
  256. package/src/layers/quantized-embedding.ts +39 -0
  257. package/src/layers/quantized-linear.ts +137 -0
  258. package/src/layers/quantized-switch-linear.ts +37 -0
  259. package/src/layers/qwen-append.ts +12 -0
  260. package/src/layers/qwen-mrope.ts +238 -0
  261. package/src/layers/rope-2d.ts +110 -0
  262. package/src/layers/rope.ts +389 -0
  263. package/src/layers/swiglu.ts +23 -0
  264. package/src/layers/trellis-codebook-down.ts +52 -0
  265. package/src/layers/trellis-codebook-gate-up.ts +42 -0
  266. package/src/layers/trellis-down.ts +117 -0
  267. package/src/layers/trellis-gate-up.ts +71 -0
  268. package/src/layers/trellis-linear.ts +211 -0
  269. package/src/layers/trellis-prompt.ts +102 -0
  270. package/src/layers/trellis-reduce-gate-up.ts +73 -0
  271. package/src/layers/trellis-scatter-down.ts +98 -0
  272. package/src/models/ane-install.ts +74 -0
  273. package/src/models/audio/conformer.ts +656 -0
  274. package/src/models/cache-composition.ts +44 -0
  275. package/src/models/capabilities.ts +89 -0
  276. package/src/models/chat-template.ts +10 -0
  277. package/src/models/composition.ts +107 -0
  278. package/src/models/diffusion-gemma/experts.ts +59 -0
  279. package/src/models/diffusion-gemma/family.ts +21 -0
  280. package/src/models/diffusion-gemma/model.ts +900 -0
  281. package/src/models/diffusion-gemma/vision.ts +549 -0
  282. package/src/models/drafter-loaders.ts +49 -0
  283. package/src/models/drafters.ts +39 -0
  284. package/src/models/factory.ts +351 -0
  285. package/src/models/families.ts +70 -0
  286. package/src/models/family.ts +125 -0
  287. package/src/models/gemma4/assistant-target.ts +46 -0
  288. package/src/models/gemma4/assistant.ts +327 -0
  289. package/src/models/gemma4/blocks.ts +755 -0
  290. package/src/models/gemma4/compiled-decode.ts +452 -0
  291. package/src/models/gemma4/family.ts +39 -0
  292. package/src/models/gemma4/gemma4-12b.ts +677 -0
  293. package/src/models/gemma4/gemma4-26b.ts +544 -0
  294. package/src/models/gemma4/gemma4-e4b.ts +599 -0
  295. package/src/models/gemma4/graphs.ts +147 -0
  296. package/src/models/gemma4/media.ts +88 -0
  297. package/src/models/gemma4/model.ts +860 -0
  298. package/src/models/gemma4/serving-blocks.ts +72 -0
  299. package/src/models/gemma4/trainable.ts +186 -0
  300. package/src/models/gemma4/written-blocks.ts +232 -0
  301. package/src/models/gemma4/written-forward.ts +159 -0
  302. package/src/models/gemma4/written-input.ts +29 -0
  303. package/src/models/glm52/atlas.ts +507 -0
  304. package/src/models/glm52/coupling.ts +388 -0
  305. package/src/models/glm52/dsa.ts +601 -0
  306. package/src/models/glm52/family.ts +20 -0
  307. package/src/models/glm52/mla.ts +812 -0
  308. package/src/models/glm52/model.ts +1127 -0
  309. package/src/models/glm52/moe.ts +223 -0
  310. package/src/models/glm52/mtp.ts +60 -0
  311. package/src/models/glm52/pilot.ts +537 -0
  312. package/src/models/glm52/reference.ts +445 -0
  313. package/src/models/glm52/residency.ts +557 -0
  314. package/src/models/glm52/streamed-experts.ts +447 -0
  315. package/src/models/graph.ts +59 -0
  316. package/src/models/implementation.ts +230 -0
  317. package/src/models/index.ts +15 -0
  318. package/src/models/media-input.ts +15 -0
  319. package/src/models/memory-plan.ts +39 -0
  320. package/src/models/minicpm5/family.ts +29 -0
  321. package/src/models/minicpm5/model.ts +394 -0
  322. package/src/models/minicpm5/trainable.ts +90 -0
  323. package/src/models/profile.ts +337 -0
  324. package/src/models/qwen/blocks.ts +658 -0
  325. package/src/models/qwen/checkpoint.ts +190 -0
  326. package/src/models/qwen/families.ts +57 -0
  327. package/src/models/qwen/media-input.ts +161 -0
  328. package/src/models/qwen/mtp.ts +101 -0
  329. package/src/models/qwen/qwen3-moe.ts +355 -0
  330. package/src/models/qwen/qwen3.ts +323 -0
  331. package/src/models/qwen/qwen38-27b-trellis-m1max.ts +1532 -0
  332. package/src/models/qwen/qwen38-27b-trellis-m4pro.ts +1092 -0
  333. package/src/models/qwen/qwen3_5.ts +433 -0
  334. package/src/models/qwen/written-layers.ts +285 -0
  335. package/src/models/row-table.ts +1 -0
  336. package/src/models/runtime.ts +73 -0
  337. package/src/models/speculative/deepspec-artifact.ts +10 -0
  338. package/src/models/speculative/deepspec.ts +744 -0
  339. package/src/models/speculative/dflash.ts +553 -0
  340. package/src/models/speculative/dflash2-artifact.ts +9 -0
  341. package/src/models/speculative/dflash2-operations.ts +1 -0
  342. package/src/models/speculative/dflash2.ts +576 -0
  343. package/src/models/speculative/loader.ts +29 -0
  344. package/src/models/support.ts +79 -0
  345. package/src/models/universal/archs.ts +365 -0
  346. package/src/models/universal/blocks.ts +479 -0
  347. package/src/models/universal/dense.ts +255 -0
  348. package/src/models/universal/family.ts +17 -0
  349. package/src/models/vision/qwen3vl.ts +566 -0
  350. package/src/models/vision/siglip.ts +520 -0
  351. package/src/models/vision/unified.ts +176 -0
  352. package/src/models/whisper/family.ts +19 -0
  353. package/src/models/whisper/fast.ts +734 -0
  354. package/src/models/whisper/model.ts +430 -0
  355. package/src/runtime/compiled-trace.ts +16 -0
  356. package/src/runtime/config.ts +77 -0
  357. package/src/runtime/expert-trace.ts +71 -0
  358. package/src/runtime/graph-forward.ts +65 -0
  359. package/src/runtime/integers.ts +6 -0
  360. package/src/runtime/native.ts +16 -0
  361. package/src/runtime/resources.ts +53 -0
  362. package/src/runtime/row-operations.ts +42 -0
  363. package/src/runtime/trace.ts +161 -0
  364. package/src/sampling/curve.ts +122 -0
  365. package/src/sampling/draft.ts +55 -0
  366. package/src/sampling/extras.ts +45 -0
  367. package/src/sampling/filters.ts +134 -0
  368. package/src/sampling/grammar.ts +630 -0
  369. package/src/sampling/hlg.ts +290 -0
  370. package/src/sampling/index.ts +9 -0
  371. package/src/sampling/processors.ts +142 -0
  372. package/src/sampling/sampler.ts +120 -0
  373. package/src/sampling/step.ts +343 -0
  374. package/src/sampling/types.ts +161 -0
  375. package/src/sampling/window-filters.ts +46 -0
  376. package/src/scoring/decisions.ts +96 -0
  377. package/src/scoring/full-sequence.ts +103 -0
  378. package/src/scoring/index.ts +9 -0
  379. package/src/scoring/kl.ts +29 -0
  380. package/src/scoring/perplexity.ts +165 -0
  381. package/src/scoring/response-logps.ts +65 -0
  382. package/src/state/affine-attention.ts +180 -0
  383. package/src/state/attachment.ts +68 -0
  384. package/src/state/attention-read.ts +215 -0
  385. package/src/state/batched-kv.ts +294 -0
  386. package/src/state/batched-mask.ts +445 -0
  387. package/src/state/batched-quant.ts +389 -0
  388. package/src/state/batched-quantized-kv.ts +209 -0
  389. package/src/state/batched-rotating-quant.ts +457 -0
  390. package/src/state/batched-rotating-state.ts +149 -0
  391. package/src/state/batched-rotating.ts +430 -0
  392. package/src/state/batched-row-storage.ts +179 -0
  393. package/src/state/batched-ssm.ts +54 -0
  394. package/src/state/batched-turboquant-kv.ts +144 -0
  395. package/src/state/bf16-first-kv.ts +663 -0
  396. package/src/state/cache-service.ts +592 -0
  397. package/src/state/capabilities.ts +65 -0
  398. package/src/state/checkpoint.ts +46 -0
  399. package/src/state/continuation-persistence.ts +126 -0
  400. package/src/state/decode-step-inputs.ts +31 -0
  401. package/src/state/decoded-kv-donor.ts +12 -0
  402. package/src/state/delayed-quantized-kv.ts +141 -0
  403. package/src/state/delayed-rotating-quantized-kv.ts +178 -0
  404. package/src/state/delayed-turboquant-kv.ts +123 -0
  405. package/src/state/durability.ts +214 -0
  406. package/src/state/encoder-cache.ts +26 -0
  407. package/src/state/full-kv-row-append.ts +33 -0
  408. package/src/state/full-kv-row-donor.ts +54 -0
  409. package/src/state/full-prefill-padding.ts +56 -0
  410. package/src/state/full-prefill-row.ts +112 -0
  411. package/src/state/full-transitioning-kv-rows.ts +70 -0
  412. package/src/state/glm52-cache.ts +783 -0
  413. package/src/state/grouped-heads-kv4-cache.ts +26 -0
  414. package/src/state/index.ts +38 -0
  415. package/src/state/kv-attention-view.ts +77 -0
  416. package/src/state/kv-budget.ts +14 -0
  417. package/src/state/kv-scheme.ts +315 -0
  418. package/src/state/kv-storage.ts +57 -0
  419. package/src/state/kv-tensor-rows.ts +212 -0
  420. package/src/state/kv.ts +324 -0
  421. package/src/state/kv4-head256-cache.ts +46 -0
  422. package/src/state/latent-legos.ts +895 -0
  423. package/src/state/layout.ts +277 -0
  424. package/src/state/leases.ts +26 -0
  425. package/src/state/paged/cache.ts +689 -0
  426. package/src/state/paged/codec.ts +36 -0
  427. package/src/state/paged/rows.ts +223 -0
  428. package/src/state/persistence-types.ts +173 -0
  429. package/src/state/persistence-worker.ts +83 -0
  430. package/src/state/persistence.ts +1036 -0
  431. package/src/state/persistence.worker.d.ts +3 -0
  432. package/src/state/persistence.worker.js +264 -0
  433. package/src/state/prefix-cache.ts +685 -0
  434. package/src/state/quantized-kv.ts +369 -0
  435. package/src/state/quantized-tensor.ts +26 -0
  436. package/src/state/request-policy.ts +48 -0
  437. package/src/state/retention-policy.ts +37 -0
  438. package/src/state/rollback.ts +131 -0
  439. package/src/state/rotating-kv-donor.ts +35 -0
  440. package/src/state/rotating-kv-layout.ts +341 -0
  441. package/src/state/rotating-kv.ts +529 -0
  442. package/src/state/rotating-quantized-kv.ts +616 -0
  443. package/src/state/rotating-row-transaction.ts +35 -0
  444. package/src/state/rows.ts +104 -0
  445. package/src/state/softcap-attention.ts +118 -0
  446. package/src/state/speculative/glm52-mtp-state.ts +38 -0
  447. package/src/state/speculative/qwen-mtp-state.ts +34 -0
  448. package/src/state/speculative-rotating-kv.ts +113 -0
  449. package/src/state/ssd-cache.ts +434 -0
  450. package/src/state/ssm-prefill-padding.ts +39 -0
  451. package/src/state/ssm.ts +422 -0
  452. package/src/state/target-layout.ts +7 -0
  453. package/src/state/tiered-prefix-cache.ts +45 -0
  454. package/src/state/training-cache.ts +300 -0
  455. package/src/state/transitioning-kv-rows.ts +267 -0
  456. package/src/state/turboquant-attention.ts +97 -0
  457. package/src/state/turboquant-codec.ts +90 -0
  458. package/src/state/turboquant-kv.ts +442 -0
  459. package/src/state/views.ts +26 -0
  460. package/src/transcription/index.ts +3 -0
  461. package/src/transcription/silero-vad.ts +379 -0
  462. package/src/transcription/whisper/decode.ts +773 -0
  463. package/src/transcription/whisper/format.ts +74 -0
  464. package/src/transcription/whisper/index.ts +4 -0
  465. package/src/transcription/whisper/timing.ts +274 -0
  466. package/src/transcription/whisper/transcribe.ts +394 -0
  467. package/src/transcription/whisper/types.ts +22 -0
@@ -0,0 +1,510 @@
1
+ import type { MlxArray } from "@mlx-bun/mlx/array";
2
+ import type { Dtype } from "@mlx-bun/mlx/ffi";
3
+ import type * as ops from "@mlx-bun/mlx/ops";
4
+
5
+ export type MaskMode = "" | "causal";
6
+ export interface Mask {
7
+ mode: MaskMode | "array";
8
+ arr: MlxArray | null;
9
+ /** True when `arr` is exactly the bottom-right-aligned causal matrix
10
+ * (offset continuation, no window) — the case where mlx-lm would
11
+ * have handed the string "causal" instead. Only these array masks
12
+ * are eligible for the fused tiled SDPA: the optiq wrapper falls
13
+ * back to unfused on every array mask, and window/bidir masks must
14
+ * match that to stay scenario-bit-exact. */
15
+ causalEquivalent?: boolean;
16
+ }
17
+
18
+ /** Fetched KV handed from a donor layer to its sharers (and to the
19
+ * speculative drafter). Owned by forwardLayers for the pass.
20
+ * `offsetArr` is an owned pre-write position snapshot. Donor and sharing
21
+ * attention layers keep it until the fetched KV is released, even if the
22
+ * cache advances or replaces its borrowed row-position array. */
23
+ export type SharedKv =
24
+ | { kind: "plain"; keys: MlxArray; values: MlxArray; offset: number;
25
+ offsetArr?: MlxArray;
26
+ /** TurboQuant deferred-V: `values` are still in the rotated (FWHT)
27
+ * domain — every consumer must un-rotate its attention OUTPUT
28
+ * (tq.unrotateValues) after sdpa. Attention is linear in V, so the
29
+ * result is the same decode, just transformed once per query row
30
+ * instead of once per cached token. */
31
+ vRotated?: boolean;
32
+ restoreValues?: (output: MlxArray) => MlxArray }
33
+ | { kind: "quant"; keys: ops.QuantizedTensor; values: ops.QuantizedTensor;
34
+ offset: number; groupSize: number; bits: number; offsetArr?: MlxArray }
35
+ | { kind: "view"; attention: KvAttentionView; offset: number; offsetArr?: MlxArray };
36
+
37
+ /** Attention over a cache's positions as of one phase-named call. The cache
38
+ * picked the kernel when it was built and builds the mask from the offsets, row
39
+ * layout and sliding window it owns. The caller supplies only queries.
40
+ *
41
+ * The read owns its tensor handles. It stays valid after later appends, trims,
42
+ * row changes or disposal of its cache. Holding it across the cache's next
43
+ * append can make that append copy storage instead of writing in place, so
44
+ * dispose it when the forward that made it is done. It does no attention work
45
+ * before `attend`; disposing an unused read only releases handles. */
46
+ export interface AttentionRead {
47
+ /** Queries `q` [B, Hq, L, Dk] (borrowed, positional encoding applied, Hq a
48
+ * multiple of the stored Hkv) to an owned output [B, Hq, L, Dv]. `B` and `L`
49
+ * must match the call that made this read, and the result is defined only for
50
+ * that call's phase. Callable any number of times: layers that share a
51
+ * donor's keys and values attend the donor's read with their own queries. */
52
+ attend(q: MlxArray, scale: number): MlxArray;
53
+ /** Releases the read's handles. Call exactly once. */
54
+ dispose(): void;
55
+ }
56
+
57
+ /** A key/value cache that owns its attention read. Each method appends the new
58
+ * keys and values for the phase it names and returns the read for that phase.
59
+ * The caller never sees stored keys or values and never chooses a kernel. The
60
+ * storage (bf16, affine, TurboQuant, paged, rotating, delayed quantization) is
61
+ * not visible here: the loader composes the cache, and the cache fixes one
62
+ * kernel per read at construction.
63
+ *
64
+ * Every append has these obligations:
65
+ * - `k` [B, Hkv, L, Dk] and `v` [B, Hkv, L, Dv] are borrowed. The caller
66
+ * disposes them after the call returns. `k` already carries the positional
67
+ * encoding for the positions it occupies, which start at each row's offset.
68
+ * - Rows follow this cache's row layout: one row for a single-sequence cache;
69
+ * `rowOffsets`, `leftPad` and padding prepared through `PaddedPrefillCache`
70
+ * for a batchable layout. Each row appends at its own offset, and the offsets
71
+ * have advanced by `L` when the call returns.
72
+ * - The caller owns the returned read (see {@link AttentionRead}).
73
+ * - The method name is the phase. A cache never infers the phase from `L`, from
74
+ * the query shape or from a mask. Calling a method outside its phase gives an
75
+ * undefined result. */
76
+ export interface AttentionCache extends Cache {
77
+ /** Decode: one new position per row (`L` = 1). Each row's query sees that
78
+ * row's valid stored positions up to and including the one just appended,
79
+ * limited to the cache's sliding window. */
80
+ appendDecode(k: MlxArray, v: MlxArray): AttentionRead;
81
+ /** Window: `L` new positions per row, causal within the window, for prefill
82
+ * chunks, prefill tails and speculative verify windows. Query `i` of a row
83
+ * sees the row's earlier valid positions and window positions `0..i`, limited
84
+ * to the cache's sliding window. Left padding and prepared prefill padding are
85
+ * never visible. Outputs at padded query positions are unspecified and the
86
+ * caller ignores them. To append context without attending, make this call
87
+ * and dispose the read unused. */
88
+ appendWindow(k: MlxArray, v: MlxArray): AttentionRead;
89
+ }
90
+
91
+ /** A training pass's cache: it stores nothing and owns the positions its pass
92
+ * reads at, the uniform positions from its offset or, for a prefix-shared
93
+ * concat [prompt; chosen; rejected], each response restarted after the prompt. */
94
+ export interface TrainingAttentionCache extends AttentionCache {
95
+ /** `x` [B, H, T, D] rotated at this pass's positions: `rope` rotates one
96
+ * contiguous block of positions from a scalar offset. The caller owns `x`. */
97
+ ropePositions(x: MlxArray, rope: (block: MlxArray, offset: number) => MlxArray): MlxArray;
98
+ }
99
+
100
+ /** A cache composed for committed-token appends (token fill), where every
101
+ * position of the span is already decided. */
102
+ export interface CommittedAttentionCache extends AttentionCache {
103
+ /** Committed span: `L` decided positions per row, causal within the span.
104
+ * Each query attends its own causal prefix with the arithmetic of a
105
+ * one-position read, so the span keeps the single-position reduction order
106
+ * the graph qualifies per KV format (`MlxKnownSpans`, read by `appendKnown`). This replaces the
107
+ * `independentPositions` flag. The only caller today runs one row with up to
108
+ * four positions. */
109
+ appendCommitted(k: MlxArray, v: MlxArray): AttentionRead;
110
+ }
111
+
112
+ /** A cache composed for prompts whose media tokens attend each other in both
113
+ * directions (Gemma 4 vision prefill). */
114
+ export interface BidirectionalAttentionCache extends AttentionCache {
115
+ /** Bidirectional window: the same as `appendWindow`, except that two
116
+ * positions both flagged in `bidirectional` see each other in either
117
+ * direction, regardless of order or the sliding window. `bidirectional` is a
118
+ * borrowed bool [L] that applies to every row. Defined only for the first
119
+ * window of a sequence (offset 0). */
120
+ appendBidirectional(k: MlxArray, v: MlxArray, bidirectional: MlxArray): AttentionRead;
121
+ }
122
+
123
+ /** A cache composed for an encoder that reads its whole prompt with no sliding
124
+ * window, its media tokens attending each other in both directions (the
125
+ * DiffusionGemma vision encoder, which reads every layer, sliding or full,
126
+ * through one mask over the whole prompt). */
127
+ export interface EncoderAttentionCache extends AttentionCache {
128
+ /** Encoder window: the first window of a sequence (offset 0), `L` new
129
+ * positions per row, stored as `appendWindow` stores them. Query `i` sees
130
+ * window positions `0..i`, and two positions both flagged in `bidirectional`
131
+ * see each other in either direction. The cache's sliding window does not
132
+ * limit this read: every query sees the whole window, whatever its length.
133
+ * (`appendBidirectional` is the read the sliding window does limit.)
134
+ * `bidirectional` is a borrowed bool [L] that applies to every row. */
135
+ appendEncoderWindow(k: MlxArray, v: MlxArray, bidirectional: MlxArray): AttentionRead;
136
+ }
137
+
138
+ /** A cache composed for block reads, where a block's queries attend the stored
139
+ * context plus the block's own keys and values without storing them
140
+ * (DiffusionGemma's canvas pass, the DFlash 2 drafter's block over its
141
+ * projected context). */
142
+ export interface BlockAttentionCache extends AttentionCache {
143
+ /** Block read: `k` [B, Hkv, L, Dk] and `v` [B, Hkv, L, Dv] are the block's
144
+ * keys and values, borrowed and not appended. Offsets do not move. Every
145
+ * query of a row sees that row's valid stored positions, limited to the
146
+ * cache's sliding window, and all `L` block positions. The read takes queries
147
+ * for exactly this block. */
148
+ readBlock(k: MlxArray, v: MlxArray): AttentionRead;
149
+ }
150
+
151
+ /** A gated DeltaNet block's heads for one recurrence call. */
152
+ export interface GatedDeltaHeads {
153
+ /** [B, S, Hk, Dk], normalized and scaled by the block. */
154
+ readonly q: MlxArray;
155
+ /** [B, S, Hk, Dk], normalized and scaled by the block. */
156
+ readonly k: MlxArray;
157
+ /** [B, S, Hv, Dv]. */
158
+ readonly v: MlxArray;
159
+ }
160
+
161
+ /** What a gated DeltaNet block lends its recurrent cache for one call: the
162
+ * layer's recurrence weights and the block's glue between the convolution and
163
+ * the recurrence. The block keeps its projections, norms and activations. The
164
+ * cache keeps the convolution state, the recurrent state and the kernels that
165
+ * update them. */
166
+ export interface GatedDeltaParameters {
167
+ /** Depthwise causal convolution weight [convDim, K, 1]. */
168
+ readonly convWeight: MlxArray;
169
+ /** Per-value-head decay logarithm (`A_log`) [Hv]. */
170
+ readonly aLog: MlxArray;
171
+ /** Per-value-head timestep bias [Hv]. */
172
+ readonly dtBias: MlxArray;
173
+ /** The block's glue: the activation of the convolution output, the split
174
+ * into q, k and v heads, and their norms and scaling. Pure. `convolved`
175
+ * [B, S, convDim] is the raw convolution output (before activation) and is
176
+ * borrowed. The cache owns and disposes the returned heads. The cache calls
177
+ * this once per recurrence call; a speculative round keeps the window's k and
178
+ * v for the rows a rollback retains. */
179
+ heads(convolved: MlxArray): GatedDeltaHeads;
180
+ }
181
+
182
+ /** Recurrent state for one gated DeltaNet layer. It owns its read the way
183
+ * {@link AttentionCache} does: the block hands over its projected inputs and
184
+ * receives the recurrence output. The cache zeroes padded positions, runs the
185
+ * causal convolution over its stored convolution state, keeps each row's
186
+ * convolution tail, runs the gated-delta recurrence with the kernels in
187
+ * `kernels/delta`, replaces both states and advances its offsets. A training
188
+ * cache runs the differentiable recurrence behind the same calls.
189
+ *
190
+ * Both calls have these obligations:
191
+ * - `qkv` [B, S, convDim] is the `in_proj_qkv` output before convolution, and
192
+ * `a`, `b` [B, S, Hv] are the raw `in_proj_a` and `in_proj_b` outputs. The
193
+ * call consumes all three: the cache disposes them, or keeps them for an
194
+ * armed speculative round. The caller must not use or dispose them after the
195
+ * call.
196
+ * - `layer` is borrowed and must stay valid until an armed speculative round
197
+ * resolves, because rollback replays through it.
198
+ * - The caller owns the output [B, S, Hv, Dv]. The block applies the output
199
+ * gate (`z`) and the output projection itself.
200
+ * - Inside an armed round (`specRoundBegin`), the call records the pre-call
201
+ * states and its inputs, so `specRoundRollback(keep)` restores and replays the
202
+ * accepted prefix inside the cache. At most one call per armed round.
203
+ * - Rows follow this cache's row layout, as for {@link AttentionCache}. The
204
+ * method name is the phase; a cache never infers it from `S`. */
205
+ export interface GatedDeltaCache extends Cache {
206
+ /** Decode: one new position per row (`S` = 1), with no prefill padding in
207
+ * effect. */
208
+ recurDecode(qkv: MlxArray, a: MlxArray, b: MlxArray, layer: GatedDeltaParameters): MlxArray;
209
+ /** Window: `S` positions per row, for prefill chunks and tails, speculative
210
+ * verify windows and committed spans. Padding prepared through
211
+ * `PaddedPrefillCache` holds: padded positions change neither state, each
212
+ * row's convolution tail ends at its last real position, and each row's offset
213
+ * advances by its real count. Outputs at padded positions are unspecified. */
214
+ recurWindow(qkv: MlxArray, a: MlxArray, b: MlxArray, layer: GatedDeltaParameters): MlxArray;
215
+ }
216
+
217
+ /** The compressed state of one latent attention layer after an append, as
218
+ * caller-owned views of every stored position in order (float32). The caller
219
+ * disposes all three. Rows follow the cache's row layout: right-justified, row
220
+ * `b`'s positions starting at `leftPad[b]`. */
221
+ export interface LatentAttentionState {
222
+ /** [B, T, kvLoraRank]: the normalized compressed content state. */
223
+ readonly latent: MlxArray;
224
+ /** [B, T, ropeHeadDim]: the decoupled RoPE key, already rotated. */
225
+ readonly rope: MlxArray;
226
+ /** [B, T, indexHeadDim]: the sparse-attention (DSA) index keys, on a cache
227
+ * composed to store them; null otherwise. */
228
+ readonly indexKeys: MlxArray | null;
229
+ }
230
+
231
+ /** State for one multi-head latent attention layer (GLM-5.2's MLA): it stores
232
+ * the checkpoint-native compressed state per position (the latent and the
233
+ * decoupled RoPE key, and on a sparse-attention layer the DSA index key), never
234
+ * per-head keys and values. The attention block projects its queries and that
235
+ * state, appends the state here and reads back everything stored, from which
236
+ * it reconstructs or absorbs keys and values itself (the same split as
237
+ * {@link GatedDeltaCache}: the block keeps its projections, the cache keeps the
238
+ * state and its row layout). A layer composed with DSA appends an index key
239
+ * with every position and reads the index keys stored before its append to
240
+ * select positions.
241
+ *
242
+ * Rows: one row for a single sequence; a batch keeps its rows right-justified
243
+ * along the sequence axis, `rowOffsets[b]` positions in row `b` starting at
244
+ * `leftPad[b]`. Inputs to an append are borrowed and float32. */
245
+ export interface LatentAttentionCache extends Cache {
246
+ readonly kvLoraRank: number;
247
+ readonly ropeHeadDim: number;
248
+ /** Rows in the layout, or null before the first append. */
249
+ readonly batchSize: number | null;
250
+ readonly rowOffsets: readonly number[];
251
+ readonly leftPad: readonly number[];
252
+ /** The index keys stored so far, [B, offset, indexHeadDim], owned by the
253
+ * caller; null when none are stored (a cache without DSA, or an empty one). */
254
+ storedIndexKeys(): MlxArray | null;
255
+ /** Appends `L` positions per row (`latent` [B, L, kvLoraRank], `rope`
256
+ * [B, L, ropeHeadDim], and `indexKeys` [B, L, indexHeadDim] exactly when the
257
+ * cache stores them), advancing every row by `L`, and returns the state as of
258
+ * this append. A rejected append leaves the cache unchanged. */
259
+ appendLatent(latent: MlxArray, rope: MlxArray, indexKeys: MlxArray | null): LatentAttentionState;
260
+ }
261
+
262
+ /** A captured numerical view supports multiple queries without appending KV
263
+ * again. It owns its tensor handles independently of later cache membership or
264
+ * precision changes. Query/mask inputs are borrowed; outputs are owned. */
265
+ export interface KvAttentionView {
266
+ /** Qualified committed spans retain the single-position reduction order. */
267
+ attend(q: MlxArray, scale: number, mask: Mask, independentPositions?: boolean): MlxArray;
268
+ dispose(): void;
269
+ }
270
+
271
+ /** Owned read-only planes with validity separate from physical padding. */
272
+ export interface KvDonorRows {
273
+ readonly keys: MlxArray;
274
+ readonly values: MlxArray;
275
+ readonly offsets: readonly number[];
276
+ readonly starts: readonly number[];
277
+ readonly ends: readonly number[];
278
+ }
279
+
280
+ /** Captured Q-only attention hides plain or encoded donor storage. */
281
+ export interface KvDonorAttention extends KvAttentionView {
282
+ readonly width: number;
283
+ readonly dtype: Dtype;
284
+ readonly offsets: readonly number[];
285
+ readonly starts: readonly number[];
286
+ readonly ends: readonly number[];
287
+ }
288
+
289
+ /** The row-layout half of a composition's KV scheme, over one request's layer
290
+ * caches: where its serial caches (the graph's composed legos) join row
291
+ * layouts. The legos convert themselves inside their own appends; nothing here
292
+ * converts a serial cache. */
293
+ export interface KvMaintenance {
294
+ /** Limit committed work at a pending precision transition. */
295
+ maxAppendTokens?(cache: readonly Cache[]): number;
296
+ /** Bind state requiring row-local maintenance before shared decode. */
297
+ prepareBatch?(cache: Cache[]): void;
298
+ /** Bind all precision policies before a prefill cohort owns row boundaries. */
299
+ preparePrefill?(cache: Cache[]): void;
300
+ }
301
+
302
+ /** The storage a composed cache holds and converts (the bf16-first KV legos a
303
+ * graph's `makeCache` builds for its composition's KV scheme). The row
304
+ * layouts, clones and saved files take the storage, never the lego; whoever
305
+ * hands storage back to serial use composes it with `over`. */
306
+ export interface ComposedStorage {
307
+ /** The storage held now, borrowed: bf16 before the transition, quantized or
308
+ * encoded after. */
309
+ storage(): Cache;
310
+ /** This lego's composition over `storage`, which the result owns: storage
311
+ * that already holds the conversion start converts before this returns, and
312
+ * quantized storage reads with this lego's kernels. */
313
+ over(storage: Cache): Cache;
314
+ /** Hands the storage held now to the caller and leaves this lego empty. */
315
+ release(): Cache;
316
+ }
317
+
318
+ export interface Cache {
319
+ /** Present on a cache that composes the storage it holds (see ComposedStorage). */
320
+ readonly composed?: ComposedStorage;
321
+ /** Maximum committed positions before this state changes precision. */
322
+ maxAppendTokens?(): number;
323
+ captureDonorRows?(): KvDonorRows;
324
+ captureDonorAttention?(): KvDonorAttention;
325
+ /** A preparation method commits each request's own precision boundary.
326
+ * Splitting a forward for a sibling must not move that boundary. */
327
+ readonly prefillMaintenance?: {
328
+ beginPrefill(): void;
329
+ commitPrefill(rows: readonly number[]): void;
330
+ endPrefill(): void;
331
+ };
332
+ /** Earliest prefix whose retained representation can resume generation.
333
+ * Irreversible transitions may preserve bytes while invalidating older
334
+ * precision boundaries. Reuse policy must not trim below this offset. */
335
+ minimumReusableOffset?: number;
336
+ offset: number;
337
+ /** Stable storage identity for compatibility guards and persistence.
338
+ * REQUIRED: every capability predicate (isPlainKvCache, isRotating*,
339
+ * packages/inference/src/state/persistence.ts codecs) is a string compare on
340
+ * this value, so a missing
341
+ * override used to fail OPEN into wrong routing (PRs #42/#43:
342
+ * BatchedRotatingCache shipped without one and batched joins dropped
343
+ * running rows). Wrappers report their own kind plus the inner kind. */
344
+ signature(): string;
345
+ /** Physical cache storage consumed by one additional token for one row.
346
+ * Recurrent caches return 0 because their state does not grow with the
347
+ * sequence. Optional for stateless/training adapters that are never
348
+ * admitted or persisted. */
349
+ bytesPerToken?(): number;
350
+ /** state() returned temporary views that the caller must release. */
351
+ readonly stateNeedsDispose?: boolean;
352
+ /** Compiled-decode trace adapters expose the RoPE offset as an int32
353
+ * array input here; real caches leave it unset (static int path). */
354
+ readonly ropeOffsetArr?: MlxArray;
355
+ state(): MlxArray[];
356
+ /** Can `trim(n)` drop the last n tokens? (Ring caches lose trimability
357
+ * once wrapped.) */
358
+ isTrimmable(): boolean;
359
+ /** Drop the last n tokens (future writes overwrite them). `bypass` (default
360
+ * false → unchanged behavior) skips the isTrimmable guard for the
361
+ * speculative-decode rollback case (trim the last n ≤ γ tips right after a
362
+ * >1 concat write); rotating caches then physically shrink the buffer tail. */
363
+ trim(n: number, bypass?: boolean): void;
364
+ /** Speculative verify-round support for NON-trimmable recurrent caches
365
+ * (SSMCache — gated-DeltaNet conv + recurrent state). A cache exposing
366
+ * these is spec-eligible without isTrimmable(): the serve loop arms a
367
+ * round before the verify forward (the layer snapshots pre-round state —
368
+ * free, MLX arrays are immutable — and records its position-local kernel
369
+ * inputs), then resolves it: commit on full accept, or rollback(keep)
370
+ * which restores the snapshot and bit-exactly REPLAYS the first `keep`
371
+ * window tokens through the recurrence (identical arithmetic prefix ⇒
372
+ * identical state). Trimmable caches leave these unset and keep trim(). */
373
+ specRoundBegin?(): void;
374
+ specRoundCommit?(): void;
375
+ specRoundRollback?(keep: number): void;
376
+ dispose(): void;
377
+ }
378
+
379
+ export interface RowBatchCache extends Cache {
380
+ readonly batchSize: number;
381
+ filterRows(keep: readonly number[]): void;
382
+ extractRow(row: number): Cache | null;
383
+ }
384
+
385
+ /**
386
+ * Capability contract for cache layouts that own their dynamic-row batching.
387
+ * The scheduler uses this for every storage family (plain and quantized KV,
388
+ * sliding windows, recurrent state, and layouts such as GLM's compressed MLA/DSA
389
+ * state) instead of teaching the scheduler their tensor layout. `mergeRows`
390
+ * writes into an empty cache and does not consume inputs: its sources are a
391
+ * running layout or one serial cache, then one serial cache per joining row.
392
+ * Extracted rows are independent owned serial caches.
393
+ */
394
+ export interface BatchableCache extends Cache {
395
+ readonly batchSize: number | null;
396
+ readonly rowOffsets: readonly number[];
397
+ readonly leftPad: readonly number[];
398
+ readonly maxTokens?: number;
399
+ makeEmptyBatch(): BatchableCache;
400
+ mergeRows(rows: readonly Cache[]): void;
401
+ extractRow(row: number): Cache;
402
+ filterRows(keep: readonly number[]): void;
403
+ projectedBytes(tokens: number): number;
404
+ /** Whether `row` can be published as a cache covering exactly `tokens`
405
+ * positions. State that cannot be trimmed (recurrent) refuses a row whose own
406
+ * count differs: an entry keyed to other tokens would corrupt every later
407
+ * exact hit. Absent: any row can be published. */
408
+ canPublishRow?(row: number, tokens: number): boolean;
409
+ }
410
+
411
+ /**
412
+ * Verification rows: the row layout a speculative method keeps its target rows
413
+ * in, holding the speculative transaction. Every storage a cache lego holds
414
+ * names one (state's `targetCacheLayout`), so any lego serves speculation.
415
+ *
416
+ * The method arms a round before the verify window (`specRoundBegin`), appends
417
+ * the window, then resolves it: `specRoundCommit` keeps every row's window;
418
+ * `specRoundRollback(keep)` keeps the first `keep` positions of each row's
419
+ * window (one count for every row, or one per row). After either, every row is
420
+ * exactly as if only its kept positions had been appended: the same offsets and
421
+ * stored positions, the same reads from then on.
422
+ */
423
+ export interface SpeculativeRowLayout extends BatchableCache {
424
+ makeEmptyBatch(): SpeculativeRowLayout;
425
+ specRoundBegin(): void;
426
+ specRoundCommit(): void;
427
+ specRoundRollback(keep: number | readonly number[]): void;
428
+ }
429
+
430
+ /** Padding is interpreted by cache geometry, independently of scheduling.
431
+ * Left padding initializes an empty group; lengths count input columns before
432
+ * trailing padding. Finalize before ordinary decode or publishing checkpoints. */
433
+ export interface PrefillPadding {
434
+ readonly leftPadding?: readonly number[];
435
+ readonly lengths: readonly number[];
436
+ readonly rightPadding?: readonly number[];
437
+ }
438
+ export interface PaddedPrefillCache extends Cache {
439
+ preparePrefill(padding: PrefillPadding): void;
440
+ finalizePrefill(): void;
441
+ }
442
+
443
+ /** How one decode step interacts with a cache under compiled decode
444
+ * (returned by prepareDecodeStep, consumed by compiled-decode.ts):
445
+ * - "concat": the compiled graph fetches concat(active prefix, new kv)
446
+ * — same values as today's write-then-slice — and the WRITE happens
447
+ * outside the graph right after (writeDecodeStep), keeping the buffer
448
+ * single-referenced at its slice_update so mlx donates it in place.
449
+ * - "ring": the write happens IN-graph (slice_update_dynamic at
450
+ * writePos) and the fetch is the full updated buffer — the rotating
451
+ * steady state, where attention reads the whole ring in ring order
452
+ * (a concat would permute KV positions and change summation order).
453
+ * The updated buffers come back as closure outputs; adoptDecodeStep
454
+ * swaps them in. */
455
+ export interface DecodeStepPlan {
456
+ fetch: "concat" | "ring";
457
+ /** Write position on axis 2 (== ring index for rotating caches). */
458
+ writePos: number;
459
+ /** Valid prefix length for "concat" fetches (== offset). */
460
+ activeLen: number;
461
+ }
462
+
463
+ /** What a compiled decode step hands a cache to assemble its closure inputs. The
464
+ * arrays it returns live for one step; the runner releases them afterwards. */
465
+ export interface DecodeStepInputs {
466
+ /** `array[.., 0:length, ..]` along the sequence axis (axis 2). */
467
+ activeView(array: MlxArray, length: number): MlxArray;
468
+ /** The int32 `[1]` write position (shared between caches at the same position). */
469
+ writePosition(position: number): MlxArray;
470
+ /** Registers `array`, which the cache computed for this step's inputs (a
471
+ * prefix it decodes outside the recorded graph), for release after the step;
472
+ * returns it. Takes ownership. */
473
+ own(array: MlxArray): MlxArray;
474
+ }
475
+
476
+ /** The stand-in a cache places in the traced graph for one step: attention
477
+ * appends to it exactly as it would to the real cache, and the arrays it appends
478
+ * become closure outputs (`outs`) instead of a buffer write. */
479
+ export interface DecodeTrace extends Cache {
480
+ outs: MlxArray[];
481
+ }
482
+
483
+ /** One cache's slot in a compiled decode closure. Plain data: it captures no
484
+ * cache, so a closure built once serves every later step and generation. */
485
+ export interface DecodeSlot {
486
+ /** Graph-shape signature (cache kind, quantization); offsets and capacities
487
+ * are array values or shapeless dimensions and stay out of it. */
488
+ readonly key: string;
489
+ /** The write happens in the graph (ring) or outside it after the step (concat). */
490
+ readonly fetch: DecodeStepPlan["fetch"];
491
+ /** Closure inputs this cache feeds, and closure outputs it returns. */
492
+ readonly inputs: number;
493
+ readonly outputs: number;
494
+ /** The traced stand-in over this slot's `inputs`; `ropeOffset` is the int32 RoPE position input. */
495
+ trace(inputs: readonly MlxArray[], ropeOffset: MlxArray): DecodeTrace;
496
+ }
497
+
498
+ /** A cache the compiled decode step can drive: it declares the slot it occupies
499
+ * in the closure for the coming step and applies the closure's outputs back. */
500
+ export interface CompiledDecodeCache extends Cache {
501
+ /** Host-side bookkeeping for a 1-token step (growth, rotation), without the write. */
502
+ prepareDecodeStep(): DecodeStepPlan;
503
+ /** Non-mutating: the fetch `prepareDecodeStep` will choose. */
504
+ decodePhase(): DecodeStepPlan["fetch"];
505
+ decodeSlot(plan: DecodeStepPlan): DecodeSlot;
506
+ /** The closure inputs of `slot`, in order. */
507
+ decodeInputs(plan: DecodeStepPlan, step: DecodeStepInputs): MlxArray[];
508
+ /** Apply the closure's outputs (takes ownership); returns arrays to evaluate with the step. */
509
+ commitDecodeStep(slot: DecodeSlot, outputs: MlxArray[]): MlxArray[];
510
+ }
@@ -0,0 +1,10 @@
1
+ import type { MlxArray } from "@mlx-bun/mlx/array";
2
+
3
+ /** Generation-method state accompanying the target cache. The method owns
4
+ * its schema and alignment; storage owns these immutable tensor snapshots.
5
+ * Attachments require an exact prefix boundary and are never trimmed. */
6
+ export interface CheckpointAttachment {
7
+ schema: string;
8
+ metadata: Record<string, string | number | boolean>;
9
+ tensors: MlxArray[];
10
+ }
@@ -0,0 +1,14 @@
1
+ import type { CheckpointAttachment } from "./checkpoint";
2
+
3
+ export interface DraftRowCheckpoint {
4
+ readonly processedTokens: number;
5
+ readonly attachment: CheckpointAttachment;
6
+ }
7
+
8
+ /** Attachment schemas of the draft methods' persisted row state. The strings
9
+ * are stored in checkpoints, so they never change with the code that reads them. */
10
+ export const DRAFT_CHECKPOINT_SCHEMA = Object.freeze({
11
+ assistant: "gemma-assistant-v1",
12
+ qwenMtp: "qwen-mtp-v1",
13
+ glm52Mtp: "glm52-native-mtp-v1",
14
+ });
@@ -0,0 +1,27 @@
1
+ import type { MlxArray } from "@mlx-bun/mlx/array";
2
+ import type { Dtype } from "@mlx-bun/mlx/ffi";
3
+ import type { MlxRowTable } from "./row-table";
4
+ import type { MlxHeadForward, MlxHeadRange } from "./head";
5
+
6
+ export type DraftHeadOperations = MlxRowTable<MlxHeadForward> | readonly MlxHeadRange[];
7
+
8
+ /** Numerical ports are backend-specific; returned arrays are caller-owned. */
9
+ export interface DraftProjection {
10
+ readonly embed: {
11
+ encode(ids: MlxArray): MlxArray;
12
+ readonly scales: { readonly dtype: Dtype };
13
+ };
14
+ /** The target's output head per row count or range: the drafter indexes it by the
15
+ * rows it projects. Borrows the hidden; the logits belong to the caller. */
16
+ readonly logits: DraftHeadOperations;
17
+ /** Declared by a graph whose composition measured a drafter selecting over the
18
+ * target's frequency-ranked draft vocabulary: its ids [N] (ascending, uint32,
19
+ * borrowed) and the head's projection onto those rows per row count or range
20
+ * (logits [..., N], caller-owned). A drafter that selects by its scores alone
21
+ * selects over these rows; the target still verifies over its full head.
22
+ * Absent: the full head. */
23
+ readonly vocabulary?: {
24
+ readonly ids: MlxArray;
25
+ readonly logits: DraftHeadOperations;
26
+ };
27
+ }
@@ -0,0 +1,84 @@
1
+ import type { MlxArray } from "@mlx-bun/mlx/array";
2
+ import type { AssistantDonors } from "./attention";
3
+ import type { DraftProjection } from "./draft-projection";
4
+ import type { MlxRowTable } from "./row-table";
5
+
6
+ /** Read-only target state and embedding, independent of draft scheduling. */
7
+ export interface AssistantRowsTarget {
8
+ readonly hiddenSize: number;
9
+ embed(ids: MlxArray): MlxArray;
10
+ readDonors(): AssistantDonors & {
11
+ readonly positions: readonly number[];
12
+ dispose(): void;
13
+ };
14
+ }
15
+
16
+ /** What a recurrent multi-token-prediction head reads from its target: the
17
+ * final hidden layer's output (tapped before the final norm), the token
18
+ * embedding, and the output head. */
19
+ export interface RecurrentMtpTarget {
20
+ readonly hiddenSize: number;
21
+ readonly layerCount: number;
22
+ embed(ids: MlxArray): MlxArray;
23
+ /** The output head per row count or range, indexed by the rows the drafter projects. */
24
+ readonly logits: MlxRowTable<(hidden: MlxArray) => MlxArray>;
25
+ /** The untied quantized vocabulary projection, when the drafter may project
26
+ * onto a row subset of it (frequency-ranked draft vocabulary). Borrowed. */
27
+ readonly vocabularyHead?: {
28
+ readonly w: MlxArray; readonly scales: MlxArray; readonly biases: MlxArray | null;
29
+ readonly spec: { bits: number; groupSize: number; mode: string };
30
+ readonly vocabSize: number;
31
+ };
32
+ }
33
+
34
+ /** Multi-layer hidden-state taps and the embedding/head projection a drafter
35
+ * conditions on. */
36
+ export interface HiddenLayerTapsTarget {
37
+ readonly layerCount: number;
38
+ readonly projection: DraftProjection;
39
+ }
40
+
41
+ /** A residual stream in another basis than the trained model's: the TurboQuant
42
+ * R1 fold (packages/quantize/src/rotate.ts) stores h·R1, R1 = diag(s)·M, with s
43
+ * the seed's lane-0 sign vector and M MLX's hadamard_transform/√n, and moves
44
+ * the final-norm gain into the head. */
45
+ export interface ResidualBasis {
46
+ /** Seed of R1's sign vector. */
47
+ readonly r1Seed: number;
48
+ /** The final-norm gain the fold moved into the head (effective, 1+w), one per hidden channel. */
49
+ readonly finalGain: Float32Array;
50
+ }
51
+
52
+ /** A projection kernel the target's composition measured on its device, built over a 4-bit, group-64 affine
53
+ * projection a drafter quantized itself (its packed weight, scales and biases, borrowed for the kernel's life):
54
+ * the forward over [.., inputs] activations, caller-owned output. */
55
+ export type DraftProjectionKernel = (w: MlxArray, scales: MlxArray, biases: MlxArray) => (x: MlxArray) => MlxArray;
56
+ export interface DraftProjectionRange { readonly from: number; readonly to: number; readonly operation: DraftProjectionKernel }
57
+ export type DraftProjectionKernels = MlxRowTable<DraftProjectionKernel> | readonly DraftProjectionRange[];
58
+
59
+ /** Graph-declared ports over the target's live state, named for what they
60
+ * provide. Sources request only the ports they consume and never inspect a
61
+ * concrete model or cache; a source refuses a target that lacks one with
62
+ * `targetLacks(port)` before any draft-side allocation. */
63
+ export interface TargetView {
64
+ /** Opaque identity for providers borrowing weights from one exact target. */
65
+ readonly identity: object;
66
+ readonly assistantRows?: AssistantRowsTarget;
67
+ readonly hiddenLayerTaps?: HiddenLayerTapsTarget;
68
+ readonly recurrentMtp?: RecurrentMtpTarget;
69
+ /** Declared by a graph whose residual stream carries a rotation fold; absent,
70
+ * the stream is in the trained model's basis. The same object on every view. */
71
+ readonly residualBasis?: ResidualBasis;
72
+ /** Declared by a graph whose composition measured the kernels a drafter's own 4-bit projections run on its
73
+ * device: one per row count or range of the rows they project. Absent, the drafter keeps its own rule. The same
74
+ * table on every view. */
75
+ readonly draftProjections?: DraftProjectionKernels;
76
+ }
77
+
78
+ export type TargetPort = "assistantRows" | "hiddenLayerTaps" | "recurrentMtp";
79
+
80
+ /** The refusal for a target graph that does not provide a requested port. */
81
+ export function targetLacks(port: TargetPort): Error {
82
+ return new Error(`target graph does not provide ${port}`);
83
+ }
84
+