mlx-bun 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/README.md +71 -588
  2. package/docs/README.md +94 -0
  3. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  4. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  5. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  6. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  7. package/docs/archive/investigations/openjarvis-fit.md +198 -0
  8. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  9. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  10. package/docs/archive/investigations/qwen38-27b-campaign-log.md +1092 -0
  11. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  12. package/docs/archive/planning/release-notes-v0.3.0.md +35 -0
  13. package/docs/design/batching.md +1841 -0
  14. package/docs/design/decode-speed-program.md +2346 -169
  15. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  16. package/docs/design/generic-model-support.md +655 -334
  17. package/docs/design/kv-cache.md +824 -0
  18. package/docs/design/orpo-training.md +673 -1239
  19. package/docs/design/speculative-decoding.md +1990 -0
  20. package/docs/design/turboquant.md +2212 -0
  21. package/docs/design/unified-engine-frontier-plan.md +1833 -727
  22. package/docs/design/web-chat-redesign.md +666 -1083
  23. package/docs/planning/PRODUCT_ROADMAP.md +50 -1
  24. package/docs/planning/release-notes-v0.4.0.md +45 -0
  25. package/docs/planning/video-series.md +2 -2
  26. package/docs/reference/benchmarks.md +3613 -0
  27. package/docs/reference/cli.md +434 -160
  28. package/docs/reference/distribution.md +328 -182
  29. package/docs/reference/environment.md +398 -0
  30. package/docs/reference/glossary.md +39 -0
  31. package/docs/reference/library-api.md +566 -168
  32. package/docs/reference/memory.md +227 -64
  33. package/docs/reference/models.md +113 -6
  34. package/docs/reference/server-api.md +944 -429
  35. package/docs/reference/server-config.md +740 -338
  36. package/docs/reference/training.md +393 -254
  37. package/docs/reference/troubleshooting.md +158 -0
  38. package/package.json +9 -4
  39. package/src/audio/decode.ts +2 -2
  40. package/src/audio/features.ts +2 -2
  41. package/src/backends/mlx/assistant-target.ts +46 -0
  42. package/src/backends/mlx/autoregressive-draft-rows.ts +120 -0
  43. package/src/backends/mlx/autoregressive.ts +108 -0
  44. package/src/backends/mlx/batch-group.ts +1790 -0
  45. package/src/backends/mlx/cache-attachment.ts +67 -0
  46. package/src/backends/mlx/cache-layout.ts +31 -0
  47. package/src/backends/mlx/checkpoint-state.ts +53 -0
  48. package/src/backends/mlx/continuation-persistence.ts +106 -0
  49. package/src/backends/mlx/continuation-request.ts +43 -0
  50. package/src/backends/mlx/continuation.ts +77 -0
  51. package/src/backends/mlx/diffusion.ts +39 -0
  52. package/src/backends/mlx/draft-target.ts +32 -0
  53. package/src/backends/mlx/evaluation.ts +105 -0
  54. package/src/backends/mlx/fill-append.ts +45 -0
  55. package/src/backends/mlx/full-kv-row-append.ts +32 -0
  56. package/src/backends/mlx/full-kv-row-donor.ts +54 -0
  57. package/src/backends/mlx/full-transitioning-kv-rows.ts +65 -0
  58. package/src/backends/mlx/gateway-binding.ts +130 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/kv-codec.ts +9 -0
  61. package/src/backends/mlx/kv-maintenance.ts +133 -0
  62. package/src/backends/mlx/kv-tensor-rows.ts +212 -0
  63. package/src/backends/mlx/memory-client.ts +189 -0
  64. package/src/backends/mlx/methods.ts +90 -0
  65. package/src/backends/mlx/model-prompt.ts +164 -0
  66. package/src/backends/mlx/model-serving.ts +79 -0
  67. package/src/backends/mlx/prefill-cohort.ts +89 -0
  68. package/src/backends/mlx/prefill-rows.ts +200 -0
  69. package/src/backends/mlx/prefill.ts +33 -0
  70. package/src/backends/mlx/projected-context-rows.ts +72 -0
  71. package/src/backends/mlx/request-policy.ts +20 -0
  72. package/src/backends/mlx/request-state-policy.ts +41 -0
  73. package/src/backends/mlx/rollback.ts +89 -0
  74. package/src/backends/mlx/row-sampling.ts +49 -0
  75. package/src/backends/mlx/serial-executor.ts +242 -0
  76. package/src/backends/mlx/speculative-group.ts +359 -0
  77. package/src/backends/mlx/speculative-round.ts +161 -0
  78. package/src/backends/mlx/speculative.ts +114 -0
  79. package/src/backends/mlx/state-rows.ts +104 -0
  80. package/src/backends/mlx/state-views.ts +46 -0
  81. package/src/backends/mlx/target-layout-capability.ts +35 -0
  82. package/src/backends/mlx/text-engine.ts +73 -0
  83. package/src/backends/mlx/transitioning-kv-rows.ts +165 -0
  84. package/src/cli.ts +66 -58
  85. package/src/client.ts +66 -0
  86. package/src/config.ts +21 -4
  87. package/src/contracts/completion.ts +16 -0
  88. package/src/contracts/execution.ts +60 -0
  89. package/src/contracts/generation.ts +103 -0
  90. package/src/contracts/host.ts +7 -0
  91. package/src/contracts/jobs.ts +66 -0
  92. package/src/contracts/pi-provider.ts +30 -0
  93. package/src/contracts/pi.ts +259 -0
  94. package/src/contracts/prefix-cache.ts +23 -0
  95. package/src/contracts/resources.ts +25 -0
  96. package/src/contracts/sampling.ts +23 -0
  97. package/src/contracts/scheduling.ts +45 -0
  98. package/src/contracts/tsconfig.json +14 -0
  99. package/src/diffusion/diffusion-generate.ts +218 -153
  100. package/src/embed.ts +1 -1
  101. package/src/engine/admission.ts +59 -0
  102. package/src/engine/cancellation.ts +38 -0
  103. package/src/engine/engine.ts +56 -0
  104. package/src/engine/execution-coordinator.ts +70 -0
  105. package/src/engine/execution-plan.ts +53 -0
  106. package/src/engine/resources.ts +53 -0
  107. package/src/engine/scheduler.ts +72 -0
  108. package/src/engine/session.ts +247 -0
  109. package/src/eval/README.md +44 -1
  110. package/src/eval/kl.ts +236 -3
  111. package/src/eval/reference-logits.ts +207 -0
  112. package/src/eval/runner.ts +8 -96
  113. package/src/fill/echo-index.ts +188 -0
  114. package/src/fill/fill-session.ts +452 -0
  115. package/src/fill/proposal.ts +68 -0
  116. package/src/fill/schema-rows.ts +506 -0
  117. package/src/fill/tool-boundary.ts +103 -0
  118. package/src/fit.ts +30 -16
  119. package/src/generate.ts +709 -417
  120. package/src/grammar.ts +12 -7
  121. package/src/harness-pi.ts +14 -33
  122. package/src/hub-rest.ts +4 -4
  123. package/src/index.ts +7 -0
  124. package/src/inference/denoising.ts +17 -0
  125. package/src/inference/draft-acceptance.ts +41 -0
  126. package/src/inference/draft-output.ts +49 -0
  127. package/src/inference/graph.ts +33 -0
  128. package/src/inference/prefill.ts +39 -0
  129. package/src/inference/rollback.ts +7 -0
  130. package/src/jobs/db.ts +4 -0
  131. package/src/jobs/index.ts +2 -0
  132. package/src/jobs/job-entry.ts +12 -12
  133. package/src/jobs/runner.ts +98 -13
  134. package/src/jobs/task-client.ts +19 -0
  135. package/src/jobs/types.ts +2 -58
  136. package/src/kv-scheme.ts +70 -12
  137. package/src/kv-store.ts +177 -63
  138. package/src/lab/README.md +18 -0
  139. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  140. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  141. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +5 -5
  142. package/src/lab/paged-kv/paged-kv-rows.ts +83 -0
  143. package/src/{model → lab/paged-kv}/paged-kv.ts +32 -15
  144. package/src/library.ts +40 -0
  145. package/src/lora.ts +18 -0
  146. package/src/media-fetch.ts +1 -1
  147. package/src/memory/article.ts +1 -1
  148. package/src/memory/chunk.ts +1 -1
  149. package/src/memory/model.ts +30 -169
  150. package/src/memory/prompts.ts +1 -1
  151. package/src/memory/rest.ts +1 -1
  152. package/src/memory/schedule.ts +1 -1
  153. package/src/memory/stages.ts +4 -1
  154. package/src/memory/vault.ts +1 -3
  155. package/src/mlx/array.ts +11 -11
  156. package/src/mlx/compile.ts +12 -2
  157. package/src/mlx/ffi.ts +58 -11
  158. package/src/mlx/materialize.ts +23 -0
  159. package/src/mlx/metal-kernel.ts +10 -11
  160. package/src/mlx/ops.ts +33 -13
  161. package/src/mlx/quantized-rows.ts +36 -0
  162. package/src/mlx/token-bitmask.ts +52 -0
  163. package/src/mlx/turboquant-kv-decode.ts +82 -0
  164. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  165. package/src/mlx/turboquant-ops.ts +33 -3
  166. package/src/mlx/turboquant-tables.ts +2 -2
  167. package/src/model/artifact-identity.ts +73 -0
  168. package/src/model/batched-kv.ts +235 -0
  169. package/src/model/batched-mask.ts +20 -6
  170. package/src/model/batched-quant.ts +9 -3
  171. package/src/model/batched-quantized-kv.ts +144 -0
  172. package/src/model/batched-rotating-quant.ts +78 -17
  173. package/src/model/batched-rotating-state.ts +76 -0
  174. package/src/model/batched-rotating.ts +65 -23
  175. package/src/model/batched-row-storage.ts +52 -0
  176. package/src/model/batched-ssm.ts +52 -0
  177. package/src/model/batched-turboquant-kv.ts +93 -0
  178. package/src/model/compiled-decode.ts +8 -2
  179. package/src/model/decoded-kv-donor.ts +12 -0
  180. package/src/model/delayed-quantized-kv.ts +72 -0
  181. package/src/model/delayed-rotating-quantized-kv.ts +93 -0
  182. package/src/model/delayed-turboquant-kv.ts +55 -0
  183. package/src/model/diffusion-gemma.ts +8 -8
  184. package/src/model/factory.ts +76 -33
  185. package/src/model/fingerprint.ts +1 -1
  186. package/src/model/flash-attention.ts +3 -3
  187. package/src/model/full-prefill-padding.ts +56 -0
  188. package/src/model/full-prefill-row.ts +105 -0
  189. package/src/model/gemma4-base.ts +179 -80
  190. package/src/model/gemma4.ts +40 -32
  191. package/src/model/generated/gemma4-12b.ts +6 -3
  192. package/src/model/generated/gemma4-26b.ts +6 -3
  193. package/src/model/generated/gemma4-e4b.ts +6 -3
  194. package/src/model/glm52-cache.ts +80 -4
  195. package/src/model/glm52-dsa.ts +13 -9
  196. package/src/model/glm52-memory.ts +1 -1
  197. package/src/model/glm52-mla.ts +12 -6
  198. package/src/model/glm52.ts +19 -40
  199. package/src/model/implementation.ts +69 -0
  200. package/src/model/kv-attention-view.ts +67 -0
  201. package/src/model/minicpm5.ts +17 -15
  202. package/src/model/profile.ts +12 -2
  203. package/src/model/qwen-append.ts +12 -0
  204. package/src/model/qwen-conv.ts +52 -0
  205. package/src/model/qwen3-delta-state.ts +74 -0
  206. package/src/model/qwen3-delta.ts +59 -36
  207. package/src/model/qwen3_5-checkpoint.ts +164 -0
  208. package/src/model/qwen3_5.ts +202 -78
  209. package/src/model/rotating-kv-donor.ts +35 -0
  210. package/src/model/rotating-kv-layout.ts +262 -0
  211. package/src/model/rotating-row-transaction.ts +35 -0
  212. package/src/model/speculative-rotating-kv.ts +101 -0
  213. package/src/model/ssm-prefill-padding.ts +39 -0
  214. package/src/model/support.ts +1 -1
  215. package/src/model/trellis-balanced-scatter.ts +51 -0
  216. package/src/model/trellis-linear.ts +672 -0
  217. package/src/model/trellis-shared-m.ts +151 -0
  218. package/src/model/trellis-shared-scatter.ts +144 -0
  219. package/src/model/trellis-splitk-prefill.ts +158 -0
  220. package/src/model/trellis-tiled-prefill.ts +136 -0
  221. package/src/model/trellis-vector-expand.ts +62 -0
  222. package/src/model/trellis-wide-prefill.ts +94 -0
  223. package/src/model/turboquant-codec.ts +83 -0
  224. package/src/model/universal/dense.ts +15 -14
  225. package/src/model/universal/modules.ts +8 -1
  226. package/src/native-pack.ts +6 -5
  227. package/src/pi-provider.ts +6 -64
  228. package/src/pi-web.ts +8 -315
  229. package/src/preflight.ts +31 -15
  230. package/src/prompt-cache.ts +110 -69
  231. package/src/quantize/allocator.ts +1 -1
  232. package/src/quantize/config-writer.ts +10 -3
  233. package/src/quantize/rotate.ts +4 -4
  234. package/src/quantize/trellis.ts +586 -0
  235. package/src/responses.ts +28 -1
  236. package/src/runtime-config.ts +18 -4
  237. package/src/sampler.ts +40 -29
  238. package/src/serve/batch-scheduler.ts +8 -1671
  239. package/src/serve/chat-request.ts +391 -0
  240. package/src/serve/chat-stage.ts +195 -0
  241. package/src/serve/checkpoint-identity.ts +64 -0
  242. package/src/serve/completion-executor.ts +15 -7
  243. package/src/serve/discovery-routes.ts +12 -13
  244. package/src/serve/generation-gateway.ts +183 -213
  245. package/src/serve/http.ts +159 -0
  246. package/src/serve/inference-request.ts +79 -0
  247. package/src/serve/isolate.ts +297 -105
  248. package/src/serve/lab-routes.ts +3 -0
  249. package/src/serve/lane-registry.ts +2 -1
  250. package/src/serve/model-admin-routes.ts +7 -5
  251. package/src/serve/model-binding.ts +43 -0
  252. package/src/serve/model-host.ts +511 -0
  253. package/src/serve/openai-wire.ts +103 -0
  254. package/src/serve/parent-application.ts +56 -0
  255. package/src/serve/pipeline.ts +33 -0
  256. package/src/serve/preparation.ts +33 -0
  257. package/src/serve/request-plan.ts +23 -18
  258. package/src/serve/request-prep.ts +344 -0
  259. package/src/serve/response-lease.ts +24 -0
  260. package/src/serve/responses-client.ts +69 -0
  261. package/src/serve/session-completion-engine.ts +110 -0
  262. package/src/serve/session-search.ts +1 -1
  263. package/src/serve/static-routes.ts +5 -5
  264. package/src/serve/text-completion-stage.ts +104 -0
  265. package/src/serve/token-streams.ts +519 -0
  266. package/src/server.ts +335 -2711
  267. package/src/spec/assistant-rows.ts +92 -0
  268. package/src/spec/assistant-source.ts +31 -55
  269. package/src/spec/cache-identity.ts +22 -0
  270. package/src/spec/deepspec-rows.ts +29 -0
  271. package/src/spec/deepspec-source.ts +16 -14
  272. package/src/spec/dflash-source.ts +36 -12
  273. package/src/spec/drafter.ts +153 -142
  274. package/src/spec/dspark/ab-stats.ts +3 -3
  275. package/src/spec/dspark/calibration.ts +2 -2
  276. package/src/spec/dspark/deepspec-module.ts +97 -122
  277. package/src/spec/dspark/generate-dflash.ts +2 -2
  278. package/src/spec/dspark/generate.ts +2 -2
  279. package/src/spec/dspark/loader.ts +1 -1
  280. package/src/spec/dspark/module-dflash.ts +129 -172
  281. package/src/spec/dspark/module.ts +3 -3
  282. package/src/spec/dspark/quantize-drafter.ts +1 -1
  283. package/src/spec/generate.ts +1 -1
  284. package/src/spec/glm52-mtp-graph.ts +29 -0
  285. package/src/spec/glm52-mtp-rows.ts +132 -0
  286. package/src/spec/glm52-mtp-source.ts +54 -137
  287. package/src/spec/glm52-mtp-state.ts +33 -0
  288. package/src/spec/ngram-source.ts +93 -21
  289. package/src/spec/projected-draft-rows.ts +73 -0
  290. package/src/spec/qwen-mtp-module.ts +171 -0
  291. package/src/spec/qwen-mtp-rows.ts +219 -0
  292. package/src/spec/qwen-mtp-source.ts +147 -195
  293. package/src/spec/qwen-mtp-state.ts +30 -0
  294. package/src/spec/serve-loop.ts +201 -201
  295. package/src/spec/source.ts +110 -13
  296. package/src/spec/two-model-rows.ts +61 -0
  297. package/src/spec/two-model.ts +44 -102
  298. package/src/ssd-cache.ts +99 -19
  299. package/src/ssd-durability.ts +36 -20
  300. package/src/tool-call.ts +51 -14
  301. package/src/train/flash-cce.ts +2 -2
  302. package/src/train/forward.ts +6 -0
  303. package/src/train/loss.ts +1 -1
  304. package/src/train/prefix-shared.ts +5 -1
  305. package/src/train/segmented.ts +5 -3
  306. package/src/train/trainer.ts +6 -6
  307. package/src/vision/prompt.ts +1 -1
  308. package/src/vision/qwen3vl-tower.ts +52 -10
  309. package/src/web/app.html +1 -1
  310. package/src/web/app.js +62 -60
  311. package/src/web/src/adapters-panel.ts +3 -3
  312. package/src/web/src/assistant.ts +2 -36
  313. package/src/web/src/chat.ts +4 -4
  314. package/src/web/src/composer.ts +4 -4
  315. package/src/web/src/hub.ts +1 -1
  316. package/src/web/src/markdown.ts +0 -0
  317. package/src/web/src/memory-panel.ts +1 -1
  318. package/src/web/src/model-picker.ts +1 -1
  319. package/src/web/src/palette.ts +1 -1
  320. package/src/web/src/protocol.ts +3 -39
  321. package/src/web/src/sessions.ts +1 -1
  322. package/src/web/src/ui-catalog.ts +4 -18
  323. package/src/web-assets.ts +47 -0
  324. package/src/weights.ts +55 -9
  325. package/docs/archive/investigations/curve-runs/bisector-route.json +0 -98
  326. package/docs/archive/investigations/curve-runs/bisector-trace.json +0 -1393
  327. package/docs/archive/investigations/curve-runs/curve-terrain.json +0 -1179
  328. package/docs/archive/investigations/curve-runs/curve-terrain.svg +0 -42
  329. package/docs/archive/investigations/hlg-ab.html +0 -34
  330. package/docs/archive/investigations/hlg-explorer.html +0 -238
  331. package/docs/archive/investigations/hlg-figs/cliff.svg +0 -1
  332. package/docs/archive/investigations/hlg-figs/cross.svg +0 -1
  333. package/docs/archive/investigations/hlg-figs/edges.svg +0 -1
  334. package/docs/archive/investigations/hlg-figs/k20-grids.svg +0 -1
  335. package/docs/archive/investigations/hlg-figs/k20-peaks.svg +0 -1
  336. package/docs/archive/investigations/hlg-figs/lw-curve.svg +0 -1
  337. package/docs/archive/investigations/hlg-figs/terrain.svg +0 -1
  338. package/docs/archive/investigations/hlg-report.html +0 -262
  339. package/docs/archive/investigations/hlg-runs/hlg-ab.json +0 -149
  340. package/docs/archive/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  341. package/docs/archive/investigations/hlg-runs/hlg-blind.json +0 -107
  342. package/docs/archive/investigations/hlg-runs/hlg-cliff.json +0 -197
  343. package/docs/archive/investigations/hlg-runs/hlg-cross.json +0 -505
  344. package/docs/archive/investigations/hlg-runs/hlg-edge.json +0 -388
  345. package/docs/archive/investigations/hlg-runs/hlg-eval1.json +0 -25
  346. package/docs/archive/investigations/hlg-runs/hlg-frontier.json +0 -86
  347. package/docs/archive/investigations/hlg-runs/hlg-grid.json +0 -242
  348. package/docs/archive/investigations/hlg-runs/hlg-grid2.json +0 -343
  349. package/docs/archive/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  350. package/docs/archive/investigations/hlg-runs/hlg-map.json +0 -383
  351. package/docs/archive/investigations/hlg-runs/run0-original.log +0 -159
  352. package/docs/archive/investigations/hlg-runs/runA-recommended.log +0 -131
  353. package/docs/archive/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  354. package/docs/archive/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  355. package/docs/archive/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  356. package/docs/archive/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  357. package/docs/archive/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  358. package/docs/archive/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  359. package/docs/archive/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  360. package/docs/archive/investigations/hlg-runs/runB-gain-variants.log +0 -192
  361. package/docs/archive/investigations/hlg-runs/runC-pivots.log +0 -162
  362. package/docs/archive/investigations/hlg-runs/runD-oetf.log +0 -132
  363. package/docs/archive/investigations/hlg-runs/runE-eotf.log +0 -162
  364. package/docs/archive/investigations/hlg-runs/runF-shaper-working.log +0 -86
  365. package/docs/archive/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  366. package/docs/archive/investigations/hlg-runs/runH-wsweep.log +0 -176
  367. package/docs/archive/investigations/hlg-runs/runI-asweep.log +0 -176
  368. package/docs/archive/investigations/hlg-runs/runJ-knobmap.log +0 -49
  369. package/docs/archive/investigations/hlg-runs/runK-frontier.log +0 -19
  370. package/docs/archive/investigations/hlg-runs/runL-widemap.log +0 -65
  371. package/docs/archive/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  372. package/docs/archive/investigations/hlg-runs/runN-verify.log +0 -116
  373. package/docs/archive/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  374. package/docs/archive/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  375. package/docs/archive/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  376. package/docs/archive/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  377. package/docs/archive/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  378. package/docs/archive/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  379. package/docs/archive/investigations/hlg-runs/runU-cross-12b.log +0 -33
  380. package/docs/archive/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  381. package/docs/archive/investigations/hlg-runs/runW-lw-12b.log +0 -22
  382. package/docs/archive/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  383. package/docs/archive/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  384. package/docs/archive/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  385. package/docs/archive/mlx-bun-lab-report.html +0 -275
  386. package/docs/archive/wwdc-mlx-bun.html +0 -848
  387. package/docs/design/adapters-end-to-end.md +0 -205
  388. package/docs/design/batching-perf-path.md +0 -255
  389. package/docs/design/batching-v2-plan.md +0 -529
  390. package/docs/design/bucketing-stage.md +0 -197
  391. package/docs/design/compat-cli-surface-design.md +0 -230
  392. package/docs/design/docs-reorg-plan.md +0 -165
  393. package/docs/design/dspark-serving-program.md +0 -371
  394. package/docs/design/dspark-speculative-decoding.md +0 -318
  395. package/docs/design/grammar-spec-batching-integration.md +0 -301
  396. package/docs/design/memory-inference-path.md +0 -422
  397. package/docs/design/memory-synthesis.md +0 -287
  398. package/docs/design/memory-system.md +0 -237
  399. package/docs/design/mlx-lm-serving-execution-seam.md +0 -81
  400. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  401. package/docs/design/omlx-adoption-map.md +0 -98
  402. package/docs/design/orpo-dynamic-lambda.md +0 -220
  403. package/docs/design/orpo-future-enhancements.md +0 -340
  404. package/docs/design/paged-kv-cache.md +0 -214
  405. package/docs/design/parallel-slots.md +0 -567
  406. package/docs/design/parity-tier-dag.md +0 -161
  407. package/docs/design/repo-cleanup-plan.md +0 -231
  408. package/docs/design/runtime-isolation.md +0 -263
  409. package/docs/design/segmented-backward-training.md +0 -543
  410. package/docs/design/spec-decode-larger-targets.md +0 -229
  411. package/docs/design/ssd-kv-cold-tier.md +0 -415
  412. package/docs/design/structured-output.md +0 -484
  413. package/docs/design/tauri-desktop-app.md +0 -127
  414. package/docs/design/the-dreaming-master-plan.md +0 -445
  415. package/docs/design/turboquant-kv.md +0 -235
  416. package/docs/design/turboquant-weights.md +0 -467
  417. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  418. package/docs/design/web-chat-beat-matrix.md +0 -315
  419. package/docs/design/write-pipeline-entity.md +0 -468
  420. package/docs/planning/IDEAS.md +0 -69
  421. package/docs/reference/embedding.md +0 -197
  422. package/docs/reference/features-matrix.md +0 -101
  423. package/docs/reference/orpo-quickstart.md +0 -135
  424. package/src/flags.ts +0 -11
  425. /package/docs/{design → archive/investigations}/colibri-glm52-port.md +0 -0
  426. /package/docs/{planning → archive/planning}/chunk-task-roadmap.md +0 -0
  427. /package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +0 -0
  428. /package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +0 -0
  429. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  430. /package/docs/{planning → archive/planning}/release-notes-v0.2.0.md +0 -0
  431. /package/src/{memory-plan.ts → admission-plan.ts} +0 -0
  432. /package/{docs/archive/investigations → src/serve/assets}/curve-terrain.html +0 -0
  433. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
