@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,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,61 +51,135 @@ 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`);
68
+ }
69
+ const LLM_PROVIDER_NAMES = [
70
+ "anthropic",
71
+ "openai",
72
+ "gemini",
73
+ "openrouter",
74
+ "minimax"
75
+ ];
76
+ const LLM_PROVIDER_KEYS = {
77
+ anthropic: ["ANTHROPIC_API_KEY"],
78
+ openai: ["OPENAI_API_KEY"],
79
+ gemini: ["GEMINI_API_KEY", "GOOGLE_API_KEY"],
80
+ openrouter: ["OPENROUTER_API_KEY"],
81
+ minimax: ["MINIMAX_API_KEY"]
82
+ };
83
+ const REMOTE_EMBEDDING_PROVIDER_KEYS = {
84
+ gemini: ["GEMINI_API_KEY"],
85
+ openai: ["OPENAI_API_KEY", "OPENAI_EMBEDDING_API_KEY"],
86
+ voyage: ["VOYAGE_API_KEY"],
87
+ cohere: ["COHERE_API_KEY"],
88
+ openrouter: ["OPENROUTER_API_KEY"]
89
+ };
90
+ function isLlmProviderName(value) {
91
+ return LLM_PROVIDER_NAMES.includes(value);
92
+ }
93
+ function selectedLlmProviderValue(env) {
94
+ return (env["AGENTMEMORY_LLM_PROVIDER"] || "").trim().toLowerCase();
95
+ }
96
+ function llmProviderHasKey(env, name) {
97
+ return LLM_PROVIDER_KEYS[name].some((k) => hasRealValue(env[k]));
98
+ }
99
+ function envFileLabel(path = ENV_FILE) {
100
+ const home = homedir();
101
+ return path.startsWith(`${home}/`) ? `~${path.slice(home.length)}` : path;
102
+ }
103
+ function llmOptInHint(env = getMergedEnv()) {
104
+ const selected = selectedLlmProviderValue(env);
105
+ if (selected) {
106
+ if (!isLlmProviderName(selected)) return `AGENTMEMORY_LLM_PROVIDER=${selected} is not a known provider. Use one of: ${LLM_PROVIDER_NAMES.join(", ")}.`;
107
+ if (!llmProviderHasKey(env, selected)) return `AGENTMEMORY_LLM_PROVIDER=${selected} is set, but ${LLM_PROVIDER_KEYS[selected].join(" or ")} is not. Add the key to ${envFileLabel()}.`;
108
+ return null;
109
+ }
110
+ if (env["AGENTMEMORY_ALLOW_AGENT_SDK"] === "true") return null;
111
+ const withKey = LLM_PROVIDER_NAMES.filter((name) => llmProviderHasKey(env, name));
112
+ if (withKey.length === 0) return null;
113
+ return `Found ${withKey.flatMap((name) => LLM_PROVIDER_KEYS[name].filter((k) => hasRealValue(env[k]))).join(", ")}, but agentmemory sends nothing to an LLM provider until you choose one for it. To turn on LLM summaries and compression, add AGENTMEMORY_LLM_PROVIDER=${withKey[0]} to ${envFileLabel()}.`;
114
+ }
115
+ function embeddingOptInHint(env = getMergedEnv()) {
116
+ const chosen = (env["EMBEDDING_PROVIDER"] || "").trim().toLowerCase();
117
+ if (chosen) {
118
+ const keys = REMOTE_EMBEDDING_PROVIDER_KEYS[chosen];
119
+ if (keys && !keys.some((k) => hasRealValue(env[k]))) return `EMBEDDING_PROVIDER=${chosen} is set, but ${keys.join(" or ")} is not. Add the key to ${envFileLabel()}, or set EMBEDDING_PROVIDER=local for on-device embeddings.`;
120
+ return null;
121
+ }
122
+ const withKey = Object.keys(REMOTE_EMBEDDING_PROVIDER_KEYS).filter((name) => REMOTE_EMBEDDING_PROVIDER_KEYS[name].some((k) => hasRealValue(env[k])));
123
+ if (withKey.length === 0) return null;
124
+ return `A ${withKey.join("/")} key is present, but cloud embeddings stay off until you choose them. Add EMBEDDING_PROVIDER=${withKey[0]} to ${envFileLabel()}, or EMBEDDING_PROVIDER=local for on-device embeddings.`;
410
125
  }
411
126
  function detectProvider(env) {
412
127
  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
- };
419
- if (hasRealValue(env["MINIMAX_API_KEY"])) return {
420
- provider: "minimax",
421
- model: env["MINIMAX_MODEL"] || "MiniMax-M3",
128
+ const noop = {
129
+ provider: "noop",
130
+ model: "noop",
422
131
  maxTokens
423
132
  };
424
- if (hasRealValue(env["ANTHROPIC_API_KEY"])) return {
425
- provider: "anthropic",
426
- model: env["ANTHROPIC_MODEL"] || "claude-sonnet-5",
427
- maxTokens,
428
- baseURL: env["ANTHROPIC_BASE_URL"]
429
- };
430
- if (hasRealValue(env["GEMINI_API_KEY"]) || hasRealValue(env["GOOGLE_API_KEY"])) {
431
- if (!hasRealValue(env["GEMINI_API_KEY"]) && hasRealValue(env["GOOGLE_API_KEY"])) process.stderr.write("[agentmemory] GOOGLE_API_KEY detected — treating as GEMINI_API_KEY. Set GEMINI_API_KEY in ~/.agentmemory/.env to silence this warning.\n");
432
- return {
433
- provider: "gemini",
434
- model: env["GEMINI_MODEL"] || "gemini-3.7-flash",
435
- maxTokens
436
- };
437
- }
438
- if (hasRealValue(env["OPENROUTER_API_KEY"])) {
439
- 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`);
133
+ const selected = selectedLlmProviderValue(env);
134
+ if (selected) {
135
+ if (!isLlmProviderName(selected) || !llmProviderHasKey(env, selected)) {
136
+ writeProviderNoticeOnce(`[agentmemory] ${llmOptInHint(env)} Running zero-LLM.\n`);
137
+ return noop;
138
+ }
139
+ switch (selected) {
140
+ case "openai": {
141
+ const model = env["OPENAI_MODEL"] || "gpt-5.6-luna";
142
+ warnIfPremiumModel(env, "OPENAI_MODEL", model);
143
+ return {
144
+ provider: "openai",
145
+ model,
146
+ maxTokens,
147
+ baseURL: env["OPENAI_BASE_URL"]
148
+ };
149
+ }
150
+ case "minimax": return {
151
+ provider: "minimax",
152
+ model: env["MINIMAX_MODEL"] || "MiniMax-M3",
153
+ maxTokens
154
+ };
155
+ case "anthropic": return {
156
+ provider: "anthropic",
157
+ model: env["ANTHROPIC_MODEL"] || "claude-sonnet-5",
158
+ maxTokens,
159
+ baseURL: env["ANTHROPIC_BASE_URL"]
160
+ };
161
+ case "gemini":
162
+ if (!hasRealValue(env["GEMINI_API_KEY"])) process.stderr.write("[agentmemory] GOOGLE_API_KEY detected — treating as GEMINI_API_KEY. Set GEMINI_API_KEY in ~/.agentmemory/.env to silence this warning.\n");
163
+ return {
164
+ provider: "gemini",
165
+ model: env["GEMINI_MODEL"] || "gemini-3.7-flash",
166
+ maxTokens
167
+ };
168
+ case "openrouter": {
169
+ const model = env["OPENROUTER_MODEL"] || "anthropic/claude-sonnet-5";
170
+ warnIfPremiumModel(env, "OPENROUTER_MODEL", model);
171
+ return {
172
+ provider: "openrouter",
173
+ model,
174
+ maxTokens
175
+ };
176
+ }
443
177
  }
444
- return {
445
- provider: "openrouter",
446
- model,
447
- maxTokens
448
- };
449
178
  }
