mlx-bun 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/README.md +1453 -88
  2. package/THIRD_PARTY_NOTICES.md +882 -0
  3. package/bin/mlx-bun.convert.mjs +4 -0
  4. package/bin/mlx-bun.fuse.mjs +4 -0
  5. package/bin/mlx-bun.generate.mjs +4 -0
  6. package/bin/mlx-bun.lora.mjs +4 -0
  7. package/bin/mlx-bun.mjs +13 -21
  8. package/bin/mlx-bun.server.mjs +4 -0
  9. package/bin/mlx-bun.upload.mjs +4 -0
  10. package/dist/web/app.js +9584 -0
  11. package/package.json +50 -53
  12. package/src/cli/ane-install.ts +76 -0
  13. package/src/cli/args.ts +179 -0
  14. package/src/cli/engine-entry.ts +68 -0
  15. package/src/cli/inference.ts +214 -0
  16. package/src/cli/job-entry.ts +97 -0
  17. package/src/cli/library-host.ts +117 -0
  18. package/src/cli/main.ts +57 -0
  19. package/src/cli/memory-engine.ts +163 -0
  20. package/src/cli/memory.ts +36 -0
  21. package/src/cli/mlx-lm-aliases.ts +309 -0
  22. package/src/cli/model-choice.ts +33 -0
  23. package/src/cli/model-selection.ts +84 -0
  24. package/src/cli/module-host.ts +11 -0
  25. package/src/cli/module-verbs.ts +50 -0
  26. package/src/cli/numerical-policy.ts +12 -0
  27. package/src/cli/perplexity.ts +89 -0
  28. package/src/cli/serve-host.ts +423 -0
  29. package/src/cli/serve-isolated.ts +217 -0
  30. package/src/cli/serve-options.ts +106 -0
  31. package/src/cli/serve-state.ts +205 -0
  32. package/src/cli/serve.ts +500 -0
  33. package/src/cli/served-model-host.ts +102 -0
  34. package/src/cli/server-entry.ts +148 -0
  35. package/src/cli/serving-unit.ts +177 -0
  36. package/src/{tui.ts → cli/terminal.ts} +13 -8
  37. package/src/cli/worker-adapters.ts +34 -0
  38. package/src/cli/worker-entry.ts +272 -0
  39. package/src/cli/worker-unit.ts +179 -0
  40. package/src/engine/adapter-operation.ts +26 -0
  41. package/src/engine/cache-services.ts +114 -0
  42. package/src/engine/completion.ts +39 -0
  43. package/src/engine/generation-gateway.ts +358 -0
  44. package/src/engine/index.ts +59 -0
  45. package/src/engine/kv-budget.ts +120 -0
  46. package/src/engine/media-preparation.ts +232 -0
  47. package/src/engine/model-binding.ts +24 -0
  48. package/src/engine/model-host.ts +513 -0
  49. package/src/engine/model-serving.ts +89 -0
  50. package/src/{serve → engine}/preparation.ts +10 -8
  51. package/src/{serve → engine}/session-completion-engine.ts +6 -6
  52. package/src/engine/telemetry.ts +109 -0
  53. package/src/hub/downloads.ts +116 -0
  54. package/src/jobs/db.ts +16 -7
  55. package/src/jobs/events.ts +29 -0
  56. package/src/jobs/executable.ts +5 -0
  57. package/src/jobs/host.ts +51 -0
  58. package/src/jobs/in-process.ts +55 -0
  59. package/src/{contracts/jobs.ts → jobs/protocol.ts} +7 -9
  60. package/src/jobs/runner.ts +150 -231
  61. package/src/jobs/service.ts +75 -0
  62. package/src/jobs/sse.ts +59 -23
  63. package/src/jobs/worker-memory.ts +46 -0
  64. package/src/jobs/worker-process.ts +163 -0
  65. package/src/jobs/worker-supervisor.ts +258 -0
  66. package/src/modules.ts +58 -0
  67. package/src/publishing/catalog-hub.ts +18 -0
  68. package/src/publishing/credentials.ts +31 -0
  69. package/src/publishing/upload.ts +37 -0
  70. package/src/residency/leased-adapters.ts +21 -0
  71. package/src/residency/local-records.ts +16 -0
  72. package/src/residency/model-residency.ts +405 -0
  73. package/src/residency/record-index.ts +28 -0
  74. package/src/residency/resident-estimate.ts +50 -0
  75. package/src/{anthropic.ts → server/anthropic.ts} +3 -81
  76. package/src/server/cache-routes.ts +36 -0
  77. package/src/{serve → server}/chat-request.ts +12 -10
  78. package/src/{serve → server}/chat-stage.ts +27 -22
  79. package/src/{client.ts → server/client.ts} +28 -2
  80. package/src/{serve → server}/completion-executor.ts +42 -42
  81. package/src/server/decision-body.ts +55 -0
  82. package/src/server/decision-routes.ts +134 -0
  83. package/src/server/decision-wire.ts +228 -0
  84. package/src/{serve → server}/discovery-routes.ts +42 -83
  85. package/src/server/generated-token-history.ts +57 -0
  86. package/src/{serve → server}/http.ts +25 -13
  87. package/src/{serve → server}/inference-request.ts +5 -5
  88. package/src/server/job-routes.ts +20 -0
  89. package/src/server/media-prompt.ts +63 -0
  90. package/src/server/memory-completion-client.ts +46 -0
  91. package/src/server/model-routes.ts +192 -0
  92. package/src/{serve → server}/openai-wire.ts +3 -2
  93. package/src/{serve → server}/pipeline.ts +1 -1
  94. package/src/server/prompt-builder.ts +13 -0
  95. package/src/server/prompt-contracts.ts +17 -0
  96. package/src/server/proxy-routes.ts +187 -0
  97. package/src/server/publishing-routes.ts +41 -0
  98. package/src/{serve → server}/request-plan.ts +8 -8
  99. package/src/{serve → server}/request-prep.ts +82 -68
  100. package/src/{serve → server}/responses-client.ts +30 -13
  101. package/src/{responses.ts → server/responses.ts} +12 -93
  102. package/src/server/routes.ts +205 -0
  103. package/src/server/start.ts +72 -0
  104. package/src/server/status-routes.ts +108 -0
  105. package/src/{serve → server}/text-completion-stage.ts +25 -4
  106. package/src/server/text-prompt.ts +12 -0
  107. package/src/{serve → server}/token-streams.ts +36 -38
  108. package/src/server/worker-routes.ts +311 -0
  109. package/src/storage/paths.ts +61 -0
  110. package/src/web/assets.ts +37 -0
  111. package/src/web/{src → browser}/api.ts +5 -23
  112. package/src/web/browser/chat-host.ts +17 -0
  113. package/src/web/browser/installed-panels.ts +6 -0
  114. package/src/web/browser/main.ts +55 -0
  115. package/src/web/browser/markdown.ts +279 -0
  116. package/src/web/browser/memory-panel.ts +9 -0
  117. package/src/web/browser/palette.ts +64 -0
  118. package/src/web/browser/protocol.ts +13 -0
  119. package/src/web/browser/shell.ts +467 -0
  120. package/src/web/{src → browser}/status.ts +32 -36
  121. package/src/web/build.ts +51 -0
  122. package/src/web/public/app.html +1054 -0
  123. package/src/web/{sw.js → public/sw.js} +4 -3
  124. package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
  125. package/src/web/{vendor → public/vendor}/hljs.js +2 -2
  126. package/THIRD_PARTY_LICENSES.md +0 -51
  127. package/docs/README.md +0 -94
  128. package/docs/archive/hlg-sampling.md +0 -350
  129. package/docs/archive/investigations/audio-input-plan.md +0 -356
  130. package/docs/archive/investigations/chunk-finetune-experiment.md +0 -84
  131. package/docs/archive/investigations/colibri-glm52-port.md +0 -1486
  132. package/docs/archive/investigations/colibri-oracle-pin.md +0 -1284
  133. package/docs/archive/investigations/curve-bisector-routing.md +0 -123
  134. package/docs/archive/investigations/decode-roofline-lookagain.md +0 -348
  135. package/docs/archive/investigations/diffusion-gemma-port.md +0 -602
  136. package/docs/archive/investigations/dspark-handoff.md +0 -224
  137. package/docs/archive/investigations/expert-offload-single-user-moe.md +0 -292
  138. package/docs/archive/investigations/faithful-l1-consolidation.md +0 -310
  139. package/docs/archive/investigations/hlg-sampling-investigation.md +0 -970
  140. package/docs/archive/investigations/indexshare-performance-spike.md +0 -357
  141. package/docs/archive/investigations/kernel-perf-review-2026-07.md +0 -171
  142. package/docs/archive/investigations/lab-build-journal.md +0 -157
  143. package/docs/archive/investigations/minicpm5-decode-megakernel.md +0 -489
  144. package/docs/archive/investigations/openjarvis-fit.md +0 -198
  145. package/docs/archive/investigations/openwiki-evaluation.md +0 -249
  146. package/docs/archive/investigations/optimization_plan.md +0 -346
  147. package/docs/archive/investigations/orpo-base-uf-experiment-and-directions.md +0 -120
  148. package/docs/archive/investigations/orpo-flash-cce-pin-leak.md +0 -167
  149. package/docs/archive/investigations/orpo-uf-testing-handoff.md +0 -126
  150. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +0 -92
  151. package/docs/archive/investigations/pi-builtin-investigation.md +0 -308
  152. package/docs/archive/investigations/pre-colibri-stabilization.md +0 -329
  153. package/docs/archive/investigations/qwen38-27b-campaign-log.md +0 -1092
  154. package/docs/archive/investigations/segmented-backward-handoff.md +0 -148
  155. package/docs/archive/investigations/starter-model-port-handoff.md +0 -342
  156. package/docs/archive/investigations/steel-flash-cce-handoff.md +0 -489
  157. package/docs/archive/investigations/the-dreaming-handoff.md +0 -141
  158. package/docs/archive/investigations/trainer-validation-experiment.md +0 -173
  159. package/docs/archive/planning/chat-ui-vision-memory-first.md +0 -199
  160. package/docs/archive/planning/chat-ui-vision.md +0 -50
  161. package/docs/archive/planning/chunk-task-roadmap.md +0 -77
  162. package/docs/archive/planning/curve-sampler-research-plan.md +0 -331
  163. package/docs/archive/planning/journal.md +0 -316
  164. package/docs/archive/planning/memory-docs-and-dag-plan.md +0 -194
  165. package/docs/archive/planning/pi-integration-review.md +0 -178
  166. package/docs/archive/planning/release-notes-v0.0.10.md +0 -57
  167. package/docs/archive/planning/release-notes-v0.0.11.md +0 -239
  168. package/docs/archive/planning/release-notes-v0.0.12.md +0 -80
  169. package/docs/archive/planning/release-notes-v0.0.13.md +0 -77
  170. package/docs/archive/planning/release-notes-v0.0.9.md +0 -122
  171. package/docs/archive/planning/release-notes-v0.2.0.md +0 -49
  172. package/docs/archive/planning/release-notes-v0.3.0.md +0 -35
  173. package/docs/archive/planning/web-ui-pass-plan.md +0 -213
  174. package/docs/archive/planning/website-readme-pass-plan.md +0 -224
  175. package/docs/design/batching.md +0 -1841
  176. package/docs/design/decode-speed-program.md +0 -2349
  177. package/docs/design/dreaming-nightly-pipeline.md +0 -684
  178. package/docs/design/generic-model-support.md +0 -705
  179. package/docs/design/kv-cache.md +0 -824
  180. package/docs/design/orpo-training.md +0 -680
  181. package/docs/design/speculative-decoding.md +0 -1990
  182. package/docs/design/turboquant.md +0 -2212
  183. package/docs/design/unified-engine-frontier-plan.md +0 -1880
  184. package/docs/design/web-chat-redesign.md +0 -695
  185. package/docs/planning/PRODUCT_ROADMAP.md +0 -594
  186. package/docs/planning/ResearchTopics.md +0 -119
  187. package/docs/planning/release-notes-v0.4.0.md +0 -45
  188. package/docs/planning/video-series.md +0 -421
  189. package/docs/reference/benchmarks.md +0 -3613
  190. package/docs/reference/cli.md +0 -585
  191. package/docs/reference/distribution.md +0 -355
  192. package/docs/reference/environment.md +0 -398
  193. package/docs/reference/glossary.md +0 -39
  194. package/docs/reference/library-api.md +0 -674
  195. package/docs/reference/memory.md +0 -260
  196. package/docs/reference/models.md +0 -334
  197. package/docs/reference/server-api.md +0 -1775
  198. package/docs/reference/server-config.md +0 -846
  199. package/docs/reference/training.md +0 -462
  200. package/docs/reference/troubleshooting.md +0 -158
  201. package/src/admission-plan.ts +0 -18
  202. package/src/audio/conformer.ts +0 -647
  203. package/src/audio/decode.ts +0 -133
  204. package/src/audio/features.ts +0 -202
  205. package/src/audio/transcode.ts +0 -67
  206. package/src/backends/mlx/assistant-target.ts +0 -46
  207. package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
  208. package/src/backends/mlx/autoregressive.ts +0 -108
  209. package/src/backends/mlx/batch-group.ts +0 -1790
  210. package/src/backends/mlx/cache-attachment.ts +0 -67
  211. package/src/backends/mlx/cache-layout.ts +0 -31
  212. package/src/backends/mlx/checkpoint-state.ts +0 -53
  213. package/src/backends/mlx/continuation-persistence.ts +0 -106
  214. package/src/backends/mlx/continuation-request.ts +0 -43
  215. package/src/backends/mlx/continuation.ts +0 -77
  216. package/src/backends/mlx/diffusion.ts +0 -39
  217. package/src/backends/mlx/draft-target.ts +0 -32
  218. package/src/backends/mlx/evaluation.ts +0 -105
  219. package/src/backends/mlx/fill-append.ts +0 -45
  220. package/src/backends/mlx/full-kv-row-append.ts +0 -32
  221. package/src/backends/mlx/full-kv-row-donor.ts +0 -54
  222. package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
  223. package/src/backends/mlx/gateway-binding.ts +0 -130
  224. package/src/backends/mlx/graph.ts +0 -38
  225. package/src/backends/mlx/kv-codec.ts +0 -9
  226. package/src/backends/mlx/kv-maintenance.ts +0 -133
  227. package/src/backends/mlx/kv-tensor-rows.ts +0 -212
  228. package/src/backends/mlx/memory-client.ts +0 -189
  229. package/src/backends/mlx/methods.ts +0 -90
  230. package/src/backends/mlx/model-prompt.ts +0 -164
  231. package/src/backends/mlx/model-serving.ts +0 -79
  232. package/src/backends/mlx/prefill-cohort.ts +0 -89
  233. package/src/backends/mlx/prefill-rows.ts +0 -200
  234. package/src/backends/mlx/prefill.ts +0 -33
  235. package/src/backends/mlx/projected-context-rows.ts +0 -72
  236. package/src/backends/mlx/request-policy.ts +0 -20
  237. package/src/backends/mlx/request-state-policy.ts +0 -41
  238. package/src/backends/mlx/rollback.ts +0 -89
  239. package/src/backends/mlx/row-sampling.ts +0 -49
  240. package/src/backends/mlx/serial-executor.ts +0 -242
  241. package/src/backends/mlx/speculative-group.ts +0 -359
  242. package/src/backends/mlx/speculative-round.ts +0 -161
  243. package/src/backends/mlx/speculative.ts +0 -114
  244. package/src/backends/mlx/state-rows.ts +0 -104
  245. package/src/backends/mlx/state-views.ts +0 -46
  246. package/src/backends/mlx/target-layout-capability.ts +0 -35
  247. package/src/backends/mlx/text-engine.ts +0 -73
  248. package/src/backends/mlx/transitioning-kv-rows.ts +0 -165
  249. package/src/chat-template.ts +0 -382
  250. package/src/cli.ts +0 -3168
  251. package/src/config.ts +0 -399
  252. package/src/contracts/completion.ts +0 -16
  253. package/src/contracts/execution.ts +0 -60
  254. package/src/contracts/generation.ts +0 -103
  255. package/src/contracts/host.ts +0 -7
  256. package/src/contracts/pi-provider.ts +0 -30
  257. package/src/contracts/pi.ts +0 -259
  258. package/src/contracts/prefix-cache.ts +0 -23
  259. package/src/contracts/resources.ts +0 -25
  260. package/src/contracts/sampling.ts +0 -23
  261. package/src/contracts/scheduling.ts +0 -45
  262. package/src/contracts/tsconfig.json +0 -14
  263. package/src/dataset/generators.ts +0 -1087
  264. package/src/dataset/index.ts +0 -12
  265. package/src/dataset/job.ts +0 -81
  266. package/src/dataset/llm.ts +0 -71
  267. package/src/dataset/registry.ts +0 -528
  268. package/src/diffusion/diffusion-generate.ts +0 -507
  269. package/src/download.ts +0 -505
  270. package/src/embed.ts +0 -77
  271. package/src/engine/admission.ts +0 -59
  272. package/src/engine/cancellation.ts +0 -38
  273. package/src/engine/engine.ts +0 -56
  274. package/src/engine/execution-coordinator.ts +0 -70
  275. package/src/engine/execution-plan.ts +0 -53
  276. package/src/engine/resources.ts +0 -53
  277. package/src/engine/scheduler.ts +0 -72
  278. package/src/engine/session.ts +0 -247
  279. package/src/eval/README.md +0 -130
  280. package/src/eval/ifeval.ts +0 -81
  281. package/src/eval/kl-prompts.ts +0 -29
  282. package/src/eval/kl.ts +0 -590
  283. package/src/eval/perplexity.ts +0 -164
  284. package/src/eval/quality-db.ts +0 -92
  285. package/src/eval/reference-logits.ts +0 -207
  286. package/src/eval/runner.ts +0 -124
  287. package/src/eval/score.ts +0 -49
  288. package/src/eval/tasks/bfcl.ts +0 -535
  289. package/src/eval/tasks/gsm8k.ts +0 -98
  290. package/src/eval/tasks/hashhop.ts +0 -139
  291. package/src/eval/tasks/humaneval.ts +0 -275
  292. package/src/eval/tasks/ifeval.ts +0 -525
  293. package/src/eval/tasks/mmlu.ts +0 -157
  294. package/src/eval/ultrafeedback.ts +0 -60
  295. package/src/evaldb.ts +0 -199
  296. package/src/expert-io.ts +0 -393
  297. package/src/expert-offload-build.ts +0 -77
  298. package/src/expert-offload.ts +0 -76
  299. package/src/expert-residency.ts +0 -1134
  300. package/src/expert-usage.ts +0 -415
  301. package/src/fill/echo-index.ts +0 -188
  302. package/src/fill/fill-session.ts +0 -452
  303. package/src/fill/proposal.ts +0 -68
  304. package/src/fill/schema-rows.ts +0 -506
  305. package/src/fill/tool-boundary.ts +0 -103
  306. package/src/fit.ts +0 -249
  307. package/src/generate.ts +0 -1346
  308. package/src/grammar.ts +0 -591
  309. package/src/harness-pi.ts +0 -184
  310. package/src/hf-push.ts +0 -628
  311. package/src/hub-rest.ts +0 -242
  312. package/src/index.ts +0 -63
  313. package/src/inference/denoising.ts +0 -17
  314. package/src/inference/draft-acceptance.ts +0 -41
  315. package/src/inference/draft-output.ts +0 -49
  316. package/src/inference/graph.ts +0 -33
  317. package/src/inference/prefill.ts +0 -39
  318. package/src/inference/rollback.ts +0 -7
  319. package/src/jobs/index.ts +0 -31
  320. package/src/jobs/job-entry.ts +0 -107
  321. package/src/jobs/task-client.ts +0 -19
  322. package/src/jobs/types.ts +0 -2
  323. package/src/kv-scheme.ts +0 -257
  324. package/src/kv-store.ts +0 -1099
  325. package/src/lab/README.md +0 -18
  326. package/src/lab/curve/curve-designer.html +0 -303
  327. package/src/lab/curve/curve-sampler.ts +0 -122
  328. package/src/lab/expert-trace/expert-trace.ts +0 -69
  329. package/src/lab/paged-kv/paged-kv-rows.ts +0 -83
  330. package/src/lab/paged-kv/paged-kv.ts +0 -270
  331. package/src/library.ts +0 -40
  332. package/src/lora.ts +0 -408
  333. package/src/md-modules.d.ts +0 -49
  334. package/src/media-fetch.ts +0 -442
  335. package/src/memory/article.ts +0 -558
  336. package/src/memory/chunk-validation.ts +0 -150
  337. package/src/memory/chunk.ts +0 -318
  338. package/src/memory/cluster.ts +0 -351
  339. package/src/memory/coverage.ts +0 -134
  340. package/src/memory/crosslink.ts +0 -0
  341. package/src/memory/db.ts +0 -253
  342. package/src/memory/entity.ts +0 -203
  343. package/src/memory/gate.ts +0 -187
  344. package/src/memory/history.ts +0 -152
  345. package/src/memory/ingest.ts +0 -335
  346. package/src/memory/model.ts +0 -183
  347. package/src/memory/normalize.ts +0 -671
  348. package/src/memory/parse.ts +0 -22
  349. package/src/memory/pipeline.ts +0 -275
  350. package/src/memory/prompts.ts +0 -65
  351. package/src/memory/query.ts +0 -334
  352. package/src/memory/reconcile.ts +0 -734
  353. package/src/memory/redirect.ts +0 -108
  354. package/src/memory/reindex.ts +0 -325
  355. package/src/memory/resolve.ts +0 -307
  356. package/src/memory/rest.ts +0 -245
  357. package/src/memory/route.ts +0 -272
  358. package/src/memory/schedule.ts +0 -165
  359. package/src/memory/stages.ts +0 -777
  360. package/src/memory/synthesize.ts +0 -1638
  361. package/src/memory/tools.ts +0 -749
  362. package/src/memory/vault.ts +0 -1194
  363. package/src/memory/wikify.ts +0 -1064
  364. package/src/mlx/array.ts +0 -388
  365. package/src/mlx/autograd.ts +0 -304
  366. package/src/mlx/checkpoint.ts +0 -149
  367. package/src/mlx/compile.ts +0 -168
  368. package/src/mlx/custom-vjp.ts +0 -188
  369. package/src/mlx/ffi.ts +0 -512
  370. package/src/mlx/materialize.ts +0 -23
  371. package/src/mlx/metal-kernel.ts +0 -159
  372. package/src/mlx/ops.ts +0 -1021
  373. package/src/mlx/quantized-rows.ts +0 -36
  374. package/src/mlx/token-bitmask.ts +0 -52
  375. package/src/mlx/turboquant-kv-decode.ts +0 -82
  376. package/src/mlx/turboquant-kv-inverse.ts +0 -122
  377. package/src/mlx/turboquant-ops.ts +0 -861
  378. package/src/mlx/turboquant-tables.ts +0 -237
  379. package/src/mmap.ts +0 -90
  380. package/src/model/artifact-identity.ts +0 -73
  381. package/src/model/batched-kv.ts +0 -235
  382. package/src/model/batched-mask.ts +0 -279
  383. package/src/model/batched-quant.ts +0 -212
  384. package/src/model/batched-quantized-kv.ts +0 -144
  385. package/src/model/batched-rotating-quant.ts +0 -353
  386. package/src/model/batched-rotating-state.ts +0 -149
  387. package/src/model/batched-rotating.ts +0 -338
  388. package/src/model/batched-row-storage.ts +0 -179
  389. package/src/model/batched-ssm.ts +0 -52
  390. package/src/model/batched-turboquant-kv.ts +0 -93
  391. package/src/model/compiled-decode.ts +0 -712
  392. package/src/model/decoded-kv-donor.ts +0 -12
  393. package/src/model/delayed-quantized-kv.ts +0 -72
  394. package/src/model/delayed-rotating-quantized-kv.ts +0 -93
  395. package/src/model/delayed-turboquant-kv.ts +0 -55
  396. package/src/model/diffusion-gemma.ts +0 -1026
  397. package/src/model/factory.ts +0 -189
  398. package/src/model/fingerprint.ts +0 -33
  399. package/src/model/flash-attention.ts +0 -694
  400. package/src/model/full-prefill-padding.ts +0 -56
  401. package/src/model/full-prefill-row.ts +0 -105
  402. package/src/model/gemma4-base.ts +0 -2351
  403. package/src/model/gemma4.ts +0 -1315
  404. package/src/model/generated/gemma4-12b.ts +0 -429
  405. package/src/model/generated/gemma4-26b.ts +0 -448
  406. package/src/model/generated/gemma4-e4b.ts +0 -717
  407. package/src/model/generated/index.ts +0 -18
  408. package/src/model/glm52-atlas.ts +0 -511
  409. package/src/model/glm52-cache.ts +0 -792
  410. package/src/model/glm52-config.ts +0 -262
  411. package/src/model/glm52-container.ts +0 -305
  412. package/src/model/glm52-coupling.ts +0 -388
  413. package/src/model/glm52-dsa.ts +0 -606
  414. package/src/model/glm52-expert-layout.ts +0 -253
  415. package/src/model/glm52-layout.ts +0 -152
  416. package/src/model/glm52-memory.ts +0 -500
  417. package/src/model/glm52-mla.ts +0 -792
  418. package/src/model/glm52-moe.ts +0 -223
  419. package/src/model/glm52-pilot.ts +0 -537
  420. package/src/model/glm52-reference.ts +0 -445
  421. package/src/model/glm52-residency.ts +0 -557
  422. package/src/model/glm52-resident-weights.ts +0 -135
  423. package/src/model/glm52-streamed-experts.ts +0 -453
  424. package/src/model/glm52-streamed-metal.ts +0 -610
  425. package/src/model/glm52-weights.ts +0 -503
  426. package/src/model/glm52.ts +0 -1132
  427. package/src/model/implementation.ts +0 -69
  428. package/src/model/kv-attention-view.ts +0 -67
  429. package/src/model/minicpm5.ts +0 -376
  430. package/src/model/profile.ts +0 -443
  431. package/src/model/qwen-append.ts +0 -12
  432. package/src/model/qwen-conv.ts +0 -52
  433. package/src/model/qwen3-delta-state.ts +0 -74
  434. package/src/model/qwen3-delta.ts +0 -451
  435. package/src/model/qwen3-moe.ts +0 -404
  436. package/src/model/qwen3-mrope.ts +0 -252
  437. package/src/model/qwen3.ts +0 -277
  438. package/src/model/qwen3_5-checkpoint.ts +0 -164
  439. package/src/model/qwen3_5.ts +0 -819
  440. package/src/model/rotating-kv-donor.ts +0 -35
  441. package/src/model/rotating-kv-layout.ts +0 -262
  442. package/src/model/rotating-row-transaction.ts +0 -35
  443. package/src/model/speculative-rotating-kv.ts +0 -101
  444. package/src/model/ssm-prefill-padding.ts +0 -39
  445. package/src/model/support.ts +0 -102
  446. package/src/model/trellis-balanced-scatter.ts +0 -51
  447. package/src/model/trellis-linear.ts +0 -672
  448. package/src/model/trellis-shared-m.ts +0 -151
  449. package/src/model/trellis-shared-scatter.ts +0 -144
  450. package/src/model/trellis-splitk-prefill.ts +0 -158
  451. package/src/model/trellis-tiled-prefill.ts +0 -136
  452. package/src/model/trellis-vector-expand.ts +0 -62
  453. package/src/model/trellis-wide-prefill.ts +0 -94
  454. package/src/model/turboquant-codec.ts +0 -83
  455. package/src/model/universal/archs.ts +0 -332
  456. package/src/model/universal/dense.ts +0 -612
  457. package/src/model/universal/modules.ts +0 -170
  458. package/src/model/universal/rope.ts +0 -381
  459. package/src/native/expert_io.c +0 -523
  460. package/src/native/frame_extract.swift +0 -140
  461. package/src/native-pack.ts +0 -162
  462. package/src/pi-provider.ts +0 -53
  463. package/src/pi-session.ts +0 -81
  464. package/src/pi-terminal.ts +0 -274
  465. package/src/pi-web.ts +0 -1932
  466. package/src/preflight.ts +0 -158
  467. package/src/prompt-cache.ts +0 -460
  468. package/src/quantize/allocator.ts +0 -627
  469. package/src/quantize/atomic-output.ts +0 -38
  470. package/src/quantize/calibration.ts +0 -181
  471. package/src/quantize/config-writer.ts +0 -145
  472. package/src/quantize/index.ts +0 -84
  473. package/src/quantize/job.ts +0 -162
  474. package/src/quantize/quantizer.ts +0 -666
  475. package/src/quantize/rotate.ts +0 -603
  476. package/src/quantize/safetensors-writer.ts +0 -249
  477. package/src/quantize/sensitivity.ts +0 -216
  478. package/src/quantize/trellis.ts +0 -586
  479. package/src/quantize/weight-transform.ts +0 -292
  480. package/src/registry.ts +0 -602
  481. package/src/runtime-config.ts +0 -81
  482. package/src/safetensors.ts +0 -158
  483. package/src/sampler.ts +0 -1011
  484. package/src/serve/admin-routes.ts +0 -184
  485. package/src/serve/assets/curve-terrain.html +0 -105
  486. package/src/serve/assets/training-inference-map.html +0 -575
  487. package/src/serve/aux-routes.ts +0 -132
  488. package/src/serve/batch-scheduler.ts +0 -8
  489. package/src/serve/checkpoint-identity.ts +0 -64
  490. package/src/serve/generation-gateway.ts +0 -496
  491. package/src/serve/isolate.ts +0 -609
  492. package/src/serve/kv-budget.ts +0 -14
  493. package/src/serve/lab-routes.ts +0 -341
  494. package/src/serve/lane-registry.ts +0 -45
  495. package/src/serve/model-admin-routes.ts +0 -155
  496. package/src/serve/model-binding.ts +0 -43
  497. package/src/serve/model-host.ts +0 -511
  498. package/src/serve/parent-application.ts +0 -56
  499. package/src/serve/prompt-response-trace.ts +0 -147
  500. package/src/serve/response-lease.ts +0 -24
  501. package/src/serve/session-search.ts +0 -326
  502. package/src/serve/static-routes.ts +0 -101
  503. package/src/server.ts +0 -1314
  504. package/src/spec/assistant-rows.ts +0 -92
  505. package/src/spec/assistant-source.ts +0 -126
  506. package/src/spec/cache-identity.ts +0 -22
  507. package/src/spec/deepspec-rows.ts +0 -29
  508. package/src/spec/deepspec-source.ts +0 -145
  509. package/src/spec/dflash-source.ts +0 -149
  510. package/src/spec/drafter.ts +0 -304
  511. package/src/spec/dspark/ab-stats.ts +0 -136
  512. package/src/spec/dspark/calibration.ts +0 -112
  513. package/src/spec/dspark/data-dflash.ts +0 -156
  514. package/src/spec/dspark/data.ts +0 -201
  515. package/src/spec/dspark/deepspec-module.ts +0 -776
  516. package/src/spec/dspark/generate-dflash.ts +0 -245
  517. package/src/spec/dspark/generate.ts +0 -290
  518. package/src/spec/dspark/loader.ts +0 -23
  519. package/src/spec/dspark/loss.ts +0 -213
  520. package/src/spec/dspark/module-dflash.ts +0 -560
  521. package/src/spec/dspark/module.ts +0 -540
  522. package/src/spec/dspark/quantize-drafter.ts +0 -91
  523. package/src/spec/dspark/sample.ts +0 -112
  524. package/src/spec/generate.ts +0 -276
  525. package/src/spec/glm52-mtp-graph.ts +0 -29
  526. package/src/spec/glm52-mtp-rows.ts +0 -132
  527. package/src/spec/glm52-mtp-source.ts +0 -317
  528. package/src/spec/glm52-mtp-state.ts +0 -33
  529. package/src/spec/ngram-source.ts +0 -204
  530. package/src/spec/projected-draft-rows.ts +0 -73
  531. package/src/spec/qwen-mtp-module.ts +0 -171
  532. package/src/spec/qwen-mtp-rows.ts +0 -219
  533. package/src/spec/qwen-mtp-source.ts +0 -383
  534. package/src/spec/qwen-mtp-state.ts +0 -30
  535. package/src/spec/serve-loop.ts +0 -585
  536. package/src/spec/source.ts +0 -215
  537. package/src/spec/two-model-rows.ts +0 -61
  538. package/src/spec/two-model.ts +0 -113
  539. package/src/ssd-cache.ts +0 -372
  540. package/src/ssd-durability.ts +0 -211
  541. package/src/tokenizer.ts +0 -335
  542. package/src/tool-approvals.ts +0 -131
  543. package/src/tool-call.ts +0 -695
  544. package/src/train/dataset.ts +0 -484
  545. package/src/train/diffusion-lora.ts +0 -216
  546. package/src/train/export.ts +0 -32
  547. package/src/train/flash-cce.ts +0 -1234
  548. package/src/train/forward.ts +0 -266
  549. package/src/train/fuse.ts +0 -243
  550. package/src/train/index.ts +0 -46
  551. package/src/train/job.ts +0 -205
  552. package/src/train/lora-params.ts +0 -254
  553. package/src/train/loss.ts +0 -1591
  554. package/src/train/merge.ts +0 -195
  555. package/src/train/optimizer.ts +0 -183
  556. package/src/train/prefix-shared.ts +0 -490
  557. package/src/train/rank.ts +0 -137
  558. package/src/train/segmented.ts +0 -1828
  559. package/src/train/steel-qmm-header.ts +0 -1461
  560. package/src/train/trainer.ts +0 -1221
  561. package/src/train/watch.ts +0 -542
  562. package/src/vision/diffusion-vision.ts +0 -620
  563. package/src/vision/embedder.ts +0 -168
  564. package/src/vision/preprocess.ts +0 -247
  565. package/src/vision/prompt.ts +0 -373
  566. package/src/vision/qwen3vl-preprocess.ts +0 -409
  567. package/src/vision/qwen3vl-prompt.ts +0 -196
  568. package/src/vision/qwen3vl-tower.ts +0 -555
  569. package/src/vision/siglip.ts +0 -599
  570. package/src/vision/video-frames.ts +0 -148
  571. package/src/web/app.html +0 -2143
  572. package/src/web/app.js +0 -5703
  573. package/src/web/skills/memory/SKILL.md +0 -120
  574. package/src/web/skills/web-research/SKILL.md +0 -46
  575. package/src/web/skills.ts +0 -97
  576. package/src/web/src/adapters-panel.ts +0 -288
  577. package/src/web/src/assistant.ts +0 -451
  578. package/src/web/src/chat.ts +0 -1057
  579. package/src/web/src/composer.ts +0 -959
  580. package/src/web/src/dataset.ts +0 -132
  581. package/src/web/src/finetune.ts +0 -267
  582. package/src/web/src/hub.ts +0 -428
  583. package/src/web/src/main.ts +0 -98
  584. package/src/web/src/markdown.ts +0 -0
  585. package/src/web/src/memory-panel.ts +0 -572
  586. package/src/web/src/model-picker.ts +0 -159
  587. package/src/web/src/palette.ts +0 -346
  588. package/src/web/src/protocol.ts +0 -26
  589. package/src/web/src/quantize.ts +0 -167
  590. package/src/web/src/rag.ts +0 -274
  591. package/src/web/src/sessions.ts +0 -469
  592. package/src/web/src/shell.ts +0 -804
  593. package/src/web/src/ui-catalog.ts +0 -78
  594. package/src/web/vendor/README.md +0 -61
  595. package/src/web-assets.ts +0 -47
  596. package/src/web-tools.ts +0 -478
  597. package/src/weights.ts +0 -255
  598. /package/src/{serve → server}/completion-sink.ts +0 -0
  599. /package/src/web/{icon.svg → public/icon.svg} +0 -0
  600. /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
  601. /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
