mlx-bun 0.0.13 → 0.3.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 (427) hide show
  1. package/README.md +71 -578
  2. package/bin/mlx-bun.mjs +1 -1
  3. package/docs/README.md +91 -0
  4. package/docs/{design → archive}/hlg-sampling.md +3 -3
  5. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  6. package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
  7. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  8. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  9. package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
  10. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  11. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  12. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
  13. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  14. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  15. package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
  16. package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
  17. package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
  18. package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
  19. package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
  20. package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
  21. package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
  22. package/docs/design/batching.md +569 -0
  23. package/docs/design/decode-speed-program.md +3178 -169
  24. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  25. package/docs/design/generic-model-support.md +579 -334
  26. package/docs/design/kv-cache.md +680 -0
  27. package/docs/design/orpo-training.md +673 -1239
  28. package/docs/design/speculative-decoding.md +1627 -0
  29. package/docs/design/turboquant.md +2102 -0
  30. package/docs/design/unified-engine-frontier-plan.md +1831 -727
  31. package/docs/design/web-chat-redesign.md +666 -1083
  32. package/docs/planning/PRODUCT_ROADMAP.md +34 -1
  33. package/docs/planning/release-notes-v0.3.0.md +35 -0
  34. package/docs/planning/video-series.md +421 -0
  35. package/docs/reference/benchmarks.md +1162 -0
  36. package/docs/reference/cli.md +395 -149
  37. package/docs/reference/distribution.md +321 -181
  38. package/docs/reference/environment.md +348 -0
  39. package/docs/reference/glossary.md +39 -0
  40. package/docs/reference/library-api.md +580 -142
  41. package/docs/reference/memory.md +227 -64
  42. package/docs/reference/models.md +137 -6
  43. package/docs/reference/server-api.md +938 -422
  44. package/docs/reference/server-config.md +652 -320
  45. package/docs/reference/training.md +393 -254
  46. package/docs/reference/troubleshooting.md +166 -0
  47. package/package.json +10 -5
  48. package/src/admission-plan.ts +18 -0
  49. package/src/anthropic.ts +92 -3
  50. package/src/audio/decode.ts +2 -2
  51. package/src/audio/features.ts +2 -2
  52. package/src/backends/mlx/autoregressive.ts +108 -0
  53. package/src/backends/mlx/batch-group.ts +1646 -0
  54. package/src/backends/mlx/diffusion.ts +39 -0
  55. package/src/backends/mlx/draft-target.ts +47 -0
  56. package/src/backends/mlx/evaluation.ts +105 -0
  57. package/src/backends/mlx/fill-append.ts +45 -0
  58. package/src/backends/mlx/gateway-binding.ts +71 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/memory-client.ts +189 -0
  61. package/src/backends/mlx/memory-guard.ts +40 -0
  62. package/src/backends/mlx/methods.ts +90 -0
  63. package/src/backends/mlx/model-prompt.ts +164 -0
  64. package/src/backends/mlx/model-serving.ts +79 -0
  65. package/src/backends/mlx/prefill.ts +33 -0
  66. package/src/backends/mlx/request-policy.ts +20 -0
  67. package/src/backends/mlx/rollback.ts +51 -0
  68. package/src/backends/mlx/serial-executor.ts +273 -0
  69. package/src/backends/mlx/speculative.ts +114 -0
  70. package/src/backends/mlx/state-views.ts +26 -0
  71. package/src/backends/mlx/text-engine.ts +73 -0
  72. package/src/cli.ts +189 -61
  73. package/src/client.ts +66 -0
  74. package/src/config.ts +21 -4
  75. package/src/contracts/completion.ts +16 -0
  76. package/src/contracts/execution.ts +49 -0
  77. package/src/contracts/generation.ts +103 -0
  78. package/src/contracts/host.ts +7 -0
  79. package/src/contracts/jobs.ts +66 -0
  80. package/src/contracts/pi-provider.ts +30 -0
  81. package/src/contracts/pi.ts +259 -0
  82. package/src/contracts/resources.ts +18 -0
  83. package/src/contracts/scheduling.ts +27 -0
  84. package/src/contracts/tsconfig.json +14 -0
  85. package/src/diffusion/diffusion-generate.ts +218 -153
  86. package/src/embed.ts +1 -1
  87. package/src/engine/admission.ts +59 -0
  88. package/src/engine/cancellation.ts +38 -0
  89. package/src/engine/engine.ts +56 -0
  90. package/src/engine/execution-coordinator.ts +70 -0
  91. package/src/engine/execution-plan.ts +51 -0
  92. package/src/engine/resources.ts +42 -0
  93. package/src/engine/scheduler.ts +67 -0
  94. package/src/engine/session.ts +247 -0
  95. package/src/eval/README.md +44 -1
  96. package/src/eval/kl.ts +263 -23
  97. package/src/eval/reference-logits.ts +207 -0
  98. package/src/eval/runner.ts +10 -79
  99. package/src/eval/tasks/bfcl.ts +2 -1
  100. package/src/eval/tasks/gsm8k.ts +2 -1
  101. package/src/eval/tasks/hashhop.ts +2 -1
  102. package/src/eval/tasks/humaneval.ts +5 -4
  103. package/src/eval/tasks/ifeval.ts +2 -1
  104. package/src/eval/tasks/mmlu.ts +2 -1
  105. package/src/expert-io.ts +3 -1
  106. package/src/expert-offload.ts +3 -1
  107. package/src/fill/echo-index.ts +188 -0
  108. package/src/fill/fill-session.ts +452 -0
  109. package/src/fill/proposal.ts +68 -0
  110. package/src/fill/schema-rows.ts +506 -0
  111. package/src/fill/tool-boundary.ts +103 -0
  112. package/src/fit.ts +24 -43
  113. package/src/generate.ts +740 -337
  114. package/src/grammar.ts +14 -8
  115. package/src/harness-pi.ts +15 -34
  116. package/src/hub-rest.ts +4 -4
  117. package/src/index.ts +27 -0
  118. package/src/inference/denoising.ts +17 -0
  119. package/src/inference/graph.ts +33 -0
  120. package/src/inference/prefill.ts +39 -0
  121. package/src/inference/rollback.ts +7 -0
  122. package/src/jobs/db.ts +4 -0
  123. package/src/jobs/index.ts +2 -0
  124. package/src/jobs/job-entry.ts +15 -14
  125. package/src/jobs/runner.ts +98 -13
  126. package/src/jobs/task-client.ts +19 -0
  127. package/src/jobs/types.ts +2 -58
  128. package/src/kv-scheme.ts +199 -0
  129. package/src/kv-store.ts +459 -234
  130. package/src/lab/README.md +18 -0
  131. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  132. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  133. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
  134. package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
  135. package/src/library.ts +40 -0
  136. package/src/lora.ts +18 -0
  137. package/src/media-fetch.ts +20 -4
  138. package/src/memory/article.ts +1 -1
  139. package/src/memory/chunk.ts +1 -1
  140. package/src/memory/model.ts +32 -170
  141. package/src/memory/prompts.ts +1 -1
  142. package/src/memory/rest.ts +1 -1
  143. package/src/memory/schedule.ts +1 -1
  144. package/src/memory/stages.ts +4 -1
  145. package/src/memory/vault.ts +3 -4
  146. package/src/mlx/array.ts +9 -10
  147. package/src/mlx/compile.ts +12 -2
  148. package/src/mlx/ffi.ts +66 -22
  149. package/src/mlx/materialize.ts +23 -0
  150. package/src/mlx/metal-kernel.ts +10 -11
  151. package/src/mlx/ops.ts +64 -19
  152. package/src/mlx/quantized-rows.ts +36 -0
  153. package/src/mlx/token-bitmask.ts +52 -0
  154. package/src/mlx/turboquant-kv-decode.ts +82 -0
  155. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  156. package/src/mlx/turboquant-ops.ts +33 -3
  157. package/src/mlx/turboquant-tables.ts +2 -2
  158. package/src/model/batched-mask.ts +9 -3
  159. package/src/model/batched-quant.ts +2 -2
  160. package/src/model/batched-rotating-quant.ts +45 -99
  161. package/src/model/batched-rotating-state.ts +73 -0
  162. package/src/model/batched-rotating.ts +57 -106
  163. package/src/model/batched-row-storage.ts +127 -0
  164. package/src/model/compiled-decode.ts +4 -3
  165. package/src/model/diffusion-gemma.ts +8 -8
  166. package/src/model/factory.ts +87 -49
  167. package/src/model/fingerprint.ts +1 -1
  168. package/src/model/flash-attention.ts +3 -3
  169. package/src/model/gemma4-base.ts +187 -17
  170. package/src/model/gemma4.ts +6 -6
  171. package/src/model/generated/gemma4-12b.ts +52 -148
  172. package/src/model/generated/gemma4-26b.ts +34 -94
  173. package/src/model/generated/gemma4-e4b.ts +28 -76
  174. package/src/model/glm52-cache.ts +19 -9
  175. package/src/model/glm52-dsa.ts +13 -9
  176. package/src/model/glm52-memory.ts +28 -1
  177. package/src/model/implementation.ts +69 -0
  178. package/src/model/minicpm5.ts +7 -8
  179. package/src/model/profile.ts +443 -0
  180. package/src/model/qwen-append.ts +12 -0
  181. package/src/model/qwen-conv.ts +52 -0
  182. package/src/model/qwen3-delta.ts +98 -2
  183. package/src/model/qwen3-mrope.ts +252 -0
  184. package/src/model/qwen3_5-checkpoint.ts +164 -0
  185. package/src/model/qwen3_5.ts +336 -60
  186. package/src/model/support.ts +1 -1
  187. package/src/model/trellis-balanced-scatter.ts +51 -0
  188. package/src/model/trellis-linear.ts +672 -0
  189. package/src/model/trellis-shared-m.ts +151 -0
  190. package/src/model/trellis-shared-scatter.ts +144 -0
  191. package/src/model/trellis-splitk-prefill.ts +158 -0
  192. package/src/model/trellis-tiled-prefill.ts +136 -0
  193. package/src/model/trellis-vector-expand.ts +62 -0
  194. package/src/model/trellis-wide-prefill.ts +94 -0
  195. package/src/model/universal/dense.ts +1 -1
  196. package/src/model/universal/modules.ts +8 -1
  197. package/src/native/frame_extract.swift +140 -0
  198. package/src/native-pack.ts +15 -7
  199. package/src/pi-provider.ts +6 -64
  200. package/src/pi-web.ts +14 -320
  201. package/src/prompt-cache.ts +97 -54
  202. package/src/quantize/allocator.ts +1 -1
  203. package/src/quantize/atomic-output.ts +38 -0
  204. package/src/quantize/calibration.ts +2 -1
  205. package/src/quantize/config-writer.ts +16 -3
  206. package/src/quantize/index.ts +28 -1
  207. package/src/quantize/job.ts +11 -0
  208. package/src/quantize/quantizer.ts +265 -100
  209. package/src/quantize/rotate.ts +603 -0
  210. package/src/quantize/safetensors-writer.ts +79 -1
  211. package/src/quantize/sensitivity.ts +41 -59
  212. package/src/quantize/trellis.ts +586 -0
  213. package/src/quantize/weight-transform.ts +292 -0
  214. package/src/responses.ts +130 -3
  215. package/src/runtime-config.ts +81 -0
  216. package/src/sampler.ts +276 -4
  217. package/src/serve/admin-routes.ts +184 -0
  218. package/src/serve/aux-routes.ts +132 -0
  219. package/src/serve/batch-scheduler.ts +8 -1558
  220. package/src/serve/chat-request.ts +391 -0
  221. package/src/serve/chat-stage.ts +195 -0
  222. package/src/serve/checkpoint-identity.ts +64 -0
  223. package/src/serve/completion-executor.ts +354 -0
  224. package/src/serve/completion-sink.ts +157 -0
  225. package/src/serve/discovery-routes.ts +204 -0
  226. package/src/serve/generation-gateway.ts +211 -243
  227. package/src/serve/http.ts +159 -0
  228. package/src/serve/inference-request.ts +79 -0
  229. package/src/serve/isolate.ts +297 -105
  230. package/src/serve/kv-budget.ts +14 -0
  231. package/src/serve/lab-routes.ts +341 -0
  232. package/src/serve/lane-registry.ts +2 -1
  233. package/src/serve/model-admin-routes.ts +155 -0
  234. package/src/serve/model-binding.ts +43 -0
  235. package/src/serve/model-host.ts +512 -0
  236. package/src/serve/openai-wire.ts +103 -0
  237. package/src/serve/parent-application.ts +56 -0
  238. package/src/serve/pipeline.ts +33 -0
  239. package/src/serve/preparation.ts +33 -0
  240. package/src/serve/prompt-response-trace.ts +147 -0
  241. package/src/serve/request-plan.ts +162 -0
  242. package/src/serve/request-prep.ts +346 -0
  243. package/src/serve/response-lease.ts +24 -0
  244. package/src/serve/responses-client.ts +69 -0
  245. package/src/serve/session-completion-engine.ts +110 -0
  246. package/src/serve/session-search.ts +1 -1
  247. package/src/serve/static-routes.ts +101 -0
  248. package/src/serve/text-completion-stage.ts +104 -0
  249. package/src/serve/token-streams.ts +519 -0
  250. package/src/server.ts +523 -3551
  251. package/src/spec/assistant-source.ts +10 -44
  252. package/src/spec/deepspec-source.ts +6 -6
  253. package/src/spec/dflash-source.ts +9 -8
  254. package/src/spec/dspark/ab-stats.ts +3 -3
  255. package/src/spec/dspark/calibration.ts +2 -2
  256. package/src/spec/dspark/deepspec-module.ts +2 -2
  257. package/src/spec/dspark/generate-dflash.ts +2 -2
  258. package/src/spec/dspark/generate.ts +2 -2
  259. package/src/spec/dspark/loader.ts +1 -1
  260. package/src/spec/dspark/module-dflash.ts +5 -4
  261. package/src/spec/dspark/module.ts +3 -3
  262. package/src/spec/dspark/quantize-drafter.ts +1 -1
  263. package/src/spec/generate.ts +1 -1
  264. package/src/spec/glm52-mtp-source.ts +9 -1
  265. package/src/spec/ngram-source.ts +1 -1
  266. package/src/spec/prefix-state.ts +45 -0
  267. package/src/spec/qwen-mtp-source.ts +528 -0
  268. package/src/spec/serve-loop.ts +179 -213
  269. package/src/spec/source.ts +42 -10
  270. package/src/spec/two-model.ts +1 -1
  271. package/src/ssd-cache.ts +95 -24
  272. package/src/ssd-durability.ts +207 -0
  273. package/src/tool-call.ts +51 -14
  274. package/src/train/flash-cce.ts +14 -13
  275. package/src/train/forward.ts +38 -1
  276. package/src/train/loss.ts +3 -2
  277. package/src/train/prefix-shared.ts +5 -1
  278. package/src/train/segmented.ts +9 -6
  279. package/src/train/trainer.ts +9 -8
  280. package/src/vision/preprocess.ts +1 -1
  281. package/src/vision/prompt.ts +48 -2
  282. package/src/vision/qwen3vl-preprocess.ts +409 -0
  283. package/src/vision/qwen3vl-prompt.ts +196 -0
  284. package/src/vision/qwen3vl-tower.ts +555 -0
  285. package/src/vision/video-frames.ts +148 -0
  286. package/src/web/app.html +1 -1
  287. package/src/web/app.js +15 -6
  288. package/src/web/src/adapters-panel.ts +3 -3
  289. package/src/web/src/assistant.ts +2 -36
  290. package/src/web/src/chat.ts +16 -9
  291. package/src/web/src/composer.ts +4 -4
  292. package/src/web/src/hub.ts +1 -1
  293. package/src/web/src/markdown.ts +0 -0
  294. package/src/web/src/memory-panel.ts +1 -1
  295. package/src/web/src/model-picker.ts +1 -1
  296. package/src/web/src/palette.ts +1 -1
  297. package/src/web/src/protocol.ts +3 -39
  298. package/src/web/src/sessions.ts +1 -1
  299. package/src/web/src/ui-catalog.ts +4 -18
  300. package/src/web-assets.ts +47 -0
  301. package/src/weights.ts +134 -33
  302. package/docs/archive/mlx-bun-lab-report.html +0 -275
  303. package/docs/archive/wwdc-mlx-bun.html +0 -848
  304. package/docs/design/adapters-end-to-end.md +0 -205
  305. package/docs/design/batching-perf-path.md +0 -255
  306. package/docs/design/batching-v2-plan.md +0 -529
  307. package/docs/design/bucketing-stage.md +0 -197
  308. package/docs/design/compat-cli-surface-design.md +0 -230
  309. package/docs/design/docs-reorg-plan.md +0 -165
  310. package/docs/design/dspark-serving-program.md +0 -371
  311. package/docs/design/dspark-speculative-decoding.md +0 -268
  312. package/docs/design/grammar-spec-batching-integration.md +0 -301
  313. package/docs/design/memory-inference-path.md +0 -422
  314. package/docs/design/memory-synthesis.md +0 -287
  315. package/docs/design/memory-system.md +0 -237
  316. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  317. package/docs/design/omlx-adoption-map.md +0 -98
  318. package/docs/design/orpo-dynamic-lambda.md +0 -220
  319. package/docs/design/orpo-future-enhancements.md +0 -340
  320. package/docs/design/paged-kv-cache.md +0 -214
  321. package/docs/design/parallel-slots.md +0 -567
  322. package/docs/design/parity-tier-dag.md +0 -161
  323. package/docs/design/repo-cleanup-plan.md +0 -189
  324. package/docs/design/runtime-isolation.md +0 -263
  325. package/docs/design/segmented-backward-training.md +0 -543
  326. package/docs/design/spec-decode-larger-targets.md +0 -229
  327. package/docs/design/ssd-kv-cold-tier.md +0 -288
  328. package/docs/design/structured-output.md +0 -484
  329. package/docs/design/tauri-desktop-app.md +0 -127
  330. package/docs/design/the-dreaming-master-plan.md +0 -445
  331. package/docs/design/turboquant-kv.md +0 -235
  332. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  333. package/docs/design/web-chat-beat-matrix.md +0 -315
  334. package/docs/design/write-pipeline-entity.md +0 -468
  335. package/docs/investigations/curve-runs/bisector-route.json +0 -98
  336. package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
  337. package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
  338. package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
  339. package/docs/investigations/hlg-ab.html +0 -34
  340. package/docs/investigations/hlg-explorer.html +0 -238
  341. package/docs/investigations/hlg-figs/cliff.svg +0 -1
  342. package/docs/investigations/hlg-figs/cross.svg +0 -1
  343. package/docs/investigations/hlg-figs/edges.svg +0 -1
  344. package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
  345. package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
  346. package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
  347. package/docs/investigations/hlg-figs/terrain.svg +0 -1
  348. package/docs/investigations/hlg-report.html +0 -262
  349. package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
  350. package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  351. package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
  352. package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
  353. package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
  354. package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
  355. package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
  356. package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
  357. package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
  358. package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
  359. package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  360. package/docs/investigations/hlg-runs/hlg-map.json +0 -383
  361. package/docs/investigations/hlg-runs/run0-original.log +0 -159
  362. package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
  363. package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  364. package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  365. package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  366. package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  367. package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  368. package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  369. package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  370. package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
  371. package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
  372. package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
  373. package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
  374. package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
  375. package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  376. package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
  377. package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
  378. package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
  379. package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
  380. package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
  381. package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  382. package/docs/investigations/hlg-runs/runN-verify.log +0 -116
  383. package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  384. package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  385. package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  386. package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  387. package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  388. package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  389. package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
  390. package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  391. package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
  392. package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  393. package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  394. package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  395. package/docs/planning/IDEAS.md +0 -69
  396. package/docs/reference/embedding.md +0 -197
  397. package/docs/reference/features-matrix.md +0 -100
  398. package/docs/reference/orpo-quickstart.md +0 -135
  399. package/src/flags.ts +0 -13
  400. /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
  401. /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
  402. /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
  403. /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
  404. /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
  405. /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
  406. /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
  407. /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
  408. /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
  409. /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
  410. /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
  411. /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
  412. /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
  413. /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
  414. /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
  415. /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
  416. /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
  417. /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
  418. /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
  419. /package/docs/{planning → archive/planning}/journal.md +0 -0
  420. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  421. /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
  422. /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
  423. /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
  424. /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
  425. /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
  426. /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
  427. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -0,0 +1,166 @@
