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.
Files changed (427) hide show
  1. package/README.md +71 -578
  2. package/bin/mlx-bun.mjs +1 -1
  3. package/docs/README.md +91 -0
  4. package/docs/{design → archive}/hlg-sampling.md +3 -3
  5. package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
  6. package/docs/{design → archive/investigations}/colibri-glm52-port.md +1 -1
  7. package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
  8. package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
  9. package/docs/{investigations → archive/investigations}/hlg-sampling-investigation.md +1 -1
  10. package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
  11. package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
  12. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +92 -0
  13. package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
  14. package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
  15. package/docs/{planning → archive/planning}/chat-ui-vision.md +1 -1
  16. package/docs/{planning → archive/planning}/chunk-task-roadmap.md +1 -1
  17. package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +4 -4
  18. package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +1 -1
  19. package/docs/{planning → archive/planning}/release-notes-v0.0.9.md +1 -1
  20. package/docs/archive/planning/release-notes-v0.2.0.md +49 -0
  21. package/docs/{planning → archive/planning}/website-readme-pass-plan.md +1 -1
  22. package/docs/design/batching.md +569 -0
  23. package/docs/design/decode-speed-program.md +3178 -169
  24. package/docs/design/dreaming-nightly-pipeline.md +675 -282
  25. package/docs/design/generic-model-support.md +579 -334
  26. package/docs/design/kv-cache.md +680 -0
  27. package/docs/design/orpo-training.md +673 -1239
  28. package/docs/design/speculative-decoding.md +1627 -0
  29. package/docs/design/turboquant.md +2102 -0
  30. package/docs/design/unified-engine-frontier-plan.md +1831 -727
  31. package/docs/design/web-chat-redesign.md +666 -1083
  32. package/docs/planning/PRODUCT_ROADMAP.md +34 -1
  33. package/docs/planning/release-notes-v0.3.0.md +35 -0
  34. package/docs/planning/video-series.md +421 -0
  35. package/docs/reference/benchmarks.md +1162 -0
  36. package/docs/reference/cli.md +395 -149
  37. package/docs/reference/distribution.md +321 -181
  38. package/docs/reference/environment.md +348 -0
  39. package/docs/reference/glossary.md +39 -0
  40. package/docs/reference/library-api.md +580 -142
  41. package/docs/reference/memory.md +227 -64
  42. package/docs/reference/models.md +137 -6
  43. package/docs/reference/server-api.md +938 -422
  44. package/docs/reference/server-config.md +652 -320
  45. package/docs/reference/training.md +393 -254
  46. package/docs/reference/troubleshooting.md +166 -0
  47. package/package.json +10 -5
  48. package/src/admission-plan.ts +18 -0
  49. package/src/anthropic.ts +92 -3
  50. package/src/audio/decode.ts +2 -2
  51. package/src/audio/features.ts +2 -2
  52. package/src/backends/mlx/autoregressive.ts +108 -0
  53. package/src/backends/mlx/batch-group.ts +1646 -0
  54. package/src/backends/mlx/diffusion.ts +39 -0
  55. package/src/backends/mlx/draft-target.ts +47 -0
  56. package/src/backends/mlx/evaluation.ts +105 -0
  57. package/src/backends/mlx/fill-append.ts +45 -0
  58. package/src/backends/mlx/gateway-binding.ts +71 -0
  59. package/src/backends/mlx/graph.ts +38 -0
  60. package/src/backends/mlx/memory-client.ts +189 -0
  61. package/src/backends/mlx/memory-guard.ts +40 -0
  62. package/src/backends/mlx/methods.ts +90 -0
  63. package/src/backends/mlx/model-prompt.ts +164 -0
  64. package/src/backends/mlx/model-serving.ts +79 -0
  65. package/src/backends/mlx/prefill.ts +33 -0
  66. package/src/backends/mlx/request-policy.ts +20 -0
  67. package/src/backends/mlx/rollback.ts +51 -0
  68. package/src/backends/mlx/serial-executor.ts +273 -0
  69. package/src/backends/mlx/speculative.ts +114 -0
  70. package/src/backends/mlx/state-views.ts +26 -0
  71. package/src/backends/mlx/text-engine.ts +73 -0
  72. package/src/cli.ts +189 -61
  73. package/src/client.ts +66 -0
  74. package/src/config.ts +21 -4
  75. package/src/contracts/completion.ts +16 -0
  76. package/src/contracts/execution.ts +49 -0
  77. package/src/contracts/generation.ts +103 -0
  78. package/src/contracts/host.ts +7 -0
  79. package/src/contracts/jobs.ts +66 -0
  80. package/src/contracts/pi-provider.ts +30 -0
  81. package/src/contracts/pi.ts +259 -0
  82. package/src/contracts/resources.ts +18 -0
  83. package/src/contracts/scheduling.ts +27 -0
  84. package/src/contracts/tsconfig.json +14 -0
  85. package/src/diffusion/diffusion-generate.ts +218 -153
  86. package/src/embed.ts +1 -1
  87. package/src/engine/admission.ts +59 -0
  88. package/src/engine/cancellation.ts +38 -0
  89. package/src/engine/engine.ts +56 -0
  90. package/src/engine/execution-coordinator.ts +70 -0
  91. package/src/engine/execution-plan.ts +51 -0
  92. package/src/engine/resources.ts +42 -0
  93. package/src/engine/scheduler.ts +67 -0
  94. package/src/engine/session.ts +247 -0
  95. package/src/eval/README.md +44 -1
  96. package/src/eval/kl.ts +263 -23
  97. package/src/eval/reference-logits.ts +207 -0
  98. package/src/eval/runner.ts +10 -79
  99. package/src/eval/tasks/bfcl.ts +2 -1
  100. package/src/eval/tasks/gsm8k.ts +2 -1
  101. package/src/eval/tasks/hashhop.ts +2 -1
  102. package/src/eval/tasks/humaneval.ts +5 -4
  103. package/src/eval/tasks/ifeval.ts +2 -1
  104. package/src/eval/tasks/mmlu.ts +2 -1
  105. package/src/expert-io.ts +3 -1
  106. package/src/expert-offload.ts +3 -1
  107. package/src/fill/echo-index.ts +188 -0
  108. package/src/fill/fill-session.ts +452 -0
  109. package/src/fill/proposal.ts +68 -0
  110. package/src/fill/schema-rows.ts +506 -0
  111. package/src/fill/tool-boundary.ts +103 -0
  112. package/src/fit.ts +24 -43
  113. package/src/generate.ts +740 -337
  114. package/src/grammar.ts +14 -8
  115. package/src/harness-pi.ts +15 -34
  116. package/src/hub-rest.ts +4 -4
  117. package/src/index.ts +27 -0
  118. package/src/inference/denoising.ts +17 -0
  119. package/src/inference/graph.ts +33 -0
  120. package/src/inference/prefill.ts +39 -0
  121. package/src/inference/rollback.ts +7 -0
  122. package/src/jobs/db.ts +4 -0
  123. package/src/jobs/index.ts +2 -0
  124. package/src/jobs/job-entry.ts +15 -14
  125. package/src/jobs/runner.ts +98 -13
  126. package/src/jobs/task-client.ts +19 -0
  127. package/src/jobs/types.ts +2 -58
  128. package/src/kv-scheme.ts +199 -0
  129. package/src/kv-store.ts +459 -234
  130. package/src/lab/README.md +18 -0
  131. package/src/{assets → lab/curve}/curve-designer.html +2 -2
  132. package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
  133. package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +7 -5
  134. package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
  135. package/src/library.ts +40 -0
  136. package/src/lora.ts +18 -0
  137. package/src/media-fetch.ts +20 -4
  138. package/src/memory/article.ts +1 -1
  139. package/src/memory/chunk.ts +1 -1
  140. package/src/memory/model.ts +32 -170
  141. package/src/memory/prompts.ts +1 -1
  142. package/src/memory/rest.ts +1 -1
  143. package/src/memory/schedule.ts +1 -1
  144. package/src/memory/stages.ts +4 -1
  145. package/src/memory/vault.ts +3 -4
  146. package/src/mlx/array.ts +9 -10
  147. package/src/mlx/compile.ts +12 -2
  148. package/src/mlx/ffi.ts +66 -22
  149. package/src/mlx/materialize.ts +23 -0
  150. package/src/mlx/metal-kernel.ts +10 -11
  151. package/src/mlx/ops.ts +64 -19
  152. package/src/mlx/quantized-rows.ts +36 -0
  153. package/src/mlx/token-bitmask.ts +52 -0
  154. package/src/mlx/turboquant-kv-decode.ts +82 -0
  155. package/src/mlx/turboquant-kv-inverse.ts +122 -0
  156. package/src/mlx/turboquant-ops.ts +33 -3
  157. package/src/mlx/turboquant-tables.ts +2 -2
  158. package/src/model/batched-mask.ts +9 -3
  159. package/src/model/batched-quant.ts +2 -2
  160. package/src/model/batched-rotating-quant.ts +45 -99
  161. package/src/model/batched-rotating-state.ts +73 -0
  162. package/src/model/batched-rotating.ts +57 -106
  163. package/src/model/batched-row-storage.ts +127 -0
  164. package/src/model/compiled-decode.ts +4 -3
  165. package/src/model/diffusion-gemma.ts +8 -8
  166. package/src/model/factory.ts +87 -49
  167. package/src/model/fingerprint.ts +1 -1
  168. package/src/model/flash-attention.ts +3 -3
  169. package/src/model/gemma4-base.ts +187 -17
  170. package/src/model/gemma4.ts +6 -6
  171. package/src/model/generated/gemma4-12b.ts +52 -148
  172. package/src/model/generated/gemma4-26b.ts +34 -94
  173. package/src/model/generated/gemma4-e4b.ts +28 -76
  174. package/src/model/glm52-cache.ts +19 -9
  175. package/src/model/glm52-dsa.ts +13 -9
  176. package/src/model/glm52-memory.ts +28 -1
  177. package/src/model/implementation.ts +69 -0
  178. package/src/model/minicpm5.ts +7 -8
  179. package/src/model/profile.ts +443 -0
  180. package/src/model/qwen-append.ts +12 -0
  181. package/src/model/qwen-conv.ts +52 -0
  182. package/src/model/qwen3-delta.ts +98 -2
  183. package/src/model/qwen3-mrope.ts +252 -0
  184. package/src/model/qwen3_5-checkpoint.ts +164 -0
  185. package/src/model/qwen3_5.ts +336 -60
  186. package/src/model/support.ts +1 -1
  187. package/src/model/trellis-balanced-scatter.ts +51 -0
  188. package/src/model/trellis-linear.ts +672 -0
  189. package/src/model/trellis-shared-m.ts +151 -0
  190. package/src/model/trellis-shared-scatter.ts +144 -0
  191. package/src/model/trellis-splitk-prefill.ts +158 -0
  192. package/src/model/trellis-tiled-prefill.ts +136 -0
  193. package/src/model/trellis-vector-expand.ts +62 -0
  194. package/src/model/trellis-wide-prefill.ts +94 -0
  195. package/src/model/universal/dense.ts +1 -1
  196. package/src/model/universal/modules.ts +8 -1
  197. package/src/native/frame_extract.swift +140 -0
  198. package/src/native-pack.ts +15 -7
  199. package/src/pi-provider.ts +6 -64
  200. package/src/pi-web.ts +14 -320
  201. package/src/prompt-cache.ts +97 -54
  202. package/src/quantize/allocator.ts +1 -1
  203. package/src/quantize/atomic-output.ts +38 -0
  204. package/src/quantize/calibration.ts +2 -1
  205. package/src/quantize/config-writer.ts +16 -3
  206. package/src/quantize/index.ts +28 -1
  207. package/src/quantize/job.ts +11 -0
  208. package/src/quantize/quantizer.ts +265 -100
  209. package/src/quantize/rotate.ts +603 -0
  210. package/src/quantize/safetensors-writer.ts +79 -1
  211. package/src/quantize/sensitivity.ts +41 -59
  212. package/src/quantize/trellis.ts +586 -0
  213. package/src/quantize/weight-transform.ts +292 -0
  214. package/src/responses.ts +130 -3
  215. package/src/runtime-config.ts +81 -0
  216. package/src/sampler.ts +276 -4
  217. package/src/serve/admin-routes.ts +184 -0
  218. package/src/serve/aux-routes.ts +132 -0
  219. package/src/serve/batch-scheduler.ts +8 -1558
  220. package/src/serve/chat-request.ts +391 -0
  221. package/src/serve/chat-stage.ts +195 -0
  222. package/src/serve/checkpoint-identity.ts +64 -0
  223. package/src/serve/completion-executor.ts +354 -0
  224. package/src/serve/completion-sink.ts +157 -0
  225. package/src/serve/discovery-routes.ts +204 -0
  226. package/src/serve/generation-gateway.ts +211 -243
  227. package/src/serve/http.ts +159 -0
  228. package/src/serve/inference-request.ts +79 -0
  229. package/src/serve/isolate.ts +297 -105
  230. package/src/serve/kv-budget.ts +14 -0
  231. package/src/serve/lab-routes.ts +341 -0
  232. package/src/serve/lane-registry.ts +2 -1
  233. package/src/serve/model-admin-routes.ts +155 -0
  234. package/src/serve/model-binding.ts +43 -0
  235. package/src/serve/model-host.ts +512 -0
  236. package/src/serve/openai-wire.ts +103 -0
  237. package/src/serve/parent-application.ts +56 -0
  238. package/src/serve/pipeline.ts +33 -0
  239. package/src/serve/preparation.ts +33 -0
  240. package/src/serve/prompt-response-trace.ts +147 -0
  241. package/src/serve/request-plan.ts +162 -0
  242. package/src/serve/request-prep.ts +346 -0
  243. package/src/serve/response-lease.ts +24 -0
  244. package/src/serve/responses-client.ts +69 -0
  245. package/src/serve/session-completion-engine.ts +110 -0
  246. package/src/serve/session-search.ts +1 -1
  247. package/src/serve/static-routes.ts +101 -0
  248. package/src/serve/text-completion-stage.ts +104 -0
  249. package/src/serve/token-streams.ts +519 -0
  250. package/src/server.ts +523 -3551
  251. package/src/spec/assistant-source.ts +10 -44
  252. package/src/spec/deepspec-source.ts +6 -6
  253. package/src/spec/dflash-source.ts +9 -8
  254. package/src/spec/dspark/ab-stats.ts +3 -3
  255. package/src/spec/dspark/calibration.ts +2 -2
  256. package/src/spec/dspark/deepspec-module.ts +2 -2
  257. package/src/spec/dspark/generate-dflash.ts +2 -2
  258. package/src/spec/dspark/generate.ts +2 -2
  259. package/src/spec/dspark/loader.ts +1 -1
  260. package/src/spec/dspark/module-dflash.ts +5 -4
  261. package/src/spec/dspark/module.ts +3 -3
  262. package/src/spec/dspark/quantize-drafter.ts +1 -1
  263. package/src/spec/generate.ts +1 -1
  264. package/src/spec/glm52-mtp-source.ts +9 -1
  265. package/src/spec/ngram-source.ts +1 -1
  266. package/src/spec/prefix-state.ts +45 -0
  267. package/src/spec/qwen-mtp-source.ts +528 -0
  268. package/src/spec/serve-loop.ts +179 -213
  269. package/src/spec/source.ts +42 -10
  270. package/src/spec/two-model.ts +1 -1
  271. package/src/ssd-cache.ts +95 -24
  272. package/src/ssd-durability.ts +207 -0
  273. package/src/tool-call.ts +51 -14
  274. package/src/train/flash-cce.ts +14 -13
  275. package/src/train/forward.ts +38 -1
  276. package/src/train/loss.ts +3 -2
  277. package/src/train/prefix-shared.ts +5 -1
  278. package/src/train/segmented.ts +9 -6
  279. package/src/train/trainer.ts +9 -8
  280. package/src/vision/preprocess.ts +1 -1
  281. package/src/vision/prompt.ts +48 -2
  282. package/src/vision/qwen3vl-preprocess.ts +409 -0
  283. package/src/vision/qwen3vl-prompt.ts +196 -0
  284. package/src/vision/qwen3vl-tower.ts +555 -0
  285. package/src/vision/video-frames.ts +148 -0
  286. package/src/web/app.html +1 -1
  287. package/src/web/app.js +15 -6
  288. package/src/web/src/adapters-panel.ts +3 -3
  289. package/src/web/src/assistant.ts +2 -36
  290. package/src/web/src/chat.ts +16 -9
  291. package/src/web/src/composer.ts +4 -4
  292. package/src/web/src/hub.ts +1 -1
  293. package/src/web/src/markdown.ts +0 -0
  294. package/src/web/src/memory-panel.ts +1 -1
  295. package/src/web/src/model-picker.ts +1 -1
  296. package/src/web/src/palette.ts +1 -1
  297. package/src/web/src/protocol.ts +3 -39
  298. package/src/web/src/sessions.ts +1 -1
  299. package/src/web/src/ui-catalog.ts +4 -18
  300. package/src/web-assets.ts +47 -0
  301. package/src/weights.ts +134 -33
  302. package/docs/archive/mlx-bun-lab-report.html +0 -275
  303. package/docs/archive/wwdc-mlx-bun.html +0 -848
  304. package/docs/design/adapters-end-to-end.md +0 -205
  305. package/docs/design/batching-perf-path.md +0 -255
  306. package/docs/design/batching-v2-plan.md +0 -529
  307. package/docs/design/bucketing-stage.md +0 -197
  308. package/docs/design/compat-cli-surface-design.md +0 -230
  309. package/docs/design/docs-reorg-plan.md +0 -165
  310. package/docs/design/dspark-serving-program.md +0 -371
  311. package/docs/design/dspark-speculative-decoding.md +0 -268
  312. package/docs/design/grammar-spec-batching-integration.md +0 -301
  313. package/docs/design/memory-inference-path.md +0 -422
  314. package/docs/design/memory-synthesis.md +0 -287
  315. package/docs/design/memory-system.md +0 -237
  316. package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
  317. package/docs/design/omlx-adoption-map.md +0 -98
  318. package/docs/design/orpo-dynamic-lambda.md +0 -220
  319. package/docs/design/orpo-future-enhancements.md +0 -340
  320. package/docs/design/paged-kv-cache.md +0 -214
  321. package/docs/design/parallel-slots.md +0 -567
  322. package/docs/design/parity-tier-dag.md +0 -161
  323. package/docs/design/repo-cleanup-plan.md +0 -189
  324. package/docs/design/runtime-isolation.md +0 -263
  325. package/docs/design/segmented-backward-training.md +0 -543
  326. package/docs/design/spec-decode-larger-targets.md +0 -229
  327. package/docs/design/ssd-kv-cold-tier.md +0 -288
  328. package/docs/design/structured-output.md +0 -484
  329. package/docs/design/tauri-desktop-app.md +0 -127
  330. package/docs/design/the-dreaming-master-plan.md +0 -445
  331. package/docs/design/turboquant-kv.md +0 -235
  332. package/docs/design/w4a16-compute-precision-spike.md +0 -232
  333. package/docs/design/web-chat-beat-matrix.md +0 -315
  334. package/docs/design/write-pipeline-entity.md +0 -468
  335. package/docs/investigations/curve-runs/bisector-route.json +0 -98
  336. package/docs/investigations/curve-runs/bisector-trace.json +0 -1393
  337. package/docs/investigations/curve-runs/curve-terrain.json +0 -1179
  338. package/docs/investigations/curve-runs/curve-terrain.svg +0 -42
  339. package/docs/investigations/hlg-ab.html +0 -34
  340. package/docs/investigations/hlg-explorer.html +0 -238
  341. package/docs/investigations/hlg-figs/cliff.svg +0 -1
  342. package/docs/investigations/hlg-figs/cross.svg +0 -1
  343. package/docs/investigations/hlg-figs/edges.svg +0 -1
  344. package/docs/investigations/hlg-figs/k20-grids.svg +0 -1
  345. package/docs/investigations/hlg-figs/k20-peaks.svg +0 -1
  346. package/docs/investigations/hlg-figs/lw-curve.svg +0 -1
  347. package/docs/investigations/hlg-figs/terrain.svg +0 -1
  348. package/docs/investigations/hlg-report.html +0 -262
  349. package/docs/investigations/hlg-runs/hlg-ab.json +0 -149
  350. package/docs/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
  351. package/docs/investigations/hlg-runs/hlg-blind.json +0 -107
  352. package/docs/investigations/hlg-runs/hlg-cliff.json +0 -197
  353. package/docs/investigations/hlg-runs/hlg-cross.json +0 -505
  354. package/docs/investigations/hlg-runs/hlg-edge.json +0 -388
  355. package/docs/investigations/hlg-runs/hlg-eval1.json +0 -25
  356. package/docs/investigations/hlg-runs/hlg-frontier.json +0 -86
  357. package/docs/investigations/hlg-runs/hlg-grid.json +0 -242
  358. package/docs/investigations/hlg-runs/hlg-grid2.json +0 -343
  359. package/docs/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
  360. package/docs/investigations/hlg-runs/hlg-map.json +0 -383
  361. package/docs/investigations/hlg-runs/run0-original.log +0 -159
  362. package/docs/investigations/hlg-runs/runA-recommended.log +0 -131
  363. package/docs/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
  364. package/docs/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
  365. package/docs/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
  366. package/docs/investigations/hlg-runs/runAD-ab-samples.log +0 -8
  367. package/docs/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
  368. package/docs/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
  369. package/docs/investigations/hlg-runs/runAG-eval-config2.log +0 -16
  370. package/docs/investigations/hlg-runs/runB-gain-variants.log +0 -192
  371. package/docs/investigations/hlg-runs/runC-pivots.log +0 -162
  372. package/docs/investigations/hlg-runs/runD-oetf.log +0 -132
  373. package/docs/investigations/hlg-runs/runE-eotf.log +0 -162
  374. package/docs/investigations/hlg-runs/runF-shaper-working.log +0 -86
  375. package/docs/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
  376. package/docs/investigations/hlg-runs/runH-wsweep.log +0 -176
  377. package/docs/investigations/hlg-runs/runI-asweep.log +0 -176
  378. package/docs/investigations/hlg-runs/runJ-knobmap.log +0 -49
  379. package/docs/investigations/hlg-runs/runK-frontier.log +0 -19
  380. package/docs/investigations/hlg-runs/runL-widemap.log +0 -65
  381. package/docs/investigations/hlg-runs/runM-frontier-emb.log +0 -15
  382. package/docs/investigations/hlg-runs/runN-verify.log +0 -116
  383. package/docs/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
  384. package/docs/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
  385. package/docs/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
  386. package/docs/investigations/hlg-runs/runR-blind-transcript.log +0 -79
  387. package/docs/investigations/hlg-runs/runS-cross-coherence.log +0 -33
  388. package/docs/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
  389. package/docs/investigations/hlg-runs/runU-cross-12b.log +0 -33
  390. package/docs/investigations/hlg-runs/runV-lw-e4b.log +0 -22
  391. package/docs/investigations/hlg-runs/runW-lw-12b.log +0 -22
  392. package/docs/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
  393. package/docs/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
  394. package/docs/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
  395. package/docs/planning/IDEAS.md +0 -69
  396. package/docs/reference/embedding.md +0 -197
  397. package/docs/reference/features-matrix.md +0 -100
  398. package/docs/reference/orpo-quickstart.md +0 -135
  399. package/src/flags.ts +0 -13
  400. /package/docs/{investigations → archive/investigations}/chunk-finetune-experiment.md +0 -0
  401. /package/docs/{investigations → archive/investigations}/colibri-oracle-pin.md +0 -0
  402. /package/docs/{investigations → archive/investigations}/curve-bisector-routing.md +0 -0
  403. /package/docs/{investigations → archive/investigations}/decode-roofline-lookagain.md +0 -0
  404. /package/docs/{investigations → archive/investigations}/dspark-handoff.md +0 -0
  405. /package/docs/{investigations → archive/investigations}/expert-offload-single-user-moe.md +0 -0
  406. /package/docs/{investigations → archive/investigations}/indexshare-performance-spike.md +0 -0
  407. /package/docs/{investigations → archive/investigations}/kernel-perf-review-2026-07.md +0 -0
  408. /package/docs/{investigations → archive/investigations}/lab-build-journal.md +0 -0
  409. /package/docs/{investigations → archive/investigations}/openwiki-evaluation.md +0 -0
  410. /package/docs/{investigations → archive/investigations}/orpo-base-uf-experiment-and-directions.md +0 -0
  411. /package/docs/{investigations → archive/investigations}/orpo-flash-cce-pin-leak.md +0 -0
  412. /package/docs/{investigations → archive/investigations}/orpo-uf-testing-handoff.md +0 -0
  413. /package/docs/{investigations → archive/investigations}/pi-builtin-investigation.md +0 -0
  414. /package/docs/{investigations → archive/investigations}/segmented-backward-handoff.md +0 -0
  415. /package/docs/{investigations → archive/investigations}/starter-model-port-handoff.md +0 -0
  416. /package/docs/{investigations → archive/investigations}/steel-flash-cce-handoff.md +0 -0
  417. /package/docs/{investigations → archive/investigations}/trainer-validation-experiment.md +0 -0
  418. /package/docs/{planning → archive/planning}/chat-ui-vision-memory-first.md +0 -0
  419. /package/docs/{planning → archive/planning}/journal.md +0 -0
  420. /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
  421. /package/docs/{planning → archive/planning}/release-notes-v0.0.10.md +0 -0
  422. /package/docs/{planning → archive/planning}/release-notes-v0.0.11.md +0 -0
  423. /package/docs/{planning → archive/planning}/release-notes-v0.0.12.md +0 -0
  424. /package/docs/{planning → archive/planning}/release-notes-v0.0.13.md +0 -0
  425. /package/docs/{planning → archive/planning}/web-ui-pass-plan.md +0 -0
  426. /package/{docs/investigations → src/serve/assets}/curve-terrain.html +0 -0
  427. /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
