@agentmemory/agentmemory 0.9.30 → 0.9.31

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 (331) hide show
  1. package/.env.example +39 -33
  2. package/AGENTS.md +8 -8
  3. package/README.md +173 -558
  4. package/dist/.env.example +39 -33
  5. package/dist/cli.d.mts.map +1 -1
  6. package/dist/cli.mjs +1741 -966
  7. package/dist/cli.mjs.map +1 -1
  8. package/dist/compression-recovery-CnhLQC6N.mjs +5912 -0
  9. package/dist/compression-recovery-CnhLQC6N.mjs.map +1 -0
  10. package/dist/{connect-B4_ca6BD.mjs → connect-BSLIAMpw.mjs} +874 -267
  11. package/dist/connect-BSLIAMpw.mjs.map +1 -0
  12. package/dist/hooks/_capture.d.mts +5 -2
  13. package/dist/hooks/_capture.d.mts.map +1 -1
  14. package/dist/hooks/_capture.mjs +55 -19
  15. package/dist/hooks/_capture.mjs.map +1 -1
  16. package/dist/hooks/notification.mjs +20 -6
  17. package/dist/hooks/notification.mjs.map +1 -1
  18. package/dist/hooks/post-commit.mjs +25 -5
  19. package/dist/hooks/post-commit.mjs.map +1 -1
  20. package/dist/hooks/post-tool-failure.mjs +12 -4
  21. package/dist/hooks/post-tool-failure.mjs.map +1 -1
  22. package/dist/hooks/post-tool-use.mjs +12 -4
  23. package/dist/hooks/post-tool-use.mjs.map +1 -1
  24. package/dist/hooks/pre-compact.mjs +37 -10
  25. package/dist/hooks/pre-compact.mjs.map +1 -1
  26. package/dist/hooks/pre-tool-use.mjs +25 -5
  27. package/dist/hooks/pre-tool-use.mjs.map +1 -1
  28. package/dist/hooks/prompt-submit.mjs +12 -4
  29. package/dist/hooks/prompt-submit.mjs.map +1 -1
  30. package/dist/hooks/session-end.mjs +47 -16
  31. package/dist/hooks/session-end.mjs.map +1 -1
  32. package/dist/hooks/session-start.mjs +37 -10
  33. package/dist/hooks/session-start.mjs.map +1 -1
  34. package/dist/hooks/stop.mjs +74 -72
  35. package/dist/hooks/stop.mjs.map +1 -1
  36. package/dist/hooks/subagent-start.mjs +13 -5
  37. package/dist/hooks/subagent-start.mjs.map +1 -1
  38. package/dist/hooks/subagent-stop.mjs +18 -6
  39. package/dist/hooks/subagent-stop.mjs.map +1 -1
  40. package/dist/hooks/task-completed.mjs +13 -5
  41. package/dist/hooks/task-completed.mjs.map +1 -1
  42. package/dist/{image-refs-T_urbwHM.mjs → image-refs-Cyta4Lf9.mjs} +2 -2
  43. package/dist/{image-refs-T_urbwHM.mjs.map → image-refs-Cyta4Lf9.mjs.map} +1 -1
  44. package/dist/index.mjs +8539 -4203
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/integrations/dsh.d.mts +55 -0
  47. package/dist/integrations/dsh.d.mts.map +1 -0
  48. package/dist/integrations/dsh.mjs +1145 -0
  49. package/dist/integrations/dsh.mjs.map +1 -0
  50. package/dist/{keyed-mutex-DchXsyfP.mjs → keyed-mutex-DCUh7PG-.mjs} +58 -9
  51. package/dist/keyed-mutex-DCUh7PG-.mjs.map +1 -0
  52. package/dist/{secret-store-BnY3A50C.mjs → secret-store-D9GwO0xp.mjs} +535 -434
  53. package/dist/secret-store-D9GwO0xp.mjs.map +1 -0
  54. package/dist/session-arguments-zxsbbd8y.mjs +113 -0
  55. package/dist/session-arguments-zxsbbd8y.mjs.map +1 -0
  56. package/dist/{src-Jsq9LCeH.mjs → src-DaMtDzt_.mjs} +4087 -3788
  57. package/dist/src-DaMtDzt_.mjs.map +1 -0
  58. package/dist/{standalone-DKCdrf1d.mjs → standalone-BlqshyZ5.mjs} +213 -56
  59. package/dist/standalone-BlqshyZ5.mjs.map +1 -0
  60. package/dist/standalone.d.mts +1 -1
  61. package/dist/standalone.d.mts.map +1 -1
  62. package/dist/standalone.mjs +626 -73
  63. package/dist/standalone.mjs.map +1 -1
  64. package/dist/viewer/index.html +288 -140
  65. package/integrations/hermes/README.md +84 -0
  66. package/integrations/hermes/__init__.py +669 -0
  67. package/integrations/hermes/plugin.yaml +27 -0
  68. package/integrations/omp/LICENSE +190 -0
  69. package/integrations/omp/README.md +76 -0
  70. package/integrations/omp/capture.ts +1 -0
  71. package/integrations/omp/dist/index.mjs +1450 -0
  72. package/integrations/omp/index.ts +488 -0
  73. package/integrations/omp/package.json +13 -0
  74. package/integrations/omp/security.ts +67 -0
  75. package/integrations/omp/skills/agentmemory-agents/REFERENCE.md +32 -0
  76. package/integrations/omp/skills/agentmemory-agents/SKILL.md +48 -0
  77. package/integrations/omp/skills/agentmemory-agents/TROUBLESHOOTING.md +70 -0
  78. package/integrations/omp/skills/agentmemory-architecture/SKILL.md +33 -0
  79. package/integrations/omp/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
  80. package/integrations/omp/skills/agentmemory-config/REFERENCE.md +90 -0
  81. package/integrations/omp/skills/agentmemory-config/SKILL.md +78 -0
  82. package/integrations/omp/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
  83. package/integrations/omp/skills/agentmemory-hooks/REFERENCE.md +20 -0
  84. package/integrations/omp/skills/agentmemory-hooks/SKILL.md +49 -0
  85. package/integrations/omp/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
  86. package/integrations/omp/skills/agentmemory-mcp-tools/REFERENCE.md +66 -0
  87. package/integrations/omp/skills/agentmemory-mcp-tools/SKILL.md +42 -0
  88. package/integrations/omp/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
  89. package/integrations/omp/skills/agentmemory-rest-api/REFERENCE.md +158 -0
  90. package/integrations/omp/skills/agentmemory-rest-api/SKILL.md +49 -0
  91. package/integrations/omp/skills/agentmemory-rest-api/TROUBLESHOOTING.md +70 -0
  92. package/integrations/omp/skills/commit-context/EXAMPLES.md +71 -0
  93. package/integrations/omp/skills/commit-context/SKILL.md +64 -0
  94. package/integrations/omp/skills/commit-context/TROUBLESHOOTING.md +70 -0
  95. package/integrations/omp/skills/commit-history/EXAMPLES.md +71 -0
  96. package/integrations/omp/skills/commit-history/SKILL.md +62 -0
  97. package/integrations/omp/skills/commit-history/TROUBLESHOOTING.md +70 -0
  98. package/integrations/omp/skills/forget/EXAMPLES.md +40 -0
  99. package/integrations/omp/skills/forget/SKILL.md +73 -0
  100. package/integrations/omp/skills/forget/TROUBLESHOOTING.md +70 -0
  101. package/integrations/omp/skills/handoff/EXAMPLES.md +57 -0
  102. package/integrations/omp/skills/handoff/SKILL.md +75 -0
  103. package/integrations/omp/skills/handoff/TROUBLESHOOTING.md +70 -0
  104. package/integrations/omp/skills/lesson/SKILL.md +64 -0
  105. package/integrations/omp/skills/lesson/TROUBLESHOOTING.md +70 -0
  106. package/integrations/omp/skills/memory-discipline/SKILL.md +65 -0
  107. package/integrations/omp/skills/memory-discipline/TROUBLESHOOTING.md +70 -0
  108. package/integrations/omp/skills/recall/EXAMPLES.md +74 -0
  109. package/integrations/omp/skills/recall/SKILL.md +74 -0
  110. package/integrations/omp/skills/recall/TROUBLESHOOTING.md +70 -0
  111. package/integrations/omp/skills/recap/EXAMPLES.md +62 -0
  112. package/integrations/omp/skills/recap/SKILL.md +68 -0
  113. package/integrations/omp/skills/recap/TROUBLESHOOTING.md +70 -0
  114. package/integrations/omp/skills/remember/EXAMPLES.md +67 -0
  115. package/integrations/omp/skills/remember/SKILL.md +66 -0
  116. package/integrations/omp/skills/remember/TROUBLESHOOTING.md +70 -0
  117. package/integrations/omp/skills/session-history/EXAMPLES.md +59 -0
  118. package/integrations/omp/skills/session-history/SKILL.md +67 -0
  119. package/integrations/omp/skills/session-history/TROUBLESHOOTING.md +70 -0
  120. package/integrations/omp/skills/write-agentmemory-skill/SKILL.md +41 -0
  121. package/integrations/omp/skills/write-agentmemory-skill/TROUBLESHOOTING.md +70 -0
  122. package/integrations/openclaw/LICENSE +190 -0
  123. package/integrations/openclaw/README.md +88 -0
  124. package/integrations/openclaw/openclaw.plugin.json +71 -0
  125. package/integrations/openclaw/package.json +38 -0
  126. package/integrations/openclaw/plugin.mjs +425 -0
  127. package/integrations/openclaw/plugin.yaml +26 -0
  128. package/integrations/openclaw/skills/agentmemory-agents/REFERENCE.md +32 -0
  129. package/integrations/openclaw/skills/agentmemory-agents/SKILL.md +48 -0
  130. package/integrations/openclaw/skills/agentmemory-agents/TROUBLESHOOTING.md +70 -0
  131. package/integrations/openclaw/skills/agentmemory-architecture/SKILL.md +33 -0
  132. package/integrations/openclaw/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
  133. package/integrations/openclaw/skills/agentmemory-config/REFERENCE.md +90 -0
  134. package/integrations/openclaw/skills/agentmemory-config/SKILL.md +78 -0
  135. package/integrations/openclaw/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
  136. package/integrations/openclaw/skills/agentmemory-hooks/REFERENCE.md +20 -0
  137. package/integrations/openclaw/skills/agentmemory-hooks/SKILL.md +49 -0
  138. package/integrations/openclaw/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
  139. package/integrations/openclaw/skills/agentmemory-mcp-tools/REFERENCE.md +66 -0
  140. package/integrations/openclaw/skills/agentmemory-mcp-tools/SKILL.md +42 -0
  141. package/integrations/openclaw/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
  142. package/integrations/openclaw/skills/agentmemory-rest-api/REFERENCE.md +158 -0
  143. package/integrations/openclaw/skills/agentmemory-rest-api/SKILL.md +49 -0
  144. package/integrations/openclaw/skills/agentmemory-rest-api/TROUBLESHOOTING.md +70 -0
  145. package/integrations/openclaw/skills/commit-context/EXAMPLES.md +71 -0
  146. package/integrations/openclaw/skills/commit-context/SKILL.md +64 -0
  147. package/integrations/openclaw/skills/commit-context/TROUBLESHOOTING.md +70 -0
  148. package/integrations/openclaw/skills/commit-history/EXAMPLES.md +71 -0
  149. package/integrations/openclaw/skills/commit-history/SKILL.md +62 -0
  150. package/integrations/openclaw/skills/commit-history/TROUBLESHOOTING.md +70 -0
  151. package/integrations/openclaw/skills/forget/EXAMPLES.md +40 -0
  152. package/integrations/openclaw/skills/forget/SKILL.md +73 -0
  153. package/integrations/openclaw/skills/forget/TROUBLESHOOTING.md +70 -0
  154. package/integrations/openclaw/skills/handoff/EXAMPLES.md +57 -0
  155. package/integrations/openclaw/skills/handoff/SKILL.md +75 -0
  156. package/integrations/openclaw/skills/handoff/TROUBLESHOOTING.md +70 -0
  157. package/integrations/openclaw/skills/lesson/SKILL.md +64 -0
  158. package/integrations/openclaw/skills/lesson/TROUBLESHOOTING.md +70 -0
  159. package/integrations/openclaw/skills/memory-discipline/SKILL.md +65 -0
  160. package/integrations/openclaw/skills/memory-discipline/TROUBLESHOOTING.md +70 -0
  161. package/integrations/openclaw/skills/recall/EXAMPLES.md +74 -0
  162. package/integrations/openclaw/skills/recall/SKILL.md +74 -0
  163. package/integrations/openclaw/skills/recall/TROUBLESHOOTING.md +70 -0
  164. package/integrations/openclaw/skills/recap/EXAMPLES.md +62 -0
  165. package/integrations/openclaw/skills/recap/SKILL.md +68 -0
  166. package/integrations/openclaw/skills/recap/TROUBLESHOOTING.md +70 -0
  167. package/integrations/openclaw/skills/remember/EXAMPLES.md +67 -0
  168. package/integrations/openclaw/skills/remember/SKILL.md +66 -0
  169. package/integrations/openclaw/skills/remember/TROUBLESHOOTING.md +70 -0
  170. package/integrations/openclaw/skills/session-history/EXAMPLES.md +59 -0
  171. package/integrations/openclaw/skills/session-history/SKILL.md +67 -0
  172. package/integrations/openclaw/skills/session-history/TROUBLESHOOTING.md +70 -0
  173. package/integrations/openclaw/skills/write-agentmemory-skill/SKILL.md +41 -0
  174. package/integrations/openclaw/skills/write-agentmemory-skill/TROUBLESHOOTING.md +70 -0
  175. package/integrations/pi/LICENSE +190 -0
  176. package/integrations/pi/README.md +45 -51
  177. package/integrations/pi/dist/index.mjs +1379 -0
  178. package/integrations/pi/index.ts +138 -171
  179. package/integrations/pi/package.json +16 -6
  180. package/integrations/pi/security.ts +6 -26
  181. package/integrations/pi/skills/agentmemory-agents/REFERENCE.md +32 -0
  182. package/integrations/pi/skills/agentmemory-agents/SKILL.md +48 -0
  183. package/integrations/pi/skills/agentmemory-agents/TROUBLESHOOTING.md +70 -0
  184. package/integrations/pi/skills/agentmemory-architecture/SKILL.md +33 -0
  185. package/integrations/pi/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
  186. package/integrations/pi/skills/agentmemory-config/REFERENCE.md +90 -0
  187. package/integrations/pi/skills/agentmemory-config/SKILL.md +78 -0
  188. package/integrations/pi/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
  189. package/integrations/pi/skills/agentmemory-hooks/REFERENCE.md +20 -0
  190. package/integrations/pi/skills/agentmemory-hooks/SKILL.md +49 -0
  191. package/integrations/pi/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
  192. package/integrations/pi/skills/agentmemory-mcp-tools/REFERENCE.md +66 -0
  193. package/integrations/pi/skills/agentmemory-mcp-tools/SKILL.md +42 -0
  194. package/integrations/pi/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
  195. package/integrations/pi/skills/agentmemory-rest-api/REFERENCE.md +158 -0
  196. package/integrations/pi/skills/agentmemory-rest-api/SKILL.md +49 -0
  197. package/integrations/pi/skills/agentmemory-rest-api/TROUBLESHOOTING.md +70 -0
  198. package/integrations/pi/skills/commit-context/EXAMPLES.md +71 -0
  199. package/integrations/pi/skills/commit-context/SKILL.md +64 -0
  200. package/integrations/pi/skills/commit-context/TROUBLESHOOTING.md +70 -0
  201. package/integrations/pi/skills/commit-history/EXAMPLES.md +71 -0
  202. package/integrations/pi/skills/commit-history/SKILL.md +62 -0
  203. package/integrations/pi/skills/commit-history/TROUBLESHOOTING.md +70 -0
  204. package/integrations/pi/skills/forget/EXAMPLES.md +40 -0
  205. package/integrations/pi/skills/forget/SKILL.md +73 -0
  206. package/integrations/pi/skills/forget/TROUBLESHOOTING.md +70 -0
  207. package/integrations/pi/skills/handoff/EXAMPLES.md +57 -0
  208. package/integrations/pi/skills/handoff/SKILL.md +75 -0
  209. package/integrations/pi/skills/handoff/TROUBLESHOOTING.md +70 -0
  210. package/integrations/pi/skills/lesson/SKILL.md +64 -0
  211. package/integrations/pi/skills/lesson/TROUBLESHOOTING.md +70 -0
  212. package/integrations/pi/skills/memory-discipline/SKILL.md +65 -0
  213. package/integrations/pi/skills/memory-discipline/TROUBLESHOOTING.md +70 -0
  214. package/integrations/pi/skills/recall/EXAMPLES.md +74 -0
  215. package/integrations/pi/skills/recall/SKILL.md +74 -0
  216. package/integrations/pi/skills/recall/TROUBLESHOOTING.md +70 -0
  217. package/integrations/pi/skills/recap/EXAMPLES.md +62 -0
  218. package/integrations/pi/skills/recap/SKILL.md +68 -0
  219. package/integrations/pi/skills/recap/TROUBLESHOOTING.md +70 -0
  220. package/integrations/pi/skills/remember/EXAMPLES.md +67 -0
  221. package/integrations/pi/skills/remember/SKILL.md +66 -0
  222. package/integrations/pi/skills/remember/TROUBLESHOOTING.md +70 -0
  223. package/integrations/pi/skills/session-history/EXAMPLES.md +59 -0
  224. package/integrations/pi/skills/session-history/SKILL.md +67 -0
  225. package/integrations/pi/skills/session-history/TROUBLESHOOTING.md +70 -0
  226. package/integrations/pi/skills/write-agentmemory-skill/SKILL.md +41 -0
  227. package/integrations/pi/skills/write-agentmemory-skill/TROUBLESHOOTING.md +70 -0
  228. package/package.json +32 -11
  229. package/plugin/.claude-plugin/plugin.json +1 -1
  230. package/plugin/.codex-plugin/plugin.json +4 -3
  231. package/plugin/.devin-plugin/plugin.json +5 -3
  232. package/plugin/cursor/hooks.json +23 -8
  233. package/plugin/hooks.json +67 -0
  234. package/plugin/opencode/README.md +1 -1
  235. package/plugin/opencode/agentmemory-capture.ts +25 -11
  236. package/plugin/opencode/plugin.json +1 -1
  237. package/plugin/plugin.json +1 -1
  238. package/plugin/scripts/_capture.d.mts +5 -2
  239. package/plugin/scripts/_capture.d.mts.map +1 -1
  240. package/plugin/scripts/_capture.mjs +55 -19
  241. package/plugin/scripts/_capture.mjs.map +1 -1
  242. package/plugin/scripts/cursor/run-detached.d.mts +1 -0
  243. package/plugin/scripts/cursor/run-detached.mjs +786 -0
  244. package/plugin/scripts/cursor/run-detached.mjs.map +1 -0
  245. package/plugin/scripts/cursor/run-hook.d.mts +1 -0
  246. package/plugin/scripts/cursor/run-hook.mjs +704 -0
  247. package/plugin/scripts/cursor/run-hook.mjs.map +1 -0
  248. package/plugin/scripts/notification.mjs +20 -6
  249. package/plugin/scripts/notification.mjs.map +1 -1
  250. package/plugin/scripts/plugin-bridge.mjs +37 -6
  251. package/plugin/scripts/post-commit.mjs +25 -5
  252. package/plugin/scripts/post-commit.mjs.map +1 -1
  253. package/plugin/scripts/post-tool-failure.mjs +12 -4
  254. package/plugin/scripts/post-tool-failure.mjs.map +1 -1
  255. package/plugin/scripts/post-tool-use.mjs +12 -4
  256. package/plugin/scripts/post-tool-use.mjs.map +1 -1
  257. package/plugin/scripts/pre-compact.mjs +37 -10
  258. package/plugin/scripts/pre-compact.mjs.map +1 -1
  259. package/plugin/scripts/pre-tool-use.mjs +25 -5
  260. package/plugin/scripts/pre-tool-use.mjs.map +1 -1
  261. package/plugin/scripts/prompt-submit.mjs +12 -4
  262. package/plugin/scripts/prompt-submit.mjs.map +1 -1
  263. package/plugin/scripts/session-end.mjs +47 -16
  264. package/plugin/scripts/session-end.mjs.map +1 -1
  265. package/plugin/scripts/session-start.mjs +37 -10
  266. package/plugin/scripts/session-start.mjs.map +1 -1
  267. package/plugin/scripts/stop.mjs +74 -72
  268. package/plugin/scripts/stop.mjs.map +1 -1
  269. package/plugin/scripts/subagent-start.mjs +13 -5
  270. package/plugin/scripts/subagent-start.mjs.map +1 -1
  271. package/plugin/scripts/subagent-stop.mjs +18 -6
  272. package/plugin/scripts/subagent-stop.mjs.map +1 -1
  273. package/plugin/scripts/task-completed.mjs +13 -5
  274. package/plugin/scripts/task-completed.mjs.map +1 -1
  275. package/plugin/skills/_shared/TROUBLESHOOTING.md +21 -7
  276. package/plugin/skills/agentmemory-agents/REFERENCE.md +7 -6
  277. package/plugin/skills/agentmemory-agents/SKILL.md +19 -5
  278. package/plugin/skills/agentmemory-agents/TROUBLESHOOTING.md +70 -0
  279. package/plugin/skills/agentmemory-architecture/SKILL.md +4 -4
  280. package/plugin/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
  281. package/plugin/skills/agentmemory-config/REFERENCE.md +12 -15
  282. package/plugin/skills/agentmemory-config/SKILL.md +7 -3
  283. package/plugin/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
  284. package/plugin/skills/agentmemory-hooks/SKILL.md +15 -5
  285. package/plugin/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
  286. package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +4 -4
  287. package/plugin/skills/agentmemory-mcp-tools/SKILL.md +6 -3
  288. package/plugin/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
  289. package/plugin/skills/agentmemory-rest-api/REFERENCE.md +9 -1
  290. package/plugin/skills/agentmemory-rest-api/SKILL.md +12 -6
  291. package/plugin/skills/agentmemory-rest-api/TROUBLESHOOTING.md +70 -0
  292. package/plugin/skills/commit-context/SKILL.md +1 -1
  293. package/plugin/skills/commit-context/TROUBLESHOOTING.md +70 -0
  294. package/plugin/skills/commit-history/SKILL.md +1 -1
  295. package/plugin/skills/commit-history/TROUBLESHOOTING.md +70 -0
  296. package/plugin/skills/forget/EXAMPLES.md +19 -54
  297. package/plugin/skills/forget/SKILL.md +16 -12
  298. package/plugin/skills/forget/TROUBLESHOOTING.md +70 -0
  299. package/plugin/skills/handoff/EXAMPLES.md +5 -4
  300. package/plugin/skills/handoff/SKILL.md +10 -5
  301. package/plugin/skills/handoff/TROUBLESHOOTING.md +70 -0
  302. package/plugin/skills/lesson/SKILL.md +1 -1
  303. package/plugin/skills/lesson/TROUBLESHOOTING.md +70 -0
  304. package/plugin/skills/memory-discipline/SKILL.md +1 -1
  305. package/plugin/skills/memory-discipline/TROUBLESHOOTING.md +70 -0
  306. package/plugin/skills/recall/SKILL.md +18 -7
  307. package/plugin/skills/recall/TROUBLESHOOTING.md +70 -0
  308. package/plugin/skills/recap/EXAMPLES.md +5 -3
  309. package/plugin/skills/recap/SKILL.md +11 -6
  310. package/plugin/skills/recap/TROUBLESHOOTING.md +70 -0
  311. package/plugin/skills/remember/EXAMPLES.md +3 -3
  312. package/plugin/skills/remember/SKILL.md +1 -1
  313. package/plugin/skills/remember/TROUBLESHOOTING.md +70 -0
  314. package/plugin/skills/session-history/EXAMPLES.md +2 -2
  315. package/plugin/skills/session-history/SKILL.md +10 -4
  316. package/plugin/skills/session-history/TROUBLESHOOTING.md +70 -0
  317. package/plugin/skills/write-agentmemory-skill/SKILL.md +2 -1
  318. package/plugin/skills/write-agentmemory-skill/TROUBLESHOOTING.md +70 -0
  319. package/dist/connect-B4_ca6BD.mjs.map +0 -1
  320. package/dist/docker-compose.yml +0 -73
  321. package/dist/iii-config.docker.yaml +0 -53
  322. package/dist/iii-config.yaml +0 -63
  323. package/dist/keyed-mutex-DchXsyfP.mjs.map +0 -1
  324. package/dist/secret-store-BnY3A50C.mjs.map +0 -1
  325. package/dist/src-Jsq9LCeH.mjs.map +0 -1
  326. package/dist/standalone-DKCdrf1d.mjs.map +0 -1
  327. package/dist/status-IRz7ta8-.mjs +0 -2344
  328. package/dist/status-IRz7ta8-.mjs.map +0 -1
  329. package/docker-compose.yml +0 -73
  330. package/iii-config.docker.yaml +0 -53
  331. package/iii-config.yaml +0 -63
