@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
@@ -1,373 +1,22 @@
1
- import { o as generateId, r as KV, t as withKeyedLock } from "./keyed-mutex-DchXsyfP.mjs";
2
- import { chmodSync, closeSync, existsSync, linkSync, mkdirSync, openSync, readFileSync, rmSync, unlinkSync, writeSync } from "node:fs";
3
- import { basename, dirname, isAbsolute, join, resolve } from "node:path";
1
+ import { a as KV, r as withKeyedLock, s as generateId } from "./keyed-mutex-DCUh7PG-.mjs";
2
+ import { chmodSync, closeSync, existsSync, linkSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeSync } from "node:fs";
3
+ import { join } from "node:path";
4
4
  import { homedir } from "node:os";
5
5
  import pc from "picocolors";
6
6
  import { randomBytes } from "node:crypto";
7
7
  import { readFile, stat } from "node:fs/promises";
8
- //#region src/cli/engine-config.ts
9
- const SEEDED_BUILTIN_WORKERS = [
10
- "http",
11
- "iii-http",
12
- "state",
13
- "iii-state",
14
- "queue",
15
- "iii-queue",
16
- "pubsub",
17
- "iii-pubsub",
18
- "cron",
19
- "iii-cron",
20
- "iii-stream",
21
- "iii-observability",
22
- "iii-worker-manager"
23
- ];
24
- function configuredPersistDir(renderedConfig) {
25
- const lines = renderedConfig.split("\n");
26
- const block = workerBlock(lines, "configuration");
27
- if (!block) return null;
28
- for (let i = block.start + 1; i < block.end; i++) {
29
- const match = lines[i].trim().match(/^directory:\s*(.+?)\s*$/);
30
- if (match) return match[1].replace(/^(['"])(.*)\1$/, "$2");
31
- }
32
- return null;
33
- }
34
- const ENGINE_DEFAULT_SAVE_INTERVAL_MS = 5e3;
35
- const ENGINE_FLUSH_MARGIN_MS = 1500;
36
- function engineFlushWaitMs(stateBackend, configTexts) {
37
- if (stateBackend === "redis") return 0;
38
- return engineSaveIntervalMs(configTexts) + ENGINE_FLUSH_MARGIN_MS;
39
- }
40
- function captureDurableAfterMs(stateBackend, configTexts) {
41
- if (stateBackend === "redis") return ENGINE_FLUSH_MARGIN_MS;
42
- return engineSaveIntervalMs(configTexts) + ENGINE_FLUSH_MARGIN_MS;
43
- }
44
- function engineSaveIntervalMs(configTexts) {
45
- const intervals = [];
46
- for (const text of configTexts) {
47
- const explicit = [...text.matchAll(/save_interval_ms:\s*(\d+)/g)].map((m) => parseInt(m[1], 10));
48
- intervals.push(...explicit);
49
- if ((text.match(/store_method:\s*file_based/g)?.length ?? 0) > explicit.length) intervals.push(ENGINE_DEFAULT_SAVE_INTERVAL_MS);
50
- }
51
- return intervals.length > 0 ? Math.max(...intervals) : ENGINE_DEFAULT_SAVE_INTERVAL_MS;
52
- }
53
- function engineStateConfigPaths(engineCwd, runtimePath) {
54
- return [...persistedBuiltinConfigDirs(engineCwd, runtimePath).map((dir) => join(dir, "iii-state.yaml")), runtimePath];
55
- }
56
- function persistedBuiltinConfigDirs(engineCwd, configPath, renderedConfig) {
57
- const dirs = [
58
- join(engineCwd, "config"),
59
- join(dirname(configPath), "config"),
60
- join(engineCwd, "data", "configuration")
61
- ];
62
- const custom = renderedConfig ? configuredPersistDir(renderedConfig) : null;
63
- if (custom) dirs.unshift(resolve(engineCwd, custom));
64
- return [...new Set(dirs)];
65
- }
66
- function persistedBuiltinConfigPaths(engineCwd, configPath, renderedConfig) {
67
- return persistedBuiltinConfigDirs(engineCwd, configPath, renderedConfig).flatMap((dir) => SEEDED_BUILTIN_WORKERS.map((id) => join(dir, `${id}.yaml`)));
68
- }
69
- function isPersistedBuiltinEntry(content, id) {
70
- return content.split("\n").find((line) => line.trim() !== "")?.trim() === `id: ${id}`;
71
- }
72
- function clearPersistedBuiltinConfig(engineCwd, configPath, renderedConfig) {
73
- const cleared = [];
74
- for (const path of persistedBuiltinConfigPaths(engineCwd, configPath, renderedConfig)) try {
75
- if (!isPersistedBuiltinEntry(readFileSync(path, "utf8"), basename(path, ".yaml"))) continue;
76
- rmSync(path);
77
- cleared.push(path);
78
- } catch (err) {
79
- if (err.code === "ENOENT") continue;
80
- throw new Error(`could not remove persisted engine config ${path}: ${String(err)}`);
81
- }
82
- return cleared;
83
- }
84
- function yamlSingleQuote(value) {
85
- return `'${value.replace(/'/g, "''")}'`;
86
- }
87
- function workerBlock(lines, name) {
88
- const marker = `- name: ${name}`;
89
- const start = lines.findIndex((line) => line.trim() === marker);
90
- if (start === -1) return null;
91
- const indent = lines[start].match(/^\s*/)?.[0] ?? "";
92
- let end = lines.length;
93
- for (let i = start + 1; i < lines.length; i++) {
94
- const line = lines[i];
95
- if (line.startsWith(indent) && line.trim().startsWith("- name: ")) {
96
- end = i;
97
- break;
98
- }
99
- }
100
- return {
101
- start,
102
- end,
103
- indent
104
- };
105
- }
106
- function setWorkerPort(lines, name, port) {
107
- let block = workerBlock(lines, name);
108
- if (!block && name === "iii-worker-manager") {
109
- const workersIndex = lines.findIndex((line) => line.trim() === "workers:");
110
- if (workersIndex === -1) return;
111
- lines.splice(workersIndex + 1, 0, " - name: iii-worker-manager", " config:", ` port: ${port}`, " host: 127.0.0.1");
112
- return;
113
- }
114
- if (!block) return;
115
- const portIndex = lines.findIndex((line, index) => index > block.start && index < block.end && line.trim().startsWith("port:"));
116
- if (portIndex !== -1) {
117
- lines[portIndex] = `${lines[portIndex].match(/^\s*/)?.[0] ?? `${block.indent} `}port: ${port}`;
118
- return;
119
- }
120
- const configIndex = lines.findIndex((line, index) => index > block.start && index < block.end && line.trim() === "config:");
121
- if (configIndex !== -1) {
122
- const configIndent = lines[configIndex].match(/^\s*/)?.[0] ?? `${block.indent} `;
123
- lines.splice(configIndex + 1, 0, `${configIndent} port: ${port}`);
124
- }
125
- }
126
- function setFileStoreSaveInterval(lines, workerName, override) {
127
- const block = workerBlock(lines, workerName);
128
- if (!block) return;
129
- const methodIndex = lines.findIndex((line, index) => index > block.start && index < block.end && line.trim() === "store_method: file_based");
130
- if (methodIndex === -1) return;
131
- const indent = lines[methodIndex].match(/^\s*/)?.[0] ?? "";
132
- const intervalIndex = lines.findIndex((line, index) => index > block.start && index < block.end && line.trim().startsWith("save_interval_ms:"));
133
- if (intervalIndex !== -1) {
134
- if (override === void 0) return;
135
- lines[intervalIndex] = `${lines[intervalIndex].match(/^\s*/)?.[0] ?? indent}save_interval_ms: ${override}`;
136
- return;
137
- }
138
- lines.splice(methodIndex + 1, 0, `${indent}save_interval_ms: ${override ?? 2e3}`);
139
- }
140
- const REDIS_URL_ENV_REF = "${AGENTMEMORY_REDIS_URL}";
141
- const UNSAFE_REDIS_URL_CHARS = /['\u0000-\u001f\u007f]/;
142
- function replaceKvAdapterWithRedis(lines, workerName) {
143
- const block = workerBlock(lines, workerName);
144
- if (!block) throw new Error(`AGENTMEMORY_STATE_BACKEND=redis requires a "${workerName}" worker in the engine config, but none was found.`);
145
- const adapterIndex = lines.findIndex((line, index) => index > block.start && index < block.end && line.trim() === "adapter:");
146
- if (adapterIndex === -1) throw new Error(`AGENTMEMORY_STATE_BACKEND=redis requires an "adapter:" block under the "${workerName}" worker in the engine config, but none was found.`);
147
- const adapterIndent = lines[adapterIndex].match(/^\s*/)?.[0] ?? "";
148
- let end = block.end;
149
- for (let i = adapterIndex + 1; i < block.end; i++) {
150
- const line = lines[i];
151
- if (line.trim() === "") continue;
152
- if ((line.match(/^\s*/)?.[0] ?? "").length <= adapterIndent.length) {
153
- end = i;
154
- break;
155
- }
156
- }
157
- const childIndent = `${adapterIndent} `;
158
- const grandchildIndent = `${adapterIndent} `;
159
- lines.splice(adapterIndex + 1, end - (adapterIndex + 1), `${childIndent}name: redis`, `${childIndent}config:`, `${grandchildIndent}redis_url: ${yamlSingleQuote(REDIS_URL_ENV_REF)}`);
160
- }
161
- function setManagedCorsOrigins(lines, restPort, viewerPort) {
162
- const block = workerBlock(lines, "iii-http");
163
- if (!block) return;
164
- const originsIndex = lines.findIndex((line, index) => index > block.start && index < block.end && line.trim().startsWith("allowed_origins:"));
165
- if (originsIndex === -1) return;
166
- lines[originsIndex] = `${lines[originsIndex].match(/^\s*/)?.[0] ?? " "}allowed_origins: ["http://localhost:${restPort}", "http://localhost:${viewerPort}", "http://127.0.0.1:${restPort}", "http://127.0.0.1:${viewerPort}"]`;
167
- }
168
- function renderEngineConfig(template, options) {
169
- if (options.stateBackend?.kind === "redis" && !options.stateBackend.redisUrl) throw new Error("AGENTMEMORY_STATE_BACKEND=redis requires AGENTMEMORY_REDIS_URL to be set (e.g. redis://localhost:6379).");
170
- if (options.stateBackend?.kind === "redis" && UNSAFE_REDIS_URL_CHARS.test(options.stateBackend.redisUrl ?? "")) throw new Error("AGENTMEMORY_REDIS_URL contains a single quote or a control character, which breaks the engine config once the engine expands it. Percent-encode those characters in the URL (for example a single quote as %27).");
171
- const rendered = template.replace("file_path: ./data/state_store.db", `file_path: ${yamlSingleQuote(join(options.dataDir, "state_store.db"))}`).replace("file_path: ./data/stream_store", `file_path: ${yamlSingleQuote(join(options.dataDir, "stream_store"))}`);
172
- const usesRedis = options.stateBackend?.kind === "redis";
173
- const lines = rendered.split("\n");
174
- setFileStoreSaveInterval(lines, "iii-state", options.saveIntervalMs);
175
- setFileStoreSaveInterval(lines, "iii-stream", options.saveIntervalMs);
176
- if (options.ports) {
177
- setWorkerPort(lines, "iii-http", options.ports.restPort);
178
- setWorkerPort(lines, "iii-stream", options.ports.streamPort);
179
- setWorkerPort(lines, "iii-worker-manager", options.ports.enginePort);
180
- setManagedCorsOrigins(lines, options.ports.restPort, options.ports.viewerPort);
181
- }
182
- if (usesRedis) {
183
- replaceKvAdapterWithRedis(lines, "iii-state");
184
- replaceKvAdapterWithRedis(lines, "iii-stream");
185
- }
186
- return lines.join("\n");
187
- }
188
- //#endregion
189
- //#region src/cli/engine-launch.ts
190
- function agentmemoryHome(home) {
191
- return join(home, ".agentmemory");
192
- }
193
- function runtimeConfigPath(dataDir) {
194
- return join(dataDir, "iii-config.runtime.yaml");
195
- }
196
- function dockerProjectName(restPort) {
197
- return `agentmemory-${restPort}`;
198
- }
199
- function dockerComposeArgs(composeFile, projectName, command) {
200
- return [
201
- "compose",
202
- ...projectName ? ["-p", projectName] : [],
203
- "-f",
204
- composeFile,
205
- ...command
206
- ];
207
- }
208
- function isBundledConfig(configPath, packageDir) {
209
- const resolved = resolve(configPath);
210
- return resolved === resolve(join(packageDir, "iii-config.yaml")) || resolved === resolve(join(packageDir, "..", "iii-config.yaml"));
211
- }
212
- function resolveEngineCwd(configPath, invocationCwd, home, bundledConfig = false) {
213
- if (bundledConfig) return agentmemoryHome(home);
214
- return dirname(isAbsolute(configPath) ? configPath : resolve(invocationCwd, configPath));
215
- }
216
- function indentation(line) {
217
- return line.length - line.trimStart().length;
218
- }
219
- function yamlScalar(value) {
220
- const trimmed = value.trim();
221
- const first = trimmed[0];
222
- const last = trimmed.at(-1);
223
- if (first === "\"" && last === "\"" || first === "'" && last === "'") return trimmed.slice(1, -1);
224
- return trimmed;
225
- }
226
- function isAgentmemoryExecCommand(line, nodeBin, workerEntry) {
227
- const match = line.match(/^\s*-\s+(.+?)\s*$/);
228
- if (!match) return false;
229
- const command = yamlScalar(match[1]).replaceAll("\\", "/");
230
- return command === `${nodeBin} ${workerEntry}`.replaceAll("\\", "/") || /^(?:node|node\.exe)\s+\.\/dist\/index\.mjs$/.test(command) || /^(?:node|node\.exe)\s+dist\/index\.mjs$/.test(command);
231
- }
232
- function removeAgentmemoryExecCommand(raw, nodeBin, workerEntry) {
233
- const lines = raw.split("\n");
234
- const output = [];
235
- let index = 0;
236
- while (index < lines.length) {
237
- const line = lines[index];
238
- if (line.trim() !== "- name: iii-exec") {
239
- output.push(line);
240
- index++;
241
- continue;
242
- }
243
- const blockIndent = indentation(line);
244
- let blockEnd = index + 1;
245
- while (blockEnd < lines.length) {
246
- const candidate = lines[blockEnd];
247
- if (candidate.trim() !== "") {
248
- const candidateIndent = indentation(candidate);
249
- if (candidateIndent < blockIndent || candidateIndent === blockIndent && candidate.trim().startsWith("- name: ")) break;
250
- }
251
- blockEnd++;
252
- }
253
- const block = lines.slice(index, blockEnd);
254
- const execIndex = block.findIndex((candidate) => candidate.trim() === "exec:");
255
- if (execIndex === -1) {
256
- output.push(...block);
257
- index = blockEnd;
258
- continue;
259
- }
260
- const execIndent = indentation(block[execIndex]);
261
- let execEnd = execIndex + 1;
262
- while (execEnd < block.length) {
263
- const candidate = block[execEnd];
264
- if (candidate.trim() !== "" && indentation(candidate) <= execIndent) break;
265
- execEnd++;
266
- }
267
- const beforeExec = block.slice(0, execIndex + 1);
268
- const execLines = block.slice(execIndex + 1, execEnd);
269
- const afterExec = block.slice(execEnd);
270
- const remainingExecLines = execLines.filter((candidate) => !isAgentmemoryExecCommand(candidate, nodeBin, workerEntry));
271
- const removed = remainingExecLines.length !== execLines.length;
272
- const hasExecCommand = remainingExecLines.some((candidate) => /^\s*-\s+/.test(candidate) && indentation(candidate) > execIndent);
273
- if (!removed) output.push(...block);
274
- else if (hasExecCommand) output.push(...beforeExec, ...remainingExecLines, ...afterExec);
275
- index = blockEnd;
276
- }
277
- return output.join("\n");
278
- }
279
- function rewriteBundledConfig(raw, home, nodeBin, workerEntry, options) {
280
- return removeAgentmemoryExecCommand(renderEngineConfig(raw, {
281
- dataDir: options?.dataDir ?? join(agentmemoryHome(home), "data"),
282
- ...options?.ports ? { ports: options.ports } : {},
283
- ...options?.stateBackend ? { stateBackend: options.stateBackend } : {},
284
- ...options?.saveIntervalMs !== void 0 ? { saveIntervalMs: options.saveIntervalMs } : {}
285
- }), nodeBin, workerEntry);
286
- }
287
- function legacyDataMigrations(invocationCwd, home, resolvedDataDir = join(agentmemoryHome(home), "data")) {
288
- return [{
289
- from: join(invocationCwd, "data", "state_store.db"),
290
- to: join(resolvedDataDir, "state_store.db")
291
- }, {
292
- from: join(invocationCwd, "data", "stream_store"),
293
- to: join(resolvedDataDir, "stream_store")
294
- }];
295
- }
296
- function engineChildEnv(base, platform = process.platform) {
297
- const env = {
298
- ...base,
299
- III_TELEMETRY_ENABLED: base["III_TELEMETRY_ENABLED"] ?? "false"
300
- };
301
- if (platform === "linux" && !base.MALLOC_ARENA_MAX) env.MALLOC_ARENA_MAX = "2";
302
- return env;
303
- }
304
- function resolveLaunchRenderFailure(stateBackendKind, err) {
305
- if (stateBackendKind !== "redis") return { fatal: false };
306
- return {
307
- fatal: true,
308
- message: `Failed to render the Redis state backend into the engine config: ${err instanceof Error ? err.message : String(err)} Refusing to start the engine, since it would silently fall back to the file (or in-memory) store instead of Redis. Fix the config or unset AGENTMEMORY_STATE_BACKEND to use the default file store.`
309
- };
310
- }
311
- const CREDENTIAL_URL_PATTERN = /:\/\/[^@\s/]*@/g;
312
- function redactCredentialUrls(text) {
313
- return text.replace(CREDENTIAL_URL_PATTERN, "://***@");
314
- }
315
- //#endregion
316
- //#region src/logger.ts
317
- function fmt(level, msg, fields) {
318
- if (!fields || Object.keys(fields).length === 0) return `[agentmemory] ${level} ${msg}`;
319
- try {
320
- return `[agentmemory] ${level} ${msg} ${JSON.stringify(fields)}`;
321
- } catch {
322
- return `[agentmemory] ${level} ${msg}`;
323
- }
324
- }
325
- function emit(level, msg, fields) {
326
- try {
327
- process.stderr.write(fmt(level, msg, fields) + "\n");
328
- } catch {}
329
- }
330
- const logger = {
331
- info(msg, fields) {
332
- emit("info", msg, fields);
333
- },
334
- warn(msg, fields) {
335
- emit("warn", msg, fields);
336
- },
337
- error(msg, fields) {
338
- emit("error", msg, fields);
339
- }
340
- };
341
- let bootVerbose = process.env["AGENTMEMORY_VERBOSE"] === "1" || process.env["AGENTMEMORY_VERBOSE"] === "true";
342
- const bootBuffer = [];
343
- function setBootVerbose(enabled) {
344
- bootVerbose = enabled;
345
- }
346
- function bootLog(msg) {
347
- if (bootVerbose) {
348
- try {
349
- process.stderr.write(`[agentmemory] ${msg}\n`);
350
- } catch {}
351
- return;
352
- }
353
- if (bootBuffer.length < 500) bootBuffer.push(msg);
354
- }
355
- function bootWarn(msg) {
356
- try {
357
- process.stderr.write(`[agentmemory] warn ${msg}\n`);
358
- } catch {}
359
- }
360
- //#endregion
361
8
  //#region src/config.ts
9
+ const MAX_IMPORT_OBS_PER_SESSION = 5e3;
362
10
  function safeParseInt(value, fallback) {
363
11
  if (!value) return fallback;
364
12
  const parsed = parseInt(value, 10);
365
13
  return Number.isNaN(parsed) ? fallback : parsed;
366
14
  }
367
- const DATA_DIR = join(homedir(), ".agentmemory");
368
- const ENV_FILE = join(DATA_DIR, ".env");
15
+ const DATA_DIR = process.env["AGENTMEMORY_DATA_DIR"] || join(homedir(), ".agentmemory");
16
+ const ENV_FILE = process.env["AGENTMEMORY_ENV_FILE"] || join(homedir(), ".agentmemory", ".env");
369
17
  let warnPremiumModelShown = false;
370
18
  let providerNoticeShown = false;
19
+ let obsCapImportCeilingWarned = false;
371
20
  function writeProviderNoticeOnce(text) {
372
21
  if (providerNoticeShown) return;
373
22
  providerNoticeShown = true;
@@ -380,7 +29,10 @@ function loadEnvFile() {
380
29
  envFileCache = {};
381
30
  return envFileCache;
382
31
  }
383
- const content = readFileSync(ENV_FILE, "utf-8");
32
+ envFileCache = parseEnvContent(readFileSync(ENV_FILE, "utf-8"));
33
+ return envFileCache;
34
+ }
35
+ function parseEnvContent(content) {
384
36
  const vars = {};
385
37
  for (const line of content.split("\n")) {
386
38
  const trimmed = line.trim();
@@ -399,23 +51,33 @@ function loadEnvFile() {
399
51
  }
400
52
  vars[key] = val;
401
53
  }
402
- envFileCache = vars;
403
- return envFileCache;
54
+ return vars;
404
55
  }
405
56
  function hasRealValue(v) {
406
57
  return typeof v === "string" && v.trim().length > 0;
407
58
  }
408
59
  function hydrateProcessEnvFromFile() {
60
+ const beforeHydration = { ...process.env };
409
61
  for (const [k, v] of Object.entries(loadEnvFile())) if (process.env[k] === void 0) process.env[k] = v;
62
+ return beforeHydration;
63
+ }
64
+ function warnIfPremiumModel(env, envName, model) {
65
+ if (warnPremiumModelShown || !/sonnet|opus|gpt-5\.\d+-sol|gpt-4o(?!.*mini)|gpt-4-turbo/i.test(model) || env["AGENTMEMORY_SUPPRESS_COST_WARNING"] === "1" || env["AGENTMEMORY_SUPPRESS_COST_WARNING"] === "true") return;
66
+ warnPremiumModelShown = true;
67
+ process.stderr.write(`[agentmemory] ${envName}=${model} is in the premium tier. Background compression on this model can cost $5+/day under active use. Cheaper alternatives with comparable quality for memory compression: deepseek/deepseek-v4-flash-0731, deepseek/deepseek-v4-pro, qwen/qwen3-coder. See README "Cost-aware model selection" for the full table. Set AGENTMEMORY_SUPPRESS_COST_WARNING=1 to silence.\n`);
410
68
  }
411
69
  function detectProvider(env) {
412
70
  const maxTokens = parseInt(env["MAX_TOKENS"] || "4096", 10);
413
- if (hasRealValue(env["OPENAI_API_KEY"]) && env["OPENAI_API_KEY_FOR_LLM"] !== "false") return {
414
- provider: "openai",
415
- model: env["OPENAI_MODEL"] || "gpt-5.6-luna",
416
- maxTokens,
417
- baseURL: env["OPENAI_BASE_URL"]
418
- };
71
+ if (hasRealValue(env["OPENAI_API_KEY"]) && env["OPENAI_API_KEY_FOR_LLM"] !== "false") {
72
+ const model = env["OPENAI_MODEL"] || "gpt-5.6-luna";
73
+ warnIfPremiumModel(env, "OPENAI_MODEL", model);
74
+ return {
75
+ provider: "openai",
76
+ model,
77
+ maxTokens,
78
+ baseURL: env["OPENAI_BASE_URL"]
79
+ };
80
+ }
419
81
  if (hasRealValue(env["MINIMAX_API_KEY"])) return {
420
82
  provider: "minimax",
421
83
  model: env["MINIMAX_MODEL"] || "MiniMax-M3",
@@ -437,10 +99,7 @@ function detectProvider(env) {
437
99
  }
438
100
  if (hasRealValue(env["OPENROUTER_API_KEY"])) {
439
101
  const model = env["OPENROUTER_MODEL"] || "anthropic/claude-sonnet-5";
440
- if (!warnPremiumModelShown && /sonnet|opus|gpt-5\.\d+-sol|gpt-4o(?!.*mini)|gpt-4-turbo/i.test(model) && env["AGENTMEMORY_SUPPRESS_COST_WARNING"] !== "1" && env["AGENTMEMORY_SUPPRESS_COST_WARNING"] !== "true") {
441
- warnPremiumModelShown = true;
442
- process.stderr.write(`[agentmemory] OPENROUTER_MODEL=${model} is in the premium tier. Background compression on this model can cost $5+/day under active use. Cheaper alternatives with comparable quality for memory compression: deepseek/deepseek-v4-flash-0731, deepseek/deepseek-v4-pro, qwen/qwen3-coder. See README "Cost-aware model selection" for the full table. Set AGENTMEMORY_SUPPRESS_COST_WARNING=1 to silence.\n`);
443
- }
102
+ warnIfPremiumModel(env, "OPENROUTER_MODEL", model);
444
103
  return {
445
104
  provider: "openrouter",
446
105
  model,
@@ -466,16 +125,21 @@ function loadConfig() {
466
125
  const env = getMergedEnv();
467
126
  const provider = detectProvider(env);
468
127
  const restPort = parseInt(env["III_REST_PORT"] || "3111", 10) || 3111;
469
- const streamsPort = parseInt(env["III_STREAM_PORT"] || env["III_STREAMS_PORT"] || "", 10) || restPort + 1;
470
128
  const viewerPort = parseInt(env["III_VIEWER_PORT"] || "", 10) || restPort + 2;
129
+ const engineUrl = env["III_ENGINE_URL"] || env["III_URL"] || `ws://localhost:${parseInt(env["III_ENGINE_PORT"] || "", 10) || restPort + 46023}`;
130
+ const maxObservationsPerSession = safeParseInt(env["MAX_OBS_PER_SESSION"], 500);
131
+ if (!obsCapImportCeilingWarned && (maxObservationsPerSession === 0 || maxObservationsPerSession > 5e3)) {
132
+ obsCapImportCeilingWarned = true;
133
+ const capDesc = maxObservationsPerSession === 0 ? "uncapped (0)" : String(maxObservationsPerSession);
134
+ process.stderr.write(`[agentmemory] WARNING: MAX_OBS_PER_SESSION is ${capDesc}, above the ${MAX_IMPORT_OBS_PER_SESSION}-per-session import ceiling (MAX_IMPORT_OBS_PER_SESSION). Sessions past that ceiling make every mem::export -> mem::import restore fail wholesale. Keep MAX_OBS_PER_SESSION at or below ${MAX_IMPORT_OBS_PER_SESSION} if you rely on export/import backups.\n`);
135
+ }
471
136
  return {
472
- engineUrl: env["III_ENGINE_URL"] || `ws://localhost:${parseInt(env["III_ENGINE_PORT"] || "", 10) || restPort + 46023}`,
137
+ engineUrl,
473
138
  restPort,
474
- streamsPort,
475
139
  viewerPort,
476
140
  provider,
477
141
  tokenBudget: safeParseInt(env["TOKEN_BUDGET"], 2e3),
478
- maxObservationsPerSession: safeParseInt(env["MAX_OBS_PER_SESSION"], 500),
142
+ maxObservationsPerSession,
479
143
  compressionModel: provider.model,
480
144
  dataDir: DATA_DIR
481
145
  };
@@ -499,6 +163,11 @@ function getSessionSweepStaleHours() {
499
163
  const parsed = parseInt(raw.trim(), 10);
500
164
  return parsed > 0 ? parsed : 24;
501
165
  }
166
+ function getFinalizeIdleMs() {
167
+ const raw = getMergedEnv()["AGENTMEMORY_FINALIZE_IDLE_MS"];
168
+ if (!raw || !/^\d+$/.test(raw.trim())) return 12e4;
169
+ return parseInt(raw.trim(), 10);
170
+ }
502
171
  function isGraphCompactOnBootEnabled() {
503
172
  return getMergedEnv()["AGENTMEMORY_GRAPH_COMPACT_ON_BOOT"] !== "false";
504
173
  }
@@ -526,6 +195,16 @@ function detectLlmProviderKind(env = getMergedEnv()) {
526
195
  if (hasRealValue(env["ANTHROPIC_API_KEY"]) || hasRealValue(env["GEMINI_API_KEY"]) || hasRealValue(env["GOOGLE_API_KEY"]) || hasRealValue(env["OPENROUTER_API_KEY"]) || hasRealValue(env["MINIMAX_API_KEY"]) || hasRealValue(env["OPENAI_API_KEY"]) && env["OPENAI_API_KEY_FOR_LLM"] !== "false" || env["AGENTMEMORY_ALLOW_AGENT_SDK"] === "true") return "llm";
527
196
  return "noop";
528
197
  }
198
+ function describeLlmRoute(provider) {
199
+ if (provider.provider === "noop") return null;
200
+ const parts = [provider.provider, provider.model];
201
+ if (provider.baseURL) try {
202
+ parts.push(new URL(provider.baseURL).host);
203
+ } catch {
204
+ parts.push("custom base URL");
205
+ }
206
+ return parts.join(" · ");
207
+ }
529
208
  function loadEmbeddingConfig() {
530
209
  const env = getMergedEnv();
531
210
  let bm25Weight = parseFloat(env["BM25_WEIGHT"] || "0.4");
@@ -613,20 +292,6 @@ const FOLLOWUP_WINDOW_DEFAULT_SECONDS = 30;
613
292
  function getFollowupWindowSeconds() {
614
293
  return safeParseInt(getMergedEnv()["AGENTMEMORY_FOLLOWUP_WINDOW_SECONDS"], FOLLOWUP_WINDOW_DEFAULT_SECONDS);
615
294
  }
616
- const VIEWER_STREAM_MAX_DEFAULT = 500;
617
- const VIEWER_STREAM_MAX_FLOOR = 200;
618
- function parseExactInt(value, fallback) {
619
- if (!value) return fallback;
620
- const trimmed = value.trim();
621
- if (!/^-?\d+$/.test(trimmed)) return fallback;
622
- const parsed = Number(trimmed);
623
- return Number.isSafeInteger(parsed) ? parsed : fallback;
624
- }
625
- function getViewerStreamMax() {
626
- const parsed = parseExactInt(getMergedEnv()["AGENTMEMORY_VIEWER_STREAM_MAX"], VIEWER_STREAM_MAX_DEFAULT);
627
- if (parsed < 0) return VIEWER_STREAM_MAX_DEFAULT;
628
- return Math.max(parsed, VIEWER_STREAM_MAX_FLOOR);
629
- }
630
295
  function isConsolidationEnabled() {
631
296
  const env = getMergedEnv();
632
297
  const explicit = env["CONSOLIDATION_ENABLED"];
@@ -659,9 +324,13 @@ function getIndexSaveIntervalMs() {
659
324
  const raw = safeParseInt(getMergedEnv()["AGENTMEMORY_INDEX_SAVE_INTERVAL_MS"], INDEX_SAVE_INTERVAL_DEFAULT_MS);
660
325
  return raw > 0 ? raw : INDEX_SAVE_INTERVAL_DEFAULT_MS;
661
326
  }
327
+ const STATE_SAVE_INTERVAL_DEFAULT_MS = 2e3;
662
328
  function getStateSaveIntervalMs() {
663
- const raw = safeParseInt(getMergedEnv()["AGENTMEMORY_STATE_SAVE_INTERVAL_MS"], 0);
664
- return raw > 0 ? raw : void 0;
329
+ const value = getMergedEnv()["AGENTMEMORY_STATE_SAVE_INTERVAL_MS"];
330
+ if (value === void 0 || value.trim() === "") return STATE_SAVE_INTERVAL_DEFAULT_MS;
331
+ if (!/^\d+$/.test(value.trim())) return STATE_SAVE_INTERVAL_DEFAULT_MS;
332
+ const raw = Number(value);
333
+ return Number.isSafeInteger(raw) && raw >= 100 && raw <= 36e5 ? raw : STATE_SAVE_INTERVAL_DEFAULT_MS;
665
334
  }
666
335
  function getVectorBucketSize() {
667
336
  const raw = safeParseInt(getMergedEnv()["AGENTMEMORY_VECTOR_BUCKET_SIZE"], 500);
@@ -698,15 +367,105 @@ function loadFallbackConfig() {
698
367
  }) };
699
368
  }
700
369
  //#endregion
370
+ //#region src/cli/engine-launch.ts
371
+ function runtimeConfigPath(dataDir) {
372
+ return join(dataDir, "iii-config.runtime.yaml");
373
+ }
374
+ const CREDENTIAL_URL_PATTERN = /:\/\/[^@\s/]*@/g;
375
+ function redactCredentialUrls(text) {
376
+ return text.replace(CREDENTIAL_URL_PATTERN, "://***@");
377
+ }
378
+ //#endregion
379
+ //#region src/cli/engine-config.ts
380
+ const ENGINE_DEFAULT_SAVE_INTERVAL_MS = 5e3;
381
+ const ENGINE_FLUSH_MARGIN_MS = 1500;
382
+ function engineFlushWaitMs(stateBackend, configTexts) {
383
+ if (stateBackend === "redis") return 0;
384
+ return engineSaveIntervalMs(configTexts) + ENGINE_FLUSH_MARGIN_MS;
385
+ }
386
+ function captureDurableAfterMs(stateBackend, configTexts) {
387
+ if (stateBackend === "redis") return ENGINE_FLUSH_MARGIN_MS;
388
+ return engineSaveIntervalMs(configTexts) + ENGINE_FLUSH_MARGIN_MS;
389
+ }
390
+ function engineSaveIntervalMs(configTexts, env = process.env) {
391
+ const intervals = [];
392
+ for (const text of configTexts) {
393
+ const explicit = [];
394
+ for (const match of text.matchAll(/save_interval_ms:\s*["']?(\d+|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-(\d+))?\})/g)) {
395
+ const raw = match[2] ? env[match[2]] || match[3] : match[1];
396
+ if (raw && /^\d+$/.test(raw) && Number.isSafeInteger(Number(raw))) explicit.push(Number(raw));
397
+ }
398
+ intervals.push(...explicit);
399
+ if ((text.match(/store_method:\s*file_based/g)?.length ?? 0) > explicit.length) intervals.push(ENGINE_DEFAULT_SAVE_INTERVAL_MS);
400
+ }
401
+ return intervals.length > 0 ? Math.max(...intervals) : ENGINE_DEFAULT_SAVE_INTERVAL_MS;
402
+ }
403
+ function engineStateConfigPaths(engineCwd, runtimePath) {
404
+ return [...new Set([
405
+ join(engineCwd, "compose", "worker-compose.yaml"),
406
+ join(engineCwd, "compose", "config", "state.yaml"),
407
+ join(engineCwd, "worker-compose.runtime.yaml"),
408
+ join(engineCwd, "config", "state.yaml"),
409
+ runtimePath
410
+ ])];
411
+ }
412
+ //#endregion
413
+ //#region src/logger.ts
414
+ function fmt(level, msg, fields) {
415
+ if (!fields || Object.keys(fields).length === 0) return `[agentmemory] ${level} ${msg}`;
416
+ try {
417
+ return `[agentmemory] ${level} ${msg} ${JSON.stringify(fields)}`;
418
+ } catch {
419
+ return `[agentmemory] ${level} ${msg}`;
420
+ }
421
+ }
422
+ function emit(level, msg, fields) {
423
+ try {
424
+ const line = fmt(level, msg, fields) + "\n";
425
+ if (level === "error" || process.env["AGENTMEMORY_MCP_STDIO__"] === "1") process.stderr.write(line);
426
+ else process.stdout.write(line);
427
+ } catch {}
428
+ }
429
+ const logger = {
430
+ info(msg, fields) {
431
+ emit("info", msg, fields);
432
+ },
433
+ warn(msg, fields) {
434
+ emit("warn", msg, fields);
435
+ },
436
+ error(msg, fields) {
437
+ emit("error", msg, fields);
438
+ }
439
+ };
440
+ let bootVerbose = process.env["AGENTMEMORY_VERBOSE"] === "1" || process.env["AGENTMEMORY_VERBOSE"] === "true";
441
+ const bootBuffer = [];
442
+ function setBootVerbose(enabled) {
443
+ bootVerbose = enabled;
444
+ }
445
+ function bootLog(msg) {
446
+ if (bootVerbose) {
447
+ try {
448
+ process.stderr.write(`[agentmemory] ${msg}\n`);
449
+ } catch {}
450
+ return;
451
+ }
452
+ if (bootBuffer.length < 500) bootBuffer.push(msg);
453
+ }
454
+ function bootWarn(msg) {
455
+ try {
456
+ process.stderr.write(`[agentmemory] warn ${msg}\n`);
457
+ } catch {}
458
+ }
459
+ //#endregion
701
460
  //#region src/version.ts
702
- const VERSION = "0.9.30";
703
- const III_PINNED_VERSION = "0.22.1";
461
+ const VERSION = "0.9.31";
462
+ const III_PINNED_VERSION = "0.25.0";
704
463
  //#endregion
705
464
  //#region src/mcp/tools-registry.ts
706
465
  const CORE_TOOLS = [
707
466
  {
708
467
  name: "memory_recall",
709
- 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.",
468
+ 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.",
710
469
  inputSchema: {
711
470
  type: "object",
712
471
  properties: {
@@ -724,7 +483,28 @@ const CORE_TOOLS = [
724
483
  },
725
484
  token_budget: {
726
485
  type: "number",
727
- description: "Optional token budget to trim returned results"
486
+ description: "Optional estimated content token budget; response includes truncation and recovery metadata"
487
+ },
488
+ targetLayer: {
489
+ type: "string",
490
+ enum: [
491
+ "all",
492
+ "memory",
493
+ "observation"
494
+ ],
495
+ description: "Search all indexed layers (default), durable memories, or raw observations before ranking"
496
+ },
497
+ project: {
498
+ type: "string",
499
+ description: "Filter by project path"
500
+ },
501
+ cwd: {
502
+ type: "string",
503
+ description: "Filter by session working directory"
504
+ },
505
+ agentId: {
506
+ type: "string",
507
+ description: "Filter by owning agent; '*' reads across agents"
728
508
  }
729
509
  },
730
510
  required: ["query"]
@@ -813,15 +593,32 @@ const CORE_TOOLS = [
813
593
  },
814
594
  {
815
595
  name: "memory_sessions",
816
- description: "List recent sessions with their status and observation counts.",
596
+ description: "List recent sessions with status, observation counts, summaries and a continuation cursor. Filters apply before pagination; retain them when requesting the next page.",
817
597
  inputSchema: {
818
598
  type: "object",
819
- properties: {}
599
+ properties: {
600
+ project: {
601
+ type: "string",
602
+ description: "Exact project identifier used when sessions were started"
603
+ },
604
+ agentId: {
605
+ type: "string",
606
+ description: "Filter by owning agent; '*' reads across agents"
607
+ },
608
+ limit: {
609
+ type: "integer",
610
+ description: "Page size (default 20, max 100)"
611
+ },
612
+ cursor: {
613
+ type: "string",
614
+ description: "nextCursor from the previous page; omit for the first page"
615
+ }
616
+ }
820
617
  }
821
618
  },
822
619
  {
823
620
  name: "memory_smart_search",
824
- description: "Hybrid semantic+keyword search with progressive disclosure.",
621
+ description: "Hybrid semantic+keyword search with progressive disclosure. Pass query to search, or expandIds to recover full results.",
825
622
  inputSchema: {
826
623
  type: "object",
827
624
  properties: {
@@ -831,14 +628,34 @@ const CORE_TOOLS = [
831
628
  },
832
629
  expandIds: {
833
630
  type: "string",
834
- description: "Comma-separated observation IDs to expand"
631
+ description: "Comma-separated memory or observation IDs to expand; query is optional when provided"
835
632
  },
836
633
  limit: {
837
634
  type: "number",
838
635
  description: "Max results (default 10)"
636
+ },
637
+ targetLayer: {
638
+ type: "string",
639
+ enum: [
640
+ "all",
641
+ "memory",
642
+ "observation"
643
+ ],
644
+ description: "Search all indexed layers (default), durable memories, or raw observations before ranking"
645
+ },
646
+ project: {
647
+ type: "string",
648
+ description: "Filter by project path"
649
+ },
650
+ agentId: {
651
+ type: "string",
652
+ description: "Filter by owning agent; '*' reads across agents"
653
+ },
654
+ includeLessons: {
655
+ type: "boolean",
656
+ description: "Include lesson matches when targetLayer is all (default true)"
839
657
  }
840
- },
841
- required: ["query"]
658
+ }
842
659
  }
843
660
  },
844
661
  {
@@ -916,10 +733,31 @@ const CORE_TOOLS = [
916
733
  },
917
734
  {
918
735
  name: "memory_export",
919
- description: "Export all memory data as JSON.",
736
+ description: "Export memory data as JSON. Past the transport size limit the export is refused, so use the paging arguments on a large store.",
920
737
  inputSchema: {
921
738
  type: "object",
922
- properties: {}
739
+ properties: {
740
+ maxSessions: {
741
+ type: "number",
742
+ description: "Sessions per page (with their observations)"
743
+ },
744
+ offset: {
745
+ type: "number",
746
+ description: "Session offset"
747
+ },
748
+ collectionLimit: {
749
+ type: "number",
750
+ 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"
751
+ },
752
+ collectionOffset: {
753
+ type: "number",
754
+ description: "Row offset for the top-level collections"
755
+ },
756
+ collections: {
757
+ type: "string",
758
+ 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."
759
+ }
760
+ }
923
761
  }
924
762
  },
925
763
  {
@@ -1925,7 +1763,7 @@ async function auditMigrationDeleteDelayMs() {
1925
1763
  const dataDir = getEnvVar("AGENTMEMORY_DATA_DIR");
1926
1764
  if (!dataDir) return ENGINE_DEFAULT_SAVE_INTERVAL_MS * AUDIT_MIGRATION_DELETE_WAIT_INTERVALS;
1927
1765
  const configTexts = [];
1928
- for (const path of engineStateConfigPaths(join(homedir(), ".agentmemory"), runtimeConfigPath(dataDir))) try {
1766
+ for (const path of engineStateConfigPaths(dataDir, runtimeConfigPath(dataDir))) try {
1929
1767
  configTexts.push(await readFile(path, "utf-8"));
1930
1768
  } catch {}
1931
1769
  return engineSaveIntervalMs(configTexts) * AUDIT_MIGRATION_DELETE_WAIT_INTERVALS;
@@ -2224,10 +2062,225 @@ async function runAuditRetentionSweep(kv, retentionMonths) {
2224
2062
  };
2225
2063
  }
2226
2064
  //#endregion
2065
+ //#region src/state/search-layer.ts
2066
+ function isSearchLayer(value) {
2067
+ return value === "all" || value === "memory" || value === "observation";
2068
+ }
2069
+ function isSearchResultLayer(value) {
2070
+ return value === "memory" || value === "observation" || value === "lesson" || value === "insight";
2071
+ }
2072
+ function getSearchResultLayer(obsId, sessionId) {
2073
+ if (obsId.startsWith("mem_")) return "memory";
2074
+ if (sessionId === "lesson" || obsId.startsWith("lsn_")) return "lesson";
2075
+ if (sessionId === "insight" || obsId.startsWith("ins_")) return "insight";
2076
+ return "observation";
2077
+ }
2078
+ function matchesSearchLayer(obsId, sessionId, targetLayer = "all", layer) {
2079
+ return targetLayer === "all" || (layer ?? getSearchResultLayer(obsId, sessionId)) === targetLayer;
2080
+ }
2081
+ //#endregion
2082
+ //#region src/state/memory-utils.ts
2083
+ function memoryToObservation(memory) {
2084
+ return {
2085
+ id: memory.id,
2086
+ sessionId: memory.sessionIds?.[0] ?? "memory",
2087
+ timestamp: memory.createdAt,
2088
+ type: "decision",
2089
+ title: memory.title,
2090
+ facts: [memory.content],
2091
+ narrative: memory.content,
2092
+ concepts: memory.concepts,
2093
+ files: memory.files,
2094
+ importance: memory.strength,
2095
+ ...memory.agentId ? { agentId: memory.agentId } : {}
2096
+ };
2097
+ }
2098
+ function lessonToObservation(l) {
2099
+ return {
2100
+ id: l.id,
2101
+ sessionId: "lesson",
2102
+ timestamp: l.createdAt,
2103
+ type: "decision",
2104
+ title: l.content.slice(0, 120),
2105
+ facts: [l.content],
2106
+ narrative: l.context || "",
2107
+ concepts: l.tags,
2108
+ files: [],
2109
+ importance: l.confidence
2110
+ };
2111
+ }
2112
+ //#endregion
2113
+ //#region src/functions/recall-response.ts
2114
+ function estimateTokens(value) {
2115
+ return Math.max(1, Math.ceil(JSON.stringify(value).length / 3));
2116
+ }
2117
+ function prefix(text, length) {
2118
+ let end = Math.min(length, text.length);
2119
+ if (end > 0 && end < text.length && /[\uD800-\uDBFF]/.test(text[end - 1])) end--;
2120
+ return text.slice(0, end);
2121
+ }
2122
+ function fitText(text, budget, makeResult) {
2123
+ let low = 0;
2124
+ let high = text.length;
2125
+ while (low < high) {
2126
+ const middle = Math.ceil((low + high) / 2);
2127
+ if (estimateTokens(makeResult(prefix(text, middle))) <= budget) low = middle;
2128
+ else high = middle - 1;
2129
+ }
2130
+ return makeResult(prefix(text, low));
2131
+ }
2132
+ function formatResult(result, format) {
2133
+ if (format === "full") return result;
2134
+ const observation = result.observation;
2135
+ const compact = {
2136
+ obsId: observation.id,
2137
+ sessionId: result.sessionId,
2138
+ title: observation.title,
2139
+ type: observation.type,
2140
+ score: result.score,
2141
+ timestamp: observation.timestamp,
2142
+ ...result.layer !== void 0 && { layer: result.layer }
2143
+ };
2144
+ if (format === "compact") return compact;
2145
+ const { type: _type, ...narrative } = compact;
2146
+ return {
2147
+ ...narrative,
2148
+ narrative: observation.narrative
2149
+ };
2150
+ }
2151
+ function clipResult(result, format, budget) {
2152
+ const observation = result.observation;
2153
+ const layer = result.layer !== void 0 ? { layer: result.layer } : {};
2154
+ if (format === "compact") {
2155
+ const base = {
2156
+ obsId: observation.id,
2157
+ sessionId: result.sessionId,
2158
+ title: "",
2159
+ type: observation.type,
2160
+ score: result.score,
2161
+ timestamp: observation.timestamp,
2162
+ ...layer,
2163
+ content_truncated: true
2164
+ };
2165
+ const minimum = estimateTokens(base);
2166
+ if (minimum > budget) return { minimum };
2167
+ return {
2168
+ result: fitText(observation.title, budget, (title) => ({
2169
+ ...base,
2170
+ title
2171
+ })),
2172
+ minimum
2173
+ };
2174
+ }
2175
+ const makeResult = (title, narrative) => {
2176
+ if (format === "narrative") return {
2177
+ obsId: observation.id,
2178
+ sessionId: result.sessionId,
2179
+ title,
2180
+ narrative,
2181
+ score: result.score,
2182
+ timestamp: observation.timestamp,
2183
+ ...layer,
2184
+ content_truncated: true
2185
+ };
2186
+ return {
2187
+ observation: {
2188
+ id: observation.id,
2189
+ sessionId: observation.sessionId,
2190
+ timestamp: observation.timestamp,
2191
+ type: observation.type,
2192
+ title,
2193
+ facts: [],
2194
+ narrative,
2195
+ concepts: [],
2196
+ files: [],
2197
+ importance: observation.importance,
2198
+ ...observation.confidence !== void 0 && { confidence: observation.confidence },
2199
+ ...observation.agentId !== void 0 && { agentId: observation.agentId },
2200
+ ...observation.origin && { origin: {
2201
+ channel: observation.origin.channel,
2202
+ capturedAt: observation.origin.capturedAt
2203
+ } }
2204
+ },
2205
+ score: result.score,
2206
+ sessionId: result.sessionId,
2207
+ ...layer,
2208
+ content_truncated: true
2209
+ };
2210
+ };
2211
+ const minimum = estimateTokens(makeResult("", ""));
2212
+ if (minimum > budget) return { minimum };
2213
+ const titleResult = fitText(prefix(observation.title, 120), budget, (title) => makeResult(title, ""));
2214
+ const title = "observation" in titleResult ? titleResult.observation.title : titleResult.title;
2215
+ return {
2216
+ result: fitText(observation.narrative || observation.facts.join("\n"), budget, (text) => makeResult(title, text)),
2217
+ minimum
2218
+ };
2219
+ }
2220
+ function buildRecallResponse(results, format, tokenBudget) {
2221
+ const selected = [];
2222
+ let used = 0;
2223
+ let clipped = false;
2224
+ let minimumBudget;
2225
+ for (const result of results) {
2226
+ const formatted = formatResult(result, format);
2227
+ const tokens = estimateTokens(formatted);
2228
+ if (tokenBudget === void 0 || used + tokens <= tokenBudget) {
2229
+ selected.push(formatted);
2230
+ used += tokens;
2231
+ continue;
2232
+ }
2233
+ if (selected.length === 0) {
2234
+ const preview = clipResult(result, format, tokenBudget);
2235
+ if (preview.result) {
2236
+ selected.push(preview.result);
2237
+ used = estimateTokens(preview.result);
2238
+ clipped = true;
2239
+ continue;
2240
+ } else minimumBudget = Math.min(preview.minimum, tokens);
2241
+ }
2242
+ break;
2243
+ }
2244
+ const excluded = results.slice(selected.length);
2245
+ const metadata = {
2246
+ tokens_used: used,
2247
+ tokens_budget: tokenBudget,
2248
+ truncated: clipped || excluded.length > 0,
2249
+ matched_count: results.length,
2250
+ excluded_by_budget: excluded.length,
2251
+ excluded_results: excluded.slice(0, 10).map((result) => ({
2252
+ obsId: result.observation.id,
2253
+ sessionId: result.sessionId,
2254
+ title: prefix(result.observation.title, 120)
2255
+ })),
2256
+ excluded_results_truncated: excluded.length > 10,
2257
+ ...minimumBudget !== void 0 && { minimum_budget: minimumBudget }
2258
+ };
2259
+ if (format === "narrative") {
2260
+ const narrativeResults = selected;
2261
+ return {
2262
+ ...metadata,
2263
+ format,
2264
+ results: narrativeResults,
2265
+ text: narrativeResults.map((result, index) => `${index + 1}. ${result.title}\n${result.narrative}`).join("\n\n")
2266
+ };
2267
+ }
2268
+ if (format === "compact") return {
2269
+ ...metadata,
2270
+ format,
2271
+ results: selected
2272
+ };
2273
+ return {
2274
+ ...metadata,
2275
+ format,
2276
+ results: selected
2277
+ };
2278
+ }
2279
+ //#endregion
2227
2280
  //#region src/secret-store.ts
2228
2281
  const SECRET_KEY = "AGENTMEMORY_SECRET";
2229
2282
  function agentmemoryHomeDir() {
2230
- return join(homedir(), ".agentmemory");
2283
+ return process.env["AGENTMEMORY_DATA_DIR"] || join(homedir(), ".agentmemory");
2231
2284
  }
2232
2285
  function secretFilePath() {
2233
2286
  return join(agentmemoryHomeDir(), "secret");
@@ -2251,7 +2304,7 @@ function unquote(value) {
2251
2304
  function readEnvFileSecret() {
2252
2305
  let content;
2253
2306
  try {
2254
- content = readFileSync(join(agentmemoryHomeDir(), ".env"), "utf-8");
2307
+ content = readFileSync(process.env["AGENTMEMORY_ENV_FILE"] || join(homedir(), ".agentmemory", ".env"), "utf-8");
2255
2308
  } catch {
2256
2309
  return "";
2257
2310
  }
@@ -2267,13 +2320,29 @@ function readEnvFileSecret() {
2267
2320
  }
2268
2321
  return found;
2269
2322
  }
2270
- function readStoredSecret() {
2323
+ function readSecretFile(path) {
2271
2324
  try {
2272
- return usable(readFileSync(secretFilePath(), "utf-8"));
2325
+ return usable(readFileSync(path, "utf-8"));
2273
2326
  } catch {
2274
2327
  return "";
2275
2328
  }
2276
2329
  }
2330
+ function legacyDataDirSecretPaths(env = process.env) {
2331
+ const dataDir = env["AGENTMEMORY_DATA_DIR"];
2332
+ if (!dataDir) return [];
2333
+ const paths = [
2334
+ join(dataDir, "secret"),
2335
+ join(dataDir, ".hmac"),
2336
+ join(dataDir, "..", ".hmac")
2337
+ ];
2338
+ return [...new Set(paths.filter((path) => path !== secretFilePath()))];
2339
+ }
2340
+ function readStoredSecret(env = process.env) {
2341
+ const canonicalPath = canonicalSecretPath();
2342
+ const localPath = secretFilePath();
2343
+ const legacyPaths = legacyDataDirSecretPaths(env);
2344
+ return readSecretFile(canonicalPath) || (localPath === canonicalPath ? "" : readSecretFile(localPath)) || legacyPaths.map(readSecretFile).find(Boolean) || "";
2345
+ }
2277
2346
  function explicitSecret(env = process.env) {
2278
2347
  return usable(env[SECRET_KEY]) || readEnvFileSecret();
2279
2348
  }
@@ -2290,30 +2359,44 @@ function isLoopbackUrl(url) {
2290
2359
  function resolveClientSecret(baseUrl, env = process.env) {
2291
2360
  const fromEnv = usable(env[SECRET_KEY]);
2292
2361
  if (fromEnv) return fromEnv;
2362
+ if (env.AGENTMEMORY_CREDENTIAL_MODE === "explicit") return "";
2293
2363
  if (!isLoopbackUrl(baseUrl)) return "";
2294
- return readEnvFileSecret() || readStoredSecret();
2364
+ return readEnvFileSecret() || readStoredSecret(env);
2295
2365
  }
2296
- function ensureServerSecret(env = process.env) {
2297
- const configured = explicitSecret(env);
2298
- if (configured) return {
2299
- secret: configured,
2300
- source: "env"
2301
- };
2302
- const stored = readStoredSecret();
2303
- if (stored) return {
2304
- secret: stored,
2305
- source: "file"
2306
- };
2307
- const generated = randomBytes(32).toString("hex");
2308
- const path = secretFilePath();
2309
- mkdirSync(agentmemoryHomeDir(), {
2366
+ function canonicalSecretPath() {
2367
+ return join(homedir(), ".agentmemory", "secret");
2368
+ }
2369
+ function writeSecretFile(path, secret) {
2370
+ mkdirSync(join(path, ".."), {
2371
+ recursive: true,
2372
+ mode: 448
2373
+ });
2374
+ const staging = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
2375
+ const fd = openSync(staging, "wx", 384);
2376
+ try {
2377
+ writeSync(fd, `${secret}\n`);
2378
+ } finally {
2379
+ closeSync(fd);
2380
+ }
2381
+ try {
2382
+ chmodSync(staging, 384);
2383
+ renameSync(staging, path);
2384
+ chmodSync(path, 384);
2385
+ } finally {
2386
+ try {
2387
+ unlinkSync(staging);
2388
+ } catch {}
2389
+ }
2390
+ }
2391
+ function writeSecretIfAbsent(path, secret) {
2392
+ mkdirSync(join(path, ".."), {
2310
2393
  recursive: true,
2311
2394
  mode: 448
2312
2395
  });
2313
2396
  const staging = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
2314
2397
  const fd = openSync(staging, "wx", 384);
2315
2398
  try {
2316
- writeSync(fd, `${generated}\n`);
2399
+ writeSync(fd, `${secret}\n`);
2317
2400
  } finally {
2318
2401
  closeSync(fd);
2319
2402
  }
@@ -2322,20 +2405,38 @@ function ensureServerSecret(env = process.env) {
2322
2405
  linkSync(staging, path);
2323
2406
  } catch (err) {
2324
2407
  if (err.code !== "EEXIST") throw err;
2325
- const raced = readStoredSecret();
2326
- if (!raced) throw err;
2327
- return {
2328
- secret: raced,
2329
- source: "file"
2330
- };
2331
2408
  } finally {
2332
2409
  try {
2333
2410
  unlinkSync(staging);
2334
2411
  } catch {}
2335
2412
  }
2413
+ const stored = readSecretFile(path);
2414
+ if (!stored) throw new Error(`Could not read stored API secret at ${path}.`);
2415
+ return stored;
2416
+ }
2417
+ function ensureServerSecret(env = process.env) {
2418
+ const configured = explicitSecret(env);
2419
+ if (configured) return {
2420
+ secret: configured,
2421
+ source: "env"
2422
+ };
2423
+ const localPath = secretFilePath();
2424
+ const canonicalPath = canonicalSecretPath();
2425
+ const canonical = localPath === canonicalPath ? "" : readSecretFile(canonicalPath);
2426
+ if (canonical) {
2427
+ if (localPath !== canonicalPath && readSecretFile(localPath) !== canonical) writeSecretFile(localPath, canonical);
2428
+ return {
2429
+ secret: canonical,
2430
+ source: "file"
2431
+ };
2432
+ }
2433
+ const legacy = readSecretFile(localPath) || legacyDataDirSecretPaths(env).map(readSecretFile).find(Boolean) || "";
2434
+ const localSecret = writeSecretIfAbsent(localPath, legacy || randomBytes(32).toString("hex"));
2435
+ const secret = localPath === canonicalPath ? localSecret : writeSecretIfAbsent(canonicalPath, localSecret);
2436
+ if (localPath !== canonicalPath && localSecret !== secret) writeSecretFile(localPath, secret);
2336
2437
  return {
2337
- secret: generated,
2338
- source: "generated"
2438
+ secret,
2439
+ source: legacy ? "file" : "generated"
2339
2440
  };
2340
2441
  }
2341
2442
  function bearerHeaders(baseUrl, env = process.env) {
@@ -2343,6 +2444,6 @@ function bearerHeaders(baseUrl, env = process.env) {
2343
2444
  return secret ? { Authorization: `Bearer ${secret}` } : {};
2344
2445
  }
2345
2446
  //#endregion
2346
- export { bootWarn as $, getStandalonePersistPath as A, isContextInjectionEnabled as B, getConsolidationDecayDays as C, getIndexSaveIntervalMs as D, getFollowupWindowSeconds as E, getViewerStreamMax as F, isVectorBackfillAllEnabled as G, isGraphCompactOnBootEnabled as H, hydrateProcessEnvFromFile as I, loadEmbeddingConfig as J, loadClaudeBridgeConfig as K, isAgentScopeIsolated as L, getStateSaveIntervalMs as M, getVectorBackfillMax as N, getRedisUrl as O, getVectorBucketSize as P, bootLog as Q, isAutoCompressEnabled as R, getConsolidationCooldownMs as S, getEnvVar as T, isGraphExtractionEnabled as U, isDropStaleIndexEnabled as V, isSessionSweepEnabled as W, loadSnapshotConfig as X, loadFallbackConfig as Y, loadTeamConfig as Z, VERSION as _, secretFilePath as a, isBundledConfig as at, getAgentId as b, recordAudit as c, resolveEngineCwd as ct, setAuditRecordedListener as d, runtimeConfigPath as dt, logger as et, startAuditMigration as f, captureDurableAfterMs as ft, III_PINNED_VERSION as g, renderEngineConfig as gt, getVisibleTools as h, engineStateConfigPaths as ht, resolveClientSecret as i, engineChildEnv as it, getStateBackend as j, getSessionSweepStaleHours as k, runAuditRetentionSweep as l, resolveLaunchRenderFailure as lt, getAllTools as m, engineFlushWaitMs as mt, ensureServerSecret as n, dockerComposeArgs as nt, AUDIT_MIGRATION_STATE_KEY as o, legacyDataMigrations as ot, ESSENTIAL_TOOLS as p, clearPersistedBuiltinConfig as pt, loadConfig as q, explicitSecret as r, dockerProjectName as rt, queryAudit as s, redactCredentialUrls as st, bearerHeaders as t, setBootVerbose as tt, safeAudit as u, rewriteBundledConfig as ut, detectEmbeddingProvider as v, getConsolidationIntervalMs as w, getAuditRetentionMonths as x, detectLlmProviderKind as y, isConsolidationEnabled as z };
2447
+ export { getVectorBucketSize as $, engineFlushWaitMs as A, getConsolidationCooldownMs as B, III_PINNED_VERSION as C, logger as D, bootWarn as E, describeLlmRoute as F, getFollowupWindowSeconds as G, getConsolidationIntervalMs as H, detectEmbeddingProvider as I, getSessionSweepStaleHours as J, getIndexSaveIntervalMs as K, detectLlmProviderKind as L, redactCredentialUrls as M, runtimeConfigPath as N, setBootVerbose as O, MAX_IMPORT_OBS_PER_SESSION as P, getVectorBackfillMax as Q, getAgentId as R, getVisibleTools as S, bootLog as T, getEnvVar as U, getConsolidationDecayDays as V, getFinalizeIdleMs as W, getStateBackend as X, getStandalonePersistPath as Y, getStateSaveIntervalMs as Z, safeAudit as _, secretFilePath as a, isDropStaleIndexEnabled as at, ESSENTIAL_TOOLS as b, memoryToObservation as c, isSessionSweepEnabled as ct, isSearchResultLayer as d, loadConfig as dt, hydrateProcessEnvFromFile as et, matchesSearchLayer as f, loadEmbeddingConfig as ft, runAuditRetentionSweep as g, parseEnvContent as gt, recordAudit as h, loadTeamConfig as ht, resolveClientSecret as i, isContextInjectionEnabled as it, engineStateConfigPaths as j, captureDurableAfterMs as k, getSearchResultLayer as l, isVectorBackfillAllEnabled as lt, queryAudit as m, loadSnapshotConfig as mt, ensureServerSecret as n, isAutoCompressEnabled as nt, buildRecallResponse as o, isGraphCompactOnBootEnabled as ot, AUDIT_MIGRATION_STATE_KEY as p, loadFallbackConfig as pt, getRedisUrl as q, explicitSecret as r, isConsolidationEnabled as rt, lessonToObservation as s, isGraphExtractionEnabled as st, bearerHeaders as t, isAgentScopeIsolated as tt, isSearchLayer as u, loadClaudeBridgeConfig as ut, setAuditRecordedListener as v, VERSION as w, getAllTools as x, startAuditMigration as y, getAuditRetentionMonths as z };
2347
2448
 
2348
- //# sourceMappingURL=secret-store-BnY3A50C.mjs.map
2449
+ //# sourceMappingURL=secret-store-D9GwO0xp.mjs.map