@@ -0,0 +1,92 @@
1
+ import type { MlxArray } from "../mlx/array";
2
+ import * as ops from "../mlx/ops";
3
+ import { materializeCopy } from "../mlx/materialize";
4
+ import { disposeResources, applyStateChanges } from "../engine/resources";
5
+ import type { PreparedStateChange } from "../contracts/resources";
6
+ import type { AssistantRowsTarget, DraftPrefillGroup, DraftRowGroup, DraftRowCheckpoint, GroupedDraftProvider } from "./source";
7
+ import type { GemmaAssistantDrafter } from "./drafter";
8
+
9
+ /** The assistant owns only its last true target hidden and coverage. Donor
10
+ * attention stays with target storage; checkpoints contain no duplicate KV. */
11
+ class AssistantRows implements DraftPrefillGroup, DraftRowGroup {
12
+ readonly prefillMode = "tail-split" as const;
13
+ readonly tapLayers: readonly number[] = [];
14
+ #hidden: MlxArray | null = null;
15
+ #processed: number[] = [];
16
+ constructor(readonly target: AssistantRowsTarget, readonly drafter: GemmaAssistantDrafter,
17
+ readonly namespace: string, checkpoints: readonly (DraftRowCheckpoint | null)[]) { this.append(checkpoints); }
18
+ get rowCount(): number { return this.#processed.length; }
19
+ append(checkpoints: readonly (DraftRowCheckpoint | null)[]): void {
20
+ if (checkpoints.length) applyStateChanges([() => this.prepareAppend(checkpoints)]);
21
+ }
22
+ prepareAppend(checkpoints: readonly (DraftRowCheckpoint | null)[]): PreparedStateChange {
23
+ const processed = [...this.#processed, ...checkpoints.map(checkpoint => checkpoint?.processedTokens ?? 0)];
24
+ const example = this.#hidden ?? checkpoints.find(checkpoint => checkpoint !== null)?.attachment.tensors[0];
25
+ const held: MlxArray[] = []; let hidden: MlxArray | null = null;
26
+ try {
27
+ for (const checkpoint of checkpoints) if (checkpoint && (checkpoint.attachment.schema !== "gemma-assistant-v1" ||
28
+ checkpoint.attachment.metadata.processedTokens !== checkpoint.processedTokens))
29
+ throw new Error("invalid assistant checkpoint alignment");
30
+ if (example) {
31
+ const zero = (rows: number) => { const value = ops.zeros([rows,1,this.target.hiddenSize],example.dtype); held.push(value); return value; };
32
+ hidden = ops.concatAxis([...(this.rowCount ? [this.#hidden ?? zero(this.rowCount)] : []),
33
+ ...checkpoints.map(checkpoint => checkpoint?.attachment.tensors[0] ?? zero(1))],0);
34
+ }
35
+ } finally { disposeResources(held); }
36
+ return { commit: () => { const old = this.#hidden; this.#hidden=hidden; hidden=old; this.#processed=processed; },
37
+ dispose: () => { hidden?.dispose(); hidden=null; } };
38
+ }
39
+ filterRows(keep: readonly number[]): void {
40
+ if (!keep.length) { this.dispose(); return; }
41
+ using indices = ops.fromInt32([...keep],[keep.length]);
42
+ const next = this.#hidden && keep.length ? ops.takeAxis(this.#hidden,indices,0) : null;
43
+ this.#hidden?.dispose(); this.#hidden=next; this.#processed=keep.map(row=>this.#processed[row]!);
44
+ }
45
+ prefill(tokens: MlxArray, context?: MlxArray): void {
46
+ const [B,N] = tokens.shape as [number,number];
47
+ using tail = context!.slice([0,N-1,0],[B,N,context!.shape[2]!]);
48
+ const hidden = materializeCopy(tail);
49
+ this.#hidden?.dispose(); this.#hidden=hidden; this.#processed=this.#processed.map(count=>count+N);
50
+ }
51
+ materialize(): void { this.#hidden?.eval(); }
52
+ capture(row: number): DraftRowCheckpoint {
53
+ const processedTokens=this.#processed[row]!;
54
+ const hidden=this.#hidden!.slice([row,0,0],[row+1,1,this.target.hiddenSize]);
55
+ return { processedTokens, attachment: { schema:"gemma-assistant-v1",metadata:{processedTokens},tensors:[hidden] } };
56
+ }
57
+ draft(pending: readonly number[], depth: number, _steps: readonly number[]): number[][] {
58
+ if (!depth) return pending.map(()=>[]);
59
+ const B=pending.length, owned: MlxArray[]=[];
60
+ const donors=this.target.readDonors();
61
+ let ids=ops.fromInt32([...pending],[B,1]), hidden=this.#hidden!;
62
+ const tokens: MlxArray[]=[];
63
+ try {
64
+ for(let step=0;step<depth;step++) {
65
+ using emb=this.target.embed(ids);
66
+ const positions=donors.positions.map(position=>position+step);
67
+ const common=positions.every(position=>position===positions[0]);
68
+ using offsets=common ? null : ops.fromInt32(positions,[B]);
69
+ const next=this.drafter.forwardRows(emb,hidden,donors,offsets ?? positions[0]!);
70
+ owned.push(next.nextHidden); tokens.push(next.tokens); hidden=next.nextHidden;
71
+ ids.dispose(); ids=ops.reshape(next.tokens,[B,1]);
72
+ }
73
+ using packed=ops.concatAxis(tokens,0);
74
+ const values=packed.toIntTokens();
75
+ return pending.map((_,row)=>Array.from({length:depth},(_,step)=>values[step*B+row]!));
76
+ } finally { ids.dispose(); donors.dispose(); disposeResources([...owned,...tokens]); }
77
+ }
78
+ commit(accepted: readonly number[], context: MlxArray): void {
79
+ using indices=ops.fromInt32([...accepted],[accepted.length,1,1]);
80
+ const hidden=ops.takeAlongAxis(context,indices,1);
81
+ this.#hidden?.dispose(); this.#hidden=hidden;
82
+ this.#processed=this.#processed.map((count,row)=>count+accepted[row]!+1);
83
+ }
84
+ dispose(): void { this.#hidden?.dispose(); this.#hidden=null; this.#processed=[]; }
85
+ }
86
+
87
+ export function assistantGroups(drafter: GemmaAssistantDrafter, namespace: string): GroupedDraftProvider {
88
+ return {
89
+ openPrefill: ({target,checkpoints}) => new AssistantRows(target.assistantRows!,drafter,namespace,checkpoints),
90
+ open: ({target,checkpoints}) => new AssistantRows(target.assistantRows!,drafter,namespace,checkpoints),
91
+ };
92
+ }
@@ -1,3 +1,6 @@
1
+ import * as ops from "../mlx/ops";
2
+ import { artifactIdentity } from "../model/artifact-identity";
3
+ import { assistantGroups } from "./assistant-rows";
1
4
  // AssistantSource — the optiq KV-borrowing Gemma "-assistant" drafter
2
5
  // (src/spec/drafter.ts) behind the serve-time DraftSource seam. L2 oracle:
3
6
  // optiq spec_generate. This is the SAME drafter the standalone specGenerate
@@ -21,10 +24,8 @@
21
24
  import { readdirSync, statSync } from "node:fs";
22
25
  import { join } from "node:path";
23
26
  import type { MlxArray } from "../mlx/array";
24
- import * as ops from "../mlx/ops";
25
- import { Gemma4Model, type Cache } from "../model/gemma4";
26
27
  import { GemmaAssistantDrafter } from "./drafter";
27
- import type { DraftProvider, DraftSource, TargetView } from "./source";
28
+ import type { DraftProvider, DraftSource, TargetView, AssistantRowsTarget } from "./source";
28
29
 
29
30
  /** Sum of the drafter's on-disk safetensors — admission accounting only. */
30
31
  function safetensorsBytes(dir: string): number {
@@ -34,36 +35,30 @@ function safetensorsBytes(dir: string): number {
34
35
  return total;
35
36
  }
36
37
 
37
- /** The target's LAST sliding and LAST full cache owners (port of optiq
38
- * kv_view.find_donor_layers; mirrors donorIndices in generate.ts). */
39
- function donorIndices(model: Gemma4Model): { sliding: number; full: number } {
40
- let sliding = -1;
41
- let full = -1;
42
- for (let i = 0; i < model.numDonors; i++) {
43
- if (model.layers[i]!.layerType === "sliding_attention") sliding = i;
44
- else full = i;
45
- }
46
- if (sliding < 0 || full < 0) throw new Error("assistant drafter: missing donor layer type");
47
- return { sliding, full };
48
- }
49
-
50
38
  export class AssistantProvider implements DraftProvider {
51
39
  readonly id: string;
52
40
  readonly weightsBytes: number;
41
+ readonly grouped: import("./source").GroupedDraftProvider;
53
42
 
54
43
  private constructor(
55
44
  private readonly drafter: GemmaAssistantDrafter,
56
45
  id: string,
57
- weightsBytes: number,
46
+ weightsBytes: number, namespace: string,
58
47
  ) {
59
48
  this.id = id;
60
49
  this.weightsBytes = weightsBytes;
50
+ this.grouped = assistantGroups(drafter,namespace);
61
51
  }
62
52
 
63
53
  static async load(modelDir: string): Promise<AssistantProvider> {
64
54
  const drafter = await GemmaAssistantDrafter.load(modelDir);
65
55
  const id = modelDir.split("/").filter(Boolean).at(-1)!;
66
- return new AssistantProvider(drafter, id, safetensorsBytes(modelDir));
56
+ try {
57
+ const identity = await artifactIdentity(await Bun.file(`${modelDir}/config.json`).text(),
58
+ readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
59
+ .map(name => ({ name, path: join(modelDir, name) })));
60
+ return new AssistantProvider(drafter, id, safetensorsBytes(modelDir), `gemma-assistant-v1:${identity}`);
61
+ } catch (error) { drafter.dispose(); throw error; }
67
62
  }
68
63
 
69
64
  open(opts: Parameters<DraftProvider["open"]>[0]): DraftSource {
@@ -71,50 +66,31 @@ export class AssistantProvider implements DraftProvider {
71
66
  }
72
67
 
73
68
  dispose(): void {
74
- // The drafter's Weights are process-lifetime (pinned mmaps); nothing to free.
69
+ this.drafter.dispose();
75
70
  }
76
71
  }
77
72
 
78
- class AssistantSource implements DraftSource {
73
+ export class AssistantSource implements DraftSource {
79
74
  readonly weightsBytes = 0; // provider-owned weights; per-request adds nothing
80
- private readonly model: Gemma4Model;
81
- private readonly caches: Cache[];
82
- private readonly donors: { sliding: number; full: number };
75
+ private readonly target: AssistantRowsTarget;
83
76
 
84
- constructor(private readonly drafter: GemmaAssistantDrafter, target: TargetView) {
85
- if (!(target.model instanceof Gemma4Model))
86
- throw new Error("assistant drafter requires a Gemma4 target");
87
- this.model = target.model;
88
- this.caches = target.caches;
89
- this.donors = donorIndices(this.model);
77
+ constructor(private readonly drafter: Pick<GemmaAssistantDrafter, "forwardRows">, target: TargetView) {
78
+ if (!target.assistantRows)
79
+ throw new Error("assistant drafter requires a Gemma4 target with donor views");
80
+ this.target = target.assistantRows;
90
81
  }
91
82
 
92
83
  /** No own cache to prime — the drafter reads the target's live state. */
93
84
  prefill(_promptIds: number[], _ctxML?: MlxArray): void {}
94
85
 
95
- private embedScaled(token: number): MlxArray {
96
- const ids = ops.fromInt32([token], [1, 1]);
97
- const e = this.model.embed.encode(ids);
98
- ids.dispose();
99
- const s = ops.mulScalar(e, this.model.embedScale);
100
- e.dispose();
101
- return s;
102
- }
103
-
104
- private readDonors(): { sliding: [MlxArray, MlxArray]; full: [MlxArray, MlxArray] } {
105
- const view = (i: number) =>
106
- (this.caches[i] as unknown as { temporalView(): [MlxArray, MlxArray] }).temporalView();
107
- return { sliding: view(this.donors.sliding), full: view(this.donors.full) };
108
- }
109
-
110
86
  /** Draft n tokens against the target's donor K/V, conditioning the first
111
87
  * step on the anchor (the last emitted token + its target hidden) and
112
88
  * chaining the drafter's own post-projected hiddens after that — exactly
113
89
  * specGenerate's 2a block. anchorHidden is borrowed; never disposed here. */
114
90
  draft(feed: number[], n: number, _stepBase: number, anchorHidden?: MlxArray): number[] {
115
91
  if (!anchorHidden) throw new Error("assistant drafter needs the target anchor hidden");
116
- const position = this.caches[0]!.offset - 1;
117
- const shared = this.readDonors();
92
+ const shared = this.target.readDonors();
93
+ const position = shared.positions[0]!;
118
94
  const drafts: number[] = [];
119
95
  const ownedHiddens: MlxArray[] = [];
120
96
  let dTok = feed[feed.length - 1]!; // the pending token (anchorHidden's token)
@@ -122,22 +98,22 @@ class AssistantSource implements DraftSource {
122
98
  let emb: MlxArray | null = null; // hoisted so a mid-loop throw still frees it
123
99
  try {
124
100
  for (let k = 0; k < n; k++) {
125
- emb = this.embedScaled(dTok);
126
- const step = this.drafter.forward(emb, dHid, shared, position + k);
101
+ using ids = ops.fromInt32([dTok], [1, 1]);
102
+ emb = this.target.embed(ids);
103
+ const step = this.drafter.forwardRows(emb, dHid, shared, position + k);
104
+ ownedHiddens.push(step.nextHidden);
105
+ let token: number;
106
+ try { token = ops.itemUint32(step.tokens); } finally { step.tokens.dispose(); }
127
107
  emb.dispose();
128
108
  emb = null;
129
- drafts.push(step.token);
130
- ownedHiddens.push(step.nextHidden);
131
- dTok = step.token;
109
+ drafts.push(token);
110
+ dTok = token;
132
111
  dHid = step.nextHidden;
133
112
  }
134
113
  } finally {
135
114
  emb?.dispose();
136
115
  for (const a of ownedHiddens) a.dispose();
137
- for (const [k, v] of [shared.sliding, shared.full]) {
138
- k.dispose();
139
- v.dispose();
140
- }
116
+ shared.dispose();
141
117
  }
142
118
  return drafts;
143
119
  }
@@ -0,0 +1,22 @@
1
+ import type { GenerateOptions } from "../generate";
2
+
3
+ /** Snapshot numerical configuration when the request is bound. Caller-owned
4
+ * arrays must not change the graph or persistence identity after grouping. */
5
+ export function captureSpeculativeOptions(options: GenerateOptions): GenerateOptions {
6
+ return { ...options,
7
+ ...(options.kvConfig ? { kvConfig: options.kvConfig.map(({ layerIdx, bits, groupSize }) =>
8
+ ({ layerIdx, bits, groupSize })).sort((a, b) => a.layerIdx - b.layerIdx) } : {}),
9
+ ...(options.turboQuant ? { turboQuant: { ...options.turboQuant } } : {}),
10
+ };
11
+ }
12
+
13
+ /** Existing namespaces remain byte-identical when no per-layer scheme is
14
+ * supplied. Execution and persistence consume the same captured settings. */
15
+ export function speculativePrefixNamespace(method: string | undefined, adapters: string | string[],
16
+ options: GenerateOptions): string {
17
+ return JSON.stringify({ method, adapters, kvBits: options.kvBits ?? null,
18
+ kvGroupSize: options.kvGroupSize ?? 64, quantizedKvStart: options.quantizedKvStart ?? null,
19
+ turboQuant: options.turboQuant ?? null,
20
+ ...(options.kvConfig?.length ? { kvConfig: options.kvConfig } : {}),
21
+ });
22
+ }
@@ -0,0 +1,29 @@
1
+ import { projectedDraftGroups } from "./projected-draft-rows";
2
+ import type { GroupedDraftProvider, TargetView } from "./source";
3
+ import type { DeepspecDrafter } from "./dspark/deepspec-module";
4
+
5
+ /** Existing pairing requirements are checked once when the provider opens. */
6
+ export function bindDeepspecTarget(target: TargetView, drafter: Pick<DeepspecDrafter, "cfg">): void {
7
+ if (!target.gemmaTaps) throw new Error("DeepSpec drafter requires a Gemma4 target");
8
+ const layers = drafter.cfg.num_target_layers;
9
+ if (target.gemmaTaps.layerCount !== layers) throw new Error(
10
+ `DeepSpec drafter was trained for a ${layers}-layer target; ` +
11
+ `this model has ${target.gemmaTaps.layerCount} layers — wrong (target, drafter) pairing`);
12
+ }
13
+
14
+ export function deepspecGroups(drafter: DeepspecDrafter, namespace: string): GroupedDraftProvider {
15
+ return projectedDraftGroups(target => {
16
+ bindDeepspecTarget(target, drafter);
17
+ return {
18
+ namespace, schema: "deepspec-context-v1",
19
+ layers: drafter.cfg.num_hidden_layers, tapLayers: drafter.tapLayers,
20
+ project(hidden, positions) {
21
+ using projected = drafter.projectContext(hidden);
22
+ return drafter.projectContextKVRows(projected, positions);
23
+ },
24
+ draft(context, pending, positions, depth) {
25
+ return drafter.draftRows(context, pending, positions).tokens.map(row => row.slice(0, depth));
26
+ },
27
+ };
28
+ });
29
+ }
@@ -4,7 +4,7 @@
4
4
  // (github.com/deepseek-ai/DeepSpec, MIT); the module port with transcription
5
5
  // notes lives in src/spec/dspark/deepspec-module.ts. Oracle: DeepSpec's eval
6
6
  // at temperature 0 (RNG-free — verify degenerates to argmax token-match),
7
- // scripts/oracle-dspark-deepspec.py → scripts/dspark-deepspec-compare.ts.
7
+ // scripts/oracle/oracle-dspark-deepspec.py → dspark-deepspec-compare.ts (deleted 2026-08-23; git history).
8
8
  //
9
9
  // Seam mapping (why this fits without serve-loop changes): the reference
10
10
  // recycles target hidden states from each verify pass into the drafter's
@@ -22,11 +22,12 @@
22
22
  // Context rows are cached post-norm-post-rope — bit-equivalent to their
23
23
  // in-round concat (per-row RMSNorm/RoPE; argued in projectContextKV's doc).
24
24
 
25
+ import { artifactIdentity } from "../model/artifact-identity";
26
+ import { deepspecGroups, bindDeepspecTarget } from "./deepspec-rows";
25
27
  import { readdirSync, statSync } from "node:fs";
26
28
  import { join } from "node:path";
27
29
  import type { MlxArray } from "../mlx/array";
28
30
  import * as ops from "../mlx/ops";
29
- import { Gemma4Model } from "../model/gemma4";
30
31
  import { DeepspecDrafter, type ContextKV } from "./dspark/deepspec-module";
31
32
  import type { DraftProvider, DraftSource, TargetView } from "./source";
32
33
 
@@ -40,20 +41,27 @@ function safetensorsBytes(dir: string): number {
40
41
  export class DeepspecProvider implements DraftProvider {
41
42
  readonly id: string;
42
43
  readonly weightsBytes: number;
44
+ readonly grouped: import("./source").GroupedDraftProvider;
43
45
  /** Trained block width (config block_size, e.g. 7) — the server pins
44
46
  * numDraftTokens to this. */
45
47
  readonly gamma: number;
46
48
 
47
- private constructor(private readonly drafter: DeepspecDrafter, id: string, weightsBytes: number) {
49
+ private constructor(private readonly drafter: DeepspecDrafter, id: string, weightsBytes: number, namespace: string) {
48
50
  this.id = id;
49
51
  this.weightsBytes = weightsBytes;
50
52
  this.gamma = drafter.gamma;
53
+ this.grouped = deepspecGroups(drafter, namespace);
51
54
  }
52
55
 
53
56
  static async load(modelDir: string): Promise<DeepspecProvider> {
54
57
  const drafter = await DeepspecDrafter.load(modelDir);
55
58
  const id = modelDir.split("/").filter(Boolean).at(-1)!;
56
- return new DeepspecProvider(drafter, id, safetensorsBytes(modelDir));
59
+ try {
60
+ const identity = await artifactIdentity(await Bun.file(`${modelDir}/config.json`).text(),
61
+ readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
62
+ .map(name => ({ name, path: join(modelDir, name) })));
63
+ return new DeepspecProvider(drafter, id, safetensorsBytes(modelDir), `deepspec-context-v1:${identity}`);
64
+ } catch (error) { drafter.dispose(); throw error; }
57
65
  }
58
66
 
59
67
  open(opts: Parameters<DraftProvider["open"]>[0]): DraftSource {
@@ -65,21 +73,15 @@ export class DeepspecProvider implements DraftProvider {
65
73
  }
66
74
  }
67
75
 
68
- class DeepspecSource implements DraftSource {
76
+ export class DeepspecSource implements DraftSource {
69
77
  readonly weightsBytes = 0; // provider-owned weights
70
78
  readonly tapLayers: number[];
71
79
  private ctxKV: ContextKV[] | null = null; // per-layer projected context rows
72
80
  private ctxLen = 0; // context rows cached == the anchor's absolute position
73
81
 
74
- constructor(private readonly drafter: DeepspecDrafter, target: TargetView) {
75
- if (!(target.model instanceof Gemma4Model))
76
- throw new Error("DeepSpec drafter requires a Gemma4 target");
77
- const nLayers = target.model.layers.length;
78
- if (nLayers !== drafter.cfg.num_target_layers)
79
- throw new Error(
80
- `DeepSpec drafter was trained for a ${drafter.cfg.num_target_layers}-layer target; ` +
81
- `this model has ${nLayers} layers — wrong (target, drafter) pairing`,
82
- );
82
+ constructor(private readonly drafter: Pick<DeepspecDrafter,
83
+ "cfg" | "tapLayers" | "projectContext" | "projectContextKV" | "draftBlock">, target: TargetView) {
84
+ bindDeepspecTarget(target, drafter);
83
85
  this.tapLayers = drafter.tapLayers;
84
86
  }
85
87
 
@@ -18,14 +18,15 @@
18
18
  // target verify decides). The richer rejection-sampling verify stays in the
19
19
  // standalone dflashGenerate for the measure script.
20
20
 
21
+ import { artifactIdentity } from "../model/artifact-identity";
22
+ import { projectedDraftGroups } from "./projected-draft-rows";
21
23
  import { readdirSync, statSync } from "node:fs";
22
24
  import { join } from "node:path";
23
25
  import type { MlxArray } from "../mlx/array";
24
26
  import * as ops from "../mlx/ops";
25
- import { Gemma4Model } from "../model/gemma4";
26
27
  import type { DflashDrafter } from "./dspark/module-dflash";
27
28
  import { loadDsparkDrafter } from "./dspark/loader";
28
- import type { DraftProvider, DraftSource, TargetView } from "./source";
29
+ import type { DraftProvider, DraftSource, TargetView, DraftProjection } from "./source";
29
30
  import { runtimeValue } from "../runtime-config";
30
31
 
31
32
  function safetensorsBytes(dir: string): number {
@@ -38,20 +39,43 @@ function safetensorsBytes(dir: string): number {
38
39
  export class DflashProvider implements DraftProvider {
39
40
  readonly id: string;
40
41
  readonly weightsBytes: number;
42
+ readonly grouped: import("./source").GroupedDraftProvider;
41
43
  /** The trained block width — the server pins numDraftTokens to this so the
42
44
  * serve loop never asks for more positions than the block was trained for. */
43
45
  readonly gamma: number;
44
46
 
45
- private constructor(private readonly drafter: DflashDrafter, id: string, weightsBytes: number) {
47
+ private constructor(private readonly drafter: DflashDrafter, id: string, weightsBytes: number, namespace: string) {
46
48
  this.id = id;
47
49
  this.weightsBytes = weightsBytes;
48
50
  this.gamma = drafter.cfg.gamma;
51
+ this.grouped = projectedDraftGroups(target => {
52
+ if (!target.gemmaTaps) throw new Error("DSpark drafter requires a Gemma4 target");
53
+ const projection = target.gemmaTaps.projection;
54
+ const minConf = runtimeValue("MLX_BUN_DSPARK_MINCONF");
55
+ return {
56
+ namespace, schema: "dflash-context-v1",
57
+ layers: drafter.cfg.nLayers, tapLayers: drafter.cfg.tapLayers,
58
+ project: hidden => drafter.projectContextRows(hidden),
59
+ draft(context, pending, _positions, depth) {
60
+ return drafter.forwardRows(projection, null, pending, depth, {
61
+ collectLogits: false, collectConfidence: false,
62
+ thresholds: drafter.cfg.sts?.thresholds,
63
+ ...(minConf ? { minConf: Number(minConf) } : {}),
64
+ }, context).tokens;
65
+ },
66
+ };
67
+ });
49
68
  }
50
69
 
51
70
  static async load(modelDir: string): Promise<DflashProvider> {
52
71
  const drafter = loadDsparkDrafter(modelDir); // variant dispatch (dspark|legacy dflash)
53
72
  const id = modelDir.split("/").filter(Boolean).at(-1)!;
54
- return new DflashProvider(drafter, id, safetensorsBytes(modelDir));
73
+ try {
74
+ const identity = await artifactIdentity(await Bun.file(`${modelDir}/dspark.json`).text(),
75
+ readdirSync(modelDir).filter(file => file.endsWith(".safetensors"))
76
+ .map(name => ({ name, path: join(modelDir, name) })));
77
+ return new DflashProvider(drafter, id, safetensorsBytes(modelDir), `dflash-context-v1:${identity}`);
78
+ } catch (error) { drafter.dispose(); throw error; }
55
79
  }
56
80
 
57
81
  open(opts: Parameters<DraftProvider["open"]>[0]): DraftSource {
@@ -59,22 +83,22 @@ export class DflashProvider implements DraftProvider {
59
83
  }
60
84
 
61
85
  dispose(): void {
62
- // Unlike the assistant drafter (process-pinned mmaps), DflashDrafter
63
- // materializes owned MlxArrays — free them on teardown.
86
+ // Provider-owned weights are released when the mounted draft is closed.
64
87
  this.drafter.dispose();
65
88
  }
66
89
  }
67
90
 
68
- class DflashSource implements DraftSource {
91
+ export class DflashSource implements DraftSource {
69
92
  readonly weightsBytes = 0; // provider-owned weights
70
93
  readonly tapLayers: number[];
71
- private readonly model: Gemma4Model;
94
+ private readonly model: DraftProjection;
95
+ private readonly minConf = runtimeValue("MLX_BUN_DSPARK_MINCONF");
72
96
  private hCtx: MlxArray | null = null; // [1, L, m*H] — grows with the accepted stream
73
97
 
74
- constructor(private readonly drafter: DflashDrafter, target: TargetView) {
75
- if (!(target.model instanceof Gemma4Model))
98
+ constructor(private readonly drafter: Pick<DflashDrafter, "cfg" | "forwardInfer">, target: TargetView) {
99
+ if (!target.gemmaTaps)
76
100
  throw new Error("DSpark drafter requires a Gemma4 target");
77
- this.model = target.model;
101
+ this.model = target.gemmaTaps.projection;
78
102
  this.tapLayers = drafter.cfg.tapLayers;
79
103
  }
80
104
 
@@ -94,7 +118,7 @@ class DflashSource implements DraftSource {
94
118
  draft(feed: number[], n: number, _stepBase: number, _anchorHidden?: MlxArray): number[] {
95
119
  if (!this.hCtx) throw new Error("DSpark drafter: draft before prefill");
96
120
  const anchorTok = feed[feed.length - 1]!;
97
- const envMin = runtimeValue("MLX_BUN_DSPARK_MINCONF");
121
+ const envMin = this.minConf;
98
122
  const block = this.drafter.forwardInfer(this.model, this.hCtx, anchorTok, n, {
99
123
  thresholds: this.drafter.cfg.sts?.thresholds,
100
124
  collectLogits: false, // serve loop runs its own verify lm-head, never reads this