@@ -4,6 +4,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
4
  import { dirname, join } from "node:path";
5
5
  import { homedir } from "node:os";
6
6
  import "picocolors";
7
+ import { AsyncLocalStorage } from "node:async_hooks";
7
8
  //#region src/mcp/in-memory-kv.ts
8
9
  var InMemoryKV = class {
9
10
  store = /* @__PURE__ */ new Map();
@@ -34,20 +35,23 @@ var InMemoryKV = class {
34
35
  return entries ? Array.from(entries.values()) : [];
35
36
  }
36
37
  persist() {
37
- if (!this.persistPath) return;
38
+ if (!this.persistPath) return false;
38
39
  try {
39
40
  const dir = dirname(this.persistPath);
40
41
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
41
42
  const data = {};
42
43
  for (const [scope, entries] of this.store) data[scope] = Object.fromEntries(entries);
43
44
  writeFileSync(this.persistPath, JSON.stringify(data), "utf-8");
45
+ return true;
44
46
  } catch (err) {
45
47
  process.stderr.write(`[@agentmemory/mcp] Persist failed: ${err instanceof Error ? err.message : String(err)}\n`);
48
+ return false;
46
49
  }
47
50
  }
48
51
  };
49
52
  //#endregion
50
53
  //#region src/mcp/transport.ts