450
179
  if (!(env["AGENTMEMORY_ALLOW_AGENT_SDK"] === "true")) {
451
- writeProviderNoticeOnce(pc.dim("[agentmemory] No LLM provider key set — running zero-LLM: no LLM compression or summaries; search uses BM25 plus any configured embedding provider. Set EMBEDDING_PROVIDER=local for on-device semantic embeddings if none is configured. Set ANTHROPIC_API_KEY (or GEMINI/OPENAI/OPENROUTER/MINIMAX) in ~/.agentmemory/.env for LLM compression and summaries. Agent-SDK fallback stays off by default to avoid a Stop-hook recursion loop; opt in with AGENTMEMORY_AUTO_COMPRESS=true + AGENTMEMORY_ALLOW_AGENT_SDK=true.\n"));
452
- return {
453
- provider: "noop",
454
- model: "noop",
455
- maxTokens
456
- };
180
+ const hint = llmOptInHint(env);
181
+ writeProviderNoticeOnce(hint ? `[agentmemory] ${hint}\n` : pc.dim("[agentmemory] No LLM provider chosen, so agentmemory runs zero-LLM: no LLM compression or summaries, and no session content leaves this machine for an LLM. Search uses BM25 plus any embedding provider you set with EMBEDDING_PROVIDER (EMBEDDING_PROVIDER=local runs on-device). To turn on LLM summaries, set AGENTMEMORY_LLM_PROVIDER (anthropic, openai, gemini, openrouter or minimax) and that provider's key in ~/.agentmemory/.env.\n"));
182
+ return noop;
457
183
  }
458
184
  writeProviderNoticeOnce("[agentmemory] WARNING: agent-sdk fallback enabled via AGENTMEMORY_ALLOW_AGENT_SDK=true. This spawns @anthropic-ai/claude-agent-sdk child sessions that can trigger the Stop-hook recursion loop. A SDK-child env marker is set to block re-entry, but prefer setting a real API key in ~/.agentmemory/.env instead.\n");