package/src/sampler.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  import { Dtype } from "./mlx/ffi";
12
12
  import { MlxArray } from "./mlx/array";
13
13
  import * as ops from "./mlx/ops";
14
- import { applyCurve, type CurveParams } from "./curve-sampler";
14
+ import { applyCurve, type CurveParams } from "./lab/curve/curve-sampler";
15
15
 
16
16
  /** Resolved HLG sampling config (the user-facing knobs). The mid gain is NOT
17
17
  * here — it folds from temperature (m = 1/T) when the sampler is built. */
@@ -82,11 +82,11 @@ export interface SamplerOptions {
82
82
  seed?: number;
83
83
  /** HLG tone-curve sampling. When enabled, replaces temperature's flat slope
84
84
  * with the piecewise curve (temperature becomes the mid gain). Off/undefined
85
- * ⇒ the plain temperature path, unchanged. docs/design/hlg-sampling.md. */
85
+ * ⇒ the plain temperature path, unchanged. docs/archive/hlg-sampling.md. */
86
86
  hlg?: HlgConfig;
87
87
  /** v2 log-prob transfer-curve sampler. When set, the drawn monotone curve
88
88
  * REPLACES temperature+softmax entirely (stochastic, seeded) — see
89
- * src/curve-sampler.ts. Identity curve ≡ temperature 1. */
89
+ * src/lab/curve/curve-sampler.ts. Identity curve ≡ temperature 1. */
90
90
  curve?: CurveParams;
91
91
  }
