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