@agentmemory/agentmemory 0.9.30 → 0.9.32

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 (334) hide show
  1. package/.env.example +57 -48
  2. package/AGENTS.md +8 -8
  3. package/README.md +256 -819
  4. package/dist/.env.example +57 -48
  5. package/dist/cli.d.mts.map +1 -1
  6. package/dist/cli.mjs +2257 -1027
  7. package/dist/cli.mjs.map +1 -1
  8. package/dist/compression-recovery-CZh63Jmz.mjs +5997 -0
  9. package/dist/compression-recovery-CZh63Jmz.mjs.map +1 -0
  10. package/dist/{connect-B4_ca6BD.mjs → connect-BX3njQ3Y.mjs} +897 -276
  11. package/dist/connect-BX3njQ3Y.mjs.map +1 -0
  12. package/dist/hooks/_capture.d.mts +5 -1
  13. package/dist/hooks/_capture.d.mts.map +1 -1
  14. package/dist/hooks/_capture.mjs +141 -26
  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 +83 -10
  19. package/dist/hooks/post-commit.mjs.map +1 -1
  20. package/dist/hooks/post-tool-failure.mjs +19 -6
  21. package/dist/hooks/post-tool-failure.mjs.map +1 -1
  22. package/dist/hooks/post-tool-use.mjs +19 -6
  23. package/dist/hooks/post-tool-use.mjs.map +1 -1
  24. package/dist/hooks/pre-compact.mjs +104 -22
  25. package/dist/hooks/pre-compact.mjs.map +1 -1
  26. package/dist/hooks/pre-tool-use.mjs +83 -10
  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 +59 -17
  31. package/dist/hooks/session-end.mjs.map +1 -1
  32. package/dist/hooks/session-start.mjs +95 -15
  33. package/dist/hooks/session-start.mjs.map +1 -1
  34. package/dist/hooks/stop.mjs +75 -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 +32 -10
  39. package/dist/hooks/subagent-stop.mjs.map +1 -1
  40. package/dist/hooks/task-completed.mjs +21 -6
  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 +16390 -11530
  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 +1172 -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-iYXRcrO8.mjs} +717 -474
  53. package/dist/secret-store-iYXRcrO8.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-C23nMpda.mjs} +5263 -4667
  57. package/dist/src-C23nMpda.mjs.map +1 -0
  58. package/dist/{standalone-DKCdrf1d.mjs → standalone-BYo5USDb.mjs} +379 -63
  59. package/dist/standalone-BYo5USDb.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 +864 -81
  63. package/dist/standalone.mjs.map +1 -1
  64. package/dist/viewer/index.html +337 -168
  65. package/integrations/hermes/README.md +94 -0
  66. package/integrations/hermes/__init__.py +670 -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 +1477 -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 +37 -0
  79. package/integrations/omp/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
  80. package/integrations/omp/skills/agentmemory-config/REFERENCE.md +91 -0
  81. package/integrations/omp/skills/agentmemory-config/SKILL.md +98 -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 +60 -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 +52 -0
  88. package/integrations/omp/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
  89. package/integrations/omp/skills/agentmemory-rest-api/REFERENCE.md +159 -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 +98 -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 +37 -0
  132. package/integrations/openclaw/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
  133. package/integrations/openclaw/skills/agentmemory-config/REFERENCE.md +91 -0
  134. package/integrations/openclaw/skills/agentmemory-config/SKILL.md +98 -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 +60 -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 +52 -0
  141. package/integrations/openclaw/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
  142. package/integrations/openclaw/skills/agentmemory-rest-api/REFERENCE.md +159 -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 +46 -51
  177. package/integrations/pi/dist/index.mjs +1460 -0
  178. package/integrations/pi/index.ts +192 -175
  179. package/integrations/pi/package.json +17 -7
  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 +37 -0
  185. package/integrations/pi/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
  186. package/integrations/pi/skills/agentmemory-config/REFERENCE.md +91 -0
  187. package/integrations/pi/skills/agentmemory-config/SKILL.md +98 -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 +60 -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 +52 -0
  194. package/integrations/pi/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
  195. package/integrations/pi/skills/agentmemory-rest-api/REFERENCE.md +159 -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 +33 -11
  229. package/plugin/.claude-plugin/plugin.json +16 -3
  230. package/plugin/.codex-plugin/plugin.json +4 -3
  231. package/plugin/.devin-plugin/plugin.json +6 -5
  232. package/plugin/.mcp.json +5 -1
  233. package/plugin/README.md +71 -0
  234. package/plugin/cursor/hooks.json +23 -8
  235. package/plugin/hooks/hooks.json +24 -12
  236. package/plugin/hooks.json +67 -0
  237. package/plugin/opencode/README.md +1 -1
  238. package/plugin/opencode/agentmemory-capture.ts +25 -11
  239. package/plugin/opencode/plugin.json +1 -1
  240. package/plugin/plugin.json +1 -1
  241. package/plugin/scripts/_capture.d.mts +5 -1
  242. package/plugin/scripts/_capture.d.mts.map +1 -1
  243. package/plugin/scripts/_capture.mjs +141 -26
  244. package/plugin/scripts/_capture.mjs.map +1 -1
  245. package/plugin/scripts/cursor/run-detached.mjs +786 -0
  246. package/plugin/scripts/cursor/run-detached.mjs.map +1 -0
  247. package/plugin/scripts/cursor/run-hook.d.mts +1 -0
  248. package/plugin/scripts/cursor/run-hook.mjs +704 -0
  249. package/plugin/scripts/cursor/run-hook.mjs.map +1 -0
  250. package/plugin/scripts/notification.mjs +20 -6
  251. package/plugin/scripts/notification.mjs.map +1 -1
  252. package/plugin/scripts/plugin-bridge.mjs +61 -11
  253. package/plugin/scripts/post-tool-failure.mjs +19 -6
  254. package/plugin/scripts/post-tool-failure.mjs.map +1 -1
  255. package/plugin/scripts/post-tool-use.mjs +19 -6
  256. package/plugin/scripts/post-tool-use.mjs.map +1 -1
  257. package/plugin/scripts/pre-compact.mjs +104 -22
  258. package/plugin/scripts/pre-compact.mjs.map +1 -1
  259. package/plugin/scripts/pre-tool-use.mjs +83 -10
  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 +59 -17
  264. package/plugin/scripts/session-end.mjs.map +1 -1
  265. package/plugin/scripts/session-start.mjs +95 -15
  266. package/plugin/scripts/session-start.mjs.map +1 -1
  267. package/plugin/scripts/stop.mjs +75 -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 +32 -10
  272. package/plugin/scripts/subagent-stop.mjs.map +1 -1
  273. package/plugin/scripts/task-completed.mjs +21 -6
  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 +8 -7
  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 +8 -4
  280. package/plugin/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
  281. package/plugin/skills/agentmemory-config/REFERENCE.md +13 -15
  282. package/plugin/skills/agentmemory-config/SKILL.md +34 -10
  283. package/plugin/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
  284. package/plugin/skills/agentmemory-hooks/SKILL.md +31 -10
  285. package/plugin/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
  286. package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +5 -5
  287. package/plugin/skills/agentmemory-mcp-tools/SKILL.md +16 -3
  288. package/plugin/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
  289. package/plugin/skills/agentmemory-rest-api/REFERENCE.md +10 -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
  332. package/plugin/scripts/post-commit.mjs +0 -184
  333. package/plugin/scripts/post-commit.mjs.map +0 -1
  334. /package/plugin/scripts/{post-commit.d.mts → cursor/run-detached.d.mts} +0 -0
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { chmodSync, closeSync, existsSync, fchmodSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
4
4
  import { dirname, join } from "node:path";
5
- import { homedir } from "node:os";
5
+ import { homedir, tmpdir } 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,35 @@ 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
- writeFileSync(this.persistPath, JSON.stringify(data), "utf-8");
44
+ const tmpPath = `${this.persistPath}.${process.pid}.tmp`;
45
+ try {
46
+ writeFileSync(tmpPath, JSON.stringify(data), {
47
+ encoding: "utf-8",
48
+ mode: 384
49
+ });
50
+ renameSync(tmpPath, this.persistPath);
51
+ } catch (err) {
52
+ try {
53
+ rmSync(tmpPath, { force: true });
54
+ } catch {}
55
+ throw err;
56
+ }
57
+ return true;
44
58
  } catch (err) {
45
59
  process.stderr.write(`[@agentmemory/mcp] Persist failed: ${err instanceof Error ? err.message : String(err)}\n`);
60
+ return false;
46
61
  }