92
92
 
@@ -112,6 +112,75 @@ export type Sampler = (logprobs: MlxArray, step: number) => MlxArray;
112
112
  /** (deviceTokens [n] | null, logits [1, V]) → logits [1, V]. */
113
113
  export type LogitsProcessor = (tokens: MlxArray | null, logits: MlxArray) => MlxArray;
114
114
 
115
+ /** Optional arrays captured from the same post-processor logprobs used to
116
+ * sample a token. The caller controls readback timing and owns disposal. */
117
+ export interface StepExtras {
118
+ sel: MlxArray | null;
119
+ topIdx: MlxArray | null;
120
+ topVals: MlxArray | null;
121
+ }
122
+
123
+ export interface StepSample<T> {
124
+ token: T;
125
+ extras: StepExtras | null;
126
+ }
127
+
128
+ interface StepGrammar {
129
+ readonly isTerminated: boolean;
130
+ ready(): Promise<void>;
131
+ applyMask(logits: MlxArray): MlxArray;
132
+ accept(token: number): void;
133
+ }
134
+
135
+ export interface StepSamplerOptions extends SamplerOptions, LogitsProcessorOptions {
136
+ grammar?: StepGrammar | null;
137
+ }
138
+
139
+ interface StepSamplerConfigBase {
140
+ /** The grammar owner already awaited ready(), or this sampler must do it. */
141
+ grammarWait: "external" | "before-sample";
142
+ /** Update processor history in sample(), or let the decode loop commit later. */
143
+ historyUpdate: "after-sample" | "manual";
144
+ initialHistory?: readonly number[];
145
+ captureSelectedLogprob?: boolean;
146
+ captureTopLogprobs?: number;
147
+ /** Eager-number mode can advance grammar after sampling. */
148
+ acceptGrammar?: boolean;
149
+ eosTokenIds?: readonly number[];
150
+ /** Reuse a sampler already shared with a speculative draft source. */
151
+ sampler?: Sampler;
152
+ }
153
+
154
+ export interface DeviceStepSamplerConfig extends StepSamplerConfigBase {
155
+ tokenRepresentation: "device";
156
+ grammarWait: "external";
157
+ }
158
+
159
+ export interface NumberStepSamplerConfig extends StepSamplerConfigBase {
160
+ tokenRepresentation: "number";
161
+ grammarWait: "before-sample";
162
+ }
163
+
164
+ export interface DeviceStepSampler {
165
+ readonly isPlainGreedy: boolean;
166
+ readonly needsHistory: boolean;
167
+ sample(logits: MlxArray, step: number): StepSample<MlxArray>;
168
+ seedHistory(tokens: readonly number[]): void;
169
+ commitDevice(token: MlxArray): void;
170
+ commitNumbers(tokens: readonly number[]): void;
171
+ dispose(): void;
172
+ }
173
+
174
+ export interface NumberStepSampler {
175
+ readonly isPlainGreedy: boolean;
176
+ readonly needsHistory: boolean;
177
+ sample(logits: MlxArray, step: number): Promise<StepSample<number>>;
178
+ seedHistory(tokens: readonly number[]): void;
179
+ commitDevice(token: MlxArray): void;
180
+ commitNumbers(tokens: readonly number[]): void;
181
+ dispose(): void;
182
+ }
183
+
115
184
  const GOLDEN = 0x9e3779b97f4a7c15n;