1
+ # Troubleshooting
2
+
3
+ Symptom → cause → fix, for the problems users actually hit. Every path and
4
+ flag below is taken from the code (`src/`) or the linked reference doc; when a
5
+ sentence here disagrees with the code, the code wins — fix the doc.
6
+
7
+ Related: [cli.md](./cli.md) (commands), [server-config.md](./server-config.md)
8
+ (serve flags, admission), [distribution.md](./distribution.md) (install paths,
9
+ signing), [docs/reference/distribution.md](./distribution.md) (sidecar layout, self-signing),
10
+ [environment.md](./environment.md) (contributor/agent platform facts).
11
+
12
+ ## Runtime and install
13
+
14
+ ### `dlopen` fails / `libmlxc.dylib` not found
15
+
16
+ **Cause.** The `mlx-bun` executable ships without the MLX native runtime
17
+ (`libmlxc.dylib`, `libmlx.dylib`, `libjaccl.dylib`, `mlx.metallib`, plus the
18
+ expert-IO dylib and frame-extract helper — the list is `NATIVE_PACK_FILES` in
19
+ `src/native-pack.ts`). The runtime is a versioned tarball downloaded on first
20
+ run into `~/Library/Caches/mlx-bun/native-v<ver>-<arch>/`. The download is
21
+ resumable and sha256-verified through the same machinery as model downloads
22
+ (`src/download.ts`), so an interrupted first run leaves a partial file, not a
23
+ broken install.
24
+
25
+ **Fix.** Rerun `mlx-bun serve` (or any command that loads the runtime); it
26
+ resumes and verifies. The library is resolved in this order
27
+ (`resolveLibmlxc()` in `src/mlx/ffi.ts`, mirrored by `nativeRuntimeDir()` in
28
+ `src/native-pack.ts`):
29
+
30
+ 1. `MLX_BUN_LIBMLXC=/path/to/libmlxc.dylib` — explicit override; the other
31
+ libs are expected in the same directory.
32
+ 2. Beside the executable (the sidecar layout from `docs/reference/distribution.md`).
33
+ 3. The native-pack cache dir above.
34
+ 4. Homebrew: `/opt/homebrew/lib`, then `/usr/local/lib`.
35
+
36
+ To use your own build, set `MLX_BUN_LIBMLXC`. If you see
37
+ `no native pack published for <arch> — set MLX_BUN_LIBMLXC or install mlx via
38
+ homebrew`, there is no published pack for that CPU architecture (only `arm64`
39
+ has a baked checksum in `src/native-pack.ts`); use one of the two escapes in
40
+ the message. `MLX_BUN_NATIVE_PACK_URL` overrides the download URL.
41
+
42
+ ### Gatekeeper: "unidentified developer" / app can't be opened
43
+
44
+ **Cause.** Released binaries are Developer-ID signed and notarized. macOS only
45
+ checks the notarization ticket when a file carries the `com.apple.quarantine`
46
+ xattr, which browser downloads and `curl -O`-style saves get. Homebrew installs
47
+ and the documented `curl ... | tar -xz` one-liner never write a quarantined
48
+ file, so they never prompt (`distribution.md`, "Direct download").
49
+
50
+ **Fix.**
51
+ - Online: the notarization ticket resolves the check; allow it once.
52
+ - Offline: `xattr -d com.apple.quarantine mlx-bun` (the manual escape hatch
53
+ from `distribution.md`).
54
+ - Self-built binary: the bundle's dylibs must be (re)signed with the hardened
55
+ runtime and entitlements — see "Signing & notarization" in
56
+ [docs/reference/distribution.md](./distribution.md).
57
+
58
+ ### Wrong Bun version / `Bun.Image` missing / FFI crashes in a source checkout
59
+
60
+ **Cause.** `package.json` pins `"bun": ">=1.4.0"`. Two things depend on it:
61
+ `Bun.Image` is the vision decode path (`src/vision/preprocess.ts`), and Bun
62
+ 1.4 fixed a `bun:ffi` stack-argument ABI bug on macOS arm64 that made
63
+ multi-argument mlx-c bindings hand the callee shifted garbage
64
+ (`lab/repro/bun-ffi-stack-args/ISSUE.md`; the code now uses natural mlx-c
65
+ signatures with no workaround).
66
+
67
+ **Fix.** `bun upgrade`, then `bun --version` ≥ 1.4.0. The compiled release
68
+ binary embeds its own Bun, so this only affects running from source.
69
+
70
+ ### `port 8080 is already serving …`
71
+
72
+ **Cause.** `serve` probes the port before loading weights and refuses to start
73
+ a second server on a port that already answers `/v1` (`src/cli.ts`, serve
74
+ branch; `--port` row in `server-config.md`).
75
+
76
+ **Fix.** Reuse the running server (`mlx-bun pi` attaches automatically), stop
77
+ it, or pass `--port <other>`. A second server is a second model in memory;
78
+ check `mlx-bun fit` first.
79
+
80
+ ## Models and downloads
81
+
82
+ ### `no models match (try \`mlx-bun scan\`)`
83
+
84
+ **Cause.** `ls`/`serve`/`fit` resolve models from a registry built by scanning
85
+ the Hugging Face hub cache. The registry is stale or empty, or the model is
86
+ not in the cache directory the registry reads.
87
+
88
+ **Fix.** Run `mlx-bun scan` after downloading. The cache path is resolved
89
+ exactly as `huggingface_hub` does (`DEFAULT_HUB` in `src/registry.ts`):
90
+ `HF_HUB_CACHE`, else `HF_HOME/hub`, else `~/.cache/huggingface/hub`. If you
91
+ downloaded to a custom location, set the same env var for `mlx-bun`. The
92
+ registry database lives at `~/.cache/mlx-bun/registry.sqlite`.
93
+
94
+ ### Hugging Face download stalls at 0%
95
+
96
+ **Cause.** The Python `hf` downloader uses the Xet transfer path, which stalls
97
+ on some networks.
98
+
99
+ **Fix.** Use `mlx-bun get <org/repo>` — it speaks plain HTTPS resolve/CDN with
100
+ no Xet, Range-resumes partial blobs, and verifies every file (sha256 for LFS
101
+ blobs, git-blob sha1 for small files) into the standard hub cache layout
102
+ (`src/download.ts`). Rerunning the same command resumes verified
103
+ `.incomplete` prefixes. If you must use the Python CLI, set
104
+ `HF_HUB_DISABLE_XET=1` before the download command.
105
+
106
+ ### `get` refuses for lack of disk space
107
+
108
+ **Cause.** Before transferring, `get` credits complete blobs and partial
109
+ prefixes, then requires free space for the exact remainder plus a fixed 1 GiB
110
+ reserve (`cli.md`, `get`).
111
+
112
+ **Fix.** Free space, or point `HF_HUB_CACHE` at a larger volume before
113
+ starting.
114
+
115
+ ### Gated repo: 401/403 from Hugging Face
116
+
117
+ **Cause.** No token. `get` reads `HF_TOKEN`, else
118
+ `~/.cache/huggingface/token` (`hfToken()` in `src/download.ts`).
119
+
120
+ **Fix.** `hf auth login`, or export `HF_TOKEN`.
121
+
122
+ ## Memory and performance
123
+
124
+ ### Will it fit? / decode is very slow on a model near the RAM ceiling
125
+
126
+ **Cause.** A model whose weights plus KV cache exceed the wired-memory budget
127
+ pages weights every token. The default budget is machine RAM × 0.75
128
+ (`WIRED_FRACTION` in `src/fit.ts`; `--memory-budget` in `server-config.md`).
129
+
130
+ **Fix.** Check first:
131
+
132
+ ```sh
133
+ mlx-bun fit <model> --ctx 8192 # this machine
134
+ mlx-bun fit <model> --ctx 8192 --skus # across the Apple Silicon lineup
135
+ mlx-bun fit <model> --kv-quant 4 # window with a 4-bit KV cache
136
+ ```
137
+
138
+ `fit` reports weights bytes (from safetensors headers), KV bytes/token, the
139
+ calibrated prefill transient, and the wired ceiling. Then close memory-heavy
140
+ apps, pick a smaller quantization, or serve with `--kv-quant 4|8` for a larger
141
+ context window in the same budget. GLM-5.2 uses its own streamed-runtime plan
142
+ (`fit GLM-5.2`; `--context-length`), not the resident-weights estimator.
143
+
144
+ ### Completion stops before my `max_tokens` (no error)
145
+
146
+ **Cause.** This is memory admission clamping, not a bug. When the prompt fits
147
+ but the client's `max_tokens` would push the reservation past the safe
148
+ context, the server caps `max_tokens` to the remaining room and proceeds
149
+ (`admitRequestContext()` in `src/server.ts`: `max_tokens` is a ceiling, not a
150
+ promise). Earlier versions returned 400 for this case; the clamp shipped for
151
+ GLM-5.2 fixed-context serving in v0.0.13 and for all memory admission in
152
+ v0.2.0 (`docs/archive/planning/release-notes-v0.2.0.md`).
153
+
154
+ **Fix.** Nothing is required. To get more room: shorten the prompt, raise
155
+ `--memory-budget` if the machine allows, or serve with `--kv-quant 4|8`. The
156
+ current ceiling is visible at `/stats` (`context_tokens`).
157
+
158
+ ### `400` with `"type": "memory_admission"`, `"code": "context_over_budget"`
159
+
160
+ **Cause.** The prompt alone leaves no generation slot inside the safe context.
161
+ Only this case is rejected; the alternative is an uncatchable GPU OOM
162
+ (`server-api.md`, error table; `--memory-budget` in `server-config.md`).
163
+
164
+ **Fix.** Same levers as above: shorter prompt, larger budget, quantized KV.
165
+ The server never refuses to *start* over budget — a budget too small for any
166
+ context logs a warning and serves, and requests then get this 400.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mlx-bun",
3
- "version": "0.0.13",
3
+ "version": "0.3.0",
4
4
  "description": "Native MLX inference for Bun on Apple Silicon — local LLM server (OpenAI/Anthropic-compatible) and TypeScript library. No Python.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,7 +26,9 @@
