mlx-bun 0.0.13 → 0.2.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.
Files changed (224) hide show
  1. package/README.md +31 -21
  2. package/bin/mlx-bun.mjs +1 -1
  3. package/docs/{design → archive}/hlg-sampling.md +3 -3
  4. package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
  5. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
  6. package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
  7. package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
  8. package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
  9. package/docs/design/colibri-glm52-port.md +1 -1
  10. package/docs/design/compat-cli-surface-design.md +1 -1
  11. package/docs/design/decode-speed-program.md +1 -1
  12. package/docs/design/docs-reorg-plan.md +1 -1
  13. package/docs/design/dspark-serving-program.md +1 -1
  14. package/docs/design/dspark-speculative-decoding.md +53 -3
  15. package/docs/design/grammar-spec-batching-integration.md +1 -1
  16. package/docs/design/mlx-lm-serving-execution-seam.md +81 -0
  17. package/docs/design/orpo-dynamic-lambda.md +1 -1
  18. package/docs/design/orpo-future-enhancements.md +1 -1
  19. package/docs/design/orpo-training.md +2 -2
  20. package/docs/design/parity-tier-dag.md +1 -1
  21. package/docs/design/repo-cleanup-plan.md +46 -4
  22. package/docs/design/segmented-backward-training.md +2 -2
  23. package/docs/design/ssd-kv-cold-tier.md +127 -0
  24. package/docs/design/turboquant-weights.md +467 -0
  25. package/docs/design/w4a16-compute-precision-spike.md +1 -1
  26. package/docs/design/web-chat-redesign.md +5 -5
  27. package/docs/planning/chunk-task-roadmap.md +1 -1
  28. package/docs/planning/curve-sampler-research-plan.md +4 -4
  29. package/docs/planning/memory-docs-and-dag-plan.md +1 -1
  30. package/docs/planning/release-notes-v0.2.0.md +49 -0
  31. package/docs/planning/video-series.md +421 -0
  32. package/docs/reference/cli.md +15 -4
  33. package/docs/reference/distribution.md +1 -0
  34. package/docs/reference/features-matrix.md +3 -2
  35. package/docs/reference/library-api.md +41 -1
  36. package/docs/reference/models.md +33 -0
  37. package/docs/reference/server-api.md +69 -14
  38. package/docs/reference/server-config.md +57 -33
  39. package/package.json +2 -2
  40. package/src/anthropic.ts +92 -3
  41. package/src/cli.ts +131 -36
  42. package/src/eval/kl.ts +27 -20
  43. package/src/eval/runner.ts +23 -4
  44. package/src/eval/tasks/bfcl.ts +2 -1
  45. package/src/eval/tasks/gsm8k.ts +2 -1
  46. package/src/eval/tasks/hashhop.ts +2 -1
  47. package/src/eval/tasks/humaneval.ts +5 -4
  48. package/src/eval/tasks/ifeval.ts +2 -1
  49. package/src/eval/tasks/mmlu.ts +2 -1
  50. package/src/expert-io.ts +3 -1
  51. package/src/expert-offload.ts +3 -1
  52. package/src/expert-trace.ts +3 -1
  53. package/src/fit.ts +24 -43
  54. package/src/flags.ts +7 -9
  55. package/src/generate.ts +107 -92
  56. package/src/grammar.ts +2 -1
  57. package/src/harness-pi.ts +1 -1
  58. package/src/index.ts +20 -0
  59. package/src/jobs/job-entry.ts +3 -2
  60. package/src/kv-scheme.ts +199 -0
  61. package/src/kv-store.ts +370 -205
  62. package/src/media-fetch.ts +19 -3
  63. package/src/memory/model.ts +2 -1
  64. package/src/memory/vault.ts +2 -1
  65. package/src/memory-plan.ts +18 -0
  66. package/src/mlx/ffi.ts +8 -11
  67. package/src/mlx/ops.ts +31 -6
  68. package/src/model/batched-mask.ts +1 -1
  69. package/src/model/batched-quant.ts +1 -1
  70. package/src/model/batched-rotating-quant.ts +43 -97
  71. package/src/model/batched-rotating-state.ts +73 -0
  72. package/src/model/batched-rotating.ts +56 -105
  73. package/src/model/batched-row-storage.ts +127 -0
  74. package/src/model/compiled-decode.ts +3 -2
  75. package/src/model/factory.ts +44 -49
  76. package/src/model/gemma4-base.ts +163 -10
  77. package/src/model/generated/gemma4-12b.ts +50 -146
  78. package/src/model/generated/gemma4-26b.ts +32 -92
  79. package/src/model/generated/gemma4-e4b.ts +26 -74
  80. package/src/model/glm52-cache.ts +19 -9
  81. package/src/model/glm52-memory.ts +28 -1
  82. package/src/model/minicpm5.ts +2 -1
  83. package/src/model/profile.ts +433 -0
  84. package/src/model/qwen3-delta.ts +98 -2
  85. package/src/model/qwen3-mrope.ts +252 -0
  86. package/src/model/qwen3_5.ts +217 -25
  87. package/src/native/frame_extract.swift +140 -0
  88. package/src/native-pack.ts +13 -6
  89. package/src/pi-web.ts +6 -5
  90. package/src/prompt-cache.ts +2 -2
  91. package/src/quantize/atomic-output.ts +38 -0
  92. package/src/quantize/calibration.ts +2 -1
  93. package/src/quantize/config-writer.ts +6 -0
  94. package/src/quantize/index.ts +28 -1
  95. package/src/quantize/job.ts +11 -0
  96. package/src/quantize/quantizer.ts +265 -100
  97. package/src/quantize/rotate.ts +603 -0
  98. package/src/quantize/safetensors-writer.ts +79 -1
  99. package/src/quantize/sensitivity.ts +41 -59
  100. package/src/quantize/weight-transform.ts +292 -0
  101. package/src/responses.ts +102 -2
  102. package/src/runtime-config.ts +67 -0
  103. package/src/sampler.ts +272 -0
  104. package/src/serve/admin-routes.ts +184 -0
  105. package/src/serve/aux-routes.ts +132 -0
  106. package/src/serve/batch-scheduler.ts +200 -87
  107. package/src/serve/completion-executor.ts +346 -0
  108. package/src/serve/completion-sink.ts +157 -0
  109. package/src/serve/discovery-routes.ts +205 -0
  110. package/src/serve/generation-gateway.ts +116 -109
  111. package/src/serve/kv-budget.ts +14 -0
  112. package/src/serve/lab-routes.ts +338 -0
  113. package/src/serve/model-admin-routes.ts +153 -0
  114. package/src/serve/prompt-response-trace.ts +147 -0
  115. package/src/serve/request-plan.ts +158 -0
  116. package/src/serve/static-routes.ts +101 -0
  117. package/src/server.ts +704 -1400
  118. package/src/spec/dflash-source.ts +2 -1
  119. package/src/spec/dspark/module-dflash.ts +1 -1
  120. package/src/spec/glm52-mtp-source.ts +8 -0
  121. package/src/spec/qwen-mtp-source.ts +431 -0
  122. package/src/spec/serve-loop.ts +36 -68
  123. package/src/ssd-cache.ts +17 -14
  124. package/src/ssd-durability.ts +195 -0
  125. package/src/train/flash-cce.ts +12 -11
  126. package/src/train/forward.ts +32 -1
  127. package/src/train/loss.ts +2 -1
  128. package/src/train/segmented.ts +4 -3
  129. package/src/train/trainer.ts +3 -2
  130. package/src/vision/preprocess.ts +1 -1
  131. package/src/vision/prompt.ts +47 -1
  132. package/src/vision/qwen3vl-preprocess.ts +409 -0
  133. package/src/vision/qwen3vl-prompt.ts +196 -0
  134. package/src/vision/qwen3vl-tower.ts +513 -0
  135. package/src/vision/video-frames.ts +148 -0
  136. package/src/web/app.js +10 -3
  137. package/src/web/src/chat.ts +12 -5
  138. package/src/weights.ts +81 -26
  139. /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
  140. /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
  141. /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
  142. /package/docs/{investigations → archive/investigations}/curve-runs/bisector-route.json +0 -0
  143. /package/docs/{investigations → archive/investigations}/curve-runs/bisector-trace.json +0 -0
  144. /package/docs/{investigations → archive/investigations}/curve-runs/curve-terrain.json +0 -0
  145. /package/docs/{investigations → archive/investigations}/curve-runs/curve-terrain.svg +0 -0
  146. /package/docs/{investigations → archive/investigations}/curve-terrain.html +0 -0
  147. /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
  148. /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
  149. /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
  150. /package/docs/{investigations → archive/investigations}/hlg-ab.html +0 -0
  151. /package/docs/{investigations → archive/investigations}/hlg-explorer.html +0 -0
  152. /package/docs/{investigations → archive/investigations}/hlg-figs/cliff.svg +0 -0
  153. /package/docs/{investigations → archive/investigations}/hlg-figs/cross.svg +0 -0
  154. /package/docs/{investigations → archive/investigations}/hlg-figs/edges.svg +0 -0
  155. /package/docs/{investigations → archive/investigations}/hlg-figs/k20-grids.svg +0 -0
  156. /package/docs/{investigations → archive/investigations}/hlg-figs/k20-peaks.svg +0 -0
  157. /package/docs/{investigations → archive/investigations}/hlg-figs/lw-curve.svg +0 -0
  158. /package/docs/{investigations → archive/investigations}/hlg-figs/terrain.svg +0 -0
  159. /package/docs/{investigations → archive/investigations}/hlg-report.html +0 -0
  160. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-ab.json +0 -0
  161. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-blind-prompts.md +0 -0
  162. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-blind.json +0 -0
  163. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-cliff.json +0 -0
  164. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-cross.json +0 -0
  165. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-edge.json +0 -0
  166. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-eval1.json +0 -0
  167. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-frontier.json +0 -0
  168. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-grid.json +0 -0
  169. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-grid2.json +0 -0
  170. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-lw-coarse.json +0 -0
  171. /package/docs/{investigations → archive/investigations}/hlg-runs/hlg-map.json +0 -0
  172. /package/docs/{investigations → archive/investigations}/hlg-runs/run0-original.log +0 -0
  173. /package/docs/{investigations → archive/investigations}/hlg-runs/runA-recommended.log +0 -0
  174. /package/docs/{investigations → archive/investigations}/hlg-runs/runAA-cliff-cpm5.log +0 -0
  175. /package/docs/{investigations → archive/investigations}/hlg-runs/runAB-grid2-e4b.log +0 -0
  176. /package/docs/{investigations → archive/investigations}/hlg-runs/runAC-peak-e4b-partial.log +0 -0
  177. /package/docs/{investigations → archive/investigations}/hlg-runs/runAD-ab-samples.log +0 -0
  178. /package/docs/{investigations → archive/investigations}/hlg-runs/runAE-edge-e4b.log +0 -0
  179. /package/docs/{investigations → archive/investigations}/hlg-runs/runAF-logit-calibration.log +0 -0
  180. /package/docs/{investigations → archive/investigations}/hlg-runs/runAG-eval-config2.log +0 -0
  181. /package/docs/{investigations → archive/investigations}/hlg-runs/runB-gain-variants.log +0 -0
  182. /package/docs/{investigations → archive/investigations}/hlg-runs/runC-pivots.log +0 -0
  183. /package/docs/{investigations → archive/investigations}/hlg-runs/runD-oetf.log +0 -0
  184. /package/docs/{investigations → archive/investigations}/hlg-runs/runE-eotf.log +0 -0
  185. /package/docs/{investigations → archive/investigations}/hlg-runs/runF-shaper-working.log +0 -0
  186. /package/docs/{investigations → archive/investigations}/hlg-runs/runG-shaper-sweep.log +0 -0
  187. /package/docs/{investigations → archive/investigations}/hlg-runs/runH-wsweep.log +0 -0
  188. /package/docs/{investigations → archive/investigations}/hlg-runs/runI-asweep.log +0 -0
  189. /package/docs/{investigations → archive/investigations}/hlg-runs/runJ-knobmap.log +0 -0
  190. /package/docs/{investigations → archive/investigations}/hlg-runs/runK-frontier.log +0 -0
  191. /package/docs/{investigations → archive/investigations}/hlg-runs/runL-widemap.log +0 -0
  192. /package/docs/{investigations → archive/investigations}/hlg-runs/runM-frontier-emb.log +0 -0
  193. /package/docs/{investigations → archive/investigations}/hlg-runs/runN-verify.log +0 -0
  194. /package/docs/{investigations → archive/investigations}/hlg-runs/runO-frontier-seed5000.log +0 -0
  195. /package/docs/{investigations → archive/investigations}/hlg-runs/runP-grid-AxSm.log +0 -0
  196. /package/docs/{investigations → archive/investigations}/hlg-runs/runQ-grid-tgW.log +0 -0
  197. /package/docs/{investigations → archive/investigations}/hlg-runs/runR-blind-transcript.log +0 -0
  198. /package/docs/{investigations → archive/investigations}/hlg-runs/runS-cross-coherence.log +0 -0
  199. /package/docs/{investigations → archive/investigations}/hlg-runs/runT-cross-cpm5.log +0 -0
  200. /package/docs/{investigations → archive/investigations}/hlg-runs/runU-cross-12b.log +0 -0
  201. /package/docs/{investigations → archive/investigations}/hlg-runs/runV-lw-e4b.log +0 -0
  202. /package/docs/{investigations → archive/investigations}/hlg-runs/runW-lw-12b.log +0 -0
  203. /package/docs/{investigations → archive/investigations}/hlg-runs/runX-lw-cpm5.log +0 -0
  204. /package/docs/{investigations → archive/investigations}/hlg-runs/runY-cliff-e4b.log +0 -0
  205. /package/docs/{investigations → archive/investigations}/hlg-runs/runZ-cliff-12b.log +0 -0
  206. /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
  207. /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
  208. /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
  209. /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
  210. /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
  211. /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
  212. /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
  213. /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
  214. /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
  215. /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
  216. /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
  217. /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
  218. /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
  219. /package/docs/{planning → archive/planning}/journal.md +0 -0
  220. /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
  221. /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
  222. /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
  223. /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
  224. /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
