mlx-bun 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/README.md +1453 -88
  2. package/THIRD_PARTY_NOTICES.md +882 -0
  3. package/bin/mlx-bun.convert.mjs +4 -0
  4. package/bin/mlx-bun.fuse.mjs +4 -0
  5. package/bin/mlx-bun.generate.mjs +4 -0
  6. package/bin/mlx-bun.lora.mjs +4 -0
  7. package/bin/mlx-bun.mjs +13 -21
  8. package/bin/mlx-bun.server.mjs +4 -0
  9. package/bin/mlx-bun.upload.mjs +4 -0
  10. package/dist/web/app.js +9584 -0
  11. package/package.json +50 -53
  12. package/src/cli/ane-install.ts +76 -0
  13. package/src/cli/args.ts +179 -0
  14. package/src/cli/engine-entry.ts +68 -0
  15. package/src/cli/inference.ts +214 -0
  16. package/src/cli/job-entry.ts +97 -0
  17. package/src/cli/library-host.ts +117 -0
  18. package/src/cli/main.ts +57 -0
  19. package/src/cli/memory-engine.ts +163 -0
  20. package/src/cli/memory.ts +36 -0
  21. package/src/cli/mlx-lm-aliases.ts +309 -0
  22. package/src/cli/model-choice.ts +33 -0
  23. package/src/cli/model-selection.ts +84 -0
  24. package/src/cli/module-host.ts +11 -0
  25. package/src/cli/module-verbs.ts +50 -0
  26. package/src/cli/numerical-policy.ts +12 -0
  27. package/src/cli/perplexity.ts +89 -0
  28. package/src/cli/serve-host.ts +423 -0
  29. package/src/cli/serve-isolated.ts +217 -0
  30. package/src/cli/serve-options.ts +106 -0
  31. package/src/cli/serve-state.ts +205 -0
  32. package/src/cli/serve.ts +500 -0
  33. package/src/cli/served-model-host.ts +102 -0
  34. package/src/cli/server-entry.ts +148 -0
  35. package/src/cli/serving-unit.ts +177 -0
  36. package/src/{tui.ts → cli/terminal.ts} +13 -8
  37. package/src/cli/worker-adapters.ts +34 -0
  38. package/src/cli/worker-entry.ts +272 -0
  39. package/src/cli/worker-unit.ts +179 -0
  40. package/src/engine/adapter-operation.ts +26 -0
  41. package/src/engine/cache-services.ts +114 -0
  42. package/src/engine/completion.ts +39 -0
  43. package/src/engine/generation-gateway.ts +358 -0
  44. package/src/engine/index.ts +59 -0
  45. package/src/engine/kv-budget.ts +120 -0
  46. package/src/engine/media-preparation.ts +232 -0
  47. package/src/engine/model-binding.ts +24 -0
  48. package/src/engine/model-host.ts +513 -0
  49. package/src/engine/model-serving.ts +89 -0
  50. package/src/{serve → engine}/preparation.ts +10 -8
  51. package/src/{serve → engine}/session-completion-engine.ts +6 -6
  52. package/src/engine/telemetry.ts +109 -0
  53. package/src/hub/downloads.ts +116 -0
  54. package/src/jobs/db.ts +16 -7
  55. package/src/jobs/events.ts +29 -0
  56. package/src/jobs/executable.ts +5 -0
  57. package/src/jobs/host.ts +51 -0
  58. package/src/jobs/in-process.ts +55 -0
  59. package/src/{contracts/jobs.ts → jobs/protocol.ts} +7 -9
  60. package/src/jobs/runner.ts +150 -231
  61. package/src/jobs/service.ts +75 -0
  62. package/src/jobs/sse.ts +59 -23
  63. package/src/jobs/worker-memory.ts +46 -0
  64. package/src/jobs/worker-process.ts +163 -0
  65. package/src/jobs/worker-supervisor.ts +258 -0
  66. package/src/modules.ts +58 -0
  67. package/src/publishing/catalog-hub.ts +18 -0
  68. package/src/publishing/credentials.ts +31 -0
  69. package/src/publishing/upload.ts +37 -0
  70. package/src/residency/leased-adapters.ts +21 -0
  71. package/src/residency/local-records.ts +16 -0
  72. package/src/residency/model-residency.ts +405 -0
  73. package/src/residency/record-index.ts +28 -0
  74. package/src/residency/resident-estimate.ts +50 -0
  75. package/src/{anthropic.ts → server/anthropic.ts} +3 -81
  76. package/src/server/cache-routes.ts +36 -0
  77. package/src/{serve → server}/chat-request.ts +12 -10
  78. package/src/{serve → server}/chat-stage.ts +27 -22
  79. package/src/{client.ts → server/client.ts} +28 -2
  80. package/src/{serve → server}/completion-executor.ts +42 -42
  81. package/src/server/decision-body.ts +55 -0
  82. package/src/server/decision-routes.ts +134 -0
  83. package/src/server/decision-wire.ts +228 -0
  84. package/src/{serve → server}/discovery-routes.ts +42 -83
  85. package/src/server/generated-token-history.ts +57 -0
  86. package/src/{serve → server}/http.ts +25 -13
  87. package/src/{serve → server}/inference-request.ts +5 -5
  88. package/src/server/job-routes.ts +20 -0
  89. package/src/server/media-prompt.ts +63 -0
  90. package/src/server/memory-completion-client.ts +46 -0
  91. package/src/server/model-routes.ts +192 -0
  92. package/src/{serve → server}/openai-wire.ts +3 -2
  93. package/src/{serve → server}/pipeline.ts +1 -1
  94. package/src/server/prompt-builder.ts +13 -0
  95. package/src/server/prompt-contracts.ts +17 -0
  96. package/src/server/proxy-routes.ts +187 -0
  97. package/src/server/publishing-routes.ts +41 -0
  98. package/src/{serve → server}/request-plan.ts +8 -8
  99. package/src/{serve → server}/request-prep.ts +82 -68
  100. package/src/{serve → server}/responses-client.ts +30 -13
  101. package/src/{responses.ts → server/responses.ts} +12 -93
  102. package/src/server/routes.ts +205 -0
  103. package/src/server/start.ts +72 -0
  104. package/src/server/status-routes.ts +108 -0
  105. package/src/{serve → server}/text-completion-stage.ts +25 -4
  106. package/src/server/text-prompt.ts +12 -0
  107. package/src/{serve → server}/token-streams.ts +36 -38
  108. package/src/server/worker-routes.ts +311 -0
  109. package/src/storage/paths.ts +61 -0
  110. package/src/web/assets.ts +37 -0
  111. package/src/web/{src → browser}/api.ts +5 -23
  112. package/src/web/browser/chat-host.ts +17 -0
  113. package/src/web/browser/installed-panels.ts +6 -0
  114. package/src/web/browser/main.ts +55 -0
  115. package/src/web/browser/markdown.ts +279 -0
  116. package/src/web/browser/memory-panel.ts +9 -0
  117. package/src/web/browser/palette.ts +64 -0
  118. package/src/web/browser/protocol.ts +13 -0
  119. package/src/web/browser/shell.ts +467 -0
  120. package/src/web/{src → browser}/status.ts +32 -36
  121. package/src/web/build.ts +51 -0
  122. package/src/web/public/app.html +1054 -0
  123. package/src/web/{sw.js → public/sw.js} +4 -3
  124. package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
  125. package/src/web/{vendor → public/vendor}/hljs.js +2 -2
  126. package/THIRD_PARTY_LICENSES.md +0 -51
  127. package/docs/README.md +0 -94
  128. package/docs/archive/hlg-sampling.md +0 -350
  129. package/docs/archive/investigations/audio-input-plan.md +0 -356
  130. package/docs/archive/investigations/chunk-finetune-experiment.md +0 -84
  131. package/docs/archive/investigations/colibri-glm52-port.md +0 -1486
  132. package/docs/archive/investigations/colibri-oracle-pin.md +0 -1284
  133. package/docs/archive/investigations/curve-bisector-routing.md +0 -123
  134. package/docs/archive/investigations/decode-roofline-lookagain.md +0 -348
  135. package/docs/archive/investigations/diffusion-gemma-port.md +0 -602
  136. package/docs/archive/investigations/dspark-handoff.md +0 -224
  137. package/docs/archive/investigations/expert-offload-single-user-moe.md +0 -292
  138. package/docs/archive/investigations/faithful-l1-consolidation.md +0 -310
  139. package/docs/archive/investigations/hlg-sampling-investigation.md +0 -970
  140. package/docs/archive/investigations/indexshare-performance-spike.md +0 -357
  141. package/docs/archive/investigations/kernel-perf-review-2026-07.md +0 -171
  142. package/docs/archive/investigations/lab-build-journal.md +0 -157
  143. package/docs/archive/investigations/minicpm5-decode-megakernel.md +0 -489
  144. package/docs/archive/investigations/openjarvis-fit.md +0 -198
  145. package/docs/archive/investigations/openwiki-evaluation.md +0 -249
  146. package/docs/archive/investigations/optimization_plan.md +0 -346
  147. package/docs/archive/investigations/orpo-base-uf-experiment-and-directions.md +0 -120
  148. package/docs/archive/investigations/orpo-flash-cce-pin-leak.md +0 -167
  149. package/docs/archive/investigations/orpo-uf-testing-handoff.md +0 -126
  150. package/docs/archive/investigations/pareto-specialized-runtime-findings.md +0 -92
  151. package/docs/archive/investigations/pi-builtin-investigation.md +0 -308
  152. package/docs/archive/investigations/pre-colibri-stabilization.md +0 -329
  153. package/docs/archive/investigations/qwen38-27b-campaign-log.md +0 -1092
  154. package/docs/archive/investigations/segmented-backward-handoff.md +0 -148
  155. package/docs/archive/investigations/starter-model-port-handoff.md +0 -342
  156. package/docs/archive/investigations/steel-flash-cce-handoff.md +0 -489
  157. package/docs/archive/investigations/the-dreaming-handoff.md +0 -141
  158. package/docs/archive/investigations/trainer-validation-experiment.md +0 -173
  159. package/docs/archive/planning/chat-ui-vision-memory-first.md +0 -199
  160. package/docs/archive/planning/chat-ui-vision.md +0 -50
  161. package/docs/archive/planning/chunk-task-roadmap.md +0 -77
  162. package/docs/archive/planning/curve-sampler-research-plan.md +0 -331
  163. package/docs/archive/planning/journal.md +0 -316
  164. package/docs/archive/planning/memory-docs-and-dag-plan.md +0 -194
  165. package/docs/archive/planning/pi-integration-review.md +0 -178
  166. package/docs/archive/planning/release-notes-v0.0.10.md +0 -57
  167. package/docs/archive/planning/release-notes-v0.0.11.md +0 -239
  168. package/docs/archive/planning/release-notes-v0.0.12.md +0 -80
  169. package/docs/archive/planning/release-notes-v0.0.13.md +0 -77
  170. package/docs/archive/planning/release-notes-v0.0.9.md +0 -122
  171. package/docs/archive/planning/release-notes-v0.2.0.md +0 -49
  172. package/docs/archive/planning/release-notes-v0.3.0.md +0 -35
  173. package/docs/archive/planning/web-ui-pass-plan.md +0 -213
  174. package/docs/archive/planning/website-readme-pass-plan.md +0 -224
  175. package/docs/design/batching.md +0 -1841
  176. package/docs/design/decode-speed-program.md +0 -2349
  177. package/docs/design/dreaming-nightly-pipeline.md +0 -684
  178. package/docs/design/generic-model-support.md +0 -705
  179. package/docs/design/kv-cache.md +0 -824
  180. package/docs/design/orpo-training.md +0 -680
  181. package/docs/design/speculative-decoding.md +0 -1990
  182. package/docs/design/turboquant.md +0 -2212
  183. package/docs/design/unified-engine-frontier-plan.md +0 -1880
  184. package/docs/design/web-chat-redesign.md +0 -695
  185. package/docs/planning/PRODUCT_ROADMAP.md +0 -594
  186. package/docs/planning/ResearchTopics.md +0 -119
  187. package/docs/planning/release-notes-v0.4.0.md +0 -45
  188. package/docs/planning/video-series.md +0 -421
  189. package/docs/reference/benchmarks.md +0 -3613
  190. package/docs/reference/cli.md +0 -585
  191. package/docs/reference/distribution.md +0 -355
  192. package/docs/reference/environment.md +0 -398
  193. package/docs/reference/glossary.md +0 -39
  194. package/docs/reference/library-api.md +0 -674
  195. package/docs/reference/memory.md +0 -260
  196. package/docs/reference/models.md +0 -334
  197. package/docs/reference/server-api.md +0 -1775
  198. package/docs/reference/server-config.md +0 -846
  199. package/docs/reference/training.md +0 -462
  200. package/docs/reference/troubleshooting.md +0 -158
  201. package/src/admission-plan.ts +0 -18
  202. package/src/audio/conformer.ts +0 -647
  203. package/src/audio/decode.ts +0 -133
  204. package/src/audio/features.ts +0 -202
  205. package/src/audio/transcode.ts +0 -67
  206. package/src/backends/mlx/assistant-target.ts +0 -46
  207. package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
  208. package/src/backends/mlx/autoregressive.ts +0 -108
  209. package/src/backends/mlx/batch-group.ts +0 -1790
  210. package/src/backends/mlx/cache-attachment.ts +0 -67
  211. package/src/backends/mlx/cache-layout.ts +0 -31
  212. package/src/backends/mlx/checkpoint-state.ts +0 -53
  213. package/src/backends/mlx/continuation-persistence.ts +0 -106
  214. package/src/backends/mlx/continuation-request.ts +0 -43
  215. package/src/backends/mlx/continuation.ts +0 -77
  216. package/src/backends/mlx/diffusion.ts +0 -39
  217. package/src/backends/mlx/draft-target.ts +0 -32
  218. package/src/backends/mlx/evaluation.ts +0 -105
  219. package/src/backends/mlx/fill-append.ts +0 -45
  220. package/src/backends/mlx/full-kv-row-append.ts +0 -32
  221. package/src/backends/mlx/full-kv-row-donor.ts +0 -54
  222. package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
  223. package/src/backends/mlx/gateway-binding.ts +0 -130
  224. package/src/backends/mlx/graph.ts +0 -38
  225. package/src/backends/mlx/kv-codec.ts +0 -9
  226. package/src/backends/mlx/kv-maintenance.ts +0 -133
  227. package/src/backends/mlx/kv-tensor-rows.ts +0 -212
  228. package/src/backends/mlx/memory-client.ts +0 -189
  229. package/src/backends/mlx/methods.ts +0 -90
  230. package/src/backends/mlx/model-prompt.ts +0 -164
  231. package/src/backends/mlx/model-serving.ts +0 -79
  232. package/src/backends/mlx/prefill-cohort.ts +0 -89
  233. package/src/backends/mlx/prefill-rows.ts +0 -200
  234. package/src/backends/mlx/prefill.ts +0 -33
  235. package/src/backends/mlx/projected-context-rows.ts +0 -72
  236. package/src/backends/mlx/request-policy.ts +0 -20
  237. package/src/backends/mlx/request-state-policy.ts +0 -41
  238. package/src/backends/mlx/rollback.ts +0 -89
  239. package/src/backends/mlx/row-sampling.ts +0 -49
  240. package/src/backends/mlx/serial-executor.ts +0 -242
  241. package/src/backends/mlx/speculative-group.ts +0 -359
  242. package/src/backends/mlx/speculative-round.ts +0 -161
  243. package/src/backends/mlx/speculative.ts +0 -114
  244. package/src/backends/mlx/state-rows.ts +0 -104
  245. package/src/backends/mlx/state-views.ts +0 -46
  246. package/src/backends/mlx/target-layout-capability.ts +0 -35
  247. package/src/backends/mlx/text-engine.ts +0 -73
  248. package/src/backends/mlx/transitioning-kv-rows.ts +0 -165
  249. package/src/chat-template.ts +0 -382
  250. package/src/cli.ts +0 -3168
  251. package/src/config.ts +0 -399
  252. package/src/contracts/completion.ts +0 -16
  253. package/src/contracts/execution.ts +0 -60
  254. package/src/contracts/generation.ts +0 -103
  255. package/src/contracts/host.ts +0 -7
  256. package/src/contracts/pi-provider.ts +0 -30
  257. package/src/contracts/pi.ts +0 -259
  258. package/src/contracts/prefix-cache.ts +0 -23
  259. package/src/contracts/resources.ts +0 -25
  260. package/src/contracts/sampling.ts +0 -23
  261. package/src/contracts/scheduling.ts +0 -45
  262. package/src/contracts/tsconfig.json +0 -14
  263. package/src/dataset/generators.ts +0 -1087
  264. package/src/dataset/index.ts +0 -12
  265. package/src/dataset/job.ts +0 -81
  266. package/src/dataset/llm.ts +0 -71
  267. package/src/dataset/registry.ts +0 -528
  268. package/src/diffusion/diffusion-generate.ts +0 -507
  269. package/src/download.ts +0 -505
  270. package/src/embed.ts +0 -77
  271. package/src/engine/admission.ts +0 -59
  272. package/src/engine/cancellation.ts +0 -38
  273. package/src/engine/engine.ts +0 -56
  274. package/src/engine/execution-coordinator.ts +0 -70
  275. package/src/engine/execution-plan.ts +0 -53
  276. package/src/engine/resources.ts +0 -53
  277. package/src/engine/scheduler.ts +0 -72
  278. package/src/engine/session.ts +0 -247
  279. package/src/eval/README.md +0 -130
  280. package/src/eval/ifeval.ts +0 -81
  281. package/src/eval/kl-prompts.ts +0 -29
  282. package/src/eval/kl.ts +0 -590
  283. package/src/eval/perplexity.ts +0 -164
  284. package/src/eval/quality-db.ts +0 -92
  285. package/src/eval/reference-logits.ts +0 -207
  286. package/src/eval/runner.ts +0 -124
  287. package/src/eval/score.ts +0 -49
  288. package/src/eval/tasks/bfcl.ts +0 -535
  289. package/src/eval/tasks/gsm8k.ts +0 -98
  290. package/src/eval/tasks/hashhop.ts +0 -139
  291. package/src/eval/tasks/humaneval.ts +0 -275
  292. package/src/eval/tasks/ifeval.ts +0 -525
  293. package/src/eval/tasks/mmlu.ts +0 -157
  294. package/src/eval/ultrafeedback.ts +0 -60
  295. package/src/evaldb.ts +0 -199
  296. package/src/expert-io.ts +0 -393
  297. package/src/expert-offload-build.ts +0 -77
  298. package/src/expert-offload.ts +0 -76
  299. package/src/expert-residency.ts +0 -1134
  300. package/src/expert-usage.ts +0 -415
  301. package/src/fill/echo-index.ts +0 -188
  302. package/src/fill/fill-session.ts +0 -452
  303. package/src/fill/proposal.ts +0 -68
  304. package/src/fill/schema-rows.ts +0 -506
  305. package/src/fill/tool-boundary.ts +0 -103
  306. package/src/fit.ts +0 -249
  307. package/src/generate.ts +0 -1346
  308. package/src/grammar.ts +0 -591
  309. package/src/harness-pi.ts +0 -184
  310. package/src/hf-push.ts +0 -628
  311. package/src/hub-rest.ts +0 -242
  312. package/src/index.ts +0 -63
  313. package/src/inference/denoising.ts +0 -17
  314. package/src/inference/draft-acceptance.ts +0 -41
  315. package/src/inference/draft-output.ts +0 -49
  316. package/src/inference/graph.ts +0 -33
  317. package/src/inference/prefill.ts +0 -39
  318. package/src/inference/rollback.ts +0 -7
  319. package/src/jobs/index.ts +0 -31
  320. package/src/jobs/job-entry.ts +0 -107
  321. package/src/jobs/task-client.ts +0 -19
  322. package/src/jobs/types.ts +0 -2
  323. package/src/kv-scheme.ts +0 -257
  324. package/src/kv-store.ts +0 -1099
  325. package/src/lab/README.md +0 -18
  326. package/src/lab/curve/curve-designer.html +0 -303
  327. package/src/lab/curve/curve-sampler.ts +0 -122
  328. package/src/lab/expert-trace/expert-trace.ts +0 -69
  329. package/src/lab/paged-kv/paged-kv-rows.ts +0 -83
  330. package/src/lab/paged-kv/paged-kv.ts +0 -270
  331. package/src/library.ts +0 -40
  332. package/src/lora.ts +0 -408
  333. package/src/md-modules.d.ts +0 -49
  334. package/src/media-fetch.ts +0 -442
  335. package/src/memory/article.ts +0 -558
  336. package/src/memory/chunk-validation.ts +0 -150
  337. package/src/memory/chunk.ts +0 -318
  338. package/src/memory/cluster.ts +0 -351
  339. package/src/memory/coverage.ts +0 -134
  340. package/src/memory/crosslink.ts +0 -0
  341. package/src/memory/db.ts +0 -253
  342. package/src/memory/entity.ts +0 -203
  343. package/src/memory/gate.ts +0 -187
  344. package/src/memory/history.ts +0 -152
  345. package/src/memory/ingest.ts +0 -335
  346. package/src/memory/model.ts +0 -183
  347. package/src/memory/normalize.ts +0 -671
  348. package/src/memory/parse.ts +0 -22
  349. package/src/memory/pipeline.ts +0 -275
  350. package/src/memory/prompts.ts +0 -65
  351. package/src/memory/query.ts +0 -334
  352. package/src/memory/reconcile.ts +0 -734
  353. package/src/memory/redirect.ts +0 -108
  354. package/src/memory/reindex.ts +0 -325
  355. package/src/memory/resolve.ts +0 -307
  356. package/src/memory/rest.ts +0 -245
  357. package/src/memory/route.ts +0 -272
  358. package/src/memory/schedule.ts +0 -165
  359. package/src/memory/stages.ts +0 -777
  360. package/src/memory/synthesize.ts +0 -1638
  361. package/src/memory/tools.ts +0 -749
  362. package/src/memory/vault.ts +0 -1194
  363. package/src/memory/wikify.ts +0 -1064
  364. package/src/mlx/array.ts +0 -388
  365. package/src/mlx/autograd.ts +0 -304
  366. package/src/mlx/checkpoint.ts +0 -149
  367. package/src/mlx/compile.ts +0 -168
  368. package/src/mlx/custom-vjp.ts +0 -188
  369. package/src/mlx/ffi.ts +0 -512
  370. package/src/mlx/materialize.ts +0 -23
  371. package/src/mlx/metal-kernel.ts +0 -159
  372. package/src/mlx/ops.ts +0 -1021
  373. package/src/mlx/quantized-rows.ts +0 -36
  374. package/src/mlx/token-bitmask.ts +0 -52
  375. package/src/mlx/turboquant-kv-decode.ts +0 -82
  376. package/src/mlx/turboquant-kv-inverse.ts +0 -122
  377. package/src/mlx/turboquant-ops.ts +0 -861
  378. package/src/mlx/turboquant-tables.ts +0 -237
  379. package/src/mmap.ts +0 -90
  380. package/src/model/artifact-identity.ts +0 -73
  381. package/src/model/batched-kv.ts +0 -235
  382. package/src/model/batched-mask.ts +0 -279
  383. package/src/model/batched-quant.ts +0 -212
  384. package/src/model/batched-quantized-kv.ts +0 -144
  385. package/src/model/batched-rotating-quant.ts +0 -353
  386. package/src/model/batched-rotating-state.ts +0 -149
  387. package/src/model/batched-rotating.ts +0 -338
  388. package/src/model/batched-row-storage.ts +0 -179
  389. package/src/model/batched-ssm.ts +0 -52
  390. package/src/model/batched-turboquant-kv.ts +0 -93
  391. package/src/model/compiled-decode.ts +0 -712
  392. package/src/model/decoded-kv-donor.ts +0 -12
  393. package/src/model/delayed-quantized-kv.ts +0 -72
  394. package/src/model/delayed-rotating-quantized-kv.ts +0 -93
  395. package/src/model/delayed-turboquant-kv.ts +0 -55
  396. package/src/model/diffusion-gemma.ts +0 -1026
  397. package/src/model/factory.ts +0 -189
  398. package/src/model/fingerprint.ts +0 -33
  399. package/src/model/flash-attention.ts +0 -694
  400. package/src/model/full-prefill-padding.ts +0 -56
  401. package/src/model/full-prefill-row.ts +0 -105
  402. package/src/model/gemma4-base.ts +0 -2351
  403. package/src/model/gemma4.ts +0 -1315
  404. package/src/model/generated/gemma4-12b.ts +0 -429
  405. package/src/model/generated/gemma4-26b.ts +0 -448
  406. package/src/model/generated/gemma4-e4b.ts +0 -717
  407. package/src/model/generated/index.ts +0 -18
  408. package/src/model/glm52-atlas.ts +0 -511
  409. package/src/model/glm52-cache.ts +0 -792
  410. package/src/model/glm52-config.ts +0 -262
  411. package/src/model/glm52-container.ts +0 -305
  412. package/src/model/glm52-coupling.ts +0 -388
  413. package/src/model/glm52-dsa.ts +0 -606
  414. package/src/model/glm52-expert-layout.ts +0 -253
  415. package/src/model/glm52-layout.ts +0 -152
  416. package/src/model/glm52-memory.ts +0 -500
  417. package/src/model/glm52-mla.ts +0 -792
  418. package/src/model/glm52-moe.ts +0 -223
  419. package/src/model/glm52-pilot.ts +0 -537
  420. package/src/model/glm52-reference.ts +0 -445
  421. package/src/model/glm52-residency.ts +0 -557
  422. package/src/model/glm52-resident-weights.ts +0 -135
  423. package/src/model/glm52-streamed-experts.ts +0 -453
  424. package/src/model/glm52-streamed-metal.ts +0 -610
  425. package/src/model/glm52-weights.ts +0 -503
  426. package/src/model/glm52.ts +0 -1132
  427. package/src/model/implementation.ts +0 -69
  428. package/src/model/kv-attention-view.ts +0 -67
  429. package/src/model/minicpm5.ts +0 -376
  430. package/src/model/profile.ts +0 -443
  431. package/src/model/qwen-append.ts +0 -12
  432. package/src/model/qwen-conv.ts +0 -52
  433. package/src/model/qwen3-delta-state.ts +0 -74
  434. package/src/model/qwen3-delta.ts +0 -451
  435. package/src/model/qwen3-moe.ts +0 -404
  436. package/src/model/qwen3-mrope.ts +0 -252
  437. package/src/model/qwen3.ts +0 -277
  438. package/src/model/qwen3_5-checkpoint.ts +0 -164
  439. package/src/model/qwen3_5.ts +0 -819
  440. package/src/model/rotating-kv-donor.ts +0 -35
  441. package/src/model/rotating-kv-layout.ts +0 -262
  442. package/src/model/rotating-row-transaction.ts +0 -35
  443. package/src/model/speculative-rotating-kv.ts +0 -101
  444. package/src/model/ssm-prefill-padding.ts +0 -39
  445. package/src/model/support.ts +0 -102
  446. package/src/model/trellis-balanced-scatter.ts +0 -51
  447. package/src/model/trellis-linear.ts +0 -672
  448. package/src/model/trellis-shared-m.ts +0 -151
  449. package/src/model/trellis-shared-scatter.ts +0 -144
  450. package/src/model/trellis-splitk-prefill.ts +0 -158
  451. package/src/model/trellis-tiled-prefill.ts +0 -136
  452. package/src/model/trellis-vector-expand.ts +0 -62
  453. package/src/model/trellis-wide-prefill.ts +0 -94
  454. package/src/model/turboquant-codec.ts +0 -83
  455. package/src/model/universal/archs.ts +0 -332
  456. package/src/model/universal/dense.ts +0 -612
  457. package/src/model/universal/modules.ts +0 -170
  458. package/src/model/universal/rope.ts +0 -381
  459. package/src/native/expert_io.c +0 -523
  460. package/src/native/frame_extract.swift +0 -140
  461. package/src/native-pack.ts +0 -162
  462. package/src/pi-provider.ts +0 -53
  463. package/src/pi-session.ts +0 -81
  464. package/src/pi-terminal.ts +0 -274
  465. package/src/pi-web.ts +0 -1932
  466. package/src/preflight.ts +0 -158
  467. package/src/prompt-cache.ts +0 -460
  468. package/src/quantize/allocator.ts +0 -627
  469. package/src/quantize/atomic-output.ts +0 -38
  470. package/src/quantize/calibration.ts +0 -181
  471. package/src/quantize/config-writer.ts +0 -145
  472. package/src/quantize/index.ts +0 -84
  473. package/src/quantize/job.ts +0 -162
  474. package/src/quantize/quantizer.ts +0 -666
  475. package/src/quantize/rotate.ts +0 -603
  476. package/src/quantize/safetensors-writer.ts +0 -249
  477. package/src/quantize/sensitivity.ts +0 -216
  478. package/src/quantize/trellis.ts +0 -586
  479. package/src/quantize/weight-transform.ts +0 -292
  480. package/src/registry.ts +0 -602
  481. package/src/runtime-config.ts +0 -81
  482. package/src/safetensors.ts +0 -158
  483. package/src/sampler.ts +0 -1011
  484. package/src/serve/admin-routes.ts +0 -184
  485. package/src/serve/assets/curve-terrain.html +0 -105
  486. package/src/serve/assets/training-inference-map.html +0 -575
  487. package/src/serve/aux-routes.ts +0 -132
  488. package/src/serve/batch-scheduler.ts +0 -8
  489. package/src/serve/checkpoint-identity.ts +0 -64
  490. package/src/serve/generation-gateway.ts +0 -496
  491. package/src/serve/isolate.ts +0 -609
  492. package/src/serve/kv-budget.ts +0 -14
  493. package/src/serve/lab-routes.ts +0 -341
  494. package/src/serve/lane-registry.ts +0 -45
  495. package/src/serve/model-admin-routes.ts +0 -155
  496. package/src/serve/model-binding.ts +0 -43
  497. package/src/serve/model-host.ts +0 -511
  498. package/src/serve/parent-application.ts +0 -56
  499. package/src/serve/prompt-response-trace.ts +0 -147
  500. package/src/serve/response-lease.ts +0 -24
  501. package/src/serve/session-search.ts +0 -326
  502. package/src/serve/static-routes.ts +0 -101
  503. package/src/server.ts +0 -1314
  504. package/src/spec/assistant-rows.ts +0 -92
  505. package/src/spec/assistant-source.ts +0 -126
  506. package/src/spec/cache-identity.ts +0 -22
  507. package/src/spec/deepspec-rows.ts +0 -29
  508. package/src/spec/deepspec-source.ts +0 -145
  509. package/src/spec/dflash-source.ts +0 -149
  510. package/src/spec/drafter.ts +0 -304
  511. package/src/spec/dspark/ab-stats.ts +0 -136
  512. package/src/spec/dspark/calibration.ts +0 -112
  513. package/src/spec/dspark/data-dflash.ts +0 -156
  514. package/src/spec/dspark/data.ts +0 -201
  515. package/src/spec/dspark/deepspec-module.ts +0 -776
  516. package/src/spec/dspark/generate-dflash.ts +0 -245
  517. package/src/spec/dspark/generate.ts +0 -290
  518. package/src/spec/dspark/loader.ts +0 -23
  519. package/src/spec/dspark/loss.ts +0 -213
  520. package/src/spec/dspark/module-dflash.ts +0 -560
  521. package/src/spec/dspark/module.ts +0 -540
  522. package/src/spec/dspark/quantize-drafter.ts +0 -91
  523. package/src/spec/dspark/sample.ts +0 -112
  524. package/src/spec/generate.ts +0 -276
  525. package/src/spec/glm52-mtp-graph.ts +0 -29
  526. package/src/spec/glm52-mtp-rows.ts +0 -132
  527. package/src/spec/glm52-mtp-source.ts +0 -317
  528. package/src/spec/glm52-mtp-state.ts +0 -33
  529. package/src/spec/ngram-source.ts +0 -204
  530. package/src/spec/projected-draft-rows.ts +0 -73
  531. package/src/spec/qwen-mtp-module.ts +0 -171
  532. package/src/spec/qwen-mtp-rows.ts +0 -219
  533. package/src/spec/qwen-mtp-source.ts +0 -383
  534. package/src/spec/qwen-mtp-state.ts +0 -30
  535. package/src/spec/serve-loop.ts +0 -585
  536. package/src/spec/source.ts +0 -215
  537. package/src/spec/two-model-rows.ts +0 -61
  538. package/src/spec/two-model.ts +0 -113
  539. package/src/ssd-cache.ts +0 -372
  540. package/src/ssd-durability.ts +0 -211
  541. package/src/tokenizer.ts +0 -335
  542. package/src/tool-approvals.ts +0 -131
  543. package/src/tool-call.ts +0 -695
  544. package/src/train/dataset.ts +0 -484
  545. package/src/train/diffusion-lora.ts +0 -216
  546. package/src/train/export.ts +0 -32
  547. package/src/train/flash-cce.ts +0 -1234
  548. package/src/train/forward.ts +0 -266
  549. package/src/train/fuse.ts +0 -243
  550. package/src/train/index.ts +0 -46
  551. package/src/train/job.ts +0 -205
  552. package/src/train/lora-params.ts +0 -254
  553. package/src/train/loss.ts +0 -1591
  554. package/src/train/merge.ts +0 -195
  555. package/src/train/optimizer.ts +0 -183
  556. package/src/train/prefix-shared.ts +0 -490
  557. package/src/train/rank.ts +0 -137
  558. package/src/train/segmented.ts +0 -1828
  559. package/src/train/steel-qmm-header.ts +0 -1461
  560. package/src/train/trainer.ts +0 -1221
  561. package/src/train/watch.ts +0 -542
  562. package/src/vision/diffusion-vision.ts +0 -620
  563. package/src/vision/embedder.ts +0 -168
  564. package/src/vision/preprocess.ts +0 -247
  565. package/src/vision/prompt.ts +0 -373
  566. package/src/vision/qwen3vl-preprocess.ts +0 -409
  567. package/src/vision/qwen3vl-prompt.ts +0 -196
  568. package/src/vision/qwen3vl-tower.ts +0 -555
  569. package/src/vision/siglip.ts +0 -599
  570. package/src/vision/video-frames.ts +0 -148
  571. package/src/web/app.html +0 -2143
  572. package/src/web/app.js +0 -5703
  573. package/src/web/skills/memory/SKILL.md +0 -120
  574. package/src/web/skills/web-research/SKILL.md +0 -46
  575. package/src/web/skills.ts +0 -97
  576. package/src/web/src/adapters-panel.ts +0 -288
  577. package/src/web/src/assistant.ts +0 -451
  578. package/src/web/src/chat.ts +0 -1057
  579. package/src/web/src/composer.ts +0 -959
  580. package/src/web/src/dataset.ts +0 -132
  581. package/src/web/src/finetune.ts +0 -267
  582. package/src/web/src/hub.ts +0 -428
  583. package/src/web/src/main.ts +0 -98
  584. package/src/web/src/markdown.ts +0 -0
  585. package/src/web/src/memory-panel.ts +0 -572
  586. package/src/web/src/model-picker.ts +0 -159
  587. package/src/web/src/palette.ts +0 -346
  588. package/src/web/src/protocol.ts +0 -26
  589. package/src/web/src/quantize.ts +0 -167
  590. package/src/web/src/rag.ts +0 -274
  591. package/src/web/src/sessions.ts +0 -469
  592. package/src/web/src/shell.ts +0 -804
  593. package/src/web/src/ui-catalog.ts +0 -78
  594. package/src/web/vendor/README.md +0 -61
  595. package/src/web-assets.ts +0 -47
  596. package/src/web-tools.ts +0 -478
  597. package/src/weights.ts +0 -255
  598. /package/src/{serve → server}/completion-sink.ts +0 -0
  599. /package/src/web/{icon.svg → public/icon.svg} +0 -0
  600. /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
  601. /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