26
26
  },
27
27
  "exports": {
28
28
  ".": "./src/index.ts",
29
- "./package.json": "./package.json"
29
+ "./package.json": "./package.json",
30
+ "./engine": "./src/library.ts",
31
+ "./client": "./src/client.ts"
30
32
  },
31
33
  "files": [
32
34
  "bin",
@@ -37,7 +39,7 @@
37
39
  "THIRD_PARTY_LICENSES.md"
38
40
  ],
39
41
  "engines": {
40
- "bun": ">=1.3.14"
42
+ "bun": ">=1.4.0"
41
43
  },
42
44
  "os": [
43
45
  "darwin"
@@ -47,16 +49,19 @@
47
49
  ],
48
50
  "scripts": {
49
51
  "test": "bash scripts/test.sh",
52
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.web.json --noEmit && tsc -p src/contracts/tsconfig.json --noEmit",
50
53
  "link-cli": "chmod +x src/cli.ts && ln -sf $PWD/src/cli.ts $HOME/.bun/bin/mlx-bun && mlx-bun --version",
51
54
  "build:binary": "sh scripts/build-binary.sh",
52
55
  "release": "PUBLISH=1 sh scripts/release-binary.sh",
53
- "publish:npm": "bun publish"
56
+ "publish:npm": "bun publish",
57
+ "clean": "bun scripts/clean.ts"
54
58
  },
