pi-obsidian-memory 0.0.1 → 0.1.1

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 (572) hide show
  1. package/README.md +237 -7
  2. package/package.json +41 -11
  3. package/skills/obsidian-memory/SKILL.md +101 -0
  4. package/src/domain/capture/constants.ts +5 -0
  5. package/src/domain/capture/index.ts +6 -0
  6. package/src/domain/capture/input-problems.ts +9 -0
  7. package/src/domain/capture/schemas.ts +92 -0
  8. package/src/domain/capture/tally.ts +26 -0
  9. package/src/domain/capture/types.ts +49 -0
  10. package/src/domain/capture/validate.ts +75 -0
  11. package/src/domain/command-flags/constants.ts +141 -0
  12. package/src/domain/command-flags/index.ts +1 -0
  13. package/src/domain/config/change.ts +105 -0
  14. package/src/domain/config/constants.ts +25 -0
  15. package/src/domain/config/diagnostics.ts +35 -0
  16. package/src/domain/config/disclosures.ts +8 -0
  17. package/src/domain/config/fields.ts +7 -0
  18. package/src/domain/config/index.ts +11 -0
  19. package/src/domain/config/inspection.ts +43 -0
  20. package/src/domain/config/invariants.ts +68 -0
  21. package/src/domain/config/legacy-capture.ts +17 -0
  22. package/src/domain/config/observations.ts +109 -0
  23. package/src/domain/config/parse.ts +25 -0
  24. package/src/domain/config/paths.ts +61 -0
  25. package/src/domain/config/registration.ts +34 -0
  26. package/src/domain/config/repair.ts +36 -0
  27. package/src/domain/config/resources.ts +65 -0
  28. package/src/domain/config/rules.ts +49 -0
  29. package/src/domain/config/schemas.ts +155 -0
  30. package/src/domain/config/settings.ts +23 -0
  31. package/src/domain/config/types.ts +239 -0
  32. package/src/domain/decision-model/constants.ts +7 -0
  33. package/src/domain/decision-model/cutoffs.ts +8 -0
  34. package/src/domain/decision-model/endpoint.ts +11 -0
  35. package/src/domain/decision-model/failure-detail.ts +8 -0
  36. package/src/domain/decision-model/index.ts +6 -0
  37. package/src/domain/decision-model/rank.ts +36 -0
  38. package/src/domain/decision-model/types.ts +77 -0
  39. package/src/domain/embeddings/constants.ts +55 -0
  40. package/src/domain/embeddings/identity.ts +30 -0
  41. package/src/domain/embeddings/index.ts +5 -0
  42. package/src/domain/embeddings/schemas.ts +25 -0
  43. package/src/domain/embeddings/types.ts +52 -0
  44. package/src/domain/embeddings/vectors.ts +53 -0
  45. package/src/domain/folder-index/constants.ts +9 -0
  46. package/src/domain/folder-index/display.ts +22 -0
  47. package/src/domain/folder-index/index.ts +5 -0
  48. package/src/domain/folder-index/listing.ts +58 -0
  49. package/src/domain/folder-index/render.ts +114 -0
  50. package/src/domain/folder-index/types.ts +41 -0
  51. package/src/domain/index.ts +22 -0
  52. package/src/domain/lifecycle/index.ts +2 -0
  53. package/src/domain/lifecycle/lifecycle.ts +39 -0
  54. package/src/domain/lifecycle/types.ts +17 -0
  55. package/src/domain/loaded-memory/budget.ts +14 -0
  56. package/src/domain/loaded-memory/constants.ts +9 -0
  57. package/src/domain/loaded-memory/index.ts +4 -0
  58. package/src/domain/loaded-memory/render.ts +30 -0
  59. package/src/domain/loaded-memory/types.ts +19 -0
  60. package/src/domain/memory/draft.ts +12 -0
  61. package/src/domain/memory/index.ts +4 -0
  62. package/src/domain/memory/schemas.ts +15 -0
  63. package/src/domain/memory/target.ts +27 -0
  64. package/src/domain/memory/types.ts +20 -0
  65. package/src/domain/memory-agent/index.ts +5 -0
  66. package/src/domain/memory-agent/input-problems.ts +9 -0
  67. package/src/domain/memory-agent/refusal.ts +6 -0
  68. package/src/domain/memory-agent/schemas.ts +112 -0
  69. package/src/domain/memory-agent/types.ts +25 -0
  70. package/src/domain/memory-agent/validate.ts +67 -0
  71. package/src/domain/names/constants.ts +32 -0
  72. package/src/domain/names/index.ts +2 -0
  73. package/src/domain/names/names.ts +83 -0
  74. package/src/domain/note/check.ts +68 -0
  75. package/src/domain/note/constants.ts +15 -0
  76. package/src/domain/note/frontmatter-fields.ts +175 -0
  77. package/src/domain/note/frontmatter.ts +138 -0
  78. package/src/domain/note/index.ts +9 -0
  79. package/src/domain/note/parse.ts +41 -0
  80. package/src/domain/note/render.ts +27 -0
  81. package/src/domain/note/schema-errors.ts +41 -0
  82. package/src/domain/note/schemas.ts +38 -0
  83. package/src/domain/note/types.ts +53 -0
  84. package/src/domain/note/validate.ts +19 -0
  85. package/src/domain/path-platform/index.ts +2 -0
  86. package/src/domain/path-platform/path-module.ts +11 -0
  87. package/src/domain/path-platform/types.ts +1 -0
  88. package/src/domain/search-catalog/constants.ts +1 -0
  89. package/src/domain/search-catalog/coverage.ts +35 -0
  90. package/src/domain/search-catalog/dont-forget.ts +10 -0
  91. package/src/domain/search-catalog/fingerprint.ts +9 -0
  92. package/src/domain/search-catalog/index.ts +10 -0
  93. package/src/domain/search-catalog/inspection.ts +47 -0
  94. package/src/domain/search-catalog/plan.ts +68 -0
  95. package/src/domain/search-catalog/ranking.ts +27 -0
  96. package/src/domain/search-catalog/schemas.ts +49 -0
  97. package/src/domain/search-catalog/types.ts +103 -0
  98. package/src/domain/search-catalog/vector-refresh.ts +22 -0
  99. package/src/domain/shell-edit/command-segments.ts +28 -0
  100. package/src/domain/shell-edit/command-words.ts +22 -0
  101. package/src/domain/shell-edit/constants.ts +125 -0
  102. package/src/domain/shell-edit/executed-files.ts +154 -0
  103. package/src/domain/shell-edit/index.ts +6 -0
  104. package/src/domain/shell-edit/powershell-files.ts +38 -0
  105. package/src/domain/shell-edit/rules.ts +19 -0
  106. package/src/domain/shell-edit/types.ts +75 -0
  107. package/src/domain/tool-flags/constants.ts +178 -0
  108. package/src/domain/tool-flags/index.ts +2 -0
  109. package/src/domain/tool-flags/types.ts +7 -0
  110. package/src/domain/validation/constants.ts +1 -0
  111. package/src/domain/validation/describe.ts +137 -0
  112. package/src/domain/validation/index.ts +3 -0
  113. package/src/domain/validation/types.ts +3 -0
  114. package/src/domain/vault-access/absolute-candidate.ts +81 -0
  115. package/src/domain/vault-access/argument-tokens.ts +22 -0
  116. package/src/domain/vault-access/command-mentions-vault.ts +115 -0
  117. package/src/domain/vault-access/constants.ts +54 -0
  118. package/src/domain/vault-access/index.ts +7 -0
  119. package/src/domain/vault-access/types.ts +18 -0
  120. package/src/domain/vault-access/vault-access-refusal.ts +36 -0
  121. package/src/domain/vault-access/vault-location.ts +22 -0
  122. package/src/domain/vault-assets/index.ts +2 -0
  123. package/src/domain/vault-assets/render.ts +51 -0
  124. package/src/domain/vault-assets/types.ts +36 -0
  125. package/src/domain/vault-catalog/analyze.ts +37 -0
  126. package/src/domain/vault-catalog/classify.ts +37 -0
  127. package/src/domain/vault-catalog/dont-forget.ts +6 -0
  128. package/src/domain/vault-catalog/export-entries.ts +10 -0
  129. package/src/domain/vault-catalog/index.ts +5 -0
  130. package/src/domain/vault-catalog/types.ts +114 -0
  131. package/src/domain/vault-diagnosis/diagnose.ts +79 -0
  132. package/src/domain/vault-diagnosis/index.ts +2 -0
  133. package/src/domain/vault-diagnosis/types.ts +31 -0
  134. package/src/domain/vault-path/constants.ts +13 -0
  135. package/src/domain/vault-path/index.ts +2 -0
  136. package/src/domain/vault-path/vault-path.ts +65 -0
  137. package/src/pi/capture/cadence.ts +49 -0
  138. package/src/pi/capture/completion.ts +26 -0
  139. package/src/pi/capture/constants.ts +5 -0
  140. package/src/pi/capture/handlers.ts +30 -0
  141. package/src/pi/capture/index.ts +8 -0
  142. package/src/pi/capture/runtime.ts +83 -0
  143. package/src/pi/capture/schemas.ts +8 -0
  144. package/src/pi/capture/tool-calls.ts +6 -0
  145. package/src/pi/capture/transcript.ts +55 -0
  146. package/src/pi/capture/types.ts +46 -0
  147. package/src/pi/change-report/constants.ts +15 -0
  148. package/src/pi/change-report/index.ts +3 -0
  149. package/src/pi/change-report/report.ts +54 -0
  150. package/src/pi/change-report/types.ts +8 -0
  151. package/src/pi/context/constants.ts +5 -0
  152. package/src/pi/context/index.ts +3 -0
  153. package/src/pi/context/status.ts +15 -0
  154. package/src/pi/context/types.ts +98 -0
  155. package/src/pi/extension.ts +100 -0
  156. package/src/pi/index.ts +26 -0
  157. package/src/pi/memory-add/constants.ts +13 -0
  158. package/src/pi/memory-add/index.ts +5 -0
  159. package/src/pi/memory-add/memory-add.ts +31 -0
  160. package/src/pi/memory-add/respond.ts +55 -0
  161. package/src/pi/memory-add/schemas.ts +29 -0
  162. package/src/pi/memory-add/types.ts +15 -0
  163. package/src/pi/memory-archive/constants.ts +8 -0
  164. package/src/pi/memory-archive/index.ts +4 -0
  165. package/src/pi/memory-archive/memory-archive.ts +29 -0
  166. package/src/pi/memory-archive/schemas.ts +15 -0
  167. package/src/pi/memory-archive/types.ts +8 -0
  168. package/src/pi/memory-block/block.ts +75 -0
  169. package/src/pi/memory-block/constants.ts +24 -0
  170. package/src/pi/memory-block/index.ts +4 -0
  171. package/src/pi/memory-block/render.ts +54 -0
  172. package/src/pi/memory-block/types.ts +24 -0
  173. package/src/pi/memory-doctor/constants.ts +43 -0
  174. package/src/pi/memory-doctor/index.ts +4 -0
  175. package/src/pi/memory-doctor/memory-doctor.ts +135 -0
  176. package/src/pi/memory-doctor/report.ts +101 -0
  177. package/src/pi/memory-doctor/types.ts +13 -0
  178. package/src/pi/memory-export/constants.ts +15 -0
  179. package/src/pi/memory-export/index.ts +4 -0
  180. package/src/pi/memory-export/memory-export.ts +57 -0
  181. package/src/pi/memory-export/name.ts +9 -0
  182. package/src/pi/memory-export/types.ts +4 -0
  183. package/src/pi/memory-get/constants.ts +12 -0
  184. package/src/pi/memory-get/index.ts +5 -0
  185. package/src/pi/memory-get/memory-get.ts +23 -0
  186. package/src/pi/memory-get/respond.ts +38 -0
  187. package/src/pi/memory-get/schemas.ts +13 -0
  188. package/src/pi/memory-get/types.ts +10 -0
  189. package/src/pi/memory-init/constants.ts +17 -0
  190. package/src/pi/memory-init/index.ts +2 -0
  191. package/src/pi/memory-init/memory-init.ts +63 -0
  192. package/src/pi/memory-search/constants.ts +16 -0
  193. package/src/pi/memory-search/index.ts +5 -0
  194. package/src/pi/memory-search/memory-search.ts +22 -0
  195. package/src/pi/memory-search/respond.ts +62 -0
  196. package/src/pi/memory-search/schemas.ts +11 -0
  197. package/src/pi/memory-search/types.ts +10 -0
  198. package/src/pi/memory-session/constants.ts +7 -0
  199. package/src/pi/memory-session/index.ts +4 -0
  200. package/src/pi/memory-session/keeper.ts +101 -0
  201. package/src/pi/memory-session/respond.ts +6 -0
  202. package/src/pi/memory-session/types.ts +23 -0
  203. package/src/pi/memory-settings/constants.ts +69 -0
  204. package/src/pi/memory-settings/edits.ts +46 -0
  205. package/src/pi/memory-settings/index.ts +9 -0
  206. package/src/pi/memory-settings/lines.ts +119 -0
  207. package/src/pi/memory-settings/models.ts +81 -0
  208. package/src/pi/memory-settings/projects.ts +46 -0
  209. package/src/pi/memory-settings/providers.ts +77 -0
  210. package/src/pi/memory-settings/save.ts +16 -0
  211. package/src/pi/memory-settings/screen.ts +27 -0
  212. package/src/pi/memory-settings/types.ts +87 -0
  213. package/src/pi/memory-setup/constants.ts +33 -0
  214. package/src/pi/memory-setup/disclosure.ts +22 -0
  215. package/src/pi/memory-setup/index.ts +4 -0
  216. package/src/pi/memory-setup/memory-setup.ts +153 -0
  217. package/src/pi/memory-setup/types.ts +6 -0
  218. package/src/pi/memory-succeed/constants.ts +10 -0
  219. package/src/pi/memory-succeed/index.ts +4 -0
  220. package/src/pi/memory-succeed/memory-succeed.ts +34 -0
  221. package/src/pi/memory-succeed/schemas.ts +30 -0
  222. package/src/pi/memory-succeed/types.ts +8 -0
  223. package/src/pi/memory-update/constants.ts +8 -0
  224. package/src/pi/memory-update/index.ts +4 -0
  225. package/src/pi/memory-update/memory-update.ts +29 -0
  226. package/src/pi/memory-update/schemas.ts +24 -0
  227. package/src/pi/memory-update/types.ts +8 -0
  228. package/src/pi/paths/constants.ts +7 -0
  229. package/src/pi/paths/index.ts +2 -0
  230. package/src/pi/paths/paths.ts +15 -0
  231. package/src/pi/paths/platform.ts +7 -0
  232. package/src/pi/registrar.ts +25 -0
  233. package/src/pi/registration-report/constants.ts +13 -0
  234. package/src/pi/registration-report/index.ts +2 -0
  235. package/src/pi/registration-report/report.ts +26 -0
  236. package/src/pi/relevant-memory/constants.ts +3 -0
  237. package/src/pi/relevant-memory/index.ts +4 -0
  238. package/src/pi/relevant-memory/prompt.ts +23 -0
  239. package/src/pi/relevant-memory/runtime.ts +88 -0
  240. package/src/pi/relevant-memory/types.ts +14 -0
  241. package/src/pi/semantic/constants.ts +3 -0
  242. package/src/pi/semantic/index.ts +2 -0
  243. package/src/pi/semantic/runtime.ts +59 -0
  244. package/src/pi/session-start/constants.ts +7 -0
  245. package/src/pi/session-start/index.ts +3 -0
  246. package/src/pi/session-start/session-start.ts +48 -0
  247. package/src/pi/session-start/types.ts +5 -0
  248. package/src/pi/shell-edit-guard/guard.ts +41 -0
  249. package/src/pi/shell-edit-guard/index.ts +3 -0
  250. package/src/pi/shell-edit-guard/prompt.ts +30 -0
  251. package/src/pi/shell-edit-guard/types.ts +13 -0
  252. package/src/pi/types.ts +44 -0
  253. package/src/pi/vault-guard/constants.ts +1 -0
  254. package/src/pi/vault-guard/index.ts +4 -0
  255. package/src/pi/vault-guard/request.ts +39 -0
  256. package/src/pi/vault-guard/types.ts +5 -0
  257. package/src/pi/vault-guard/vault-guard.ts +21 -0
  258. package/src/services/capture-cadence/domain-rules.ts +8 -0
  259. package/src/services/capture-cadence/index.ts +1 -0
  260. package/src/services/clock/clock.ts +7 -0
  261. package/src/services/clock/index.ts +1 -0
  262. package/src/services/config/canonicalize.ts +163 -0
  263. package/src/services/config/constants.ts +1 -0
  264. package/src/services/config/fully-qualified-path.ts +14 -0
  265. package/src/services/config/index.ts +12 -0
  266. package/src/services/config/path-identity.ts +65 -0
  267. package/src/services/config/publication.ts +75 -0
  268. package/src/services/config/read.ts +47 -0
  269. package/src/services/config/registration.ts +26 -0
  270. package/src/services/config/resolve-input.ts +27 -0
  271. package/src/services/config/snapshot.ts +26 -0
  272. package/src/services/config/target.ts +2 -0
  273. package/src/services/config/types.ts +97 -0
  274. package/src/services/config/vault-access.ts +2 -0
  275. package/src/services/config/volume-namespace.ts +5 -0
  276. package/src/services/config/write.ts +63 -0
  277. package/src/services/decision-model/constants.ts +16 -0
  278. package/src/services/decision-model/decide.ts +42 -0
  279. package/src/services/decision-model/diagnostics.ts +6 -0
  280. package/src/services/decision-model/endpoint.ts +1 -0
  281. package/src/services/decision-model/failure-detail.ts +1 -0
  282. package/src/services/decision-model/index.ts +7 -0
  283. package/src/services/decision-model/interruption.ts +29 -0
  284. package/src/services/decision-model/jev.ts +61 -0
  285. package/src/services/decision-model/laya-batch.ts +64 -0
  286. package/src/services/decision-model/laya-http-failure.ts +41 -0
  287. package/src/services/decision-model/laya-response.ts +95 -0
  288. package/src/services/decision-model/laya.ts +35 -0
  289. package/src/services/decision-model/preflight.ts +24 -0
  290. package/src/services/decision-model/prompts.ts +36 -0
  291. package/src/services/decision-model/schemas.ts +43 -0
  292. package/src/services/decision-model/score-candidates.ts +41 -0
  293. package/src/services/decision-model/types.ts +182 -0
  294. package/src/services/embeddings/asset-download.ts +45 -0
  295. package/src/services/embeddings/asset-fetch.ts +39 -0
  296. package/src/services/embeddings/asset-inspection.ts +36 -0
  297. package/src/services/embeddings/batch.ts +32 -0
  298. package/src/services/embeddings/chunks.ts +80 -0
  299. package/src/services/embeddings/configuration.ts +8 -0
  300. package/src/services/embeddings/constants.ts +24 -0
  301. package/src/services/embeddings/errors.ts +11 -0
  302. package/src/services/embeddings/google.ts +90 -0
  303. package/src/services/embeddings/http.ts +64 -0
  304. package/src/services/embeddings/index.ts +17 -0
  305. package/src/services/embeddings/inference.ts +35 -0
  306. package/src/services/embeddings/local.ts +138 -0
  307. package/src/services/embeddings/model-asset.ts +68 -0
  308. package/src/services/embeddings/model-cache.ts +30 -0
  309. package/src/services/embeddings/openai.ts +64 -0
  310. package/src/services/embeddings/operation.ts +31 -0
  311. package/src/services/embeddings/responses.ts +41 -0
  312. package/src/services/embeddings/runtime.ts +13 -0
  313. package/src/services/embeddings/schemas.ts +53 -0
  314. package/src/services/embeddings/types.ts +116 -0
  315. package/src/services/id/id.ts +5 -0
  316. package/src/services/id/index.ts +1 -0
  317. package/src/services/index.ts +11 -0
  318. package/src/services/llm/capture.ts +19 -0
  319. package/src/services/llm/check-chat-models.ts +38 -0
  320. package/src/services/llm/complete.ts +57 -0
  321. package/src/services/llm/constants.ts +32 -0
  322. package/src/services/llm/domain-rules.ts +2 -0
  323. package/src/services/llm/index.ts +6 -0
  324. package/src/services/llm/lifetime.ts +16 -0
  325. package/src/services/llm/retrieve.ts +19 -0
  326. package/src/services/llm/schemas.ts +9 -0
  327. package/src/services/llm/types.ts +94 -0
  328. package/src/services/search-index/catalog-query.ts +34 -0
  329. package/src/services/search-index/catalog-statements.ts +33 -0
  330. package/src/services/search-index/catalog.ts +19 -0
  331. package/src/services/search-index/cleanup.ts +13 -0
  332. package/src/services/search-index/close.ts +5 -0
  333. package/src/services/search-index/constants.ts +102 -0
  334. package/src/services/search-index/dont-forget.ts +1 -0
  335. package/src/services/search-index/fingerprint.ts +17 -0
  336. package/src/services/search-index/folder-index-statements.ts +17 -0
  337. package/src/services/search-index/folder-index-storage.ts +54 -0
  338. package/src/services/search-index/folder-indexes.ts +13 -0
  339. package/src/services/search-index/index.ts +14 -0
  340. package/src/services/search-index/inspection.ts +1 -0
  341. package/src/services/search-index/inventory.ts +67 -0
  342. package/src/services/search-index/legacy.ts +64 -0
  343. package/src/services/search-index/location.ts +12 -0
  344. package/src/services/search-index/open.ts +46 -0
  345. package/src/services/search-index/query.ts +39 -0
  346. package/src/services/search-index/ranking.ts +12 -0
  347. package/src/services/search-index/reconcile.ts +93 -0
  348. package/src/services/search-index/recovery.ts +56 -0
  349. package/src/services/search-index/refusals.ts +21 -0
  350. package/src/services/search-index/schema.ts +42 -0
  351. package/src/services/search-index/schemas.ts +181 -0
  352. package/src/services/search-index/search.ts +5 -0
  353. package/src/services/search-index/statements.ts +18 -0
  354. package/src/services/search-index/storage.ts +207 -0
  355. package/src/services/search-index/types.ts +113 -0
  356. package/src/services/search-index/vector-statements.ts +18 -0
  357. package/src/services/search-index/vector-storage.ts +169 -0
  358. package/src/services/search-index/vectors.ts +18 -0
  359. package/src/services/search-index/write.ts +9 -0
  360. package/src/services/shell-edit/ask.ts +53 -0
  361. package/src/services/shell-edit/domain-rules.ts +2 -0
  362. package/src/services/shell-edit/index.ts +4 -0
  363. package/src/services/shell-edit/schemas.ts +23 -0
  364. package/src/services/shell-edit/types.ts +61 -0
  365. package/src/services/shell-scripts/constants.ts +1 -0
  366. package/src/services/shell-scripts/files.ts +16 -0
  367. package/src/services/shell-scripts/index.ts +5 -0
  368. package/src/services/shell-scripts/package-scripts.ts +74 -0
  369. package/src/services/shell-scripts/schemas.ts +3 -0
  370. package/src/services/shell-scripts/scripts.ts +27 -0
  371. package/src/services/shell-scripts/types.ts +11 -0
  372. package/src/services/vault/archive.ts +31 -0
  373. package/src/services/vault/bootstrap/ensure.ts +50 -0
  374. package/src/services/vault/bootstrap/index.ts +2 -0
  375. package/src/services/vault/bootstrap/paths.ts +57 -0
  376. package/src/services/vault/bootstrap/types.ts +17 -0
  377. package/src/services/vault/bootstrap/write.ts +47 -0
  378. package/src/services/vault/catalog/bytes.ts +51 -0
  379. package/src/services/vault/catalog/dont-forget.ts +1 -0
  380. package/src/services/vault/catalog/enumerate.ts +69 -0
  381. package/src/services/vault/catalog/export.ts +21 -0
  382. package/src/services/vault/catalog/failures.ts +16 -0
  383. package/src/services/vault/catalog/index.ts +10 -0
  384. package/src/services/vault/catalog/inspect.ts +41 -0
  385. package/src/services/vault/catalog/observe.ts +35 -0
  386. package/src/services/vault/catalog/resolve.ts +94 -0
  387. package/src/services/vault/catalog/stat.ts +23 -0
  388. package/src/services/vault/catalog/types.ts +69 -0
  389. package/src/services/vault/catalog/visit.ts +58 -0
  390. package/src/services/vault/complete-blank.ts +66 -0
  391. package/src/services/vault/constants.ts +3 -0
  392. package/src/services/vault/context/index.ts +1 -0
  393. package/src/services/vault/context/types.ts +10 -0
  394. package/src/services/vault/create.ts +19 -0
  395. package/src/services/vault/display.ts +6 -0
  396. package/src/services/vault/domain-rules.ts +10 -0
  397. package/src/services/vault/draft.ts +2 -0
  398. package/src/services/vault/filesystem/failures.ts +53 -0
  399. package/src/services/vault/filesystem/hash.ts +5 -0
  400. package/src/services/vault/filesystem/index.ts +5 -0
  401. package/src/services/vault/filesystem/read.ts +61 -0
  402. package/src/services/vault/filesystem/types.ts +36 -0
  403. package/src/services/vault/filesystem/write.ts +80 -0
  404. package/src/services/vault/find.ts +27 -0
  405. package/src/services/vault/folder-contents.ts +31 -0
  406. package/src/services/vault/folder-index/index.ts +2 -0
  407. package/src/services/vault/folder-index/read.ts +87 -0
  408. package/src/services/vault/folder-index/types.ts +19 -0
  409. package/src/services/vault/folder-listing.ts +1 -0
  410. package/src/services/vault/index.ts +21 -0
  411. package/src/services/vault/inspect-folder.ts +13 -0
  412. package/src/services/vault/list.ts +121 -0
  413. package/src/services/vault/memory-folder.ts +24 -0
  414. package/src/services/vault/paths.ts +11 -0
  415. package/src/services/vault/publish.ts +52 -0
  416. package/src/services/vault/read.ts +46 -0
  417. package/src/services/vault/refresh-folders.ts +197 -0
  418. package/src/services/vault/refresh-plan.ts +79 -0
  419. package/src/services/vault/refresh.ts +8 -0
  420. package/src/services/vault/refusals.ts +23 -0
  421. package/src/services/vault/relocate.ts +131 -0
  422. package/src/services/vault/relocation-checks.ts +89 -0
  423. package/src/services/vault/resolve-stored-file.ts +43 -0
  424. package/src/services/vault/resolve.ts +109 -0
  425. package/src/services/vault/succeed.ts +45 -0
  426. package/src/services/vault/types.ts +199 -0
  427. package/src/services/vault/update-file.ts +58 -0
  428. package/src/services/vault/update.ts +22 -0
  429. package/src/services/vault/write-new-file.ts +37 -0
  430. package/src/shared/index.ts +1 -0
  431. package/src/shared/result/index.ts +1 -0
  432. package/src/shared/result/types.ts +17 -0
  433. package/src/usecases/add-memory/add-memory.ts +83 -0
  434. package/src/usecases/add-memory/index.ts +4 -0
  435. package/src/usecases/add-memory/maintenance.ts +23 -0
  436. package/src/usecases/add-memory/schemas.ts +12 -0
  437. package/src/usecases/add-memory/types.ts +47 -0
  438. package/src/usecases/archive-memory/archive-memory.ts +27 -0
  439. package/src/usecases/archive-memory/index.ts +3 -0
  440. package/src/usecases/archive-memory/schemas.ts +11 -0
  441. package/src/usecases/archive-memory/types.ts +17 -0
  442. package/src/usecases/capture-memory/apply.ts +73 -0
  443. package/src/usecases/capture-memory/capture-memory.ts +117 -0
  444. package/src/usecases/capture-memory/constants.ts +15 -0
  445. package/src/usecases/capture-memory/index.ts +5 -0
  446. package/src/usecases/capture-memory/observe.ts +122 -0
  447. package/src/usecases/capture-memory/settings.ts +20 -0
  448. package/src/usecases/capture-memory/types.ts +103 -0
  449. package/src/usecases/check-shell-edit/check-shell-edit.ts +28 -0
  450. package/src/usecases/check-shell-edit/index.ts +2 -0
  451. package/src/usecases/check-shell-edit/types.ts +30 -0
  452. package/src/usecases/check-vault-access/check-vault-access.ts +23 -0
  453. package/src/usecases/check-vault-access/constants.ts +7 -0
  454. package/src/usecases/check-vault-access/index.ts +4 -0
  455. package/src/usecases/check-vault-access/raw-device.ts +10 -0
  456. package/src/usecases/check-vault-access/targets.ts +49 -0
  457. package/src/usecases/check-vault-access/types.ts +33 -0
  458. package/src/usecases/complete-blank-memory/complete-blank-memory.ts +48 -0
  459. package/src/usecases/complete-blank-memory/constants.ts +3 -0
  460. package/src/usecases/complete-blank-memory/index.ts +4 -0
  461. package/src/usecases/complete-blank-memory/schemas.ts +14 -0
  462. package/src/usecases/complete-blank-memory/types.ts +28 -0
  463. package/src/usecases/diagnose-memory/constants.ts +3 -0
  464. package/src/usecases/diagnose-memory/decision.ts +36 -0
  465. package/src/usecases/diagnose-memory/diagnose-memory.ts +52 -0
  466. package/src/usecases/diagnose-memory/embeddings.ts +39 -0
  467. package/src/usecases/diagnose-memory/index.ts +5 -0
  468. package/src/usecases/diagnose-memory/types.ts +86 -0
  469. package/src/usecases/diagnose-memory/vault.ts +33 -0
  470. package/src/usecases/export-memory/collect.ts +20 -0
  471. package/src/usecases/export-memory/constants.ts +3 -0
  472. package/src/usecases/export-memory/export-memory.ts +84 -0
  473. package/src/usecases/export-memory/index.ts +3 -0
  474. package/src/usecases/export-memory/types.ts +28 -0
  475. package/src/usecases/get-memory/get-memory.ts +97 -0
  476. package/src/usecases/get-memory/index.ts +2 -0
  477. package/src/usecases/get-memory/types.ts +25 -0
  478. package/src/usecases/index.ts +25 -0
  479. package/src/usecases/list-memory/index.ts +2 -0
  480. package/src/usecases/list-memory/leased/index.ts +2 -0
  481. package/src/usecases/list-memory/leased/read.ts +16 -0
  482. package/src/usecases/list-memory/leased/types.ts +21 -0
  483. package/src/usecases/list-memory/list-memory.ts +33 -0
  484. package/src/usecases/list-memory/types.ts +8 -0
  485. package/src/usecases/load-dont-forget/index.ts +2 -0
  486. package/src/usecases/load-dont-forget/load-dont-forget.ts +111 -0
  487. package/src/usecases/load-dont-forget/types.ts +26 -0
  488. package/src/usecases/memory-change/change.ts +42 -0
  489. package/src/usecases/memory-change/index.ts +5 -0
  490. package/src/usecases/memory-change/maintenance.ts +11 -0
  491. package/src/usecases/memory-change/partial.ts +18 -0
  492. package/src/usecases/memory-change/receipt.ts +40 -0
  493. package/src/usecases/memory-change/types.ts +44 -0
  494. package/src/usecases/operation-context/context.ts +37 -0
  495. package/src/usecases/operation-context/index.ts +2 -0
  496. package/src/usecases/operation-context/types.ts +19 -0
  497. package/src/usecases/registration/check.ts +6 -0
  498. package/src/usecases/registration/entry.ts +33 -0
  499. package/src/usecases/registration/index.ts +8 -0
  500. package/src/usecases/registration/init.ts +94 -0
  501. package/src/usecases/registration/prepare-init.ts +43 -0
  502. package/src/usecases/registration/prepare.ts +35 -0
  503. package/src/usecases/registration/propose.ts +34 -0
  504. package/src/usecases/registration/publication.ts +90 -0
  505. package/src/usecases/registration/setup.ts +41 -0
  506. package/src/usecases/registration/types.ts +107 -0
  507. package/src/usecases/relevant-memory/agent.ts +55 -0
  508. package/src/usecases/relevant-memory/constants.ts +28 -0
  509. package/src/usecases/relevant-memory/cutoffs.ts +29 -0
  510. package/src/usecases/relevant-memory/decision.ts +102 -0
  511. package/src/usecases/relevant-memory/index.ts +11 -0
  512. package/src/usecases/relevant-memory/loaded.ts +31 -0
  513. package/src/usecases/relevant-memory/refresh.ts +30 -0
  514. package/src/usecases/relevant-memory/retrieve-memory.ts +62 -0
  515. package/src/usecases/relevant-memory/schemas.ts +20 -0
  516. package/src/usecases/relevant-memory/session-memory.ts +53 -0
  517. package/src/usecases/relevant-memory/track-dont-forget.ts +13 -0
  518. package/src/usecases/relevant-memory/types.ts +106 -0
  519. package/src/usecases/resolve-memory/index.ts +2 -0
  520. package/src/usecases/resolve-memory/leased/index.ts +2 -0
  521. package/src/usecases/resolve-memory/leased/resolve.ts +109 -0
  522. package/src/usecases/resolve-memory/leased/types.ts +35 -0
  523. package/src/usecases/resolve-memory/resolve-memory.ts +23 -0
  524. package/src/usecases/resolve-memory/types.ts +7 -0
  525. package/src/usecases/search-memory/constants.ts +1 -0
  526. package/src/usecases/search-memory/index.ts +3 -0
  527. package/src/usecases/search-memory/search-memory.ts +132 -0
  528. package/src/usecases/search-memory/types.ts +39 -0
  529. package/src/usecases/semantic/constants.ts +7 -0
  530. package/src/usecases/semantic/index.ts +5 -0
  531. package/src/usecases/semantic/prepare.ts +30 -0
  532. package/src/usecases/semantic/rank.ts +83 -0
  533. package/src/usecases/semantic/refresh-vectors.ts +95 -0
  534. package/src/usecases/semantic/types.ts +17 -0
  535. package/src/usecases/semantic-port/index.ts +1 -0
  536. package/src/usecases/semantic-port/types.ts +20 -0
  537. package/src/usecases/semantic-provider/constants.ts +6 -0
  538. package/src/usecases/semantic-provider/index.ts +5 -0
  539. package/src/usecases/semantic-provider/local.ts +33 -0
  540. package/src/usecases/semantic-provider/remote.ts +10 -0
  541. package/src/usecases/semantic-provider/size.ts +10 -0
  542. package/src/usecases/semantic-provider/types.ts +19 -0
  543. package/src/usecases/session/index.ts +2 -0
  544. package/src/usecases/session/lease.ts +70 -0
  545. package/src/usecases/session/receipts.ts +46 -0
  546. package/src/usecases/session/state.ts +106 -0
  547. package/src/usecases/session/types.ts +45 -0
  548. package/src/usecases/settings/change.ts +142 -0
  549. package/src/usecases/settings/index.ts +3 -0
  550. package/src/usecases/settings/prepare.ts +24 -0
  551. package/src/usecases/settings/types.ts +32 -0
  552. package/src/usecases/succeed-memory/index.ts +3 -0
  553. package/src/usecases/succeed-memory/schemas.ts +13 -0
  554. package/src/usecases/succeed-memory/succeed-memory.ts +34 -0
  555. package/src/usecases/succeed-memory/types.ts +18 -0
  556. package/src/usecases/synchronize-memory/index.ts +2 -0
  557. package/src/usecases/synchronize-memory/leased/aliases.ts +55 -0
  558. package/src/usecases/synchronize-memory/leased/folder-states.ts +58 -0
  559. package/src/usecases/synchronize-memory/leased/index.ts +2 -0
  560. package/src/usecases/synchronize-memory/leased/inspection.ts +32 -0
  561. package/src/usecases/synchronize-memory/leased/maintenance.ts +41 -0
  562. package/src/usecases/synchronize-memory/leased/publication.ts +55 -0
  563. package/src/usecases/synchronize-memory/leased/scan.ts +37 -0
  564. package/src/usecases/synchronize-memory/leased/synchronize.ts +102 -0
  565. package/src/usecases/synchronize-memory/leased/types.ts +60 -0
  566. package/src/usecases/synchronize-memory/synchronize-memory.ts +26 -0
  567. package/src/usecases/synchronize-memory/types.ts +5 -0
  568. package/src/usecases/update-memory/index.ts +3 -0
  569. package/src/usecases/update-memory/schemas.ts +14 -0
  570. package/src/usecases/update-memory/types.ts +16 -0
  571. package/src/usecases/update-memory/update-memory.ts +31 -0
  572. package/CHANGELOG.md +0 -21
