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
package/src/hf-push.ts
DELETED
|
@@ -1,628 +0,0 @@
|
|
|
1
|
-
// Native Hugging Face push-to-hub — no Python, no huggingface_hub.
|
|
2
|
-
//
|
|
3
|
-
// Uploads a local directory (a quantized model dir, a LoRA adapter dir, or
|
|
4
|
-
// a dataset dir) to the Hub by speaking the same HTTP protocol the official
|
|
5
|
-
// client uses:
|
|
6
|
-
//
|
|
7
|
-
// 1. POST {base}/api/repos/create — create the repo (exist_ok)
|
|
8
|
-
// 2. POST {base}/api/{models|datasets}/<repo>/preupload/<rev>
|
|
9
|
-
// — learn which files are LFS
|
|
10
|
-
// 3. POST {base}/<prefix><repo>.git/info/lfs/objects/batch
|
|
11
|
-
// + PUT to the returned S3 href — upload LFS blobs
|
|
12
|
-
// (+ optional POST to a `verify` href)
|
|
13
|
-
// 4. POST {base}/api/{models|datasets}/<repo>/commit/<rev>
|
|
14
|
-
// — NDJSON commit (header +
|
|
15
|
-
// regular `file` + `lfsFile`)
|
|
16
|
-
//
|
|
17
|
-
// This is the UX contract the optiq Lab routes expect ({repo_id, private}
|
|
18
|
-
// → create repo, upload folder, return {ok, url}) minus the Fernet
|
|
19
|
-
// password-derived token store: we keep a single plain write token at
|
|
20
|
-
// ~/.mlx-bun/hf.json (mode 0600). See the module note on saveHfToken.
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
mkdirSync,
|
|
24
|
-
readFileSync,
|
|
25
|
-
writeFileSync,
|
|
26
|
-
chmodSync,
|
|
27
|
-
statSync,
|
|
28
|
-
readdirSync,
|
|
29
|
-
existsSync,
|
|
30
|
-
} from "node:fs";
|
|
31
|
-
import { join, relative, sep } from "node:path";
|
|
32
|
-
import { homedir } from "node:os";
|
|
33
|
-
|
|
34
|
-
/** Home dir, honoring $HOME at call time (node:os homedir() caches the
|
|
35
|
-
* password-DB value at startup and ignores runtime $HOME changes on
|
|
36
|
-
* macOS). Matches src/download.ts, which reads process.env.HOME. */
|
|
37
|
-
function home(): string {
|
|
38
|
-
return process.env.HOME || homedir();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const DEFAULT_BASE = "https://huggingface.co";
|
|
42
|
-
|
|
43
|
-
// HF's default .gitattributes promotes these to LFS regardless of size, plus
|
|
44
|
-
// anything over the size threshold. Mirrors huggingface_hub's defaults.
|
|
45
|
-
const LFS_SUFFIXES = [
|
|
46
|
-
".safetensors",
|
|
47
|
-
".bin",
|
|
48
|
-
".gguf",
|
|
49
|
-
".pt",
|
|
50
|
-
".pth",
|
|
51
|
-
".ckpt",
|
|
52
|
-
".onnx",
|
|
53
|
-
".npz",
|
|
54
|
-
".npy",
|
|
55
|
-
".h5",
|
|
56
|
-
".tflite",
|
|
57
|
-
".msgpack",
|
|
58
|
-
".arrow",
|
|
59
|
-
".parquet",
|
|
60
|
-
".pickle",
|
|
61
|
-
".pkl",
|
|
62
|
-
".model",
|
|
63
|
-
".tar",
|
|
64
|
-
".tar.gz",
|
|
65
|
-
".tgz",
|
|
66
|
-
".zip",
|
|
67
|
-
".gz",
|
|
68
|
-
".7z",
|
|
69
|
-
".bz2",
|
|
70
|
-
".xz",
|
|
71
|
-
".zst",
|
|
72
|
-
".mp3",
|
|
73
|
-
".wav",
|
|
74
|
-
".flac",
|
|
75
|
-
".ogg",
|
|
76
|
-
".mp4",
|
|
77
|
-
".webm",
|
|
78
|
-
".tif",
|
|
79
|
-
".tiff",
|
|
80
|
-
".png",
|
|
81
|
-
".jpg",
|
|
82
|
-
".jpeg",
|
|
83
|
-
".webp",
|
|
84
|
-
];
|
|
85
|
-
const LFS_SIZE_THRESHOLD = 10 * 1024 * 1024; // ~10 MB
|
|
86
|
-
|
|
87
|
-
export type RepoType = "model" | "dataset";
|
|
88
|
-
|
|
89
|
-
export interface HfTokenFile {
|
|
90
|
-
token: string;
|
|
91
|
-
savedAt: string;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface UploadOptions {
|
|
95
|
-
repoType?: RepoType;
|
|
96
|
-
private?: boolean;
|
|
97
|
-
token?: string | null;
|
|
98
|
-
commitMessage?: string;
|
|
99
|
-
/** Optional glob-free prefix/substring allowlist; if set, only files whose
|
|
100
|
-
* repo path includes one of these substrings are uploaded. */
|
|
101
|
-
allowPatterns?: string[];
|
|
102
|
-
/** Override the Hub base URL — tests point this at a local mock. */
|
|
103
|
-
baseUrl?: string;
|
|
104
|
-
/** Per-file progress: (repoPath, bytesSent, bytesTotal). */
|
|
105
|
-
onProgress?: (file: string, sent: number, total: number) => void;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface UploadResult {
|
|
109
|
-
ok: true;
|
|
110
|
-
url: string;
|
|
111
|
-
commitOid?: string;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// ---------------------------------------------------------------------------
|
|
115
|
-
// Token storage
|
|
116
|
-
// ---------------------------------------------------------------------------
|
|
117
|
-
|
|
118
|
-
function tokenPath(): string {
|
|
119
|
-
return join(home(), ".mlx-bun", "hf.json");
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Persist a plain HF write token to ~/.mlx-bun/hf.json (mode 0600).
|
|
124
|
-
*
|
|
125
|
-
* NOTE — simplification vs optiq's encrypted store: optiq encrypts the
|
|
126
|
-
* token at rest with a Fernet key derived from the Lab password (so a
|
|
127
|
-
* stolen DB is useless without the password). We store the token in
|
|
128
|
-
* plaintext, protected only by file permissions. The threat model for
|
|
129
|
-
* mlx-bun is a single local user on their own machine; if you need
|
|
130
|
-
* encryption-at-rest, prefer the env var / shared HF cache fallbacks.
|
|
131
|
-
*/
|
|
132
|
-
export function saveHfToken(token: string): void {
|
|
133
|
-
const t = (token ?? "").trim();
|
|
134
|
-
if (!t) throw new Error("saveHfToken: token is empty");
|
|
135
|
-
const dir = join(home(), ".mlx-bun");
|
|
136
|
-
mkdirSync(dir, { recursive: true });
|
|
137
|
-
const path = tokenPath();
|
|
138
|
-
const body: HfTokenFile = { token: t, savedAt: new Date().toISOString() };
|
|
139
|
-
writeFileSync(path, JSON.stringify(body, null, 2) + "\n", { mode: 0o600 });
|
|
140
|
-
// writeFileSync mode is masked by umask on create; force it.
|
|
141
|
-
chmodSync(path, 0o600);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Resolve an HF token, in priority order:
|
|
146
|
-
* 1. the token we stored (~/.mlx-bun/hf.json)
|
|
147
|
-
* 2. $HF_TOKEN
|
|
148
|
-
* 3. the standard huggingface_hub cache token (~/.cache/huggingface/token)
|
|
149
|
-
* Returns null if none is found.
|
|
150
|
-
*/
|
|
151
|
-
export function getHfToken(): string | null {
|
|
152
|
-
try {
|
|
153
|
-
const raw = readFileSync(tokenPath(), "utf8");
|
|
154
|
-
const parsed = JSON.parse(raw) as Partial<HfTokenFile>;
|
|
155
|
-
if (parsed.token && parsed.token.trim()) return parsed.token.trim();
|
|
156
|
-
} catch {
|
|
157
|
-
// fall through to env / cache
|
|
158
|
-
}
|
|
159
|
-
if (process.env.HF_TOKEN && process.env.HF_TOKEN.trim()) {
|
|
160
|
-
return process.env.HF_TOKEN.trim();
|
|
161
|
-
}
|
|
162
|
-
try {
|
|
163
|
-
const cache = join(home(), ".cache", "huggingface", "token");
|
|
164
|
-
const t = readFileSync(cache, "utf8").trim();
|
|
165
|
-
if (t) return t;
|
|
166
|
-
} catch {
|
|
167
|
-
// none available
|
|
168
|
-
}
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** True if a token is resolvable from any source (for settings UI). */
|
|
173
|
-
export function hasHfToken(): boolean {
|
|
174
|
-
return getHfToken() !== null;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// ---------------------------------------------------------------------------
|
|
178
|
-
// HTTP helpers
|
|
179
|
-
// ---------------------------------------------------------------------------
|
|
180
|
-
|
|
181
|
-
function authHeaders(token: string | null | undefined): Record<string, string> {
|
|
182
|
-
return token ? { authorization: `Bearer ${token}` } : {};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/** Turn a transport-level HTTP failure into a clear, actionable error. */
|
|
186
|
-
async function httpError(action: string, res: Response): Promise<Error> {
|
|
187
|
-
let detail = "";
|
|
188
|
-
try {
|
|
189
|
-
detail = (await res.text()).slice(0, 300);
|
|
190
|
-
} catch {
|
|
191
|
-
/* ignore */
|
|
192
|
-
}
|
|
193
|
-
const hints: Record<number, string> = {
|
|
194
|
-
401: "unauthorized — your HF token is missing, invalid, or expired (need a *write* token)",
|
|
195
|
-
403: "forbidden — the token lacks write access to this repo/org, or the repo is gated",
|
|
196
|
-
404: "not found — check the repo id and that you can write to that namespace",
|
|
197
|
-
};
|
|
198
|
-
const hint = hints[res.status];
|
|
199
|
-
return new Error(
|
|
200
|
-
`${action} failed (HTTP ${res.status}${hint ? `: ${hint}` : ""})` +
|
|
201
|
-
(detail ? `: ${detail}` : ""),
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// ---------------------------------------------------------------------------
|
|
206
|
-
// Repo type → URL prefix
|
|
207
|
-
// ---------------------------------------------------------------------------
|
|
208
|
-
|
|
209
|
-
/** API path segment: models live at /api/models/..., datasets at
|
|
210
|
-
* /api/datasets/... (spaces would be /api/spaces/, unused here). */
|
|
211
|
-
function apiPrefix(repoType: RepoType): string {
|
|
212
|
-
return repoType === "dataset" ? "datasets" : "models";
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/** git/LFS URL prefix: models have no prefix, datasets are under datasets/. */
|
|
216
|
-
function gitPrefix(repoType: RepoType): string {
|
|
217
|
-
return repoType === "dataset" ? "datasets/" : "";
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// ---------------------------------------------------------------------------
|
|
221
|
-
// 1. Create repo
|
|
222
|
-
// ---------------------------------------------------------------------------
|
|
223
|
-
|
|
224
|
-
export interface CreateRepoOptions {
|
|
225
|
-
repoType?: RepoType;
|
|
226
|
-
private?: boolean;
|
|
227
|
-
token?: string | null;
|
|
228
|
-
baseUrl?: string;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Create a Hub repo. Idempotent: an "already exists / 409" response is
|
|
233
|
-
* treated as success so callers can always create-then-push.
|
|
234
|
-
*/
|
|
235
|
-
export async function createRepo(
|
|
236
|
-
repoId: string,
|
|
237
|
-
opts: CreateRepoOptions = {},
|
|
238
|
-
): Promise<{ url: string }> {
|
|
239
|
-
const base = opts.baseUrl ?? DEFAULT_BASE;
|
|
240
|
-
const repoType = opts.repoType ?? "model";
|
|
241
|
-
const token = opts.token === undefined ? getHfToken() : opts.token;
|
|
242
|
-
|
|
243
|
-
// repoId may be "org/name" or just "name" (lands under the token's user).
|
|
244
|
-
const slash = repoId.indexOf("/");
|
|
245
|
-
const organization = slash >= 0 ? repoId.slice(0, slash) : undefined;
|
|
246
|
-
const name = slash >= 0 ? repoId.slice(slash + 1) : repoId;
|
|
247
|
-
|
|
248
|
-
const body: Record<string, unknown> = {
|
|
249
|
-
type: repoType,
|
|
250
|
-
name,
|
|
251
|
-
private: opts.private ?? false,
|
|
252
|
-
};
|
|
253
|
-
if (organization) body.organization = organization;
|
|
254
|
-
|
|
255
|
-
const res = await fetch(`${base}/api/repos/create`, {
|
|
256
|
-
method: "POST",
|
|
257
|
-
headers: { "content-type": "application/json", ...authHeaders(token) },
|
|
258
|
-
body: JSON.stringify(body),
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
if (res.ok) {
|
|
262
|
-
let json: { url?: string } = {};
|
|
263
|
-
try {
|
|
264
|
-
json = (await res.json()) as { url?: string };
|
|
265
|
-
} catch {
|
|
266
|
-
/* some servers return empty body */
|
|
267
|
-
}
|
|
268
|
-
return { url: json.url ?? `${base}/${repoType === "dataset" ? "datasets/" : ""}${repoId}` };
|
|
269
|
-
}
|
|
270
|
-
// Already-exists is fine (HF returns 409 with a message we can detect).
|
|
271
|
-
if (res.status === 409) {
|
|
272
|
-
return { url: `${base}/${repoType === "dataset" ? "datasets/" : ""}${repoId}` };
|
|
273
|
-
}
|
|
274
|
-
throw await httpError("create repo", res);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// ---------------------------------------------------------------------------
|
|
278
|
-
// File walking + LFS classification
|
|
279
|
-
// ---------------------------------------------------------------------------
|
|
280
|
-
|
|
281
|
-
interface LocalFile {
|
|
282
|
-
/** absolute path on disk */
|
|
283
|
-
abs: string;
|
|
284
|
-
/** forward-slash repo-relative path */
|
|
285
|
-
repoPath: string;
|
|
286
|
-
size: number;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function walkDir(dir: string): LocalFile[] {
|
|
290
|
-
const out: LocalFile[] = [];
|
|
291
|
-
const recurse = (cur: string) => {
|
|
292
|
-
for (const entry of readdirSync(cur, { withFileTypes: true })) {
|
|
293
|
-
// Skip VCS / hidden cruft that would never belong in a push.
|
|
294
|
-
if (entry.name === ".git" || entry.name === ".cache") continue;
|
|
295
|
-
const abs = join(cur, entry.name);
|
|
296
|
-
if (entry.isDirectory()) {
|
|
297
|
-
recurse(abs);
|
|
298
|
-
} else if (entry.isFile()) {
|
|
299
|
-
const st = statSync(abs);
|
|
300
|
-
out.push({
|
|
301
|
-
abs,
|
|
302
|
-
repoPath: relative(dir, abs).split(sep).join("/"),
|
|
303
|
-
size: st.size,
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
recurse(dir);
|
|
309
|
-
return out;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
function isLfs(file: LocalFile): boolean {
|
|
313
|
-
const lower = file.repoPath.toLowerCase();
|
|
314
|
-
if (LFS_SUFFIXES.some((s) => lower.endsWith(s))) return true;
|
|
315
|
-
return file.size >= LFS_SIZE_THRESHOLD;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function sha256Hex(bytes: Uint8Array): string {
|
|
319
|
-
return new Bun.CryptoHasher("sha256").update(bytes).digest("hex");
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// ---------------------------------------------------------------------------
|
|
323
|
-
// 2. Preupload
|
|
324
|
-
// ---------------------------------------------------------------------------
|
|
325
|
-
|
|
326
|
-
interface PreuploadEntry {
|
|
327
|
-
path: string;
|
|
328
|
-
uploadMode: "lfs" | "regular";
|
|
329
|
-
shouldIgnore?: boolean;
|
|
330
|
-
oid?: string | null;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
async function preupload(
|
|
334
|
-
base: string,
|
|
335
|
-
repoId: string,
|
|
336
|
-
repoType: RepoType,
|
|
337
|
-
revision: string,
|
|
338
|
-
files: { file: LocalFile; sample: Uint8Array }[],
|
|
339
|
-
token: string | null,
|
|
340
|
-
): Promise<Map<string, PreuploadEntry>> {
|
|
341
|
-
const url = `${base}/api/${apiPrefix(repoType)}/${repoId}/preupload/${encodeURIComponent(revision)}`;
|
|
342
|
-
const res = await fetch(url, {
|
|
343
|
-
method: "POST",
|
|
344
|
-
headers: { "content-type": "application/json", ...authHeaders(token) },
|
|
345
|
-
body: JSON.stringify({
|
|
346
|
-
files: files.map(({ file, sample }) => ({
|
|
347
|
-
path: file.repoPath,
|
|
348
|
-
sample: Buffer.from(sample).toString("base64"),
|
|
349
|
-
size: file.size,
|
|
350
|
-
})),
|
|
351
|
-
}),
|
|
352
|
-
});
|
|
353
|
-
if (!res.ok) throw await httpError("preupload", res);
|
|
354
|
-
const json = (await res.json()) as { files?: PreuploadEntry[] };
|
|
355
|
-
const map = new Map<string, PreuploadEntry>();
|
|
356
|
-
for (const e of json.files ?? []) map.set(e.path, e);
|
|
357
|
-
return map;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// ---------------------------------------------------------------------------
|
|
361
|
-
// 3. LFS upload (batch → PUT → optional verify)
|
|
362
|
-
// ---------------------------------------------------------------------------
|
|
363
|
-
|
|
364
|
-
interface LfsAction {
|
|
365
|
-
href: string;
|
|
366
|
-
header?: Record<string, string>;
|
|
367
|
-
}
|
|
368
|
-
interface LfsObject {
|
|
369
|
-
oid: string;
|
|
370
|
-
size: number;
|
|
371
|
-
actions?: { upload?: LfsAction; verify?: LfsAction } | null;
|
|
372
|
-
error?: { code: number; message: string };
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
async function uploadLfsFiles(
|
|
376
|
-
base: string,
|
|
377
|
-
repoId: string,
|
|
378
|
-
repoType: RepoType,
|
|
379
|
-
revision: string,
|
|
380
|
-
items: { file: LocalFile; oid: string; bytes: Uint8Array }[],
|
|
381
|
-
token: string | null,
|
|
382
|
-
onProgress?: UploadOptions["onProgress"],
|
|
383
|
-
): Promise<void> {
|
|
384
|
-
if (items.length === 0) return;
|
|
385
|
-
|
|
386
|
-
const batchUrl = `${base}/${gitPrefix(repoType)}${repoId}.git/info/lfs/objects/batch`;
|
|
387
|
-
const batchRes = await fetch(batchUrl, {
|
|
388
|
-
method: "POST",
|
|
389
|
-
headers: {
|
|
390
|
-
accept: "application/vnd.git-lfs+json",
|
|
391
|
-
"content-type": "application/vnd.git-lfs+json",
|
|
392
|
-
...authHeaders(token),
|
|
393
|
-
},
|
|
394
|
-
body: JSON.stringify({
|
|
395
|
-
operation: "upload",
|
|
396
|
-
transfers: ["basic"], // we implement the simple single-PUT transfer
|
|
397
|
-
hash_algo: "sha256",
|
|
398
|
-
ref: { name: revision },
|
|
399
|
-
objects: items.map((i) => ({ oid: i.oid, size: i.file.size })),
|
|
400
|
-
}),
|
|
401
|
-
});
|
|
402
|
-
if (!batchRes.ok) throw await httpError("LFS batch", batchRes);
|
|
403
|
-
const batch = (await batchRes.json()) as { objects?: LfsObject[] };
|
|
404
|
-
|
|
405
|
-
const byOid = new Map(items.map((i) => [i.oid, i]));
|
|
406
|
-
for (const obj of batch.objects ?? []) {
|
|
407
|
-
if (obj.error) {
|
|
408
|
-
throw new Error(`LFS batch error for ${obj.oid}: ${obj.error.message} (code ${obj.error.code})`);
|
|
409
|
-
}
|
|
410
|
-
const item = byOid.get(obj.oid);
|
|
411
|
-
if (!item) continue;
|
|
412
|
-
|
|
413
|
-
// No upload action = the blob already exists upstream; skip the PUT.
|
|
414
|
-
const upload = obj.actions?.upload;
|
|
415
|
-
if (!upload) {
|
|
416
|
-
onProgress?.(item.file.repoPath, item.file.size, item.file.size);
|
|
417
|
-
continue;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const putRes = await fetch(upload.href, {
|
|
421
|
-
method: "PUT",
|
|
422
|
-
headers: { ...(upload.header ?? {}) },
|
|
423
|
-
body: new Blob([Uint8Array.from(item.bytes)]),
|
|
424
|
-
});
|
|
425
|
-
if (!putRes.ok) throw await httpError(`LFS upload of ${item.file.repoPath}`, putRes);
|
|
426
|
-
onProgress?.(item.file.repoPath, item.file.size, item.file.size);
|
|
427
|
-
|
|
428
|
-
// Optional verify step (S3 transfers often request it).
|
|
429
|
-
const verify = obj.actions?.verify;
|
|
430
|
-
if (verify) {
|
|
431
|
-
const vRes = await fetch(verify.href, {
|
|
432
|
-
method: "POST",
|
|
433
|
-
headers: {
|
|
434
|
-
"content-type": "application/vnd.git-lfs+json",
|
|
435
|
-
...(verify.header ?? {}),
|
|
436
|
-
...authHeaders(token),
|
|
437
|
-
},
|
|
438
|
-
body: JSON.stringify({ oid: obj.oid, size: item.file.size }),
|
|
439
|
-
});
|
|
440
|
-
if (!vRes.ok) throw await httpError(`LFS verify of ${item.file.repoPath}`, vRes);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// ---------------------------------------------------------------------------
|
|
446
|
-
// 4. Commit (NDJSON)
|
|
447
|
-
// ---------------------------------------------------------------------------
|
|
448
|
-
|
|
449
|
-
async function commit(
|
|
450
|
-
base: string,
|
|
451
|
-
repoId: string,
|
|
452
|
-
repoType: RepoType,
|
|
453
|
-
revision: string,
|
|
454
|
-
message: string,
|
|
455
|
-
regularFiles: { file: LocalFile; bytes: Uint8Array }[],
|
|
456
|
-
lfsFiles: { file: LocalFile; oid: string }[],
|
|
457
|
-
token: string | null,
|
|
458
|
-
): Promise<{ commitOid?: string; commitUrl?: string }> {
|
|
459
|
-
const lines: string[] = [];
|
|
460
|
-
lines.push(
|
|
461
|
-
JSON.stringify({
|
|
462
|
-
key: "header",
|
|
463
|
-
value: { summary: message, description: "" },
|
|
464
|
-
}),
|
|
465
|
-
);
|
|
466
|
-
for (const { file, bytes } of regularFiles) {
|
|
467
|
-
lines.push(
|
|
468
|
-
JSON.stringify({
|
|
469
|
-
key: "file",
|
|
470
|
-
value: {
|
|
471
|
-
path: file.repoPath,
|
|
472
|
-
encoding: "base64",
|
|
473
|
-
content: Buffer.from(bytes).toString("base64"),
|
|
474
|
-
},
|
|
475
|
-
}),
|
|
476
|
-
);
|
|
477
|
-
}
|
|
478
|
-
for (const { file, oid } of lfsFiles) {
|
|
479
|
-
lines.push(
|
|
480
|
-
JSON.stringify({
|
|
481
|
-
key: "lfsFile",
|
|
482
|
-
value: {
|
|
483
|
-
path: file.repoPath,
|
|
484
|
-
algo: "sha256",
|
|
485
|
-
oid,
|
|
486
|
-
size: file.size,
|
|
487
|
-
},
|
|
488
|
-
}),
|
|
489
|
-
);
|
|
490
|
-
}
|
|
491
|
-
const ndjson = lines.join("\n") + "\n";
|
|
492
|
-
|
|
493
|
-
const url = `${base}/api/${apiPrefix(repoType)}/${repoId}/commit/${encodeURIComponent(revision)}`;
|
|
494
|
-
const res = await fetch(url, {
|
|
495
|
-
method: "POST",
|
|
496
|
-
headers: {
|
|
497
|
-
"content-type": "application/x-ndjson",
|
|
498
|
-
...authHeaders(token),
|
|
499
|
-
},
|
|
500
|
-
body: ndjson,
|
|
501
|
-
});
|
|
502
|
-
if (!res.ok) throw await httpError("commit", res);
|
|
503
|
-
let json: { commitOid?: string; commitUrl?: string } = {};
|
|
504
|
-
try {
|
|
505
|
-
json = (await res.json()) as { commitOid?: string; commitUrl?: string };
|
|
506
|
-
} catch {
|
|
507
|
-
/* empty body is acceptable */
|
|
508
|
-
}
|
|
509
|
-
return json;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// ---------------------------------------------------------------------------
|
|
513
|
-
// Public: uploadFolder
|
|
514
|
-
// ---------------------------------------------------------------------------
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* Upload a local directory to the Hub as a model or dataset repo.
|
|
518
|
-
*
|
|
519
|
-
* Walks `dir`, classifies each file as LFS (large or a binary suffix per
|
|
520
|
-
* HF's default gitattributes) vs regular, runs preupload to confirm the
|
|
521
|
-
* server's verdict, uploads LFS blobs via the LFS batch + PUT flow, then
|
|
522
|
-
* posts a single NDJSON commit (regular files inlined as base64, LFS files
|
|
523
|
-
* referenced by oid/size). Creates the repo first (idempotent).
|
|
524
|
-
*/
|
|
525
|
-
export async function uploadFolder(
|
|
526
|
-
dir: string,
|
|
527
|
-
repoId: string,
|
|
528
|
-
opts: UploadOptions = {},
|
|
529
|
-
): Promise<UploadResult> {
|
|
530
|
-
const base = opts.baseUrl ?? DEFAULT_BASE;
|
|
531
|
-
const repoType = opts.repoType ?? "model";
|
|
532
|
-
const revision = "main";
|
|
533
|
-
const token = opts.token === undefined ? getHfToken() : opts.token;
|
|
534
|
-
const message = opts.commitMessage ?? "Upload with mlx-bun";
|
|
535
|
-
|
|
536
|
-
if (!existsSync(dir) || !statSync(dir).isDirectory()) {
|
|
537
|
-
throw new Error(`uploadFolder: not a directory: ${dir}`);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// Discover + filter files.
|
|
541
|
-
let files = walkDir(dir);
|
|
542
|
-
if (opts.allowPatterns && opts.allowPatterns.length > 0) {
|
|
543
|
-
const pats = opts.allowPatterns;
|
|
544
|
-
files = files.filter((f) => pats.some((p) => f.repoPath.includes(p)));
|
|
545
|
-
}
|
|
546
|
-
if (files.length === 0) {
|
|
547
|
-
throw new Error(`uploadFolder: no files to upload in ${dir}`);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
// Create the repo (idempotent) before any upload.
|
|
551
|
-
await createRepo(repoId, {
|
|
552
|
-
repoType,
|
|
553
|
-
private: opts.private,
|
|
554
|
-
token,
|
|
555
|
-
baseUrl: base,
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
// Read bytes + compute the LFS sha256 oids; build the preupload samples
|
|
559
|
-
// (first 512 bytes, what huggingface_hub sends).
|
|
560
|
-
const loaded = await Promise.all(
|
|
561
|
-
files.map(async (file) => {
|
|
562
|
-
const bytes = new Uint8Array(await Bun.file(file.abs).arrayBuffer());
|
|
563
|
-
return {
|
|
564
|
-
file,
|
|
565
|
-
bytes,
|
|
566
|
-
oid: sha256Hex(bytes),
|
|
567
|
-
sample: bytes.subarray(0, 512),
|
|
568
|
-
};
|
|
569
|
-
}),
|
|
570
|
-
);
|
|
571
|
-
|
|
572
|
-
// Local LFS guess feeds the preupload request's sample/size; the server's
|
|
573
|
-
// verdict is authoritative.
|
|
574
|
-
const verdict = await preupload(
|
|
575
|
-
base,
|
|
576
|
-
repoId,
|
|
577
|
-
repoType,
|
|
578
|
-
revision,
|
|
579
|
-
loaded.map((l) => ({ file: l.file, sample: l.sample })),
|
|
580
|
-
token,
|
|
581
|
-
);
|
|
582
|
-
|
|
583
|
-
const regularFiles: { file: LocalFile; bytes: Uint8Array }[] = [];
|
|
584
|
-
const lfsToUpload: { file: LocalFile; oid: string; bytes: Uint8Array }[] = [];
|
|
585
|
-
const lfsForCommit: { file: LocalFile; oid: string }[] = [];
|
|
586
|
-
|
|
587
|
-
for (const l of loaded) {
|
|
588
|
-
const v = verdict.get(l.file.repoPath);
|
|
589
|
-
if (v?.shouldIgnore) continue; // server says don't track this file
|
|
590
|
-
// Prefer the server's verdict; fall back to our local heuristic.
|
|
591
|
-
const mode = v?.uploadMode ?? (isLfs(l.file) ? "lfs" : "regular");
|
|
592
|
-
if (mode === "lfs") {
|
|
593
|
-
lfsToUpload.push({ file: l.file, oid: l.oid, bytes: l.bytes });
|
|
594
|
-
lfsForCommit.push({ file: l.file, oid: l.oid });
|
|
595
|
-
} else {
|
|
596
|
-
regularFiles.push({ file: l.file, bytes: l.bytes });
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
await uploadLfsFiles(
|
|
601
|
-
base,
|
|
602
|
-
repoId,
|
|
603
|
-
repoType,
|
|
604
|
-
revision,
|
|
605
|
-
lfsToUpload,
|
|
606
|
-
token,
|
|
607
|
-
opts.onProgress,
|
|
608
|
-
);
|
|
609
|
-
|
|
610
|
-
// Report progress for inlined regular files too.
|
|
611
|
-
for (const { file } of regularFiles) {
|
|
612
|
-
opts.onProgress?.(file.repoPath, file.size, file.size);
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
const result = await commit(
|
|
616
|
-
base,
|
|
617
|
-
repoId,
|
|
618
|
-
repoType,
|
|
619
|
-
revision,
|
|
620
|
-
message,
|
|
621
|
-
regularFiles,
|
|
622
|
-
lfsForCommit,
|
|
623
|
-
token,
|
|
624
|
-
);
|
|
625
|
-
|
|
626
|
-
const url = `${base}/${repoType === "dataset" ? "datasets/" : ""}${repoId}`;
|
|
627
|
-
return { ok: true, url, commitOid: result.commitOid };
|
|
628
|
-
}
|