55
59
  "devDependencies": {
56
60
  "@anthropic-ai/sdk": "^0.104.1",
57
61
  "@types/bun": "^1.3.14",
58
62
  "happy-dom": "^20.10.6",
59
- "openai": "^6.42.0"
63
+ "openai": "^6.42.0",
64
+ "typescript": "6.0.3"
60
65
  },
61
66
  "dependencies": {
62
67
  "@earendil-works/pi-ai": "0.80.3",
@@ -0,0 +1,18 @@
1
+ /** Common admission contract for every runtime. Representation-specific
2
+ * planners may expose richer fields, but serving consumes only this shape. */
3
+ export interface MemoryPlan {
4
+ readonly schemaVersion: 1;
5
+ readonly strategy: "generic-kv" | "glm52-colibri";
6
+ readonly fits: boolean;
7
+ readonly contextTokens: number;
8
+ readonly maxSafeContext: number;
9
+ readonly weightsBytes: number;
10
+ readonly kvBytes: number;
11
+ readonly transientBytes: number;
12
+ readonly reserveBytes: number;
13
+ readonly totalBytes: number;
14
+ readonly usableBytes: number;
15
+ readonly predictedDecodeTps: number | null;
16
+ /** mlx allocator-cache limit, distinct from the process admission limit. */
17
+ readonly allocatorLimitBytes?: number;
18
+ }
package/src/anthropic.ts CHANGED
@@ -23,6 +23,10 @@
23
23
  // semantics) instead of the oracle's json.dumps fallback.
24
24
 
25
25
  import type { ChatMessage, ToolDefinition } from "./chat-template";
26
+ import type {
27
+ CompletionEvent,
28
+ CompletionStreamProtocol,
29
+ } from "./serve/completion-sink";
26
30
 
27
31
  // ---------------------------------------------------------------------
28
32
  // Request translation: Anthropic → OpenAI (our ChatRequest shape)
@@ -128,7 +132,15 @@ export function anthropicToChatBody(body: AnthropicRequest): Record<string, unkn
128
132
  break; // prior-turn thinking is not re-fed (Anthropic semantics)
129
133
  case "image": {
130
134
  const part = imagePartFromBlock(block);
131
- if (part) imageParts.push(part);
135
+ if (!part)
136
+ // e.g. a Files-API {type:"file"} source we cannot fetch —
137
+ // reject loudly, never answer about an image the model can't
138
+ // see (2026-08-18 review; the audio-doctrine below).
139
+ throw new Error(
140
+ `unsupported image source "${block.source?.type ?? "missing"}" — ` +
141
+ `send base64 or url image sources`,
142
+ );
143
+ imageParts.push(part);
132
144
  break;
133
145
  }
134
146
  case "tool_use":
@@ -141,15 +153,52 @@ export function anthropicToChatBody(body: AnthropicRequest): Record<string, unkn
141
153
  },