47
62
  }
48
63
  };
49
64
  //#endregion
50
65
  //#region src/mcp/transport.ts
66
+ let activeStdioTransports = 0;
51
67
  var JsonRpcError = class extends Error {
52
68
  constructor(code, message) {
53
69
  super(message);
@@ -200,6 +216,7 @@ function createMessageParser(onMessage, writeErr = (msg) => process.stderr.write
200
216
  function createStdioTransport(handler) {
201
217
  let parser = null;
202
218
  let queue = Promise.resolve();
219
+ let active = false;
203
220
  const writeResponse = (response) => {
204
221
  const formatted = formatResponse(response, parser?.isFramed() ?? false);
205
222
  if (typeof formatted === "string") {
@@ -211,6 +228,10 @@ function createStdioTransport(handler) {
211
228
  const onData = (chunk) => parser?.push(chunk);
212
229
  return {
213
230
  start() {
231
+ if (active) return;
232
+ active = true;
233
+ activeStdioTransports += 1;
234
+ process.env["AGENTMEMORY_MCP_STDIO__"] = "1";
214
235
  parser = createMessageParser((message) => {
215
236
  queue = queue.then(() => processLine(message, handler, writeResponse));
216
237
  queue.catch((err) => {
@@ -221,16 +242,204 @@ function createStdioTransport(handler) {
221
242
  },
222
243
  stop() {
223
244
  process.stdin.off("data", onData);
245
+ if (active) {
246
+ active = false;
247
+ activeStdioTransports -= 1;
248
+ if (activeStdioTransports === 0) delete process.env["AGENTMEMORY_MCP_STDIO__"];
249
+ }
224
250
  parser = null;
225
251
  }
226
252
  };
227
253
  }
228
254
  //#endregion
255
+ //#region src/cli/engine-launch.ts
256
+ const CREDENTIAL_URL_PATTERN = /:\/\/[^@\s/]*@/g;
257
+ function redactCredentialUrls(text) {
258
+ return text.replace(CREDENTIAL_URL_PATTERN, "://***@");
259
+ }
260
+ const MAX_CRASH_LINE_BYTES = 64 * 1024;
261
+ function writeStderr(text) {
262
+ process.stderr.write(text);
263
+ }
264
+ function stderrWriteMayBlock(platform = process.platform, isTTY = process.stderr.isTTY) {
265
+ return platform === "win32" && !isTTY;
266
+ }
267
+ function mcpCrashLogPath(env = process.env) {
268
+ return join(env["AGENTMEMORY_DATA_DIR"] || join(homedir(), ".agentmemory"), "mcp-crash.log");
269
+ }
270
+ function formatFatal(kind, reason, now = /* @__PURE__ */ new Date()) {
271
+ const detail = reason instanceof Error ? reason.stack || reason.message : String(reason);
272
+ return redactCredentialUrls(`[${now.toISOString()}] pid=${process.pid} ${kind}: ${detail}\n`);
273
+ }
274
+ function safeFormat(kind, reason) {
275
+ try {
276
+ return formatFatal(kind, reason);
277
+ } catch {
278
+ return `[${(/* @__PURE__ */ new Date()).toISOString()}] pid=${process.pid} ${kind}: (the error could not be formatted)\n`;
279
+ }
280
+ }
281
+ function describe(err) {
282
+ return err instanceof Error ? err.message : String(err);
283
+ }
284
+ function rotateCrashLog(logPath, notices) {
285
+ const rotated = `${logPath}.1`;
286
+ try {
287
+ renameSync(logPath, rotated);
288
+ } catch (err) {
289
+ if (err.code === "ENOENT") return;
290
+ throw err;
291
+ }
292
+ try {
293
+ chmodSync(rotated, 384);
294
+ } catch (err) {
295
+ notices.push(`[@agentmemory/mcp] rotated crash log ${rotated} could not be made owner-only: ${describe(err)}\n`);
296
+ }
297
+ }
298
+ function boundCrashLine(line, maxBytes = MAX_CRASH_LINE_BYTES) {
299
+ const bytes = Buffer.from(line, "utf8");
300
+ if (bytes.length <= maxBytes) return line;
301
+ const marker = " ...(truncated)\n";
302
+ const markerBytes = Buffer.byteLength(marker);
303
+ if (maxBytes <= markerBytes) return bytes.subarray(0, Math.max(0, maxBytes)).toString("utf8").replace(/�+$/, "");
304
+ return `${bytes.subarray(0, maxBytes - markerBytes).toString("utf8").replace(/�+$/, "")}${marker}`;
305
+ }
306
+ function writeAll(fd, data, write = writeSync) {
307
+ let offset = 0;
308
+ while (offset < data.length) {
309
+ const n = write(fd, data, offset, data.length - offset);
310
+ if (!(n > 0)) throw new Error(`crash log write stopped after ${offset} of ${data.length} bytes`);
311
+ offset += n;
312
+ }
313
+ }
314
+ function writeCrashLog(line, logPath = mcpCrashLogPath()) {
315
+ const notices = [];
316
+ const bounded = boundCrashLine(line);
317
+ let fd;
318
+ try {
319
+ mkdirSync(dirname(logPath), {
320
+ recursive: true,
321
+ mode: 448
322
+ });
323
+ if (existsSync(logPath) && statSync(logPath).size + Buffer.byteLength(bounded) > 1048576) rotateCrashLog(logPath, notices);
324
+ fd = openSync(logPath, "a", 384);
325
+ try {
326
+ fchmodSync(fd, 384);
327
+ } catch (err) {
328
+ notices.push(`[@agentmemory/mcp] crash log ${logPath} could not be made owner-only, so it was not written: ${describe(err)}\n`);
329
+ return {
330
+ written: false,
331
+ notices
332
+ };
333
+ }
334
+ writeAll(fd, Buffer.from(bounded, "utf8"));
335
+ notices.push(`[@agentmemory/mcp] crash log: ${logPath}\n`);
336
+ return {
337
+ written: true,
338
+ notices
339
+ };
340
+ } catch (err) {
341
+ notices.push(`[@agentmemory/mcp] crash log not written to ${logPath}: ${describe(err)}\n`);
342
+ return {
343
+ written: false,
344
+ notices
345
+ };
346
+ } finally {
347
+ if (fd !== void 0) try {
348
+ closeSync(fd);
349
+ } catch {}
350
+ }
351
+ }
352
+ function fallbackCrashLogPath() {
353
+ return join(tmpdir(), "agentmemory-mcp-crash.log");
354
+ }
355
+ function handleFatal(kind, reason, hooks) {
356
+ const line = safeFormat(kind, reason);
357
+ const stderrMayBlock = hooks.stderrMayBlock ?? stderrWriteMayBlock();
358
+ let result = {
359
+ written: false,
360
+ notices: []
361
+ };
362
+ try {
363
+ result = writeCrashLog(line, hooks.logPath ?? mcpCrashLogPath());
364
+ } catch {}
365
+ const notices = result.notices;
366
+ if (!result.written && stderrMayBlock) try {
367
+ writeCrashLog(line + notices.join(""), hooks.fallbackLogPath ?? fallbackCrashLogPath());
368
+ } catch {}
369
+ try {
370
+ hooks.persist();
371
+ } catch {}
372
+ if (!stderrMayBlock) {
373
+ const write = hooks.write ?? writeStderr;
374
+ for (const text of [`[@agentmemory/mcp] fatal ${line}`, ...notices]) try {
375
+ write(text);
376
+ } catch {}
377
+ }
378
+ (hooks.exit ?? ((code) => process.exit(code)))(1);
379
+ }
380
+ function installCrashHandlers(hooks) {
381
+ process.on("uncaughtException", (err) => handleFatal("uncaughtException", err, hooks));
382
+ process.on("unhandledRejection", (reason) => handleFatal("unhandledRejection", reason, hooks));
383
+ }
384
+ //#endregion
229
385
  //#region src/mcp/tools-registry.ts
386
+ const READ_ONLY_TOOLS = new Set([
387
+ "memory_recall",
388
+ "memory_file_history",
389
+ "memory_patterns",
390
+ "memory_sessions",
391
+ "memory_smart_search",
392
+ "memory_vision_search",
393
+ "memory_timeline",
394
+ "memory_export",
395
+ "memory_relations",
396
+ "memory_commit_lookup",
397
+ "memory_commits",
398
+ "memory_graph_query",
399
+ "memory_team_feed",
400
+ "memory_audit",
401
+ "memory_frontier",
402
+ "memory_next",
403
+ "memory_diagnose",
404
+ "memory_facet_query",
405
+ "memory_verify",
406
+ "memory_lesson_recall",
407
+ "memory_insight_list",
408
+ "memory_slot_list",
409
+ "memory_slot_get"
410
+ ]);
411
+ const DESTRUCTIVE_TOOLS = new Set([
412
+ "memory_action_update",
413
+ "memory_compress_file",
414
+ "memory_claude_bridge_sync",
415
+ "memory_governance_delete",
416
+ "memory_heal",
417
+ "memory_lesson_delete",
418
+ "memory_obsidian_export",
419
+ "memory_slot_replace",
420
+ "memory_slot_delete"
421
+ ]);
422
+ const IDEMPOTENT_WRITE_TOOLS = new Set([
423
+ "memory_governance_delete",
424
+ "memory_lesson_delete",
425
+ "memory_slot_replace",
426
+ "memory_slot_delete",
427
+ "memory_claude_bridge_sync"
428
+ ]);
429
+ const OPEN_WORLD_TOOLS = new Set(["memory_mesh_sync"]);
430
+ function toolAnnotations(name) {
431
+ const readOnly = READ_ONLY_TOOLS.has(name);
432
+ return {
433
+ readOnlyHint: readOnly,
434
+ destructiveHint: !readOnly && DESTRUCTIVE_TOOLS.has(name),
435
+ idempotentHint: readOnly || IDEMPOTENT_WRITE_TOOLS.has(name),
436
+ openWorldHint: OPEN_WORLD_TOOLS.has(name)
437
+ };
438
+ }
230
439
  const CORE_TOOLS = [
231
440
  {
232
441
  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.",
442
+ 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
443
  inputSchema: {
235
444
  type: "object",
236
445
  properties: {
@@ -248,7 +457,28 @@ const CORE_TOOLS = [
248
457
  },
249
458
  token_budget: {
250
459
  type: "number",
251
- description: "Optional token budget to trim returned results"
460
+ description: "Optional estimated content token budget; response includes truncation and recovery metadata"
461
+ },
462
+ targetLayer: {
463
+ type: "string",
464
+ enum: [
465
+ "all",
466
+ "memory",
467
+ "observation"
468
+ ],
469
+ description: "Search all indexed layers (default), durable memories, or raw observations before ranking"
470
+ },
471
+ project: {
472
+ type: "string",
473
+ description: "Filter by project path"
474
+ },
475
+ cwd: {
476
+ type: "string",
477
+ description: "Filter by session working directory"
478
+ },
479
+ agentId: {
480
+ type: "string",
481
+ description: "Filter by owning agent; '*' reads across agents"
252
482
  }
253
483
  },
254
484
  required: ["query"]
@@ -337,15 +567,32 @@ const CORE_TOOLS = [
337
567
  },
338
568
  {
339
569
  name: "memory_sessions",
340
- description: "List recent sessions with their status and observation counts.",
570
+ 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
571
  inputSchema: {
342
572
  type: "object",
343
- properties: {}
573
+ properties: {
574
+ project: {
575
+ type: "string",
576
+ description: "Exact project identifier used when sessions were started"
577
+ },
578
+ agentId: {
579
+ type: "string",
580
+ description: "Filter by owning agent; '*' reads across agents"
581
+ },
582
+ limit: {
583
+ type: "integer",
584
+ description: "Page size (default 20, max 100)"
585
+ },
586
+ cursor: {
587
+ type: "string",
588
+ description: "nextCursor from the previous page; omit for the first page"
589
+ }
590
+ }
344
591
  }
345
592
  },
346
593
  {
347
594
  name: "memory_smart_search",
348
- description: "Hybrid semantic+keyword search with progressive disclosure.",
595
+ description: "Hybrid semantic+keyword search with progressive disclosure. Pass query to search, or expandIds to recover full results.",
349
596
  inputSchema: {
350
597
  type: "object",
351
598
  properties: {
@@ -355,14 +602,34 @@ const CORE_TOOLS = [
355
602
  },
356
603
  expandIds: {
357
604
  type: "string",
358
- description: "Comma-separated observation IDs to expand"
605
+ description: "Comma-separated memory or observation IDs to expand; query is optional when provided"
359
606
  },
360
607
  limit: {
361
608
  type: "number",
362
609
  description: "Max results (default 10)"
610
+ },
611
+ targetLayer: {
612
+ type: "string",
613
+ enum: [
614
+ "all",
615
+ "memory",
616
+ "observation"
617
+ ],
618
+ description: "Search all indexed layers (default), durable memories, or raw observations before ranking"
619
+ },
620
+ project: {
621
+ type: "string",
622
+ description: "Filter by project path"
623
+ },
624
+ agentId: {
625
+ type: "string",
626
+ description: "Filter by owning agent; '*' reads across agents"
627
+ },
628
+ includeLessons: {
629
+ type: "boolean",
630
+ description: "Include lesson matches when targetLayer is all (default true)"
363
631
  }
364
- },
365
- required: ["query"]
632
+ }
366
633
  }
367
634
  },
368
635
  {
@@ -440,10 +707,31 @@ const CORE_TOOLS = [
440
707
  },
441
708
  {
442
709
  name: "memory_export",
443
- description: "Export all memory data as JSON.",
710
+ 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
711
  inputSchema: {
445
712
  type: "object",
446
- properties: {}
713
+ properties: {
714
+ maxSessions: {
715
+ type: "number",
716
+ description: "Sessions per page (with their observations)"
717
+ },
718
+ offset: {
719
+ type: "number",
720
+ description: "Session offset"
721
+ },
722
+ collectionLimit: {
723
+ type: "number",
724
+ 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"
725
+ },
726
+ collectionOffset: {
727
+ type: "number",
728
+ description: "Row offset for the top-level collections"
729
+ },
730
+ collections: {
731
+ type: "string",
732
+ 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."
733
+ }
734
+ }
447
735
  }
448
736
  },
449
737
  {
@@ -1128,6 +1416,11 @@ const V070_TOOLS = [
1128
1416
  tags: {
1129
1417
  type: "string",
1130
1418
  description: "Comma-separated tags"
1419
+ },
1420
+ sourceIds: {
1421
+ type: "array",
1422
+ items: { type: "string" },
1423
+ description: "Ids of the session, memory, observation or crystal this lesson came from (max 50)"
1131
1424
  }
1132
1425
  },
1133
1426
  required: ["content"]
@@ -1340,9 +1633,13 @@ function getAllTools() {
1340
1633
  ...V070_TOOLS,
1341
1634
  ...V073_TOOLS,
1342
1635
  ...V010_SLOTS_TOOLS
1343
- ];
1636
+ ].map((tool) => ({
1637
+ ...tool,
1638
+ annotations: toolAnnotations(tool.name)
1639
+ }));
1344
1640
  }
1345
- const ENV_FILE = join(join(homedir(), ".agentmemory"), ".env");
1641
+ process.env["AGENTMEMORY_DATA_DIR"] || join(homedir(), ".agentmemory");
1642
+ const ENV_FILE = process.env["AGENTMEMORY_ENV_FILE"] || join(homedir(), ".agentmemory", ".env");
1346
1643
  let envFileCache;
1347
1644
  function loadEnvFile() {
1348
1645
  if (envFileCache) return envFileCache;
@@ -1350,7 +1647,10 @@ function loadEnvFile() {
1350
1647
  envFileCache = {};
1351
1648
  return envFileCache;
1352
1649
  }
1353
- const content = readFileSync(ENV_FILE, "utf-8");
1650
+ envFileCache = parseEnvContent(readFileSync(ENV_FILE, "utf-8"));
1651
+ return envFileCache;
1652
+ }
1653
+ function parseEnvContent(content) {
1354
1654
  const vars = {};
1355
1655
  for (const line of content.split("\n")) {
1356
1656
  const trimmed = line.trim();
@@ -1369,8 +1669,7 @@ function loadEnvFile() {
1369
1669
  }
1370
1670
  vars[key] = val;
1371
1671
  }
1372
- envFileCache = vars;
1373
- return envFileCache;
1672
+ return vars;
1374
1673
  }
1375
1674
  function getMergedEnv(overrides) {
1376
1675
  return {
@@ -1379,12 +1678,303 @@ function getMergedEnv(overrides) {
1379
1678
  ...overrides
1380
1679
  };
1381
1680
  }
1681
+ function loadAgentScope() {
1682
+ const env = getMergedEnv();
1683
+ const raw = env["AGENT_ID"];
1684
+ if (!raw) return null;
1685
+ const agentId = raw.trim().slice(0, 128);
1686
+ if (!agentId) return null;
1687
+ return {
1688
+ agentId,
1689
+ mode: env["AGENTMEMORY_AGENT_SCOPE"] === "isolated" ? "isolated" : "shared"
1690
+ };
1691
+ }
1692
+ function getAgentId() {
1693
+ return loadAgentScope()?.agentId;
1694
+ }
1695
+ function isAgentScopeIsolated() {
1696
+ return loadAgentScope()?.mode === "isolated";
1697
+ }
1382
1698
  function getStandalonePersistPath() {
1383
1699
  return getMergedEnv()["STANDALONE_PERSIST_PATH"] || join(homedir(), ".agentmemory", "standalone.json");
1384
1700
  }
1385
1701
  //#endregion
1702
+ //#region src/state/search-layer.ts
1703
+ function isSearchLayer(value) {
1704
+ return value === "all" || value === "memory" || value === "observation";
1705
+ }
1706
+ //#endregion
1707
+ //#region src/state/memory-utils.ts
1708
+ function memoryToObservation(memory) {
1709
+ return {
1710
+ id: memory.id,
1711
+ sessionId: memory.sessionIds?.[0] ?? "memory",
1712
+ timestamp: memory.createdAt,
1713
+ type: "decision",
1714
+ memoryType: memory.type,
1715
+ title: memory.title,
1716
+ facts: [memory.content],
1717
+ narrative: memory.content,
1718
+ concepts: memory.concepts,
1719
+ files: memory.files,
1720
+ importance: memory.strength,
1721
+ ...memory.agentId ? { agentId: memory.agentId } : {}
1722
+ };
1723
+ }
1724
+ //#endregion
1725
+ //#region src/functions/recall-response.ts
1726
+ function estimateTokens(value) {
1727
+ return Math.max(1, Math.ceil(JSON.stringify(value).length / 3));
1728
+ }
1729
+ function prefix(text, length) {
1730
+ let end = Math.min(length, text.length);
1731
+ if (end > 0 && end < text.length && /[\uD800-\uDBFF]/.test(text[end - 1])) end--;
1732
+ return text.slice(0, end);
1733
+ }
1734
+ function fitText(text, budget, makeResult) {
1735
+ let low = 0;
1736
+ let high = text.length;
1737
+ while (low < high) {
1738
+ const middle = Math.ceil((low + high) / 2);
1739
+ if (estimateTokens(makeResult(prefix(text, middle))) <= budget) low = middle;
1740
+ else high = middle - 1;
1741
+ }
1742
+ return makeResult(prefix(text, low));
1743
+ }
1744
+ function formatResult(result, format) {
1745
+ if (format === "full") return result;
1746
+ const observation = result.observation;
1747
+ const compact = {
1748
+ obsId: observation.id,
1749
+ sessionId: result.sessionId,
1750
+ title: observation.title,
1751
+ type: observation.type,
1752
+ ...observation.memoryType !== void 0 && { memoryType: observation.memoryType },
1753
+ score: result.score,
1754
+ timestamp: observation.timestamp,
1755
+ ...result.layer !== void 0 && { layer: result.layer }
1756
+ };
1757
+ if (format === "compact") return compact;
1758
+ const { type: _type, ...narrative } = compact;
1759
+ return {
1760
+ ...narrative,
1761
+ narrative: observation.narrative
1762
+ };
1763
+ }
1764
+ function clipResult(result, format, budget) {
1765
+ const observation = result.observation;
1766
+ const layer = result.layer !== void 0 ? { layer: result.layer } : {};
1767
+ if (format === "compact") {
1768
+ const base = {
1769
+ obsId: observation.id,
1770
+ sessionId: result.sessionId,
1771
+ title: "",
1772
+ type: observation.type,
1773
+ ...observation.memoryType !== void 0 && { memoryType: observation.memoryType },
1774
+ score: result.score,
1775
+ timestamp: observation.timestamp,
1776
+ ...layer,
1777
+ content_truncated: true
1778
+ };
1779
+ const minimum = estimateTokens(base);
1780
+ if (minimum > budget) return { minimum };
1781
+ return {
1782
+ result: fitText(observation.title, budget, (title) => ({
1783
+ ...base,
1784
+ title
1785
+ })),
1786
+ minimum
1787
+ };
1788
+ }
1789
+ const makeResult = (title, narrative) => {
1790
+ if (format === "narrative") return {
1791
+ obsId: observation.id,
1792
+ sessionId: result.sessionId,
1793
+ title,
1794
+ narrative,
1795
+ ...observation.memoryType !== void 0 && { memoryType: observation.memoryType },
1796
+ score: result.score,
1797
+ timestamp: observation.timestamp,
1798
+ ...layer,
1799
+ content_truncated: true
1800
+ };
1801
+ return {
1802
+ observation: {
1803
+ id: observation.id,
1804
+ sessionId: observation.sessionId,
1805
+ timestamp: observation.timestamp,
1806
+ type: observation.type,
1807
+ ...observation.memoryType !== void 0 && { memoryType: observation.memoryType },
1808
+ title,
1809
+ facts: [],
1810
+ narrative,
1811
+ concepts: [],
1812
+ files: [],
1813
+ importance: observation.importance,
1814
+ ...observation.confidence !== void 0 && { confidence: observation.confidence },
1815
+ ...observation.agentId !== void 0 && { agentId: observation.agentId },
1816
+ ...observation.origin && { origin: {
1817
+ channel: observation.origin.channel,
1818
+ capturedAt: observation.origin.capturedAt
1819
+ } }
1820
+ },
1821
+ score: result.score,
1822
+ sessionId: result.sessionId,
1823
+ ...layer,
1824
+ content_truncated: true
1825
+ };
1826
+ };
1827
+ const minimum = estimateTokens(makeResult("", ""));
1828
+ if (minimum > budget) return { minimum };
1829
+ const titleResult = fitText(prefix(observation.title, 120), budget, (title) => makeResult(title, ""));
1830
+ const title = "observation" in titleResult ? titleResult.observation.title : titleResult.title;
1831
+ return {
1832
+ result: fitText(observation.narrative || observation.facts.join("\n"), budget, (text) => makeResult(title, text)),
1833
+ minimum
1834
+ };
1835
+ }
1836
+ function buildRecallResponse(results, format, tokenBudget) {
1837
+ const selected = [];
1838
+ let used = 0;
1839
+ let clipped = false;
1840
+ let minimumBudget;
1841
+ for (const result of results) {
1842
+ const formatted = formatResult(result, format);
1843
+ const tokens = estimateTokens(formatted);
1844
+ if (tokenBudget === void 0 || used + tokens <= tokenBudget) {
1845
+ selected.push(formatted);
1846
+ used += tokens;
1847
+ continue;
1848
+ }
1849
+ if (selected.length === 0) {
1850
+ const preview = clipResult(result, format, tokenBudget);
1851
+ if (preview.result) {
1852
+ selected.push(preview.result);
1853
+ used = estimateTokens(preview.result);
1854
+ clipped = true;
1855
+ continue;
1856
+ } else minimumBudget = Math.min(preview.minimum, tokens);
1857
+ }
1858
+ break;
1859
+ }
1860
+ const excluded = results.slice(selected.length);
1861
+ const metadata = {
1862
+ tokens_used: used,
1863
+ tokens_budget: tokenBudget,
1864
+ truncated: clipped || excluded.length > 0,
1865
+ matched_count: results.length,
1866
+ excluded_by_budget: excluded.length,
1867
+ excluded_results: excluded.slice(0, 10).map((result) => ({
1868
+ obsId: result.observation.id,
1869
+ sessionId: result.sessionId,
1870
+ title: prefix(result.observation.title, 120)
1871
+ })),
1872
+ excluded_results_truncated: excluded.length > 10,
1873
+ ...minimumBudget !== void 0 && { minimum_budget: minimumBudget }
1874
+ };
1875
+ if (format === "narrative") {
1876
+ const narrativeResults = selected;
1877
+ return {
1878
+ ...metadata,
1879
+ format,
1880
+ results: narrativeResults,
1881
+ text: narrativeResults.map((result, index) => `${index + 1}. ${result.title}\n${result.narrative}`).join("\n\n")
1882
+ };
1883
+ }
1884
+ if (format === "compact") return {
1885
+ ...metadata,
1886
+ format,
1887
+ results: selected
1888
+ };
1889
+ return {
1890
+ ...metadata,
1891
+ format,
1892
+ results: selected
1893
+ };
1894
+ }
1895
+ //#endregion
1896
+ //#region src/mcp/search-arguments.ts
1897
+ function parseSearchExpansionIds(value) {
1898
+ return (typeof value === "string" ? value.split(",") : Array.isArray(value) ? value : []).flatMap((entry) => {
1899
+ if (typeof entry === "string") return entry.trim() ? [entry.trim()] : [];
1900
+ if (!entry || typeof entry !== "object" || typeof entry.obsId !== "string" || !entry.obsId.trim()) return [];
1901
+ const obsId = entry.obsId.trim();
1902
+ return typeof entry.sessionId === "string" && entry.sessionId.trim() ? [{
1903
+ obsId,
1904
+ sessionId: entry.sessionId.trim()
1905
+ }] : [obsId];
1906
+ });
1907
+ }
1908
+ //#endregion
1909
+ //#region src/state/list-query.ts
1910
+ function encodeCursor(position) {
1911
+ return Buffer.from(JSON.stringify(position), "utf-8").toString("base64url");
1912
+ }
1913
+ function decodeCursor(cursor) {
1914
+ if (!cursor) return null;
1915
+ try {
1916
+ const parsed = JSON.parse(Buffer.from(cursor, "base64url").toString("utf-8"));
1917
+ if (!parsed || typeof parsed !== "object") return null;
1918
+ const position = {};
1919
+ if (typeof parsed.key === "string") position.key = parsed.key;
1920
+ if (typeof parsed.id === "string") position.id = parsed.id;
1921
+ if (Number.isInteger(parsed.offset) && parsed.offset >= 0) position.offset = parsed.offset;
1922
+ return position;
1923
+ } catch {
1924
+ return null;
1925
+ }
1926
+ }
1927
+ function compareDesc(aKey, aId, bKey, bId) {
1928
+ if (aKey !== bKey) return aKey < bKey ? 1 : -1;
1929
+ if (aId === bId) return 0;
1930
+ return aId < bId ? 1 : -1;
1931
+ }
1932
+ function sortByKeyDesc(items, keyOf, idOf) {
1933
+ return items.sort((a, b) => compareDesc(keyOf(a), idOf(a), keyOf(b), idOf(b)));
1934
+ }
1935
+ function pageAfterCursor(sortedDesc, keyOf, idOf, cursor, limit) {
1936
+ const position = decodeCursor(cursor);
1937
+ let start = 0;
1938
+ if (position?.key !== void 0 && position.id !== void 0) {
1939
+ const { key, id } = position;
1940
+ start = sortedDesc.findIndex((item) => compareDesc(keyOf(item), idOf(item), key, id) > 0);
1941
+ if (start < 0) start = sortedDesc.length;
1942
+ }
1943
+ const page = sortedDesc.slice(start, start + limit);
1944
+ const last = page[page.length - 1];
1945
+ return {
1946
+ page,
1947
+ nextCursor: last !== void 0 && start + limit < sortedDesc.length ? encodeCursor({
1948
+ key: keyOf(last),
1949
+ id: idOf(last)
1950
+ }) : null
1951
+ };
1952
+ }
1953
+ //#endregion
1954
+ //#region src/mcp/session-arguments.ts
1955
+ function parseSessionArguments(args) {
1956
+ const limit = args.limit === void 0 ? 20 : args.limit;
1957
+ if (typeof limit !== "number" || !Number.isInteger(limit) || limit < 1) throw new Error("limit must be a positive integer");
1958
+ const query = { limit: String(Math.min(limit, 100)) };
1959
+ for (const field of [
1960
+ "project",
1961
+ "agentId",
1962
+ "cursor"
1963
+ ]) {
1964
+ if (args[field] === void 0) continue;
1965
+ if (field === "cursor" && typeof args[field] === "string" && !args[field].trim()) continue;
1966
+ if (typeof args[field] !== "string" || !args[field].trim()) throw new Error(`${field} must be a non-empty string`);
1967
+ query[field] = args[field].trim();
1968
+ }
1969
+ if (query.cursor) {
1970
+ const position = decodeCursor(query.cursor);
1971
+ if (!position || typeof position.key !== "string" || typeof position.id !== "string") throw new Error("cursor must be a session continuation token");
1972
+ }
1973
+ return query;
1974
+ }
1975
+ //#endregion
1386
1976
  //#region src/version.ts
1387
- const VERSION = "0.9.30";
1977
+ const VERSION = "0.9.32";
1388
1978
  createRequire(import.meta.url);
1389
1979
  //#endregion
1390
1980
  //#region src/state/schema.ts
@@ -1393,6 +1983,7 @@ const KV = {
1393
1983
  observations: (sessionId) => `mem:obs:${sessionId}`,
1394
1984
  memories: "mem:memories",
1395
1985
  summaries: "mem:summaries",
1986
+ summaryRepairs: "mem:summary:repairs",
1396
1987
  config: "mem:config",
1397
1988
  metrics: "mem:metrics",
1398
1989
  health: "mem:health",
@@ -1403,11 +1994,17 @@ const KV = {
1403
1994
  profiles: "mem:profiles",
1404
1995
  claudeBridge: "mem:claude-bridge",
1405
1996
  graphNodes: "mem:graph:nodes",
1997
+ graphControl: "mem:graph:control",
1406
1998
  graphEdges: "mem:graph:edges",
1407
1999
  graphSnapshot: "mem:graph:snapshot",
1408
2000
  graphNameIndex: "mem:graph:name-index",
1409
2001
  graphEdgeKey: "mem:graph:edge-key",
1410
2002
  graphNodeDegree: "mem:graph:node-degree",
2003
+ graphMembership: "mem:graph:membership",
2004
+ graphRetrievalControl: "mem:graph:retrieval-control",
2005
+ graphRetrievalData: "mem:graph:retrieval-data",
2006
+ graphIndexMigration: "mem:graph:index-migration",
2007
+ graphIndexManifest: "mem:graph:index-manifest",
1411
2008
  semantic: "mem:semantic",
1412
2009
  procedural: "mem:procedural",
1413
2010
  teamShared: (teamId) => `mem:team:${teamId}:shared`,
@@ -1452,6 +2049,7 @@ function generateId(prefix) {
1452
2049
  return `${prefix}_${Date.now().toString(36)}_${crypto.randomUUID().replace(/-/g, "").slice(0, 12)}`;
1453
2050
  }
1454
2051
  process.env["AGENTMEMORY_VERBOSE"] === "1" || process.env["AGENTMEMORY_VERBOSE"];
2052
+ new AsyncLocalStorage();
1455
2053
  KV.auditMonths;
1456
2054
  const AUDIT_MIGRATION_STATE_KEY = "migration";
1457
2055
  async function readAuditMigrationState(kv) {
@@ -1530,7 +2128,7 @@ async function queryAudit(kv, filter) {
1530
2128
  //#region src/secret-store.ts
1531
2129
  const SECRET_KEY = "AGENTMEMORY_SECRET";
1532
2130
  function agentmemoryHomeDir() {
1533
- return join(homedir(), ".agentmemory");
2131
+ return process.env["AGENTMEMORY_DATA_DIR"] || join(homedir(), ".agentmemory");
1534
2132
  }
1535
2133
  function secretFilePath() {
1536
2134
  return join(agentmemoryHomeDir(), "secret");
@@ -1554,7 +2152,7 @@ function unquote(value) {
1554
2152
  function readEnvFileSecret() {
1555
2153
  let content;
1556
2154
  try {
1557
- content = readFileSync(join(agentmemoryHomeDir(), ".env"), "utf-8");
2155
+ content = readFileSync(process.env["AGENTMEMORY_ENV_FILE"] || join(homedir(), ".agentmemory", ".env"), "utf-8");
1558
2156
  } catch {
1559
2157
  return "";
1560
2158
  }
@@ -1570,13 +2168,29 @@ function readEnvFileSecret() {
1570
2168
  }
1571
2169
  return found;
1572
2170
  }
1573
- function readStoredSecret() {
2171
+ function readSecretFile(path) {
1574
2172
  try {
1575
- return usable(readFileSync(secretFilePath(), "utf-8"));
2173
+ return usable(readFileSync(path, "utf-8"));
1576
2174
  } catch {
1577
2175
  return "";
1578
2176
  }
1579
2177
  }
2178
+ function legacyDataDirSecretPaths(env = process.env) {
2179
+ const dataDir = env["AGENTMEMORY_DATA_DIR"];
2180
+ if (!dataDir) return [];
2181
+ const paths = [
2182
+ join(dataDir, "secret"),
2183
+ join(dataDir, ".hmac"),
2184
+ join(dataDir, "..", ".hmac")
2185
+ ];
2186
+ return [...new Set(paths.filter((path) => path !== secretFilePath()))];
2187
+ }
2188
+ function readStoredSecret(env = process.env) {
2189
+ const canonicalPath = canonicalSecretPath();
2190
+ const localPath = secretFilePath();
2191
+ const legacyPaths = legacyDataDirSecretPaths(env);
2192
+ return readSecretFile(canonicalPath) || (localPath === canonicalPath ? "" : readSecretFile(localPath)) || legacyPaths.map(readSecretFile).find(Boolean) || "";
2193
+ }
1580
2194
  function isLoopbackUrl(url) {
1581
2195
  let hostname;
1582
2196
  try {
@@ -1590,8 +2204,34 @@ function isLoopbackUrl(url) {
1590
2204
  function resolveClientSecret(baseUrl, env = process.env) {
1591
2205
  const fromEnv = usable(env[SECRET_KEY]);
1592
2206
  if (fromEnv) return fromEnv;
2207
+ if (env.AGENTMEMORY_CREDENTIAL_MODE === "explicit") return "";
1593
2208
  if (!isLoopbackUrl(baseUrl)) return "";
1594
- return readEnvFileSecret() || readStoredSecret();
2209
+ return readEnvFileSecret() || readStoredSecret(env);
2210
+ }
2211
+ function canonicalSecretPath() {
2212
+ return join(homedir(), ".agentmemory", "secret");
2213
+ }
2214
+ //#endregion
2215
+ //#region src/hooks/_endpoint.ts
2216
+ const OPTION_PREFIX = "CLAUDE_PLUGIN_OPTION_";
2217
+ function filled(value) {
2218
+ const trimmed = value?.trim();
2219
+ if (!trimmed || trimmed.startsWith("${") && trimmed.endsWith("}")) return void 0;
2220
+ return value;
2221
+ }
2222
+ function hookSetting(name, env = process.env) {
2223
+ const optionKey = `${OPTION_PREFIX}${name}`;
2224
+ const option = filled(env[optionKey])?.trim();
2225
+ if (option) return option;
2226
+ if (name === "AGENTMEMORY_SECRET" && optionKey in env) return void 0;
2227
+ return filled(env[name]);
2228
+ }
2229
+ function resolveSettingSecret(url, env = process.env) {
2230
+ const secretEnv = { ...env };
2231
+ const explicit = hookSetting("AGENTMEMORY_SECRET", env);
2232
+ if (explicit === void 0) delete secretEnv["AGENTMEMORY_SECRET"];
2233
+ else secretEnv["AGENTMEMORY_SECRET"] = explicit;
2234
+ return resolveClientSecret(url, secretEnv);
1595
2235
  }
1596
2236
  //#endregion
1597
2237
  //#region src/mcp/rest-proxy.ts
@@ -1605,7 +2245,7 @@ function probeTimeoutMs() {
1605
2245
  const n = Number(raw);
1606
2246
  return Number.isFinite(n) && n > 0 ? Math.floor(n) : DEFAULT_HEALTH_PROBE_TIMEOUT_MS;
1607
2247
  }
1608
- function forceProxy() {
2248
+ function isProxyRequired() {
1609
2249
  const raw = process.env["AGENTMEMORY_FORCE_PROXY"];
1610
2250
  return raw === "1" || raw === "true";
1611
2251
  }
@@ -1620,26 +2260,32 @@ var ProxyCallError = class extends Error {
1620
2260
  }
1621
2261
  };
1622
2262
  let cached = null;
2263
+ let cachedUrl = null;
1623
2264
  let cachedAt = 0;
1624
2265
  let probeInFlight = null;
1625
2266
  function resolveEnvOrEmpty(name) {
1626
- const raw = process.env[name];
1627
- if (!raw) return "";
1628
- if (raw.startsWith("${") && raw.endsWith("}")) return "";
1629
- return raw;
2267
+ return hookSetting(name) ?? "";
1630
2268
  }
1631
2269
  function baseUrl() {
1632
- return (resolveEnvOrEmpty("AGENTMEMORY_URL") || DEFAULT_URL).replace(/\/+$/, "");
2270
+ const value = resolveEnvOrEmpty("AGENTMEMORY_URL") || DEFAULT_URL;
2271
+ try {
2272
+ const parsed = new URL(value);
2273
+ if (!["http:", "https:"].includes(parsed.protocol) || !parsed.hostname || parsed.username || parsed.password || /[?#\s]/.test(value)) throw new Error();
2274
+ return value.replace(/\/+$/, "");
2275
+ } catch {
2276
+ throw new Error("AGENTMEMORY_URL must be an HTTP(S) URL without credentials, query, or fragment");
2277
+ }
1633
2278
  }
1634
- function authHeader() {
1635
- const secret = resolveClientSecret(baseUrl());
2279
+ function authHeader(url) {
2280
+ const secret = resolveSettingSecret(url);
1636
2281
  return secret ? { authorization: `Bearer ${secret}` } : {};
1637
2282
  }
1638
2283
  const defaultLivezProbe = async (url, timeoutMs, headers) => {
1639
2284
  const res = await fetch(`${url}/agentmemory/livez`, {
1640
2285
  method: "GET",
1641
2286
  headers,
1642
- signal: AbortSignal.timeout(timeoutMs)
2287
+ signal: AbortSignal.timeout(timeoutMs),
2288
+ redirect: "error"
1643
2289
  });
1644
2290
  return {
1645
2291
  ok: res.ok,
@@ -1651,7 +2297,7 @@ let livezProbe = defaultLivezProbe;
1651
2297
  async function probe(url) {
1652
2298
  const timeout = probeTimeoutMs();
1653
2299
  try {
1654
- const res = await livezProbe(url, timeout, authHeader());
2300
+ const res = await livezProbe(url, timeout, authHeader(url));
1655
2301
  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
2302
  return res.ok;
1657
2303
  } catch (err) {
@@ -1661,33 +2307,38 @@ async function probe(url) {
1661
2307
  }
1662
2308
  function invalidateHandle() {
1663
2309
  cached = null;
2310
+ cachedUrl = null;
1664
2311
  cachedAt = 0;
1665
2312
  }
1666
2313
  async function resolveHandle() {
1667
2314
  const now = Date.now();
2315
+ const url = baseUrl();
2316
+ if (cached && (cachedUrl !== url || cached.mode === "local" && isProxyRequired())) invalidateHandle();
1668
2317
  if (cached) if (cached.mode === "local" && now - cachedAt >= LOCAL_MODE_TTL_MS) {
1669
2318
  cached = null;
1670
2319
  cachedAt = 0;
1671
2320
  } else return cached;
1672
- if (probeInFlight) return probeInFlight;
1673
- const url = baseUrl();
1674
- const skipProbe = forceProxy();
1675
- probeInFlight = (async () => {
2321
+ const skipProbe = isProxyRequired();
2322
+ if (probeInFlight?.url === url && probeInFlight.forceProxy === skipProbe) return probeInFlight.promise;
2323
+ const pending = (async () => {
1676
2324
  const up = skipProbe ? true : await probe(url);
2325
+ if (baseUrl() !== url || isProxyRequired() !== skipProbe) return resolveHandle();
1677
2326
  if (skipProbe) process.stderr.write(`[@agentmemory/mcp] AGENTMEMORY_FORCE_PROXY set; skipping livez probe and trusting ${url}\n`);
1678
2327
  if (up) {
1679
2328
  const handle = {
1680
2329
  mode: "proxy",
1681
2330
  baseUrl: url,
1682
2331
  call: async (path, init) => {
2332
+ if (baseUrl() !== url) throw new Error("AgentMemory endpoint changed; resolve a new proxy handle before retrying.");
1683
2333
  const res = await fetch(`${url}${path}`, {
1684
2334
  ...init,
1685
2335
  headers: {
1686
2336
  "content-type": "application/json",
1687
- ...authHeader(),
2337
+ ...authHeader(url),
1688
2338
  ...init?.headers
1689
2339
  },
1690
- signal: AbortSignal.timeout(CALL_TIMEOUT_MS)
2340
+ signal: AbortSignal.timeout(CALL_TIMEOUT_MS),
2341
+ redirect: "error"
1691
2342
  });
1692
2343
  if (!res.ok) {
1693
2344
  const errText = await res.text().catch(() => "");
@@ -1704,18 +2355,25 @@ async function resolveHandle() {
1704
2355
  }
1705
2356
  };
1706
2357
  cached = handle;
2358
+ cachedUrl = url;
1707
2359
  cachedAt = Date.now();
1708
2360
  return handle;
1709
2361
  }
1710
2362
  const local = { mode: "local" };
1711
2363
  cached = local;
2364
+ cachedUrl = url;
1712
2365
  cachedAt = Date.now();
1713
2366
  return local;
1714
2367
  })();
2368
+ probeInFlight = {
2369
+ url,
2370
+ forceProxy: skipProbe,
2371
+ promise: pending
2372
+ };
1715
2373
  try {
1716
- return await probeInFlight;
2374
+ return await pending;
1717
2375
  } finally {
1718
- probeInFlight = null;
2376
+ if (probeInFlight?.promise === pending) probeInFlight = null;
1719
2377
  }
1720
2378
  }
1721
2379
  //#endregion
@@ -1775,6 +2433,9 @@ function textResponse(payload, pretty = false) {
1775
2433
  text: JSON.stringify(payload, null, pretty ? 2 : 0)
1776
2434
  }] };
1777
2435
  }
2436
+ function isAuthenticationError(error) {
2437
+ return error instanceof ProxyCallError && (error.status === 401 || error.status === 403);
2438
+ }
1778
2439
  function validate(toolName, args) {
1779
2440
  if (!IMPLEMENTED_TOOLS.has(toolName)) throw new Error(`Unknown tool: ${toolName}`);
1780
2441
  const v = { tool: toolName };
@@ -1792,22 +2453,41 @@ function validate(toolName, args) {
1792
2453
  }
1793
2454
  case "memory_recall":
1794
2455
  case "memory_smart_search": {
2456
+ if (args.targetLayer !== void 0 && !isSearchLayer(args.targetLayer)) throw new Error("targetLayer must be one of: all, memory, observation");
2457
+ v.targetLayer = args.targetLayer ?? "all";
2458
+ for (const field of [
2459
+ "project",
2460
+ "cwd",
2461
+ "agentId",
2462
+ "sessionId",
2463
+ "source"
2464
+ ]) {
2465
+ if (args[field] !== void 0 && typeof args[field] !== "string") throw new Error(`${field} must be a string`);
2466
+ if (typeof args[field] === "string" && args[field].trim()) v[field] = args[field].trim();
2467
+ }
2468
+ if (toolName === "memory_smart_search") {
2469
+ v.expandIds = parseSearchExpansionIds(args.expandIds);
2470
+ if (typeof args.includeLessons === "boolean") v.includeLessons = args.includeLessons;
2471
+ }
1795
2472
  const query = args["query"];
1796
- if (typeof query !== "string" || !query.trim()) throw new Error("query is required");
1797
- v.query = query.trim();
2473
+ if (typeof query !== "string" || !query.trim()) {
2474
+ if (!v.expandIds?.length) throw new Error("query is required unless expandIds is provided");
2475
+ } else v.query = query.trim();
1798
2476
  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);
2477
+ if (toolName === "memory_recall") {
2478
+ const format = typeof args.format === "string" ? args.format.trim().toLowerCase() : args.format ?? "full";
2479
+ if (format !== "full" && format !== "compact" && format !== "narrative") throw new Error("format must be one of: full, compact, narrative");
2480
+ v.format = format;
2481
+ if (args.token_budget !== void 0) {
2482
+ const budget = typeof args.token_budget === "string" ? Number(args.token_budget) : args.token_budget;
2483
+ if (typeof budget !== "number" || !Number.isInteger(budget) || budget < 1) throw new Error("token_budget must be a positive integer");
2484
+ v.tokenBudget = budget;
2485
+ }
1806
2486
  }
1807
2487
  return v;
1808
2488
  }
1809
2489
  case "memory_sessions":
1810
- v.limit = parseLimit(args["limit"], 20);
2490
+ v.sessionQuery = parseSessionArguments(args);
1811
2491
  return v;
1812
2492
  case "memory_governance_delete": {
1813
2493
  const ids = normalizeList(args["memoryIds"]);
@@ -1816,7 +2496,22 @@ function validate(toolName, args) {
1816
2496
  v.reason = args["reason"] || "plugin skill request";
1817
2497
  return v;
1818
2498
  }
1819
- case "memory_export": return v;
2499
+ case "memory_export": {
2500
+ const query = new URLSearchParams();
2501
+ for (const key of [
2502
+ "maxSessions",
2503
+ "offset",
2504
+ "collectionLimit",
2505
+ "collectionOffset"
2506
+ ]) {
2507
+ const n = Number(args[key]);
2508
+ const min = key === "maxSessions" || key === "collectionLimit" ? 1 : 0;
2509
+ if (args[key] !== void 0 && Number.isInteger(n) && n >= min) query.set(key, String(n));
2510
+ }
2511
+ if (typeof args["collections"] === "string") query.set("collections", args["collections"]);
2512
+ v.exportQuery = query.toString();
2513
+ return v;
2514
+ }
1820
2515
  case "memory_audit":
1821
2516
  v.limit = parseLimit(args["limit"], 50);
1822
2517
  return v;
@@ -1840,7 +2535,11 @@ async function handleProxy(v, handle) {
1840
2535
  const body = {
1841
2536
  query: v.query,
1842
2537
  limit: v.limit,
1843
- format: v.format ?? "full"
2538
+ format: v.format ?? "full",
2539
+ targetLayer: v.targetLayer,
2540
+ project: v.project,
2541
+ cwd: v.cwd,
2542
+ agentId: v.agentId
1844
2543
  };
1845
2544
  if (v.tokenBudget != null) body["token_budget"] = v.tokenBudget;
1846
2545
  return textResponse(await handle.call("/agentmemory/search", {
@@ -1851,16 +2550,21 @@ async function handleProxy(v, handle) {
1851
2550
  case "memory_smart_search": {
1852
2551
  const body = {
1853
2552
  query: v.query,
1854
- limit: v.limit
2553
+ limit: v.limit,
2554
+ targetLayer: v.targetLayer,
2555
+ project: v.project,
2556
+ agentId: v.agentId,
2557
+ expandIds: v.expandIds,
2558
+ sessionId: v.sessionId,
2559
+ source: v.source,
2560
+ includeLessons: v.includeLessons
1855
2561
  };
1856
- if (v.format != null) body["format"] = v.format;
1857
- if (v.tokenBudget != null) body["token_budget"] = v.tokenBudget;
1858
2562
  return textResponse(await handle.call("/agentmemory/smart-search", {
1859
2563
  method: "POST",
1860
2564
  body: JSON.stringify(body)
1861
2565
  }), true);
1862
2566
  }
1863
- case "memory_sessions": return textResponse(await handle.call(`/agentmemory/sessions?limit=${v.limit}`, { method: "GET" }), true);
2567
+ case "memory_sessions": return textResponse(await handle.call(`/agentmemory/sessions?${new URLSearchParams(v.sessionQuery)}`, { method: "GET" }), true);
1864
2568
  case "memory_governance_delete": return textResponse(await handle.call("/agentmemory/governance/memories", {
1865
2569
  method: "DELETE",
1866
2570
  body: JSON.stringify({
@@ -1869,15 +2573,22 @@ async function handleProxy(v, handle) {
1869
2573
  })
1870
2574
  }));
1871
2575
  case "memory_export": try {
1872
- return textResponse(await handle.call("/agentmemory/export", { method: "GET" }), true);
2576
+ return textResponse(await handle.call(`/agentmemory/export${v.exportQuery ? `?${v.exportQuery}` : ""}`, { method: "GET" }), true);
1873
2577
  } catch (err) {
1874
- if (err instanceof ProxyCallError && err.body != null && typeof err.body === "object" && err.body.oversized === true) return textResponse(err.body, true);
2578
+ if (err instanceof ProxyCallError && err.status === 413 && err.body != null && typeof err.body === "object" && err.body.oversized === true) return textResponse(err.body, true);
1875
2579
  throw err;
1876
2580
  }
1877
2581
  case "memory_audit": return textResponse(await handle.call(`/agentmemory/audit?limit=${v.limit}`, { method: "GET" }), true);
1878
2582
  default: throw new Error(`Unknown tool: ${v.tool}`);
1879
2583
  }
1880
2584
  }
2585
+ function localFallbackNotice(persisted) {
2586
+ 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";
2587
+ return {
2588
+ storage: "local",
2589
+ warning: `agentmemory server at ${displayAgentmemoryUrl()} did not confirm this call, so it ran against ${store}.`
2590
+ };
2591
+ }
1881
2592
  async function handleLocal(v, kvInstance) {
1882
2593
  switch (v.tool) {
1883
2594
  case "memory_save": {
@@ -1895,34 +2606,98 @@ async function handleLocal(v, kvInstance) {
1895
2606
  strength: 7,
1896
2607
  version: 1,
1897
2608
  isLatest: true,
1898
- sessionIds: []
2609
+ sessionIds: [],
2610
+ ...v.project !== void 0 && { project: v.project },
2611
+ ...(v.agentId ?? getAgentId()) !== void 0 && { agentId: v.agentId ?? getAgentId() }
2612
+ });
2613
+ return textResponse({
2614
+ saved: id,
2615
+ ...localFallbackNotice(kvInstance.persist())
1899
2616
  });
1900
- kvInstance.persist();
1901
- return textResponse({ saved: id });
1902
2617
  }
1903
2618
  case "memory_recall":
1904
2619
  case "memory_smart_search": {
2620
+ const isolated = isAgentScopeIsolated();
2621
+ const agentId = v.agentId === "*" ? void 0 : v.agentId ?? (isolated ? getAgentId() : void 0);
2622
+ if (isolated && v.agentId !== "*" && !agentId) throw new Error("AGENTMEMORY_AGENT_SCOPE=isolated requires an agentId; pass '*' to read across agents");
1905
2623
  const query = (v.query || "").toLowerCase();
1906
2624
  const limit = v.limit ?? DEFAULT_LIMIT;
2625
+ const all = v.targetLayer === "observation" ? [] : await kvInstance.list("mem:memories");
2626
+ const sessions = v.project || v.cwd ? await kvInstance.list("mem:sessions") : [];
2627
+ const sessionsById = new Map(sessions.map((session) => [session.id, session]));
2628
+ const scoped = all.filter((memory) => {
2629
+ if (memory.isLatest === false || agentId && memory.agentId !== agentId) return false;
2630
+ const linkedSessions = (memory.sessionIds ?? []).map((id) => sessionsById.get(id));
2631
+ if (v.project && (memory.project ? memory.project !== v.project : !linkedSessions.some((session) => session?.project === v.project))) return false;
2632
+ if (v.cwd && !linkedSessions.some((session) => session?.cwd === v.cwd)) return false;
2633
+ return true;
2634
+ });
2635
+ if (v.tool === "memory_smart_search" && v.expandIds?.length) {
2636
+ const ids = v.expandIds.map((entry) => typeof entry === "string" ? entry : entry.obsId);
2637
+ const byId = new Map(scoped.map((memory) => [memory.id, memory]));
2638
+ const eligible = ids.filter((id) => byId.has(id));
2639
+ return textResponse({
2640
+ mode: "expanded",
2641
+ results: eligible.slice(0, 20).map((id) => {
2642
+ const observation = memoryToObservation(byId.get(id));
2643
+ return {
2644
+ obsId: id,
2645
+ sessionId: observation.sessionId,
2646
+ observation,
2647
+ layer: "memory"
2648
+ };
2649
+ }),
2650
+ truncated: eligible.length > 20
2651
+ }, true);
2652
+ }
2653
+ const results = scoped.filter((memory) => {
2654
+ const text = [
2655
+ memory.title,
2656
+ memory.content,
2657
+ ...memory.files ?? [],
2658
+ ...memory.concepts ?? [],
2659
+ ...memory.sessionIds ?? [],
2660
+ memory.id
2661
+ ].join(" ").toLowerCase();
2662
+ return query.split(/\s+/).every((word) => text.includes(word));
2663
+ }).slice(0, limit);
2664
+ if (v.tool === "memory_recall") return textResponse(buildRecallResponse(results.map((memory) => {
2665
+ const observation = memoryToObservation(memory);
2666
+ return {
2667
+ sessionId: observation.sessionId,
2668
+ observation,
2669
+ score: 1,
2670
+ layer: "memory"
2671
+ };
2672
+ }), v.format ?? "full", v.tokenBudget), true);
1907
2673
  return textResponse({
1908
2674
  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)
2675
+ results: results.map((memory) => ({
2676
+ ...memory,
2677
+ type: "decision",
2678
+ memoryType: memory.type,
2679
+ obsId: memory.id,
2680
+ sessionId: memory.sessionIds?.[0] ?? "memory",
2681
+ layer: "memory"
2682
+ }))
1920
2683
  }, true);
1921
2684
  }
1922
2685
  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);
2686
+ const query = v.sessionQuery;
2687
+ const agentId = query.agentId === "*" ? void 0 : query.agentId ?? (isAgentScopeIsolated() ? getAgentId() : void 0);
2688
+ 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);
2689
+ const key = (session) => session.startedAt || "";
2690
+ const { page, nextCursor } = pageAfterCursor(sortByKeyDesc(sessions, key, (session) => session.id), key, (session) => session.id, query.cursor, Number(query.limit));
2691
+ return textResponse({
2692
+ sessions: await Promise.all(page.map(async (session) => {
2693
+ const summary = await kvInstance.get("mem:summaries", session.id);
2694
+ return summary ? {
2695
+ ...session,
2696
+ summary
2697
+ } : session;
2698
+ })),
2699
+ nextCursor
2700
+ }, true);
1926
2701
  }
1927
2702
  case "memory_governance_delete": {
1928
2703
  let deleted = 0;
@@ -1930,11 +2705,12 @@ async function handleLocal(v, kvInstance) {
1930
2705
  await kvInstance.delete("mem:memories", id);
1931
2706
  deleted++;
1932
2707
  }
1933
- kvInstance.persist();
2708
+ const persisted = kvInstance.persist();
1934
2709
  return textResponse({
1935
2710
  deleted,
1936
2711
  requested: (v.memoryIds || []).length,
1937
- reason: v.reason
2712
+ reason: v.reason,
2713
+ ...localFallbackNotice(persisted)
1938
2714
  });
1939
2715
  }
1940
2716
  case "memory_export": return textResponse({
@@ -1974,6 +2750,10 @@ async function handleToolCall(toolName, args, kvInstance = kv) {
1974
2750
  if (handle.mode === "proxy") try {
1975
2751
  return await handleProxy(validated, handle);
1976
2752
  } catch (err) {
2753
+ if (toolName === "memory_sessions" || isAuthenticationError(err) || isProxyRequired()) {
2754
+ invalidateHandle();
2755
+ throw err;
2756
+ }
1977
2757
  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
2758
  invalidateHandle();
1979
2759
  }
@@ -1994,10 +2774,12 @@ async function handleToolsList() {
1994
2774
  if (debug) process.stderr.write(`[@agentmemory/mcp] tools/list: returning ${remote.tools.length} tools from server\n`);
1995
2775
  return { tools: remote.tools };
1996
2776
  }
2777
+ if (isProxyRequired()) throw new Error("AgentMemory returned an invalid tool inventory");
1997
2778
  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
2779
  } 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
2780
  invalidateHandle();
2781
+ if (isAuthenticationError(err) || isProxyRequired()) throw err;
2782
+ process.stderr.write(`[@agentmemory/mcp] tools/list proxy failed: ${err instanceof Error ? err.message : String(err)}; falling back to local list\n`);
2001
2783
  }
2002
2784
  const fallback = getAllTools().filter((t) => IMPLEMENTED_TOOLS.has(t.name));
2003
2785
  if (debug) process.stderr.write(`[@agentmemory/mcp] tools/list: returning ${fallback.length} local fallback tools (${fallback.map((t) => t.name).join(",")})\n`);
@@ -2036,6 +2818,7 @@ const transport = createStdioTransport(async (method, params) => {
2036
2818
  default: throw new Error(`Unknown method: ${method}`);
2037
2819
  }
2038
2820
  });
2821
+ installCrashHandlers({ persist: () => kv.persist() });
2039
2822
  process.stderr.write(`[@agentmemory/mcp] Standalone MCP server v${SERVER_INFO.version} starting...\n`);
2040
2823
  transport.start();
2041
2824
  process.on("SIGINT", () => {