mlx-bun 0.5.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (640) hide show
  1. package/README.md +1449 -109
  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 +7 -5
  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 +10 -10
  78. package/src/{serve → server}/chat-stage.ts +14 -14
  79. package/src/{client.ts → server/client.ts} +28 -2
  80. package/src/{serve → server}/completion-executor.ts +33 -41
  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 +25 -82
  85. package/src/{serve → server}/http.ts +25 -13
  86. package/src/{serve → server}/inference-request.ts +5 -5
  87. package/src/server/job-routes.ts +20 -0
  88. package/src/server/media-prompt.ts +63 -0
  89. package/src/server/memory-completion-client.ts +46 -0
  90. package/src/server/model-routes.ts +192 -0
  91. package/src/{serve → server}/openai-wire.ts +3 -2
  92. package/src/{serve → server}/pipeline.ts +1 -1
  93. package/src/server/prompt-builder.ts +13 -0
  94. package/src/server/prompt-contracts.ts +17 -0
  95. package/src/server/proxy-routes.ts +187 -0
  96. package/src/server/publishing-routes.ts +41 -0
  97. package/src/{serve → server}/request-plan.ts +6 -8
  98. package/src/{serve → server}/request-prep.ts +47 -50
  99. package/src/{serve → server}/responses-client.ts +30 -13
  100. package/src/{responses.ts → server/responses.ts} +12 -93
  101. package/src/server/routes.ts +205 -0
  102. package/src/server/start.ts +72 -0
  103. package/src/server/status-routes.ts +108 -0
  104. package/src/{serve → server}/text-completion-stage.ts +25 -4
  105. package/src/server/text-prompt.ts +12 -0
  106. package/src/{serve → server}/token-streams.ts +36 -38
  107. package/src/server/worker-routes.ts +311 -0
  108. package/src/storage/paths.ts +61 -0
  109. package/src/web/assets.ts +37 -0
  110. package/src/web/{src → browser}/api.ts +5 -23
  111. package/src/web/browser/chat-host.ts +17 -0
  112. package/src/web/browser/installed-panels.ts +6 -0
  113. package/src/web/browser/main.ts +55 -0
  114. package/src/web/browser/markdown.ts +279 -0
  115. package/src/web/browser/memory-panel.ts +9 -0
  116. package/src/web/browser/palette.ts +64 -0
  117. package/src/web/browser/protocol.ts +13 -0
  118. package/src/web/browser/shell.ts +467 -0
  119. package/src/web/{src → browser}/status.ts +32 -36
  120. package/src/web/build.ts +51 -0
  121. package/src/web/public/app.html +1054 -0
  122. package/src/web/{sw.js → public/sw.js} +4 -3
  123. package/src/web/{vendor → public/vendor}/hljs-theme.css +2 -2
  124. package/src/web/{vendor → public/vendor}/hljs.js +2 -2
  125. package/THIRD_PARTY_LICENSES.md +0 -51
  126. package/docs/README.md +0 -107
  127. package/docs/archive/hlg-sampling.md +0 -350
  128. package/docs/archive/investigations/audio-input-plan.md +0 -356
  129. package/docs/archive/investigations/benchmark-ledger-through-v0.4.0.md +0 -3617
  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/release-notes-v0.4.0.md +0 -45
  174. package/docs/archive/planning/release-notes-v0.5.0.md +0 -37
  175. package/docs/archive/planning/web-ui-pass-plan.md +0 -213
  176. package/docs/archive/planning/website-readme-pass-plan.md +0 -224
  177. package/docs/design/batching.md +0 -2054
  178. package/docs/design/decode-speed-program.md +0 -2404
  179. package/docs/design/dreaming-nightly-pipeline.md +0 -684
  180. package/docs/design/generic-model-support.md +0 -821
  181. package/docs/design/kv-cache.md +0 -993
  182. package/docs/design/orpo-training.md +0 -680
  183. package/docs/design/speculative-decoding.md +0 -2129
  184. package/docs/design/turboquant.md +0 -2225
  185. package/docs/design/unified-engine-frontier-plan.md +0 -1987
  186. package/docs/design/web-chat-redesign.md +0 -695
  187. package/docs/planning/PRODUCT_ROADMAP.md +0 -593
  188. package/docs/planning/ResearchTopics.md +0 -119
  189. package/docs/planning/public-readiness-handoff.md +0 -244
  190. package/docs/planning/public-readiness.md +0 -149
  191. package/docs/planning/video-series.md +0 -421
  192. package/docs/reference/benchmarks.md +0 -3587
  193. package/docs/reference/cli.md +0 -646
  194. package/docs/reference/distribution.md +0 -380
  195. package/docs/reference/environment.md +0 -494
  196. package/docs/reference/glossary.md +0 -39
  197. package/docs/reference/library-api.md +0 -688
  198. package/docs/reference/memory.md +0 -260
  199. package/docs/reference/models.md +0 -346
  200. package/docs/reference/server-api.md +0 -1945
  201. package/docs/reference/server-config.md +0 -973
  202. package/docs/reference/training.md +0 -462
  203. package/docs/reference/troubleshooting.md +0 -158
  204. package/src/admission-plan.ts +0 -18
  205. package/src/audio/audiotoolbox.ts +0 -112
  206. package/src/audio/conformer.ts +0 -655
  207. package/src/audio/decode.ts +0 -133
  208. package/src/audio/features.ts +0 -202
  209. package/src/audio/mic-capture.ts +0 -98
  210. package/src/audio/silero-vad.ts +0 -379
  211. package/src/audio/transcode.ts +0 -67
  212. package/src/audio/whisper-decode.ts +0 -774
  213. package/src/audio/whisper-fast.ts +0 -732
  214. package/src/audio/whisper-format.ts +0 -73
  215. package/src/audio/whisper-mel.ts +0 -185
  216. package/src/audio/whisper-timing.ts +0 -274
  217. package/src/audio/whisper-tokenizer.ts +0 -239
  218. package/src/audio/whisper-transcribe.ts +0 -410
  219. package/src/backends/mlx/assistant-target.ts +0 -46
  220. package/src/backends/mlx/autoregressive-draft-rows.ts +0 -120
  221. package/src/backends/mlx/autoregressive.ts +0 -129
  222. package/src/backends/mlx/batch-group.ts +0 -1874
  223. package/src/backends/mlx/cache-attachment.ts +0 -67
  224. package/src/backends/mlx/cache-layout.ts +0 -31
  225. package/src/backends/mlx/checkpoint-state.ts +0 -53
  226. package/src/backends/mlx/continuation-persistence.ts +0 -107
  227. package/src/backends/mlx/continuation-request.ts +0 -43
  228. package/src/backends/mlx/continuation.ts +0 -77
  229. package/src/backends/mlx/diffusion.ts +0 -39
  230. package/src/backends/mlx/draft-target.ts +0 -32
  231. package/src/backends/mlx/encoder-cache.ts +0 -25
  232. package/src/backends/mlx/evaluation.ts +0 -105
  233. package/src/backends/mlx/fill-append.ts +0 -58
  234. package/src/backends/mlx/fill-group.ts +0 -497
  235. package/src/backends/mlx/full-kv-row-append.ts +0 -32
  236. package/src/backends/mlx/full-kv-row-donor.ts +0 -54
  237. package/src/backends/mlx/full-transitioning-kv-rows.ts +0 -65
  238. package/src/backends/mlx/gateway-binding.ts +0 -174
  239. package/src/backends/mlx/graph.ts +0 -38
  240. package/src/backends/mlx/kv-codec.ts +0 -9
  241. package/src/backends/mlx/kv-maintenance.ts +0 -161
  242. package/src/backends/mlx/kv-tensor-rows.ts +0 -212
  243. package/src/backends/mlx/memory-client.ts +0 -189
  244. package/src/backends/mlx/methods.ts +0 -90
  245. package/src/backends/mlx/mixed-iteration.ts +0 -62
  246. package/src/backends/mlx/model-prompt.ts +0 -178
  247. package/src/backends/mlx/model-serving.ts +0 -80
  248. package/src/backends/mlx/paged-cache-codec.ts +0 -27
  249. package/src/backends/mlx/prefill-cohort.ts +0 -100
  250. package/src/backends/mlx/prefill-policy.ts +0 -26
  251. package/src/backends/mlx/prefill-rows.ts +0 -244
  252. package/src/backends/mlx/prefill.ts +0 -33
  253. package/src/backends/mlx/projected-context-rows.ts +0 -72
  254. package/src/backends/mlx/prompt-input.ts +0 -29
  255. package/src/backends/mlx/qwen-prompt-input.ts +0 -40
  256. package/src/backends/mlx/request-policy.ts +0 -20
  257. package/src/backends/mlx/request-state-policy.ts +0 -54
  258. package/src/backends/mlx/rollback.ts +0 -92
  259. package/src/backends/mlx/row-sampling.ts +0 -49
  260. package/src/backends/mlx/serial-executor.ts +0 -251
  261. package/src/backends/mlx/speculative-group.ts +0 -438
  262. package/src/backends/mlx/speculative-round.ts +0 -161
  263. package/src/backends/mlx/speculative.ts +0 -131
  264. package/src/backends/mlx/state-rows.ts +0 -104
  265. package/src/backends/mlx/state-views.ts +0 -46
  266. package/src/backends/mlx/target-layout-capability.ts +0 -35
  267. package/src/backends/mlx/text-engine.ts +0 -73
  268. package/src/backends/mlx/transitioning-kv-rows.ts +0 -173
  269. package/src/chat-template.ts +0 -382
  270. package/src/cli.ts +0 -3490
  271. package/src/config.ts +0 -399
  272. package/src/contracts/completion.ts +0 -16
  273. package/src/contracts/execution.ts +0 -70
  274. package/src/contracts/generation.ts +0 -103
  275. package/src/contracts/host.ts +0 -7
  276. package/src/contracts/object-cache.ts +0 -8
  277. package/src/contracts/pi-provider.ts +0 -30
  278. package/src/contracts/pi.ts +0 -261
  279. package/src/contracts/prefix-cache.ts +0 -33
  280. package/src/contracts/resources.ts +0 -25
  281. package/src/contracts/sampling.ts +0 -23
  282. package/src/contracts/scheduling.ts +0 -54
  283. package/src/contracts/tsconfig.json +0 -14
  284. package/src/dataset/generators.ts +0 -1087
  285. package/src/dataset/index.ts +0 -12
  286. package/src/dataset/job.ts +0 -81
  287. package/src/dataset/llm.ts +0 -71
  288. package/src/dataset/registry.ts +0 -528
  289. package/src/diffusion/diffusion-generate.ts +0 -507
  290. package/src/download.ts +0 -505
  291. package/src/embed.ts +0 -77
  292. package/src/engine/admission.ts +0 -59
  293. package/src/engine/cancellation.ts +0 -38
  294. package/src/engine/engine.ts +0 -56
  295. package/src/engine/execution-coordinator.ts +0 -70
  296. package/src/engine/execution-plan.ts +0 -64
  297. package/src/engine/execution-tasks.ts +0 -44
  298. package/src/engine/namespaced-cache.ts +0 -13
  299. package/src/engine/resources.ts +0 -53
  300. package/src/engine/scheduler.ts +0 -92
  301. package/src/engine/session.ts +0 -247
  302. package/src/eval/README.md +0 -130
  303. package/src/eval/ifeval.ts +0 -81
  304. package/src/eval/kl-prompts.ts +0 -29
  305. package/src/eval/kl.ts +0 -590
  306. package/src/eval/perplexity.ts +0 -164
  307. package/src/eval/quality-db.ts +0 -92
  308. package/src/eval/reference-logits.ts +0 -207
  309. package/src/eval/runner.ts +0 -124
  310. package/src/eval/score.ts +0 -49
  311. package/src/eval/tasks/bfcl.ts +0 -535
  312. package/src/eval/tasks/gsm8k.ts +0 -98
  313. package/src/eval/tasks/hashhop.ts +0 -139
  314. package/src/eval/tasks/humaneval.ts +0 -275
  315. package/src/eval/tasks/ifeval.ts +0 -525
  316. package/src/eval/tasks/mmlu.ts +0 -157
  317. package/src/eval/ultrafeedback.ts +0 -60
  318. package/src/evaldb.ts +0 -199
  319. package/src/expert-io.ts +0 -393
  320. package/src/expert-offload-build.ts +0 -77
  321. package/src/expert-offload.ts +0 -76
  322. package/src/expert-residency.ts +0 -1134
  323. package/src/expert-usage.ts +0 -415
  324. package/src/fill/echo-index.ts +0 -188
  325. package/src/fill/fill-session.ts +0 -463
  326. package/src/fill/proposal.ts +0 -68
  327. package/src/fill/schema-rows.ts +0 -506
  328. package/src/fill/tool-boundary.ts +0 -103
  329. package/src/fit.ts +0 -249
  330. package/src/generate.ts +0 -1352
  331. package/src/grammar.ts +0 -604
  332. package/src/harness-pi.ts +0 -184
  333. package/src/hf-push.ts +0 -628
  334. package/src/hub-rest.ts +0 -242
  335. package/src/index.ts +0 -63
  336. package/src/inference/denoising.ts +0 -17
  337. package/src/inference/draft-acceptance.ts +0 -41
  338. package/src/inference/draft-output.ts +0 -49
  339. package/src/inference/graph.ts +0 -33
  340. package/src/inference/prefill.ts +0 -45
  341. package/src/inference/rollback.ts +0 -7
  342. package/src/jobs/index.ts +0 -31
  343. package/src/jobs/job-entry.ts +0 -107
  344. package/src/jobs/task-client.ts +0 -19
  345. package/src/jobs/types.ts +0 -2
  346. package/src/kv-scheme.ts +0 -279
  347. package/src/kv-store.ts +0 -1135
  348. package/src/lab/README.md +0 -22
  349. package/src/lab/curve/curve-designer.html +0 -303
  350. package/src/lab/curve/curve-sampler.ts +0 -122
  351. package/src/lab/expert-trace/expert-trace.ts +0 -69
  352. package/src/lab/paged-kv/paged-attention.ts +0 -117
  353. package/src/lab/paged-kv/paged-kv-rows.ts +0 -111
  354. package/src/lab/paged-kv/paged-kv.ts +0 -336
  355. package/src/library.ts +0 -40
  356. package/src/lora.ts +0 -408
  357. package/src/md-modules.d.ts +0 -54
  358. package/src/media-fetch.ts +0 -442
  359. package/src/memory/article.ts +0 -558
  360. package/src/memory/chunk-validation.ts +0 -150
  361. package/src/memory/chunk.ts +0 -318
  362. package/src/memory/cluster.ts +0 -351
  363. package/src/memory/coverage.ts +0 -134
  364. package/src/memory/crosslink.ts +0 -0
  365. package/src/memory/db.ts +0 -253
  366. package/src/memory/entity.ts +0 -203
  367. package/src/memory/gate.ts +0 -187
  368. package/src/memory/history.ts +0 -152
  369. package/src/memory/ingest.ts +0 -335
  370. package/src/memory/model.ts +0 -183
  371. package/src/memory/normalize.ts +0 -671
  372. package/src/memory/parse.ts +0 -22
  373. package/src/memory/pipeline.ts +0 -275
  374. package/src/memory/prompts.ts +0 -65
  375. package/src/memory/query.ts +0 -334
  376. package/src/memory/reconcile.ts +0 -734
  377. package/src/memory/redirect.ts +0 -108
  378. package/src/memory/reindex.ts +0 -325
  379. package/src/memory/resolve.ts +0 -307
  380. package/src/memory/rest.ts +0 -245
  381. package/src/memory/route.ts +0 -272
  382. package/src/memory/schedule.ts +0 -165
  383. package/src/memory/stages.ts +0 -777
  384. package/src/memory/synthesize.ts +0 -1638
  385. package/src/memory/tools.ts +0 -749
  386. package/src/memory/vault.ts +0 -1194
  387. package/src/memory/wikify.ts +0 -1064
  388. package/src/mlx/array.ts +0 -425
  389. package/src/mlx/autograd.ts +0 -304
  390. package/src/mlx/checkpoint.ts +0 -149
  391. package/src/mlx/compile.ts +0 -168
  392. package/src/mlx/custom-vjp.ts +0 -188
  393. package/src/mlx/ffi.ts +0 -531
  394. package/src/mlx/materialize.ts +0 -23
  395. package/src/mlx/metal-kernel.ts +0 -159
  396. package/src/mlx/normalized-argmax.ts +0 -116
  397. package/src/mlx/ops.ts +0 -1108
  398. package/src/mlx/quantized-rows.ts +0 -36
  399. package/src/mlx/token-bitmask.ts +0 -52
  400. package/src/mlx/turboquant-kv-decode.ts +0 -82
  401. package/src/mlx/turboquant-kv-inverse.ts +0 -122
  402. package/src/mlx/turboquant-ops.ts +0 -861
  403. package/src/mlx/turboquant-tables.ts +0 -237
  404. package/src/mmap.ts +0 -90
  405. package/src/model/artifact-identity.ts +0 -73
  406. package/src/model/batched-kv.ts +0 -235
  407. package/src/model/batched-mask.ts +0 -279
  408. package/src/model/batched-quant.ts +0 -212
  409. package/src/model/batched-quantized-kv.ts +0 -144
  410. package/src/model/batched-rotating-quant.ts +0 -353
  411. package/src/model/batched-rotating-state.ts +0 -149
  412. package/src/model/batched-rotating.ts +0 -338
  413. package/src/model/batched-row-storage.ts +0 -179
  414. package/src/model/batched-ssm.ts +0 -52
  415. package/src/model/batched-turboquant-kv.ts +0 -94
  416. package/src/model/compiled-decode.ts +0 -712
  417. package/src/model/decoded-kv-donor.ts +0 -12
  418. package/src/model/delayed-quantized-kv.ts +0 -72
  419. package/src/model/delayed-rotating-quantized-kv.ts +0 -93
  420. package/src/model/delayed-turboquant-kv.ts +0 -57
  421. package/src/model/diffusion-gemma.ts +0 -1026
  422. package/src/model/factory.ts +0 -215
  423. package/src/model/fingerprint.ts +0 -45
  424. package/src/model/flash-attention.ts +0 -694
  425. package/src/model/full-prefill-padding.ts +0 -56
  426. package/src/model/full-prefill-row.ts +0 -105
  427. package/src/model/gemma4-base.ts +0 -2370
  428. package/src/model/gemma4.ts +0 -1395
  429. package/src/model/generated/gemma4-12b.ts +0 -429
  430. package/src/model/generated/gemma4-26b.ts +0 -448
  431. package/src/model/generated/gemma4-e4b.ts +0 -717
  432. package/src/model/generated/index.ts +0 -18
  433. package/src/model/glm52-atlas.ts +0 -511
  434. package/src/model/glm52-cache.ts +0 -792
  435. package/src/model/glm52-config.ts +0 -262
  436. package/src/model/glm52-container.ts +0 -305
  437. package/src/model/glm52-coupling.ts +0 -388
  438. package/src/model/glm52-dsa.ts +0 -606
  439. package/src/model/glm52-expert-layout.ts +0 -253
  440. package/src/model/glm52-layout.ts +0 -152
  441. package/src/model/glm52-memory.ts +0 -500
  442. package/src/model/glm52-mla.ts +0 -792
  443. package/src/model/glm52-moe.ts +0 -223
  444. package/src/model/glm52-pilot.ts +0 -537
  445. package/src/model/glm52-reference.ts +0 -445
  446. package/src/model/glm52-residency.ts +0 -557
  447. package/src/model/glm52-resident-weights.ts +0 -135
  448. package/src/model/glm52-streamed-experts.ts +0 -453
  449. package/src/model/glm52-streamed-metal.ts +0 -610
  450. package/src/model/glm52-weights.ts +0 -503
  451. package/src/model/glm52.ts +0 -1132
  452. package/src/model/implementation.ts +0 -69
  453. package/src/model/kv-attention-view.ts +0 -70
  454. package/src/model/minicpm5.ts +0 -376
  455. package/src/model/profile.ts +0 -468
  456. package/src/model/quantized-append-attention.ts +0 -31
  457. package/src/model/qwen-append.ts +0 -12
  458. package/src/model/qwen-conv.ts +0 -52
  459. package/src/model/qwen3-delta-state.ts +0 -74
  460. package/src/model/qwen3-delta.ts +0 -451
  461. package/src/model/qwen3-moe.ts +0 -404
  462. package/src/model/qwen3-mrope.ts +0 -250
  463. package/src/model/qwen3.ts +0 -277
  464. package/src/model/qwen3_5-checkpoint.ts +0 -164
  465. package/src/model/qwen3_5.ts +0 -881
  466. package/src/model/rotating-kv-donor.ts +0 -35
  467. package/src/model/rotating-kv-layout.ts +0 -262
  468. package/src/model/rotating-row-transaction.ts +0 -35
  469. package/src/model/speculative-rotating-kv.ts +0 -101
  470. package/src/model/ssm-prefill-padding.ts +0 -39
  471. package/src/model/support.ts +0 -110
  472. package/src/model/token-groups.ts +0 -66
  473. package/src/model/trellis-balanced-scatter.ts +0 -51
  474. package/src/model/trellis-linear.ts +0 -672
  475. package/src/model/trellis-shared-m.ts +0 -151
  476. package/src/model/trellis-shared-scatter.ts +0 -144
  477. package/src/model/trellis-splitk-prefill.ts +0 -158
  478. package/src/model/trellis-tiled-prefill.ts +0 -136
  479. package/src/model/trellis-vector-expand.ts +0 -62
  480. package/src/model/trellis-wide-prefill.ts +0 -94
  481. package/src/model/turboquant-codec.ts +0 -89
  482. package/src/model/universal/archs.ts +0 -332
  483. package/src/model/universal/dense.ts +0 -612
  484. package/src/model/universal/modules.ts +0 -170
  485. package/src/model/universal/rope.ts +0 -381
  486. package/src/model/whisper.ts +0 -435
  487. package/src/native/expert_io.c +0 -523
  488. package/src/native/frame_extract.swift +0 -140
  489. package/src/native/mic_capture.swift +0 -92
  490. package/src/native-pack.ts +0 -163
  491. package/src/pi-provider.ts +0 -53
  492. package/src/pi-session.ts +0 -81
  493. package/src/pi-terminal.ts +0 -274
  494. package/src/pi-web.ts +0 -1940
  495. package/src/preflight.ts +0 -158
  496. package/src/prompt-cache.ts +0 -682
  497. package/src/quantize/allocator.ts +0 -627
  498. package/src/quantize/atomic-output.ts +0 -38
  499. package/src/quantize/calibration.ts +0 -181
  500. package/src/quantize/config-writer.ts +0 -145
  501. package/src/quantize/index.ts +0 -84
  502. package/src/quantize/job.ts +0 -162
  503. package/src/quantize/quantizer.ts +0 -666
  504. package/src/quantize/rotate.ts +0 -603
  505. package/src/quantize/safetensors-writer.ts +0 -249
  506. package/src/quantize/sensitivity.ts +0 -216
  507. package/src/quantize/trellis.ts +0 -586
  508. package/src/quantize/weight-transform.ts +0 -292
  509. package/src/registry.ts +0 -602
  510. package/src/runtime-config.ts +0 -77
  511. package/src/safetensors.ts +0 -165
  512. package/src/sampler.ts +0 -1012
  513. package/src/serve/admin-routes.ts +0 -184
  514. package/src/serve/assets/curve-terrain.html +0 -105
  515. package/src/serve/assets/training-inference-map.html +0 -575
  516. package/src/serve/audio-routes.ts +0 -323
  517. package/src/serve/aux-routes.ts +0 -132
  518. package/src/serve/batch-scheduler.ts +0 -8
  519. package/src/serve/checkpoint-identity.ts +0 -64
  520. package/src/serve/generation-gateway.ts +0 -537
  521. package/src/serve/isolate.ts +0 -609
  522. package/src/serve/kv-budget.ts +0 -14
  523. package/src/serve/lab-routes.ts +0 -341
  524. package/src/serve/lane-registry.ts +0 -45
  525. package/src/serve/model-admin-routes.ts +0 -155
  526. package/src/serve/model-binding.ts +0 -49
  527. package/src/serve/model-host.ts +0 -511
  528. package/src/serve/parent-application.ts +0 -56
  529. package/src/serve/prompt-response-trace.ts +0 -161
  530. package/src/serve/response-lease.ts +0 -24
  531. package/src/serve/session-search.ts +0 -326
  532. package/src/serve/static-routes.ts +0 -101
  533. package/src/serve/transcription-server.ts +0 -64
  534. package/src/serve/transcription-service.ts +0 -502
  535. package/src/server.ts +0 -1282
  536. package/src/spec/assistant-rows.ts +0 -93
  537. package/src/spec/assistant-source.ts +0 -126
  538. package/src/spec/cache-identity.ts +0 -22
  539. package/src/spec/deepspec-rows.ts +0 -29
  540. package/src/spec/deepspec-source.ts +0 -145
  541. package/src/spec/dflash-source.ts +0 -149
  542. package/src/spec/drafter.ts +0 -304
  543. package/src/spec/dspark/ab-stats.ts +0 -136
  544. package/src/spec/dspark/calibration.ts +0 -112
  545. package/src/spec/dspark/data-dflash.ts +0 -156
  546. package/src/spec/dspark/data.ts +0 -201
  547. package/src/spec/dspark/deepspec-module.ts +0 -776
  548. package/src/spec/dspark/generate-dflash.ts +0 -245
  549. package/src/spec/dspark/generate.ts +0 -290
  550. package/src/spec/dspark/loader.ts +0 -23
  551. package/src/spec/dspark/loss.ts +0 -213
  552. package/src/spec/dspark/module-dflash.ts +0 -560
  553. package/src/spec/dspark/module.ts +0 -540
  554. package/src/spec/dspark/quantize-drafter.ts +0 -91
  555. package/src/spec/dspark/sample.ts +0 -112
  556. package/src/spec/generate.ts +0 -276
  557. package/src/spec/glm52-mtp-graph.ts +0 -29
  558. package/src/spec/glm52-mtp-rows.ts +0 -132
  559. package/src/spec/glm52-mtp-source.ts +0 -318
  560. package/src/spec/glm52-mtp-state.ts +0 -33
  561. package/src/spec/ngram-source.ts +0 -226
  562. package/src/spec/projected-draft-rows.ts +0 -73
  563. package/src/spec/qwen-mtp-module.ts +0 -171
  564. package/src/spec/qwen-mtp-rows.ts +0 -230
  565. package/src/spec/qwen-mtp-source.ts +0 -386
  566. package/src/spec/qwen-mtp-state.ts +0 -30
  567. package/src/spec/serve-loop.ts +0 -587
  568. package/src/spec/source.ts +0 -228
  569. package/src/spec/two-model-rows.ts +0 -62
  570. package/src/spec/two-model.ts +0 -113
  571. package/src/ssd-cache.ts +0 -431
  572. package/src/ssd-durability.ts +0 -209
  573. package/src/storage/host-buffer.ts +0 -24
  574. package/src/storage/kv-writer.ts +0 -83
  575. package/src/storage/kv-writer.worker.js +0 -264
  576. package/src/storage/retention-policy.ts +0 -37
  577. package/src/tiered-prompt-cache.ts +0 -45
  578. package/src/tokenizer.ts +0 -335
  579. package/src/tool-approvals.ts +0 -131
  580. package/src/tool-call.ts +0 -695
  581. package/src/train/dataset.ts +0 -484
  582. package/src/train/diffusion-lora.ts +0 -216
  583. package/src/train/export.ts +0 -32
  584. package/src/train/flash-cce.ts +0 -1234
  585. package/src/train/forward.ts +0 -266
  586. package/src/train/fuse.ts +0 -243
  587. package/src/train/index.ts +0 -46
  588. package/src/train/job.ts +0 -205
  589. package/src/train/lora-params.ts +0 -254
  590. package/src/train/loss.ts +0 -1591
  591. package/src/train/merge.ts +0 -195
  592. package/src/train/optimizer.ts +0 -183
  593. package/src/train/prefix-shared.ts +0 -490
  594. package/src/train/rank.ts +0 -137
  595. package/src/train/segmented.ts +0 -1828
  596. package/src/train/steel-qmm-header.ts +0 -1461
  597. package/src/train/trainer.ts +0 -1221
  598. package/src/train/watch.ts +0 -542
  599. package/src/vision/diffusion-vision.ts +0 -620
  600. package/src/vision/embedder.ts +0 -176
  601. package/src/vision/preprocess.ts +0 -247
  602. package/src/vision/prompt.ts +0 -409
  603. package/src/vision/qwen3vl-preprocess.ts +0 -409
  604. package/src/vision/qwen3vl-prompt.ts +0 -233
  605. package/src/vision/qwen3vl-tower.ts +0 -566
  606. package/src/vision/siglip.ts +0 -607
  607. package/src/vision/video-frames.ts +0 -148
  608. package/src/web/app.html +0 -2155
  609. package/src/web/app.js +0 -5863
  610. package/src/web/skills/memory/SKILL.md +0 -120
  611. package/src/web/skills/web-research/SKILL.md +0 -46
  612. package/src/web/skills.ts +0 -97
  613. package/src/web/src/adapters-panel.ts +0 -288
  614. package/src/web/src/assistant.ts +0 -451
  615. package/src/web/src/chat.ts +0 -1060
  616. package/src/web/src/composer.ts +0 -962
  617. package/src/web/src/dataset.ts +0 -132
  618. package/src/web/src/finetune.ts +0 -267
  619. package/src/web/src/hub.ts +0 -428
  620. package/src/web/src/main.ts +0 -98
  621. package/src/web/src/markdown.ts +0 -0
  622. package/src/web/src/memory-panel.ts +0 -572
  623. package/src/web/src/model-picker.ts +0 -159
  624. package/src/web/src/palette.ts +0 -346
  625. package/src/web/src/protocol.ts +0 -26
  626. package/src/web/src/quantize.ts +0 -167
  627. package/src/web/src/rag.ts +0 -274
  628. package/src/web/src/sessions.ts +0 -469
  629. package/src/web/src/shell.ts +0 -804
  630. package/src/web/src/ui-catalog.ts +0 -78
  631. package/src/web/src/voice.ts +0 -141
  632. package/src/web/vendor/README.md +0 -61
  633. package/src/web-assets.ts +0 -47
  634. package/src/web-tools.ts +0 -478
  635. package/src/weights.ts +0 -255
  636. /package/src/{serve → server}/completion-sink.ts +0 -0
  637. /package/src/{serve → server}/generated-token-history.ts +0 -0
  638. /package/src/web/{icon.svg → public/icon.svg} +0 -0
  639. /package/src/web/{manifest.webmanifest → public/manifest.webmanifest} +0 -0
  640. /package/src/web/{vendor → public/vendor}/hljs-LICENSE +0 -0