@@ -0,0 +1,63 @@
1
+ import type { MemoryCommand, MemoryPaths, MemoryPiContext } from "#src/pi/context"
2
+ import type { MemorySessionKeeper } from "#src/pi/memory-session"
3
+ import { describeRegistered, describeRegistrationFailure } from "#src/pi/registration-report"
4
+ import {
5
+ checkProjectName,
6
+ type InitPreparation,
7
+ initProjectMemory,
8
+ prepareProjectInit,
9
+ type RegistrationContext,
10
+ } from "#src/usecases"
11
+ import {
12
+ INIT_CANCELLED,
13
+ INIT_DONE,
14
+ INIT_NAME_TITLE,
15
+ INIT_REPOINT_VAULT_TITLE,
16
+ INIT_SETUP_HINT,
17
+ INIT_VAULT_PLACEHOLDER,
18
+ INIT_VAULT_TITLE,
19
+ MEMORY_INIT_DESCRIPTION,
20
+ } from "./constants.ts"
21
+
22
+ export function memoryInitCommand(paths: MemoryPaths, sessions: MemorySessionKeeper): MemoryCommand {
23
+ return {
24
+ description: MEMORY_INIT_DESCRIPTION,
25
+ async handler(_args, ctx) {
26
+ if (!ctx.hasUI) return
27
+ const { registration } = sessions.registrationFlow(ctx, paths)
28
+ await runMemoryInit(ctx, registration)
29
+ },
30
+ }
31
+ }
32
+
33
+ async function runMemoryInit(ctx: MemoryPiContext, registration: RegistrationContext): Promise<void> {
34
+ const preparation = await prepareProjectInit(registration)
35
+ if (!preparation.succeeded) {
36
+ const lines = [...preparation.problems]
37
+ if (preparation.reason !== "unreadable") lines.push(INIT_SETUP_HINT)
38
+ return ctx.ui.notify(lines.join("\n"), "error")
39
+ }
40
+ const name = await askName(ctx, preparation.output)
41
+ if (typeof name !== "string") return ctx.ui.notify(INIT_CANCELLED, "info")
42
+ const vault = await askVault(ctx, preparation.output)
43
+ if (typeof vault !== "string") return ctx.ui.notify(INIT_CANCELLED, "info")
44
+ const result = await initProjectMemory({ name, vault, expectedHash: preparation.output.expectedHash }, registration)
45
+ if (!result.succeeded) return ctx.ui.notify(describeRegistrationFailure(result), "error")
46
+ ctx.ui.notify(describeRegistered(`${INIT_DONE} ${name}`, result.output), "info")
47
+ }
48
+
49
+ async function askName(ctx: MemoryPiContext, preparation: InitPreparation): Promise<string | null> {
50
+ if (preparation.existing) return preparation.existing.name
51
+ for (;;) {
52
+ const answer = await ctx.ui.input(INIT_NAME_TITLE, preparation.defaultName)
53
+ if (typeof answer !== "string") return null
54
+ const checked = checkProjectName(preparation, answer)
55
+ if (checked.succeeded) return checked.output
56
+ ctx.ui.notify(checked.problems.join("\n"), "error")
57
+ }
58
+ }
59
+
60
+ function askVault(ctx: MemoryPiContext, preparation: InitPreparation): Promise<string | undefined> {
61
+ if (preparation.existing) return ctx.ui.input(INIT_REPOINT_VAULT_TITLE, INIT_VAULT_PLACEHOLDER)
62
+ return ctx.ui.input(INIT_VAULT_TITLE, INIT_VAULT_PLACEHOLDER)
63
+ }
@@ -0,0 +1,16 @@
1
+ export const MEMORY_SEARCH_TOOL_NAME = "memory_search"
2
+
3
+ export const MEMORY_SEARCH_TOOL_LABEL = "Memory search"
4
+
5
+ export const MEMORY_SEARCH_TOOL_DESCRIPTION =
6
+ "Search long-term memory by words. Archived notes and notes without valid frontmatter are not searched."
7
+
8
+ export const NO_PROJECT_VAULT = "No project vault is registered for this folder."
9
+
10
+ export const READ_HINT = 'Try other words or walk folders with memory_get (path "" is the vault root).'
11
+
12
+ export const SEARCH_FIELD_SEPARATOR = " · "
13
+
14
+ export const DONT_FORGET_MARK = "don't forget"
15
+
16
+ export const NEEDS_FIXING_MARK = "needs fixing"
@@ -0,0 +1,5 @@
1
+ export * from "./constants.ts"
2
+ export * from "./memory-search.ts"
3
+ export * from "./respond.ts"
4
+ export * from "./schemas.ts"
5
+ export * from "./types.ts"
@@ -0,0 +1,22 @@
1
+ import type { MemoryPaths } from "#src/pi/context"
2
+ import { type MemorySessionKeeper, noSessionResponse } from "#src/pi/memory-session"
3
+ import { searchMemory } from "#src/usecases"
4
+ import { MEMORY_SEARCH_TOOL_DESCRIPTION, MEMORY_SEARCH_TOOL_LABEL, MEMORY_SEARCH_TOOL_NAME } from "./constants.ts"
5
+ import { respondToSearch } from "./respond.ts"
6
+ import { MemorySearchParamsSchema } from "./schemas.ts"
7
+ import type { MemorySearchTool } from "./types.ts"
8
+
9
+ export function memorySearchTool(paths: MemoryPaths, sessions: MemorySessionKeeper): MemorySearchTool {
10
+ return {
11
+ name: MEMORY_SEARCH_TOOL_NAME,
12
+ label: MEMORY_SEARCH_TOOL_LABEL,
13
+ description: MEMORY_SEARCH_TOOL_DESCRIPTION,
14
+ parameters: MemorySearchParamsSchema,
15
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
16
+ const request = { query: params.query, vault: params.vault }
17
+ const result = await sessions.readFresh(ctx.cwd, paths, signal, (context) => searchMemory(request, context))
18
+ if (!result) return noSessionResponse()
19
+ return respondToSearch(result)
20
+ },
21
+ }
22
+ }
@@ -0,0 +1,62 @@
1
+ import { SETUP_GUIDANCE } from "#src/pi/memory-add"
2
+ import type { SearchedMemory, SearchMemoryResult, VaultSearchFailure, VaultSearchHits } from "#src/usecases"
3
+ import {
4
+ DONT_FORGET_MARK,
5
+ NEEDS_FIXING_MARK,
6
+ NO_PROJECT_VAULT,
7
+ READ_HINT,
8
+ SEARCH_FIELD_SEPARATOR,
9
+ } from "./constants.ts"
10
+ import type { MemorySearchResponse } from "./types.ts"
11
+
12
+ export function respondToSearch(result: SearchMemoryResult): MemorySearchResponse {
13
+ if (result.succeeded) return describeSearched(result.output)
14
+ switch (result.reason) {
15
+ case "not-configured":
16
+ case "invalid-config":
17
+ return reply([...result.problems, SETUP_GUIDANCE], true)
18
+ default:
19
+ return reply(result.problems, true)
20
+ }
21
+ }
22
+
23
+ function describeSearched(searched: SearchedMemory): MemorySearchResponse {
24
+ const lines: string[] = []
25
+ const failures = searched.vaults.filter(isFailure)
26
+ const answered = searched.vaults.filter(isHits)
27
+ for (const entry of answered) {
28
+ for (const hit of entry.hits) lines.push(describeHit(entry.vault, hit))
29
+ }
30
+ if (answered.length > 0 && lines.length === 0) {
31
+ const names = answered.map((entry) => entry.vault).join(", ")
32
+ lines.push(`No notes found in ${names}. ${READ_HINT}`)
33
+ }
34
+ for (const entry of failures) {
35
+ for (const problem of entry.problems) lines.push(`Could not search ${entry.vault}: ${problem}`)
36
+ }
37
+ for (const entry of answered) {
38
+ for (const warning of entry.warnings) lines.push(`Warning: ${warning}`)
39
+ }
40
+ lines.push(...searched.semantic.problems)
41
+ if (searched.projectMissing) lines.push(NO_PROJECT_VAULT)
42
+ return reply(lines, answered.length === 0)
43
+ }
44
+
45
+ function describeHit(vault: string, hit: VaultSearchHits["hits"][number]): string {
46
+ const fields = [vault, hit.path, hit.type]
47
+ if (hit.dontForget) fields.push(DONT_FORGET_MARK)
48
+ if (hit.needsFixing) fields.push(NEEDS_FIXING_MARK)
49
+ return fields.join(SEARCH_FIELD_SEPARATOR)
50
+ }
51
+
52
+ function isFailure(entry: VaultSearchHits | VaultSearchFailure): entry is VaultSearchFailure {
53
+ return "problems" in entry
54
+ }
55
+
56
+ function isHits(entry: VaultSearchHits | VaultSearchFailure): entry is VaultSearchHits {
57
+ return "hits" in entry
58
+ }
59
+
60
+ function reply(lines: string[], isError: boolean): MemorySearchResponse {
61
+ return { content: [{ type: "text", text: lines.join("\n") }], details: undefined, isError }
62
+ }
@@ -0,0 +1,11 @@
1
+ import Type from "typebox"
2
+
3
+ export const MemorySearchParamsSchema = Type.Object(
4
+ {
5
+ query: Type.String({ minLength: 1, description: "Words to look for, in English." }),
6
+ vault: Type.Union([Type.Literal("global"), Type.Literal("project"), Type.Literal("both")], {
7
+ description: "global: about the user. project: about this project. both: search the two, each on its own.",
8
+ }),
9
+ },
10
+ { additionalProperties: false },
11
+ )
@@ -0,0 +1,10 @@
1
+ import type { AgentToolResult, ToolDefinition } from "@earendil-works/pi-coding-agent"
2
+ import type { Static } from "typebox"
3
+
4
+ import type { MemorySearchParamsSchema } from "./schemas.ts"
5
+
6
+ export type MemorySearchParams = Static<typeof MemorySearchParamsSchema>
7
+
8
+ export type MemorySearchTool = ToolDefinition<typeof MemorySearchParamsSchema, undefined>
9
+
10
+ export type MemorySearchResponse = AgentToolResult<undefined>
@@ -0,0 +1,7 @@
1
+ export const NO_SESSION_NOTICE = "Memory is not ready in this session; try again after the session has started."
2
+
3
+ export const STALE_SESSION_REASON = "stale-session"
4
+
5
+ export const CAPTURE_BRANCH = "capture"
6
+
7
+ export const RETRIEVAL_BRANCH = "retrieval"
@@ -0,0 +1,4 @@
1
+ export * from "./constants.ts"
2
+ export * from "./keeper.ts"
3
+ export * from "./respond.ts"
4
+ export * from "./types.ts"
@@ -0,0 +1,101 @@
1
+ import type { MemoryPaths, MemoryPiContext } from "#src/pi/context"
2
+ import { hostPathPlatform } from "#src/pi/paths"
3
+ import type { SemanticRuntime } from "#src/pi/semantic"
4
+ import { createMemorySession, LoadedMemory, type MemoryOperationContext, type MemorySession } from "#src/usecases"
5
+ import { CAPTURE_BRANCH, RETRIEVAL_BRANCH, STALE_SESSION_REASON } from "./constants.ts"
6
+ import type { ReadOutcome, ReadRun, RegistrationFlow } from "./types.ts"
7
+
8
+ export class MemorySessionKeeper {
9
+ #session: MemorySession | null = null
10
+ #semantic: SemanticRuntime | null = null
11
+ #loaded = new LoadedMemory()
12
+
13
+ constructor(semantic?: SemanticRuntime) {
14
+ if (semantic) this.#semantic = semantic
15
+ }
16
+
17
+ start(ctx: MemoryPiContext): MemorySession {
18
+ if (this.#session) this.#session.abortPending()
19
+ const session = createMemorySession({ sessionId: ctx.sessionManager.getSessionId(), branchId: null })
20
+ if (this.#semantic) this.#semantic.attach(ctx)
21
+ this.#session = session
22
+ this.#loaded = new LoadedMemory()
23
+ return session
24
+ }
25
+
26
+ shutdown(): void {
27
+ if (this.#session) this.#session.abortPending()
28
+ this.#session = null
29
+ }
30
+
31
+ operationContext(
32
+ session: MemorySession,
33
+ workingFolder: string,
34
+ paths: MemoryPaths,
35
+ callerSignal: AbortSignal | undefined,
36
+ ): MemoryOperationContext {
37
+ const stamp = session.stamp()
38
+ let signal = session.signal(stamp)
39
+ if (callerSignal) signal = AbortSignal.any([signal, callerSignal])
40
+ const context: MemoryOperationContext = {
41
+ configPath: paths.configPath,
42
+ indexPath: paths.indexPath,
43
+ workingFolder,
44
+ platform: hostPathPlatform(process.platform),
45
+ session,
46
+ stamp,
47
+ signal,
48
+ }
49
+ if (this.#semantic) context.semantic = this.#semantic.source
50
+ return context
51
+ }
52
+
53
+ currentOperation(
54
+ workingFolder: string,
55
+ paths: MemoryPaths,
56
+ callerSignal: AbortSignal | undefined,
57
+ ): MemoryOperationContext | null {
58
+ if (!this.#session) return null
59
+ return this.operationContext(this.#session, workingFolder, paths, callerSignal)
60
+ }
61
+
62
+ loaded(): LoadedMemory {
63
+ return this.#loaded
64
+ }
65
+
66
+ captureOperation(workingFolder: string, paths: MemoryPaths): MemoryOperationContext | null {
67
+ return this.#siblingOperation(CAPTURE_BRANCH, workingFolder, paths)
68
+ }
69
+
70
+ retrievalOperation(workingFolder: string, paths: MemoryPaths): MemoryOperationContext | null {
71
+ return this.#siblingOperation(RETRIEVAL_BRANCH, workingFolder, paths)
72
+ }
73
+
74
+ #siblingOperation(branchId: string, workingFolder: string, paths: MemoryPaths): MemoryOperationContext | null {
75
+ const main = this.#session
76
+ if (!main) return null
77
+ const sibling = main.sibling({ sessionId: main.stamp().sessionId, branchId })
78
+ return this.operationContext(sibling, workingFolder, paths, main.signal(main.stamp()))
79
+ }
80
+
81
+ async readFresh<Outcome extends ReadOutcome>(
82
+ workingFolder: string,
83
+ paths: MemoryPaths,
84
+ callerSignal: AbortSignal | undefined,
85
+ run: ReadRun<Outcome>,
86
+ ): Promise<Outcome | null> {
87
+ const first = this.currentOperation(workingFolder, paths, callerSignal)
88
+ if (!first) return null
89
+ const result = await run(first)
90
+ if (result.succeeded || result.reason !== STALE_SESSION_REASON) return result
91
+ const second = this.currentOperation(workingFolder, paths, callerSignal)
92
+ if (!second) return result
93
+ return run(second)
94
+ }
95
+
96
+ registrationFlow(ctx: MemoryPiContext, paths: MemoryPaths): RegistrationFlow {
97
+ let session = this.#session
98
+ if (!session) session = this.start(ctx)
99
+ return { session, registration: this.operationContext(session, ctx.cwd, paths, undefined) }
100
+ }
101
+ }
@@ -0,0 +1,6 @@
1
+ import { NO_SESSION_NOTICE } from "./constants.ts"
2
+ import type { NoSessionResponse } from "./types.ts"
3
+
4
+ export function noSessionResponse(): NoSessionResponse {
5
+ return { content: [{ type: "text", text: NO_SESSION_NOTICE }], details: undefined, isError: true }
6
+ }
@@ -0,0 +1,23 @@
1
+ import type { AgentToolResult, SessionShutdownEvent } from "@earendil-works/pi-coding-agent"
2
+
3
+ import type { MemoryPiContext } from "#src/pi/context"
4
+ import type { Done } from "#src/shared"
5
+ import type { MemoryOperationContext, MemorySession, RegistrationContext } from "#src/usecases"
6
+
7
+ export interface RegistrationFlow {
8
+ session: MemorySession
9
+ registration: RegistrationContext
10
+ }
11
+
12
+ export type SessionShutdownHandler = (event: SessionShutdownEvent, ctx: MemoryPiContext) => Promise<void>
13
+
14
+ export type NoSessionResponse = AgentToolResult<undefined>
15
+
16
+ export interface ReadRefusal {
17
+ succeeded: false
18
+ reason: string
19
+ }
20
+
21
+ export type ReadOutcome = Done | ReadRefusal
22
+
23
+ export type ReadRun<Outcome extends ReadOutcome> = (context: MemoryOperationContext) => Promise<Outcome>
@@ -0,0 +1,69 @@
1
+ import type { EmbeddingChoice } from "./types.ts"
2
+
3
+ export const CURRENT_MARK = "(current)"
4
+
5
+ export const IN_USE_MARK = "(in use)"
6
+
7
+ export const PRICE_SEPARATOR = " · "
8
+
9
+ export const PRICE_DECIMALS = 4
10
+
11
+ export const DISCLOSURE_TITLE = "Before setup: what leaves this machine"
12
+
13
+ export const CHAT_MODELS_DISCLOSURE =
14
+ "Capture and the memory agent send conversation and note content to the chat model you chose."
15
+
16
+ export const JEV_DISCLOSURE = "TypeSafe (Jev) receives your messages and candidate notes."
17
+
18
+ export const REMOTE_EMBEDDINGS_DISCLOSURE =
19
+ "The remote embeddings provider receives note content, secrets included, and search queries."
20
+
21
+ export const SETTINGS_TITLE = "Memory settings (Done or Escape leaves)"
22
+
23
+ export const DONE_LABEL = "Done"
24
+
25
+ export const SAVED = "Saved:"
26
+
27
+ export const RELOAD_NOTE =
28
+ "The Don't forget notes already loaded into this conversation's memory block update at the next session or /reload."
29
+
30
+ export const CAPTURE_MODEL_TITLE =
31
+ "Chat model for automatic capture (a cheap model is usually enough; Escape keeps the current one)"
32
+
33
+ export const AGENT_MODEL_TITLE =
34
+ "Chat model for the memory agent (it searches memory for each message; Escape keeps the current one)"
35
+
36
+ export const DECISION_TITLE = "Decision model (Escape keeps the current one)"
37
+
38
+ export const JEV_OPTION = "Jev (TypeSafe, by API)"
39
+
40
+ export const LAYA_OPTION = "Laya (local)"
41
+
42
+ export const LAYA_ENDPOINT_TITLE = "Laya endpoint (empty keeps the current one)"
43
+
44
+ export const LAYA_DEFAULT_ENDPOINT = "http://127.0.0.1:8000/v1/systemone"
45
+
46
+ export const EMBEDDINGS_TITLE = "Embeddings provider (Escape keeps the current one)"
47
+
48
+ export const NONE_WORD = "none"
49
+
50
+ export const NO_PROJECTS_NOTICE = "No project is registered. Run /memory-init in a project folder to register one."
51
+
52
+ export const PROJECT_TITLE = "Project (Escape goes back)"
53
+
54
+ export const PROJECT_ACTION_TITLE = "What to do with this project? (Escape goes back)"
55
+
56
+ export const PROJECT_CHANGE_VAULT = "Change its vault"
57
+
58
+ export const PROJECT_REMOVE = "Remove it from the memory"
59
+
60
+ export const PROJECT_VAULT_TITLE = "Project vault (an existing folder; empty keeps the current one)"
61
+
62
+ export const EMBEDDING_CHOICES: EmbeddingChoice[] = [
63
+ {
64
+ value: { provider: "local", model: "Xenova/multilingual-e5-small" },
65
+ label: "local (Xenova/multilingual-e5-small)",
66
+ },
67
+ { value: { provider: "openai", model: "text-embedding-3-small" }, label: "openai (text-embedding-3-small)" },
68
+ { value: { provider: "google", model: "gemini-embedding-001" }, label: "google (gemini-embedding-001)" },
69
+ ]
@@ -0,0 +1,46 @@
1
+ import { parseSettingNumber } from "#src/usecases"
2
+ import { NONE_WORD } from "./constants.ts"
3
+ import { chooseModel } from "./models.ts"
4
+ import { saveChange } from "./save.ts"
5
+ import type { LineEdit, ModelEditSpec, NumberEditSpec, SwitchEditSpec } from "./types.ts"
6
+
7
+ export function modelEdit(spec: ModelEditSpec): LineEdit {
8
+ return async (env) => {
9
+ const chosen = await chooseModel(env.ctx, spec.title, spec.current, {})
10
+ if (!chosen) return
11
+ if (chosen.provider === spec.current.provider && chosen.id === spec.current.id) return
12
+ await saveChange(env, {
13
+ change: { kind: spec.kind, model: chosen },
14
+ what: `${spec.what} is now ${chosen.provider}/${chosen.id}`,
15
+ reload: false,
16
+ })
17
+ }
18
+ }
19
+
20
+ export function switchEdit(spec: SwitchEditSpec): LineEdit {
21
+ return async (env) => {
22
+ const value = !spec.current
23
+ let state = "off"
24
+ if (value) state = "on"
25
+ await saveChange(env, {
26
+ change: { kind: "captureSwitch", name: spec.name, value },
27
+ what: `${spec.what} is now ${state}`,
28
+ reload: false,
29
+ })
30
+ }
31
+ }
32
+
33
+ export function numberEdit(spec: NumberEditSpec): LineEdit {
34
+ return async (env) => {
35
+ const answer = await env.ctx.ui.input(spec.title, spec.current)
36
+ if (typeof answer !== "string" || answer.trim() === "") return
37
+ const typed = answer.trim()
38
+ if (spec.clear && typed.toLowerCase() === NONE_WORD) {
39
+ await saveChange(env, { change: spec.clear, what: `${spec.what} is now not set`, reload: false })
40
+ return
41
+ }
42
+ const parsed = parseSettingNumber(typed, spec.kind)
43
+ if (!parsed.succeeded) return env.ctx.ui.notify(`${spec.what}: ${parsed.problems.join("; ")}`, "error")
44
+ await saveChange(env, { change: spec.change(parsed.output), what: `${spec.what} is now ${typed}`, reload: false })
45
+ }
46
+ }
@@ -0,0 +1,9 @@
1
+ export * from "./constants.ts"
2
+ export * from "./edits.ts"
3
+ export * from "./lines.ts"
4
+ export * from "./models.ts"
5
+ export * from "./projects.ts"
6
+ export * from "./providers.ts"
7
+ export * from "./save.ts"
8
+ export * from "./screen.ts"
9
+ export * from "./types.ts"
@@ -0,0 +1,119 @@
1
+ import type { CutoffValue, MemoryConfig } from "#src/usecases"
2
+ import { resolveCutoffs } from "#src/usecases"
3
+ import { AGENT_MODEL_TITLE, CAPTURE_MODEL_TITLE } from "./constants.ts"
4
+ import { modelEdit, numberEdit, switchEdit } from "./edits.ts"
5
+ import { projectsEdit } from "./projects.ts"
6
+ import { decisionEdit, embeddingsEdit } from "./providers.ts"
7
+ import type { CaptureCountName, CaptureSwitchName, NumberChange, SettingLine } from "./types.ts"
8
+
9
+ function cutoffText(cutoff: CutoffValue): string {
10
+ if (typeof cutoff.value !== "number") return "not set"
11
+ if (cutoff.source === "config") return `${cutoff.value} (set)`
12
+ return `${cutoff.value} (TypeSafe starting value)`
13
+ }
14
+
15
+ function decisionText(config: MemoryConfig): string {
16
+ const { decisionModel } = config
17
+ if (decisionModel.provider === "laya") return `Laya (${decisionModel.endpoint})`
18
+ return "Jev (TypeSafe)"
19
+ }
20
+
21
+ function captureSwitchLine(label: string, name: CaptureSwitchName, config: MemoryConfig): SettingLine {
22
+ const current = config.capture[name]
23
+ let state = "off"
24
+ if (current) state = "on"
25
+ return { label: `${label}: ${state}`, edit: switchEdit({ name, what: label.toLowerCase(), current }) }
26
+ }
27
+
28
+ function cutoffLine(label: string, which: "gate" | "relevance", config: MemoryConfig): SettingLine {
29
+ const cutoff = resolveCutoffs(config.decisionModel)[which]
30
+ const title = `${label}, 0 to 1 (currently ${cutoffText(cutoff)}; type none to clear it; empty keeps it)`
31
+ const kind = `${which}Threshold` as const
32
+ return {
33
+ label: `${label}: ${cutoffText(cutoff)}`,
34
+ edit: numberEdit({
35
+ title,
36
+ what: label.toLowerCase(),
37
+ kind: "threshold",
38
+ current: cutoffText(cutoff),
39
+ change: (value) => ({ kind, value }),
40
+ clear: { kind, value: null },
41
+ }),
42
+ }
43
+ }
44
+
45
+ function countLine(label: string, unit: string, current: number, change: NumberChange): SettingLine {
46
+ return {
47
+ label: `${label}: ${current}${unit}`,
48
+ edit: numberEdit({
49
+ title: `${label} (a whole number of 1 or more; currently ${current}; empty keeps it)`,
50
+ what: label.toLowerCase(),
51
+ kind: "count",
52
+ current: String(current),
53
+ change,
54
+ clear: null,
55
+ }),
56
+ }
57
+ }
58
+
59
+ function captureCountLine(label: string, unit: string, name: CaptureCountName, config: MemoryConfig): SettingLine {
60
+ return countLine(label, unit, config.capture[name], (value) => ({ kind: "captureCount", name, value }))
61
+ }
62
+
63
+ function captureLines(config: MemoryConfig): SettingLine[] {
64
+ return [
65
+ {
66
+ label: `Capture model: ${config.capture.model.provider}/${config.capture.model.id}`,
67
+ edit: modelEdit({
68
+ title: CAPTURE_MODEL_TITLE,
69
+ what: "capture model",
70
+ kind: "captureModel",
71
+ current: config.capture.model,
72
+ }),
73
+ },
74
+ captureSwitchLine("Review during the session", "reviewEnabled", config),
75
+ captureCountLine("Review every", " turns", "nudgeInterval", config),
76
+ captureCountLine("Review after tool calls", "", "nudgeToolCalls", config),
77
+ captureSwitchLine("Flush at compaction", "flushOnCompact", config),
78
+ captureSwitchLine("Flush at session end", "flushOnShutdown", config),
79
+ captureCountLine("Flush minimum user messages", "", "flushMinTurns", config),
80
+ ]
81
+ }
82
+
83
+ export function settingLines(config: MemoryConfig): SettingLine[] {
84
+ const { limits } = config
85
+ return [
86
+ ...captureLines(config),
87
+ {
88
+ label: `Memory agent model: ${config.memoryAgent.model.provider}/${config.memoryAgent.model.id}`,
89
+ edit: modelEdit({
90
+ title: AGENT_MODEL_TITLE,
91
+ what: "memory agent model",
92
+ kind: "agentModel",
93
+ current: config.memoryAgent.model,
94
+ }),
95
+ },
96
+ { label: `Decision model: ${decisionText(config)}`, edit: decisionEdit },
97
+ cutoffLine("Gate cutoff", "gate", config),
98
+ cutoffLine("Relevance cutoff", "relevance", config),
99
+ { label: `Embeddings: ${config.embeddings.provider} (${config.embeddings.model})`, edit: embeddingsEdit },
100
+ countLine("Context budget", " characters", config.context.budgetChars, (value) => ({ kind: "budgetChars", value })),
101
+ countLine("Max note body", " characters", limits.maxBodyChars, (value) => ({
102
+ kind: "limit",
103
+ name: "maxBodyChars",
104
+ value,
105
+ })),
106
+ countLine("Max statement", " characters", limits.maxStatementChars, (value) => ({
107
+ kind: "limit",
108
+ name: "maxStatementChars",
109
+ value,
110
+ })),
111
+ countLine("Max notes per folder", "", limits.maxNotesPerFolder, (value) => ({
112
+ kind: "limit",
113
+ name: "maxNotesPerFolder",
114
+ value,
115
+ })),
116
+ { label: `Global vault: ${config.global.vault}`, edit: (env) => env.deps.changeGlobalVault(env.context) },
117
+ { label: `Projects: ${config.projects.length}`, edit: projectsEdit },
118
+ ]
119
+ }
@@ -0,0 +1,81 @@
1
+ import type { ChatModelSource, MemoryPiContext } from "#src/pi/context"
2
+ import type { ChatModelReference } from "#src/usecases"
3
+ import { CURRENT_MARK, IN_USE_MARK, PRICE_DECIMALS, PRICE_SEPARATOR } from "./constants.ts"
4
+ import type { CurrentModel, ModelChoice } from "./types.ts"
5
+
6
+ function priceText(value: number): string {
7
+ return `$${Number(value.toFixed(PRICE_DECIMALS))}`
8
+ }
9
+
10
+ export function modelLabel(model: ChatModelSource, mark: string | null): string {
11
+ let label = `${model.provider}/${model.id}`
12
+ if (mark) label = `${label} ${mark}`
13
+ if (!model.cost) return label
14
+ const prices = `${priceText(model.cost.input)} in / ${priceText(model.cost.output)} out per 1M tokens`
15
+ return `${label}${PRICE_SEPARATOR}${prices}`
16
+ }
17
+
18
+ function sameModel(model: ChatModelSource, current: CurrentModel): boolean {
19
+ return model.provider === current.provider && model.id === current.id
20
+ }
21
+
22
+ function inputPrice(model: ChatModelSource): number {
23
+ if (model.cost) return model.cost.input
24
+ return Number.POSITIVE_INFINITY
25
+ }
26
+
27
+ function byPrice(left: ChatModelSource, right: ChatModelSource): number {
28
+ const leftPrice = inputPrice(left)
29
+ const rightPrice = inputPrice(right)
30
+ if (leftPrice === rightPrice) return 0
31
+ if (leftPrice < rightPrice) return -1
32
+ return 1
33
+ }
34
+
35
+ function firstChoice(available: ChatModelSource[], current: CurrentModel, inUse: CurrentModel): ModelChoice | null {
36
+ let first = current
37
+ let mark = CURRENT_MARK
38
+ if (typeof current.provider !== "string" || typeof current.id !== "string") {
39
+ first = inUse
40
+ mark = IN_USE_MARK
41
+ }
42
+ if (typeof first.provider !== "string" || typeof first.id !== "string") return null
43
+ const reference = { provider: first.provider, id: first.id }
44
+ let shown: ChatModelSource = reference
45
+ const known = available.find((model) => sameModel(model, first))
46
+ if (known) shown = known
47
+ return { label: modelLabel(shown, mark), reference, current: true }
48
+ }
49
+
50
+ export function modelChoices(available: ChatModelSource[], current: CurrentModel, inUse: CurrentModel): ModelChoice[] {
51
+ const first = firstChoice(available, current, inUse)
52
+ const others = available
53
+ .filter((model) => !first || !sameModel(model, first.reference))
54
+ .sort(byPrice)
55
+ .map((model) => ({
56
+ label: modelLabel(model, null),
57
+ reference: { provider: model.provider, id: model.id },
58
+ current: false,
59
+ }))
60
+ if (!first) return others
61
+ return [first, ...others]
62
+ }
63
+
64
+ export async function chooseModel(
65
+ ctx: MemoryPiContext,
66
+ title: string,
67
+ current: CurrentModel,
68
+ inUse: CurrentModel,
69
+ ): Promise<ChatModelReference | null> {
70
+ const choices = modelChoices(ctx.modelRegistry.getAvailable(), current, inUse)
71
+ const answer = await ctx.ui.select(
72
+ title,
73
+ choices.map((choice) => choice.label),
74
+ )
75
+ const chosen = choices.find((choice) => choice.label === answer)
76
+ if (chosen) return chosen.reference
77
+ if (typeof answer === "string" && answer !== "") return null
78
+ const kept = choices.find((choice) => choice.current)
79
+ if (kept) return kept.reference
80
+ return null
81
+ }