mlx-bun 0.0.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -578
- package/bin/mlx-bun.mjs +1 -1
- package/docs/README.md +91 -0
- package/docs/{design → archive}/hlg-sampling.md +3 -3
- package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
- package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
- package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
- package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
- package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
- package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
- package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
- package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
- package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
- package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
- package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
- package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
- package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
- package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
- package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
- package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
- package/docs/design/batching.md +569 -0
- package/docs/design/decode-speed-program.md +3178 -169
- package/docs/design/dreaming-nightly-pipeline.md +675 -282
- package/docs/design/generic-model-support.md +579 -334
- package/docs/design/kv-cache.md +680 -0
- package/docs/design/orpo-training.md +673 -1239
- package/docs/design/speculative-decoding.md +1627 -0
- package/docs/design/turboquant.md +2102 -0
- package/docs/design/unified-engine-frontier-plan.md +1831 -727
- package/docs/design/web-chat-redesign.md +666 -1083
- package/docs/planning/PRODUCT_ROADMAP.md +34 -1
- package/docs/planning/release-notes-v0.3.0.md +35 -0
- package/docs/planning/video-series.md +421 -0
- package/docs/reference/benchmarks.md +1162 -0
- package/docs/reference/cli.md +395 -149
- package/docs/reference/distribution.md +321 -181
- package/docs/reference/environment.md +348 -0
- package/docs/reference/glossary.md +39 -0
- package/docs/reference/library-api.md +580 -142
- package/docs/reference/memory.md +227 -64
- package/docs/reference/models.md +137 -6
- package/docs/reference/server-api.md +938 -422
- package/docs/reference/server-config.md +652 -320
- package/docs/reference/training.md +393 -254
- package/docs/reference/troubleshooting.md +166 -0
- package/package.json +10 -5
- package/src/admission-plan.ts +18 -0
- package/src/anthropic.ts +92 -3
- package/src/audio/decode.ts +2 -2
- package/src/audio/features.ts +2 -2
- package/src/backends/mlx/autoregressive.ts +108 -0
- package/src/backends/mlx/batch-group.ts +1646 -0
- package/src/backends/mlx/diffusion.ts +39 -0
- package/src/backends/mlx/draft-target.ts +47 -0
- package/src/backends/mlx/evaluation.ts +105 -0
- package/src/backends/mlx/fill-append.ts +45 -0
- package/src/backends/mlx/gateway-binding.ts +71 -0
- package/src/backends/mlx/graph.ts +38 -0
- package/src/backends/mlx/memory-client.ts +189 -0
- package/src/backends/mlx/memory-guard.ts +40 -0
- package/src/backends/mlx/methods.ts +90 -0
- package/src/backends/mlx/model-prompt.ts +164 -0
- package/src/backends/mlx/model-serving.ts +79 -0
- package/src/backends/mlx/prefill.ts +33 -0
- package/src/backends/mlx/request-policy.ts +20 -0
- package/src/backends/mlx/rollback.ts +51 -0
- package/src/backends/mlx/serial-executor.ts +273 -0
- package/src/backends/mlx/speculative.ts +114 -0
- package/src/backends/mlx/state-views.ts +26 -0
- package/src/backends/mlx/text-engine.ts +73 -0
- package/src/cli.ts +189 -61
- package/src/client.ts +66 -0
- package/src/config.ts +21 -4
- package/src/contracts/completion.ts +16 -0
- package/src/contracts/execution.ts +49 -0
- package/src/contracts/generation.ts +103 -0
- package/src/contracts/host.ts +7 -0
- package/src/contracts/jobs.ts +66 -0
- package/src/contracts/pi-provider.ts +30 -0
- package/src/contracts/pi.ts +259 -0
- package/src/contracts/resources.ts +18 -0
- package/src/contracts/scheduling.ts +27 -0
- package/src/contracts/tsconfig.json +14 -0
- package/src/diffusion/diffusion-generate.ts +218 -153
- package/src/embed.ts +1 -1
- package/src/engine/admission.ts +59 -0
- package/src/engine/cancellation.ts +38 -0
- package/src/engine/engine.ts +56 -0
- package/src/engine/execution-coordinator.ts +70 -0
- package/src/engine/execution-plan.ts +51 -0
- package/src/engine/resources.ts +42 -0
- package/src/engine/scheduler.ts +67 -0
- package/src/engine/session.ts +247 -0
- package/src/eval/README.md +44 -1
- package/src/eval/kl.ts +263 -23
- package/src/eval/reference-logits.ts +207 -0
- package/src/eval/runner.ts +10 -79
- package/src/eval/tasks/bfcl.ts +2 -1
- package/src/eval/tasks/gsm8k.ts +2 -1
- package/src/eval/tasks/hashhop.ts +2 -1
- package/src/eval/tasks/humaneval.ts +5 -4
- package/src/eval/tasks/ifeval.ts +2 -1
- package/src/eval/tasks/mmlu.ts +2 -1
- package/src/expert-io.ts +3 -1
- package/src/expert-offload.ts +3 -1
- package/src/fill/echo-index.ts +188 -0
- package/src/fill/fill-session.ts +452 -0
- package/src/fill/proposal.ts +68 -0
- package/src/fill/schema-rows.ts +506 -0
- package/src/fill/tool-boundary.ts +103 -0
- package/src/fit.ts +24 -43
- package/src/generate.ts +740 -337
- package/src/grammar.ts +14 -8
- package/src/harness-pi.ts +15 -34
- package/src/hub-rest.ts +4 -4
- package/src/index.ts +27 -0
- package/src/inference/denoising.ts +17 -0
- package/src/inference/graph.ts +33 -0
- package/src/inference/prefill.ts +39 -0
- package/src/inference/rollback.ts +7 -0
- package/src/jobs/db.ts +4 -0
- package/src/jobs/index.ts +2 -0
- package/src/jobs/job-entry.ts +15 -14
- package/src/jobs/runner.ts +98 -13
- package/src/jobs/task-client.ts +19 -0
- package/src/jobs/types.ts +2 -58
- package/src/kv-scheme.ts +199 -0
- package/src/kv-store.ts +459 -234
- package/src/lab/README.md +18 -0
- package/src/{assets → lab/curve}/curve-designer.html +2 -2
- package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
- package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
- package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
- package/src/library.ts +40 -0
- package/src/lora.ts +18 -0
- package/src/media-fetch.ts +20 -4
- package/src/memory/article.ts +1 -1
- package/src/memory/chunk.ts +1 -1
- package/src/memory/model.ts +32 -170
- package/src/memory/prompts.ts +1 -1
- package/src/memory/rest.ts +1 -1
- package/src/memory/schedule.ts +1 -1
- package/src/memory/stages.ts +4 -1
- package/src/memory/vault.ts +3 -4
- package/src/mlx/array.ts +9 -10
- package/src/mlx/compile.ts +12 -2
- package/src/mlx/ffi.ts +66 -22
- package/src/mlx/materialize.ts +23 -0
- package/src/mlx/metal-kernel.ts +10 -11
- package/src/mlx/ops.ts +64 -19
- package/src/mlx/quantized-rows.ts +36 -0
- package/src/mlx/token-bitmask.ts +52 -0
- package/src/mlx/turboquant-kv-decode.ts +82 -0
- package/src/mlx/turboquant-kv-inverse.ts +122 -0
- package/src/mlx/turboquant-ops.ts +33 -3
- package/src/mlx/turboquant-tables.ts +2 -2
- package/src/model/batched-mask.ts +9 -3
- package/src/model/batched-quant.ts +2 -2
- package/src/model/batched-rotating-quant.ts +45 -99
- package/src/model/batched-rotating-state.ts +73 -0
- package/src/model/batched-rotating.ts +57 -106
- package/src/model/batched-row-storage.ts +127 -0
- package/src/model/compiled-decode.ts +4 -3
- package/src/model/diffusion-gemma.ts +8 -8
- package/src/model/factory.ts +87 -49
- package/src/model/fingerprint.ts +1 -1
- package/src/model/flash-attention.ts +3 -3
- package/src/model/gemma4-base.ts +187 -17
- package/src/model/gemma4.ts +6 -6
- package/src/model/generated/gemma4-12b.ts +52 -148
- package/src/model/generated/gemma4-26b.ts +34 -94
- package/src/model/generated/gemma4-e4b.ts +28 -76
- package/src/model/glm52-cache.ts +19 -9
- package/src/model/glm52-dsa.ts +13 -9
- package/src/model/glm52-memory.ts +28 -1
- package/src/model/implementation.ts +69 -0
- package/src/model/minicpm5.ts +7 -8
- package/src/model/profile.ts +443 -0
- package/src/model/qwen-append.ts +12 -0
- package/src/model/qwen-conv.ts +52 -0
- package/src/model/qwen3-delta.ts +98 -2
- package/src/model/qwen3-mrope.ts +252 -0
- package/src/model/qwen3_5-checkpoint.ts +164 -0
- package/src/model/qwen3_5.ts +336 -60
- package/src/model/support.ts +1 -1
- package/src/model/trellis-balanced-scatter.ts +51 -0
- package/src/model/trellis-linear.ts +672 -0
- package/src/model/trellis-shared-m.ts +151 -0
- package/src/model/trellis-shared-scatter.ts +144 -0
- package/src/model/trellis-splitk-prefill.ts +158 -0
- package/src/model/trellis-tiled-prefill.ts +136 -0
- package/src/model/trellis-vector-expand.ts +62 -0
- package/src/model/trellis-wide-prefill.ts +94 -0
- package/src/model/universal/dense.ts +1 -1
- package/src/model/universal/modules.ts +8 -1
- package/src/native/frame_extract.swift +140 -0
- package/src/native-pack.ts +15 -7
- package/src/pi-provider.ts +6 -64
- package/src/pi-web.ts +14 -320
- package/src/prompt-cache.ts +97 -54
- package/src/quantize/allocator.ts +1 -1
- package/src/quantize/atomic-output.ts +38 -0
- package/src/quantize/calibration.ts +2 -1
- package/src/quantize/config-writer.ts +16 -3
- package/src/quantize/index.ts +28 -1
- package/src/quantize/job.ts +11 -0
- package/src/quantize/quantizer.ts +265 -100
- package/src/quantize/rotate.ts +603 -0
- package/src/quantize/safetensors-writer.ts +79 -1
- package/src/quantize/sensitivity.ts +41 -59
- package/src/quantize/trellis.ts +586 -0
- package/src/quantize/weight-transform.ts +292 -0
- package/src/responses.ts +130 -3
- package/src/runtime-config.ts +81 -0
- package/src/sampler.ts +276 -4
- package/src/serve/admin-routes.ts +184 -0
- package/src/serve/aux-routes.ts +132 -0
- package/src/serve/batch-scheduler.ts +8 -1558
- package/src/serve/chat-request.ts +391 -0
- package/src/serve/chat-stage.ts +195 -0
- package/src/serve/checkpoint-identity.ts +64 -0
- package/src/serve/completion-executor.ts +354 -0
- package/src/serve/completion-sink.ts +157 -0
- package/src/serve/discovery-routes.ts +204 -0
- package/src/serve/generation-gateway.ts +211 -243
- package/src/serve/http.ts +159 -0
- package/src/serve/inference-request.ts +79 -0
- package/src/serve/isolate.ts +297 -105
- package/src/serve/kv-budget.ts +14 -0
- package/src/serve/lab-routes.ts +341 -0
- package/src/serve/lane-registry.ts +2 -1
- package/src/serve/model-admin-routes.ts +155 -0
- package/src/serve/model-binding.ts +43 -0
- package/src/serve/model-host.ts +512 -0
- package/src/serve/openai-wire.ts +103 -0
- package/src/serve/parent-application.ts +56 -0
- package/src/serve/pipeline.ts +33 -0
- package/src/serve/preparation.ts +33 -0
- package/src/serve/prompt-response-trace.ts +147 -0
- package/src/serve/request-plan.ts +162 -0
- package/src/serve/request-prep.ts +346 -0
- package/src/serve/response-lease.ts +24 -0
- package/src/serve/responses-client.ts +69 -0
- package/src/serve/session-completion-engine.ts +110 -0
- package/src/serve/session-search.ts +1 -1
- package/src/serve/static-routes.ts +101 -0
- package/src/serve/text-completion-stage.ts +104 -0
- package/src/serve/token-streams.ts +519 -0
- package/src/server.ts +523 -3551
- package/src/spec/assistant-source.ts +10 -44
- package/src/spec/deepspec-source.ts +6 -6
- package/src/spec/dflash-source.ts +9 -8
- package/src/spec/dspark/ab-stats.ts +3 -3
- package/src/spec/dspark/calibration.ts +2 -2
- package/src/spec/dspark/deepspec-module.ts +2 -2
- package/src/spec/dspark/generate-dflash.ts +2 -2
- package/src/spec/dspark/generate.ts +2 -2
- package/src/spec/dspark/loader.ts +1 -1
- package/src/spec/dspark/module-dflash.ts +5 -4
- package/src/spec/dspark/module.ts +3 -3
- package/src/spec/dspark/quantize-drafter.ts +1 -1
- package/src/spec/generate.ts +1 -1
- package/src/spec/glm52-mtp-source.ts +9 -1
- package/src/spec/ngram-source.ts +1 -1
- package/src/spec/prefix-state.ts +45 -0
- package/src/spec/qwen-mtp-source.ts +528 -0
- package/src/spec/serve-loop.ts +179 -213
- package/src/spec/source.ts +42 -10
- package/src/spec/two-model.ts +1 -1
- package/src/ssd-cache.ts +95 -24
- package/src/ssd-durability.ts +207 -0
- package/src/tool-call.ts +51 -14
- package/src/train/flash-cce.ts +14 -13
- package/src/train/forward.ts +38 -1
- package/src/train/loss.ts +3 -2
- package/src/train/prefix-shared.ts +5 -1
- package/src/train/segmented.ts +9 -6
- package/src/train/trainer.ts +9 -8
- package/src/vision/preprocess.ts +1 -1
- package/src/vision/prompt.ts +48 -2
- package/src/vision/qwen3vl-preprocess.ts +409 -0
- package/src/vision/qwen3vl-prompt.ts +196 -0
- package/src/vision/qwen3vl-tower.ts +555 -0
- package/src/vision/video-frames.ts +148 -0
- package/src/web/app.html +1 -1
- package/src/web/app.js +15 -6
- package/src/web/src/adapters-panel.ts +3 -3
- package/src/web/src/assistant.ts +2 -36
- package/src/web/src/chat.ts +16 -9
- package/src/web/src/composer.ts +4 -4
- package/src/web/src/hub.ts +1 -1
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +1 -1
- package/src/web/src/model-picker.ts +1 -1
- package/src/web/src/palette.ts +1 -1
- package/src/web/src/protocol.ts +3 -39
- package/src/web/src/sessions.ts +1 -1
- package/src/web/src/ui-catalog.ts +4 -18
- package/src/web-assets.ts +47 -0
- package/src/weights.ts +134 -33
- package/docs/archive/mlx-bun-lab-report.html +0 -275
- package/docs/archive/wwdc-mlx-bun.html +0 -848
- package/docs/design/adapters-end-to-end.md +0 -205
- package/docs/design/batching-perf-path.md +0 -255
- package/docs/design/batching-v2-plan.md +0 -529
- package/docs/design/bucketing-stage.md +0 -197
- package/docs/design/compat-cli-surface-design.md +0 -230
- package/docs/design/docs-reorg-plan.md +0 -165
- package/docs/design/dspark-serving-program.md +0 -371
- package/docs/design/dspark-speculative-decoding.md +0 -268
- package/docs/design/grammar-spec-batching-integration.md +0 -301
- package/docs/design/memory-inference-path.md +0 -422
- package/docs/design/memory-synthesis.md +0 -287
- package/docs/design/memory-system.md +0 -237
- package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
- package/docs/design/omlx-adoption-map.md +0 -98
- package/docs/design/orpo-dynamic-lambda.md +0 -220
- package/docs/design/orpo-future-enhancements.md +0 -340
- package/docs/design/paged-kv-cache.md +0 -214
- package/docs/design/parallel-slots.md +0 -567
- package/docs/design/parity-tier-dag.md +0 -161
- package/docs/design/repo-cleanup-plan.md +0 -189
- package/docs/design/runtime-isolation.md +0 -263
- package/docs/design/segmented-backward-training.md +0 -543
- package/docs/design/spec-decode-larger-targets.md +0 -229
- package/docs/design/ssd-kv-cold-tier.md +0 -288
- package/docs/design/structured-output.md +0 -484
- package/docs/design/tauri-desktop-app.md +0 -127
- package/docs/design/the-dreaming-master-plan.md +0 -445
- package/docs/design/turboquant-kv.md +0 -235
- package/docs/design/w4a16-compute-precision-spike.md +0 -232
- package/docs/design/web-chat-beat-matrix.md +0 -315
- package/docs/design/write-pipeline-entity.md +0 -468
- package/docs/investigations/curve-runs/bisector-route.json +0 -98
- package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
- package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
- package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
- package/docs/investigations/hlg-ab.html +0 -34
- package/docs/investigations/hlg-explorer.html +0 -238
- package/docs/investigations/hlg-figs/cliff.svg +0 -1
- package/docs/investigations/hlg-figs/cross.svg +0 -1
- package/docs/investigations/hlg-figs/edges.svg +0 -1
- package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
- package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
- package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
- package/docs/investigations/hlg-figs/terrain.svg +0 -1
- package/docs/investigations/hlg-report.html +0 -262
- package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
- package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
- package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
- package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
- package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
- package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
- package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
- package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
- package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
- package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
- package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
- package/docs/investigations/hlg-runs/hlg-map.json +0 -383
- package/docs/investigations/hlg-runs/run0-original.log +0 -159
- package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
- package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
- package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
- package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
- package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
- package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
- package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
- package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
- package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
- package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
- package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
- package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
- package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
- package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
- package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
- package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
- package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
- package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
- package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
- package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
- package/docs/investigations/hlg-runs/runN-verify.log +0 -116
- package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
- package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
- package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
- package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
- package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
- package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
- package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
- package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
- package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
- package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
- package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
- package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
- package/docs/planning/IDEAS.md +0 -69
- package/docs/reference/embedding.md +0 -197
- package/docs/reference/features-matrix.md +0 -100
- package/docs/reference/orpo-quickstart.md +0 -135
- package/src/flags.ts +0 -13
- /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
- /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
- /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
- /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
- /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
- /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
- /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
- /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
- /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
- /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
- /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
- /package/docs/{planning → archive/planning}/journal.md +0 -0
- /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
- /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
- /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
- /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
package/src/grammar.ts
CHANGED
|
@@ -33,6 +33,8 @@ import xgrammar, {
|
|
|
33
33
|
import { readFileSync } from "node:fs";
|
|
34
34
|
import { MlxArray } from "./mlx/array";
|
|
35
35
|
import * as ops from "./mlx/ops";
|
|
36
|
+
import { applyTokenBitmask } from "./mlx/token-bitmask";
|
|
37
|
+
import { runtimeValue } from "./runtime-config";
|
|
36
38
|
import type { LoadedTokenizer } from "./tokenizer";
|
|
37
39
|
|
|
38
40
|
/** The request shape — the union of every structured-output field name across
|
|
@@ -51,7 +53,7 @@ export interface GrammarRequest {
|
|
|
51
53
|
guided_grammar?: string;
|
|
52
54
|
/** vLLM/oMLX: regex. Compiled via `root ::= <regex>` EBNF embedding, so
|
|
53
55
|
* only the regex∩EBNF subset works (the F5 gap — real regex→EBNF or
|
|
54
|
-
* structural-tag RegexFormat is the tracked fix,
|
|
56
|
+
* structural-tag RegexFormat is the tracked fix, docs/reference/server-api.md). */
|
|
55
57
|
guidedRegex?: string;
|
|
56
58
|
guided_regex?: string;
|
|
57
59
|
/** vLLM/oMLX: restrict output to one of these strings (enum). */
|
|
@@ -79,7 +81,7 @@ export interface CompiledGrammarResult {
|
|
|
79
81
|
/** Module-level serializer for ALL xgrammar WASM calls. The WASM instance is
|
|
80
82
|
* single-threaded; CONCURRENT async calls corrupt emscripten's binding
|
|
81
83
|
* layer (BindingError: Expected null or instance of VectorInt, got an
|
|
82
|
-
* instance of VectorInt — reproduced in tests/grammar.test.ts B1 test, which
|
|
84
|
+
* instance of VectorInt — reproduced in tests/parity/grammar.test.ts B1 test, which
|
|
83
85
|
* fires 4 overlapping compiles + fills). Under `--batch N` the scheduler
|
|
84
86
|
* fires N accept()s (each kicks an async fill) then awaits ready() on all;
|
|
85
87
|
* and the server compiles grammar for concurrent requests. Without
|
|
@@ -118,7 +120,7 @@ let cachedTokenizerInfo: {
|
|
|
118
120
|
* - decoder is Sequence w/ ByteFallback → byte_fallback (Gemma/SP)
|
|
119
121
|
* - otherwise → raw
|
|
120
122
|
* prependSpace is true for byte_level (ByteLevel pretokenizers add a leading
|
|
121
|
-
* space). Validated in
|
|
123
|
+
* space). Validated in xgrammar-spike.ts (deleted 2026-08-23; git history) across Gemma
|
|
122
124
|
* (byte_fallback, 256k), Llama-3 / Qwen2.5 (byte_level, 128k/151k). */
|
|
123
125
|
function loadVocab(tokenizerJsonPath: string): {
|
|
124
126
|
vocab: string[];
|
|
@@ -206,6 +208,7 @@ export class GrammarController {
|
|
|
206
208
|
private pending: Promise<void> | null;
|
|
207
209
|
private terminated = false;
|
|
208
210
|
private disposed = false;
|
|
211
|
+
private readonly metalMask = runtimeValue("MLX_BUN_TOKEN_MASK") === "metal";
|
|
209
212
|
/** Tokens emitted via jumpForward() this generation — telemetry/test hook. */
|
|
210
213
|
jumpedTokens = 0;
|
|
211
214
|
|
|
@@ -237,6 +240,7 @@ export class GrammarController {
|
|
|
237
240
|
* Sync — the mask is already materialized. Returns a NEW array (caller
|
|
238
241
|
* disposes the input). Mirrors oMLX's apply_token_bitmask_mlx. */
|
|
239
242
|
applyMask(logits: MlxArray): MlxArray {
|
|
243
|
+
if (this.metalMask) return applyTokenBitmask(logits, this.readyMask);
|
|
240
244
|
// Build a -inf/0 additive float mask on device from the int32 bitmask.
|
|
241
245
|
// Each int32 bit b (little-endian within the word) gates token
|
|
242
246
|
// word*32 + b. Set = valid (xgrammar convention). Adding -inf → -inf,
|
|
@@ -254,7 +258,9 @@ export class GrammarController {
|
|
|
254
258
|
const valid = (w >>> bit) & 1;
|
|
255
259
|
maskArr[id] = valid ? 0 : -Infinity;
|
|
256
260
|
}
|
|
257
|
-
const
|
|
261
|
+
const raw = MlxArray.fromFloat32(maskArr, [1, V]);
|
|
262
|
+
const mask = raw.astype(logits.dtype);
|
|
263
|
+
raw.dispose();
|
|
258
264
|
const out = ops.add(logits, mask);
|
|
259
265
|
mask.dispose();
|
|
260
266
|
return out;
|
|
@@ -284,7 +290,7 @@ export class GrammarController {
|
|
|
284
290
|
* time: a controller disposed while its fill is still queued (an exception
|
|
285
291
|
* between accept/jumpForward and ready()) must not call into the deleted
|
|
286
292
|
* WASM matcher — that BindingError poisons the module-wide wasmChain for
|
|
287
|
-
* every later grammar request (found by tests/grammar-jump.test.ts). */
|
|
293
|
+
* every later grammar request (found by tests/parity/grammar-jump.test.ts). */
|
|
288
294
|
private fireFill(): Promise<void> {
|
|
289
295
|
return wasmQueue(() =>
|
|
290
296
|
this.disposed
|
|
@@ -457,7 +463,7 @@ export async function compileGrammarRequest(
|
|
|
457
463
|
if (!degradeHint) degradeHint = resolved.degradeDescription ?? "grammar compile failed";
|
|
458
464
|
// The compiler is the cached per-TokenizerInfo instance (F4) — a failed
|
|
459
465
|
// compile must NOT dispose it; the WASM abort is catchable and the
|
|
460
|
-
// compiler state survives (verified in tests/grammar.test.ts).
|
|
466
|
+
// compiler state survives (verified in tests/parity/grammar.test.ts).
|
|
461
467
|
// Return the hint (NOT bare null): it drives the degrade path's
|
|
462
468
|
// system-prompt injection + Warning header. Dropping it here served
|
|
463
469
|
// unconstrained output with no Warning at all (found 2026-07-07 sweep).
|
|
@@ -538,7 +544,7 @@ function resolveGrammarRequest(req: GrammarRequest):
|
|
|
538
544
|
kind: "json_schema",
|
|
539
545
|
schema,
|
|
540
546
|
strict: js?.strict,
|
|
541
|
-
// Whitespace-stall escape hatch (
|
|
547
|
+
// Whitespace-stall escape hatch (docs/reference/server-api.md known gaps):
|
|
542
548
|
// any_whitespace=false compiles the schema with xgrammar's compact
|
|
543
549
|
// separators — no whitespace choice points, so a whitespace-
|
|
544
550
|
// degenerate base model can't greedily tab-loop to max_tokens.
|
|
@@ -581,5 +587,5 @@ function resolveGrammarRequest(req: GrammarRequest):
|
|
|
581
587
|
* (requests degrade to prompt injection). Matches the project's envelope-gated
|
|
582
588
|
* kill-switch discipline (MLX_BUN_COMPILED_DECODE, MLX_BUN_GRAMMAR_BATCH, …). */
|
|
583
589
|
export function grammarEnabled(): boolean {
|
|
584
|
-
return
|
|
590
|
+
return runtimeValue("MLX_BUN_GRAMMAR") !== "0";
|
|
585
591
|
}
|
package/src/harness-pi.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// mlx-bun harness pi — register mlx-bun as a provider in the user's pi
|
|
2
|
-
// install (Phase 16 P1, docs/investigations/pi-builtin-investigation.md).
|
|
2
|
+
// install (Phase 16 P1, docs/archive/investigations/pi-builtin-investigation.md).
|
|
3
3
|
//
|
|
4
4
|
// Mechanism: a generated extension file in ~/.pi/agent/extensions/ that
|
|
5
5
|
// calls pi.registerProvider() with dynamic discovery — it fetches
|
|
@@ -13,7 +13,9 @@ import { homedir } from "node:os";
|
|
|
13
13
|
import { dirname, join } from "node:path";
|
|
14
14
|
|
|
15
15
|
export const PI_EXTENSION_FILENAME = "mlx-bun-provider.ts";
|
|
16
|
-
|
|
16
|
+
import { PI_PROVIDER_ID, PI_LOCAL_MODEL_ID, PI_API_KEY, PI_API, piModelDefinition,
|
|
17
|
+
DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_TOKENS } from "./contracts/pi-provider";
|
|
18
|
+
export { PI_PROVIDER_ID, PI_LOCAL_MODEL_ID } from "./contracts/pi-provider";
|
|
17
19
|
/** Stable pi-facing model id. The server runs exactly one model at a time
|
|
18
20
|
* (memory: the 26B alone is 18 GB) and which one varies run-to-run, so
|
|
19
21
|
* advertising the real, changing repo id makes pi's persisted default go
|
|
@@ -21,7 +23,7 @@ export const PI_PROVIDER_ID = "mlx-bun";
|
|
|
21
23
|
* model is loaded; the real model is carried in the `name` field, and the
|
|
22
24
|
* server still reports the true id in /v1/models and responses. Gives a
|
|
23
25
|
* clean `mlx-bun/local` handle instead of `mlx-bun/mlx-community/…`. */
|
|
24
|
-
|
|
26
|
+
|
|
25
27
|
// 127.0.0.1 (the server's actual default bind), not "localhost": the generated
|
|
26
28
|
// extension runs under the USER'S pi (node/jiti, not Bun), so don't depend on
|
|
27
29
|
// how that runtime's resolver maps localhost.
|
|
@@ -89,8 +91,8 @@ export async function fetchServerModels(baseUrl: string, timeoutMs = 3000): Prom
|
|
|
89
91
|
if (!served) return [];
|
|
90
92
|
return [{
|
|
91
93
|
id: served.id,
|
|
92
|
-
contextWindow: served.context_window ??
|
|
93
|
-
maxTokens:
|
|
94
|
+
contextWindow: served.context_window ?? DEFAULT_CONTEXT_WINDOW,
|
|
95
|
+
maxTokens: DEFAULT_MAX_TOKENS,
|
|
94
96
|
reasoning: !!served.reasoning,
|
|
95
97
|
vision: !!served.vision,
|
|
96
98
|
}];
|
|
@@ -120,6 +122,7 @@ export function renderPiExtension(baseUrl: string, fallbackModels: ServerModel[]
|
|
|
120
122
|
// is the fallback when the server isn't running.
|
|
121
123
|
const BASE_URL = ${JSON.stringify(baseUrl)};
|
|
122
124
|
const FALLBACK_MODELS = ${fallback};
|
|
125
|
+
const modelEntry = ${piModelDefinition.toString()};
|
|
123
126
|
|
|
124
127
|
export default async function (pi: any) {
|
|
125
128
|
let models = FALLBACK_MODELS;
|
|
@@ -131,27 +134,19 @@ export default async function (pi: any) {
|
|
|
131
134
|
// The SERVED model is the row with the capability extras (first);
|
|
132
135
|
// the rest are servable-but-not-served registry entries.
|
|
133
136
|
const served = data.find((m: any) => m.context_window !== undefined) ?? data[0];
|
|
134
|
-
models = [{
|
|
135
|
-
id: ${JSON.stringify(PI_LOCAL_MODEL_ID)},
|
|
137
|
+
models = [modelEntry({
|
|
136
138
|
name: \`\${served.id} (mlx-bun local)\`,
|
|
137
|
-
reasoning: !!served.reasoning,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
...(served.reasoning ? { thinkingFormat: "qwen-chat-template" } : {}),
|
|
141
|
-
},
|
|
142
|
-
input: served.vision ? ["text", "image"] : ["text"],
|
|
143
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
144
|
-
contextWindow: served.context_window ?? 32768,
|
|
145
|
-
maxTokens: 8192,
|
|
146
|
-
}];
|
|
139
|
+
reasoning: !!served.reasoning, vision: !!served.vision,
|
|
140
|
+
contextWindow: served.context_window,
|
|
141
|
+
})];
|
|
147
142
|
}
|
|
148
143
|
}
|
|
149
144
|
} catch {}
|
|
150
145
|
if (models.length === 0) return; // nothing to register
|
|
151
146
|
pi.registerProvider(${JSON.stringify(PI_PROVIDER_ID)}, {
|
|
152
147
|
baseUrl: BASE_URL,
|
|
153
|
-
apiKey:
|
|
154
|
-
api:
|
|
148
|
+
apiKey: ${JSON.stringify(PI_API_KEY)},
|
|
149
|
+
api: ${JSON.stringify(PI_API)},
|
|
155
150
|
models,
|
|
156
151
|
});
|
|
157
152
|
}
|
|
@@ -159,21 +154,7 @@ export default async function (pi: any) {
|
|
|
159
154
|
}
|
|
160
155
|
|
|
161
156
|
function modelEntry(m: ServerModel) {
|
|
162
|
-
return {
|
|
163
|
-
id: PI_LOCAL_MODEL_ID,
|
|
164
|
-
name: `${m.id} (mlx-bun local)`,
|
|
165
|
-
reasoning: !!m.reasoning,
|
|
166
|
-
// Kept aligned with buildPiProvider (src/pi-provider.ts): the system
|
|
167
|
-
// prompt must arrive as `system`, not `developer`.
|
|
168
|
-
compat: {
|
|
169
|
-
supportsDeveloperRole: false,
|
|
170
|
-
...(m.reasoning ? { thinkingFormat: "qwen-chat-template" } : {}),
|
|
171
|
-
},
|
|
172
|
-
input: m.vision ? ["text", "image"] : ["text"],
|
|
173
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
174
|
-
contextWindow: m.contextWindow,
|
|
175
|
-
maxTokens: m.maxTokens,
|
|
176
|
-
};
|
|
157
|
+
return piModelDefinition({ ...m, name: `${m.id} (mlx-bun local)` });
|
|
177
158
|
}
|
|
178
159
|
|
|
179
160
|
export interface InstallResult {
|
package/src/hub-rest.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Axis 3 "Hub" row). Same posture as src/memory/rest.ts: pure (request|url)
|
|
4
4
|
// => Response handlers with no `ctx` dependency, dispatched from
|
|
5
5
|
// src/server.ts by path+method, so they're unit-testable without booting a
|
|
6
|
-
// model context (see tests/hub-rest.test.ts).
|
|
6
|
+
// model context (see tests/serve/hub-rest.test.ts).
|
|
7
7
|
//
|
|
8
8
|
// Three sources, same as optiq Lab's Hub, plus the hardware-fit column optiq
|
|
9
9
|
// lacks:
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// - POST /api/hub/serve — model-swap investigation (see the doc header
|
|
20
20
|
// above the handler): today this ALWAYS returns
|
|
21
21
|
// { ok:false, restart_required:true, command } — see
|
|
22
|
-
// docs/
|
|
22
|
+
// docs/reference/server-config.md for why no in-process swap seam is
|
|
23
23
|
// reachable from the web chat's serving path today.
|
|
24
24
|
|
|
25
25
|
import { loadModelConfig } from "./config";
|
|
@@ -43,7 +43,7 @@ function jsonErr(error: string, status = 400): Response {
|
|
|
43
43
|
* fixed 8k context (the same "typical" context /fit and /library use, so
|
|
44
44
|
* the three surfaces never disagree). `reg`/`hubDir` are injectable so
|
|
45
45
|
* tests can point at a synthetic hub dir instead of the real
|
|
46
|
-
* ~/.cache/huggingface/hub (matching tests/registry-fit.test.ts's pattern);
|
|
46
|
+
* ~/.cache/huggingface/hub (matching tests/unit/registry-fit.test.ts's pattern);
|
|
47
47
|
* the live server route omits both and gets the real registry. */
|
|
48
48
|
export async function handleHubLocal(
|
|
49
49
|
opts: { reg?: Registry; hubDir?: string } = {},
|
|
@@ -210,7 +210,7 @@ export async function handleHubDownload(request: Request): Promise<Response> {
|
|
|
210
210
|
|
|
211
211
|
// ---- POST /api/hub/serve --------------------------------------------------
|
|
212
212
|
|
|
213
|
-
/** Model-swap investigation (docs/
|
|
213
|
+
/** Model-swap investigation (docs/reference/server-config.md): the web
|
|
214
214
|
* chat's `/ws/chat` is explicitly NOT proxied even under `--isolate`
|
|
215
215
|
* (src/serve/isolate.ts serves it a 501 with a pointer back to the direct,
|
|
216
216
|
* non-isolated server) and `--isolate` itself is opt-in, not the default —
|
package/src/index.ts
CHANGED
|
@@ -16,10 +16,36 @@ export {
|
|
|
16
16
|
createModel,
|
|
17
17
|
openGlm52RuntimeModel,
|
|
18
18
|
openModel,
|
|
19
|
+
type ModelOpenOptions,
|
|
19
20
|
type Glm52RuntimeOpenOptions,
|
|
20
21
|
type RuntimeModel,
|
|
21
22
|
} from "./model/factory";
|
|
23
|
+
export { ModelImplementationRegistry, type ModelImplementation, type ModelImplementationProvider } from "./model/implementation";
|
|
24
|
+
export type { ModelServingBinding, ModelPromptBuilder, BuiltPrompt, ServedModelInfo } from "./serve/model-binding";
|
|
25
|
+
export type { ServingContext, ModelHostSource, AdapterService } from "./serve/model-host";
|
|
26
|
+
export type { MlxGatewayBinding, MlxBatchGroup } from "./backends/mlx/gateway-binding";
|
|
27
|
+
export type { MlxSerialServices, MlxSerialBinding } from "./backends/mlx/serial-executor";
|
|
22
28
|
export { Qwen3Model } from "./model/qwen3";
|
|
29
|
+
export { configFingerprint } from "./model/fingerprint";
|
|
30
|
+
export {
|
|
31
|
+
BUILTIN_ARTIFACT_PROFILES,
|
|
32
|
+
ENGINE_CAPABILITIES,
|
|
33
|
+
externalArtifactFingerprint,
|
|
34
|
+
resolveModelProfile,
|
|
35
|
+
type ArtifactModelProfile,
|
|
36
|
+
type EngineCapability,
|
|
37
|
+
type FidelityTarget,
|
|
38
|
+
type FidelityTier,
|
|
39
|
+
type GenerationLoop,
|
|
40
|
+
type ModelArtifactIdentity,
|
|
41
|
+
type ModelExecutionComposition,
|
|
42
|
+
type ModelGraph,
|
|
43
|
+
type ModelLoader,
|
|
44
|
+
type ModelProfile,
|
|
45
|
+
type ModelSpecialization,
|
|
46
|
+
type ResolveModelProfileOptions,
|
|
47
|
+
type ResolvedModelProfile,
|
|
48
|
+
} from "./model/profile";
|
|
23
49
|
export { generate } from "./generate";
|
|
24
50
|
export { loadTokenizer } from "./tokenizer";
|
|
25
51
|
export { embedOne, embedMany, isEmbeddingModel, withInstruction, type EmbedResult } from "./embed";
|
|
@@ -29,6 +55,7 @@ export { downloadModel } from "./download";
|
|
|
29
55
|
export { Registry } from "./registry";
|
|
30
56
|
export {
|
|
31
57
|
createServer,
|
|
58
|
+
shutdownServer,
|
|
32
59
|
loadContext,
|
|
33
60
|
type LoadContextOptions,
|
|
34
61
|
type ServerContext,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GraphDescriptor } from "./graph";
|
|
2
|
+
|
|
3
|
+
/** Denoising has canvas state and feedback, independent of AR token caches.
|
|
4
|
+
* Returned tensors/state are owned by the run. Inputs remain borrowed. A
|
|
5
|
+
* fused method may bypass this graph and implement InferenceMethod directly. */
|
|
6
|
+
export interface DenoisingGraph<Tensor, State> {
|
|
7
|
+
readonly descriptor: GraphDescriptor;
|
|
8
|
+
readonly vocabSize: number;
|
|
9
|
+
readonly canvasLength: number;
|
|
10
|
+
readonly embedScale: number;
|
|
11
|
+
prefill(promptIds: number[], vision?: Tensor): State;
|
|
12
|
+
extendPrefill(tokens: Tensor, state: State): void;
|
|
13
|
+
decoderLogits(canvas: Tensor, state: State, feedback: Tensor | null): Tensor;
|
|
14
|
+
dequantEmbedWeight(): Tensor;
|
|
15
|
+
softEmbeddings(logits: Tensor, weight: Tensor): Tensor;
|
|
16
|
+
closeState(state: State): void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Describes an implementation's ABI, not a claim of oracle parity or speed. */
|
|
2
|
+
export interface GraphDescriptor {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly backend: string;
|
|
5
|
+
readonly graphAbi: string;
|
|
6
|
+
readonly stateAbi: string;
|
|
7
|
+
readonly artifact: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type LogitSelection =
|
|
11
|
+
| { readonly type: "all" }
|
|
12
|
+
| { readonly type: "last" }
|
|
13
|
+
| { readonly type: "range"; readonly start: number; readonly end: number };
|
|
14
|
+
|
|
15
|
+
/** Backend-bound graph. Tensor/State/Inputs stay concrete within the binding.
|
|
16
|
+
* Inputs and hidden are borrowed until the returned lazy work completes;
|
|
17
|
+
* returned hidden/logits are owned by the caller. The graph appends to state.
|
|
18
|
+
* Hidden is [batch, positions, hidden-width]; logits are [batch, selected
|
|
19
|
+
* positions, vocabulary]. Selection precedes the vocabulary projection.
|
|
20
|
+
* Dtypes and evaluation/fence semantics belong to the declared backend ABI.
|
|
21
|
+
* Per-run masks, positions, media, taps, and adapters belong in Inputs or in
|
|
22
|
+
* a bound graph context; they are not mutable session fields. */
|
|
23
|
+
export interface AutoregressiveGraph<Tensor, State, Inputs> {
|
|
24
|
+
readonly descriptor: GraphDescriptor;
|
|
25
|
+
forwardHidden(inputs: Inputs, state: State): Tensor | Promise<Tensor>;
|
|
26
|
+
projectLogits(hidden: Tensor, selection: LogitSelection): Tensor;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A fused InferenceMethod can bypass this graph interface entirely. It need
|
|
30
|
+
* only satisfy the method's output, cancellation, and ownership contracts. */
|
|
31
|
+
export interface GraphFactory<Artifact, Binding, Graph> {
|
|
32
|
+
open(artifact: Artifact, binding: Binding): Promise<{ graph: Graph; close(): Promise<void> }>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface PrefillPosition {
|
|
2
|
+
readonly length: number;
|
|
3
|
+
readonly position: number;
|
|
4
|
+
readonly chunkSize: number;
|
|
5
|
+
readonly tailSplit: boolean;
|
|
6
|
+
readonly snapshotAt?: number | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface PrefillStep {
|
|
10
|
+
readonly start: number;
|
|
11
|
+
readonly end: number;
|
|
12
|
+
readonly kind: "drain" | "final";
|
|
13
|
+
readonly snapshot: boolean;
|
|
14
|
+
/** Batch admission may finish a short last drain and token zero in one tick.
|
|
15
|
+
* Serial execution still yields between every drain and the next forward. */
|
|
16
|
+
readonly batchYield: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Shared serial/solo-batch prefill program. No tensors, runtime policy reads,
|
|
20
|
+
* or sampling. Advance position only after executing the returned step. */
|
|
21
|
+
export function nextPrefillStep(input: PrefillPosition): PrefillStep {
|
|
22
|
+
const { length, position, chunkSize, tailSplit, snapshotAt } = input;
|
|
23
|
+
if (!Number.isSafeInteger(length) || !Number.isSafeInteger(position) ||
|
|
24
|
+
!Number.isSafeInteger(chunkSize) || chunkSize < 1 || position < 0 || position >= length)
|
|
25
|
+
throw new Error("invalid prefill position or chunk size");
|
|
26
|
+
if (snapshotAt != null && (!Number.isSafeInteger(snapshotAt) || snapshotAt < 0 || snapshotAt > length))
|
|
27
|
+
throw new Error("invalid prefill snapshot boundary");
|
|
28
|
+
if (snapshotAt != null && snapshotAt > position && snapshotAt < length) {
|
|
29
|
+
const end = Math.min(position + chunkSize, snapshotAt);
|
|
30
|
+
return { start: position, end, kind: "drain", snapshot: end === snapshotAt, batchYield: true };
|
|
31
|
+
}
|
|
32
|
+
const remaining = length - position;
|
|
33
|
+
if (remaining > (tailSplit ? 1 : chunkSize)) {
|
|
34
|
+
const end = position + (tailSplit ? Math.min(chunkSize, remaining - 1) : chunkSize);
|
|
35
|
+
return { start: position, end, kind: "drain", snapshot: false,
|
|
36
|
+
batchYield: !tailSplit || remaining - 1 > chunkSize };
|
|
37
|
+
}
|
|
38
|
+
return { start: position, end: length, kind: "final", snapshot: false, batchYield: false };
|
|
39
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** A complete transaction over every participating target state layer.
|
|
2
|
+
* A failed begin/resolve invalidates the run; its state must be discarded. */
|
|
3
|
+
export interface SpeculativeTransaction {
|
|
4
|
+
canBegin(drafts: number): boolean;
|
|
5
|
+
begin(drafts: number): void;
|
|
6
|
+
resolve(accepted: number): void;
|
|
7
|
+
}
|
package/src/jobs/db.ts
CHANGED
|
@@ -55,6 +55,10 @@ export class JobStore {
|
|
|
55
55
|
this.dbPath = dbPath;
|
|
56
56
|
this.logsDir = logsDir;
|
|
57
57
|
this.db = new Database(dbPath);
|
|
58
|
+
// Parent submissions and child progress updates share this WAL database.
|
|
59
|
+
// Wait for a short writer transaction instead of failing a valid job with
|
|
60
|
+
// SQLITE_BUSY while the other process commits its terminal event.
|
|
61
|
+
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
58
62
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
59
63
|
this.db.exec(SCHEMA);
|
|
60
64
|
this.migrate();
|
package/src/jobs/index.ts
CHANGED
package/src/jobs/job-entry.ts
CHANGED
|
@@ -7,17 +7,19 @@
|
|
|
7
7
|
// the runner, runs it with a log-appending emit, sets terminal status, and
|
|
8
8
|
// exits 0 (done) / 1 (failed).
|
|
9
9
|
|
|
10
|
+
import { createJobTaskClient } from "./task-client";
|
|
10
11
|
import { JobStore } from "./db";
|
|
11
12
|
import { getRunner, makeEmit } from "./runner";
|
|
12
13
|
import type { JobRunner } from "./types";
|
|
14
|
+
import { runtimeValue } from "../runtime-config";
|
|
13
15
|
|
|
14
16
|
/** kind → module to dynamically import so it registers its runner. Real job
|
|
15
17
|
* kinds are built by parallel efforts; importing the module is expected to
|
|
16
18
|
* call `registerRunner(kind, ...)` at top level. Missing module ⇒ the job
|
|
17
19
|
* fails cleanly (see resolveRunner). */
|
|
18
|
-
const KIND_MODULES: Record<string,
|
|
19
|
-
quantize: "../quantize/job
|
|
20
|
-
finetune: "../train/job
|
|
20
|
+
const KIND_MODULES: Record<string, () => Promise<unknown>> = {
|
|
21
|
+
quantize: () => import("../quantize/job"),
|
|
22
|
+
finetune: () => import("../train/job"),
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
/** Resolve a runner for `kind`. Test kinds (noop/crash) are pre-registered in
|
|
@@ -27,19 +29,19 @@ async function resolveRunner(kind: string): Promise<JobRunner> {
|
|
|
27
29
|
const existing = getRunner(kind);
|
|
28
30
|
if (existing) return existing;
|
|
29
31
|
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
32
|
+
const load = KIND_MODULES[kind];
|
|
33
|
+
if (load) {
|
|
32
34
|
try {
|
|
33
|
-
await
|
|
35
|
+
await load();
|
|
34
36
|
} catch (e) {
|
|
35
37
|
throw new Error(
|
|
36
|
-
`kind "${kind}": failed to load runner module ${
|
|
38
|
+
`kind "${kind}": failed to load runner module ${kind} ` +
|
|
37
39
|
`(${e instanceof Error ? e.message : String(e)})`,
|
|
38
40
|
);
|
|
39
41
|
}
|
|
40
42
|
const loaded = getRunner(kind);
|
|
41
43
|
if (loaded) return loaded;
|
|
42
|
-
throw new Error(`kind "${kind}": module ${
|
|
44
|
+
throw new Error(`kind "${kind}": module ${kind} did not register a runner`);
|
|
43
45
|
}
|
|
44
46
|
throw new Error(`no runner registered for kind "${kind}"`);
|
|
45
47
|
}
|
|
@@ -48,8 +50,7 @@ function nowIso(): string {
|
|
|
48
50
|
return new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
async function
|
|
52
|
-
const jobId = process.argv[2];
|
|
53
|
+
export async function runJobEntry(jobId = process.argv[2]): Promise<void> {
|
|
53
54
|
if (!jobId) {
|
|
54
55
|
console.error("usage: bun job-entry.ts <jobId>");
|
|
55
56
|
process.exit(2);
|
|
@@ -58,8 +59,8 @@ async function main(): Promise<void> {
|
|
|
58
59
|
// Own fresh connection — overrides come from env so a spawned child finds
|
|
59
60
|
// the same DB/logs the parent used (tests set these to a tmp dir).
|
|
60
61
|
const store = new JobStore(
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
runtimeValue("MLX_BUN_JOBS_DB") || undefined,
|
|
63
|
+
runtimeValue("MLX_BUN_JOBS_DIR") || undefined,
|
|
63
64
|
);
|
|
64
65
|
|
|
65
66
|
const row = store.get(jobId);
|
|
@@ -86,7 +87,7 @@ async function main(): Promise<void> {
|
|
|
86
87
|
|
|
87
88
|
try {
|
|
88
89
|
const runner = await resolveRunner(row.kind);
|
|
89
|
-
const result = await runner(
|
|
90
|
+
const result = await createJobTaskClient(runner).run(config, emit);
|
|
90
91
|
const out = result?.outputPath;
|
|
91
92
|
if (out) store.setOutputPath(jobId, out);
|
|
92
93
|
store.setProgress(jobId, 1);
|
|
@@ -103,4 +104,4 @@ async function main(): Promise<void> {
|
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
main();
|
|
107
|
+
if (import.meta.main) void runJobEntry();
|