459
185
  return {
@@ -466,16 +192,21 @@ function loadConfig() {
466
192
  const env = getMergedEnv();
467
193
  const provider = detectProvider(env);
468
194
  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
195
  const viewerPort = parseInt(env["III_VIEWER_PORT"] || "", 10) || restPort + 2;
196
+ const engineUrl = env["III_ENGINE_URL"] || env["III_URL"] || `ws://localhost:${parseInt(env["III_ENGINE_PORT"] || "", 10) || restPort + 46023}`;
197
+ const maxObservationsPerSession = safeParseInt(env["MAX_OBS_PER_SESSION"], 500);
198
+ if (!obsCapImportCeilingWarned && (maxObservationsPerSession === 0 || maxObservationsPerSession > 5e3)) {
199
+ obsCapImportCeilingWarned = true;
200
+ const capDesc = maxObservationsPerSession === 0 ? "uncapped (0)" : String(maxObservationsPerSession);
201
+ 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`);
202
+ }
471
203
  return {
472
- engineUrl: env["III_ENGINE_URL"] || `ws://localhost:${parseInt(env["III_ENGINE_PORT"] || "", 10) || restPort + 46023}`,
204
+ engineUrl,
473
205
  restPort,
474
- streamsPort,
475
206
  viewerPort,
476
207
  provider,
477
208
  tokenBudget: safeParseInt(env["TOKEN_BUDGET"], 2e3),
478
- maxObservationsPerSession: safeParseInt(env["MAX_OBS_PER_SESSION"], 500),
209
+ maxObservationsPerSession,
479
210
  compressionModel: provider.model,
480
211
  dataDir: DATA_DIR
481
212
  };
@@ -499,6 +230,11 @@ function getSessionSweepStaleHours() {
499
230
  const parsed = parseInt(raw.trim(), 10);
500
231
  return parsed > 0 ? parsed : 24;
501
232
  }
233
+ function getFinalizeIdleMs() {
234
+ const raw = getMergedEnv()["AGENTMEMORY_FINALIZE_IDLE_MS"];
235
+ if (!raw || !/^\d+$/.test(raw.trim())) return 12e4;
236
+ return parseInt(raw.trim(), 10);
237
+ }
502
238
  function isGraphCompactOnBootEnabled() {
503
239
  return getMergedEnv()["AGENTMEMORY_GRAPH_COMPACT_ON_BOOT"] !== "false";
504
240
  }
@@ -523,9 +259,21 @@ function getAuditMigrateMaxBytes() {
523
259
  return safeParseInt(getMergedEnv()["AGENTMEMORY_AUDIT_MIGRATE_MAX_BYTES"], 32 * 1024 * 1024);
524
260
  }
525
261
  function detectLlmProviderKind(env = getMergedEnv()) {
526
- 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";
262
+ const selected = selectedLlmProviderValue(env);
263
+ if (selected && isLlmProviderName(selected) && llmProviderHasKey(env, selected)) return "llm";
264
+ if (!selected && env["AGENTMEMORY_ALLOW_AGENT_SDK"] === "true") return "llm";
527
265
  return "noop";
528
266
  }
267
+ function describeLlmRoute(provider) {
268
+ if (provider.provider === "noop") return null;
269
+ const parts = [provider.provider, provider.model];
270
+ if (provider.baseURL) try {
271
+ parts.push(new URL(provider.baseURL).host);
272
+ } catch {
273
+ parts.push("custom base URL");
274
+ }
275
+ return parts.join(" · ");
276
+ }
529
277
  function loadEmbeddingConfig() {
530
278
  const env = getMergedEnv();
531
279
  let bm25Weight = parseFloat(env["BM25_WEIGHT"] || "0.4");
@@ -539,15 +287,8 @@ function loadEmbeddingConfig() {
539
287
  };
540
288
  }
541
289
  function detectEmbeddingProvider(env) {
542
- const source = env ?? getMergedEnv();
543
- const forced = source["EMBEDDING_PROVIDER"];
544
- if (forced) return forced;
545
- if (source["GEMINI_API_KEY"]) return "gemini";
546
- if (source["OPENAI_API_KEY"] || source["OPENAI_EMBEDDING_API_KEY"]) return "openai";
547
- if (source["VOYAGE_API_KEY"]) return "voyage";
548
- if (source["COHERE_API_KEY"]) return "cohere";
549
- if (source["OPENROUTER_API_KEY"]) return "openrouter";
550
- return null;
290
+ const forced = ((env ?? getMergedEnv())["EMBEDDING_PROVIDER"] || "").trim();
291
+ return forced ? forced : null;
551
292
  }
552
293
  function loadClaudeBridgeConfig() {
553
294
  const env = getMergedEnv();
@@ -613,20 +354,6 @@ const FOLLOWUP_WINDOW_DEFAULT_SECONDS = 30;
613
354
  function getFollowupWindowSeconds() {
614
355
  return safeParseInt(getMergedEnv()["AGENTMEMORY_FOLLOWUP_WINDOW_SECONDS"], FOLLOWUP_WINDOW_DEFAULT_SECONDS);
615
356
  }
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
357
  function isConsolidationEnabled() {
631
358
  const env = getMergedEnv();
632
359
  const explicit = env["CONSOLIDATION_ENABLED"];
@@ -659,9 +386,13 @@ function getIndexSaveIntervalMs() {
659
386
  const raw = safeParseInt(getMergedEnv()["AGENTMEMORY_INDEX_SAVE_INTERVAL_MS"], INDEX_SAVE_INTERVAL_DEFAULT_MS);
660
387
  return raw > 0 ? raw : INDEX_SAVE_INTERVAL_DEFAULT_MS;
661
388
  }
389
+ const STATE_SAVE_INTERVAL_DEFAULT_MS = 2e3;
662
390
  function getStateSaveIntervalMs() {
663
- const raw = safeParseInt(getMergedEnv()["AGENTMEMORY_STATE_SAVE_INTERVAL_MS"], 0);
664
- return raw > 0 ? raw : void 0;
391
+ const value = getMergedEnv()["AGENTMEMORY_STATE_SAVE_INTERVAL_MS"];
392
+ if (value === void 0 || value.trim() === "") return STATE_SAVE_INTERVAL_DEFAULT_MS;
393
+ if (!/^\d+$/.test(value.trim())) return STATE_SAVE_INTERVAL_DEFAULT_MS;
394
+ const raw = Number(value);
395
+ return Number.isSafeInteger(raw) && raw >= 100 && raw <= 36e5 ? raw : STATE_SAVE_INTERVAL_DEFAULT_MS;
665
396
  }
666
397
  function getVectorBucketSize() {
667
398
  const raw = safeParseInt(getMergedEnv()["AGENTMEMORY_VECTOR_BUCKET_SIZE"], 500);
@@ -698,15 +429,158 @@ function loadFallbackConfig() {
698
429
  }) };
699
430
  }
700
431
  //#endregion
432
+ //#region src/cli/engine-launch.ts
433
+ function runtimeConfigPath(dataDir) {
434
+ return join(dataDir, "iii-config.runtime.yaml");
435
+ }
436
+ const CREDENTIAL_URL_PATTERN = /:\/\/[^@\s/]*@/g;
437
+ function redactCredentialUrls(text) {
438
+ return text.replace(CREDENTIAL_URL_PATTERN, "://***@");
439
+ }
440
+ //#endregion
441
+ //#region src/cli/engine-config.ts
442
+ const ENGINE_DEFAULT_SAVE_INTERVAL_MS = 5e3;
443
+ const ENGINE_FLUSH_MARGIN_MS = 1500;
444
+ function engineFlushWaitMs(stateBackend, configTexts) {
445
+ if (stateBackend === "redis") return 0;
446
+ return engineSaveIntervalMs(configTexts) + ENGINE_FLUSH_MARGIN_MS;
447
+ }
448
+ function captureDurableAfterMs(stateBackend, configTexts) {
449
+ if (stateBackend === "redis") return ENGINE_FLUSH_MARGIN_MS;
450
+ return engineSaveIntervalMs(configTexts) + ENGINE_FLUSH_MARGIN_MS;
451
+ }
452
+ function engineSaveIntervalMs(configTexts, env = process.env) {
453
+ const intervals = [];
454
+ for (const text of configTexts) {
455
+ const explicit = [];
456
+ for (const match of text.matchAll(/save_interval_ms:\s*["']?(\d+|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-(\d+))?\})/g)) {
457
+ const raw = match[2] ? env[match[2]] || match[3] : match[1];
458
+ if (raw && /^\d+$/.test(raw) && Number.isSafeInteger(Number(raw))) explicit.push(Number(raw));
459
+ }
460
+ intervals.push(...explicit);
461
+ if ((text.match(/store_method:\s*file_based/g)?.length ?? 0) > explicit.length) intervals.push(ENGINE_DEFAULT_SAVE_INTERVAL_MS);
462
+ }
463
+ return intervals.length > 0 ? Math.max(...intervals) : ENGINE_DEFAULT_SAVE_INTERVAL_MS;
464
+ }
465
+ function engineStateConfigPaths(engineCwd, runtimePath) {
466
+ return [...new Set([
467
+ join(engineCwd, "compose", "worker-compose.yaml"),
468
+ join(engineCwd, "compose", "config", "state.yaml"),
469
+ join(engineCwd, "worker-compose.runtime.yaml"),
470
+ join(engineCwd, "config", "state.yaml"),
471
+ runtimePath
472
+ ])];
473
+ }
474
+ //#endregion
475
+ //#region src/logger.ts
476
+ function fmt(level, msg, fields) {
477
+ if (!fields || Object.keys(fields).length === 0) return `[agentmemory] ${level} ${msg}`;
478
+ try {
479
+ return `[agentmemory] ${level} ${msg} ${JSON.stringify(fields)}`;
480
+ } catch {
481
+ return `[agentmemory] ${level} ${msg}`;
482
+ }
483
+ }
484
+ function emit(level, msg, fields) {
485
+ try {
486
+ const line = fmt(level, msg, fields) + "\n";
487
+ if (level === "error" || process.env["AGENTMEMORY_MCP_STDIO__"] === "1") process.stderr.write(line);
488
+ else process.stdout.write(line);
489
+ } catch {}
490
+ }
491
+ const logger = {
492
+ info(msg, fields) {
493
+ emit("info", msg, fields);
494
+ },
495
+ warn(msg, fields) {
496
+ emit("warn", msg, fields);
497
+ },
498
+ error(msg, fields) {
499
+ emit("error", msg, fields);
500
+ }
501
+ };
502
+ let bootVerbose = process.env["AGENTMEMORY_VERBOSE"] === "1" || process.env["AGENTMEMORY_VERBOSE"] === "true";
503
+ const bootBuffer = [];
504
+ function setBootVerbose(enabled) {
505
+ bootVerbose = enabled;
506
+ }
507
+ function bootLog(msg) {
508
+ if (bootVerbose) {
509
+ try {
510
+ process.stderr.write(`[agentmemory] ${msg}\n`);
511
+ } catch {}
512
+ return;
513
+ }
514
+ if (bootBuffer.length < 500) bootBuffer.push(msg);
515
+ }
516
+ function bootWarn(msg) {
517
+ try {
518
+ process.stderr.write(`[agentmemory] warn ${msg}\n`);
519
+ } catch {}
520
+ }
521
+ //#endregion
701
522
  //#region src/version.ts
702
- const VERSION = "0.9.30";
703
- const III_PINNED_VERSION = "0.22.1";
523
+ const VERSION = "0.9.32";
524
+ const III_PINNED_VERSION = "0.25.0";
704
525
  //#endregion
705
526
  //#region src/mcp/tools-registry.ts
527
+ const READ_ONLY_TOOLS = new Set([
528
+ "memory_recall",
529
+ "memory_file_history",
530
+ "memory_patterns",
531
+ "memory_sessions",
532
+ "memory_smart_search",
533
+ "memory_vision_search",
534
+ "memory_timeline",
535
+ "memory_export",
536
+ "memory_relations",
537
+ "memory_commit_lookup",
538
+ "memory_commits",
539
+ "memory_graph_query",
540
+ "memory_team_feed",
541
+ "memory_audit",
542
+ "memory_frontier",
543
+ "memory_next",
544
+ "memory_diagnose",
545
+ "memory_facet_query",
546
+ "memory_verify",
547
+ "memory_lesson_recall",
548
+ "memory_insight_list",
549
+ "memory_slot_list",
550
+ "memory_slot_get"
551
+ ]);
552
+ const DESTRUCTIVE_TOOLS = new Set([
553
+ "memory_action_update",
554
+ "memory_compress_file",
555
+ "memory_claude_bridge_sync",
556
+ "memory_governance_delete",
557
+ "memory_heal",
558
+ "memory_lesson_delete",
559
+ "memory_obsidian_export",
560
+ "memory_slot_replace",
561
+ "memory_slot_delete"
562
+ ]);
563
+ const IDEMPOTENT_WRITE_TOOLS = new Set([
564
+ "memory_governance_delete",
565
+ "memory_lesson_delete",
566
+ "memory_slot_replace",
567
+ "memory_slot_delete",
568
+ "memory_claude_bridge_sync"
569
+ ]);
570
+ const OPEN_WORLD_TOOLS = new Set(["memory_mesh_sync"]);
571
+ function toolAnnotations(name) {
572
+ const readOnly = READ_ONLY_TOOLS.has(name);
573
+ return {
574
+ readOnlyHint: readOnly,
575
+ destructiveHint: !readOnly && DESTRUCTIVE_TOOLS.has(name),
576
+ idempotentHint: readOnly || IDEMPOTENT_WRITE_TOOLS.has(name),
577
+ openWorldHint: OPEN_WORLD_TOOLS.has(name)
578
+ };
579
+ }
706
580
  const CORE_TOOLS = [
707
581
  {
708
582
  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.",
583
+ 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
584
  inputSchema: {
711
585
  type: "object",
712
586
  properties: {
@@ -724,7 +598,28 @@ const CORE_TOOLS = [
724
598
  },
725
599
  token_budget: {
726
600
  type: "number",
727
- description: "Optional token budget to trim returned results"
601
+ description: "Optional estimated content token budget; response includes truncation and recovery metadata"
602
+ },
603
+ targetLayer: {
604
+ type: "string",
605
+ enum: [
606
+ "all",
607
+ "memory",
608
+ "observation"
609
+ ],
610
+ description: "Search all indexed layers (default), durable memories, or raw observations before ranking"
611
+ },
612
+ project: {
613
+ type: "string",
614
+ description: "Filter by project path"
615
+ },
616
+ cwd: {
617
+ type: "string",
618
+ description: "Filter by session working directory"
619
+ },
620
+ agentId: {
621
+ type: "string",
622
+ description: "Filter by owning agent; '*' reads across agents"
728
623
  }
729
624
  },
730
625
  required: ["query"]
@@ -813,15 +708,32 @@ const CORE_TOOLS = [
813
708
  },
814
709
  {
815
710
  name: "memory_sessions",
816
- description: "List recent sessions with their status and observation counts.",
711
+ 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
712
  inputSchema: {
818
713
  type: "object",
819
- properties: {}
714
+ properties: {
715
+ project: {
716
+ type: "string",
717
+ description: "Exact project identifier used when sessions were started"
718
+ },
719
+ agentId: {
720
+ type: "string",
721
+ description: "Filter by owning agent; '*' reads across agents"
722
+ },
723
+ limit: {
724
+ type: "integer",
725
+ description: "Page size (default 20, max 100)"
726
+ },
727
+ cursor: {
728
+ type: "string",
729
+ description: "nextCursor from the previous page; omit for the first page"
730
+ }
731
+ }
820
732
  }
821
733
  },
822
734
  {
823
735
  name: "memory_smart_search",
824
- description: "Hybrid semantic+keyword search with progressive disclosure.",
736
+ description: "Hybrid semantic+keyword search with progressive disclosure. Pass query to search, or expandIds to recover full results.",
825
737
  inputSchema: {
826
738
  type: "object",
827
739
  properties: {
@@ -831,14 +743,34 @@ const CORE_TOOLS = [
831
743
  },
832
744
  expandIds: {
833
745
  type: "string",
834
- description: "Comma-separated observation IDs to expand"
746
+ description: "Comma-separated memory or observation IDs to expand; query is optional when provided"
835
747
  },
836
748
  limit: {
837
749
  type: "number",
838
750
  description: "Max results (default 10)"
751
+ },
752
+ targetLayer: {
753
+ type: "string",
754
+ enum: [
755
+ "all",
756
+ "memory",
757
+ "observation"
758
+ ],
759
+ description: "Search all indexed layers (default), durable memories, or raw observations before ranking"
760
+ },
761
+ project: {
762
+ type: "string",
763
+ description: "Filter by project path"
764
+ },
765
+ agentId: {
766
+ type: "string",
767
+ description: "Filter by owning agent; '*' reads across agents"
768
+ },
769
+ includeLessons: {
770
+ type: "boolean",
771
+ description: "Include lesson matches when targetLayer is all (default true)"
839
772
  }
840
- },
841
- required: ["query"]
773
+ }
842
774
  }
843
775
  },
844
776
  {
@@ -916,10 +848,31 @@ const CORE_TOOLS = [
916
848
  },
917
849
  {
918
850
  name: "memory_export",
919
- description: "Export all memory data as JSON.",
851
+ 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
852
  inputSchema: {
921
853
  type: "object",
922
- properties: {}
854
+ properties: {
855
+ maxSessions: {
856
+ type: "number",
857
+ description: "Sessions per page (with their observations)"
858
+ },
859
+ offset: {
860
+ type: "number",
861
+ description: "Session offset"
862
+ },
863
+ collectionLimit: {
864
+ type: "number",
865
+ 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"
866
+ },
867
+ collectionOffset: {
868
+ type: "number",
869
+ description: "Row offset for the top-level collections"
870
+ },
871
+ collections: {
872
+ type: "string",
873
+ 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."
874
+ }
875
+ }
923
876
  }
924
877
  },
925
878
  {
@@ -1604,6 +1557,11 @@ const V070_TOOLS = [
1604
1557
  tags: {
1605
1558
  type: "string",
1606
1559
  description: "Comma-separated tags"
1560
+ },
1561
+ sourceIds: {
1562
+ type: "array",
1563
+ items: { type: "string" },
1564
+ description: "Ids of the session, memory, observation or crystal this lesson came from (max 50)"
1607
1565
  }
1608
1566
  },
1609
1567
  required: ["content"]
@@ -1826,7 +1784,10 @@ function getAllTools() {
1826
1784
  ...V070_TOOLS,
1827
1785
  ...V073_TOOLS,
1828
1786
  ...V010_SLOTS_TOOLS
1829
- ];
1787
+ ].map((tool) => ({
1788
+ ...tool,
1789
+ annotations: toolAnnotations(tool.name)
1790
+ }));
1830
1791
  }
1831
1792
  function getVisibleTools() {
1832
1793
  if ((process.env["AGENTMEMORY_TOOLS"] || "all") === "core") return getAllTools().filter((t) => ESSENTIAL_TOOLS.has(t.name));
@@ -1925,7 +1886,7 @@ async function auditMigrationDeleteDelayMs() {
1925
1886
  const dataDir = getEnvVar("AGENTMEMORY_DATA_DIR");
1926
1887
  if (!dataDir) return ENGINE_DEFAULT_SAVE_INTERVAL_MS * AUDIT_MIGRATION_DELETE_WAIT_INTERVALS;
1927
1888
  const configTexts = [];
1928
- for (const path of engineStateConfigPaths(join(homedir(), ".agentmemory"), runtimeConfigPath(dataDir))) try {
1889
+ for (const path of engineStateConfigPaths(dataDir, runtimeConfigPath(dataDir))) try {
1929
1890
  configTexts.push(await readFile(path, "utf-8"));
1930
1891
  } catch {}
1931
1892
  return engineSaveIntervalMs(configTexts) * AUDIT_MIGRATION_DELETE_WAIT_INTERVALS;
@@ -2224,10 +2185,244 @@ async function runAuditRetentionSweep(kv, retentionMonths) {
2224
2185
  };
2225
2186
  }
2226
2187
  //#endregion
2188
+ //#region src/state/search-layer.ts
2189
+ function isSearchLayer(value) {
2190
+ return value === "all" || value === "memory" || value === "observation";
2191
+ }
2192
+ function isSearchResultLayer(value) {
2193
+ return value === "memory" || value === "observation" || value === "lesson" || value === "insight";
2194
+ }
2195
+ function getSearchResultLayer(obsId, sessionId) {
2196
+ if (obsId.startsWith("mem_")) return "memory";
2197
+ if (sessionId === "lesson" || obsId.startsWith("lsn_")) return "lesson";
2198
+ if (sessionId === "insight" || obsId.startsWith("ins_")) return "insight";
2199
+ return "observation";
2200
+ }
2201
+ function matchesSearchLayer(obsId, sessionId, targetLayer = "all", layer) {
2202
+ return targetLayer === "all" || (layer ?? getSearchResultLayer(obsId, sessionId)) === targetLayer;
2203
+ }
2204
+ //#endregion
2205
+ //#region src/state/memory-utils.ts
2206
+ const MAX_DATE_MS = 864e13;
2207
+ function supersededAt(previous, now) {
2208
+ const prior = previous ? Date.parse(previous) : NaN;
2209
+ const current = Date.parse(now);
2210
+ if (Number.isNaN(prior) || current > prior) return now;
2211
+ return new Date(Math.min(prior + 1, MAX_DATE_MS)).toISOString();
2212
+ }
2213
+ function memoryToObservation(memory) {
2214
+ return {
2215
+ id: memory.id,
2216
+ sessionId: memory.sessionIds?.[0] ?? "memory",
2217
+ timestamp: memory.createdAt,
2218
+ type: "decision",
2219
+ memoryType: memory.type,
2220
+ title: memory.title,
2221
+ facts: [memory.content],
2222
+ narrative: memory.content,
2223
+ concepts: memory.concepts,
2224
+ files: memory.files,
2225
+ importance: memory.strength,
2226
+ ...memory.agentId ? { agentId: memory.agentId } : {}
2227
+ };
2228
+ }
2229
+ function lessonToObservation(l) {
2230
+ return {
2231
+ id: l.id,
2232
+ sessionId: "lesson",
2233
+ timestamp: l.createdAt,
2234
+ type: "decision",
2235
+ title: l.content.slice(0, 120),
2236
+ facts: [l.content],
2237
+ narrative: l.context || "",
2238
+ concepts: l.tags,
2239
+ files: [],
2240
+ importance: l.confidence
2241
+ };
2242
+ }
2243
+ function observationEmbedText(record) {
2244
+ return [
2245
+ record.title,
2246
+ ...record.concepts || [],
2247
+ record.narrative || ""
2248
+ ].filter((part) => part && part.trim()).join(" ").trim();
2249
+ }
2250
+ //#endregion
2251
+ //#region src/functions/recall-response.ts
2252
+ function estimateTokens(value) {
2253
+ return Math.max(1, Math.ceil(JSON.stringify(value).length / 3));
2254
+ }
2255
+ function prefix(text, length) {
2256
+ let end = Math.min(length, text.length);
2257
+ if (end > 0 && end < text.length && /[\uD800-\uDBFF]/.test(text[end - 1])) end--;
2258
+ return text.slice(0, end);
2259
+ }
2260
+ function fitText(text, budget, makeResult) {
2261
+ let low = 0;
2262
+ let high = text.length;
2263
+ while (low < high) {
2264
+ const middle = Math.ceil((low + high) / 2);
2265
+ if (estimateTokens(makeResult(prefix(text, middle))) <= budget) low = middle;
2266
+ else high = middle - 1;
2267
+ }
2268
+ return makeResult(prefix(text, low));
2269
+ }
2270
+ function formatResult(result, format) {
2271
+ if (format === "full") return result;
2272
+ const observation = result.observation;
2273
+ const compact = {
2274
+ obsId: observation.id,
2275
+ sessionId: result.sessionId,
2276
+ title: observation.title,
2277
+ type: observation.type,
2278
+ ...observation.memoryType !== void 0 && { memoryType: observation.memoryType },
2279
+ score: result.score,
2280
+ timestamp: observation.timestamp,
2281
+ ...result.layer !== void 0 && { layer: result.layer }
2282
+ };
2283
+ if (format === "compact") return compact;
2284
+ const { type: _type, ...narrative } = compact;
2285
+ return {
2286
+ ...narrative,
2287
+ narrative: observation.narrative
2288
+ };
2289
+ }
2290
+ function clipResult(result, format, budget) {
2291
+ const observation = result.observation;
2292
+ const layer = result.layer !== void 0 ? { layer: result.layer } : {};
2293
+ if (format === "compact") {
2294
+ const base = {
2295
+ obsId: observation.id,
2296
+ sessionId: result.sessionId,
2297
+ title: "",
2298
+ type: observation.type,
2299
+ ...observation.memoryType !== void 0 && { memoryType: observation.memoryType },
2300
+ score: result.score,
2301
+ timestamp: observation.timestamp,
2302
+ ...layer,
2303
+ content_truncated: true
2304
+ };
2305
+ const minimum = estimateTokens(base);
2306
+ if (minimum > budget) return { minimum };
2307
+ return {
2308
+ result: fitText(observation.title, budget, (title) => ({
2309
+ ...base,
2310
+ title
2311
+ })),
2312
+ minimum
2313
+ };
2314
+ }
2315
+ const makeResult = (title, narrative) => {
2316
+ if (format === "narrative") return {
2317
+ obsId: observation.id,
2318
+ sessionId: result.sessionId,
2319
+ title,
2320
+ narrative,
2321
+ ...observation.memoryType !== void 0 && { memoryType: observation.memoryType },
2322
+ score: result.score,
2323
+ timestamp: observation.timestamp,
2324
+ ...layer,
2325
+ content_truncated: true
2326
+ };
2327
+ return {
2328
+ observation: {
2329
+ id: observation.id,
2330
+ sessionId: observation.sessionId,
2331
+ timestamp: observation.timestamp,
2332
+ type: observation.type,
2333
+ ...observation.memoryType !== void 0 && { memoryType: observation.memoryType },
2334
+ title,
2335
+ facts: [],
2336
+ narrative,
2337
+ concepts: [],
2338
+ files: [],
2339
+ importance: observation.importance,
2340
+ ...observation.confidence !== void 0 && { confidence: observation.confidence },
2341
+ ...observation.agentId !== void 0 && { agentId: observation.agentId },
2342
+ ...observation.origin && { origin: {
2343
+ channel: observation.origin.channel,
2344
+ capturedAt: observation.origin.capturedAt
2345
+ } }
2346
+ },
2347
+ score: result.score,
2348
+ sessionId: result.sessionId,
2349
+ ...layer,
2350
+ content_truncated: true
2351
+ };
2352
+ };
2353
+ const minimum = estimateTokens(makeResult("", ""));
2354
+ if (minimum > budget) return { minimum };
2355
+ const titleResult = fitText(prefix(observation.title, 120), budget, (title) => makeResult(title, ""));
2356
+ const title = "observation" in titleResult ? titleResult.observation.title : titleResult.title;
2357
+ return {
2358
+ result: fitText(observation.narrative || observation.facts.join("\n"), budget, (text) => makeResult(title, text)),
2359
+ minimum
2360
+ };
2361
+ }
2362
+ function buildRecallResponse(results, format, tokenBudget) {
2363
+ const selected = [];
2364
+ let used = 0;
2365
+ let clipped = false;
2366
+ let minimumBudget;
2367
+ for (const result of results) {
2368
+ const formatted = formatResult(result, format);
2369
+ const tokens = estimateTokens(formatted);
2370
+ if (tokenBudget === void 0 || used + tokens <= tokenBudget) {
2371
+ selected.push(formatted);
2372
+ used += tokens;
2373
+ continue;
2374
+ }
2375
+ if (selected.length === 0) {
2376
+ const preview = clipResult(result, format, tokenBudget);
2377
+ if (preview.result) {
2378
+ selected.push(preview.result);
2379
+ used = estimateTokens(preview.result);
2380
+ clipped = true;
2381
+ continue;
2382
+ } else minimumBudget = Math.min(preview.minimum, tokens);
2383
+ }
2384
+ break;
2385
+ }
2386
+ const excluded = results.slice(selected.length);
2387
+ const metadata = {
2388
+ tokens_used: used,
2389
+ tokens_budget: tokenBudget,
2390
+ truncated: clipped || excluded.length > 0,
2391
+ matched_count: results.length,
2392
+ excluded_by_budget: excluded.length,
2393
+ excluded_results: excluded.slice(0, 10).map((result) => ({
2394
+ obsId: result.observation.id,
2395
+ sessionId: result.sessionId,
2396
+ title: prefix(result.observation.title, 120)
2397
+ })),
2398
+ excluded_results_truncated: excluded.length > 10,
2399
+ ...minimumBudget !== void 0 && { minimum_budget: minimumBudget }
2400
+ };
2401
+ if (format === "narrative") {
2402
+ const narrativeResults = selected;
2403
+ return {
2404
+ ...metadata,
2405
+ format,
2406
+ results: narrativeResults,
2407
+ text: narrativeResults.map((result, index) => `${index + 1}. ${result.title}\n${result.narrative}`).join("\n\n")
2408
+ };
2409
+ }
2410
+ if (format === "compact") return {
2411
+ ...metadata,
2412
+ format,
2413
+ results: selected
2414
+ };
2415
+ return {
2416
+ ...metadata,
2417
+ format,
2418
+ results: selected
2419
+ };
2420
+ }
2421
+ //#endregion
2227
2422
  //#region src/secret-store.ts
2228
2423
  const SECRET_KEY = "AGENTMEMORY_SECRET";
2229
2424
  function agentmemoryHomeDir() {
2230
- return join(homedir(), ".agentmemory");
2425
+ return process.env["AGENTMEMORY_DATA_DIR"] || join(homedir(), ".agentmemory");
2231
2426
  }
2232
2427
  function secretFilePath() {
2233
2428
  return join(agentmemoryHomeDir(), "secret");
@@ -2251,7 +2446,7 @@ function unquote(value) {
2251
2446
  function readEnvFileSecret() {
2252
2447
  let content;
2253
2448
  try {
2254
- content = readFileSync(join(agentmemoryHomeDir(), ".env"), "utf-8");
2449
+ content = readFileSync(process.env["AGENTMEMORY_ENV_FILE"] || join(homedir(), ".agentmemory", ".env"), "utf-8");
2255
2450
  } catch {
2256
2451
  return "";
2257
2452
  }
@@ -2267,13 +2462,29 @@ function readEnvFileSecret() {
2267
2462
  }
2268
2463
  return found;
2269
2464
  }
2270
- function readStoredSecret() {
2465
+ function readSecretFile(path) {
2271
2466
  try {
2272
- return usable(readFileSync(secretFilePath(), "utf-8"));
2467
+ return usable(readFileSync(path, "utf-8"));
2273
2468
  } catch {
2274
2469
  return "";
2275
2470
  }
2276
2471
  }
2472
+ function legacyDataDirSecretPaths(env = process.env) {
2473
+ const dataDir = env["AGENTMEMORY_DATA_DIR"];
2474
+ if (!dataDir) return [];
2475
+ const paths = [
2476
+ join(dataDir, "secret"),
2477
+ join(dataDir, ".hmac"),
2478
+ join(dataDir, "..", ".hmac")
2479
+ ];
2480
+ return [...new Set(paths.filter((path) => path !== secretFilePath()))];
2481
+ }
2482
+ function readStoredSecret(env = process.env) {
2483
+ const canonicalPath = canonicalSecretPath();
2484
+ const localPath = secretFilePath();
2485
+ const legacyPaths = legacyDataDirSecretPaths(env);
2486
+ return readSecretFile(canonicalPath) || (localPath === canonicalPath ? "" : readSecretFile(localPath)) || legacyPaths.map(readSecretFile).find(Boolean) || "";
2487
+ }
2277
2488
  function explicitSecret(env = process.env) {
2278
2489
  return usable(env[SECRET_KEY]) || readEnvFileSecret();
2279
2490
  }
@@ -2290,30 +2501,44 @@ function isLoopbackUrl(url) {
2290
2501
  function resolveClientSecret(baseUrl, env = process.env) {
2291
2502
  const fromEnv = usable(env[SECRET_KEY]);
2292
2503
  if (fromEnv) return fromEnv;
2504
+ if (env.AGENTMEMORY_CREDENTIAL_MODE === "explicit") return "";
2293
2505
  if (!isLoopbackUrl(baseUrl)) return "";
2294
- return readEnvFileSecret() || readStoredSecret();
2506
+ return readEnvFileSecret() || readStoredSecret(env);
2295
2507
  }
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(), {
2508
+ function canonicalSecretPath() {
2509
+ return join(homedir(), ".agentmemory", "secret");
2510
+ }
2511
+ function writeSecretFile(path, secret) {
2512
+ mkdirSync(join(path, ".."), {
2310
2513
  recursive: true,
2311
2514
  mode: 448
2312
2515
  });
2313
2516
  const staging = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
2314
2517
  const fd = openSync(staging, "wx", 384);
2315
2518
  try {
2316
- writeSync(fd, `${generated}\n`);
2519
+ writeSync(fd, `${secret}\n`);
2520
+ } finally {
2521
+ closeSync(fd);
2522
+ }
2523
+ try {
2524
+ chmodSync(staging, 384);
2525
+ renameSync(staging, path);
2526
+ chmodSync(path, 384);
2527
+ } finally {
2528
+ try {
2529
+ unlinkSync(staging);
2530
+ } catch {}
2531
+ }
2532
+ }
2533
+ function writeSecretIfAbsent(path, secret) {
2534
+ mkdirSync(join(path, ".."), {
2535
+ recursive: true,
2536
+ mode: 448
2537
+ });
2538
+ const staging = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
2539
+ const fd = openSync(staging, "wx", 384);
2540
+ try {
2541
+ writeSync(fd, `${secret}\n`);
2317
2542
  } finally {
2318
2543
  closeSync(fd);
2319
2544
  }
@@ -2322,20 +2547,38 @@ function ensureServerSecret(env = process.env) {
2322
2547
  linkSync(staging, path);
2323
2548
  } catch (err) {
2324
2549
  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
2550
  } finally {
2332
2551
  try {
2333
2552
  unlinkSync(staging);
2334
2553
  } catch {}
2335
2554
  }
2555
+ const stored = readSecretFile(path);
2556
+ if (!stored) throw new Error(`Could not read stored API secret at ${path}.`);
2557
+ return stored;
2558
+ }
2559
+ function ensureServerSecret(env = process.env) {
2560
+ const configured = explicitSecret(env);
2561
+ if (configured) return {
2562
+ secret: configured,
2563
+ source: "env"
2564
+ };
2565
+ const localPath = secretFilePath();
2566
+ const canonicalPath = canonicalSecretPath();
2567
+ const canonical = localPath === canonicalPath ? "" : readSecretFile(canonicalPath);
2568
+ if (canonical) {
2569
+ if (localPath !== canonicalPath && readSecretFile(localPath) !== canonical) writeSecretFile(localPath, canonical);
2570
+ return {
2571
+ secret: canonical,
2572
+ source: "file"
2573
+ };
2574
+ }
2575
+ const legacy = readSecretFile(localPath) || legacyDataDirSecretPaths(env).map(readSecretFile).find(Boolean) || "";
2576
+ const localSecret = writeSecretIfAbsent(localPath, legacy || randomBytes(32).toString("hex"));
2577
+ const secret = localPath === canonicalPath ? localSecret : writeSecretIfAbsent(canonicalPath, localSecret);
2578
+ if (localPath !== canonicalPath && localSecret !== secret) writeSecretFile(localPath, secret);
2336
2579
  return {
2337
- secret: generated,
2338
- source: "generated"
2580
+ secret,
2581
+ source: legacy ? "file" : "generated"
2339
2582
  };
2340
2583
  }
2341
2584
  function bearerHeaders(baseUrl, env = process.env) {
@@ -2343,6 +2586,6 @@ function bearerHeaders(baseUrl, env = process.env) {
2343
2586
  return secret ? { Authorization: `Bearer ${secret}` } : {};
2344
2587
  }
2345
2588
  //#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 };
2589
+ export { getStandalonePersistPath as $, setBootVerbose as A, detectLlmProviderKind as B, getAllTools as C, bootLog as D, VERSION as E, runtimeConfigPath as F, getConsolidationDecayDays as G, getAgentId as H, LLM_PROVIDER_KEYS as I, getFinalizeIdleMs as J, getConsolidationIntervalMs as K, MAX_IMPORT_OBS_PER_SESSION as L, engineFlushWaitMs as M, engineStateConfigPaths as N, bootWarn as O, redactCredentialUrls as P, getSessionSweepStaleHours as Q, describeLlmRoute as R, ESSENTIAL_TOOLS as S, III_PINNED_VERSION as T, getAuditRetentionMonths as U, embeddingOptInHint as V, getConsolidationCooldownMs as W, getIndexSaveIntervalMs as X, getFollowupWindowSeconds as Y, getRedisUrl as Z, recordAudit as _, loadEmbeddingConfig as _t, secretFilePath as a, isAgentScopeIsolated as at, setAuditRecordedListener as b, loadTeamConfig as bt, memoryToObservation as c, isContextInjectionEnabled as ct, getSearchResultLayer as d, isGraphExtractionEnabled as dt, getStateBackend as et, isSearchLayer as f, isSessionSweepEnabled as ft, queryAudit as g, loadConfig as gt, AUDIT_MIGRATION_STATE_KEY as h, loadClaudeBridgeConfig as ht, resolveClientSecret as i, hydrateProcessEnvFromFile as it, captureDurableAfterMs as j, logger as k, observationEmbedText as l, isDropStaleIndexEnabled as lt, matchesSearchLayer as m, llmOptInHint as mt, ensureServerSecret as n, getVectorBackfillMax as nt, buildRecallResponse as o, isAutoCompressEnabled as ot, isSearchResultLayer as p, isVectorBackfillAllEnabled as pt, getEnvVar as q, explicitSecret as r, getVectorBucketSize as rt, lessonToObservation as s, isConsolidationEnabled as st, bearerHeaders as t, getStateSaveIntervalMs as tt, supersededAt as u, isGraphCompactOnBootEnabled as ut, runAuditRetentionSweep as v, loadFallbackConfig as vt, getVisibleTools as w, startAuditMigration as x, parseEnvContent as xt, safeAudit as y, loadSnapshotConfig as yt, detectEmbeddingProvider as z };
2347
2590
 
2348
- //# sourceMappingURL=secret-store-BnY3A50C.mjs.map
2591
+ //# sourceMappingURL=secret-store-iYXRcrO8.mjs.map