@hasna/mementos 0.14.84 → 0.14.86

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 (556) hide show
  1. package/bun.lock +63 -4
  2. package/dist/cli/index.js +769 -261
  3. package/dist/diagnostics/historical-project-registration-receipt.js +1675 -0
  4. package/dist/index.js +343 -85
  5. package/dist/mcp/index.js +419 -99
  6. package/dist/pg-sync-worker.js +7 -5
  7. package/dist/project-registration.js +309 -68
  8. package/dist/sdk/index.js +123 -30
  9. package/dist/server/index.js +677 -317
  10. package/dist/storage.js +63 -26
  11. package/hasna.contract.json +5 -4
  12. package/package.json +6 -4
  13. package/dist/cli/__fixtures__/clean-fallback-stub-server.d.ts +0 -2
  14. package/dist/cli/__fixtures__/clean-fallback-stub-server.d.ts.map +0 -1
  15. package/dist/cli/brains.d.ts +0 -3
  16. package/dist/cli/brains.d.ts.map +0 -1
  17. package/dist/cli/commands/agent.d.ts +0 -3
  18. package/dist/cli/commands/agent.d.ts.map +0 -1
  19. package/dist/cli/commands/consolidation.d.ts +0 -3
  20. package/dist/cli/commands/consolidation.d.ts.map +0 -1
  21. package/dist/cli/commands/entity.d.ts +0 -3
  22. package/dist/cli/commands/entity.d.ts.map +0 -1
  23. package/dist/cli/commands/graph.d.ts +0 -3
  24. package/dist/cli/commands/graph.d.ts.map +0 -1
  25. package/dist/cli/commands/info-context.d.ts +0 -3
  26. package/dist/cli/commands/info-context.d.ts.map +0 -1
  27. package/dist/cli/commands/info-history.d.ts +0 -3
  28. package/dist/cli/commands/info-history.d.ts.map +0 -1
  29. package/dist/cli/commands/info-report.d.ts +0 -3
  30. package/dist/cli/commands/info-report.d.ts.map +0 -1
  31. package/dist/cli/commands/info-stale.d.ts +0 -3
  32. package/dist/cli/commands/info-stale.d.ts.map +0 -1
  33. package/dist/cli/commands/info-stats.d.ts +0 -3
  34. package/dist/cli/commands/info-stats.d.ts.map +0 -1
  35. package/dist/cli/commands/info.d.ts +0 -12
  36. package/dist/cli/commands/info.d.ts.map +0 -1
  37. package/dist/cli/commands/init.d.ts +0 -3
  38. package/dist/cli/commands/init.d.ts.map +0 -1
  39. package/dist/cli/commands/io-backup.d.ts +0 -3
  40. package/dist/cli/commands/io-backup.d.ts.map +0 -1
  41. package/dist/cli/commands/io-clean.d.ts +0 -3
  42. package/dist/cli/commands/io-clean.d.ts.map +0 -1
  43. package/dist/cli/commands/io-export.d.ts +0 -3
  44. package/dist/cli/commands/io-export.d.ts.map +0 -1
  45. package/dist/cli/commands/io-import.d.ts +0 -3
  46. package/dist/cli/commands/io-import.d.ts.map +0 -1
  47. package/dist/cli/commands/io-restore.d.ts +0 -3
  48. package/dist/cli/commands/io-restore.d.ts.map +0 -1
  49. package/dist/cli/commands/io.d.ts +0 -12
  50. package/dist/cli/commands/io.d.ts.map +0 -1
  51. package/dist/cli/commands/memory-cmd-bulk.d.ts +0 -3
  52. package/dist/cli/commands/memory-cmd-bulk.d.ts.map +0 -1
  53. package/dist/cli/commands/memory-cmd-chain.d.ts +0 -3
  54. package/dist/cli/commands/memory-cmd-chain.d.ts.map +0 -1
  55. package/dist/cli/commands/memory-cmd-crud.d.ts +0 -3
  56. package/dist/cli/commands/memory-cmd-crud.d.ts.map +0 -1
  57. package/dist/cli/commands/memory-cmd-diff.d.ts +0 -3
  58. package/dist/cli/commands/memory-cmd-diff.d.ts.map +0 -1
  59. package/dist/cli/commands/memory-cmd-list.d.ts +0 -3
  60. package/dist/cli/commands/memory-cmd-list.d.ts.map +0 -1
  61. package/dist/cli/commands/memory-cmd-recall-exit.d.ts +0 -3
  62. package/dist/cli/commands/memory-cmd-recall-exit.d.ts.map +0 -1
  63. package/dist/cli/commands/memory-cmd-recall.d.ts +0 -3
  64. package/dist/cli/commands/memory-cmd-recall.d.ts.map +0 -1
  65. package/dist/cli/commands/memory-cmd-remove.d.ts +0 -3
  66. package/dist/cli/commands/memory-cmd-remove.d.ts.map +0 -1
  67. package/dist/cli/commands/memory-cmd-search.d.ts +0 -3
  68. package/dist/cli/commands/memory-cmd-search.d.ts.map +0 -1
  69. package/dist/cli/commands/memory-cmd-tail.d.ts +0 -3
  70. package/dist/cli/commands/memory-cmd-tail.d.ts.map +0 -1
  71. package/dist/cli/commands/memory-cmd-util.d.ts +0 -3
  72. package/dist/cli/commands/memory-cmd-util.d.ts.map +0 -1
  73. package/dist/cli/commands/memory-cmd-view.d.ts +0 -3
  74. package/dist/cli/commands/memory-cmd-view.d.ts.map +0 -1
  75. package/dist/cli/commands/memory-cmd-watch.d.ts +0 -3
  76. package/dist/cli/commands/memory-cmd-watch.d.ts.map +0 -1
  77. package/dist/cli/commands/memory-cmd-when-to-use.d.ts +0 -3
  78. package/dist/cli/commands/memory-cmd-when-to-use.d.ts.map +0 -1
  79. package/dist/cli/commands/memory.d.ts +0 -3
  80. package/dist/cli/commands/memory.d.ts.map +0 -1
  81. package/dist/cli/commands/project-panel.d.ts +0 -3
  82. package/dist/cli/commands/project-panel.d.ts.map +0 -1
  83. package/dist/cli/commands/project.d.ts +0 -3
  84. package/dist/cli/commands/project.d.ts.map +0 -1
  85. package/dist/cli/commands/relation.d.ts +0 -3
  86. package/dist/cli/commands/relation.d.ts.map +0 -1
  87. package/dist/cli/commands/storage.d.ts +0 -3
  88. package/dist/cli/commands/storage.d.ts.map +0 -1
  89. package/dist/cli/commands/system-auto-memory.d.ts +0 -3
  90. package/dist/cli/commands/system-auto-memory.d.ts.map +0 -1
  91. package/dist/cli/commands/system-completions.d.ts +0 -13
  92. package/dist/cli/commands/system-completions.d.ts.map +0 -1
  93. package/dist/cli/commands/system-config.d.ts +0 -3
  94. package/dist/cli/commands/system-config.d.ts.map +0 -1
  95. package/dist/cli/commands/system-doctor.d.ts +0 -3
  96. package/dist/cli/commands/system-doctor.d.ts.map +0 -1
  97. package/dist/cli/commands/system-hooks.d.ts +0 -3
  98. package/dist/cli/commands/system-hooks.d.ts.map +0 -1
  99. package/dist/cli/commands/system-mcp.d.ts +0 -3
  100. package/dist/cli/commands/system-mcp.d.ts.map +0 -1
  101. package/dist/cli/commands/system-misc.d.ts +0 -3
  102. package/dist/cli/commands/system-misc.d.ts.map +0 -1
  103. package/dist/cli/commands/system-profile.d.ts +0 -3
  104. package/dist/cli/commands/system-profile.d.ts.map +0 -1
  105. package/dist/cli/commands/system-session.d.ts +0 -3
  106. package/dist/cli/commands/system-session.d.ts.map +0 -1
  107. package/dist/cli/commands/system-sessions.d.ts +0 -3
  108. package/dist/cli/commands/system-sessions.d.ts.map +0 -1
  109. package/dist/cli/commands/system-synthesis.d.ts +0 -3
  110. package/dist/cli/commands/system-synthesis.d.ts.map +0 -1
  111. package/dist/cli/commands/system-synthesized-profile.d.ts +0 -3
  112. package/dist/cli/commands/system-synthesized-profile.d.ts.map +0 -1
  113. package/dist/cli/commands/system-tools.d.ts +0 -3
  114. package/dist/cli/commands/system-tools.d.ts.map +0 -1
  115. package/dist/cli/commands/system-watch.d.ts +0 -3
  116. package/dist/cli/commands/system-watch.d.ts.map +0 -1
  117. package/dist/cli/commands/system.d.ts +0 -3
  118. package/dist/cli/commands/system.d.ts.map +0 -1
  119. package/dist/cli/exit-codes.d.ts +0 -13
  120. package/dist/cli/exit-codes.d.ts.map +0 -1
  121. package/dist/cli/global-options.d.ts +0 -27
  122. package/dist/cli/global-options.d.ts.map +0 -1
  123. package/dist/cli/helpers.d.ts +0 -119
  124. package/dist/cli/helpers.d.ts.map +0 -1
  125. package/dist/cli/index.d.ts +0 -3
  126. package/dist/cli/index.d.ts.map +0 -1
  127. package/dist/cli/register-all.d.ts +0 -17
  128. package/dist/cli/register-all.d.ts.map +0 -1
  129. package/dist/cli/startup-side-effects.d.ts +0 -9
  130. package/dist/cli/startup-side-effects.d.ts.map +0 -1
  131. package/dist/db/__fixtures__/fail-closed-stub-server.d.ts +0 -2
  132. package/dist/db/__fixtures__/fail-closed-stub-server.d.ts.map +0 -1
  133. package/dist/db/acl.d.ts +0 -34
  134. package/dist/db/acl.d.ts.map +0 -1
  135. package/dist/db/agents.d.ts +0 -21
  136. package/dist/db/agents.d.ts.map +0 -1
  137. package/dist/db/analytics.d.ts +0 -107
  138. package/dist/db/analytics.d.ts.map +0 -1
  139. package/dist/db/api-mode.d.ts +0 -127
  140. package/dist/db/api-mode.d.ts.map +0 -1
  141. package/dist/db/audit.d.ts +0 -53
  142. package/dist/db/audit.d.ts.map +0 -1
  143. package/dist/db/database.d.ts +0 -26
  144. package/dist/db/database.d.ts.map +0 -1
  145. package/dist/db/entities.d.ts +0 -62
  146. package/dist/db/entities.d.ts.map +0 -1
  147. package/dist/db/entity-memories.d.ts +0 -34
  148. package/dist/db/entity-memories.d.ts.map +0 -1
  149. package/dist/db/feedback.d.ts +0 -9
  150. package/dist/db/feedback.d.ts.map +0 -1
  151. package/dist/db/locks.d.ts +0 -63
  152. package/dist/db/locks.d.ts.map +0 -1
  153. package/dist/db/machines.d.ts +0 -23
  154. package/dist/db/machines.d.ts.map +0 -1
  155. package/dist/db/memories.d.ts +0 -137
  156. package/dist/db/memories.d.ts.map +0 -1
  157. package/dist/db/memory-links.d.ts +0 -21
  158. package/dist/db/memory-links.d.ts.map +0 -1
  159. package/dist/db/memory-project-link.d.ts +0 -13
  160. package/dist/db/memory-project-link.d.ts.map +0 -1
  161. package/dist/db/migrations.d.ts +0 -3
  162. package/dist/db/migrations.d.ts.map +0 -1
  163. package/dist/db/pg-migrate.d.ts +0 -27
  164. package/dist/db/pg-migrate.d.ts.map +0 -1
  165. package/dist/db/pg-migrations.d.ts +0 -2
  166. package/dist/db/pg-migrations.d.ts.map +0 -1
  167. package/dist/db/projects.d.ts +0 -27
  168. package/dist/db/projects.d.ts.map +0 -1
  169. package/dist/db/ratings.d.ts +0 -23
  170. package/dist/db/ratings.d.ts.map +0 -1
  171. package/dist/db/relations.d.ts +0 -49
  172. package/dist/db/relations.d.ts.map +0 -1
  173. package/dist/db/session-jobs.d.ts +0 -49
  174. package/dist/db/session-jobs.d.ts.map +0 -1
  175. package/dist/db/store-backend.d.ts +0 -42
  176. package/dist/db/store-backend.d.ts.map +0 -1
  177. package/dist/db/subscriptions.d.ts +0 -24
  178. package/dist/db/subscriptions.d.ts.map +0 -1
  179. package/dist/db/synthesis.d.ts +0 -101
  180. package/dist/db/synthesis.d.ts.map +0 -1
  181. package/dist/db/tasks.d.ts +0 -89
  182. package/dist/db/tasks.d.ts.map +0 -1
  183. package/dist/db/tool-events.d.ts +0 -27
  184. package/dist/db/tool-events.d.ts.map +0 -1
  185. package/dist/db/webhook_hooks.d.ts +0 -25
  186. package/dist/db/webhook_hooks.d.ts.map +0 -1
  187. package/dist/generated/storage-kit/backend.d.ts +0 -20
  188. package/dist/generated/storage-kit/backend.d.ts.map +0 -1
  189. package/dist/generated/storage-kit/health.d.ts +0 -20
  190. package/dist/generated/storage-kit/health.d.ts.map +0 -1
  191. package/dist/generated/storage-kit/index.d.ts +0 -8
  192. package/dist/generated/storage-kit/index.d.ts.map +0 -1
  193. package/dist/generated/storage-kit/migrations.d.ts +0 -48
  194. package/dist/generated/storage-kit/migrations.d.ts.map +0 -1
  195. package/dist/generated/storage-kit/own.d.ts +0 -11
  196. package/dist/generated/storage-kit/own.d.ts.map +0 -1
  197. package/dist/generated/storage-kit/pool.d.ts +0 -35
  198. package/dist/generated/storage-kit/pool.d.ts.map +0 -1
  199. package/dist/generated/storage-kit/query.d.ts +0 -36
  200. package/dist/generated/storage-kit/query.d.ts.map +0 -1
  201. package/dist/generated/storage-kit/tls.d.ts +0 -53
  202. package/dist/generated/storage-kit/tls.d.ts.map +0 -1
  203. package/dist/index.d.ts +0 -45
  204. package/dist/index.d.ts.map +0 -1
  205. package/dist/lib/activation-matcher.d.ts +0 -17
  206. package/dist/lib/activation-matcher.d.ts.map +0 -1
  207. package/dist/lib/asmr/categorizer.d.ts +0 -31
  208. package/dist/lib/asmr/categorizer.d.ts.map +0 -1
  209. package/dist/lib/asmr/context-agent.d.ts +0 -4
  210. package/dist/lib/asmr/context-agent.d.ts.map +0 -1
  211. package/dist/lib/asmr/ensemble.d.ts +0 -23
  212. package/dist/lib/asmr/ensemble.d.ts.map +0 -1
  213. package/dist/lib/asmr/fact-agent.d.ts +0 -4
  214. package/dist/lib/asmr/fact-agent.d.ts.map +0 -1
  215. package/dist/lib/asmr/index.d.ts +0 -7
  216. package/dist/lib/asmr/index.d.ts.map +0 -1
  217. package/dist/lib/asmr/orchestrator.d.ts +0 -4
  218. package/dist/lib/asmr/orchestrator.d.ts.map +0 -1
  219. package/dist/lib/asmr/recall.d.ts +0 -3
  220. package/dist/lib/asmr/recall.d.ts.map +0 -1
  221. package/dist/lib/asmr/temporal-agent.d.ts +0 -4
  222. package/dist/lib/asmr/temporal-agent.d.ts.map +0 -1
  223. package/dist/lib/asmr/types.d.ts +0 -27
  224. package/dist/lib/asmr/types.d.ts.map +0 -1
  225. package/dist/lib/auto-inject-orchestrator.d.ts +0 -57
  226. package/dist/lib/auto-inject-orchestrator.d.ts.map +0 -1
  227. package/dist/lib/auto-memory-queue.d.ts +0 -48
  228. package/dist/lib/auto-memory-queue.d.ts.map +0 -1
  229. package/dist/lib/auto-memory.d.ts +0 -19
  230. package/dist/lib/auto-memory.d.ts.map +0 -1
  231. package/dist/lib/bench.d.ts +0 -20
  232. package/dist/lib/bench.d.ts.map +0 -1
  233. package/dist/lib/built-in-hooks.d.ts +0 -12
  234. package/dist/lib/built-in-hooks.d.ts.map +0 -1
  235. package/dist/lib/channel-pusher.d.ts +0 -39
  236. package/dist/lib/channel-pusher.d.ts.map +0 -1
  237. package/dist/lib/config.d.ts +0 -9
  238. package/dist/lib/config.d.ts.map +0 -1
  239. package/dist/lib/connectors/files.d.ts +0 -8
  240. package/dist/lib/connectors/files.d.ts.map +0 -1
  241. package/dist/lib/connectors/github.d.ts +0 -7
  242. package/dist/lib/connectors/github.d.ts.map +0 -1
  243. package/dist/lib/connectors/index.d.ts +0 -12
  244. package/dist/lib/connectors/index.d.ts.map +0 -1
  245. package/dist/lib/connectors/notion.d.ts +0 -7
  246. package/dist/lib/connectors/notion.d.ts.map +0 -1
  247. package/dist/lib/connectors/types.d.ts +0 -27
  248. package/dist/lib/connectors/types.d.ts.map +0 -1
  249. package/dist/lib/consolidation.d.ts +0 -52
  250. package/dist/lib/consolidation.d.ts.map +0 -1
  251. package/dist/lib/context-extractor.d.ts +0 -14
  252. package/dist/lib/context-extractor.d.ts.map +0 -1
  253. package/dist/lib/context.d.ts +0 -36
  254. package/dist/lib/context.d.ts.map +0 -1
  255. package/dist/lib/contradiction.d.ts +0 -50
  256. package/dist/lib/contradiction.d.ts.map +0 -1
  257. package/dist/lib/decay.d.ts +0 -35
  258. package/dist/lib/decay.d.ts.map +0 -1
  259. package/dist/lib/dedup.d.ts +0 -33
  260. package/dist/lib/dedup.d.ts.map +0 -1
  261. package/dist/lib/duration.d.ts +0 -28
  262. package/dist/lib/duration.d.ts.map +0 -1
  263. package/dist/lib/embeddings.d.ts +0 -20
  264. package/dist/lib/embeddings.d.ts.map +0 -1
  265. package/dist/lib/enum-validation.d.ts +0 -20
  266. package/dist/lib/enum-validation.d.ts.map +0 -1
  267. package/dist/lib/export-v1.d.ts +0 -30
  268. package/dist/lib/export-v1.d.ts.map +0 -1
  269. package/dist/lib/extractor.d.ts +0 -9
  270. package/dist/lib/extractor.d.ts.map +0 -1
  271. package/dist/lib/extractors/audio.d.ts +0 -8
  272. package/dist/lib/extractors/audio.d.ts.map +0 -1
  273. package/dist/lib/extractors/index.d.ts +0 -12
  274. package/dist/lib/extractors/index.d.ts.map +0 -1
  275. package/dist/lib/extractors/ocr.d.ts +0 -7
  276. package/dist/lib/extractors/ocr.d.ts.map +0 -1
  277. package/dist/lib/extractors/pdf.d.ts +0 -7
  278. package/dist/lib/extractors/pdf.d.ts.map +0 -1
  279. package/dist/lib/extractors/types.d.ts +0 -12
  280. package/dist/lib/extractors/types.d.ts.map +0 -1
  281. package/dist/lib/file-deps.d.ts +0 -27
  282. package/dist/lib/file-deps.d.ts.map +0 -1
  283. package/dist/lib/focus.d.ts +0 -58
  284. package/dist/lib/focus.d.ts.map +0 -1
  285. package/dist/lib/gatherer.d.ts +0 -16
  286. package/dist/lib/gatherer.d.ts.map +0 -1
  287. package/dist/lib/gdpr.d.ts +0 -39
  288. package/dist/lib/gdpr.d.ts.map +0 -1
  289. package/dist/lib/hooks.d.ts +0 -50
  290. package/dist/lib/hooks.d.ts.map +0 -1
  291. package/dist/lib/importers/index.d.ts +0 -38
  292. package/dist/lib/importers/index.d.ts.map +0 -1
  293. package/dist/lib/injector.d.ts +0 -89
  294. package/dist/lib/injector.d.ts.map +0 -1
  295. package/dist/lib/machine-visibility.d.ts +0 -6
  296. package/dist/lib/machine-visibility.d.ts.map +0 -1
  297. package/dist/lib/matryoshka.d.ts +0 -50
  298. package/dist/lib/matryoshka.d.ts.map +0 -1
  299. package/dist/lib/memory-lock.d.ts +0 -58
  300. package/dist/lib/memory-lock.d.ts.map +0 -1
  301. package/dist/lib/model-config.d.ts +0 -14
  302. package/dist/lib/model-config.d.ts.map +0 -1
  303. package/dist/lib/open-sessions-connector.d.ts +0 -60
  304. package/dist/lib/open-sessions-connector.d.ts.map +0 -1
  305. package/dist/lib/package-version.d.ts +0 -3
  306. package/dist/lib/package-version.d.ts.map +0 -1
  307. package/dist/lib/poisoning.d.ts +0 -19
  308. package/dist/lib/poisoning.d.ts.map +0 -1
  309. package/dist/lib/poll.d.ts +0 -17
  310. package/dist/lib/poll.d.ts.map +0 -1
  311. package/dist/lib/procedural-extractor.d.ts +0 -21
  312. package/dist/lib/procedural-extractor.d.ts.map +0 -1
  313. package/dist/lib/profile-sync.d.ts +0 -20
  314. package/dist/lib/profile-sync.d.ts.map +0 -1
  315. package/dist/lib/profile-synthesizer.d.ts +0 -20
  316. package/dist/lib/profile-synthesizer.d.ts.map +0 -1
  317. package/dist/lib/project-detect.d.ts +0 -18
  318. package/dist/lib/project-detect.d.ts.map +0 -1
  319. package/dist/lib/project-panel.d.ts +0 -7
  320. package/dist/lib/project-panel.d.ts.map +0 -1
  321. package/dist/lib/providers/anthropic.d.ts +0 -21
  322. package/dist/lib/providers/anthropic.d.ts.map +0 -1
  323. package/dist/lib/providers/base.d.ts +0 -96
  324. package/dist/lib/providers/base.d.ts.map +0 -1
  325. package/dist/lib/providers/cerebras.d.ts +0 -20
  326. package/dist/lib/providers/cerebras.d.ts.map +0 -1
  327. package/dist/lib/providers/grok.d.ts +0 -19
  328. package/dist/lib/providers/grok.d.ts.map +0 -1
  329. package/dist/lib/providers/index.d.ts +0 -7
  330. package/dist/lib/providers/index.d.ts.map +0 -1
  331. package/dist/lib/providers/openai-compat.d.ts +0 -18
  332. package/dist/lib/providers/openai-compat.d.ts.map +0 -1
  333. package/dist/lib/providers/openai.d.ts +0 -20
  334. package/dist/lib/providers/openai.d.ts.map +0 -1
  335. package/dist/lib/providers/registry.d.ts +0 -38
  336. package/dist/lib/providers/registry.d.ts.map +0 -1
  337. package/dist/lib/quality.d.ts +0 -16
  338. package/dist/lib/quality.d.ts.map +0 -1
  339. package/dist/lib/redact.d.ts +0 -10
  340. package/dist/lib/redact.d.ts.map +0 -1
  341. package/dist/lib/reflection.d.ts +0 -83
  342. package/dist/lib/reflection.d.ts.map +0 -1
  343. package/dist/lib/retention.d.ts +0 -17
  344. package/dist/lib/retention.d.ts.map +0 -1
  345. package/dist/lib/retired-storage-mode.d.ts +0 -11
  346. package/dist/lib/retired-storage-mode.d.ts.map +0 -1
  347. package/dist/lib/search.d.ts +0 -52
  348. package/dist/lib/search.d.ts.map +0 -1
  349. package/dist/lib/session-auto-resolve.d.ts +0 -28
  350. package/dist/lib/session-auto-resolve.d.ts.map +0 -1
  351. package/dist/lib/session-processor.d.ts +0 -38
  352. package/dist/lib/session-processor.d.ts.map +0 -1
  353. package/dist/lib/session-queue.d.ts +0 -28
  354. package/dist/lib/session-queue.d.ts.map +0 -1
  355. package/dist/lib/session-registry.d.ts +0 -47
  356. package/dist/lib/session-registry.d.ts.map +0 -1
  357. package/dist/lib/session-start-briefing.d.ts +0 -10
  358. package/dist/lib/session-start-briefing.d.ts.map +0 -1
  359. package/dist/lib/session-watcher.d.ts +0 -30
  360. package/dist/lib/session-watcher.d.ts.map +0 -1
  361. package/dist/lib/storage-sync.d.ts +0 -45
  362. package/dist/lib/storage-sync.d.ts.map +0 -1
  363. package/dist/lib/sync.d.ts +0 -10
  364. package/dist/lib/sync.d.ts.map +0 -1
  365. package/dist/lib/synthesis/corpus-builder.d.ts +0 -30
  366. package/dist/lib/synthesis/corpus-builder.d.ts.map +0 -1
  367. package/dist/lib/synthesis/executor.d.ts +0 -14
  368. package/dist/lib/synthesis/executor.d.ts.map +0 -1
  369. package/dist/lib/synthesis/index.d.ts +0 -37
  370. package/dist/lib/synthesis/index.d.ts.map +0 -1
  371. package/dist/lib/synthesis/llm-analyzer.d.ts +0 -18
  372. package/dist/lib/synthesis/llm-analyzer.d.ts.map +0 -1
  373. package/dist/lib/synthesis/metrics.d.ts +0 -13
  374. package/dist/lib/synthesis/metrics.d.ts.map +0 -1
  375. package/dist/lib/synthesis/scheduler.d.ts +0 -18
  376. package/dist/lib/synthesis/scheduler.d.ts.map +0 -1
  377. package/dist/lib/synthesis/validator.d.ts +0 -19
  378. package/dist/lib/synthesis/validator.d.ts.map +0 -1
  379. package/dist/lib/task-runner.d.ts +0 -37
  380. package/dist/lib/task-runner.d.ts.map +0 -1
  381. package/dist/lib/tool-lesson-extractor.d.ts +0 -24
  382. package/dist/lib/tool-lesson-extractor.d.ts.map +0 -1
  383. package/dist/lib/tool-memory-synthesizer.d.ts +0 -28
  384. package/dist/lib/tool-memory-synthesizer.d.ts.map +0 -1
  385. package/dist/lib/topic-clusterer.d.ts +0 -21
  386. package/dist/lib/topic-clusterer.d.ts.map +0 -1
  387. package/dist/lib/when-to-use-generator.d.ts +0 -22
  388. package/dist/lib/when-to-use-generator.d.ts.map +0 -1
  389. package/dist/mcp/http.d.ts +0 -17
  390. package/dist/mcp/http.d.ts.map +0 -1
  391. package/dist/mcp/index.d.ts +0 -6
  392. package/dist/mcp/index.d.ts.map +0 -1
  393. package/dist/mcp/memory-broadcast.d.ts +0 -12
  394. package/dist/mcp/memory-broadcast.d.ts.map +0 -1
  395. package/dist/mcp/tools/agent-tools.d.ts +0 -3
  396. package/dist/mcp/tools/agent-tools.d.ts.map +0 -1
  397. package/dist/mcp/tools/auto-memory-tools.d.ts +0 -5
  398. package/dist/mcp/tools/auto-memory-tools.d.ts.map +0 -1
  399. package/dist/mcp/tools/bulk-tools.d.ts +0 -3
  400. package/dist/mcp/tools/bulk-tools.d.ts.map +0 -1
  401. package/dist/mcp/tools/consolidation-tools.d.ts +0 -3
  402. package/dist/mcp/tools/consolidation-tools.d.ts.map +0 -1
  403. package/dist/mcp/tools/focus-tools.d.ts +0 -3
  404. package/dist/mcp/tools/focus-tools.d.ts.map +0 -1
  405. package/dist/mcp/tools/graph-entity-tools.d.ts +0 -3
  406. package/dist/mcp/tools/graph-entity-tools.d.ts.map +0 -1
  407. package/dist/mcp/tools/graph-query-tools.d.ts +0 -3
  408. package/dist/mcp/tools/graph-query-tools.d.ts.map +0 -1
  409. package/dist/mcp/tools/graph-relation-tools.d.ts +0 -3
  410. package/dist/mcp/tools/graph-relation-tools.d.ts.map +0 -1
  411. package/dist/mcp/tools/graph-tools.d.ts +0 -3
  412. package/dist/mcp/tools/graph-tools.d.ts.map +0 -1
  413. package/dist/mcp/tools/graph-utils.d.ts +0 -5
  414. package/dist/mcp/tools/graph-utils.d.ts.map +0 -1
  415. package/dist/mcp/tools/hook-tools.d.ts +0 -3
  416. package/dist/mcp/tools/hook-tools.d.ts.map +0 -1
  417. package/dist/mcp/tools/lock-tools.d.ts +0 -3
  418. package/dist/mcp/tools/lock-tools.d.ts.map +0 -1
  419. package/dist/mcp/tools/memory-audit.d.ts +0 -3
  420. package/dist/mcp/tools/memory-audit.d.ts.map +0 -1
  421. package/dist/mcp/tools/memory-crud.d.ts +0 -3
  422. package/dist/mcp/tools/memory-crud.d.ts.map +0 -1
  423. package/dist/mcp/tools/memory-health.d.ts +0 -3
  424. package/dist/mcp/tools/memory-health.d.ts.map +0 -1
  425. package/dist/mcp/tools/memory-history.d.ts +0 -3
  426. package/dist/mcp/tools/memory-history.d.ts.map +0 -1
  427. package/dist/mcp/tools/memory-inject.d.ts +0 -3
  428. package/dist/mcp/tools/memory-inject.d.ts.map +0 -1
  429. package/dist/mcp/tools/memory-io.d.ts +0 -3
  430. package/dist/mcp/tools/memory-io.d.ts.map +0 -1
  431. package/dist/mcp/tools/memory-lifecycle.d.ts +0 -3
  432. package/dist/mcp/tools/memory-lifecycle.d.ts.map +0 -1
  433. package/dist/mcp/tools/memory-search.d.ts +0 -3
  434. package/dist/mcp/tools/memory-search.d.ts.map +0 -1
  435. package/dist/mcp/tools/memory-stats.d.ts +0 -3
  436. package/dist/mcp/tools/memory-stats.d.ts.map +0 -1
  437. package/dist/mcp/tools/memory-tools.d.ts +0 -17
  438. package/dist/mcp/tools/memory-tools.d.ts.map +0 -1
  439. package/dist/mcp/tools/memory-utils.d.ts +0 -27
  440. package/dist/mcp/tools/memory-utils.d.ts.map +0 -1
  441. package/dist/mcp/tools/memory-validation.d.ts +0 -3
  442. package/dist/mcp/tools/memory-validation.d.ts.map +0 -1
  443. package/dist/mcp/tools/project-tools.d.ts +0 -3
  444. package/dist/mcp/tools/project-tools.d.ts.map +0 -1
  445. package/dist/mcp/tools/session-tools.d.ts +0 -3
  446. package/dist/mcp/tools/session-tools.d.ts.map +0 -1
  447. package/dist/mcp/tools/storage-tools.d.ts +0 -3
  448. package/dist/mcp/tools/storage-tools.d.ts.map +0 -1
  449. package/dist/mcp/tools/synthesis-tools.d.ts +0 -3
  450. package/dist/mcp/tools/synthesis-tools.d.ts.map +0 -1
  451. package/dist/mcp/tools/system-tools-events.d.ts +0 -3
  452. package/dist/mcp/tools/system-tools-events.d.ts.map +0 -1
  453. package/dist/mcp/tools/system-tools-memory-admin.d.ts +0 -3
  454. package/dist/mcp/tools/system-tools-memory-admin.d.ts.map +0 -1
  455. package/dist/mcp/tools/system-tools-shared.d.ts +0 -23
  456. package/dist/mcp/tools/system-tools-shared.d.ts.map +0 -1
  457. package/dist/mcp/tools/system-tools.d.ts +0 -3
  458. package/dist/mcp/tools/system-tools.d.ts.map +0 -1
  459. package/dist/mcp/tools/tool-registry.d.ts +0 -30
  460. package/dist/mcp/tools/tool-registry.d.ts.map +0 -1
  461. package/dist/mcp/tools/utility-tools.d.ts +0 -3
  462. package/dist/mcp/tools/utility-tools.d.ts.map +0 -1
  463. package/dist/memory-project-link/index.d.ts +0 -2
  464. package/dist/memory-project-link/index.d.ts.map +0 -1
  465. package/dist/memory-project-link/schema.d.ts +0 -5
  466. package/dist/memory-project-link/schema.d.ts.map +0 -1
  467. package/dist/pg-sync-worker.d.ts +0 -2
  468. package/dist/pg-sync-worker.d.ts.map +0 -1
  469. package/dist/project-registration/authority.d.ts +0 -43
  470. package/dist/project-registration/authority.d.ts.map +0 -1
  471. package/dist/project-registration/http.d.ts +0 -32
  472. package/dist/project-registration/http.d.ts.map +0 -1
  473. package/dist/project-registration/identity.d.ts +0 -20
  474. package/dist/project-registration/identity.d.ts.map +0 -1
  475. package/dist/project-registration/index.d.ts +0 -11
  476. package/dist/project-registration/index.d.ts.map +0 -1
  477. package/dist/project-registration/project-references.d.ts +0 -71
  478. package/dist/project-registration/project-references.d.ts.map +0 -1
  479. package/dist/project-registration/project-resources.d.ts +0 -22
  480. package/dist/project-registration/project-resources.d.ts.map +0 -1
  481. package/dist/project-registration/schema.d.ts +0 -5
  482. package/dist/project-registration/schema.d.ts.map +0 -1
  483. package/dist/project-registration/types.d.ts +0 -293
  484. package/dist/project-registration/types.d.ts.map +0 -1
  485. package/dist/project-registration.d.ts +0 -2
  486. package/dist/project-registration.d.ts.map +0 -1
  487. package/dist/sdk/index.d.ts +0 -971
  488. package/dist/sdk/index.d.ts.map +0 -1
  489. package/dist/server/auth.d.ts +0 -11
  490. package/dist/server/auth.d.ts.map +0 -1
  491. package/dist/server/helpers.d.ts +0 -22
  492. package/dist/server/helpers.d.ts.map +0 -1
  493. package/dist/server/index.d.ts +0 -14
  494. package/dist/server/index.d.ts.map +0 -1
  495. package/dist/server/openapi.d.ts +0 -2
  496. package/dist/server/openapi.d.ts.map +0 -1
  497. package/dist/server/router.d.ts +0 -17
  498. package/dist/server/router.d.ts.map +0 -1
  499. package/dist/server/routes/agents.d.ts +0 -2
  500. package/dist/server/routes/agents.d.ts.map +0 -1
  501. package/dist/server/routes/entities.d.ts +0 -2
  502. package/dist/server/routes/entities.d.ts.map +0 -1
  503. package/dist/server/routes/memories-bulk.d.ts +0 -2
  504. package/dist/server/routes/memories-bulk.d.ts.map +0 -1
  505. package/dist/server/routes/memories-crud.d.ts +0 -2
  506. package/dist/server/routes/memories-crud.d.ts.map +0 -1
  507. package/dist/server/routes/memories-io.d.ts +0 -2
  508. package/dist/server/routes/memories-io.d.ts.map +0 -1
  509. package/dist/server/routes/memories-misc.d.ts +0 -2
  510. package/dist/server/routes/memories-misc.d.ts.map +0 -1
  511. package/dist/server/routes/memories-search.d.ts +0 -2
  512. package/dist/server/routes/memories-search.d.ts.map +0 -1
  513. package/dist/server/routes/memories-stats.d.ts +0 -2
  514. package/dist/server/routes/memories-stats.d.ts.map +0 -1
  515. package/dist/server/routes/memories.d.ts +0 -19
  516. package/dist/server/routes/memories.d.ts.map +0 -1
  517. package/dist/server/routes/memory-project-link.d.ts +0 -2
  518. package/dist/server/routes/memory-project-link.d.ts.map +0 -1
  519. package/dist/server/routes/project-registration.d.ts +0 -2
  520. package/dist/server/routes/project-registration.d.ts.map +0 -1
  521. package/dist/server/routes/projects.d.ts +0 -2
  522. package/dist/server/routes/projects.d.ts.map +0 -1
  523. package/dist/server/routes/system-auto-memory.d.ts +0 -2
  524. package/dist/server/routes/system-auto-memory.d.ts.map +0 -1
  525. package/dist/server/routes/system-chain.d.ts +0 -2
  526. package/dist/server/routes/system-chain.d.ts.map +0 -1
  527. package/dist/server/routes/system-consolidation.d.ts +0 -2
  528. package/dist/server/routes/system-consolidation.d.ts.map +0 -1
  529. package/dist/server/routes/system-hooks.d.ts +0 -2
  530. package/dist/server/routes/system-hooks.d.ts.map +0 -1
  531. package/dist/server/routes/system-sessions.d.ts +0 -2
  532. package/dist/server/routes/system-sessions.d.ts.map +0 -1
  533. package/dist/server/routes/system-subscriptions.d.ts +0 -2
  534. package/dist/server/routes/system-subscriptions.d.ts.map +0 -1
  535. package/dist/server/routes/system-synthesis.d.ts +0 -2
  536. package/dist/server/routes/system-synthesis.d.ts.map +0 -1
  537. package/dist/server/routes/system-tools.d.ts +0 -2
  538. package/dist/server/routes/system-tools.d.ts.map +0 -1
  539. package/dist/server/routes/system.d.ts +0 -2
  540. package/dist/server/routes/system.d.ts.map +0 -1
  541. package/dist/server/routes/tasks.d.ts +0 -2
  542. package/dist/server/routes/tasks.d.ts.map +0 -1
  543. package/dist/storage.d.ts +0 -266
  544. package/dist/storage.d.ts.map +0 -1
  545. package/dist/test-support/preload-local-store.d.ts +0 -2
  546. package/dist/test-support/preload-local-store.d.ts.map +0 -1
  547. package/dist/test-support/project-authority-identity.d.ts +0 -8
  548. package/dist/test-support/project-authority-identity.d.ts.map +0 -1
  549. package/dist/test-support/store-isolation.d.ts +0 -108
  550. package/dist/test-support/store-isolation.d.ts.map +0 -1
  551. package/dist/test-support/strip-ansi.d.ts +0 -3
  552. package/dist/test-support/strip-ansi.d.ts.map +0 -1
  553. package/dist/types/hooks.d.ts +0 -136
  554. package/dist/types/hooks.d.ts.map +0 -1
  555. package/dist/types/index.d.ts +0 -472
  556. package/dist/types/index.d.ts.map +0 -1
