@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.
- package/.env.example +39 -33
- package/AGENTS.md +8 -8
- package/README.md +173 -558
- package/dist/.env.example +39 -33
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +1741 -966
- package/dist/cli.mjs.map +1 -1
- package/dist/compression-recovery-CnhLQC6N.mjs +5912 -0
- package/dist/compression-recovery-CnhLQC6N.mjs.map +1 -0
- package/dist/{connect-B4_ca6BD.mjs → connect-BSLIAMpw.mjs} +874 -267
- package/dist/connect-BSLIAMpw.mjs.map +1 -0
- package/dist/hooks/_capture.d.mts +5 -2
- package/dist/hooks/_capture.d.mts.map +1 -1
- package/dist/hooks/_capture.mjs +55 -19
- package/dist/hooks/_capture.mjs.map +1 -1
- package/dist/hooks/notification.mjs +20 -6
- package/dist/hooks/notification.mjs.map +1 -1
- package/dist/hooks/post-commit.mjs +25 -5
- package/dist/hooks/post-commit.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +12 -4
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +12 -4
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +37 -10
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +25 -5
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/prompt-submit.mjs +12 -4
- package/dist/hooks/prompt-submit.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +47 -16
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +37 -10
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +74 -72
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-start.mjs +13 -5
- package/dist/hooks/subagent-start.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +18 -6
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +13 -5
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/{image-refs-T_urbwHM.mjs → image-refs-Cyta4Lf9.mjs} +2 -2
- package/dist/{image-refs-T_urbwHM.mjs.map → image-refs-Cyta4Lf9.mjs.map} +1 -1
- package/dist/index.mjs +8539 -4203
- package/dist/index.mjs.map +1 -1
- package/dist/integrations/dsh.d.mts +55 -0
- package/dist/integrations/dsh.d.mts.map +1 -0
- package/dist/integrations/dsh.mjs +1145 -0
- package/dist/integrations/dsh.mjs.map +1 -0
- package/dist/{keyed-mutex-DchXsyfP.mjs → keyed-mutex-DCUh7PG-.mjs} +58 -9
- package/dist/keyed-mutex-DCUh7PG-.mjs.map +1 -0
- package/dist/{secret-store-BnY3A50C.mjs → secret-store-D9GwO0xp.mjs} +535 -434
- package/dist/secret-store-D9GwO0xp.mjs.map +1 -0
- package/dist/session-arguments-zxsbbd8y.mjs +113 -0
- package/dist/session-arguments-zxsbbd8y.mjs.map +1 -0
- package/dist/{src-Jsq9LCeH.mjs → src-DaMtDzt_.mjs} +4087 -3788
- package/dist/src-DaMtDzt_.mjs.map +1 -0
- package/dist/{standalone-DKCdrf1d.mjs → standalone-BlqshyZ5.mjs} +213 -56
- package/dist/standalone-BlqshyZ5.mjs.map +1 -0
- package/dist/standalone.d.mts +1 -1
- package/dist/standalone.d.mts.map +1 -1
- package/dist/standalone.mjs +626 -73
- package/dist/standalone.mjs.map +1 -1
- package/dist/viewer/index.html +288 -140
- package/integrations/hermes/README.md +84 -0
- package/integrations/hermes/__init__.py +669 -0
- package/integrations/hermes/plugin.yaml +27 -0
- package/integrations/omp/LICENSE +190 -0
- package/integrations/omp/README.md +76 -0
- package/integrations/omp/capture.ts +1 -0
- package/integrations/omp/dist/index.mjs +1450 -0
- package/integrations/omp/index.ts +488 -0
- package/integrations/omp/package.json +13 -0
- package/integrations/omp/security.ts +67 -0
- package/integrations/omp/skills/agentmemory-agents/REFERENCE.md +32 -0
- package/integrations/omp/skills/agentmemory-agents/SKILL.md +48 -0
- package/integrations/omp/skills/agentmemory-agents/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/agentmemory-architecture/SKILL.md +33 -0
- package/integrations/omp/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/agentmemory-config/REFERENCE.md +90 -0
- package/integrations/omp/skills/agentmemory-config/SKILL.md +78 -0
- package/integrations/omp/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/agentmemory-hooks/REFERENCE.md +20 -0
- package/integrations/omp/skills/agentmemory-hooks/SKILL.md +49 -0
- package/integrations/omp/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/agentmemory-mcp-tools/REFERENCE.md +66 -0
- package/integrations/omp/skills/agentmemory-mcp-tools/SKILL.md +42 -0
- package/integrations/omp/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/agentmemory-rest-api/REFERENCE.md +158 -0
- package/integrations/omp/skills/agentmemory-rest-api/SKILL.md +49 -0
- package/integrations/omp/skills/agentmemory-rest-api/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/commit-context/EXAMPLES.md +71 -0
- package/integrations/omp/skills/commit-context/SKILL.md +64 -0
- package/integrations/omp/skills/commit-context/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/commit-history/EXAMPLES.md +71 -0
- package/integrations/omp/skills/commit-history/SKILL.md +62 -0
- package/integrations/omp/skills/commit-history/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/forget/EXAMPLES.md +40 -0
- package/integrations/omp/skills/forget/SKILL.md +73 -0
- package/integrations/omp/skills/forget/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/handoff/EXAMPLES.md +57 -0
- package/integrations/omp/skills/handoff/SKILL.md +75 -0
- package/integrations/omp/skills/handoff/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/lesson/SKILL.md +64 -0
- package/integrations/omp/skills/lesson/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/memory-discipline/SKILL.md +65 -0
- package/integrations/omp/skills/memory-discipline/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/recall/EXAMPLES.md +74 -0
- package/integrations/omp/skills/recall/SKILL.md +74 -0
- package/integrations/omp/skills/recall/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/recap/EXAMPLES.md +62 -0
- package/integrations/omp/skills/recap/SKILL.md +68 -0
- package/integrations/omp/skills/recap/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/remember/EXAMPLES.md +67 -0
- package/integrations/omp/skills/remember/SKILL.md +66 -0
- package/integrations/omp/skills/remember/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/session-history/EXAMPLES.md +59 -0
- package/integrations/omp/skills/session-history/SKILL.md +67 -0
- package/integrations/omp/skills/session-history/TROUBLESHOOTING.md +70 -0
- package/integrations/omp/skills/write-agentmemory-skill/SKILL.md +41 -0
- package/integrations/omp/skills/write-agentmemory-skill/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/LICENSE +190 -0
- package/integrations/openclaw/README.md +88 -0
- package/integrations/openclaw/openclaw.plugin.json +71 -0
- package/integrations/openclaw/package.json +38 -0
- package/integrations/openclaw/plugin.mjs +425 -0
- package/integrations/openclaw/plugin.yaml +26 -0
- package/integrations/openclaw/skills/agentmemory-agents/REFERENCE.md +32 -0
- package/integrations/openclaw/skills/agentmemory-agents/SKILL.md +48 -0
- package/integrations/openclaw/skills/agentmemory-agents/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/agentmemory-architecture/SKILL.md +33 -0
- package/integrations/openclaw/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/agentmemory-config/REFERENCE.md +90 -0
- package/integrations/openclaw/skills/agentmemory-config/SKILL.md +78 -0
- package/integrations/openclaw/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/agentmemory-hooks/REFERENCE.md +20 -0
- package/integrations/openclaw/skills/agentmemory-hooks/SKILL.md +49 -0
- package/integrations/openclaw/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/agentmemory-mcp-tools/REFERENCE.md +66 -0
- package/integrations/openclaw/skills/agentmemory-mcp-tools/SKILL.md +42 -0
- package/integrations/openclaw/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/agentmemory-rest-api/REFERENCE.md +158 -0
- package/integrations/openclaw/skills/agentmemory-rest-api/SKILL.md +49 -0
- package/integrations/openclaw/skills/agentmemory-rest-api/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/commit-context/EXAMPLES.md +71 -0
- package/integrations/openclaw/skills/commit-context/SKILL.md +64 -0
- package/integrations/openclaw/skills/commit-context/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/commit-history/EXAMPLES.md +71 -0
- package/integrations/openclaw/skills/commit-history/SKILL.md +62 -0
- package/integrations/openclaw/skills/commit-history/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/forget/EXAMPLES.md +40 -0
- package/integrations/openclaw/skills/forget/SKILL.md +73 -0
- package/integrations/openclaw/skills/forget/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/handoff/EXAMPLES.md +57 -0
- package/integrations/openclaw/skills/handoff/SKILL.md +75 -0
- package/integrations/openclaw/skills/handoff/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/lesson/SKILL.md +64 -0
- package/integrations/openclaw/skills/lesson/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/memory-discipline/SKILL.md +65 -0
- package/integrations/openclaw/skills/memory-discipline/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/recall/EXAMPLES.md +74 -0
- package/integrations/openclaw/skills/recall/SKILL.md +74 -0
- package/integrations/openclaw/skills/recall/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/recap/EXAMPLES.md +62 -0
- package/integrations/openclaw/skills/recap/SKILL.md +68 -0
- package/integrations/openclaw/skills/recap/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/remember/EXAMPLES.md +67 -0
- package/integrations/openclaw/skills/remember/SKILL.md +66 -0
- package/integrations/openclaw/skills/remember/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/session-history/EXAMPLES.md +59 -0
- package/integrations/openclaw/skills/session-history/SKILL.md +67 -0
- package/integrations/openclaw/skills/session-history/TROUBLESHOOTING.md +70 -0
- package/integrations/openclaw/skills/write-agentmemory-skill/SKILL.md +41 -0
- package/integrations/openclaw/skills/write-agentmemory-skill/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/LICENSE +190 -0
- package/integrations/pi/README.md +45 -51
- package/integrations/pi/dist/index.mjs +1379 -0
- package/integrations/pi/index.ts +138 -171
- package/integrations/pi/package.json +16 -6
- package/integrations/pi/security.ts +6 -26
- package/integrations/pi/skills/agentmemory-agents/REFERENCE.md +32 -0
- package/integrations/pi/skills/agentmemory-agents/SKILL.md +48 -0
- package/integrations/pi/skills/agentmemory-agents/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/agentmemory-architecture/SKILL.md +33 -0
- package/integrations/pi/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/agentmemory-config/REFERENCE.md +90 -0
- package/integrations/pi/skills/agentmemory-config/SKILL.md +78 -0
- package/integrations/pi/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/agentmemory-hooks/REFERENCE.md +20 -0
- package/integrations/pi/skills/agentmemory-hooks/SKILL.md +49 -0
- package/integrations/pi/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/agentmemory-mcp-tools/REFERENCE.md +66 -0
- package/integrations/pi/skills/agentmemory-mcp-tools/SKILL.md +42 -0
- package/integrations/pi/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/agentmemory-rest-api/REFERENCE.md +158 -0
- package/integrations/pi/skills/agentmemory-rest-api/SKILL.md +49 -0
- package/integrations/pi/skills/agentmemory-rest-api/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/commit-context/EXAMPLES.md +71 -0
- package/integrations/pi/skills/commit-context/SKILL.md +64 -0
- package/integrations/pi/skills/commit-context/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/commit-history/EXAMPLES.md +71 -0
- package/integrations/pi/skills/commit-history/SKILL.md +62 -0
- package/integrations/pi/skills/commit-history/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/forget/EXAMPLES.md +40 -0
- package/integrations/pi/skills/forget/SKILL.md +73 -0
- package/integrations/pi/skills/forget/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/handoff/EXAMPLES.md +57 -0
- package/integrations/pi/skills/handoff/SKILL.md +75 -0
- package/integrations/pi/skills/handoff/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/lesson/SKILL.md +64 -0
- package/integrations/pi/skills/lesson/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/memory-discipline/SKILL.md +65 -0
- package/integrations/pi/skills/memory-discipline/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/recall/EXAMPLES.md +74 -0
- package/integrations/pi/skills/recall/SKILL.md +74 -0
- package/integrations/pi/skills/recall/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/recap/EXAMPLES.md +62 -0
- package/integrations/pi/skills/recap/SKILL.md +68 -0
- package/integrations/pi/skills/recap/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/remember/EXAMPLES.md +67 -0
- package/integrations/pi/skills/remember/SKILL.md +66 -0
- package/integrations/pi/skills/remember/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/session-history/EXAMPLES.md +59 -0
- package/integrations/pi/skills/session-history/SKILL.md +67 -0
- package/integrations/pi/skills/session-history/TROUBLESHOOTING.md +70 -0
- package/integrations/pi/skills/write-agentmemory-skill/SKILL.md +41 -0
- package/integrations/pi/skills/write-agentmemory-skill/TROUBLESHOOTING.md +70 -0
- package/package.json +32 -11
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +4 -3
- package/plugin/.devin-plugin/plugin.json +5 -3
- package/plugin/cursor/hooks.json +23 -8
- package/plugin/hooks.json +67 -0
- package/plugin/opencode/README.md +1 -1
- package/plugin/opencode/agentmemory-capture.ts +25 -11
- package/plugin/opencode/plugin.json +1 -1
- package/plugin/plugin.json +1 -1
- package/plugin/scripts/_capture.d.mts +5 -2
- package/plugin/scripts/_capture.d.mts.map +1 -1
- package/plugin/scripts/_capture.mjs +55 -19
- package/plugin/scripts/_capture.mjs.map +1 -1
- package/plugin/scripts/cursor/run-detached.d.mts +1 -0
- package/plugin/scripts/cursor/run-detached.mjs +786 -0
- package/plugin/scripts/cursor/run-detached.mjs.map +1 -0
- package/plugin/scripts/cursor/run-hook.d.mts +1 -0
- package/plugin/scripts/cursor/run-hook.mjs +704 -0
- package/plugin/scripts/cursor/run-hook.mjs.map +1 -0
- package/plugin/scripts/notification.mjs +20 -6
- package/plugin/scripts/notification.mjs.map +1 -1
- package/plugin/scripts/plugin-bridge.mjs +37 -6
- package/plugin/scripts/post-commit.mjs +25 -5
- package/plugin/scripts/post-commit.mjs.map +1 -1
- package/plugin/scripts/post-tool-failure.mjs +12 -4
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +12 -4
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +37 -10
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +25 -5
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/prompt-submit.mjs +12 -4
- package/plugin/scripts/prompt-submit.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +47 -16
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +37 -10
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +74 -72
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-start.mjs +13 -5
- package/plugin/scripts/subagent-start.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +18 -6
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +13 -5
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/plugin/skills/_shared/TROUBLESHOOTING.md +21 -7
- package/plugin/skills/agentmemory-agents/REFERENCE.md +7 -6
- package/plugin/skills/agentmemory-agents/SKILL.md +19 -5
- package/plugin/skills/agentmemory-agents/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/agentmemory-architecture/SKILL.md +4 -4
- package/plugin/skills/agentmemory-architecture/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/agentmemory-config/REFERENCE.md +12 -15
- package/plugin/skills/agentmemory-config/SKILL.md +7 -3
- package/plugin/skills/agentmemory-config/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/agentmemory-hooks/SKILL.md +15 -5
- package/plugin/skills/agentmemory-hooks/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/agentmemory-mcp-tools/REFERENCE.md +4 -4
- package/plugin/skills/agentmemory-mcp-tools/SKILL.md +6 -3
- package/plugin/skills/agentmemory-mcp-tools/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/agentmemory-rest-api/REFERENCE.md +9 -1
- package/plugin/skills/agentmemory-rest-api/SKILL.md +12 -6
- package/plugin/skills/agentmemory-rest-api/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/commit-context/SKILL.md +1 -1
- package/plugin/skills/commit-context/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/commit-history/SKILL.md +1 -1
- package/plugin/skills/commit-history/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/forget/EXAMPLES.md +19 -54
- package/plugin/skills/forget/SKILL.md +16 -12
- package/plugin/skills/forget/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/handoff/EXAMPLES.md +5 -4
- package/plugin/skills/handoff/SKILL.md +10 -5
- package/plugin/skills/handoff/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/lesson/SKILL.md +1 -1
- package/plugin/skills/lesson/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/memory-discipline/SKILL.md +1 -1
- package/plugin/skills/memory-discipline/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/recall/SKILL.md +18 -7
- package/plugin/skills/recall/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/recap/EXAMPLES.md +5 -3
- package/plugin/skills/recap/SKILL.md +11 -6
- package/plugin/skills/recap/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/remember/EXAMPLES.md +3 -3
- package/plugin/skills/remember/SKILL.md +1 -1
- package/plugin/skills/remember/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/session-history/EXAMPLES.md +2 -2
- package/plugin/skills/session-history/SKILL.md +10 -4
- package/plugin/skills/session-history/TROUBLESHOOTING.md +70 -0
- package/plugin/skills/write-agentmemory-skill/SKILL.md +2 -1
- package/plugin/skills/write-agentmemory-skill/TROUBLESHOOTING.md +70 -0
- package/dist/connect-B4_ca6BD.mjs.map +0 -1
- package/dist/docker-compose.yml +0 -73
- package/dist/iii-config.docker.yaml +0 -53
- package/dist/iii-config.yaml +0 -63
- package/dist/keyed-mutex-DchXsyfP.mjs.map +0 -1
- package/dist/secret-store-BnY3A50C.mjs.map +0 -1
- package/dist/src-Jsq9LCeH.mjs.map +0 -1
- package/dist/standalone-DKCdrf1d.mjs.map +0 -1
- package/dist/status-IRz7ta8-.mjs +0 -2344
- package/dist/status-IRz7ta8-.mjs.map +0 -1
- package/docker-compose.yml +0 -73
- package/iii-config.docker.yaml +0 -53
- package/iii-config.yaml +0 -63
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# agentmemory for OpenClaw
|
|
2
|
+
|
|
3
|
+
The native plugin recalls relevant project memories before a turn and captures completed user/assistant conversations. It includes the shared AgentMemory skills. Start the AgentMemory backend before testing either capture or recall.
|
|
4
|
+
|
|
5
|
+
## Install and configure
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @agentmemory/agentmemory
|
|
9
|
+
agentmemory connect openclaw --dry-run
|
|
10
|
+
agentmemory connect openclaw
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The connector installs the packaged plugin and its skills before activating it in the native configuration. It honors `OPENCLAW_STATE_DIR`, `OPENCLAW_HOME` and `OPENCLAW_CONFIG_PATH`; the default is `~/.openclaw/openclaw.json`. Use the same environment as the OpenClaw profile you intend to configure. For a named profile, set `OPENCLAW_STATE_DIR` to that profile's state directory before connecting.
|
|
14
|
+
|
|
15
|
+
Setup preserves unrelated settings, supports JSON5, backs up changed configuration and checks managed plugin files before upgrading. A different selected memory provider, disabled conversation access or locally modified installation requires an explicit `--force`. Failed activation rolls back the plugin changes. Authentication is verified only by a successful request after setup.
|
|
16
|
+
|
|
17
|
+
Run `agentmemory` in another terminal, then restart OpenClaw and validate its configuration with `openclaw config validate`. A new conversation should produce an AgentMemory observation; a fresh session in the same profile should recall it.
|
|
18
|
+
|
|
19
|
+
The connector selects `plugins.slots.memory: "agentmemory"` and grants `hooks.allowConversationAccess` for capture. A separately configured `hooks.allowPromptInjection: false` still disables recalled context. Copying the source folder manually does not record native installation provenance; use the connector or the host's installer with a prepared archive.
|
|
20
|
+
|
|
21
|
+
## Credentials
|
|
22
|
+
|
|
23
|
+
`plugins.entries.agentmemory.config.base_url` overrides `AGENTMEMORY_URL`; the default is `http://localhost:3111`. Use HTTPS for a remote backend.
|
|
24
|
+
|
|
25
|
+
For an explicitly scoped credential, set `secret_env` to the **name** of an environment variable supplied to this OpenClaw profile:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"plugins": {
|
|
30
|
+
"entries": {
|
|
31
|
+
"agentmemory": {
|
|
32
|
+
"config": {
|
|
33
|
+
"base_url": "https://memory.example.com",
|
|
34
|
+
"secret_env": "WORK_MEMORY_SECRET"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Keep the value in the host's environment or secret management, not in this configuration. A missing or unresolved named variable never falls back to another key. Without `secret_env`, the plugin uses `AGENTMEMORY_SECRET`, then the local `~/.agentmemory/.env` or generated `~/.agentmemory/secret` for loopback endpoints only. File lookup remains bound to the home where the plugin registered. Remote endpoints require an explicit environment credential.
|
|
43
|
+
|
|
44
|
+
Same-endpoint credential rotations take effect on the next request. Endpoint or credential-variable configuration changes require a plugin reload; an old instance refuses to send a new credential to its previous endpoint. Redirects are refused. `AGENTMEMORY_REQUIRE_HTTPS=1` rejects bearer authentication to remote plaintext HTTP; otherwise that combination warns once.
|
|
45
|
+
|
|
46
|
+
## Profiles and lifecycle
|
|
47
|
+
|
|
48
|
+
Automatic recall and capture derive a stable backend agent identity from the active OpenClaw state directory and native agent ID. Sessions are also namespaced. Two profiles sharing a workspace and backend cannot collide solely because both use the native agent name `main` or the same session key. A new session or restart within the same profile retains its memory scope. Moving a profile directory changes that identity.
|
|
49
|
+
|
|
50
|
+
Project resolution follows `AGENTMEMORY_PROJECT_NAME`, the canonical Git repository name (including linked worktrees), then the workspace basename. Missing workspace or session metadata skips capture/recall with a warning. Automatic recall searches and expands results with both project and profile-agent filters. Legacy unscoped memories and other clients' agent scopes are not automatically included. This is retrieval partitioning, not separate backend authorization or per-sender isolation within a shared gateway profile.
|
|
51
|
+
|
|
52
|
+
The plugin registers only `before_prompt_build` for recall, avoiding duplicate injection on hosts that still expose the older hook. `agent_end` captures the latest completed user/assistant turn, bounded to 1,000 and 4,000 characters respectively. It does not capture individual tool executions. Stable event IDs make duplicate callbacks retryable. Session startup binds the scoped identity before capture, and `session_end` drains pending captures before finalizing a known session.
|
|
53
|
+
|
|
54
|
+
Configuration supports `token_budget` (0 to 32,000; zero disables recall), `min_confidence` (0 to 1), `timeout_ms` (1 to 60,000), and `fallback_on_error`. The token budget bounds the complete injected context at approximately four UTF-8 bytes per token. Fallback warns and lets a turn continue; it does not queue failed captures for later delivery. The memory-slot capability supplies a prompt builder and uses the AgentMemory REST API, rather than implementing OpenClaw's in-process memory runtime.
|
|
55
|
+
|
|
56
|
+
## Optional full MCP tools
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
agentmemory connect openclaw --with-mcp
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This adds `mcp.servers.agentmemory`, pointing to the exact installed package's `dist/standalone.mjs`, with forced proxy mode. Keep that package installation available and rerun setup after moving it. Existing custom MCP settings are preserved unless `--force` is supplied. The connector migrates its recognized older `mcpServers.agentmemory` entry; unrelated legacy entries require separate migration.
|
|
63
|
+
|
|
64
|
+
MCP exposes the full shared backend tool surface. It does not enforce the native plugin's automatic profile filters and is suitable only for a deliberately shared, trusted backend. Skills requiring `memory_*` tools need this connection; native recall/capture itself does not. Verify the tools shown by the host before running a skill. Existing MCP connections are not removed by native-only setup.
|
|
65
|
+
|
|
66
|
+
## Package and verify
|
|
67
|
+
|
|
68
|
+
From a source checkout, build the standalone archive with:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npm run skills:gen
|
|
72
|
+
npm run plugin:pack:openclaw
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This prepares `dist/plugins/agentmemory-<version>.tgz` with plugin metadata, license and all 17 skills including their supporting files. Root `npm pack` also prepares these resources automatically. These commands create local artifacts and do not publish them.
|
|
76
|
+
|
|
77
|
+
The native release gate accepts an installed AgentMemory package and real host binaries:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
node scripts/release-gate/openclaw.mjs \
|
|
81
|
+
--package-root /path/to/node_modules/@agentmemory/agentmemory \
|
|
82
|
+
--node /path/to/node \
|
|
83
|
+
--openclaw-cli /path/to/openclaw/openclaw.mjs \
|
|
84
|
+
--engine /path/to/iii \
|
|
85
|
+
--out /tmp/agentmemory-openclaw-gate
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Repeat `--openclaw-cli` to exercise additional hosts. The deterministic gate inspects model and backend traffic. `scripts/release-gate/openclaw-live.mjs` exercises real model conversations with separate profiles and a backend restart; see `docs/native-integration-tests.md` for its required isolated runtime inputs.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "agentmemory",
|
|
3
|
+
"kind": "memory",
|
|
4
|
+
"name": "agentmemory",
|
|
5
|
+
"description": "Persistent cross-session memory for OpenClaw via agentmemory.",
|
|
6
|
+
"version": "0.9.31",
|
|
7
|
+
"configSchema": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"additionalProperties": false,
|
|
10
|
+
"properties": {
|
|
11
|
+
"enabled": {
|
|
12
|
+
"type": "boolean"
|
|
13
|
+
},
|
|
14
|
+
"base_url": {
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"token_budget": {
|
|
18
|
+
"type": "integer",
|
|
19
|
+
"minimum": 0,
|
|
20
|
+
"maximum": 32000
|
|
21
|
+
},
|
|
22
|
+
"min_confidence": {
|
|
23
|
+
"type": "number",
|
|
24
|
+
"minimum": 0,
|
|
25
|
+
"maximum": 1
|
|
26
|
+
},
|
|
27
|
+
"fallback_on_error": {
|
|
28
|
+
"type": "boolean"
|
|
29
|
+
},
|
|
30
|
+
"timeout_ms": {
|
|
31
|
+
"type": "integer",
|
|
32
|
+
"minimum": 1,
|
|
33
|
+
"maximum": 60000
|
|
34
|
+
},
|
|
35
|
+
"secret_env": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"uiHints": {
|
|
42
|
+
"enabled": {
|
|
43
|
+
"label": "Enabled"
|
|
44
|
+
},
|
|
45
|
+
"base_url": {
|
|
46
|
+
"label": "Base URL",
|
|
47
|
+
"help": "agentmemory REST server base URL"
|
|
48
|
+
},
|
|
49
|
+
"token_budget": {
|
|
50
|
+
"label": "Token Budget",
|
|
51
|
+
"help": "Approximate injected context budget (4 UTF-8 bytes per token); 0 disables recall"
|
|
52
|
+
},
|
|
53
|
+
"min_confidence": {
|
|
54
|
+
"label": "Min Confidence",
|
|
55
|
+
"help": "Minimum normalized retrieval score, between 0 and 1"
|
|
56
|
+
},
|
|
57
|
+
"fallback_on_error": {
|
|
58
|
+
"label": "Fallback On Error"
|
|
59
|
+
},
|
|
60
|
+
"timeout_ms": {
|
|
61
|
+
"label": "Timeout (ms)"
|
|
62
|
+
},
|
|
63
|
+
"secret_env": {
|
|
64
|
+
"label": "Credential environment variable",
|
|
65
|
+
"help": "Name of an environment variable holding this endpoint credential. Setting it disables local credential-file fallback."
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"skills": [
|
|
69
|
+
"./skills"
|
|
70
|
+
]
|
|
71
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentmemory",
|
|
3
|
+
"version": "0.9.31",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"openclaw": {
|
|
6
|
+
"extensions": [
|
|
7
|
+
"./plugin.mjs"
|
|
8
|
+
],
|
|
9
|
+
"compat": {
|
|
10
|
+
"pluginApi": ">=2026.7.1"
|
|
11
|
+
},
|
|
12
|
+
"build": {
|
|
13
|
+
"openclawVersion": "2026.7.1-2"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"description": "Persistent project memory with automatic recall and conversation capture for OpenClaw.",
|
|
17
|
+
"license": "Apache-2.0",
|
|
18
|
+
"homepage": "https://github.com/rohitg00/agentmemory/tree/main/integrations/openclaw",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/rohitg00/agentmemory.git",
|
|
22
|
+
"directory": "integrations/openclaw"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"openclaw",
|
|
26
|
+
"memory",
|
|
27
|
+
"persistent-memory",
|
|
28
|
+
"agentmemory"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
"plugin.mjs",
|
|
32
|
+
"openclaw.plugin.json",
|
|
33
|
+
"plugin.yaml",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE",
|
|
36
|
+
"skills/"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agentmemory plugin for OpenClaw
|
|
3
|
+
*
|
|
4
|
+
* Deeper integration than raw MCP:
|
|
5
|
+
* - claims the plugins.slots.memory slot via api.registerMemoryCapability({ promptBuilder })
|
|
6
|
+
* - recalls relevant memories before the agent starts (before_prompt_build hook)
|
|
7
|
+
* - captures completed conversation turns after the agent finishes (agent_end hook)
|
|
8
|
+
*
|
|
9
|
+
* Requires the agentmemory server on localhost:3111.
|
|
10
|
+
* Start it with: npx @agentmemory/agentmemory
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { execFileSync } from "node:child_process";
|
|
14
|
+
import { createHash } from "node:crypto";
|
|
15
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
18
|
+
|
|
19
|
+
const DEFAULT_BASE_URL = "http://localhost:3111";
|
|
20
|
+
const DEFAULT_TIMEOUT_MS = 5000;
|
|
21
|
+
|
|
22
|
+
const configSchema = {
|
|
23
|
+
type: "object",
|
|
24
|
+
additionalProperties: false,
|
|
25
|
+
properties: {
|
|
26
|
+
enabled: { type: "boolean" },
|
|
27
|
+
base_url: { type: "string" },
|
|
28
|
+
secret_env: { type: "string", pattern: "^[A-Za-z_][A-Za-z0-9_]*$" },
|
|
29
|
+
token_budget: { type: "integer", minimum: 0, maximum: 32000 },
|
|
30
|
+
min_confidence: { type: "number", minimum: 0, maximum: 1 },
|
|
31
|
+
fallback_on_error: { type: "boolean" },
|
|
32
|
+
timeout_ms: { type: "integer", minimum: 1, maximum: 60000 },
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function extractText(content) {
|
|
37
|
+
if (typeof content === "string") return content;
|
|
38
|
+
if (!Array.isArray(content)) return "";
|
|
39
|
+
return content
|
|
40
|
+
.flatMap((block) => {
|
|
41
|
+
if (!block || typeof block !== "object") return [];
|
|
42
|
+
if (block.type === "text" && typeof block.text === "string") return [block.text];
|
|
43
|
+
return [];
|
|
44
|
+
})
|
|
45
|
+
.join("\n")
|
|
46
|
+
.trim();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function lastAssistantText(messages) {
|
|
50
|
+
for (const message of [...messages].reverse()) {
|
|
51
|
+
if (!message || typeof message !== "object") continue;
|
|
52
|
+
if (message.role === "user") break;
|
|
53
|
+
if (message.role !== "assistant") continue;
|
|
54
|
+
const text = extractText(message.content);
|
|
55
|
+
if (text) return text;
|
|
56
|
+
}
|
|
57
|
+
return "";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function latestUserText(messages) {
|
|
61
|
+
for (const message of [...messages].reverse()) {
|
|
62
|
+
if (!message || typeof message !== "object") continue;
|
|
63
|
+
if (message.role !== "user") continue;
|
|
64
|
+
return extractText(message.content);
|
|
65
|
+
}
|
|
66
|
+
return "";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function resolveProject(cwd) {
|
|
70
|
+
const explicit = process.env.AGENTMEMORY_PROJECT_NAME?.trim();
|
|
71
|
+
if (explicit) return explicit;
|
|
72
|
+
try {
|
|
73
|
+
const [top, gitDir, commonDir] = execFileSync("git", ["rev-parse", "--show-toplevel", "--git-dir", "--git-common-dir"], {
|
|
74
|
+
cwd, stdio: ["ignore", "pipe", "ignore"], timeout: 500, encoding: "utf8",
|
|
75
|
+
}).trim().split(/\r?\n/);
|
|
76
|
+
if (top) {
|
|
77
|
+
const physical = realpathSync(cwd);
|
|
78
|
+
const common = resolve(physical, commonDir || ".git");
|
|
79
|
+
return basename(gitDir && commonDir && resolve(physical, gitDir) !== common && basename(common) === ".git" ? dirname(common) : top);
|
|
80
|
+
}
|
|
81
|
+
} catch {}
|
|
82
|
+
return basename(cwd) || cwd;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function profileNamespace(api) {
|
|
86
|
+
const expand = (value, home) => resolve(value.replace(/^~(?=$|[/\\])/, () => home));
|
|
87
|
+
const home = expand(process.env.OPENCLAW_HOME?.trim() || homedir(), homedir());
|
|
88
|
+
const preferred = join(home, ".openclaw");
|
|
89
|
+
const legacy = join(home, ".clawdbot");
|
|
90
|
+
const fallback = process.env.OPENCLAW_STATE_DIR?.trim()
|
|
91
|
+
? expand(process.env.OPENCLAW_STATE_DIR.trim(), home)
|
|
92
|
+
: !existsSync(preferred) && existsSync(legacy) ? legacy : preferred;
|
|
93
|
+
let canonical = resolve(api.runtime?.state?.resolveStateDir?.() || fallback);
|
|
94
|
+
try { canonical = realpathSync(canonical); } catch {}
|
|
95
|
+
return createHash("sha256").update(canonical).digest("hex").slice(0, 24);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function nativeAgent(event, ctx = {}) {
|
|
99
|
+
return [ctx.agentId, event?.agentId, process.env.AGENT_ID]
|
|
100
|
+
.find((value) => typeof value === "string" && value.trim())?.trim() || "main";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function nativeContext(event, ctx = {}, namespace) {
|
|
104
|
+
const string = (...values) => values.find((value) => typeof value === "string" && value.trim())?.trim();
|
|
105
|
+
const cwd = string(ctx.workspaceDir, event?.workspaceDir, event?.cwd);
|
|
106
|
+
const sessionId = string(ctx.sessionId, ctx.sessionKey, event?.sessionId, event?.sessionKey);
|
|
107
|
+
if (!cwd || !sessionId) return null;
|
|
108
|
+
const agent = nativeAgent(event, ctx);
|
|
109
|
+
const agentId = "openclaw-" + createHash("sha256").update(JSON.stringify([namespace, agent])).digest("hex");
|
|
110
|
+
const scopedSession = "openclaw-" + createHash("sha256").update(JSON.stringify([namespace, agent, sessionId])).digest("hex");
|
|
111
|
+
return { cwd, project: resolveProject(cwd), sessionId: scopedSession, agentId };
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function formatResults(results) {
|
|
116
|
+
if (!Array.isArray(results) || results.length === 0) return "";
|
|
117
|
+
return results
|
|
118
|
+
.slice(0, 5)
|
|
119
|
+
.map((result, index) => {
|
|
120
|
+
const obs = result?.observation ?? result ?? {};
|
|
121
|
+
const title = typeof obs.title === "string" ? obs.title.trim() : `Memory ${index + 1}`;
|
|
122
|
+
const narrative = typeof obs.narrative === "string" ? obs.narrative.trim() : "";
|
|
123
|
+
const type = typeof obs.type === "string" ? obs.type.trim() : "memory";
|
|
124
|
+
return `- ${title} (${type})${narrative ? `: ${narrative}` : ""}`;
|
|
125
|
+
})
|
|
126
|
+
.join("\n");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function boundedContext(block, budget) {
|
|
130
|
+
const text = `Relevant long-term memory from agentmemory (untrusted background):\n${block}`;
|
|
131
|
+
const maxBytes = budget * 4;
|
|
132
|
+
let used = 0;
|
|
133
|
+
let result = "";
|
|
134
|
+
for (const character of text) {
|
|
135
|
+
used += Buffer.byteLength(character, "utf8");
|
|
136
|
+
if (used > maxBytes) break;
|
|
137
|
+
result += character;
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function usesPlaintextBearerAuth(baseUrl, secret) {
|
|
143
|
+
if (!secret) return false;
|
|
144
|
+
try {
|
|
145
|
+
const parsed = new URL(baseUrl);
|
|
146
|
+
return parsed.protocol === "http:" && !isLoopbackUrl(baseUrl);
|
|
147
|
+
} catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function plaintextBearerAuthMessage(baseUrl) {
|
|
153
|
+
return `agentmemory: AGENTMEMORY_SECRET is configured for plaintext HTTP to ${baseUrl}. Bearer tokens and memory payloads can be observed on the network; use HTTPS or an SSH tunnel.`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function createPlaintextBearerAuthGuard(warn, env) {
|
|
157
|
+
let warned = false;
|
|
158
|
+
return function guardPlaintextBearerAuth(baseUrl, secret) {
|
|
159
|
+
if (!usesPlaintextBearerAuth(baseUrl, secret)) return;
|
|
160
|
+
const message = plaintextBearerAuthMessage(baseUrl);
|
|
161
|
+
if ((env || process.env).AGENTMEMORY_REQUIRE_HTTPS === "1") throw new Error(message);
|
|
162
|
+
if (!warned) {
|
|
163
|
+
warned = true;
|
|
164
|
+
warn(message);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function usableSecret(value) {
|
|
170
|
+
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
171
|
+
if (!trimmed || (trimmed.startsWith("${") && trimmed.endsWith("}"))) return "";
|
|
172
|
+
return trimmed;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function readAgentmemoryFile(name, home = homedir()) {
|
|
176
|
+
try {
|
|
177
|
+
return readFileSync(join(home, ".agentmemory", name), "utf-8");
|
|
178
|
+
} catch {
|
|
179
|
+
return "";
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function envFileSecret(home) {
|
|
184
|
+
let found = "";
|
|
185
|
+
for (const line of readAgentmemoryFile(".env", home).split("\n")) {
|
|
186
|
+
const trimmed = line.trim();
|
|
187
|
+
if (trimmed.startsWith("#")) continue;
|
|
188
|
+
const eq = trimmed.indexOf("=");
|
|
189
|
+
if (eq === -1) continue;
|
|
190
|
+
if (trimmed.slice(0, eq).replace(/^export\s+/, "").trim() !== "AGENTMEMORY_SECRET") continue;
|
|
191
|
+
let value = trimmed.slice(eq + 1).trim();
|
|
192
|
+
const quote = value[0];
|
|
193
|
+
const close = quote === '"' || quote === "'" ? value.indexOf(quote, 1) : -1;
|
|
194
|
+
if (close > 0) value = value.slice(1, close);
|
|
195
|
+
else if (value.includes(" #")) value = value.slice(0, value.indexOf(" #"));
|
|
196
|
+
found = usableSecret(value);
|
|
197
|
+
}
|
|
198
|
+
return found;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function isLoopbackUrl(url) {
|
|
202
|
+
try {
|
|
203
|
+
const host = new URL(url).hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
204
|
+
return host === "localhost" || host === "::1" || /^127(?:\.\d{1,3}){3}$/.test(host);
|
|
205
|
+
} catch {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function resolveSecret(url, explicit, home = homedir()) {
|
|
211
|
+
const configured = usableSecret(explicit);
|
|
212
|
+
if (configured) return configured;
|
|
213
|
+
if (!isLoopbackUrl(url)) return "";
|
|
214
|
+
return envFileSecret(home) || usableSecret(readAgentmemoryFile("secret", home));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function createClient(cfg, api) {
|
|
218
|
+
const baseUrl = String(cfg.base_url || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
219
|
+
let parsed;
|
|
220
|
+
try { parsed = new URL(baseUrl); } catch {}
|
|
221
|
+
if (!parsed || !["http:", "https:"].includes(parsed.protocol) || parsed.username || parsed.password || /[?#]/.test(baseUrl)) {
|
|
222
|
+
throw new Error("agentmemory: base_url must be an HTTP(S) URL without credentials, query, or fragment");
|
|
223
|
+
}
|
|
224
|
+
const timeoutMs = Number(cfg.timeout_ms || DEFAULT_TIMEOUT_MS);
|
|
225
|
+
const fallbackOnError = cfg.fallback_on_error !== false;
|
|
226
|
+
const credentialHome = homedir();
|
|
227
|
+
const secret = () => {
|
|
228
|
+
const currentUrl = String(api.pluginConfig?.base_url || process.env.AGENTMEMORY_URL || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
229
|
+
if (currentUrl !== baseUrl || api.pluginConfig?.secret_env !== cfg.secret_env) {
|
|
230
|
+
throw new Error("agentmemory: endpoint or credential configuration changed; reload the plugin before using its credentials");
|
|
231
|
+
}
|
|
232
|
+
return cfg.secret_env ? usableSecret(process.env[cfg.secret_env]) : resolveSecret(baseUrl, process.env.AGENTMEMORY_SECRET, credentialHome);
|
|
233
|
+
};
|
|
234
|
+
const guardPlaintextBearerAuth = createPlaintextBearerAuthGuard(
|
|
235
|
+
(message) => api.logger.warn?.(message),
|
|
236
|
+
);
|
|
237
|
+
if (process.env.AGENTMEMORY_REQUIRE_HTTPS === "1") {
|
|
238
|
+
guardPlaintextBearerAuth(baseUrl, secret());
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function postJson(path, payload) {
|
|
242
|
+
const token = secret();
|
|
243
|
+
guardPlaintextBearerAuth(baseUrl, token);
|
|
244
|
+
const headers = { "Content-Type": "application/json" };
|
|
245
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
246
|
+
let failure = `agentmemory ${path} failed: network or invalid response`;
|
|
247
|
+
try {
|
|
248
|
+
const res = await fetch(`${baseUrl}${path}`, {
|
|
249
|
+
method: "POST",
|
|
250
|
+
headers,
|
|
251
|
+
body: JSON.stringify(payload),
|
|
252
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
253
|
+
redirect: "error",
|
|
254
|
+
});
|
|
255
|
+
if (!res.ok) {
|
|
256
|
+
failure = `agentmemory ${path} failed: HTTP ${res.status}`;
|
|
257
|
+
throw new Error(failure);
|
|
258
|
+
}
|
|
259
|
+
return await res.json();
|
|
260
|
+
} catch (error) {
|
|
261
|
+
if (!fallbackOnError) throw new Error(failure);
|
|
262
|
+
api.logger.warn?.(failure);
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return { postJson, baseUrl };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const plugin = {
|
|
271
|
+
id: "agentmemory",
|
|
272
|
+
name: "agentmemory",
|
|
273
|
+
description: "Shared cross-session memory via the local agentmemory server.",
|
|
274
|
+
configSchema,
|
|
275
|
+
register(api) {
|
|
276
|
+
const cfg = {
|
|
277
|
+
enabled: api.pluginConfig?.enabled !== false,
|
|
278
|
+
secret_env: api.pluginConfig?.secret_env,
|
|
279
|
+
base_url: api.pluginConfig?.base_url || process.env.AGENTMEMORY_URL || DEFAULT_BASE_URL,
|
|
280
|
+
token_budget: api.pluginConfig?.token_budget ?? 2000,
|
|
281
|
+
min_confidence: api.pluginConfig?.min_confidence ?? 0.5,
|
|
282
|
+
fallback_on_error: api.pluginConfig?.fallback_on_error !== false,
|
|
283
|
+
timeout_ms: api.pluginConfig?.timeout_ms ?? DEFAULT_TIMEOUT_MS,
|
|
284
|
+
};
|
|
285
|
+
if (!cfg.enabled) return;
|
|
286
|
+
if (cfg.secret_env !== undefined && (typeof cfg.secret_env !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(cfg.secret_env))) {
|
|
287
|
+
throw new Error("agentmemory: invalid secret_env");
|
|
288
|
+
}
|
|
289
|
+
const namespace = profileNamespace(api);
|
|
290
|
+
if (!Number.isInteger(cfg.token_budget) || cfg.token_budget < 0 || cfg.token_budget > 32000 ||
|
|
291
|
+
!Number.isFinite(cfg.min_confidence) || cfg.min_confidence < 0 || cfg.min_confidence > 1 ||
|
|
292
|
+
!Number.isInteger(cfg.timeout_ms) || cfg.timeout_ms < 1 || cfg.timeout_ms > 60000) {
|
|
293
|
+
throw new Error("agentmemory: invalid token_budget, min_confidence, or timeout_ms");
|
|
294
|
+
}
|
|
295
|
+
const client = createClient(cfg, api);
|
|
296
|
+
|
|
297
|
+
if (typeof api.registerMemoryCapability === "function") {
|
|
298
|
+
api.registerMemoryCapability({
|
|
299
|
+
// OpenClaw passes { availableTools: Set<string>, citationsMode? }. We
|
|
300
|
+
// don't currently branch on tool availability, but accept the params
|
|
301
|
+
// object so the signature matches MemoryPromptSectionBuilder exactly.
|
|
302
|
+
promptBuilder: (_params) => [
|
|
303
|
+
"Long-term memory provider: agentmemory (external REST service on " +
|
|
304
|
+
client.baseUrl +
|
|
305
|
+
").",
|
|
306
|
+
"agentmemory recalls relevant prior observations before each turn via the before_prompt_build hook and captures completed turns via agent_end.",
|
|
307
|
+
"Treat recalled context as background, not authoritative — prefer current workspace state and explicit user instructions when they conflict.",
|
|
308
|
+
],
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const recall = async (event, ctx) => {
|
|
313
|
+
if (!cfg.enabled || cfg.token_budget === 0) return;
|
|
314
|
+
const prompt = typeof event?.prompt === "string" ? event.prompt.trim() : "";
|
|
315
|
+
if (!prompt) return;
|
|
316
|
+
const identity = nativeContext(event, ctx, namespace);
|
|
317
|
+
if (!identity) {
|
|
318
|
+
api.logger.warn?.("agentmemory: recall skipped because native session/workspace metadata is missing");
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const scope = { project: identity.project, agentId: identity.agentId,
|
|
322
|
+
sessionId: identity.sessionId, source: "openclaw" };
|
|
323
|
+
const result = await client.postJson("/agentmemory/smart-search", {
|
|
324
|
+
query: prompt, limit: 5, includeLessons: false, ...scope,
|
|
325
|
+
});
|
|
326
|
+
const ids = (Array.isArray(result?.results) ? result.results : [])
|
|
327
|
+
.filter((item) => typeof item?.obsId === "string" && Number.isFinite(item.score) && item.score >= cfg.min_confidence)
|
|
328
|
+
.slice(0, 5)
|
|
329
|
+
.map((item) => ({ obsId: item.obsId, ...(item.sessionId ? { sessionId: item.sessionId } : {}) }));
|
|
330
|
+
if (!ids.length) return;
|
|
331
|
+
const expanded = await client.postJson("/agentmemory/smart-search", { expandIds: ids, ...scope });
|
|
332
|
+
const block = formatResults(expanded?.results || []);
|
|
333
|
+
if (!block) return;
|
|
334
|
+
return { prependContext: boundedContext(block, cfg.token_budget) };
|
|
335
|
+
};
|
|
336
|
+
api.on("before_prompt_build", recall);
|
|
337
|
+
|
|
338
|
+
const startedSessions = new Map();
|
|
339
|
+
const captures = new Map();
|
|
340
|
+
const sessionAliases = new Map();
|
|
341
|
+
const capture = async (event, ctx) => {
|
|
342
|
+
if (!cfg.enabled || !event?.success || !Array.isArray(event.messages)) return;
|
|
343
|
+
const userText = latestUserText(event.messages);
|
|
344
|
+
const assistantText = lastAssistantText(event.messages);
|
|
345
|
+
if (!userText || !assistantText) return;
|
|
346
|
+
const identity = nativeContext(event, ctx, namespace);
|
|
347
|
+
if (!identity) {
|
|
348
|
+
api.logger.warn?.("agentmemory: capture skipped because native session/workspace metadata is missing");
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const key = JSON.stringify(identity);
|
|
352
|
+
let starting = startedSessions.get(key);
|
|
353
|
+
if (!starting) {
|
|
354
|
+
starting = client.postJson("/agentmemory/session/start", identity);
|
|
355
|
+
startedSessions.set(key, starting);
|
|
356
|
+
if (startedSessions.size > 256) startedSessions.delete(startedSessions.keys().next().value);
|
|
357
|
+
}
|
|
358
|
+
let started;
|
|
359
|
+
try {
|
|
360
|
+
started = await starting;
|
|
361
|
+
} catch (error) {
|
|
362
|
+
if (startedSessions.get(key) === starting) startedSessions.delete(key);
|
|
363
|
+
throw error;
|
|
364
|
+
}
|
|
365
|
+
if (started?.session?.id !== identity.sessionId) {
|
|
366
|
+
if (startedSessions.get(key) === starting) startedSessions.delete(key);
|
|
367
|
+
if (started) api.logger.warn?.("agentmemory: capture skipped because session startup did not confirm the requested session");
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const eventId = "openclaw-" + createHash("sha256").update(JSON.stringify([
|
|
371
|
+
identity, ctx?.runId || event.runId || null, event.messages.length, userText, assistantText,
|
|
372
|
+
])).digest("hex");
|
|
373
|
+
await client.postJson("/agentmemory/observe", {
|
|
374
|
+
hookType: "post_tool_use",
|
|
375
|
+
...identity,
|
|
376
|
+
eventId,
|
|
377
|
+
timestamp: new Date().toISOString(),
|
|
378
|
+
data: {
|
|
379
|
+
tool_name: "conversation",
|
|
380
|
+
tool_input: userText.slice(0, 1000),
|
|
381
|
+
tool_output: assistantText.slice(0, 4000),
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
};
|
|
385
|
+
api.on("agent_end", async (event, ctx) => {
|
|
386
|
+
const identity = nativeContext(event, ctx, namespace);
|
|
387
|
+
const task = capture(event, ctx);
|
|
388
|
+
if (!identity) return task;
|
|
389
|
+
const aliases = [ctx?.sessionId, ctx?.sessionKey, event?.sessionId, event?.sessionKey]
|
|
390
|
+
.filter((value) => typeof value === "string" && value.trim()).map((value) => value.trim());
|
|
391
|
+
sessionAliases.set(identity.sessionId, { aliases, nativeAgent: nativeAgent(event, ctx) });
|
|
392
|
+
if (sessionAliases.size > 1024) {
|
|
393
|
+
const idle = [...sessionAliases.keys()].find((id) => id !== identity.sessionId && !captures.has(id));
|
|
394
|
+
if (idle) sessionAliases.delete(idle);
|
|
395
|
+
}
|
|
396
|
+
const pending = captures.get(identity.sessionId) || new Set();
|
|
397
|
+
pending.add(task);
|
|
398
|
+
captures.set(identity.sessionId, pending);
|
|
399
|
+
try { return await task; }
|
|
400
|
+
finally {
|
|
401
|
+
pending.delete(task);
|
|
402
|
+
if (!pending.size) captures.delete(identity.sessionId);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
api.on("session_end", async (event, ctx) => {
|
|
406
|
+
const candidates = [ctx?.sessionId, event?.sessionId, ctx?.sessionKey, event?.sessionKey]
|
|
407
|
+
.filter((value) => typeof value === "string" && value.trim()).map((value) => value.trim());
|
|
408
|
+
const agent = ctx?.agentId || event?.agentId ? nativeAgent(event, ctx) : undefined;
|
|
409
|
+
const matching = [...sessionAliases].filter(([, value]) =>
|
|
410
|
+
(!agent || value.nativeAgent === agent) && candidates.some((id) => value.aliases.includes(id)));
|
|
411
|
+
if (matching.length !== 1) return;
|
|
412
|
+
const sessionId = matching[0][0];
|
|
413
|
+
await Promise.allSettled([...(captures.get(sessionId) || [])]);
|
|
414
|
+
const result = await client.postJson("/agentmemory/session/end", { sessionId, final: true });
|
|
415
|
+
if (result) {
|
|
416
|
+
sessionAliases.delete(sessionId);
|
|
417
|
+
for (const key of startedSessions.keys()) {
|
|
418
|
+
if (JSON.parse(key).sessionId === sessionId) startedSessions.delete(key);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
export default plugin;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: agentmemory
|
|
2
|
+
version: 0.9.31
|
|
3
|
+
description: "Persistent cross-session memory for OpenClaw via agentmemory."
|
|
4
|
+
author: "Rohit Ghumare"
|
|
5
|
+
homepage: "https://github.com/rohitg00/agentmemory"
|
|
6
|
+
license: Apache-2.0
|
|
7
|
+
|
|
8
|
+
category: memory
|
|
9
|
+
tags:
|
|
10
|
+
- memory
|
|
11
|
+
- persistence
|
|
12
|
+
- mcp
|
|
13
|
+
- context
|
|
14
|
+
|
|
15
|
+
hooks:
|
|
16
|
+
- before_prompt_build
|
|
17
|
+
- agent_end
|
|
18
|
+
- session_end
|
|
19
|
+
|
|
20
|
+
config:
|
|
21
|
+
enabled: true
|
|
22
|
+
base_url: http://localhost:3111
|
|
23
|
+
token_budget: 2000
|
|
24
|
+
min_confidence: 0.5
|
|
25
|
+
fallback_on_error: true
|
|
26
|
+
timeout_ms: 5000
|