142
154
  });
143
155
  break;
144
- case "tool_result":
156
+ case "tool_result": {
145
157
  // Anthropic packs tool results into the next user message;
146
158
  // OpenAI (and the gemma template) want role:"tool" messages.
159
+ // Nested image blocks (screenshot-returning tools — the
160
+ // computer-use shape) are PRESERVED as image parts: flattening
161
+ // them away had the model answering about screenshots it never
162
+ // saw (2026-08-18 review). An unrenderable pairing downstream
163
+ // fails loudly on the media-count check, never silently.
164
+ const trImages: Record<string, unknown>[] = [];
165
+ if (Array.isArray(block.content)) {
166
+ for (const b of block.content as AnthropicContentBlock[]) {
167
+ if (b && typeof b === "object" && b.type === "image") {
168
+ const part = imagePartFromBlock(b);
169
+ if (!part)
170
+ throw new Error(
171
+ `unsupported image source "${b.source?.type ?? "missing"}" ` +
172
+ `in tool_result — send base64 or url image sources`,
173
+ );
174
+ trImages.push(part);
175
+ }
176
+ }
177
+ }
178
+ const txt = flattenText(block.content);
147
179
  messages.push({
148
180
  role: "tool",
149
181
  tool_call_id: block.tool_use_id,
150
- content: flattenText(block.content),
182
+ content: trImages.length
183
+ ? [
184
+ ...(txt ? [{ type: "text", text: txt }] : []),
185
+ ...trImages,
186
+ ] as never
187
+ : txt,
151
188
  });
152
189
  break;
190
+ }
191
+ case "video":
192
+ case "video_url":
193
+ // Not an Anthropic Messages block type — reject loudly instead of
194
+ // silently answering about a video the model never saw (same
195
+ // doctrine as audio below; the OpenAI surface serves video on
196
+ // Qwen3.5-family models).
197
+ throw new Error(
198
+ `"${block.type}" content blocks are not part of the Anthropic ` +
199
+ `Messages protocol — send video to the OpenAI endpoint ` +
200
+ `/v1/chat/completions as a video_url content part`,
201
+ );
153
202
  case "audio":
