mlx-bun 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1453 -88
- package/THIRD_PARTY_NOTICES.md +882 -0
- package/bin/mlx-bun.convert.mjs +4 -0
- package/bin/mlx-bun.fuse.mjs +4 -0
- package/bin/mlx-bun.generate.mjs +4 -0
- package/bin/mlx-bun.lora.mjs +4 -0
- package/bin/mlx-bun.mjs +13 -21
- package/bin/mlx-bun.server.mjs +4 -0
- package/bin/mlx-bun.upload.mjs +4 -0
- package/dist/web/app.js +9584 -0
- package/package.json +50 -53
- package/src/cli/ane-install.ts +76 -0
- package/src/cli/args.ts +179 -0
- package/src/cli/engine-entry.ts +68 -0
- package/src/cli/inference.ts +214 -0
- package/src/cli/job-entry.ts +97 -0
- package/src/cli/library-host.ts +117 -0
- package/src/cli/main.ts +57 -0
- package/src/cli/memory-engine.ts +163 -0
- package/src/cli/memory.ts +36 -0
- package/src/cli/mlx-lm-aliases.ts +309 -0
- package/src/cli/model-choice.ts +33 -0
- package/src/cli/model-selection.ts +84 -0
- package/src/cli/module-host.ts +11 -0
- package/src/cli/module-verbs.ts +50 -0
- package/src/cli/numerical-policy.ts +12 -0
- package/src/cli/perplexity.ts +89 -0
- package/src/cli/serve-host.ts +423 -0
- package/src/cli/serve-isolated.ts +217 -0
- package/src/cli/serve-options.ts +106 -0
- package/src/cli/serve-state.ts +205 -0
- package/src/cli/serve.ts +500 -0
- package/src/cli/served-model-host.ts +102 -0
- package/src/cli/server-entry.ts +148 -0
- package/src/cli/serving-unit.ts +177 -0
- package/src/{tui.ts → cli/terminal.ts} +13 -8
- package/src/cli/worker-adapters.ts +34 -0
- package/src/cli/worker-entry.ts +272 -0
- package/src/cli/worker-unit.ts +179 -0
- package/src/engine/adapter-operation.ts +26 -0
- package/src/engine/cache-services.ts +114 -0
- package/src/engine/completion.ts +39 -0
- package/src/engine/generation-gateway.ts +358 -0
- package/src/engine/index.ts +59 -0
- package/src/engine/kv-budget.ts +120 -0
- package/src/engine/media-preparation.ts +232 -0
- package/src/engine/model-binding.ts +24 -0
- package/src/engine/model-host.ts +513 -0
- package/src/engine/model-serving.ts +89 -0
- package/src/{serve → engine}/preparation.ts +10 -8
- package/src/{serve → engine}/session-completion-engine.ts +6 -6
- package/src/engine/telemetry.ts +109 -0
- package/src/hub/downloads.ts +116 -0
- package/src/jobs/db.ts +16 -7
- package/src/jobs/events.ts +29 -0
- package/src/jobs/executable.ts +5 -0
- package/src/jobs/host.ts +51 -0
- package/src/jobs/in-process.ts +55 -0
- package/src/{contracts/jobs.ts → jobs/protocol.ts} +7 -9
- package/src/jobs/runner.ts +150 -231
- package/src/jobs/service.ts +75 -0
- package/src/jobs/sse.ts +59 -23
- package/src/jobs/worker-memory.ts +46 -0
- package/src/jobs/worker-process.ts +163 -0
- package/src/jobs/worker-supervisor.ts +258 -0
- package/src/modules.ts +58 -0
- package/src/publishing/catalog-hub.ts +18 -0
- package/src/publishing/credentials.ts +31 -0
- package/src/publishing/upload.ts +37 -0
- package/src/residency/leased-adapters.ts +21 -0
- package/src/residency/local-records.ts +16 -0
- package/src/residency/model-residency.ts +405 -0
- package/src/residency/record-index.ts +28 -0
- package/src/residency/resident-estimate.ts +50 -0
- package/src/{anthropic.ts → server/anthropic.ts} +3 -81
- package/src/server/cache-routes.ts +36 -0
- package/src/{serve → server}/chat-request.ts +12 -10
- package/src/{serve → server}/chat-stage.ts +27 -22
- package/src/{client.ts → server/client.ts} +28 -2
- package/src/{serve → server}/completion-executor.ts +42 -42
- package/src/server/decision-body.ts +55 -0
- package/src/server/decision-routes.ts +134 -0
- package/src/server/decision-wire.ts +228 -0
- package/src/{serve → server}/discovery-routes.ts +42 -83
- package/src/server/generated-token-history.ts +57 -0
- package/src/{serve → server}/http.ts +25 -13
- package/src/{serve → server}/inference-request.ts +5 -5
- package/src/server/job-routes.ts +20 -0
- package/src/server/media-prompt.ts +63 -0
- package/src/server/memory-completion-client.ts +46 -0
- package/src/server/model-routes.ts +192 -0
- package/src/{serve → server}/openai-wire.ts +3 -2
- package/src/{serve → server}/pipeline.ts +1 -1
- package/src/server/prompt-builder.ts +13 -0
- package/src/server/prompt-contracts.ts +17 -0
- package/src/server/proxy-routes.ts +187 -0
- package/src/server/publishing-routes.ts +41 -0
- package/src/{serve → server}/request-plan.ts +8 -8
- package/src/{serve → server}/request-prep.ts +82 -68
- package/src/{serve → server}/responses-client.ts +30 -13
- package/src/{responses.ts → server/responses.ts} +12 -93
- package/src/server/routes.ts +205 -0
- package/src/server/start.ts +72 -0
- package/src/server/status-routes.ts +108 -0
- package/src/{serve → server}/text-completion-stage.ts +25 -4
- package/src/server/text-prompt.ts +12 -0
- package/src/{serve → server}/token-streams.ts +36 -38
- package/src/server/worker-routes.ts +311 -0
- package/src/storage/paths.ts +61 -0
- package/src/web/assets.ts +37 -0
- package/src/web/{src → browser}/api.ts +5 -23
- package/src/web/browser/chat-host.ts +17 -0
- package/src/web/browser/installed-panels.ts +6 -0
- package/src/web/browser/main.ts +55 -0
- package/src/web/browser/markdown.ts +279 -0
- package/src/web/browser/memory-panel.ts +9 -0
- package/src/web/browser/palette.ts +64 -0
- package/src/web/browser/protocol.ts +13 -0
- package/src/web/browser/shell.ts +467 -0
- package/src/web/{src → browser}/status.ts +32 -36
- package/src/web/build.ts +51 -0
- package/src/web/public/app.html +1054 -0
- package/src/web/{sw.js → public/sw.js} +4 -3
- package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
- package/src/web/{vendor → public/vendor}/hljs.js +2 -2
- package/THIRD_PARTY_LICENSES.md +0 -51
- package/docs/README.md +0 -94
- package/docs/archive/hlg-sampling.md +0 -350
- package/docs/archive/investigations/audio-input-plan.md +0 -356
- package/docs/archive/investigations/chunk-finetune-experiment.md +0 -84
- package/docs/archive/investigations/colibri-glm52-port.md +0 -1486
- package/docs/archive/investigations/colibri-oracle-pin.md +0 -1284
- package/docs/archive/investigations/curve-bisector-routing.md +0 -123
- package/docs/archive/investigations/decode-roofline-lookagain.md +0 -348
- package/docs/archive/investigations/diffusion-gemma-port.md +0 -602
- package/docs/archive/investigations/dspark-handoff.md +0 -224
- package/docs/archive/investigations/expert-offload-single-user-moe.md +0 -292
- package/docs/archive/investigations/faithful-l1-consolidation.md +0 -310
- package/docs/archive/investigations/hlg-sampling-investigation.md +0 -970
- package/docs/archive/investigations/indexshare-performance-spike.md +0 -357
- package/docs/archive/investigations/kernel-perf-review-2026-07.md +0 -171
- package/docs/archive/investigations/lab-build-journal.md +0 -157
- package/docs/archive/investigations/minicpm5-decode-megakernel.md +0 -489
- package/docs/archive/investigations/openjarvis-fit.md +0 -198
- package/docs/archive/investigations/openwiki-evaluation.md +0 -249
- package/docs/archive/investigations/optimization_plan.md +0 -346
- package/docs/archive/investigations/orpo-base-uf-experiment-and-directions.md +0 -120
- package/docs/archive/investigations/orpo-flash-cce-pin-leak.md +0 -167
- package/docs/archive/investigations/orpo-uf-testing-handoff.md +0 -126
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +0 -92
- package/docs/archive/investigations/pi-builtin-investigation.md +0 -308
- package/docs/archive/investigations/pre-colibri-stabilization.md +0 -329
- package/docs/archive/investigations/qwen38-27b-campaign-log.md +0 -1092
- package/docs/archive/investigations/segmented-backward-handoff.md +0 -148
- package/docs/archive/investigations/starter-model-port-handoff.md +0 -342
- package/docs/archive/investigations/steel-flash-cce-handoff.md +0 -489
- package/docs/archive/investigations/the-dreaming-handoff.md +0 -141
- package/docs/archive/investigations/trainer-validation-experiment.md +0 -173
- package/docs/archive/planning/chat-ui-vision-memory-first.md +0 -199
- package/docs/archive/planning/chat-ui-vision.md +0 -50
- package/docs/archive/planning/chunk-task-roadmap.md +0 -77
- package/docs/archive/planning/curve-sampler-research-plan.md +0 -331
- package/docs/archive/planning/journal.md +0 -316
- package/docs/archive/planning/memory-docs-and-dag-plan.md +0 -194
- package/docs/archive/planning/pi-integration-review.md +0 -178
- package/docs/archive/planning/release-notes-v0.0.10.md +0 -57
- package/docs/archive/planning/release-notes-v0.0.11.md +0 -239
- package/docs/archive/planning/release-notes-v0.0.12.md +0 -80
- package/docs/archive/planning/release-notes-v0.0.13.md +0 -77
- package/docs/archive/planning/release-notes-v0.0.9.md +0 -122
- package/docs/archive/planning/release-notes-v0.2.0.md +0 -49
- package/docs/archive/planning/release-notes-v0.3.0.md +0 -35
- package/docs/archive/planning/web-ui-pass-plan.md +0 -213
- package/docs/archive/planning/website-readme-pass-plan.md +0 -224
- package/docs/design/batching.md +0 -1841
- package/docs/design/decode-speed-program.md +0 -2349
- package/docs/design/dreaming-nightly-pipeline.md +0 -684
- package/docs/design/generic-model-support.md +0 -705
- package/docs/design/kv-cache.md +0 -824
- package/docs/design/orpo-training.md +0 -680
- package/docs/design/speculative-decoding.md +0 -1990
- package/docs/design/turboquant.md +0 -2212
- package/docs/design/unified-engine-frontier-plan.md +0 -1880
- package/docs/design/web-chat-redesign.md +0 -695
- package/docs/planning/PRODUCT_ROADMAP.md +0 -594
- package/docs/planning/ResearchTopics.md +0 -119
- package/docs/planning/release-notes-v0.4.0.md +0 -45
- package/docs/planning/video-series.md +0 -421
- package/docs/reference/benchmarks.md +0 -3613
- package/docs/reference/cli.md +0 -585
- package/docs/reference/distribution.md +0 -355
- package/docs/reference/environment.md +0 -398
- package/docs/reference/glossary.md +0 -39
- package/docs/reference/library-api.md +0 -674
- package/docs/reference/memory.md +0 -260
- package/docs/reference/models.md +0 -334
- package/docs/reference/server-api.md +0 -1775
- package/docs/reference/server-config.md +0 -846
- package/docs/reference/training.md +0 -462
- package/docs/reference/troubleshooting.md +0 -158
- package/src/admission-plan.ts +0 -18
- package/src/audio/conformer.ts +0 -647
- package/src/audio/decode.ts +0 -133
- package/src/audio/features.ts +0 -202
- package/src/audio/transcode.ts +0 -67
- package/src/backends/mlx/assistant-target.ts +0 -46
- package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
- package/src/backends/mlx/autoregressive.ts +0 -108
- package/src/backends/mlx/batch-group.ts +0 -1790
- package/src/backends/mlx/cache-attachment.ts +0 -67
- package/src/backends/mlx/cache-layout.ts +0 -31
- package/src/backends/mlx/checkpoint-state.ts +0 -53
- package/src/backends/mlx/continuation-persistence.ts +0 -106
- package/src/backends/mlx/continuation-request.ts +0 -43
- package/src/backends/mlx/continuation.ts +0 -77
- package/src/backends/mlx/diffusion.ts +0 -39
- package/src/backends/mlx/draft-target.ts +0 -32
- package/src/backends/mlx/evaluation.ts +0 -105
- package/src/backends/mlx/fill-append.ts +0 -45
- package/src/backends/mlx/full-kv-row-append.ts +0 -32
- package/src/backends/mlx/full-kv-row-donor.ts +0 -54
- package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
- package/src/backends/mlx/gateway-binding.ts +0 -130
- package/src/backends/mlx/graph.ts +0 -38
- package/src/backends/mlx/kv-codec.ts +0 -9
- package/src/backends/mlx/kv-maintenance.ts +0 -133
- package/src/backends/mlx/kv-tensor-rows.ts +0 -212
- package/src/backends/mlx/memory-client.ts +0 -189
- package/src/backends/mlx/methods.ts +0 -90
- package/src/backends/mlx/model-prompt.ts +0 -164
- package/src/backends/mlx/model-serving.ts +0 -79
- package/src/backends/mlx/prefill-cohort.ts +0 -89
- package/src/backends/mlx/prefill-rows.ts +0 -200
- package/src/backends/mlx/prefill.ts +0 -33
- package/src/backends/mlx/projected-context-rows.ts +0 -72
- package/src/backends/mlx/request-policy.ts +0 -20
- package/src/backends/mlx/request-state-policy.ts +0 -41
- package/src/backends/mlx/rollback.ts +0 -89
- package/src/backends/mlx/row-sampling.ts +0 -49
- package/src/backends/mlx/serial-executor.ts +0 -242
- package/src/backends/mlx/speculative-group.ts +0 -359
- package/src/backends/mlx/speculative-round.ts +0 -161
- package/src/backends/mlx/speculative.ts +0 -114
- package/src/backends/mlx/state-rows.ts +0 -104
- package/src/backends/mlx/state-views.ts +0 -46
- package/src/backends/mlx/target-layout-capability.ts +0 -35
- package/src/backends/mlx/text-engine.ts +0 -73
- package/src/backends/mlx/transitioning-kv-rows.ts +0 -165
- package/src/chat-template.ts +0 -382
- package/src/cli.ts +0 -3168
- package/src/config.ts +0 -399
- package/src/contracts/completion.ts +0 -16
- package/src/contracts/execution.ts +0 -60
- package/src/contracts/generation.ts +0 -103
- package/src/contracts/host.ts +0 -7
- package/src/contracts/pi-provider.ts +0 -30
- package/src/contracts/pi.ts +0 -259
- package/src/contracts/prefix-cache.ts +0 -23
- package/src/contracts/resources.ts +0 -25
- package/src/contracts/sampling.ts +0 -23
- package/src/contracts/scheduling.ts +0 -45
- package/src/contracts/tsconfig.json +0 -14
- package/src/dataset/generators.ts +0 -1087
- package/src/dataset/index.ts +0 -12
- package/src/dataset/job.ts +0 -81
- package/src/dataset/llm.ts +0 -71
- package/src/dataset/registry.ts +0 -528
- package/src/diffusion/diffusion-generate.ts +0 -507
- package/src/download.ts +0 -505
- package/src/embed.ts +0 -77
- package/src/engine/admission.ts +0 -59
- package/src/engine/cancellation.ts +0 -38
- package/src/engine/engine.ts +0 -56
- package/src/engine/execution-coordinator.ts +0 -70
- package/src/engine/execution-plan.ts +0 -53
- package/src/engine/resources.ts +0 -53
- package/src/engine/scheduler.ts +0 -72
- package/src/engine/session.ts +0 -247
- package/src/eval/README.md +0 -130
- package/src/eval/ifeval.ts +0 -81
- package/src/eval/kl-prompts.ts +0 -29
- package/src/eval/kl.ts +0 -590
- package/src/eval/perplexity.ts +0 -164
- package/src/eval/quality-db.ts +0 -92
- package/src/eval/reference-logits.ts +0 -207
- package/src/eval/runner.ts +0 -124
- package/src/eval/score.ts +0 -49
- package/src/eval/tasks/bfcl.ts +0 -535
- package/src/eval/tasks/gsm8k.ts +0 -98
- package/src/eval/tasks/hashhop.ts +0 -139
- package/src/eval/tasks/humaneval.ts +0 -275
- package/src/eval/tasks/ifeval.ts +0 -525
- package/src/eval/tasks/mmlu.ts +0 -157
- package/src/eval/ultrafeedback.ts +0 -60
- package/src/evaldb.ts +0 -199
- package/src/expert-io.ts +0 -393
- package/src/expert-offload-build.ts +0 -77
- package/src/expert-offload.ts +0 -76
- package/src/expert-residency.ts +0 -1134
- package/src/expert-usage.ts +0 -415
- package/src/fill/echo-index.ts +0 -188
- package/src/fill/fill-session.ts +0 -452
- package/src/fill/proposal.ts +0 -68
- package/src/fill/schema-rows.ts +0 -506
- package/src/fill/tool-boundary.ts +0 -103
- package/src/fit.ts +0 -249
- package/src/generate.ts +0 -1346
- package/src/grammar.ts +0 -591
- package/src/harness-pi.ts +0 -184
- package/src/hf-push.ts +0 -628
- package/src/hub-rest.ts +0 -242
- package/src/index.ts +0 -63
- package/src/inference/denoising.ts +0 -17
- package/src/inference/draft-acceptance.ts +0 -41
- package/src/inference/draft-output.ts +0 -49
- package/src/inference/graph.ts +0 -33
- package/src/inference/prefill.ts +0 -39
- package/src/inference/rollback.ts +0 -7
- package/src/jobs/index.ts +0 -31
- package/src/jobs/job-entry.ts +0 -107
- package/src/jobs/task-client.ts +0 -19
- package/src/jobs/types.ts +0 -2
- package/src/kv-scheme.ts +0 -257
- package/src/kv-store.ts +0 -1099
- package/src/lab/README.md +0 -18
- package/src/lab/curve/curve-designer.html +0 -303
- package/src/lab/curve/curve-sampler.ts +0 -122
- package/src/lab/expert-trace/expert-trace.ts +0 -69
- package/src/lab/paged-kv/paged-kv-rows.ts +0 -83
- package/src/lab/paged-kv/paged-kv.ts +0 -270
- package/src/library.ts +0 -40
- package/src/lora.ts +0 -408
- package/src/md-modules.d.ts +0 -49
- package/src/media-fetch.ts +0 -442
- package/src/memory/article.ts +0 -558
- package/src/memory/chunk-validation.ts +0 -150
- package/src/memory/chunk.ts +0 -318
- package/src/memory/cluster.ts +0 -351
- package/src/memory/coverage.ts +0 -134
- package/src/memory/crosslink.ts +0 -0
- package/src/memory/db.ts +0 -253
- package/src/memory/entity.ts +0 -203
- package/src/memory/gate.ts +0 -187
- package/src/memory/history.ts +0 -152
- package/src/memory/ingest.ts +0 -335
- package/src/memory/model.ts +0 -183
- package/src/memory/normalize.ts +0 -671
- package/src/memory/parse.ts +0 -22
- package/src/memory/pipeline.ts +0 -275
- package/src/memory/prompts.ts +0 -65
- package/src/memory/query.ts +0 -334
- package/src/memory/reconcile.ts +0 -734
- package/src/memory/redirect.ts +0 -108
- package/src/memory/reindex.ts +0 -325
- package/src/memory/resolve.ts +0 -307
- package/src/memory/rest.ts +0 -245
- package/src/memory/route.ts +0 -272
- package/src/memory/schedule.ts +0 -165
- package/src/memory/stages.ts +0 -777
- package/src/memory/synthesize.ts +0 -1638
- package/src/memory/tools.ts +0 -749
- package/src/memory/vault.ts +0 -1194
- package/src/memory/wikify.ts +0 -1064
- package/src/mlx/array.ts +0 -388
- package/src/mlx/autograd.ts +0 -304
- package/src/mlx/checkpoint.ts +0 -149
- package/src/mlx/compile.ts +0 -168
- package/src/mlx/custom-vjp.ts +0 -188
- package/src/mlx/ffi.ts +0 -512
- package/src/mlx/materialize.ts +0 -23
- package/src/mlx/metal-kernel.ts +0 -159
- package/src/mlx/ops.ts +0 -1021
- package/src/mlx/quantized-rows.ts +0 -36
- package/src/mlx/token-bitmask.ts +0 -52
- package/src/mlx/turboquant-kv-decode.ts +0 -82
- package/src/mlx/turboquant-kv-inverse.ts +0 -122
- package/src/mlx/turboquant-ops.ts +0 -861
- package/src/mlx/turboquant-tables.ts +0 -237
- package/src/mmap.ts +0 -90
- package/src/model/artifact-identity.ts +0 -73
- package/src/model/batched-kv.ts +0 -235
- package/src/model/batched-mask.ts +0 -279
- package/src/model/batched-quant.ts +0 -212
- package/src/model/batched-quantized-kv.ts +0 -144
- package/src/model/batched-rotating-quant.ts +0 -353
- package/src/model/batched-rotating-state.ts +0 -149
- package/src/model/batched-rotating.ts +0 -338
- package/src/model/batched-row-storage.ts +0 -179
- package/src/model/batched-ssm.ts +0 -52
- package/src/model/batched-turboquant-kv.ts +0 -93
- package/src/model/compiled-decode.ts +0 -712
- package/src/model/decoded-kv-donor.ts +0 -12
- package/src/model/delayed-quantized-kv.ts +0 -72
- package/src/model/delayed-rotating-quantized-kv.ts +0 -93
- package/src/model/delayed-turboquant-kv.ts +0 -55
- package/src/model/diffusion-gemma.ts +0 -1026
- package/src/model/factory.ts +0 -189
- package/src/model/fingerprint.ts +0 -33
- package/src/model/flash-attention.ts +0 -694
- package/src/model/full-prefill-padding.ts +0 -56
- package/src/model/full-prefill-row.ts +0 -105
- package/src/model/gemma4-base.ts +0 -2351
- package/src/model/gemma4.ts +0 -1315
- package/src/model/generated/gemma4-12b.ts +0 -429
- package/src/model/generated/gemma4-26b.ts +0 -448
- package/src/model/generated/gemma4-e4b.ts +0 -717
- package/src/model/generated/index.ts +0 -18
- package/src/model/glm52-atlas.ts +0 -511
- package/src/model/glm52-cache.ts +0 -792
- package/src/model/glm52-config.ts +0 -262
- package/src/model/glm52-container.ts +0 -305
- package/src/model/glm52-coupling.ts +0 -388
- package/src/model/glm52-dsa.ts +0 -606
- package/src/model/glm52-expert-layout.ts +0 -253
- package/src/model/glm52-layout.ts +0 -152
- package/src/model/glm52-memory.ts +0 -500
- package/src/model/glm52-mla.ts +0 -792
- package/src/model/glm52-moe.ts +0 -223
- package/src/model/glm52-pilot.ts +0 -537
- package/src/model/glm52-reference.ts +0 -445
- package/src/model/glm52-residency.ts +0 -557
- package/src/model/glm52-resident-weights.ts +0 -135
- package/src/model/glm52-streamed-experts.ts +0 -453
- package/src/model/glm52-streamed-metal.ts +0 -610
- package/src/model/glm52-weights.ts +0 -503
- package/src/model/glm52.ts +0 -1132
- package/src/model/implementation.ts +0 -69
- package/src/model/kv-attention-view.ts +0 -67
- package/src/model/minicpm5.ts +0 -376
- package/src/model/profile.ts +0 -443
- package/src/model/qwen-append.ts +0 -12
- package/src/model/qwen-conv.ts +0 -52
- package/src/model/qwen3-delta-state.ts +0 -74
- package/src/model/qwen3-delta.ts +0 -451
- package/src/model/qwen3-moe.ts +0 -404
- package/src/model/qwen3-mrope.ts +0 -252
- package/src/model/qwen3.ts +0 -277
- package/src/model/qwen3_5-checkpoint.ts +0 -164
- package/src/model/qwen3_5.ts +0 -819
- package/src/model/rotating-kv-donor.ts +0 -35
- package/src/model/rotating-kv-layout.ts +0 -262
- package/src/model/rotating-row-transaction.ts +0 -35
- package/src/model/speculative-rotating-kv.ts +0 -101
- package/src/model/ssm-prefill-padding.ts +0 -39
- package/src/model/support.ts +0 -102
- package/src/model/trellis-balanced-scatter.ts +0 -51
- package/src/model/trellis-linear.ts +0 -672
- package/src/model/trellis-shared-m.ts +0 -151
- package/src/model/trellis-shared-scatter.ts +0 -144
- package/src/model/trellis-splitk-prefill.ts +0 -158
- package/src/model/trellis-tiled-prefill.ts +0 -136
- package/src/model/trellis-vector-expand.ts +0 -62
- package/src/model/trellis-wide-prefill.ts +0 -94
- package/src/model/turboquant-codec.ts +0 -83
- package/src/model/universal/archs.ts +0 -332
- package/src/model/universal/dense.ts +0 -612
- package/src/model/universal/modules.ts +0 -170
- package/src/model/universal/rope.ts +0 -381
- package/src/native/expert_io.c +0 -523
- package/src/native/frame_extract.swift +0 -140
- package/src/native-pack.ts +0 -162
- package/src/pi-provider.ts +0 -53
- package/src/pi-session.ts +0 -81
- package/src/pi-terminal.ts +0 -274
- package/src/pi-web.ts +0 -1932
- package/src/preflight.ts +0 -158
- package/src/prompt-cache.ts +0 -460
- package/src/quantize/allocator.ts +0 -627
- package/src/quantize/atomic-output.ts +0 -38
- package/src/quantize/calibration.ts +0 -181
- package/src/quantize/config-writer.ts +0 -145
- package/src/quantize/index.ts +0 -84
- package/src/quantize/job.ts +0 -162
- package/src/quantize/quantizer.ts +0 -666
- package/src/quantize/rotate.ts +0 -603
- package/src/quantize/safetensors-writer.ts +0 -249
- package/src/quantize/sensitivity.ts +0 -216
- package/src/quantize/trellis.ts +0 -586
- package/src/quantize/weight-transform.ts +0 -292
- package/src/registry.ts +0 -602
- package/src/runtime-config.ts +0 -81
- package/src/safetensors.ts +0 -158
- package/src/sampler.ts +0 -1011
- package/src/serve/admin-routes.ts +0 -184
- package/src/serve/assets/curve-terrain.html +0 -105
- package/src/serve/assets/training-inference-map.html +0 -575
- package/src/serve/aux-routes.ts +0 -132
- package/src/serve/batch-scheduler.ts +0 -8
- package/src/serve/checkpoint-identity.ts +0 -64
- package/src/serve/generation-gateway.ts +0 -496
- package/src/serve/isolate.ts +0 -609
- package/src/serve/kv-budget.ts +0 -14
- package/src/serve/lab-routes.ts +0 -341
- package/src/serve/lane-registry.ts +0 -45
- package/src/serve/model-admin-routes.ts +0 -155
- package/src/serve/model-binding.ts +0 -43
- package/src/serve/model-host.ts +0 -511
- package/src/serve/parent-application.ts +0 -56
- package/src/serve/prompt-response-trace.ts +0 -147
- package/src/serve/response-lease.ts +0 -24
- package/src/serve/session-search.ts +0 -326
- package/src/serve/static-routes.ts +0 -101
- package/src/server.ts +0 -1314
- package/src/spec/assistant-rows.ts +0 -92
- package/src/spec/assistant-source.ts +0 -126
- package/src/spec/cache-identity.ts +0 -22
- package/src/spec/deepspec-rows.ts +0 -29
- package/src/spec/deepspec-source.ts +0 -145
- package/src/spec/dflash-source.ts +0 -149
- package/src/spec/drafter.ts +0 -304
- package/src/spec/dspark/ab-stats.ts +0 -136
- package/src/spec/dspark/calibration.ts +0 -112
- package/src/spec/dspark/data-dflash.ts +0 -156
- package/src/spec/dspark/data.ts +0 -201
- package/src/spec/dspark/deepspec-module.ts +0 -776
- package/src/spec/dspark/generate-dflash.ts +0 -245
- package/src/spec/dspark/generate.ts +0 -290
- package/src/spec/dspark/loader.ts +0 -23
- package/src/spec/dspark/loss.ts +0 -213
- package/src/spec/dspark/module-dflash.ts +0 -560
- package/src/spec/dspark/module.ts +0 -540
- package/src/spec/dspark/quantize-drafter.ts +0 -91
- package/src/spec/dspark/sample.ts +0 -112
- package/src/spec/generate.ts +0 -276
- package/src/spec/glm52-mtp-graph.ts +0 -29
- package/src/spec/glm52-mtp-rows.ts +0 -132
- package/src/spec/glm52-mtp-source.ts +0 -317
- package/src/spec/glm52-mtp-state.ts +0 -33
- package/src/spec/ngram-source.ts +0 -204
- package/src/spec/projected-draft-rows.ts +0 -73
- package/src/spec/qwen-mtp-module.ts +0 -171
- package/src/spec/qwen-mtp-rows.ts +0 -219
- package/src/spec/qwen-mtp-source.ts +0 -383
- package/src/spec/qwen-mtp-state.ts +0 -30
- package/src/spec/serve-loop.ts +0 -585
- package/src/spec/source.ts +0 -215
- package/src/spec/two-model-rows.ts +0 -61
- package/src/spec/two-model.ts +0 -113
- package/src/ssd-cache.ts +0 -372
- package/src/ssd-durability.ts +0 -211
- package/src/tokenizer.ts +0 -335
- package/src/tool-approvals.ts +0 -131
- package/src/tool-call.ts +0 -695
- package/src/train/dataset.ts +0 -484
- package/src/train/diffusion-lora.ts +0 -216
- package/src/train/export.ts +0 -32
- package/src/train/flash-cce.ts +0 -1234
- package/src/train/forward.ts +0 -266
- package/src/train/fuse.ts +0 -243
- package/src/train/index.ts +0 -46
- package/src/train/job.ts +0 -205
- package/src/train/lora-params.ts +0 -254
- package/src/train/loss.ts +0 -1591
- package/src/train/merge.ts +0 -195
- package/src/train/optimizer.ts +0 -183
- package/src/train/prefix-shared.ts +0 -490
- package/src/train/rank.ts +0 -137
- package/src/train/segmented.ts +0 -1828
- package/src/train/steel-qmm-header.ts +0 -1461
- package/src/train/trainer.ts +0 -1221
- package/src/train/watch.ts +0 -542
- package/src/vision/diffusion-vision.ts +0 -620
- package/src/vision/embedder.ts +0 -168
- package/src/vision/preprocess.ts +0 -247
- package/src/vision/prompt.ts +0 -373
- package/src/vision/qwen3vl-preprocess.ts +0 -409
- package/src/vision/qwen3vl-prompt.ts +0 -196
- package/src/vision/qwen3vl-tower.ts +0 -555
- package/src/vision/siglip.ts +0 -599
- package/src/vision/video-frames.ts +0 -148
- package/src/web/app.html +0 -2143
- package/src/web/app.js +0 -5703
- package/src/web/skills/memory/SKILL.md +0 -120
- package/src/web/skills/web-research/SKILL.md +0 -46
- package/src/web/skills.ts +0 -97
- package/src/web/src/adapters-panel.ts +0 -288
- package/src/web/src/assistant.ts +0 -451
- package/src/web/src/chat.ts +0 -1057
- package/src/web/src/composer.ts +0 -959
- package/src/web/src/dataset.ts +0 -132
- package/src/web/src/finetune.ts +0 -267
- package/src/web/src/hub.ts +0 -428
- package/src/web/src/main.ts +0 -98
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +0 -572
- package/src/web/src/model-picker.ts +0 -159
- package/src/web/src/palette.ts +0 -346
- package/src/web/src/protocol.ts +0 -26
- package/src/web/src/quantize.ts +0 -167
- package/src/web/src/rag.ts +0 -274
- package/src/web/src/sessions.ts +0 -469
- package/src/web/src/shell.ts +0 -804
- package/src/web/src/ui-catalog.ts +0 -78
- package/src/web/vendor/README.md +0 -61
- package/src/web-assets.ts +0 -47
- package/src/web-tools.ts +0 -478
- package/src/weights.ts +0 -255
- /package/src/{serve → server}/completion-sink.ts +0 -0
- /package/src/web/{icon.svg → public/icon.svg} +0 -0
- /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
- /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
import type { SpecRunServices } from "../../spec/serve-loop";
|
|
2
|
-
import { cleanupFailure, disposeResources, ownResource } from "../../engine/resources";
|
|
3
|
-
import { bindGeneration } from "../../generate";
|
|
4
|
-
import type { RuntimeModel } from "../../model/factory";
|
|
5
|
-
import { Qwen35Model } from "../../model/qwen3_5";
|
|
6
|
-
import type { Cache } from "../../model/gemma4";
|
|
7
|
-
import type { MlxPrefixCache } from "./checkpoint-state";
|
|
8
|
-
import type { SsdCacheStore } from "../../ssd-cache";
|
|
9
|
-
import type { DraftProvider } from "../../spec/source";
|
|
10
|
-
import type { SerialRun, Vision } from "../../serve/generation-gateway";
|
|
11
|
-
import { bindContinuationPolicy } from "./continuation";
|
|
12
|
-
import { runtimeConfig, withRuntimeConfig, type RuntimeConfig } from "../../runtime-config";
|
|
13
|
-
import { bindLegacySpeculativeModel } from "./speculative";
|
|
14
|
-
|
|
15
|
-
/** Native serial execution depends on this bound port, never a model union.
|
|
16
|
-
* Weights remain borrowed. The gateway supplies the exclusive runtime lease. */
|
|
17
|
-
export interface MlxSerialBinding {
|
|
18
|
-
readonly runtime: RuntimeConfig;
|
|
19
|
-
readonly generate: ReturnType<typeof bindGeneration>;
|
|
20
|
-
readonly speculate?: (
|
|
21
|
-
promptIds: Parameters<SerialRun>[0], options: Parameters<SerialRun>[1],
|
|
22
|
-
onToken: Parameters<SerialRun>[2], services?: SpecRunServices,
|
|
23
|
-
) => ReturnType<SerialRun>;
|
|
24
|
-
makeCache(): Cache[];
|
|
25
|
-
enterMedia?(vision?: Vision): () => void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Family-specific context is bound once at the compatibility boundary. */
|
|
29
|
-
export function bindLegacySerialModel(
|
|
30
|
-
model: RuntimeModel,
|
|
31
|
-
draft?: { provider: DraftProvider; numDraftTokens: number },
|
|
32
|
-
): MlxSerialBinding {
|
|
33
|
-
const speculative = draft ? bindLegacySpeculativeModel(model, draft.provider) : undefined;
|
|
34
|
-
return {
|
|
35
|
-
runtime: runtimeConfig(),
|
|
36
|
-
generate: bindGeneration(model),
|
|
37
|
-
makeCache: model.makeCache.bind(model),
|
|
38
|
-
...(speculative && draft ? { speculate: (async (prompt, options, onToken, services) => {
|
|
39
|
-
const { specRun } = await import("../../spec/serve-loop");
|
|
40
|
-
return specRun(speculative, draft.numDraftTokens, prompt, options, onToken, services);
|
|
41
|
-
}) satisfies NonNullable<MlxSerialBinding["speculate"]> } : {}),
|
|
42
|
-
...(model instanceof Qwen35Model ? { enterMedia(vision?: Vision) {
|
|
43
|
-
const previous = model.mrope;
|
|
44
|
-
if (vision?.mrope) model.mrope = vision.mrope;
|
|
45
|
-
return () => { model.mrope = previous; };
|
|
46
|
-
} } : {}),
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface MlxSerialServices {
|
|
51
|
-
readonly promptCache: MlxPrefixCache & { readonly maxBytes?: number };
|
|
52
|
-
readonly checkpoints: Pick<SsdCacheStore, "findGenerationCheckpoint" | "restore" |
|
|
53
|
-
"storeGenerationCheckpoint" | "removeGenerationCheckpoints"> | null;
|
|
54
|
-
readonly checkpointEveryTokens?: number;
|
|
55
|
-
readonly checkpointPersistence?: import("./continuation-persistence").ContinuationPersistence;
|
|
56
|
-
/** Artifact, implementation, state ABI and codec identity captured at load. */
|
|
57
|
-
readonly identity: unknown;
|
|
58
|
-
adapterNamespace(adapters: string[]): string;
|
|
59
|
-
cloneState(caches: Cache[]): Cache[];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Cache lookup, replay, prompt snapshots and checkpoint persistence belong to
|
|
63
|
-
* native execution. HTTP only composes this service and frames its output.
|
|
64
|
-
* The caller transfers prepared native inputs; caches created/taken here are
|
|
65
|
-
* owned until returned to the prefix store or disposed after execution. */
|
|
66
|
-
export function createMlxSerialExecutor(binding: MlxSerialBinding, services: MlxSerialServices): SerialRun {
|
|
67
|
-
const { promptCache, checkpoints: ssdStore } = services;
|
|
68
|
-
return (promptIds, options, onToken, vision, trace, execution) => withRuntimeConfig(binding.runtime, async () => {
|
|
69
|
-
let releaseContinuation: (() => void) | undefined;
|
|
70
|
-
let caches: Cache[] = [];
|
|
71
|
-
let retain: (() => void) | undefined;
|
|
72
|
-
let closeMedia: (() => void) | undefined;
|
|
73
|
-
const cleanup = ownResource(null, () => disposeResources([
|
|
74
|
-
{ dispose() {
|
|
75
|
-
disposeResources(caches);
|
|
76
|
-
retain?.(); // backing release requires successful cache disposal
|
|
77
|
-
} },
|
|
78
|
-
{ dispose: () => closeMedia?.() },
|
|
79
|
-
{ dispose: () => releaseContinuation?.() },
|
|
80
|
-
...[options.grammar, vision?.embeddings, vision?.imageMask,
|
|
81
|
-
vision?.multimodalMask, options.visionPixels].filter((value) => value != null),
|
|
82
|
-
]));
|
|
83
|
-
try {
|
|
84
|
-
options.signal?.throwIfAborted();
|
|
85
|
-
if (!execution) throw new Error("serial execution requires a resolved plan");
|
|
86
|
-
if (execution.method === "speculative") {
|
|
87
|
-
if (!binding.speculate) throw new Error("resolved speculation requires a bound verifier");
|
|
88
|
-
return await binding.speculate(promptIds, options, onToken, {
|
|
89
|
-
...(binding.runtime.flag("MLX_BUN_MTP_PROMPT_CACHE", true) && services.promptCache.maxBytes !== 0
|
|
90
|
-
? { prefixCache: services.promptCache } : {}),
|
|
91
|
-
cloneState: services.cloneState,
|
|
92
|
-
cacheNamespace: options.adapters?.length ? services.adapterNamespace(options.adapters) : "",
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
// Cache entries are adapter-specific: KV computed under one adapter
|
|
96
|
-
// must never seed another's (or the base's) prefill.
|
|
97
|
-
const cacheNs = options.adapters?.length ? services.adapterNamespace(options.adapters) : "";
|
|
98
|
-
// Paged-KV request scope (docs/design/kv-cache.md): media
|
|
99
|
-
// prompts (bidir overlay) and LoRA-adapter requests are v1 non-goals —
|
|
100
|
-
// they run the PLAIN cache path even under --paged-kv (scope the flag
|
|
101
|
-
// per request, never 400). Effective value computed ONCE so the
|
|
102
|
-
// prompt-cache bypass below and the generate() options can't disagree.
|
|
103
|
-
const pagedKv = execution.pagedKv ? options.pagedKv : undefined;
|
|
104
|
-
// Paged requests bypass the prompt cache entirely (v1 non-goal:
|
|
105
|
-
// PagedKVCache has no cloneKvCaches/restore path — the vision
|
|
106
|
-
// precedent). Fresh caches per request, disposed on completion.
|
|
107
|
-
const skipPromptCache = !execution.promptCache;
|
|
108
|
-
const checkpointEvery = services.checkpointEveryTokens;
|
|
109
|
-
const checkpointEligible = execution.checkpoint;
|
|
110
|
-
const continuation = checkpointEligible ? bindContinuationPolicy({ store: ssdStore!,
|
|
111
|
-
restore: entry => ssdStore!.restore(entry, binding), prompt: promptIds,
|
|
112
|
-
options, execution, identity: services.identity, namespace: cacheNs, persistence: services.checkpointPersistence }) : null;
|
|
113
|
-
releaseContinuation = continuation?.release;
|
|
114
|
-
const checkpointKey = continuation?.key;
|
|
115
|
-
// Both tiers in one call (Layer 0): take() prefers a strictly-longer
|
|
116
|
-
// SSD prefix, restores it zero-copy, and trims — see PromptCache.take.
|
|
117
|
-
const closeCacheLookup = trace?.begin("cache.lookup_restore", {
|
|
118
|
-
mechanism: "serial",
|
|
119
|
-
bypassed: skipPromptCache,
|
|
120
|
-
});
|
|
121
|
-
const checkpoint = continuation?.restore();
|
|
122
|
-
caches = checkpoint?.caches ?? [];
|
|
123
|
-
const resuming = Boolean(checkpoint);
|
|
124
|
-
const generationPromptIds = checkpoint?.cacheTokens ?? promptIds;
|
|
125
|
-
const entry = skipPromptCache || resuming
|
|
126
|
-
? null
|
|
127
|
-
: promptCache.take(promptIds, cacheNs);
|
|
128
|
-
if (entry) { caches = entry.caches; retain = entry.retain; }
|
|
129
|
-
if (!checkpoint && !entry) caches = binding.makeCache();
|
|
130
|
-
closeCacheLookup?.();
|
|
131
|
-
// Prompt-boundary snapshot (the multi-turn agent fix, 2026-07-04): the
|
|
132
|
-
// prompt+gen entry put() below is UNTRIMMABLE at context > sliding
|
|
133
|
-
// window (wrapped rings) and under quantized KV (mid-group), so any
|
|
134
|
-
// decode→encode roundtrip drift in the reply the client sends back
|
|
135
|
-
// turns the next turn into a total miss (measured: 12B turn-2 TTFT
|
|
136
|
-
// 8.9 s instead of ~0.2 s). A prompt-ONLY entry is always an exact
|
|
137
|
-
// prefix of the next turn's rendering regardless of reply drift.
|
|
138
|
-
// Zero-copy (cloneKvCaches = slice views); only for substantial cold
|
|
139
|
-
// prefills, where the re-prefill it saves is worth an extra entry.
|
|
140
|
-
// The oracle invariant (mlx-lm insert_segments): a trim-free STRICT
|
|
141
|
-
// prefix of the prompt exists for EVERY substantial request — cap the
|
|
142
|
-
// boundary at len-1 so even a stableLen == len prompt (e4b: the
|
|
143
|
-
// template tail survives the probe render) snapshots prompt[:-1]. An
|
|
144
|
-
// exact repeat then matches with trimNeeded == 0, bypassing
|
|
145
|
-
// isTrimmable() entirely — the only reuse path a wrapped ring has.
|
|
146
|
-
const boundary = Math.min(options.snapshotAt ?? promptIds.length, promptIds.length - 1);
|
|
147
|
-
// Re-snapshot on EVERY substantial request whose stable boundary extends
|
|
148
|
-
// past the cached prefix; the clone is zero-copy views, so re-putting
|
|
149
|
-
// is ~free.
|
|
150
|
-
const snapshotBoundary =
|
|
151
|
-
!skipPromptCache && !resuming && boundary >= 256 &&
|
|
152
|
-
boundary > (entry?.tokens.length ?? 0);
|
|
153
|
-
closeMedia = binding.enterMedia?.(vision);
|
|
154
|
-
if (resuming) {
|
|
155
|
-
const replay = generationPromptIds.slice(promptIds.length);
|
|
156
|
-
console.log(
|
|
157
|
-
`[generation-checkpoint] resuming ${checkpointKey} at ` +
|
|
158
|
-
`${replay.length} emitted tokens`,
|
|
159
|
-
);
|
|
160
|
-
for (const token of replay) {
|
|
161
|
-
options.signal?.throwIfAborted();
|
|
162
|
-
if ((await onToken(token)) === false)
|
|
163
|
-
throw new Error("saved generation prefix triggered a terminal stop while replaying");
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
const gen = binding.generate(generationPromptIds, {
|
|
167
|
-
...options,
|
|
168
|
-
decodePolicy: execution,
|
|
169
|
-
...(resuming ? { seed: checkpoint!.seed } : {}),
|
|
170
|
-
fill: execution.fill ? options.fill : undefined,
|
|
171
|
-
pagedKv, // request-scoped (undefined strips the server-wide flag)
|
|
172
|
-
cache: caches,
|
|
173
|
-
...(resuming
|
|
174
|
-
? {
|
|
175
|
-
initialPendingToken: checkpoint!.pendingToken,
|
|
176
|
-
initialGeneratedTokens: checkpoint!.generatedTokens,
|
|
177
|
-
originalPromptTokens: promptIds.length,
|
|
178
|
-
}
|
|
179
|
-
: {}),
|
|
180
|
-
...(checkpointEligible
|
|
181
|
-
? {
|
|
182
|
-
checkpointEveryTokens: checkpointEvery,
|
|
183
|
-
onDecodeCheckpoint: async (state: {
|
|
184
|
-
cacheTokens: number[];
|
|
185
|
-
caches: Cache[];
|
|
186
|
-
generatedTokens: number;
|
|
187
|
-
pendingToken: number;
|
|
188
|
-
}) => {
|
|
189
|
-
if (services.checkpointPersistence)
|
|
190
|
-
continuation!.captureOwned({ ...state, caches: services.cloneState(state.caches) });
|
|
191
|
-
else await continuation!.capture(state);
|
|
192
|
-
},
|
|
193
|
-
}
|
|
194
|
-
: {}),
|
|
195
|
-
...(snapshotBoundary
|
|
196
|
-
? {
|
|
197
|
-
// snapshotAt MUST travel with the hook: generate() splits the
|
|
198
|
-
// prefill at exactly this many tokens and fires the hook while
|
|
199
|
-
// the caches hold exactly that prefix — putting boundary
|
|
200
|
-
// tokens against caches at any other offset is silent KV
|
|
201
|
-
// corruption.
|
|
202
|
-
snapshotAt: boundary,
|
|
203
|
-
onPrefillDone: () => {
|
|
204
|
-
try {
|
|
205
|
-
const snapshot = ownResource(services.cloneState(caches), disposeResources);
|
|
206
|
-
try {
|
|
207
|
-
promptCache.put(promptIds.slice(0, boundary), snapshot.borrow(), cacheNs);
|
|
208
|
-
snapshot.transfer();
|
|
209
|
-
} finally { snapshot.close(); }
|
|
210
|
-
} catch (e) {
|
|
211
|
-
console.warn(`prompt-boundary snapshot skipped: ${(e as Error).message}`);
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
}
|
|
215
|
-
: {}),
|
|
216
|
-
...(vision
|
|
217
|
-
? {
|
|
218
|
-
promptEmbeddings: vision.embeddings,
|
|
219
|
-
...(vision.imageMask ? { imageMask: vision.imageMask } : {}),
|
|
220
|
-
...(vision.multimodalMask ? { multimodalMask: vision.multimodalMask } : {}),
|
|
221
|
-
}
|
|
222
|
-
: {}),
|
|
223
|
-
}, { trace, mechanism: "serial" });
|
|
224
|
-
for await (const t of gen) {
|
|
225
|
-
if ((await onToken(t.token, t.logprobs)) === false) break;
|
|
226
|
-
}
|
|
227
|
-
const s = gen.stats!; // set on completion AND on early break
|
|
228
|
-
continuation?.complete();
|
|
229
|
-
if (!skipPromptCache) {
|
|
230
|
-
// put() fires onPut → the debounced write-behind SSD snapshot
|
|
231
|
-
// (wired below), covering the batch lane's puts too.
|
|
232
|
-
promptCache.put(s.cacheTokens, caches, cacheNs, retain);
|
|
233
|
-
caches = []; retain = undefined; // ownership returned to the prefix store
|
|
234
|
-
}
|
|
235
|
-
return s;
|
|
236
|
-
} catch (error) {
|
|
237
|
-
cleanupFailure(error, () => cleanup.close());
|
|
238
|
-
} finally {
|
|
239
|
-
cleanup.close();
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
}
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
import {captureSpeculativeOptions, speculativePrefixNamespace} from "../../spec/cache-identity";
|
|
2
|
-
import type { RuntimeModel } from "../../model/factory";
|
|
3
|
-
import type { GenerateOptions } from "../../generate";
|
|
4
|
-
import type { DraftProvider, DraftRowGroup, DraftPrefillGroup, DraftRowCheckpoint } from "../../spec/source";
|
|
5
|
-
import { makeSampler, makeStepSampler, readStepExtras, type NumberStepSampler, type Sampler } from "../../sampler";
|
|
6
|
-
import { MlxArray } from "../../mlx/array";
|
|
7
|
-
import * as ops from "../../mlx/ops";
|
|
8
|
-
import { clearCache } from "../../mlx/ffi";
|
|
9
|
-
import { applyStateChanges, cleanupFailure, disposeResources } from "../../engine/resources";
|
|
10
|
-
import { cloneKvCaches } from "../../kv-store";
|
|
11
|
-
import type { Cache } from "../../model/gemma4-base";
|
|
12
|
-
import { targetCacheLayout } from "./cache-layout";
|
|
13
|
-
import { MlxStateRows } from "./state-rows";
|
|
14
|
-
import { bindLegacySpeculativeModel, type MlxSpeculativeBinding } from "./speculative";
|
|
15
|
-
import { bindLegacyDraftTarget } from "./draft-target";
|
|
16
|
-
import { bindRowCacheRollback } from "./rollback";
|
|
17
|
-
import { createKvMaintenance } from "./kv-maintenance";
|
|
18
|
-
import { disposeAttachments, type CheckpointAttachment } from "./checkpoint-state";
|
|
19
|
-
import { advanceSpeculativeOutputs } from "./speculative-round";
|
|
20
|
-
import { MlxPrefillRows, type MlxPrefillState } from "./prefill-rows";
|
|
21
|
-
import type { MlxGroupMethodHost, MlxGroupMethodRequest, MlxGroupPreparation, MlxGroupedMethod, Row } from "./batch-group";
|
|
22
|
-
|
|
23
|
-
interface RequestState {
|
|
24
|
-
sampling: NumberStepSampler;
|
|
25
|
-
draftSampling: Sampler;
|
|
26
|
-
retain?: () => void;
|
|
27
|
-
namespace: string;
|
|
28
|
-
prefixLength: number;
|
|
29
|
-
/** Generated inputs retained by committed target/draft rounds. The pending
|
|
30
|
-
* correction is excluded until a later round actually processes it. */
|
|
31
|
-
processed?: number[];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Binding owns graph/layout selection. The executor receives only the method
|
|
35
|
-
* key and lifecycle; sampling, checkpoints and numerical state remain ports. */
|
|
36
|
-
export function bindSpeculativeGroupRequests(model: RuntimeModel, provider: DraftProvider, depth: number) {
|
|
37
|
-
const binding = bindLegacySpeculativeModel(model, provider);
|
|
38
|
-
return (input: GenerateOptions): MlxGroupMethodRequest => {
|
|
39
|
-
const options = captureSpeculativeOptions(input);
|
|
40
|
-
return {
|
|
41
|
-
key: JSON.stringify(["speculative", provider.id, depth, options.kvBits ?? null,
|
|
42
|
-
options.kvGroupSize ?? 64, options.quantizedKvStart ?? null, options.turboQuant ?? null,
|
|
43
|
-
...(options.kvConfig?.length ? [options.kvConfig] : [])]),
|
|
44
|
-
data: options,
|
|
45
|
-
open: host => new SpeculativeGroup(host, model, provider, binding, depth),
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
class SpeculativeGroup implements MlxGroupedMethod {
|
|
51
|
-
#target: MlxStateRows<ReturnType<typeof targetCacheLayout>> | null = null;
|
|
52
|
-
#draft: DraftRowGroup | null = null;
|
|
53
|
-
readonly #requests = new Map<Row, RequestState>();
|
|
54
|
-
#steps = 0;
|
|
55
|
-
|
|
56
|
-
constructor(readonly host: MlxGroupMethodHost, readonly model: RuntimeModel,
|
|
57
|
-
readonly provider: DraftProvider, readonly binding: MlxSpeculativeBinding, readonly depth: number) {}
|
|
58
|
-
|
|
59
|
-
prepare(first: Row): MlxGroupPreparation {
|
|
60
|
-
const method = this;
|
|
61
|
-
const options = first.req.method!.data as GenerateOptions;
|
|
62
|
-
const maintain = createKvMaintenance(options);
|
|
63
|
-
interface Preparation extends MlxPrefillState {
|
|
64
|
-
request: RequestState;
|
|
65
|
-
end: number;
|
|
66
|
-
chunkSize: number;
|
|
67
|
-
pendingPrompt: boolean;
|
|
68
|
-
boundary: number;
|
|
69
|
-
transferred: boolean;
|
|
70
|
-
closed: boolean;
|
|
71
|
-
}
|
|
72
|
-
interface Ready {
|
|
73
|
-
row: Row;
|
|
74
|
-
request: RequestState;
|
|
75
|
-
caches: Cache[];
|
|
76
|
-
draft: DraftRowCheckpoint;
|
|
77
|
-
retain?: () => void;
|
|
78
|
-
transferred: boolean;
|
|
79
|
-
}
|
|
80
|
-
let prefix: DraftPrefillGroup | undefined;
|
|
81
|
-
let context: MlxArray | null = null;
|
|
82
|
-
const ready: Ready[] = [];
|
|
83
|
-
const closeReady = (state: Ready) => {
|
|
84
|
-
const caches = state.caches.splice(0), attachments = [state.draft.attachment];
|
|
85
|
-
const release = state.retain; state.retain = undefined;
|
|
86
|
-
disposeResources([...caches, { dispose: () => disposeAttachments(attachments) },
|
|
87
|
-
{ dispose: () => release?.() }, ...(!state.transferred ? [state.request.sampling] : [])]);
|
|
88
|
-
};
|
|
89
|
-
const capture = (state: Preparation, snapshot: () => Cache[], index: number) => {
|
|
90
|
-
let caches: Cache[] = [], attachments: CheckpointAttachment[] = [];
|
|
91
|
-
try {
|
|
92
|
-
caches = snapshot(); attachments.push(prefix!.capture(index).attachment);
|
|
93
|
-
method.host.promptCache!.put(state.row.req.promptIds.slice(0, state.pos), caches,
|
|
94
|
-
state.request.namespace, undefined, attachments);
|
|
95
|
-
caches = []; attachments = [];
|
|
96
|
-
} finally { disposeResources([...caches, { dispose: () => disposeAttachments(attachments) }]); }
|
|
97
|
-
};
|
|
98
|
-
const target = new MlxPrefillRows<Preparation>({
|
|
99
|
-
maintain,
|
|
100
|
-
open(row) {
|
|
101
|
-
const options = row.req.method!.data as GenerateOptions;
|
|
102
|
-
row.spec = { drafted: 0, accepted: 0, targetCalls: 0, rejected: 0, rounds: 0,
|
|
103
|
-
acceptanceLengths: [], tokensPerForward: 0, forwardsSaved: 0, draftedByPos: [], acceptedByPos: [] };
|
|
104
|
-
const sampler = makeSampler(options);
|
|
105
|
-
const request: RequestState = { draftSampling: sampler, namespace: "", prefixLength: 0,
|
|
106
|
-
processed: method.host.promptCache ? [] : undefined,
|
|
107
|
-
sampling: makeStepSampler(options, { tokenRepresentation: "number", grammarWait: "before-sample",
|
|
108
|
-
historyUpdate: "after-sample", initialHistory: row.req.promptIds, acceptGrammar: true,
|
|
109
|
-
eosTokenIds: row.req.eosTokenIds, captureSelectedLogprob: options.logprobs === true,
|
|
110
|
-
captureTopLogprobs: options.topLogprobs }) };
|
|
111
|
-
let caches: Cache[] = [], retained: (() => void) | undefined;
|
|
112
|
-
let appended = false;
|
|
113
|
-
const previous = prefix?.rowCount ?? 0;
|
|
114
|
-
try {
|
|
115
|
-
caches = method.binding.makeCache();
|
|
116
|
-
prefix ??= method.provider.grouped!.openPrefill({ target: bindLegacyDraftTarget(method.model, caches), checkpoints: [] });
|
|
117
|
-
const prompt = row.req.promptIds;
|
|
118
|
-
const pendingPrompt = prefix.prefillMode !== "full" && method.binding.prefillTailSplit && prompt.length > 1;
|
|
119
|
-
request.prefixLength = prompt.length - Number(pendingPrompt);
|
|
120
|
-
request.namespace = speculativePrefixNamespace(prefix.namespace, row.cacheNamespace ?? "", options);
|
|
121
|
-
const hit = method.host.promptCache?.take(prompt, request.namespace);
|
|
122
|
-
if (hit) {
|
|
123
|
-
try {
|
|
124
|
-
disposeResources(caches); caches = hit.caches.splice(0);
|
|
125
|
-
retained = hit.retain; hit.retain = undefined;
|
|
126
|
-
prefix.append([{ processedTokens: hit.tokens.length, attachment: hit.attachments![0]! }]);
|
|
127
|
-
appended = true;
|
|
128
|
-
// Target membership later releases backing leases after its own
|
|
129
|
-
// copies resolve. Settle companion copies under the same lease.
|
|
130
|
-
if (retained) prefix.materialize();
|
|
131
|
-
row.cachedTokens = hit.tokens.length;
|
|
132
|
-
} finally { disposeResources([...hit.caches, { dispose: () => disposeAttachments(hit.attachments) },
|
|
133
|
-
{ dispose: () => hit.retain?.() }]); }
|
|
134
|
-
} else { prefix.append([null]); appended = true; }
|
|
135
|
-
return { row, request, solo: caches, retain: retained, pos: row.cachedTokens,
|
|
136
|
-
end: request.prefixLength, pendingPrompt, transferred: false, closed: false,
|
|
137
|
-
chunkSize: options.prefillChunkSize ?? method.host.prefillChunkSize,
|
|
138
|
-
boundary: method.host.promptCache ? Math.min(row.req.snapshotAt ?? prompt.length, prompt.length - 1) : -1 };
|
|
139
|
-
} catch (error) {
|
|
140
|
-
return cleanupFailure(error, () => disposeResources([
|
|
141
|
-
{ dispose: () => { if (appended) prefix!.filterRows(Array.from({ length: previous }, (_, i) => i)); } },
|
|
142
|
-
...caches, request.sampling, { dispose: () => retained?.() },
|
|
143
|
-
]));
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
plan(state) {
|
|
147
|
-
const end = Math.min(state.pos + state.chunkSize, state.end, state.boundary > state.pos ? state.boundary : Infinity);
|
|
148
|
-
return { start: state.pos, end, kind: end === state.end ? "final" : "drain",
|
|
149
|
-
snapshot: end === state.boundary && end > state.row.cachedTokens, batchYield: true, maintain: true };
|
|
150
|
-
},
|
|
151
|
-
async forward(ids, caches) {
|
|
152
|
-
const taps = prefix!.tapLayers;
|
|
153
|
-
const output = await method.binding.forward(ids, caches, taps.length ? [...taps] : undefined);
|
|
154
|
-
context = output.ctxML;
|
|
155
|
-
return output.hidden;
|
|
156
|
-
},
|
|
157
|
-
afterForward(ids, _caches, _states, hidden) {
|
|
158
|
-
// Tapped providers consume their captured layers; assistant drafting
|
|
159
|
-
// consumes the true target hidden. Other providers ignore context.
|
|
160
|
-
const captured = context; context = null;
|
|
161
|
-
try {
|
|
162
|
-
const pending = prefix!.prefill(ids, captured ?? hidden);
|
|
163
|
-
if (pending) return pending.finally(() => captured?.dispose());
|
|
164
|
-
} catch (error) { captured?.dispose(); throw error; }
|
|
165
|
-
captured?.dispose();
|
|
166
|
-
},
|
|
167
|
-
project(hidden, _caches, completed) {
|
|
168
|
-
if (completed.every(state => state.pendingPrompt)) return null;
|
|
169
|
-
using last = hidden.slice([0, hidden.shape[1]! - 1, 0], [hidden.shape[0]!, hidden.shape[1]!, hidden.shape[2]!]);
|
|
170
|
-
return method.binding.projectLogits(last);
|
|
171
|
-
},
|
|
172
|
-
checkpoint: capture,
|
|
173
|
-
async complete(state, logits, index) {
|
|
174
|
-
const row = state.row;
|
|
175
|
-
row.spec!.targetCalls++;
|
|
176
|
-
if (state.pendingPrompt) { row.current = row.req.promptIds[state.end]!; row.generated = row.sampled = 0; }
|
|
177
|
-
else {
|
|
178
|
-
using scores = ops.reshape(logits!, [1, logits!.shape.at(-1)!]);
|
|
179
|
-
const sampled = await state.request.sampling.sample(scores, 0);
|
|
180
|
-
row.current = sampled.token; row.generated = row.sampled = 1;
|
|
181
|
-
if (row.req.eosTokenIds.includes(row.current)) {
|
|
182
|
-
if (method.host.promptCache) capture(state, () => cloneKvCaches(state.solo), index);
|
|
183
|
-
disposeResources(state.solo.splice(0)); state.retain?.(); state.retain = undefined;
|
|
184
|
-
method.host.finish(row, "stop"); return;
|
|
185
|
-
}
|
|
186
|
-
const more = await method.host.publish(row, row.current, readStepExtras(sampled.extras));
|
|
187
|
-
if (more === false || row.req.grammar?.isTerminated || row.generated >= row.req.maxTokens) {
|
|
188
|
-
if (method.host.promptCache && !row.req.signal?.aborted) capture(state, () => cloneKvCaches(state.solo), index);
|
|
189
|
-
disposeResources(state.solo.splice(0)); state.retain?.(); state.retain = undefined;
|
|
190
|
-
method.host.finish(row, more === false || row.req.grammar?.isTerminated ? "stop" : "length"); return;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
ready.push({ row, request: state.request, caches: state.solo, retain: state.retain,
|
|
194
|
-
draft: prefix!.capture(index), transferred: false });
|
|
195
|
-
state.transferred = true;
|
|
196
|
-
},
|
|
197
|
-
reject(row, error) { row.reject(error); },
|
|
198
|
-
close(state) {
|
|
199
|
-
if (state.closed) return;
|
|
200
|
-
state.closed = true;
|
|
201
|
-
if (!state.transferred) state.request.sampling.dispose();
|
|
202
|
-
},
|
|
203
|
-
filterRows(keep) { prefix!.filterRows(keep); },
|
|
204
|
-
dispose() {
|
|
205
|
-
const held = [prefix, context].filter(value => value != null);
|
|
206
|
-
prefix = undefined; context = null; disposeResources(held);
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
const preparation: MlxGroupPreparation = {
|
|
210
|
-
get rows() { return [...target.rows, ...ready.map(state => state.row)]; },
|
|
211
|
-
get canAdmit() { return target.canAdmit; },
|
|
212
|
-
get tokenWeight() { return target.tokenWeight + ready.reduce((sum, state) => sum + state.row.promptTokens - state.row.cachedTokens, 0); },
|
|
213
|
-
admit: row => target.admit(row),
|
|
214
|
-
advance: async () => {
|
|
215
|
-
// Publication returns to scheduling before prepared state joins active
|
|
216
|
-
// decode. This preserves the first-output flush boundary at every B.
|
|
217
|
-
if (ready.length) {
|
|
218
|
-
while (ready.length) {
|
|
219
|
-
const state = ready[0]!;
|
|
220
|
-
try {
|
|
221
|
-
if (state.row.req.signal?.aborted) {
|
|
222
|
-
state.row.reject(state.row.req.signal.reason);
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
maintain.prepareBatch?.(state.caches);
|
|
226
|
-
this.#target ??= new MlxStateRows(state.caches.map(targetCacheLayout));
|
|
227
|
-
this.#draft ??= this.provider.grouped!.open({ target: bindLegacyDraftTarget(this.model, this.#target.caches),
|
|
228
|
-
checkpoints: [], sampling: { sample: (lp, steps) => this.#sampleDraftRows(lp, steps) } });
|
|
229
|
-
applyStateChanges([() => this.#target!.prepareAppend(state.caches),
|
|
230
|
-
() => this.#draft!.prepareAppend([state.draft]), () => ({ commit: () => {
|
|
231
|
-
state.request.retain = state.retain; state.retain = undefined;
|
|
232
|
-
this.#requests.set(state.row, state.request); state.transferred = true;
|
|
233
|
-
this.host.join(state.row);
|
|
234
|
-
}, dispose() {} })]);
|
|
235
|
-
} finally { ready.shift(); closeReady(state); }
|
|
236
|
-
}
|
|
237
|
-
return target.rows.length === 0;
|
|
238
|
-
}
|
|
239
|
-
const done = await target.advance();
|
|
240
|
-
return done && ready.length === 0;
|
|
241
|
-
},
|
|
242
|
-
dispose() {
|
|
243
|
-
const held = ready.splice(0);
|
|
244
|
-
disposeResources([target, ...held.map(state => ({ dispose: () => closeReady(state) }))]);
|
|
245
|
-
},
|
|
246
|
-
};
|
|
247
|
-
try { target.admit(first); return preparation; }
|
|
248
|
-
catch (error) { return cleanupFailure(error, () => preparation.dispose()); }
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
#sampleDraftRows(logprobs: MlxArray, steps: readonly number[]): MlxArray {
|
|
252
|
-
const tokens: MlxArray[] = [];
|
|
253
|
-
try {
|
|
254
|
-
for (let row = 0; row < this.host.rows.length; row++) {
|
|
255
|
-
using scores = logprobs.slice([row, 0], [row + 1, logprobs.shape[1]!]);
|
|
256
|
-
tokens.push(this.#requests.get(this.host.rows[row]!)!.draftSampling(scores, steps[row]!));
|
|
257
|
-
}
|
|
258
|
-
return ops.concatAxis(tokens, 0);
|
|
259
|
-
} finally { disposeResources(tokens); }
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
async advance(): Promise<void> {
|
|
263
|
-
const active = [...this.host.rows];
|
|
264
|
-
const live = active.flatMap((row, index) => row.req.signal?.aborted ? [] : [index]);
|
|
265
|
-
if (live.length !== active.length) {
|
|
266
|
-
for (const row of active) if (row.req.signal?.aborted) row.reject(row.req.signal.reason);
|
|
267
|
-
this.host.filterRows(live);
|
|
268
|
-
}
|
|
269
|
-
const rows = [...this.host.rows];
|
|
270
|
-
if (!rows.length) return;
|
|
271
|
-
const depth = Math.min(this.depth, Math.max(...rows.map(row => row.req.maxTokens - row.generated)));
|
|
272
|
-
const halted = new Set<Row>();
|
|
273
|
-
const pin = this.binding.pinVerify?.();
|
|
274
|
-
try {
|
|
275
|
-
const completed = await advanceSpeculativeOutputs(rows.map(row => ({ pending: row.current,
|
|
276
|
-
step: row.sampled, remaining: row.req.maxTokens - row.generated, eosTokenIds: row.req.eosTokenIds,
|
|
277
|
-
sampling: this.#requests.get(row)!.sampling, grammarDone: () => row.req.grammar?.isTerminated === true,
|
|
278
|
-
output: { commit: async (ids, metadata) => {
|
|
279
|
-
row.generated++;
|
|
280
|
-
const more = await this.host.publish(row, ids[0]!, metadata?.[0]);
|
|
281
|
-
if (more === false) { halted.add(row); return false; }
|
|
282
|
-
} },
|
|
283
|
-
})), depth, this.#draft!, {
|
|
284
|
-
transaction: bindRowCacheRollback(this.#target!.caches, rows.length),
|
|
285
|
-
forward: async ids => {
|
|
286
|
-
const taps = this.#draft!.tapLayers;
|
|
287
|
-
const result = await this.binding.forward(ids, this.#target!.caches, taps.length ? [...taps] : undefined);
|
|
288
|
-
const context = result.ctxML ?? result.hidden;
|
|
289
|
-
try { return { logits: this.binding.projectLogits(result.hidden), context }; }
|
|
290
|
-
catch (error) { context.dispose(); throw error; }
|
|
291
|
-
finally { if (result.ctxML) result.hidden.dispose(); }
|
|
292
|
-
},
|
|
293
|
-
});
|
|
294
|
-
const keep: number[] = [];
|
|
295
|
-
for (let index = 0; index < rows.length; index++) {
|
|
296
|
-
const row = rows[index]!, output = completed.outputs[index]!, round = completed.rounds[index]!;
|
|
297
|
-
const request = this.#requests.get(row)!;
|
|
298
|
-
if (output.kind !== "failed" && output.kind !== "cancelled")
|
|
299
|
-
request.processed?.push(row.current, ...round.drafts.slice(0, output.accepted));
|
|
300
|
-
const stats = row.spec!;
|
|
301
|
-
stats.drafted += round.drafts.length;
|
|
302
|
-
stats.accepted += round.acceptance.accepted;
|
|
303
|
-
stats.rejected = stats.drafted - stats.accepted;
|
|
304
|
-
stats.rounds!++; stats.targetCalls++;
|
|
305
|
-
stats.acceptanceLengths!.push(round.acceptance.accepted);
|
|
306
|
-
for (let p = 0; p < round.drafts.length; p++) stats.draftedByPos![p] = (stats.draftedByPos![p] ?? 0) + 1;
|
|
307
|
-
for (let p = 0; p < round.acceptance.accepted; p++) stats.acceptedByPos![p] = (stats.acceptedByPos![p] ?? 0) + 1;
|
|
308
|
-
row.sampled += round.acceptance.emitted.length + Number(round.acceptance.sawEos);
|
|
309
|
-
// A consumer may stop inside a verified burst before its terminal EOS.
|
|
310
|
-
if (output.kind === "stop" && !halted.has(row) && round.acceptance.sawEos &&
|
|
311
|
-
output.generated === round.acceptance.emitted.length && row.generated < row.req.maxTokens)
|
|
312
|
-
row.generated++;
|
|
313
|
-
stats.tokensPerForward = row.generated / stats.rounds!;
|
|
314
|
-
stats.forwardsSaved = Math.max(0, row.generated - 1 - stats.rounds!);
|
|
315
|
-
if (output.kind === "continue") { row.current = output.pending; keep.push(index); }
|
|
316
|
-
else if (output.kind === "failed") row.reject(output.error);
|
|
317
|
-
else if (output.kind === "cancelled") row.reject(row.req.signal?.reason ?? new Error(output.reason));
|
|
318
|
-
else {
|
|
319
|
-
if (!row.req.signal?.aborted) this.#publishCheckpoint(row, index, request);
|
|
320
|
-
this.host.finish(row, output.kind);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if (keep.length !== rows.length) this.host.filterRows(keep);
|
|
324
|
-
if (++this.#steps % 256 === 0) clearCache();
|
|
325
|
-
} finally { pin?.close(); }
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/** The method aligns token coverage and captures its state. The cache owns
|
|
329
|
-
* RAM retention and eventual SSD persistence; no storage work is awaited. */
|
|
330
|
-
#publishCheckpoint(row: Row, index: number, request: RequestState): void {
|
|
331
|
-
if (!this.host.promptCache || !request.processed) return;
|
|
332
|
-
let target: Cache[] = [], attachments: CheckpointAttachment[] = [];
|
|
333
|
-
try {
|
|
334
|
-
target = this.#target!.extractRow(index);
|
|
335
|
-
attachments.push(this.#draft!.capture(index).attachment);
|
|
336
|
-
this.host.promptCache.put([...row.req.promptIds.slice(0, request.prefixLength), ...request.processed], target,
|
|
337
|
-
request.namespace, undefined, attachments);
|
|
338
|
-
target = []; attachments = [];
|
|
339
|
-
} finally { disposeResources([...target, { dispose: () => disposeAttachments(attachments) }]); }
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
filterRows(keep: readonly number[], _discard: boolean): void {
|
|
343
|
-
this.#target?.filterRows(keep); this.#draft?.filterRows(keep);
|
|
344
|
-
const retained = new Set(keep.map(index => this.host.rows[index]!));
|
|
345
|
-
const releases: { dispose(): void }[] = [];
|
|
346
|
-
for (const [row, request] of this.#requests) if (!retained.has(row)) {
|
|
347
|
-
this.#requests.delete(row);
|
|
348
|
-
releases.push(request.sampling, { dispose: () => request.retain?.() });
|
|
349
|
-
}
|
|
350
|
-
disposeResources(releases);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
dispose(): void {
|
|
354
|
-
const resources = [...(this.#target ? [this.#target] : []), ...(this.#draft ? [this.#draft] : []),
|
|
355
|
-
...[...this.#requests.values()].flatMap(request => [request.sampling, { dispose: () => request.retain?.() }])];
|
|
356
|
-
this.#target = null; this.#draft = null; this.#requests.clear();
|
|
357
|
-
disposeResources(resources);
|
|
358
|
-
}
|
|
359
|
-
}
|