116
185
 
117
186
  function stepKey(seed: number, step: number): MlxArray {
@@ -241,7 +310,7 @@ export function applyXtc(
241
310
  }
242
311
 
243
312
  /** HLG sampling parameters — a piecewise tone curve on the logprobs.
244
- * See docs/design/hlg-sampling.md. Knobs are in nats (the logprob unit). */
313
+ * See docs/archive/hlg-sampling.md. Knobs are in nats (the logprob unit). */
245
314
  export interface HlgParams {
246
315
  /** m — mid-region slope. Folds temperature: m = 1/temperature. */
247
316
  gain: number;
@@ -717,6 +786,209 @@ export function makeLogitsProcessors(opts: LogitsProcessorOptions = {}): LogitsP
717
786
  return out;
718
787
  }
719
788
 
789
+ /** Whether a whole [B,V] row can use the scheduler's vectorized argmax path. */
790
+ export function isPlainGreedy(
791
+ opts: StepSamplerOptions,
792
+ hasProcessors = makeLogitsProcessors(opts).length > 0,
793
+ ): boolean {
794
+ return (opts.temperature ?? 0) === 0 && !opts.curve && !hasProcessors && !opts.grammar;
795
+ }
796
+
797
+ export function stepExtrasArrays(extras: StepExtras | null): MlxArray[] {
798
+ return extras
799
+ ? [extras.sel, extras.topIdx, extras.topVals].filter(
800
+ (array): array is MlxArray => array !== null,
801
+ )
802
+ : [];
803
+ }
804
+
805
+ export function disposeStepExtras(extras: StepExtras | null): void {
806
+ if (!extras) return;
807
+ extras.sel?.dispose();
808
+ extras.topIdx?.dispose();
809
+ extras.topVals?.dispose();
810
+ }
811
+
812
+ export function makeStepSampler(
813
+ options: StepSamplerOptions,
814
+ config: DeviceStepSamplerConfig,
815
+ ): DeviceStepSampler;
816
+ export function makeStepSampler(
817
+ options: StepSamplerOptions,
818
+ config: NumberStepSamplerConfig,
819
+ ): NumberStepSampler;
820
+ export function makeStepSampler(
821
+ options: StepSamplerOptions,
822
+ config: DeviceStepSamplerConfig | NumberStepSamplerConfig,
823
+ ): DeviceStepSampler | NumberStepSampler {
824
+ const sampler = config.sampler ?? makeSampler(options);
825
+ const processors = makeLogitsProcessors(options);
826
+ const grammar = options.grammar ?? null;
827
+ const captureSelected = config.captureSelectedLogprob === true;
828
+ const captureTop = Math.max(0, config.captureTopLogprobs ?? 0);
829
+ const capture = captureSelected || captureTop > 0;
830
+ let history: MlxArray | null = null;
831
+
832
+ const seedHistory = (tokens: readonly number[]): void => {
833
+ if (processors.length === 0) return;
834
+ const next = ops.fromInt32([...tokens], [tokens.length]);
835
+ const previous = history;
836
+ history = next;
837
+ previous?.dispose();
838
+ };
839
+
840
+ const commitDevice = (token: MlxArray): void => {
841
+ if (processors.length === 0) return;
842
+ const one = ops.reshape(token, [1]);
843
+ if (!history) {
844
+ history = one;
845
+ return;
846
+ }
847
+ const previous = history;
848
+ try {
849
+ history = ops.concatAxis([previous, one], 0);
850
+ previous.dispose();
851
+ } finally {
852
+ one.dispose();
853
+ }
854
+ };
855
+
856
+ const commitNumbers = (tokens: readonly number[]): void => {
857
+ if (tokens.length === 0 || processors.length === 0) return;
858
+ const next = ops.fromInt32([...tokens], [tokens.length]);
859
+ if (!history) {
860
+ history = next;
861
+ return;
862
+ }
863
+ const previous = history;
864
+ try {
865
+ history = ops.concatAxis([previous, next], 0);
866
+ previous.dispose();
867
+ } finally {
868
+ next.dispose();
869
+ }
870
+ };
871
+
872
+ const sampleDevice = (input: MlxArray, step: number): StepSample<MlxArray> => {
873
+ const vocab = input.shape[input.shape.length - 1]!;
874
+ let current = input.shape.length === 2 ? input : ops.reshape(input, [1, vocab]);
875
+ let ownsCurrent = current !== input;
876
+ let logprobs: MlxArray | null = null;
877
+ let token: MlxArray | null = null;
878
+ let extras: StepExtras | null = null;
879
+ try {
880
+ for (const processor of processors) {
881
+ const next = processor(history, current);
882
+ if (ownsCurrent && next !== current) current.dispose();
883
+ current = next;
884
+ ownsCurrent = current !== input;
885
+ }
886
+ if (grammar && !grammar.isTerminated) {
887
+ const next = grammar.applyMask(current);
888
+ if (ownsCurrent && next !== current) current.dispose();
889
+ current = next;
890
+ ownsCurrent = current !== input;
891
+ }
892
+ logprobs = toLogprobs(current);
893
+ if (ownsCurrent) current.dispose();
894
+ current = input;
895
+ ownsCurrent = false;
896
+ token = sampler(logprobs, step);
897
+
898
+ if (capture) {
899
+ extras = { sel: null, topIdx: null, topVals: null };
900
+ if (captureSelected) {
901
+ const idx = ops.reshape(token, [1, 1]);
902
+ try {
903
+ extras.sel = ops.takeAlongAxis(logprobs, idx, -1);
904
+ } finally {
905
+ idx.dispose();
906
+ }
907
+ }
908
+ if (captureTop > 0) {
909
+ const k = Math.min(captureTop, vocab);
910
+ let neg: MlxArray | null = null;
911
+ let partition: MlxArray | null = null;
912
+ let view: MlxArray | null = null;
913
+ try {
914
+ neg = ops.neg(logprobs);
915
+ partition = ops.argpartitionAxis(neg, k - 1, -1);
916
+ view = partition.slice([0, 0], [1, k]);
917
+ extras.topIdx = ops.contiguous(view);
918
+ extras.topVals = ops.takeAlongAxis(logprobs, extras.topIdx, -1);
919
+ } finally {
920
+ neg?.dispose();
921
+ partition?.dispose();
922
+ view?.dispose();
923
+ }
924
+ }
925
+ }
926
+
927
+ logprobs.dispose();
928
+ logprobs = null;
929
+ const result = { token, extras };
930
+ token = null;
931
+ extras = null;
932
+ return result;
933
+ } finally {
934
+ if (ownsCurrent) current.dispose();
935
+ logprobs?.dispose();
936
+ token?.dispose();
937
+ disposeStepExtras(extras);
938
+ }
939
+ };
940
+
941
+ if (config.initialHistory) seedHistory(config.initialHistory);
942
+
943
+ const common = {
944
+ isPlainGreedy: isPlainGreedy(options, processors.length > 0),
945
+ needsHistory: processors.length > 0,
946
+ seedHistory,
947
+ commitDevice,
948
+ commitNumbers,
949
+ dispose: () => {
950
+ history?.dispose();
951
+ history = null;
952
+ },
953
+ };
954
+
955
+ if (config.tokenRepresentation === "device") {
956
+ return {
957
+ ...common,
958
+ sample(logits, step) {
959
+ const result = sampleDevice(logits, step);
960
+ if (config.historyUpdate === "after-sample") commitDevice(result.token);
961
+ return result;
962
+ },
963
+ };
964
+ }
965
+
966
+ return {
967
+ ...common,
968
+ async sample(logits, step) {
969
+ if (grammar && !grammar.isTerminated) await grammar.ready();
970
+ const result = sampleDevice(logits, step);
971
+ let tokenArray: MlxArray | null = result.token;
972
+ try {
973
+ // Read the sampler's integer result directly. Adding an astype here
974
+ // would append work behind the next dispatched decode step.
975
+ const token = ops.itemUint32(tokenArray);
976
+ tokenArray.dispose();
977
+ tokenArray = null;
978
+ if (config.acceptGrammar && grammar && !config.eosTokenIds?.includes(token))
979
+ grammar.accept(token);
980
+ if (config.historyUpdate === "after-sample") commitNumbers([token]);
981
+ return { token, extras: result.extras };
982
+ } catch (error) {
983
+ disposeStepExtras(result.extras);
984
+ throw error;
985
+ } finally {
986
+ tokenArray?.dispose();
987
+ }
988
+ },
989
+ };
990
+ }
991
+
720
992
  /** logits [1, V] → logprobs [1, V] (logits - logsumexp). */
721
993
  export function toLogprobs(logits: MlxArray): MlxArray {
722
994
  const lse = ops.logsumexpAxis(logits, -1, true);
@@ -0,0 +1,184 @@
1
+ import type { JobStore } from "../jobs";
2
+
3
+ export interface AdminRouteDeps {
4
+ ensureJobs(): Promise<JobStore>;
5
+ invalidateLibrary(): void;
6
+ }
7
+
8
+ export type AdminRoute =
9
+ | { kind: "hf-token-get" }
10
+ | { kind: "hf-token-set" }
11
+ | { kind: "tool-approvals-get" }
12
+ | { kind: "tool-approvals-delete" }
13
+ | { kind: "push"; artifactKind: "quantize" | "finetune" | "dataset" }
14
+ | { kind: "gc-plan" }
15
+ | { kind: "gc-execute" }
16
+ | { kind: "jobs-list" }
17
+ | { kind: "job-get"; jobId: string; stream: boolean };
18
+
19
+ export function matchAdminRoute(method: string, pathname: string): AdminRoute | null {
20
+ switch (`${method} ${pathname}`) {
21
+ case "GET /api/settings/hf-token": return { kind: "hf-token-get" };
22
+ case "POST /api/settings/hf-token": return { kind: "hf-token-set" };
23
+ case "GET /api/settings/tool-approvals": return { kind: "tool-approvals-get" };
24
+ case "DELETE /api/settings/tool-approvals": return { kind: "tool-approvals-delete" };
25
+ case "GET /api/gc/plan": return { kind: "gc-plan" };
26
+ case "POST /api/gc/execute": return { kind: "gc-execute" };
27
+ case "GET /api/jobs": return { kind: "jobs-list" };
28
+ }
29
+
30
+ if (method === "POST") {
31
+ const push = pathname.match(/^\/api\/(quantize|finetune|dataset)\/push$/);
32
+ if (push) {
33
+ return {
34
+ kind: "push",
35
+ artifactKind: push[1] as "quantize" | "finetune" | "dataset",
36
+ };
37
+ }
38
+ }
39
+
40
+ if (method === "GET") {
41
+ const job = pathname.match(/^\/api\/jobs\/([^/]+?)(\/stream)?$/);
42
+ if (job) {
43
+ return {
44
+ kind: "job-get",
45
+ jobId: job[1]!,
46
+ stream: !!job[2],
47
+ };
48
+ }
49
+ }
50
+
51
+ return null;
52
+ }
53
+
54
+ export async function handleAdminRoute(
55
+ url: URL,
56
+ request: Request,
57
+ deps: AdminRouteDeps,
58
+ ): Promise<Response | null> {
59
+ const route = matchAdminRoute(request.method, url.pathname);
60
+ if (!route) return null;
61
+
62
+ switch (route.kind) {
63
+ case "hf-token-get": {
64
+ const { hasHfToken } = await import("../hf-push");
65
+ return Response.json({ ok: true, hasToken: hasHfToken() });
66
+ }
67
+ case "hf-token-set": {
68
+ const body = (await request.json().catch(() => ({}))) as { token?: string };
69
+ if (!body.token)
70
+ return Response.json({ ok: false, error: "token required" }, { status: 400 });
71
+ const { saveHfToken } = await import("../hf-push");
72
+ saveHfToken(body.token);
73
+ return Response.json({ ok: true });
74
+ }
75
+ case "tool-approvals-get": {
76
+ const { listAlwaysAllowedTools } = await import("../tool-approvals");
77
+ return Response.json({ ok: true, alwaysAllow: listAlwaysAllowedTools() });
78
+ }
79
+ case "tool-approvals-delete": {
80
+ const body = (await request.json().catch(() => ({}))) as { tool?: string };
81
+ if (!body.tool)
82
+ return Response.json({ ok: false, error: "tool required" }, { status: 400 });
83
+ const { revokeToolAlwaysAllowed } = await import("../tool-approvals");
84
+ const file = revokeToolAlwaysAllowed(body.tool);
85
+ return Response.json({ ok: true, alwaysAllow: Object.keys(file.allows).sort() });
86
+ }
87
+ case "push": {
88
+ const body = (await request.json().catch(() => ({}))) as {
89
+ job_id?: string;
90
+ repo_id?: string;
91
+ private?: boolean;
92
+ source_path?: string;
93
+ };
94
+ if (!body.repo_id)
95
+ return Response.json({ ok: false, error: "repo_id required" }, { status: 400 });
96
+ const { getHfToken, uploadFolder } = await import("../hf-push");
97
+ const token = getHfToken();
98
+ if (!token) {
99
+ return Response.json(
100
+ { ok: false, error: "no HF token saved — add one in Settings → Hugging Face" },
101
+ { status: 400 },
102
+ );
103
+ }
104
+ const store = await deps.ensureJobs();
105
+ let dir = body.source_path;
106
+ if (!dir && body.job_id) dir = store.get(body.job_id)?.output_path ?? undefined;
107
+ if (!dir) {
108
+ return Response.json(
109
+ { ok: false, error: "no source dir (pass job_id or source_path)" },
110
+ { status: 400 },
111
+ );
112
+ }
113
+ try {
114
+ const result = await uploadFolder(dir, body.repo_id, {
115
+ repoType: route.artifactKind === "dataset" ? "dataset" : "model",
116
+ private: !!body.private,
117
+ token,
118
+ });
119
+ return Response.json({ ok: true, url: result.url });
120
+ } catch (error) {
121
+ return Response.json({ ok: false, error: (error as Error).message }, { status: 400 });
122
+ }
123
+ }
124
+ case "gc-plan": {
125
+ const { planGc } = await import("../registry");
126
+ const plans = planGc().filter(
127
+ (plan) => plan.pruneSnapshots.length || plan.skippedSnapshots.length || plan.deadBlobs.length,
128
+ );
129
+ const superseded = plans.map((plan) => ({
130
+ repo_id: plan.repoId,
131
+ prune_snapshots: plan.pruneSnapshots.length,
132
+ skipped_snapshots: plan.skippedSnapshots.length,
133
+ dead_blobs: plan.deadBlobs.length,
134
+ reclaim_bytes: plan.reclaimBytes,
135
+ }));
136
+ const reclaim_bytes = plans.reduce((total, plan) => total + plan.reclaimBytes, 0);
137
+ return Response.json({ ok: true, superseded, reclaim_bytes });
138
+ }
139
+ case "gc-execute": {
140
+ const body = (await request.json().catch(() => ({}))) as { yes?: boolean };
141
+ if (body.yes !== true) {
142
+ return Response.json(
143
+ { ok: false, error: "pass {\"yes\": true} to confirm deletion" },
144
+ { status: 400 },
145
+ );
146
+ }
147
+ const { planGc, executeGc, Registry } = await import("../registry");
148
+ const plans = planGc().filter(
149
+ (plan) => plan.pruneSnapshots.length || plan.skippedSnapshots.length || plan.deadBlobs.length,
150
+ );
151
+ const result = executeGc(plans);
152
+ const registry = new Registry();
153
+ try {
154
+ await registry.scan();
155
+ } finally {
156
+ registry.close();
157
+ }
158
+ deps.invalidateLibrary();
159
+ return Response.json({
160
+ ok: true,
161
+ snapshots: result.snapshots,
162
+ blobs: result.blobs,
163
+ reclaimed_bytes: result.reclaimedBytes,
164
+ });
165
+ }
166
+ case "jobs-list": {
167
+ const store = await deps.ensureJobs();
168
+ const limit = Number(url.searchParams.get("limit") ?? "50");
169
+ const kind = url.searchParams.get("kind") ?? undefined;
170
+ return Response.json({ ok: true, jobs: store.recent(limit, kind) });
171
+ }
172
+ case "job-get": {
173
+ const store = await deps.ensureJobs();
174
+ if (route.stream) {
175
+ const { streamJobResponse } = await import("../jobs");
176
+ return streamJobResponse(store, route.jobId);
177
+ }
178
+ const job = store.get(route.jobId);
179
+ if (!job)
180
+ return Response.json({ ok: false, error: "job not found" }, { status: 404 });
181
+ return Response.json({ ok: true, job });
182
+ }
183
+ }
184
+ }
@@ -0,0 +1,132 @@
1
+ export type AuxiliaryRoute =
2
+ | "memory-status"
3
+ | "memory-list"
4
+ | "memory-search"
5
+ | "memory-article"
6
+ | "memory-links"
7
+ | "memory-history"
8
+ | "memory-diff"
9
+ | "memory-init"
10
+ | "memory-synthesize"
11
+ | "hub-local"
12
+ | "hub-search"
13
+ | "hub-download"
14
+ | "hub-serve"
15
+ | "sessions-search"
16
+ | "sessions-export";
17
+
18
+ /** Match request-only routes that do not depend on the loaded model or
19
+ * createServer's live generation state. */
20
+ export function matchAuxiliaryRoute(method: string, pathname: string): AuxiliaryRoute | null {
21
+ switch (`${method} ${pathname}`) {
22
+ case "GET /api/memory/status": return "memory-status";
23
+ case "GET /api/memory/list": return "memory-list";
24
+ case "GET /api/memory/search": return "memory-search";
25
+ case "GET /api/memory/article": return "memory-article";
26
+ case "GET /api/memory/links": return "memory-links";
27
+ case "GET /api/memory/history": return "memory-history";
28
+ case "GET /api/memory/diff": return "memory-diff";
29
+ case "POST /api/memory/init": return "memory-init";
30
+ case "GET /v1/memory/synthesize": return "memory-synthesize";
31
+ case "GET /api/hub/local": return "hub-local";
32
+ case "GET /api/hub/search": return "hub-search";
33
+ case "POST /api/hub/download": return "hub-download";
34
+ case "POST /api/hub/serve": return "hub-serve";
35
+ case "GET /api/sessions/search": return "sessions-search";
36
+ case "GET /api/sessions/export": return "sessions-export";
37
+ default: return null;
38
+ }
39
+ }
40
+
41
+ export async function handleAuxiliaryRoute(
42
+ url: URL,
43
+ request: Request,
44
+ ): Promise<Response | null> {
45
+ switch (matchAuxiliaryRoute(request.method, url.pathname)) {
46
+ case "memory-status": {
47
+ const { handleMemoryStatus } = await import("../memory/rest");
48
+ return handleMemoryStatus();
49
+ }
50
+ case "memory-list": {
51
+ const { handleMemoryList } = await import("../memory/rest");
52
+ return handleMemoryList();
53
+ }
54
+ case "memory-search": {
55
+ const { handleMemorySearch } = await import("../memory/rest");
56
+ return handleMemorySearch(url);
57
+ }
58
+ case "memory-article": {
59
+ const { handleMemoryArticle } = await import("../memory/rest");
60
+ return handleMemoryArticle(url);
61
+ }
62
+ case "memory-links": {
63
+ const { handleMemoryLinks } = await import("../memory/rest");
64
+ return handleMemoryLinks(url);
65
+ }
66
+ case "memory-history": {
67
+ const { handleMemoryHistory } = await import("../memory/rest");
68
+ return handleMemoryHistory(url);
69
+ }
70
+ case "memory-diff": {
71
+ const { handleMemoryDiff } = await import("../memory/rest");
72
+ return handleMemoryDiff(url);
73
+ }
74
+ case "memory-init": {
75
+ const { handleMemoryInit } = await import("../memory/rest");
76
+ return handleMemoryInit(request);
77
+ }
78
+ case "memory-synthesize": {
79
+ const dryRun = url.searchParams.get("dry") === "1";
80
+ const { runSynthesis } = await import("../memory/pipeline");
81
+ const encoder = new TextEncoder();
82
+ const stream = new ReadableStream({
83
+ async start(controller) {
84
+ const send = (event: unknown) =>
85
+ controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`));
86
+ try {
87
+ const summary = await runSynthesis({ dryRun }, (event) => send(event));
88
+ send({ type: "summary", ...summary });
89
+ controller.enqueue(encoder.encode("data: [DONE]\n\n"));
90
+ } catch (error) {
91
+ send({ type: "error", message: (error as Error).message });
92
+ } finally {
93
+ controller.close();
94
+ }
95
+ },
96
+ });
97
+ return new Response(stream, {
98
+ headers: {
99
+ "content-type": "text/event-stream",
100
+ "cache-control": "no-cache",
101
+ connection: "keep-alive",
102
+ },
103
+ });
104
+ }
105
+ case "hub-local": {
106
+ const { handleHubLocal } = await import("../hub-rest");
107
+ return handleHubLocal();
108
+ }
109
+ case "hub-search": {
110
+ const { handleHubSearch } = await import("../hub-rest");
111
+ return handleHubSearch(url);
112
+ }
113
+ case "hub-download": {
114
+ const { handleHubDownload } = await import("../hub-rest");
115
+ return handleHubDownload(request);
116
+ }
117
+ case "hub-serve": {
118
+ const { handleHubServe } = await import("../hub-rest");
119
+ return handleHubServe(request);
120
+ }
121
+ case "sessions-search": {
122
+ const { handleSessionsSearch } = await import("./session-search");
123
+ return handleSessionsSearch(url);
124
+ }
125
+ case "sessions-export": {
126
+ const { handleSessionsExport } = await import("./session-search");
127
+ return handleSessionsExport(url);
128
+ }
129
+ default:
130
+ return null;
131
+ }
132
+ }