154
203
  case "input_audio":
155
204
  case "audio_url":
@@ -168,6 +217,11 @@ export function anthropicToChatBody(body: AnthropicRequest): Record<string, unkn
168
217
  }
169
218
  }
170
219
  if (role === "assistant") {
220
+ if (imageParts.length)
221
+ // Assistants don't produce images in the Anthropic protocol; a
222
+ // client that puts one here would previously have it silently
223
+ // discarded (2026-08-18 review — loud beats silent).
224
+ throw new Error("image content blocks are not supported in assistant messages");
171
225
  const msg: ChatMessage = { role, content: textParts.join("\n") || null };
172
226
  if (toolCalls.length) msg.tool_calls = toolCalls;
173
227
  if (msg.content || toolCalls.length) messages.push(msg);
@@ -457,6 +511,41 @@ export class AnthropicStreamTranslator {
457
511
  }
458
512
  }
459
513
 
514
+ /** Direct semantic-event adapter used by the server. This avoids encoding
515
+ * OpenAI SSE only to parse those bytes back into protocol events. */
516
+ export function createAnthropicStreamProtocol(model: string): CompletionStreamProtocol {
517
+ const translator = new AnthropicStreamTranslator(model);
518
+ const chunk = (delta: Record<string, unknown>) => ({ choices: [{ delta }] });
519
+ return {
520
+ start: () => translator.addChunk(chunk({ role: "assistant", content: "" })),
521
+ addEvents(events: CompletionEvent[]) {
522
+ return events.flatMap((event) => {
523
+ if (event.type === "reasoning") {
524
+ return translator.addChunk(chunk({ reasoning: event.text }));
525
+ }
526
+ if (event.type === "content") {
527
+ return translator.addChunk(chunk({ content: event.text }));
528
+ }
529
+ return translator.addChunk(chunk({
530
+ tool_calls: event.calls.map((call, index) => ({ index, ...call })),
531
+ }));
532
+ });
533
+ },
534
+ finish(reason, usage) {
535
+ return [
536
+ ...translator.addChunk({ choices: [{ delta: {}, finish_reason: reason }], usage }),
537
+ ...translator.finalize(),
538
+ ];
539
+ },
540
+ error(message) {
541
+ return [sse("error", {
542
+ type: "error",
543
+ error: { type: "api_error", message },
544
+ })];
545
+ },
546
+ };
547
+ }
548
+
460
549
  /** Wrap our OpenAI SSE byte stream as an Anthropic SSE byte stream.
461
550
  * Frames translate as they arrive (per-chunk flush preserved — the
462
551
  * upstream already rate-limits socket flushes). */