@@ -1,749 +0,0 @@
1
- // mlx-bun memory — the read tools the local assistant uses to consult your wiki.
2
- //
3
- // These are pi custom tools (defineTool), registered alongside the coding +
4
- // web tools in both front doors (pi-terminal.ts, pi-web.ts). They're read-only,
5
- // so they auto-allow (not in GATED_TOOLS) — consulting your own memory never
6
- // needs an approval gate. They read ~/.mlx-bun/wiki via src/memory/vault.ts +
7
- // the deterministic navigation index in src/memory/query.ts.
8
- //
9
- // The read surface is a deliberate FIND → READ path, never a vector search and
10
- // never an infobox-field filter (the infobox is CONTENT the model reads, not a
11
- // query target — there is NO memory_infobox_query):
12
- //
13
- // memory_resolve (name/alias → the article) ─┐ FIND the article
14
- // memory_category (category/type/series → members) ─┘ deterministically
15
- // memory_read (TOC + lead by default) ─┐ READ it small:
16
- // memory_section (one section's body — THE DEFAULT) ─┘ TOC → one section
17
- // memory_links / memory_infobox (follow the graph / read the infobox)
18
- // memory_search (LAST resort: substring fallback when FIND failed)
19
- //
20
- // Silent-colleague contract (ported from lucien's LUCIEN_INSTRUCTIONS): look the
21
- // article up BEFORE answering; each article is the consolidated current position,
22
- // so read it rather than reconstructing from raw history; then speak as a
23
- // continuation, never "per the wiki…". Knowing *when* to consult is driven by
24
- // these tool descriptions + the bundled memory skill (pi surfaces its description
25
- // and loads the body on demand); the system prompt carries only a one-line
26
- // presence hint (memoryIndexHint), not a title dump.
27
-
28
- import { defineTool, type ToolDefinition } from "@earendil-works/pi-coding-agent";
29
- import { Type } from "typebox";
30
- import {
31
- infoboxFieldValues,
32
- parseInfobox,
33
- parseSeriesBanner,
34
- type Infobox,
35
- } from "./article";
36
- import {
37
- articlesInCategory,
38
- buildMemoryIndex,
39
- resolveName,
40
- type MemoryIndex,
41
- } from "./query";
42
- import { scheduleStatus } from "./schedule";
43
- import {
44
- extractSection,
45
- extractWikilinkTargets,
46
- listArticles,
47
- listReferenceDocs,
48
- parseToc,
49
- readArticle,
50
- resolveWikilinkToStem,
51
- searchArticles,
52
- vaultRoot,
53
- vaultStatus,
54
- type SearchHit,
55
- } from "./vault";
56
-
57
- /** Tool names, exported so the front doors can add them to the allowlist. The
58
- * order is the recommended call order: FIND (resolve/category) → READ (read/
59
- * section) → follow (links/infobox) → reference utilities → search LAST. */
60
- export const MEMORY_TOOL_NAMES = [
61
- "memory_resolve",
62
- "memory_category",
63
- "memory_read",
64
- "memory_section",
65
- "memory_links",
66
- "memory_infobox",
67
- "memory_list",
68
- "memory_status",
69
- "memory_search",
70
- ] as const;
71
-
72
- export const REFERENCE_TOOL_NAMES = [
73
- "reference_search",
74
- "reference_read",
75
- "reference_list",
76
- ] as const;
77
-
78
- const MAX_SEARCH_HITS = 30;
79
- /** memory_search is the demoted fallback: only the strongest few summaries. */
80
- const MAX_MEMORY_SUMMARIES = 8;
81
- /** A whole-article read above this many bytes degrades to TOC+lead+steer. */
82
- const MAX_FULL_READ_BYTES = 8 * 1024;
83
- /** memory_category page size (rows) and per-row lead budget. */
84
- const MAX_CATEGORY_ROWS = 40;
85
- const CATEGORY_LEAD_CHARS = 140;
86
- /** memory_links: cap per origin group before "+N more". */
87
- const MAX_LINKS_PER_GROUP = 25;
88
-
89
- function textResult(text: string): { content: [{ type: "text"; text: string }]; details: Record<string, never> } {
90
- return { content: [{ type: "text", text }], details: {} };
91
- }
92
-
93
- export async function isMemoryEnabled(): Promise<boolean> {
94
- try {
95
- return (await vaultStatus()).exists;
96
- } catch {
97
- return false;
98
- }
99
- }
100
-
101
- function isReferenceId(article: string): boolean {
102
- return article.trim().startsWith("Reference/");
103
- }
104
-
105
- async function memoryUnavailableMessage(): Promise<string | null> {
106
- const st = await vaultStatus();
107
- if (st.exists) return null;
108
- return `Memory is not set up yet at ${st.root}. Run \`mlx-bun memory init\` to create the local Markdown wiki, or ask the user before setting it up.`;
109
- }
110
-
111
- /** Title form of a stem (underscores → spaces). */
112
- function titleOf(stem: string): string {
113
- return stem.replace(/_/g, " ");
114
- }
115
-
116
- /** Casefold + collapse whitespace/underscores (mirrors query.ts/reindex.ts). */
117
- function normalizeAlias(s: string): string {
118
- return s.trim().toLowerCase().replace(/_/g, " ").replace(/\s+/g, " ").trim();
119
- }
120
-
121
- /** Truncate to a budget, marking the cut so callers never silently lose text. */
122
- function clip(text: string, max: number): string {
123
- const t = text.trim();
124
- return t.length <= max ? t : `${t.slice(0, max - 1).trimEnd()}…`;
125
- }
126
-
127
- /** Compact, model-friendly rendering of search hits grouped by relevance. */
128
- function formatSearch(
129
- query: string,
130
- summaries: { article: string; occurrences: number; matched_terms?: string[] }[],
131
- hits: SearchHit[],
132
- opts: { corpusLabel?: string; readTool?: string; maxSummaries?: number } = {},
133
- ): string {
134
- const corpus = opts.corpusLabel ?? "personal-memory articles";
135
- const readTool = opts.readTool ?? "memory_read";
136
- const maxSummaries = opts.maxSummaries ?? 12;
137
- if (summaries.length === 0) return `No ${corpus} match "${query}".`;
138
- const top = summaries.slice(0, maxSummaries);
139
- const lines = [`${corpus[0]!.toUpperCase()}${corpus.slice(1)} matching "${query}" (most relevant first):`, ""];
140
- for (const s of top) {
141
- const terms = s.matched_terms && s.matched_terms.length ? ` [${s.matched_terms.join(", ")}]` : "";
142
- lines.push(`- ${s.article} (${s.occurrences} hit${s.occurrences === 1 ? "" : "s"})${terms}`);
143
- }
144
- if (summaries.length > top.length) lines.push(` …and ${summaries.length - top.length} more.`);
145
- if (hits.length) {
146
- lines.push("", "Sample lines:");
147
- for (const h of hits.slice(0, 8)) {
148
- const where = h.anchor ? `${h.article}#${h.anchor}` : h.article;
149
- lines.push(`- ${where}:${h.line} ${h.excerpt}`);
150
- }
151
- }
152
- lines.push("", `Read a result with ${readTool} (e.g. ${readTool} stem="${top[0]!.article}").`);
153
- return lines.join("\n");
154
- }
155
-
156
- // ---- index access -----------------------------------------------------
157
-
158
- /** Build the (mtime-cached) navigation index over the live vault. */
159
- function index(): MemoryIndex {
160
- return buildMemoryIndex(vaultRoot());
161
- }
162
-
163
- function kindOf(idx: MemoryIndex, stem: string): string {
164
- return idx.infoboxByStem.get(stem)?.entityKind ?? "thing";
165
- }
166
-
167
- function leadOf(idx: MemoryIndex, stem: string): string | null {
168
- return idx.leadByStem.get(stem) ?? null;
169
- }
170
-
171
- // ---- FIND: resolve by name/alias --------------------------------------
172
-
173
- const memoryResolveTool = defineTool({
174
- name: "memory_resolve",
175
- label: "Resolve Memory Article",
176
- description:
177
- "FIND the user's article for a name or alias — the first move when the user names a specific thing, person, project, or topic. " +
178
- "Deterministic alias lookup (no model, no substring search): returns the matched article's stem, title, kind, and lead so you can then read it. " +
179
- "On a miss it offers up to 3 near candidates. Look the article up before answering rather than guessing from raw history.",
180
- parameters: Type.Object({
181
- surface: Type.String({ description: "The name or alias as the user said it (a short form or the way they referred to the thing)." }),
182
- }),
183
- execute: async (_id, params) => {
184
- const surface = params.surface.trim();
185
- if (!surface) return textResult("memory_resolve needs a name or alias.");
186
- try {
187
- const unavailable = await memoryUnavailableMessage();
188
- if (unavailable) return textResult(unavailable);
189
- const idx = index();
190
- const stem = resolveName(idx, surface);
191
- if (stem) {
192
- const lead = leadOf(idx, stem);
193
- return textResult(
194
- [
195
- `${titleOf(stem)} (stem: ${stem}, kind: ${kindOf(idx, stem)})`,
196
- lead ? `\n${clip(lead, 360)}` : "",
197
- `\n\nRead it with memory_read stem="${stem}" (TOC + lead), then memory_section for the part you need.`,
198
- ].join(""),
199
- );
200
- }
201
- // Miss: deterministic token-overlap candidates (no substring, no model).
202
- const qTokens = new Set(normalizeAlias(surface).split(" ").filter(Boolean));
203
- const scored = new Map<string, number>();
204
- for (const [alias, st] of idx.aliasToStem) {
205
- let shared = 0;
206
- for (const tok of alias.split(" ")) if (qTokens.has(tok)) shared++;
207
- if (shared > 0) scored.set(st, Math.max(scored.get(st) ?? 0, shared));
208
- }
209
- const candidates = [...scored.entries()]
210
- .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
211
- .slice(0, 3)
212
- .map(([st]) => st);
213
- if (candidates.length === 0) {
214
- return textResult(`No article resolves "${surface}". Try memory_category to find articles about a topic, or memory_search as a last resort.`);
215
- }
216
- return textResult(
217
- `No exact match for "${surface}". Did you mean one of:\n` +
218
- candidates.map((st) => `- ${titleOf(st)} (stem: ${st})`).join("\n") +
219
- `\n\nResolve one with memory_read, or use memory_category for a topic.`,
220
- );
221
- } catch (err) {
222
- return textResult(`memory_resolve failed: ${err instanceof Error ? err.message : String(err)}`);
223
- }
224
- },
225
- });
226
-
227
- // ---- FIND: articles about a category / type / series ------------------
228
-
229
- const memoryCategoryTool = defineTool({
230
- name: "memory_category",
231
- label: "Articles in Category",
232
- description:
233
- "FIND the articles ABOUT a topic by membership — the \"articles about X\" finder. " +
234
- "Pass exactly one of category, type, or series; returns the member articles as \"stem · lead\" rows. " +
235
- "This is deterministic set membership (declared [[Category:…]] / infobox type / series banner), NOT a search and NOT an infobox-field filter. " +
236
- "Use it to land on the right article, then memory_read its TOC and memory_section the one part you need.",
237
- parameters: Type.Object({
238
- category: Type.Optional(Type.String({ description: "Category name — the grouping declared as [[Category:<Name>]] near the top of member articles." })),
239
- type: Type.Optional(Type.String({ description: "Infobox type label (the article's `type:` field value)." })),
240
- series: Type.Optional(Type.String({ description: "Series name from a *Part of a series on [[X]]* banner." })),
241
- }),
242
- execute: async (_id, params) => {
243
- const category = params.category?.trim();
244
- const type = params.type?.trim();
245
- const series = params.series?.trim();
246
- const picked = [category, type, series].filter((v) => v && v.length > 0);
247
- if (picked.length !== 1) {
248
- return textResult("memory_category needs exactly one of: category, type, or series.");
249
- }
250
- try {
251
- const unavailable = await memoryUnavailableMessage();
252
- if (unavailable) return textResult(unavailable);
253
- const idx = index();
254
- let stems: string[];
255
- let label: string;
256
- if (category) {
257
- stems = articlesInCategory(idx, category);
258
- label = `Category:${category}`;
259
- } else if (type) {
260
- stems = [...(idx.typeToStems.get(type) ?? [])];
261
- label = `type:${type}`;
262
- } else {
263
- stems = [...(idx.seriesToStems.get(series!) ?? [])];
264
- label = `series:${series}`;
265
- }
266
- if (stems.length === 0) return textResult(`No articles in ${label}.`);
267
- const page = stems.slice(0, MAX_CATEGORY_ROWS);
268
- const lines = [`Articles in ${label} (${stems.length}):`, ""];
269
- for (const stem of page) {
270
- const lead = leadOf(idx, stem);
271
- lines.push(lead ? `- ${stem} · ${clip(lead, CATEGORY_LEAD_CHARS)}` : `- ${stem}`);
272
- }
273
- if (stems.length > page.length) lines.push(` …and ${stems.length - page.length} more.`);
274
- lines.push("", "Open one with memory_read, then memory_section for the relevant part.");
275
- return textResult(lines.join("\n"));
276
- } catch (err) {
277
- return textResult(`memory_category failed: ${err instanceof Error ? err.message : String(err)}`);
278
- }
279
- },
280
- });
281
-
282
- // ---- READ: TOC + lead by default; full only on force -------------------
283
-
284
- function tocAndLead(content: string, stem: string, idx: MemoryIndex, note?: string): string {
285
- const lead = leadOf(idx, stem);
286
- const toc = parseToc(content);
287
- const lines = [`${titleOf(stem)} (stem: ${stem})`];
288
- if (lead) lines.push("", clip(lead, 480));
289
- if (note) lines.push("", note);
290
- lines.push("", "Sections:");
291
- if (toc.length === 0) lines.push("- (no headings)");
292
- else for (const h of toc) lines.push(`${" ".repeat(Math.max(0, h.depth - 1))}- ${h.title} (#${h.anchor})`);
293
- lines.push("", `Read the one relevant section with memory_section stem="${stem}" anchor="…". Whole article: memory_read stem="${stem}" force=true.`);
294
- return lines.join("\n");
295
- }
296
-
297
- const memoryReadTool = defineTool({
298
- name: "memory_read",
299
- label: "Read Memory Article",
300
- description:
301
- "Open one article. BY DEFAULT returns its TOC + lead so you can pick the one section you need — small focused reads are the norm, never a whole-article dump. " +
302
- "Pass force=true for the full prose+infobox, but only when you genuinely need the whole article (large articles still degrade to TOC+lead). " +
303
- "The article is the user's consolidated current position on its topic; read it before answering rather than reconstructing from history. " +
304
- "Pass the article stem (underscored, e.g. an \"<Article_Stem>\" filename without .md).",
305
- parameters: Type.Object({
306
- stem: Type.String({ description: "Article stem (underscored filename, no .md — e.g. \"<Article_Stem>\")." }),
307
- force: Type.Optional(Type.Boolean({ description: "Return the FULL article instead of TOC+lead. Use sparingly." })),
308
- }),
309
- execute: async (_id, params) => {
310
- const stem = params.stem.trim();
311
- if (!stem) return textResult("memory_read needs an article stem.");
312
- try {
313
- const unavailable = await memoryUnavailableMessage();
314
- if (unavailable) return textResult(unavailable);
315
- if (isReferenceId(stem)) return textResult("memory_read is for personal-memory articles. Use reference_read for Reference/ documents.");
316
- const { content } = await readArticle(vaultRoot(), stem);
317
- const idx = index();
318
- if (!params.force) return textResult(tocAndLead(content, stem, idx));
319
- const bytes = Buffer.byteLength(content, "utf8");
320
- if (bytes > MAX_FULL_READ_BYTES) {
321
- return textResult(
322
- tocAndLead(content, stem, idx, `(This article is large — ${(bytes / 1024).toFixed(1)} KB. Read just the section you need.)`),
323
- );
324
- }
325
- return textResult(content);
326
- } catch (err) {
327
- return textResult(`${err instanceof Error ? err.message : String(err)} — try memory_resolve or memory_category to find the right article.`);
328
- }
329
- },
330
- });
331
-
332
- const memorySectionTool = defineTool({
333
- name: "memory_section",
334
- label: "Read Memory Section",
335
- description:
336
- "Read ONE section of an article by its heading anchor. This is the DEFAULT read: find the article, scan its TOC with memory_read, then read just the relevant section here — much cheaper than the whole article. " +
337
- "Get anchors from memory_read's TOC.",
338
- parameters: Type.Object({
339
- stem: Type.String({ description: "Article stem (underscored, e.g. \"<Article_Stem>\")." }),
340
- anchor: Type.String({ description: "Heading anchor (the slug of a section heading from memory_read's TOC, e.g. \"<section-anchor>\")." }),
341
- }),
342
- execute: async (_id, params) => {
343
- const stem = params.stem.trim();
344
- const anchor = params.anchor.trim().replace(/^#/, "");
345
- if (!stem) return textResult("memory_section needs an article stem.");
346
- if (!anchor) return textResult("memory_section needs a heading anchor.");
347
- try {
348
- const unavailable = await memoryUnavailableMessage();
349
- if (unavailable) return textResult(unavailable);
350
- if (isReferenceId(stem)) return textResult("memory_section is for personal-memory articles. Use reference_read for Reference/ documents.");
351
- const { content } = await readArticle(vaultRoot(), stem);
352
- const section = extractSection(content, anchor);
353
- if (!section) return textResult(`No section #${anchor} in ${stem}. Use memory_read stem="${stem}" to see the TOC.`);
354
- return textResult(section);
355
- } catch (err) {
356
- return textResult(`${err instanceof Error ? err.message : String(err)} — try memory_resolve or memory_category to find the right article.`);
357
- }
358
- },
359
- });
360
-
361
- // ---- FOLLOW: links grouped by origin ----------------------------------
362
-
363
- const WIKILINK_RE = /\[\[([^\]]+)\]\]/g;
364
-
365
- /** Resolved outbound links grouped by where they appear in the article. Mirrors
366
- * the reindex `via` taxonomy (infobox/series/seealso/prose); red links (no
367
- * existing article) are dropped, matching getArticleLinks. */
368
- function groupedOutbound(content: string, stem: string, stemSet: Set<string>, box: Infobox | null): {
369
- infobox: string[];
370
- series: string[];
371
- seealso: string[];
372
- prose: string[];
373
- } {
374
- const dedupe = (arr: string[]): string[] => [...new Set(arr)].sort((a, b) => a.localeCompare(b));
375
- const resolve = (raw: string): string | null => {
376
- const base = raw.split("|")[0]!.split("#")[0]!.trim();
377
- const r = resolveWikilinkToStem(base, stemSet);
378
- return r && r !== stem ? r : null;
379
- };
380
-
381
- const infobox: string[] = [];
382
- if (box) {
383
- for (const field of box.fields) {
384
- for (const value of infoboxFieldValues(field)) {
385
- WIKILINK_RE.lastIndex = 0;
386
- const m = WIKILINK_RE.exec(value);
387
- if (m) {
388
- const r = resolve(m[1]!);
389
- if (r) infobox.push(r);
390
- }
391
- }
392
- }
393
- }
394
-
395
- const series: string[] = [];
396
- const banner = parseSeriesBanner(content);
397
- if (banner) {
398
- const r = resolve(banner);
399
- if (r) series.push(r);
400
- }
401
-
402
- const seealso: string[] = [];
403
- const prose: string[] = [];
404
- const lines = content.split(/\r?\n/);
405
- let inFence = false;
406
- let section: string | null = null;
407
- for (const line of lines) {
408
- if (/^```/.test(line)) {
409
- inFence = !inFence;
410
- continue;
411
- }
412
- if (inFence) continue;
413
- const hm = /^(#{1,6})\s+(.+)$/.exec(line);
414
- if (hm) {
415
- if (hm[1]!.length >= 2) section = hm[2]!.trim().toLowerCase();
416
- continue;
417
- }
418
- const t = line.trim();
419
- if (/^\*part of a series on \[\[/i.test(t)) continue;
420
- if (/^categories:/i.test(t)) continue;
421
- if (/^\*?\s*main article:/i.test(t)) continue;
422
- WIKILINK_RE.lastIndex = 0;
423
- let m: RegExpExecArray | null;
424
- while ((m = WIKILINK_RE.exec(line)) !== null) {
425
- const base = m[1]!.split("|")[0]!.split("#")[0]!.trim();
426
- if (!base || /^conv:/i.test(base) || /^Category:/i.test(base)) continue;
427
- const r = resolve(base);
428
- if (!r) continue;
429
- if (section === "see also") seealso.push(r);
430
- else prose.push(r);
431
- }
432
- }
433
-
434
- return { infobox: dedupe(infobox), series: dedupe(series), seealso: dedupe(seealso), prose: dedupe(prose) };
435
- }
436
-
437
- const memoryLinksTool = defineTool({
438
- name: "memory_links",
439
- label: "Memory Links",
440
- description:
441
- "Follow the wiki graph: the article's outgoing [[links]] grouped by where they come from (infobox / series / see also / prose), plus inbound backlinks. " +
442
- "Use to hop to a neighbouring article (e.g. from one entity's infobox [[wikilink]] to the linked entity's article) when a topic genuinely spans articles.",
443
- parameters: Type.Object({
444
- stem: Type.String({ description: "Article stem (underscored, e.g. \"<Article_Stem>\")." }),
445
- }),
446
- execute: async (_id, params) => {
447
- const stem = params.stem.trim();
448
- if (!stem) return textResult("memory_links needs an article stem.");
449
- try {
450
- const unavailable = await memoryUnavailableMessage();
451
- if (unavailable) return textResult(unavailable);
452
- if (isReferenceId(stem)) return textResult("memory_links is for personal-memory articles; Reference/ documents are not in the link graph.");
453
- const { content } = await readArticle(vaultRoot(), stem);
454
- const stems = await listArticles(vaultRoot());
455
- const stemSet = new Set(stems);
456
- if (!stemSet.has(stem)) return textResult(`Article not found: ${stem}.`);
457
- const box = parseInfobox(content);
458
- const groups = groupedOutbound(content, stem, stemSet, box);
459
-
460
- // Inbound: who points here (any origin).
461
- const inbound: string[] = [];
462
- for (const other of stems) {
463
- if (other === stem) continue;
464
- try {
465
- const oc = (await readArticle(vaultRoot(), other)).content;
466
- const og = groupedOutbound(oc, other, stemSet, parseInfobox(oc));
467
- if ([...og.infobox, ...og.series, ...og.seealso, ...og.prose].includes(stem)) inbound.push(other);
468
- } catch {
469
- // best-effort
470
- }
471
- }
472
-
473
- const renderGroup = (title: string, arr: string[]): string => {
474
- if (arr.length === 0) return `${title}: (none)`;
475
- const shown = arr.slice(0, MAX_LINKS_PER_GROUP);
476
- const extra = arr.length > shown.length ? ` +${arr.length - shown.length} more` : "";
477
- return `${title}: ${shown.join(", ")}${extra}`;
478
- };
479
- return textResult(
480
- [
481
- `Links for ${stem}:`,
482
- "",
483
- renderGroup("infobox", groups.infobox),
484
- renderGroup("series", groups.series),
485
- renderGroup("see also", groups.seealso),
486
- renderGroup("prose", groups.prose),
487
- renderGroup("inbound", inbound.sort((a, b) => a.localeCompare(b))),
488
- ].join("\n"),
489
- );
490
- } catch (err) {
491
- return textResult(`${err instanceof Error ? err.message : String(err)} — try memory_resolve or memory_category to find the right article.`);
492
- }
493
- },
494
- });
495
-
496
- // ---- READ the infobox as content (NOT a query target) -----------------
497
-
498
- const memoryInfoboxTool = defineTool({
499
- name: "memory_infobox",
500
- label: "Read Memory Infobox",
501
- description:
502
- "Read an article's infobox as key:value CONTENT — the structured facts (the `type:`, `kind:`, relationship, and world-fact fields). " +
503
- "This surfaces facts to READ, not a filter: there is no way to query/sort articles by an infobox field; to find articles use memory_category or memory_resolve.",
504
- parameters: Type.Object({
505
- stem: Type.String({ description: "Article stem (underscored, e.g. \"<Article_Stem>\")." }),
506
- }),
507
- execute: async (_id, params) => {
508
- const stem = params.stem.trim();
509
- if (!stem) return textResult("memory_infobox needs an article stem.");
510
- try {
511
- const unavailable = await memoryUnavailableMessage();
512
- if (unavailable) return textResult(unavailable);
513
- if (isReferenceId(stem)) return textResult("memory_infobox is for personal-memory articles.");
514
- const idx = index();
515
- if (!idx.infoboxByStem.has(stem)) return textResult(`Article not found: ${stem}.`);
516
- const box = idx.infoboxByStem.get(stem) ?? null;
517
- if (!box || box.fields.length === 0) return textResult(`${stem} has no infobox.`);
518
- return textResult(
519
- `Infobox for ${stem} (facts to read, not a filter):\n\n` +
520
- box.fields.map((f) => `${f.key}: ${f.value}`).join("\n"),
521
- );
522
- } catch (err) {
523
- return textResult(`memory_infobox failed: ${err instanceof Error ? err.message : String(err)}`);
524
- }
525
- },
526
- });
527
-
528
- // ---- overview + status ------------------------------------------------
529
-
530
- const memoryListTool = defineTool({
531
- name: "memory_list",
532
- label: "List Memory",
533
- description:
534
- "List the stems of the user's personal-memory articles. An overview/fallback when memory_resolve and memory_category don't surface what you expected — not a first move.",
535
- parameters: Type.Object({}),
536
- execute: async () => {
537
- try {
538
- const unavailable = await memoryUnavailableMessage();
539
- if (unavailable) return textResult(unavailable);
540
- const articles = await listArticles(vaultRoot());
541
- if (articles.length === 0) return textResult("The user's memory has no personal articles yet.");
542
- return textResult(
543
- `${articles.length} personal-memory article(s):\n\n` + articles.map((s) => `- ${s}`).join("\n"),
544
- );
545
- } catch (err) {
546
- return textResult(`memory_list failed: ${err instanceof Error ? err.message : String(err)}`);
547
- }
548
- },
549
- });
550
-
551
- /** Last synthesis-pipeline write to the vault, from its git log (every
552
- * pipeline write commits with a "memory: …" message — synthesize.ts,
553
- * reconcile.ts, wikify.ts, stages.ts). null when the vault has no git repo
554
- * or no synthesis commit yet. */
555
- async function lastSynthesisCommit(root: string): Promise<{ date: string; subject: string } | null> {
556
- try {
557
- const proc = Bun.spawn(
558
- ["git", "log", "-1", "--grep=^memory: ", "--format=%cI\t%s"],
559
- { cwd: root, stdout: "pipe", stderr: "ignore" },
560
- );
561
- const out = (await new Response(proc.stdout).text()).trim();
562
- if ((await proc.exited) !== 0 || !out) return null;
563
- const tab = out.indexOf("\t");
564
- if (tab === -1) return null;
565
- return { date: out.slice(0, tab), subject: out.slice(tab + 1) };
566
- } catch {
567
- return null;
568
- }
569
- }
570
-
571
- const memoryStatusTool = defineTool({
572
- name: "memory_status",
573
- label: "Memory Status",
574
- description:
575
- "Show read-only status for the user's memory: vault path, setup state, article count, git state, last synthesis run, and nightly schedule state. Use when the user asks whether memory is on or where it lives.",
576
- parameters: Type.Object({}),
577
- execute: async () => {
578
- try {
579
- const st = await vaultStatus();
580
- const sched = await scheduleStatus();
581
- const last = st.isGitRepo ? await lastSynthesisCommit(st.root) : null;
582
- const recent = st.recentArticles.length
583
- ? st.recentArticles.slice(0, 5).map((r) => ` - ${r.article} (${new Date(r.mtimeMs).toISOString()})`).join("\n")
584
- : " - (none)";
585
- return textResult([
586
- "Memory status:",
587
- `- vault: ${st.root}`,
588
- `- setup: ${st.exists ? "yes" : "no"}`,
589
- `- articles: ${st.articleCount}`,
590
- `- read-only references: ${st.referenceCount}`,
591
- `- git: ${st.isGitRepo ? "tracked" : "not tracked"}`,
592
- `- last synthesis: ${last ? `${last.date} (${last.subject})` : "no synthesis run recorded yet"}`,
593
- "- synthesis: available — `mlx-bun memory synthesize` runs the full local pipeline (conversations → articles); the nightly job runs it automatically when scheduled",
594
- `- nightly: ${sched.installed ? (sched.loaded ? "scheduled" : "installed but not loaded") : "not scheduled"}`,
595
- sched.installed ? `- launchd plist: ${sched.plistPath}` : "- setup command: mlx-bun memory init",
596
- "- recent changed articles:",
597
- recent,
598
- ].join("\n"));
599
- } catch (err) {
600
- return textResult(`memory_status failed: ${err instanceof Error ? err.message : String(err)}`);
601
- }
602
- },
603
- });
604
-
605
- // ---- search: the demoted last-resort fallback -------------------------
606
-
607
- const memorySearchTool = defineTool({
608
- name: "memory_search",
609
- label: "Search Memory (fallback)",
610
- description:
611
- "LAST-RESORT substring search across memory articles — use ONLY when name/category lookup (memory_resolve, memory_category) has failed across a couple of phrasings. " +
612
- "It does not understand meaning; prefer the deterministic finders first. Returns the top few article matches; follow up with memory_read.",
613
- parameters: Type.Object({
614
- query: Type.String({ description: "Word or phrase to substring-match across memory articles." }),
615
- limit: Type.Optional(Type.Number({ description: `Max sample line-hits to return (default ${MAX_SEARCH_HITS}).` })),
616
- }),
617
- execute: async (_id, params) => {
618
- const query = params.query.trim();
619
- if (!query) return textResult("memory_search needs a non-empty query.");
620
- const limit = Math.max(1, Math.min(MAX_SEARCH_HITS, Math.round(params.limit ?? MAX_SEARCH_HITS)));
621
- try {
622
- const unavailable = await memoryUnavailableMessage();
623
- if (unavailable) return textResult(unavailable);
624
- const { summaries, hits } = await searchArticles(vaultRoot(), query, { limit, scope: "articles" });
625
- return textResult(formatSearch(query, summaries, hits, { maxSummaries: MAX_MEMORY_SUMMARIES }));
626
- } catch (err) {
627
- return textResult(`memory_search failed: ${err instanceof Error ? err.message : String(err)}`);
628
- }
629
- },
630
- });
631
-
632
- // ---- reference docs (separate from personal memory) -------------------
633
-
634
- const referenceSearchTool = defineTool({
635
- name: "reference_search",
636
- label: "Search mlx-bun Reference",
637
- description:
638
- "Search read-only mlx-bun reference documents that are symlinked into the memory vault. " +
639
- "Use for mlx-bun documentation questions when repository files are not enough. This is project reference, not personal memory.",
640
- parameters: Type.Object({
641
- query: Type.String({ description: "Word or phrase to search for across mlx-bun reference documents." }),
642
- limit: Type.Optional(Type.Number({ description: `Max sample line-hits to return (default ${MAX_SEARCH_HITS}).` })),
643
- }),
644
- execute: async (_id, params) => {
645
- const query = params.query.trim();
646
- if (!query) return textResult("reference_search needs a non-empty query.");
647
- const limit = Math.max(1, Math.min(MAX_SEARCH_HITS, Math.round(params.limit ?? MAX_SEARCH_HITS)));
648
- try {
649
- const unavailable = await memoryUnavailableMessage();
650
- if (unavailable) return textResult(unavailable);
651
- const { summaries, hits } = await searchArticles(vaultRoot(), query, { limit, scope: "reference" });
652
- return textResult(formatSearch(query, summaries, hits, { corpusLabel: "read-only reference documents", readTool: "reference_read" }));
653
- } catch (err) {
654
- return textResult(`reference_search failed: ${err instanceof Error ? err.message : String(err)}`);
655
- }
656
- },
657
- });
658
-
659
- const referenceReadTool = defineTool({
660
- name: "reference_read",
661
- label: "Read mlx-bun Reference",
662
- description:
663
- "Read one read-only mlx-bun reference document from the vault's Reference/ namespace. " +
664
- "Pass the id exactly as returned by reference_search or reference_list, e.g. \"Reference/mlx-bun_Server_API\".",
665
- parameters: Type.Object({
666
- article: Type.String({ description: "Reference doc id, e.g. \"Reference/mlx-bun_Server_API\"." }),
667
- }),
668
- execute: async (_id, params) => {
669
- const article = params.article.trim();
670
- if (!article) return textResult("reference_read needs a Reference/... document id.");
671
- try {
672
- const unavailable = await memoryUnavailableMessage();
673
- if (unavailable) return textResult(unavailable);
674
- const id = article.startsWith("Reference/") ? article : `Reference/${article}`;
675
- const { content } = await readArticle(vaultRoot(), id);
676
- return textResult(content);
677
- } catch (err) {
678
- return textResult(`${err instanceof Error ? err.message : String(err)} — try reference_search to find the right reference document.`);
679
- }
680
- },
681
- });
682
-
683
- const referenceListTool = defineTool({
684
- name: "reference_list",
685
- label: "List mlx-bun References",
686
- description: "List read-only mlx-bun reference documents available under the vault's Reference/ namespace.",
687
- parameters: Type.Object({}),
688
- execute: async () => {
689
- try {
690
- const unavailable = await memoryUnavailableMessage();
691
- if (unavailable) return textResult(unavailable);
692
- const refs = await listReferenceDocs(vaultRoot());
693
- if (refs.length === 0) return textResult("No read-only reference documents are linked in the memory vault.");
694
- return textResult(`${refs.length} read-only reference document(s):\n\n` + refs.map((s) => `- ${s}`).join("\n"));
695
- } catch (err) {
696
- return textResult(`reference_list failed: ${err instanceof Error ? err.message : String(err)}`);
697
- }
698
- },
699
- });
700
-
701
- export function createMemoryTools(): ToolDefinition[] {
702
- return [
703
- memoryResolveTool,
704
- memoryCategoryTool,
705
- memoryReadTool,
706
- memorySectionTool,
707
- memoryLinksTool,
708
- memoryInfoboxTool,
709
- memoryListTool,
710
- memoryStatusTool,
711
- memorySearchTool,
712
- ];
713
- }
714
-
715
- export function createReferenceTools(): ToolDefinition[] {
716
- return [referenceSearchTool, referenceReadTool, referenceListTool];
717
- }
718
-
719
- /**
720
- * One gated line for the system prompt: states that memory is ON for this user
721
- * and points at the `memory` skill, plus the FIND→READ order and the
722
- * silent-colleague contract. NOT a title dump and NOT a how-to. pi already
723
- * auto-injects every skill's name+description+location (formatSkillsForPrompt)
724
- * and loads the SKILL.md body on demand, so the skill owns the detailed
725
- * workflow. This hint is intentionally soft: memory is a scoped retrieval
726
- * capability for user-specific continuity, not a default first step for every
727
- * prompt. Returns "" when memory is not turned on (vault absent) so we never
728
- * advertise memory the user hasn't enabled. Runs once at session construction.
729
- */
730
- export async function memoryIndexHint(): Promise<string> {
731
- let st: Awaited<ReturnType<typeof vaultStatus>>;
732
- try {
733
- st = await vaultStatus();
734
- } catch {
735
- return "";
736
- }
737
- if (!st.exists) return ""; // memory not turned on → don't advertise it
738
- const articleCount = st.articleCount > 0 ? `${st.articleCount} article${st.articleCount === 1 ? "" : "s"}` : "no user articles yet";
739
- const refCount = st.referenceCount > 0 ? ` plus ${st.referenceCount} read-only mlx-bun reference doc${st.referenceCount === 1 ? "" : "s"}` : "";
740
- return (
741
- `\n\nThe user's personal memory is on (${articleCount}${refCount}). When the answer depends on user-specific ` +
742
- `continuity or missing personal context, look it up BEFORE answering: FIND the article (memory_resolve a name, ` +
743
- `or memory_category for a topic), open its TOC with memory_read, then memory_section the one relevant part — ` +
744
- `each article is the user's consolidated current position, so read it rather than reconstructing from history. ` +
745
- `Whole-article reads and memory_search are last resorts. Use what you find silently, as a continuation — never ` +
746
- `"per the wiki…". Do not use memory for weather, current public facts, generic web research, or ordinary ` +
747
- `coding/file tasks when the current files are enough. See the \`memory\` skill for the workflow.`
748
- );
749
- }