mlx-bun 0.0.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -578
- package/bin/mlx-bun.mjs +1 -1
- package/docs/README.md +91 -0
- package/docs/{design → archive}/hlg-sampling.md +3 -3
- package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
- package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
- package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
- package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
- package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
- package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
- package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
- package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
- package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
- package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
- package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
- package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
- package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
- package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
- package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
- package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
- package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
- package/docs/design/batching.md +569 -0
- package/docs/design/decode-speed-program.md +3178 -169
- package/docs/design/dreaming-nightly-pipeline.md +675 -282
- package/docs/design/generic-model-support.md +579 -334
- package/docs/design/kv-cache.md +680 -0
- package/docs/design/orpo-training.md +673 -1239
- package/docs/design/speculative-decoding.md +1627 -0
- package/docs/design/turboquant.md +2102 -0
- package/docs/design/unified-engine-frontier-plan.md +1831 -727
- package/docs/design/web-chat-redesign.md +666 -1083
- package/docs/planning/PRODUCT_ROADMAP.md +34 -1
- package/docs/planning/release-notes-v0.3.0.md +35 -0
- package/docs/planning/video-series.md +421 -0
- package/docs/reference/benchmarks.md +1162 -0
- package/docs/reference/cli.md +395 -149
- package/docs/reference/distribution.md +321 -181
- package/docs/reference/environment.md +348 -0
- package/docs/reference/glossary.md +39 -0
- package/docs/reference/library-api.md +580 -142
- package/docs/reference/memory.md +227 -64
- package/docs/reference/models.md +137 -6
- package/docs/reference/server-api.md +938 -422
- package/docs/reference/server-config.md +652 -320
- package/docs/reference/training.md +393 -254
- package/docs/reference/troubleshooting.md +166 -0
- package/package.json +10 -5
- package/src/admission-plan.ts +18 -0
- package/src/anthropic.ts +92 -3
- package/src/audio/decode.ts +2 -2
- package/src/audio/features.ts +2 -2
- package/src/backends/mlx/autoregressive.ts +108 -0
- package/src/backends/mlx/batch-group.ts +1646 -0
- package/src/backends/mlx/diffusion.ts +39 -0
- package/src/backends/mlx/draft-target.ts +47 -0
- package/src/backends/mlx/evaluation.ts +105 -0
- package/src/backends/mlx/fill-append.ts +45 -0
- package/src/backends/mlx/gateway-binding.ts +71 -0
- package/src/backends/mlx/graph.ts +38 -0
- package/src/backends/mlx/memory-client.ts +189 -0
- package/src/backends/mlx/memory-guard.ts +40 -0
- package/src/backends/mlx/methods.ts +90 -0
- package/src/backends/mlx/model-prompt.ts +164 -0
- package/src/backends/mlx/model-serving.ts +79 -0
- package/src/backends/mlx/prefill.ts +33 -0
- package/src/backends/mlx/request-policy.ts +20 -0
- package/src/backends/mlx/rollback.ts +51 -0
- package/src/backends/mlx/serial-executor.ts +273 -0
- package/src/backends/mlx/speculative.ts +114 -0
- package/src/backends/mlx/state-views.ts +26 -0
- package/src/backends/mlx/text-engine.ts +73 -0
- package/src/cli.ts +189 -61
- package/src/client.ts +66 -0
- package/src/config.ts +21 -4
- package/src/contracts/completion.ts +16 -0
- package/src/contracts/execution.ts +49 -0
- package/src/contracts/generation.ts +103 -0
- package/src/contracts/host.ts +7 -0
- package/src/contracts/jobs.ts +66 -0
- package/src/contracts/pi-provider.ts +30 -0
- package/src/contracts/pi.ts +259 -0
- package/src/contracts/resources.ts +18 -0
- package/src/contracts/scheduling.ts +27 -0
- package/src/contracts/tsconfig.json +14 -0
- package/src/diffusion/diffusion-generate.ts +218 -153
- package/src/embed.ts +1 -1
- package/src/engine/admission.ts +59 -0
- package/src/engine/cancellation.ts +38 -0
- package/src/engine/engine.ts +56 -0
- package/src/engine/execution-coordinator.ts +70 -0
- package/src/engine/execution-plan.ts +51 -0
- package/src/engine/resources.ts +42 -0
- package/src/engine/scheduler.ts +67 -0
- package/src/engine/session.ts +247 -0
- package/src/eval/README.md +44 -1
- package/src/eval/kl.ts +263 -23
- package/src/eval/reference-logits.ts +207 -0
- package/src/eval/runner.ts +10 -79
- package/src/eval/tasks/bfcl.ts +2 -1
- package/src/eval/tasks/gsm8k.ts +2 -1
- package/src/eval/tasks/hashhop.ts +2 -1
- package/src/eval/tasks/humaneval.ts +5 -4
- package/src/eval/tasks/ifeval.ts +2 -1
- package/src/eval/tasks/mmlu.ts +2 -1
- package/src/expert-io.ts +3 -1
- package/src/expert-offload.ts +3 -1
- package/src/fill/echo-index.ts +188 -0
- package/src/fill/fill-session.ts +452 -0
- package/src/fill/proposal.ts +68 -0
- package/src/fill/schema-rows.ts +506 -0
- package/src/fill/tool-boundary.ts +103 -0
- package/src/fit.ts +24 -43
- package/src/generate.ts +740 -337
- package/src/grammar.ts +14 -8
- package/src/harness-pi.ts +15 -34
- package/src/hub-rest.ts +4 -4
- package/src/index.ts +27 -0
- package/src/inference/denoising.ts +17 -0
- package/src/inference/graph.ts +33 -0
- package/src/inference/prefill.ts +39 -0
- package/src/inference/rollback.ts +7 -0
- package/src/jobs/db.ts +4 -0
- package/src/jobs/index.ts +2 -0
- package/src/jobs/job-entry.ts +15 -14
- package/src/jobs/runner.ts +98 -13
- package/src/jobs/task-client.ts +19 -0
- package/src/jobs/types.ts +2 -58
- package/src/kv-scheme.ts +199 -0
- package/src/kv-store.ts +459 -234
- package/src/lab/README.md +18 -0
- package/src/{assets → lab/curve}/curve-designer.html +2 -2
- package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
- package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
- package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
- package/src/library.ts +40 -0
- package/src/lora.ts +18 -0
- package/src/media-fetch.ts +20 -4
- package/src/memory/article.ts +1 -1
- package/src/memory/chunk.ts +1 -1
- package/src/memory/model.ts +32 -170
- package/src/memory/prompts.ts +1 -1
- package/src/memory/rest.ts +1 -1
- package/src/memory/schedule.ts +1 -1
- package/src/memory/stages.ts +4 -1
- package/src/memory/vault.ts +3 -4
- package/src/mlx/array.ts +9 -10
- package/src/mlx/compile.ts +12 -2
- package/src/mlx/ffi.ts +66 -22
- package/src/mlx/materialize.ts +23 -0
- package/src/mlx/metal-kernel.ts +10 -11
- package/src/mlx/ops.ts +64 -19
- package/src/mlx/quantized-rows.ts +36 -0
- package/src/mlx/token-bitmask.ts +52 -0
- package/src/mlx/turboquant-kv-decode.ts +82 -0
- package/src/mlx/turboquant-kv-inverse.ts +122 -0
- package/src/mlx/turboquant-ops.ts +33 -3
- package/src/mlx/turboquant-tables.ts +2 -2
- package/src/model/batched-mask.ts +9 -3
- package/src/model/batched-quant.ts +2 -2
- package/src/model/batched-rotating-quant.ts +45 -99
- package/src/model/batched-rotating-state.ts +73 -0
- package/src/model/batched-rotating.ts +57 -106
- package/src/model/batched-row-storage.ts +127 -0
- package/src/model/compiled-decode.ts +4 -3
- package/src/model/diffusion-gemma.ts +8 -8
- package/src/model/factory.ts +87 -49
- package/src/model/fingerprint.ts +1 -1
- package/src/model/flash-attention.ts +3 -3
- package/src/model/gemma4-base.ts +187 -17
- package/src/model/gemma4.ts +6 -6
- package/src/model/generated/gemma4-12b.ts +52 -148
- package/src/model/generated/gemma4-26b.ts +34 -94
- package/src/model/generated/gemma4-e4b.ts +28 -76
- package/src/model/glm52-cache.ts +19 -9
- package/src/model/glm52-dsa.ts +13 -9
- package/src/model/glm52-memory.ts +28 -1
- package/src/model/implementation.ts +69 -0
- package/src/model/minicpm5.ts +7 -8
- package/src/model/profile.ts +443 -0
- package/src/model/qwen-append.ts +12 -0
- package/src/model/qwen-conv.ts +52 -0
- package/src/model/qwen3-delta.ts +98 -2
- package/src/model/qwen3-mrope.ts +252 -0
- package/src/model/qwen3_5-checkpoint.ts +164 -0
- package/src/model/qwen3_5.ts +336 -60
- package/src/model/support.ts +1 -1
- package/src/model/trellis-balanced-scatter.ts +51 -0
- package/src/model/trellis-linear.ts +672 -0
- package/src/model/trellis-shared-m.ts +151 -0
- package/src/model/trellis-shared-scatter.ts +144 -0
- package/src/model/trellis-splitk-prefill.ts +158 -0
- package/src/model/trellis-tiled-prefill.ts +136 -0
- package/src/model/trellis-vector-expand.ts +62 -0
- package/src/model/trellis-wide-prefill.ts +94 -0
- package/src/model/universal/dense.ts +1 -1
- package/src/model/universal/modules.ts +8 -1
- package/src/native/frame_extract.swift +140 -0
- package/src/native-pack.ts +15 -7
- package/src/pi-provider.ts +6 -64
- package/src/pi-web.ts +14 -320
- package/src/prompt-cache.ts +97 -54
- package/src/quantize/allocator.ts +1 -1
- package/src/quantize/atomic-output.ts +38 -0
- package/src/quantize/calibration.ts +2 -1
- package/src/quantize/config-writer.ts +16 -3
- package/src/quantize/index.ts +28 -1
- package/src/quantize/job.ts +11 -0
- package/src/quantize/quantizer.ts +265 -100
- package/src/quantize/rotate.ts +603 -0
- package/src/quantize/safetensors-writer.ts +79 -1
- package/src/quantize/sensitivity.ts +41 -59
- package/src/quantize/trellis.ts +586 -0
- package/src/quantize/weight-transform.ts +292 -0
- package/src/responses.ts +130 -3
- package/src/runtime-config.ts +81 -0
- package/src/sampler.ts +276 -4
- package/src/serve/admin-routes.ts +184 -0
- package/src/serve/aux-routes.ts +132 -0
- package/src/serve/batch-scheduler.ts +8 -1558
- package/src/serve/chat-request.ts +391 -0
- package/src/serve/chat-stage.ts +195 -0
- package/src/serve/checkpoint-identity.ts +64 -0
- package/src/serve/completion-executor.ts +354 -0
- package/src/serve/completion-sink.ts +157 -0
- package/src/serve/discovery-routes.ts +204 -0
- package/src/serve/generation-gateway.ts +211 -243
- package/src/serve/http.ts +159 -0
- package/src/serve/inference-request.ts +79 -0
- package/src/serve/isolate.ts +297 -105
- package/src/serve/kv-budget.ts +14 -0
- package/src/serve/lab-routes.ts +341 -0
- package/src/serve/lane-registry.ts +2 -1
- package/src/serve/model-admin-routes.ts +155 -0
- package/src/serve/model-binding.ts +43 -0
- package/src/serve/model-host.ts +512 -0
- package/src/serve/openai-wire.ts +103 -0
- package/src/serve/parent-application.ts +56 -0
- package/src/serve/pipeline.ts +33 -0
- package/src/serve/preparation.ts +33 -0
- package/src/serve/prompt-response-trace.ts +147 -0
- package/src/serve/request-plan.ts +162 -0
- package/src/serve/request-prep.ts +346 -0
- package/src/serve/response-lease.ts +24 -0
- package/src/serve/responses-client.ts +69 -0
- package/src/serve/session-completion-engine.ts +110 -0
- package/src/serve/session-search.ts +1 -1
- package/src/serve/static-routes.ts +101 -0
- package/src/serve/text-completion-stage.ts +104 -0
- package/src/serve/token-streams.ts +519 -0
- package/src/server.ts +523 -3551
- package/src/spec/assistant-source.ts +10 -44
- package/src/spec/deepspec-source.ts +6 -6
- package/src/spec/dflash-source.ts +9 -8
- package/src/spec/dspark/ab-stats.ts +3 -3
- package/src/spec/dspark/calibration.ts +2 -2
- package/src/spec/dspark/deepspec-module.ts +2 -2
- package/src/spec/dspark/generate-dflash.ts +2 -2
- package/src/spec/dspark/generate.ts +2 -2
- package/src/spec/dspark/loader.ts +1 -1
- package/src/spec/dspark/module-dflash.ts +5 -4
- package/src/spec/dspark/module.ts +3 -3
- package/src/spec/dspark/quantize-drafter.ts +1 -1
- package/src/spec/generate.ts +1 -1
- package/src/spec/glm52-mtp-source.ts +9 -1
- package/src/spec/ngram-source.ts +1 -1
- package/src/spec/prefix-state.ts +45 -0
- package/src/spec/qwen-mtp-source.ts +528 -0
- package/src/spec/serve-loop.ts +179 -213
- package/src/spec/source.ts +42 -10
- package/src/spec/two-model.ts +1 -1
- package/src/ssd-cache.ts +95 -24
- package/src/ssd-durability.ts +207 -0
- package/src/tool-call.ts +51 -14
- package/src/train/flash-cce.ts +14 -13
- package/src/train/forward.ts +38 -1
- package/src/train/loss.ts +3 -2
- package/src/train/prefix-shared.ts +5 -1
- package/src/train/segmented.ts +9 -6
- package/src/train/trainer.ts +9 -8
- package/src/vision/preprocess.ts +1 -1
- package/src/vision/prompt.ts +48 -2
- package/src/vision/qwen3vl-preprocess.ts +409 -0
- package/src/vision/qwen3vl-prompt.ts +196 -0
- package/src/vision/qwen3vl-tower.ts +555 -0
- package/src/vision/video-frames.ts +148 -0
- package/src/web/app.html +1 -1
- package/src/web/app.js +15 -6
- package/src/web/src/adapters-panel.ts +3 -3
- package/src/web/src/assistant.ts +2 -36
- package/src/web/src/chat.ts +16 -9
- package/src/web/src/composer.ts +4 -4
- package/src/web/src/hub.ts +1 -1
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +1 -1
- package/src/web/src/model-picker.ts +1 -1
- package/src/web/src/palette.ts +1 -1
- package/src/web/src/protocol.ts +3 -39
- package/src/web/src/sessions.ts +1 -1
- package/src/web/src/ui-catalog.ts +4 -18
- package/src/web-assets.ts +47 -0
- package/src/weights.ts +134 -33
- package/docs/archive/mlx-bun-lab-report.html +0 -275
- package/docs/archive/wwdc-mlx-bun.html +0 -848
- package/docs/design/adapters-end-to-end.md +0 -205
- package/docs/design/batching-perf-path.md +0 -255
- package/docs/design/batching-v2-plan.md +0 -529
- package/docs/design/bucketing-stage.md +0 -197
- package/docs/design/compat-cli-surface-design.md +0 -230
- package/docs/design/docs-reorg-plan.md +0 -165
- package/docs/design/dspark-serving-program.md +0 -371
- package/docs/design/dspark-speculative-decoding.md +0 -268
- package/docs/design/grammar-spec-batching-integration.md +0 -301
- package/docs/design/memory-inference-path.md +0 -422
- package/docs/design/memory-synthesis.md +0 -287
- package/docs/design/memory-system.md +0 -237
- package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
- package/docs/design/omlx-adoption-map.md +0 -98
- package/docs/design/orpo-dynamic-lambda.md +0 -220
- package/docs/design/orpo-future-enhancements.md +0 -340
- package/docs/design/paged-kv-cache.md +0 -214
- package/docs/design/parallel-slots.md +0 -567
- package/docs/design/parity-tier-dag.md +0 -161
- package/docs/design/repo-cleanup-plan.md +0 -189
- package/docs/design/runtime-isolation.md +0 -263
- package/docs/design/segmented-backward-training.md +0 -543
- package/docs/design/spec-decode-larger-targets.md +0 -229
- package/docs/design/ssd-kv-cold-tier.md +0 -288
- package/docs/design/structured-output.md +0 -484
- package/docs/design/tauri-desktop-app.md +0 -127
- package/docs/design/the-dreaming-master-plan.md +0 -445
- package/docs/design/turboquant-kv.md +0 -235
- package/docs/design/w4a16-compute-precision-spike.md +0 -232
- package/docs/design/web-chat-beat-matrix.md +0 -315
- package/docs/design/write-pipeline-entity.md +0 -468
- package/docs/investigations/curve-runs/bisector-route.json +0 -98
- package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
- package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
- package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
- package/docs/investigations/hlg-ab.html +0 -34
- package/docs/investigations/hlg-explorer.html +0 -238
- package/docs/investigations/hlg-figs/cliff.svg +0 -1
- package/docs/investigations/hlg-figs/cross.svg +0 -1
- package/docs/investigations/hlg-figs/edges.svg +0 -1
- package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
- package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
- package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
- package/docs/investigations/hlg-figs/terrain.svg +0 -1
- package/docs/investigations/hlg-report.html +0 -262
- package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
- package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
- package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
- package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
- package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
- package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
- package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
- package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
- package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
- package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
- package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
- package/docs/investigations/hlg-runs/hlg-map.json +0 -383
- package/docs/investigations/hlg-runs/run0-original.log +0 -159
- package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
- package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
- package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
- package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
- package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
- package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
- package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
- package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
- package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
- package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
- package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
- package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
- package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
- package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
- package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
- package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
- package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
- package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
- package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
- package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
- package/docs/investigations/hlg-runs/runN-verify.log +0 -116
- package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
- package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
- package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
- package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
- package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
- package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
- package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
- package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
- package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
- package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
- package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
- package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
- package/docs/planning/IDEAS.md +0 -69
- package/docs/reference/embedding.md +0 -197
- package/docs/reference/features-matrix.md +0 -100
- package/docs/reference/orpo-quickstart.md +0 -135
- package/src/flags.ts +0 -13
- /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
- /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
- /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
- /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
- /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
- /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
- /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
- /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
- /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
- /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
- /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
- /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
- /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
- /package/docs/{planning → archive/planning}/journal.md +0 -0
- /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
- /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
- /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
- /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Video file → RGB frames via the AVFoundation sidecar (PLAN 14w) — the
|
|
2
|
+
// video twin of the audio path's afconvert doctrine: macOS-native codecs
|
|
3
|
+
// (H.264/HEVC/ProRes/…), zero vendored decoders. The sidecar
|
|
4
|
+
// (src/native/frame_extract.swift, shipped as `mlx-bun-frame-extract` beside
|
|
5
|
+
// the binary and in the native pack) samples frames at fps=2 with
|
|
6
|
+
// zero-tolerance timestamps — mirroring mlx-vlm's do_sample_frames — and
|
|
7
|
+
// writes PNGs that decode through the SAME fast-png path as image inputs.
|
|
8
|
+
//
|
|
9
|
+
// Resolution order (afconvert needs none of this because /usr/bin ships it;
|
|
10
|
+
// our extractor is the missing CLI face on Apple's decoder):
|
|
11
|
+
// MLX_BUN_FRAME_EXTRACT env → beside the executable (release bundle) →
|
|
12
|
+
// the native-pack cache → dist-native (dev tree) → compile-on-demand from
|
|
13
|
+
// src/native (from-source installs with Xcode CLT; cached in dist-native).
|
|
14
|
+
|
|
15
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
16
|
+
import { rm } from "node:fs/promises";
|
|
17
|
+
import { randomUUID } from "node:crypto";
|
|
18
|
+
import { tmpdir } from "node:os";
|
|
19
|
+
import { dirname, join } from "node:path";
|
|
20
|
+
import { nativePackDir } from "../native-pack";
|
|
21
|
+
import { decodeImage, type RGBImage } from "./preprocess";
|
|
22
|
+
import { runtimeValue } from "../runtime-config";
|
|
23
|
+
|
|
24
|
+
export const VIDEO_SAMPLE_FPS = 2;
|
|
25
|
+
export const VIDEO_MAX_FRAMES = 768; // Qwen3VLVideoProcessor max_frames
|
|
26
|
+
|
|
27
|
+
const BIN = "mlx-bun-frame-extract";
|
|
28
|
+
|
|
29
|
+
/** Memoize the PROMISE, not the result: a second video request arriving
|
|
30
|
+
* while the first compile is in flight must await the same compile, not
|
|
31
|
+
* observe a half-set cache and spuriously report the sidecar missing. */
|
|
32
|
+
let devCompile: Promise<string | null> | null = null;
|
|
33
|
+
|
|
34
|
+
/** Compile the sidecar from the repo tree (dev/from-source convenience —
|
|
35
|
+
* needs swiftc from the Xcode CLT). Null when the source or toolchain is
|
|
36
|
+
* unavailable. */
|
|
37
|
+
function compileFromSource(): Promise<string | null> {
|
|
38
|
+
devCompile ??= (async () => {
|
|
39
|
+
const src = join(import.meta.dir, "..", "native", "frame_extract.swift");
|
|
40
|
+
if (!existsSync(src)) return null;
|
|
41
|
+
const out = join(import.meta.dir, "..", "..", "dist-native", BIN);
|
|
42
|
+
try {
|
|
43
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
44
|
+
const proc = Bun.spawn(["swiftc", "-O", src, "-o", out], {
|
|
45
|
+
stdout: "ignore", stderr: "pipe",
|
|
46
|
+
});
|
|
47
|
+
if ((await proc.exited) === 0 && existsSync(out)) return out;
|
|
48
|
+
} catch {
|
|
49
|
+
// no swiftc — resolver returns null and serving 400s with the reason
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
})();
|
|
53
|
+
return devCompile;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Locate (or dev-compile) the extractor; null ⟹ video input unavailable
|
|
57
|
+
* on this install (surfaced as a clear 400, never a crash). */
|
|
58
|
+
export async function resolveFrameExtract(): Promise<string | null> {
|
|
59
|
+
const explicit = runtimeValue("MLX_BUN_FRAME_EXTRACT");
|
|
60
|
+
if (explicit) return explicit;
|
|
61
|
+
const candidates = [
|
|
62
|
+
join(dirname(process.execPath), BIN),
|
|
63
|
+
join(nativePackDir(), BIN),
|
|
64
|
+
join(import.meta.dir, "..", "..", "dist-native", BIN),
|
|
65
|
+
];
|
|
66
|
+
for (const c of candidates) if (existsSync(c)) return c;
|
|
67
|
+
return compileFromSource();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Decode a video container to sampled RGB frames. Throws with the
|
|
71
|
+
* sidecar's diagnostic on failure (the serve layer surfaces it as a 400,
|
|
72
|
+
* the afconvert pattern — timeout kill included). */
|
|
73
|
+
export async function extractVideoFrames(
|
|
74
|
+
bytes: Uint8Array,
|
|
75
|
+
opts: { fps?: number; maxFrames?: number } = {},
|
|
76
|
+
): Promise<RGBImage[]> {
|
|
77
|
+
const bin = await resolveFrameExtract();
|
|
78
|
+
if (!bin)
|
|
79
|
+
throw new Error(
|
|
80
|
+
"video input needs the frame-extraction sidecar (mlx-bun-frame-extract) " +
|
|
81
|
+
"— ships beside the release binary and in the native pack; from a " +
|
|
82
|
+
"source tree it compiles on first use via the Xcode CLT (swiftc)",
|
|
83
|
+
);
|
|
84
|
+
const base = join(tmpdir(), `mlx-bun-video-${randomUUID()}`);
|
|
85
|
+
// AVFoundation infers the container from the path EXTENSION — sniff the
|
|
86
|
+
// ISO-BMFF `ftyp` box (mp4/mov share it; the `qt ` major brand is
|
|
87
|
+
// QuickTime) so the temp file opens. Unknown magic defaults to .mp4.
|
|
88
|
+
const isFtyp = bytes.length >= 12 &&
|
|
89
|
+
bytes[4] === 0x66 && bytes[5] === 0x74 && bytes[6] === 0x79 && bytes[7] === 0x70;
|
|
90
|
+
const brand = isFtyp
|
|
91
|
+
? String.fromCharCode(bytes[8]!, bytes[9]!, bytes[10]!, bytes[11]!)
|
|
92
|
+
: "";
|
|
93
|
+
const ext = brand.startsWith("qt") ? "mov" : "mp4";
|
|
94
|
+
const inPath = `${base}.${ext}`;
|
|
95
|
+
const outDir = `${base}.frames`;
|
|
96
|
+
try {
|
|
97
|
+
// Inside the try so a part-way write failure (ENOSPC on a large clip)
|
|
98
|
+
// still hits the finally's cleanup instead of stranding the temp file.
|
|
99
|
+
await Bun.write(inPath, bytes);
|
|
100
|
+
const proc = Bun.spawn(
|
|
101
|
+
[
|
|
102
|
+
bin, inPath, outDir,
|
|
103
|
+
String(opts.fps ?? VIDEO_SAMPLE_FPS),
|
|
104
|
+
String(opts.maxFrames ?? VIDEO_MAX_FRAMES),
|
|
105
|
+
],
|
|
106
|
+
{ stdout: "pipe", stderr: "pipe" },
|
|
107
|
+
);
|
|
108
|
+
// Decoding is fast (hardware) but long clips take real time; a hung
|
|
109
|
+
// decoder must not pin the request forever — kill → nonzero → 400.
|
|
110
|
+
const killer = setTimeout(() => proc.kill(), 120_000);
|
|
111
|
+
const exit = await proc.exited;
|
|
112
|
+
clearTimeout(killer);
|
|
113
|
+
if (exit !== 0) {
|
|
114
|
+
const err = (await new Response(proc.stderr).text()).trim();
|
|
115
|
+
throw new Error(
|
|
116
|
+
`video decode failed (frame-extract exit ${exit}): ` +
|
|
117
|
+
`${err.split("\n").at(-1) || "unknown error"} — supported containers: ` +
|
|
118
|
+
`whatever AVFoundation decodes on this macOS (mp4/mov H.264/HEVC/ProRes/…)`,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
const head = (await new Response(proc.stdout).text()).trim();
|
|
122
|
+
const n = Number(/^N (\d+)/.exec(head)?.[1] ?? 0);
|
|
123
|
+
if (!n) throw new Error(`video decode produced no frames (${head})`);
|
|
124
|
+
// Aggregate decoded-RGB budget (belt over the sidecar's 1024px
|
|
125
|
+
// longest-edge cap): a valid low-bitrate clip must not balloon into
|
|
126
|
+
// gigabytes of frame buffers before preprocessing.
|
|
127
|
+
const w = Number(/W (\d+)/.exec(head)?.[1] ?? 0);
|
|
128
|
+
const hh = Number(/H (\d+)/.exec(head)?.[1] ?? 0);
|
|
129
|
+
const DECODED_BUDGET = 1536 * 1024 * 1024; // 1.5 GiB
|
|
130
|
+
if (n * w * hh * 3 > DECODED_BUDGET)
|
|
131
|
+
throw new Error(
|
|
132
|
+
`video decodes to ${(n * w * hh * 3 / 1024 / 1024).toFixed(0)} MB of ` +
|
|
133
|
+
`frames (${n} × ${w}x${hh}) — over the ${DECODED_BUDGET / 1024 / 1024} MB ` +
|
|
134
|
+
`budget; send a shorter or smaller clip`,
|
|
135
|
+
);
|
|
136
|
+
const frames: RGBImage[] = [];
|
|
137
|
+
for (let i = 0; i < n; i++) {
|
|
138
|
+
const f = join(outDir, `frame-${String(i).padStart(4, "0")}.png`);
|
|
139
|
+
frames.push(await decodeImage(new Uint8Array(await Bun.file(f).arrayBuffer())));
|
|
140
|
+
}
|
|
141
|
+
return frames;
|
|
142
|
+
} finally {
|
|
143
|
+
await Promise.allSettled([
|
|
144
|
+
rm(inPath, { force: true }),
|
|
145
|
+
rm(outDir, { recursive: true, force: true }),
|
|
146
|
+
]);
|
|
147
|
+
}
|
|
148
|
+
}
|
package/src/web/app.html
CHANGED
|
@@ -1216,7 +1216,7 @@
|
|
|
1216
1216
|
<!-- PWA installability (plan §9 Phase 3, beat-matrix Axis 10): manifest +
|
|
1217
1217
|
inline SVG icon (src/web/manifest.webmanifest, src/web/icon.svg — no
|
|
1218
1218
|
binary PNGs, per the hygiene gate; some browsers won't render an SVG
|
|
1219
|
-
app icon and that's an accepted tradeoff, see
|
|
1219
|
+
app icon and that's an accepted tradeoff, see docs/reference/server-config.md).
|
|
1220
1220
|
theme-color matches the app's --bg token so the OS chrome doesn't
|
|
1221
1221
|
flash a mismatched color on launch. -->
|
|
1222
1222
|
<link rel="manifest" href="/manifest.webmanifest">
|
package/src/web/app.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// GENERATED — do not edit by hand.
|
|
2
2
|
// Source: src/web/src/*.ts (entrypoint main.ts). To regenerate:
|
|
3
3
|
// bun scripts/build-web.ts
|
|
4
|
-
// tests/web-build.test.ts enforces that this file matches the source.
|
|
4
|
+
// tests/using/web-build.test.ts enforces that this file matches the source.
|
|
5
5
|
// src/web/src/api.ts
|
|
6
6
|
async function api(path, opts) {
|
|
7
7
|
const { body, ...rest } = opts || {};
|
|
@@ -2892,11 +2892,13 @@ function initMemoryPanel() {
|
|
|
2892
2892
|
maybeShowConsentCard();
|
|
2893
2893
|
}
|
|
2894
2894
|
|
|
2895
|
+
// src/contracts/pi.ts
|
|
2896
|
+
var APP_ROUTE_IDS = ["chat", "quantize", "finetune", "dataset", "status"];
|
|
2897
|
+
|
|
2895
2898
|
// src/web/src/ui-catalog.ts
|
|
2896
|
-
var ROUTE_IDS = ["chat", "quantize", "finetune", "dataset", "status"];
|
|
2897
2899
|
var VIEW_IDS = ["memory-panel", "hub-panel", "settings", "adapters-panel"];
|
|
2898
2900
|
function isRouteId(v) {
|
|
2899
|
-
return
|
|
2901
|
+
return APP_ROUTE_IDS.includes(v);
|
|
2900
2902
|
}
|
|
2901
2903
|
function isViewId(v) {
|
|
2902
2904
|
return VIEW_IDS.includes(v);
|
|
@@ -3496,15 +3498,21 @@ function createChatController() {
|
|
|
3496
3498
|
t0: performance.now(),
|
|
3497
3499
|
tFirst: 0,
|
|
3498
3500
|
tokens: 0,
|
|
3501
|
+
settled: false,
|
|
3499
3502
|
blockState: { blocks: [] },
|
|
3500
3503
|
scheduleText: () => {},
|
|
3501
3504
|
scheduleThinking: () => {},
|
|
3502
3505
|
citations: pendingCitations
|
|
3503
3506
|
};
|
|
3504
3507
|
pendingCitations = [];
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
+
const assistant = curAssistant;
|
|
3509
|
+
assistant.scheduleText = makeFrameScheduler(() => {
|
|
3510
|
+
if (!assistant.settled)
|
|
3511
|
+
renderBlocksIncremental(assistant.textNode, assistant.text, assistant.blockState);
|
|
3512
|
+
}, atBottom, stick);
|
|
3513
|
+
assistant.scheduleThinking = makeFrameScheduler(() => {
|
|
3514
|
+
if (!assistant.settled)
|
|
3515
|
+
assistant.thinkBody.textContent = assistant.thinking;
|
|
3508
3516
|
}, atBottom, stick);
|
|
3509
3517
|
stick(true);
|
|
3510
3518
|
}
|
|
@@ -3670,6 +3678,7 @@ function createChatController() {
|
|
|
3670
3678
|
function finishStreaming(a) {
|
|
3671
3679
|
if (!a)
|
|
3672
3680
|
return;
|
|
3681
|
+
a.settled = true;
|
|
3673
3682
|
const previewIdx = captureCanvasViewStates(a.textNode);
|
|
3674
3683
|
a.textNode.innerHTML = mdToHtml(a.text);
|
|
3675
3684
|
restoreCanvasViewStates(a.textNode, previewIdx);
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
// docs/reference/server-api.md), with compatible-graying and a why-not
|
|
10
10
|
// tooltip. Actions: mount, select, unselect, and stack two compatible
|
|
11
11
|
// adapters as "a+b" — resolveSpec/injectAdapter already support composite
|
|
12
|
-
// ids end to end (proved in tests/pi-web.test.ts's stacking test; the
|
|
12
|
+
// ids end to end (proved in tests/research/pi-web.test.ts's stacking test; the
|
|
13
13
|
// shape-validated mount is proved against real weights in the
|
|
14
|
-
// MLX_BUN_TEST_LORA=1-gated tests/lora.test.ts).
|
|
14
|
+
// MLX_BUN_TEST_LORA=1-gated tests/parity/lora.test.ts).
|
|
15
15
|
//
|
|
16
16
|
// Single source of SELECTION state, not a single fetch: composer.ts's quick
|
|
17
17
|
// <select> and this table each hit /v1/adapters(+/available) independently
|
|
@@ -158,7 +158,7 @@ export function renderAdapterRow(
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
/** Full table body: a stack-mode toggle + composed-spec bar (when picks
|
|
161
|
-
* exist), then one section of rows. Exported so tests/web-app.test.ts can
|
|
161
|
+
* exist), then one section of rows. Exported so tests/using/web-app.test.ts can
|
|
162
162
|
* exercise esc() discipline without a live DOM/network. */
|
|
163
163
|
export function renderAdaptersBodyHtml(state: AdaptersPanelState): string {
|
|
164
164
|
if (!state.available.length) {
|
package/src/web/src/assistant.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { UiSnapshotElement, UiSnapshot, WizardStep } from "../../contracts/pi";
|
|
2
|
+
export type { UiSnapshotElement, UiSnapshot, WizardStep } from "../../contracts/pi";
|
|
1
3
|
// GENERATED-ADJACENT source module — part of the src/web/src/* split (plan
|
|
2
4
|
// §6.6 "the app-aware assistant", §9 Phase 3, beat matrix Axis 12). Built
|
|
3
5
|
// into src/web/app.js by scripts/build-web.ts.
|
|
@@ -26,42 +28,6 @@
|
|
|
26
28
|
|
|
27
29
|
import { getSpotlightTarget, isViewId, ROUTE_LABELS, type RouteId, type ViewId } from "./ui-catalog";
|
|
28
30
|
|
|
29
|
-
/* ────────────────────────────────────────────────────────────────────
|
|
30
|
-
1. SEE — the structured DOM snapshot
|
|
31
|
-
──────────────────────────────────────────────────────────────────── */
|
|
32
|
-
|
|
33
|
-
export interface UiSnapshotElement {
|
|
34
|
-
ref: string;
|
|
35
|
-
tag: string;
|
|
36
|
-
label: string;
|
|
37
|
-
kind: "interactive" | "region";
|
|
38
|
-
role?: string;
|
|
39
|
-
selector: string;
|
|
40
|
-
spotlightId?: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface UiSnapshot {
|
|
44
|
-
route: string;
|
|
45
|
-
capturedAt: string;
|
|
46
|
-
elements: UiSnapshotElement[];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Process-state fields layered onto the snapshot (§6.6 "the snapshot
|
|
50
|
-
* carries process state, not just elements") — wizard step for the
|
|
51
|
-
* quantize/finetune/dataset wizards, when the current route has one.
|
|
52
|
-
* Derived by reading the DOM the step indicator already renders
|
|
53
|
-
* (markdown.ts's renderSteps into #q-steps/#f-steps/#d-steps + the
|
|
54
|
-
* [data-qstep]/[data-fstep]/[data-dstep] visibility toggle quantize.ts/
|
|
55
|
-
* finetune.ts/dataset.ts already do) rather than adding a callback hook to
|
|
56
|
-
* those three controllers — zero behavior change to files outside this
|
|
57
|
-
* wave's scope, and the DOM IS the source of truth those controllers
|
|
58
|
-
* already write to. */
|
|
59
|
-
export interface WizardStep {
|
|
60
|
-
index: number;
|
|
61
|
-
count: number;
|
|
62
|
-
label: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
31
|
const STEP_CONTAINER_BY_ROUTE: Partial<Record<RouteId, string>> = {
|
|
66
32
|
quantize: "q-steps",
|
|
67
33
|
finetune: "f-steps",
|
package/src/web/src/chat.ts
CHANGED
|
@@ -10,15 +10,15 @@
|
|
|
10
10
|
// typed, checkable seams between these concerns).
|
|
11
11
|
//
|
|
12
12
|
// Typed WS contract (plan §9 Phase 2 item 2): ClientMessage/ServerMessage
|
|
13
|
-
// and the history/session shapes are imported TYPE-ONLY from ../../pi
|
|
13
|
+
// and the history/session shapes are imported TYPE-ONLY from ../../contracts/pi
|
|
14
14
|
// so this module (and the whole bundle) contains zero server code — the
|
|
15
15
|
// bundler errors on bun:ffi if a value import ever sneaks in here, which is
|
|
16
16
|
// the intended guard (see scripts/build-web.ts).
|
|
17
17
|
|
|
18
18
|
import type {
|
|
19
19
|
ClientMessage, HistoryItem, ReadyGenDefaults, ServerMessage, SessionListItem,
|
|
20
|
-
} from "../../pi
|
|
21
|
-
import type { Lane } from "../../
|
|
20
|
+
} from "../../contracts/pi";
|
|
21
|
+
import type { Lane } from "../../contracts/pi";
|
|
22
22
|
import {
|
|
23
23
|
$, el, toast, currentRoute, closeDrawer,
|
|
24
24
|
storedCodingToolsPreference, renderCodingToolsState, renderToolApprovals,
|
|
@@ -44,7 +44,7 @@ import { isRouteId } from "./ui-catalog";
|
|
|
44
44
|
|
|
45
45
|
/* ────────────────────────────────────────────────────────────────────
|
|
46
46
|
Chat-with-files RAG v1 — Sources panel (plan §9 Phase 3, beat matrix
|
|
47
|
-
Axis 5). Pure HTML builder so tests/web-app.test.ts can exercise the
|
|
47
|
+
Axis 5). Pure HTML builder so tests/using/web-app.test.ts can exercise the
|
|
48
48
|
esc() discipline directly, same reasoning as renderAdapterOptionsHtml
|
|
49
49
|
etc. in composer.ts.
|
|
50
50
|
──────────────────────────────────────────────────────────────────── */
|
|
@@ -142,6 +142,7 @@ interface AssistantMsgState {
|
|
|
142
142
|
t0: number;
|
|
143
143
|
tFirst: number;
|
|
144
144
|
tokens: number;
|
|
145
|
+
settled: boolean;
|
|
145
146
|
blockState: BlockState;
|
|
146
147
|
scheduleText: () => void;
|
|
147
148
|
scheduleThinking: () => void;
|
|
@@ -373,7 +374,7 @@ export function createChatController() {
|
|
|
373
374
|
const meta = el("div", "meta", m);
|
|
374
375
|
curAssistant = {
|
|
375
376
|
m, bubble, thinkBox, thinkBody, textNode, cursor, meta, tools: new Map(),
|
|
376
|
-
text: "", thinking: "", t0: performance.now(), tFirst: 0, tokens: 0,
|
|
377
|
+
text: "", thinking: "", t0: performance.now(), tFirst: 0, tokens: 0, settled: false,
|
|
377
378
|
// Block-memoization state (see renderBlocksIncremental) for the main
|
|
378
379
|
// markdown text stream, plus a shared rAF scheduler so a burst of
|
|
379
380
|
// deltas within one frame (e.g. spec-decode emitting several tokens
|
|
@@ -390,11 +391,16 @@ export function createChatController() {
|
|
|
390
391
|
// Consumed — a later turn with no RAG'd attachments must not inherit
|
|
391
392
|
// this turn's citation set (see the pendingCitations declaration above).
|
|
392
393
|
pendingCitations = [];
|
|
393
|
-
|
|
394
|
-
|
|
394
|
+
const assistant = curAssistant;
|
|
395
|
+
assistant.scheduleText = makeFrameScheduler(
|
|
396
|
+
() => {
|
|
397
|
+
if (!assistant.settled) renderBlocksIncremental(assistant.textNode, assistant.text, assistant.blockState);
|
|
398
|
+
},
|
|
395
399
|
atBottom, stick);
|
|
396
|
-
|
|
397
|
-
() => {
|
|
400
|
+
assistant.scheduleThinking = makeFrameScheduler(
|
|
401
|
+
() => {
|
|
402
|
+
if (!assistant.settled) assistant.thinkBody.textContent = assistant.thinking;
|
|
403
|
+
},
|
|
398
404
|
atBottom, stick);
|
|
399
405
|
stick(true);
|
|
400
406
|
}
|
|
@@ -612,6 +618,7 @@ export function createChatController() {
|
|
|
612
618
|
* directly on the full string. */
|
|
613
619
|
function finishStreaming(a: AssistantMsgState | null): void {
|
|
614
620
|
if (!a) return;
|
|
621
|
+
a.settled = true;
|
|
615
622
|
// Preserve any Canvas Preview toggle the user made mid-stream (Principle
|
|
616
623
|
// 9: this full non-memoized re-render must not throw away user
|
|
617
624
|
// interaction state) — mdCodeBlock always emits qualifying fences back
|
package/src/web/src/composer.ts
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
// the original single IIFE), but every WS send goes through a callback
|
|
11
11
|
// passed in from chat.ts, which owns the actual WebSocket.
|
|
12
12
|
|
|
13
|
-
import type { ReadyGenDefaults, SamplingOverrides } from "../../pi
|
|
14
|
-
import type { Lane } from "../../
|
|
13
|
+
import type { ReadyGenDefaults, SamplingOverrides } from "../../contracts/pi";
|
|
14
|
+
import type { Lane } from "../../contracts/pi";
|
|
15
15
|
import { api } from "./api";
|
|
16
16
|
import type { ApiEnvelope } from "./protocol";
|
|
17
17
|
import {
|
|
@@ -200,7 +200,7 @@ function escHtml(s: unknown): string {
|
|
|
200
200
|
|
|
201
201
|
/** Pure: builds the <option> markup for the adapter <select> from the
|
|
202
202
|
* /v1/adapters/available list. Split out from refreshAdapters() (which
|
|
203
|
-
* does the fetch + DOM write) so tests/web-app.test.ts can exercise the
|
|
203
|
+
* does the fetch + DOM write) so tests/using/web-app.test.ts can exercise the
|
|
204
204
|
* esc() discipline on this template directly without a DOM or network —
|
|
205
205
|
* every interpolated field (id, rank, path, base_model) must be escaped,
|
|
206
206
|
* since adapter ids/paths are user-controlled (on-disk directory names). */
|
|
@@ -719,7 +719,7 @@ export function renderLane(lane: Lane | undefined): void {
|
|
|
719
719
|
already resolves, so the agent's memory tools pick it up naturally, same
|
|
720
720
|
as in the vault's own prose). No vault -> files-only picker. Pure
|
|
721
721
|
query-detection/insertion helpers below are unit-tested directly
|
|
722
|
-
(tests/web-app.test.ts); DOM wiring (initMentionPicker) owns the
|
|
722
|
+
(tests/using/web-app.test.ts); DOM wiring (initMentionPicker) owns the
|
|
723
723
|
picker's open/close/keyboard-nav state.
|
|
724
724
|
──────────────────────────────────────────────────────────────────── */
|
|
725
725
|
|
package/src/web/src/hub.ts
CHANGED
|
@@ -119,7 +119,7 @@ function localRowHtml(m: HubLocalRow): string {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/** Pure render, exported for esc()-discipline + empty-state tests
|
|
122
|
-
* (tests/web-app.test.ts, mirroring renderModelPopBodyHtml's pattern). */
|
|
122
|
+
* (tests/using/web-app.test.ts, mirroring renderModelPopBodyHtml's pattern). */
|
|
123
123
|
export function renderHubLocalHtml(models: HubLocalRow[]): string {
|
|
124
124
|
if (!models.length) {
|
|
125
125
|
return '<div class="hub-empty">No models downloaded yet — search Hugging Face below to get one.</div>';
|
package/src/web/src/markdown.ts
CHANGED
|
Binary file
|
|
@@ -394,7 +394,7 @@ export async function refreshSidebarEntry(): Promise<void> {
|
|
|
394
394
|
// by a literal list rather than an import: this module must stay
|
|
395
395
|
// server-code-free (bundler-enforced, see chat.ts's header comment), so it
|
|
396
396
|
// can't import a value from src/memory/tools.ts even though the identifiers
|
|
397
|
-
// are the same. tests/web-app.test.ts cross-checks this list against the
|
|
397
|
+
// are the same. tests/using/web-app.test.ts cross-checks this list against the
|
|
398
398
|
// real export so drift is caught at test time instead of silently.
|
|
399
399
|
export const MEMORY_CHIP_TOOL_NAMES = [
|
|
400
400
|
"memory_resolve", "memory_category", "memory_read", "memory_section",
|
|
@@ -85,7 +85,7 @@ function renderRow(m: LibraryRow): string {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/** Pure render of the popover body from a /library response. Exported for
|
|
88
|
-
* tests/web-app.test.ts's esc() discipline check (repo ids are
|
|
88
|
+
* tests/using/web-app.test.ts's esc() discipline check (repo ids are
|
|
89
89
|
* user-controlled HF strings — the same class of interpolation hazard
|
|
90
90
|
* finding #15 flagged for the adapter dropdown). */
|
|
91
91
|
export function renderModelPopBodyHtml(models: LibraryRow[]): string {
|
package/src/web/src/palette.ts
CHANGED
|
@@ -39,7 +39,7 @@ interface PaletteAction {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/** Pure: the static action list, independent of any live session data —
|
|
42
|
-
* independently testable (tests/web-app.test.ts asserts labels/ids without
|
|
42
|
+
* independently testable (tests/using/web-app.test.ts asserts labels/ids without
|
|
43
43
|
* needing a DOM). Session rows and message-search hits are appended
|
|
44
44
|
* dynamically in refreshResults() below, not part of this list. */
|
|
45
45
|
export function staticActions(): PaletteAction[] {
|
package/src/web/src/protocol.ts
CHANGED
|
@@ -1,47 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// ServerMessage / HistoryItem / SessionListItem / ReadyGenDefaults) is
|
|
4
|
-
// imported type-only from ../../pi-web — see chat.ts. This file only holds
|
|
5
|
-
// shapes with no server-side export to anchor to (e.g. the SSE job-stream
|
|
6
|
-
// events, which live as a doc-comment in app.html today, not a type).
|
|
7
|
-
//
|
|
8
|
-
// Pointer comment for the server side: src/web/src/protocol.ts mirrors the
|
|
9
|
-
// SSE line protocol documented at the jobStream() call site (api.ts) —
|
|
10
|
-
// keep the two adjacent if the job event shape changes server-side
|
|
11
|
-
// (scripts/ that emit `data:` lines for /api/jobs/:id/stream).
|
|
12
|
-
|
|
13
|
-
/** One line of the /api/jobs/:id/stream SSE protocol (JSON per `data:` line). */
|
|
14
|
-
export type JobEvent =
|
|
15
|
-
| { type: "log"; line: string }
|
|
16
|
-
| {
|
|
17
|
-
type: "stage";
|
|
18
|
-
stage: string;
|
|
19
|
-
progress?: number;
|
|
20
|
-
message?: string;
|
|
21
|
-
output_dir?: string;
|
|
22
|
-
adapter_path?: string;
|
|
23
|
-
// Dataset-generation-specific row counts (present on the dataset
|
|
24
|
-
// builder's job stream only; absent/ignored for quantize/finetune).
|
|
25
|
-
n_train?: number;
|
|
26
|
-
n_valid?: number;
|
|
27
|
-
}
|
|
28
|
-
| {
|
|
29
|
-
type: "metric";
|
|
30
|
-
kind: "train" | "val";
|
|
31
|
-
step: number;
|
|
32
|
-
loss: number;
|
|
33
|
-
learning_rate?: number;
|
|
34
|
-
tokens_per_sec?: number;
|
|
35
|
-
progress?: number;
|
|
36
|
-
message?: string;
|
|
37
|
-
}
|
|
38
|
-
| { type: "done"; n_train?: number; n_valid?: number }
|
|
39
|
-
| { type: "failed"; error?: string };
|
|
1
|
+
import type { JobEvent } from "../../contracts/jobs";
|
|
2
|
+
export type { JobEvent } from "../../contracts/jobs";
|
|
40
3
|
|
|
41
4
|
/** Handlers passed to jobStream(); each key is an optional callback for the
|
|
42
5
|
* matching JobEvent variant, plus an `error` callback for the EventSource's
|
|
43
6
|
* own onerror (transport failure, not a `failed` protocol event). */
|
|
44
7
|
export interface JobStreamHandlers {
|
|
8
|
+
started?: (e: Extract<JobEvent, { type: "started" }>) => void;
|
|
45
9
|
log?: (e: Extract<JobEvent, { type: "log" }>) => void;
|
|
46
10
|
stage?: (e: Extract<JobEvent, { type: "stage" }>) => void;
|
|
47
11
|
metric?: (e: Extract<JobEvent, { type: "metric" }>) => void;
|
package/src/web/src/sessions.ts
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
// wires each rendered `.sess` row's click to `onOpen` below — this just
|
|
21
21
|
// finds and clicks the right row instead of duplicating that send()).
|
|
22
22
|
|
|
23
|
-
import type { SessionListItem } from "../../pi
|
|
23
|
+
import type { SessionListItem } from "../../contracts/pi";
|
|
24
24
|
import { $, el, injectStyles } from "./shell";
|
|
25
25
|
import { api } from "./api";
|
|
26
26
|
|
|
@@ -2,28 +2,14 @@
|
|
|
2
2
|
// §7/§9 Phase 3, §6.6 "app-aware assistant"). Built into src/web/app.js by
|
|
3
3
|
// scripts/build-web.ts.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// ui-catalog.ts + server/src/agent/ui-catalog.ts, read together with
|
|
8
|
-
// server/src/agent/portfolio-tools.ts as the reference implementation) but
|
|
9
|
-
// inlined as a TS module (not a shared JSON file) since mlx-bun's server and
|
|
10
|
-
// browser bundles are separate build outputs (scripts/build-web.ts vs bun's
|
|
11
|
-
// own TS execution) with no shared-JSON-import convention today — pi-web.ts
|
|
12
|
-
// mirrors ROUTE_IDS/SPOTLIGHT_TARGETS as plain string arrays for its own
|
|
13
|
-
// server-side validation (navigate_app/spotlight_ui reject anything not in
|
|
14
|
-
// that list BEFORE touching the browser) so route validity is checked at
|
|
15
|
-
// both ends without a build-time shared asset.
|
|
16
|
-
//
|
|
17
|
-
// Keep this list's ROUTE_IDS in sync with shell.ts's ROUTES tuple (chat,
|
|
18
|
-
// quantize, finetune, dataset, status) plus the Developer-only overlays that
|
|
19
|
-
// aren't hash-routes (memory panel, hub panel, settings) — those are
|
|
20
|
-
// `view`s, not `route`s (see UiContext.view below), reached by opening an
|
|
21
|
-
// overlay rather than changing the URL hash.
|
|
5
|
+
// Shared route IDs keep browser navigation and server validation in agreement.
|
|
6
|
+
// Spotlight selectors and overlay IDs belong to the browser.
|
|
22
7
|
|
|
23
8
|
/** A hash-routed page (shell.ts's Route union, minus "routes" — the DAG
|
|
24
9
|
* diagram tab isn't a useful assistant destination and is itself
|
|
25
10
|
* feature-detected/hidden when unavailable). */
|
|
26
|
-
|
|
11
|
+
import { APP_ROUTE_IDS as ROUTE_IDS } from "../../contracts/pi";
|
|
12
|
+
export { ROUTE_IDS };
|
|
27
13
|
export type RouteId = (typeof ROUTE_IDS)[number];
|
|
28
14
|
|
|
29
15
|
/** A non-route overlay/panel the assistant can navigate to or spotlight
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Embedded web app — the unified SPA (chat / quantize / finetune /
|
|
2
|
+
// dataset / status). `with { type: "text" }` inlines the file in both
|
|
3
|
+
// `bun run` and the compiled single binary. bun-types types *.html
|
|
4
|
+
// imports as HTMLBundle (the html loader), but the text attribute makes
|
|
5
|
+
// the runtime value a string — hence the double cast.
|
|
6
|
+
import appHtml from "./web/app.html" with { type: "text" };
|
|
7
|
+
import curveDesignerHtml from "./lab/curve/curve-designer.html" with { type: "text" };
|
|
8
|
+
// Vendored, no-CDN static assets referenced by app.html (convention: any
|
|
9
|
+
// self-contained JS/CSS too big to inline gets `with { type: "text" }`
|
|
10
|
+
// imported here and served under /assets/<name>; see src/web/vendor/README
|
|
11
|
+
// for how hljs.js was built). Add new vendored assets the same way.
|
|
12
|
+
import hljsJs from "./web/vendor/hljs.js" with { type: "text" };
|
|
13
|
+
import hljsCss from "./web/vendor/hljs-theme.css" with { type: "text" };
|
|
14
|
+
// The frontend bundle (plan §7/§9 Phase 2 module split): GENERATED from
|
|
15
|
+
// src/web/src/*.ts by `bun scripts/build-web.ts` — see that file's header
|
|
16
|
+
// and tests/using/web-build.test.ts (the freshness gate). Same
|
|
17
|
+
// with { type: "text" } + /assets/<name> pattern as the vendored assets
|
|
18
|
+
// above; app.html's <script defer src="/assets/app.js"> loads it.
|
|
19
|
+
import appJs from "./web/app.js" with { type: "text" };
|
|
20
|
+
// PWA installability (plan §9 Phase 3, beat-matrix Axis 10): a manifest +
|
|
21
|
+
// a single inline SVG icon (no binary PNGs — the hygiene gate forbids
|
|
22
|
+
// tracked binary files; some browsers won't show an SVG app icon, which is
|
|
23
|
+
// an accepted tradeoff, see docs/reference/server-config.md) + a shell-
|
|
24
|
+
// only service worker. Same with { type: "text" } + /assets/<name>-shaped
|
|
25
|
+
// pattern as the vendored assets above; see src/web/sw.js's header for why
|
|
26
|
+
// it deliberately does NOT cache API/WS traffic.
|
|
27
|
+
import manifestWebmanifest from "./web/manifest.webmanifest" with { type: "text" };
|
|
28
|
+
import iconSvg from "./web/icon.svg" with { type: "text" };
|
|
29
|
+
import swJs from "./web/sw.js" with { type: "text" };
|
|
30
|
+
const APP_PAGE = appHtml as unknown as string;
|
|
31
|
+
const HLJS_JS = hljsJs as unknown as string;
|
|
32
|
+
const HLJS_CSS = hljsCss as unknown as string;
|
|
33
|
+
const APP_JS = appJs as unknown as string;
|
|
34
|
+
const MANIFEST_WEBMANIFEST = manifestWebmanifest as unknown as string;
|
|
35
|
+
const ICON_SVG = iconSvg as unknown as string;
|
|
36
|
+
const SW_JS = swJs as unknown as string;
|
|
37
|
+
const CURVE_PAGE = curveDesignerHtml as unknown as string;
|
|
38
|
+
export const STATIC_ROUTE_ASSETS = {
|
|
39
|
+
appPage: APP_PAGE,
|
|
40
|
+
appJs: APP_JS,
|
|
41
|
+
hljsJs: HLJS_JS,
|
|
42
|
+
hljsCss: HLJS_CSS,
|
|
43
|
+
manifest: MANIFEST_WEBMANIFEST,
|
|
44
|
+
iconSvg: ICON_SVG,
|
|
45
|
+
serviceWorker: SW_JS,
|
|
46
|
+
curvePage: CURVE_PAGE,
|
|
47
|
+
};
|