@agentmemory/agentmemory 0.9.29 → 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 +102 -35
- package/AGENTS.md +19 -26
- package/README.md +417 -525
- package/dist/.env.example +102 -35
- package/dist/cli.d.mts.map +1 -1
- package/dist/cli.mjs +2316 -655
- 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-Qaeq15TQ.mjs → connect-BSLIAMpw.mjs} +900 -302
- package/dist/connect-BSLIAMpw.mjs.map +1 -0
- package/dist/hooks/_capture.d.mts +25 -0
- package/dist/hooks/_capture.d.mts.map +1 -0
- package/dist/hooks/_capture.mjs +944 -0
- package/dist/hooks/_capture.mjs.map +1 -0
- package/dist/hooks/antigravity-bridge.d.mts +1 -1
- package/dist/hooks/antigravity-bridge.d.mts.map +1 -1
- package/dist/hooks/antigravity-bridge.mjs +24 -15
- package/dist/hooks/antigravity-bridge.mjs.map +1 -1
- package/dist/hooks/notification.mjs +35 -29
- package/dist/hooks/notification.mjs.map +1 -1
- package/dist/hooks/post-commit.mjs +91 -1
- package/dist/hooks/post-commit.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +71 -29
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +99 -39
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +113 -6
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +91 -1
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/prompt-submit.mjs +25 -25
- package/dist/hooks/prompt-submit.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +67 -31
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +110 -6
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +80 -8
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-start.mjs +28 -29
- package/dist/hooks/subagent-start.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +33 -29
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +31 -31
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/{image-refs-BKLmp_sD.mjs → image-refs-BaT-9oMU.mjs} +2 -2
- package/dist/image-refs-BaT-9oMU.mjs.map +1 -0
- package/dist/{image-refs-CJgZmb9X.mjs → image-refs-Cyta4Lf9.mjs} +3 -3
- package/dist/image-refs-Cyta4Lf9.mjs.map +1 -0
- package/dist/{keyed-mutex-DTHtcZrt.mjs → image-store-BsN4vyjr.mjs} +2 -14
- package/dist/image-store-BsN4vyjr.mjs.map +1 -0
- package/dist/index.mjs +15180 -4119
- 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/{schema-BFZhNTF7.mjs → keyed-mutex-DCUh7PG-.mjs} +81 -8
- package/dist/keyed-mutex-DCUh7PG-.mjs.map +1 -0
- package/dist/secret-store-D9GwO0xp.mjs +2449 -0
- 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-G7yt8gGm.mjs → src-DaMtDzt_.mjs} +8320 -4260
- package/dist/src-DaMtDzt_.mjs.map +1 -0
- package/dist/{standalone-BqNJDJ04.mjs → standalone-BlqshyZ5.mjs} +246 -62
- 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 +866 -78
- package/dist/standalone.mjs.map +1 -1
- package/dist/viewer/index.html +7394 -2816
- 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 +139 -173
- package/integrations/pi/package.json +16 -6
- package/integrations/pi/security.ts +54 -22
- 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 +42 -12
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.codex-plugin/plugin.json +27 -4
- package/plugin/.devin-plugin/plugin.json +5 -3
- package/plugin/.mcp.codex.json +12 -0
- package/plugin/.mcp.copilot.json +2 -7
- package/plugin/.mcp.json +2 -7
- package/plugin/assets/icon.svg +35 -0
- package/plugin/cursor/hooks.json +23 -8
- package/plugin/hooks/hooks.copilot.json +11 -11
- package/plugin/hooks.json +67 -0
- package/plugin/opencode/README.md +267 -31
- package/plugin/opencode/agentmemory-capture.ts +594 -11
- package/plugin/opencode/plugin.json +1 -1
- package/plugin/plugin.json +1 -1
- package/plugin/scripts/_capture.d.mts +25 -0
- package/plugin/scripts/_capture.d.mts.map +1 -0
- package/plugin/scripts/_capture.mjs +944 -0
- package/plugin/scripts/_capture.mjs.map +1 -0
- package/plugin/scripts/antigravity-bridge.d.mts +1 -1
- package/plugin/scripts/antigravity-bridge.d.mts.map +1 -1
- package/plugin/scripts/antigravity-bridge.mjs +24 -15
- package/plugin/scripts/antigravity-bridge.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 +35 -29
- package/plugin/scripts/notification.mjs.map +1 -1
- package/plugin/scripts/plugin-bridge.mjs +409 -0
- package/plugin/scripts/post-commit.mjs +91 -1
- package/plugin/scripts/post-commit.mjs.map +1 -1
- package/plugin/scripts/post-tool-failure.mjs +71 -29
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +99 -39
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +113 -6
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +91 -1
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/prompt-submit.mjs +25 -25
- package/plugin/scripts/prompt-submit.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +67 -31
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +110 -6
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +80 -8
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-start.mjs +28 -29
- package/plugin/scripts/subagent-start.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +33 -29
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +31 -31
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/plugin/skills/_shared/TROUBLESHOOTING.md +42 -12
- package/plugin/skills/agentmemory-agents/REFERENCE.md +10 -9
- 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 +48 -3
- package/plugin/skills/agentmemory-config/SKILL.md +51 -10
- 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 +5 -5
- 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 +18 -2
- 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 +13 -6
- 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 +14 -6
- 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-Qaeq15TQ.mjs.map +0 -1
- package/dist/docker-compose.yml +0 -47
- package/dist/iii-config.docker.yaml +0 -53
- package/dist/iii-config.yaml +0 -61
- package/dist/image-refs-BKLmp_sD.mjs.map +0 -1
- package/dist/image-refs-CJgZmb9X.mjs.map +0 -1
- package/dist/keyed-mutex-DTHtcZrt.mjs.map +0 -1
- package/dist/logger-BEB7pCI9.mjs +0 -43
- package/dist/logger-BEB7pCI9.mjs.map +0 -1
- package/dist/schema-BFZhNTF7.mjs.map +0 -1
- package/dist/src-G7yt8gGm.mjs.map +0 -1
- package/dist/standalone-BqNJDJ04.mjs.map +0 -1
- package/dist/tools-registry-BV_2bu7z.mjs +0 -1405
- package/dist/tools-registry-BV_2bu7z.mjs.map +0 -1
- package/docker-compose.yml +0 -47
- package/iii-config.docker.yaml +0 -53
- package/iii-config.yaml +0 -61
|
@@ -0,0 +1,786 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { execSync, spawn, spawnSync } from "node:child_process";
|
|
4
|
+
import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
7
|
+
import { homedir, tmpdir } from "node:os";
|
|
8
|
+
//#region src/hooks/_project.ts
|
|
9
|
+
function resolveProject(cwd) {
|
|
10
|
+
const explicit = process.env["AGENTMEMORY_PROJECT_NAME"];
|
|
11
|
+
if (explicit && explicit.trim()) return explicit.trim();
|
|
12
|
+
const dir = cwd && cwd.trim() ? cwd : process.cwd();
|
|
13
|
+
try {
|
|
14
|
+
const [top, gitDir, commonDir] = execSync("git rev-parse --show-toplevel --git-dir --git-common-dir", {
|
|
15
|
+
cwd: dir,
|
|
16
|
+
stdio: [
|
|
17
|
+
"ignore",
|
|
18
|
+
"pipe",
|
|
19
|
+
"ignore"
|
|
20
|
+
],
|
|
21
|
+
timeout: 500
|
|
22
|
+
}).toString().trim().split(/\r?\n/);
|
|
23
|
+
if (top) return basename(repositoryRoot(dir, top, gitDir, commonDir));
|
|
24
|
+
} catch {}
|
|
25
|
+
return basename(dir);
|
|
26
|
+
}
|
|
27
|
+
function repositoryRoot(dir, top, gitDir, commonDir) {
|
|
28
|
+
if (!gitDir || !commonDir) return top;
|
|
29
|
+
const physical = realpathSync(dir);
|
|
30
|
+
const common = resolve(physical, commonDir);
|
|
31
|
+
if (resolve(physical, gitDir) === common || basename(common) !== ".git") return top;
|
|
32
|
+
return dirname(common);
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/hooks/cursor/cursor-db.ts
|
|
36
|
+
/**
|
|
37
|
+
* Exact session -> workspace lookup from Cursor's own SQLite storage.
|
|
38
|
+
*
|
|
39
|
+
* Everything else in the resolver infers the workspace: from payload fields
|
|
40
|
+
* Cursor may or may not send, from paths that happen to appear in tool
|
|
41
|
+
* arguments, from a transcript directory name whose path separators have been
|
|
42
|
+
* flattened into hyphens. Those work, but they are inference, and inference
|
|
43
|
+
* that lands on the wrong project writes a user's memories into the wrong
|
|
44
|
+
* place without ever reporting an error.
|
|
45
|
+
*
|
|
46
|
+
* Cursor knows the answer exactly, and stores it. The layout (reverse
|
|
47
|
+
* engineered; see integrations/cursor/README.md for the full picture):
|
|
48
|
+
*
|
|
49
|
+
* <userdir>/globalStorage/state.vscdb
|
|
50
|
+
* ItemTable["composer.composerHeaders"]
|
|
51
|
+
* -> { allComposers: [ { composerId, workspaceIdentifier: {
|
|
52
|
+
* id, uri: { fsPath, ... } } } ] }
|
|
53
|
+
*
|
|
54
|
+
* A Cursor hook's `session_id` is the `composerId`, so one indexed lookup
|
|
55
|
+
* gives the workspace path with no guessing.
|
|
56
|
+
*
|
|
57
|
+
* Two things stop this from being the only strategy:
|
|
58
|
+
*
|
|
59
|
+
* - Cursor 3.0 (April 2026) moved this index from per-workspace databases
|
|
60
|
+
* into the global one, and the migration is lazy: a workspace migrates
|
|
61
|
+
* when it is next opened. Machines still on <=2.6, or with workspaces not
|
|
62
|
+
* opened since the upgrade, keep the old per-workspace `allComposers`
|
|
63
|
+
* array instead. Both shapes are handled below.
|
|
64
|
+
* - Reading SQLite needs a driver. `node:sqlite` only exists from Node 22.5,
|
|
65
|
+
* and this package supports Node >=20. better-sqlite3 is an optional
|
|
66
|
+
* dependency of the daemon, not something a hook can count on.
|
|
67
|
+
*
|
|
68
|
+
* So every failure path here returns null and the caller falls back to
|
|
69
|
+
* inference. This module is an accuracy upgrade, never a requirement.
|
|
70
|
+
*/
|
|
71
|
+
const require = createRequire(import.meta.url);
|
|
72
|
+
let driverCache;
|
|
73
|
+
let warningFilterInstalled = false;
|
|
74
|
+
function suppressSqliteExperimentalWarning() {
|
|
75
|
+
if (warningFilterInstalled) return;
|
|
76
|
+
warningFilterInstalled = true;
|
|
77
|
+
const previous = process.listeners("warning");
|
|
78
|
+
process.removeAllListeners("warning");
|
|
79
|
+
process.on("warning", (warning) => {
|
|
80
|
+
if (warning.name === "ExperimentalWarning" && /sqlite/i.test(warning.message)) return;
|
|
81
|
+
for (const listener of previous) listener(warning);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function requireQuietly(id) {
|
|
85
|
+
suppressSqliteExperimentalWarning();
|
|
86
|
+
try {
|
|
87
|
+
return require(id);
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function loadDriver() {
|
|
93
|
+
if (driverCache !== void 0) return driverCache;
|
|
94
|
+
const nodeSqlite = requireQuietly("node:sqlite");
|
|
95
|
+
if (nodeSqlite?.DatabaseSync) {
|
|
96
|
+
driverCache = { open: (path) => new nodeSqlite.DatabaseSync(path, { readOnly: true }) };
|
|
97
|
+
return driverCache;
|
|
98
|
+
}
|
|
99
|
+
const better = requireQuietly("better-sqlite3");
|
|
100
|
+
if (better) {
|
|
101
|
+
driverCache = { open: (path) => new better(path, {
|
|
102
|
+
readonly: true,
|
|
103
|
+
fileMustExist: true
|
|
104
|
+
}) };
|
|
105
|
+
return driverCache;
|
|
106
|
+
}
|
|
107
|
+
driverCache = null;
|
|
108
|
+
return driverCache;
|
|
109
|
+
}
|
|
110
|
+
/** Read one ItemTable value. Returns null for any failure, including a locked DB. */
|
|
111
|
+
function readItemTableValue(dbPath, key) {
|
|
112
|
+
if (!existsSync(dbPath)) return null;
|
|
113
|
+
const driver = loadDriver();
|
|
114
|
+
if (!driver) return null;
|
|
115
|
+
let db = null;
|
|
116
|
+
try {
|
|
117
|
+
db = driver.open(dbPath);
|
|
118
|
+
const value = db.prepare("SELECT value FROM ItemTable WHERE key = ?").get(key)?.value;
|
|
119
|
+
if (typeof value === "string") return value;
|
|
120
|
+
if (value instanceof Uint8Array) return Buffer.from(value).toString("utf-8");
|
|
121
|
+
return null;
|
|
122
|
+
} catch {
|
|
123
|
+
return null;
|
|
124
|
+
} finally {
|
|
125
|
+
try {
|
|
126
|
+
db?.close();
|
|
127
|
+
} catch {}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function cursorStorageRoots() {
|
|
131
|
+
const home = homedir();
|
|
132
|
+
const bases = [];
|
|
133
|
+
if (process.platform === "win32") {
|
|
134
|
+
const appData = process.env["APPDATA"];
|
|
135
|
+
if (appData) bases.push(join(appData, "Cursor", "User"));
|
|
136
|
+
bases.push(join(home, "AppData", "Roaming", "Cursor", "User"));
|
|
137
|
+
} else if (process.platform === "darwin") bases.push(join(home, "Library", "Application Support", "Cursor", "User"));
|
|
138
|
+
else {
|
|
139
|
+
const configHome = process.env["XDG_CONFIG_HOME"];
|
|
140
|
+
if (configHome) bases.push(join(configHome, "Cursor", "User"));
|
|
141
|
+
bases.push(join(home, ".config", "Cursor", "User"));
|
|
142
|
+
}
|
|
143
|
+
for (const base of bases) {
|
|
144
|
+
const globalStorage = join(base, "globalStorage");
|
|
145
|
+
if (existsSync(globalStorage)) return {
|
|
146
|
+
globalStorage,
|
|
147
|
+
workspaceStorage: join(base, "workspaceStorage")
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function fsPathFromHeader(header) {
|
|
153
|
+
const uri = header?.workspaceIdentifier?.uri;
|
|
154
|
+
const value = uri?.fsPath ?? uri?.path;
|
|
155
|
+
return typeof value === "string" && value.trim() ? value : null;
|
|
156
|
+
}
|
|
157
|
+
/** Cursor 3.0+: one central index in the global database. */
|
|
158
|
+
function fromGlobalIndex(sessionId, roots) {
|
|
159
|
+
const raw = readItemTableValue(join(roots.globalStorage, "state.vscdb"), "composer.composerHeaders");
|
|
160
|
+
if (!raw) return null;
|
|
161
|
+
try {
|
|
162
|
+
const hit = JSON.parse(raw).allComposers?.find((c) => c?.composerId === sessionId);
|
|
163
|
+
return fsPathFromHeader(hit);
|
|
164
|
+
} catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/** `{"folder":"file:///d%3A/repo"}`, or a vscode-remote:// URI we cannot map. */
|
|
169
|
+
function folderFromWorkspaceJson(workspaceDir) {
|
|
170
|
+
const file = join(workspaceDir, "workspace.json");
|
|
171
|
+
if (!existsSync(file)) return null;
|
|
172
|
+
try {
|
|
173
|
+
const folder = JSON.parse(readFileSync(file, "utf-8")).folder;
|
|
174
|
+
if (typeof folder !== "string" || !folder.startsWith("file://")) return null;
|
|
175
|
+
return fileURLToPath(folder);
|
|
176
|
+
} catch {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const LEGACY_SCAN_LIMIT = 40;
|
|
181
|
+
function fromLegacyWorkspaceDbs(sessionId, roots) {
|
|
182
|
+
if (!existsSync(roots.workspaceStorage)) return null;
|
|
183
|
+
let dirs;
|
|
184
|
+
try {
|
|
185
|
+
dirs = readdirSync(roots.workspaceStorage).map((dir) => {
|
|
186
|
+
try {
|
|
187
|
+
return {
|
|
188
|
+
dir,
|
|
189
|
+
mtime: statSync(join(roots.workspaceStorage, dir, "state.vscdb")).mtimeMs
|
|
190
|
+
};
|
|
191
|
+
} catch {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
}).filter((x) => x !== null).sort((a, b) => b.mtime - a.mtime).slice(0, LEGACY_SCAN_LIMIT);
|
|
195
|
+
} catch {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
for (const { dir } of dirs) {
|
|
199
|
+
const raw = readItemTableValue(join(roots.workspaceStorage, dir, "state.vscdb"), "composer.composerData");
|
|
200
|
+
if (!raw) continue;
|
|
201
|
+
try {
|
|
202
|
+
const parsed = JSON.parse(raw);
|
|
203
|
+
if (!Array.isArray(parsed.allComposers)) continue;
|
|
204
|
+
if (!parsed.allComposers.some((c) => c?.composerId === sessionId)) continue;
|
|
205
|
+
return folderFromWorkspaceJson(join(roots.workspaceStorage, dir));
|
|
206
|
+
} catch {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* The workspace directory Cursor recorded for this session, or null when it
|
|
214
|
+
* cannot be determined (no driver, no storage, workspace-less window, or a
|
|
215
|
+
* remote URI that does not map to a local path).
|
|
216
|
+
*/
|
|
217
|
+
function workspaceFromCursorDb(sessionId) {
|
|
218
|
+
if (!sessionId) return null;
|
|
219
|
+
const roots = cursorStorageRoots();
|
|
220
|
+
if (!roots) return null;
|
|
221
|
+
return fromGlobalIndex(sessionId, roots) ?? fromLegacyWorkspaceDbs(sessionId, roots);
|
|
222
|
+
}
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/hooks/cursor/workspace.ts
|
|
225
|
+
const HOME = homedir();
|
|
226
|
+
const CURSOR_PROJECTS_DIR = join(HOME, ".cursor", "projects");
|
|
227
|
+
const SESSION_CACHE_PATH = join(HOME, ".cursor", "hooks", ".agentmemory-session-cache.json");
|
|
228
|
+
const HOOK_PAYLOAD_DIR = join(HOME, ".cursor", "hooks", ".am-hook-payloads");
|
|
229
|
+
const SESSION_CACHE_MAX_AGE_MS = 10080 * 60 * 1e3;
|
|
230
|
+
const SESSION_CACHE_MAX_ENTRIES = 200;
|
|
231
|
+
function normalizePathSlashes(value) {
|
|
232
|
+
return String(value).replace(/\\/g, "/");
|
|
233
|
+
}
|
|
234
|
+
function isCursorMetadataPath(value) {
|
|
235
|
+
if (!value || typeof value !== "string") return false;
|
|
236
|
+
const trimmed = normalizePathSlashes(value.trim());
|
|
237
|
+
if (trimmed === ".cursor") return true;
|
|
238
|
+
if (/(^|\/)\.cursor\/worktrees\/[^/]/.test(trimmed)) return false;
|
|
239
|
+
return /(^|\/)\.cursor(\/|$)/.test(trimmed);
|
|
240
|
+
}
|
|
241
|
+
function pathUnderHome(value) {
|
|
242
|
+
if (typeof value !== "string") return false;
|
|
243
|
+
const homeNorm = normalizePathSlashes(HOME);
|
|
244
|
+
const valueNorm = normalizePathSlashes(value);
|
|
245
|
+
return valueNorm === homeNorm || valueNorm.startsWith(`${homeNorm}/`);
|
|
246
|
+
}
|
|
247
|
+
function isIdeInstallPath(value) {
|
|
248
|
+
if (!value || typeof value !== "string") return false;
|
|
249
|
+
const norm = normalizePathSlashes(value).toLowerCase();
|
|
250
|
+
return /(^|[\\/])(programs|program files|program files \(x86\))[\\/]cursor([\\/]|$)/i.test(norm) || /cursor\.app[\\/]contents/i.test(norm) || /(^|[\\/])microsoft vs code[\\/]resources[\\/]app([\\/]|$)/i.test(norm);
|
|
251
|
+
}
|
|
252
|
+
function isBadPath(value) {
|
|
253
|
+
if (!value || typeof value !== "string") return true;
|
|
254
|
+
const trimmed = normalizePathSlashes(value.trim());
|
|
255
|
+
if (!trimmed || trimmed === "/" || trimmed === ".") return true;
|
|
256
|
+
if (/^[a-zA-Z]:\/?$/.test(trimmed)) return true;
|
|
257
|
+
if (isCursorMetadataPath(trimmed)) return true;
|
|
258
|
+
if (isIdeInstallPath(trimmed)) return true;
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
function sleepMs(ms) {
|
|
262
|
+
const end = Date.now() + ms;
|
|
263
|
+
while (Date.now() < end);
|
|
264
|
+
}
|
|
265
|
+
function withSessionCacheLock(fn) {
|
|
266
|
+
const lockPath = `${SESSION_CACHE_PATH}.lock`;
|
|
267
|
+
mkdirSync(dirname(SESSION_CACHE_PATH), { recursive: true });
|
|
268
|
+
let fd;
|
|
269
|
+
for (let i = 0; i < 50; i++) try {
|
|
270
|
+
fd = openSync(lockPath, "wx");
|
|
271
|
+
break;
|
|
272
|
+
} catch {
|
|
273
|
+
sleepMs(10);
|
|
274
|
+
}
|
|
275
|
+
if (fd === void 0) return void 0;
|
|
276
|
+
try {
|
|
277
|
+
return fn();
|
|
278
|
+
} finally {
|
|
279
|
+
closeSync(fd);
|
|
280
|
+
try {
|
|
281
|
+
unlinkSync(lockPath);
|
|
282
|
+
} catch {}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function loadSessionCache() {
|
|
286
|
+
try {
|
|
287
|
+
const value = JSON.parse(readFileSync(SESSION_CACHE_PATH, "utf-8"));
|
|
288
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
289
|
+
} catch {
|
|
290
|
+
return {};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function pruneSessionCache(cache, now) {
|
|
294
|
+
const fresh = Object.entries(cache).filter(([, entry]) => {
|
|
295
|
+
const updated = Date.parse(entry?.updatedAt ?? "");
|
|
296
|
+
return typeof entry?.project === "string" && typeof entry?.cwd === "string" && Number.isFinite(updated) && now - updated < SESSION_CACHE_MAX_AGE_MS;
|
|
297
|
+
});
|
|
298
|
+
fresh.sort((a, b) => Date.parse(b[1].updatedAt) - Date.parse(a[1].updatedAt));
|
|
299
|
+
return Object.fromEntries(fresh.slice(0, SESSION_CACHE_MAX_ENTRIES));
|
|
300
|
+
}
|
|
301
|
+
function rememberSession(sessionId, project, cwd) {
|
|
302
|
+
if (!sessionId || !project || project === ".cursor") return;
|
|
303
|
+
withSessionCacheLock(() => {
|
|
304
|
+
try {
|
|
305
|
+
const now = Date.now();
|
|
306
|
+
const previous = loadSessionCache();
|
|
307
|
+
delete previous[sessionId];
|
|
308
|
+
const cache = pruneSessionCache({
|
|
309
|
+
[sessionId]: {
|
|
310
|
+
project,
|
|
311
|
+
cwd,
|
|
312
|
+
updatedAt: new Date(now).toISOString()
|
|
313
|
+
},
|
|
314
|
+
...previous
|
|
315
|
+
}, now);
|
|
316
|
+
const tmp = `${SESSION_CACHE_PATH}.${process.pid}.${Date.now()}.tmp`;
|
|
317
|
+
writeFileSync(tmp, JSON.stringify(cache, null, 2));
|
|
318
|
+
renameSync(tmp, SESSION_CACHE_PATH);
|
|
319
|
+
} catch {}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
function recallSession(sessionId) {
|
|
323
|
+
if (!sessionId) return null;
|
|
324
|
+
const cache = pruneSessionCache(loadSessionCache(), Date.now());
|
|
325
|
+
return Object.hasOwn(cache, sessionId) ? cache[sessionId] : null;
|
|
326
|
+
}
|
|
327
|
+
const SYSTEM_PATH_PREFIXES = [
|
|
328
|
+
"/usr/",
|
|
329
|
+
"/etc/",
|
|
330
|
+
"/bin/",
|
|
331
|
+
"/sbin/",
|
|
332
|
+
"/lib/",
|
|
333
|
+
"/lib64/",
|
|
334
|
+
"/opt/",
|
|
335
|
+
"/var/",
|
|
336
|
+
"/proc/",
|
|
337
|
+
"/sys/",
|
|
338
|
+
"/dev/",
|
|
339
|
+
"/run/",
|
|
340
|
+
"/boot/",
|
|
341
|
+
"/snap/",
|
|
342
|
+
"/nix/"
|
|
343
|
+
];
|
|
344
|
+
function isSystemPath(value) {
|
|
345
|
+
const norm = normalizePathSlashes(value);
|
|
346
|
+
const temp = normalizePathSlashes(tmpdir()).replace(/\/$/, "");
|
|
347
|
+
if (norm.startsWith(`${temp}/`)) return false;
|
|
348
|
+
return SYSTEM_PATH_PREFIXES.some((prefix) => norm.startsWith(prefix));
|
|
349
|
+
}
|
|
350
|
+
function isCollectablePath(value) {
|
|
351
|
+
if (typeof value !== "string" || isCursorMetadataPath(value)) return false;
|
|
352
|
+
if (pathUnderHome(value)) return true;
|
|
353
|
+
if (/^[a-zA-Z]:[\\/]/.test(value)) return true;
|
|
354
|
+
if (value.startsWith("/")) return !isSystemPath(value);
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
function collectPathStrings(value, out = []) {
|
|
358
|
+
if (typeof value === "string") {
|
|
359
|
+
if (isCollectablePath(value)) out.push(value);
|
|
360
|
+
return out;
|
|
361
|
+
}
|
|
362
|
+
if (Array.isArray(value)) {
|
|
363
|
+
for (const item of value) collectPathStrings(item, out);
|
|
364
|
+
return out;
|
|
365
|
+
}
|
|
366
|
+
if (value && typeof value === "object") for (const v of Object.values(value)) collectPathStrings(v, out);
|
|
367
|
+
return out;
|
|
368
|
+
}
|
|
369
|
+
function pathExists(pathValue) {
|
|
370
|
+
if (existsSync(pathValue)) return true;
|
|
371
|
+
if (process.platform === "win32") {
|
|
372
|
+
const native = pathValue.replace(/\//g, "\\");
|
|
373
|
+
if (native !== pathValue && existsSync(native)) return true;
|
|
374
|
+
}
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
const MAX_ANCESTOR_STEPS = 64;
|
|
378
|
+
function existingAncestor(pathValue) {
|
|
379
|
+
let current = pathValue;
|
|
380
|
+
for (let step = 0; step < MAX_ANCESTOR_STEPS; step++) {
|
|
381
|
+
if (!current || current === HOME || current === "/") return null;
|
|
382
|
+
if (pathExists(current)) {
|
|
383
|
+
const resolved = process.platform === "win32" ? current.replace(/\//g, "\\") : current;
|
|
384
|
+
try {
|
|
385
|
+
if (statSync(resolved).isFile()) return dirname(resolved);
|
|
386
|
+
} catch {}
|
|
387
|
+
return resolved;
|
|
388
|
+
}
|
|
389
|
+
const parent = dirname(current);
|
|
390
|
+
if (parent === current) return null;
|
|
391
|
+
current = parent;
|
|
392
|
+
}
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
function gitRootFromPath(targetPath) {
|
|
396
|
+
return execSync("git rev-parse --show-toplevel", {
|
|
397
|
+
cwd: targetPath,
|
|
398
|
+
encoding: "utf-8",
|
|
399
|
+
stdio: [
|
|
400
|
+
"ignore",
|
|
401
|
+
"pipe",
|
|
402
|
+
"ignore"
|
|
403
|
+
],
|
|
404
|
+
timeout: 500
|
|
405
|
+
}).trim();
|
|
406
|
+
}
|
|
407
|
+
function gitRootNearby(startPath) {
|
|
408
|
+
let current = startPath;
|
|
409
|
+
for (let step = 0; step < MAX_ANCESTOR_STEPS; step++) {
|
|
410
|
+
if (!current || current === "/") return null;
|
|
411
|
+
if (pathExists(join(current, ".git"))) return current;
|
|
412
|
+
const parent = dirname(current);
|
|
413
|
+
if (parent === current) return null;
|
|
414
|
+
current = parent;
|
|
415
|
+
}
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
function projectFromPath(targetPath) {
|
|
419
|
+
try {
|
|
420
|
+
return {
|
|
421
|
+
name: resolveProject(gitRootFromPath(targetPath)),
|
|
422
|
+
fromGitRoot: true
|
|
423
|
+
};
|
|
424
|
+
} catch {
|
|
425
|
+
return {
|
|
426
|
+
name: resolveProject(targetPath),
|
|
427
|
+
fromGitRoot: false
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
function decodeSlugCandidates(slug) {
|
|
432
|
+
if (!slug || slug === "empty-window") return [];
|
|
433
|
+
if (/^\d{10,}$/.test(slug)) return [];
|
|
434
|
+
const parts = slug.split("-");
|
|
435
|
+
if (!parts.length) return [];
|
|
436
|
+
const results = /* @__PURE__ */ new Set();
|
|
437
|
+
function walk(index, currentPath) {
|
|
438
|
+
if (index >= parts.length) {
|
|
439
|
+
results.add(currentPath);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
for (let take = 1; index + take <= parts.length; take++) {
|
|
443
|
+
const next = `${currentPath}/${parts.slice(index, index + take).join("-")}`;
|
|
444
|
+
if (!pathExists(next)) continue;
|
|
445
|
+
walk(index + take, next);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const first = parts[0];
|
|
449
|
+
if (first && /^[a-zA-Z]$/.test(first)) walk(1, `${first.toUpperCase()}:`);
|
|
450
|
+
walk(0, "");
|
|
451
|
+
return [...results];
|
|
452
|
+
}
|
|
453
|
+
function pickBestCandidate(candidates, preferredLabel) {
|
|
454
|
+
if (!candidates.length) return null;
|
|
455
|
+
if (preferredLabel) {
|
|
456
|
+
const labelMatch = candidates.find((p) => basename(p) === preferredLabel);
|
|
457
|
+
if (labelMatch) return labelMatch;
|
|
458
|
+
}
|
|
459
|
+
const gitRoots = [];
|
|
460
|
+
for (const candidate of candidates) try {
|
|
461
|
+
gitRoots.push(gitRootFromPath(candidate));
|
|
462
|
+
} catch {}
|
|
463
|
+
const uniqueGitRoots = [...new Set(gitRoots)];
|
|
464
|
+
if (uniqueGitRoots.length === 1) return uniqueGitRoots[0] ?? null;
|
|
465
|
+
return candidates.sort((a, b) => b.length - a.length)[0] ?? null;
|
|
466
|
+
}
|
|
467
|
+
function findSessionTranscript(sessionId) {
|
|
468
|
+
if (!sessionId || !existsSync(CURSOR_PROJECTS_DIR)) return null;
|
|
469
|
+
for (const slug of readdirSync(CURSOR_PROJECTS_DIR)) {
|
|
470
|
+
const transcriptsRoot = join(CURSOR_PROJECTS_DIR, slug, "agent-transcripts");
|
|
471
|
+
if (!existsSync(transcriptsRoot)) continue;
|
|
472
|
+
for (const entry of readdirSync(transcriptsRoot)) if (entry === sessionId || entry.startsWith(`${sessionId}-`)) {
|
|
473
|
+
const transcriptFile = join(transcriptsRoot, entry, `${entry}.jsonl`);
|
|
474
|
+
return {
|
|
475
|
+
slug,
|
|
476
|
+
transcriptFile: existsSync(transcriptFile) ? transcriptFile : null
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
const TRANSCRIPT_SCAN_BYTES = 25e4;
|
|
483
|
+
const TRANSCRIPT_CANDIDATE_LIMIT = 120;
|
|
484
|
+
const TRANSCRIPT_MATCH_LIMIT = 4e3;
|
|
485
|
+
const TRANSCRIPT_MIN_VOTES = 3;
|
|
486
|
+
const TRANSCRIPT_PATH_PATTERNS = [/[a-zA-Z]:[A-Za-z0-9._@+\-/]{3,240}/g, /\/[A-Za-z0-9._@+\-/]{3,240}/g];
|
|
487
|
+
function workspaceFromTranscriptFile(transcriptFile) {
|
|
488
|
+
if (!transcriptFile || !existsSync(transcriptFile)) return null;
|
|
489
|
+
let chunk;
|
|
490
|
+
const fd = openSync(transcriptFile, "r");
|
|
491
|
+
try {
|
|
492
|
+
const buffer = Buffer.alloc(TRANSCRIPT_SCAN_BYTES);
|
|
493
|
+
const bytes = readSync(fd, buffer, 0, buffer.length, 0);
|
|
494
|
+
chunk = normalizePathSlashes(buffer.subarray(0, bytes).toString("utf8"));
|
|
495
|
+
} finally {
|
|
496
|
+
closeSync(fd);
|
|
497
|
+
}
|
|
498
|
+
const counts = /* @__PURE__ */ new Map();
|
|
499
|
+
const seen = /* @__PURE__ */ new Set();
|
|
500
|
+
for (const pattern of TRANSCRIPT_PATH_PATTERNS) {
|
|
501
|
+
pattern.lastIndex = 0;
|
|
502
|
+
let match;
|
|
503
|
+
let scanned = 0;
|
|
504
|
+
while ((match = pattern.exec(chunk)) !== null) {
|
|
505
|
+
if (++scanned > TRANSCRIPT_MATCH_LIMIT) break;
|
|
506
|
+
if (seen.size >= TRANSCRIPT_CANDIDATE_LIMIT) break;
|
|
507
|
+
const value = match[0];
|
|
508
|
+
if (seen.has(value)) continue;
|
|
509
|
+
seen.add(value);
|
|
510
|
+
if (value.startsWith("//")) continue;
|
|
511
|
+
if (isCursorMetadataPath(value) || isIdeInstallPath(value) || isSystemPath(value)) continue;
|
|
512
|
+
const existing = existingDirectory(value);
|
|
513
|
+
if (!existing || existing === HOME || isBadPath(existing)) continue;
|
|
514
|
+
const root = gitRootNearby(existing);
|
|
515
|
+
if (!root || root === HOME || isBadPath(root)) continue;
|
|
516
|
+
counts.set(root, (counts.get(root) || 0) + 1);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
let best = null;
|
|
520
|
+
let bestCount = 0;
|
|
521
|
+
for (const [pathValue, count] of counts) if (count > bestCount) {
|
|
522
|
+
best = pathValue;
|
|
523
|
+
bestCount = count;
|
|
524
|
+
}
|
|
525
|
+
return bestCount >= TRANSCRIPT_MIN_VOTES ? best : null;
|
|
526
|
+
}
|
|
527
|
+
function workspaceFromSessionId(sessionId) {
|
|
528
|
+
const hit = findSessionTranscript(sessionId);
|
|
529
|
+
if (!hit) return null;
|
|
530
|
+
const preferredLabel = process.env["CURSOR_WORKSPACE_LABEL"] || "";
|
|
531
|
+
const fromSlug = pickBestCandidate(decodeSlugCandidates(hit.slug), preferredLabel);
|
|
532
|
+
if (fromSlug) return fromSlug;
|
|
533
|
+
return workspaceFromTranscriptFile(hit.transcriptFile);
|
|
534
|
+
}
|
|
535
|
+
function readHookStdinComplete(maxWaitMs = 3e4) {
|
|
536
|
+
return new Promise((resolve) => {
|
|
537
|
+
let input = "";
|
|
538
|
+
let done = false;
|
|
539
|
+
const finish = () => {
|
|
540
|
+
if (done) return;
|
|
541
|
+
done = true;
|
|
542
|
+
try {
|
|
543
|
+
process.stdin.destroy();
|
|
544
|
+
} catch {}
|
|
545
|
+
resolve(input);
|
|
546
|
+
};
|
|
547
|
+
const t = setTimeout(finish, maxWaitMs);
|
|
548
|
+
if (t.unref) t.unref();
|
|
549
|
+
process.stdin.on("data", (c) => {
|
|
550
|
+
input += c;
|
|
551
|
+
});
|
|
552
|
+
process.stdin.on("end", () => {
|
|
553
|
+
clearTimeout(t);
|
|
554
|
+
finish();
|
|
555
|
+
});
|
|
556
|
+
process.stdin.on("error", () => {
|
|
557
|
+
clearTimeout(t);
|
|
558
|
+
finish();
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
function writeHookPayloadTemp(input) {
|
|
563
|
+
mkdirSync(HOOK_PAYLOAD_DIR, { recursive: true });
|
|
564
|
+
try {
|
|
565
|
+
chmodSync(HOOK_PAYLOAD_DIR, 448);
|
|
566
|
+
} catch {}
|
|
567
|
+
const path = join(HOOK_PAYLOAD_DIR, `am-hook-${process.pid}-${Date.now()}.json`);
|
|
568
|
+
writeFileSync(path, input, {
|
|
569
|
+
encoding: "utf-8",
|
|
570
|
+
mode: 384
|
|
571
|
+
});
|
|
572
|
+
return path;
|
|
573
|
+
}
|
|
574
|
+
function readWorkerHookPayload() {
|
|
575
|
+
const file = process.env["AM_HOOK_INPUT_FILE"];
|
|
576
|
+
if (!file) {
|
|
577
|
+
console.error("[agentmemory] missing AM_HOOK_INPUT_FILE in worker");
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
try {
|
|
581
|
+
const raw = readFileSync(file, "utf-8");
|
|
582
|
+
const value = JSON.parse(raw);
|
|
583
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
584
|
+
} catch (err) {
|
|
585
|
+
console.error("[agentmemory] failed to parse hook payload:", err.message);
|
|
586
|
+
return null;
|
|
587
|
+
} finally {
|
|
588
|
+
try {
|
|
589
|
+
unlinkSync(file);
|
|
590
|
+
} catch {}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function isMetadataProject(project) {
|
|
594
|
+
return project.name.startsWith(".") && !project.fromGitRoot;
|
|
595
|
+
}
|
|
596
|
+
function isHomeDirectory(pathValue) {
|
|
597
|
+
return normalizePathSlashes(pathValue) === normalizePathSlashes(HOME);
|
|
598
|
+
}
|
|
599
|
+
function existingDirectory(pathValue) {
|
|
600
|
+
if (!pathExists(pathValue)) return null;
|
|
601
|
+
const resolved = process.platform === "win32" ? pathValue.replace(/\//g, "\\") : pathValue;
|
|
602
|
+
try {
|
|
603
|
+
return statSync(resolved).isFile() ? dirname(resolved) : resolved;
|
|
604
|
+
} catch {
|
|
605
|
+
return null;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function resolveFromPathCandidates(candidates, sessionId, options = {}) {
|
|
609
|
+
for (const candidate of candidates) {
|
|
610
|
+
if (typeof candidate !== "string" || isBadPath(candidate)) continue;
|
|
611
|
+
const existing = options.exact ? existingDirectory(candidate) : existingAncestor(candidate);
|
|
612
|
+
if (!existing || isBadPath(existing)) continue;
|
|
613
|
+
const project = projectFromPath(existing);
|
|
614
|
+
if (isHomeDirectory(existing) && !project.fromGitRoot) continue;
|
|
615
|
+
if (!isMetadataProject(project)) {
|
|
616
|
+
if (options.remember !== false) rememberSession(sessionId, project.name, existing);
|
|
617
|
+
return {
|
|
618
|
+
project: project.name,
|
|
619
|
+
cwd: existing
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
function debugLayer(layer, result) {
|
|
626
|
+
if (result && process.env["AM_CURSOR_DEBUG"] === "1") console.error(`[agentmemory] workspace resolved by ${layer}: ${result.project} (${result.cwd})`);
|
|
627
|
+
return result;
|
|
628
|
+
}
|
|
629
|
+
function resolveWorkspace(data) {
|
|
630
|
+
const sessionId = [
|
|
631
|
+
data?.["session_id"],
|
|
632
|
+
data?.["sessionId"],
|
|
633
|
+
data?.["conversation_id"]
|
|
634
|
+
].find((value) => typeof value === "string" && Boolean(value.trim()));
|
|
635
|
+
const cached = recallSession(sessionId);
|
|
636
|
+
if (cached?.cwd && !isBadPath(cached.cwd) && existingDirectory(cached.cwd)) return {
|
|
637
|
+
project: resolveProject(cached.cwd),
|
|
638
|
+
cwd: cached.cwd
|
|
639
|
+
};
|
|
640
|
+
const fromPayload = debugLayer("payload", resolveFromPathCandidates([
|
|
641
|
+
...Array.isArray(data?.["workspace_roots"]) ? data["workspace_roots"] : [],
|
|
642
|
+
...Array.isArray(data?.["workspace_folders"]) ? data["workspace_folders"] : [],
|
|
643
|
+
data?.["workspace_folder"],
|
|
644
|
+
data?.["workspaceFolder"],
|
|
645
|
+
data?.["workspace"],
|
|
646
|
+
data?.["cwd"],
|
|
647
|
+
data?.["root_path"],
|
|
648
|
+
data?.["project_path"]
|
|
649
|
+
], sessionId));
|
|
650
|
+
if (fromPayload) return fromPayload;
|
|
651
|
+
const fromTools = debugLayer("tool_input", resolveFromPathCandidates(collectPathStrings(data?.["tool_input"] ?? data?.["toolArgs"]).map(existingDirectory).filter((p) => Boolean(p) && !isIdeInstallPath(p)), sessionId));
|
|
652
|
+
if (fromTools) return fromTools;
|
|
653
|
+
if (sessionId) {
|
|
654
|
+
const fromDb = debugLayer("cursor-db", resolveFromPathCandidates([workspaceFromCursorDb(sessionId)], sessionId, { exact: true }));
|
|
655
|
+
if (fromDb) return fromDb;
|
|
656
|
+
const fromSession = debugLayer("transcript-dir", resolveFromPathCandidates([workspaceFromSessionId(sessionId)], sessionId, { exact: true }));
|
|
657
|
+
if (fromSession) return fromSession;
|
|
658
|
+
}
|
|
659
|
+
const fromEnv = debugLayer("env", resolveFromPathCandidates([
|
|
660
|
+
process.env["CURSOR_PROJECT_DIR"],
|
|
661
|
+
process.env["CURSOR_WORKSPACE_ROOT"],
|
|
662
|
+
process.env["CURSOR_WORKSPACE_FOLDER"]
|
|
663
|
+
], sessionId));
|
|
664
|
+
if (fromEnv) return fromEnv;
|
|
665
|
+
const fromLaunch = debugLayer("launch-env", resolveFromPathCandidates([process.env["PWD"], process.env["VSCODE_CWD"]], sessionId, { remember: false }));
|
|
666
|
+
if (fromLaunch) return fromLaunch;
|
|
667
|
+
const label = process.env["CURSOR_WORKSPACE_LABEL"];
|
|
668
|
+
if (label) return {
|
|
669
|
+
project: label,
|
|
670
|
+
cwd: label
|
|
671
|
+
};
|
|
672
|
+
return {
|
|
673
|
+
project: "unknown-project",
|
|
674
|
+
cwd: "unknown-project"
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
//#endregion
|
|
678
|
+
//#region src/hooks/cursor/delegate.ts
|
|
679
|
+
const HOOK_MAP = {
|
|
680
|
+
sessionStart: "session-start.mjs",
|
|
681
|
+
beforeSubmitPrompt: "prompt-submit.mjs",
|
|
682
|
+
preToolUse: "pre-tool-use.mjs",
|
|
683
|
+
postToolUse: "post-tool-use.mjs",
|
|
684
|
+
postToolUseFailure: "post-tool-failure.mjs",
|
|
685
|
+
preCompact: "pre-compact.mjs",
|
|
686
|
+
subagentStart: "subagent-start.mjs",
|
|
687
|
+
subagentStop: "subagent-stop.mjs",
|
|
688
|
+
stop: "stop.mjs",
|
|
689
|
+
sessionEnd: "session-end.mjs"
|
|
690
|
+
};
|
|
691
|
+
function isCursorHookKey(value) {
|
|
692
|
+
return typeof value === "string" && Object.hasOwn(HOOK_MAP, value);
|
|
693
|
+
}
|
|
694
|
+
const SLOW_HOOKS = new Set(["stop", "sessionEnd"]);
|
|
695
|
+
function defaultOfficialDir() {
|
|
696
|
+
return join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
697
|
+
}
|
|
698
|
+
function enrichPayload(data) {
|
|
699
|
+
const { project: resolvedProject, cwd } = resolveWorkspace(data);
|
|
700
|
+
const project = process.env["AGENTMEMORY_PROJECT_NAME"]?.trim() || resolvedProject;
|
|
701
|
+
return {
|
|
702
|
+
project,
|
|
703
|
+
payload: {
|
|
704
|
+
...data,
|
|
705
|
+
session_id: data["session_id"] ?? data["sessionId"] ?? data["conversation_id"],
|
|
706
|
+
cwd,
|
|
707
|
+
project
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
function delegateHook(hookKey, data, options = {}) {
|
|
712
|
+
const script = HOOK_MAP[hookKey];
|
|
713
|
+
const scriptPath = join(options.officialDir ?? defaultOfficialDir(), script);
|
|
714
|
+
if (!existsSync(scriptPath)) {
|
|
715
|
+
console.error(`[agentmemory] cursor hook "${hookKey}": canonical hook not found at ${scriptPath}. Run \`npm run build\` in the agentmemory checkout.`);
|
|
716
|
+
return 0;
|
|
717
|
+
}
|
|
718
|
+
const { project, payload } = enrichPayload(data);
|
|
719
|
+
const child = spawnSync(process.execPath, [scriptPath], {
|
|
720
|
+
input: JSON.stringify(payload),
|
|
721
|
+
env: {
|
|
722
|
+
...process.env,
|
|
723
|
+
AGENTMEMORY_PROJECT_NAME: project
|
|
724
|
+
},
|
|
725
|
+
encoding: "utf-8",
|
|
726
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
727
|
+
timeout: SLOW_HOOKS.has(hookKey) ? 18e4 : 3e4
|
|
728
|
+
});
|
|
729
|
+
if (child.stdout) process.stdout.write(child.stdout);
|
|
730
|
+
if (child.stderr) process.stderr.write(child.stderr);
|
|
731
|
+
if (child.error) {
|
|
732
|
+
console.error(`[agentmemory] cursor hook "${hookKey}" could not run ${script}: ${child.error.message}`);
|
|
733
|
+
return 0;
|
|
734
|
+
}
|
|
735
|
+
if (child.signal) {
|
|
736
|
+
console.error(`[agentmemory] cursor hook "${hookKey}" (${script}) was killed by ${child.signal} -- treating as no-op`);
|
|
737
|
+
return 0;
|
|
738
|
+
}
|
|
739
|
+
return child.status ?? 0;
|
|
740
|
+
}
|
|
741
|
+
//#endregion
|
|
742
|
+
//#region src/hooks/cursor/run-detached.ts
|
|
743
|
+
const IS_WORKER = process.env["AM_HOOK_WORKER"] === "1";
|
|
744
|
+
const hookKey = process.argv[2];
|
|
745
|
+
function runWorker() {
|
|
746
|
+
const watchdog = setTimeout(() => process.exit(0), hookKey === "sessionEnd" ? 25e4 : 13e4);
|
|
747
|
+
try {
|
|
748
|
+
const data = readWorkerHookPayload();
|
|
749
|
+
if (!data || !isCursorHookKey(hookKey)) return;
|
|
750
|
+
delegateHook(hookKey, data);
|
|
751
|
+
} finally {
|
|
752
|
+
clearTimeout(watchdog);
|
|
753
|
+
process.exit(0);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
async function runParent() {
|
|
757
|
+
if (!isCursorHookKey(hookKey)) process.exit(0);
|
|
758
|
+
const payloadFile = writeHookPayloadTemp(await readHookStdinComplete());
|
|
759
|
+
const child = spawn(process.execPath, [fileURLToPath(import.meta.url), hookKey], {
|
|
760
|
+
detached: true,
|
|
761
|
+
stdio: "ignore",
|
|
762
|
+
windowsHide: true,
|
|
763
|
+
env: {
|
|
764
|
+
...process.env,
|
|
765
|
+
AM_HOOK_WORKER: "1",
|
|
766
|
+
AM_HOOK_INPUT_FILE: payloadFile
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
child.unref();
|
|
770
|
+
const bail = setTimeout(() => process.exit(0), 2e3);
|
|
771
|
+
if (bail.unref) bail.unref();
|
|
772
|
+
child.on("spawn", () => process.exit(0));
|
|
773
|
+
child.on("error", (err) => {
|
|
774
|
+
console.error("[agentmemory] failed to spawn detached hook worker:", err.message);
|
|
775
|
+
try {
|
|
776
|
+
unlinkSync(payloadFile);
|
|
777
|
+
} catch {}
|
|
778
|
+
process.exit(0);
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
if (IS_WORKER) runWorker();
|
|
782
|
+
else runParent().catch(() => process.exit(0));
|
|
783
|
+
//#endregion
|
|
784
|
+
export {};
|
|
785
|
+
|
|
786
|
+
//# sourceMappingURL=run-detached.mjs.map
|