mlx-bun 0.5.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 +1449 -109
- 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 +7 -5
- 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 +10 -10
- package/src/{serve → server}/chat-stage.ts +14 -14
- package/src/{client.ts → server/client.ts} +28 -2
- package/src/{serve → server}/completion-executor.ts +33 -41
- 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 +25 -82
- 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 +6 -8
- package/src/{serve → server}/request-prep.ts +47 -50
- 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 -107
- package/docs/archive/hlg-sampling.md +0 -350
- package/docs/archive/investigations/audio-input-plan.md +0 -356
- package/docs/archive/investigations/benchmark-ledger-through-v0.4.0.md +0 -3617
- 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/release-notes-v0.4.0.md +0 -45
- package/docs/archive/planning/release-notes-v0.5.0.md +0 -37
- 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 -2054
- package/docs/design/decode-speed-program.md +0 -2404
- package/docs/design/dreaming-nightly-pipeline.md +0 -684
- package/docs/design/generic-model-support.md +0 -821
- package/docs/design/kv-cache.md +0 -993
- package/docs/design/orpo-training.md +0 -680
- package/docs/design/speculative-decoding.md +0 -2129
- package/docs/design/turboquant.md +0 -2225
- package/docs/design/unified-engine-frontier-plan.md +0 -1987
- package/docs/design/web-chat-redesign.md +0 -695
- package/docs/planning/PRODUCT_ROADMAP.md +0 -593
- package/docs/planning/ResearchTopics.md +0 -119
- package/docs/planning/public-readiness-handoff.md +0 -244
- package/docs/planning/public-readiness.md +0 -149
- package/docs/planning/video-series.md +0 -421
- package/docs/reference/benchmarks.md +0 -3587
- package/docs/reference/cli.md +0 -646
- package/docs/reference/distribution.md +0 -380
- package/docs/reference/environment.md +0 -494
- package/docs/reference/glossary.md +0 -39
- package/docs/reference/library-api.md +0 -688
- package/docs/reference/memory.md +0 -260
- package/docs/reference/models.md +0 -346
- package/docs/reference/server-api.md +0 -1945
- package/docs/reference/server-config.md +0 -973
- package/docs/reference/training.md +0 -462
- package/docs/reference/troubleshooting.md +0 -158
- package/src/admission-plan.ts +0 -18
- package/src/audio/audiotoolbox.ts +0 -112
- package/src/audio/conformer.ts +0 -655
- package/src/audio/decode.ts +0 -133
- package/src/audio/features.ts +0 -202
- package/src/audio/mic-capture.ts +0 -98
- package/src/audio/silero-vad.ts +0 -379
- package/src/audio/transcode.ts +0 -67
- package/src/audio/whisper-decode.ts +0 -774
- package/src/audio/whisper-fast.ts +0 -732
- package/src/audio/whisper-format.ts +0 -73
- package/src/audio/whisper-mel.ts +0 -185
- package/src/audio/whisper-timing.ts +0 -274
- package/src/audio/whisper-tokenizer.ts +0 -239
- package/src/audio/whisper-transcribe.ts +0 -410
- 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 -129
- package/src/backends/mlx/batch-group.ts +0 -1874
- 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 -107
- 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/encoder-cache.ts +0 -25
- package/src/backends/mlx/evaluation.ts +0 -105
- package/src/backends/mlx/fill-append.ts +0 -58
- package/src/backends/mlx/fill-group.ts +0 -497
- 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 -174
- 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 -161
- 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/mixed-iteration.ts +0 -62
- package/src/backends/mlx/model-prompt.ts +0 -178
- package/src/backends/mlx/model-serving.ts +0 -80
- package/src/backends/mlx/paged-cache-codec.ts +0 -27
- package/src/backends/mlx/prefill-cohort.ts +0 -100
- package/src/backends/mlx/prefill-policy.ts +0 -26
- package/src/backends/mlx/prefill-rows.ts +0 -244
- package/src/backends/mlx/prefill.ts +0 -33
- package/src/backends/mlx/projected-context-rows.ts +0 -72
- package/src/backends/mlx/prompt-input.ts +0 -29
- package/src/backends/mlx/qwen-prompt-input.ts +0 -40
- package/src/backends/mlx/request-policy.ts +0 -20
- package/src/backends/mlx/request-state-policy.ts +0 -54
- package/src/backends/mlx/rollback.ts +0 -92
- package/src/backends/mlx/row-sampling.ts +0 -49
- package/src/backends/mlx/serial-executor.ts +0 -251
- package/src/backends/mlx/speculative-group.ts +0 -438
- package/src/backends/mlx/speculative-round.ts +0 -161
- package/src/backends/mlx/speculative.ts +0 -131
- 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 -173
- package/src/chat-template.ts +0 -382
- package/src/cli.ts +0 -3490
- package/src/config.ts +0 -399
- package/src/contracts/completion.ts +0 -16
- package/src/contracts/execution.ts +0 -70
- package/src/contracts/generation.ts +0 -103
- package/src/contracts/host.ts +0 -7
- package/src/contracts/object-cache.ts +0 -8
- package/src/contracts/pi-provider.ts +0 -30
- package/src/contracts/pi.ts +0 -261
- package/src/contracts/prefix-cache.ts +0 -33
- package/src/contracts/resources.ts +0 -25
- package/src/contracts/sampling.ts +0 -23
- package/src/contracts/scheduling.ts +0 -54
- 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 -64
- package/src/engine/execution-tasks.ts +0 -44
- package/src/engine/namespaced-cache.ts +0 -13
- package/src/engine/resources.ts +0 -53
- package/src/engine/scheduler.ts +0 -92
- 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 -463
- 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 -1352
- package/src/grammar.ts +0 -604
- 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 -45
- 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 -279
- package/src/kv-store.ts +0 -1135
- package/src/lab/README.md +0 -22
- 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-attention.ts +0 -117
- package/src/lab/paged-kv/paged-kv-rows.ts +0 -111
- package/src/lab/paged-kv/paged-kv.ts +0 -336
- package/src/library.ts +0 -40
- package/src/lora.ts +0 -408
- package/src/md-modules.d.ts +0 -54
- 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 -425
- 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 -531
- package/src/mlx/materialize.ts +0 -23
- package/src/mlx/metal-kernel.ts +0 -159
- package/src/mlx/normalized-argmax.ts +0 -116
- package/src/mlx/ops.ts +0 -1108
- 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 -94
- 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 -57
- package/src/model/diffusion-gemma.ts +0 -1026
- package/src/model/factory.ts +0 -215
- package/src/model/fingerprint.ts +0 -45
- 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 -2370
- package/src/model/gemma4.ts +0 -1395
- 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 -70
- package/src/model/minicpm5.ts +0 -376
- package/src/model/profile.ts +0 -468
- package/src/model/quantized-append-attention.ts +0 -31
- 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 -250
- package/src/model/qwen3.ts +0 -277
- package/src/model/qwen3_5-checkpoint.ts +0 -164
- package/src/model/qwen3_5.ts +0 -881
- 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 -110
- package/src/model/token-groups.ts +0 -66
- 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 -89
- 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/model/whisper.ts +0 -435
- package/src/native/expert_io.c +0 -523
- package/src/native/frame_extract.swift +0 -140
- package/src/native/mic_capture.swift +0 -92
- package/src/native-pack.ts +0 -163
- 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 -1940
- package/src/preflight.ts +0 -158
- package/src/prompt-cache.ts +0 -682
- 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 -77
- package/src/safetensors.ts +0 -165
- package/src/sampler.ts +0 -1012
- 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/audio-routes.ts +0 -323
- 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 -537
- 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 -49
- package/src/serve/model-host.ts +0 -511
- package/src/serve/parent-application.ts +0 -56
- package/src/serve/prompt-response-trace.ts +0 -161
- 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/serve/transcription-server.ts +0 -64
- package/src/serve/transcription-service.ts +0 -502
- package/src/server.ts +0 -1282
- package/src/spec/assistant-rows.ts +0 -93
- 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 -318
- package/src/spec/glm52-mtp-state.ts +0 -33
- package/src/spec/ngram-source.ts +0 -226
- 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 -230
- package/src/spec/qwen-mtp-source.ts +0 -386
- package/src/spec/qwen-mtp-state.ts +0 -30
- package/src/spec/serve-loop.ts +0 -587
- package/src/spec/source.ts +0 -228
- package/src/spec/two-model-rows.ts +0 -62
- package/src/spec/two-model.ts +0 -113
- package/src/ssd-cache.ts +0 -431
- package/src/ssd-durability.ts +0 -209
- package/src/storage/host-buffer.ts +0 -24
- package/src/storage/kv-writer.ts +0 -83
- package/src/storage/kv-writer.worker.js +0 -264
- package/src/storage/retention-policy.ts +0 -37
- package/src/tiered-prompt-cache.ts +0 -45
- 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 -176
- package/src/vision/preprocess.ts +0 -247
- package/src/vision/prompt.ts +0 -409
- package/src/vision/qwen3vl-preprocess.ts +0 -409
- package/src/vision/qwen3vl-prompt.ts +0 -233
- package/src/vision/qwen3vl-tower.ts +0 -566
- package/src/vision/siglip.ts +0 -607
- package/src/vision/video-frames.ts +0 -148
- package/src/web/app.html +0 -2155
- package/src/web/app.js +0 -5863
- 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 -1060
- package/src/web/src/composer.ts +0 -962
- 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/src/voice.ts +0 -141
- 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/{serve → server}/generated-token-history.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
|
@@ -0,0 +1,1054 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>mlx-bun</title>
|
|
7
|
+
<style>
|
|
8
|
+
/* ════════════════════════════════════════════════════════════════════
|
|
9
|
+
mlx-bun · unified app
|
|
10
|
+
One product, five sections (Chat · Quantize · Fine-tune · Dataset · Status).
|
|
11
|
+
Apple keynote grammar: black stage, SF Pro, gradient hero type,
|
|
12
|
+
hairline cards, ambient color blooms, numbers that land.
|
|
13
|
+
Fully self-contained — no external fonts, CDNs, or scripts.
|
|
14
|
+
════════════════════════════════════════════════════════════════════ */
|
|
15
|
+
|
|
16
|
+
/* ─── design tokens (shared across every section) ─── */
|
|
17
|
+
:root{
|
|
18
|
+
--bg:#000;
|
|
19
|
+
--ink:#f5f5f7;
|
|
20
|
+
--dim:#86868b;
|
|
21
|
+
--dimmer:#515154;
|
|
22
|
+
--hairline:rgba(255,255,255,.14);
|
|
23
|
+
--hairline-soft:rgba(255,255,255,.07);
|
|
24
|
+
--hairline-strong:rgba(255,255,255,.28);
|
|
25
|
+
--card:rgba(255,255,255,.045);
|
|
26
|
+
--card-hover:rgba(255,255,255,.08);
|
|
27
|
+
--card-2:rgba(255,255,255,.025);
|
|
28
|
+
--blue:#0a84ff; --cyan:#64d2ff; --indigo:#5e5ce6; --purple:#bf5af2;
|
|
29
|
+
--pink:#ff375f; --orange:#ff9f0a; --yellow:#ffd60a; --green:#30d158;
|
|
30
|
+
--red:#ff453a;
|
|
31
|
+
--ease:cubic-bezier(.22,.61,.21,1);
|
|
32
|
+
--nav-h:60px;
|
|
33
|
+
--mono:"SF Mono",ui-monospace,Menlo,Monaco,monospace;
|
|
34
|
+
/* bloom radial-gradient stop opacities — separate tokens so the light
|
|
35
|
+
theme can dial them down (the gradient identity/positions/colors stay
|
|
36
|
+
identical, only intensity changes) */
|
|
37
|
+
--bloom-a:.13; --bloom-b:.16; --bloom-c:.10;
|
|
38
|
+
--overlay-scrim:rgba(0,0,0,.55);
|
|
39
|
+
--overlay-panel:rgba(22,22,24,.96);
|
|
40
|
+
--popover-panel:rgba(30,30,34,.98);
|
|
41
|
+
/* Code/log/tool-output surfaces (pre blocks, .logbox, edit textarea)
|
|
42
|
+
deliberately stay dark-chrome in BOTH themes — the conventional
|
|
43
|
+
"code block keeps its own dark surface" pattern (GitHub, VS Code
|
|
44
|
+
light themes, etc.), so monospace content keeps consistent contrast
|
|
45
|
+
regardless of the surrounding chat theme.
|
|
46
|
+
These MUST be opaque: the original rgba(0,0,0,.45) composited to
|
|
47
|
+
mid-GRAY over the light theme's white page, washing out the
|
|
48
|
+
near-white code ink + #86868b hljs comments (2026-07-06 visual QA).
|
|
49
|
+
Opaque values render identically over any page background. */
|
|
50
|
+
--code-bg:#121214; --code-bg-soft:#1a1a1d; --code-ink:#f5f5f7;
|
|
51
|
+
--nav-bg:rgba(0,0,0,.62);
|
|
52
|
+
--scrollbar-thumb:rgba(255,255,255,.12); --scrollbar-thumb-hover:rgba(255,255,255,.22);
|
|
53
|
+
}
|
|
54
|
+
/* ─── light theme: tasteful equivalents, same gradient identity ───
|
|
55
|
+
Applied via [data-theme="light"] on <html> (explicit user choice,
|
|
56
|
+
persisted to localStorage) OR by prefers-color-scheme:light when the
|
|
57
|
+
user's choice is "auto" (default — see initTheme()). */
|
|
58
|
+
[data-theme="light"]{
|
|
59
|
+
--bg:#f4f4f6;
|
|
60
|
+
--ink:#1d1d1f;
|
|
61
|
+
--dim:#6e6e73;
|
|
62
|
+
--dimmer:#a1a1a6;
|
|
63
|
+
--hairline:rgba(0,0,0,.12);
|
|
64
|
+
--hairline-soft:rgba(0,0,0,.06);
|
|
65
|
+
--hairline-strong:rgba(0,0,0,.28);
|
|
66
|
+
--card:rgba(0,0,0,.035);
|
|
67
|
+
--card-hover:rgba(0,0,0,.065);
|
|
68
|
+
--card-2:rgba(0,0,0,.02);
|
|
69
|
+
--bloom-a:.09; --bloom-b:.10; --bloom-c:.07;
|
|
70
|
+
--overlay-scrim:rgba(0,0,0,.28);
|
|
71
|
+
--overlay-panel:rgba(255,255,255,.97);
|
|
72
|
+
--popover-panel:rgba(255,255,255,.98);
|
|
73
|
+
--nav-bg:rgba(255,255,255,.72);
|
|
74
|
+
--scrollbar-thumb:rgba(0,0,0,.14); --scrollbar-thumb-hover:rgba(0,0,0,.26);
|
|
75
|
+
}
|
|
76
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
77
|
+
html,body{height:100%}
|
|
78
|
+
body{
|
|
79
|
+
background:var(--bg);color:var(--ink);
|
|
80
|
+
font-family:"SF Pro Display","SF Pro Text",-apple-system,BlinkMacSystemFont,"Helvetica Neue",Helvetica,Arial,sans-serif;
|
|
81
|
+
-webkit-font-smoothing:antialiased;
|
|
82
|
+
overflow:hidden; /* app shell owns its own scroll regions */
|
|
83
|
+
}
|
|
84
|
+
::selection{background:rgba(10,132,255,.4)}
|
|
85
|
+
.num{font-variant-numeric:tabular-nums}
|
|
86
|
+
code,.mono{font-family:var(--mono)}
|
|
87
|
+
code{font-size:.86em;background:rgba(127,127,127,.16);padding:2px 8px;border-radius:6px}
|
|
88
|
+
a{color:inherit}
|
|
89
|
+
::-webkit-scrollbar{width:10px;height:10px}
|
|
90
|
+
::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:6px;border:2px solid transparent;background-clip:content-box}
|
|
91
|
+
::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover);background-clip:content-box}
|
|
92
|
+
::-webkit-scrollbar-track{background:transparent}
|
|
93
|
+
|
|
94
|
+
/* gradient text helpers (lifted from status/chat pages) */
|
|
95
|
+
.grad{background-clip:text;-webkit-background-clip:text;color:transparent}
|
|
96
|
+
.g-hero{background-image:linear-gradient(96deg,var(--orange) 0%,var(--pink) 30%,var(--purple) 62%,var(--blue) 100%)}
|
|
97
|
+
.g-blue{background-image:linear-gradient(94deg,var(--cyan),var(--blue) 55%,var(--indigo))}
|
|
98
|
+
.g-green{background-image:linear-gradient(94deg,#a8ff9e,var(--green) 45%,var(--cyan))}
|
|
99
|
+
.g-pink{background-image:linear-gradient(94deg,var(--orange),var(--pink) 55%,var(--purple))}
|
|
100
|
+
.g-purple{background-image:linear-gradient(94deg,var(--purple),var(--indigo) 55%,var(--blue))}
|
|
101
|
+
|
|
102
|
+
/* ─── ambient blooms behind everything ─── */
|
|
103
|
+
.bloom{position:fixed;inset:-25%;pointer-events:none;z-index:0;
|
|
104
|
+
background:
|
|
105
|
+
radial-gradient(55vw 42vh at 12% 6%, rgba(255,159,10,var(--bloom-a)), transparent 68%),
|
|
106
|
+
radial-gradient(60vw 48vh at 88% 24%, rgba(94,92,230,var(--bloom-b)), transparent 68%),
|
|
107
|
+
radial-gradient(50vw 40vh at 30% 96%, rgba(10,132,255,var(--bloom-c)), transparent 68%);
|
|
108
|
+
filter:blur(74px);
|
|
109
|
+
transition:opacity 1.2s var(--ease);
|
|
110
|
+
}
|
|
111
|
+
/* Ambient bloom is a slow continuous drift, gated behind
|
|
112
|
+
prefers-reduced-motion: with no explicit opacity set inline
|
|
113
|
+
by the route dimmer, it just sits static — no keyframe loop to begin
|
|
114
|
+
with, so the only "animation" to guard is the opacity transition
|
|
115
|
+
above, which is a one-shot per-route dim, not a decorative loop. The
|
|
116
|
+
shimmer/pulse/blink loops below are the actual ambient animations. */
|
|
117
|
+
@media (prefers-reduced-motion:reduce){
|
|
118
|
+
.bloom{transition:none}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* ═══════════════════ top navigation ═══════════════════ */
|
|
122
|
+
nav{
|
|
123
|
+
position:fixed;top:0;left:0;right:0;height:var(--nav-h);z-index:50;
|
|
124
|
+
display:flex;align-items:center;gap:18px;padding:0 22px;
|
|
125
|
+
border-bottom:1px solid var(--hairline);
|
|
126
|
+
background:var(--nav-bg);backdrop-filter:saturate(180%) blur(22px);
|
|
127
|
+
-webkit-backdrop-filter:saturate(180%) blur(22px);
|
|
128
|
+
}
|
|
129
|
+
nav .brand{font-size:18px;font-weight:700;letter-spacing:-.02em;text-decoration:none;
|
|
130
|
+
white-space:nowrap;flex:0 0 auto}
|
|
131
|
+
nav .tabs{display:flex;gap:2px;flex:1 1 auto;overflow-x:auto;scrollbar-width:none}
|
|
132
|
+
nav .tabs::-webkit-scrollbar{display:none}
|
|
133
|
+
/* Scroll-edge fades (2026-07-06 jank fix): the tab row scrolls with its
|
|
134
|
+
scrollbar hidden, so a clipped "Build Datase" read as broken/overlapped.
|
|
135
|
+
JS (updateTabFades) toggles .fade-r/.fade-l per scroll position so a
|
|
136
|
+
soft fade signals "more tabs this way" only when actually clipped. */
|
|
137
|
+
nav .tabs.fade-r{-webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 34px),transparent);
|
|
138
|
+
mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 34px),transparent)}
|
|
139
|
+
nav .tabs.fade-l{-webkit-mask-image:linear-gradient(90deg,transparent,#000 34px,#000);
|
|
140
|
+
mask-image:linear-gradient(90deg,transparent,#000 34px,#000)}
|
|
141
|
+
nav .tabs.fade-l.fade-r{-webkit-mask-image:linear-gradient(90deg,transparent,#000 34px,#000 calc(100% - 34px),transparent);
|
|
142
|
+
mask-image:linear-gradient(90deg,transparent,#000 34px,#000 calc(100% - 34px),transparent)}
|
|
143
|
+
nav .tab{
|
|
144
|
+
appearance:none;background:none;border:none;cursor:pointer;
|
|
145
|
+
color:var(--dim);font:600 14px/1 inherit;letter-spacing:-.01em;
|
|
146
|
+
padding:8px 14px;border-radius:10px;text-decoration:none;white-space:nowrap;
|
|
147
|
+
transition:color .22s var(--ease),background .22s var(--ease)}
|
|
148
|
+
nav .tab:hover{color:var(--ink)}
|
|
149
|
+
nav .tab.active{color:var(--ink);background:rgba(255,255,255,.08)}
|
|
150
|
+
nav .right{display:flex;align-items:center;gap:12px;flex:0 0 auto}
|
|
151
|
+
nav .model{font:12px var(--mono);color:var(--dim);
|
|
152
|
+
background:var(--card);border:1px solid var(--hairline);border-radius:8px;padding:5px 10px;
|
|
153
|
+
max-width:34vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
|
|
154
|
+
appearance:none;-webkit-appearance:none;cursor:pointer;transition:color .18s var(--ease),border-color .18s var(--ease)}
|
|
155
|
+
nav .model:hover{color:var(--ink);border-color:var(--hairline-strong)}
|
|
156
|
+
.pill{display:inline-flex;align-items:center;gap:8px;
|
|
157
|
+
border:1px solid var(--hairline);border-radius:999px;padding:6px 13px;
|
|
158
|
+
font-size:12.5px;font-weight:600;color:var(--dim);letter-spacing:.01em;white-space:nowrap}
|
|
159
|
+
.pill .dot{width:8px;height:8px;border-radius:50%;background:var(--dimmer);
|
|
160
|
+
box-shadow:0 0 0 transparent;transition:all .4s}
|
|
161
|
+
.pill.ok .dot{background:var(--green);box-shadow:0 0 11px var(--green)}
|
|
162
|
+
.pill.ok{color:var(--ink)}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
.pill.bad .dot{background:var(--red);box-shadow:0 0 11px var(--red)}
|
|
167
|
+
.pill.warn .dot{background:var(--orange);box-shadow:0 0 11px var(--orange)}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
.samplepop{position:absolute;bottom:calc(100% + 9px);right:0;z-index:40;width:300px;
|
|
176
|
+
max-height:min(70vh,560px);overflow-y:auto;
|
|
177
|
+
background:var(--popover-panel);border:1px solid var(--hairline);border-radius:13px;padding:13px 14px;
|
|
178
|
+
backdrop-filter:blur(22px) saturate(1.3);-webkit-backdrop-filter:blur(22px) saturate(1.3);
|
|
179
|
+
box-shadow:0 18px 50px rgba(0,0,0,.35);display:none;
|
|
180
|
+
transform:translateY(4px);opacity:0;transition:opacity .16s var(--ease),transform .16s var(--ease)}
|
|
181
|
+
.samplepop.open{display:block;transform:translateY(0);opacity:1}
|
|
182
|
+
.samplepop h4{font-size:12px;font-weight:600;color:var(--dim);letter-spacing:.02em;
|
|
183
|
+
text-transform:uppercase;margin:0}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
#nav-download{color:var(--ink);font-family:var(--mono);font-size:11.5px;font-weight:500}
|
|
217
|
+
#nav-download .dot{background:var(--orange);box-shadow:0 0 11px var(--orange);animation:dlpulse 1.4s ease-in-out infinite}
|
|
218
|
+
@keyframes dlpulse{0%,100%{opacity:.4}50%{opacity:1}}
|
|
219
|
+
.hf-gear,.icon-btn{appearance:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
|
|
220
|
+
width:34px;height:34px;border-radius:10px;background:var(--card);border:1px solid var(--hairline);
|
|
221
|
+
color:var(--dim);flex:0 0 auto;transition:color .22s var(--ease),background .22s var(--ease),border-color .22s var(--ease)}
|
|
222
|
+
.hf-gear:hover,.icon-btn:hover{color:var(--ink);background:var(--card-hover);border-color:var(--hairline-strong)}
|
|
223
|
+
.hf-gear.saved{color:var(--green);border-color:rgba(48,209,88,.4)}
|
|
224
|
+
|
|
225
|
+
/* mobile drawer hamburger — chat route only, hidden ≥760px via the
|
|
226
|
+
media query beside #chat-sidebar above */
|
|
227
|
+
#chat-hamburger{align-items:center;justify-content:center;gap:3px}
|
|
228
|
+
|
|
229
|
+
/* theme toggle: 3-way auto/dark/light segmented control, nav-pill sized */
|
|
230
|
+
#theme-toggle{display:inline-flex;border:1px solid var(--hairline);border-radius:10px;overflow:hidden;flex:0 0 auto}
|
|
231
|
+
#theme-toggle button{appearance:none;cursor:pointer;background:transparent;border:none;color:var(--dim);
|
|
232
|
+
padding:0 9px;height:34px;font-size:13px;line-height:1;transition:color .18s var(--ease),background .18s var(--ease)}
|
|
233
|
+
#theme-toggle button:not(:last-child){border-right:1px solid var(--hairline)}
|
|
234
|
+
#theme-toggle button:hover{color:var(--ink);background:var(--card-hover)}
|
|
235
|
+
#theme-toggle button.active{color:var(--ink);background:var(--card-hover)}
|
|
236
|
+
#theme-toggle button:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
|
|
237
|
+
/* Auto's ◐ icon only appears when the text label hides at narrow widths
|
|
238
|
+
(see the 900px media block) — never both, never neither. */
|
|
239
|
+
#theme-toggle .tt-icon{display:none}
|
|
240
|
+
|
|
241
|
+
/* Developer toggle: a small switch, same nav-pill
|
|
242
|
+
sizing language as #theme-toggle, showing/hiding the Quantize/Fine-tune/
|
|
243
|
+
Build Dataset/Status/Curves/Routes tabs. aria-pressed reflects state
|
|
244
|
+
(kept in sync by shell.ts's applyDeveloperMode). */
|
|
245
|
+
#nav-developer{appearance:none;cursor:pointer;display:inline-flex;align-items:center;gap:7px;
|
|
246
|
+
border:1px solid var(--hairline);border-radius:10px;background:transparent;color:var(--dim);
|
|
247
|
+
padding:0 10px;height:34px;font-size:12.5px;font-weight:600;letter-spacing:.01em;flex:0 0 auto;
|
|
248
|
+
transition:color .18s var(--ease),background .18s var(--ease),border-color .18s var(--ease)}
|
|
249
|
+
#nav-developer:hover{color:var(--ink);background:var(--card-hover);border-color:var(--hairline-strong)}
|
|
250
|
+
#nav-developer:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
|
|
251
|
+
#nav-developer .nd-dot{width:8px;height:8px;border-radius:50%;background:var(--dimmer);flex:0 0 auto;
|
|
252
|
+
transition:background .18s var(--ease)}
|
|
253
|
+
#nav-developer .nd-dot.on{background:var(--green)}
|
|
254
|
+
#nav-developer[aria-checked="true"]{color:var(--ink)}
|
|
255
|
+
|
|
256
|
+
/* ─── keyboard shortcut sheet (Cmd/Ctrl+/) ─── */
|
|
257
|
+
#shortcut-overlay{position:fixed;inset:0;z-index:210;display:none;align-items:flex-start;justify-content:center;
|
|
258
|
+
background:var(--overlay-scrim);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);padding:calc(var(--nav-h) + 24px) 20px 20px}
|
|
259
|
+
#shortcut-overlay.open{display:flex;animation:fade .2s var(--ease)}
|
|
260
|
+
#shortcut-modal{width:min(480px,100%);max-height:min(76vh,620px);overflow-y:auto;background:var(--overlay-panel);
|
|
261
|
+
border:1px solid var(--hairline);border-radius:20px;padding:22px 26px;box-shadow:0 30px 80px rgba(0,0,0,.35)}
|
|
262
|
+
.sk-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
|
|
263
|
+
.sk-title{font-size:18px;font-weight:700;letter-spacing:-.02em}
|
|
264
|
+
.sk-close{appearance:none;background:none;border:none;cursor:pointer;color:var(--dim);font-size:16px;
|
|
265
|
+
width:30px;height:30px;border-radius:8px;transition:color .2s,background .2s}
|
|
266
|
+
.sk-close:hover{color:var(--ink);background:var(--card-hover)}
|
|
267
|
+
.sk-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:8px 0;
|
|
268
|
+
border-bottom:1px solid var(--hairline-soft)}
|
|
269
|
+
.sk-row:last-child{border-bottom:none}
|
|
270
|
+
.sk-desc{font-size:13.5px;color:var(--ink)}
|
|
271
|
+
.sk-keys{display:flex;gap:5px;flex:0 0 auto}
|
|
272
|
+
.sk-key{font:600 11.5px var(--mono);color:var(--ink);background:var(--card);border:1px solid var(--hairline);
|
|
273
|
+
border-radius:6px;padding:3px 8px;min-width:20px;text-align:center}
|
|
274
|
+
|
|
275
|
+
/* ─── HF settings overlay ─── */
|
|
276
|
+
#hf-overlay{position:fixed;inset:0;z-index:200;display:none;align-items:flex-start;justify-content:center;
|
|
277
|
+
background:var(--overlay-scrim);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);padding:calc(var(--nav-h) + 24px) 20px 20px}
|
|
278
|
+
#hf-overlay.open{display:flex;animation:fade .3s var(--ease)}
|
|
279
|
+
#hf-modal{width:min(460px,100%);background:var(--overlay-panel);border:1px solid var(--hairline);border-radius:20px;
|
|
280
|
+
padding:24px 26px;box-shadow:0 30px 80px rgba(0,0,0,.35)}
|
|
281
|
+
.hf-modal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
|
|
282
|
+
.hf-modal-title{font-size:20px;font-weight:700;letter-spacing:-.02em}
|
|
283
|
+
.hf-modal-sub{font-size:13.5px;color:var(--dim);margin-bottom:20px;line-height:1.5}
|
|
284
|
+
.hf-close{appearance:none;background:none;border:none;cursor:pointer;color:var(--dim);font-size:16px;
|
|
285
|
+
width:30px;height:30px;border-radius:8px;transition:color .2s,background .2s}
|
|
286
|
+
.hf-close:hover{color:var(--ink);background:var(--card-hover)}
|
|
287
|
+
|
|
288
|
+
/* ─── Settings modal sections ─── */
|
|
289
|
+
.settings-section{margin:0 0 20px;padding:0 0 20px;border-bottom:1px solid var(--hairline-soft)}
|
|
290
|
+
.settings-section:last-child{border-bottom:none;padding-bottom:0;margin-bottom:0}
|
|
291
|
+
.settings-h{font-size:12px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--dim);margin:0 0 12px}
|
|
292
|
+
.settings-toggle-row{display:flex;align-items:center;gap:10px;font-size:13.5px;color:var(--ink);
|
|
293
|
+
cursor:pointer;font-weight:500;margin-bottom:8px}
|
|
294
|
+
.settings-toggle-row input{width:auto;margin:0;accent-color:var(--blue)}
|
|
295
|
+
.settings-note{font-size:12px;color:var(--orange);margin:8px 0 0;line-height:1.5}
|
|
296
|
+
#settings-approvals-list{margin-top:12px}
|
|
297
|
+
.settings-approvals-empty{font-size:12.5px;color:var(--dimmer)}
|
|
298
|
+
.settings-approval-row{display:flex;align-items:center;gap:10px;padding:7px 0;font-size:13px;
|
|
299
|
+
border-top:1px solid var(--hairline-soft)}
|
|
300
|
+
.settings-approval-row:first-child{border-top:none}
|
|
301
|
+
.settings-approval-row .satool{font:600 12.5px var(--mono);color:var(--ink);flex:1 1 auto}
|
|
302
|
+
.settings-approval-row .saforget{appearance:none;cursor:pointer;background:none;border:1px solid var(--hairline);
|
|
303
|
+
color:var(--dim);border-radius:7px;padding:3px 9px;font-size:11.5px;font-weight:600;flex:0 0 auto;
|
|
304
|
+
transition:color .18s var(--ease),border-color .18s var(--ease)}
|
|
305
|
+
.settings-approval-row .saforget:hover{color:var(--red);border-color:rgba(255,69,58,.4)}
|
|
306
|
+
|
|
307
|
+
/* ─── inline push-to-hub panel (in done-step cards) ─── */
|
|
308
|
+
.pushpanel{margin-top:14px;border-top:1px solid var(--hairline-soft);padding-top:14px}
|
|
309
|
+
.pushpanel .field{margin-bottom:12px}
|
|
310
|
+
.pushpanel label.chk{display:flex;align-items:center;gap:9px;font-size:13.5px;color:var(--ink);cursor:pointer;font-weight:500}
|
|
311
|
+
.pushpanel label.chk input{width:auto;margin:0;accent-color:var(--blue)}
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
/* ═══════════════════ app shell / routing ═══════════════════ */
|
|
335
|
+
#app{position:fixed;inset:var(--nav-h) 0 0 0;z-index:1}
|
|
336
|
+
section[data-route]{display:none;position:absolute;inset:0}
|
|
337
|
+
section[data-route].active{display:block;animation:fade .5s var(--ease)}
|
|
338
|
+
@keyframes fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
|
|
339
|
+
|
|
340
|
+
/* a scrolling content column used by the doc-style sections */
|
|
341
|
+
.scroller{height:100%;overflow-y:auto}
|
|
342
|
+
.wrap{max-width:1180px;margin:0 auto;padding:46px 28px 120px}
|
|
343
|
+
.wrap.narrow{max-width:860px}
|
|
344
|
+
|
|
345
|
+
/* ─── shared typographic bits ─── */
|
|
346
|
+
.eyebrow{font-size:12.5px;font-weight:600;letter-spacing:.22em;text-transform:uppercase;color:var(--dim);margin-bottom:14px}
|
|
347
|
+
h1.title{font-size:clamp(38px,5.4vw,68px);font-weight:700;letter-spacing:-.032em;line-height:1.02}
|
|
348
|
+
.lead{font-size:clamp(15px,1.4vw,19px);line-height:1.55;color:var(--dim);max-width:66ch;margin-top:18px}
|
|
349
|
+
.lead strong{color:var(--ink);font-weight:600}
|
|
350
|
+
h2{font-size:clamp(26px,3.6vw,46px);font-weight:700;letter-spacing:-.026em;line-height:1.06}
|
|
351
|
+
h2 .soft{color:var(--dimmer)}
|
|
352
|
+
h3.kicker{font-size:12.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);margin-bottom:14px}
|
|
353
|
+
|
|
354
|
+
/* ─── reveals ─── */
|
|
355
|
+
[data-reveal]{opacity:0;transform:translateY(22px);
|
|
356
|
+
transition:opacity .8s var(--ease),transform .8s var(--ease);transition-delay:calc(var(--d,0)*1ms)}
|
|
357
|
+
.lit [data-reveal]{opacity:1;transform:none}
|
|
358
|
+
@media (prefers-reduced-motion:reduce){
|
|
359
|
+
[data-reveal]{transition:none;opacity:1;transform:none}
|
|
360
|
+
*{scroll-behavior:auto}
|
|
361
|
+
/* Ambient/decorative infinite-loop animations: shimmer
|
|
362
|
+
skeleton sweep, download-pulse dot, streaming cursor blink, running-
|
|
363
|
+
tool status dot. These loop forever by design and carry no state —
|
|
364
|
+
freezing them (not hiding) keeps the element visible+legible without
|
|
365
|
+
motion. One-shot transitions (fade-in on route change, toast slide-in,
|
|
366
|
+
popover open) are left alone; they're brief and convey state change,
|
|
367
|
+
not ambient decoration. */
|
|
368
|
+
#nav-download .dot,.shimmer,.cursor,.tool.running .sdot{animation:none!important}
|
|
369
|
+
.shimmer{color:inherit!important;background:var(--card)}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/* ─── cards ─── */
|
|
373
|
+
.grid{display:grid;gap:14px}
|
|
374
|
+
.g4{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
|
|
375
|
+
.card{background:var(--card);border:1px solid var(--hairline);border-radius:20px;
|
|
376
|
+
padding:24px 26px;transition:background .3s var(--ease),border-color .3s var(--ease)}
|
|
377
|
+
.card:hover{background:var(--card-hover)}
|
|
378
|
+
.card h3{font-size:12.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);margin-bottom:14px}
|
|
379
|
+
.stat{font-size:clamp(28px,3.2vw,42px);font-weight:700;letter-spacing:-.025em;line-height:1.05}
|
|
380
|
+
.stat small{font-size:.42em;font-weight:600;color:var(--dim);letter-spacing:0;margin-left:6px}
|
|
381
|
+
.card .cap{margin-top:8px;font-size:13.5px;color:var(--dim);line-height:1.5}
|
|
382
|
+
.kv{display:flex;justify-content:space-between;gap:10px;padding:5px 0;font-size:14.5px;border-bottom:1px solid var(--hairline-soft)}
|
|
383
|
+
.kv:last-child{border-bottom:none}
|
|
384
|
+
.kv b{font-weight:500;color:var(--dim)}
|
|
385
|
+
.kv span{font-weight:600}
|
|
386
|
+
.meter{height:5px;border-radius:3px;background:rgba(255,255,255,.09);margin-top:16px;overflow:hidden}
|
|
387
|
+
.meter i{display:block;height:100%;border-radius:3px;width:0%;
|
|
388
|
+
background:linear-gradient(90deg,var(--cyan),var(--blue));transition:width .8s var(--ease)}
|
|
389
|
+
.meter.warm i{background:linear-gradient(90deg,var(--orange),var(--pink))}
|
|
390
|
+
.meter.green i{background:linear-gradient(90deg,#a8ff9e,var(--green))}
|
|
391
|
+
|
|
392
|
+
/* ─── tables ─── */
|
|
393
|
+
table{width:100%;border-collapse:collapse;font-size:14.5px}
|
|
394
|
+
th,td{text-align:right;padding:13px 16px;border-bottom:1px solid var(--hairline-soft)}
|
|
395
|
+
th:first-child,td:first-child{text-align:left}
|
|
396
|
+
td:not(:first-child),th:not(:first-child){white-space:nowrap}
|
|
397
|
+
th{font-size:11.5px;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--dim)}
|
|
398
|
+
tr:last-child td{border-bottom:none}
|
|
399
|
+
tbody tr{transition:background .2s}
|
|
400
|
+
tbody tr:hover{background:rgba(255,255,255,.04)}
|
|
401
|
+
td.fit-yes{color:var(--green);font-weight:600}
|
|
402
|
+
td.fit-no{color:var(--dimmer)}
|
|
403
|
+
tr.you td{background:rgba(10,132,255,.10)}
|
|
404
|
+
tr.you td:first-child{border-left:3px solid var(--blue);border-radius:2px}
|
|
405
|
+
.tablecard{padding:8px 6px}
|
|
406
|
+
|
|
407
|
+
/* ─── forms (used by all three wizards) ─── */
|
|
408
|
+
.field{margin-bottom:18px}
|
|
409
|
+
.field>label{display:block;font-size:13px;font-weight:600;color:var(--ink);margin-bottom:8px;letter-spacing:-.01em}
|
|
410
|
+
.field .hint{font-size:12.5px;color:var(--dim);margin-top:7px;line-height:1.5}
|
|
411
|
+
input[type=text],input[type=number],input[type=password],textarea,select{
|
|
412
|
+
width:100%;background:var(--card);border:1px solid var(--hairline);border-radius:12px;
|
|
413
|
+
color:var(--ink);font:14.5px/1.5 inherit;padding:11px 14px;outline:none;
|
|
414
|
+
transition:border-color .22s var(--ease),background .22s var(--ease)}
|
|
415
|
+
input::placeholder,textarea::placeholder{color:var(--dimmer)}
|
|
416
|
+
input:focus,textarea:focus,select:focus{border-color:rgba(10,132,255,.55);background:var(--card-hover)}
|
|
417
|
+
textarea{resize:vertical;min-height:96px;font-family:var(--mono);font-size:13px}
|
|
418
|
+
select{appearance:none;-webkit-appearance:none;cursor:pointer;
|
|
419
|
+
background-image:url("data:image/svg+xml;charset=US-ASCII,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2386868b' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
|
|
420
|
+
background-repeat:no-repeat;background-position:right 14px center;padding-right:34px}
|
|
421
|
+
.hpgrid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
|
|
422
|
+
.hpgrid .field{margin-bottom:0}
|
|
423
|
+
input[type=range]{width:100%;accent-color:var(--blue);background:transparent;cursor:pointer;height:24px}
|
|
424
|
+
|
|
425
|
+
/* segmented control */
|
|
426
|
+
.seg{display:inline-flex;background:var(--card);border:1px solid var(--hairline);border-radius:12px;padding:3px;gap:3px}
|
|
427
|
+
.seg button{appearance:none;background:none;border:none;cursor:pointer;color:var(--dim);
|
|
428
|
+
font:600 13.5px/1 inherit;padding:9px 18px;border-radius:9px;transition:all .22s var(--ease)}
|
|
429
|
+
.seg button.on{background:rgba(255,255,255,.12);color:var(--ink)}
|
|
430
|
+
.seg button:hover:not(.on){color:var(--ink)}
|
|
431
|
+
|
|
432
|
+
/* buttons */
|
|
433
|
+
.btn{appearance:none;border:none;cursor:pointer;font:600 14px/1 inherit;border-radius:13px;
|
|
434
|
+
padding:0 22px;height:46px;display:inline-flex;align-items:center;justify-content:center;gap:8px;
|
|
435
|
+
transition:filter .2s,opacity .2s,background .22s var(--ease)}
|
|
436
|
+
.btn.primary{background:linear-gradient(120deg,var(--blue),var(--purple));color:#fff}
|
|
437
|
+
.btn.primary:hover{filter:brightness(1.13)}
|
|
438
|
+
.btn.ghost{background:var(--card);border:1px solid var(--hairline);color:var(--ink)}
|
|
439
|
+
.btn.ghost:hover{background:var(--card-hover)}
|
|
440
|
+
.btn:disabled{filter:grayscale(.7) brightness(.55);cursor:default;opacity:.7}
|
|
441
|
+
.btn.sm{height:38px;padding:0 16px;font-size:13px;border-radius:11px}
|
|
442
|
+
.btnrow{display:flex;gap:10px;margin-top:24px;flex-wrap:wrap;align-items:center}
|
|
443
|
+
|
|
444
|
+
/* flash / status banners */
|
|
445
|
+
.flash{border-radius:14px;padding:13px 16px;font-size:14px;line-height:1.5;border:1px solid;margin-top:14px}
|
|
446
|
+
.flash.ok{background:rgba(48,209,88,.10);border-color:rgba(48,209,88,.35);color:#b8f5c4}
|
|
447
|
+
.flash.warn{background:rgba(255,159,10,.10);border-color:rgba(255,159,10,.35);color:#ffe0a8}
|
|
448
|
+
.flash.err{background:rgba(255,69,58,.10);border-color:rgba(255,69,58,.35);color:#ffb8b3}
|
|
449
|
+
.flash code{background:rgba(0,0,0,.3)}
|
|
450
|
+
.flash strong{color:var(--ink)}
|
|
451
|
+
|
|
452
|
+
.soon{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;letter-spacing:.06em;
|
|
453
|
+
text-transform:uppercase;color:var(--dimmer);border:1px solid var(--hairline-soft);border-radius:999px;padding:3px 10px}
|
|
454
|
+
|
|
455
|
+
/* step indicator */
|
|
456
|
+
.steps{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 30px;font:600 12px var(--mono);
|
|
457
|
+
text-transform:uppercase;letter-spacing:.05em;color:var(--dimmer)}
|
|
458
|
+
.steps .s{display:inline-flex;align-items:center;gap:8px}
|
|
459
|
+
.steps .s .n{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;
|
|
460
|
+
border:1px solid var(--hairline);font-size:11px;color:var(--dim);transition:all .3s var(--ease)}
|
|
461
|
+
.steps .s.done .n{background:rgba(255,255,255,.10);color:var(--ink);border-color:transparent}
|
|
462
|
+
.steps .s.cur .n{background:linear-gradient(120deg,var(--blue),var(--purple));color:#fff;border-color:transparent}
|
|
463
|
+
.steps .s.cur{color:var(--ink)}
|
|
464
|
+
.steps .s.done{color:var(--dim)}
|
|
465
|
+
.steps .arrow{color:var(--dimmer);margin:0 2px}
|
|
466
|
+
|
|
467
|
+
/* progress + log shared by every job stream */
|
|
468
|
+
.progressbar{height:8px;background:rgba(255,255,255,.09);border-radius:5px;overflow:hidden}
|
|
469
|
+
.progressbar i{display:block;height:100%;width:0%;border-radius:5px;
|
|
470
|
+
background:linear-gradient(90deg,var(--cyan),var(--blue));transition:width .5s var(--ease)}
|
|
471
|
+
.progressbar.green i{background:linear-gradient(90deg,#a8ff9e,var(--green))}
|
|
472
|
+
.progmeta{display:flex;justify-content:space-between;font-size:12.5px;color:var(--dim);margin-top:8px}
|
|
473
|
+
.logbox{margin-top:18px;background:var(--code-bg-soft);border:1px solid var(--hairline-soft);border-radius:14px;
|
|
474
|
+
padding:14px 16px;max-height:340px;overflow-y:auto;font:11.5px/1.55 var(--mono);color:rgba(245,245,247,.7);white-space:pre-wrap;word-break:break-word}
|
|
475
|
+
.logbox:empty::before{content:"waiting for output…";color:var(--dimmer)}
|
|
476
|
+
|
|
477
|
+
/* shimmer skeletons */
|
|
478
|
+
.shimmer{background:linear-gradient(100deg,rgba(255,255,255,.04) 30%,rgba(255,255,255,.10) 50%,rgba(255,255,255,.04) 70%);
|
|
479
|
+
background-size:200% 100%;animation:sh 1.4s ease-in-out infinite;border-radius:8px;color:transparent!important}
|
|
480
|
+
@keyframes sh{0%{background-position:200% 0}100%{background-position:-200% 0}}
|
|
481
|
+
|
|
482
|
+
/* toasts */
|
|
483
|
+
#toasts{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);z-index:100;
|
|
484
|
+
display:flex;flex-direction:column;gap:10px;align-items:center;pointer-events:none}
|
|
485
|
+
.toast{background:var(--overlay-panel);backdrop-filter:blur(20px);border:1px solid var(--hairline);
|
|
486
|
+
border-radius:13px;padding:12px 18px;font-size:14px;font-weight:500;box-shadow:0 16px 50px rgba(0,0,0,.35);
|
|
487
|
+
animation:toastIn .4s var(--ease);max-width:min(560px,90vw)}
|
|
488
|
+
.toast.err{border-color:rgba(255,69,58,.5)}
|
|
489
|
+
.toast.ok{border-color:rgba(48,209,88,.5)}
|
|
490
|
+
@keyframes toastIn{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
/* empty state */
|
|
497
|
+
.empty{text-align:center;color:var(--dim);padding:60px 20px}
|
|
498
|
+
.empty h3{font-size:18px;font-weight:600;color:var(--ink);margin-bottom:8px;letter-spacing:-.01em}
|
|
499
|
+
.empty p{font-size:14px;max-width:46ch;margin:0 auto}
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
#chat-hamburger{display:none}
|
|
520
|
+
@media (max-width:760px){
|
|
521
|
+
#chat-hamburger{display:inline-flex}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
/* markdown-ish rendering — shared by chat bubbles AND the memory panel's
|
|
544
|
+
article view (.mem-article-render renders vault/Reference docs through
|
|
545
|
+
the same mdToHtml; without this scope the panel's code fences lost
|
|
546
|
+
their header chrome — "shCopy" mash, 2026-07-07 visual QA). */
|
|
547
|
+
:is(.bubble,.mem-article-render) p{margin:0 0 10px}:is(.bubble,.mem-article-render) p:last-child{margin-bottom:0}
|
|
548
|
+
:is(.bubble,.mem-article-render) ul,:is(.bubble,.mem-article-render) ol{margin:0 0 10px;padding-left:22px}
|
|
549
|
+
:is(.bubble,.mem-article-render) li{margin:3px 0}
|
|
550
|
+
:is(.bubble,.mem-article-render) strong{font-weight:700;color:var(--ink)}
|
|
551
|
+
:is(.bubble,.mem-article-render) em{font-style:italic}
|
|
552
|
+
:is(.bubble,.mem-article-render) code{font-family:var(--mono);font-size:.86em;background:rgba(127,127,127,.18);padding:2px 7px;border-radius:6px}
|
|
553
|
+
:is(.bubble,.mem-article-render) pre{background:var(--code-bg);color:var(--code-ink);border:1px solid var(--hairline-soft);border-radius:12px;
|
|
554
|
+
padding:13px 15px;overflow-x:auto;margin:10px 0;font:12.5px/1.6 var(--mono)}
|
|
555
|
+
:is(.bubble,.mem-article-render) pre code{background:none;padding:0;font-size:inherit;color:inherit}
|
|
556
|
+
:is(.bubble,.mem-article-render) h1,:is(.bubble,.mem-article-render) h2,:is(.bubble,.mem-article-render) h3,:is(.bubble,.mem-article-render) h4,:is(.bubble,.mem-article-render) h5,:is(.bubble,.mem-article-render) h6{font-weight:700;margin:14px 0 7px;letter-spacing:-.01em;line-height:1.3}
|
|
557
|
+
:is(.bubble,.mem-article-render) h1{font-size:1.28em}:is(.bubble,.mem-article-render) h2{font-size:1.16em}:is(.bubble,.mem-article-render) h3{font-size:1.06em}
|
|
558
|
+
:is(.bubble,.mem-article-render) h4,:is(.bubble,.mem-article-render) h5,:is(.bubble,.mem-article-render) h6{font-size:1em;color:var(--dim)}
|
|
559
|
+
:is(.bubble,.mem-article-render) h1:first-child,:is(.bubble,.mem-article-render) h2:first-child,:is(.bubble,.mem-article-render) h3:first-child{margin-top:0}
|
|
560
|
+
:is(.bubble,.mem-article-render) a{color:var(--cyan);text-decoration:none;border-bottom:1px solid rgba(100,210,255,.34)}
|
|
561
|
+
:is(.bubble,.mem-article-render) a:hover{border-bottom-color:var(--cyan)}
|
|
562
|
+
:is(.bubble,.mem-article-render) del{opacity:.55}
|
|
563
|
+
:is(.bubble,.mem-article-render) blockquote{margin:9px 0;padding:3px 14px;border-left:3px solid var(--hairline);color:var(--dim)}
|
|
564
|
+
:is(.bubble,.mem-article-render) blockquote p:last-child{margin-bottom:0}
|
|
565
|
+
:is(.bubble,.mem-article-render) hr{border:none;border-top:1px solid var(--hairline);margin:15px 0}
|
|
566
|
+
:is(.bubble,.mem-article-render) li.task{list-style:none;margin-left:-18px}
|
|
567
|
+
:is(.bubble,.mem-article-render) li.task input{margin-right:7px;accent-color:var(--blue);vertical-align:-1px}
|
|
568
|
+
:is(.bubble,.mem-article-render) .md-tablewrap{overflow-x:auto;margin:11px 0}
|
|
569
|
+
:is(.bubble,.mem-article-render) table.md-table{width:100%;border-collapse:collapse;font-size:.92em}
|
|
570
|
+
:is(.bubble,.mem-article-render) table.md-table th,:is(.bubble,.mem-article-render) table.md-table td{border:1px solid var(--hairline-soft);padding:6px 11px;text-align:left}
|
|
571
|
+
:is(.bubble,.mem-article-render) table.md-table th{background:rgba(255,255,255,.05);font-weight:600;color:var(--ink)}
|
|
572
|
+
:is(.bubble,.mem-article-render) .codeblock{margin:11px 0;border:1px solid var(--hairline-soft);border-radius:12px;overflow:hidden;background:var(--code-bg);color:var(--code-ink)}
|
|
573
|
+
:is(.bubble,.mem-article-render) .cbhead{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:5px 9px 5px 13px;background:rgba(255,255,255,.04);border-bottom:1px solid var(--hairline-soft)}
|
|
574
|
+
:is(.bubble,.mem-article-render) .cblang{font:11px/1 var(--mono);color:rgba(245,245,247,.65);letter-spacing:.02em}
|
|
575
|
+
:is(.bubble,.mem-article-render) .cbcopy{font:11px/1 var(--mono);color:rgba(245,245,247,.65);background:transparent;border:1px solid rgba(255,255,255,.2);border-radius:6px;padding:4px 10px;cursor:pointer;transition:color .15s,border-color .15s}
|
|
576
|
+
:is(.bubble,.mem-article-render) .cbcopy:hover{color:var(--code-ink);border-color:rgba(255,255,255,.4)}
|
|
577
|
+
:is(.bubble,.mem-article-render) .codeblock pre{margin:0;border:none;border-radius:0;background:transparent;color:inherit}
|
|
578
|
+
/* Canvas v1 (`02d723a:docs/design/web-chat-redesign.md` Appendix A,
|
|
579
|
+
beat-matrix Axis 2): Preview|Source toggle
|
|
580
|
+
for html/svg fences, sharing .cbhead with the existing lang tag + Copy
|
|
581
|
+
button. .cbhead keeps lang pinned left; the toggle+copy group sits
|
|
582
|
+
right via margin-left:auto on the first right-side element instead of
|
|
583
|
+
space-between, since space-between with 3 children would push the
|
|
584
|
+
toggle to the dead center of the bar. */
|
|
585
|
+
:is(.bubble,.mem-article-render) .cbhead{justify-content:flex-start}
|
|
586
|
+
:is(.bubble,.mem-article-render) .cbtoggle{display:inline-flex;gap:2px;margin-left:auto;padding:2px;border-radius:7px;background:rgba(255,255,255,.05)}
|
|
587
|
+
:is(.bubble,.mem-article-render) .cbview{font:11px/1 var(--mono);color:rgba(245,245,247,.55);background:transparent;border:none;
|
|
588
|
+
border-radius:5px;padding:4px 9px;cursor:pointer;transition:color .15s,background .15s}
|
|
589
|
+
:is(.bubble,.mem-article-render) .cbview:hover{color:var(--code-ink)}
|
|
590
|
+
:is(.bubble,.mem-article-render) .cbview.active{color:var(--code-ink);background:rgba(255,255,255,.14)}
|
|
591
|
+
/* has-canvas keeps Copy visually last, right after the toggle group. */
|
|
592
|
+
:is(.bubble,.mem-article-render) .codeblock.has-canvas .cbcopy{margin-left:2px}
|
|
593
|
+
:is(.bubble,.mem-article-render) .cbcanvas{position:relative;background:#fff}
|
|
594
|
+
:is(.bubble,.mem-article-render) .cbframe{display:block;width:100%;height:420px;min-height:160px;max-height:80vh;
|
|
595
|
+
border:none;resize:vertical;overflow:auto;background:#fff}
|
|
596
|
+
/* No layout shift on toggle: pre and cbcanvas are simply swapped via
|
|
597
|
+
[hidden] — the codeblock's own border/rounding stays put, and the
|
|
598
|
+
iframe's own default height (420px) plus resize:vertical means the
|
|
599
|
+
block doesn't jump when Preview first opens vs. later re-opens. */
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
/* loss chart */
|
|
694
|
+
.chartcard{margin-top:20px}
|
|
695
|
+
/* the chart's SVG gridlines are hardcoded white-on-dark (drawChart()), so
|
|
696
|
+
the wrap keeps the always-dark code-panel surface for contrast rather
|
|
697
|
+
than following the chat theme — same rationale as .bubble pre above. */
|
|
698
|
+
.chart-wrap{position:relative;background:var(--code-bg-soft);border:1px solid var(--hairline-soft);border-radius:14px;padding:14px;margin-top:6px}
|
|
699
|
+
.chart-legend{display:flex;gap:18px;font-size:12px;color:var(--dim);margin-bottom:8px}
|
|
700
|
+
.chart-legend .lg{display:inline-flex;align-items:center;gap:7px}
|
|
701
|
+
.chart-legend .sw{width:14px;height:3px;border-radius:2px}
|
|
702
|
+
.chart-stats{display:flex;gap:22px;flex-wrap:wrap;margin-top:12px;font-size:13px}
|
|
703
|
+
.chart-stats .cs b{display:block;font-size:11px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);margin-bottom:3px}
|
|
704
|
+
.chart-stats .cs span{font-size:20px;font-weight:700;letter-spacing:-.02em}
|
|
705
|
+
|
|
706
|
+
/* Tablet band (2026-07-06 jank fix): with up to 7 tabs (fewer once the
|
|
707
|
+
Developer toggle is off — see nav .tab[data-dev] above) +
|
|
708
|
+
hamburger + shortcuts + theme toggle + gear + conn pill, the tab row
|
|
709
|
+
can overflow well above the 900px cutoff — tighten tab padding first
|
|
710
|
+
so fewer widths need the scroll-fade at all. */
|
|
711
|
+
@media (max-width:1160px){
|
|
712
|
+
nav{gap:12px}
|
|
713
|
+
nav .tab{padding:8px 9px;font-size:13px}
|
|
714
|
+
}
|
|
715
|
+
@media (max-width:900px){
|
|
716
|
+
.hpgrid{grid-template-columns:1fr}
|
|
717
|
+
nav .model{display:none}
|
|
718
|
+
.wrap{padding:34px 18px 100px}
|
|
719
|
+
nav{gap:12px;padding:0 16px}
|
|
720
|
+
/* Icon-only theme toggle a bit earlier than 560px — the nav is already
|
|
721
|
+
tight here (hamburger + shortcuts + toggle + hf-gear + conn pill) and
|
|
722
|
+
"Auto" as a text label isn't worth the horizontal cost at this width.
|
|
723
|
+
The ◐ tt-icon stands in so the Auto button never renders as an empty
|
|
724
|
+
sliver (2026-07-06 QA finding). */
|
|
725
|
+
#theme-toggle button{padding:0 7px;font-size:15px}
|
|
726
|
+
#theme-toggle .tt-label{display:none}
|
|
727
|
+
#theme-toggle .tt-icon{display:inline}
|
|
728
|
+
/* Developer toggle: dot-only past this width, same reasoning as the
|
|
729
|
+
theme toggle above — "Developer" as a text label costs more than
|
|
730
|
+
the dot alone conveys once the row is already tight. */
|
|
731
|
+
#nav-developer span:not(.nd-dot){display:none}
|
|
732
|
+
#nav-developer{padding:0;width:34px;justify-content:center}
|
|
733
|
+
}
|
|
734
|
+
@media (max-width:760px){
|
|
735
|
+
/* Touch band (2026-07-06 QA): a keyboard-shortcut sheet button is dead
|
|
736
|
+
weight on touch viewports, and the nav needs its width back. */
|
|
737
|
+
#nav-shortcuts{display:none}
|
|
738
|
+
/* The conn pill collapses to its status dot (title keeps the text for
|
|
739
|
+
long-press/hover); "live · localhost" was clipping at the viewport
|
|
740
|
+
edge at 375px. */
|
|
741
|
+
#nav-conn #nav-conn-text{display:none}
|
|
742
|
+
#nav-conn{padding:6px 9px}
|
|
743
|
+
/* Keep a scrollable strip of tabs alive — flex shrank them to 0 width
|
|
744
|
+
at phone sizes, silently removing Quantize/Status navigation. The
|
|
745
|
+
scroll-fade masks signal the rest. With the Developer toggle off
|
|
746
|
+
(the fresh-browser default) this row can be just the single Chat
|
|
747
|
+
tab — min-width still holds so the fade-mask math in
|
|
748
|
+
updateTabFades() never divides against a zero-width strip. */
|
|
749
|
+
nav .tabs{min-width:96px}
|
|
750
|
+
}
|
|
751
|
+
@media (max-width:560px){
|
|
752
|
+
nav .brand{font-size:16px}
|
|
753
|
+
nav .tab{padding:8px 10px;font-size:13px}
|
|
754
|
+
nav .right{gap:6px}
|
|
755
|
+
.icon-btn,.hf-gear{width:30px;height:30px}
|
|
756
|
+
/* Phones follow the system theme (Auto is the default); the explicit
|
|
757
|
+
3-way toggle returns ≥560px. Freeing its ~110px is what keeps the
|
|
758
|
+
tab strip + status dot inside a 375px viewport (2026-07-06 QA). */
|
|
759
|
+
#theme-toggle{display:none}
|
|
760
|
+
}
|
|
761
|
+
</style>
|
|
762
|
+
<!-- Vendored syntax-highlighting theme (apps/mlx-bun/src/web/public/vendor/hljs-theme.css,
|
|
763
|
+
hand-derived from the design tokens above — see that file's header). No CDN;
|
|
764
|
+
served by apps/mlx-bun/src/web/assets.ts alongside this page. -->
|
|
765
|
+
<link rel="stylesheet" href="/assets/hljs.css">
|
|
766
|
+
<!-- PWA installability (`02d723a:docs/design/web-chat-redesign.md` Appendix A,
|
|
767
|
+
beat-matrix Axis 10): manifest +
|
|
768
|
+
inline SVG icon (apps/mlx-bun/src/web/public/manifest.webmanifest,
|
|
769
|
+
apps/mlx-bun/src/web/public/icon.svg — no binary PNGs, per the hygiene gate;
|
|
770
|
+
some browsers won't render an SVG app icon and that's an accepted tradeoff).
|
|
771
|
+
theme-color matches the app's --bg token so the OS chrome doesn't
|
|
772
|
+
flash a mismatched color on launch. -->
|
|
773
|
+
<link rel="manifest" href="/manifest.webmanifest">
|
|
774
|
+
<link rel="icon" href="/assets/icon.svg" type="image/svg+xml">
|
|
775
|
+
<link rel="apple-touch-icon" href="/assets/icon.svg">
|
|
776
|
+
<meta name="theme-color" content="#000000">
|
|
777
|
+
</head>
|
|
778
|
+
<body>
|
|
779
|
+
<div class="bloom" id="bloom"></div>
|
|
780
|
+
|
|
781
|
+
<!-- ═══════════════════ TOP NAV ═══════════════════ -->
|
|
782
|
+
<nav>
|
|
783
|
+
<!-- Mobile drawer trigger — chat route only (CSS keeps it hidden ≥760px
|
|
784
|
+
and JS keeps it hidden off the chat route, since there is no
|
|
785
|
+
sidebar to open elsewhere). aria-controls/expanded kept in sync by
|
|
786
|
+
the drawer open/close functions. -->
|
|
787
|
+
<button class="icon-btn" id="chat-hamburger" title="Open recent chats" aria-label="Open recent chats"
|
|
788
|
+
aria-controls="chat-sidebar" aria-expanded="false">
|
|
789
|
+
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
|
|
790
|
+
</button>
|
|
791
|
+
<a class="brand grad g-hero" href="#/chat">mlx-bun</a>
|
|
792
|
+
<div class="tabs" id="tabs">
|
|
793
|
+
<a class="tab" href="#/status" data-tab="status" data-dev>Status</a>
|
|
794
|
+
<a class="tab" href="#/routes" data-tab="routes" data-dev>Routes</a>
|
|
795
|
+
</div>
|
|
796
|
+
<div class="right">
|
|
797
|
+
<!-- Developer toggle: collapses Quantize/Fine-tune/
|
|
798
|
+
Build Dataset/Status/Curves/Routes behind one switch. State + the
|
|
799
|
+
one-time existing-user default live in shell.ts's
|
|
800
|
+
initDeveloperToggle/isDeveloperMode. -->
|
|
801
|
+
<button id="nav-developer" data-spotlight="developer-toggle" type="button" role="switch" aria-checked="false"
|
|
802
|
+
title="Show developer tools (Quantize, Fine-tune, Build Dataset, Status, Curves, Routes)"
|
|
803
|
+
aria-label="Toggle developer tools">
|
|
804
|
+
<span class="nd-dot" id="nav-developer-dot" aria-hidden="true"></span><span>Developer</span>
|
|
805
|
+
</button>
|
|
806
|
+
<button class="icon-btn" id="nav-shortcuts" title="Keyboard shortcuts (Cmd/Ctrl+/)" aria-label="Keyboard shortcuts"
|
|
807
|
+
aria-haspopup="dialog" aria-controls="shortcut-overlay" aria-expanded="false">
|
|
808
|
+
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="6" width="20" height="12" rx="2"></rect><path d="M6 10h.01M10 10h.01M14 10h.01M18 10h.01M6 14h12"></path></svg>
|
|
809
|
+
</button>
|
|
810
|
+
<!-- 3-way theme toggle: auto follows prefers-color-scheme,
|
|
811
|
+
dark/light are explicit user overrides — all persisted to
|
|
812
|
+
localStorage by setTheme() below. -->
|
|
813
|
+
<div id="theme-toggle" role="group" aria-label="Theme">
|
|
814
|
+
<button type="button" data-theme-choice="auto" title="Match system theme" aria-label="Auto theme"><span class="tt-icon" aria-hidden="true">◐</span><span class="tt-label">Auto</span></button>
|
|
815
|
+
<button type="button" data-theme-choice="dark" title="Dark theme" aria-label="Dark theme">🌙</button>
|
|
816
|
+
<button type="button" data-theme-choice="light" title="Light theme" aria-label="Light theme">☀️</button>
|
|
817
|
+
</div>
|
|
818
|
+
<button class="hf-gear" id="nav-hf" title="Hugging Face token settings" aria-label="Hugging Face settings">
|
|
819
|
+
<svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
|
820
|
+
</button>
|
|
821
|
+
<!-- The active model; clicking it opens the Models page (the models module's panel). -->
|
|
822
|
+
<button class="model" id="nav-model" data-spotlight="model-picker" type="button" title="active model — click to manage models">connecting…</button>
|
|
823
|
+
<span class="pill" id="nav-conn"><span class="dot"></span><span id="nav-conn-text">connecting…</span></span>
|
|
824
|
+
<span class="pill" id="nav-download" style="display:none" title="A more capable model is downloading in the background"><span class="dot"></span><span id="nav-download-text"></span></span>
|
|
825
|
+
</div>
|
|
826
|
+
</nav>
|
|
827
|
+
|
|
828
|
+
<!-- ═══════════════════ SETTINGS OVERLAY ═══════════════════
|
|
829
|
+
(was "HF settings" — widened in place for the Agent tools section.
|
|
830
|
+
Same ids/behavior for the HF piece; nothing
|
|
831
|
+
about push-to-hub or the hf-* wiring changed.) -->
|
|
832
|
+
<div id="hf-overlay">
|
|
833
|
+
<div id="hf-modal" role="dialog" aria-modal="true" aria-labelledby="hf-modal-title-el">
|
|
834
|
+
<div class="hf-modal-head">
|
|
835
|
+
<div class="hf-modal-title" id="hf-modal-title-el">Settings</div>
|
|
836
|
+
<button class="hf-close" id="hf-close" aria-label="Close">✕</button>
|
|
837
|
+
</div>
|
|
838
|
+
|
|
839
|
+
<!-- Agent tools: the codingTools opt-in + the durable
|
|
840
|
+
always-allow list. Lives above Hugging Face since it's the more
|
|
841
|
+
chat-relevant setting. -->
|
|
842
|
+
<div class="settings-section">
|
|
843
|
+
<h3 class="settings-h">Agent tools</h3>
|
|
844
|
+
<label class="chk settings-toggle-row" for="settings-coding-tools">
|
|
845
|
+
<input type="checkbox" id="settings-coding-tools">
|
|
846
|
+
<span>Let the agent touch files on this machine</span>
|
|
847
|
+
</label>
|
|
848
|
+
<div class="hint">
|
|
849
|
+
Off by default. When on, the chat assistant can run shell commands and
|
|
850
|
+
edit or create files — each one asks first, in the chat, unless you
|
|
851
|
+
choose "always allow" for that action. Nothing runs without your
|
|
852
|
+
review the first time.
|
|
853
|
+
</div>
|
|
854
|
+
<p class="settings-note" id="settings-coding-tools-note" style="display:none"></p>
|
|
855
|
+
<div id="settings-approvals-list"></div>
|
|
856
|
+
</div>
|
|
857
|
+
|
|
858
|
+
<div class="settings-section">
|
|
859
|
+
<h3 class="settings-h">Hugging Face</h3>
|
|
860
|
+
<p class="hf-modal-sub" id="hf-state">Checking for a saved token…</p>
|
|
861
|
+
<div class="field" style="margin-bottom:10px">
|
|
862
|
+
<label>Write token</label>
|
|
863
|
+
<input type="password" id="hf-token-input" placeholder="hf_…" autocomplete="off" spellcheck="false">
|
|
864
|
+
<div class="hint">A <strong>write</strong> token from huggingface.co/settings/tokens. Stored locally at <code>~/.mlx-bun/hf.json</code> — never sent anywhere but your own Hub pushes.</div>
|
|
865
|
+
</div>
|
|
866
|
+
<div id="hf-settings-msg"></div>
|
|
867
|
+
<div class="btnrow" style="margin-top:14px">
|
|
868
|
+
<button class="btn primary sm" id="hf-save">Save token</button>
|
|
869
|
+
</div>
|
|
870
|
+
</div>
|
|
871
|
+
</div>
|
|
872
|
+
</div>
|
|
873
|
+
|
|
874
|
+
<!-- ═══════════════════ KEYBOARD SHORTCUT SHEET ═══════════════════ -->
|
|
875
|
+
<div id="shortcut-overlay">
|
|
876
|
+
<div id="shortcut-modal" role="dialog" aria-modal="true" aria-labelledby="sk-modal-title">
|
|
877
|
+
<div class="sk-head">
|
|
878
|
+
<div class="sk-title" id="sk-modal-title">Keyboard shortcuts</div>
|
|
879
|
+
<button class="sk-close" id="sk-close" aria-label="Close">✕</button>
|
|
880
|
+
</div>
|
|
881
|
+
<div class="sk-row"><span class="sk-desc">Show this shortcut sheet</span><span class="sk-keys"><span class="sk-key" id="sk-mod-label">⌘</span><span class="sk-key">/</span></span></div>
|
|
882
|
+
<div class="sk-row"><span class="sk-desc">New chat</span><span class="sk-keys"><span class="sk-key sk-mod"></span><span class="sk-key">Shift</span><span class="sk-key">O</span></span></div>
|
|
883
|
+
<div class="sk-row"><span class="sk-desc">Focus the composer</span><span class="sk-keys"><span class="sk-key">Shift</span><span class="sk-key">Esc</span></span></div>
|
|
884
|
+
<div class="sk-row"><span class="sk-desc">Copy last response</span><span class="sk-keys"><span class="sk-key sk-mod"></span><span class="sk-key">Shift</span><span class="sk-key">C</span></span></div>
|
|
885
|
+
<div class="sk-row"><span class="sk-desc">Send message</span><span class="sk-keys"><span class="sk-key">Enter</span></span></div>
|
|
886
|
+
<div class="sk-row"><span class="sk-desc">New line in composer</span><span class="sk-keys"><span class="sk-key">Shift</span><span class="sk-key">Enter</span></span></div>
|
|
887
|
+
<div class="sk-row"><span class="sk-desc">Close popover / drawer / sheet</span><span class="sk-keys"><span class="sk-key">Esc</span></span></div>
|
|
888
|
+
</div>
|
|
889
|
+
</div>
|
|
890
|
+
|
|
891
|
+
<!-- The chat is the module panel (`@mlx-bun/module-chat`): the shell mounts it as the first page. -->
|
|
892
|
+
|
|
893
|
+
<div id="app">
|
|
894
|
+
|
|
895
|
+
<!-- The chat workspace panel is mounted by the shell. -->
|
|
896
|
+
|
|
897
|
+
<!-- ═══════════════════ QUANTIZE ═══════════════════ -->
|
|
898
|
+
|
|
899
|
+
<!-- ═══════════════════ FINE-TUNE ═══════════════════ -->
|
|
900
|
+
|
|
901
|
+
<!-- ═══════════════════ DATASET ═══════════════════ -->
|
|
902
|
+
|
|
903
|
+
<!-- ═══════════════════ STATUS ═══════════════════ -->
|
|
904
|
+
<section data-route="status" id="s-status">
|
|
905
|
+
<div class="scroller"><div class="wrap" id="status-page">
|
|
906
|
+
|
|
907
|
+
<div style="text-align:center;margin-bottom:18px" data-reveal>
|
|
908
|
+
<div class="eyebrow" style="margin-bottom:18px">local ai · apple silicon · one binary</div>
|
|
909
|
+
<h1 class="title grad g-hero" style="font-size:clamp(48px,8vw,110px)">mlx-bun</h1>
|
|
910
|
+
<p class="lead" style="margin:18px auto 0;text-align:center">The Python-free local AI engine. <strong>Bun + MLX, nothing else.</strong></p>
|
|
911
|
+
</div>
|
|
912
|
+
|
|
913
|
+
<section style="margin-top:56px" data-reveal>
|
|
914
|
+
<h2>Now serving<span class="soft">.</span></h2>
|
|
915
|
+
<div class="grid g4" style="margin-top:24px">
|
|
916
|
+
<div class="card" id="st-model-card" style="grid-column:1 / -1;display:flex;flex-wrap:wrap;align-items:baseline;gap:14px 26px">
|
|
917
|
+
<div><h3>Model</h3><div id="st-model-id" style="font-size:clamp(20px,2.6vw,32px);font-weight:700;letter-spacing:-.02em;word-break:break-all">—</div></div>
|
|
918
|
+
<div id="st-model-meta" style="font-size:14.5px;color:var(--dim);font-weight:500">—</div>
|
|
919
|
+
</div>
|
|
920
|
+
<div class="card">
|
|
921
|
+
<h3>Decode · predicted</h3>
|
|
922
|
+
<div class="stat num grad g-green"><span id="st-tps">—</span><small>tok/s</small></div>
|
|
923
|
+
<div class="cap" id="st-tps-cap">from weights ÷ bandwidth on this machine</div>
|
|
924
|
+
</div>
|
|
925
|
+
<div class="card">
|
|
926
|
+
<h3>Max safe context</h3>
|
|
927
|
+
<div class="stat num grad g-blue"><span id="st-safe-ctx">—</span><small>tokens</small></div>
|
|
928
|
+
<div class="cap">solved from KV growth + prefill transient, never guessed</div>
|
|
929
|
+
</div>
|
|
930
|
+
<div class="card">
|
|
931
|
+
<h3>Memory</h3>
|
|
932
|
+
<div class="kv"><b>weights</b><span class="num" id="st-weights">—</span></div>
|
|
933
|
+
<div class="kv"><b>usable</b><span class="num" id="st-usable">—</span></div>
|
|
934
|
+
<div class="kv"><b>budget</b><span class="num" id="st-budget">—</span></div>
|
|
935
|
+
<div class="meter warm"><i id="st-mem-bar"></i></div>
|
|
936
|
+
</div>
|
|
937
|
+
<div class="card">
|
|
938
|
+
<h3>Prompt cache</h3>
|
|
939
|
+
<div class="kv"><b>hit rate</b><span class="num" id="st-pc-hits">—</span></div>
|
|
940
|
+
<div class="kv"><b>entries</b><span class="num" id="st-pc-entries">—</span></div>
|
|
941
|
+
<div class="kv"><b>bytes</b><span class="num" id="st-pc-bytes">—</span></div>
|
|
942
|
+
<div class="meter"><i id="st-pc-bar"></i></div>
|
|
943
|
+
</div>
|
|
944
|
+
<div class="card">
|
|
945
|
+
<h3>Response store</h3>
|
|
946
|
+
<div class="kv"><b>entries</b><span class="num" id="st-rs-entries">—</span></div>
|
|
947
|
+
<div class="kv"><b>bytes</b><span class="num" id="st-rs-bytes">—</span></div>
|
|
948
|
+
<div class="kv"><b>ttl</b><span class="num" id="st-rs-ttl">—</span></div>
|
|
949
|
+
<div class="meter"><i id="st-rs-bar"></i></div>
|
|
950
|
+
</div>
|
|
951
|
+
<div class="card">
|
|
952
|
+
<h3>KV quantization</h3>
|
|
953
|
+
<div class="kv"><b>mode</b><span id="st-kv-mode">—</span></div>
|
|
954
|
+
<div id="st-kv-layers"></div>
|
|
955
|
+
</div>
|
|
956
|
+
<div class="card" id="st-expert-card" style="display:none">
|
|
957
|
+
<h3>Expert tiers · last turn</h3>
|
|
958
|
+
<div class="kv"><b>main cache hit</b><span class="num" id="st-expert-main-hit">—</span></div>
|
|
959
|
+
<div class="kv"><b>main SSD read</b><span class="num" id="st-expert-main-read">—</span></div>
|
|
960
|
+
<div class="kv"><b>MTP cache hit</b><span class="num" id="st-expert-mtp-hit">—</span></div>
|
|
961
|
+
<div class="kv"><b>MTP SSD read</b><span class="num" id="st-expert-mtp-read">—</span></div>
|
|
962
|
+
<div class="cap" id="st-expert-residency">waiting for the first completed turn</div>
|
|
963
|
+
</div>
|
|
964
|
+
<div class="card" id="st-dl-card" style="grid-column:1 / -1;display:none">
|
|
965
|
+
<h3>Downloads</h3>
|
|
966
|
+
<div id="st-dl-list"></div>
|
|
967
|
+
</div>
|
|
968
|
+
</div>
|
|
969
|
+
</section>
|
|
970
|
+
|
|
971
|
+
<section style="margin-top:80px" data-reveal>
|
|
972
|
+
<h2>Library<span class="soft">.</span> <span class="grad g-green">Every model, assessed.</span></h2>
|
|
973
|
+
<p class="lead">Everything in the local cache, each judged by the fit solver for <strong>this machine</strong>.</p>
|
|
974
|
+
<div class="card tablecard" style="margin-top:26px">
|
|
975
|
+
<table>
|
|
976
|
+
<thead><tr><th>Model</th><th>Size</th><th>Status</th><th>Max context</th><th>Decode</th></tr></thead>
|
|
977
|
+
<tbody id="st-lib-body"><tr><td colspan="5" style="text-align:center;color:var(--dimmer)">waiting for server…</td></tr></tbody>
|
|
978
|
+
</table>
|
|
979
|
+
</div>
|
|
980
|
+
</section>
|
|
981
|
+
|
|
982
|
+
<section style="margin-top:80px" data-reveal>
|
|
983
|
+
<h2>Will it fit<span class="soft">?</span> <span class="grad g-blue">Solved, not guessed.</span></h2>
|
|
984
|
+
<p class="lead">Weights + KV growth + prefill transient against wired memory — the same assessment that gates every request.</p>
|
|
985
|
+
<div class="grid g4" style="margin:26px 0 14px">
|
|
986
|
+
<div class="card">
|
|
987
|
+
<h3>This machine</h3>
|
|
988
|
+
<div class="kv"><b>RAM</b><span class="num" id="st-m-ram">—</span></div>
|
|
989
|
+
<div class="kv"><b>bandwidth</b><span class="num" id="st-m-bw">—</span></div>
|
|
990
|
+
<div class="kv"><b>verdict</b><span id="st-m-fits">—</span></div>
|
|
991
|
+
</div>
|
|
992
|
+
<div class="card">
|
|
993
|
+
<h3>At max context · <span class="num" id="st-fit-ctx">—</span> tokens</h3>
|
|
994
|
+
<div class="kv" data-plan-fit style="display:none"><b>artifact on disk</b><span class="num" id="st-f-artifact">—</span></div>
|
|
995
|
+
<div class="kv"><b id="st-f-weights-label">weights</b><span class="num" id="st-f-weights">—</span></div>
|
|
996
|
+
<div id="st-f-streamed"></div>
|
|
997
|
+
<div class="kv"><b>kv cache</b><span class="num" id="st-f-kv">—</span></div>
|
|
998
|
+
<div class="kv"><b id="st-f-transient-label">transient</b><span class="num" id="st-f-transient">—</span></div>
|
|
999
|
+
<div class="kv"><b>total / usable</b><span class="num" id="st-f-total">—</span></div>
|
|
1000
|
+
<div class="meter"><i id="st-fit-bar"></i></div>
|
|
1001
|
+
</div>
|
|
1002
|
+
</div>
|
|
1003
|
+
<div class="card tablecard">
|
|
1004
|
+
<table>
|
|
1005
|
+
<thead><tr><th>Apple silicon · this model @ <span class="num" id="st-sku-ctx">32,768</span> ctx</th>
|
|
1006
|
+
<th>RAM</th><th>Fits</th><th>Max context</th><th>Decode</th></tr></thead>
|
|
1007
|
+
<tbody id="st-sku-body"><tr><td colspan="5" style="text-align:center;color:var(--dimmer)">waiting for server…</td></tr></tbody>
|
|
1008
|
+
</table>
|
|
1009
|
+
</div>
|
|
1010
|
+
</section>
|
|
1011
|
+
|
|
1012
|
+
<footer style="margin-top:90px;border-top:1px solid var(--hairline);padding-top:26px;display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;font-size:13px;color:var(--dimmer)">
|
|
1013
|
+
<span>mlx-bun · M-series Macs · no Python anywhere in the serving path</span>
|
|
1014
|
+
<span>server up <span id="st-uptime">—</span> · updated <span id="st-updated">never</span></span>
|
|
1015
|
+
</footer>
|
|
1016
|
+
</div></div>
|
|
1017
|
+
</section>
|
|
1018
|
+
|
|
1019
|
+
<!-- ═══════════════════ ROUTES ═══════════════════ -->
|
|
1020
|
+
<!-- `02d723a:docs/archive/planning/web-ui-pass-plan.md` #17: /dag 404s outside a repo checkout (readFileSync
|
|
1021
|
+
on a repo-relative doc, absent from compiled binaries/npm installs).
|
|
1022
|
+
shell.ts's initRoutesProbe() HEAD-checks /dag at boot: on success this
|
|
1023
|
+
iframe renders as-is; on 404 it hides the Routes tab and swaps this
|
|
1024
|
+
section's innerHTML for a graceful note instead of a raw 404 iframe.
|
|
1025
|
+
Could instead embed the artifact server-side like /curves' fallback
|
|
1026
|
+
does. -->
|
|
1027
|
+
<section data-route="routes" id="s-routes">
|
|
1028
|
+
<iframe src="/dag" title="Training · inference route map"
|
|
1029
|
+
style="width:100%;height:100%;border:0;display:block"></iframe>
|
|
1030
|
+
</section>
|
|
1031
|
+
|
|
1032
|
+
</div>
|
|
1033
|
+
|
|
1034
|
+
<div id="toasts"></div>
|
|
1035
|
+
|
|
1036
|
+
<!-- Vendored syntax highlighter (apps/mlx-bun/src/web/public/vendor/hljs.js — highlight.js core +
|
|
1037
|
+
a curated language set, BSD-3-Clause, see that file's header). `defer`
|
|
1038
|
+
means this loads/executes at DOMContentLoaded, which happens well before
|
|
1039
|
+
any real highlighting call (those only fire later, on streamed content
|
|
1040
|
+
or history replay) — app.js (below) only *calls* highlightIn() from
|
|
1041
|
+
async event handlers, so load order here is safe in practice.
|
|
1042
|
+
highlightIn() still guards with `typeof hljs !== "undefined"` for the
|
|
1043
|
+
case this tag is ever stripped or the asset 404s. No CDN; served by
|
|
1044
|
+
apps/mlx-bun/src/web/assets.ts at /assets/hljs.js. -->
|
|
1045
|
+
<script defer src="/assets/hljs.js"></script>
|
|
1046
|
+
<!-- The app itself: GENERATED bundle of the src/web/browser/*.ts
|
|
1047
|
+
module split, built by `bun run --filter mlx-bun build:web` into dist/web/app.js
|
|
1048
|
+
and served by apps/mlx-bun/src/web/assets.ts at /assets/app.js — see that file's header
|
|
1049
|
+
comment. `defer` (like hljs.js above) means both scripts run in document
|
|
1050
|
+
order at DOMContentLoaded, after the DOM this script queries with $()
|
|
1051
|
+
is fully parsed. Edit src/web/browser/*.ts, never this bundle or this tag. -->
|
|
1052
|
+
<script defer src="/assets/app.js"></script>
|
|
1053
|
+
</body>
|
|
1054
|
+
</html>
|