@@ -0,0 +1,158 @@
1
+ import type { GenerateOptions } from "../generate";
2
+ import type { RequestShape } from "./generation-gateway";
3
+
4
+ export interface DisposableResource {
5
+ dispose(): void;
6
+ }
7
+
8
+ export class RequestOwnership {
9
+ #resources = new Set<DisposableResource>();
10
+ #transferred = false;
11
+
12
+ own<T extends DisposableResource | null | undefined>(resource: T): T {
13
+ if (resource) this.#resources.add(resource);
14
+ return resource;
15
+ }
16
+
17
+ transfer(): void {
18
+ this.#transferred = true;
19
+ this.#resources.clear();
20
+ }
21
+
22
+ dispose(): void {
23
+ if (this.#transferred) return;
24
+ for (const resource of this.#resources) resource.dispose();
25
+ this.#resources.clear();
26
+ }
27
+ }
28
+
29
+ export interface RequestPlanInput {
30
+ promptIds: number[];
31
+ options: GenerateOptions & { stopSequences: string[] };
32
+ requestedMaxTokens: number;
33
+ maxSafeContext: number;
34
+ stream: boolean;
35
+ wantLogprobs: boolean;
36
+ topLogprobs: number;
37
+ adapterIds: string[];
38
+ hasVision: boolean;
39
+ userSeed: boolean;
40
+ hasGrammar: boolean;
41
+ hasDraft: boolean;
42
+ ownership: RequestOwnership;
43
+ }
44
+
45
+ export class RequestRejection {
46
+ readonly ok = false;
47
+ readonly status = 400;
48
+ readonly error: {
49
+ message: string;
50
+ type: "memory_admission";
51
+ code: "context_over_budget";
52
+ };
53
+
54
+ readonly #ownership: RequestOwnership;
55
+
56
+ constructor(message: string, ownership: RequestOwnership) {
57
+ this.error = {
58
+ message,
59
+ type: "memory_admission",
60
+ code: "context_over_budget",
61
+ };
62
+ this.#ownership = ownership;
63
+ }
64
+
65
+ dispose(): void {
66
+ this.#ownership.dispose();
67
+ }
68
+ }
69
+
70
+ export class RequestPlan {
71
+ readonly ok = true;
72
+ readonly promptIds: number[];
73
+ readonly options: GenerateOptions & { stopSequences: string[] };
74
+ readonly shape: RequestShape;
75
+ readonly captureLogprobs: boolean;
76
+ readonly wantLogprobs: boolean;
77
+ readonly topLogprobs: number;
78
+ readonly #ownership: RequestOwnership;
79
+
80
+ constructor(input: {
81
+ promptIds: number[];
82
+ options: GenerateOptions & { stopSequences: string[] };
83
+ shape: RequestShape;
84
+ captureLogprobs: boolean;
85
+ wantLogprobs: boolean;
86
+ topLogprobs: number;
87
+ ownership: RequestOwnership;
88
+ }) {
89
+ this.promptIds = input.promptIds;
90
+ this.options = input.options;
91
+ this.shape = input.shape;
92
+ this.captureLogprobs = input.captureLogprobs;
93
+ this.wantLogprobs = input.wantLogprobs;
94
+ this.topLogprobs = input.topLogprobs;
95
+ this.#ownership = input.ownership;
96
+ }
97
+
98
+ transferOwnership(): void {
99
+ this.#ownership.transfer();
100
+ }
101
+
102
+ dispose(): void {
103
+ this.#ownership.dispose();
104
+ }
105
+ }
106
+
107
+ export type PlanRequestResult = RequestPlan | RequestRejection;
108
+
109
+ /** Compile the model-independent part of request execution into one value.
110
+ * Prompt/media construction happens before this boundary; admission, capture
111
+ * options, adapter selection, and lane shape are derived here once for chat
112
+ * and raw completions. */
113
+ export function planRequest(input: RequestPlanInput): PlanRequestResult {
114
+ const available = input.maxSafeContext - input.promptIds.length;
115
+ if (available < 1) {
116
+ return new RequestRejection(
117
+ `prompt is ${input.promptIds.length} tokens but the memory budget caps ` +
118
+ `safe context at ${input.maxSafeContext} — no room to generate; ` +
119
+ "shorten the prompt or raise --memory-budget",
120
+ input.ownership,
121
+ );
122
+ }
123
+
124
+ const options = { ...input.options };
125
+ options.maxTokens = Math.min(input.requestedMaxTokens, available);
126
+ if (input.adapterIds.length) options.adapters = [...input.adapterIds];
127
+ const captureLogprobs = !input.stream && (input.wantLogprobs || input.topLogprobs > 0);
128
+ if (captureLogprobs) {
129
+ options.logprobs = input.wantLogprobs;
130
+ options.topLogprobs = input.topLogprobs;
131
+ }
132
+
133
+ const shape: RequestShape = {
134
+ hasVision: input.hasVision,
135
+ hasAdapters: !!options.adapters?.length,
136
+ hasRepetitionPenalty: !!options.repetitionPenalty,
137
+ hasLogitsExtras: !!(
138
+ options.minP || options.xtcProbability || options.logitBias ||
139
+ options.presencePenalty || options.frequencyPenalty
140
+ ),
141
+ wantsLogprobs: captureLogprobs,
142
+ userSeed: input.userSeed,
143
+ kvQuant: !!(options.kvConfig?.length || options.kvBits),
144
+ turboQuant: !!options.turboQuant,
145
+ hasGrammar: input.hasGrammar,
146
+ hasDraft: input.hasDraft,
147
+ };
148
+
149
+ return new RequestPlan({
150
+ promptIds: input.promptIds,
151
+ options,
152
+ shape,
153
+ captureLogprobs,
154
+ wantLogprobs: input.wantLogprobs,
155
+ topLogprobs: input.topLogprobs,
156
+ ownership: input.ownership,
157
+ });
158
+ }
@@ -0,0 +1,101 @@
1
+ import { readFileSync } from "node:fs";
2
+
3
+ export interface StaticRouteAssets {
4
+ appPage: string;
5
+ appJs: string;
6
+ hljsJs: string;
7
+ hljsCss: string;
8
+ manifest: string;
9
+ iconSvg: string;
10
+ serviceWorker: string;
11
+ curvePage: string;
12
+ }
13
+
14
+ const ASSET_HEADERS = { "cache-control": "public, max-age=3600" } as const;
15
+ const LEGACY_PATHS = new Set(["/status", "/chat", "/quantize", "/finetune", "/dataset"]);
16
+
17
+ /** Serve the web shell and its static companion pages. Returns null when the
18
+ * request belongs to another route family. */
19
+ export function handleStaticRoute(
20
+ url: URL,
21
+ request: Request,
22
+ assets: StaticRouteAssets,
23
+ ): Response | null {
24
+ if (request.method !== "GET") return null;
25
+
26
+ switch (url.pathname) {
27
+ case "/":
28
+ return new Response(assets.appPage, {
29
+ headers: { "content-type": "text/html; charset=utf-8" },
30
+ });
31
+ case "/assets/hljs.js":
32
+ return new Response(assets.hljsJs, {
33
+ headers: { "content-type": "text/javascript; charset=utf-8", ...ASSET_HEADERS },
34
+ });
35
+ case "/assets/hljs.css":
36
+ return new Response(assets.hljsCss, {
37
+ headers: { "content-type": "text/css; charset=utf-8", ...ASSET_HEADERS },
38
+ });
39
+ case "/assets/app.js":
40
+ return new Response(assets.appJs, {
41
+ headers: { "content-type": "text/javascript; charset=utf-8", ...ASSET_HEADERS },
42
+ });
43
+ case "/manifest.webmanifest":
44
+ return new Response(assets.manifest, {
45
+ headers: { "content-type": "application/manifest+json; charset=utf-8", ...ASSET_HEADERS },
46
+ });
47
+ case "/assets/icon.svg":
48
+ return new Response(assets.iconSvg, {
49
+ headers: { "content-type": "image/svg+xml; charset=utf-8", ...ASSET_HEADERS },
50
+ });
51
+ case "/sw.js":
52
+ return new Response(assets.serviceWorker, {
53
+ headers: { "content-type": "text/javascript; charset=utf-8", "cache-control": "no-store" },
54
+ });
55
+ case "/curves": {
56
+ let html = assets.curvePage;
57
+ try {
58
+ html = readFileSync(new URL("../assets/curve-designer.html", import.meta.url), "utf8");
59
+ } catch {
60
+ // Compiled binaries use the embedded copy.
61
+ }
62
+ return new Response(html, {
63
+ headers: { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" },
64
+ });
65
+ }
66
+ case "/dag":
67
+ try {
68
+ const html = readFileSync(
69
+ new URL("../../docs/dag/training-inference-map.html", import.meta.url),
70
+ "utf8",
71
+ );
72
+ return new Response(html, {
73
+ headers: { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" },
74
+ });
75
+ } catch {
76
+ return new Response(
77
+ "DAG map artifact not found at docs/dag/training-inference-map.html",
78
+ { status: 404 },
79
+ );
80
+ }
81
+ case "/curve-terrain":
82
+ try {
83
+ const html = readFileSync(
84
+ new URL("../../docs/archive/investigations/curve-terrain.html", import.meta.url),
85
+ "utf8",
86
+ );
87
+ return new Response(html, {
88
+ headers: { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" },
89
+ });
90
+ } catch {
91
+ return new Response(
92
+ "curve terrain artifact not found; run scripts/experiments/curve-terrain.ts first",
93
+ { status: 404 },
94
+ );
95
+ }
96
+ }
97
+
98
+ return LEGACY_PATHS.has(url.pathname)
99
+ ? Response.redirect(`/#${url.pathname}`, 302)
100
+ : null;
101
+ }