@@ -1,671 +0,0 @@
1
- // mlx-bun memory — deterministic NORMALIZE pass (P6-T2). No model.
2
- //
3
- // After every write, before `commitVault`, an article is run through this pass
4
- // so the invariants the read path depends on are CONSTITUTIVE, not advisory.
5
- // Ported from lucien (~/Code/lucien): `normalize-footnotes.ts` (footnote
6
- // bijection + contiguous renumber) and `normalize-wikilinks.ts` (spaced →
7
- // underscore link canonicalization), extended with the Dreaming structural
8
- // guards (infobox key sort, `## References` last / `## See also` before it,
9
- // `{{stub}}` for thin articles, `title = H1 = stem`).
10
- //
11
- // Everything here is PURE (string in, string out) and idempotent: a second pass
12
- // over a normalized article is a byte-identical no-op. Every step is non-fatal —
13
- // a step that cannot complete logs a note and the others still run, so a single
14
- // malformed region never corrupts the vault. `normalizeVault` is the on-disk
15
- // entry the pipeline calls; the per-article core is `normalizeArticle`.
16
-
17
- import { readFile, writeFile } from "node:fs/promises";
18
- import { join } from "node:path";
19
- import { isFenceLine, fenceLabel, parseInfobox, repairFences, serializeInfobox } from "./article";
20
- import { articlesDir, listArticles, resolveWikilinkToStem, vaultRoot } from "./vault";
21
-
22
- // ---- shared scanners --------------------------------------------------
23
-
24
- const HEADING_RE = /^(#{1,6})\s+(.+)$/;
25
- const DEF_LINE = /^[ \t]*\[\^(\d+)\]:/;
26
- const SERIES_RE = /^\*Part of a series on \[\[([^\]]+)\]\]\.?\*$/;
27
- /** A merged-away title's one-line pointer at its canonical article. */
28
- const REDIRECT_RE = /^\*Redirects to \[\[[^\]]+\]\]\.?\*$/m;
29
- /** The `{{stub}}` template, recognized only as a line of its own. */
30
- const STUB_LINE_RE = /^\{\{stub\}\}\s*$/;
31
- /** The `{{Main}}` summary-style pointer (`*Main article: [[Target]]*`). */
32
- export const MAIN_POINTER_RE = /^\*Main article: \[\[[^\]]+\]\]\*$/;
33
-
34
- // ---- footnote integrity (local copy of lucien wikify.ts) -------------
35
-
36
- export interface CheckResult {
37
- ok: boolean;
38
- errors: string[];
39
- }
40
-
41
- /**
42
- * Verify footnote markers and definitions are consistent:
43
- * every `[^N]` body marker has a `[^N]:` definition and vice-versa; marker
44
- * numbers are contiguous from 1; every definition carries exactly one
45
- * backticked `conv:HASH`. (Ported from lucien `wikify.ts`.)
46
- */
47
- export function checkFootnoteIntegrity(text: string): CheckResult {
48
- const errors: string[] = [];
49
-
50
- const defNums = new Set<number>();
51
- const defLineByNum = new Map<number, string>();
52
- for (const m of text.matchAll(/^\[\^(\d+)\]:(.*)$/gm)) {
53
- const n = parseInt(m[1]!, 10);
54
- defNums.add(n);
55
- defLineByNum.set(n, m[2]!);
56
- }
57
-
58
- // Body markers = every `[^N]` NOT on a `[^N]:` definition line. Only a
59
- // line-START `[^N]:` is a definition; a marker glued to a list colon
60
- // (`two types[^2]:`) is still a marker.
61
- const bodyText = text
62
- .split("\n")
63
- .filter((l) => !/^\[\^\d+\]:/.test(l))
64
- .join("\n");
65
- const markerNums = new Set<number>();
66
- for (const m of bodyText.matchAll(/\[\^(\d+)\]/g)) {
67
- markerNums.add(parseInt(m[1]!, 10));
68
- }
69
-
70
- for (const n of markerNums) {
71
- if (!defNums.has(n)) errors.push(`marker [^${n}] has no definition`);
72
- }
73
- for (const n of defNums) {
74
- if (!markerNums.has(n)) errors.push(`definition [^${n}] has no marker`);
75
- }
76
-
77
- const all = [...new Set([...markerNums, ...defNums])].sort((a, b) => a - b);
78
- for (let i = 0; i < all.length; i++) {
79
- if (all[i] !== i + 1) {
80
- errors.push(`footnote numbers not contiguous from 1 (saw ${all.join(",")})`);
81
- break;
82
- }
83
- }
84
-
85
- for (const [n, line] of defLineByNum) {
86
- const backticked = line.match(/`conv:[0-9a-z]{8}`/gi) ?? [];
87
- if (backticked.length !== 1) {
88
- errors.push(`[^${n}] definition lacks a backticked \`conv:HASH\` (found ${backticked.length})`);
89
- }
90
- }
91
-
92
- return { ok: errors.length === 0, errors };
93
- }
94
-
95
- /** True when two `[^N]:` definitions cite the same `conv:HASH` (the duplicate
96
- * the merge step collapses); ignores defs without a hash. */
97
- function hasDuplicateConvDefs(text: string): boolean {
98
- const seen = new Set<string>();
99
- for (const line of text.split("\n")) {
100
- const m = line.match(/^[ \t]*\[\^(\d+)\]:(.*)$/);
101
- if (!m) continue;
102
- const c = m[2]!.match(/conv:[0-9a-z]{8}/i);
103
- if (!c) continue;
104
- const h = c[0]!.toLowerCase();
105
- if (seen.has(h)) return true;
106
- seen.add(h);
107
- }
108
- return false;
109
- }
110
-
111
- // ---- footnote normalization (ported + merge) -------------------------
112
-
113
- export interface NormalizeFootnoteResult {
114
- article: string;
115
- changed: boolean;
116
- /** Orphan body markers (no definition) that were dropped. */
117
- droppedMarkers: number[];
118
- /** Orphan definitions (no body marker) that were dropped. */
119
- droppedDefs: { num: number; conv: string | null }[];
120
- /** Definitions merged into an earlier def citing the same `conv:HASH`. */
121
- mergedDefs: number[];
122
- /** Auditable summary of what changed, or null on a no-op. */
123
- talk: string | null;
124
- }
125
-
126
- /** Distinct body-marker numbers in order of first appearance (defs masked). */
127
- function bodyMarkerOrder(text: string): number[] {
128
- const masked = text
129
- .split("\n")
130
- .map((l) => (DEF_LINE.test(l) ? "" : l))
131
- .join("\n");
132
- const order: number[] = [];
133
- const seen = new Set<number>();
134
- for (const m of masked.matchAll(/\[\^(\d+)\]/g)) {
135
- const n = parseInt(m[1]!, 10);
136
- if (!seen.has(n)) {
137
- seen.add(n);
138
- order.push(n);
139
- }
140
- }
141
- return order;
142
- }
143
-
144
- /**
145
- * Deterministically repair footnote integrity (ported from lucien
146
- * `normalize-footnotes.ts`, extended to merge duplicate `conv:HASH` defs):
147
- * drop orphan markers and orphan defs, collapse two defs that cite the same
148
- * conversation into the earlier one, then renumber the survivors 1..k in order
149
- * of first body appearance. A bijective, duplicate-free article is returned
150
- * byte-identical (no-op), hence idempotent. Throws only if the post-condition
151
- * (`checkFootnoteIntegrity`) fails — the orchestrator catches that.
152
- */
153
- export function normalizeFootnotes(article: string): NormalizeFootnoteResult {
154
- if (checkFootnoteIntegrity(article).ok && !hasDuplicateConvDefs(article)) {
155
- return { article, changed: false, droppedMarkers: [], droppedDefs: [], mergedDefs: [], talk: null };
156
- }
157
-
158
- const defNums = new Set<number>();
159
- const defConv = new Map<number, string | null>();
160
- for (const line of article.split("\n")) {
161
- const m = line.match(/^[ \t]*\[\^(\d+)\]:(.*)$/);
162
- if (m) {
163
- const n = parseInt(m[1]!, 10);
164
- defNums.add(n);
165
- const c = m[2]!.match(/conv:[0-9a-z]{8}/i);
166
- defConv.set(n, c ? c[0]!.toLowerCase() : null);
167
- }
168
- }
169
-
170
- const bodyOrder = bodyMarkerOrder(article);
171
- const bodySet = new Set(bodyOrder);
172
-
173
- // Markers that also have a definition — the merge/renumber candidates.
174
- const candidates = bodyOrder.filter((n) => defNums.has(n));
175
- const droppedMarkers = bodyOrder.filter((n) => !defNums.has(n));
176
- const droppedDefs = [...defNums]
177
- .filter((n) => !bodySet.has(n))
178
- .sort((a, b) => a - b)
179
- .map((n) => ({ num: n, conv: defConv.get(n) ?? null }));
180
-
181
- // Merge: each conv:HASH maps to its first-appearing candidate.
182
- const canonByConv = new Map<string, number>();
183
- const canonMap = new Map<number, number>();
184
- for (const n of candidates) {
185
- const c = defConv.get(n) ?? null;
186
- if (c === null) {
187
- canonMap.set(n, n);
188
- continue;
189
- }
190
- if (!canonByConv.has(c)) canonByConv.set(c, n);
191
- canonMap.set(n, canonByConv.get(c)!);
192
- }
193
- const mergedDefs = candidates.filter((n) => canonMap.get(n) !== n);
194
-
195
- // Survivors in first-appearance order → contiguous 1..k.
196
- const survivorOrder: number[] = [];
197
- const seenSurv = new Set<number>();
198
- for (const n of candidates) {
199
- const c = canonMap.get(n)!;
200
- if (!seenSurv.has(c)) {
201
- seenSurv.add(c);
202
- survivorOrder.push(c);
203
- }
204
- }
205
- const remap = new Map<number, number>();
206
- survivorOrder.forEach((oldN, i) => remap.set(oldN, i + 1));
207
-
208
- const dropMarkerSet = new Set(droppedMarkers);
209
- const dropDefSet = new Set<number>([...droppedDefs.map((d) => d.num), ...mergedDefs]);
210
-
211
- const out = article
212
- .split("\n")
213
- .filter((line) => {
214
- const m = line.match(DEF_LINE);
215
- return !(m && dropDefSet.has(parseInt(m[1]!, 10)));
216
- })
217
- .map((line) =>
218
- line.replace(/[ \t]?\[\^(\d+)\]/g, (whole, num: string) => {
219
- const n = parseInt(num, 10);
220
- if (dropMarkerSet.has(n)) return ""; // orphan marker
221
- const canon = canonMap.get(n) ?? n;
222
- const nn = remap.get(canon);
223
- const lead = /^[ \t]/.test(whole) ? whole[0]! : "";
224
- return nn ? `${lead}[^${nn}]` : whole;
225
- }),
226
- )
227
- .join("\n");
228
-
229
- const post = checkFootnoteIntegrity(out);
230
- if (!post.ok) {
231
- throw new Error(`normalize-footnotes post-condition failed: ${post.errors.join("; ")}`);
232
- }
233
-
234
- const parts: string[] = [];
235
- if (droppedMarkers.length) {
236
- parts.push(
237
- `Dropped ${droppedMarkers.length} orphan citation marker(s) — ` +
238
- droppedMarkers.map((n) => `[^${n}]`).join(", ") +
239
- ` — marker emitted with no definition; nothing recoverable, prose left intact.`,
240
- );
241
- }
242
- if (droppedDefs.length) {
243
- parts.push(
244
- `Dropped ${droppedDefs.length} unused definition(s): ` +
245
- droppedDefs.map((d) => `[^${d.num}]${d.conv ? ` (\`${d.conv}\`)` : ""}`).join(", ") +
246
- ` — no body marker referenced them.`,
247
- );
248
- }
249
- if (mergedDefs.length) {
250
- parts.push(
251
- `Merged ${mergedDefs.length} duplicate definition(s) (${mergedDefs
252
- .map((n) => `[^${n}]`)
253
- .join(", ")}) into the earlier footnote citing the same conversation.`,
254
- );
255
- }
256
- parts.push("Renumbered surviving footnotes contiguously from 1.");
257
-
258
- return {
259
- article: out,
260
- changed: out !== article,
261
- droppedMarkers,
262
- droppedDefs,
263
- mergedDefs,
264
- talk: parts.join(" "),
265
- };
266
- }
267
-
268
- // ---- wikilink canonicalization (ported) ------------------------------
269
-
270
- export interface NormalizeWikilinkResult {
271
- content: string;
272
- /** Number of link targets rewritten to their canonical stem. */
273
- edits: number;
274
- /** Distinct unresolved (redlink) targets — flagged, not modified. */
275
- orphans: string[];
276
- }
277
-
278
- /**
279
- * Rewrite spaced/uncanonical wikilink targets to their underscore stem when the
280
- * stem is a known article (ported from lucien `normalize-wikilinks.ts`, using
281
- * `resolveWikilinkToStem` for resolution). The alias (`|alias`) and section
282
- * anchor (`#Section`) are display/match text and are preserved verbatim;
283
- * `conv:` and `Category:` links are left alone. Unresolved targets are true
284
- * redlinks — collected for flagging, never rewritten. Idempotent: an already
285
- * canonical link is untouched. Infobox entity-values are normalized by the same
286
- * pass (the replace runs over the whole article text, fence included).
287
- */
288
- export function normalizeWikilinks(content: string, stems: Set<string>): NormalizeWikilinkResult {
289
- let edits = 0;
290
- const orphans = new Set<string>();
291
-
292
- const out = content.replace(/\[\[([^\]]+?)\]\]/g, (whole, inner: string) => {
293
- const pipeIdx = inner.indexOf("|");
294
- const alias = pipeIdx === -1 ? null : inner.slice(pipeIdx + 1);
295
- const beforeAlias = pipeIdx === -1 ? inner : inner.slice(0, pipeIdx);
296
-
297
- const hashIdx = beforeAlias.indexOf("#");
298
- const section = hashIdx === -1 ? null : beforeAlias.slice(hashIdx + 1);
299
- const target = hashIdx === -1 ? beforeAlias : beforeAlias.slice(0, hashIdx);
300
-
301
- const t = target.trim();
302
- if (!t || /^conv:/i.test(t) || /^Category:/i.test(t)) return whole;
303
-
304
- const resolved = resolveWikilinkToStem(t, stems);
305
- if (resolved === null) {
306
- orphans.add(t); // true redlink — flag, leave verbatim
307
- return whole;
308
- }
309
- if (resolved === target) return whole; // already canonical
310
-
311
- let rebuilt = resolved;
312
- if (section !== null) rebuilt += `#${section}`;
313
- if (alias !== null) rebuilt += `|${alias}`;
314
- edits++;
315
- return `[[${rebuilt}]]`;
316
- });
317
-
318
- return { content: out, edits, orphans: [...orphans] };
319
- }
320
-
321
- // ---- infobox key sort -------------------------------------------------
322
-
323
- function findInfoBlock(lines: string[]): { start: number; end: number } | null {
324
- for (let i = 0; i < lines.length; i++) {
325
- if (isFenceLine(lines[i]!) && fenceLabel(lines[i]!) === "info") {
326
- for (let j = i + 1; j < lines.length; j++) {
327
- if (isFenceLine(lines[j]!)) return { start: i, end: j };
328
- }
329
- return null; // unterminated
330
- }
331
- }
332
- return null;
333
- }
334
-
335
- /** Schema keys lead (`type`, `kind`), `aliases` trails, the rest alphabetical. */
336
- function infoboxKeyRank(key: string): number {
337
- if (key === "type") return 0;
338
- if (key === "kind") return 1;
339
- if (key === "aliases") return 3;
340
- return 2;
341
- }
342
-
343
- /** Sort an article's infobox fields into a deterministic, idempotent order. */
344
- export function sortInfoboxKeys(content: string): { content: string; changed: boolean } {
345
- const box = parseInfobox(content);
346
- if (!box || box.fields.length === 0) return { content, changed: false };
347
-
348
- const sorted = box.fields
349
- .map((f, i) => ({ f, i }))
350
- .sort((a, b) => {
351
- const ra = infoboxKeyRank(a.f.key);
352
- const rb = infoboxKeyRank(b.f.key);
353
- if (ra !== rb) return ra - rb;
354
- const c = a.f.key.localeCompare(b.f.key);
355
- return c !== 0 ? c : a.i - b.i; // stable on equal keys
356
- })
357
- .map((x) => x.f);
358
-
359
- const sameOrder = sorted.every((f, i) => f === box.fields[i]);
360
- if (sameOrder) return { content, changed: false };
361
-
362
- const lines = content.split(/\r?\n/);
363
- const block = findInfoBlock(lines);
364
- if (!block) return { content, changed: false };
365
-
366
- const rendered = serializeInfobox({ ...box, fields: sorted }).split("\n");
367
- const next = [...lines.slice(0, block.start), ...rendered, ...lines.slice(block.end + 1)].join("\n");
368
- return { content: next, changed: next !== content };
369
- }
370
-
371
- // ---- structural guards ------------------------------------------------
372
-
373
- interface TopSection {
374
- kind: "body" | "see" | "notes" | "refs";
375
- lines: string[];
376
- }
377
-
378
- function splitTopSections(content: string): { head: string[]; sections: TopSection[] } {
379
- const lines = content.split(/\r?\n/);
380
- const head: string[] = [];
381
- const sections: TopSection[] = [];
382
- let cur: TopSection | null = null;
383
- let inFence = false;
384
- for (const line of lines) {
385
- if (isFenceLine(line)) {
386
- inFence = !inFence;
387
- (cur ? cur.lines : head).push(line);
388
- continue;
389
- }
390
- if (!inFence) {
391
- const h = HEADING_RE.exec(line);
392
- if (h && h[1]!.length === 2) {
393
- const title = h[2]!.trim().toLowerCase();
394
- const kind: TopSection["kind"] =
395
- title === "see also" ? "see" : title === "notes" ? "notes" : title === "references" ? "refs" : "body";
396
- cur = { kind, lines: [line] };
397
- sections.push(cur);
398
- continue;
399
- }
400
- }
401
- (cur ? cur.lines : head).push(line);
402
- }
403
- return { head, sections };
404
- }
405
-
406
- /** Merge several same-kind trailing-meta sections (the duplicate `## References` /
407
- * `## See also` blocks a fence-confused PATCH/cross-link left behind) into ONE:
408
- * keep the first heading, then the union of every block's body lines with
409
- * duplicate lines dropped (first occurrence wins) so repeated See-also bullets
410
- * collapse and split footnote defs coalesce. Idempotent on a singleton group. */
411
- function mergeMetaGroup(group: TopSection[]): TopSection {
412
- if (group.length === 1) return group[0]!;
413
- const heading = group[0]!.lines[0]!;
414
- const body: string[] = [];
415
- const seen = new Set<string>();
416
- for (const s of group) {
417
- for (const line of s.lines.slice(1)) {
418
- const key = line.trim();
419
- if (key === "") {
420
- if (body.length && body[body.length - 1] !== "") body.push("");
421
- continue;
422
- }
423
- if (seen.has(key)) continue;
424
- seen.add(key);
425
- body.push(line);
426
- }
427
- }
428
- while (body.length && body[body.length - 1] === "") body.pop();
429
- return { kind: group[0]!.kind, lines: [heading, ...body, ""] };
430
- }
431
-
432
- /** Reorder trailing meta sections so body → `See also` → `Notes` → `References`
433
- * (References always last), MERGING any duplicate same-kind meta blocks into one
434
- * along the way. Idempotent: an already-correct article (one block per kind, in
435
- * order) is returned untouched. */
436
- export function reorderSections(content: string): { content: string; changed: boolean } {
437
- const { head, sections } = splitTopSections(content);
438
- if (sections.length === 0) return { content, changed: false };
439
-
440
- // Body sections stay distinct and in document order; the trailing-meta kinds are
441
- // singletons by grammar, so collapse any duplicates into one block per kind.
442
- const ordered: TopSection[] = sections.filter((s) => s.kind === "body");
443
- for (const kind of ["see", "notes", "refs"] as const) {
444
- const group = sections.filter((s) => s.kind === kind);
445
- if (group.length) ordered.push(mergeMetaGroup(group));
446
- }
447
-
448
- const same = ordered.length === sections.length && ordered.every((s, i) => s === sections[i]);
449
- if (same) return { content, changed: false };
450
-
451
- const next = [...head, ...ordered.flatMap((s) => s.lines)].join("\n");
452
- return { content: next, changed: next !== content };
453
- }
454
-
455
- /** Enforce `title = H1 = stem` (underscores → spaces). Rewrites a divergent H1
456
- * and prepends one when absent. */
457
- export function enforceH1Title(content: string, stem: string): { content: string; changed: boolean } {
458
- const canonical = stem.replace(/_/g, " ");
459
- const lines = content.split(/\r?\n/);
460
- let inFence = false;
461
- for (let i = 0; i < lines.length; i++) {
462
- if (isFenceLine(lines[i]!)) {
463
- inFence = !inFence;
464
- continue;
465
- }
466
- if (inFence) continue;
467
- const h = HEADING_RE.exec(lines[i]!);
468
- if (h && h[1]!.length === 1) {
469
- if (h[2]!.trim() === canonical) return { content, changed: false };
470
- lines[i] = `# ${canonical}`;
471
- return { content: lines.join("\n"), changed: true };
472
- }
473
- }
474
- // No H1 found — prepend the canonical title.
475
- return { content: `# ${canonical}\n\n${content}`, changed: true };
476
- }
477
-
478
- /** Body-section count and body-prose word count, EXCLUDING the infobox and the
479
- * `## References` section (the L1 stub threshold inputs). */
480
- export function articleThinness(content: string): { bodySections: number; bodyWords: number; stub: boolean } {
481
- const lines = content.split(/\r?\n/);
482
- let inFence = false;
483
- let inRefs = false;
484
- let bodySections = 0;
485
- let bodyWords = 0;
486
- for (const line of lines) {
487
- if (isFenceLine(line)) {
488
- inFence = !inFence;
489
- continue;
490
- }
491
- if (inFence) continue;
492
- const h = HEADING_RE.exec(line);
493
- if (h) {
494
- if (h[1]!.length === 2) {
495
- const title = h[2]!.trim().toLowerCase();
496
- inRefs = title === "references";
497
- if (title !== "references" && title !== "see also" && title !== "notes") bodySections++;
498
- }
499
- continue; // headings are not prose
500
- }
501
- if (inRefs) continue;
502
- const t = line.trim();
503
- if (!t) continue;
504
- if (STUB_LINE_RE.test(t)) continue;
505
- if (/^categories:/i.test(t)) continue;
506
- if (SERIES_RE.test(t)) continue;
507
- bodyWords += t.split(/\s+/).length;
508
- }
509
- return { bodySections, bodyWords, stub: bodySections < 2 || bodyWords < 40 };
510
- }
511
-
512
- /** True when the article carries a `{{stub}}` line. */
513
- export function hasStubMarker(content: string): boolean {
514
- return content.split(/\r?\n/).some((l) => STUB_LINE_RE.test(l));
515
- }
516
-
517
- /** Mark a thin article `{{stub}}` (after the H1); remove a stale marker once the
518
- * article has outgrown the threshold. */
519
- export function stubGuard(content: string): { content: string; changed: boolean } {
520
- const thin = articleThinness(content).stub;
521
- const has = hasStubMarker(content);
522
- if (thin === has) return { content, changed: false };
523
-
524
- const lines = content.split(/\r?\n/);
525
- if (!thin && has) {
526
- const next = lines.filter((l) => !STUB_LINE_RE.test(l)).join("\n");
527
- return { content: next, changed: next !== content };
528
- }
529
- // thin && !has — insert after the H1 (or at the very top if none).
530
- let inFence = false;
531
- let h1 = -1;
532
- for (let i = 0; i < lines.length; i++) {
533
- if (isFenceLine(lines[i]!)) {
534
- inFence = !inFence;
535
- continue;
536
- }
537
- if (inFence) continue;
538
- const h = HEADING_RE.exec(lines[i]!);
539
- if (h && h[1]!.length === 1) {
540
- h1 = i;
541
- break;
542
- }
543
- }
544
- if (h1 < 0) lines.unshift("{{stub}}", "");
545
- else lines.splice(h1 + 1, 0, "", "{{stub}}");
546
- return { content: lines.join("\n"), changed: true };
547
- }
548
-
549
- // ---- orchestrator -----------------------------------------------------
550
-
551
- export interface NormalizeArticleResult {
552
- content: string;
553
- changed: boolean;
554
- /** Human-readable record of every normalization applied (non-fatal log). */
555
- notes: string[];
556
- /** Whether the normalized article is marked `{{stub}}`. */
557
- stub: boolean;
558
- /** Whether the article is a merge redirect (heavy guards are skipped). */
559
- redirect: boolean;
560
- }
561
-
562
- /**
563
- * Run the full deterministic NORMALIZE pass over one article. Every step is
564
- * non-fatal: a step that throws (a footnote post-condition it cannot satisfy,
565
- * say) is logged and skipped while the others still run, so a malformed region
566
- * never blocks the rest. Idempotent.
567
- */
568
- export function normalizeArticle(content: string, opts: { stem: string; stems: Set<string> }): NormalizeArticleResult {
569
- const notes: string[] = [];
570
- let out = content;
571
- const redirect = REDIRECT_RE.test(out);
572
-
573
- // 0. Fence repair — heal an unbalanced ``` BEFORE any fence-aware step runs.
574
- // An odd fence count leaves reorder/stub/H1 (and the read path) stuck "in code"
575
- // for the rest of the file, so trailing ## References / ## See also are never
576
- // recognized. Closing the dangling fence restores them. Non-fatal, idempotent.
577
- const fx = repairFences(out);
578
- if (fx.changed) {
579
- out = fx.content;
580
- notes.push("repaired unbalanced code fence");
581
- }
582
-
583
- // 1. Footnote bijection + renumber + merge.
584
- try {
585
- const fr = normalizeFootnotes(out);
586
- if (fr.changed) {
587
- out = fr.article;
588
- if (fr.droppedMarkers.length) notes.push(`dropped ${fr.droppedMarkers.length} orphan footnote marker(s)`);
589
- if (fr.droppedDefs.length) notes.push(`dropped ${fr.droppedDefs.length} orphan footnote def(s)`);
590
- if (fr.mergedDefs.length) notes.push(`merged ${fr.mergedDefs.length} duplicate footnote def(s)`);
591
- notes.push("renumbered footnotes contiguously");
592
- }
593
- } catch (err) {
594
- notes.push(`footnote normalization skipped: ${(err as Error).message}`);
595
- }
596
-
597
- // 2. Wikilink canonicalization (prose + infobox entity-values).
598
- const wl = normalizeWikilinks(out, opts.stems);
599
- if (wl.edits > 0) {
600
- out = wl.content;
601
- notes.push(`canonicalized ${wl.edits} wikilink(s)`);
602
- }
603
- if (wl.orphans.length) notes.push(`unresolved wikilink(s): ${wl.orphans.join(", ")}`);
604
-
605
- // 3. Infobox key sort.
606
- const ib = sortInfoboxKeys(out);
607
- if (ib.changed) {
608
- out = ib.content;
609
- notes.push("sorted infobox keys");
610
- }
611
-
612
- // 4. Structural guards.
613
- const h1 = enforceH1Title(out, opts.stem);
614
- if (h1.changed) {
615
- out = h1.content;
616
- notes.push("normalized H1 title to stem");
617
- }
618
- if (!redirect) {
619
- const ro = reorderSections(out);
620
- if (ro.changed) {
621
- out = ro.content;
622
- notes.push("reordered trailing sections (References last)");
623
- }
624
- const sg = stubGuard(out);
625
- if (sg.changed) {
626
- out = sg.content;
627
- notes.push(hasStubMarker(out) ? "marked {{stub}} (thin article)" : "removed stale {{stub}}");
628
- }
629
- }
630
-
631
- return { content: out, changed: out !== content, notes, stub: hasStubMarker(out), redirect };
632
- }
633
-
634
- // ---- on-disk entry (runs after every write, before commitVault) ------
635
-
636
- export interface VaultNormalizeSummary {
637
- /** Stems whose on-disk content changed. */
638
- normalized: string[];
639
- /** Per-stem normalization notes (only stems with at least one note). */
640
- notes: Record<string, string[]>;
641
- }
642
-
643
- /**
644
- * Normalize every article in the vault, writing back the ones that changed.
645
- * Best-effort and non-fatal per article; the caller commits afterward. The stem
646
- * set is the whole article list so wikilink resolution sees every neighbor.
647
- */
648
- export async function normalizeVault(root = vaultRoot()): Promise<VaultNormalizeSummary> {
649
- const stems = await listArticles(root);
650
- const stemSet = new Set(stems);
651
- const normalized: string[] = [];
652
- const notes: Record<string, string[]> = {};
653
-
654
- for (const stem of stems) {
655
- const path = join(articlesDir(root), `${stem}.md`);
656
- let content: string;
657
- try {
658
- content = await readFile(path, "utf8");
659
- } catch {
660
- continue;
661
- }
662
- const r = normalizeArticle(content, { stem, stems: stemSet });
663
- if (r.notes.length) notes[stem] = r.notes;
664
- if (r.changed) {
665
- await writeFile(path, r.content);
666
- normalized.push(stem);
667
- }
668
- }
669
-
670
- return { normalized, notes };
671
- }
@@ -1,22 +0,0 @@
1
- // mlx-bun memory — parse contracts for model outputs.
2
- //
3
- // The synthesis pipeline drives the model with small, structured prompts and
4
- // needs deterministic parsing of free-text completions back into typed values.
5
- // Two shapes cover the cases: a yes/no binary gate and a newline list.
6
-
7
- /** Binary gate: true iff the output starts with `y`/`Y` (everything else → false). */
8
- export function parseBinary(out: string): boolean {
9
- return /^\s*y/i.test(out);
10
- }
11
-
12
- /**
13
- * List output: split on newlines, trim each line, and drop empties as well as
14
- * any line that is exactly "NONE" (case-insensitive) — the model's sentinel for
15
- * "no items".
16
- */
17
- export function parseLines(out: string): string[] {
18
- return out
19
- .split("\n")
20
- .map((line) => line.trim())
21
- .filter((line) => line.length > 0 && line.toLowerCase() !== "none");
22
- }