@@ -243,6 +243,7 @@ function translateSql(sql) {
243
243
  let translated = sql.replace(/\?/g, () => `$${++parameterIndex}`);
244
244
  const ISO_FMT = `'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'`;
245
245
  translated = translated.replace(/datetime\s*\(\s*'now'\s*\)/gi, `to_char(now() AT TIME ZONE 'UTC', ${ISO_FMT})`);
246
+ translated = translated.replace(/strftime\s*\(\s*'%Y-%m-%dT%H:%M:%fZ'\s*,\s*'now'\s*\)/gi, `to_char(now() AT TIME ZONE 'UTC', ${ISO_FMT})`);
246
247
  translated = translated.replace(/datetime\s*\(\s*'now'\s*,\s*'(-?\d+)\s+(minutes?|hours?|days?|seconds?)'\s*\)/gi, (_match, amount, unit) => {
247
248
  const parsed = parseInt(String(amount), 10);
248
249
  const absolute = Math.abs(parsed);
@@ -524,8 +525,13 @@ var init_storage = __esm(() => {
524
525
  data;
525
526
  closed = false;
526
527
  lastError = null;
528
+ generation = 0;
527
529
  static DATA_BYTES = 128 * 1024 * 1024;
528
- static QUERY_TIMEOUT_MS = 60000;
530
+ static queryTimeoutMs() {
531
+ const raw = process.env["MEMENTOS_PGSYNC_QUERY_TIMEOUT_MS"]?.trim();
532
+ const parsed = raw ? Number(raw) : Number.NaN;
533
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 60000;
534
+ }
529
535
  static resolveWorkerPath() {
530
536
  const ext = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
531
537
  const here = fileURLToPath(new URL(".", import.meta.url));
@@ -540,12 +546,12 @@ var init_storage = __esm(() => {
540
546
  }
541
547
  return candidates[0];
542
548
  }
543
- constructor(connectionString) {
544
- const control = new SharedArrayBuffer(8);
549
+ constructor(connectionString, workerPath) {
550
+ const control = new SharedArrayBuffer(12);
545
551
  const dataSab = new SharedArrayBuffer(PgSyncPool.DATA_BYTES);
546
552
  this.status = new Int32Array(control);
547
553
  this.data = new Uint8Array(dataSab);
548
- this.worker = new Worker(PgSyncPool.resolveWorkerPath(), {
554
+ this.worker = new Worker(workerPath ?? PgSyncPool.resolveWorkerPath(), {
549
555
  workerData: {
550
556
  dsn: stripSslParams(connectionString),
551
557
  ssl: sslConfigFor(connectionString),
@@ -563,21 +569,35 @@ var init_storage = __esm(() => {
563
569
  throw new Error("PgSyncPool is closed");
564
570
  if (this.lastError)
565
571
  throw this.lastError;
572
+ const timeoutMs = PgSyncPool.queryTimeoutMs();
573
+ const gen = ++this.generation;
566
574
  Atomics.store(this.status, 0, 0);
567
- this.worker.postMessage({ sql, params });
568
- const waitResult = Atomics.wait(this.status, 0, 0, PgSyncPool.QUERY_TIMEOUT_MS);
569
- const code = Atomics.load(this.status, 0);
570
- if (code === 0 || waitResult === "timed-out") {
571
- if (this.lastError)
572
- throw this.lastError;
573
- throw new Error("PostgreSQL query timed out after 60s");
574
- }
575
- const len = Atomics.load(this.status, 1);
576
- const payload = JSON.parse(new TextDecoder().decode(this.data.subarray(0, len)));
577
- if (code === 2) {
578
- throw new Error(payload.message ?? "PostgreSQL error");
575
+ Atomics.store(this.status, 2, 0);
576
+ this.worker.postMessage({ sql, params, gen });
577
+ const deadline = Date.now() + timeoutMs;
578
+ for (;; ) {
579
+ const remaining = deadline - Date.now();
580
+ const responding = Atomics.load(this.status, 0);
581
+ if (responding === gen) {
582
+ const code = Atomics.load(this.status, 2);
583
+ const len = Atomics.load(this.status, 1);
584
+ const payload = JSON.parse(new TextDecoder().decode(this.data.subarray(0, len)));
585
+ if (code === 2) {
586
+ throw new Error(payload.message ?? "PostgreSQL error");
587
+ }
588
+ return payload;
589
+ }
590
+ if (responding !== 0) {
591
+ Atomics.compareExchange(this.status, 0, responding, 0);
592
+ continue;
593
+ }
594
+ if (remaining <= 0) {
595
+ if (this.lastError)
596
+ throw this.lastError;
597
+ throw new Error(`PostgreSQL query timed out after ${timeoutMs}ms`);
598
+ }
599
+ Atomics.wait(this.status, 0, 0, remaining);
579
600
  }
580
- return payload;
581
601
  }
582
602
  end() {
583
603
  if (this.closed)
@@ -780,7 +800,16 @@ x-api-key: ${cfg.apiKey}
780
800
  function apiJson(method, path, body, options) {
781
801
  const raw = apiRequestRaw(method, path, body);
782
802
  if (raw.status >= 200 && raw.status < 300) {
783
- const data = raw.body.trim() ? JSON.parse(raw.body) : undefined;
803
+ let data;
804
+ if (raw.body.trim()) {
805
+ try {
806
+ data = JSON.parse(raw.body);
807
+ } catch (e) {
808
+ throw new ApiRequestError(`mementos cloud ${method} ${path} returned status ${raw.status} with a body that is not valid JSON (${e instanceof Error ? e.message : String(e)}) \u2014 the response is truncated or the server is unhealthy`, raw.status, raw.body.slice(0, 500));
809
+ }
810
+ } else {
811
+ data = undefined;
812
+ }
784
813
  return { status: raw.status, data };
785
814
  }
786
815
  if (raw.status === 404 && options?.allow404) {
@@ -2695,8 +2724,12 @@ __export(exports_memories, {
2695
2724
  updateMemory: () => updateMemory,
2696
2725
  touchMemory: () => touchMemory,
2697
2726
  semanticSearch: () => semanticSearch,
2727
+ reservedAgentIdViolation: () => reservedAgentIdViolation,
2698
2728
  parseMemoryRow: () => parseMemoryRow,
2729
+ listMemoryHistoryPage: () => listMemoryHistoryPage,
2699
2730
  listMemoryHistory: () => listMemoryHistory,
2731
+ listMemoriesPage: () => listMemoriesPage,
2732
+ listMemoriesBounded: () => listMemoriesBounded,
2700
2733
  listMemories: () => listMemories,
2701
2734
  listLowTrustMemories: () => listLowTrustMemories,
2702
2735
  indexMemoryEmbedding: () => indexMemoryEmbedding,
@@ -2710,6 +2743,8 @@ __export(exports_memories, {
2710
2743
  getMemoriesByKey: () => getMemoriesByKey,
2711
2744
  deleteMemory: () => deleteMemory,
2712
2745
  createMemory: () => createMemory,
2746
+ countMemoryHistory: () => countMemoryHistory,
2747
+ countMemories: () => countMemories,
2713
2748
  cleanExpiredMemories: () => cleanExpiredMemories,
2714
2749
  bulkUpsertMemories: () => bulkUpsertMemories,
2715
2750
  bulkDeleteMemories: () => bulkDeleteMemories
@@ -2761,7 +2796,20 @@ function parseMemoryRow(row) {
2761
2796
  accessed_at: row["accessed_at"] || null
2762
2797
  };
2763
2798
  }
2799
+ function reservedAgentIdViolation(agentId) {
2800
+ if (!agentId)
2801
+ return null;
2802
+ const normalized = agentId.trim().toLowerCase();
2803
+ if (RESERVED_AGENT_IDS.has(normalized)) {
2804
+ return `Reserved placeholder agent id "${agentId}" cannot own a memory. ` + `Refusing to write: test harnesses must not write memories under placeholder agent ` + `identities. Register a real agent (mementos register-agent <name>) and pass its id.`;
2805
+ }
2806
+ return null;
2807
+ }
2764
2808
  function createMemory(input, dedupeMode = "merge", db) {
2809
+ const reservedViolation = reservedAgentIdViolation(input.agent_id);
2810
+ if (reservedViolation) {
2811
+ throw new Error(reservedViolation);
2812
+ }
2765
2813
  if (!db && isApiMode()) {
2766
2814
  const { status, data } = apiJson("POST", "/memories", { ...input, dedupe: dedupeMode });
2767
2815
  if (!data || !data.id) {
@@ -2811,7 +2859,8 @@ function createMemory(input, dedupeMode = "merge", db) {
2811
2859
  importance = ?, metadata = ?, expires_at = ?,
2812
2860
  when_to_use = ?,
2813
2861
  pinned = COALESCE(pinned, 0),
2814
- version = version + 1, updated_at = ?
2862
+ version = version + 1, updated_at = ?,
2863
+ updated_by_agent = ?
2815
2864
  WHERE id = ?`, [
2816
2865
  safeValue,
2817
2866
  input.category || "knowledge",
@@ -2822,6 +2871,7 @@ function createMemory(input, dedupeMode = "merge", db) {
2822
2871
  expiresAt,
2823
2872
  input.when_to_use || null,
2824
2873
  timestamp,
2874
+ input.agent_id || null,
2825
2875
  existing.id
2826
2876
  ]);
2827
2877
  d.run("DELETE FROM memory_tags WHERE memory_id = ?", [existing.id]);
@@ -2926,6 +2976,12 @@ function bulkUpsertMemories(memories, db) {
2926
2976
  errors.push(`Rejected "${key}": ${formatEnumViolation(violation)}`);
2927
2977
  continue;
2928
2978
  }
2979
+ const agentViolation = reservedAgentIdViolation(typeof mem["agent_id"] === "string" ? mem["agent_id"] : undefined);
2980
+ if (agentViolation) {
2981
+ rejected++;
2982
+ errors.push(`Rejected "${key}": ${agentViolation}`);
2983
+ continue;
2984
+ }
2929
2985
  const timestamp = now();
2930
2986
  let tags = [];
2931
2987
  const rawTags = mem["tags"];
@@ -3076,29 +3132,7 @@ function getMemoriesByKey(key, scope, agentId, projectId, db) {
3076
3132
  const rows = d.query(sql).all(...params);
3077
3133
  return rows.map(parseMemoryRow);
3078
3134
  }
3079
- function listMemories(filter, db) {
3080
- if (!db && isApiMode()) {
3081
- const f = filter || {};
3082
- const q = toQuery({
3083
- key: f.key,
3084
- scope: f.scope,
3085
- category: f.category,
3086
- status: f.status,
3087
- tags: f.tags,
3088
- min_importance: f.min_importance,
3089
- pinned: f.pinned,
3090
- agent_id: f.agent_id,
3091
- project_id: f.project_id,
3092
- session_id: f.session_id,
3093
- namespace: f.namespace,
3094
- as_of: f.as_of,
3095
- limit: f.limit,
3096
- offset: f.offset
3097
- });
3098
- const { data } = apiJson("GET", `/memories${q}`);
3099
- return data?.memories ?? [];
3100
- }
3101
- const d = db || getDatabase();
3135
+ function buildMemoryListConditions(filter) {
3102
3136
  const conditions = [];
3103
3137
  const params = [];
3104
3138
  if (filter) {
@@ -3210,21 +3244,114 @@ function listMemories(filter, db) {
3210
3244
  } else {
3211
3245
  conditions.push("status = 'active'");
3212
3246
  }
3247
+ return { conditions, params };
3248
+ }
3249
+ function listMemoriesPage(filter, db) {
3250
+ const f = filter || {};
3251
+ if (!db && isApiMode()) {
3252
+ const q = toQuery({
3253
+ key: f.key,
3254
+ scope: f.scope,
3255
+ category: f.category,
3256
+ status: f.status,
3257
+ tags: f.tags,
3258
+ min_importance: f.min_importance,
3259
+ pinned: f.pinned,
3260
+ agent_id: f.agent_id,
3261
+ project_id: f.project_id,
3262
+ session_id: f.session_id,
3263
+ machine_id: f.machine_id,
3264
+ visible_to_machine_id: f.visible_to_machine_id,
3265
+ search: f.search,
3266
+ source: f.source,
3267
+ flag: f.flag,
3268
+ namespace: f.namespace,
3269
+ as_of: f.as_of,
3270
+ limit: f.limit,
3271
+ offset: f.offset
3272
+ });
3273
+ const { data } = apiJson("GET", `/memories${q}`);
3274
+ return {
3275
+ rows: data?.memories ?? [],
3276
+ has_more: data?.has_more,
3277
+ next_cursor: data?.next_cursor ?? null
3278
+ };
3279
+ }
3280
+ const d = db || getDatabase();
3281
+ const { conditions, params } = buildMemoryListConditions(f);
3213
3282
  let sql = "SELECT * FROM memories";
3214
3283
  if (conditions.length > 0) {
3215
3284
  sql += ` WHERE ${conditions.join(" AND ")}`;
3216
3285
  }
3217
3286
  sql += " ORDER BY importance DESC, created_at DESC";
3218
- if (filter?.limit) {
3287
+ if (f.limit) {
3219
3288
  sql += " LIMIT ?";
3220
- params.push(filter.limit);
3289
+ params.push(f.limit);
3221
3290
  }
3222
- if (filter?.offset) {
3291
+ if (f.offset) {
3223
3292
  sql += " OFFSET ?";
3224
- params.push(filter.offset);
3293
+ params.push(f.offset);
3225
3294
  }
3226
3295
  const rows = d.query(sql).all(...params);
3227
- return rows.map(parseMemoryRow);
3296
+ const parsed = rows.map(parseMemoryRow);
3297
+ const hasMore = f.limit !== undefined && parsed.length === f.limit;
3298
+ return {
3299
+ rows: parsed,
3300
+ has_more: hasMore,
3301
+ next_cursor: hasMore ? (f.offset ?? 0) + parsed.length : null
3302
+ };
3303
+ }
3304
+ function listMemories(filter, db) {
3305
+ return listMemoriesPage(filter, db).rows;
3306
+ }
3307
+ function listMemoriesBounded(filter = {}, target, db) {
3308
+ const pageSize = 1000;
3309
+ const maxPages = 1000;
3310
+ const want = target === undefined ? undefined : target + 1;
3311
+ const rows = [];
3312
+ const seenCursors = new Set;
3313
+ let cursor = filter.offset ?? 0;
3314
+ let pages = 0;
3315
+ for (;; ) {
3316
+ if (want !== undefined && rows.length >= want)
3317
+ break;
3318
+ if (++pages > maxPages) {
3319
+ throw new Error(`memories list traversal exceeded ${maxPages} pages while collecting rows \u2014 aborting (cursor cycle?)`);
3320
+ }
3321
+ const limit = Math.min(want === undefined ? pageSize : want - rows.length, pageSize);
3322
+ const page = listMemoriesPage({ ...filter, limit, offset: cursor }, db);
3323
+ rows.push(...page.rows);
3324
+ if (page.has_more === false)
3325
+ break;
3326
+ if (page.has_more === undefined && page.rows.length < limit)
3327
+ break;
3328
+ if (page.has_more === true && (page.next_cursor === null || page.next_cursor === undefined)) {
3329
+ throw new Error("memories list page claimed more results without a next cursor \u2014 aborting");
3330
+ }
3331
+ const next = page.next_cursor ?? cursor + page.rows.length;
3332
+ if (seenCursors.has(next)) {
3333
+ throw new Error("memories list traversal repeated a cursor \u2014 aborting");
3334
+ }
3335
+ seenCursors.add(next);
3336
+ cursor = next;
3337
+ }
3338
+ const hasMore = target !== undefined && rows.length > target;
3339
+ const trimmed = hasMore ? rows.slice(0, target) : rows;
3340
+ return {
3341
+ rows: trimmed,
3342
+ has_more: hasMore,
3343
+ next_cursor: hasMore ? (filter.offset ?? 0) + trimmed.length : null
3344
+ };
3345
+ }
3346
+ function countMemories(filter, db) {
3347
+ const d = db || getDatabase();
3348
+ const { conditions, params } = buildMemoryListConditions(filter);
3349
+ let sql = "SELECT COUNT(*) AS c FROM memories";
3350
+ if (conditions.length > 0) {
3351
+ sql += ` WHERE ${conditions.join(" AND ")}`;
3352
+ }
3353
+ const row = d.query(sql).get(...params);
3354
+ return row?.c ?? 0;
3228
3355
  }
3229
3356
  function getMemoryBriefing(opts, db) {
3230
3357
  const limit = opts.limit ?? 20;
@@ -3286,13 +3413,17 @@ function listLowTrustMemories(opts = {}, db) {
3286
3413
  const rows = d.prepare(`SELECT * FROM memories WHERE ${conditions.join(" AND ")} ORDER BY trust_score ASC LIMIT ? OFFSET ?`).all(...params);
3287
3414
  return rows.map(parseMemoryRow);
3288
3415
  }
3289
- function listMemoryHistory(opts = {}, db) {
3416
+ function listMemoryHistoryPage(opts = {}, db) {
3290
3417
  const limit = opts.limit ?? 20;
3291
3418
  const offset = opts.offset ?? 0;
3292
3419
  if (!db && isApiMode()) {
3293
3420
  const q = toQuery({ limit, offset });
3294
3421
  const { data } = apiJson("GET", `/memories/history${q}`);
3295
- return data?.memories ?? [];
3422
+ return {
3423
+ rows: data?.memories ?? [],
3424
+ has_more: data?.has_more,
3425
+ next_cursor: data?.next_cursor ?? null
3426
+ };
3296
3427
  }
3297
3428
  const d = db || getDatabase();
3298
3429
  const params = [limit];
@@ -3302,7 +3433,21 @@ function listMemoryHistory(opts = {}, db) {
3302
3433
  params.push(offset);
3303
3434
  }
3304
3435
  const rows = d.query(sql).all(...params);
3305
- return rows.map(parseMemoryRow);
3436
+ const parsed = rows.map(parseMemoryRow);
3437
+ const hasMore = parsed.length === limit;
3438
+ return {
3439
+ rows: parsed,
3440
+ has_more: hasMore,
3441
+ next_cursor: hasMore ? offset + parsed.length : null
3442
+ };
3443
+ }
3444
+ function listMemoryHistory(opts = {}, db) {
3445
+ return listMemoryHistoryPage(opts, db).rows;
3446
+ }
3447
+ function countMemoryHistory(db) {
3448
+ const d = db || getDatabase();
3449
+ const row = d.query("SELECT COUNT(*) AS c FROM memories WHERE status = 'active' AND accessed_at IS NOT NULL").get();
3450
+ return row?.c ?? 0;
3306
3451
  }
3307
3452
  function getMemoryChain(sequenceGroup, projectId, db) {
3308
3453
  if (!db && isApiMode()) {
@@ -3399,20 +3544,29 @@ function updateMemory(id, input, db) {
3399
3544
  sets.push("when_to_use = ?");
3400
3545
  params.push(input.when_to_use ?? null);
3401
3546
  }
3547
+ if (input.updated_by_agent !== undefined) {
3548
+ sets.push("updated_by_agent = ?");
3549
+ params.push(input.updated_by_agent ?? null);
3550
+ }
3402
3551
  if (input.tags !== undefined) {
3403
3552
  sets.push("tags = ?");
3404
3553
  params.push(JSON.stringify(input.tags));
3405
- d.run("DELETE FROM memory_tags WHERE memory_id = ?", [memoryId]);
3406
- const insertTag = d.prepare("INSERT OR IGNORE INTO memory_tags (memory_id, tag) VALUES (?, ?)");
3407
- for (const tag of input.tags) {
3408
- insertTag.run(memoryId, tag);
3409
- }
3410
3554
  }
3411
3555
  params.push(memoryId);
3412
- const result = d.run(`UPDATE memories SET ${sets.join(", ")} WHERE id = ?`, params);
3413
- if (result.changes === 0) {
3414
- throw new Error(`Update affected no rows for memory ${memoryId}: the record was read but not written. ` + `This is a bug in @hasna/mementos, not a bad argument \u2014 please report it.`);
3415
- }
3556
+ d.transaction(() => {
3557
+ const res = d.run(`UPDATE memories SET ${sets.join(", ")} WHERE id = ?`, params);
3558
+ if (res.changes === 0) {
3559
+ throw new Error(`Update affected no rows for memory ${memoryId}: the record was read but not written. ` + `This is a bug in @hasna/mementos, not a bad argument \u2014 please report it.`);
3560
+ }
3561
+ if (input.tags !== undefined) {
3562
+ d.run("DELETE FROM memory_tags WHERE memory_id = ?", [memoryId]);
3563
+ const insertTag = d.prepare("INSERT OR IGNORE INTO memory_tags (memory_id, tag) VALUES (?, ?)");
3564
+ for (const tag of input.tags) {
3565
+ insertTag.run(memoryId, tag);
3566
+ }
3567
+ }
3568
+ return res;
3569
+ });
3416
3570
  const updated = getMemory(memoryId, d);
3417
3571
  if (input.value !== undefined) {
3418
3572
  try {
@@ -3583,7 +3737,7 @@ async function semanticSearch(queryText, options = {}, db) {
3583
3737
  scored.sort((a, b) => b.score - a.score);
3584
3738
  return scored.slice(0, limit);
3585
3739
  }
3586
- var RECALL_PROMOTE_THRESHOLD = 3;
3740
+ var RESERVED_AGENT_IDS, RECALL_PROMOTE_THRESHOLD = 3;
3587
3741
  var init_memories = __esm(() => {
3588
3742
  init_types();
3589
3743
  init_database();
@@ -3593,6 +3747,12 @@ var init_memories = __esm(() => {
3593
3747
  init_poisoning();
3594
3748
  init_entity_memories();
3595
3749
  init_api_mode();
3750
+ RESERVED_AGENT_IDS = new Set([
3751
+ "agent-a",
3752
+ "agent-x",
3753
+ "agent-z",
3754
+ "nonexistent-agent"
3755
+ ]);
3596
3756
  });
3597
3757
 
3598
3758
  // src/db/entities.ts
@@ -4175,7 +4335,7 @@ function buildFilterConditions(filter) {
4175
4335
  const conditions = [];
4176
4336
  const params = [];
4177
4337
  conditions.push("m.status = 'active'");
4178
- conditions.push("(m.expires_at IS NULL OR m.expires_at >= datetime('now'))");
4338
+ conditions.push("(m.expires_at IS NULL OR m.expires_at >= strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))");
4179
4339
  if (!filter)
4180
4340
  return { conditions, params };
4181
4341
  if (filter.scope) {
@@ -6211,7 +6371,7 @@ async function detectContradiction(newKey, newValue, options = {}, db) {
6211
6371
  conditions.push("project_id = ?");
6212
6372
  params.push(project_id);
6213
6373
  }
6214
- conditions.push("(valid_until IS NULL OR valid_until > datetime('now'))");
6374
+ conditions.push("(valid_until IS NULL OR valid_until > strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))");
6215
6375
  const sql = `SELECT * FROM memories WHERE ${conditions.join(" AND ")} ORDER BY importance DESC LIMIT 10`;
6216
6376
  const rows = d.query(sql).all(...params);
6217
6377
  if (rows.length === 0) {
@@ -19888,7 +20048,7 @@ class JSONSchemaGenerator {
19888
20048
  if (val === undefined) {
19889
20049
  if (this.unrepresentable === "throw") {
19890
20050
  throw new Error("Literal `undefined` cannot be represented in JSON Schema");
19891
- } else {}
20051
+ }
19892
20052
  } else if (typeof val === "bigint") {
19893
20053
  if (this.unrepresentable === "throw") {
19894
20054
  throw new Error("BigInt literals cannot be represented in JSON Schema");
@@ -41538,7 +41698,7 @@ var require_tracestate_impl = __commonJS((exports) => {
41538
41698
  const value = listMember.slice(i + 1, part.length);
41539
41699
  if ((0, tracestate_validators_1.validateKey)(key) && (0, tracestate_validators_1.validateValue)(value)) {
41540
41700
  agg.set(key, value);
41541
- } else {}
41701
+ }
41542
41702
  }
41543
41703
  return agg;
41544
41704
  }, new Map);
@@ -55845,6 +56005,18 @@ function getNextPendingJob(db) {
55845
56005
  return null;
55846
56006
  return parseJobRow(row);
55847
56007
  }
56008
+ function claimSessionJob(id, db) {
56009
+ const d = db || getDatabase();
56010
+ const startedAt = now();
56011
+ const result = d.run("UPDATE session_memory_jobs SET status = 'processing', started_at = ? WHERE id = ? AND status = 'pending'", [startedAt, id]);
56012
+ return result.changes;
56013
+ }
56014
+ function recoverStaleProcessingJobs(maxAgeMs, db) {
56015
+ const d = db || getDatabase();
56016
+ const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
56017
+ const result = d.run("UPDATE session_memory_jobs SET status = 'pending', started_at = NULL WHERE status = 'processing' AND started_at < ?", [cutoff]);
56018
+ return result.changes;
56019
+ }
55848
56020
 
55849
56021
  // src/lib/session-processor.ts
55850
56022
  init_memories();
@@ -56347,7 +56519,11 @@ async function processSessionJob(jobId, db) {
56347
56519
  return result;
56348
56520
  }
56349
56521
  try {
56350
- updateSessionJob(jobId, { status: "processing", started_at: new Date().toISOString() }, db);
56522
+ const changes = claimSessionJob(jobId, db);
56523
+ if (changes === 0) {
56524
+ result.errors.push(`Job already claimed or not pending: ${jobId}`);
56525
+ return result;
56526
+ }
56351
56527
  } catch (e) {
56352
56528
  result.errors.push(`Failed to mark job as processing: ${String(e)}`);
56353
56529
  return result;
@@ -56455,6 +56631,9 @@ function startSessionQueueWorker() {
56455
56631
  return;
56456
56632
  _workerStarted = true;
56457
56633
  setInterval(() => {
56634
+ try {
56635
+ recoverStaleProcessingJobs(30 * 60 * 1000);
56636
+ } catch {}
56458
56637
  _processNext();
56459
56638
  }, 5000);
56460
56639
  }
@@ -56726,7 +56905,7 @@ function getTaskStats(db, filter) {
56726
56905
  const priorityRows = db.query(`SELECT priority, COUNT(*) as c FROM tasks ${where} GROUP BY priority`).all(...params);
56727
56906
  for (const row of priorityRows)
56728
56907
  byPriority[row.priority] = row.c;
56729
- const overdue = db.query(`SELECT COUNT(*) as c FROM tasks ${where} AND status != 'completed' AND status != 'cancelled' AND due_at IS NOT NULL AND due_at < datetime('now')`).get(...params).c;
56908
+ const overdue = db.query(`SELECT COUNT(*) as c FROM tasks ${where} AND status != 'completed' AND status != 'cancelled' AND due_at IS NOT NULL AND due_at < strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`).get(...params).c;
56730
56909
  return {
56731
56910
  total,
56732
56911
  by_status: {
@@ -56857,6 +57036,255 @@ async function _tick() {
56857
57036
 
56858
57037
  // src/server/index.ts
56859
57038
  init_storage();
57039
+
57040
+ // src/db/analytics.ts
57041
+ init_database();
57042
+ init_api_mode();
57043
+ function getMemoryStats(db) {
57044
+ if (!db && isApiMode()) {
57045
+ const { data } = apiJson("GET", "/memories/stats");
57046
+ return normalizeStats(data);
57047
+ }
57048
+ const d = db || getDatabase();
57049
+ const total = d.query("SELECT COUNT(*) as c FROM memories WHERE status = 'active'").get().c;
57050
+ const byScope = d.query("SELECT scope, COUNT(*) as c FROM memories WHERE status = 'active' GROUP BY scope").all();
57051
+ const byCategory = d.query("SELECT category, COUNT(*) as c FROM memories WHERE status = 'active' GROUP BY category").all();
57052
+ const byStatus = d.query("SELECT status, COUNT(*) as c FROM memories WHERE status = 'active' GROUP BY status").all();
57053
+ const pinnedCount = d.query("SELECT COUNT(*) as c FROM memories WHERE pinned = 1 AND status = 'active'").get().c;
57054
+ const expiredCount = d.query("SELECT COUNT(*) as c FROM memories WHERE status = 'expired'").get().c;
57055
+ const expiresAtCount = d.query("SELECT COUNT(*) as c FROM memories WHERE expires_at IS NOT NULL").get().c;
57056
+ const nowIso = new Date().toISOString();
57057
+ const expiredDueCount = d.query("SELECT COUNT(*) as c FROM memories WHERE status = 'expired' OR (expires_at IS NOT NULL AND expires_at < ?)").get(nowIso).c;
57058
+ const stats = {
57059
+ total,
57060
+ by_scope: { global: 0, shared: 0, private: 0, working: 0 },
57061
+ by_category: { preference: 0, fact: 0, knowledge: 0, history: 0, procedural: 0, resource: 0 },
57062
+ by_status: { active: 0, archived: 0, expired: 0 },
57063
+ by_agent: {},
57064
+ pinned_count: pinnedCount,
57065
+ expired_count: expiredCount,
57066
+ expires_at_count: expiresAtCount,
57067
+ expired_due_count: expiredDueCount
57068
+ };
57069
+ for (const row of byScope)
57070
+ if (row.scope in stats.by_scope)
57071
+ stats.by_scope[row.scope] = row.c;
57072
+ for (const row of byCategory)
57073
+ if (row.category in stats.by_category)
57074
+ stats.by_category[row.category] = row.c;
57075
+ for (const row of byStatus) {
57076
+ if (row.status in stats.by_status) {
57077
+ stats.by_status[row.status] = row.c;
57078
+ }
57079
+ }
57080
+ const byAgent = d.query("SELECT agent_id, COUNT(*) as c FROM memories WHERE status = 'active' AND agent_id IS NOT NULL GROUP BY agent_id").all();
57081
+ for (const row of byAgent)
57082
+ stats.by_agent[row.agent_id] = row.c;
57083
+ return stats;
57084
+ }
57085
+ function normalizeStats(data) {
57086
+ return {
57087
+ total: data?.total ?? 0,
57088
+ by_scope: { global: 0, shared: 0, private: 0, working: 0, ...data?.by_scope ?? {} },
57089
+ by_category: {
57090
+ preference: 0,
57091
+ fact: 0,
57092
+ knowledge: 0,
57093
+ history: 0,
57094
+ procedural: 0,
57095
+ resource: 0,
57096
+ ...data?.by_category ?? {}
57097
+ },
57098
+ by_status: { active: 0, archived: 0, expired: 0, ...data?.by_status ?? {} },
57099
+ by_agent: data?.by_agent ?? {},
57100
+ pinned_count: data?.pinned_count ?? 0,
57101
+ expired_count: data?.expired_count ?? 0,
57102
+ expires_at_count: data?.expires_at_count ?? 0,
57103
+ expired_due_count: data?.expired_due_count ?? 0
57104
+ };
57105
+ }
57106
+ function getMemoryActivity(filter = {}, db) {
57107
+ const days = Math.min(filter.days || 30, 365);
57108
+ if (!db && isApiMode()) {
57109
+ const q = toQuery({ days, scope: filter.scope, agent_id: filter.agent_id, project_id: filter.project_id });
57110
+ const { data } = apiJson("GET", `/activity${q}`);
57111
+ return { activity: data?.activity ?? [], days: data?.days ?? days, total: data?.total ?? 0 };
57112
+ }
57113
+ const d = db || getDatabase();
57114
+ const conditions = ["status = 'active'"];
57115
+ const params = [];
57116
+ if (filter.scope) {
57117
+ conditions.push("scope = ?");
57118
+ params.push(filter.scope);
57119
+ }
57120
+ if (filter.agent_id) {
57121
+ conditions.push("agent_id = ?");
57122
+ params.push(filter.agent_id);
57123
+ }
57124
+ if (filter.project_id) {
57125
+ conditions.push("project_id = ?");
57126
+ params.push(filter.project_id);
57127
+ }
57128
+ const where = conditions.map((c) => `AND ${c}`).join(" ");
57129
+ const cutoffDate = new Date(Date.now() - days * 86400000).toISOString().slice(0, 10);
57130
+ params.push(cutoffDate);
57131
+ const rows = d.query(`
57132
+ SELECT
57133
+ date(created_at) AS date,
57134
+ COUNT(*) AS memories_created,
57135
+ SUM(CASE WHEN scope = 'global' THEN 1 ELSE 0 END) AS global_count,
57136
+ SUM(CASE WHEN scope = 'shared' THEN 1 ELSE 0 END) AS shared_count,
57137
+ SUM(CASE WHEN scope = 'private' THEN 1 ELSE 0 END) AS private_count,
57138
+ AVG(importance) AS avg_importance
57139
+ FROM memories
57140
+ WHERE date(created_at) >= ? ${where}
57141
+ GROUP BY date(created_at)
57142
+ ORDER BY date ASC
57143
+ `).all(...params);
57144
+ return { activity: rows, days, total: rows.reduce((s, r) => s + r.memories_created, 0) };
57145
+ }
57146
+ function getMemoryReport(filter = {}, db) {
57147
+ const days = Math.min(filter.days || 7, 365);
57148
+ if (!db && isApiMode()) {
57149
+ const q = toQuery({ days, project_id: filter.project_id, agent_id: filter.agent_id });
57150
+ const { data } = apiJson("GET", `/report${q}`);
57151
+ return {
57152
+ total: data?.total ?? 0,
57153
+ pinned: data?.pinned ?? 0,
57154
+ days: data?.days ?? days,
57155
+ recent: data?.recent ?? { total: 0, activity: [] },
57156
+ by_scope: data?.by_scope ?? {},
57157
+ by_category: data?.by_category ?? {},
57158
+ top_memories: data?.top_memories ?? [],
57159
+ top_agents: data?.top_agents ?? []
57160
+ };
57161
+ }
57162
+ const d = db || getDatabase();
57163
+ const cutoffDate = new Date(Date.now() - days * 86400000).toISOString().slice(0, 10);
57164
+ const scopedCond = [
57165
+ filter.project_id ? "AND project_id = ?" : "",
57166
+ filter.agent_id ? "AND agent_id = ?" : ""
57167
+ ].filter(Boolean).join(" ");
57168
+ const scopedParams = [
57169
+ ...filter.project_id ? [filter.project_id] : [],
57170
+ ...filter.agent_id ? [filter.agent_id] : []
57171
+ ];
57172
+ const recentParams = [cutoffDate, ...scopedParams];
57173
+ const total = d.query(`SELECT COUNT(*) as c FROM memories WHERE status = 'active' ${scopedCond}`).get(...scopedParams).c;
57174
+ const pinned = d.query(`SELECT COUNT(*) as c FROM memories WHERE status = 'active' AND pinned = 1 ${scopedCond}`).get(...scopedParams).c;
57175
+ const actRows = d.query(`
57176
+ SELECT date(created_at) AS date, COUNT(*) AS memories_created
57177
+ FROM memories WHERE status = 'active' AND date(created_at) >= ? ${scopedCond}
57178
+ GROUP BY date(created_at) ORDER BY date(created_at) ASC
57179
+ `).all(...recentParams);
57180
+ const recentTotal = actRows.reduce((s, r) => s + r.memories_created, 0);
57181
+ const byScopeRows = d.query(`SELECT scope, COUNT(*) as c FROM memories WHERE status = 'active' ${scopedCond} GROUP BY scope`).all(...scopedParams);
57182
+ const byCatRows = d.query(`SELECT category, COUNT(*) as c FROM memories WHERE status = 'active' ${scopedCond} GROUP BY category`).all(...scopedParams);
57183
+ const topMems = d.query(`SELECT id, key, value, importance, scope, category FROM memories WHERE status = 'active' ${scopedCond} ORDER BY importance DESC, access_count DESC LIMIT 5`).all(...scopedParams);
57184
+ const topAgents = d.query(`SELECT agent_id, COUNT(*) as c FROM memories WHERE status = 'active' AND agent_id IS NOT NULL ${scopedCond} GROUP BY agent_id ORDER BY c DESC LIMIT 5`).all(...scopedParams);
57185
+ return {
57186
+ total,
57187
+ pinned,
57188
+ days,
57189
+ recent: { total: recentTotal, activity: actRows },
57190
+ by_scope: Object.fromEntries(byScopeRows.map((r) => [r.scope, r.c])),
57191
+ by_category: Object.fromEntries(byCatRows.map((r) => [r.category, r.c])),
57192
+ top_memories: topMems,
57193
+ top_agents: topAgents
57194
+ };
57195
+ }
57196
+ function getStaleMemoriesPage(filter = {}, db) {
57197
+ const days = Math.min(filter.days || 30, 365);
57198
+ const limit = filter.limit ?? 20;
57199
+ const offset = filter.offset ?? 0;
57200
+ if (!db && isApiMode()) {
57201
+ const q = toQuery({ days, project_id: filter.project_id, agent_id: filter.agent_id, pinned: filter.pinned, limit, offset });
57202
+ const { data } = apiJson("GET", `/memories/stale${q}`);
57203
+ const rows2 = data?.memories ?? [];
57204
+ return {
57205
+ rows: rows2,
57206
+ total: data?.total ?? rows2.length,
57207
+ has_more: data?.has_more,
57208
+ next_cursor: data?.next_cursor ?? null
57209
+ };
57210
+ }
57211
+ const d = db || getDatabase();
57212
+ const cutoffDate = new Date(Date.now() - days * 86400000).toISOString();
57213
+ const conds = ["status = 'active'", "(accessed_at IS NULL OR accessed_at < ?)"];
57214
+ const params = [cutoffDate];
57215
+ if (filter.pinned !== undefined) {
57216
+ conds.push("pinned = ?");
57217
+ params.push(filter.pinned ? 1 : 0);
57218
+ } else {
57219
+ conds.push("pinned = 0");
57220
+ }
57221
+ if (filter.project_id) {
57222
+ conds.push("project_id = ?");
57223
+ params.push(filter.project_id);
57224
+ }
57225
+ if (filter.agent_id) {
57226
+ conds.push("agent_id = ?");
57227
+ params.push(filter.agent_id);
57228
+ }
57229
+ const where = conds.join(" AND ");
57230
+ const countRow = d.query(`SELECT COUNT(*) AS c FROM memories WHERE ${where}`).get(...params);
57231
+ let sql = `SELECT id, key, value, importance, scope, category, accessed_at, access_count, created_at FROM memories WHERE ${where} ORDER BY COALESCE(accessed_at, created_at) ASC LIMIT ?`;
57232
+ params.push(limit);
57233
+ if (offset) {
57234
+ sql += " OFFSET ?";
57235
+ params.push(offset);
57236
+ }
57237
+ const rows = d.query(sql).all(...params);
57238
+ const hasMore = rows.length === limit;
57239
+ return {
57240
+ rows,
57241
+ total: countRow?.c ?? 0,
57242
+ has_more: hasMore,
57243
+ next_cursor: hasMore ? offset + rows.length : null
57244
+ };
57245
+ }
57246
+ function getMemoryHealth(filter = {}, db) {
57247
+ const staleDays = filter.stale_days ?? 30;
57248
+ const forgottenDays = filter.forgotten_days ?? 60;
57249
+ const limit = filter.limit ?? 10;
57250
+ if (!db && isApiMode()) {
57251
+ const q = toQuery({
57252
+ stale_days: staleDays,
57253
+ forgotten_days: forgottenDays,
57254
+ project_id: filter.project_id,
57255
+ agent_id: filter.agent_id,
57256
+ limit
57257
+ });
57258
+ const { data } = apiJson("GET", `/memories/health${q}`);
57259
+ return { stale: data?.stale ?? [], forgotten: data?.forgotten ?? [], dupes: data?.dupes ?? [] };
57260
+ }
57261
+ const d = db || getDatabase();
57262
+ const extraWhere = [
57263
+ ...filter.project_id ? ["project_id = ?"] : [],
57264
+ ...filter.agent_id ? ["agent_id = ?"] : []
57265
+ ].join(" AND ");
57266
+ const scopeParams = [
57267
+ ...filter.project_id ? [filter.project_id] : [],
57268
+ ...filter.agent_id ? [filter.agent_id] : []
57269
+ ];
57270
+ const staleCutoff = new Date(Date.now() - staleDays * 86400000).toISOString();
57271
+ const forgottenCutoff = new Date(Date.now() - forgottenDays * 86400000).toISOString();
57272
+ const base = `status = 'active' AND pinned = 0${extraWhere ? " AND " + extraWhere : ""}`;
57273
+ const stale = d.prepare(`SELECT id, key, value, importance, scope, created_at FROM memories
57274
+ WHERE ${base} AND access_count = 0 AND created_at < ?
57275
+ ORDER BY created_at ASC LIMIT ?`).all(...scopeParams, staleCutoff, limit);
57276
+ const forgotten = d.prepare(`SELECT id, key, value, importance, scope, accessed_at FROM memories
57277
+ WHERE ${base} AND importance >= 7
57278
+ AND (accessed_at IS NULL OR accessed_at < ?)
57279
+ ORDER BY importance DESC, COALESCE(accessed_at, created_at) ASC LIMIT ?`).all(...scopeParams, forgottenCutoff, limit);
57280
+ const dupes = d.prepare(`SELECT key, COUNT(*) as cnt, MAX(updated_at) as latest, MIN(created_at) as oldest
57281
+ FROM memories WHERE ${base}
57282
+ GROUP BY key HAVING COUNT(*) > 1
57283
+ ORDER BY cnt DESC LIMIT ?`).all(...scopeParams, limit);
57284
+ return { stale, forgotten, dupes };
57285
+ }
57286
+
57287
+ // src/server/index.ts
56860
57288
  init_router();
56861
57289
 
56862
57290
  // src/server/helpers.ts
@@ -57102,6 +57530,7 @@ var FORMAT_UNITS = [
57102
57530
 
57103
57531
  // src/server/routes/memories-crud.ts
57104
57532
  init_router();
57533
+ init_database();
57105
57534
  init_enum_validation();
57106
57535
  init_types();
57107
57536
  addRoute("GET", "/api/memories", (_req, url) => {
@@ -57127,21 +57556,49 @@ addRoute("GET", "/api/memories", (_req, url) => {
57127
57556
  filter.project_id = q["project_id"];
57128
57557
  if (q["session_id"])
57129
57558
  filter.session_id = q["session_id"];
57559
+ if (q["machine_id"])
57560
+ filter.machine_id = q["machine_id"];
57561
+ if (q["visible_to_machine_id"])
57562
+ filter.visible_to_machine_id = q["visible_to_machine_id"];
57563
+ if (q["search"])
57564
+ filter.search = q["search"];
57565
+ if (q["source"])
57566
+ filter.source = q["source"].includes(",") ? q["source"].split(",") : q["source"];
57567
+ if (q["flag"])
57568
+ filter.flag = q["flag"];
57130
57569
  if (q["namespace"])
57131
57570
  filter.namespace = q["namespace"];
57132
57571
  if (q["status"])
57133
57572
  filter.status = q["status"];
57134
- if (q["limit"])
57135
- filter.limit = parseInt(q["limit"], 10);
57136
- if (q["offset"])
57137
- filter.offset = parseInt(q["offset"], 10);
57573
+ const parsedLimit = Number(q["limit"]);
57574
+ const limit = Number.isInteger(parsedLimit) && parsedLimit > 0 ? Math.min(parsedLimit, 1000) : 1000;
57575
+ const parsedOffset = Number(q["offset"]);
57576
+ filter.limit = limit;
57577
+ filter.offset = Number.isInteger(parsedOffset) && parsedOffset >= 0 ? parsedOffset : 0;
57138
57578
  const memories = listMemories(filter);
57579
+ const total = countMemories(filter, getDatabase());
57580
+ const hasMore = memories.length === limit;
57581
+ const nextCursor = hasMore ? (filter.offset ?? 0) + memories.length : null;
57139
57582
  if (q["fields"]) {
57140
57583
  const fields = q["fields"].split(",").map((f) => f.trim());
57141
57584
  const filtered = memories.map((m) => Object.fromEntries(fields.map((f) => [f, m[f]]).filter(([, v]) => v !== undefined)));
57142
- return json({ memories: filtered, count: filtered.length });
57585
+ return json({
57586
+ memories: filtered,
57587
+ count: filtered.length,
57588
+ total,
57589
+ limit,
57590
+ has_more: hasMore,
57591
+ next_cursor: nextCursor
57592
+ });
57143
57593
  }
57144
- return json({ memories, count: memories.length });
57594
+ return json({
57595
+ memories,
57596
+ count: memories.length,
57597
+ total,
57598
+ limit,
57599
+ has_more: hasMore,
57600
+ next_cursor: nextCursor
57601
+ });
57145
57602
  });
57146
57603
  addRoute("POST", "/api/memories", async (req) => {
57147
57604
  const body = await readJson(req);
@@ -57239,227 +57696,6 @@ addRoute("DELETE", "/api/memories/:id", (_req, _url, params) => {
57239
57696
 
57240
57697
  // src/server/routes/memories-stats.ts
57241
57698
  init_database();
57242
-
57243
- // src/db/analytics.ts
57244
- init_database();
57245
- init_api_mode();
57246
- function getMemoryStats(db) {
57247
- if (!db && isApiMode()) {
57248
- const { data } = apiJson("GET", "/memories/stats");
57249
- return normalizeStats(data);
57250
- }
57251
- const d = db || getDatabase();
57252
- const total = d.query("SELECT COUNT(*) as c FROM memories WHERE status = 'active'").get().c;
57253
- const byScope = d.query("SELECT scope, COUNT(*) as c FROM memories WHERE status = 'active' GROUP BY scope").all();
57254
- const byCategory = d.query("SELECT category, COUNT(*) as c FROM memories WHERE status = 'active' GROUP BY category").all();
57255
- const byStatus = d.query("SELECT status, COUNT(*) as c FROM memories WHERE status = 'active' GROUP BY status").all();
57256
- const pinnedCount = d.query("SELECT COUNT(*) as c FROM memories WHERE pinned = 1 AND status = 'active'").get().c;
57257
- const expiredCount = d.query("SELECT COUNT(*) as c FROM memories WHERE status = 'expired' OR (expires_at IS NOT NULL AND expires_at < datetime('now'))").get().c;
57258
- const stats = {
57259
- total,
57260
- by_scope: { global: 0, shared: 0, private: 0, working: 0 },
57261
- by_category: { preference: 0, fact: 0, knowledge: 0, history: 0, procedural: 0, resource: 0 },
57262
- by_status: { active: 0, archived: 0, expired: 0 },
57263
- by_agent: {},
57264
- pinned_count: pinnedCount,
57265
- expired_count: expiredCount
57266
- };
57267
- for (const row of byScope)
57268
- if (row.scope in stats.by_scope)
57269
- stats.by_scope[row.scope] = row.c;
57270
- for (const row of byCategory)
57271
- if (row.category in stats.by_category)
57272
- stats.by_category[row.category] = row.c;
57273
- for (const row of byStatus) {
57274
- if (row.status in stats.by_status) {
57275
- stats.by_status[row.status] = row.c;
57276
- }
57277
- }
57278
- const byAgent = d.query("SELECT agent_id, COUNT(*) as c FROM memories WHERE status = 'active' AND agent_id IS NOT NULL GROUP BY agent_id").all();
57279
- for (const row of byAgent)
57280
- stats.by_agent[row.agent_id] = row.c;
57281
- return stats;
57282
- }
57283
- function normalizeStats(data) {
57284
- return {
57285
- total: data?.total ?? 0,
57286
- by_scope: { global: 0, shared: 0, private: 0, working: 0, ...data?.by_scope ?? {} },
57287
- by_category: {
57288
- preference: 0,
57289
- fact: 0,
57290
- knowledge: 0,
57291
- history: 0,
57292
- procedural: 0,
57293
- resource: 0,
57294
- ...data?.by_category ?? {}
57295
- },
57296
- by_status: { active: 0, archived: 0, expired: 0, ...data?.by_status ?? {} },
57297
- by_agent: data?.by_agent ?? {},
57298
- pinned_count: data?.pinned_count ?? 0,
57299
- expired_count: data?.expired_count ?? 0
57300
- };
57301
- }
57302
- function getMemoryActivity(filter = {}, db) {
57303
- const days = Math.min(filter.days || 30, 365);
57304
- if (!db && isApiMode()) {
57305
- const q = toQuery({ days, scope: filter.scope, agent_id: filter.agent_id, project_id: filter.project_id });
57306
- const { data } = apiJson("GET", `/activity${q}`);
57307
- return { activity: data?.activity ?? [], days: data?.days ?? days, total: data?.total ?? 0 };
57308
- }
57309
- const d = db || getDatabase();
57310
- const conditions = ["status = 'active'"];
57311
- const params = [];
57312
- if (filter.scope) {
57313
- conditions.push("scope = ?");
57314
- params.push(filter.scope);
57315
- }
57316
- if (filter.agent_id) {
57317
- conditions.push("agent_id = ?");
57318
- params.push(filter.agent_id);
57319
- }
57320
- if (filter.project_id) {
57321
- conditions.push("project_id = ?");
57322
- params.push(filter.project_id);
57323
- }
57324
- const where = conditions.map((c) => `AND ${c}`).join(" ");
57325
- const cutoffDate = new Date(Date.now() - days * 86400000).toISOString().slice(0, 10);
57326
- params.push(cutoffDate);
57327
- const rows = d.query(`
57328
- SELECT
57329
- date(created_at) AS date,
57330
- COUNT(*) AS memories_created,
57331
- SUM(CASE WHEN scope = 'global' THEN 1 ELSE 0 END) AS global_count,
57332
- SUM(CASE WHEN scope = 'shared' THEN 1 ELSE 0 END) AS shared_count,
57333
- SUM(CASE WHEN scope = 'private' THEN 1 ELSE 0 END) AS private_count,
57334
- AVG(importance) AS avg_importance
57335
- FROM memories
57336
- WHERE date(created_at) >= ? ${where}
57337
- GROUP BY date(created_at)
57338
- ORDER BY date ASC
57339
- `).all(...params);
57340
- return { activity: rows, days, total: rows.reduce((s, r) => s + r.memories_created, 0) };
57341
- }
57342
- function getMemoryReport(filter = {}, db) {
57343
- const days = Math.min(filter.days || 7, 365);
57344
- if (!db && isApiMode()) {
57345
- const q = toQuery({ days, project_id: filter.project_id, agent_id: filter.agent_id });
57346
- const { data } = apiJson("GET", `/report${q}`);
57347
- return {
57348
- total: data?.total ?? 0,
57349
- pinned: data?.pinned ?? 0,
57350
- days: data?.days ?? days,
57351
- recent: data?.recent ?? { total: 0, activity: [] },
57352
- by_scope: data?.by_scope ?? {},
57353
- by_category: data?.by_category ?? {},
57354
- top_memories: data?.top_memories ?? [],
57355
- top_agents: data?.top_agents ?? []
57356
- };
57357
- }
57358
- const d = db || getDatabase();
57359
- const cutoffDate = new Date(Date.now() - days * 86400000).toISOString().slice(0, 10);
57360
- const scopedCond = [
57361
- filter.project_id ? "AND project_id = ?" : "",
57362
- filter.agent_id ? "AND agent_id = ?" : ""
57363
- ].filter(Boolean).join(" ");
57364
- const scopedParams = [
57365
- ...filter.project_id ? [filter.project_id] : [],
57366
- ...filter.agent_id ? [filter.agent_id] : []
57367
- ];
57368
- const recentParams = [cutoffDate, ...scopedParams];
57369
- const total = d.query(`SELECT COUNT(*) as c FROM memories WHERE status = 'active' ${scopedCond}`).get(...scopedParams).c;
57370
- const pinned = d.query(`SELECT COUNT(*) as c FROM memories WHERE status = 'active' AND pinned = 1 ${scopedCond}`).get(...scopedParams).c;
57371
- const actRows = d.query(`
57372
- SELECT date(created_at) AS date, COUNT(*) AS memories_created
57373
- FROM memories WHERE status = 'active' AND date(created_at) >= ? ${scopedCond}
57374
- GROUP BY date(created_at) ORDER BY date(created_at) ASC
57375
- `).all(...recentParams);
57376
- const recentTotal = actRows.reduce((s, r) => s + r.memories_created, 0);
57377
- const byScopeRows = d.query(`SELECT scope, COUNT(*) as c FROM memories WHERE status = 'active' ${scopedCond} GROUP BY scope`).all(...scopedParams);
57378
- const byCatRows = d.query(`SELECT category, COUNT(*) as c FROM memories WHERE status = 'active' ${scopedCond} GROUP BY category`).all(...scopedParams);
57379
- const topMems = d.query(`SELECT id, key, value, importance, scope, category FROM memories WHERE status = 'active' ${scopedCond} ORDER BY importance DESC, access_count DESC LIMIT 5`).all(...scopedParams);
57380
- const topAgents = d.query(`SELECT agent_id, COUNT(*) as c FROM memories WHERE status = 'active' AND agent_id IS NOT NULL ${scopedCond} GROUP BY agent_id ORDER BY c DESC LIMIT 5`).all(...scopedParams);
57381
- return {
57382
- total,
57383
- pinned,
57384
- days,
57385
- recent: { total: recentTotal, activity: actRows },
57386
- by_scope: Object.fromEntries(byScopeRows.map((r) => [r.scope, r.c])),
57387
- by_category: Object.fromEntries(byCatRows.map((r) => [r.category, r.c])),
57388
- top_memories: topMems,
57389
- top_agents: topAgents
57390
- };
57391
- }
57392
- function getStaleMemories(filter = {}, db) {
57393
- const days = Math.min(filter.days || 30, 365);
57394
- const limit = filter.limit ?? 20;
57395
- const offset = filter.offset ?? 0;
57396
- if (!db && isApiMode()) {
57397
- const q = toQuery({ days, project_id: filter.project_id, agent_id: filter.agent_id, limit, offset });
57398
- const { data } = apiJson("GET", `/memories/stale${q}`);
57399
- return data?.memories ?? [];
57400
- }
57401
- const d = db || getDatabase();
57402
- const cutoffDate = new Date(Date.now() - days * 86400000).toISOString();
57403
- const conds = ["status = 'active'", "(accessed_at IS NULL OR accessed_at < ?)", "pinned = 0"];
57404
- const params = [cutoffDate];
57405
- if (filter.project_id) {
57406
- conds.push("project_id = ?");
57407
- params.push(filter.project_id);
57408
- }
57409
- if (filter.agent_id) {
57410
- conds.push("agent_id = ?");
57411
- params.push(filter.agent_id);
57412
- }
57413
- let sql = `SELECT id, key, value, importance, scope, category, accessed_at, access_count, created_at FROM memories WHERE ${conds.join(" AND ")} ORDER BY COALESCE(accessed_at, created_at) ASC LIMIT ?`;
57414
- params.push(limit);
57415
- if (offset) {
57416
- sql += " OFFSET ?";
57417
- params.push(offset);
57418
- }
57419
- return d.query(sql).all(...params);
57420
- }
57421
- function getMemoryHealth(filter = {}, db) {
57422
- const staleDays = filter.stale_days ?? 30;
57423
- const forgottenDays = filter.forgotten_days ?? 60;
57424
- const limit = filter.limit ?? 10;
57425
- if (!db && isApiMode()) {
57426
- const q = toQuery({
57427
- stale_days: staleDays,
57428
- forgotten_days: forgottenDays,
57429
- project_id: filter.project_id,
57430
- agent_id: filter.agent_id,
57431
- limit
57432
- });
57433
- const { data } = apiJson("GET", `/memories/health${q}`);
57434
- return { stale: data?.stale ?? [], forgotten: data?.forgotten ?? [], dupes: data?.dupes ?? [] };
57435
- }
57436
- const d = db || getDatabase();
57437
- const extraWhere = [
57438
- ...filter.project_id ? ["project_id = ?"] : [],
57439
- ...filter.agent_id ? ["agent_id = ?"] : []
57440
- ].join(" AND ");
57441
- const scopeParams = [
57442
- ...filter.project_id ? [filter.project_id] : [],
57443
- ...filter.agent_id ? [filter.agent_id] : []
57444
- ];
57445
- const staleCutoff = new Date(Date.now() - staleDays * 86400000).toISOString();
57446
- const forgottenCutoff = new Date(Date.now() - forgottenDays * 86400000).toISOString();
57447
- const base = `status = 'active' AND pinned = 0${extraWhere ? " AND " + extraWhere : ""}`;
57448
- const stale = d.prepare(`SELECT id, key, value, importance, scope, created_at FROM memories
57449
- WHERE ${base} AND access_count = 0 AND created_at < ?
57450
- ORDER BY created_at ASC LIMIT ?`).all(...scopeParams, staleCutoff, limit);
57451
- const forgotten = d.prepare(`SELECT id, key, value, importance, scope, accessed_at FROM memories
57452
- WHERE ${base} AND importance >= 7
57453
- AND (accessed_at IS NULL OR accessed_at < ?)
57454
- ORDER BY importance DESC, COALESCE(accessed_at, created_at) ASC LIMIT ?`).all(...scopeParams, forgottenCutoff, limit);
57455
- const dupes = d.prepare(`SELECT key, COUNT(*) as cnt, MAX(updated_at) as latest, MIN(created_at) as oldest
57456
- FROM memories WHERE ${base}
57457
- GROUP BY key HAVING COUNT(*) > 1
57458
- ORDER BY cnt DESC LIMIT ?`).all(...scopeParams, limit);
57459
- return { stale, forgotten, dupes };
57460
- }
57461
-
57462
- // src/server/routes/memories-stats.ts
57463
57699
  init_memories();
57464
57700
  init_router();
57465
57701
  addRoute("GET", "/api/memories/stats", () => {
@@ -57499,23 +57735,45 @@ addRoute("GET", "/api/activity", (_req, url) => {
57499
57735
  addRoute("GET", "/api/memories/stale", (_req, url) => {
57500
57736
  const q = getSearchParams(url);
57501
57737
  const days = q["days"] ? parseInt(q["days"], 10) : undefined;
57502
- const limit = Math.min(q["limit"] ? parseInt(q["limit"], 10) : 20, 100);
57503
- const memories = getStaleMemories({
57738
+ const parsedLimit = Number(q["limit"]);
57739
+ const limit = Number.isInteger(parsedLimit) && parsedLimit > 0 ? Math.min(parsedLimit, 1000) : 20;
57740
+ const parsedOffset = Number(q["offset"]);
57741
+ const offset = Number.isInteger(parsedOffset) && parsedOffset >= 0 ? parsedOffset : 0;
57742
+ const pinned = q["pinned"] === "1" || q["pinned"] === "true" ? true : q["pinned"] === "0" || q["pinned"] === "false" ? false : undefined;
57743
+ const page = getStaleMemoriesPage({
57504
57744
  days,
57745
+ pinned,
57505
57746
  project_id: q["project_id"],
57506
57747
  agent_id: q["agent_id"],
57507
57748
  limit,
57508
- offset: q["offset"] ? parseInt(q["offset"], 10) : undefined
57749
+ offset
57509
57750
  }, getDatabase());
57510
- return json({ memories, count: memories.length, days: Math.min(days || 30, 365) });
57751
+ return json({
57752
+ memories: page.rows,
57753
+ count: page.rows.length,
57754
+ total: page.total,
57755
+ days: Math.min(days || 30, 365),
57756
+ limit,
57757
+ has_more: page.has_more,
57758
+ next_cursor: page.next_cursor
57759
+ });
57511
57760
  });
57512
57761
  addRoute("GET", "/api/memories/history", (_req, url) => {
57513
57762
  const q = getSearchParams(url);
57514
- const memories = listMemoryHistory({
57515
- limit: Math.min(q["limit"] ? parseInt(q["limit"], 10) : 20, 200),
57516
- offset: q["offset"] ? parseInt(q["offset"], 10) : undefined
57517
- }, getDatabase());
57518
- return json({ memories, count: memories.length });
57763
+ const parsedLimit = Number(q["limit"]);
57764
+ const limit = Number.isInteger(parsedLimit) && parsedLimit > 0 ? Math.min(parsedLimit, 200) : 20;
57765
+ const parsedOffset = Number(q["offset"]);
57766
+ const offset = Number.isInteger(parsedOffset) && parsedOffset >= 0 ? parsedOffset : 0;
57767
+ const page = listMemoryHistoryPage({ limit, offset }, getDatabase());
57768
+ const total = countMemoryHistory(getDatabase());
57769
+ return json({
57770
+ memories: page.rows,
57771
+ count: page.rows.length,
57772
+ total,
57773
+ limit,
57774
+ has_more: page.has_more,
57775
+ next_cursor: page.next_cursor
57776
+ });
57519
57777
  });
57520
57778
  addRoute("GET", "/api/memories/health", (_req, url) => {
57521
57779
  const q = getSearchParams(url);
@@ -57556,7 +57814,7 @@ function hasFts5Table2(db) {
57556
57814
  function buildScopeFilter(opts) {
57557
57815
  const conditions = [
57558
57816
  "m.status = 'active'",
57559
- "(m.expires_at IS NULL OR m.expires_at >= datetime('now'))",
57817
+ "(m.expires_at IS NULL OR m.expires_at >= strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))",
57560
57818
  "m.category IN ('preference', 'fact', 'knowledge')"
57561
57819
  ];
57562
57820
  const params = [];
@@ -57824,7 +58082,7 @@ async function runTemporalAgent(db, query, opts) {
57824
58082
  const maxResults = opts.max_results ?? 20;
57825
58083
  const limit = maxResults * 3;
57826
58084
  const conditions = [
57827
- "(m.expires_at IS NULL OR m.expires_at >= datetime('now'))"
58085
+ "(m.expires_at IS NULL OR m.expires_at >= strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))"
57828
58086
  ];
57829
58087
  const params = [];
57830
58088
  if (opts.project_id) {
@@ -58594,6 +58852,90 @@ class MementosProjectRegistrationError extends Error {
58594
58852
  }
58595
58853
  }
58596
58854
 
58855
+ // src/project-registration/historical-receipt.ts
58856
+ var ROOT_TENANT_ID = "adfd95c7-ee8b-52cb-ae47-4ae65dae3313";
58857
+ var FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION = {
58858
+ authority: "mementos",
58859
+ authority_route: "mementos.project-registration.v1",
58860
+ package_version: "1.0.0-rc.3",
58861
+ authority_id: "mementos",
58862
+ tenant_id: "default",
58863
+ corpus_id: "default",
58864
+ operation_id: "op-cli-register-full",
58865
+ step_id: "mementos_project",
58866
+ resource_kind: "project",
58867
+ direction: "forward",
58868
+ target_selector: "wks_005285827590a93b70e5",
58869
+ target_id: "mm_project_f75606ef14e51fb577a15882ba0ab8ed333b2c29",
58870
+ idempotency_key: "prk_786cdc6babddeae1be8d5078d0f75322d1ea1010ac5d8a50",
58871
+ receipt_id: "mmpr_a647f9908a33bb64bf137f584202590f91b72a33",
58872
+ request_digest: "8eb0e3fee26fdb7edb8a444aeddaaedb79a84a5a36e742ae03616f62b19f5c22",
58873
+ precondition_digest: "0b6c22fcf75d835f9f27308b1a9d40e8902e48a97da370fd56df5acacfcd968e",
58874
+ result_revision: "2026-08-09T13:37:43.068Z",
58875
+ result_digest: "26fb0dd5c5e20909d3653ab0ddd8fa45e5142728e4e66d595e2419f7ed40b036",
58876
+ created_at: "2026-08-09T13:37:43.068Z",
58877
+ identity_digest: "1108dd972c90e4989036fb6ecec7dde10f54641a697bd53cfcd64017f589ace7",
58878
+ target_digest: "72789fcd60668eeb66ee068936d3afa96deadcb007228830c64b6de783b6dcef",
58879
+ operation_digest: "d7e37bfb2c0d28f8c4086c53224cd855d14694f32807b74c102b61a99963f3c0",
58880
+ idempotency_digest: "b56d8ec37efb818759cdd2ee3b58bc1401ac13384c8d64c1813bb5c198b1e376",
58881
+ receipt_digest: "52ce90c5de6817989f107d9d27e06156962a2b9c365e34e16a57aa37886501a2",
58882
+ response_digest: "2fa3ed508f5f192c18753b1205ced996340fdf02f735420d32db897fc239805c"
58883
+ };
58884
+ var FLEET_RESOURCES_HISTORICAL_RECEIPT = {
58885
+ receipt_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.receipt_id,
58886
+ authority: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.authority,
58887
+ route: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.authority_route,
58888
+ package_version: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.package_version,
58889
+ authority_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.authority_id,
58890
+ tenant_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.tenant_id,
58891
+ corpus_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.corpus_id,
58892
+ operation_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.operation_id,
58893
+ step_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.step_id,
58894
+ resource_kind: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.resource_kind,
58895
+ direction: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.direction,
58896
+ idempotency_key: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.idempotency_key,
58897
+ request_digest: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.request_digest,
58898
+ precondition_digest: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.precondition_digest,
58899
+ outcome: "accepted",
58900
+ reason: null,
58901
+ target_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.target_id,
58902
+ result_revision: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.result_revision,
58903
+ result_digest: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.result_digest,
58904
+ duplicate_of_receipt_id: null,
58905
+ accepted_receipt_id: null,
58906
+ created_by_operation: true,
58907
+ created_at: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.created_at
58908
+ };
58909
+ var FLEET_RESOURCES_CURRENT_PROJECT_REGISTRATION_IDENTITY = {
58910
+ authority_id: "mementos",
58911
+ tenant_id: ROOT_TENANT_ID,
58912
+ corpus_id: "mementos:postgresql"
58913
+ };
58914
+ var FLEET_RESOURCES_HISTORICAL_LOOKUP_IDENTITY = {
58915
+ source: {
58916
+ authority: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.authority,
58917
+ authority_route: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.authority_route,
58918
+ package_version: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.package_version,
58919
+ authority_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.authority_id,
58920
+ tenant_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.tenant_id,
58921
+ corpus_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.corpus_id,
58922
+ operation_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.operation_id,
58923
+ step_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.step_id,
58924
+ resource_kind: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.resource_kind,
58925
+ direction: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.direction,
58926
+ target_selector: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.target_selector,
58927
+ target_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.target_id,
58928
+ idempotency_key: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.idempotency_key,
58929
+ receipt_id: FLEET_RESOURCES_HISTORICAL_PROJECT_REGISTRATION.receipt_id
58930
+ },
58931
+ destination: FLEET_RESOURCES_CURRENT_PROJECT_REGISTRATION_IDENTITY,
58932
+ lookup_only: true,
58933
+ immutable_receipt: true
58934
+ };
58935
+ function supportsFleetResourcesHistoricalReceiptLookup(capability) {
58936
+ return capability.authority_id === FLEET_RESOURCES_CURRENT_PROJECT_REGISTRATION_IDENTITY.authority_id && capability.tenant_id === FLEET_RESOURCES_CURRENT_PROJECT_REGISTRATION_IDENTITY.tenant_id && capability.corpus_id === FLEET_RESOURCES_CURRENT_PROJECT_REGISTRATION_IDENTITY.corpus_id;
58937
+ }
58938
+
58597
58939
  // src/project-registration/identity.ts
58598
58940
  var MEMENTOS_PROJECT_AUTHORITY_ENV = {
58599
58941
  authorityId: "MEMENTOS_PROJECT_AUTHORITY_ID",
@@ -58635,12 +58977,13 @@ function resolveMementosProjectAuthorityIdentity(options = {}) {
58635
58977
  }
58636
58978
  function buildMementosProjectRegistrationCapability(options = {}) {
58637
58979
  const identity = resolveMementosProjectAuthorityIdentity(options);
58638
- return {
58980
+ const capability = {
58639
58981
  authority: "mementos",
58640
58982
  route: MEMENTOS_PROJECT_REGISTRATION_ROUTE,
58641
58983
  package_version: options.packageVersion ?? getMementosPackageVersion(),
58642
58984
  ...identity,
58643
58985
  supported_resources: ["project"],
58986
+ supported_historical_lookup_identities: [],
58644
58987
  conditional_create: true,
58645
58988
  immutable_receipts: true,
58646
58989
  exact_terminal_lookup: true,
@@ -58659,6 +59002,12 @@ function buildMementosProjectRegistrationCapability(options = {}) {
58659
59002
  stable_keyset_pagination: true,
58660
59003
  explicit_membership_only: true
58661
59004
  };
59005
+ if (supportsFleetResourcesHistoricalReceiptLookup(capability)) {
59006
+ capability.supported_historical_lookup_identities = [
59007
+ FLEET_RESOURCES_HISTORICAL_LOOKUP_IDENTITY
59008
+ ];
59009
+ }
59010
+ return capability;
58662
59011
  }
58663
59012
 
58664
59013
  // src/db/memory-project-link.ts
@@ -59567,7 +59916,7 @@ function acquireLock(agentId, resourceType, resourceId, lockType = "exclusive",
59567
59916
  }
59568
59917
  const d = db || getDatabase();
59569
59918
  cleanExpiredLocks(d);
59570
- const ownLock = d.query("SELECT * FROM resource_locks WHERE resource_type = ? AND resource_id = ? AND agent_id = ? AND lock_type = ? AND expires_at > datetime('now')").get(resourceType, resourceId, agentId, lockType);
59919
+ const ownLock = d.query("SELECT * FROM resource_locks WHERE resource_type = ? AND resource_id = ? AND agent_id = ? AND lock_type = ? AND expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')").get(resourceType, resourceId, agentId, lockType);
59571
59920
  if (ownLock) {
59572
59921
  const newExpiry = new Date(Date.now() + ttlSeconds * 1000).toISOString();
59573
59922
  d.run("UPDATE resource_locks SET expires_at = ? WHERE id = ?", [
@@ -59577,7 +59926,7 @@ function acquireLock(agentId, resourceType, resourceId, lockType = "exclusive",
59577
59926
  return parseLockRow({ ...ownLock, expires_at: newExpiry });
59578
59927
  }
59579
59928
  if (lockType === "exclusive") {
59580
- const existing = d.query("SELECT * FROM resource_locks WHERE resource_type = ? AND resource_id = ? AND lock_type = 'exclusive' AND agent_id != ? AND expires_at > datetime('now')").get(resourceType, resourceId, agentId);
59929
+ const existing = d.query("SELECT * FROM resource_locks WHERE resource_type = ? AND resource_id = ? AND lock_type = 'exclusive' AND agent_id != ? AND expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')").get(resourceType, resourceId, agentId);
59581
59930
  if (existing) {
59582
59931
  return null;
59583
59932
  }
@@ -59622,7 +59971,7 @@ function checkLock(resourceType, resourceId, lockType, db) {
59622
59971
  }
59623
59972
  const d = db || getDatabase();
59624
59973
  cleanExpiredLocks(d);
59625
- const query = lockType ? "SELECT * FROM resource_locks WHERE resource_type = ? AND resource_id = ? AND lock_type = ? AND expires_at > datetime('now')" : "SELECT * FROM resource_locks WHERE resource_type = ? AND resource_id = ? AND expires_at > datetime('now')";
59974
+ const query = lockType ? "SELECT * FROM resource_locks WHERE resource_type = ? AND resource_id = ? AND lock_type = ? AND expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')" : "SELECT * FROM resource_locks WHERE resource_type = ? AND resource_id = ? AND expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')";
59626
59975
  const rows = lockType ? d.query(query).all(resourceType, resourceId, lockType) : d.query(query).all(resourceType, resourceId);
59627
59976
  return rows.map(parseLockRow);
59628
59977
  }
@@ -59633,7 +59982,7 @@ function listAgentLocks(agentId, db) {
59633
59982
  }
59634
59983
  const d = db || getDatabase();
59635
59984
  cleanExpiredLocks(d);
59636
- const rows = d.query("SELECT * FROM resource_locks WHERE agent_id = ? AND expires_at > datetime('now') ORDER BY locked_at DESC").all(agentId);
59985
+ const rows = d.query("SELECT * FROM resource_locks WHERE agent_id = ? AND expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now') ORDER BY locked_at DESC").all(agentId);
59637
59986
  return rows.map(parseLockRow);
59638
59987
  }
59639
59988
  function cleanExpiredLocks(db) {
@@ -59642,7 +59991,7 @@ function cleanExpiredLocks(db) {
59642
59991
  return data?.cleaned ?? 0;
59643
59992
  }
59644
59993
  const d = db || getDatabase();
59645
- const result = d.run("DELETE FROM resource_locks WHERE expires_at <= datetime('now')");
59994
+ const result = d.run("DELETE FROM resource_locks WHERE expires_at <= strftime('%Y-%m-%dT%H:%M:%fZ', 'now')");
59646
59995
  return result.changes;
59647
59996
  }
59648
59997
 
@@ -60822,12 +61171,21 @@ function assertInverseRequest(request, capability) {
60822
61171
  }
60823
61172
  return accepted;
60824
61173
  }
61174
+ function matchesCurrentLookupIdentity(request, capability) {
61175
+ return request.authority_route === capability.route && request.package_version === capability.package_version && request.authority_id === capability.authority_id && request.tenant_id === capability.tenant_id && request.corpus_id === capability.corpus_id;
61176
+ }
61177
+ function matchesFleetResourcesHistoricalLookup(request, capability) {
61178
+ if (!supportsFleetResourcesHistoricalReceiptLookup(capability))
61179
+ return false;
61180
+ const source = FLEET_RESOURCES_HISTORICAL_LOOKUP_IDENTITY.source;
61181
+ return request.authority === source.authority && request.authority_route === source.authority_route && request.package_version === source.package_version && request.authority_id === source.authority_id && request.tenant_id === source.tenant_id && request.corpus_id === source.corpus_id && request.operation_id === source.operation_id && request.step_id === source.step_id && request.resource_kind === source.resource_kind && request.direction === source.direction && request.target_selector === source.target_selector && request.target_id === source.target_id && request.idempotency_key === source.idempotency_key;
61182
+ }
60825
61183
  function assertLookup(request, capability) {
60826
61184
  assertBounds(request);
60827
61185
  if (request.max_items !== 1) {
60828
61186
  throw new MementosProjectRegistrationError("MEMENTOS_PROJECT_REGISTRATION_INVALID_BOUNDS", "terminal receipt lookup requires max_items exactly 1");
60829
61187
  }
60830
- if (request.authority !== "mementos" || request.resource_kind !== "project" || request.authority_route !== capability.route || request.package_version !== capability.package_version || request.authority_id !== capability.authority_id || request.tenant_id !== capability.tenant_id || request.corpus_id !== capability.corpus_id) {
61188
+ if (request.authority !== "mementos" || request.resource_kind !== "project" || !matchesCurrentLookupIdentity(request, capability) && !matchesFleetResourcesHistoricalLookup(request, capability)) {
60831
61189
  throw new MementosProjectRegistrationError("MEMENTOS_PROJECT_REGISTRATION_CAPABILITY_MISMATCH", "receipt lookup does not match this authority capability identity");
60832
61190
  }
60833
61191
  requireString(request.operation_id, "operation_id", { pattern: OPERATION_PATTERN });
@@ -60845,6 +61203,7 @@ function assertLookup(request, capability) {
60845
61203
  pattern: PROJECT_ID_PATTERN
60846
61204
  });
60847
61205
  }
61206
+ return matchesCurrentLookupIdentity(request, capability) ? "current" : "fleet_resources_historical";
60848
61207
  }
60849
61208
 
60850
61209
  class PackageOwnedMementosProjectRegistrationAuthority {
@@ -61109,11 +61468,14 @@ class PackageOwnedMementosProjectRegistrationAuthority {
61109
61468
  }
61110
61469
  async lookupReceipt(request) {
61111
61470
  const startedAt = Date.now();
61112
- assertLookup(request, this.capabilityValue);
61471
+ const lookupIdentity = assertLookup(request, this.capabilityValue);
61113
61472
  const receipt = getReceiptForLookup(this.db, request);
61114
61473
  if (!receipt || request.target_id !== undefined && receipt.target_id !== request.target_id) {
61115
61474
  throw new MementosProjectRegistrationError("MEMENTOS_PROJECT_REGISTRATION_RECEIPT_NOT_FOUND", "exact immutable terminal receipt was not found");
61116
61475
  }
61476
+ if (lookupIdentity === "fleet_resources_historical" && (receipt.receipt_id !== FLEET_RESOURCES_HISTORICAL_LOOKUP_IDENTITY.source.receipt_id || canonicalMementosProjectRegistrationJson(publicReceipt(receipt)) !== canonicalMementosProjectRegistrationJson(FLEET_RESOURCES_HISTORICAL_RECEIPT))) {
61477
+ throw new MementosProjectRegistrationError("MEMENTOS_PROJECT_REGISTRATION_RECEIPT_NOT_FOUND", "exact immutable historical terminal receipt was not found");
61478
+ }
61117
61479
  return withResponseControl(publicReceipt(receipt), request, startedAt);
61118
61480
  }
61119
61481
  async compensate(request) {
@@ -64720,13 +65082,11 @@ function startServer(port) {
64720
65082
  const profile = getActiveProfile();
64721
65083
  try {
64722
65084
  const db = getDatabase();
64723
- const total = db.query("SELECT COUNT(*) as c FROM memories WHERE status = 'active'").get().c;
64724
- const expired = db.query("SELECT COUNT(*) as c FROM memories WHERE status = 'expired' OR (expires_at IS NOT NULL AND expires_at < datetime('now'))").get().c;
64725
- const pinned = db.query("SELECT COUNT(*) as c FROM memories WHERE status = 'active' AND pinned = 1").get().c;
65085
+ const stats = getMemoryStats(db);
64726
65086
  const agents = db.query("SELECT COUNT(*) as c FROM agents").get().c;
64727
65087
  const projects = db.query("SELECT COUNT(*) as c FROM projects").get().c;
64728
- const status = expired > 50 ? "warn" : "ok";
64729
- return json({ status, version: pkgVersion(), backend, profile: profile ?? "default", db_path: getDbPath(), hostname: hostname3, memories: { total, expired, pinned }, agents, projects });
65088
+ const status = stats.expired_due_count > 50 ? "warn" : "ok";
65089
+ return json({ status, version: pkgVersion(), backend, profile: profile ?? "default", db_path: getDbPath(), hostname: hostname3, memories: { total: stats.total, expired: stats.expired_count, expired_due: stats.expired_due_count, pinned: stats.pinned_count }, agents, projects });
64730
65090
  } catch (e) {
64731
65091
  return json({ status: "error", version: pkgVersion(), backend, error: e instanceof Error ? e.message : String(e) }, 503);
64732
65092
  }