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