mlx-bun 0.2.0 → 0.4.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 (433) hide show
  1. package/README.md +71 -588
  2. package/docs/README.md +94 -0
  3. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  4. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  5. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  6. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  7. package/docs/archive/investigations/openjarvis-fit.md +198 -0
  8. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  9. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  10. package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
  11. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  12. package/docs/archive/planning/release-notes-v0.3.0.md +35 -0
  13. package/docs/design/batching.md +1841 -0
  14. package/docs/design/decode-speed-program.md +2346 -169
  15. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  16. package/docs/design/generic-model-support.md +655 -334
  17. package/docs/design/kv-cache.md +824 -0
  18. package/docs/design/orpo-training.md +673 -1239
  19. package/docs/design/speculative-decoding.md +1990 -0
  20. package/docs/design/turboquant.md +2212 -0
  21. package/docs/design/unified-engine-frontier-plan.md +1833 -727
  22. package/docs/design/web-chat-redesign.md +666 -1083
  23. package/docs/planning/PRODUCT_ROADMAP.md +50 -1
  24. package/docs/planning/release-notes-v0.4.0.md +45 -0
  25. package/docs/planning/video-series.md +2 -2
  26. package/docs/reference/benchmarks.md +3613 -0
  27. package/docs/reference/cli.md +434 -160
  28. package/docs/reference/distribution.md +328 -182
  29. package/docs/reference/environment.md +398 -0
  30. package/docs/reference/glossary.md +39 -0
  31. package/docs/reference/library-api.md +566 -168
  32. package/docs/reference/memory.md +227 -64
  33. package/docs/reference/models.md +113 -6
  34. package/docs/reference/server-api.md +944 -429
  35. package/docs/reference/server-config.md +740 -338
  36. package/docs/reference/training.md +393 -254
  37. package/docs/reference/troubleshooting.md +158 -0
  38. package/package.json +9 -4
  39. package/src/audio/decode.ts +2 -2
  40. package/src/audio/features.ts +2 -2
  41. package/src/backends/mlx/assistant-target.ts +46 -0
  42. package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
  43. package/src/backends/mlx/autoregressive.ts +108 -0
  44. package/src/backends/mlx/batch-group.ts +1790 -0
  45. package/src/backends/mlx/cache-attachment.ts +67 -0
  46. package/src/backends/mlx/cache-layout.ts +31 -0
  47. package/src/backends/mlx/checkpoint-state.ts +53 -0
  48. package/src/backends/mlx/continuation-persistence.ts +106 -0
  49. package/src/backends/mlx/continuation-request.ts +43 -0
  50. package/src/backends/mlx/continuation.ts +77 -0
  51. package/src/backends/mlx/diffusion.ts +39 -0
  52. package/src/backends/mlx/draft-target.ts +32 -0
  53. package/src/backends/mlx/evaluation.ts +105 -0
  54. package/src/backends/mlx/fill-append.ts +45 -0
  55. package/src/backends/mlx/full-kv-row-append.ts +32 -0
  56. package/src/backends/mlx/full-kv-row-donor.ts +54 -0
  57. package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
  58. package/src/backends/mlx/gateway-binding.ts +130 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/kv-codec.ts +9 -0
  61. package/src/backends/mlx/kv-maintenance.ts +133 -0
  62. package/src/backends/mlx/kv-tensor-rows.ts +212 -0
  63. package/src/backends/mlx/memory-client.ts +189 -0
  64. package/src/backends/mlx/methods.ts +90 -0
  65. package/src/backends/mlx/model-prompt.ts +164 -0
  66. package/src/backends/mlx/model-serving.ts +79 -0
  67. package/src/backends/mlx/prefill-cohort.ts +89 -0
  68. package/src/backends/mlx/prefill-rows.ts +200 -0
  69. package/src/backends/mlx/prefill.ts +33 -0
  70. package/src/backends/mlx/projected-context-rows.ts +72 -0
  71. package/src/backends/mlx/request-policy.ts +20 -0
  72. package/src/backends/mlx/request-state-policy.ts +41 -0
  73. package/src/backends/mlx/rollback.ts +89 -0
  74. package/src/backends/mlx/row-sampling.ts +49 -0
  75. package/src/backends/mlx/serial-executor.ts +242 -0
  76. package/src/backends/mlx/speculative-group.ts +359 -0
  77. package/src/backends/mlx/speculative-round.ts +161 -0
  78. package/src/backends/mlx/speculative.ts +114 -0
  79. package/src/backends/mlx/state-rows.ts +104 -0
  80. package/src/backends/mlx/state-views.ts +46 -0
  81. package/src/backends/mlx/target-layout-capability.ts +35 -0
  82. package/src/backends/mlx/text-engine.ts +73 -0
  83. package/src/backends/mlx/transitioning-kv-rows.ts +165 -0
  84. package/src/cli.ts +66 -58
  85. package/src/client.ts +66 -0
  86. package/src/config.ts +21 -4
  87. package/src/contracts/completion.ts +16 -0
  88. package/src/contracts/execution.ts +60 -0
  89. package/src/contracts/generation.ts +103 -0
  90. package/src/contracts/host.ts +7 -0
  91. package/src/contracts/jobs.ts +66 -0
  92. package/src/contracts/pi-provider.ts +30 -0
  93. package/src/contracts/pi.ts +259 -0
  94. package/src/contracts/prefix-cache.ts +23 -0
  95. package/src/contracts/resources.ts +25 -0
  96. package/src/contracts/sampling.ts +23 -0
  97. package/src/contracts/scheduling.ts +45 -0
  98. package/src/contracts/tsconfig.json +14 -0
  99. package/src/diffusion/diffusion-generate.ts +218 -153
  100. package/src/embed.ts +1 -1
  101. package/src/engine/admission.ts +59 -0
  102. package/src/engine/cancellation.ts +38 -0
  103. package/src/engine/engine.ts +56 -0
  104. package/src/engine/execution-coordinator.ts +70 -0
  105. package/src/engine/execution-plan.ts +53 -0
  106. package/src/engine/resources.ts +53 -0
  107. package/src/engine/scheduler.ts +72 -0
  108. package/src/engine/session.ts +247 -0
  109. package/src/eval/README.md +44 -1
  110. package/src/eval/kl.ts +236 -3
  111. package/src/eval/reference-logits.ts +207 -0
  112. package/src/eval/runner.ts +8 -96
  113. package/src/fill/echo-index.ts +188 -0
  114. package/src/fill/fill-session.ts +452 -0
  115. package/src/fill/proposal.ts +68 -0
  116. package/src/fill/schema-rows.ts +506 -0
  117. package/src/fill/tool-boundary.ts +103 -0
  118. package/src/fit.ts +30 -16
  119. package/src/generate.ts +709 -417
  120. package/src/grammar.ts +12 -7
  121. package/src/harness-pi.ts +14 -33
  122. package/src/hub-rest.ts +4 -4
  123. package/src/index.ts +7 -0
  124. package/src/inference/denoising.ts +17 -0
  125. package/src/inference/draft-acceptance.ts +41 -0
  126. package/src/inference/draft-output.ts +49 -0
  127. package/src/inference/graph.ts +33 -0
  128. package/src/inference/prefill.ts +39 -0
  129. package/src/inference/rollback.ts +7 -0
  130. package/src/jobs/db.ts +4 -0
  131. package/src/jobs/index.ts +2 -0
  132. package/src/jobs/job-entry.ts +12 -12
  133. package/src/jobs/runner.ts +98 -13
  134. package/src/jobs/task-client.ts +19 -0
  135. package/src/jobs/types.ts +2 -58
  136. package/src/kv-scheme.ts +70 -12
  137. package/src/kv-store.ts +177 -63
  138. package/src/lab/README.md +18 -0
  139. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  140. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  141. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +5 -5
  142. package/src/lab/paged-kv/paged-kv-rows.ts +83 -0
  143. package/src/{model → lab/paged-kv}/paged-kv.ts +32 -15
  144. package/src/library.ts +40 -0
  145. package/src/lora.ts +18 -0
  146. package/src/media-fetch.ts +1 -1
  147. package/src/memory/article.ts +1 -1
  148. package/src/memory/chunk.ts +1 -1
  149. package/src/memory/model.ts +30 -169
  150. package/src/memory/prompts.ts +1 -1
  151. package/src/memory/rest.ts +1 -1
  152. package/src/memory/schedule.ts +1 -1
  153. package/src/memory/stages.ts +4 -1
  154. package/src/memory/vault.ts +1 -3
  155. package/src/mlx/array.ts +11 -11
  156. package/src/mlx/compile.ts +12 -2
  157. package/src/mlx/ffi.ts +58 -11
  158. package/src/mlx/materialize.ts +23 -0
  159. package/src/mlx/metal-kernel.ts +10 -11
  160. package/src/mlx/ops.ts +33 -13
  161. package/src/mlx/quantized-rows.ts +36 -0
  162. package/src/mlx/token-bitmask.ts +52 -0
  163. package/src/mlx/turboquant-kv-decode.ts +82 -0
  164. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  165. package/src/mlx/turboquant-ops.ts +33 -3
  166. package/src/mlx/turboquant-tables.ts +2 -2
  167. package/src/model/artifact-identity.ts +73 -0
  168. package/src/model/batched-kv.ts +235 -0
  169. package/src/model/batched-mask.ts +20 -6
  170. package/src/model/batched-quant.ts +9 -3
  171. package/src/model/batched-quantized-kv.ts +144 -0
  172. package/src/model/batched-rotating-quant.ts +78 -17
  173. package/src/model/batched-rotating-state.ts +76 -0
  174. package/src/model/batched-rotating.ts +65 -23
  175. package/src/model/batched-row-storage.ts +52 -0
  176. package/src/model/batched-ssm.ts +52 -0
  177. package/src/model/batched-turboquant-kv.ts +93 -0
  178. package/src/model/compiled-decode.ts +8 -2
  179. package/src/model/decoded-kv-donor.ts +12 -0
  180. package/src/model/delayed-quantized-kv.ts +72 -0
  181. package/src/model/delayed-rotating-quantized-kv.ts +93 -0
  182. package/src/model/delayed-turboquant-kv.ts +55 -0
  183. package/src/model/diffusion-gemma.ts +8 -8
  184. package/src/model/factory.ts +76 -33
  185. package/src/model/fingerprint.ts +1 -1
  186. package/src/model/flash-attention.ts +3 -3
  187. package/src/model/full-prefill-padding.ts +56 -0
  188. package/src/model/full-prefill-row.ts +105 -0
  189. package/src/model/gemma4-base.ts +179 -80
  190. package/src/model/gemma4.ts +40 -32
  191. package/src/model/generated/gemma4-12b.ts +6 -3
  192. package/src/model/generated/gemma4-26b.ts +6 -3
  193. package/src/model/generated/gemma4-e4b.ts +6 -3
  194. package/src/model/glm52-cache.ts +80 -4
  195. package/src/model/glm52-dsa.ts +13 -9
  196. package/src/model/glm52-memory.ts +1 -1
  197. package/src/model/glm52-mla.ts +12 -6
  198. package/src/model/glm52.ts +19 -40
  199. package/src/model/implementation.ts +69 -0
  200. package/src/model/kv-attention-view.ts +67 -0
  201. package/src/model/minicpm5.ts +17 -15
  202. package/src/model/profile.ts +12 -2
  203. package/src/model/qwen-append.ts +12 -0
  204. package/src/model/qwen-conv.ts +52 -0
  205. package/src/model/qwen3-delta-state.ts +74 -0
  206. package/src/model/qwen3-delta.ts +59 -36
  207. package/src/model/qwen3_5-checkpoint.ts +164 -0
  208. package/src/model/qwen3_5.ts +202 -78
  209. package/src/model/rotating-kv-donor.ts +35 -0
  210. package/src/model/rotating-kv-layout.ts +262 -0
  211. package/src/model/rotating-row-transaction.ts +35 -0
  212. package/src/model/speculative-rotating-kv.ts +101 -0
  213. package/src/model/ssm-prefill-padding.ts +39 -0
  214. package/src/model/support.ts +1 -1
  215. package/src/model/trellis-balanced-scatter.ts +51 -0
  216. package/src/model/trellis-linear.ts +672 -0
  217. package/src/model/trellis-shared-m.ts +151 -0
  218. package/src/model/trellis-shared-scatter.ts +144 -0
  219. package/src/model/trellis-splitk-prefill.ts +158 -0
  220. package/src/model/trellis-tiled-prefill.ts +136 -0
  221. package/src/model/trellis-vector-expand.ts +62 -0
  222. package/src/model/trellis-wide-prefill.ts +94 -0
  223. package/src/model/turboquant-codec.ts +83 -0
  224. package/src/model/universal/dense.ts +15 -14
  225. package/src/model/universal/modules.ts +8 -1
  226. package/src/native-pack.ts +6 -5
  227. package/src/pi-provider.ts +6 -64
  228. package/src/pi-web.ts +8 -315
  229. package/src/preflight.ts +31 -15
  230. package/src/prompt-cache.ts +110 -69
  231. package/src/quantize/allocator.ts +1 -1
  232. package/src/quantize/config-writer.ts +10 -3
  233. package/src/quantize/rotate.ts +4 -4
  234. package/src/quantize/trellis.ts +586 -0
  235. package/src/responses.ts +28 -1
  236. package/src/runtime-config.ts +18 -4
  237. package/src/sampler.ts +40 -29
  238. package/src/serve/batch-scheduler.ts +8 -1671
  239. package/src/serve/chat-request.ts +391 -0
  240. package/src/serve/chat-stage.ts +195 -0
  241. package/src/serve/checkpoint-identity.ts +64 -0
  242. package/src/serve/completion-executor.ts +15 -7
  243. package/src/serve/discovery-routes.ts +12 -13
  244. package/src/serve/generation-gateway.ts +183 -213
  245. package/src/serve/http.ts +159 -0
  246. package/src/serve/inference-request.ts +79 -0
  247. package/src/serve/isolate.ts +297 -105
  248. package/src/serve/lab-routes.ts +3 -0
  249. package/src/serve/lane-registry.ts +2 -1
  250. package/src/serve/model-admin-routes.ts +7 -5
  251. package/src/serve/model-binding.ts +43 -0
  252. package/src/serve/model-host.ts +511 -0
  253. package/src/serve/openai-wire.ts +103 -0
  254. package/src/serve/parent-application.ts +56 -0
  255. package/src/serve/pipeline.ts +33 -0
  256. package/src/serve/preparation.ts +33 -0
  257. package/src/serve/request-plan.ts +23 -18
  258. package/src/serve/request-prep.ts +344 -0
  259. package/src/serve/response-lease.ts +24 -0
  260. package/src/serve/responses-client.ts +69 -0
  261. package/src/serve/session-completion-engine.ts +110 -0
  262. package/src/serve/session-search.ts +1 -1
  263. package/src/serve/static-routes.ts +5 -5
  264. package/src/serve/text-completion-stage.ts +104 -0
  265. package/src/serve/token-streams.ts +519 -0
  266. package/src/server.ts +335 -2711
  267. package/src/spec/assistant-rows.ts +92 -0
  268. package/src/spec/assistant-source.ts +31 -55
  269. package/src/spec/cache-identity.ts +22 -0
  270. package/src/spec/deepspec-rows.ts +29 -0
  271. package/src/spec/deepspec-source.ts +16 -14
  272. package/src/spec/dflash-source.ts +36 -12
  273. package/src/spec/drafter.ts +153 -142
  274. package/src/spec/dspark/ab-stats.ts +3 -3
  275. package/src/spec/dspark/calibration.ts +2 -2
  276. package/src/spec/dspark/deepspec-module.ts +97 -122
  277. package/src/spec/dspark/generate-dflash.ts +2 -2
  278. package/src/spec/dspark/generate.ts +2 -2
  279. package/src/spec/dspark/loader.ts +1 -1
  280. package/src/spec/dspark/module-dflash.ts +129 -172
  281. package/src/spec/dspark/module.ts +3 -3
  282. package/src/spec/dspark/quantize-drafter.ts +1 -1
  283. package/src/spec/generate.ts +1 -1
  284. package/src/spec/glm52-mtp-graph.ts +29 -0
  285. package/src/spec/glm52-mtp-rows.ts +132 -0
  286. package/src/spec/glm52-mtp-source.ts +54 -137
  287. package/src/spec/glm52-mtp-state.ts +33 -0
  288. package/src/spec/ngram-source.ts +93 -21
  289. package/src/spec/projected-draft-rows.ts +73 -0
  290. package/src/spec/qwen-mtp-module.ts +171 -0
  291. package/src/spec/qwen-mtp-rows.ts +219 -0
  292. package/src/spec/qwen-mtp-source.ts +147 -195
  293. package/src/spec/qwen-mtp-state.ts +30 -0
  294. package/src/spec/serve-loop.ts +201 -201
  295. package/src/spec/source.ts +110 -13
  296. package/src/spec/two-model-rows.ts +61 -0
  297. package/src/spec/two-model.ts +44 -102
  298. package/src/ssd-cache.ts +99 -19
  299. package/src/ssd-durability.ts +36 -20
  300. package/src/tool-call.ts +51 -14
  301. package/src/train/flash-cce.ts +2 -2
  302. package/src/train/forward.ts +6 -0
  303. package/src/train/loss.ts +1 -1
  304. package/src/train/prefix-shared.ts +5 -1
  305. package/src/train/segmented.ts +5 -3
  306. package/src/train/trainer.ts +6 -6
  307. package/src/vision/prompt.ts +1 -1
  308. package/src/vision/qwen3vl-tower.ts +52 -10
  309. package/src/web/app.html +1 -1
  310. package/src/web/app.js +62 -60
  311. package/src/web/src/adapters-panel.ts +3 -3
  312. package/src/web/src/assistant.ts +2 -36
  313. package/src/web/src/chat.ts +4 -4
  314. package/src/web/src/composer.ts +4 -4
  315. package/src/web/src/hub.ts +1 -1
  316. package/src/web/src/markdown.ts +0 -0
  317. package/src/web/src/memory-panel.ts +1 -1
  318. package/src/web/src/model-picker.ts +1 -1
  319. package/src/web/src/palette.ts +1 -1
  320. package/src/web/src/protocol.ts +3 -39
  321. package/src/web/src/sessions.ts +1 -1
  322. package/src/web/src/ui-catalog.ts +4 -18
  323. package/src/web-assets.ts +47 -0
  324. package/src/weights.ts +55 -9
  325. package/docs/archive/investigations/curve-runs/bisector-route.json +0 -98
  326. package/docs/archive/investigations/curve-runs/bisector-trace.json +0 -1393
  327. package/docs/archive/investigations/curve-runs/curve-terrain.json +0 -1179
  328. package/docs/archive/investigations/curve-runs/curve-terrain.svg +0 -42
  329. package/docs/archive/investigations/hlg-ab.html +0 -34
  330. package/docs/archive/investigations/hlg-explorer.html +0 -238
  331. package/docs/archive/investigations/hlg-figs/cliff.svg +0 -1
  332. package/docs/archive/investigations/hlg-figs/cross.svg +0 -1
  333. package/docs/archive/investigations/hlg-figs/edges.svg +0 -1
  334. package/docs/archive/investigations/hlg-figs/k20-grids.svg +0 -1
  335. package/docs/archive/investigations/hlg-figs/k20-peaks.svg +0 -1
  336. package/docs/archive/investigations/hlg-figs/lw-curve.svg +0 -1
  337. package/docs/archive/investigations/hlg-figs/terrain.svg +0 -1
  338. package/docs/archive/investigations/hlg-report.html +0 -262
  339. package/docs/archive/investigations/hlg-runs/hlg-ab.json +0 -149
  340. package/docs/archive/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  341. package/docs/archive/investigations/hlg-runs/hlg-blind.json +0 -107
  342. package/docs/archive/investigations/hlg-runs/hlg-cliff.json +0 -197
  343. package/docs/archive/investigations/hlg-runs/hlg-cross.json +0 -505
  344. package/docs/archive/investigations/hlg-runs/hlg-edge.json +0 -388
  345. package/docs/archive/investigations/hlg-runs/hlg-eval1.json +0 -25
  346. package/docs/archive/investigations/hlg-runs/hlg-frontier.json +0 -86
  347. package/docs/archive/investigations/hlg-runs/hlg-grid.json +0 -242
  348. package/docs/archive/investigations/hlg-runs/hlg-grid2.json +0 -343
  349. package/docs/archive/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  350. package/docs/archive/investigations/hlg-runs/hlg-map.json +0 -383
  351. package/docs/archive/investigations/hlg-runs/run0-original.log +0 -159
  352. package/docs/archive/investigations/hlg-runs/runA-recommended.log +0 -131
  353. package/docs/archive/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  354. package/docs/archive/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  355. package/docs/archive/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  356. package/docs/archive/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  357. package/docs/archive/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  358. package/docs/archive/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  359. package/docs/archive/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  360. package/docs/archive/investigations/hlg-runs/runB-gain-variants.log +0 -192
  361. package/docs/archive/investigations/hlg-runs/runC-pivots.log +0 -162
  362. package/docs/archive/investigations/hlg-runs/runD-oetf.log +0 -132
  363. package/docs/archive/investigations/hlg-runs/runE-eotf.log +0 -162
  364. package/docs/archive/investigations/hlg-runs/runF-shaper-working.log +0 -86
  365. package/docs/archive/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  366. package/docs/archive/investigations/hlg-runs/runH-wsweep.log +0 -176
  367. package/docs/archive/investigations/hlg-runs/runI-asweep.log +0 -176
  368. package/docs/archive/investigations/hlg-runs/runJ-knobmap.log +0 -49
  369. package/docs/archive/investigations/hlg-runs/runK-frontier.log +0 -19
  370. package/docs/archive/investigations/hlg-runs/runL-widemap.log +0 -65
  371. package/docs/archive/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  372. package/docs/archive/investigations/hlg-runs/runN-verify.log +0 -116
  373. package/docs/archive/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  374. package/docs/archive/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  375. package/docs/archive/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  376. package/docs/archive/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  377. package/docs/archive/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  378. package/docs/archive/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  379. package/docs/archive/investigations/hlg-runs/runU-cross-12b.log +0 -33
  380. package/docs/archive/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  381. package/docs/archive/investigations/hlg-runs/runW-lw-12b.log +0 -22
  382. package/docs/archive/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  383. package/docs/archive/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  384. package/docs/archive/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  385. package/docs/archive/mlx-bun-lab-report.html +0 -275
  386. package/docs/archive/wwdc-mlx-bun.html +0 -848
  387. package/docs/design/adapters-end-to-end.md +0 -205
  388. package/docs/design/batching-perf-path.md +0 -255
  389. package/docs/design/batching-v2-plan.md +0 -529
  390. package/docs/design/bucketing-stage.md +0 -197
  391. package/docs/design/compat-cli-surface-design.md +0 -230
  392. package/docs/design/docs-reorg-plan.md +0 -165
  393. package/docs/design/dspark-serving-program.md +0 -371
  394. package/docs/design/dspark-speculative-decoding.md +0 -318
  395. package/docs/design/grammar-spec-batching-integration.md +0 -301
  396. package/docs/design/memory-inference-path.md +0 -422
  397. package/docs/design/memory-synthesis.md +0 -287
  398. package/docs/design/memory-system.md +0 -237
  399. package/docs/design/mlx-lm-serving-execution-seam.md +0 -81
  400. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  401. package/docs/design/omlx-adoption-map.md +0 -98
  402. package/docs/design/orpo-dynamic-lambda.md +0 -220
  403. package/docs/design/orpo-future-enhancements.md +0 -340
  404. package/docs/design/paged-kv-cache.md +0 -214
  405. package/docs/design/parallel-slots.md +0 -567
  406. package/docs/design/parity-tier-dag.md +0 -161
  407. package/docs/design/repo-cleanup-plan.md +0 -231
  408. package/docs/design/runtime-isolation.md +0 -263
  409. package/docs/design/segmented-backward-training.md +0 -543
  410. package/docs/design/spec-decode-larger-targets.md +0 -229
  411. package/docs/design/ssd-kv-cold-tier.md +0 -415
  412. package/docs/design/structured-output.md +0 -484
  413. package/docs/design/tauri-desktop-app.md +0 -127
  414. package/docs/design/the-dreaming-master-plan.md +0 -445
  415. package/docs/design/turboquant-kv.md +0 -235
  416. package/docs/design/turboquant-weights.md +0 -467
  417. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  418. package/docs/design/web-chat-beat-matrix.md +0 -315
  419. package/docs/design/write-pipeline-entity.md +0 -468
  420. package/docs/planning/IDEAS.md +0 -69
  421. package/docs/reference/embedding.md +0 -197
  422. package/docs/reference/features-matrix.md +0 -101
  423. package/docs/reference/orpo-quickstart.md +0 -135
  424. package/src/flags.ts +0 -11
  425. /package/docs/{design → archive/investigations}/colibri-glm52-port.md +0 -0
  426. /package/docs/{planning → archive/planning}/chunk-task-roadmap.md +0 -0
  427. /package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +0 -0
  428. /package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +0 -0
  429. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  430. /package/docs/{planning → archive/planning}/release-notes-v0.2.0.md +0 -0
  431. /package/src/{memory-plan.ts → admission-plan.ts} +0 -0
  432. /package/{docs/archive/investigations → src/serve/assets}/curve-terrain.html +0 -0
  433. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -0,0 +1,161 @@