package/src/mlx/array.ts DELETED
@@ -1,388 +0,0 @@
1
- // MlxArray: ownership wrapper around an mlx_array handle.
2
- // Explicit .dispose() is the contract; a FinalizationRegistry backstop
3
- // frees leaked handles on GC (verified in lab/spikes/phase0-memory.ts).
4
-
5
- import { dlopen, ptr, toArrayBuffer } from "bun:ffi";
6
- import { C, Dtype, DTYPE_NAMES, type MlxHandle, optInt, outArray, takeMlxError } from "./ffi";
7
- import type { SafetensorsDtype } from "../safetensors";
8
-
9
- export const gpuStream: MlxHandle = C.mlx_default_gpu_stream_new();
10
- export const cpuStream: MlxHandle = C.mlx_default_cpu_stream_new();
11
-
12
- /** Shape buffer for FFI; ptr() rejects empty views, so 0-d arrays pass a
13
- * dummy buffer with dim=0 (the pointee is never read). */
14
- function shapeBuf(shape: number[]): Int32Array {
15
- return shape.length === 0 ? new Int32Array(1) : new Int32Array(shape);
16
- }
17
-
18
- export const SAFETENSORS_TO_MLX: Record<SafetensorsDtype, Dtype> = {
19
- BOOL: Dtype.bool, U8: Dtype.uint8, I8: Dtype.int8,
20
- U16: Dtype.uint16, I16: Dtype.int16, U32: Dtype.uint32, I32: Dtype.int32,
21
- U64: Dtype.uint64, I64: Dtype.int64,
22
- F16: Dtype.float16, BF16: Dtype.bfloat16, F32: Dtype.float32, F64: Dtype.float64,
23
- };
24
-
25
- // --- zero-copy pinning ---------------------------------------------------
26
- // Buffers handed to mlx via new_data_managed_payload must outlive the mlx
27
- // array. fromView pins the JS view in this map (a GC root, nothing more);
28
- // release is EXPLICIT and JS-thread-only via unpinHostBuffer() — never an
29
- // mlx dtor. See the hazard note below.
30
-
31
- const pinned = new Map<number, Uint8Array>();
32
- let nextPinId = 1;
33
-
34
- // HAZARD (root cause of the 2026-07-06 restart-restore hang): mlx releases
35
- // buffer Data wherever the LAST shared_ptr drops — often the Metal
36
- // COMPLETION thread (gpu::eval retains buffers until the command buffer
37
- // finishes, i.e. past dispose()). A bun:ffi JSCallback dtor invoked from
38
- // that thread deadlocks when the JS thread is inside a blocking FFI eval
39
- // (completion waits on JS, JS waits on completion) and SIGTRAPs mid-GC.
40
- // So NO array here ever gets a JS dtor: fromPointer AND fromView both hand
41
- // mlx the native no-op dtor below (payload 0), and host-buffer lifetime is
42
- // the CALLER's contract, released only from the JS thread (unpinHostBuffer)
43
- // or never (process-lifetime mmaps: expert-offload).
44
-
45
- // Native no-op dtor: payload is always 0, and libc free(NULL) is defined to
46
- // do nothing — a dtor mlx can safely call from ANY thread. The pointed-to
47
- // memory's lifetime is the CALLER's contract (weight mmaps live for the
48
- // process; restored KV is COPIED at load since 2026-07-07 — see kv-store.ts
49
- // loadKvCache — so no restore mapping needs pinning anymore). Bun >= 1.4
50
- // returns a numeric function address from .ptr; verified against dlsym on
51
- // 1.4.0 and 1.4.2. Keep the library open for every native destructor's lifetime.
52
- const libcFree = dlopen("/usr/lib/libSystem.B.dylib", {
53
- free: { args: ["ptr"], returns: "void" },
54
- });
55
- // The pinned bun-types predates the runtime's numeric .ptr property.
56
- const freeFnAddr = Number(Reflect.get(libcFree.symbols.free, "ptr"));
57
- if (!Number.isSafeInteger(freeFnAddr) || freeFnAddr <= 0)
58
- throw new Error("free.ptr is invalid — zero-copy arrays need a native no-op dtor");
59
-
60
- export function pinnedBufferCount(): number {
61
- return pinned.size;
62
- }
63
-
64
- // --- finalization backstop ----------------------------------------------
65
-
66
- const registry = new FinalizationRegistry((handle: MlxHandle) => {
67
- C.mlx_array_free(handle);
68
- });
69
-
70
- export class MlxArray {
71
- #handle: MlxHandle;
72
- #disposed = false;
73
- #token = {};
74
- #pinId = 0; // fromView only: key into the pinned-view map (0 = no pin)
75
-
76
- constructor(handle: MlxHandle) {
77
- this.#handle = handle;
78
- registry.register(this, handle, this.#token);
79
- }
80
-
81
- /** Zero-copy: wrap an existing JS buffer. The view is pinned (GC-rooted)
82
- * in a process-side map; mlx gets the NATIVE no-op dtor (free(NULL)) —
83
- * never a JS callback, so the last release may happen on the Metal
84
- * completion thread without deadlock (see hazard note above). Buffer
85
- * lifetime is therefore the CALLER's contract:
86
- * - mmap-backed views (toArrayBuffer aliases): the mapping owns the
87
- * memory; prefer fromPointer, which skips the pin entirely.
88
- * - JS-heap buffers: the pin keeps the buffer alive; call
89
- * unpinHostBuffer() only after a JS-side sync point proves mlx is
90
- * done with it (everything depending on the array evaluated AND the
91
- * array disposed), or never (process-lifetime, e.g. short scripts). */
92
- static fromView(view: Uint8Array, shape: number[], dtype: Dtype): MlxArray {
93
- const sb = shapeBuf(shape);
94
- const id = nextPinId++;
95
- pinned.set(id, view);
96
- const handle = C.mlx_array_new_data_managed_payload(
97
- ptr(view), ptr(sb), shape.length, dtype, 0, freeFnAddr,
98
- );
99
- const arr = new MlxArray(handle);
100
- arr.#pinId = id;
101
- return arr;
102
- }
103
-
104
- /** Release the GC root fromView placed on this array's host buffer.
105
- * JS-thread-only by construction (it's a plain method) — this is the
106
- * replacement for the deadlocking JSCallback unpin dtor. Idempotent;
107
- * no-op for non-fromView arrays. Caller contract: only call once mlx can
108
- * no longer touch the buffer (see fromView doc), or when the memory is
109
- * owned elsewhere (an mmap kept mapped past every use). */
110
- unpinHostBuffer(): void {
111
- if (this.#pinId !== 0) {
112
- pinned.delete(this.#pinId);
113
- this.#pinId = 0;
114
- }
115
- }
116
-
117
- /** Zero-copy: wrap a raw pointer (e.g. into an mmap'd weight shard).
118
- * The caller guarantees the memory outlives EVERY mlx
119
- * reference to the array — including GPU command buffers that retain the
120
- * buffer past dispose() — i.e. mmaps backing these arrays stay mapped for
121
- * the process. The dtor is free(NULL) (payload 0): native + no-op, so
122
- * mlx may run it from the Metal completion thread without touching the
123
- * JS runtime (the old JSCallback dtor deadlocked serving / SIGTRAPed
124
- * under GC when that thread held the last reference — 2026-07-06). */
125
- static fromPointer(dataPtr: number, shape: number[], dtype: Dtype): MlxArray {
126
- const sb = shapeBuf(shape);
127
- const handle = C.mlx_array_new_data_managed_payload(
128
- dataPtr, ptr(sb), shape.length, dtype, 0, freeFnAddr,
129
- );
130
- return new MlxArray(handle);
131
- }
132
-
133
- /** Copying constructor for small host data. */
134
- static fromFloat32(data: Float32Array, shape: number[]): MlxArray {
135
- const sb = shapeBuf(shape);
136
- return new MlxArray(
137
- C.mlx_array_new_data(ptr(data), ptr(sb), shape.length, Dtype.float32),
138
- );
139
- }
140
-
141
- /** Copy raw bytes into a fresh mlx-managed (page-aligned) LEAF array of the
142
- * given dtype/shape. Unlike fromView (which no-copy-wraps the host buffer and
143
- * is unsafe to feed to GPU ops when unaligned), mlx_array_new_data COPIES, so
144
- * the source bytes need not outlive the array and GPU ops are safe. Used to
145
- * detach a value from its computation graph: `MlxArray.fromBytesCopy(
146
- * x.rawBytes(), x.shape, x.dtype)` yields a graph-free leaf with x's exact
147
- * bytes (segmented-backward boundaries — src/train/segmented.ts). */
148
- static fromBytesCopy(bytes: Uint8Array, shape: number[], dtype: Dtype): MlxArray {
149
- const sb = shapeBuf(shape);
150
- return new MlxArray(
151
- C.mlx_array_new_data(ptr(bytes), ptr(sb), shape.length, dtype),
152
- );
153
- }
154
-
155
- static fromInt32(data: Int32Array, shape: number[]): MlxArray {
156
- const sb = shapeBuf(shape);
157
- return new MlxArray(
158
- C.mlx_array_new_data(ptr(data), ptr(sb), shape.length, Dtype.int32),
159
- );
160
- }
161
-
162
- /** Graph-free LEAF with this array's exact bytes — ONE copy, straight from
163
- * the (evaluated) mlx buffer into a fresh mlx-owned array, no JS-heap
164
- * intermediate (`fromBytesCopy(rawBytes())` is TWO copies: device→JS heap
165
- * →new leaf). mlx_array_new_data copies synchronously, so the source only
166
- * has to outlive this call. The buffer is read LINEARLY — the caller must
167
- * pass a row-major contiguous array (ops.contiguous first for views), same
168
- * contract as rawBytes. Segmented-backward boundary detach hot path. */
169
- detachCopy(): MlxArray {
170
- this.eval();
171
- const dt = this.dtype;
172
- const p =
173
- dt === Dtype.float32 ? C.mlx_array_data_float32(this.handle)
174
- : dt === Dtype.float16 ? C.mlx_array_data_float16(this.handle)
175
- : dt === Dtype.bfloat16 ? C.mlx_array_data_bfloat16(this.handle)
176
- : dt === Dtype.uint32 ? C.mlx_array_data_uint32(this.handle)
177
- : null;
178
- if (p === null) throw new Error(`detachCopy: unsupported dtype ${this.dtypeName}`);
179
- const sb = shapeBuf(this.shape);
180
- return new MlxArray(C.mlx_array_new_data(p as never, ptr(sb), this.ndim, dt));
181
- }
182
-
183
- get handle(): MlxHandle {
184
- if (this.#disposed) throw new Error("MlxArray used after dispose");
185
- return this.#handle;
186
- }
187
-
188
- get ndim(): number {
189
- return Number(C.mlx_array_ndim(this.handle));
190
- }
191
-
192
- // NOTE on the DFG stale-read bug (lab/repro/bun-ffi-f64/ISSUE.md): the
193
- // toArrayBuffer readbacks below (shape/rawBytes/toFloat32) are safe.
194
- // The hazard is reading a *pre-existing* typed array after an FFI call
195
- // wrote through its pointer — the JIT forwards a stale value from before
196
- // the call. Here the view is constructed *after* the call, from the
197
- // pointer the call returned: the loads are data-dependent on the call
198
- // result and there is no prior JS load/store to forward from.
199
-
200
- get shape(): number[] {
201
- const n = this.ndim;
202
- if (n === 0) return [];
203
- const shapePtr = C.mlx_array_shape(this.handle);
204
- return [...new Int32Array(toArrayBuffer(shapePtr!, 0, n * 4))];
205
- }
206
-
207
- get dtype(): Dtype {
208
- return C.mlx_array_dtype(this.handle) as Dtype;
209
- }
210
-
211
- get dtypeName(): string {
212
- return DTYPE_NAMES[this.dtype] ?? `unknown(${this.dtype})`;
213
- }
214
-
215
- get size(): number {
216
- return Number(C.mlx_array_size(this.handle));
217
- }
218
-
219
- get nbytes(): number {
220
- return Number(C.mlx_array_nbytes(this.handle));
221
- }
222
-
223
- eval(): this {
224
- if (C.mlx_array_eval(this.handle) !== 0) throw new Error(`mlx_array_eval failed: ${takeMlxError() ?? ""}`);
225
- return this;
226
- }
227
-
228
- /** Cast to another dtype (lazy). */
229
- astype(dtype: Dtype, stream: MlxHandle = gpuStream): MlxArray {
230
- return new MlxArray(
231
- outArray("astype", (slot) => C.mlx_astype(slot, this.handle, dtype, stream)),
232
- );
233
- }
234
-
235
- /** Raw bytes of a supported floating-point or integer array (copy). */
236
- rawBytes(): Uint8Array {
237
- return this.rawBytesView().slice();
238
- }
239
-
240
- /** ZERO-COPY view of the evaluated array's bytes — aliases the mlx
241
- * buffer directly, no JS-heap copy. Valid only while THIS array is
242
- * alive and unmutated: do not retain past dispose(). Built for
243
- * bulk-write paths (kv-store's streamed writer) where per-tensor
244
- * rawBytes() copies pile up in the JS heap faster than GC collects
245
- * them — the residual A7 whole-entry RSS spike (2026-07-07). The
246
- * array must be contiguous (ops.contiguous first for views), same
247
- * contract as rawBytes. */
248
- rawBytesView(): Uint8Array {
249
- this.eval();
250
- const dt = this.dtype;
251
- const p =
252
- dt === Dtype.float32 ? C.mlx_array_data_float32(this.handle)
253
- : dt === Dtype.float16 ? C.mlx_array_data_float16(this.handle)
254
- : dt === Dtype.bfloat16 ? C.mlx_array_data_bfloat16(this.handle)
255
- : dt === Dtype.uint32 ? C.mlx_array_data_uint32(this.handle)
256
- : dt === Dtype.int32 ? C.mlx_array_data_int32(this.handle)
257
- : dt === Dtype.uint8 ? C.mlx_array_data_uint8(this.handle)
258
- : dt === Dtype.int8 ? C.mlx_array_data_int8(this.handle)
259
- : null;
260
- if (p === null) throw new Error(`rawBytesView: unsupported dtype ${this.dtypeName}`);
261
- return new Uint8Array(toArrayBuffer(p!, 0, this.nbytes));
262
- }
263
-
264
- /** Read back an INTEGER array without enqueueing a cast kernel: eval +
265
- * direct buffer read for uint32/int32. A cast (`astype`) is a NEW op that
266
- * queues BEHIND everything already dispatched on the GPU stream — on the
267
- * batched decode hot path, reading the pipeline register via toFloat32
268
- * stalled the "overlapped" token read for a FULL step of GPU work every
269
- * token (the core of the Phase-0 B=1 gap; unified-engine plan Phase 2).
270
- * Non-integer dtypes fall back to the rounded float readback. */
271
- toIntTokens(): number[] {
272
- if (this.dtype === Dtype.uint32) {
273
- this.eval();
274
- const p = C.mlx_array_data_uint32(this.handle);
275
- return [...new Uint32Array(toArrayBuffer(p!, 0, this.size * 4))];
276
- }
277
- if (this.dtype === Dtype.int32) {
278
- this.eval();
279
- const p = C.mlx_array_data_int32(this.handle);
280
- return [...new Int32Array(toArrayBuffer(p!, 0, this.size * 4))];
281
- }
282
- return [...this.toFloat32()].map((x) => Math.round(x));
283
- }
284
-
285
- /** Read back as float32 (casts on GPU if needed, then copies out). */
286
- toFloat32(): Float32Array {
287
- const src = this.dtype === Dtype.float32 ? this : this.astype(Dtype.float32);
288
- src.eval();
289
- const dataPtr = C.mlx_array_data_float32(src.handle);
290
- const out = new Float32Array(toArrayBuffer(dataPtr!, 0, src.size * 4)).slice();
291
- if (src !== this) src.dispose();
292
- return out;
293
- }
294
-
295
- /** Read an f32/f16/bf16 array numerically as float32 without enqueueing a
296
- * GPU cast. This evaluates the ORIGINAL array, then expands 16-bit values
297
- * on the host. Use this for small readbacks after later GPU work has
298
- * already been dispatched: toFloat32() would append astype(float32) behind
299
- * that work and turn the readback into an accidental full-step barrier. */
300
- toFloat32Host(): Float32Array {
301
- this.eval();
302
- const dt = this.dtype;
303
- if (dt === Dtype.float32) {
304
- const p = C.mlx_array_data_float32(this.handle);
305
- return new Float32Array(toArrayBuffer(p!, 0, this.size * 4)).slice();
306
- }
307
- if (dt === Dtype.bfloat16) {
308
- const p = C.mlx_array_data_bfloat16(this.handle);
309
- const src = new Uint16Array(toArrayBuffer(p!, 0, this.size * 2));
310
- const words = new Uint32Array(src.length);
311
- for (let i = 0; i < src.length; i++) words[i] = src[i]! << 16;
312
- return new Float32Array(words.buffer);
313
- }
314
- if (dt === Dtype.float16) {
315
- const p = C.mlx_array_data_float16(this.handle);
316
- const src = new Uint16Array(toArrayBuffer(p!, 0, this.size * 2));
317
- const out = new Float32Array(src.length);
318
- for (let i = 0; i < src.length; i++) {
319
- const bits = src[i]!;
320
- const sign = bits & 0x8000;
321
- const exponent = (bits >>> 10) & 0x1f;
322
- const fraction = bits & 0x03ff;
323
- let value: number;
324
- if (exponent === 0) {
325
- value = fraction === 0 ? 0 : fraction * 2 ** -24;
326
- } else if (exponent === 0x1f) {
327
- value = fraction === 0 ? Infinity : NaN;
328
- } else {
329
- value = (1 + fraction / 1024) * 2 ** (exponent - 15);
330
- }
331
- out[i] = sign ? -value : value;
332
- }
333
- return out;
334
- }
335
- throw new Error(`toFloat32Host: unsupported dtype ${this.dtypeName}`);
336
- }
337
-
338
- /** Basic slice: start/stop per dimension (stride 1). */
339
- slice(start: number[], stop: number[], stream: MlxHandle = gpuStream): MlxArray {
340
- const s = new Int32Array(start);
341
- const e = new Int32Array(stop);
342
- const strides = new Int32Array(start.map(() => 1));
343
- return new MlxArray(
344
- outArray("slice", (slot) =>
345
- C.mlx_slice(
346
- slot, this.handle,
347
- ptr(s), BigInt(s.length), ptr(e), BigInt(e.length),
348
- ptr(strides), BigInt(strides.length), stream,
349
- ),
350
- ),
351
- );
352
- }
353
-
354
- add(other: MlxArray, stream: MlxHandle = gpuStream): MlxArray {
355
- return new MlxArray(
356
- outArray("add", (slot) => C.mlx_add(slot, this.handle, other.handle, stream)),
357
- );
358
- }
359
-
360
- /** Dequantize (w, scales, biases) → full precision. */
361
- static dequantize(
362
- w: MlxArray, scales: MlxArray, biases: MlxArray | null,
363
- groupSize: number, bits: number, mode = "affine",
364
- stream: MlxHandle = gpuStream,
365
- ): MlxArray {
366
- const modeBuf = Buffer.from(mode + "\0", "utf8");
367
- return new MlxArray(
368
- outArray("dequantize", (slot) =>
369
- C.mlx_dequantize(
370
- slot, w.handle, scales.handle, biases?.handle ?? 0n,
371
- optInt(groupSize), optInt(bits), ptr(modeBuf),
372
- 0n /* global_scale */, optInt(null) /* out dtype */, stream,
373
- ),
374
- ),
375
- );
376
- }
377
-
378
- dispose(): void {
379
- if (this.#disposed) return;
380
- this.#disposed = true;
381
- registry.unregister(this.#token);
382
- C.mlx_array_free(this.#handle);
383
- }
384
-
385
- [Symbol.dispose](): void {
386
- this.dispose();
387
- }
388
- }
@@ -1,304 +0,0 @@
1
- // Native autograd via mlx-c value_and_grad over a JS loss closure.
2
- //
3
- // Encapsulates the exact FFI lifecycle proven in lab/spikes/phase-train-vag.ts:
4
- // JS loss closure (JSCallback) → mlx_closure_new_func_payload →
5
- // mlx_value_and_grad → mlx_closure_value_and_grad_apply → read grads.
6
- //
7
- // House rules honored:
8
- // - Out-params read via bun:ffi `read.u64` (never slot[0] — DFG stale-read).
9
- // - The JS closure NEVER throws across the FFI boundary (try/catch → return 1);
10
- // the captured error is re-thrown on the JS side after apply() fails.
11
- // - All native handles (closure, value_and_grad closure, JSCallback) are held
12
- // alive on the instance and freed in dispose().
13
-
14
- import { JSCallback, ptr, read } from "bun:ffi";
15
- import { C, takeMlxError } from "./ffi";
16
- import { MlxArray } from "./array";
17
-
18
- type CallbackHandle = Pick<JSCallback, "ptr" | "close">;
19
- type NativeCall<F extends (...args: any[]) => any> =
20
- (...args: Parameters<F>) => ReturnType<F>;
21
-
22
- /** Constructor-only dependency seam for deterministic native failure tests. */
23
- export interface ValueAndGradConstructorHooks {
24
- callback?: (
25
- callback: ConstructorParameters<typeof JSCallback>[0],
26
- definition: ConstructorParameters<typeof JSCallback>[1],
27
- ) => CallbackHandle;
28
- closureNew?: NativeCall<typeof C.mlx_closure_new_func_payload>;
29
- transformedNew?: NativeCall<typeof C.mlx_closure_value_and_grad_new>;
30
- transform?: NativeCall<typeof C.mlx_value_and_grad>;
31
- transformedFree?: NativeCall<typeof C.mlx_closure_value_and_grad_free>;
32
- closureFree?: NativeCall<typeof C.mlx_closure_free>;
33
- }
34
-
35
- /** A reusable value-and-grad over a JS-built loss graph.
36
- *
37
- * `loss(primals)` receives the input arrays in argument order and must
38
- * return a single SCALAR MlxArray (the loss). The graph it builds is
39
- * differentiated w.r.t. the inputs named in `argIdx`. `apply(primals)`
40
- * returns the loss value and exactly `argIdx.length` gradients (one per
41
- * differentiated input, in `argIdx` order).
42
- *
43
- * The closure must not throw; if the user `loss` throws, the error is
44
- * captured and surfaced from `apply()`. The MlxArrays handed to `loss`
45
- * are owned by mlx — do NOT dispose them; the returned loss IS disposed
46
- * of by mlx's graph. */
47
- export class ValueAndGrad {
48
- readonly #cb: CallbackHandle;
49
- readonly #closure: bigint;
50
- readonly #vag: bigint;
51
- readonly #argIdx: Int32Array;
52
- readonly #freeClosure: NativeCall<typeof C.mlx_closure_free>;
53
- readonly #freeVag: NativeCall<typeof C.mlx_closure_value_and_grad_free>;
54
- #closureError: string | null = null;
55
- #disposed = false;
56
-
57
- constructor(
58
- loss: (primals: MlxArray[]) => MlxArray,
59
- argIdx: number[],
60
- hooks: ValueAndGradConstructorHooks = {},
61
- ) {
62
- if (argIdx.length === 0) throw new Error("ValueAndGrad: argIdx must be non-empty");
63
- this.#argIdx = new Int32Array(argIdx);
64
- const makeCallback = hooks.callback ?? ((callback, definition) => new JSCallback(callback, definition));
65
- const closureNew = hooks.closureNew ?? C.mlx_closure_new_func_payload;
66
- const transformedNew = hooks.transformedNew ?? C.mlx_closure_value_and_grad_new;
67
- const transform = hooks.transform ?? C.mlx_value_and_grad;
68
- this.#freeClosure = hooks.closureFree ?? C.mlx_closure_free;
69
- this.#freeVag = hooks.transformedFree ?? C.mlx_closure_value_and_grad_free;
70
-
71
- const cb = makeCallback(
72
- (outPtr: number, inVec: bigint, _payload: number): number => {
73
- try {
74
- // Read the primals out of the input vector_array. mlx_vector_array_get
75
- // returns a fresh (ref-counted) handle, so disposing the wrapper
76
- // afterward is correct — it drops our reference, not mlx's graph
77
- // reference (proven in lab/spikes/phase-train-vag.ts).
78
- const n = Number(C.mlx_vector_array_size(inVec));
79
- const primals: MlxArray[] = [];
80
- for (let i = 0; i < n; i++) {
81
- const slot = new BigUint64Array([C.mlx_array_new()]);
82
- const sp = ptr(slot);
83
- if (C.mlx_vector_array_get(sp, inVec, BigInt(i)) !== 0)
84
- throw new Error(`vector_array_get(${i}) failed`);
85
- primals.push(new MlxArray(read.u64(sp, 0)));
86
- }
87
- const out = loss(primals);
88
- // Populate *out with the single scalar loss. set_data copies the
89
- // handle into the output vector (mlx retains its own reference), so
90
- // disposing the loss wrapper afterward drops only our reference.
91
- const handles = new BigUint64Array([out.handle]);
92
- if (C.mlx_vector_array_set_data(outPtr as never, ptr(handles), 1n) !== 0)
93
- throw new Error("vector_array_set_data failed");
94
- for (const p of primals) p.dispose();
95
- out.dispose();
96
- return 0;
97
- } catch (e) {
98
- this.#closureError = e instanceof Error ? e.message : String(e);
99
- return 1;
100
- }
101
- },
102
- { args: ["ptr", "u64", "ptr"], returns: "i32" },
103
- );
104
-
105
- let closure: bigint | null = null;
106
- let vagSlot: BigUint64Array | null = null;
107
- try {
108
- closure = closureNew(cb.ptr as never, null, null);
109
- vagSlot = new BigUint64Array([transformedNew()]);
110
- if (transform(ptr(vagSlot), closure, ptr(this.#argIdx), BigInt(this.#argIdx.length)) !== 0)
111
- throw new Error("mlx_value_and_grad failed");
112
- this.#cb = cb;
113
- this.#closure = closure;
114
- this.#vag = read.u64(ptr(vagSlot), 0);
115
- } catch (e) {
116
- // mlx-c out-params are initialized live handles. On failure the slot
117
- // still owns whichever handle it contains and must be freed explicitly.
118
- if (vagSlot) this.#freeVag(read.u64(ptr(vagSlot), 0));
119
- if (closure !== null) this.#freeClosure(closure);
120
- cb.close();
121
- throw e;
122
- }
123
- }
124
-
125
- /** Run the loss + backward on `primals` (in argument order). Returns the
126
- * scalar loss and one gradient per differentiated input. Caller owns all
127
- * returned arrays (dispose them). */
128
- apply(primals: MlxArray[]): { value: MlxArray; grads: MlxArray[] } {
129
- if (this.#disposed) throw new Error("ValueAndGrad used after dispose");
130
- this.#closureError = null;
131
-
132
- const handles = new BigUint64Array(primals.map((p) => p.handle));
133
- const inVec = C.mlx_vector_array_new_data(ptr(handles), BigInt(primals.length));
134
-
135
- const valueSlot = new BigUint64Array([C.mlx_vector_array_new()]);
136
- const gradsSlot = new BigUint64Array([C.mlx_vector_array_new()]);
137
- const st = C.mlx_closure_value_and_grad_apply(ptr(valueSlot), ptr(gradsSlot), this.#vag, inVec);
138
- const valueVec = read.u64(ptr(valueSlot), 0);
139
- const gradsVec = read.u64(ptr(gradsSlot), 0);
140
- if (st !== 0) {
141
- C.mlx_vector_array_free(valueVec);
142
- C.mlx_vector_array_free(gradsVec);
143
- C.mlx_vector_array_free(inVec);
144
- // Surface whichever error fired: a JS throw inside the loss closure
145
- // (#closureError) or MLX's own C-level error (takeMlxError) — e.g. a
146
- // missing vjp for an op in the forward graph. Discarding the latter
147
- // turned an "unsupported gradient" into an opaque failure.
148
- const mlxErr = takeMlxError();
149
- const detail = this.#closureError ?? mlxErr ?? "";
150
- throw new Error(`value_and_grad_apply failed${detail ? `: ${detail}` : ""}`);
151
- }
152
-
153
- // value vector has exactly one entry (the scalar loss).
154
- const value = vecGet(valueVec, 0);
155
-
156
- const nGrads = Number(C.mlx_vector_array_size(gradsVec));
157
- if (nGrads !== this.#argIdx.length) {
158
- value.dispose();
159
- C.mlx_vector_array_free(valueVec);
160
- C.mlx_vector_array_free(gradsVec);
161
- C.mlx_vector_array_free(inVec);
162
- throw new Error(`expected ${this.#argIdx.length} grads, got ${nGrads}`);
163
- }
164
- const grads: MlxArray[] = [];
165
- for (let i = 0; i < nGrads; i++) grads.push(vecGet(gradsVec, i));
166
-
167
- C.mlx_vector_array_free(valueVec);
168
- C.mlx_vector_array_free(gradsVec);
169
- C.mlx_vector_array_free(inVec);
170
- return { value, grads };
171
- }
172
-
173
- dispose(): void {
174
- if (this.#disposed) return;
175
- this.#disposed = true;
176
- this.#freeVag(this.#vag);
177
- this.#freeClosure(this.#closure);
178
- this.#cb.close();
179
- }
180
-
181
- [Symbol.dispose](): void {
182
- this.dispose();
183
- }
184
- }
185
-
186
- /** Pull array `i` out of a vector_array into an owned MlxArray wrapper. */
187
- function vecGet(vec: bigint, i: number): MlxArray {
188
- const slot = new BigUint64Array([C.mlx_array_new()]);
189
- const sp = ptr(slot);
190
- if (C.mlx_vector_array_get(sp, vec, BigInt(i)) !== 0)
191
- throw new Error(`vector_array_get(${i}) failed`);
192
- return new MlxArray(read.u64(sp, 0));
193
- }
194
-
195
- /** Reverse-mode AD via mlx_vjp: given a function `fn(primals) -> outputs` and a
196
- * cotangent per output, returns the cotangent w.r.t. EVERY primal. This is the
197
- * natural primitive for segmented backward (segment forward + dh -> [dh_in,
198
- * ...dLoRA]) — no surrogate scalar and no value_and_grad closure. Unlike
199
- * ValueAndGrad it returns a vjp for ALL primals (not a selected argnum subset).
200
- *
201
- * `fn` must build its output graph from the input arrays in argument order and
202
- * return them (most often a single array). It must not throw; a throw is
203
- * captured and surfaced from apply(). The MlxArrays handed to `fn` are owned by
204
- * mlx — do NOT dispose them. Lifecycle/house-rules mirror ValueAndGrad. */
205
- export class Vjp {
206
- readonly #cb: JSCallback;
207
- readonly #closure: bigint;
208
- readonly #nOut: number;
209
- #closureError: string | null = null;
210
- #disposed = false;
211
-
212
- /** @param nOut number of arrays `fn` returns (length of the cotangent list). */
213
- constructor(fn: (primals: MlxArray[]) => MlxArray[], nOut = 1) {
214
- this.#nOut = nOut;
215
- this.#cb = new JSCallback(
216
- (outPtr: number, inVec: bigint, _payload: number): number => {
217
- try {
218
- const n = Number(C.mlx_vector_array_size(inVec));
219
- const primals: MlxArray[] = [];
220
- for (let i = 0; i < n; i++) {
221
- const slot = new BigUint64Array([C.mlx_array_new()]);
222
- const sp = ptr(slot);
223
- if (C.mlx_vector_array_get(sp, inVec, BigInt(i)) !== 0)
224
- throw new Error(`vector_array_get(${i}) failed`);
225
- primals.push(new MlxArray(read.u64(sp, 0)));
226
- }
227
- const outs = fn(primals);
228
- const handles = new BigUint64Array(outs.map((o) => o.handle));
229
- if (C.mlx_vector_array_set_data(outPtr as never, ptr(handles), BigInt(outs.length)) !== 0)
230
- throw new Error("vector_array_set_data failed");
231
- for (const p of primals) p.dispose();
232
- for (const o of outs) o.dispose();
233
- return 0;
234
- } catch (e) {
235
- this.#closureError = e instanceof Error ? e.message : String(e);
236
- return 1;
237
- }
238
- },
239
- { args: ["ptr", "u64", "ptr"], returns: "i32" },
240
- );
241
- this.#closure = C.mlx_closure_new_func_payload(this.#cb.ptr as never, null, null);
242
- }
243
-
244
- /** Run the vjp on `primals` with `cotangents` (one per output of `fn`).
245
- * Returns the outputs (fn(primals)) and one cotangent per primal (in primal
246
- * order). Caller owns all returned arrays. */
247
- apply(primals: MlxArray[], cotangents: MlxArray[]): { outputs: MlxArray[]; vjps: MlxArray[] } {
248
- if (this.#disposed) throw new Error("Vjp used after dispose");
249
- if (cotangents.length !== this.#nOut)
250
- throw new Error(`Vjp: expected ${this.#nOut} cotangents, got ${cotangents.length}`);
251
- this.#closureError = null;
252
-
253
- const pHandles = new BigUint64Array(primals.map((p) => p.handle));
254
- const cHandles = new BigUint64Array(cotangents.map((c) => c.handle));
255
- const inVec = C.mlx_vector_array_new_data(ptr(pHandles), BigInt(primals.length));
256
- const cotVec = C.mlx_vector_array_new_data(ptr(cHandles), BigInt(cotangents.length));
257
-
258
- const outSlot = new BigUint64Array([C.mlx_vector_array_new()]);
259
- const vjpSlot = new BigUint64Array([C.mlx_vector_array_new()]);
260
- const st = C.mlx_vjp(ptr(outSlot), ptr(vjpSlot), this.#closure, inVec, cotVec);
261
- const outVec = read.u64(ptr(outSlot), 0);
262
- const vjpVec = read.u64(ptr(vjpSlot), 0);
263
- if (st !== 0) {
264
- C.mlx_vector_array_free(outVec);
265
- C.mlx_vector_array_free(vjpVec);
266
- C.mlx_vector_array_free(inVec);
267
- C.mlx_vector_array_free(cotVec);
268
- const mlxErr = takeMlxError();
269
- const detail = this.#closureError ?? mlxErr ?? "";
270
- throw new Error(`mlx_vjp failed${detail ? `: ${detail}` : ""}`);
271
- }
272
-
273
- const nVjp = Number(C.mlx_vector_array_size(vjpVec));
274
- if (nVjp !== primals.length) {
275
- C.mlx_vector_array_free(outVec);
276
- C.mlx_vector_array_free(vjpVec);
277
- C.mlx_vector_array_free(inVec);
278
- C.mlx_vector_array_free(cotVec);
279
- throw new Error(`Vjp: expected ${primals.length} vjps, got ${nVjp}`);
280
- }
281
- const nOut = Number(C.mlx_vector_array_size(outVec));
282
- const outputs: MlxArray[] = [];
283
- for (let i = 0; i < nOut; i++) outputs.push(vecGet(outVec, i));
284
- const vjps: MlxArray[] = [];
285
- for (let i = 0; i < nVjp; i++) vjps.push(vecGet(vjpVec, i));
286
-
287
- C.mlx_vector_array_free(outVec);
288
- C.mlx_vector_array_free(vjpVec);
289
- C.mlx_vector_array_free(inVec);
290
- C.mlx_vector_array_free(cotVec);
291
- return { outputs, vjps };
292
- }
293
-
294
- dispose(): void {
295
- if (this.#disposed) return;
296
- this.#disposed = true;
297
- C.mlx_closure_free(this.#closure);
298
- this.#cb.close();
299
- }
300
-
301
- [Symbol.dispose](): void {
302
- this.dispose();
303
- }
304
- }