@@ -1,9 +1,9 @@
1
- // WAV decode for audio input (A1 of docs/design/audio-input-plan.md).
1
+ // WAV decode for audio input (A1 of docs/design/generic-model-support.md).
2
2
  //
3
3
  // Scope: RIFF/WAVE containers — PCM 16/24/32-bit and IEEE float32, any
4
4
  // channel count (mean mixdown), any sample rate (linear resample to 16 kHz).
5
5
  // PCM16 scales by 1/32768 to match the oracle golden generator
6
- // (scripts/gen-e4b-audio-golden.py) exactly. Non-WAV containers (mp3/m4a/
6
+ // (scripts/oracle/gen-e4b-audio-golden.py) exactly. Non-WAV containers (mp3/m4a/
7
7
  // flac/ogg) are transcoded to WAV by the serve layer via macOS `afconvert`
8
8
  // before reaching this parser.
9
9
  //
@@ -1,9 +1,9 @@
1
1
  // USM log-mel feature extraction for gemma-4 audio — a verbatim-semantics
2
2
  // port of the oracle's Gemma4AudioFeatureExtractor (optiq/vlm/_mlxvlm/
3
3
  // models/gemma4/audio_feature_extractor.py, constructor DEFAULTS — §3.3 Q3
4
- // of docs/design/audio-input-plan.md: no per-bin normalization, params are
4
+ // of docs/design/generic-model-support.md: no per-bin normalization, params are
5
5
  // fixed for all gemma-4 models). Gated bit-close against the T0 mel goldens
6
- // (goldens/e4b-audio-*-mel.bin) in tests/audio-features.test.ts.
6
+ // (goldens/e4b-audio-*-mel.bin) in tests/parity/audio-features.test.ts.
7
7
  //
8
8
  // Pipeline (single waveform, 16 kHz mono float32):
9
9
  // pad to a multiple of 128 samples (validity mask over the original part)
