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,10 @@
1
+ import type { VaultExportEntry, VaultExportFile } from "./types.ts"
2
+
3
+ export function exportEntries(
4
+ global: readonly VaultExportFile[],
5
+ project: readonly VaultExportFile[] | null,
6
+ ): VaultExportEntry[] {
7
+ const entries = global.map((file) => ({ path: `global/${file.path}`, bytes: file.bytes }))
8
+ if (!project) return entries
9
+ return [...entries, ...project.map((file) => ({ path: `project/${file.path}`, bytes: file.bytes }))]
10
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./analyze.ts"
2
+ export * from "./classify.ts"
3
+ export * from "./dont-forget.ts"
4
+ export * from "./export-entries.ts"
5
+ export * from "./types.ts"
@@ -0,0 +1,114 @@
1
+ import type { NoteFrontmatter, NoteLimits, ParsedNote } from "#src/domain/note"
2
+ import type { Failed, Succeeded } from "#src/shared"
3
+
4
+ export type VaultEntryKind = "note" | "folder" | "index" | "template" | "dashboard" | "temporary" | "other"
5
+
6
+ export interface VaultFileStat {
7
+ size: number
8
+ mtimeMs: number
9
+ ctimeMs: number
10
+ device: number
11
+ inode: number
12
+ }
13
+
14
+ export interface VaultCatalogEntry {
15
+ path: string
16
+ kind: VaultEntryKind
17
+ archived: boolean
18
+ stat: VaultFileStat
19
+ }
20
+
21
+ export interface VaultCatalogFailure extends Failed {
22
+ path: string
23
+ scope: "file" | "directory" | "entry"
24
+ reason:
25
+ | "invalid-path"
26
+ | "outside-vault"
27
+ | "not-found"
28
+ | "not-directory"
29
+ | "not-file"
30
+ | "unreadable"
31
+ | "not-writable"
32
+ | "cycle"
33
+ | "excluded"
34
+ | "changed"
35
+ | "io-error"
36
+ }
37
+
38
+ export interface VaultAlias {
39
+ path: string
40
+ target: string
41
+ }
42
+
43
+ export interface VaultEnumeration {
44
+ entries: VaultCatalogEntry[]
45
+ observedPaths: string[]
46
+ completeDirectories: string[]
47
+ failures: VaultCatalogFailure[]
48
+ aliases: VaultAlias[]
49
+ }
50
+
51
+ export type VaultEnumerationResult = Succeeded<VaultEnumeration> | VaultCatalogFailure
52
+
53
+ export interface AnalyzeVaultNoteRequest {
54
+ statement: string
55
+ text: string
56
+ archived: boolean
57
+ limits: NoteLimits
58
+ }
59
+
60
+ export interface VaultNoteProblems {
61
+ frontmatterProblems: string[]
62
+ nameProblems: string[]
63
+ bodyProblems: string[]
64
+ }
65
+
66
+ export interface ParsedVaultNote extends VaultNoteProblems {
67
+ status: "parsed"
68
+ parsed: ParsedNote
69
+ frontmatter: NoteFrontmatter | null
70
+ searchable: boolean
71
+ needsFixing: boolean
72
+ }
73
+
74
+ export interface UnclosedVaultNote extends VaultNoteProblems {
75
+ status: "unclosed"
76
+ searchable: false
77
+ needsFixing: true
78
+ }
79
+
80
+ export type VaultNoteAnalysis = ParsedVaultNote | UnclosedVaultNote
81
+
82
+ export interface VaultFileRequest {
83
+ path: string
84
+ }
85
+
86
+ export interface InspectedVaultFile {
87
+ path: string
88
+ canonicalPath: string
89
+ text: string
90
+ rawHash: string
91
+ stat: VaultFileStat
92
+ archived: boolean
93
+ analysis: VaultNoteAnalysis
94
+ }
95
+
96
+ export type VaultInspectionResult = Succeeded<InspectedVaultFile> | VaultCatalogFailure
97
+
98
+ export interface VaultExportFile {
99
+ path: string
100
+ bytes: Uint8Array
101
+ rawHash: string
102
+ stat: VaultFileStat
103
+ }
104
+
105
+ export interface VaultExportEntry {
106
+ path: string
107
+ bytes: Uint8Array
108
+ }
109
+
110
+ export interface VaultExportFailure extends Failed {
111
+ failures: VaultCatalogFailure[]
112
+ }
113
+
114
+ export type VaultExportResult = Succeeded<VaultExportFile[]> | VaultExportFailure
@@ -0,0 +1,79 @@
1
+ import { catalogFolder } from "#src/domain/search-catalog"
2
+ import { isRootArchive, type VaultCatalogEntry } from "#src/domain/vault-catalog"
3
+ import type {
4
+ CrowdedFolder,
5
+ DuplicateNoteId,
6
+ InvalidVaultNote,
7
+ VaultDiagnosis,
8
+ VaultDiagnosisRequest,
9
+ } from "./types.ts"
10
+
11
+ export function diagnoseVault(request: VaultDiagnosisRequest): VaultDiagnosis {
12
+ return {
13
+ invalid: invalidNotes(request),
14
+ blank: request.inspected
15
+ .filter((file) => file.analysis.status === "unclosed")
16
+ .map((file) => file.path)
17
+ .sort(compareText),
18
+ duplicateIds: duplicateIds(request),
19
+ temporaries: request.entries
20
+ .filter((entry) => entry.kind === "temporary")
21
+ .map((entry) => entry.path)
22
+ .sort(compareText),
23
+ crowdedFolders: crowdedFolders(request),
24
+ }
25
+ }
26
+
27
+ function invalidNotes(request: VaultDiagnosisRequest): InvalidVaultNote[] {
28
+ const invalid: InvalidVaultNote[] = []
29
+ for (const file of request.inspected) {
30
+ const { analysis } = file
31
+ if (analysis.status === "parsed" && analysis.needsFixing) {
32
+ invalid.push({
33
+ path: file.path,
34
+ problems: [...analysis.frontmatterProblems, ...analysis.nameProblems, ...analysis.bodyProblems],
35
+ })
36
+ }
37
+ }
38
+ return invalid.sort((left, right) => compareText(left.path, right.path))
39
+ }
40
+
41
+ function duplicateIds(request: VaultDiagnosisRequest): DuplicateNoteId[] {
42
+ const groups = new Map<string, string[]>()
43
+ for (const file of request.inspected) {
44
+ const { analysis } = file
45
+ if (analysis.status !== "parsed" || !analysis.frontmatter) continue
46
+ const group = groups.get(analysis.frontmatter.id)
47
+ if (group) group.push(file.path)
48
+ else groups.set(analysis.frontmatter.id, [file.path])
49
+ }
50
+ return [...groups]
51
+ .filter(([, paths]) => paths.length > 1)
52
+ .map(([id, paths]) => ({ id, paths: paths.sort(compareText) }))
53
+ .sort((left, right) => compareText(left.id, right.id))
54
+ }
55
+
56
+ function crowdedFolders(request: VaultDiagnosisRequest): CrowdedFolder[] {
57
+ const counts = new Map<string, number>()
58
+ for (const entry of request.entries) {
59
+ if (!isLiveNote(entry)) continue
60
+ const folder = catalogFolder(entry.path)
61
+ const count = counts.get(folder)
62
+ if (count) counts.set(folder, count + 1)
63
+ else counts.set(folder, 1)
64
+ }
65
+ return [...counts]
66
+ .filter(([, count]) => count > request.limits.maxNotesPerFolder)
67
+ .map(([folder, count]) => ({ folder, count }))
68
+ .sort((left, right) => compareText(left.folder, right.folder))
69
+ }
70
+
71
+ function isLiveNote(entry: VaultCatalogEntry): boolean {
72
+ return entry.kind === "note" && !entry.archived && !isRootArchive(entry.path)
73
+ }
74
+
75
+ function compareText(left: string, right: string): number {
76
+ if (left < right) return -1
77
+ if (left > right) return 1
78
+ return 0
79
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./diagnose.ts"
2
+ export * from "./types.ts"
@@ -0,0 +1,31 @@
1
+ import type { MemoryConfig } from "#src/domain/config"
2
+ import type { InspectedVaultFile, VaultCatalogEntry } from "#src/domain/vault-catalog"
3
+
4
+ export interface VaultDiagnosisRequest {
5
+ entries: readonly VaultCatalogEntry[]
6
+ inspected: readonly InspectedVaultFile[]
7
+ limits: MemoryConfig["limits"]
8
+ }
9
+
10
+ export interface InvalidVaultNote {
11
+ path: string
12
+ problems: string[]
13
+ }
14
+
15
+ export interface DuplicateNoteId {
16
+ id: string
17
+ paths: string[]
18
+ }
19
+
20
+ export interface CrowdedFolder {
21
+ folder: string
22
+ count: number
23
+ }
24
+
25
+ export interface VaultDiagnosis {
26
+ invalid: InvalidVaultNote[]
27
+ blank: string[]
28
+ duplicateIds: DuplicateNoteId[]
29
+ temporaries: string[]
30
+ crowdedFolders: CrowdedFolder[]
31
+ }
@@ -0,0 +1,13 @@
1
+ export const FOLDER_INDEX_NAME = "index"
2
+
3
+ export const ARCHIVE_FOLDER = "archive"
4
+
5
+ export const TEMPLATES_FOLDER = "_templates"
6
+
7
+ export const RESERVED_ROOT_FOLDERS = [ARCHIVE_FOLDER, TEMPLATES_FOLDER]
8
+
9
+ export const VAULT_PATH_SEPARATOR = "/"
10
+
11
+ export const DRIVE_LETTER = /^[A-Za-z]:/
12
+
13
+ export const HIDDEN_NAME_PREFIX = "."
@@ -0,0 +1,2 @@
1
+ export * from "./constants.ts"
2
+ export * from "./vault-path.ts"
@@ -0,0 +1,65 @@
1
+ import { checkEdges, checkFileSystemName, checkLinkCharacters, RELATIVE_NAMES } from "#src/domain/names"
2
+ import { DRIVE_LETTER, HIDDEN_NAME_PREFIX, RESERVED_ROOT_FOLDERS, VAULT_PATH_SEPARATOR } from "./constants.ts"
3
+
4
+ export function joinVaultPath(...parts: string[]): string {
5
+ return parts.filter((part) => part.length > 0).join(VAULT_PATH_SEPARATOR)
6
+ }
7
+
8
+ export function ancestorFolders(folder: string): string[] {
9
+ const parts = folder.split(VAULT_PATH_SEPARATOR).filter((part) => part.length > 0)
10
+ const nested = parts.map((_part, depth) => parts.slice(0, parts.length - depth).join(VAULT_PATH_SEPARATOR))
11
+
12
+ return [...nested, ""]
13
+ }
14
+
15
+ export function checkVaultPath(folder: string): string[] {
16
+ if (folder.includes("\\")) {
17
+ return ['folder: use "/" between folders']
18
+ }
19
+
20
+ if (folder.startsWith(VAULT_PATH_SEPARATOR) || DRIVE_LETTER.test(folder)) {
21
+ return ["folder: must be relative to the vault"]
22
+ }
23
+
24
+ if (folder.length === 0) {
25
+ return []
26
+ }
27
+
28
+ const problems = folder.split(VAULT_PATH_SEPARATOR).flatMap(checkFolderPart)
29
+ return [...new Set(problems)]
30
+ }
31
+
32
+ export function checkMemoryFolder(folder: string): string[] {
33
+ const problems = checkVaultPath(folder)
34
+ if (problems.length > 0 || folder.length === 0) {
35
+ return problems
36
+ }
37
+
38
+ return folder.split(VAULT_PATH_SEPARATOR).flatMap(checkMemoryFolderPart)
39
+ }
40
+
41
+ function checkFolderPart(part: string): string[] {
42
+ if (part.length === 0) {
43
+ return ["folder: has an empty part"]
44
+ }
45
+
46
+ if (RELATIVE_NAMES.includes(part)) {
47
+ return [`folder: "${part}" is not allowed`]
48
+ }
49
+
50
+ const label = `folder "${part}"`
51
+ return [...checkFileSystemName(label, part), ...checkLinkCharacters(label, part), ...checkEdges(label, part)]
52
+ }
53
+
54
+ function checkMemoryFolderPart(part: string, depth: number): string[] {
55
+ const isReservedRoot = depth === 0 && RESERVED_ROOT_FOLDERS.includes(part.toLowerCase())
56
+ if (isReservedRoot) {
57
+ return [`folder "${part}": is reserved for the vault`]
58
+ }
59
+
60
+ if (part.startsWith(HIDDEN_NAME_PREFIX)) {
61
+ return [`folder "${part}": is hidden (starts with ".")`]
62
+ }
63
+
64
+ return []
65
+ }
@@ -0,0 +1,49 @@
1
+ import type { MemoryPiContext } from "#src/pi/context"
2
+ import {
3
+ type CaptureCadenceSettings,
4
+ type CaptureTally,
5
+ captureSettings,
6
+ EMPTY_TALLY,
7
+ type FlushMoment,
8
+ shouldFlush,
9
+ tallyTurn,
10
+ tallyUserMessage,
11
+ } from "#src/usecases"
12
+ import type { CaptureRuntime } from "./runtime.ts"
13
+ import type { CaptureDeps } from "./types.ts"
14
+
15
+ export class CaptureCadence {
16
+ #runtime: CaptureRuntime
17
+ #deps: Pick<CaptureDeps, "paths" | "sessions">
18
+ #tally: CaptureTally = EMPTY_TALLY
19
+
20
+ constructor(runtime: CaptureRuntime, deps: Pick<CaptureDeps, "paths" | "sessions">) {
21
+ this.#runtime = runtime
22
+ this.#deps = deps
23
+ }
24
+
25
+ userMessageEnded(): void {
26
+ this.#tally = tallyUserMessage(this.#tally)
27
+ }
28
+
29
+ async turnEnded(toolCalls: number, ctx: MemoryPiContext): Promise<void> {
30
+ const settings = await this.#settings(ctx)
31
+ const outcome = tallyTurn(this.#tally, { toolCalls, reviewActive: this.#runtime.reviewActive }, settings)
32
+ this.#tally = outcome.tally
33
+ if (outcome.review) void this.#runtime.request({ ctx, kind: "review" })
34
+ }
35
+
36
+ async flush(moment: FlushMoment, ctx: MemoryPiContext): Promise<void> {
37
+ const settings = await this.#settings(ctx)
38
+ if (!settings || !shouldFlush(this.#tally, settings, moment)) return
39
+ await this.#runtime.request({ ctx, kind: "flush" })
40
+ }
41
+
42
+ async #settings(ctx: MemoryPiContext): Promise<CaptureCadenceSettings | null> {
43
+ const operation = this.#deps.sessions.captureOperation(ctx.cwd, this.#deps.paths)
44
+ if (!operation) return null
45
+ const result = await captureSettings(operation)
46
+ if (!result.succeeded) return null
47
+ return result.output
48
+ }
49
+ }
@@ -0,0 +1,26 @@
1
+ import type { MemoryPiContext } from "#src/pi/context"
2
+ import type { CompletionPort } from "#src/usecases"
3
+ import type { TextPart } from "./types.ts"
4
+
5
+ export function registryCompletion(ctx: MemoryPiContext): CompletionPort {
6
+ return async (request) => {
7
+ const model = ctx.modelRegistry.find(request.model.provider, request.model.id)
8
+ if (!model) return { status: "unsupported" }
9
+ const message = await ctx.modelRegistry.complete(
10
+ model,
11
+ { systemPrompt: request.system, messages: [{ role: "user", content: request.data, timestamp: Date.now() }] },
12
+ { signal: request.signal, maxTokens: model.maxTokens },
13
+ )
14
+ if (message.stopReason === "aborted") return { status: "aborted" }
15
+ if (message.stopReason === "error") {
16
+ if (message.errorMessage) return { status: "error", error: message.errorMessage }
17
+ return { status: "error" }
18
+ }
19
+ const text = message.content.flatMap((part: TextPart) => {
20
+ if (part.type === "text" && typeof part.text === "string") return [part.text]
21
+ return []
22
+ })
23
+ if (text.length === 0) return { status: "empty" }
24
+ return { status: "completed", text: text.join("") }
25
+ }
26
+ }
@@ -0,0 +1,5 @@
1
+ export const CURSOR_TYPE = "obsidian-memory-capture"
2
+
3
+ export const CAPTURE_FAILED = "Memory capture did not finish:"
4
+
5
+ export const CAPTURE_SAVED = "Memory capture applied"
@@ -0,0 +1,30 @@
1
+ import type { SessionShutdownHandler } from "#src/pi/memory-session"
2
+ import type { CaptureCadence } from "./cadence.ts"
3
+ import type { CaptureRuntime } from "./runtime.ts"
4
+ import { toolCallCount } from "./tool-calls.ts"
5
+ import type { BeforeCompactHandler, MessageEndHandler, TurnEndHandler } from "./types.ts"
6
+
7
+ export function messageEndHandler(cadence: CaptureCadence): MessageEndHandler {
8
+ return async (event) => {
9
+ if (event.message.role === "user") cadence.userMessageEnded()
10
+ }
11
+ }
12
+
13
+ export function turnEndHandler(cadence: CaptureCadence): TurnEndHandler {
14
+ return async (event, ctx) => {
15
+ await cadence.turnEnded(toolCallCount(event.message), ctx)
16
+ }
17
+ }
18
+
19
+ export function beforeCompactHandler(cadence: CaptureCadence): BeforeCompactHandler {
20
+ return async (_event, ctx) => {
21
+ await cadence.flush("compact", ctx)
22
+ }
23
+ }
24
+
25
+ export function flushOnShutdownHandler(cadence: CaptureCadence, runtime: CaptureRuntime): SessionShutdownHandler {
26
+ return async (event, ctx) => {
27
+ await runtime.stopReview()
28
+ if (event.reason !== "reload") await cadence.flush("shutdown", ctx)
29
+ }
30
+ }
@@ -0,0 +1,8 @@
1
+ export * from "./cadence.ts"
2
+ export * from "./completion.ts"
3
+ export * from "./constants.ts"
4
+ export * from "./handlers.ts"
5
+ export * from "./runtime.ts"
6
+ export * from "./schemas.ts"
7
+ export * from "./transcript.ts"
8
+ export * from "./types.ts"
@@ -0,0 +1,83 @@
1
+ import { type MemoryPiContext, STATUS_CAPTURING, withMemoryStatus } from "#src/pi/context"
2
+ import { captureMemory } from "#src/usecases"
3
+ import { CAPTURE_FAILED, CAPTURE_SAVED } from "./constants.ts"
4
+ import { reviewableSince } from "./transcript.ts"
5
+ import type { CaptureDeps, PendingCapture } from "./types.ts"
6
+
7
+ export class CaptureRuntime {
8
+ #deps: CaptureDeps
9
+ #running: Promise<void> | null = null
10
+ #current: PendingCapture | null = null
11
+ #pending: PendingCapture[] = []
12
+ #abort = new AbortController()
13
+
14
+ constructor(deps: CaptureDeps) {
15
+ this.#deps = deps
16
+ }
17
+
18
+ get reviewActive(): boolean {
19
+ return [this.#current, ...this.#pending].some((capture) => capture?.kind === "review")
20
+ }
21
+
22
+ async stopReview(): Promise<void> {
23
+ this.#pending = this.#pending.filter((capture) => capture.kind === "flush")
24
+ if (this.#current?.kind === "review") this.#abort.abort()
25
+ await this.#running
26
+ }
27
+
28
+ request(request: PendingCapture): Promise<void> {
29
+ if (this.#running) {
30
+ this.#pending.push(request)
31
+ return this.#running
32
+ }
33
+ const running = this.#drain(request).finally(() => {
34
+ this.#running = null
35
+ })
36
+ this.#running = running
37
+ return running
38
+ }
39
+
40
+ async #drain(first: PendingCapture): Promise<void> {
41
+ let next: PendingCapture | undefined = first
42
+ while (next) {
43
+ this.#current = next
44
+ this.#abort = new AbortController()
45
+ await this.#run(next)
46
+ next = this.#pending.shift()
47
+ }
48
+ this.#current = null
49
+ }
50
+
51
+ async #run(request: PendingCapture): Promise<void> {
52
+ try {
53
+ await this.#review(request)
54
+ } catch (error) {
55
+ if (!(error instanceof Error)) throw error
56
+ notifyFailure(request.ctx, "unexpected", [error.message])
57
+ }
58
+ }
59
+
60
+ async #review({ ctx }: PendingCapture): Promise<void> {
61
+ const captureOperation = this.#deps.sessions.captureOperation(ctx.cwd, this.#deps.paths)
62
+ if (!captureOperation) return
63
+ const { signal } = this.#abort
64
+ const operation = { ...captureOperation, signal: AbortSignal.any([captureOperation.signal, signal]) }
65
+ const transcript = reviewableSince(ctx.sessionManager.getBranch())
66
+ if (transcript.messages.length === 0) return
67
+ const run = { messages: transcript.messages, explicitSaves: transcript.explicitSaves }
68
+ const result = await withMemoryStatus(ctx, STATUS_CAPTURING, () =>
69
+ captureMemory(run, operation, this.#deps.completionOf(ctx)),
70
+ )
71
+ if (!result.succeeded) return notifyFailure(ctx, result.reason, result.problems)
72
+ if (result.output.reviewed && transcript.lastEntryId)
73
+ this.#deps.writeCursor({ lastEntryId: transcript.lastEntryId })
74
+ if (ctx.hasUI && result.output.applied.length > 0) {
75
+ ctx.ui.notify(`${CAPTURE_SAVED} ${result.output.applied.length} change(s).`, "info")
76
+ }
77
+ }
78
+ }
79
+
80
+ function notifyFailure(ctx: MemoryPiContext, reason: string, problems: string[]): void {
81
+ if (!ctx.hasUI || reason === "not-configured" || reason === "interrupted") return
82
+ ctx.ui.notify(`${CAPTURE_FAILED} ${problems.join("; ")}`, "warning")
83
+ }
@@ -0,0 +1,8 @@
1
+ import Type from "typebox"
2
+
3
+ export const AddedDetailsSchema = Type.Object({
4
+ vault: Type.Enum(["global", "project"]),
5
+ path: Type.String({ minLength: 1 }),
6
+ })
7
+
8
+ export const CursorSchema = Type.Object({ lastEntryId: Type.String({ minLength: 1 }) })
@@ -0,0 +1,6 @@
1
+ import type { TurnEndEvent } from "@earendil-works/pi-coding-agent"
2
+
3
+ export function toolCallCount(message: TurnEndEvent["message"]): number {
4
+ if (message.role !== "assistant") return 0
5
+ return message.content.filter((block) => block.type === "toolCall").length
6
+ }
@@ -0,0 +1,55 @@
1
+ import type { SessionEntry } from "@earendil-works/pi-coding-agent"
2
+ import { Value } from "typebox/value"
3
+
4
+ import { MEMORY_ADD_TOOL_NAME } from "#src/pi/memory-add"
5
+ import type { ExplicitSave, TranscriptMessage } from "#src/usecases"
6
+ import { CURSOR_TYPE } from "./constants.ts"
7
+ import { AddedDetailsSchema, CursorSchema } from "./schemas.ts"
8
+ import type { ReviewableTranscript, TextPart } from "./types.ts"
9
+
10
+ export function reviewableSince(entries: SessionEntry[]): ReviewableTranscript {
11
+ const messages: TranscriptMessage[] = []
12
+ const explicitSaves: ExplicitSave[] = []
13
+ for (const entry of afterCursor(entries)) {
14
+ if (entry.type !== "message") continue
15
+ const { message } = entry
16
+ if (message.role === "user") addText(messages, "user", message.content)
17
+ else if (message.role === "assistant") addText(messages, "assistant", message.content)
18
+ else if (message.role === "toolResult" && message.toolName === MEMORY_ADD_TOOL_NAME) {
19
+ if (Value.Check(AddedDetailsSchema, message.details)) explicitSaves.push(message.details)
20
+ }
21
+ }
22
+ const last = entries.at(-1)
23
+ let lastEntryId: string | null = null
24
+ if (last) lastEntryId = last.id
25
+ return { messages, explicitSaves, lastEntryId }
26
+ }
27
+
28
+ function afterCursor(entries: SessionEntry[]): SessionEntry[] {
29
+ const cursor = entries.findLast((entry) => entry.type === "custom" && entry.customType === CURSOR_TYPE)
30
+ if (cursor?.type !== "custom") return entries
31
+ const { data } = cursor
32
+ if (!Value.Check(CursorSchema, data)) return entries
33
+ const index = entries.findIndex((entry) => entry.id === data.lastEntryId)
34
+ if (index === -1) return entries
35
+ return entries.slice(index + 1)
36
+ }
37
+
38
+ function addText(
39
+ messages: TranscriptMessage[],
40
+ role: "user" | "assistant",
41
+ content: string | readonly TextPart[],
42
+ ): void {
43
+ const text = textOf(content)
44
+ if (text.trim() !== "") messages.push({ role, text })
45
+ }
46
+
47
+ function textOf(content: string | readonly TextPart[]): string {
48
+ if (typeof content === "string") return content
49
+ return content
50
+ .flatMap((part) => {
51
+ if (part.type === "text" && typeof part.text === "string") return [part.text]
52
+ return []
53
+ })
54
+ .join("\n")
55
+ }
@@ -0,0 +1,46 @@
1
+ import type { MessageEndEvent, SessionBeforeCompactEvent, TurnEndEvent } from "@earendil-works/pi-coding-agent"
2
+ import type { Static } from "typebox"
3
+
4
+ import type { MemoryPaths, MemoryPiContext } from "#src/pi/context"
5
+ import type { MemorySessionKeeper } from "#src/pi/memory-session"
6
+ import type { CompletionPort, ExplicitSave, TranscriptMessage } from "#src/usecases"
7
+ import type { CursorSchema } from "./schemas.ts"
8
+
9
+ export type CursorData = Static<typeof CursorSchema>
10
+
11
+ export interface ReviewableTranscript {
12
+ messages: TranscriptMessage[]
13
+ explicitSaves: ExplicitSave[]
14
+ lastEntryId: string | null
15
+ }
16
+
17
+ export type CompletionFactory = (ctx: MemoryPiContext) => CompletionPort
18
+
19
+ export type CursorWriter = (data: CursorData) => void
20
+
21
+ export interface CaptureDeps {
22
+ paths: MemoryPaths
23
+ sessions: MemorySessionKeeper
24
+ completionOf: CompletionFactory
25
+ writeCursor: CursorWriter
26
+ }
27
+
28
+ export type CaptureKind = "review" | "flush"
29
+
30
+ export interface PendingCapture {
31
+ ctx: MemoryPiContext
32
+ kind: CaptureKind
33
+ }
34
+
35
+ export interface TextPart {
36
+ type: string
37
+ text?: string
38
+ }
39
+
40
+ export type MessageEndHandler = (event: MessageEndEvent, ctx: MemoryPiContext) => Promise<void>
41
+
42
+ export type TurnEndHandler = (event: TurnEndEvent, ctx: MemoryPiContext) => Promise<void>
43
+
44
+ export type CompactTrigger = Pick<SessionBeforeCompactEvent, "type" | "reason">
45
+
46
+ export type BeforeCompactHandler = (event: CompactTrigger, ctx: MemoryPiContext) => Promise<void>
@@ -0,0 +1,15 @@
1
+ export const NOT_READ_GUIDANCE = "was not read with memory_get in this session. Read it, then call again."
2
+
3
+ export const CONFLICT_GUIDANCE =
4
+ "changed on disk since it was read; the user's edit was kept. Read it again with memory_get."
5
+
6
+ export const STALE_SESSION_GUIDANCE =
7
+ "Not changed: the memory configuration changed during this session. Read the note again with memory_get, then call again."
8
+
9
+ export const PARTIAL_GUIDANCE = "Do not call again; ask the user to check the vault."
10
+
11
+ export const INVALID_HEADING = "Not changed. Fix and call again:"
12
+
13
+ export const NOT_CHANGED_PREFIX = "Not changed:"
14
+
15
+ export const MAINTENANCE_WARNING_PREFIX = "Maintenance warning:"
@@ -0,0 +1,3 @@
1
+ export * from "./constants.ts"
2
+ export * from "./report.ts"
3
+ export * from "./types.ts"