1
+ import type { MlxArray } from "../../mlx/array";
2
+ import * as ops from "../../mlx/ops";
3
+ import type { Cancellation, GenerationOutput, TokenLogprobs } from "../../contracts/generation";
4
+ import type { DisposableResource } from "../../contracts/resources";
5
+ import { cleanupFailure, disposeResources } from "../../engine/resources";
6
+ import type { SpeculativeTransaction } from "../../inference/rollback";
7
+ import { DraftAcceptance } from "../../inference/draft-acceptance";
8
+ import { deliverDraftOutputs, type DraftOutputResult } from "../../inference/draft-output";
9
+ import { readStepExtras, type NumberStepSampler } from "../../sampler";
10
+
11
+ /** Draft state owns proposal generation and its committed hidden/KV state.
12
+ * It borrows verification context and knows nothing about target storage. */
13
+ export interface MlxDraftRows<Context = MlxArray> {
14
+ /** Each row returns 0..depth proposals. The method verifies the returned
15
+ * lengths; an empty row still consumes its pending token. */
16
+ draft(pending: readonly number[], depth: number, steps: readonly number[]): number[][] | Promise<number[][]>;
17
+ commit(accepted: readonly number[], context: Context): void | Promise<void>;
18
+ }
19
+
20
+ /** A bound graph transfers both tensors on success and releases partial
21
+ * allocations on failure. State retention is a separate injected interface. */
22
+ export interface MlxRowVerification<Context extends DisposableResource = MlxArray> {
23
+ readonly transaction: SpeculativeTransaction<readonly number[]>;
24
+ forward(ids: MlxArray): Promise<{ logits: MlxArray; context: Context }>;
25
+ }
26
+
27
+ export interface MlxSpeculativeRow {
28
+ readonly pending: number;
29
+ readonly step: number;
30
+ readonly remaining: number;
31
+ readonly eosTokenIds: readonly number[];
32
+ readonly sampling: NumberStepSampler;
33
+ readonly grammarDone?: () => boolean;
34
+ }
35
+
36
+ export interface MlxSpeculativeRowResult {
37
+ readonly drafts: readonly number[];
38
+ readonly acceptance: DraftAcceptance;
39
+ /** One entry per content token; stopping EOS is excluded. */
40
+ readonly logprobs: readonly (TokenLogprobs | undefined)[];
41
+ }
42
+
43
+ export interface MlxSpeculativeOutputRow extends MlxSpeculativeRow {
44
+ readonly output: Pick<GenerationOutput, "commit">;
45
+ readonly cancellation?: Cancellation;
46
+ }
47
+
48
+ /** Execute one method step through output delivery and aligned state commit.
49
+ * The caller retires terminal rows and publishes eligible completed state
50
+ * before changing membership. Consumer failures are returned per request;
51
+ * a graph/state failure throws and requires discarding the whole group. */
52
+ export async function advanceSpeculativeOutputs<Context extends DisposableResource = MlxArray>(
53
+ rows: readonly MlxSpeculativeOutputRow[], depth: number,
54
+ draft: MlxDraftRows<NoInfer<Context>>, target: MlxRowVerification<Context>,
55
+ ): Promise<{ rounds: readonly MlxSpeculativeRowResult[]; outputs: readonly DraftOutputResult[] }> {
56
+ const round = await prepareSpeculativeRows(rows, depth, draft, target);
57
+ let outputs: DraftOutputResult[];
58
+ try {
59
+ outputs = await deliverDraftOutputs(round.results.map((result, row) => ({
60
+ acceptance: result.acceptance, logprobs: result.logprobs,
61
+ output: rows[row]!.output, cancellation: rows[row]!.cancellation,
62
+ })));
63
+ await round.commit(outputs.map(output => output.accepted));
64
+ } catch (error) { return cleanupFailure(error, () => round.dispose()); }
65
+ round.dispose();
66
+ return { rounds: round.results, outputs };
67
+ }
68
+
69
+ /** Retention stays unresolved while the method delivers output. A terminal
70
+ * row may keep fewer accepted inputs for an output-aligned checkpoint;
71
+ * continuing rows retain their complete accepted prefix. Commit exactly once,
72
+ * then dispose; disposing an uncommitted round requires discarding its state. */
73
+ export interface MlxPreparedSpeculativeRound extends DisposableResource {
74
+ readonly results: readonly MlxSpeculativeRowResult[];
75
+ commit(keepAccepted?: readonly number[]): Promise<void>;
76
+ }
77
+
78
+ /** One committed method step at B=1 or B>1. The caller supplies live rows with
79
+ * a positive token budget and a common nonnegative draft depth. Admission,
80
+ * cancellation boundaries, output delivery and cache publication stay outside
81
+ * this step. On failure the caller discards the participating method state. */
82
+ export async function advanceSpeculativeRows<Context extends DisposableResource = MlxArray>(
83
+ rows: readonly MlxSpeculativeRow[], depth: number,
84
+ draft: MlxDraftRows<NoInfer<Context>>, target: MlxRowVerification<Context>,
85
+ ): Promise<readonly MlxSpeculativeRowResult[]> {
86
+ const round = await prepareSpeculativeRows(rows, depth, draft, target);
87
+ try { await round.commit(); }
88
+ catch (error) { return cleanupFailure(error, () => round.dispose()); }
89
+ round.dispose();
90
+ return round.results;
91
+ }
92
+
93
+ /** Draft, verify and sample without deciding which output-aligned state to
94
+ * retain. Graph-specific context is opaque to this operation. */
95
+ export async function prepareSpeculativeRows<Context extends DisposableResource = MlxArray>(
96
+ rows: readonly MlxSpeculativeRow[], depth: number,
97
+ draft: MlxDraftRows<NoInfer<Context>>, target: MlxRowVerification<Context>,
98
+ ): Promise<MlxPreparedSpeculativeRound> {
99
+ const proposals = await draft.draft(rows.map(row => row.pending), depth, rows.map(row => row.step));
100
+ const B = rows.length;
101
+ const verifyDepth = proposals.reduce((max, tokens) => Math.max(max, tokens.length), 0);
102
+ using ids = ops.fromInt32(proposals.flatMap((tokens, row) => {
103
+ const window = [rows[row]!.pending, ...tokens];
104
+ // Causal right padding only fills the rectangular graph. Sampling stops
105
+ // at this row's own bonus position; commit discards every padded input.
106
+ while (window.length <= verifyDepth) window.push(rows[row]!.pending);
107
+ return window;
108
+ }), [B, verifyDepth + 1]);
109
+ target.transaction.begin(verifyDepth);
110
+ const verification = await target.forward(ids);
111
+ const dispose = () => disposeResources([verification.context, verification.logits]);
112
+ try {
113
+ const results = await sampleSpeculativeRows(rows, proposals, verification.logits);
114
+ return {
115
+ results,
116
+ async commit(accepted = results.map(result => result.acceptance.accepted)) {
117
+ target.transaction.resolve(accepted);
118
+ await draft.commit(accepted, verification.context);
119
+ },
120
+ dispose,
121
+ };
122
+ } catch (error) { return cleanupFailure(error, dispose); }
123
+ }
124
+
125
+ /** Sample a borrowed verify window. Each request owns its processor history,
126
+ * grammar and RNG stream; completing one walk never samples its unused suffix.
127
+ * The existing request adapter and grouped method use this same operation. */
128
+ export async function sampleSpeculativeRows(
129
+ rows: readonly MlxSpeculativeRow[], proposals: readonly (readonly number[])[], logits: MlxArray,
130
+ ): Promise<MlxSpeculativeRowResult[]> {
131
+ const V = logits.shape[2]!, width = logits.shape[1]!;
132
+ const independent = rows[0]?.sampling.independent;
133
+ let tokens: number[] | undefined;
134
+ if (independent && rows.every(row => row.sampling.independent === independent)) {
135
+ using flat = ops.reshape(logits, [rows.length * width, V]);
136
+ using sampled = independent.sample(flat);
137
+ tokens = sampled.toIntTokens();
138
+ }
139
+ const results: MlxSpeculativeRowResult[] = [];
140
+ for (let row = 0; row < rows.length; row++) {
141
+ const request = rows[row]!;
142
+ const acceptance = new DraftAcceptance(proposals[row]!, request.remaining, request.eosTokenIds);
143
+ const logprobs: (TokenLogprobs | undefined)[] = [];
144
+ while (!acceptance.done) {
145
+ const position = acceptance.position;
146
+ let token: number, metadata: TokenLogprobs | undefined;
147
+ if (tokens) token = tokens[row * width + position]!;
148
+ else {
149
+ using slice = logits.slice([row, position, 0], [row + 1, position + 1, V]);
150
+ using scores = ops.reshape(slice, [1, V]);
151
+ const sampled = await request.sampling.sample(scores, request.step + acceptance.emitted.length);
152
+ token = sampled.token;
153
+ metadata = readStepExtras(sampled.extras);
154
+ }
155
+ acceptance.accept(token, request.grammarDone?.() ?? false);
156
+ if (!acceptance.sawEos) logprobs.push(metadata);
157
+ }
158
+ results.push({ drafts: proposals[row]!, acceptance, logprobs });
159
+ }
160
+ return results;
161
+ }
@@ -0,0 +1,114 @@
1
+ import type { MlxArray } from "../../mlx/array";
2
+ import * as ops from "../../mlx/ops";
3
+ import type { Cache } from "../../model/gemma4";
4
+ import type { RuntimeModel } from "../../model/factory";
5
+ import type { Sampler } from "../../sampler";
6
+ import type { DraftProvider, DraftSource } from "../../spec/source";
7
+ import { runtimeConfig, type RuntimeConfig } from "../../runtime-config";
8
+ import type { MlxModelMemory } from "./autoregressive";
9
+ import type { SpeculativeTransaction } from "../../inference/rollback";
10
+ import { bindCacheRollback } from "./rollback";
11
+ import type { GraphDescriptor } from "../../inference/graph";
12
+ import { bindLegacyDraftTarget } from "./draft-target";
13
+
14
+ /** Bound target operations and draft construction for one speculative run.
15
+ * A replacement graph supplies this entire port, including any hidden taps.
16
+ * The verifier never needs a RuntimeModel or an artifact-family check. */
17
+ export interface MlxSpeculativeBinding {
18
+ readonly runtime?: RuntimeConfig;
19
+ readonly memory?: MlxModelMemory;
20
+ readonly descriptor: GraphDescriptor;
21
+ readonly eosTokenIds: readonly number[];
22
+ readonly prefillTailSplit: boolean;
23
+ makeCache(): Cache[];
24
+ openDraft(sampler: Sampler, caches: Cache[]): DraftSource;
25
+ bindRollback(caches: Cache[]): SpeculativeTransaction;
26
+ forward(ids: MlxArray, caches: Cache[], tapLayers?: number[]):
27
+ Promise<{ hidden: MlxArray; ctxML: MlxArray | null }>;
28
+ projectLogits(hidden: MlxArray): MlxArray;
29
+ /** Establish the implementation's verify kernel context; restore on close. */
30
+ pinVerify?(): { close(): void };
31
+ }
32
+
33
+ /** Legacy mutable tap/kernel fields require the gateway's exclusive lease. */
34
+ export function bindLegacySpeculativeModel(model: RuntimeModel, provider: DraftProvider): MlxSpeculativeBinding {
35
+ const runtime = runtimeConfig();
36
+ return {
37
+ runtime,
38
+ memory: model,
39
+ descriptor: Object.freeze({ id: `legacy-spec:${model.config.modelType}`, backend: "mlx",
40
+ graphAbi: "mlx-hidden-bsh-v1", stateAbi: "legacy-cache-array-v1", artifact: "legacy-resident-model" }),
41
+ eosTokenIds: model.config.eosTokenIds,
42
+ prefillTailSplit: runtime.flag("MLX_BUN_PREFILL_TAIL_SPLIT", true),
43
+ makeCache: model.makeCache.bind(model),
44
+ openDraft: (sampler, caches) => provider.open({ sampler, target: bindLegacyDraftTarget(model, caches) }),
45
+ bindRollback: bindCacheRollback,
46
+ forward: (ids, caches, tapLayers) => legacyForwardWithTaps(model, ids, caches, tapLayers),
47
+ projectLogits: model.logitsFromHidden.bind(model),
48
+ ...("setSpecKernelPinned" in model ? {
49
+ pinVerify() {
50
+ model.setSpecKernelPinned(true);
51
+ return { close() { model.setSpecKernelPinned(false); } };
52
+ },
53
+ } : {}),
54
+ };
55
+ }
56
+
57
+ export function assertMlxSpeculativeBinding(binding: MlxSpeculativeBinding): void {
58
+ const descriptor = binding.descriptor;
59
+ if (descriptor.backend !== "mlx" || descriptor.graphAbi !== "mlx-hidden-bsh-v1" ||
60
+ descriptor.stateAbi !== "legacy-cache-array-v1")
61
+ throw new Error(`speculative binding ${descriptor.id} has an incompatible backend, graph, or state ABI`);
62
+ }
63
+
64
+ /** Run one target forward, and when `tapLayers` is set (⟹ a Gemma4 target — a
65
+ * DSpark-style source), also return the captured multi-layer context
66
+ * [1,L,m*H] (tapLayers concatenated on the feature axis; index nLayers is the
67
+ * post-finalNorm sentinel). Non-tapping sources get ctxML=null and never
68
+ * touch model.hiddenTap. Mirrors generate-dflash.ts forwardTapped. */
69
+ async function legacyForwardWithTaps(
70
+ model: RuntimeModel,
71
+ ids: MlxArray,
72
+ caches: Cache[],
73
+ tapLayers: number[] | undefined,
74
+ ): Promise<{ hidden: MlxArray; ctxML: MlxArray | null }> {
75
+ if (!tapLayers) {
76
+ const asyncModel = model as RuntimeModel & {
77
+ forwardHiddenAsync?: (
78
+ ids: MlxArray,
79
+ caches: Cache[],
80
+ ) => Promise<MlxArray>;
81
+ };
82
+ const hidden = typeof asyncModel.forwardHiddenAsync === "function"
83
+ ? await asyncModel.forwardHiddenAsync(ids, caches)
84
+ : model.forwardHidden(ids, caches);
85
+ return { hidden, ctxML: null };
86
+ }
87
+ if (!("hiddenTap" in model)) throw new Error("target graph does not support hidden taps");
88
+ const m = model;
89
+ const previousTap = m.hiddenTap;
90
+ const cap = new Map<number, MlxArray>();
91
+ m.hiddenTap = { layers: new Set(tapLayers), captured: cap };
92
+ let hidden: MlxArray | null = null;
93
+ try {
94
+ hidden = model.forwardHidden(ids, caches);
95
+ const perLayer = tapLayers.map((li) => {
96
+ const a = cap.get(li);
97
+ if (!a) throw new Error(`spec tap: layer ${li} not captured`);
98
+ return a;
99
+ });
100
+ const ctxML = ops.concatAxis(perLayer, 2); // [1,L,m*H]
101
+ for (const [, a] of cap) a.dispose();
102
+ cap.clear(); // consumed — the finally must not double-dispose
103
+ const out = { hidden, ctxML };
104
+ hidden = null; // ownership returned to the caller
105
+ return out;
106
+ } finally {
107
+ // On any throw (forward mid-capture, missing layer, concat), free the
108
+ // partially-captured tap tensors and the orphaned hidden. On success both
109
+ // are already gone (cap cleared, hidden nulled).
110
+ hidden?.dispose();
111
+ for (const [, a] of cap) a.dispose();
112
+ m.hiddenTap = previousTap;
113
+ }
114
+ }
@@ -0,0 +1,104 @@
1
+ import type { BatchableCache, Cache } from "../../model/gemma4-base";
2
+ import { applyStateChanges, cleanupFailure, disposeResources } from "../../engine/resources";
3
+ import type { PreparedStateChange } from "../../contracts/resources";
4
+
5
+ /** Preserve the graph's layout capabilities when an empty sibling is made. */
6
+ export interface MlxRowLayout<Layout extends BatchableCache> extends BatchableCache {
7
+ makeEmptyBatch(): Layout;
8
+ }
9
+
10
+ /** Layer layouts own tensor geometry. This collection only applies the same
11
+ * row membership operation to every layer. It has no scheduling, sampling,
12
+ * checkpoint-key or persistence policy. */
13
+ export class MlxStateRows<Layout extends MlxRowLayout<Layout> = BatchableCache> {
14
+ /** Borrowed by the bound target graph; collection ownership stays here. */
15
+ readonly caches: Layout[];
16
+ #rows = 0;
17
+
18
+ /** Takes ownership of empty, compatible layer layouts. */
19
+ constructor(layouts: readonly Layout[]) { this.caches = [...layouts]; }
20
+ get rowCount(): number { return this.#rows; }
21
+ /** Retain an immutable batch boundary without extracting or materializing
22
+ * individual rows. Layer layouts decide how to share their backing arrays. */
23
+ clone(): MlxStateRows<Layout> {
24
+ const layouts: Layout[] = [];
25
+ try {
26
+ for (const source of this.caches) {
27
+ const layout = source.makeEmptyBatch(); layouts.push(layout);
28
+ layout.mergeRows([source]);
29
+ }
30
+ const result = new MlxStateRows(layouts); result.#rows = this.#rows;
31
+ return result;
32
+ } catch (error) { return cleanupFailure(error, () => disposeResources(layouts)); }
33
+ }
34
+ /** Prepare an initial cohort with one merge per layer. */
35
+ mergeRows(rows: readonly (readonly Cache[])[]): void {
36
+ const next: Layout[] = [];
37
+ try {
38
+ for (let layer = 0; layer < this.caches.length; layer++) {
39
+ const layout = this.caches[layer]!.makeEmptyBatch(); next.push(layout);
40
+ layout.mergeRows(rows.map(row => row[layer]!));
41
+ }
42
+ } catch (error) { return cleanupFailure(error, () => disposeResources(next)); }
43
+ const previous = this.caches.splice(0, this.caches.length, ...next);
44
+ this.#rows = rows.length; disposeResources(previous);
45
+ }
46
+
47
+ /** Borrow a prepared request's state. Build every replacement before
48
+ * releasing the active group, so a failed admission leaves it intact. */
49
+ append(row: readonly Cache[]): void {
50
+ applyStateChanges([() => this.prepareAppend(row)]);
51
+ }
52
+
53
+ /** Stage membership so a method can compose it with companion-state admission. */
54
+ prepareAppend(row: readonly Cache[]): PreparedStateChange {
55
+ return this.prepareAppendMany([row]);
56
+ }
57
+
58
+ /** Stage several admissions with one membership operation per layer. */
59
+ prepareAppendMany(rows: readonly (readonly Cache[])[]): PreparedStateChange {
60
+ const next: Layout[] = [];
61
+ try {
62
+ for (let layer = 0; layer < this.caches.length; layer++) {
63
+ const layout = this.caches[layer]!;
64
+ const merged = layout.makeEmptyBatch();
65
+ next.push(merged);
66
+ merged.mergeRows([...(this.#rows ? [layout] : []), ...rows.map(row => row[layer]!)]);
67
+ }
68
+ } catch (error) { return cleanupFailure(error, () => disposeResources(next)); }
69
+ return {
70
+ commit: () => {
71
+ const previous = this.caches.splice(0, this.caches.length, ...next.splice(0));
72
+ this.#rows += rows.length;
73
+ next.push(...previous);
74
+ },
75
+ dispose: () => disposeResources(next.splice(0)),
76
+ };
77
+ }
78
+
79
+ /** The method calls this only between committed steps. A layer failure
80
+ * invalidates the group; its caller discards the state. */
81
+ filterRows(keep: readonly number[]): void {
82
+ if (!keep.length) { this.clear(); return; }
83
+ for (const layout of this.caches) layout.filterRows(keep);
84
+ this.#rows = keep.length;
85
+ }
86
+
87
+ /** Returns independent request state for a cache publisher or a new group. */
88
+ extractRow(row: number): Cache[] {
89
+ const state: Cache[] = [];
90
+ try { for (const layout of this.caches) state.push(layout.extractRow(row)); return state; }
91
+ catch (error) { return cleanupFailure(error, () => disposeResources(state)); }
92
+ }
93
+
94
+ clear(): void {
95
+ const next: Layout[] = [];
96
+ try { for (const layout of this.caches) next.push(layout.makeEmptyBatch()); }
97
+ catch (error) { return cleanupFailure(error, () => disposeResources(next)); }
98
+ const previous = this.caches.splice(0, this.caches.length, ...next);
99
+ this.#rows = 0;
100
+ disposeResources(previous);
101
+ }
102
+
103
+ dispose(): void { this.#rows = 0; disposeResources(this.caches); }
104
+ }
@@ -0,0 +1,46 @@
1
+ import type { StateView } from "../../contracts/resources";
2
+ import { disposeResources, ownResource } from "../../engine/resources";
3
+ import type { MlxArray } from "../../mlx/array";
4
+ import { isBatchableCache, type Cache } from "../../model/gemma4-base";
5
+ import { cloneKvCaches, type CacheCodecProvider } from "../../kv-store";
6
+
7
+ /** Compatibility boundary for legacy state(). Numerical code consumes a lease,
8
+ * never the legacy ownership marker. No copy, evaluation or fence is added. */
9
+ export function leaseCacheState(cache: Cache): StateView<MlxArray> {
10
+ return ownResource<readonly MlxArray[]>(cache.state(), cache.stateNeedsDispose ? disposeResources : () => {});
11
+ }
12
+
13
+ /** Preserve the existing prefill evaluation order: temporary views first,
14
+ * borrowed state second. Partial acquisition releases every acquired view. */
15
+ export function leaseCacheStates(caches: readonly Cache[]): StateView<MlxArray> {
16
+ const leases: StateView<MlxArray>[] = [];
17
+ const close = () => disposeResources(leases.map((lease) => ({ dispose: () => lease.close() })));
18
+ try {
19
+ for (const owned of [true, false]) {
20
+ for (const cache of caches) if (!!cache.stateNeedsDispose === owned) leases.push(leaseCacheState(cache));
21
+ }
22
+ return ownResource(leases.flatMap((lease) => [...lease.borrow()]), close);
23
+ } catch (error) {
24
+ try { close(); } catch (cleanupError) { throw new AggregateError([error, cleanupError], "state view acquisition failed"); }
25
+ throw error;
26
+ }
27
+ }
28
+
29
+ /** Precision/storage transitions constrain reuse independently of scheduling. */
30
+ export function minimumReusableOffset(caches: readonly Pick<Cache, "minimumReusableOffset">[]): number {
31
+ return Math.max(0, ...caches.map(cache => cache.minimumReusableOffset ?? 0));
32
+ }
33
+
34
+ /** Snapshot an adopted single-row state into persistence-compatible caches.
35
+ * Row layouts own compact extraction; ordinary serial caches use their codec. */
36
+ export function cloneSingleRowState(caches: readonly Cache[], codecs?: CacheCodecProvider): Cache[] {
37
+ const owned: Cache[] = [];
38
+ try {
39
+ for (const cache of caches) owned.push(...(isBatchableCache(cache)
40
+ ? [cache.extractRow(0)] : cloneKvCaches([cache], codecs)));
41
+ return owned;
42
+ } catch (error) {
43
+ try { disposeResources(owned); } catch (cleanupError) { throw new AggregateError([error, cleanupError], "single-row snapshot failed"); }
44
+ throw error;
45
+ }
46
+ }
@@ -0,0 +1,35 @@
1
+ import { Glm52Cache } from "../../model/glm52-cache";
2
+ import { SpeculativeRotatingKVCache } from "../../model/speculative-rotating-kv";
3
+ import { RotatingAffineLayout, SpeculativeRotatingAffineLayout } from "../../model/rotating-kv-layout";
4
+ import type { Cache } from "../../model/gemma4-base";
5
+ import { KVCache, QuantizedKVCache, TurboQuantKVCache, RotatingKVCache, RotatingQuantizedKVCache } from "../../model/gemma4-base";
6
+ import { DelayedRotatingQuantizedKVCache } from "../../model/delayed-rotating-quantized-kv";
7
+ import { DelayedQuantizedKVCache } from "../../model/delayed-quantized-kv";
8
+ import { DelayedTurboQuantKVCache } from "../../model/delayed-turboquant-kv";
9
+ import { SSMCache } from "../../model/qwen3-delta";
10
+ import { BatchedSSMCache } from "../../model/batched-ssm";
11
+ import { BatchedKVCache } from "../../model/batched-kv";
12
+ import { BatchedQuantizedKVCache } from "../../model/batched-quantized-kv";
13
+ import { BatchedTurboQuantKVCache } from "../../model/batched-turboquant-kv";
14
+
15
+ export type TargetRowLayout = Glm52Cache | DelayedRotatingQuantizedKVCache | RotatingAffineLayout | SpeculativeRotatingKVCache | BatchedKVCache | BatchedQuantizedKVCache | BatchedTurboQuantKVCache |
16
+ BatchedSSMCache | DelayedTurboQuantKVCache | DelayedQuantizedKVCache;
17
+
18
+ /** The storage binding advertises a row transaction factory. The gateway can
19
+ * compose supported model graphs without identifying their model family. */
20
+ export function targetRowLayoutFactory(cache: Cache): (() => TargetRowLayout) | undefined {
21
+ if (cache instanceof Glm52Cache) return () => cache.makeEmptyBatch();
22
+ if (cache instanceof DelayedRotatingQuantizedKVCache)
23
+ return () => new DelayedRotatingQuantizedKVCache(cache.maxSize, cache.groupSize, cache.bits, cache.start, cache.maintain, undefined, true);
24
+ if (cache instanceof RotatingAffineLayout || cache instanceof RotatingQuantizedKVCache)
25
+ return () => new SpeculativeRotatingAffineLayout(cache.maxSize, cache.groupSize, cache.bits);
26
+ if (cache instanceof RotatingKVCache || cache instanceof SpeculativeRotatingKVCache) return () => new SpeculativeRotatingKVCache(cache.maxSize);
27
+ if (cache instanceof DelayedTurboQuantKVCache || cache instanceof DelayedQuantizedKVCache ||
28
+ cache instanceof BatchedTurboQuantKVCache || cache instanceof BatchedKVCache ||
29
+ cache instanceof BatchedQuantizedKVCache || cache instanceof BatchedSSMCache) return () => cache.makeEmptyBatch();
30
+ if (cache instanceof TurboQuantKVCache) return () => new BatchedTurboQuantKVCache(cache.kBits, cache.vBits);
31
+ if (cache instanceof SSMCache) return () => new BatchedSSMCache();
32
+ if (cache instanceof QuantizedKVCache) return () => new BatchedQuantizedKVCache(cache.groupSize, cache.bits);
33
+ if (cache instanceof KVCache) return () => new BatchedKVCache();
34
+ return undefined;
35
+ }
@@ -0,0 +1,73 @@
1
+ import { createCompletionMethod } from "../../serve/session-completion-engine";
2
+ import type { ExecutionPlanner, InferenceEngine, Timer } from "../../contracts/generation";
3
+ import { createInferenceEngine, type EngineOptions } from "../../engine/engine";
4
+ import { throwIfCancelled } from "../../engine/cancellation";
5
+ import type { GenerateOptions, GenerateStats } from "../../generate";
6
+ import type { GenerationGateway, RequestShape } from "../../serve/generation-gateway";
7
+
8
+ /** Data-only API for text requests whose policy/shape was already
9
+ * resolved by the caller. Native request resources still belong to the prepared
10
+ * completion API; they are deliberately absent from this token API. */
11
+ export type TextGenerationOptions = Omit<GenerateOptions,
12
+ "signal" | "cache" | "grammar" | "fill" | "adapters" | "promptEmbeddings" |
13
+ "imageMask" | "multimodalMask" | "visionPixels" | "onPrefillDone" |
14
+ "onDecodeCheckpoint" | "initialPendingToken" | "initialGeneratedTokens" |
15
+ "originalPromptTokens" | "snapshotAt" | "checkpointEveryTokens"
16
+ >;
17
+
18
+ export interface TextGenerationRequest {
19
+ readonly promptIds: readonly number[];
20
+ readonly options: TextGenerationOptions;
21
+ readonly shape: RequestShape;
22
+ }
23
+
24
+ export const hostTimer: Timer = {
25
+ after(milliseconds, callback) {
26
+ const timer = setTimeout(callback, milliseconds);
27
+ return () => { clearTimeout(timer); };
28
+ },
29
+ };
30
+
31
+ /** Reuses the gateway's placement, exclusive lease, prompt cache, batching,
32
+ * and quant-specific execution. The portable session never imports them.
33
+ * Closing this engine cancels its sessions; it does not dispose a shared gateway. */
34
+ export function createTextInferenceEngine(
35
+ gateway: Pick<GenerationGateway, "place" | "run">,
36
+ options: Omit<EngineOptions, "timer"> & { timer?: Timer } = {},
37
+ ): InferenceEngine<TextGenerationRequest, GenerateStats> {
38
+ const planner: ExecutionPlanner<TextGenerationRequest, GenerateStats> = {
39
+ async plan(request, cancellation) {
40
+ throwIfCancelled(cancellation);
41
+ if (request.shape.hasVision || request.shape.hasAdapters || request.shape.hasGrammar)
42
+ throw new Error("native request resources require the prepared completion API");
43
+ const placement = gateway.place(request.shape, request.options);
44
+ const maxTokens = request.options.maxTokens ?? 512;
45
+ return {
46
+ id: `text:${placement.mechanism}`, outputTokenLimit: maxTokens,
47
+ method: createCompletionMethod(gateway, {
48
+ prompt: [...request.promptIds], options: request.options,
49
+ shape: request.shape, placement,
50
+ }),
51
+ };
52
+ },
53
+ };
54
+ const engine = createInferenceEngine(planner, { ...options, timer: options.timer ?? hostTimer });
55
+ return {
56
+ open(request, control) {
57
+ // Snapshot before demand-start: callers may reuse/mutate request arrays.
58
+ // TextGenerationOptions contains data only; no native handles or callbacks.
59
+ const snapshot = structuredClone(request);
60
+ if (!snapshot.promptIds.length || snapshot.promptIds.some((id) => !Number.isInteger(id) || id < 0 || id > 0xffffffff))
61
+ return Promise.reject(new Error("prompt must contain valid token ids"));
62
+ const maxTokens = snapshot.options.maxTokens ?? 512;
63
+ if (!Number.isSafeInteger(maxTokens) || maxTokens <= 0)
64
+ return Promise.reject(new Error("text generation requires a positive token limit"));
65
+ if ((snapshot.options.topLogprobs ?? 0) > (options.maxTopLogprobs ?? 20))
66
+ return Promise.reject(new Error("top logprobs exceed session delivery capacity"));
67
+ if (control.output === "collect" && (snapshot.options.logprobs || snapshot.options.topLogprobs))
68
+ return Promise.reject(new Error("token logprobs require stream consumption"));
69
+ return engine.open(snapshot, control);
70
+ },
71
+ close: () => engine.close(),
72
+ };
73
+ }