@@ -0,0 +1,108 @@
1
+ import type { AutoregressiveGraph } from "../../inference/graph";
2
+ import type { MlxArray } from "../../mlx/array";
3
+ import type { Cache, Gemma4Model } from "../../model/gemma4";
4
+ import type { RuntimeModel } from "../../model/factory";
5
+ import { CompiledDecode } from "../../model/compiled-decode";
6
+ import { runtimeConfig, type RuntimeConfig } from "../../runtime-config";
7
+ import { bindMlxGraph } from "./graph";
8
+
9
+ /** One declaration shared by planning and both native execution lanes. */
10
+ export function legacyCompiledDecodeAvailable(model: RuntimeModel): boolean {
11
+ return model.config?.modelType?.startsWith("gemma4") === true && !model.config.text.enableMoeBlock;
12
+ }
13
+
14
+ export interface MlxModelMemory {
15
+ readonly weightsBytes: number;
16
+ readonly expertRuntime?: {
17
+ readonly plan: { readonly plannedBytes: number };
18
+ flushUsage?: () => void;
19
+ finishUsage?: () => Promise<void>;
20
+ } | null;
21
+ }
22
+
23
+ export interface MlxDecodeStep {
24
+ /** Consume one pending token and advance state once. Returned arrays belong
25
+ * to the caller. null permits ordinary graph execution and MUST leave state
26
+ * unchanged. Errors propagate unless this implementation can roll back. */
27
+ tryStep(token: MlxArray, state: Cache[]): { logits: MlxArray; evalWith: MlxArray[] } | null;
28
+ /** Release per-run workspaces after pending outputs are dropped and before
29
+ * cache disposal. Wait for native work if releasing requires completion. */
30
+ close(): void | Promise<void>;
31
+ }
32
+
33
+ /** Model-owned execution for committed tokens. Recheck the chunk limit after
34
+ * each forward: native arithmetic can change at a cache-length boundary. */
35
+ export interface MlxTokenAppend {
36
+ maxChunkSize(state: readonly Cache[]): number;
37
+ forwardHidden(ids: MlxArray, state: Cache[]): MlxArray | Promise<MlxArray>;
38
+ }
39
+
40
+ /** One replaceable binding owns all graph-specific operations used by the AR
41
+ * loop. The current method requires MLX tensors and the legacy Cache[] ABI.
42
+ * Weights are borrowed for the binding's lifetime; generated caches are owned
43
+ * by the run. Caller-provided caches and media remain borrowed. */
44
+ export interface MlxAutoregressiveBinding {
45
+ readonly runtime?: RuntimeConfig;
46
+ readonly graph: AutoregressiveGraph<MlxArray, Cache[], MlxArray>;
47
+ readonly eosTokenIds: readonly number[];
48
+ readonly memory: MlxModelMemory;
49
+ readonly adapters?: { active: string[] };
50
+ makeCache(): Cache[];
51
+ forwardEmbeddings?(
52
+ embeddings: MlxArray, state: Cache[], imageMask: MlxArray | null,
53
+ ids: MlxArray, multimodalMask: MlxArray | null,
54
+ ): MlxArray;
55
+ /** Called once after prefill. A compiled/fused decoder belongs to THIS graph,
56
+ * never to a model inferred from a name or inherited by a replacement. */
57
+ createDecode?(policy: { hasAdapters: boolean; pagedKv: boolean }): MlxDecodeStep | null;
58
+ createAppend?(policy: { hasAdapters: boolean; pagedKv: boolean }): MlxTokenAppend | null;
59
+ }
60
+
61
+ /** Keep concrete model and compiled-decode decisions at the legacy boundary. */
62
+ export function bindLegacyAutoregressiveModel(model: RuntimeModel): MlxAutoregressiveBinding {
63
+ const runtime = runtimeConfig();
64
+ return {
65
+ runtime,
66
+ graph: bindMlxGraph<Cache[]>(model, {
67
+ id: `legacy:${model.config.modelType}`, artifact: "legacy-resident-model",
68
+ stateAbi: "legacy-cache-array-v1", // not a persistence identity
69
+ }),
70
+ eosTokenIds: model.config.eosTokenIds,
71
+ memory: model,
72
+ adapters: model.loraState,
73
+ makeCache: model.makeCache.bind(model),
74
+ forwardEmbeddings: model.forwardEmbeddings?.bind(model),
75
+ createAppend: "createAppend" in model ? model.createAppend.bind(model) : undefined,
76
+ createDecode(policy) {
77
+ // Preserve the existing Gemma path and exclusions. MoE shapeless replay
78
+ // retraces growing windows; adapters would bake residuals into the tape.
79
+ if (!runtime.flag("MLX_BUN_COMPILED_DECODE", true) || policy.hasAdapters || policy.pagedKv ||
80
+ !legacyCompiledDecodeAvailable(model))
81
+ return null;
82
+ let compiled: CompiledDecode | null = CompiledDecode.for(model as Gemma4Model);
83
+ return {
84
+ tryStep(token, state) {
85
+ if (!compiled || !CompiledDecode.supports(state)) return null;
86
+ try { return compiled.step(token, state); }
87
+ catch (error) {
88
+ // CompiledDecode restores committed writes on failure, so retrying
89
+ // this token through the ordinary graph is safe. Other decoders
90
+ // must establish that guarantee themselves before returning null.
91
+ compiled = null;
92
+ console.warn(`compiled decode disabled for this generation: ${error}`);
93
+ return null;
94
+ }
95
+ },
96
+ // Compiled closures belong to the model's existing unload lifecycle.
97
+ close() { compiled = null; },
98
+ };
99
+ },
100
+ };
101
+ }
102
+
103
+ export function assertMlxAutoregressiveBinding(binding: MlxAutoregressiveBinding): void {
104
+ const descriptor = binding.graph.descriptor;
105
+ if (descriptor.backend !== "mlx" || descriptor.graphAbi !== "mlx-hidden-bsh-v1" ||
106
+ descriptor.stateAbi !== "legacy-cache-array-v1")
107
+ throw new Error(`AR binding ${descriptor.id} has an incompatible backend, graph, or state ABI`);
108
+ }