54
+ let activeStdioTransports = 0;
51
55
  var JsonRpcError = class extends Error {
52
56
  constructor(code, message) {
53
57
  super(message);
@@ -200,6 +204,7 @@ function createMessageParser(onMessage, writeErr = (msg) => process.stderr.write
200
204
  function createStdioTransport(handler) {
201
205
  let parser = null;
202
206
  let queue = Promise.resolve();
207
+ let active = false;
203
208
  const writeResponse = (response) => {
204
209
  const formatted = formatResponse(response, parser?.isFramed() ?? false);
205
210
  if (typeof formatted === "string") {
@@ -211,6 +216,10 @@ function createStdioTransport(handler) {
211
216
  const onData = (chunk) => parser?.push(chunk);
212
217
  return {
213
218
  start() {
219
+ if (active) return;
220
+ active = true;
221
+ activeStdioTransports += 1;
222
+ process.env["AGENTMEMORY_MCP_STDIO__"] = "1";
214
223
  parser = createMessageParser((message) => {
215
224
  queue = queue.then(() => processLine(message, handler, writeResponse));
216
225
  queue.catch((err) => {
@@ -221,6 +230,11 @@ function createStdioTransport(handler) {
221
230
  },
222
231
  stop() {
223
232
  process.stdin.off("data", onData);
233
+ if (active) {
234
+ active = false;
235
+ activeStdioTransports -= 1;
236
+ if (activeStdioTransports === 0) delete process.env["AGENTMEMORY_MCP_STDIO__"];
237
+ }
224
238
  parser = null;
225
239
  }
226
240
  };
@@ -230,7 +244,7 @@ function createStdioTransport(handler) {
230
244
  const CORE_TOOLS = [
231
245
  {
232
246
  name: "memory_recall",
233
- description: "Search past session observations for relevant context. Use when you need to recall what happened in previous sessions, find past decisions, or look up how a file was modified before.",
247
+ description: "Search stored memories and session observations for relevant context. Use when you need to recall what happened in previous sessions, find past decisions, or look up how a file was modified before.",
234
248
  inputSchema: {
235
249
  type: "object",
236
250
  properties: {
@@ -248,7 +262,28 @@ const CORE_TOOLS = [
248
262
  },
249
263
  token_budget: {
250
264
  type: "number",
251
- description: "Optional token budget to trim returned results"
265
+ description: "Optional estimated content token budget; response includes truncation and recovery metadata"
266
+ },
267
+ targetLayer: {
268
+ type: "string",
269
+ enum: [
270
+ "all",
271
+ "memory",
272
+ "observation"
273
+ ],
274
+ description: "Search all indexed layers (default), durable memories, or raw observations before ranking"
275
+ },
276
+ project: {
277
+ type: "string",
278
+ description: "Filter by project path"
279
+ },
280
+ cwd: {
281
+ type: "string",
282
+ description: "Filter by session working directory"
283
+ },
284
+ agentId: {
285
+ type: "string",
286
+ description: "Filter by owning agent; '*' reads across agents"
252
287
  }
253
288
  },
254
289
  required: ["query"]
@@ -337,15 +372,32 @@ const CORE_TOOLS = [
337
372
  },
338
373
  {
339
374
  name: "memory_sessions",
340
- description: "List recent sessions with their status and observation counts.",
375
+ description: "List recent sessions with status, observation counts, summaries and a continuation cursor. Filters apply before pagination; retain them when requesting the next page.",
341
376
  inputSchema: {
342
377
  type: "object",
343
- properties: {}
378
+ properties: {
379
+ project: {
380
+ type: "string",
381
+ description: "Exact project identifier used when sessions were started"
382
+ },
383
+ agentId: {
384
+ type: "string",
385
+ description: "Filter by owning agent; '*' reads across agents"
386
+ },
387
+ limit: {
388
+ type: "integer",
389
+ description: "Page size (default 20, max 100)"
390
+ },
391
+ cursor: {
392
+ type: "string",
393
+ description: "nextCursor from the previous page; omit for the first page"
394
+ }
395
+ }
344
396
  }
345
397
  },
346
398
  {
347
399
  name: "memory_smart_search",
348
- description: "Hybrid semantic+keyword search with progressive disclosure.",
400
+ description: "Hybrid semantic+keyword search with progressive disclosure. Pass query to search, or expandIds to recover full results.",
349
401
  inputSchema: {
350
402
  type: "object",
351
403
  properties: {
@@ -355,14 +407,34 @@ const CORE_TOOLS = [
355
407
  },
356
408
  expandIds: {
357
409
  type: "string",
358
- description: "Comma-separated observation IDs to expand"
410
+ description: "Comma-separated memory or observation IDs to expand; query is optional when provided"
359
411
  },
360
412
  limit: {
361
413
  type: "number",
362
414
  description: "Max results (default 10)"
415
+ },
416
+ targetLayer: {
417
+ type: "string",
418
+ enum: [
419
+ "all",
420
+ "memory",
421
+ "observation"
422
+ ],
423
+ description: "Search all indexed layers (default), durable memories, or raw observations before ranking"
424
+ },
425
+ project: {
426
+ type: "string",
427
+ description: "Filter by project path"
428
+ },
429
+ agentId: {
430
+ type: "string",
431
+ description: "Filter by owning agent; '*' reads across agents"
432
+ },
433
+ includeLessons: {
434
+ type: "boolean",
435
+ description: "Include lesson matches when targetLayer is all (default true)"
363
436
  }
364
- },
365
- required: ["query"]
437
+ }
366
438
  }
367
439
  },
368
440
  {
@@ -440,10 +512,31 @@ const CORE_TOOLS = [
440
512
  },
441
513
  {
442
514
  name: "memory_export",
443
- description: "Export all memory data as JSON.",
515
+ description: "Export memory data as JSON. Past the transport size limit the export is refused, so use the paging arguments on a large store.",
444
516
  inputSchema: {
445
517
  type: "object",
446
- properties: {}
518
+ properties: {
519
+ maxSessions: {
520
+ type: "number",
521
+ description: "Sessions per page (with their observations)"
522
+ },
523
+ offset: {
524
+ type: "number",
525
+ description: "Session offset"
526
+ },
527
+ collectionLimit: {
528
+ type: "number",
529
+ description: "Rows per page for memories, summaries, graphNodes, lessons and the other top-level collections; access logs follow the memories on the page. Sessions and their observations are paged only by maxSessions and offset, so pass collections to leave them out of each page"
530
+ },
531
+ collectionOffset: {
532
+ type: "number",
533
+ description: "Row offset for the top-level collections"
534
+ },
535
+ collections: {
536
+ type: "string",
537
+ description: "Comma-separated collections to return, e.g. memories,lessons. Sessions and their observations come back only when the list names sessions, access logs only together with memories. Unknown names are ignored. Omit for everything. A paged or selected export cannot be imported with strategy replace."
538
+ }
539
+ }
447
540
  }
448
541
  },
449
542
  {
@@ -1342,7 +1435,8 @@ function getAllTools() {
1342
1435
  ...V010_SLOTS_TOOLS
1343
1436
  ];
1344
1437
  }
1345
- const ENV_FILE = join(join(homedir(), ".agentmemory"), ".env");
1438
+ process.env["AGENTMEMORY_DATA_DIR"] || join(homedir(), ".agentmemory");
1439
+ const ENV_FILE = process.env["AGENTMEMORY_ENV_FILE"] || join(homedir(), ".agentmemory", ".env");
1346
1440
  let envFileCache;
1347
1441
  function loadEnvFile() {
1348
1442
  if (envFileCache) return envFileCache;
@@ -1350,7 +1444,10 @@ function loadEnvFile() {
1350
1444
  envFileCache = {};
1351
1445
  return envFileCache;
1352
1446
  }
1353
- const content = readFileSync(ENV_FILE, "utf-8");
1447
+ envFileCache = parseEnvContent(readFileSync(ENV_FILE, "utf-8"));
1448
+ return envFileCache;
1449
+ }
1450
+ function parseEnvContent(content) {
1354
1451
  const vars = {};
1355
1452
  for (const line of content.split("\n")) {
1356
1453
  const trimmed = line.trim();
@@ -1369,8 +1466,7 @@ function loadEnvFile() {
1369
1466
  }
1370
1467
  vars[key] = val;
1371
1468
  }
1372
- envFileCache = vars;
1373
- return envFileCache;
1469
+ return vars;
1374
1470
  }
1375
1471
  function getMergedEnv(overrides) {
1376
1472
  return {
@@ -1379,12 +1475,298 @@ function getMergedEnv(overrides) {
1379
1475
  ...overrides
1380
1476
  };
1381
1477
  }
1478
+ function loadAgentScope() {
1479
+ const env = getMergedEnv();
1480
+ const raw = env["AGENT_ID"];
1481
+ if (!raw) return null;
1482
+ const agentId = raw.trim().slice(0, 128);
1483
+ if (!agentId) return null;
1484
+ return {
1485
+ agentId,
1486
+ mode: env["AGENTMEMORY_AGENT_SCOPE"] === "isolated" ? "isolated" : "shared"
1487
+ };
1488
+ }
1489
+ function getAgentId() {
1490
+ return loadAgentScope()?.agentId;
1491
+ }
1492
+ function isAgentScopeIsolated() {
1493
+ return loadAgentScope()?.mode === "isolated";
1494
+ }
1382
1495
  function getStandalonePersistPath() {
1383
1496
  return getMergedEnv()["STANDALONE_PERSIST_PATH"] || join(homedir(), ".agentmemory", "standalone.json");
1384
1497
  }
1385
1498
  //#endregion
1499
+ //#region src/state/search-layer.ts
1500
+ function isSearchLayer(value) {
1501
+ return value === "all" || value === "memory" || value === "observation";
1502
+ }
1503
+ //#endregion
1504
+ //#region src/state/memory-utils.ts
1505
+ function memoryToObservation(memory) {
1506
+ return {
1507
+ id: memory.id,
1508
+ sessionId: memory.sessionIds?.[0] ?? "memory",
1509
+ timestamp: memory.createdAt,
1510
+ type: "decision",
1511
+ title: memory.title,
1512
+ facts: [memory.content],
1513
+ narrative: memory.content,
1514
+ concepts: memory.concepts,
1515
+ files: memory.files,
1516
+ importance: memory.strength,
1517
+ ...memory.agentId ? { agentId: memory.agentId } : {}
1518
+ };
1519
+ }
1520
+ //#endregion
1521
+ //#region src/functions/recall-response.ts
1522
+ function estimateTokens(value) {
1523
+ return Math.max(1, Math.ceil(JSON.stringify(value).length / 3));
1524
+ }
1525
+ function prefix(text, length) {
1526
+ let end = Math.min(length, text.length);
1527
+ if (end > 0 && end < text.length && /[\uD800-\uDBFF]/.test(text[end - 1])) end--;
1528
+ return text.slice(0, end);
1529
+ }
1530
+ function fitText(text, budget, makeResult) {
1531
+ let low = 0;
1532
+ let high = text.length;
1533
+ while (low < high) {
1534
+ const middle = Math.ceil((low + high) / 2);
1535
+ if (estimateTokens(makeResult(prefix(text, middle))) <= budget) low = middle;
1536
+ else high = middle - 1;
1537
+ }
1538
+ return makeResult(prefix(text, low));
1539
+ }
1540
+ function formatResult(result, format) {
1541
+ if (format === "full") return result;
1542
+ const observation = result.observation;
1543
+ const compact = {
1544
+ obsId: observation.id,
1545
+ sessionId: result.sessionId,
1546
+ title: observation.title,
1547
+ type: observation.type,
1548
+ score: result.score,
1549
+ timestamp: observation.timestamp,
1550
+ ...result.layer !== void 0 && { layer: result.layer }
1551
+ };
1552
+ if (format === "compact") return compact;
1553
+ const { type: _type, ...narrative } = compact;
1554
+ return {
1555
+ ...narrative,
1556
+ narrative: observation.narrative
1557
+ };
1558
+ }
1559
+ function clipResult(result, format, budget) {
1560
+ const observation = result.observation;
1561
+ const layer = result.layer !== void 0 ? { layer: result.layer } : {};
1562
+ if (format === "compact") {
1563
+ const base = {
1564
+ obsId: observation.id,
1565
+ sessionId: result.sessionId,
1566
+ title: "",
1567
+ type: observation.type,
1568
+ score: result.score,
1569
+ timestamp: observation.timestamp,
1570
+ ...layer,
1571
+ content_truncated: true
1572
+ };
1573
+ const minimum = estimateTokens(base);
1574
+ if (minimum > budget) return { minimum };
1575
+ return {
1576
+ result: fitText(observation.title, budget, (title) => ({
1577
+ ...base,
1578
+ title
1579
+ })),
1580
+ minimum
1581
+ };
1582
+ }
1583
+ const makeResult = (title, narrative) => {
1584
+ if (format === "narrative") return {
1585
+ obsId: observation.id,
1586
+ sessionId: result.sessionId,
1587
+ title,
1588
+ narrative,
1589
+ score: result.score,
1590
+ timestamp: observation.timestamp,
1591
+ ...layer,
1592
+ content_truncated: true
1593
+ };
1594
+ return {
1595
+ observation: {
1596
+ id: observation.id,
1597
+ sessionId: observation.sessionId,
1598
+ timestamp: observation.timestamp,
1599
+ type: observation.type,
1600
+ title,
1601
+ facts: [],
1602
+ narrative,
1603
+ concepts: [],
1604
+ files: [],
1605
+ importance: observation.importance,
1606
+ ...observation.confidence !== void 0 && { confidence: observation.confidence },
1607
+ ...observation.agentId !== void 0 && { agentId: observation.agentId },
1608
+ ...observation.origin && { origin: {
1609
+ channel: observation.origin.channel,
1610
+ capturedAt: observation.origin.capturedAt
1611
+ } }
1612
+ },
1613
+ score: result.score,
1614
+ sessionId: result.sessionId,
1615
+ ...layer,
1616
+ content_truncated: true
1617
+ };
1618
+ };
1619
+ const minimum = estimateTokens(makeResult("", ""));
1620
+ if (minimum > budget) return { minimum };
1621
+ const titleResult = fitText(prefix(observation.title, 120), budget, (title) => makeResult(title, ""));
1622
+ const title = "observation" in titleResult ? titleResult.observation.title : titleResult.title;
1623
+ return {
1624
+ result: fitText(observation.narrative || observation.facts.join("\n"), budget, (text) => makeResult(title, text)),
1625
+ minimum
1626
+ };
1627
+ }
1628
+ function buildRecallResponse(results, format, tokenBudget) {
1629
+ const selected = [];
1630
+ let used = 0;
1631
+ let clipped = false;
1632
+ let minimumBudget;
1633
+ for (const result of results) {
1634
+ const formatted = formatResult(result, format);
1635
+ const tokens = estimateTokens(formatted);
1636
+ if (tokenBudget === void 0 || used + tokens <= tokenBudget) {
1637
+ selected.push(formatted);
1638
+ used += tokens;
1639
+ continue;
1640
+ }
1641
+ if (selected.length === 0) {
1642
+ const preview = clipResult(result, format, tokenBudget);
1643
+ if (preview.result) {
1644
+ selected.push(preview.result);
1645
+ used = estimateTokens(preview.result);
1646
+ clipped = true;
1647
+ continue;
1648
+ } else minimumBudget = Math.min(preview.minimum, tokens);
1649
+ }
1650
+ break;
1651
+ }
1652
+ const excluded = results.slice(selected.length);
1653
+ const metadata = {
1654
+ tokens_used: used,
1655
+ tokens_budget: tokenBudget,
1656
+ truncated: clipped || excluded.length > 0,
1657
+ matched_count: results.length,
1658
+ excluded_by_budget: excluded.length,
1659
+ excluded_results: excluded.slice(0, 10).map((result) => ({
1660
+ obsId: result.observation.id,
1661
+ sessionId: result.sessionId,
1662
+ title: prefix(result.observation.title, 120)
1663
+ })),
1664
+ excluded_results_truncated: excluded.length > 10,
1665
+ ...minimumBudget !== void 0 && { minimum_budget: minimumBudget }
1666
+ };
1667
+ if (format === "narrative") {
1668
+ const narrativeResults = selected;
1669
+ return {
1670
+ ...metadata,
1671
+ format,
1672
+ results: narrativeResults,
1673
+ text: narrativeResults.map((result, index) => `${index + 1}. ${result.title}\n${result.narrative}`).join("\n\n")
1674
+ };
1675
+ }
1676
+ if (format === "compact") return {
1677
+ ...metadata,
1678
+ format,
1679
+ results: selected
1680
+ };
1681
+ return {
1682
+ ...metadata,
1683
+ format,
1684
+ results: selected
1685
+ };
1686
+ }
1687
+ //#endregion
1688
+ //#region src/mcp/search-arguments.ts
1689
+ function parseSearchExpansionIds(value) {
1690
+ return (typeof value === "string" ? value.split(",") : Array.isArray(value) ? value : []).flatMap((entry) => {
1691
+ if (typeof entry === "string") return entry.trim() ? [entry.trim()] : [];
1692
+ if (!entry || typeof entry !== "object" || typeof entry.obsId !== "string" || !entry.obsId.trim()) return [];
1693
+ const obsId = entry.obsId.trim();
1694
+ return typeof entry.sessionId === "string" && entry.sessionId.trim() ? [{
1695
+ obsId,
1696
+ sessionId: entry.sessionId.trim()
1697
+ }] : [obsId];
1698
+ });
1699
+ }
1700
+ //#endregion
1701
+ //#region src/state/list-query.ts
1702
+ function encodeCursor(position) {
1703
+ return Buffer.from(JSON.stringify(position), "utf-8").toString("base64url");
1704
+ }
1705
+ function decodeCursor(cursor) {
1706
+ if (!cursor) return null;
1707
+ try {
1708
+ const parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf-8"));
1709
+ if (!parsed || typeof parsed !== "object") return null;
1710
+ const position = {};
1711
+ if (typeof parsed.key === "string") position.key = parsed.key;
1712
+ if (typeof parsed.id === "string") position.id = parsed.id;
1713
+ if (Number.isInteger(parsed.offset) && parsed.offset >= 0) position.offset = parsed.offset;
1714
+ return position;
1715
+ } catch {
1716
+ return null;
1717
+ }
1718
+ }
1719
+ function compareDesc(aKey, aId, bKey, bId) {
1720
+ if (aKey !== bKey) return aKey < bKey ? 1 : -1;
1721
+ if (aId === bId) return 0;
1722
+ return aId < bId ? 1 : -1;
1723
+ }
1724
+ function sortByKeyDesc(items, keyOf, idOf) {
1725
+ return items.sort((a, b) => compareDesc(keyOf(a), idOf(a), keyOf(b), idOf(b)));
1726
+ }
1727
+ function pageAfterCursor(sortedDesc, keyOf, idOf, cursor, limit) {
1728
+ const position = decodeCursor(cursor);
1729
+ let start = 0;
1730
+ if (position?.key !== void 0 && position.id !== void 0) {
1731
+ const { key, id } = position;
1732
+ start = sortedDesc.findIndex((item) => compareDesc(keyOf(item), idOf(item), key, id) > 0);
1733
+ if (start < 0) start = sortedDesc.length;
1734
+ }
1735
+ const page = sortedDesc.slice(start, start + limit);
1736
+ const last = page[page.length - 1];
1737
+ return {
1738
+ page,
1739
+ nextCursor: last !== void 0 && start + limit < sortedDesc.length ? encodeCursor({
1740
+ key: keyOf(last),
1741
+ id: idOf(last)
1742
+ }) : null
1743
+ };
1744
+ }
1745
+ //#endregion
1746
+ //#region src/mcp/session-arguments.ts
1747
+ function parseSessionArguments(args) {
1748
+ const limit = args.limit === void 0 ? 20 : args.limit;
1749
+ if (typeof limit !== "number" || !Number.isInteger(limit) || limit < 1) throw new Error("limit must be a positive integer");
1750
+ const query = { limit: String(Math.min(limit, 100)) };
1751
+ for (const field of [
1752
+ "project",
1753
+ "agentId",
1754
+ "cursor"
1755
+ ]) {
1756
+ if (args[field] === void 0) continue;
1757
+ if (field === "cursor" && typeof args[field] === "string" && !args[field].trim()) continue;
1758
+ if (typeof args[field] !== "string" || !args[field].trim()) throw new Error(`${field} must be a non-empty string`);
1759
+ query[field] = args[field].trim();
1760
+ }
1761
+ if (query.cursor) {
1762
+ const position = decodeCursor(query.cursor);
1763
+ if (!position || typeof position.key !== "string" || typeof position.id !== "string") throw new Error("cursor must be a session continuation token");
1764
+ }
1765
+ return query;
1766
+ }
1767
+ //#endregion
1386
1768
  //#region src/version.ts
1387
- const VERSION = "0.9.30";
1769
+ const VERSION = "0.9.31";
1388
1770
  createRequire(import.meta.url);
1389
1771
  //#endregion
1390
1772
  //#region src/state/schema.ts
@@ -1393,6 +1775,7 @@ const KV = {
1393
1775
  observations: (sessionId) => `mem:obs:${sessionId}`,
1394
1776
  memories: "mem:memories",
1395
1777
  summaries: "mem:summaries",
1778
+ summaryRepairs: "mem:summary:repairs",
1396
1779
  config: "mem:config",
1397
1780
  metrics: "mem:metrics",
1398
1781
  health: "mem:health",
@@ -1403,11 +1786,17 @@ const KV = {
1403
1786
  profiles: "mem:profiles",
1404
1787
  claudeBridge: "mem:claude-bridge",
1405
1788
  graphNodes: "mem:graph:nodes",
1789
+ graphControl: "mem:graph:control",
1406
1790
  graphEdges: "mem:graph:edges",
1407
1791
  graphSnapshot: "mem:graph:snapshot",
1408
1792
  graphNameIndex: "mem:graph:name-index",
1409
1793
  graphEdgeKey: "mem:graph:edge-key",
1410
1794
  graphNodeDegree: "mem:graph:node-degree",
1795
+ graphMembership: "mem:graph:membership",
1796
+ graphRetrievalControl: "mem:graph:retrieval-control",
1797
+ graphRetrievalData: "mem:graph:retrieval-data",
1798
+ graphIndexMigration: "mem:graph:index-migration",
1799
+ graphIndexManifest: "mem:graph:index-manifest",
1411
1800
  semantic: "mem:semantic",
1412
1801
  procedural: "mem:procedural",
1413
1802
  teamShared: (teamId) => `mem:team:${teamId}:shared`,
@@ -1452,6 +1841,7 @@ function generateId(prefix) {
1452
1841
  return `${prefix}_${Date.now().toString(36)}_${crypto.randomUUID().replace(/-/g, "").slice(0, 12)}`;
1453
1842
  }
1454
1843
  process.env["AGENTMEMORY_VERBOSE"] === "1" || process.env["AGENTMEMORY_VERBOSE"];
1844
+ new AsyncLocalStorage();
1455
1845
  KV.auditMonths;
1456
1846
  const AUDIT_MIGRATION_STATE_KEY = "migration";
1457
1847
  async function readAuditMigrationState(kv) {
@@ -1530,7 +1920,7 @@ async function queryAudit(kv, filter) {
1530
1920
  //#region src/secret-store.ts
1531
1921
  const SECRET_KEY = "AGENTMEMORY_SECRET";
1532
1922
  function agentmemoryHomeDir() {
1533
- return join(homedir(), ".agentmemory");
1923
+ return process.env["AGENTMEMORY_DATA_DIR"] || join(homedir(), ".agentmemory");
1534
1924
  }
1535
1925
  function secretFilePath() {
1536
1926
  return join(agentmemoryHomeDir(), "secret");
@@ -1554,7 +1944,7 @@ function unquote(value) {
1554
1944
  function readEnvFileSecret() {
1555
1945
  let content;
1556
1946
  try {
1557
- content = readFileSync(join(agentmemoryHomeDir(), ".env"), "utf-8");
1947
+ content = readFileSync(process.env["AGENTMEMORY_ENV_FILE"] || join(homedir(), ".agentmemory", ".env"), "utf-8");
1558
1948
  } catch {
1559
1949
  return "";
1560
1950
  }
@@ -1570,13 +1960,29 @@ function readEnvFileSecret() {
1570
1960
  }
1571
1961
  return found;
1572
1962
  }
1573
- function readStoredSecret() {
1963
+ function readSecretFile(path) {
1574
1964
  try {
1575
- return usable(readFileSync(secretFilePath(), "utf-8"));
1965
+ return usable(readFileSync(path, "utf-8"));
1576
1966
  } catch {
1577
1967
  return "";
1578
1968
  }
1579
1969
  }
1970
+ function legacyDataDirSecretPaths(env = process.env) {
1971
+ const dataDir = env["AGENTMEMORY_DATA_DIR"];
1972
+ if (!dataDir) return [];
1973
+ const paths = [
1974
+ join(dataDir, "secret"),
1975
+ join(dataDir, ".hmac"),
1976
+ join(dataDir, "..", ".hmac")
1977
+ ];
1978
+ return [...new Set(paths.filter((path) => path !== secretFilePath()))];
1979
+ }
1980
+ function readStoredSecret(env = process.env) {
1981
+ const canonicalPath = canonicalSecretPath();
1982
+ const localPath = secretFilePath();
1983
+ const legacyPaths = legacyDataDirSecretPaths(env);
1984
+ return readSecretFile(canonicalPath) || (localPath === canonicalPath ? "" : readSecretFile(localPath)) || legacyPaths.map(readSecretFile).find(Boolean) || "";
1985
+ }
1580
1986
  function isLoopbackUrl(url) {
1581
1987
  let hostname;
1582
1988
  try {
@@ -1590,8 +1996,12 @@ function isLoopbackUrl(url) {
1590
1996
  function resolveClientSecret(baseUrl, env = process.env) {
1591
1997
  const fromEnv = usable(env[SECRET_KEY]);
1592
1998
  if (fromEnv) return fromEnv;
1999
+ if (env.AGENTMEMORY_CREDENTIAL_MODE === "explicit") return "";
1593
2000
  if (!isLoopbackUrl(baseUrl)) return "";
1594
- return readEnvFileSecret() || readStoredSecret();
2001
+ return readEnvFileSecret() || readStoredSecret(env);
2002
+ }
2003
+ function canonicalSecretPath() {
2004
+ return join(homedir(), ".agentmemory", "secret");
1595
2005
  }
1596
2006
  //#endregion
1597
2007
  //#region src/mcp/rest-proxy.ts
@@ -1605,7 +2015,7 @@ function probeTimeoutMs() {
1605
2015
  const n = Number(raw);
1606
2016
  return Number.isFinite(n) && n > 0 ? Math.floor(n) : DEFAULT_HEALTH_PROBE_TIMEOUT_MS;
1607
2017
  }
1608
- function forceProxy() {
2018
+ function isProxyRequired() {
1609
2019
  const raw = process.env["AGENTMEMORY_FORCE_PROXY"];
1610
2020
  return raw === "1" || raw === "true";
1611
2021
  }
@@ -1620,6 +2030,7 @@ var ProxyCallError = class extends Error {
1620
2030
  }
1621
2031
  };
1622
2032
  let cached = null;
2033
+ let cachedUrl = null;
1623
2034
  let cachedAt = 0;
1624
2035
  let probeInFlight = null;
1625
2036
  function resolveEnvOrEmpty(name) {
@@ -1629,17 +2040,25 @@ function resolveEnvOrEmpty(name) {
1629
2040
  return raw;
1630
2041
  }
1631
2042
  function baseUrl() {
1632
- return (resolveEnvOrEmpty("AGENTMEMORY_URL") || DEFAULT_URL).replace(/\/+$/, "");
2043
+ const value = resolveEnvOrEmpty("AGENTMEMORY_URL") || DEFAULT_URL;
2044
+ try {
2045
+ const parsed = new URL(value);
2046
+ if (!["http:", "https:"].includes(parsed.protocol) || !parsed.hostname || parsed.username || parsed.password || /[?#\s]/.test(value)) throw new Error();
2047
+ return value.replace(/\/+$/, "");
2048
+ } catch {
2049
+ throw new Error("AGENTMEMORY_URL must be an HTTP(S) URL without credentials, query, or fragment");
2050
+ }
1633
2051
  }
1634
- function authHeader() {
1635
- const secret = resolveClientSecret(baseUrl());
2052
+ function authHeader(url) {
2053
+ const secret = resolveClientSecret(url);
1636
2054
  return secret ? { authorization: `Bearer ${secret}` } : {};
1637
2055
  }
1638
2056
  const defaultLivezProbe = async (url, timeoutMs, headers) => {
1639
2057
  const res = await fetch(`${url}/agentmemory/livez`, {
1640
2058
  method: "GET",
1641
2059
  headers,
1642
- signal: AbortSignal.timeout(timeoutMs)
2060
+ signal: AbortSignal.timeout(timeoutMs),
2061
+ redirect: "error"
1643
2062
  });
1644
2063
  return {
1645
2064
  ok: res.ok,
@@ -1651,7 +2070,7 @@ let livezProbe = defaultLivezProbe;
1651
2070
  async function probe(url) {
1652
2071
  const timeout = probeTimeoutMs();
1653
2072
  try {
1654
- const res = await livezProbe(url, timeout, authHeader());
2073
+ const res = await livezProbe(url, timeout, authHeader(url));
1655
2074
  if (!res.ok) process.stderr.write(`[@agentmemory/mcp] livez probe ${url}/agentmemory/livez -> ${res.status ?? "?"} ${res.statusText ?? ""}; falling back to local InMemoryKV (set AGENTMEMORY_FORCE_PROXY=1 to skip the probe)\n`);
1656
2075
  return res.ok;
1657
2076
  } catch (err) {
@@ -1661,33 +2080,38 @@ async function probe(url) {
1661
2080
  }
1662
2081
  function invalidateHandle() {
1663
2082
  cached = null;
2083
+ cachedUrl = null;
1664
2084
  cachedAt = 0;
1665
2085
  }
1666
2086
  async function resolveHandle() {
1667
2087
  const now = Date.now();
2088
+ const url = baseUrl();
2089
+ if (cached && (cachedUrl !== url || cached.mode === "local" && isProxyRequired())) invalidateHandle();
1668
2090
  if (cached) if (cached.mode === "local" && now - cachedAt >= LOCAL_MODE_TTL_MS) {
1669
2091
  cached = null;
1670
2092
  cachedAt = 0;
1671
2093
  } else return cached;
1672
- if (probeInFlight) return probeInFlight;
1673
- const url = baseUrl();
1674
- const skipProbe = forceProxy();
1675
- probeInFlight = (async () => {
2094
+ const skipProbe = isProxyRequired();
2095
+ if (probeInFlight?.url === url && probeInFlight.forceProxy === skipProbe) return probeInFlight.promise;
2096
+ const pending = (async () => {
1676
2097
  const up = skipProbe ? true : await probe(url);
2098
+ if (baseUrl() !== url || isProxyRequired() !== skipProbe) return resolveHandle();
1677
2099
  if (skipProbe) process.stderr.write(`[@agentmemory/mcp] AGENTMEMORY_FORCE_PROXY set; skipping livez probe and trusting ${url}\n`);
1678
2100
  if (up) {
1679
2101
  const handle = {
1680
2102
  mode: "proxy",
1681
2103
  baseUrl: url,
1682
2104
  call: async (path, init) => {
2105
+ if (baseUrl() !== url) throw new Error("AgentMemory endpoint changed; resolve a new proxy handle before retrying.");
1683
2106
  const res = await fetch(`${url}${path}`, {
1684
2107
  ...init,
1685
2108
  headers: {
1686
2109
  "content-type": "application/json",
1687
- ...authHeader(),
2110
+ ...authHeader(url),
1688
2111
  ...init?.headers
1689
2112
  },
1690
- signal: AbortSignal.timeout(CALL_TIMEOUT_MS)
2113
+ signal: AbortSignal.timeout(CALL_TIMEOUT_MS),
2114
+ redirect: "error"
1691
2115
  });
1692
2116
  if (!res.ok) {
1693
2117
  const errText = await res.text().catch(() => "");
@@ -1704,18 +2128,25 @@ async function resolveHandle() {
1704
2128
  }
1705
2129
  };
1706
2130
  cached = handle;
2131
+ cachedUrl = url;
1707
2132
  cachedAt = Date.now();
1708
2133
  return handle;
1709
2134
  }
1710
2135
  const local = { mode: "local" };
1711
2136
  cached = local;
2137
+ cachedUrl = url;
1712
2138
  cachedAt = Date.now();
1713
2139
  return local;
1714
2140
  })();
2141
+ probeInFlight = {
2142
+ url,
2143
+ forceProxy: skipProbe,
2144
+ promise: pending
2145
+ };
1715
2146
  try {
1716
- return await probeInFlight;
2147
+ return await pending;
1717
2148
  } finally {
1718
- probeInFlight = null;
2149
+ if (probeInFlight?.promise === pending) probeInFlight = null;
1719
2150
  }
1720
2151
  }
1721
2152
  //#endregion
@@ -1775,6 +2206,9 @@ function textResponse(payload, pretty = false) {
1775
2206
  text: JSON.stringify(payload, null, pretty ? 2 : 0)
1776
2207
  }] };
1777
2208
  }
2209
+ function isAuthenticationError(error) {
2210
+ return error instanceof ProxyCallError && (error.status === 401 || error.status === 403);
2211
+ }
1778
2212
  function validate(toolName, args) {
1779
2213
  if (!IMPLEMENTED_TOOLS.has(toolName)) throw new Error(`Unknown tool: ${toolName}`);
1780
2214
  const v = { tool: toolName };
@@ -1792,22 +2226,41 @@ function validate(toolName, args) {
1792
2226
  }
1793
2227
  case "memory_recall":
1794
2228
  case "memory_smart_search": {
2229
+ if (args.targetLayer !== void 0 && !isSearchLayer(args.targetLayer)) throw new Error("targetLayer must be one of: all, memory, observation");
2230
+ v.targetLayer = args.targetLayer ?? "all";
2231
+ for (const field of [
2232
+ "project",
2233
+ "cwd",
2234
+ "agentId",
2235
+ "sessionId",
2236
+ "source"
2237
+ ]) {
2238
+ if (args[field] !== void 0 && typeof args[field] !== "string") throw new Error(`${field} must be a string`);
2239
+ if (typeof args[field] === "string" && args[field].trim()) v[field] = args[field].trim();
2240
+ }
2241
+ if (toolName === "memory_smart_search") {
2242
+ v.expandIds = parseSearchExpansionIds(args.expandIds);
2243
+ if (typeof args.includeLessons === "boolean") v.includeLessons = args.includeLessons;
2244
+ }
1795
2245
  const query = args["query"];
1796
- if (typeof query !== "string" || !query.trim()) throw new Error("query is required");
1797
- v.query = query.trim();
2246
+ if (typeof query !== "string" || !query.trim()) {
2247
+ if (!v.expandIds?.length) throw new Error("query is required unless expandIds is provided");
2248
+ } else v.query = query.trim();
1798
2249
  v.limit = parseLimit(args["limit"]);
1799
- const fmt = args["format"];
1800
- if (typeof fmt === "string" && fmt.trim()) v.format = fmt.trim().toLowerCase();
1801
- const budget = args["token_budget"];
1802
- if (typeof budget === "number" && Number.isFinite(budget) && budget > 0) v.tokenBudget = Math.floor(budget);
1803
- else if (typeof budget === "string" && budget.trim()) {
1804
- const n = Number(budget);
1805
- if (Number.isFinite(n) && n > 0) v.tokenBudget = Math.floor(n);
2250
+ if (toolName === "memory_recall") {
2251
+ const format = typeof args.format === "string" ? args.format.trim().toLowerCase() : args.format ?? "full";
2252
+ if (format !== "full" && format !== "compact" && format !== "narrative") throw new Error("format must be one of: full, compact, narrative");
2253
+ v.format = format;
2254
+ if (args.token_budget !== void 0) {
2255
+ const budget = typeof args.token_budget === "string" ? Number(args.token_budget) : args.token_budget;
2256
+ if (typeof budget !== "number" || !Number.isInteger(budget) || budget < 1) throw new Error("token_budget must be a positive integer");
2257
+ v.tokenBudget = budget;
2258
+ }
1806
2259
  }
1807
2260
  return v;
1808
2261
  }
1809
2262
  case "memory_sessions":
1810
- v.limit = parseLimit(args["limit"], 20);
2263
+ v.sessionQuery = parseSessionArguments(args);
1811
2264
  return v;
1812
2265
  case "memory_governance_delete": {
1813
2266
  const ids = normalizeList(args["memoryIds"]);
@@ -1816,7 +2269,22 @@ function validate(toolName, args) {
1816
2269
  v.reason = args["reason"] || "plugin skill request";
1817
2270
  return v;
1818
2271
  }
1819
- case "memory_export": return v;
2272
+ case "memory_export": {
2273
+ const query = new URLSearchParams();
2274
+ for (const key of [
2275
+ "maxSessions",
2276
+ "offset",
2277
+ "collectionLimit",
2278
+ "collectionOffset"
2279
+ ]) {
2280
+ const n = Number(args[key]);
2281
+ const min = key === "maxSessions" || key === "collectionLimit" ? 1 : 0;
2282
+ if (args[key] !== void 0 && Number.isInteger(n) && n >= min) query.set(key, String(n));
2283
+ }
2284
+ if (typeof args["collections"] === "string") query.set("collections", args["collections"]);
2285
+ v.exportQuery = query.toString();
2286
+ return v;
2287
+ }
1820
2288
  case "memory_audit":
1821
2289
  v.limit = parseLimit(args["limit"], 50);
1822
2290
  return v;
@@ -1840,7 +2308,11 @@ async function handleProxy(v, handle) {
1840
2308
  const body = {
1841
2309
  query: v.query,
1842
2310
  limit: v.limit,
1843
- format: v.format ?? "full"
2311
+ format: v.format ?? "full",
2312
+ targetLayer: v.targetLayer,
2313
+ project: v.project,
2314
+ cwd: v.cwd,
2315
+ agentId: v.agentId
1844
2316
  };
1845
2317
  if (v.tokenBudget != null) body["token_budget"] = v.tokenBudget;
1846
2318
  return textResponse(await handle.call("/agentmemory/search", {
@@ -1851,16 +2323,21 @@ async function handleProxy(v, handle) {
1851
2323
  case "memory_smart_search": {
1852
2324
  const body = {
1853
2325
  query: v.query,
1854
- limit: v.limit
2326
+ limit: v.limit,
2327
+ targetLayer: v.targetLayer,
2328
+ project: v.project,
2329
+ agentId: v.agentId,
2330
+ expandIds: v.expandIds,
2331
+ sessionId: v.sessionId,
2332
+ source: v.source,
2333
+ includeLessons: v.includeLessons
1855
2334
  };
1856
- if (v.format != null) body["format"] = v.format;
1857
- if (v.tokenBudget != null) body["token_budget"] = v.tokenBudget;
1858
2335
  return textResponse(await handle.call("/agentmemory/smart-search", {
1859
2336
  method: "POST",
1860
2337
  body: JSON.stringify(body)
1861
2338
  }), true);
1862
2339
  }
1863
- case "memory_sessions": return textResponse(await handle.call(`/agentmemory/sessions?limit=${v.limit}`, { method: "GET" }), true);
2340
+ case "memory_sessions": return textResponse(await handle.call(`/agentmemory/sessions?${new URLSearchParams(v.sessionQuery)}`, { method: "GET" }), true);
1864
2341
  case "memory_governance_delete": return textResponse(await handle.call("/agentmemory/governance/memories", {
1865
2342
  method: "DELETE",
1866
2343
  body: JSON.stringify({
@@ -1869,15 +2346,22 @@ async function handleProxy(v, handle) {
1869
2346
  })
1870
2347
  }));
1871
2348
  case "memory_export": try {
1872
- return textResponse(await handle.call("/agentmemory/export", { method: "GET" }), true);
2349
+ return textResponse(await handle.call(`/agentmemory/export${v.exportQuery ? `?${v.exportQuery}` : ""}`, { method: "GET" }), true);
1873
2350
  } catch (err) {
1874
- if (err instanceof ProxyCallError && err.body != null && typeof err.body === "object" && err.body.oversized === true) return textResponse(err.body, true);
2351
+ if (err instanceof ProxyCallError && err.status === 413 && err.body != null && typeof err.body === "object" && err.body.oversized === true) return textResponse(err.body, true);
1875
2352
  throw err;
1876
2353
  }
1877
2354
  case "memory_audit": return textResponse(await handle.call(`/agentmemory/audit?limit=${v.limit}`, { method: "GET" }), true);
1878
2355
  default: throw new Error(`Unknown tool: ${v.tool}`);
1879
2356
  }
1880
2357
  }
2358
+ function localFallbackNotice(persisted) {
2359
+ const store = persisted ? "the local fallback file, which the server does not read" : "this process's in-memory fallback store, which is lost when the process exits";
2360
+ return {
2361
+ storage: "local",
2362
+ warning: `agentmemory server at ${displayAgentmemoryUrl()} did not confirm this call, so it ran against ${store}.`
2363
+ };
2364
+ }
1881
2365
  async function handleLocal(v, kvInstance) {
1882
2366
  switch (v.tool) {
1883
2367
  case "memory_save": {
@@ -1895,34 +2379,96 @@ async function handleLocal(v, kvInstance) {
1895
2379
  strength: 7,
1896
2380
  version: 1,
1897
2381
  isLatest: true,
1898
- sessionIds: []
2382
+ sessionIds: [],
2383
+ ...v.project !== void 0 && { project: v.project },
2384
+ ...(v.agentId ?? getAgentId()) !== void 0 && { agentId: v.agentId ?? getAgentId() }
2385
+ });
2386
+ return textResponse({
2387
+ saved: id,
2388
+ ...localFallbackNotice(kvInstance.persist())
1899
2389
  });
1900
- kvInstance.persist();
1901
- return textResponse({ saved: id });
1902
2390
  }
1903
2391
  case "memory_recall":
1904
2392
  case "memory_smart_search": {
2393
+ const isolated = isAgentScopeIsolated();
2394
+ const agentId = v.agentId === "*" ? void 0 : v.agentId ?? (isolated ? getAgentId() : void 0);
2395
+ if (isolated && v.agentId !== "*" && !agentId) throw new Error("AGENTMEMORY_AGENT_SCOPE=isolated requires an agentId; pass '*' to read across agents");
1905
2396
  const query = (v.query || "").toLowerCase();
1906
2397
  const limit = v.limit ?? DEFAULT_LIMIT;
2398
+ const all = v.targetLayer === "observation" ? [] : await kvInstance.list("mem:memories");
2399
+ const sessions = v.project || v.cwd ? await kvInstance.list("mem:sessions") : [];
2400
+ const sessionsById = new Map(sessions.map((session) => [session.id, session]));
2401
+ const scoped = all.filter((memory) => {
2402
+ if (memory.isLatest === false || agentId && memory.agentId !== agentId) return false;
2403
+ const linkedSessions = (memory.sessionIds ?? []).map((id) => sessionsById.get(id));
2404
+ if (v.project && (memory.project ? memory.project !== v.project : !linkedSessions.some((session) => session?.project === v.project))) return false;
2405
+ if (v.cwd && !linkedSessions.some((session) => session?.cwd === v.cwd)) return false;
2406
+ return true;
2407
+ });
2408
+ if (v.tool === "memory_smart_search" && v.expandIds?.length) {
2409
+ const ids = v.expandIds.map((entry) => typeof entry === "string" ? entry : entry.obsId);
2410
+ const byId = new Map(scoped.map((memory) => [memory.id, memory]));
2411
+ const eligible = ids.filter((id) => byId.has(id));
2412
+ return textResponse({
2413
+ mode: "expanded",
2414
+ results: eligible.slice(0, 20).map((id) => {
2415
+ const observation = memoryToObservation(byId.get(id));
2416
+ return {
2417
+ obsId: id,
2418
+ sessionId: observation.sessionId,
2419
+ observation,
2420
+ layer: "memory"
2421
+ };
2422
+ }),
2423
+ truncated: eligible.length > 20
2424
+ }, true);
2425
+ }
2426
+ const results = scoped.filter((memory) => {
2427
+ const text = [
2428
+ memory.title,
2429
+ memory.content,
2430
+ ...memory.files ?? [],
2431
+ ...memory.concepts ?? [],
2432
+ ...memory.sessionIds ?? [],
2433
+ memory.id
2434
+ ].join(" ").toLowerCase();
2435
+ return query.split(/\s+/).every((word) => text.includes(word));
2436
+ }).slice(0, limit);
2437
+ if (v.tool === "memory_recall") return textResponse(buildRecallResponse(results.map((memory) => {
2438
+ const observation = memoryToObservation(memory);
2439
+ return {
2440
+ sessionId: observation.sessionId,
2441
+ observation,
2442
+ score: 1,
2443
+ layer: "memory"
2444
+ };
2445
+ }), v.format ?? "full", v.tokenBudget), true);
1907
2446
  return textResponse({
1908
2447
  mode: "compact",
1909
- results: (await kvInstance.list("mem:memories")).filter((m) => {
1910
- const text = [
1911
- typeof m["title"] === "string" ? m["title"] : "",
1912
- typeof m["content"] === "string" ? m["content"] : "",
1913
- Array.isArray(m["files"]) ? m["files"].join(" ") : "",
1914
- Array.isArray(m["concepts"]) ? m["concepts"].join(" ") : "",
1915
- Array.isArray(m["sessionIds"]) ? m["sessionIds"].join(" ") : "",
1916
- typeof m["id"] === "string" ? m["id"] : ""
1917
- ].join(" ").toLowerCase();
1918
- return query.split(/\s+/).every((word) => text.includes(word));
1919
- }).slice(0, limit)
2448
+ results: results.map((memory) => ({
2449
+ ...memory,
2450
+ obsId: memory.id,
2451
+ sessionId: memory.sessionIds?.[0] ?? "memory",
2452
+ layer: "memory"
2453
+ }))
1920
2454
  }, true);
1921
2455
  }
1922
2456
  case "memory_sessions": {
1923
- const sessions = await kvInstance.list("mem:sessions");
1924
- const limit = v.limit ?? 20;
1925
- return textResponse({ sessions: sessions.slice(0, limit) }, true);
2457
+ const query = v.sessionQuery;
2458
+ const agentId = query.agentId === "*" ? void 0 : query.agentId ?? (isAgentScopeIsolated() ? getAgentId() : void 0);
2459
+ const sessions = (await kvInstance.list("mem:sessions")).filter((session) => session && typeof session.id === "string" && session.id.length > 0).filter((session) => !query.project || session.project === query.project).filter((session) => !agentId || session.agentId === agentId);
2460
+ const key = (session) => session.startedAt || "";
2461
+ const { page, nextCursor } = pageAfterCursor(sortByKeyDesc(sessions, key, (session) => session.id), key, (session) => session.id, query.cursor, Number(query.limit));
2462
+ return textResponse({
2463
+ sessions: await Promise.all(page.map(async (session) => {
2464
+ const summary = await kvInstance.get("mem:summaries", session.id);
2465
+ return summary ? {
2466
+ ...session,
2467
+ summary
2468
+ } : session;
2469
+ })),
2470
+ nextCursor
2471
+ }, true);
1926
2472
  }
1927
2473
  case "memory_governance_delete": {
1928
2474
  let deleted = 0;
@@ -1930,11 +2476,12 @@ async function handleLocal(v, kvInstance) {
1930
2476
  await kvInstance.delete("mem:memories", id);
1931
2477
  deleted++;
1932
2478
  }
1933
- kvInstance.persist();
2479
+ const persisted = kvInstance.persist();
1934
2480
  return textResponse({
1935
2481
  deleted,
1936
2482
  requested: (v.memoryIds || []).length,
1937
- reason: v.reason
2483
+ reason: v.reason,
2484
+ ...localFallbackNotice(persisted)
1938
2485
  });
1939
2486
  }
1940
2487
  case "memory_export": return textResponse({
@@ -1974,6 +2521,10 @@ async function handleToolCall(toolName, args, kvInstance = kv) {
1974
2521
  if (handle.mode === "proxy") try {
1975
2522
  return await handleProxy(validated, handle);
1976
2523
  } catch (err) {
2524
+ if (toolName === "memory_sessions" || isAuthenticationError(err) || isProxyRequired()) {
2525
+ invalidateHandle();
2526
+ throw err;
2527
+ }
1977
2528
  process.stderr.write(`[@agentmemory/mcp] proxy call failed for ${toolName}: ${err instanceof Error ? err.message : String(err)}; invalidating handle and falling back to local KV\n`);
1978
2529
  invalidateHandle();
1979
2530
  }
@@ -1994,10 +2545,12 @@ async function handleToolsList() {
1994
2545
  if (debug) process.stderr.write(`[@agentmemory/mcp] tools/list: returning ${remote.tools.length} tools from server\n`);
1995
2546
  return { tools: remote.tools };
1996
2547
  }
2548
+ if (isProxyRequired()) throw new Error("AgentMemory returned an invalid tool inventory");
1997
2549
  process.stderr.write(`[@agentmemory/mcp] tools/list: server returned unexpected shape (no .tools array); falling back to local IMPLEMENTED_TOOLS list. Set AGENTMEMORY_DEBUG=1 to inspect response.\n`);
1998
2550
  } catch (err) {
1999
- process.stderr.write(`[@agentmemory/mcp] tools/list proxy failed: ${err instanceof Error ? err.message : String(err)}; falling back to local list\n`);
2000
2551
  invalidateHandle();
2552
+ if (isAuthenticationError(err) || isProxyRequired()) throw err;
2553
+ process.stderr.write(`[@agentmemory/mcp] tools/list proxy failed: ${err instanceof Error ? err.message : String(err)}; falling back to local list\n`);
2001
2554
  }
2002
2555
  const fallback = getAllTools().filter((t) => IMPLEMENTED_TOOLS.has(t.name));
2003
2556
  if (debug) process.stderr.write(`[@agentmemory/mcp] tools/list: returning ${fallback.length} local fallback tools (${fallback.map((t) => t.name).join(",")})\n`);