@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression-recovery-CZh63Jmz.mjs","names":["CONTROL_KEY","bytes","truncate"],"sources":["../src/runtime-paths.ts","../src/shutdown.ts","../src/cli-data-dir.ts","../src/functions/privacy.ts","../src/capture/spool.ts","../src/state/graph-generation.ts","../src/state/graph-consistency.ts","../src/state/graph-retrieval-index.ts","../src/functions/graph-index-query.ts","../src/prompts/graph-extraction.ts","../src/functions/graph.ts","../src/functions/graph-compact-boot.ts","../src/functions/status.ts","../src/prompts/compression.ts","../src/prompts/vision.ts","../src/prompts/compression-output.ts","../src/state/stemmer.ts","../src/state/synonyms.ts","../src/state/search-index.ts","../src/functions/access-tracker.ts","../src/functions/observation-source.ts","../src/functions/search.ts","../src/eval/schemas.ts","../src/eval/validator.ts","../src/eval/quality.ts","../src/eval/self-correct.ts","../src/viewer/live-events.ts","../src/state/frame-guard.ts","../src/functions/observation-source-budget.ts","../src/functions/compress-synthetic.ts","../src/capture/event-id.ts","../src/functions/compression-state.ts","../src/functions/compress.ts","../src/functions/compression-recovery.ts"],"sourcesContent":["import { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\ninterface RuntimeMetadataPathOptions {\n env?: NodeJS.ProcessEnv;\n home?: string;\n}\n\nexport function runtimeMetadataPath(\n name: string,\n options: RuntimeMetadataPathOptions = {},\n): string {\n const env = options.env ?? process.env;\n const home = options.home ?? homedir();\n const baseDir = env[\"AGENTMEMORY_RUNTIME_DIR\"]\n ? resolve(env[\"AGENTMEMORY_RUNTIME_DIR\"])\n : join(home, \".agentmemory\");\n return join(baseDir, name);\n}\n","export const SHUTDOWN_FLUSH_TIMEOUT_MS = 4000;\nexport const SHUTDOWN_HARD_EXIT_MS = 8000;\n\ninterface StartupCleanup {\n cleanup: () => Promise<void>;\n pending?: Promise<void>;\n exitCode?: number;\n}\n\n// The CLI and worker are built separately, but share startup ownership in one process.\nconst STARTUP_CLEANUP = Symbol.for(\"@agentmemory/startup-cleanup\");\nconst startupGlobal = globalThis as typeof globalThis & { [STARTUP_CLEANUP]?: StartupCleanup };\n\nexport function registerStartupCleanup(cleanup: () => Promise<void>): () => void {\n const state: StartupCleanup = { cleanup };\n startupGlobal[STARTUP_CLEANUP] = state;\n return () => {\n if (startupGlobal[STARTUP_CLEANUP] === state) delete startupGlobal[STARTUP_CLEANUP];\n };\n}\n\nexport async function runStartupCleanup(exitCode: number): Promise<number> {\n const state = startupGlobal[STARTUP_CLEANUP];\n if (!state) return exitCode;\n state.exitCode ??= exitCode;\n state.pending ??= Promise.resolve().then(state.cleanup);\n await state.pending;\n return state.exitCode;\n}\n\nexport async function settleWithin(\n work: Promise<unknown>,\n ms: number,\n): Promise<boolean> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const expiry = new Promise<boolean>((resolve) => {\n timer = setTimeout(() => resolve(false), ms);\n });\n try {\n return await Promise.race([work.then(() => true), expiry]);\n } finally {\n clearTimeout(timer);\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { homedir, platform } from \"node:os\";\n\nexport type DataDirSource = \"flag\" | \"env\" | \"default\";\n\nexport type ResolvedDataDir = {\n dataDir: string;\n source: DataDirSource;\n relocatedFrom?: string;\n};\n\ntype ResolveDataDirOptions = {\n args?: string[];\n env?: NodeJS.ProcessEnv;\n cwd?: string;\n home?: string;\n platform?: NodeJS.Platform;\n};\n\nfunction argValue(args: string[], name: string): string | undefined {\n const equals = `${name}=`;\n const inline = args.find((arg) => arg.startsWith(equals));\n if (inline) return inline.slice(equals.length);\n\n const idx = args.indexOf(name);\n if (idx !== -1) return args[idx + 1];\n return undefined;\n}\n\nfunction expandHome(pathValue: string, home: string): string {\n if (pathValue === \"~\") return home;\n if (pathValue.startsWith(\"~/\") || pathValue.startsWith(\"~\\\\\")) {\n return join(home, pathValue.slice(2));\n }\n return pathValue;\n}\n\nfunction absoluteDataDir(pathValue: string, cwd: string, home: string): string {\n const expanded = expandHome(pathValue, home);\n return isAbsolute(expanded) ? expanded : resolve(cwd, expanded);\n}\n\nfunction platformDefaultDataDir(\n env: NodeJS.ProcessEnv,\n home: string,\n nodePlatform: NodeJS.Platform,\n useXdg = true,\n): string {\n if (nodePlatform === \"darwin\") {\n return join(home, \"Library\", \"Application Support\", \"agentmemory\");\n }\n if (nodePlatform === \"win32\") {\n const appData = env[\"APPDATA\"];\n return appData\n ? join(appData, \"agentmemory\")\n : join(home, \".agentmemory\");\n }\n const xdgDataHome = env[\"XDG_DATA_HOME\"];\n if (useXdg && xdgDataHome && isAbsolute(xdgDataHome)) {\n return join(xdgDataHome, \"agentmemory\");\n }\n return join(home, \".local\", \"share\", \"agentmemory\");\n}\n\nfunction nearestGitParent(pathValue: string): string | undefined {\n let current = pathValue;\n while (true) {\n if (existsSync(join(current, \".git\"))) return current;\n const parent = dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n}\n\nfunction isWithin(parent: string, child: string): boolean {\n const pathFromParent = relative(parent, child);\n return (\n pathFromParent === \"\" ||\n (pathFromParent !== \"..\" &&\n !pathFromParent.startsWith(`..${sep}`) &&\n !isAbsolute(pathFromParent))\n );\n}\n\nexport function resolveDataDir(options: ResolveDataDirOptions = {}): ResolvedDataDir {\n const args = options.args ?? process.argv.slice(2);\n const env = options.env ?? process.env;\n const cwd = options.cwd ?? process.cwd();\n const home = options.home ?? homedir();\n const nodePlatform = options.platform ?? platform();\n const parsedInstance = parseInt(argValue(args, \"--instance\") ?? \"0\", 10);\n const instance =\n parsedInstance > 0 && parsedInstance <= 50 ? parsedInstance : 0;\n const forInstance = (dataDir: string) =>\n instance ? join(dataDir, `instance-${instance}`) : dataDir;\n\n const flagValue = argValue(args, \"--data-dir\");\n if (flagValue) {\n return {\n dataDir: forInstance(absoluteDataDir(flagValue, cwd, home)),\n source: \"flag\",\n };\n }\n\n const envValue = env[\"AGENTMEMORY_DATA_DIR\"];\n if (envValue) {\n return {\n dataDir: forInstance(absoluteDataDir(envValue, cwd, home)),\n source: \"env\",\n };\n }\n\n const legacyDir = resolve(cwd, \"data\");\n const hasLegacyStore =\n existsSync(join(legacyDir, \"state_store.db\")) ||\n existsSync(join(legacyDir, \"iii-config.yaml\"));\n if (instance === 0 && hasLegacyStore) {\n return { dataDir: legacyDir, source: \"default\" };\n }\n\n const defaultDir = platformDefaultDataDir(env, home, nodePlatform);\n const gitParent = nearestGitParent(cwd);\n if (gitParent && isWithin(gitParent, defaultDir)) {\n const relocated = platformDefaultDataDir(env, home, nodePlatform, false);\n if (relocated !== defaultDir) {\n return {\n dataDir: forInstance(relocated),\n source: \"default\",\n relocatedFrom: defaultDir,\n };\n }\n }\n\n return {\n dataDir: forInstance(defaultDir),\n source: \"default\",\n };\n}\n","import type { IIIClient } from \"iii-sdk\";\n\nconst PRIVATE_TAG_TOKEN_RE = /<private(?=\\s|>)[^>]*>|<\\/private\\s*>/gi;\n\nfunction redactPrivateBlocks(input: string): string {\n const tokens = new RegExp(PRIVATE_TAG_TOKEN_RE.source, PRIVATE_TAG_TOKEN_RE.flags);\n let out = \"\";\n let cursor = 0;\n let depth = 0;\n for (let match = tokens.exec(input); match; match = tokens.exec(input)) {\n const closing = match[0].startsWith(\"</\");\n if (depth === 0) {\n if (closing) continue;\n out += input.slice(cursor, match.index);\n depth = 1;\n } else if (closing) {\n depth -= 1;\n if (depth === 0) {\n out += \"[REDACTED]\";\n cursor = match.index + match[0].length;\n }\n } else {\n depth += 1;\n }\n }\n if (depth > 0) return `${out}[REDACTED]`;\n return out + input.slice(cursor);\n}\n\nconst SECRET_PATTERN_SOURCES = [\n /(?:api[_-]?key|secret|token|password|credential|auth)[\\s]*[=:]\\s*[\"']?[A-Za-z0-9_\\-/.+]{20,}[\"']?/gi,\n /Bearer\\s+[A-Za-z0-9._\\-+/=]{20,}/gi,\n /(?<![\\p{L}\\p{N}\\p{M}_])sk-proj-[A-Za-z0-9\\-_]{20,}/gu,\n /(?<![\\p{L}\\p{N}\\p{M}_])(?:sk|pk|rk|ak)-[A-Za-z0-9][A-Za-z0-9\\-_]{19,}/gu,\n /(?<![\\p{L}\\p{N}\\p{M}_])sk-ant-[A-Za-z0-9\\-_]{20,}/gu,\n /gh[pus]_[A-Za-z0-9]{36,}/g,\n /github_pat_[A-Za-z0-9_]{22,}/g,\n /xoxb-[A-Za-z0-9\\-]+/g,\n /AKIA[0-9A-Z]{16}/g,\n /AIza[A-Za-z0-9\\-_]{35}/g,\n /eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}/g,\n /npm_[A-Za-z0-9]{36}/g,\n /glpat-[A-Za-z0-9\\-_]{20,}/g,\n /dop_v1_[A-Za-z0-9]{64}/g,\n];\n\nconst PRIVATE_KEY_BLOCK_RE =\n /-----BEGIN [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----[\\s\\S]*?(?:-----END [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----|$)/g;\n\nconst URL_CREDENTIALS_RE =\n /\\b([a-z][a-z0-9+.-]*:\\/\\/)[^\\s/?#@:\"'<>]*:[^\\s/?#@\"'<>]+@/gi;\n\nexport function stripPrivateData(input: string): string {\n let result = redactPrivateBlocks(input);\n result = result.replace(new RegExp(PRIVATE_KEY_BLOCK_RE.source, PRIVATE_KEY_BLOCK_RE.flags), \"[REDACTED_SECRET]\");\n result = result.replace(new RegExp(URL_CREDENTIALS_RE.source, URL_CREDENTIALS_RE.flags), \"$1[REDACTED_SECRET]@\");\n for (const source of SECRET_PATTERN_SOURCES) {\n const pattern = new RegExp(source.source, source.flags);\n result = result.replace(pattern, \"[REDACTED_SECRET]\");\n }\n return result;\n}\n\nexport function scrubRecord<T>(value: T, options: { scrubKeys?: boolean } = {}): T {\n if (typeof value === \"string\") return stripPrivateData(value) as T;\n if (Array.isArray(value)) return value.map((item) => scrubRecord(item, options)) as T;\n if (value !== null && typeof value === \"object\") {\n const proto = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) return value;\n const entries = Object.entries(value as Record<string, unknown>).map(([key, item]) => [\n options.scrubKeys ? stripPrivateData(key) : key,\n item,\n ] as const);\n const reserved = new Set(entries.map(([key]) => key));\n const used = new Set<string>();\n return Object.fromEntries(\n entries.map(([key, item]) => {\n let unique = key;\n if (used.has(unique)) {\n let suffix = 2;\n do { unique = `${key}_${suffix++}`; } while (reserved.has(unique) || used.has(unique));\n }\n used.add(unique);\n return [unique, scrubRecord(item, options)];\n }),\n ) as T;\n }\n return value;\n}\n\nexport const SCRUBBED_WRITE_FUNCTIONS: ReadonlySet<string> = new Set([\n \"mem::remember\",\n \"mem::evolve\",\n \"mem::slot-create\",\n \"mem::slot-append\",\n \"mem::slot-replace\",\n \"mem::lesson-save\",\n \"mem::action-create\",\n \"mem::action-update\",\n \"mem::sketch-create\",\n \"mem::sketch-add\",\n \"mem::import\",\n \"mem::mesh-receive\",\n \"mem::team-share\",\n \"mem::signal-send\",\n \"mem::routine-create\",\n \"mem::checkpoint-create\",\n \"mem::checkpoint-resolve\",\n \"mem::sentinel-create\",\n \"mem::sentinel-trigger\",\n \"mem::core-add\",\n \"mem::facet-tag\",\n]);\n\ntype RegisterFunction = (id: string, handler: unknown, ...rest: unknown[]) => unknown;\n\nexport function withWriteScrubbing<T extends object>(sdk: T): T {\n return new Proxy(sdk, {\n get(target, prop) {\n const value = Reflect.get(target, prop, target);\n if (typeof value !== \"function\") return value;\n if (prop !== \"registerFunction\") return value.bind(target);\n const register = value as RegisterFunction;\n return (id: string, handler: unknown, ...rest: unknown[]) => {\n if (!SCRUBBED_WRITE_FUNCTIONS.has(id) || typeof handler !== \"function\") {\n return register.call(target, id, handler, ...rest);\n }\n const original = handler as (data: unknown, ...args: unknown[]) => unknown;\n const scrubbed = (data: unknown, ...args: unknown[]) => original(scrubRecord(data), ...args);\n return register.call(target, id, scrubbed, ...rest);\n };\n },\n });\n}\n\nexport function registerPrivacyFunction(sdk: IIIClient): void {\n sdk.registerFunction(\"mem::privacy\", \n async (data: { input?: unknown } | undefined) => {\n if (!data || typeof data.input !== \"string\") {\n return { output: \"\", error: \"invalid input: expected string field 'input'\" };\n }\n return { output: stripPrivateData(data.input) };\n },\n );\n}\n","import {\n chmodSync,\n closeSync,\n existsSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n readdirSync,\n renameSync,\n statSync,\n unlinkSync,\n utimesSync,\n writeFileSync,\n writeSync,\n} from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { resolveDataDir } from \"../cli-data-dir.js\";\nimport { scrubRecord } from \"../functions/privacy.js\";\n\nexport interface SpoolRecord {\n v: 1;\n eventId: string;\n spooledAt: string;\n reason: string;\n attempts: number;\n body: Record<string, unknown>;\n bootId?: string;\n}\n\nexport interface SentMark {\n bootId: string;\n durableAfterMs: number;\n}\n\nexport interface SentReconcile {\n released: number;\n requeued: number;\n}\n\nexport interface SpoolPolicy {\n enabled: boolean;\n maxBytes: number;\n maxAgeMs: number;\n maxRecordBytes: number;\n}\n\nexport interface SpoolStats {\n spooled: number;\n dropped: number;\n droppedBytes: number;\n expired: number;\n delivered: number;\n duplicates: number;\n rejected: number;\n lastSpooledAt?: string;\n lastSpoolReason?: string;\n lastDropAt?: string;\n lastDropReason?: string;\n lastDrainAt?: string;\n lastDrainDelivered?: number;\n lastDrainDuplicates?: number;\n lastDrainRejected?: number;\n lastDrainRemaining?: number;\n lastDrainError?: string;\n}\n\nexport interface SpoolPaths {\n dir: string;\n name: string;\n file: string;\n lock: string;\n drainLock: string;\n stats: string;\n}\n\nexport interface SpoolSummary {\n enabled: boolean;\n path: string;\n records: number;\n bytes: number;\n oldestAt: string | null;\n retained: number;\n retainedBytes: number;\n maxBytes: number;\n maxAgeHours: number;\n stats: SpoolStats;\n}\n\nexport type SendOutcome = \"delivered\" | \"duplicate\" | \"rejected\" | \"retry\";\n\nexport interface DrainResult {\n claimed: number;\n delivered: number;\n duplicates: number;\n rejected: number;\n expired: number;\n corrupt: number;\n remaining: number;\n error?: string;\n skipped?: \"locked\" | \"empty\" | \"disabled\";\n}\n\nconst DEFAULT_MAX_BYTES = 5 * 1024 * 1024;\nconst MIN_MAX_BYTES = 64 * 1024;\nconst DEFAULT_MAX_AGE_HOURS = 168;\nconst LOCK_STALE_MS = 10_000;\nconst DRAIN_LOCK_STALE_MS = 120_000;\nconst ORPHAN_CLAIM_MS = 120_000;\nconst LOCK_WAIT_MS = 500;\nconst IMAGE_PLACEHOLDER = \"[image dropped from capture spool]\";\nconst BOOT_ID_RE = /^[A-Za-z0-9]{8,64}$/;\nconst SENT_FILE_RE = /^([A-Za-z0-9]{8,64})-(\\d+)\\.jsonl$/;\nconst SENT_BUCKET_MS = 1000;\n// Cover the maximum one-hour state flush interval plus its safety margin.\nconst MAX_DURABLE_AFTER_MS = 61 * 60_000;\n\nfunction emptyStats(): SpoolStats {\n return { spooled: 0, dropped: 0, droppedBytes: 0, expired: 0, delivered: 0, duplicates: 0, rejected: 0 };\n}\n\nfunction positiveInt(raw: string | undefined, fallback: number): number {\n if (!raw || !/^\\d+$/.test(raw.trim())) return fallback;\n const n = parseInt(raw.trim(), 10);\n return n > 0 ? n : fallback;\n}\n\nexport function spoolPolicy(env: NodeJS.ProcessEnv = process.env): SpoolPolicy {\n const maxBytes = Math.max(MIN_MAX_BYTES, positiveInt(env[\"AGENTMEMORY_CAPTURE_SPOOL_MAX_BYTES\"], DEFAULT_MAX_BYTES));\n const maxAgeHours = positiveInt(env[\"AGENTMEMORY_CAPTURE_SPOOL_MAX_AGE_HOURS\"], DEFAULT_MAX_AGE_HOURS);\n return {\n enabled: env[\"AGENTMEMORY_CAPTURE_SPOOL\"] !== \"false\",\n maxBytes,\n maxAgeMs: maxAgeHours * 3600_000,\n maxRecordBytes: Math.min(256 * 1024, Math.floor(maxBytes / 4)),\n };\n}\n\nexport function spoolDir(env: NodeJS.ProcessEnv = process.env): string {\n const explicit = env[\"AGENTMEMORY_CAPTURE_SPOOL_DIR\"];\n if (explicit && explicit.trim()) return resolve(explicit.trim());\n return join(resolveDataDir({ args: [], env }).dataDir, \"capture-spool\");\n}\n\nconst LOOPBACK = new Set([\"localhost\", \"127.0.0.1\", \"::1\", \"[::1]\", \"0.0.0.0\"]);\n\nexport function spoolTargetName(url: string): string {\n try {\n const u = new URL(url);\n const host = LOOPBACK.has(u.hostname) ? \"local\" : u.hostname.toLowerCase().replace(/[^a-z0-9.-]/g, \"_\");\n const port = u.port || (u.protocol === \"https:\" ? \"443\" : \"80\");\n return `${host}-${port}`;\n } catch {\n return \"local-3111\";\n }\n}\n\nexport function spoolPaths(url: string, dir: string = spoolDir()): SpoolPaths {\n const name = spoolTargetName(url);\n return {\n dir,\n name,\n file: join(dir, `${name}.jsonl`),\n lock: join(dir, `${name}.lock`),\n drainLock: join(dir, `${name}.drain.lock`),\n stats: join(dir, `${name}.stats.json`),\n };\n}\n\nfunction ensureDir(dir: string): void {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n try {\n chmodSync(dir, 0o700);\n } catch {}\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\nfunction tryLock(path: string, staleMs: number): boolean {\n try {\n const fd = openSync(path, \"wx\", 0o600);\n writeSync(fd, `${process.pid}\\n`);\n closeSync(fd);\n return true;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") return false;\n try {\n if (Date.now() - statSync(path).mtimeMs > staleMs) unlinkSync(path);\n } catch {}\n return false;\n }\n}\n\nfunction releaseLock(path: string): void {\n try {\n unlinkSync(path);\n } catch {}\n}\n\nfunction withLock<T>(path: string, fn: (locked: boolean) => T, waitMs = LOCK_WAIT_MS): T {\n const deadline = Date.now() + waitMs;\n let locked = tryLock(path, LOCK_STALE_MS);\n while (!locked && Date.now() < deadline) {\n sleepSync(5);\n locked = tryLock(path, LOCK_STALE_MS);\n }\n try {\n return fn(locked);\n } finally {\n if (locked) releaseLock(path);\n }\n}\n\nexport function readSpoolStats(paths: SpoolPaths): SpoolStats {\n try {\n const parsed = JSON.parse(readFileSync(paths.stats, \"utf-8\")) as Partial<SpoolStats>;\n return { ...emptyStats(), ...parsed };\n } catch {\n return emptyStats();\n }\n}\n\nfunction writeStats(paths: SpoolPaths, patch: (stats: SpoolStats) => void): void {\n try {\n const stats = readSpoolStats(paths);\n patch(stats);\n const tmp = `${paths.stats}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify(stats), { mode: 0o600 });\n renameSync(tmp, paths.stats);\n } catch {}\n}\n\nfunction fileSize(path: string): number {\n try {\n return statSync(path).size;\n } catch {\n return 0;\n }\n}\n\nfunction withoutImage(body: Record<string, unknown>): Record<string, unknown> {\n const data = body[\"data\"];\n if (!data || typeof data !== \"object\" || Array.isArray(data)) return body;\n const d = data as Record<string, unknown>;\n if (d[\"image_data\"] === undefined) return body;\n return { ...body, data: { ...d, image_data: IMAGE_PLACEHOLDER } };\n}\n\nfunction parseLines(text: string): { records: SpoolRecord[]; corrupt: number } {\n const records: SpoolRecord[] = [];\n let corrupt = 0;\n for (const line of text.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const rec = JSON.parse(line) as SpoolRecord;\n if (rec && typeof rec.eventId === \"string\" && rec.body && typeof rec.body === \"object\") records.push(rec);\n else corrupt++;\n } catch {\n corrupt++;\n }\n }\n return { records, corrupt };\n}\n\nfunction isExpired(rec: SpoolRecord, policy: SpoolPolicy, now: number): boolean {\n const at = Date.parse(rec.spooledAt);\n return Number.isFinite(at) && now - at > policy.maxAgeMs;\n}\n\nfunction serialize(records: SpoolRecord[]): string {\n return records.map((r) => JSON.stringify(r)).join(\"\\n\") + (records.length ? \"\\n\" : \"\");\n}\n\nfunction rewriteLocked(paths: SpoolPaths, records: SpoolRecord[]): void {\n const tmp = `${paths.file}.${process.pid}.tmp`;\n const fd = openSync(tmp, \"w\", 0o600);\n try {\n writeSync(fd, serialize(records));\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n renameSync(tmp, paths.file);\n}\n\nfunction pruneExpiredLocked(paths: SpoolPaths, policy: SpoolPolicy): number {\n if (!existsSync(paths.file)) return 0;\n const { records } = parseLines(readFileSync(paths.file, \"utf-8\"));\n const now = Date.now();\n const kept = records.filter((r) => !isExpired(r, policy, now));\n const expired = records.length - kept.length;\n if (expired > 0) rewriteLocked(paths, kept);\n return expired;\n}\n\nexport interface AppendResult {\n spooled: boolean;\n dropped?: \"disabled\" | \"too-large\" | \"full\" | \"error\";\n}\n\nexport function appendSpool(\n url: string,\n eventId: string,\n body: Record<string, unknown>,\n reason: string,\n options: { policy?: SpoolPolicy; dir?: string; attempts?: number } = {},\n): AppendResult {\n const policy = options.policy ?? spoolPolicy();\n if (!policy.enabled) return { spooled: false, dropped: \"disabled\" };\n const paths = spoolPaths(url, options.dir);\n const note = (dropReason: NonNullable<AppendResult[\"dropped\"]>, bytes: number) => {\n writeStats(paths, (s) => {\n s.dropped++;\n s.droppedBytes += bytes;\n s.lastDropAt = new Date().toISOString();\n s.lastDropReason = dropReason;\n });\n return { spooled: false, dropped: dropReason } as AppendResult;\n };\n try {\n ensureDir(paths.dir);\n const record: SpoolRecord = {\n v: 1,\n eventId,\n spooledAt: new Date().toISOString(),\n reason,\n attempts: options.attempts ?? 0,\n body: scrubRecord(JSON.parse(JSON.stringify(body)), { scrubKeys: true }),\n };\n let line = JSON.stringify(record) + \"\\n\";\n if (Buffer.byteLength(line) > policy.maxRecordBytes) {\n record.body = withoutImage(record.body);\n line = JSON.stringify(record) + \"\\n\";\n }\n const bytes = Buffer.byteLength(line);\n if (bytes > policy.maxRecordBytes) return note(\"too-large\", bytes);\n return withLock(paths.lock, (locked) => {\n let expired = 0;\n if (locked && fileSize(paths.file) + bytes > policy.maxBytes) expired = pruneExpiredLocked(paths, policy);\n const over = fileSize(paths.file) + sentBytes(paths) + bytes - policy.maxBytes;\n if (locked && over > 0) evictSent(paths, over);\n if (fileSize(paths.file) + sentBytes(paths) + bytes > policy.maxBytes) {\n if (expired) writeStats(paths, (s) => void (s.expired += expired));\n return note(\"full\", bytes);\n }\n const fd = openSync(paths.file, \"a\", 0o600);\n try {\n writeSync(fd, line);\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n writeStats(paths, (s) => {\n s.spooled++;\n s.expired += expired;\n s.lastSpooledAt = record.spooledAt;\n s.lastSpoolReason = reason;\n });\n return { spooled: true } as AppendResult;\n });\n } catch {\n return { spooled: false, dropped: \"error\" };\n }\n}\n\ninterface SentSegment {\n file: string;\n bootId: string;\n dueAt: number;\n bytes: number;\n}\n\nfunction listSent(paths: SpoolPaths): SentSegment[] {\n const segments: SentSegment[] = [];\n let entries: string[];\n try {\n entries = readdirSync(paths.dir);\n } catch {\n return segments;\n }\n const prefix = `${paths.name}.sent-`;\n for (const entry of entries) {\n if (!entry.startsWith(prefix)) continue;\n const match = entry.slice(prefix.length).match(SENT_FILE_RE);\n if (!match) continue;\n const file = join(paths.dir, entry);\n segments.push({ file, bootId: match[1]!, dueAt: Number(match[2]), bytes: fileSize(file) });\n }\n return segments;\n}\n\nfunction sentBytes(paths: SpoolPaths): number {\n return listSent(paths).reduce((n, s) => n + s.bytes, 0);\n}\n\nfunction evictSent(paths: SpoolPaths, need: number): void {\n let freed = 0;\n for (const seg of listSent(paths).sort((a, b) => a.dueAt - b.dueAt)) {\n if (freed >= need) return;\n try {\n unlinkSync(seg.file);\n freed += seg.bytes;\n } catch {}\n }\n}\n\nexport function parseSentMark(body: unknown): SentMark | null {\n if (!body || typeof body !== \"object\" || Array.isArray(body)) return null;\n const bootId = (body as Record<string, unknown>)[\"bootId\"];\n const after = (body as Record<string, unknown>)[\"durableAfterMs\"];\n if (typeof bootId !== \"string\" || !BOOT_ID_RE.test(bootId)) return null;\n if (typeof after !== \"number\" || !Number.isFinite(after) || after < 0) return null;\n return { bootId, durableAfterMs: Math.min(Math.ceil(after), MAX_DURABLE_AFTER_MS) };\n}\n\nexport function retainSent(\n url: string,\n eventId: string,\n body: Record<string, unknown>,\n mark: SentMark,\n options: { policy?: SpoolPolicy; dir?: string; now?: number } = {},\n): boolean {\n const policy = options.policy ?? spoolPolicy();\n if (!policy.enabled || !BOOT_ID_RE.test(mark.bootId)) return false;\n const paths = spoolPaths(url, options.dir);\n const now = options.now ?? Date.now();\n try {\n ensureDir(paths.dir);\n const record: SpoolRecord = {\n v: 1,\n eventId,\n spooledAt: new Date(now).toISOString(),\n reason: \"sent\",\n attempts: 0,\n body: scrubRecord(JSON.parse(JSON.stringify(body)), { scrubKeys: true }),\n bootId: mark.bootId,\n };\n let line = JSON.stringify(record) + \"\\n\";\n if (Buffer.byteLength(line) > policy.maxRecordBytes) {\n record.body = withoutImage(record.body);\n line = JSON.stringify(record) + \"\\n\";\n }\n const bytes = Buffer.byteLength(line);\n if (bytes > policy.maxRecordBytes) return false;\n const dueAt = Math.ceil((now + mark.durableAfterMs) / SENT_BUCKET_MS) * SENT_BUCKET_MS;\n const file = join(paths.dir, `${paths.name}.sent-${mark.bootId}-${dueAt}.jsonl`);\n return withLock(paths.lock, () => {\n if (fileSize(paths.file) + sentBytes(paths) + bytes > policy.maxBytes) return false;\n const fd = openSync(file, \"a\", 0o600);\n try {\n writeSync(fd, line);\n } finally {\n closeSync(fd);\n }\n return true;\n });\n } catch {\n return false;\n }\n}\n\nexport function reconcileSent(\n url: string,\n bootId: string,\n options: { policy?: SpoolPolicy; dir?: string; now?: number } = {},\n): SentReconcile {\n const result: SentReconcile = { released: 0, requeued: 0 };\n const policy = options.policy ?? spoolPolicy();\n if (!policy.enabled) return result;\n const paths = spoolPaths(url, options.dir);\n const now = options.now ?? Date.now();\n for (const seg of listSent(paths)) {\n if (seg.bootId === bootId) {\n if (seg.dueAt > now) continue;\n try {\n unlinkSync(seg.file);\n result.released++;\n } catch {}\n continue;\n }\n const target = join(paths.dir, `${paths.name}.draining-${process.pid}-${now}-${result.requeued}.jsonl`);\n try {\n renameSync(seg.file, target);\n } catch {\n continue;\n }\n try {\n utimesSync(target, 0, 0);\n } catch {}\n result.requeued++;\n }\n return result;\n}\n\nfunction claimFiles(paths: SpoolPaths): string[] {\n const claimed: string[] = [];\n try {\n const prefix = `${paths.name}.draining-`;\n for (const entry of readdirSync(paths.dir)) {\n if (!entry.startsWith(prefix) || !entry.endsWith(\".jsonl\")) continue;\n const full = join(paths.dir, entry);\n try {\n if (Date.now() - statSync(full).mtimeMs > ORPHAN_CLAIM_MS) claimed.push(full);\n } catch {}\n }\n } catch {}\n if (fileSize(paths.file) > 0) {\n const target = join(paths.dir, `${paths.name}.draining-${process.pid}-${Date.now()}.jsonl`);\n withLock(paths.lock, (locked) => {\n if (!locked) return;\n try {\n renameSync(paths.file, target);\n claimed.push(target);\n } catch {}\n });\n }\n return claimed;\n}\n\nfunction requeueLocked(paths: SpoolPaths, leftover: SpoolRecord[]): void {\n if (leftover.length === 0) return;\n const existing = existsSync(paths.file) ? parseLines(readFileSync(paths.file, \"utf-8\")).records : [];\n rewriteLocked(paths, [...leftover, ...existing]);\n}\n\nfunction requeueUnlocked(paths: SpoolPaths, leftover: SpoolRecord[]): void {\n if (leftover.length === 0) return;\n const target = join(paths.dir, `${paths.name}.draining-${process.pid}-${Date.now()}-requeue.jsonl`);\n const fd = openSync(target, \"wx\", 0o600);\n try {\n writeSync(fd, serialize(leftover));\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n try {\n utimesSync(target, 0, 0);\n } catch {}\n}\n\nexport function spoolHasRecords(url: string, dir?: string): boolean {\n return fileSize(spoolPaths(url, dir).file) > 0;\n}\n\nexport function drainInProgress(url: string, dir?: string): boolean {\n const paths = spoolPaths(url, dir);\n try {\n return Date.now() - statSync(paths.drainLock).mtimeMs < DRAIN_LOCK_STALE_MS;\n } catch {\n return false;\n }\n}\n\nexport async function drainSpool(\n url: string,\n send: (record: SpoolRecord) => Promise<SendOutcome>,\n options: { policy?: SpoolPolicy; dir?: string; maxRecords?: number; deadlineMs?: number } = {},\n): Promise<DrainResult> {\n const policy = options.policy ?? spoolPolicy();\n const result: DrainResult = { claimed: 0, delivered: 0, duplicates: 0, rejected: 0, expired: 0, corrupt: 0, remaining: 0 };\n const paths = spoolPaths(url, options.dir);\n if (!existsSync(paths.dir)) return { ...result, skipped: \"empty\" };\n try {\n ensureDir(paths.dir);\n } catch {}\n if (!tryLock(paths.drainLock, DRAIN_LOCK_STALE_MS)) return { ...result, skipped: \"locked\" };\n try {\n const files = claimFiles(paths);\n if (files.length === 0) return { ...result, skipped: \"empty\" };\n const records: SpoolRecord[] = [];\n for (const file of files) {\n try {\n const parsed = parseLines(readFileSync(file, \"utf-8\"));\n records.push(...parsed.records);\n result.corrupt += parsed.corrupt;\n } catch {}\n }\n result.claimed = records.length;\n const seen = new Set<string>();\n const now = Date.now();\n const deadline = options.deadlineMs ? now + options.deadlineMs : Number.POSITIVE_INFINITY;\n const maxRecords = options.maxRecords ?? Number.POSITIVE_INFINITY;\n const leftover: SpoolRecord[] = [];\n let stopped = false;\n let processed = 0;\n for (const rec of records) {\n if (seen.has(rec.eventId)) {\n result.duplicates++;\n continue;\n }\n seen.add(rec.eventId);\n if (isExpired(rec, policy, now)) {\n result.expired++;\n continue;\n }\n if (stopped || processed >= maxRecords || Date.now() > deadline) {\n leftover.push(rec);\n continue;\n }\n processed++;\n let outcome: SendOutcome;\n try {\n outcome = await send(rec);\n } catch (err) {\n outcome = \"retry\";\n result.error = err instanceof Error ? err.message : String(err);\n }\n if (outcome === \"delivered\") result.delivered++;\n else if (outcome === \"duplicate\") result.duplicates++;\n else if (outcome === \"rejected\") result.rejected++;\n else {\n stopped = true;\n leftover.push({ ...rec, attempts: (rec.attempts ?? 0) + 1 });\n }\n }\n result.remaining = leftover.length;\n withLock(paths.lock, (locked) => (locked ? requeueLocked(paths, leftover) : requeueUnlocked(paths, leftover)), 2000);\n for (const file of files) {\n try {\n unlinkSync(file);\n } catch {}\n }\n writeStats(paths, (s) => {\n s.delivered += result.delivered;\n s.duplicates += result.duplicates;\n s.rejected += result.rejected;\n s.expired += result.expired;\n s.lastDrainAt = new Date().toISOString();\n s.lastDrainDelivered = result.delivered;\n s.lastDrainDuplicates = result.duplicates;\n s.lastDrainRejected = result.rejected;\n s.lastDrainRemaining = result.remaining;\n if (result.error) s.lastDrainError = result.error;\n else delete s.lastDrainError;\n });\n return result;\n } finally {\n releaseLock(paths.drainLock);\n }\n}\n\nexport function spoolSummary(url: string, options: { policy?: SpoolPolicy; dir?: string } = {}): SpoolSummary {\n const policy = options.policy ?? spoolPolicy();\n const paths = spoolPaths(url, options.dir);\n let records = 0;\n let bytes = 0;\n let oldestAt: string | null = null;\n const files: string[] = [];\n if (existsSync(paths.file)) files.push(paths.file);\n try {\n for (const entry of readdirSync(paths.dir)) {\n if (entry.startsWith(`${paths.name}.draining-`) && entry.endsWith(\".jsonl\")) files.push(join(paths.dir, entry));\n }\n } catch {}\n for (const file of files) {\n try {\n const text = readFileSync(file, \"utf-8\");\n bytes += Buffer.byteLength(text);\n for (const rec of parseLines(text).records) {\n records++;\n if (!oldestAt || rec.spooledAt < oldestAt) oldestAt = rec.spooledAt;\n }\n } catch {}\n }\n let retained = 0;\n let retainedBytes = 0;\n for (const seg of listSent(paths)) {\n try {\n const text = readFileSync(seg.file, \"utf-8\");\n retainedBytes += Buffer.byteLength(text);\n retained += parseLines(text).records.length;\n } catch {}\n }\n return {\n enabled: policy.enabled,\n path: paths.file,\n records,\n bytes,\n oldestAt,\n retained,\n retainedBytes,\n maxBytes: policy.maxBytes,\n maxAgeHours: Math.round(policy.maxAgeMs / 3600_000),\n stats: readSpoolStats(paths),\n };\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { randomUUID } from \"node:crypto\";\nimport type { StateKV } from \"./kv.js\";\nimport { KV } from \"./schema.js\";\nimport { afterKeyedLock } from \"./keyed-mutex.js\";\nimport { initializeGraphIndex } from \"./graph-retrieval-index.js\";\n\nconst CONTROL_SCOPE = KV.graphControl;\nconst CONTROL_KEY = \"generation\";\nconst GRAPH_SCOPES = new Set<string>([\n KV.graphNodes, KV.graphEdges, KV.graphEdgeHistory, KV.graphSnapshot,\n KV.graphNameIndex, KV.graphEdgeKey, KV.graphNodeDegree, KV.graphMembership,\n KV.graphRetrievalControl, KV.graphRetrievalData, KV.graphIndexMigration, KV.graphIndexManifest,\n]);\nconst pinned = new AsyncLocalStorage<{ kv: StateKV; generation: string | null }>();\nconst views = new WeakMap<StateKV, { target: StateKV; id: string | null }>();\ntype GraphChange = \"reset\" | \"snapshot\" | \"nodes\" | \"edges\";\nlet onGraphChange: ((kind: GraphChange) => Promise<void>) | null = null;\n\nexport function setGraphGenerationListener(listener: typeof onGraphChange): void {\n onGraphChange = listener;\n}\n\n// The engine's legacy scope subscriptions cannot follow a rotated namespace.\nexport async function notifyGraphGenerationChange(kv: StateKV, scope: string, key: string): Promise<void> {\n if (!onGraphChange) return;\n const kind: GraphChange | undefined = scope === CONTROL_SCOPE && key === CONTROL_KEY ? \"reset\"\n : scope.startsWith(`${KV.graphSnapshot}:generation:`) ? \"snapshot\"\n : scope.startsWith(`${KV.graphNodes}:generation:`) ? \"nodes\"\n : scope.startsWith(`${KV.graphEdges}:generation:`) ? \"edges\" : undefined;\n if (!kind) return;\n if (afterKeyedLock(\"graph:persist\", () => notifyGraphGenerationChange(kv, scope, key), scope)) return;\n if (kind !== \"reset\" && afterKeyedLock(`graph:retrieval:${scope.slice(scope.lastIndexOf(\":generation:\") + 12)}`,\n () => notifyGraphGenerationChange(kv, scope, key), scope)) return;\n if (afterKeyedLock(\"graph:viewer-events\", () => notifyGraphGenerationChange(kv, scope, key), scope)) return;\n try {\n const current = await generation(kv);\n if (kind !== \"reset\" && !scope.endsWith(`:generation:${current}`)) return;\n await pinned.exit(() => onGraphChange!(kind));\n } catch {\n // Viewer delivery must not turn a committed state write into a failed mutation.\n }\n}\n\nexport async function isLegacyGraphState(kv: StateKV): Promise<boolean> {\n return await generation(kv) === null;\n}\n\nexport async function getGraphGeneration(kv: StateKV): Promise<string | null> {\n const view = views.get(kv);\n if (view) return view.id;\n const context = pinned.getStore();\n return context?.kv === kv ? context.generation : generation(kv);\n}\n\nexport function pinGraphStateGeneration(kv: StateKV, id: string | null): StateKV {\n return graphView(views.get(kv)?.target ?? kv, id);\n}\n\nasync function generation(kv: StateKV): Promise<string | null> {\n const value = await kv.get<unknown>(CONTROL_SCOPE, CONTROL_KEY);\n if (value === null || value === undefined) return null;\n if (typeof value !== \"string\" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(value)) {\n throw new Error(\"Invalid graph generation\");\n }\n return value;\n}\n\nfunction physicalScope(scope: string, id: string | null): string {\n return id !== null && GRAPH_SCOPES.has(scope) ? `${scope}:generation:${id}` : scope;\n}\n\n/** Used by StateKV so every graph consumer respects reset, including fallback reads. */\nexport async function resolveGraphScope(kv: StateKV, scope: string): Promise<string> {\n if (!GRAPH_SCOPES.has(scope)) return scope;\n const context = pinned.getStore();\n const id = context?.kv === kv ? context.generation : await generation(kv);\n return physicalScope(scope, id);\n}\n\n/** Pin an operation before any awaits: late writes remain in its original generation. */\nexport async function pinGraphState(kv: StateKV): Promise<StateKV> {\n if (views.has(kv)) return kv;\n const id = await generation(kv);\n return graphView(kv, id);\n}\n\nfunction graphView(kv: StateKV, id: string | null): StateKV {\n const methods = new Set([\"get\", \"set\", \"update\", \"delete\", \"list\"]);\n const view = new Proxy(kv, {\n get(target, property, receiver) {\n const value = Reflect.get(target, property, receiver);\n if (typeof property !== \"string\" || !methods.has(property)) return value;\n return (scope: string, ...args: unknown[]) => pinned.run(\n { kv: target, generation: id },\n () => value.call(target, physicalScope(scope, id), ...args),\n );\n },\n });\n views.set(view, { target: kv, id });\n return view;\n}\n\n/** Initialize first, publish last; failures cannot expose a half-reset graph. */\nexport async function resetGraphGeneration(kv: StateKV, snapshot: unknown): Promise<void> {\n const id = randomUUID();\n await kv.set(physicalScope(KV.graphSnapshot, id), \"current\", snapshot);\n await initializeGraphIndex(graphView(kv, id), { status: \"ready\" });\n await kv.set(CONTROL_SCOPE, CONTROL_KEY, id);\n}\n\nexport async function replaceGraphGeneration<T>(kv: StateKV, initialize: (fresh: StateKV) => Promise<T>): Promise<T> {\n const pinnedState = await pinGraphState(kv);\n const { target, id: previous } = views.get(pinnedState)!;\n const id = randomUUID();\n const fresh = graphView(target, id);\n await initializeGraphIndex(fresh, { status: \"ready\" });\n const result = await initialize(fresh);\n // A delayed import cannot replace a reset that happened after it was pinned.\n if (await generation(target) === previous) {\n await target.set(CONTROL_SCOPE, CONTROL_KEY, id);\n }\n return result;\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { StateKV } from \"./kv.js\";\nimport type { GraphSnapshot } from \"../types.js\";\nimport { KV } from \"./schema.js\";\nimport { isKeyedLockHeld, withKeyedLock } from \"./keyed-mutex.js\";\n\nconst recovering = new AsyncLocalStorage<boolean>();\ntype SnapshotCheck = { clean: boolean };\nconst checks = new WeakMap<StateKV, Map<string, SnapshotCheck>>();\nconst scopes = [KV.graphNodes, KV.graphEdges, KV.graphEdgeHistory, KV.graphSnapshot,\n KV.graphNameIndex, KV.graphEdgeKey, KV.graphNodeDegree, KV.graphMembership];\n\nfunction snapshotScope(scope: string): string | null {\n for (const logical of scopes) {\n if (scope === logical) return KV.graphSnapshot;\n if (scope.startsWith(`${logical}:generation:`)) return KV.graphSnapshot + scope.slice(logical.length);\n }\n return null;\n}\n\nexport function withoutGraphRecovery<T>(fn: () => Promise<T>): Promise<T> {\n return recovering.run(true, fn);\n}\n\nexport function noteGraphSnapshotWrite(kv: StateKV, scope: string, key: string): void {\n if (key === \"current\" && (scope === KV.graphSnapshot || scope.startsWith(`${KV.graphSnapshot}:generation:`))) {\n checks.get(kv)?.delete(scope);\n }\n}\n\nfunction snapshotCheck(kv: StateKV, scope: string): SnapshotCheck {\n let entries = checks.get(kv);\n if (!entries) checks.set(kv, entries = new Map());\n let check = entries.get(scope);\n if (!check) {\n if (entries.size >= 64) entries.clear();\n check = { clean: false };\n entries.set(scope, check);\n }\n return check;\n}\n\nfunction markChecked(kv: StateKV, scope: string, check: SnapshotCheck): void {\n if (checks.get(kv)?.get(scope) === check) check.clean = true;\n}\n\nexport async function ensureGraphConsistency(kv: StateKV, scope: string): Promise<void> {\n if (recovering.getStore()) return;\n const snapshot = snapshotScope(scope);\n if (!snapshot) return;\n const check = snapshotCheck(kv, snapshot);\n if (check.clean) return;\n const recover = () => withoutGraphRecovery(async () => {\n const recoveryCheck = snapshotCheck(kv, snapshot);\n const current = await kv.get<GraphSnapshot>(snapshot, \"current\");\n const pending = current?.pendingMutation;\n if (pending) {\n if (!current.dirty || !Array.isArray(pending.writes) || pending.snapshot?.version !== 1 || pending.snapshot.pendingMutation) {\n throw new Error(\"Invalid graph reconciliation journal\");\n }\n const suffix = snapshot.slice(KV.graphSnapshot.length);\n for (const write of pending.writes) {\n if (!write || typeof write !== \"object\") throw new Error(\"Invalid graph reconciliation write\");\n if (!scopes.includes(write.scope as typeof scopes[number]) || write.scope === KV.graphSnapshot || typeof write.key !== \"string\") {\n throw new Error(\"Invalid graph reconciliation write\");\n }\n }\n for (const write of pending.writes) {\n if (write.value === null) await kv.delete(write.scope + suffix, write.key);\n else await kv.set(write.scope + suffix, write.key, write.value);\n }\n await kv.set(snapshot, \"current\", pending.snapshot);\n }\n markChecked(kv, snapshot, recoveryCheck);\n });\n if (isKeyedLockHeld(\"graph:persist\")) return recover();\n const peek = await withoutGraphRecovery(() => kv.get<GraphSnapshot>(snapshot, \"current\"));\n // Writes invalidate before and after awaiting the engine, including failures.\n // Retain a clean check only if neither a write nor eviction replaced its token.\n if (!peek?.pendingMutation) {\n markChecked(kv, snapshot, check);\n return;\n }\n await withKeyedLock(\"graph:persist\", recover);\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport type { GraphEdge, GraphNode, GraphSnapshot, GraphRetrievalIndexControl, GraphRetrievalIndexRecord } from \"../types.js\";\nimport type { StateKV } from \"./kv.js\";\nimport { getGraphGeneration, pinGraphState, pinGraphStateGeneration } from \"./graph-generation.js\";\nimport { ensureGraphConsistency, noteGraphSnapshotWrite, withoutGraphRecovery } from \"./graph-consistency.js\";\nimport { isKeyedLockHeld, withKeyedLock } from \"./keyed-mutex.js\";\nimport { KV } from \"./schema.js\";\n\nexport const GRAPH_INDEX_MAX_ID_BYTES = 1024;\nexport const GRAPH_INDEX_MAX_RECORD_BYTES = 32 * 1024;\nconst MAX_CONTROL_BYTES = 8 * 1024;\nconst MAX_PROJECTION_BYTES = 16 * 1024;\nconst MAX_JOURNAL_BYTES = 8 * 1024 * 1024;\nconst MAX_POSTINGS = 192;\nconst CONTROL_KEY = \"current\";\nexport type GraphIndexRecordKind = \"node\" | \"edge\" | \"history\";\nexport type GraphPostingKind = \"name\" | \"character\" | \"observation\" | \"edgeObservation\" | \"edgeKey\" | \"adjacency\" | \"history\" | \"nodes\" | \"edges\" | \"historyEdges\";\nexport type GraphNodeProjection = GraphNode & { indexIncomplete?: boolean };\nexport type GraphEdgeProjection = GraphEdge & { indexIncomplete?: boolean };\ntype PostingRoot = { head: string | null; count: number };\ntype PostingEntry = { id: string; previous: string | null; next: string | null };\ntype IndexWrite = { key: string; value: unknown };\ntype IndexJournal = { schema: 1; buildId: string; revision: number; writes: IndexWrite[]; next: GraphRetrievalIndexControl };\n\nexport class GraphIndexError extends Error {}\nconst bytes = (value: unknown) => Buffer.byteLength(JSON.stringify(value) ?? \"\", \"utf8\");\nconst hash = (value: string) => createHash(\"sha256\").update(JSON.stringify(value)).digest(\"hex\");\nconst validId = (value: unknown): value is string => typeof value === \"string\" && value.length > 0 && Buffer.byteLength(value, \"utf8\") <= GRAPH_INDEX_MAX_ID_BYTES;\nconst finiteCount = (value: unknown): value is number => Number.isSafeInteger(value) && (value as number) >= 0;\nconst boundedOption = (value: number | undefined, fallback: number, max: number) => Number.isFinite(value) ? Math.min(max, Math.max(1, Math.floor(value!))) : fallback;\nconst graphLock = <T>(fn: () => Promise<T>) => isKeyedLockHeld(\"graph:persist\") ? fn() : withKeyedLock(\"graph:persist\", fn);\nasync function lock<T>(state: StateKV, fn: () => Promise<T>): Promise<T> {\n const key = `graph:retrieval:${await getGraphGeneration(state) ?? \"legacy\"}`;\n return isKeyedLockHeld(key) ? fn() : withKeyedLock(key, fn);\n}\nconst WAIT_FOR_BATCH = Symbol(\"graph index batch\");\nconst NODE_TYPES = new Set([\"file\", \"function\", \"concept\", \"error\", \"decision\", \"pattern\", \"library\", \"person\", \"project\", \"preference\", \"location\", \"organization\", \"event\"]);\nconst EDGE_TYPES = new Set([\"uses\", \"imports\", \"modifies\", \"causes\", \"fixes\", \"depends_on\", \"related_to\", \"works_at\", \"prefers\", \"blocked_by\", \"caused_by\", \"optimizes_for\", \"rejected\", \"avoids\", \"located_in\", \"succeeded_by\"]);\nexport const normalizeGraphIndexText = (value: string): string => value.normalize(\"NFKC\").toLowerCase();\nexport const graphEdgeLookupKey = (edge: Pick<GraphEdge, \"sourceNodeId\" | \"targetNodeId\" | \"type\">): string => JSON.stringify([edge.sourceNodeId, edge.targetNodeId, edge.type]);\nconst token = (kind: GraphPostingKind, value: string) => hash(`${kind}\\0${kind === \"name\" || kind === \"character\" ? normalizeGraphIndexText(value) : value}`);\nconst recordKey = (buildId: string, kind: GraphIndexRecordKind, id: string) => `${buildId}:record:${kind}:${hash(id)}`;\nconst rootKey = (buildId: string, posting: string) => `${buildId}:root:${posting}`;\nconst entryKey = (buildId: string, posting: string, id: string) => `${buildId}:entry:${posting}:${id}`;\nconst countKey = (kind: GraphIndexRecordKind) => kind === \"node\" ? \"nodes\" : kind === \"edge\" ? \"edges\" : \"historyEdges\";\n\nfunction validateControl(value: GraphRetrievalIndexControl): void {\n if (bytes(value) > MAX_CONTROL_BYTES || value.schema !== 2 || typeof value.buildId !== \"string\" || !/^[a-zA-Z0-9_-]{1,128}$/.test(value.buildId) ||\n ![\"building\", \"ready\", \"paused\"].includes(value.status) ||\n ![value.revision, value.nodes, value.edges, value.historyEdges, value.incompleteRecords, value.otherTypes].every(finiteCount) ||\n !value.nodesByType || !value.edgesByType ||\n Object.entries(value.nodesByType).some(([type, count]) => (!NODE_TYPES.has(type) && type !== \"other\") || !finiteCount(count)) ||\n Object.entries(value.edgesByType).some(([type, count]) => (!EDGE_TYPES.has(type) && type !== \"other\") || !finiteCount(count)) ||\n (value.batchPending !== undefined && typeof value.batchPending !== \"boolean\") ||\n (value.pending && (![\"node\", \"edge\", \"history\"].includes(value.pending.kind) || !validId(value.pending.id)))) {\n throw new GraphIndexError(\"Invalid graph retrieval index control; run explicit graph-index migration\");\n }\n}\n\nexport async function getGraphIndexStatus(state: StateKV): Promise<GraphRetrievalIndexControl | null> {\n const value = await state.get<GraphRetrievalIndexControl>(KV.graphRetrievalControl, CONTROL_KEY);\n if (value !== null && value !== undefined) validateControl(value);\n return value ?? null;\n}\n\nexport async function initializeGraphIndex(state: StateKV, options: { status: \"building\" | \"ready\"; buildId?: string }): Promise<GraphRetrievalIndexControl> {\n const kv = await pinGraphState(state);\n return lock(kv, async () => {\n const value: GraphRetrievalIndexControl = { schema: 2, buildId: options.buildId ?? randomUUID(), status: options.status,\n revision: 0, nodes: 0, edges: 0, historyEdges: 0, incompleteRecords: 0, nodesByType: {}, edgesByType: {}, otherTypes: 0, updatedAt: new Date().toISOString() };\n validateControl(value);\n const previous = await kv.get<GraphRetrievalIndexControl>(KV.graphRetrievalControl, CONTROL_KEY);\n if (previous?.buildId === value.buildId) throw new GraphIndexError(\"A graph index rebuild requires a new build ID\");\n await kv.set(KV.graphRetrievalControl, CONTROL_KEY, value);\n return value;\n });\n}\n\nfunction project(kind: GraphIndexRecordKind, id: string, input: unknown): GraphRetrievalIndexRecord | null {\n if (input === null || input === undefined) return null;\n const source = input as Record<string, unknown>;\n if (!source || typeof source !== \"object\" || Array.isArray(source) || !validId(id) || source.id !== id) {\n return { row: null, postings: [], incomplete: true };\n }\n if (source.stale === true) return { row: null, postings: [], incomplete: false };\n let incomplete = false;\n const text = (value: unknown, max = 512): string => {\n if (typeof value !== \"string\") { incomplete = true; return \"\"; }\n const result = Array.from(value.slice(0, max * 2)).slice(0, max).join(\"\");\n if (result !== value) incomplete = true;\n return result;\n };\n const ids: string[] = [];\n if (!Array.isArray(source.sourceObservationIds)) incomplete = true;\n else for (const value of source.sourceObservationIds.slice(0, 512)) {\n if (!validId(value)) { incomplete = true; continue; }\n if (ids.includes(value)) continue;\n if (ids.length >= 128) { incomplete = true; break; }\n ids.push(value);\n }\n if (Array.isArray(source.sourceObservationIds) && source.sourceObservationIds.length > 512) incomplete = true;\n const common = { id, type: text(source.type, 64), sourceObservationIds: ids, createdAt: text(source.createdAt, 64) };\n let row: GraphNodeProjection | GraphEdgeProjection;\n if (kind === \"node\") {\n const properties: Record<string, unknown> = {};\n if (!source.properties || typeof source.properties !== \"object\" || Array.isArray(source.properties)) incomplete = true;\n else for (const key in source.properties) {\n if (!Object.hasOwn(source.properties, key)) continue;\n if (Object.keys(properties).length >= 32) { incomplete = true; break; }\n const value = (source.properties as Record<string, unknown>)[key];\n if (key.length > 128) { incomplete = true; continue; }\n if (typeof value === \"string\") Object.defineProperty(properties, key, { value: text(value), enumerable: true, writable: true, configurable: true });\n else if (typeof value === \"boolean\" || (typeof value === \"number\" && Number.isFinite(value))) Object.defineProperty(properties, key, { value, enumerable: true, writable: true, configurable: true });\n else incomplete = true;\n }\n const aliases = Array.isArray(source.aliases) ? source.aliases.slice(0, 16).filter((v): v is string => typeof v === \"string\").map((v) => text(v)) : [];\n if (Array.isArray(source.aliases) && aliases.length !== source.aliases.length) incomplete = true;\n row = { ...common, type: common.type as GraphNode[\"type\"], name: text(source.name), properties, ...(aliases.length ? { aliases } : {}),\n ...(typeof source.updatedAt === \"string\" ? { updatedAt: text(source.updatedAt, 64) } : {}) };\n } else {\n if (!validId(source.sourceNodeId) || !validId(source.targetNodeId)) return { row: null, postings: [], incomplete: true };\n const edge: GraphEdgeProjection = { ...common, type: common.type as GraphEdge[\"type\"], sourceNodeId: source.sourceNodeId,\n targetNodeId: source.targetNodeId, weight: typeof source.weight === \"number\" && Number.isFinite(source.weight) ? source.weight : 0 };\n if (edge.weight !== source.weight) incomplete = true;\n for (const key of [\"tcommit\", \"tvalid\", \"tvalidEnd\", \"supersededBy\"] as const) if (typeof source[key] === \"string\") edge[key] = text(source[key], key === \"supersededBy\" ? 1024 : 64);\n if (typeof source.version === \"number\" && Number.isFinite(source.version)) edge.version = source.version;\n if (typeof source.isLatest === \"boolean\") edge.isLatest = source.isLatest;\n if (source.context && typeof source.context === \"object\" && !Array.isArray(source.context)) {\n const context = source.context as Record<string, unknown>;\n edge.context = {};\n for (const key of [\"reasoning\", \"sentiment\"] as const) if (typeof context[key] === \"string\") edge.context[key] = text(context[key]);\n if (typeof context.confidence === \"number\" && Number.isFinite(context.confidence)) edge.context.confidence = context.confidence;\n if (context.alternatives !== undefined || context.situationalFactors !== undefined) incomplete = true;\n }\n row = edge;\n }\n while (bytes(row) > MAX_PROJECTION_BYTES - 64) {\n incomplete = true;\n if (\"properties\" in row && Object.keys(row.properties).length) delete row.properties[Object.keys(row.properties).at(-1)!];\n else if (\"aliases\" in row && row.aliases?.length) row.aliases.pop();\n else if (\"context\" in row && row.context) delete row.context;\n else if (row.sourceObservationIds.length) row.sourceObservationIds.pop();\n else return { row: null, postings: [], incomplete: true };\n }\n const postings = new Set<string>([token(countKey(kind), \"\")]);\n if (kind === \"node\") {\n const node = row as GraphNodeProjection;\n for (const value of [node.name, ...(node.aliases ?? [])]) postings.add(token(\"name\", value));\n const searchable = [node.name, ...(node.aliases ?? []), ...Object.values(node.properties).filter((v): v is string => typeof v === \"string\")];\n const characters = new Set(searchable.flatMap((value) => Array.from(normalizeGraphIndexText(value))));\n for (const character of characters) {\n if (postings.size >= MAX_POSTINGS - row.sourceObservationIds.length) { incomplete = true; break; }\n postings.add(token(\"character\", character));\n }\n for (const observationId of row.sourceObservationIds) postings.add(token(\"observation\", observationId));\n } else {\n const edge = row as GraphEdgeProjection;\n for (const nodeId of [edge.sourceNodeId, edge.targetNodeId]) postings.add(token(kind === \"history\" ? \"history\" : \"adjacency\", nodeId));\n if (kind === \"edge\") {\n if (edge.isLatest !== false) postings.add(token(\"edgeKey\", graphEdgeLookupKey(edge)));\n for (const observationId of row.sourceObservationIds) postings.add(token(\"edgeObservation\", observationId));\n }\n }\n if (incomplete) row.indexIncomplete = true;\n return { row, postings: [...postings], incomplete };\n}\n\nfunction validateRecord(value: GraphRetrievalIndexRecord): void {\n if (bytes(value) > GRAPH_INDEX_MAX_RECORD_BYTES || !Array.isArray(value.postings) || value.postings.length > MAX_POSTINGS ||\n value.postings.some((p) => !/^[a-f0-9]{64}$/.test(p)) || typeof value.incomplete !== \"boolean\") throw new GraphIndexError(\"Invalid graph retrieval record\");\n}\n\nasync function planRecord(kv: StateKV, control: GraphRetrievalIndexControl, kind: GraphIndexRecordKind, id: string, input: unknown): Promise<IndexJournal> {\n const writes = new Map<string, unknown>();\n const read = async <T>(key: string): Promise<T | null> => writes.has(key) ? writes.get(key) as T | null : kv.get<T>(KV.graphRetrievalData, key);\n const put = (key: string, value: unknown) => { if (bytes(value) > GRAPH_INDEX_MAX_RECORD_BYTES) throw new GraphIndexError(\"Graph retrieval index write exceeds record budget\"); writes.set(key, value); };\n const key = recordKey(control.buildId, kind, id);\n const before = await read<GraphRetrievalIndexRecord>(key);\n if (before) validateRecord(before);\n const after = project(kind, id, input);\n if (after) validateRecord(after);\n const memberId = hash(id);\n const editPosting = async (posting: string, add: boolean) => {\n const rootId = rootKey(control.buildId, posting), itemId = entryKey(control.buildId, posting, memberId);\n const root = await read<PostingRoot>(rootId) ?? { head: null, count: 0 };\n const saved = await read<PostingEntry>(itemId);\n if (!finiteCount(root.count) || (root.head !== null && !/^[a-f0-9]{64}$/.test(root.head))) throw new GraphIndexError(\"Invalid graph posting root\");\n if (add) {\n if (saved) return;\n if (root.head) {\n const headId = entryKey(control.buildId, posting, root.head), head = await read<PostingEntry>(headId);\n if (!head) throw new GraphIndexError(\"Missing graph posting head\");\n put(headId, { ...head, previous: memberId });\n }\n put(itemId, { id, previous: null, next: root.head });\n put(rootId, { head: memberId, count: root.count + 1 });\n } else {\n if (!saved) return;\n if (saved.previous) {\n const previousId = entryKey(control.buildId, posting, saved.previous), previous = await read<PostingEntry>(previousId);\n if (!previous) throw new GraphIndexError(\"Missing previous graph posting entry\");\n put(previousId, { ...previous, next: saved.next });\n } else {\n if (root.head !== memberId) throw new GraphIndexError(\"Invalid graph posting head link\");\n root.head = saved.next;\n }\n if (saved.next) {\n const nextId = entryKey(control.buildId, posting, saved.next), next = await read<PostingEntry>(nextId);\n if (!next) throw new GraphIndexError(\"Missing next graph posting entry\");\n put(nextId, { ...next, previous: saved.previous });\n }\n put(itemId, null);\n put(rootId, { head: root.head, count: Math.max(0, root.count - 1) });\n }\n };\n const oldPostings = new Set(before?.postings ?? []), newPostings = new Set(after?.postings ?? []);\n for (const posting of oldPostings) if (!newPostings.has(posting)) await editPosting(posting, false);\n for (const posting of newPostings) if (!oldPostings.has(posting)) await editPosting(posting, true);\n put(key, after);\n const { pending: _, ...clean } = control;\n const next = { ...clean, revision: control.revision + 1, updatedAt: new Date().toISOString() };\n const counted = (row: GraphNode | GraphEdge | null | undefined) => Boolean(row && (kind !== \"edge\" || (row as GraphEdge).isLatest !== false));\n next[countKey(kind)] += Number(counted(after?.row)) - Number(counted(before?.row));\n next.incompleteRecords += Number(Boolean(after?.incomplete)) - Number(Boolean(before?.incomplete));\n if (kind !== \"history\") {\n const field = kind === \"node\" ? \"nodesByType\" : \"edgesByType\";\n const known = kind === \"node\" ? NODE_TYPES : EDGE_TYPES;\n next[field] = { ...control[field] };\n for (const [row, amount] of [[before?.row, -1], [after?.row, 1]] as const) {\n if (!row || !counted(row)) continue;\n const type = known.has(row.type) ? row.type : \"other\";\n next[field][type] = (next[field][type] ?? 0) + amount;\n if (!next[field][type]) delete next[field][type];\n if (type === \"other\") next.otherTypes += amount;\n }\n }\n validateControl(next);\n const journal: IndexJournal = { schema: 1, buildId: control.buildId, revision: control.revision, writes: [...writes].map(([key, value]) => ({ key, value })), next };\n if (bytes(journal) > MAX_JOURNAL_BYTES) throw new GraphIndexError(\"Graph retrieval index journal exceeds payload budget\");\n return journal;\n}\n\nasync function applyJournal(kv: StateKV, control: GraphRetrievalIndexControl, journal: IndexJournal): Promise<void> {\n if (journal.schema !== 1 || journal.buildId !== control.buildId || journal.revision !== control.revision ||\n !Array.isArray(journal.writes) || journal.writes.length > 2048 || bytes(journal) > MAX_JOURNAL_BYTES || journal.next.buildId !== control.buildId ||\n journal.next.revision !== control.revision + 1 || journal.next.pending) throw new GraphIndexError(\"Invalid graph retrieval recovery journal\");\n validateControl(journal.next);\n for (const write of journal.writes) {\n if (!write || typeof write.key !== \"string\" || !write.key.startsWith(`${control.buildId}:`) || write.key.length > 512 || bytes(write.value) > GRAPH_INDEX_MAX_RECORD_BYTES) {\n throw new GraphIndexError(\"Invalid graph retrieval recovery write\");\n }\n }\n for (const write of journal.writes) {\n if (write.value === null) await kv.delete(KV.graphRetrievalData, write.key);\n else await kv.set(KV.graphRetrievalData, write.key, write.value);\n }\n await kv.set(KV.graphRetrievalControl, CONTROL_KEY, journal.next);\n}\n\nasync function reconcilePending(kv: StateKV, control: GraphRetrievalIndexControl, input?: unknown): Promise<void> {\n if (!control.pending) return;\n const journalKey = `journal:${control.buildId}`;\n const saved = await kv.get<IndexJournal>(KV.graphRetrievalControl, journalKey);\n if (saved?.buildId === control.buildId && saved.revision === control.revision) return applyJournal(kv, control, saved);\n const { kind, id } = control.pending;\n const scope = kind === \"node\" ? KV.graphNodes : kind === \"edge\" ? KV.graphEdges : KV.graphEdgeHistory;\n const row = input === undefined ? await withoutGraphRecovery(() => kv.get(scope, id)) : input;\n const journal = await planRecord(kv, control, kind, id, row);\n await kv.set(KV.graphRetrievalControl, journalKey, journal);\n await applyJournal(kv, control, journal);\n}\n\nexport async function recoverGraphIndex(state: StateKV, options: { allowSnapshotRecovery?: boolean } = {}): Promise<void> {\n const kv = await pinGraphState(state);\n await graphLock(() => lock(kv, async () => {\n let control = await getGraphIndexStatus(kv);\n if (control?.batchPending && options.allowSnapshotRecovery) {\n const snapshot = await withoutGraphRecovery(() => kv.get<GraphSnapshot>(KV.graphSnapshot, \"current\"));\n if (snapshot?.pendingMutation) {\n const generation = await getGraphGeneration(kv);\n const scope = generation === null ? KV.graphSnapshot : `${KV.graphSnapshot}:generation:${generation}`;\n noteGraphSnapshotWrite(kv, scope, \"current\");\n await ensureGraphConsistency(kv, scope);\n } else if (snapshot && !snapshot.dirty) {\n const { batchPending: _, ...clean } = control;\n await kv.set(KV.graphRetrievalControl, CONTROL_KEY, { ...clean, revision: clean.revision + 1 });\n }\n control = await getGraphIndexStatus(kv);\n }\n if (control?.pending) await reconcilePending(kv, control);\n }));\n}\n\nexport async function reconcileGraphIndexRecord(state: StateKV, kind: GraphIndexRecordKind, id: string, row: GraphNode | GraphEdge | null, options: { readCanonical?: boolean } = {}): Promise<void> {\n const kv = await pinGraphState(state);\n await lock(kv, async () => {\n let control = await getGraphIndexStatus(kv);\n if (!control) throw new GraphIndexError(\"Graph retrieval index must be initialized explicitly\");\n if (control.status === \"paused\") throw new GraphIndexError(\"Graph retrieval index is paused; run explicit migration\");\n if (control.pending) { await reconcilePending(kv, control); control = (await getGraphIndexStatus(kv))!; }\n if (!validId(id)) throw new GraphIndexError(\"Graph record ID exceeds index migration budget\");\n control = { ...control, pending: { kind, id } };\n await kv.set(KV.graphRetrievalControl, CONTROL_KEY, control);\n await reconcilePending(kv, control, options.readCanonical ? undefined : row);\n });\n}\n\nexport async function mutateIndexedGraphRecord(state: StateKV, kind: GraphIndexRecordKind, id: string, transform: (row: GraphNode | GraphEdge | null) => GraphNode | GraphEdge | null | undefined): Promise<boolean> {\n const kv = await pinGraphState(state);\n return graphLock(() => lock(kv, async () => {\n const control = await getGraphIndexStatus(kv);\n if (!control || control.status !== \"ready\" || control.pending || control.batchPending) throw new GraphIndexError(\"Graph index is unavailable; retry the graph mutation after recovery\");\n const scope = kind === \"node\" ? KV.graphNodes : kind === \"edge\" ? KV.graphEdges : KV.graphEdgeHistory;\n const current = await withoutGraphRecovery(() => kv.get<GraphNode | GraphEdge>(scope, id));\n const next = transform(current);\n if (next === undefined) return false;\n if (next === null) await withoutGraphRecovery(() => kv.delete(scope, id));\n else await withoutGraphRecovery(() => kv.set(scope, id, next));\n return true;\n }));\n}\n\nexport async function finishGraphIndexBuild(state: StateKV, buildId: string): Promise<GraphRetrievalIndexControl> {\n const kv = await pinGraphState(state);\n return lock(kv, async () => {\n const current = await getGraphIndexStatus(kv);\n if (!current || current.buildId !== buildId || current.status === \"paused\" || current.pending || current.batchPending) throw new GraphIndexError(\"Graph index build is incomplete or superseded\");\n const next = { ...current, status: \"ready\" as const, revision: current.revision + 1, updatedAt: new Date().toISOString() };\n await kv.set(KV.graphRetrievalControl, CONTROL_KEY, next);\n return next;\n });\n}\n\nfunction canonicalScope(scope: string): { kind: GraphIndexRecordKind; generation: string | null } | null {\n for (const [base, kind] of [[KV.graphNodes, \"node\"], [KV.graphEdges, \"edge\"], [KV.graphEdgeHistory, \"history\"]] as const) {\n if (scope === base) return { kind, generation: null };\n if (scope.startsWith(`${base}:generation:`)) return { kind, generation: scope.slice(base.length + 12) };\n }\n return null;\n}\n\nexport async function withGraphIndexMutation<T>(state: StateKV, scope: string, id: string, mutate: () => Promise<T>): Promise<T> {\n const location = canonicalScope(scope);\n if (!location) return mutate();\n const kv = pinGraphStateGeneration(state, location.generation);\n const run = () => lock(kv, async () => {\n let control = await getGraphIndexStatus(kv);\n if (!control || control.status === \"paused\") return mutate();\n if (control.batchPending && !isKeyedLockHeld(\"graph:persist\")) throw WAIT_FOR_BATCH;\n if (control.pending) { await reconcilePending(kv, control); control = (await getGraphIndexStatus(kv))!; }\n if (!validId(id)) {\n await kv.set(KV.graphRetrievalControl, CONTROL_KEY, { ...control, status: \"paused\", error: \"Graph record ID exceeds bounded recovery budget\", revision: control.revision + 1 });\n return mutate();\n }\n control = { ...control, pending: { kind: location.kind, id } };\n await kv.set(KV.graphRetrievalControl, CONTROL_KEY, control);\n const result = await mutate();\n await reconcilePending(kv, control);\n return result;\n });\n try { return await run(); } catch (error) {\n if (error !== WAIT_FOR_BATCH) throw error;\n return graphLock(run);\n }\n}\n\nexport async function withGraphSnapshotIndexBarrier<T>(state: StateKV, scope: string, key: string, value: unknown, mutate: () => Promise<T>): Promise<T> {\n if (key !== \"current\" || !(scope === KV.graphSnapshot || scope.startsWith(`${KV.graphSnapshot}:generation:`))) return mutate();\n const kv = pinGraphStateGeneration(state, scope === KV.graphSnapshot ? null : scope.slice(KV.graphSnapshot.length + 12));\n return graphLock(() => lock(kv, async () => {\n const control = await getGraphIndexStatus(kv);\n if (!control) return mutate();\n const snapshot = value as GraphSnapshot | null;\n const dirty = !snapshot || typeof snapshot !== \"object\" || snapshot.version !== 1 || snapshot.dirty !== false || Boolean(snapshot.pendingMutation);\n if (dirty && !control.batchPending) await kv.set(KV.graphRetrievalControl, CONTROL_KEY, { ...control, batchPending: true });\n const result = await mutate();\n if (!dirty) {\n const after = await getGraphIndexStatus(kv);\n if (after?.batchPending && !after.pending) {\n const { batchPending: _, ...clean } = after;\n await kv.set(KV.graphRetrievalControl, CONTROL_KEY, { ...clean, revision: clean.revision + 1, updatedAt: new Date().toISOString() });\n }\n }\n return result;\n }));\n}\n\nexport async function withGraphSnapshotUnknownMutation<T>(state: StateKV, scope: string, key: string, mutate: () => Promise<T>): Promise<T> {\n if (key !== \"current\" || !(scope === KV.graphSnapshot || scope.startsWith(`${KV.graphSnapshot}:generation:`))) return mutate();\n return graphLock(async () => {\n const result = await withGraphSnapshotIndexBarrier(state, scope, key, { dirty: true }, mutate);\n const snapshot = await withoutGraphRecovery(() => state.get(scope, key));\n return withGraphSnapshotIndexBarrier(state, scope, key, snapshot, async () => result);\n });\n}\n\nexport interface GraphIndexReaderOptions { signal?: AbortSignal; maxReads?: number; maxBytes?: number; maxConcurrent?: number }\nexport class GraphIndexReader {\n readonly status: GraphRetrievalIndexControl;\n exhausted = false;\n private reads = 2;\n private readBytes: number;\n private active = 0;\n private waiting: Array<() => void> = [];\n private cache = new Map<string, Promise<unknown>>();\n private readonly maxReads: number;\n private readonly maxBytes: number;\n private readonly maxConcurrent: number;\n constructor(private state: StateKV, private generation: string | null, status: GraphRetrievalIndexControl, private options: GraphIndexReaderOptions) {\n this.status = status;\n this.readBytes = bytes(status);\n this.maxReads = boundedOption(options.maxReads, 512, 4096);\n this.maxBytes = boundedOption(options.maxBytes, 2 * 1024 * 1024, 16 * 1024 * 1024);\n this.maxConcurrent = boundedOption(options.maxConcurrent, 4, 8);\n }\n get remainingReads(): number { return Math.max(0, this.maxReads - this.reads - 2); }\n async read<T>(scope: string, key: string): Promise<T | null> {\n if (scope !== KV.graphRetrievalData) return this.readFresh<T>(scope, key);\n const cached = this.cache.get(key);\n if (cached) return cached as Promise<T | null>;\n const pending = this.readFresh<T>(scope, key);\n if (!this.exhausted) this.cache.set(key, pending);\n return pending;\n }\n async readFresh<T>(scope: string, key: string): Promise<T | null> {\n if (this.options.signal?.aborted || this.exhausted || this.remainingReads === 0 || this.readBytes >= this.maxBytes) { this.exhausted = true; return null; }\n this.reads++;\n if (this.active >= this.maxConcurrent) await new Promise<void>((resolve) => this.waiting.push(resolve));\n else this.active++;\n try {\n if (this.options.signal?.aborted || this.exhausted) { this.exhausted = true; return null; }\n const value = await this.state.get<T>(scope, key);\n const size = bytes(value);\n this.readBytes += size;\n if (this.readBytes > this.maxBytes || this.options.signal?.aborted) { this.exhausted = true; return null; }\n if (scope === KV.graphRetrievalData && size > GRAPH_INDEX_MAX_RECORD_BYTES) throw new GraphIndexError(\"Graph retrieval record exceeds payload budget\");\n return value;\n } finally {\n const next = this.waiting.shift();\n if (next) next(); else this.active--;\n }\n }\n private async record(kind: GraphIndexRecordKind, id: string): Promise<GraphRetrievalIndexRecord | null> {\n if (!validId(id)) { this.exhausted = true; return null; }\n const value = await this.read<GraphRetrievalIndexRecord>(KV.graphRetrievalData, recordKey(this.status.buildId, kind, id));\n if (value) validateRecord(value);\n return value;\n }\n async getNode(id: string): Promise<GraphNodeProjection | null> { return (await this.record(\"node\", id))?.row as GraphNodeProjection | null ?? null; }\n async getEdge(id: string): Promise<GraphEdgeProjection | null> { return (await this.record(\"edge\", id))?.row as GraphEdgeProjection | null ?? null; }\n async getHistoryEdge(id: string): Promise<GraphEdgeProjection | null> { return (await this.record(\"history\", id))?.row as GraphEdgeProjection | null ?? null; }\n async posting(kind: GraphPostingKind, key = \"\", options: { cursor?: string | null; limit?: number } = {}): Promise<{ ids: string[]; cursor: string | null; total: number }> {\n const posting = token(kind, key), root = await this.read<PostingRoot>(KV.graphRetrievalData, rootKey(this.status.buildId, posting));\n const inventoryCount = key === \"\" && (kind === \"nodes\" || kind === \"edges\" || kind === \"historyEdges\") ? this.status[kind] : undefined;\n if (!root) {\n if (!this.exhausted && inventoryCount) throw new GraphIndexError(\"Missing graph inventory root\");\n return { ids: [], cursor: null, total: 0 };\n }\n if (!finiteCount(root.count) || (root.head !== null && !/^[a-f0-9]{64}$/.test(root.head)) ||\n (root.count === 0) !== (root.head === null)) throw new GraphIndexError(\"Invalid graph posting root\");\n if (inventoryCount !== undefined && (kind === \"edges\" ? root.count < inventoryCount : root.count !== inventoryCount)) {\n throw new GraphIndexError(\"Graph inventory count does not match index control\");\n }\n const prefix = `${this.status.buildId}.${this.status.revision}.${posting}.`;\n if (options.cursor && (!options.cursor.startsWith(prefix) || !/^[a-f0-9]{64}$/.test(options.cursor.slice(prefix.length)))) throw new GraphIndexError(\"Invalid or expired graph posting cursor\");\n let current = options.cursor ? options.cursor.slice(prefix.length) : root.head;\n const limit = boundedOption(options.limit, 64, 128), ids: string[] = [], seen = new Set<string>();\n while (current && ids.length < limit) {\n if (seen.has(current)) throw new GraphIndexError(\"Cyclic graph posting entry\");\n seen.add(current);\n const value = await this.read<PostingEntry>(KV.graphRetrievalData, entryKey(this.status.buildId, posting, current));\n if (!value) { if (this.exhausted) break; throw new GraphIndexError(\"Missing graph posting entry\"); }\n if (!validId(value.id) || hash(value.id) !== current || (value.next !== null && !/^[a-f0-9]{64}$/.test(value.next))) throw new GraphIndexError(\"Invalid graph posting entry\");\n ids.push(value.id); current = value.next;\n }\n return { ids, cursor: current ? `${prefix}${current}` : null, total: root.count };\n }\n async finish(): Promise<boolean> {\n if (this.options.signal?.aborted || this.reads + 2 > this.maxReads) return false;\n this.reads += 2;\n const current = await getGraphIndexStatus(this.state);\n const generation = await this.state.get<string>(KV.graphControl, \"generation\");\n if ((generation ?? null) !== this.generation) return false;\n this.readBytes += bytes(generation) + bytes(current);\n if (this.readBytes > this.maxBytes) { this.exhausted = true; return false; }\n return Boolean(current && current.status === \"ready\" && !current.pending && !current.batchPending && current.buildId === this.status.buildId && current.revision === this.status.revision);\n }\n}\n\nexport async function createGraphIndexReader(state: StateKV, options: GraphIndexReaderOptions = {}): Promise<GraphIndexReader | null> {\n if (options.signal?.aborted) return null;\n const kv = await pinGraphState(state), generation = await getGraphGeneration(kv), status = await getGraphIndexStatus(kv);\n if (!status || status.status !== \"ready\" || status.pending || status.batchPending) return null;\n return new GraphIndexReader(kv, generation, status, options);\n}\n","import type { StateKV } from \"../state/kv.js\";\nimport { createGraphIndexReader, normalizeGraphIndexText } from \"../state/graph-retrieval-index.js\";\nimport type { GraphEdge, GraphNode, GraphQueryResult } from \"../types.js\";\n\nexport interface IndexedGraphQuery {\n startNodeId?: string;\n nodeType?: string;\n maxDepth?: number;\n query?: string;\n limit?: number;\n offset?: number;\n}\n\nexport async function queryGraphIndex(state: StateKV, data: IndexedGraphQuery): Promise<GraphQueryResult> {\n const integer = (value: number | undefined, fallback: number) =>\n typeof value === \"number\" && Number.isFinite(value) ? Math.floor(value) : fallback;\n const limit = Math.max(1, Math.min(integer(data.limit, 500), 500));\n const offset = Math.max(0, integer(data.offset, 0));\n const maxDepth = Math.max(0, Math.min(integer(data.maxDepth, 3), 5));\n const empty = (warning: string): GraphQueryResult => ({\n nodes: [], edges: [], depth: 0, totalNodes: 0, totalEdges: 0,\n truncated: true, limit, offset, warning,\n });\n try {\n const reader = await createGraphIndexReader(state, { maxReads: 2048, maxBytes: 4 * 1024 * 1024 });\n if (!reader) return empty(\"Graph index is unavailable. Run agentmemory graph-index status; legacy stores require an explicit migration.\");\n const nodes: GraphNode[] = [];\n const edges = new Map<string, GraphEdge>();\n let truncated = reader.status.incompleteRecords > 0;\n let fullyScanned = false;\n let depth = 0;\n const query = data.query ? normalizeGraphIndexText(data.query) : \"\";\n const matches = (node: GraphNode) => (!data.nodeType || node.type === data.nodeType) && (!query ||\n normalizeGraphIndexText(node.name).includes(query) ||\n Object.values(node.properties ?? {}).some(value => typeof value === \"string\" && normalizeGraphIndexText(value).includes(query)));\n\n if (data.startNodeId && !query) {\n const queue = [{ id: data.startNodeId, depth: 0 }];\n const queued = new Set([data.startNodeId]);\n const visited = new Set<string>();\n for (let head = 0; head < queue.length && !reader.exhausted; head++) {\n const item = queue[head]!;\n if (visited.has(item.id) || item.depth > maxDepth) continue;\n visited.add(item.id);\n const node = await reader.getNode(item.id);\n if (!node || node.stale) continue;\n depth = Math.max(depth, item.depth);\n if (matches(node)) nodes.push(node);\n let cursor: string | undefined;\n do {\n const page = await reader.posting(\"adjacency\", item.id, { cursor, limit: 64 });\n for (const id of page.ids) {\n const edge = await reader.getEdge(id);\n if (!edge || edge.stale || edge.isLatest === false) continue;\n edges.set(edge.id, edge);\n const next = edge.sourceNodeId === item.id ? edge.targetNodeId : edge.sourceNodeId;\n if (item.depth < maxDepth && !queued.has(next)) {\n if (queue.length < 512) {\n queue.push({ id: next, depth: item.depth + 1 });\n queued.add(next);\n }\n else truncated = true;\n }\n }\n cursor = page.cursor ?? undefined;\n } while (cursor && !reader.exhausted);\n if (cursor) truncated = true;\n }\n fullyScanned = !reader.exhausted && !truncated;\n } else {\n let cursor: string | undefined;\n do {\n const page = await reader.posting(query ? \"character\" : \"nodes\", query ? Array.from(query)[0]! : \"\", { cursor, limit: 64 });\n for (const id of page.ids) {\n const node = await reader.getNode(id);\n if (node && !node.stale && matches(node)) nodes.push(node);\n }\n cursor = page.cursor ?? undefined;\n fullyScanned = !cursor && !reader.exhausted;\n } while (cursor && nodes.length < offset + limit && !reader.exhausted);\n if (cursor) truncated = true;\n }\n\n const pageNodes = nodes.slice(offset, offset + limit);\n const ids = new Set(pageNodes.map(node => node.id));\n if (!data.startNodeId || query) {\n for (const node of pageNodes) {\n let cursor: string | undefined;\n do {\n const page = await reader.posting(\"adjacency\", node.id, { cursor, limit: 64 });\n for (const id of page.ids) {\n if (edges.has(id)) continue;\n const edge = await reader.getEdge(id);\n if (edge && !edge.stale && edge.isLatest !== false && ids.has(edge.sourceNodeId) && ids.has(edge.targetNodeId)) edges.set(id, edge);\n }\n cursor = page.cursor ?? undefined;\n } while (cursor && !reader.exhausted);\n if (cursor || reader.exhausted) { truncated = true; break; }\n }\n }\n if (!await reader.finish()) return empty(\"Graph changed during the query. Retry to read a consistent index revision.\");\n const pageEdges = [...edges.values()].filter(edge => ids.has(edge.sourceNodeId) && ids.has(edge.targetNodeId));\n const allNodes = !query && !data.startNodeId && !data.nodeType;\n truncated ||= reader.exhausted || !fullyScanned || nodes.length > pageNodes.length;\n return {\n nodes: pageNodes, edges: pageEdges, depth: data.startNodeId && !query ? maxDepth : depth,\n totalNodes: allNodes ? reader.status.nodes : nodes.length,\n totalEdges: allNodes ? reader.status.edges : pageEdges.length,\n truncated, limit, offset, fromSnapshot: false,\n ...(truncated ? { warning: \"Graph response is bounded. Filtered counts describe examined records; some nodes, edges or oversized fields may be omitted.\" } : {}),\n };\n } catch {\n return empty(\"Graph index could not be read consistently. Run agentmemory graph-index status before retrying.\");\n }\n}\n","export const GRAPH_EXTRACTION_SYSTEM = `You are a knowledge graph extraction engine. Given a compressed observation from a coding session, extract entities and relationships.\n\nOutput format (XML):\n<entities>\n <entity type=\"file|function|concept|error|decision|pattern|library|person\" name=\"exact name\">\n <property key=\"key\">value</property>\n </entity>\n</entities>\n<relationships>\n <relationship type=\"uses|imports|modifies|causes|fixes|depends_on|related_to\" source=\"entity name\" target=\"entity name\" weight=\"0.1-1.0\"/>\n</relationships>\n\nRules:\n- Extract concrete entities only (real file paths, function names, library names)\n- Use the most specific type available\n- Weight relationships by how strong/direct the connection is\n- If no entities found, output empty tags`;\n\nexport function buildGraphExtractionPrompt(\n observations: Array<{\n title: string;\n narrative: string;\n concepts: string[];\n files: string[];\n type: string;\n }>,\n): string {\n const items = observations\n .map(\n (o, i) =>\n `[${i + 1}] Type: ${o.type}\\nTitle: ${o.title}\\nNarrative: ${o.narrative}\\nConcepts: ${(o.concepts ?? []).join(\", \")}\\nFiles: ${(o.files ?? []).join(\", \")}`,\n )\n .join(\"\\n\\n\");\n // Some local models default to a hidden reasoning pass that consumes\n // most of the token budget before any output. The suffix is their\n // documented soft switch to skip it; other models ignore the token.\n const noThink = process.env.AGENTMEMORY_LLM_NOTHINK === \"1\" ? \"\\n/no_think\" : \"\";\n return `Extract entities and relationships from these observations:\\n\\n${items}${noThink}`;\n}\n","import { getGraphIndexStatus } from \"../state/graph-retrieval-index.js\";\nimport { queryGraphIndex } from \"./graph-index-query.js\";\nimport { isLegacyGraphState, pinGraphState, resetGraphGeneration } from \"../state/graph-generation.js\";\nimport type { IIIClient } from \"iii-sdk\";\nimport type {\n GraphNode,\n GraphEdge,\n GraphQueryResult,\n GraphSnapshot,\n CompressedObservation,\n MemoryProvider,\n} from \"../types.js\";\nimport { KV, generateId } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport {\n GRAPH_EXTRACTION_SYSTEM,\n buildGraphExtractionPrompt,\n} from \"../prompts/graph-extraction.js\";\nimport { isGraphExtractionEnabled } from \"../config.js\";\nimport { recordAudit, safeAudit } from \"./audit.js\";\nimport { logger } from \"../logger.js\";\nimport { scrubRecord } from \"./privacy.js\";\n\nconst DEFAULT_GRAPH_QUERY_LIMIT = 500;\n\nconst SNAPSHOT_TOP_NODES = DEFAULT_GRAPH_QUERY_LIMIT;\nconst SNAPSHOT_KEY = \"current\";\n\n// This deadline applies only to explicitly requested legacy snapshot rebuilds.\nconst LIVE_ENUMERATION_BUDGET_MS = 6000;\n\nfunction withTimeout<T>(p: Promise<T>, ms: number, label: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const t = setTimeout(\n () => reject(new Error(`${label}: exceeded ${ms}ms budget`)),\n ms,\n );\n p.then(\n (v) => {\n clearTimeout(t);\n resolve(v);\n },\n (err) => {\n clearTimeout(t);\n reject(err);\n },\n );\n });\n}\n\nfunction emptySnapshot(): GraphSnapshot {\n return {\n version: 1,\n topNodes: [],\n topEdges: [],\n topDegrees: {},\n stats: {\n totalNodes: 0,\n totalEdges: 0,\n nodesByType: {},\n edgesByType: {},\n },\n updatedAt: new Date(0).toISOString(),\n dirty: true,\n };\n}\n\nasync function readSnapshot(kv: StateKV): Promise<GraphSnapshot | null> {\n try {\n const snap = await kv.get<GraphSnapshot>(KV.graphSnapshot, SNAPSHOT_KEY);\n if (snap && typeof snap === \"object\" && snap.version === 1) {\n return snap;\n }\n return null;\n } catch (err) {\n logger.warn(\"Graph snapshot read failed\", {\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n}\n\nasync function readSnapshotStrict(kv: StateKV): Promise<GraphSnapshot | null> {\n let raw: unknown;\n try {\n raw = await kv.get<unknown>(KV.graphSnapshot, SNAPSHOT_KEY);\n } catch (err) {\n logger.warn(\"Graph snapshot read failed, retrying once\", {\n error: err instanceof Error ? err.message : String(err),\n });\n raw = await kv.get<unknown>(KV.graphSnapshot, SNAPSHOT_KEY);\n }\n if (raw === null || raw === undefined) return null;\n if (typeof raw === \"object\" && (raw as { version?: unknown }).version === 1) {\n return raw as GraphSnapshot;\n }\n throw new Error(\n `Graph snapshot has unknown schema version: ${JSON.stringify(\n (raw as { version?: unknown }).version,\n )}`,\n );\n}\n\nfunction buildSnapshotFromArrays(\n nodes: GraphNode[],\n edges: GraphEdge[],\n): GraphSnapshot {\n const liveNodes = nodes.filter((n) => !n.stale);\n const liveEdges = edges.filter((e) => !e.stale);\n // Build the global degree map once so we can both rank by it AND\n // snapshot the per-top-node values into topDegrees for synchronous\n // re-sort after incremental edge writes.\n const degree = new Map<string, number>();\n for (const e of liveEdges) {\n degree.set(e.sourceNodeId, (degree.get(e.sourceNodeId) ?? 0) + 1);\n degree.set(e.targetNodeId, (degree.get(e.targetNodeId) ?? 0) + 1);\n }\n const ranked = [...liveNodes]\n .sort((a, b) => (degree.get(b.id) ?? 0) - (degree.get(a.id) ?? 0))\n .slice(0, SNAPSHOT_TOP_NODES);\n const rankedIds = new Set(ranked.map((n) => n.id));\n const topEdges = liveEdges.filter(\n (e) => rankedIds.has(e.sourceNodeId) && rankedIds.has(e.targetNodeId),\n );\n const topDegrees: Record<string, number> = {};\n for (const n of ranked) {\n topDegrees[n.id] = degree.get(n.id) ?? 0;\n }\n const nodesByType: Record<string, number> = {};\n for (const n of liveNodes) {\n nodesByType[n.type] = (nodesByType[n.type] || 0) + 1;\n }\n const edgesByType: Record<string, number> = {};\n for (const e of liveEdges) {\n edgesByType[e.type] = (edgesByType[e.type] || 0) + 1;\n }\n return {\n version: 1,\n topNodes: ranked,\n topEdges,\n topDegrees,\n stats: {\n totalNodes: liveNodes.length,\n totalEdges: liveEdges.length,\n nodesByType,\n edgesByType,\n },\n updatedAt: new Date().toISOString(),\n dirty: false,\n };\n}\n\nconst REBUILD_SAFE_NODE_CEILING = 25000;\n\nfunction nameIndexKey(type: string, name: string): string {\n return `${type}|${name}`;\n}\n\nfunction edgeIndexKey(\n sourceNodeId: string,\n targetNodeId: string,\n type: string,\n): string {\n return `${sourceNodeId}|${targetNodeId}|${type}`;\n}\n\n// Mutates `snap` to apply a +1 (or -1) degree delta for nodeId,\n// maintaining the top-N ranking. Returns the new degree. Reads /\n// writes the per-node degree counter via targeted kv.get/set so we\n// never enumerate. Top-N membership flips when:\n// - node's new degree > current min in topNodes AND it's not in\n// topNodes (promote, evict tail if topNodes is full)\n// - node IS in topNodes and its position needs resorting (re-sort\n// topNodes in place)\nasync function applyDegreeDelta(\n kv: StateKV,\n snap: GraphSnapshot,\n nodeId: string,\n delta: number,\n): Promise<number> {\n const prev = (await kv.get<number>(KV.graphNodeDegree, nodeId)) ?? 0;\n const next = Math.max(0, prev + delta);\n await kv.set(KV.graphNodeDegree, nodeId, next);\n\n const inTop = snap.topNodes.findIndex((n) => n.id === nodeId);\n if (inTop !== -1) {\n // Cache the new degree in topDegrees so the comparator runs\n // synchronously over numbers, not async kv.get calls. Re-sort\n // descending by degree.\n snap.topDegrees[nodeId] = next;\n snap.topNodes.sort(\n (a, b) =>\n (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0),\n );\n return next;\n }\n\n if (snap.topNodes.length < SNAPSHOT_TOP_NODES) {\n // Capacity available — fetch + promote.\n const node = await kv.get<GraphNode>(KV.graphNodes, nodeId);\n if (node && !node.stale) {\n snap.topNodes.push(node);\n snap.topDegrees[node.id] = next;\n snap.topNodes.sort(\n (a, b) =>\n (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0),\n );\n }\n return next;\n }\n\n // topNodes is full; the cutoff is the tail's cached degree.\n const tailEntry = snap.topNodes[snap.topNodes.length - 1];\n if (!tailEntry) return next;\n const tailDegree = snap.topDegrees[tailEntry.id] ?? 0;\n if (next > tailDegree) {\n const node = await kv.get<GraphNode>(KV.graphNodes, nodeId);\n if (node && !node.stale) {\n const evicted = snap.topNodes.pop();\n if (evicted) delete snap.topDegrees[evicted.id];\n snap.topNodes.push(node);\n snap.topDegrees[node.id] = next;\n snap.topNodes.sort(\n (a, b) =>\n (snap.topDegrees[b.id] ?? 0) - (snap.topDegrees[a.id] ?? 0),\n );\n }\n }\n return next;\n}\n\nfunction snapshotPushEdgeIfBothInTop(\n snap: GraphSnapshot,\n edge: GraphEdge,\n): void {\n const topIds = new Set(snap.topNodes.map((n) => n.id));\n if (topIds.has(edge.sourceNodeId) && topIds.has(edge.targetNodeId)) {\n // Dedupe in case the same edge gets pushed twice.\n if (!snap.topEdges.find((e) => e.id === edge.id)) {\n snap.topEdges.push(edge);\n }\n }\n}\n\nexport const MAX_GRAPH_SOURCE_OBSERVATIONS = 32;\n\nexport function boundSources(existing: string[], incoming: string[]): string[] {\n const merged = new Set(existing);\n for (const id of incoming) {\n merged.delete(id);\n merged.add(id);\n }\n return [...merged].slice(-MAX_GRAPH_SOURCE_OBSERVATIONS);\n}\n\nexport function boundRecordSources<R extends object>(record: R): R {\n const sources = (record as { sourceObservationIds?: unknown } | null)?.sourceObservationIds;\n if (!Array.isArray(sources) || sources.length <= MAX_GRAPH_SOURCE_OBSERVATIONS) return record;\n return { ...record, sourceObservationIds: boundSources([], sources as string[]) };\n}\n\nfunction mergeNode(\n existing: GraphNode,\n incoming: GraphNode,\n capturedAt: string,\n): GraphNode {\n return {\n ...existing,\n sourceObservationIds: boundSources(\n existing.sourceObservationIds ?? [],\n incoming.sourceObservationIds ?? [],\n ),\n properties: { ...existing.properties, ...incoming.properties },\n updatedAt: capturedAt,\n };\n}\n\nfunction mergeEdge(existing: GraphEdge, incoming: GraphEdge): GraphEdge {\n return {\n ...existing,\n sourceObservationIds: boundSources(\n existing.sourceObservationIds ?? [],\n incoming.sourceObservationIds ?? [],\n ),\n };\n}\n\nfunction parseAttrs(raw: string): Record<string, string> {\n const attrs: Record<string, string> = {};\n const attrRegex = /([A-Za-z_][\\w:-]*)=\"([^\"]*)\"/g;\n let m;\n while ((m = attrRegex.exec(raw)) !== null) {\n attrs[m[1]] = m[2];\n }\n return attrs;\n}\n\nfunction parseGraphXml(\n xml: string,\n observationIds: string[],\n): {\n nodes: GraphNode[];\n edges: GraphEdge[];\n} {\n const nodes: GraphNode[] = [];\n const edges: GraphEdge[] = [];\n const now = new Date().toISOString();\n\n const entitySelfClose = /<entity\\b([^>]*?)\\/>/g;\n const entityWithBody = /<entity\\b([^>]*[^/])>([\\s\\S]*?)<\\/entity>/g;\n\n const addEntity = (rawAttrs: string, propsBlock = \"\"): void => {\n const attrs = parseAttrs(rawAttrs);\n const type = attrs[\"type\"] as GraphNode[\"type\"] | undefined;\n const name = attrs[\"name\"];\n if (!type || !name) return;\n const properties: Record<string, string> = {};\n const propRegex = /<property\\s+key=\"([^\"]+)\">([^<]*)<\\/property>/g;\n let propMatch;\n while ((propMatch = propRegex.exec(propsBlock)) !== null) {\n properties[propMatch[1]] = propMatch[2];\n }\n nodes.push({\n id: generateId(\"gn\"),\n type,\n name,\n properties,\n sourceObservationIds: observationIds,\n createdAt: now,\n });\n };\n\n let match;\n while ((match = entitySelfClose.exec(xml)) !== null) {\n addEntity(match[1]);\n }\n while ((match = entityWithBody.exec(xml)) !== null) {\n addEntity(match[1], match[2]);\n }\n\n const relRegex = /<relationship\\b([^>]*?)\\/>/g;\n while ((match = relRegex.exec(xml)) !== null) {\n const attrs = parseAttrs(match[1]);\n const type = attrs[\"type\"] as GraphEdge[\"type\"] | undefined;\n const sourceName = attrs[\"source\"];\n const targetName = attrs[\"target\"];\n if (!type || !sourceName || !targetName) continue;\n const parsedWeight = parseFloat(attrs[\"weight\"] ?? \"\");\n const weight = Number.isFinite(parsedWeight) ? parsedWeight : 0.5;\n\n const sourceNode = nodes.find((n) => n.name === sourceName);\n const targetNode = nodes.find((n) => n.name === targetName);\n if (!sourceNode || !targetNode) continue;\n edges.push({\n id: generateId(\"ge\"),\n type,\n sourceNodeId: sourceNode.id,\n targetNodeId: targetNode.id,\n weight: Math.max(0, Math.min(1, weight)),\n sourceObservationIds: observationIds,\n createdAt: now,\n });\n }\n\n return { nodes, edges };\n}\n\nconst HEURISTIC_EDGE_WEIGHT = 0.4;\nconst MAX_HEURISTIC_EDGES_PER_OBS = 12;\n\nexport function extractGraphHeuristics(\n observations: CompressedObservation[],\n): { nodes: GraphNode[]; edges: GraphEdge[] } {\n const now = new Date().toISOString();\n const nodes: GraphNode[] = [];\n const nodeByKey = new Map<string, GraphNode>();\n const edges: GraphEdge[] = [];\n const edgeByPair = new Map<string, GraphEdge>();\n\n const nodeFor = (\n type: GraphNode[\"type\"],\n name: string,\n obsId: string,\n ): GraphNode | null => {\n const trimmed = name.trim();\n if (!trimmed) return null;\n const key = `${type}\\u0000${trimmed.toLowerCase()}`;\n let node = nodeByKey.get(key);\n if (!node) {\n node = {\n id: generateId(\"gn\"),\n type,\n name: trimmed,\n properties: {},\n sourceObservationIds: [obsId],\n createdAt: now,\n };\n nodeByKey.set(key, node);\n nodes.push(node);\n } else if (!node.sourceObservationIds.includes(obsId)) {\n node.sourceObservationIds.push(obsId);\n }\n return node;\n };\n\n for (const obs of observations) {\n let budget = MAX_HEURISTIC_EDGES_PER_OBS;\n const link = (a: GraphNode | null, b: GraphNode | null): void => {\n if (!a || !b || a.id === b.id) return;\n const pair = a.id < b.id ? `${a.id}|${b.id}` : `${b.id}|${a.id}`;\n const existing = edgeByPair.get(pair);\n if (existing) {\n if (!existing.sourceObservationIds.includes(obs.id)) {\n existing.sourceObservationIds.push(obs.id);\n }\n return;\n }\n if (budget <= 0) return;\n budget -= 1;\n const edge: GraphEdge = {\n id: generateId(\"ge\"),\n type: \"related_to\",\n sourceNodeId: a.id,\n targetNodeId: b.id,\n weight: HEURISTIC_EDGE_WEIGHT,\n sourceObservationIds: [obs.id],\n createdAt: now,\n };\n edgeByPair.set(pair, edge);\n edges.push(edge);\n };\n\n const fileNodes = (obs.files ?? []).map((f) =>\n nodeFor(\"file\", f, obs.id),\n );\n const conceptNodes = (obs.concepts ?? []).map((c) =>\n nodeFor(\"concept\", c, obs.id),\n );\n\n for (const concept of conceptNodes) {\n for (const file of fileNodes) link(concept, file);\n }\n for (let i = 0; i + 1 < conceptNodes.length; i++) {\n link(conceptNodes[i], conceptNodes[i + 1]);\n }\n for (let i = 0; i + 1 < fileNodes.length; i++) {\n link(fileNodes[i], fileNodes[i + 1]);\n }\n }\n\n return { nodes, edges };\n}\n\nexport async function persistGraphDelta(\n kv: StateKV,\n rawNodes: GraphNode[],\n rawEdges: GraphEdge[],\n): Promise<{ newNodeCount: number; newEdgeCount: number }> {\n kv = await pinGraphState(kv);\n const nodes = rawNodes.map((node) => scrubRecord(node));\n const edges = rawEdges.map((edge) => scrubRecord(edge));\n return withKeyedLock(\"graph:persist\", async () => {\n const snap = (await readSnapshotStrict(kv)) ?? emptySnapshot();\n const legacyResetAt = await isLegacyGraphState(kv) ? snap.resetAt : undefined;\n const capturedAt = new Date().toISOString();\n let newNodeCount = 0;\n let newEdgeCount = 0;\n // Merge-only batches mutate cached topNodes/topEdges entries without\n // changing the counts; track that separately so the snapshot still persists.\n let snapMutated = false;\n const newEdgesForTopCheck: GraphEdge[] = [];\n // When a freshly-minted node merges into an existing row via the name\n // index, edges in the same batch still reference the fresh id. Remap edge\n // endpoints to the persisted ids so edges never dangle and re-runs hit the\n // same edge-index key instead of duplicating.\n const idRemap = new Map<string, string>();\n\n for (const node of nodes) {\n const indexKey = nameIndexKey(node.type, node.name);\n const existingId = await kv.get<string>(KV.graphNameIndex, indexKey);\n\n let existing: GraphNode | null = null;\n if (existingId) {\n existing = await kv.get<GraphNode>(KV.graphNodes, existingId);\n if (\n existing &&\n legacyResetAt &&\n typeof existing.createdAt === \"string\" &&\n existing.createdAt < legacyResetAt\n ) {\n existing = null;\n }\n }\n\n if (existing) {\n idRemap.set(node.id, existing.id);\n const merged = mergeNode(existing, node, capturedAt);\n await kv.set(KV.graphNodes, existing.id, merged);\n // Update topNodes entry if present so a stale clone isn't\n // returned from the snapshot fast path.\n const topIdx = snap.topNodes.findIndex((n) => n.id === existing!.id);\n if (topIdx !== -1) {\n snap.topNodes[topIdx] = merged;\n snapMutated = true;\n }\n } else {\n node.sourceObservationIds = boundSources([], node.sourceObservationIds ?? []);\n await kv.set(KV.graphNodes, node.id, node);\n await kv.set(KV.graphNameIndex, indexKey, node.id);\n await kv.set(KV.graphNodeDegree, node.id, 0);\n snap.stats.totalNodes += 1;\n snap.stats.nodesByType[node.type] =\n (snap.stats.nodesByType[node.type] ?? 0) + 1;\n newNodeCount += 1;\n if (snap.topNodes.length < SNAPSHOT_TOP_NODES) {\n // Degree 0 still beats an empty slot — sit at the tail\n // until edges arrive and promote.\n snap.topNodes.push(node);\n snap.topDegrees[node.id] = 0;\n }\n }\n }\n\n for (const rawEdge of edges) {\n const edge: GraphEdge = {\n ...rawEdge,\n sourceNodeId: idRemap.get(rawEdge.sourceNodeId) ?? rawEdge.sourceNodeId,\n targetNodeId: idRemap.get(rawEdge.targetNodeId) ?? rawEdge.targetNodeId,\n };\n const eKey = edgeIndexKey(edge.sourceNodeId, edge.targetNodeId, edge.type);\n const existingId = await kv.get<string>(KV.graphEdgeKey, eKey);\n\n let existing: GraphEdge | null = null;\n if (existingId) {\n existing = await kv.get<GraphEdge>(KV.graphEdges, existingId);\n if (\n existing &&\n legacyResetAt &&\n typeof existing.createdAt === \"string\" &&\n existing.createdAt < legacyResetAt\n ) {\n existing = null;\n }\n }\n\n if (existing) {\n const merged = mergeEdge(existing, edge);\n await kv.set(KV.graphEdges, existing.id, merged);\n // Replace cached topEdges entry too if present.\n const topIdx = snap.topEdges.findIndex((e) => e.id === existing!.id);\n if (topIdx !== -1) {\n snap.topEdges[topIdx] = merged;\n snapMutated = true;\n }\n } else {\n edge.sourceObservationIds = boundSources([], edge.sourceObservationIds ?? []);\n await kv.set(KV.graphEdges, edge.id, edge);\n await kv.set(KV.graphEdgeKey, eKey, edge.id);\n snap.stats.totalEdges += 1;\n snap.stats.edgesByType[edge.type] =\n (snap.stats.edgesByType[edge.type] ?? 0) + 1;\n newEdgeCount += 1;\n await applyDegreeDelta(kv, snap, edge.sourceNodeId, +1);\n await applyDegreeDelta(kv, snap, edge.targetNodeId, +1);\n newEdgesForTopCheck.push(edge);\n }\n }\n\n // Push newly-added edges into snapshot.topEdges if both\n // endpoints are in the top-N (post-degree-delta). Done after\n // all degree updates so the topIds set is stable.\n for (const edge of newEdgesForTopCheck) {\n snapshotPushEdgeIfBothInTop(snap, edge);\n }\n\n if (newNodeCount > 0 || newEdgeCount > 0 || snapMutated) {\n snap.updatedAt = capturedAt;\n snap.dirty = false;\n await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, snap);\n }\n\n return { newNodeCount, newEdgeCount };\n });\n}\n\nexport interface GraphCompactResult {\n nodesScanned: number;\n nodesTrimmed: number;\n edgesScanned: number;\n edgesTrimmed: number;\n historyScanned: number;\n historyTrimmed: number;\n idsRemoved: number;\n snapshotTrimmed: boolean;\n total?: number;\n nextOffset: number | null;\n}\n\nexport type GraphCompactScope = \"nodes\" | \"edges\" | \"history\" | \"snapshot\";\n\nexport interface GraphCompactOptions {\n scope?: GraphCompactScope;\n offset?: number;\n limit?: number;\n dryRun?: boolean;\n}\n\nexport const COMPACT_SCOPES: readonly GraphCompactScope[] = [\"nodes\", \"edges\", \"history\", \"snapshot\"];\n\nexport async function compactGraphProvenance(\n kv: StateKV,\n opts: GraphCompactOptions = {},\n): Promise<GraphCompactResult> {\n kv = await pinGraphState(kv);\n const { scope } = opts;\n if (scope !== undefined && !COMPACT_SCOPES.includes(scope)) {\n throw new Error(`unknown compact scope: ${String(scope)}`);\n }\n const offset = opts.offset ?? 0;\n const dryRun = opts.dryRun === true;\n const limit = opts.limit ?? Number.POSITIVE_INFINITY;\n if (!Number.isInteger(offset) || offset < 0) {\n throw new Error(`compact offset must be a non-negative integer: ${String(opts.offset)}`);\n }\n if (!(limit === Number.POSITIVE_INFINITY || (Number.isInteger(limit) && limit > 0))) {\n throw new Error(`compact limit must be a positive integer: ${String(opts.limit)}`);\n }\n\n const result: GraphCompactResult = {\n nodesScanned: 0,\n nodesTrimmed: 0,\n edgesScanned: 0,\n edgesTrimmed: 0,\n historyScanned: 0,\n historyTrimmed: 0,\n idsRemoved: 0,\n snapshotTrimmed: false,\n nextOffset: null,\n };\n\n const trimScope = async <R extends { sourceObservationIds: string[] }>(\n listIds: () => Promise<unknown[]>,\n recordScope: string,\n ): Promise<{ scanned: number; trimmed: number }> => {\n const allIds = [...new Set(await listIds())]\n .filter((id): id is string => typeof id === \"string\")\n .sort();\n const end = Math.min(allIds.length, offset + limit);\n result.total = allIds.length;\n result.nextOffset = end < allIds.length ? end : null;\n let scanned = 0;\n let trimmed = 0;\n for (const id of allIds.slice(offset, end)) {\n await withKeyedLock(\"graph:persist\", async () => {\n const record = await kv.get<R>(recordScope, id);\n if (!record) return;\n scanned += 1;\n const sources = record.sourceObservationIds ?? [];\n if (sources.length <= MAX_GRAPH_SOURCE_OBSERVATIONS) return;\n const bounded = boundSources([], sources);\n result.idsRemoved += sources.length - bounded.length;\n if (!dryRun) await kv.set(recordScope, id, { ...record, sourceObservationIds: bounded });\n trimmed += 1;\n });\n }\n return { scanned, trimmed };\n };\n\n const trimSnapshot = () =>\n withKeyedLock(\"graph:persist\", async () => {\n const snap = await readSnapshot(kv);\n if (!snap) return;\n const trimList = <R extends { sourceObservationIds: string[] }>(list: R[]) =>\n list.map((r) => {\n const sources = r.sourceObservationIds ?? [];\n if (sources.length <= MAX_GRAPH_SOURCE_OBSERVATIONS) return r;\n result.snapshotTrimmed = true;\n return { ...r, sourceObservationIds: boundSources([], sources) };\n });\n const topNodes = trimList(snap.topNodes);\n const topEdges = trimList(snap.topEdges);\n if (result.snapshotTrimmed && !dryRun) {\n await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, { ...snap, topNodes, topEdges });\n }\n });\n\n if (scope === undefined || scope === \"nodes\") {\n const n = await trimScope<GraphNode>(() => kv.list<string>(KV.graphNameIndex), KV.graphNodes);\n result.nodesScanned = n.scanned;\n result.nodesTrimmed = n.trimmed;\n }\n if (scope === undefined || scope === \"edges\") {\n const e = await trimScope<GraphEdge>(() => kv.list<string>(KV.graphEdgeKey), KV.graphEdges);\n result.edgesScanned = e.scanned;\n result.edgesTrimmed = e.trimmed;\n }\n if (scope === undefined || scope === \"history\") {\n const h = await trimScope<GraphEdge>(\n async () => (await kv.list<GraphEdge>(KV.graphEdgeHistory)).map((r) => r?.id),\n KV.graphEdgeHistory,\n );\n result.historyScanned = h.scanned;\n result.historyTrimmed = h.trimmed;\n }\n if (scope === undefined || scope === \"snapshot\") {\n await trimSnapshot();\n }\n if (scope === undefined) {\n delete result.total;\n result.nextOffset = null;\n }\n return result;\n}\n\nexport function registerGraphFunction(\n sdk: IIIClient,\n state: StateKV,\n provider: MemoryProvider,\n): void {\n const kv = state;\n sdk.registerFunction(\"mem::graph-extract\",\n async (data: { observations: CompressedObservation[] }) => {\n const kv = await pinGraphState(state);\n if (!data.observations || data.observations.length === 0) {\n return { success: false, error: \"No observations provided\" };\n }\n\n const obsIds = data.observations.map((o) => o.id);\n\n let nodes: GraphNode[] = [];\n let edges: GraphEdge[] = [];\n try {\n const heuristic = extractGraphHeuristics(data.observations);\n nodes = heuristic.nodes;\n edges = heuristic.edges;\n } catch (err) {\n logger.warn(\"heuristic graph extraction failed\", {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n\n const llmEnabled =\n isGraphExtractionEnabled() && !provider.name.includes(\"noop\");\n let llmError: string | undefined;\n if (llmEnabled) {\n const prompt = buildGraphExtractionPrompt(\n data.observations.map((o) => ({\n title: o.title,\n narrative: o.narrative,\n concepts: o.concepts,\n files: o.files,\n type: o.type,\n })),\n );\n try {\n const response = await provider.compress(\n GRAPH_EXTRACTION_SYSTEM,\n prompt,\n );\n const parsed = parseGraphXml(response, obsIds);\n nodes = nodes.concat(parsed.nodes);\n edges = edges.concat(parsed.edges);\n } catch (err) {\n llmError = err instanceof Error ? err.message : String(err);\n logger.error(\"LLM graph extraction failed\", { error: llmError });\n }\n }\n\n if (nodes.length === 0 && edges.length === 0) {\n return llmError\n ? { success: false, error: llmError }\n : { success: true, nodesAdded: 0, edgesAdded: 0 };\n }\n\n try {\n const { newNodeCount, newEdgeCount } = await persistGraphDelta(\n kv,\n nodes,\n edges,\n );\n\n await recordAudit(kv, \"observe\", \"mem::graph-extract\", obsIds, {\n nodesExtracted: nodes.length,\n edgesExtracted: edges.length,\n });\n\n logger.info(\"Graph extraction complete\", {\n nodes: nodes.length,\n edges: edges.length,\n newNodes: newNodeCount,\n newEdges: newEdgeCount,\n llm: llmEnabled && !llmError,\n });\n return {\n success: true,\n nodesAdded: nodes.length,\n edgesAdded: edges.length,\n };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\"Graph extraction failed\", { error: msg });\n return { success: false, error: msg };\n }\n },\n );\n\n sdk.registerFunction(\"mem::graph-query\",\n async (data: {\n startNodeId?: string;\n nodeType?: string;\n maxDepth?: number;\n query?: string;\n limit?: number;\n offset?: number;\n }): Promise<GraphQueryResult> => {\n return queryGraphIndex(state, data);\n },\n );\n\n sdk.registerFunction(\"mem::graph-stats\", async () => {\n const kv = await pinGraphState(state);\n const index = await getGraphIndexStatus(kv);\n if (!index || index.status !== \"ready\" || index.pending || index.batchPending) {\n return {\n totalNodes: null, totalEdges: null, nodesByType: {}, edgesByType: {},\n fromSnapshot: false, fromIndex: false, available: false, coverage: \"unknown\",\n warning: \"Graph index counts are unavailable. Run agentmemory graph-index status; legacy stores require an explicit migration.\",\n };\n }\n return {\n totalNodes: index.nodes, totalEdges: index.edges,\n nodesByType: index.nodesByType, edgesByType: index.edgesByType,\n fromSnapshot: false, fromIndex: true, available: true,\n coverage: index.incompleteRecords ? \"partial\" : \"complete\",\n updatedAt: index.updatedAt,\n ...(index.incompleteRecords || index.otherTypes ? {\n warning: \"Counts describe indexed live records; oversized projections may be incomplete and unrecognized types are grouped under other.\",\n } : {}),\n };\n });\n\n sdk.registerFunction(\n \"mem::graph-snapshot-rebuild\",\n async (data?: { force?: boolean }) => {\n const kv = await pinGraphState(state);\n const started = Date.now();\n const forceRebuild = data?.force === true;\n try {\n const existing = await readSnapshot(kv);\n if (!existing && !forceRebuild) {\n logger.warn(\"Graph snapshot rebuild refused: no prior snapshot\", {\n hint: \"legacy corpus or empty store\",\n });\n return {\n success: false,\n legacyCorpus: true,\n error:\n \"No prior snapshot found. Rebuild would call kv.list on \" +\n \"KV.graphNodes/Edges, which heartbeat-crashes the worker \" +\n \"on corpora past the iii state response budget (~25K nodes). \" +\n \"Either (a) call POST /agentmemory/graph/reset to drop into \" +\n \"incremental-only mode and rebuild from new extracts, or \" +\n \"(b) re-send with `force: true` if you're certain the \" +\n \"corpus is small.\",\n };\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.warn(\"Graph snapshot pre-flight read failed\", { error: msg });\n // Fall through; the user passed force=true or the snapshot\n // read itself failed (separate problem).\n }\n\n try {\n const outcome = await withKeyedLock(\"graph:persist\", async () => {\n const [nodes, edges] = await withTimeout(\n Promise.all([\n kv.list<GraphNode>(KV.graphNodes),\n kv.list<GraphEdge>(KV.graphEdges),\n ]),\n LIVE_ENUMERATION_BUDGET_MS,\n \"graph-snapshot-rebuild enumeration\",\n );\n\n if (nodes.length > REBUILD_SAFE_NODE_CEILING) {\n return { tooLargeNodeCount: nodes.length };\n }\n\n const liveNodes = nodes.filter((n) => !n.stale);\n const liveEdges = edges.filter((e) => !e.stale);\n const degree = new Map<string, number>();\n for (const e of liveEdges) {\n degree.set(e.sourceNodeId, (degree.get(e.sourceNodeId) ?? 0) + 1);\n degree.set(e.targetNodeId, (degree.get(e.targetNodeId) ?? 0) + 1);\n }\n const BATCH_SIZE = 100;\n for (let i = 0; i < liveNodes.length; i += BATCH_SIZE) {\n const batch = liveNodes.slice(i, i + BATCH_SIZE);\n await Promise.all(\n batch.flatMap((n) => [\n kv.set(KV.graphNameIndex, nameIndexKey(n.type, n.name), n.id),\n kv.set(KV.graphNodeDegree, n.id, degree.get(n.id) ?? 0),\n ]),\n );\n }\n for (let i = 0; i < liveEdges.length; i += BATCH_SIZE) {\n const batch = liveEdges.slice(i, i + BATCH_SIZE);\n await Promise.all(\n batch.map((e) =>\n kv.set(\n KV.graphEdgeKey,\n edgeIndexKey(e.sourceNodeId, e.targetNodeId, e.type),\n e.id,\n ),\n ),\n );\n }\n\n const rebuilt = buildSnapshotFromArrays(nodes, edges);\n await kv.set(KV.graphSnapshot, SNAPSHOT_KEY, rebuilt);\n return { snap: rebuilt };\n });\n\n if (\"tooLargeNodeCount\" in outcome) {\n const totalNodes = outcome.tooLargeNodeCount;\n logger.warn(\"Graph snapshot rebuild aborted: corpus too large\", {\n totalNodes,\n ceiling: REBUILD_SAFE_NODE_CEILING,\n });\n return {\n success: false,\n tooLarge: true,\n totalNodes,\n ceiling: REBUILD_SAFE_NODE_CEILING,\n error:\n `Corpus has ${totalNodes} graph nodes; safe-rebuild ceiling ` +\n `is ${REBUILD_SAFE_NODE_CEILING}. Run POST /agentmemory/graph/reset ` +\n `to wipe and let future extracts rebuild incrementally.`,\n };\n }\n\n const { snap } = outcome;\n const tookMs = Date.now() - started;\n logger.info(\"Graph snapshot rebuilt\", {\n totalNodes: snap.stats.totalNodes,\n totalEdges: snap.stats.totalEdges,\n topNodes: snap.topNodes.length,\n topEdges: snap.topEdges.length,\n tookMs,\n });\n return {\n success: true,\n ...snap.stats,\n topNodes: snap.topNodes.length,\n topEdges: snap.topEdges.length,\n updatedAt: snap.updatedAt,\n tookMs,\n };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\"Graph snapshot rebuild failed\", { error: msg });\n return { success: false, error: msg };\n }\n });\n\n sdk.registerFunction(\"mem::graph-compact\", async (data?: GraphCompactOptions) => {\n const kv = await pinGraphState(state);\n const started = Date.now();\n try {\n const result = await compactGraphProvenance(kv, data ?? {});\n const tookMs = Date.now() - started;\n logger.info(\"Graph provenance compacted\", { ...result, tookMs });\n if (result.idsRemoved > 0) {\n await safeAudit(kv, \"graph_compact\", \"mem::graph-compact\", [], {\n scope: data?.scope ?? \"all\",\n offset: data?.offset,\n limit: data?.limit,\n nodesTrimmed: result.nodesTrimmed,\n edgesTrimmed: result.edgesTrimmed,\n historyTrimmed: result.historyTrimmed,\n idsRemoved: result.idsRemoved,\n snapshotTrimmed: result.snapshotTrimmed,\n });\n }\n return { success: true, ...result, tookMs };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\"Graph provenance compaction failed\", { error: msg });\n return { success: false, error: msg };\n }\n });\n\n sdk.registerFunction(\"mem::graph-reset\", async () => {\n const started = Date.now();\n // Publish a fresh namespace without enumerating or deleting the old graph.\n const resetSnapshot: GraphSnapshot = {\n ...emptySnapshot(),\n resetAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n dirty: false,\n };\n await withKeyedLock(\"graph:persist\", () =>\n resetGraphGeneration(kv, resetSnapshot),\n );\n const counts: Record<string, number> = {\n [KV.graphSnapshot]: 1,\n };\n const tookMs = Date.now() - started;\n logger.info(\"Graph state reset\", { counts, tookMs });\n return {\n success: true,\n cleared: counts,\n resetMode: \"generation\",\n physicalStorageRetained: true,\n message: \"The active graph is empty. Previous graph storage is retained; this operation does not reclaim disk space.\",\n tookMs,\n };\n });\n}\n","import type { StateKV } from \"../state/kv.js\";\nimport { KV } from \"../state/schema.js\";\nimport {\n MAX_GRAPH_SOURCE_OBSERVATIONS,\n compactGraphProvenance,\n type GraphCompactResult,\n type GraphCompactScope,\n} from \"./graph.js\";\nimport { safeAudit } from \"./audit.js\";\n\nexport const GRAPH_COMPACT_BOOT_VERSION = 1;\nexport const GRAPH_COMPACT_BOOT_KEY = `graph-compact-on-boot:v${GRAPH_COMPACT_BOOT_VERSION}`;\nexport const GRAPH_COMPACT_BOOT_FUNCTION_ID = \"mem::graph-compact-on-boot\";\nexport const GRAPH_COMPACT_BOOT_DELAY_MS = 3000;\n\nconst SLICED_SCOPES = [\"nodes\", \"edges\", \"history\"] as const;\ntype SlicedScope = (typeof SLICED_SCOPES)[number];\ntype BootPhase = SlicedScope | \"snapshot\";\n\nexport interface GraphCompactBootProgress {\n version: number;\n cap: number;\n status: \"running\" | \"done\" | \"failed\";\n phase: BootPhase;\n offset: number;\n phaseTotal: number | null;\n scanned: number;\n trimmed: number;\n idsRemoved: number;\n pending?: GraphCompactBootSlicePlan;\n startedAt: string;\n updatedAt: string;\n completedAt?: string;\n error?: string;\n}\n\nexport interface GraphCompactBootSlicePlan {\n phase: BootPhase;\n offset: number;\n scanned: number;\n trimmed: number;\n idsRemoved: number;\n nextOffset: number | null;\n total: number | null;\n}\n\nexport type GraphCompactBootState = \"off\" | \"pending\" | \"running\" | \"done\" | \"failed\" | \"deferred\";\n\nexport interface GraphCompactBootStatus {\n state: GraphCompactBootState;\n phase?: BootPhase;\n processed?: number;\n total?: number | null;\n scanned?: number;\n trimmed?: number;\n idsRemoved?: number;\n startedAt?: string;\n completedAt?: string;\n error?: string;\n}\n\nexport interface GraphCompactBootOptions {\n allowLegacyScan?: boolean;\n sliceSize?: number;\n pauseMs?: number;\n maxAttempts?: number;\n retryDelayMs?: number;\n log?: (msg: string) => void;\n warn?: (msg: string) => void;\n sleep?: (ms: number) => Promise<void>;\n now?: () => Date;\n}\n\nconst DEFAULT_SLICE_SIZE = 100;\nconst DEFAULT_PAUSE_MS = 200;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_RETRY_DELAY_MS = 2000;\n\nlet current: GraphCompactBootStatus = { state: \"pending\" };\nlet running: Promise<GraphCompactBootStatus> | null = null;\n\nexport function getGraphCompactBootStatus(): GraphCompactBootStatus {\n return { ...current };\n}\n\nexport function setGraphCompactBootDisabled(): void {\n current = { state: \"off\" };\n}\n\nexport function resetGraphCompactBootStatus(): void {\n current = { state: \"pending\" };\n running = null;\n}\n\nfunction statusFrom(p: GraphCompactBootProgress): GraphCompactBootStatus {\n return {\n state: p.status,\n phase: p.phase,\n processed: p.offset,\n total: p.phaseTotal,\n scanned: p.scanned,\n trimmed: p.trimmed,\n idsRemoved: p.idsRemoved,\n startedAt: p.startedAt,\n completedAt: p.completedAt,\n error: p.error,\n };\n}\n\nfunction isResumable(p: GraphCompactBootProgress | null): p is GraphCompactBootProgress {\n return (\n !!p &&\n p.version === GRAPH_COMPACT_BOOT_VERSION &&\n p.cap === MAX_GRAPH_SOURCE_OBSERVATIONS &&\n (p.phase === \"snapshot\" || (SLICED_SCOPES as readonly string[]).includes(p.phase)) &&\n Number.isInteger(p.offset) &&\n p.offset >= 0\n );\n}\n\nfunction storedPlan(p: GraphCompactBootProgress, phase: BootPhase): GraphCompactBootSlicePlan | null {\n const plan = p.pending;\n if (!plan || plan.phase !== phase || plan.offset !== p.offset) return null;\n const counts = [plan.scanned, plan.trimmed, plan.idsRemoved];\n return counts.every((n) => Number.isInteger(n) && n >= 0) ? plan : null;\n}\n\nfunction scannedOf(scope: SlicedScope, r: GraphCompactResult): [number, number] {\n if (scope === \"nodes\") return [r.nodesScanned, r.nodesTrimmed];\n if (scope === \"edges\") return [r.edgesScanned, r.edgesTrimmed];\n return [r.historyScanned, r.historyTrimmed];\n}\n\nexport function describeGraphCompactBoot(s: GraphCompactBootStatus): string {\n if (s.state === \"off\") return \"off (AGENTMEMORY_GRAPH_COMPACT_ON_BOOT=false)\";\n if (s.state === \"pending\") return \"pending\";\n if (s.state === \"deferred\") return \"deferred (legacy scan requires explicit maintenance)\";\n const where =\n s.phase === \"snapshot\" || s.total === null || s.total === undefined\n ? `${s.phase ?? \"nodes\"}`\n : `${s.phase} ${s.processed ?? 0} of ${s.total}`;\n if (s.state === \"running\") return `running, ${where}`;\n if (s.state === \"failed\") return `failed at ${where}: ${s.error ?? \"unknown error\"}`;\n return `done, ${s.trimmed ?? 0} records trimmed, ${s.idsRemoved ?? 0} ids removed`;\n}\n\nexport function runGraphCompactOnBoot(\n kv: StateKV,\n opts: GraphCompactBootOptions = {},\n): Promise<GraphCompactBootStatus> {\n if (opts.allowLegacyScan !== true) {\n current = { state: \"deferred\" };\n return Promise.resolve(getGraphCompactBootStatus());\n }\n if (running) return running;\n running = runOnce(kv, opts).finally(() => {\n running = null;\n });\n return running;\n}\n\nasync function runOnce(kv: StateKV, opts: GraphCompactBootOptions): Promise<GraphCompactBootStatus> {\n const sliceSize = opts.sliceSize ?? DEFAULT_SLICE_SIZE;\n const pauseMs = opts.pauseMs ?? DEFAULT_PAUSE_MS;\n const maxAttempts = Math.max(1, opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS);\n const retryDelayMs = opts.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const log = opts.log ?? (() => {});\n const warn = opts.warn ?? log;\n const sleep = opts.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));\n const now = opts.now ?? (() => new Date());\n\n const attempt = async <T>(fn: () => Promise<T>): Promise<T> => {\n let lastErr: unknown;\n for (let i = 1; i <= maxAttempts; i++) {\n try {\n return await fn();\n } catch (err) {\n lastErr = err;\n if (i < maxAttempts) await sleep(retryDelayMs * i);\n }\n }\n throw lastErr;\n };\n\n let progress: GraphCompactBootProgress | null = null;\n const save = async () => {\n if (!progress) return;\n progress.updatedAt = now().toISOString();\n current = statusFrom(progress);\n await attempt(() => kv.set(KV.config, GRAPH_COMPACT_BOOT_KEY, progress));\n };\n\n try {\n const stored = await attempt(() => kv.get<GraphCompactBootProgress>(KV.config, GRAPH_COMPACT_BOOT_KEY));\n if (isResumable(stored) && stored.status === \"done\") {\n current = statusFrom(stored);\n return getGraphCompactBootStatus();\n }\n const startedAt = now().toISOString();\n if (isResumable(stored)) {\n progress = { ...stored, status: \"running\", error: undefined };\n log(`Graph provenance compaction: resuming in the background at ${progress.phase} ${progress.offset}`);\n } else {\n progress = {\n version: GRAPH_COMPACT_BOOT_VERSION,\n cap: MAX_GRAPH_SOURCE_OBSERVATIONS,\n status: \"running\",\n phase: \"nodes\",\n offset: 0,\n phaseTotal: null,\n scanned: 0,\n trimmed: 0,\n idsRemoved: 0,\n startedAt,\n updatedAt: startedAt,\n };\n log(`Graph provenance compaction: started in the background (cap ${MAX_GRAPH_SOURCE_OBSERVATIONS} ids per record)`);\n }\n await save();\n\n const p = progress;\n for (const scope of SLICED_SCOPES) {\n if (p.phase === \"snapshot\") break;\n if (SLICED_SCOPES.indexOf(p.phase) > SLICED_SCOPES.indexOf(scope)) continue;\n p.phase = scope;\n let phaseTrimmed = 0;\n let phaseScanned = 0;\n for (;;) {\n const slice = { scope: scope as GraphCompactScope, offset: p.offset, limit: sliceSize };\n let plan = storedPlan(p, scope);\n if (!plan) {\n const r = await attempt(() => compactGraphProvenance(kv, { ...slice, dryRun: true }));\n const [scanned, trimmed] = scannedOf(scope, r);\n plan = {\n phase: scope,\n offset: p.offset,\n scanned,\n trimmed,\n idsRemoved: r.idsRemoved,\n nextOffset: r.nextOffset,\n total: r.total ?? null,\n };\n if (plan.trimmed > 0) {\n p.pending = plan;\n await save();\n }\n }\n if (plan.trimmed > 0) await attempt(() => compactGraphProvenance(kv, slice));\n phaseScanned += plan.scanned;\n phaseTrimmed += plan.trimmed;\n p.scanned += plan.scanned;\n p.trimmed += plan.trimmed;\n p.idsRemoved += plan.idsRemoved;\n p.pending = undefined;\n p.phaseTotal = plan.total;\n p.offset = plan.nextOffset ?? p.phaseTotal ?? p.offset;\n await save();\n if (plan.nextOffset === null) break;\n if (pauseMs > 0) await sleep(pauseMs);\n }\n log(`Graph provenance compaction: ${scope} done (${phaseScanned} checked, ${phaseTrimmed} trimmed)`);\n const next = SLICED_SCOPES[SLICED_SCOPES.indexOf(scope) + 1];\n p.phase = next ?? \"snapshot\";\n p.offset = 0;\n p.phaseTotal = null;\n await save();\n }\n\n let snapPlan = storedPlan(p, \"snapshot\");\n if (!snapPlan) {\n const dry = await attempt(() => compactGraphProvenance(kv, { scope: \"snapshot\", dryRun: true }));\n snapPlan = {\n phase: \"snapshot\",\n offset: p.offset,\n scanned: 0,\n trimmed: dry.snapshotTrimmed ? 1 : 0,\n idsRemoved: 0,\n nextOffset: null,\n total: null,\n };\n if (snapPlan.trimmed > 0) {\n p.pending = snapPlan;\n await save();\n }\n }\n if (snapPlan.trimmed > 0) await attempt(() => compactGraphProvenance(kv, { scope: \"snapshot\" }));\n const snapshotTrimmed = snapPlan.trimmed > 0;\n p.trimmed += snapPlan.trimmed;\n p.pending = undefined;\n p.status = \"done\";\n p.completedAt = now().toISOString();\n await save();\n if (p.idsRemoved > 0) {\n await safeAudit(kv, \"graph_compact\", GRAPH_COMPACT_BOOT_FUNCTION_ID, [], {\n trigger: \"boot\",\n recordsTrimmed: p.trimmed,\n idsRemoved: p.idsRemoved,\n snapshotTrimmed,\n });\n }\n log(\n `Graph provenance compaction: done (${p.scanned} records checked, ${p.trimmed} trimmed, ${p.idsRemoved} ids removed)`,\n );\n return getGraphCompactBootStatus();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (progress) {\n progress.status = \"failed\";\n progress.error = msg;\n current = statusFrom(progress);\n try {\n await kv.set(KV.config, GRAPH_COMPACT_BOOT_KEY, { ...progress, updatedAt: now().toISOString() });\n } catch {}\n } else {\n current = { state: \"failed\", error: msg };\n }\n warn(\n `Graph provenance compaction failed (${describeGraphCompactBoot(current)}). It resumes on the next start; to run it now, POST /agentmemory/graph/compact.`,\n );\n return getGraphCompactBootStatus();\n }\n}\n","import type { IndexLegStatus, IndexPersistenceStatus } from \"../state/index-persistence.js\";\nimport type { VectorBackfillState } from \"./search.js\";\nimport { describeGraphCompactBoot, type GraphCompactBootStatus } from \"./graph-compact-boot.js\";\nimport type { CaptureStatus } from \"./capture.js\";\nimport type { GraphIndexMigrationStatus } from \"../state/graph-index-migration.js\";\n\nexport type StatusLevel = \"ok\" | \"info\" | \"warn\" | \"error\";\n\nexport interface StatusProblem {\n level: Exclude<StatusLevel, \"ok\">;\n code: string;\n message: string;\n fix?: string;\n}\n\nexport interface FunctionMetricInput {\n functionId: string;\n totalCalls: number;\n successCount: number;\n failureCount: number;\n avgLatencyMs: number;\n}\n\nexport interface StatusFlag {\n key: string;\n label: string;\n enabled: boolean;\n needsLlm: boolean;\n enableHow: string;\n}\n\nexport interface GraphStatsInput {\n totalNodes?: number | null;\n totalEdges?: number | null;\n available?: boolean;\n coverage?: \"complete\" | \"partial\" | \"unknown\";\n fromSnapshot?: boolean;\n updatedAt?: string;\n dirty?: boolean;\n warning?: string;\n fromIndex?: boolean;\n}\n\nexport interface StatusInputs {\n now: Date;\n version: string;\n enginePinnedVersion: string;\n uptimeSeconds: number;\n stateBackend: \"file\" | \"redis\";\n ports: { rest: number | null; viewer: number | null };\n health: {\n status?: string;\n alerts?: string[];\n notes?: string[];\n connectionState?: string;\n memory?: { heapUsed: number; heapTotal: number; heapLimit?: number; rss: number };\n eventLoopLagMs?: number;\n cpuPercent?: number;\n } | null;\n circuitBreaker: { state?: string; failures?: number } | null;\n llmRoute?: string | null;\n functionMetrics: FunctionMetricInput[];\n provider: string;\n providerHint?: string | null;\n embeddingProvider: string;\n embeddingHint?: string | null;\n flags: StatusFlag[];\n index: {\n bm25Documents: number;\n vectorDocuments: number | null;\n observationsIndexed: number;\n memoriesIndexed?: number;\n lessonsIndexed?: number;\n missingObservations: number | null;\n sessions: number | null;\n bm25Incomplete: boolean;\n keywordRebuildRunning?: boolean;\n pendingVectorBackfill: number;\n vectorBackfillState?: VectorBackfillState;\n };\n graph: GraphStatsInput | null;\n graphExtractionEnabled: boolean;\n graphCompaction?: GraphCompactBootStatus | null;\n graphIndex?: GraphIndexMigrationStatus | null;\n auditLegacy: { status: string; sizeBytes?: number } | null;\n indexPersistence?: IndexPersistenceStatus | null;\n stateStore?: { ok: boolean; latencyMs?: number } | null;\n capture?: CaptureStatus | null;\n observeDedup?: ObserveDedupStatus | null;\n}\n\nexport interface ObserveDedupStatus {\n skippedSinceStart: number;\n windowSeconds: number;\n}\n\nexport interface IndexBreakdown {\n observations: number;\n memories: number;\n lessons: number;\n}\n\nexport interface StatusReport {\n status: StatusLevel;\n headline: string;\n checkedAt: string;\n service: {\n version: string;\n enginePinnedVersion: string;\n uptimeSeconds: number;\n stateBackend: StatusInputs[\"stateBackend\"];\n stateStore: { ok: boolean; latencyMs?: number } | null;\n ports: StatusInputs[\"ports\"];\n };\n health: StatusInputs[\"health\"];\n provider: {\n llm: string;\n route: string | null;\n hint: string | null;\n embeddings: string;\n embeddingHint: string | null;\n circuitBreaker: StatusInputs[\"circuitBreaker\"];\n offWithoutLlm: string[];\n };\n index: StatusInputs[\"index\"] & { breakdown: IndexBreakdown | null };\n indexPersistence: IndexPersistenceStatus | null;\n graph: (GraphStatsInput & { ageSeconds: number | null; extractionEnabled: boolean }) | null;\n graphCompaction: GraphCompactBootStatus | null;\n graphIndex: GraphIndexMigrationStatus | null;\n capture: CaptureStatus | null;\n observeDedup: ObserveDedupStatus | null;\n functions: Array<FunctionMetricInput & { failureRate: number; offWithoutLlm: boolean }>;\n flags: Array<StatusFlag & { inactiveReason?: string }>;\n problems: StatusProblem[];\n}\n\nconst FAILURE_RATE_THRESHOLD = 0.2;\nconst FAILURE_MIN_CALLS = 5;\nconst GRAPH_SNAPSHOT_STALE_SECONDS = 24 * 60 * 60;\nconst LEVEL_RANK: Record<StatusLevel, number> = { ok: 0, info: 1, warn: 2, error: 3 };\n\nconst FUNCTION_FIXES: Record<string, string> = {\n \"mem::summarize\":\n \"Summaries come from your LLM provider. Check the provider key, model name and rate limits in ~/.agentmemory/.env, then look for provider errors in the server log.\",\n \"mem::compress\":\n \"Compression calls your LLM provider. Check the provider key and model, or set AGENTMEMORY_AUTO_COMPRESS=false to use zero-LLM compression.\",\n \"mem::graph-extract\":\n \"Graph extraction calls your LLM provider. Check the provider key and model, or set GRAPH_EXTRACTION_ENABLED=false.\",\n};\n\nexport const LLM_KEY_FIX =\n \"Set AGENTMEMORY_LLM_PROVIDER and that provider's key (for example AGENTMEMORY_LLM_PROVIDER=anthropic and ANTHROPIC_API_KEY) in ~/.agentmemory/.env and restart.\";\n\nexport const OFF_WITHOUT_LLM = [\n \"session summaries\",\n \"consolidation into semantic facts and procedures\",\n \"typed graph extraction\",\n \"LLM observation compression\",\n \"skill extraction from finished sessions\",\n];\n\nexport const BM25_EXPLAINER =\n \"The keyword index holds observations, memories and lessons, so its total is larger than the observation count.\";\n\nexport function describeHealthAlert(slug: string): { level: \"warn\" | \"error\"; message: string; fix: string } {\n let m: RegExpExecArray | null;\n if ((m = /^memory_(warn|critical)_(\\d+)%_rss(\\d+)mb$/.exec(slug))) {\n return {\n level: m[1] === \"critical\" ? \"error\" : \"warn\",\n message: `Memory ${m[1] === \"critical\" ? \"critically high\" : \"high\"}: ${m[2]}% of the heap limit in use, process memory ${m[3]} MB.`,\n fix: \"Restart agentmemory to release memory. If it climbs back, raise the limit with NODE_OPTIONS=--max-old-space-size=4096.\",\n };\n }\n if ((m = /^cpu_(warn|critical)_(\\d+)%$/.exec(slug))) {\n return {\n level: m[1] === \"critical\" ? \"error\" : \"warn\",\n message: `CPU ${m[1] === \"critical\" ? \"critically high\" : \"high\"}: ${m[2]}%.`,\n fix: \"Usually a burst of observations or a rebuild. If it stays high with no agent running, check the server log for a loop.\",\n };\n }\n if ((m = /^event_loop_lag_(warn|critical)_(\\d+)ms$/.exec(slug))) {\n return {\n level: m[1] === \"critical\" ? \"error\" : \"warn\",\n message: `The worker is ${m[2]} ms behind on its work (event loop delay), so requests answer slowly.`,\n fix: \"It usually clears after an import or index rebuild finishes. If it persists, restart agentmemory.\",\n };\n }\n\n if (slug === \"connection_reconnecting\") {\n return {\n level: \"warn\",\n message: \"The connection to the iii engine dropped and is reconnecting.\",\n fix: \"Wait a few seconds. If it does not recover, check that the engine is running with npx @agentmemory/agentmemory status.\",\n };\n }\n if ((m = /^connection_(.+)$/.exec(slug))) {\n return {\n level: \"error\",\n message: `The connection to the iii engine is ${m[1]}, so nothing can be stored or searched.`,\n fix: \"Restart agentmemory. Run npx @agentmemory/agentmemory doctor if the engine does not start.\",\n };\n }\n return { level: \"warn\", message: slug, fix: \"Look for this alert in the server log.\" };\n}\n\nexport function isOffWithoutLlm(functionId: string, providerKind: string): boolean {\n return providerKind === \"noop\" && functionId in FUNCTION_FIXES;\n}\n\nexport function markLlmFunctions<T extends { functionId: string }>(\n metrics: T[],\n providerKind: string,\n): Array<T & { offWithoutLlm: boolean }> {\n return metrics.map((m) => ({ ...m, offWithoutLlm: isOffWithoutLlm(m.functionId, providerKind) }));\n}\n\nfunction secondsBetween(later: Date, earlierIso: string | undefined): number | null {\n if (!earlierIso) return null;\n const earlier = Date.parse(earlierIso);\n if (Number.isNaN(earlier)) return null;\n return Math.max(0, Math.round((later.getTime() - earlier) / 1000));\n}\n\nfunction describeBackfillState(state: VectorBackfillState): string {\n if (state === \"waiting-for-opt-in\") return \"paused, waiting for opt-in\";\n if (state === \"paused\") return \"paused, retried on the next start\";\n return state;\n}\n\nfunction vectorBackfillFix(state: VectorBackfillState | undefined): string {\n if (state === \"waiting-for-opt-in\") {\n return \"Backfill is paused. Set AGENTMEMORY_VECTOR_BACKFILL=all and restart to opt in. This calls the embedding provider and is capped per boot by AGENTMEMORY_VECTOR_BACKFILL_MAX.\";\n }\n if (state === \"running\") {\n return \"Backfill is running in the background in batches of AGENTMEMORY_VECTOR_BACKFILL_MAX with a short pause between batches. If agentmemory stops first, it continues on the next start. Check the server log for embedding provider errors if progress stops.\";\n }\n if (state === \"paused\") {\n return \"Backfill stopped because the embedding provider did not return vectors. Search still works by keyword. Check the embedding provider key and the server log; the remaining documents are retried on the next start.\";\n }\n return \"Backfill is not running. Check the server log and embedding provider configuration. A full backfill requires AGENTMEMORY_VECTOR_BACKFILL=all and a restart, and can consume embedding provider tokens.\";\n}\n\nexport function evaluateStatus(input: StatusInputs): StatusReport {\n const problems: StatusProblem[] = [];\n\n if (!input.health) {\n problems.push({\n level: \"info\",\n code: \"health-check-unavailable\",\n message: \"The health monitor has no snapshot yet or did not answer in time, so its state was not checked.\",\n fix: \"The monitor writes a snapshot every 30 seconds after start. Wait a minute; if this stays, check the server log.\",\n });\n }\n const healthStatus = input.health?.status;\n const alerts = input.health?.alerts ?? [];\n if (alerts.length === 0 && healthStatus === \"critical\") {\n problems.push({\n level: \"error\",\n code: \"health-critical\",\n message: \"The health monitor reports a critical state.\",\n fix: \"Check the server log, then restart agentmemory.\",\n });\n } else if (alerts.length === 0 && healthStatus === \"degraded\") {\n problems.push({\n level: \"warn\",\n code: \"health-degraded\",\n message: \"The health monitor reports a degraded state.\",\n fix: \"Check the server log for the cause.\",\n });\n }\n const described = alerts.map(describeHealthAlert);\n if (healthStatus !== \"critical\") for (const d of described) d.level = \"warn\";\n else if (described.length && !described.some((d) => d.level === \"error\")) described[0].level = \"error\";\n for (const d of described) {\n problems.push({ level: d.level, code: \"health-alert\", message: d.message, fix: d.fix });\n }\n\n if (input.circuitBreaker?.state === \"open\") {\n problems.push({\n level: \"error\",\n code: \"provider-circuit-open\",\n message: `LLM provider calls are paused after ${input.circuitBreaker.failures ?? 0} consecutive failures.`,\n fix: \"Check the provider key and model in ~/.agentmemory/.env. Calls resume automatically once the provider answers again.\",\n });\n }\n\n if (input.provider === \"noop\") {\n problems.push({\n level: \"info\",\n code: \"no-llm-provider\",\n message: \"No LLM provider is configured, so summaries, consolidation and graph extraction stay off. Search still works.\",\n fix: input.providerHint || LLM_KEY_FIX,\n });\n }\n\n if (input.embeddingHint) {\n const keyMissing = input.embeddingHint.startsWith(\"EMBEDDING_PROVIDER=\");\n problems.push({\n level: \"info\",\n code: keyMissing ? \"embedding-provider-key-missing\" : \"embedding-provider-not-chosen\",\n message: keyMissing\n ? \"EMBEDDING_PROVIDER names a cloud provider whose key is missing, so search is keyword and graph only.\"\n : \"A cloud embedding key is present, but no embedding provider is chosen, so search is keyword and graph only.\",\n fix: input.embeddingHint,\n });\n }\n\n const noLlm = input.provider === \"noop\";\n const functions = markLlmFunctions(input.functionMetrics, input.provider).map((m) => ({\n ...m,\n failureRate: m.totalCalls > 0 ? m.failureCount / m.totalCalls : 0,\n }));\n for (const fn of functions) {\n if (fn.offWithoutLlm) continue;\n if (fn.totalCalls < FAILURE_MIN_CALLS || fn.failureRate < FAILURE_RATE_THRESHOLD) continue;\n problems.push({\n level: \"warn\",\n code: \"function-failing\",\n message: `${fn.functionId} failed ${fn.failureCount} of ${fn.totalCalls} calls (${Math.round(fn.failureRate * 100)}%).`,\n fix: FUNCTION_FIXES[fn.functionId] ?? \"Look for this function id in the server log to see the error.\",\n });\n }\n\n const missingObservations = input.index.missingObservations;\n if (!input.index.keywordRebuildRunning && missingObservations !== null && missingObservations > 0) {\n problems.push({\n level: \"warn\",\n code: \"index-missing-observations\",\n message: `${missingObservations} stored observations are not in the search index, so search cannot find them.`,\n fix: \"Restart agentmemory: the boot reconcile re-indexes observations missing from the snapshot.\",\n });\n }\n if (input.index.keywordRebuildRunning) {\n problems.push({\n level: \"info\",\n code: \"keyword-index-rebuilding\",\n message: \"The keyword index is still rebuilding from stored data, so the check for observations missing from search waits until it finishes.\",\n fix: \"No action needed. The check runs on the next health update after the rebuild.\",\n });\n } else if (missingObservations === null) {\n problems.push({\n level: \"info\",\n code: \"index-check-unavailable\",\n message: \"The session store did not answer in time, so the search index was not checked for missing observations.\",\n fix: \"The check runs again on the next health update. If it keeps timing out, the store is overloaded: check the server log.\",\n });\n }\n\n if (input.index.bm25Incomplete) {\n problems.push({\n level: \"error\",\n code: \"bm25-rebuild-incomplete\",\n message: \"The keyword index could not load every session at boot, so some observations are missing from search until the next successful rebuild.\",\n fix: \"Check the server log for the session listing failure. Restarting or the next cold-start search retries automatically.\",\n });\n }\n\n if (input.index.pendingVectorBackfill > 0) {\n problems.push({\n level: \"info\",\n code: \"index-vector-backfill-pending\",\n message: `${input.index.pendingVectorBackfill} documents are waiting for a vector embedding.`,\n fix: vectorBackfillFix(input.index.vectorBackfillState),\n });\n }\n\n const persistence = input.indexPersistence ?? null;\n const vectorLeg = persistence?.vector ?? null;\n if (persistence && vectorLeg) {\n if (vectorLeg.lastError) {\n problems.push({\n level: \"error\",\n code: \"index-save-failing\",\n message: `The vector index could not be saved: ${vectorLeg.lastError}. Search keeps working from memory, but vectors added since the last save are lost on restart.`,\n fix: \"Check the server log for the failing state write. The next save retries automatically.\",\n });\n }\n const dirtyAge = secondsBetween(input.now, vectorLeg.dirtySince ?? undefined);\n if (!vectorLeg.lastError && dirtyAge !== null && dirtyAge * 1000 > 2 * persistence.saveIntervalMs) {\n problems.push({\n level: \"warn\",\n code: \"index-save-stale\",\n message: `The vector index has unsaved changes from ${formatDuration(dirtyAge)} ago.`,\n fix: \"After the first checkpoint, saves are batched by AGENTMEMORY_INDEX_SAVE_INTERVAL_MS. Check the server log for save errors or a save that never finishes.\",\n });\n }\n }\n if (persistence?.pendingLogError) {\n problems.push({\n level: \"warn\",\n code: \"index-pending-log-failing\",\n message: `New vectors could not be written to the pending vector log: ${persistence.pendingLogError}. They are still kept by the next index save, but a crash before then means they are embedded again at the next start.`,\n fix: \"Check the server log for the failing state write. Each new vector retries the log write.\",\n });\n }\n if (persistence?.vectorCountShortfall) {\n const { expected, loaded } = persistence.vectorCountShortfall;\n problems.push({\n level: \"warn\",\n code: \"index-vector-count-shortfall\",\n message: `Only ${loaded} of ${expected} vectors loaded from the last save.`,\n fix: vectorBackfillFix(input.index.vectorBackfillState),\n });\n }\n\n let graph: StatusReport[\"graph\"] = null;\n if (input.graph) {\n const ageSeconds = secondsBetween(input.now, input.graph.updatedAt);\n graph = { ...input.graph, ageSeconds, extractionEnabled: input.graphExtractionEnabled };\n if (input.graphExtractionEnabled && !input.graph.fromSnapshot && !input.graph.fromIndex && !input.graphIndex) {\n problems.push({\n level: \"warn\",\n code: \"graph-no-snapshot\",\n message: \"Graph extraction is on but no graph snapshot exists, so graph counts are unavailable.\",\n fix: \"Use Rebuild Graph in the viewer, or POST /agentmemory/graph/snapshot-rebuild.\",\n });\n } else if (!input.graph.fromIndex && input.graph.fromSnapshot && ageSeconds !== null && ageSeconds > GRAPH_SNAPSHOT_STALE_SECONDS) {\n const age = ageSeconds >= 2 * 86400 ? `${Math.floor(ageSeconds / 86400)} days` : `${Math.round(ageSeconds / 3600)} hours`;\n problems.push({\n level: \"info\",\n code: \"graph-snapshot-stale\",\n message: `The graph snapshot is ${age} old, so dashboard graph counts can lag the live graph.`,\n fix: \"POST /agentmemory/graph/snapshot-rebuild refreshes it.\",\n });\n }\n if (input.graph.dirty) {\n problems.push({\n level: \"info\",\n code: \"graph-snapshot-dirty\",\n message: \"The graph snapshot was read while a write was in flight; counts are eventually consistent.\",\n fix: \"No action needed: the next graph write settles the counts.\",\n });\n }\n }\n\n const graphIndex = input.graphIndex ?? null;\n if (input.graphIndex === null || graphIndex?.state === \"unavailable\") {\n problems.push({ level: \"info\", code: \"graph-index-unavailable\", message: \"The bounded graph index could not be checked. Keyword and vector search remain available.\", fix: \"Run agentmemory graph-index status and check the state store.\" });\n } else if (graphIndex && !graphIndex.ready) {\n problems.push({\n level: graphIndex.state === \"paused\" ? \"warn\" : \"info\",\n code: \"graph-index-not-ready\",\n message: `Graph retrieval is unavailable while its index is ${graphIndex.state}. Keyword search, vector search and capture remain available.`,\n fix: graphIndex.action,\n });\n } else if (graphIndex?.coverage === \"partial\") {\n problems.push({ level: \"warn\", code: \"graph-index-partial\", message: `${graphIndex.incompleteRecords ?? \"Some\"} graph records exceed index limits; graph retrieval has partial coverage.`, fix: graphIndex.action });\n }\n\n const compaction = input.graphCompaction ?? null;\n if (compaction?.state === \"running\") {\n problems.push({\n level: \"info\",\n code: \"graph-compaction-running\",\n message: `Oversized graph provenance is being trimmed in the background (${describeGraphCompactBoot(compaction)}). Search and capture keep working.`,\n fix: \"No action needed. It runs once, resumes after a restart and stops by itself. AGENTMEMORY_GRAPH_COMPACT_ON_BOOT=false turns it off.\",\n });\n } else if (compaction?.state === \"failed\") {\n problems.push({\n level: \"warn\",\n code: \"graph-compaction-failed\",\n message: `The one-time graph provenance compaction stopped: ${compaction.error ?? \"unknown error\"}. Graph search can stay slow until it finishes.`,\n fix: `It resumes on the next start. To run it now: ${graphCompactCommand(input.ports.rest)}`,\n });\n }\n\n if (input.auditLegacy?.status === \"too-large\" || input.auditLegacy?.status === \"unreadable\") {\n const size = input.auditLegacy.sizeBytes;\n const sizeText = typeof size === \"number\" ? ` (${Math.round(size / (1024 * 1024))} MiB)` : \"\";\n problems.push({\n level: \"info\",\n code: \"audit-legacy-frozen\",\n message: `An older audit log${sizeText} was left in place instead of being migrated into monthly scopes, so it is no longer rewritten but its rows do not show up in audit queries.`,\n fix:\n input.stateBackend === \"redis\"\n ? \"Safe to ignore. To remove it, run redis-cli -u \\\"$AGENTMEMORY_REDIS_URL\\\" DEL state:mem:audit, then restart agentmemory.\"\n : \"Safe to ignore. To remove it, stop agentmemory, delete mem%3Aaudit.bin from the state store directory, then start it again.\",\n });\n }\n\n if (input.capture === null) {\n problems.push({\n level: \"info\",\n code: \"capture-check-unavailable\",\n message: \"The capture inbox did not answer in time, so capture was not checked.\",\n fix: \"The check runs again on the next status request. If it keeps timing out, the state store is overloaded: check the server log.\",\n });\n }\n problems.push(...captureProblems(input.capture ?? null, input.now, input.ports.rest));\n\n if (input.stateStore && !input.stateStore.ok) {\n problems.push({\n level: \"error\",\n code: \"state-store-unreachable\",\n message:\n input.stateBackend === \"redis\"\n ? \"The state store is not answering: the engine cannot reach Redis, so nothing is being saved or read.\"\n : \"The state store is not answering: the engine did not complete a state read in time, so nothing is being saved or read.\",\n fix:\n input.stateBackend === \"redis\"\n ? \"Check that Redis is running and reachable at AGENTMEMORY_REDIS_URL (redis-cli -u \\\"$AGENTMEMORY_REDIS_URL\\\" ping should answer PONG). Once Redis is back, restart agentmemory: the engine does not resume the live viewer stream after a Redis restart.\"\n : \"Check the server log for engine errors, then restart agentmemory.\",\n });\n }\n\n const status = problems.reduce<StatusLevel>(\n (worst, p) => (LEVEL_RANK[p.level] > LEVEL_RANK[worst] ? p.level : worst),\n \"ok\",\n );\n\n return {\n status,\n headline: statusHeadline(status, problems),\n checkedAt: input.now.toISOString(),\n service: {\n version: input.version,\n enginePinnedVersion: input.enginePinnedVersion,\n uptimeSeconds: input.uptimeSeconds,\n stateBackend: input.stateBackend,\n stateStore: input.stateStore ?? null,\n ports: input.ports,\n },\n health: input.health,\n provider: {\n llm: input.provider,\n route: input.provider === \"noop\" ? null : (input.llmRoute ?? null),\n hint: input.providerHint ?? null,\n embeddings: input.embeddingProvider,\n embeddingHint: input.embeddingHint ?? null,\n circuitBreaker: input.circuitBreaker,\n offWithoutLlm: noLlm ? OFF_WITHOUT_LLM : [],\n },\n index: { ...input.index, breakdown: indexBreakdown(input.index) },\n indexPersistence: persistence,\n graph,\n graphCompaction: compaction,\n graphIndex,\n capture: input.capture ?? null,\n observeDedup: input.observeDedup ?? null,\n functions,\n flags: input.flags.map((flag) =>\n flag.enabled && flag.needsLlm && noLlm\n ? { ...flag, inactiveReason: \"needs an LLM provider, none is configured\" }\n : flag,\n ),\n problems,\n };\n}\n\nconst RECENT_DROP_MS = 24 * 60 * 60 * 1000;\n\nexport const CURL_AUTH_HEADER = '-H \"Authorization: Bearer ${AGENTMEMORY_SECRET:-$(cat ~/.agentmemory/secret)}\"';\n\nexport function captureRestBase(restPort: number | null): string {\n return `http://localhost:${restPort ?? 3111}/agentmemory`;\n}\n\nfunction captureProblems(capture: CaptureStatus | null, now: Date, restPort: number | null): StatusProblem[] {\n if (!capture) return [];\n const problems: StatusProblem[] = [];\n const base = captureRestBase(restPort);\n const inbox = capture.inbox;\n if (inbox && inbox.dead > 0) {\n // Errors returned by mem::observe dead-letter on the first attempt, so the\n // message cannot claim the retry budget was used.\n const sessionCap = inbox.lastError?.startsWith(\"Session observation limit reached\") ?? false;\n const listAndRetry = `List them with curl -s ${CURL_AUTH_HEADER} '${base}/capture?status=dead'. After fixing the cause, retry them with curl -X POST ${base}/capture/retry ${CURL_AUTH_HEADER} -H \"Content-Type: application/json\" -d '{\"all\":true}'.`;\n problems.push({\n level: \"warn\",\n code: \"capture-dead-letters\",\n message: `${plural(inbox.dead, \"captured observation\")} could not be stored and ${inbox.dead === 1 ? \"is parked as a dead letter\" : \"are parked as dead letters\"}${inbox.lastError ? `: ${inbox.lastError}` : \".\"}`,\n fix: sessionCap\n ? `The session reached its MAX_OBS_PER_SESSION cap, so a retry is refused again until the cap is raised. Raise MAX_OBS_PER_SESSION in ~/.agentmemory/.env (0 = no cap) and restart agentmemory. ${listAndRetry}`\n : listAndRetry,\n });\n }\n if (inbox && inbox.retrying + inbox.pending > 0) {\n problems.push({\n level: \"info\",\n code: \"capture-retrying\",\n message: `${plural(inbox.retrying + inbox.pending, \"accepted observation\")} ${inbox.retrying + inbox.pending === 1 ? \"is\" : \"are\"} waiting to be stored${inbox.lastError ? ` after a failure: ${inbox.lastError}` : \"\"}.`,\n fix: `No action needed: the server retries every ${Math.round(capture.policy.retryIntervalMs / 1000)} s with backoff, up to ${capture.policy.maxAttempts} attempts, and again after a restart.`,\n });\n }\n const waiting = capture.spool.reduce((n, s) => n + s.records, 0);\n if (waiting > 0) {\n problems.push({\n level: \"info\",\n code: \"capture-spool-waiting\",\n message: `${plural(waiting, \"observation\")} captured while the server was unreachable ${waiting === 1 ? \"is\" : \"are\"} waiting in the local capture spool.`,\n fix: `They are sent on the next hook call and at every start. To send them now: npx @agentmemory/agentmemory capture --drain, or curl -X POST ${base}/capture/drain ${CURL_AUTH_HEADER}.`,\n });\n }\n let dropped = 0;\n let latest: { at: number; reason: string; maxBytes: number; maxAgeHours: number } | null = null;\n for (const spool of capture.spool) {\n dropped += spool.stats.dropped;\n const lastDrop = spool.stats.lastDropAt ? Date.parse(spool.stats.lastDropAt) : NaN;\n if (Number.isFinite(lastDrop) && (!latest || lastDrop > latest.at)) {\n latest = { at: lastDrop, reason: spool.stats.lastDropReason ?? \"unknown\", maxBytes: spool.maxBytes, maxAgeHours: spool.maxAgeHours };\n }\n }\n if (latest && now.getTime() - latest.at < RECENT_DROP_MS) {\n problems.push({\n level: \"warn\",\n code: \"capture-spool-dropped\",\n message: `The local capture spool dropped ${plural(dropped, \"observation\")} in total (latest reason: ${latest.reason}), so those tool calls are not in memory.`,\n fix: `The spool holds at most ${Math.round(latest.maxBytes / 1024)} KiB for ${latest.maxAgeHours} hours. Raise AGENTMEMORY_CAPTURE_SPOOL_MAX_BYTES, keep agentmemory running while agents work, or check that AGENTMEMORY_CAPTURE_SPOOL is not false.`,\n });\n }\n return problems;\n}\n\nfunction statusHeadline(status: StatusLevel, problems: StatusProblem[]): string {\n if (status === \"ok\") return \"Every check passed. Capture, search and the stream are working.\";\n if (status === \"info\") {\n return `Working normally. ${plural(problems.length, \"note\")} below about features that are off or checks that did not run.`;\n }\n const worst = problems.find((p) => p.level === status) ?? problems[0];\n const rest = problems.length - 1;\n const lead = status === \"error\" ? \"Not working correctly\" : \"Working, but needs attention\";\n return `${lead}: ${worst.message}${rest > 0 ? ` (${plural(rest, \"more item\")} below.)` : \"\"}`;\n}\n\nfunction indexBreakdown(idx: StatusInputs[\"index\"]): IndexBreakdown | null {\n if (idx.memoriesIndexed === undefined && idx.lessonsIndexed === undefined) return null;\n const lessons = idx.lessonsIndexed ?? 0;\n return {\n observations: Math.max(0, idx.observationsIndexed - lessons),\n memories: idx.memoriesIndexed ?? 0,\n lessons,\n };\n}\n\nfunction plural(count: number, word: string): string {\n return `${count} ${word}${count === 1 ? \"\" : \"s\"}`;\n}\n\nfunction documentBreakdown(idx: StatusReport[\"index\"]): string {\n const b = idx.breakdown;\n if (!b) return String(idx.bm25Documents);\n const parts = [\n plural(b.observations, \"observation\"),\n `${b.memories} ${b.memories === 1 ? \"memory\" : \"memories\"}`,\n plural(b.lessons, \"lesson\"),\n ];\n return `${idx.bm25Documents} (${parts.join(\", \")})`;\n}\n\nfunction flagState(flag: StatusReport[\"flags\"][number]): string {\n if (!flag.enabled) return \"off\";\n if (flag.inactiveReason) return `on, inactive: ${flag.inactiveReason}`;\n return \"on\";\n}\n\nfunction flagHowTo(flag: StatusReport[\"flags\"][number]): string {\n if (!flag.enabled) return flag.enableHow;\n if (flag.inactiveReason) return LLM_KEY_FIX;\n return `Set ${flag.key}=false and restart to turn it off.`;\n}\n\nfunction processHealth(report: StatusReport): string {\n const status = report.health?.status;\n if (!status) return \"no data yet\";\n if (status === \"healthy\" && report.status !== \"ok\") {\n return \"healthy (memory, CPU and engine checks only; the badge at the top covers every problem on this page)\";\n }\n return status;\n}\n\nfunction escapeHtml(value: unknown): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\nfunction formatDuration(seconds: number | null): string {\n if (seconds === null) return \"unknown\";\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n if (hours < 48) return `${hours}h ${minutes % 60}m`;\n return `${Math.floor(hours / 24)}d`;\n}\n\nfunction row(label: string, value: string): string {\n return `<tr><th>${escapeHtml(label)}</th><td>${value}</td></tr>`;\n}\n\nfunction legSummary(report: StatusReport, leg: IndexLegStatus): string {\n if (leg.lastError) return `failing: ${leg.lastError}`;\n const saved = leg.lastSavedAt ? `saved ${formatDuration(secondsBetween(new Date(report.checkedAt), leg.lastSavedAt))} ago` : \"not saved since start\";\n return leg.dirtySince ? `${saved}, unsaved changes pending` : saved;\n}\n\nconst PENDING_LOG_EXPLAINER =\n \"Every new or removed vector is also written right away to this small log. After a crash or force-kill it is replayed at start, so vectors are not lost and nothing is embedded twice. Each index save empties it.\";\n\nfunction indexPersistenceRows(report: StatusReport): string {\n const persistence = report.indexPersistence;\n if (!persistence) return \"\";\n let rows = row(\"BM25 index\", \"rebuilt from stored content at boot\");\n if (persistence.vector) {\n rows += row(\"Vector save\", escapeHtml(legSummary(report, persistence.vector)));\n rows += row(\n \"Vector storage\",\n escapeHtml(`${plural(persistence.buckets, \"bucket\")}, ${plural(persistence.pendingChanges, \"unsaved change\")}`),\n );\n if (persistence.pendingLog !== undefined) {\n rows += row(\n \"Pending vector log\",\n escapeHtml(plural(persistence.pendingLog, \"vector change\")) +\n `<p class=\"note\">${escapeHtml(PENDING_LOG_EXPLAINER)}</p>`,\n );\n }\n }\n return rows;\n}\n\nexport function describeCaptureSpool(capture: CaptureStatus): string {\n const records = capture.spool.reduce((n, s) => n + s.records, 0);\n const bytes = capture.spool.reduce((n, s) => n + s.bytes, 0);\n if (!capture.spool.some((s) => s.enabled)) return \"off (AGENTMEMORY_CAPTURE_SPOOL=false)\";\n const retained = capture.spool.reduce((n, s) => n + (s.retained ?? 0), 0);\n const held = retained > 0 ? `, ${retained} sent and kept until saved` : \"\";\n return records === 0 ? `empty${held}` : `${plural(records, \"observation\")} waiting, ${Math.ceil(bytes / 1024)} KiB${held}`;\n}\n\nfunction captureRows(report: StatusReport): string {\n const capture = report.capture;\n if (!capture) return row(\"Capture\", \"not reported\");\n const inbox = capture.inbox;\n const since = capture.sinceStart;\n let rows = row(\n \"Inbox\",\n escapeHtml(inbox ? `${inbox.pending} pending · ${inbox.retrying} retrying · ${inbox.dead} dead letters` : \"not checked\") +\n '<p class=\"note\">Every accepted observation is written here first and removed once it is stored, so a failure or restart retries it instead of losing it.</p>',\n );\n rows += row(\n \"Since start\",\n escapeHtml(`${since.accepted} accepted · ${since.completed} stored · ${since.duplicates} duplicates skipped · ${since.recovered} recovered by retry · ${since.deadLettered} dead`),\n );\n rows += row(\n \"Local spool\",\n escapeHtml(describeCaptureSpool(capture)) +\n `<p class=\"note\">Hooks write here when the server is unreachable, and keep each accepted observation here until the server has saved it to disk. ${escapeHtml(capture.spool.map((s) => s.path).join(\", \"))}</p>`,\n );\n const drained = capture.spool.map((s) => s.stats.lastDrainAt).filter(Boolean).sort().pop();\n if (drained) rows += row(\"Last spool drain\", escapeHtml(`${formatDuration(secondsBetween(new Date(report.checkedAt), drained))} ago`));\n rows += row(\n \"Duplicate protection\",\n escapeHtml(`event ids kept ${capture.policy.dedupRetentionHours} h, retries up to ${plural(capture.policy.maxAttempts, \"attempt\")}`),\n );\n return rows;\n}\n\nfunction mb(bytes: number): string {\n return `${Math.round(bytes / (1024 * 1024))} MB`;\n}\n\nfunction processRows(report: StatusReport): string {\n const h = report.health;\n let rows = row(\"Process health\", escapeHtml(processHealth(report)));\n if (h?.memory) {\n const limit = h.memory.heapLimit || h.memory.heapTotal;\n const pct = limit > 0 ? Math.round((h.memory.heapUsed / limit) * 100) : 0;\n rows += row(\n \"Heap\",\n escapeHtml(`${mb(h.memory.heapUsed)} of ${mb(limit)} (${pct}%)`) +\n '<p class=\"note\">JavaScript memory in use against the most it may grow to. Only a concern above 80% while RSS is also over 512 MB.</p>',\n );\n rows += row(\n \"RSS\",\n escapeHtml(mb(h.memory.rss)) + '<p class=\"note\">Everything the process holds from the operating system, including code and buffers.</p>',\n );\n }\n if (typeof h?.eventLoopLagMs === \"number\") {\n rows += row(\n \"Event loop delay\",\n escapeHtml(`${h.eventLoopLagMs.toFixed(1)} ms`) +\n '<p class=\"note\">How far behind the worker is. Under 100 ms is fine; above that requests answer slowly.</p>',\n );\n }\n return rows;\n}\n\nexport function renderStatusHtml(\n report: StatusReport,\n styleNonce: string,\n options: { viewerUrl?: string } = {},\n): string {\n const viewerUrl = options.viewerUrl ?? \"/agentmemory/viewer#health\";\n const problems = report.problems.length\n ? report.problems\n .map(\n (p) =>\n `<li class=\"p ${p.level}\"><span class=\"lvl\">${p.level}</span><div><p>${escapeHtml(p.message)}</p>` +\n (p.fix ? `<p class=\"fix\">${escapeHtml(p.fix)}</p>` : \"\") +\n `</div></li>`,\n )\n .join(\"\")\n : `<li class=\"p ok\"><span class=\"lvl\">ok</span><div><p>No problems found.</p></div></li>`;\n\n const functions = report.functions.length\n ? report.functions\n .slice()\n .sort((a, b) => b.totalCalls - a.totalCalls)\n .map(\n (f) =>\n `<tr${!f.offWithoutLlm && f.failureRate >= FAILURE_RATE_THRESHOLD && f.totalCalls >= FAILURE_MIN_CALLS ? ' class=\"bad\"' : \"\"}>` +\n `<td>${escapeHtml(f.functionId)}</td><td>${f.totalCalls}</td><td>${f.offWithoutLlm ? \"-\" : f.failureCount}</td>` +\n `<td>${f.offWithoutLlm ? \"off, no LLM provider\" : `${Math.round(f.failureRate * 100)}%`}</td><td>${Math.round(f.avgLatencyMs)} ms</td></tr>`,\n )\n .join(\"\")\n : `<tr><td colspan=\"5\">No function calls recorded yet.</td></tr>`;\n\n const flags = report.flags\n .map(\n (f) =>\n `<tr><td>${escapeHtml(f.label)}</td><td><code>${escapeHtml(f.key)}</code></td><td${f.inactiveReason ? ' class=\"warn\"' : \"\"}>${escapeHtml(flagState(f))}</td>` +\n `<td>${escapeHtml(flagHowTo(f))}</td></tr>`,\n )\n .join(\"\");\n\n const idx = report.index;\n const graph = report.graph;\n const ports = report.service.ports;\n\n return `<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>agentmemory status</title>\n<style nonce=\"${escapeHtml(styleNonce)}\">\n:root{--bg:#F9F9F7;--bg-alt:#F0F0EC;--ink:#111111;--ink-muted:#666666;--line:#D4D4CF;--rule:#111111;--ok:#2D6A4F;--info:#1D4E89;--warn:#B8860B;--error:#CC0000;--font-display:'Playfair Display',Georgia,'Times New Roman',serif;--font-body:'Lora',Georgia,serif;--font-ui:'Inter',-apple-system,system-ui,sans-serif;--font-mono:'JetBrains Mono','SF Mono','Fira Code',ui-monospace,monospace}\n@media (prefers-color-scheme:dark){:root{--bg:#121316;--bg-alt:#1a1c20;--ink:#eef0f3;--ink-muted:#94979d;--line:#26282c;--rule:#c9cbd1;--ok:#4ade80;--info:#93c5fd;--warn:#fbbf24;--error:#f2555a}}\n*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:14px/1.55 var(--font-body)}\nmain{max-width:960px;margin:0 auto;padding:32px 16px 64px}\nheader{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;border-bottom:3px double var(--rule);padding-bottom:12px;margin-bottom:24px}\nh1{font:700 26px/1.2 var(--font-display);margin:0}h2{font:600 11px/1.4 var(--font-ui);letter-spacing:.12em;text-transform:uppercase;color:var(--ink-muted);margin:32px 0 8px;padding-bottom:4px;border-bottom:1px solid var(--rule)}\n.badge{font:700 11px/1.4 var(--font-ui);text-transform:uppercase;letter-spacing:.08em;padding:2px 8px;border:1.5px solid currentColor}\n.ok{color:var(--ok)}.info{color:var(--info)}.warn{color:var(--warn)}.error{color:var(--error)}\n.meta{color:var(--ink-muted);font:12px/1.4 var(--font-ui);margin-left:auto}\nul.problems{list-style:none;padding:0;margin:0}\nli.p{display:grid;grid-template-columns:64px 1fr;gap:12px;padding:12px 0;border-bottom:1px solid var(--line)}\nli.p p{margin:0;color:var(--ink)}li.p .fix{color:var(--ink-muted);margin-top:4px;font-size:13px}\n.lvl{font:700 11px/1.4 var(--font-ui);text-transform:uppercase;letter-spacing:.08em;padding-top:2px}\ntable{width:100%;border-collapse:collapse;font:13px/1.5 var(--font-ui)}th,td{text-align:left;padding:6px 8px;border-bottom:1px solid var(--line);vertical-align:top;overflow-wrap:anywhere}\nth{color:var(--ink-muted);font-weight:500;width:220px}\ntable.list th{width:auto;font-size:11px;text-transform:uppercase;letter-spacing:.06em;overflow-wrap:normal}table.list td{overflow-wrap:break-word}table.list td code{overflow-wrap:break-word;word-break:normal}tr.bad td{color:var(--error)}\ntr:nth-child(even) td{background:var(--bg-alt)}\ncode{font:12px var(--font-mono);overflow-wrap:anywhere}\n.lead{font:600 16px/1.45 var(--font-body);margin:0 0 8px}.live{font:13px/1.5 var(--font-ui);color:var(--ink-muted);margin:0 0 8px}\n.note{margin:2px 0 0;color:var(--ink-muted);font-size:12px}\na{color:inherit}\n@media (max-width:640px){th{width:110px}table.list{table-layout:fixed}table.list th,table.list td{padding:6px 4px;font-size:12px}}\n</style></head><body><main>\n<header><h1>agentmemory</h1><span class=\"badge ${report.status}\">${report.status}</span>\n<span class=\"meta\">v${escapeHtml(report.service.version)} · engine pinned ${escapeHtml(report.service.enginePinnedVersion)} · checked ${escapeHtml(report.checkedAt)} · <a href=\"?format=json\">json</a></span></header>\n<p class=\"lead ${report.status}\">${escapeHtml(report.headline)}</p>\n<p class=\"live\">A snapshot from when this page loaded. <a href=\"${escapeHtml(viewerUrl)}\">Open the live version in the viewer →</a> From a terminal: <code>curl -s ${escapeHtml(CURL_AUTH_HEADER)} ${ports.rest ? `http://localhost:${escapeHtml(ports.rest)}` : \"\"}/agentmemory/status</code> returns this report as JSON.</p>\n<h2>Problems</h2><ul class=\"problems\">${problems}</ul>\n<h2>Engine and connection</h2><table>\n${row(\"Engine connection\", escapeHtml(report.health?.connectionState ?? \"unknown\"))}\n${row(\"Uptime\", escapeHtml(formatDuration(report.service.uptimeSeconds)))}\n${row(\"State backend\", escapeHtml(report.service.stateBackend))}\n${row(\"REST port\", escapeHtml(ports.rest ?? \"unknown\"))}\n${row(\"Viewer port\", escapeHtml(ports.viewer ?? \"not running\"))}\n</table>\n<h2>LLM and embeddings</h2><table>\n${row(\"LLM\", escapeHtml(report.provider.llm === \"noop\" ? \"none configured\" : (report.provider.route ?? report.provider.llm)))}\n${report.provider.offWithoutLlm.length ? row(\"Off without an LLM\", escapeHtml(report.provider.offWithoutLlm.join(\", \")) + `<p class=\"note\">${escapeHtml(LLM_KEY_FIX)}</p>`) : \"\"}\n${row(\"Embeddings\", escapeHtml(report.provider.embeddings === \"none\" ? \"none (keyword search only)\" : report.provider.embeddings))}\n${row(\"Circuit breaker\", escapeHtml(report.provider.circuitBreaker ? `${report.provider.circuitBreaker.state ?? \"unknown\"} (${report.provider.circuitBreaker.failures ?? 0} failures)` : \"not in use\"))}\n</table>\n<h2>Search index</h2><table>\n${row(\"Keyword index (BM25)\", escapeHtml(documentBreakdown(idx)) + `<p class=\"note\">${escapeHtml(BM25_EXPLAINER)}</p>`)}\n${row(\"Vector documents\", escapeHtml(idx.vectorDocuments ?? \"vector search off\"))}\n${row(\"Observations searchable\", escapeHtml(idx.breakdown ? idx.breakdown.observations : idx.observationsIndexed))}\n${row(\"Missing from index\", escapeHtml(idx.missingObservations ?? \"not checked\"))}\n${row(\"Sessions\", escapeHtml(idx.sessions ?? \"unknown\"))}\n${row(\"Keyword index rebuild\", idx.bm25Incomplete ? '<span class=\"warn\">incomplete</span>' : \"complete\")}\n${row(\"Pending vector backfill\", escapeHtml(idx.pendingVectorBackfill))}\n${idx.vectorBackfillState ? row(\"Vector backfill\", escapeHtml(describeBackfillState(idx.vectorBackfillState))) : \"\"}\n${indexPersistenceRows(report)}\n</table>\n<h2>Capture</h2><table>\n${captureRows(report)}\n${report.observeDedup ? row(\"Repeats skipped\", escapeHtml(`${report.observeDedup.skippedSinceStart} since start`) + `<p class=\"note\">${escapeHtml(`A tool call with the same input and the same output as one stored in the last ${formatDuration(report.observeDedup.windowSeconds)} is skipped when the hook sends no event id.`)}</p>`) : \"\"}\n</table>\n<h2>Knowledge graph</h2><table>\n${graph\n ? row(\"Extraction\", graph.extractionEnabled ? \"on\" : \"off\") +\n row(\"Nodes / edges\", escapeHtml(`${graph.totalNodes ?? \"unknown\"} / ${graph.totalEdges ?? \"unknown\"}`)) +\n row(graph.fromIndex ? \"Count source\" : \"Snapshot age\", escapeHtml(graph.fromIndex ? \"maintained index\" : graph.fromSnapshot ? formatDuration(graph.ageSeconds) : \"no snapshot\"))\n : row(\"Graph\", \"unavailable\")}\n${report.graphCompaction ? row(\"Provenance compaction\", escapeHtml(describeGraphCompactBoot(report.graphCompaction))) : \"\"}\n${report.graphIndex ? row(\"Retrieval index\", escapeHtml(`${report.graphIndex.state}, ${report.graphIndex.coverage} coverage`)) : \"\"}\n</table>\n<h2>Features</h2><table class=\"list\"><tr><th>Feature</th><th>Setting</th><th>State</th><th>How to change</th></tr>${flags}</table>\n<h2>Process</h2><table>\n${processRows(report)}\n</table>\n<h2>Functions</h2><table class=\"list\"><tr><th>Function</th><th>Calls</th><th>Failed</th><th>Failure rate</th><th>Avg latency</th></tr>${functions}</table>\n<h2>More</h2><p>Environment checks (keys, engine binary, stale pid files) run on your machine with <code>npx @agentmemory/agentmemory doctor</code>. JSON: <code>GET /agentmemory/status</code> with <code>Accept: application/json</code>, or add <code>?format=json</code>.</p>\n</main></body></html>`;\n}\n\nexport function graphCompactCommand(restPort: number | null): string {\n return `curl -X POST http://localhost:${restPort ?? 3111}/agentmemory/graph/compact ${CURL_AUTH_HEADER} -H \"Content-Type: application/json\" -d '{}'`;\n}\n\nexport const UNINDEXED_SCAN_REUSE_MS = 30_000;\n\nexport function singleFlight<T>(\n run: () => Promise<T>,\n reuseMs: number,\n now: () => number = Date.now,\n): () => Promise<T> {\n let current: { promise: Promise<T>; settledAt: number | null } | null = null;\n return () => {\n if (current && (current.settledAt === null || now() - current.settledAt < reuseMs)) {\n return current.promise;\n }\n const entry: { promise: Promise<T>; settledAt: number | null } = { promise: run(), settledAt: null };\n entry.promise.then(\n () => {\n entry.settledAt = now();\n },\n () => {\n if (current === entry) current = null;\n },\n );\n current = entry;\n return entry.promise;\n };\n}\n\nexport function prefersHtml(accept: string | undefined, format: string | undefined): boolean {\n if (format === \"json\") return false;\n if (format === \"html\") return true;\n if (!accept) return false;\n return /\\btext\\/html\\b/.test(accept);\n}\n","export const COMPRESSION_SYSTEM = `You are a memory compression engine for an AI coding agent. Your job is to extract the essential information from a tool usage observation and compress it into structured data.\n\nOutput EXACTLY this XML format with no additional text:\n\n<observation>\n <type>one of: file_read, file_write, file_edit, command_run, search, web_fetch, conversation, error, decision, discovery, subagent, notification, task, other</type>\n <title>Short descriptive title (max 80 chars)</title>\n <subtitle>One-line context (optional)</subtitle>\n <facts>\n <fact>Specific factual detail 1</fact>\n <fact>Specific factual detail 2</fact>\n </facts>\n <narrative>2-3 sentence summary of what happened and why it matters</narrative>\n <concepts>\n <concept>technical concept or pattern</concept>\n </concepts>\n <files>\n <file>path/to/file</file>\n </files>\n <importance>1-10 scale, 10 being critical architectural decision</importance>\n</observation>\n\nRules:\n- Escape &, <, and > inside text as &, <, and >. Use only the tags shown, with no attributes or nested tags inside text fields.\n- Be concise but preserve ALL technically relevant details\n- File paths must be exact\n- Importance: 1-3 for routine reads, 4-6 for edits/commands, 7-9 for architectural decisions, 10 for breaking changes\n- Concepts should be reusable search terms (e.g., \"React hooks\", \"SQL migration\", \"auth middleware\"); keep them in the user's language: when the source content is not English, include at least one concept in that original language, and when the observation mixes languages include both the original-language and English terms so search works in either\n- Strip any secrets, tokens, or credentials from the output`;\n\nexport function buildCompressionPrompt(observation: {\n hookType: string;\n toolName?: string;\n toolInput?: unknown;\n toolOutput?: unknown;\n userPrompt?: string;\n assistantResponse?: string;\n timestamp: string;\n}): string {\n const parts = [\n `Timestamp: ${observation.timestamp}`,\n `Hook: ${observation.hookType}`,\n ];\n\n if (observation.toolName) parts.push(`Tool: ${observation.toolName}`);\n if (observation.toolInput) {\n const input =\n typeof observation.toolInput === \"string\"\n ? observation.toolInput\n : JSON.stringify(observation.toolInput, null, 2);\n parts.push(`Input:\\n${truncate(input, 4000)}`);\n }\n if (observation.toolOutput) {\n const output =\n typeof observation.toolOutput === \"string\"\n ? observation.toolOutput\n : JSON.stringify(observation.toolOutput, null, 2);\n parts.push(`Output:\\n${truncate(output, 4000)}`);\n }\n if (observation.userPrompt) {\n parts.push(`User prompt:\\n${truncate(observation.userPrompt, 2000)}`);\n }\n if (observation.assistantResponse) {\n parts.push(`Assistant response:\\n${truncate(observation.assistantResponse, 4000)}`);\n }\n\n return parts.join(\"\\n\\n\");\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length > max ? s.slice(0, max) + \"\\n[...truncated]\" : s;\n}\n","export const VISION_DESCRIPTION_PROMPT = `Describe what this image shows in the context of software development. Extract:\n- What type of image this is (screenshot, diagram, mockup, terminal output, error, etc.)\n- Key entities visible (files, components, UI elements, error messages)\n- Relationships or flow shown\n- Any decisions, errors, or state visible\n- Text content visible in the image\n\nBe concise but preserve all technically relevant details. Output plain text, no XML.`;\n","interface XmlElement {\n name: string;\n content: string;\n}\n\nfunction elements(xml: string): XmlElement[] | null {\n const result: XmlElement[] = [];\n let remaining = xml.trim();\n while (remaining) {\n const match = /^<([a-z][a-z0-9_-]*)\\s*(?:\\/>|>([\\s\\S]*?)<\\/\\1\\s*>)/.exec(remaining);\n if (!match) return null;\n result.push({ name: match[1], content: match[2] ?? \"\" });\n remaining = remaining.slice(match[0].length).trim();\n }\n return result;\n}\n\nfunction xmlText(content: string): string | null {\n if (content.includes(\"<\") || /&(?!(?:amp|lt|gt|quot|apos|#\\d+|#x[\\da-fA-F]+);)/.test(content)) {\n return null;\n }\n const entities: Record<string, string> = {\n amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', apos: \"'\",\n };\n let valid = true;\n const text = content.replace(/&([^;]+);/g, (_, entity: string) => {\n if (entity in entities) return entities[entity];\n const code = entity.startsWith(\"#x\")\n ? parseInt(entity.slice(2), 16)\n : Number(entity.slice(1));\n if (!(code === 9 || code === 10 || code === 13 ||\n (code >= 0x20 && code <= 0xd7ff) ||\n (code >= 0xe000 && code <= 0xfffd) ||\n (code >= 0x10000 && code <= 0x10ffff))) {\n valid = false;\n return \"\";\n }\n return String.fromCodePoint(code);\n });\n return valid && !/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f]/.test(text) ? text.trim() : null;\n}\n\nconst SCALARS = new Set([\"type\", \"title\", \"subtitle\", \"narrative\", \"importance\"]);\nconst LISTS: Record<string, string> = { facts: \"fact\", concepts: \"concept\", files: \"file\" };\n\nexport function parseCompressionXml(response: string) {\n let xml = response.trim();\n // Reasoning is outside the observation contract, even when it quotes XML fields.\n xml = xml.replace(/^<(think|thought)>[\\s\\S]*?<\\/\\1>\\s*/, \"\");\n const fenced = /^```(?:xml)?\\s*\\n([\\s\\S]*?)\\n```$/i.exec(xml);\n if (fenced) xml = fenced[1].trim();\n\n const roots = elements(xml);\n if (!roots || roots.length !== 1 || roots[0].name !== \"observation\") return null;\n const fields = elements(roots[0].content);\n if (!fields) return null;\n const seen = new Set<string>();\n const scalars: Record<string, string> = {};\n const lists: Record<string, string[]> = { facts: [], concepts: [], files: [] };\n for (const field of fields) {\n if (seen.has(field.name)) return null;\n seen.add(field.name);\n if (SCALARS.has(field.name)) {\n const text = xmlText(field.content);\n if (text === null) return null;\n scalars[field.name] = text;\n } else if (Object.hasOwn(LISTS, field.name)) {\n const children = elements(field.content);\n if (!children) return null;\n for (const child of children) {\n if (child.name !== LISTS[field.name]) return null;\n const text = xmlText(child.content);\n if (text === null || !text) return null;\n lists[field.name].push(text);\n }\n } else {\n return null;\n }\n }\n return {\n type: scalars.type ?? \"\",\n title: scalars.title ?? \"\",\n subtitle: scalars.subtitle || undefined,\n facts: lists.facts,\n narrative: scalars.narrative ?? \"\",\n concepts: lists.concepts,\n files: lists.files,\n importance: /^\\d+$/.test(scalars.importance ?? \"\") ? Number(scalars.importance) : NaN,\n };\n}\n","const step2map: Record<string, string> = {\n ational: \"ate\", tional: \"tion\", enci: \"ence\", anci: \"ance\",\n izer: \"ize\", iser: \"ise\", abli: \"able\", alli: \"al\",\n entli: \"ent\", eli: \"e\", ousli: \"ous\", ization: \"ize\",\n isation: \"ise\", ation: \"ate\", ator: \"ate\", alism: \"al\",\n iveness: \"ive\", fulness: \"ful\", ousness: \"ous\", aliti: \"al\",\n iviti: \"ive\", biliti: \"ble\",\n};\n\nconst step3map: Record<string, string> = {\n icate: \"ic\", ative: \"\", alize: \"al\", alise: \"al\",\n iciti: \"ic\", ical: \"ic\", ful: \"\", ness: \"\",\n};\n\nfunction hasVowel(s: string): boolean {\n return /[aeiou]/.test(s);\n}\n\nfunction measure(s: string): number {\n const reduced = s.replace(/[^aeiouy]+/g, \"C\").replace(/[aeiouy]+/g, \"V\");\n const m = reduced.match(/VC/g);\n return m ? m.length : 0;\n}\n\nfunction endsDoubleConsonant(s: string): boolean {\n return s.length >= 2 && s[s.length - 1] === s[s.length - 2] && !/[aeiou]/.test(s[s.length - 1]);\n}\n\nfunction endsCVC(s: string): boolean {\n if (s.length < 3) return false;\n const c1 = s[s.length - 3], v = s[s.length - 2], c2 = s[s.length - 1];\n return !/[aeiou]/.test(c1) && /[aeiou]/.test(v) && !/[aeiouwxy]/.test(c2);\n}\n\nexport function stem(word: string): string {\n if (word.length <= 2) return word;\n\n let w = word;\n\n if (w.endsWith(\"sses\")) w = w.slice(0, -2);\n else if (w.endsWith(\"ies\")) w = w.slice(0, -2);\n else if (!w.endsWith(\"ss\") && w.endsWith(\"s\")) w = w.slice(0, -1);\n\n if (w.endsWith(\"eed\")) {\n if (measure(w.slice(0, -3)) > 0) w = w.slice(0, -1);\n } else if (w.endsWith(\"ed\") && hasVowel(w.slice(0, -2))) {\n w = w.slice(0, -2);\n if (w.endsWith(\"at\") || w.endsWith(\"bl\") || w.endsWith(\"iz\")) w += \"e\";\n else if (endsDoubleConsonant(w) && !/[lsz]$/.test(w)) w = w.slice(0, -1);\n else if (measure(w) === 1 && endsCVC(w)) w += \"e\";\n } else if (w.endsWith(\"ing\") && hasVowel(w.slice(0, -3))) {\n w = w.slice(0, -3);\n if (w.endsWith(\"at\") || w.endsWith(\"bl\") || w.endsWith(\"iz\")) w += \"e\";\n else if (endsDoubleConsonant(w) && !/[lsz]$/.test(w)) w = w.slice(0, -1);\n else if (measure(w) === 1 && endsCVC(w)) w += \"e\";\n }\n\n if (w.endsWith(\"y\") && hasVowel(w.slice(0, -1))) {\n w = w.slice(0, -1) + \"i\";\n }\n\n for (const [suffix, replacement] of Object.entries(step2map)) {\n if (w.endsWith(suffix)) {\n const base = w.slice(0, -suffix.length);\n if (measure(base) > 0) w = base + replacement;\n break;\n }\n }\n\n for (const [suffix, replacement] of Object.entries(step3map)) {\n if (w.endsWith(suffix)) {\n const base = w.slice(0, -suffix.length);\n if (measure(base) > 0) w = base + replacement;\n break;\n }\n }\n\n if (w.endsWith(\"al\") || w.endsWith(\"ance\") || w.endsWith(\"ence\") ||\n w.endsWith(\"er\") || w.endsWith(\"ic\") || w.endsWith(\"able\") ||\n w.endsWith(\"ible\") || w.endsWith(\"ant\") || w.endsWith(\"ement\") ||\n w.endsWith(\"ment\") || w.endsWith(\"ent\") || w.endsWith(\"tion\") ||\n w.endsWith(\"sion\") || w.endsWith(\"ou\") || w.endsWith(\"ism\") ||\n w.endsWith(\"ate\") || w.endsWith(\"iti\") || w.endsWith(\"ous\") ||\n w.endsWith(\"ive\") || w.endsWith(\"ize\") || w.endsWith(\"ise\")) {\n const suffixLen = w.match(/(ement|ment|tion|sion|ance|ence|able|ible|ism|ate|iti|ous|ive|ize|ise|ant|ent|al|er|ic|ou)$/)?.[0]?.length ?? 0;\n if (suffixLen > 0) {\n const base = w.slice(0, -suffixLen);\n if (measure(base) > 1) w = base;\n }\n }\n\n if (w.endsWith(\"e\")) {\n const base = w.slice(0, -1);\n if (measure(base) > 1 || (measure(base) === 1 && !endsCVC(base))) {\n w = base;\n }\n }\n\n if (endsDoubleConsonant(w) && w.endsWith(\"l\") && measure(w.slice(0, -1)) > 1) {\n w = w.slice(0, -1);\n }\n\n return w;\n}\n","import { stem } from \"./stemmer.js\";\n\nconst SYNONYM_GROUPS: string[][] = [\n [\"auth\", \"authentication\", \"authn\", \"authenticating\"],\n [\"authz\", \"authorization\", \"authorizing\"],\n [\"db\", \"database\", \"datastore\"],\n [\"perf\", \"performance\", \"latency\", \"throughput\", \"slow\", \"bottleneck\"],\n [\"optim\", \"optimization\", \"optimizing\", \"optimise\", \"query-optimization\"],\n [\"k8s\", \"kubernetes\", \"kube\"],\n [\"config\", \"configuration\", \"configuring\", \"setup\"],\n [\"deps\", \"dependencies\", \"dependency\"],\n [\"env\", \"environment\"],\n [\"fn\", \"function\"],\n [\"impl\", \"implementation\", \"implementing\"],\n [\"msg\", \"message\", \"messaging\"],\n [\"repo\", \"repository\"],\n [\"req\", \"request\"],\n [\"res\", \"response\"],\n [\"ts\", \"typescript\"],\n [\"js\", \"javascript\"],\n [\"pg\", \"postgres\", \"postgresql\"],\n [\"err\", \"error\", \"errors\"],\n [\"api\", \"endpoint\", \"endpoints\"],\n [\"ci\", \"continuous-integration\"],\n [\"cd\", \"continuous-deployment\"],\n [\"test\", \"testing\", \"tests\"],\n [\"doc\", \"documentation\", \"docs\"],\n [\"infra\", \"infrastructure\"],\n [\"deploy\", \"deployment\", \"deploying\"],\n [\"cache\", \"caching\", \"cached\"],\n [\"log\", \"logging\", \"logs\"],\n [\"monitor\", \"monitoring\"],\n [\"observe\", \"observability\"],\n [\"sec\", \"security\", \"secure\"],\n [\"validate\", \"validation\", \"validating\"],\n [\"migrate\", \"migration\", \"migrations\"],\n [\"debug\", \"debugging\"],\n [\"container\", \"containerization\", \"docker\"],\n [\"crash\", \"crashloop\", \"crashloopbackoff\"],\n [\"webhook\", \"webhooks\", \"callback\"],\n [\"middleware\", \"mw\"],\n [\"paginate\", \"pagination\"],\n [\"serialize\", \"serialization\"],\n [\"encrypt\", \"encryption\"],\n [\"hash\", \"hashing\"],\n];\n\nconst synonymMap = new Map<string, Set<string>>();\n\nfor (const group of SYNONYM_GROUPS) {\n const stemmed = group.map(t => stem(t.toLowerCase()));\n for (const s of stemmed) {\n if (!synonymMap.has(s)) synonymMap.set(s, new Set());\n for (const other of stemmed) {\n if (other !== s) synonymMap.get(s)!.add(other);\n }\n }\n}\n\nexport function getSynonyms(stemmedTerm: string): string[] {\n const syns = synonymMap.get(stemmedTerm);\n return syns ? [...syns] : [];\n}\n","import type { CompressedObservation } from \"../types.js\";\nimport { getSearchResultLayer, isSearchResultLayer, matchesSearchLayer, type SearchLayer, type SearchResultLayer } from \"./search-layer.js\";\nimport { stem } from \"./stemmer.js\";\nimport { getSynonyms } from \"./synonyms.js\";\nimport { segmentCjk, hasCjk } from \"./cjk-segmenter.js\";\n\ninterface IndexEntry {\n obsId: string;\n sessionId: string;\n termCount: number;\n layer: SearchResultLayer;\n timestamp?: string;\n}\n\nconst USER_PROMPT_TERM_CAP = 2000;\nconst ASSISTANT_RESPONSE_TERM_CAP = 1000;\nconst TOOL_OUTPUT_TERM_CAP = 1000;\n\nexport interface SearchIndexRevision {\n isCurrent(): boolean;\n release(): void;\n}\n\nexport class SearchIndex {\n private entries: Map<string, IndexEntry> = new Map();\n private invertedIndex: Map<string, Set<string>> = new Map();\n private docTermCounts: Map<string, Map<string, number>> = new Map();\n private totalDocLength = 0;\n private sortedTerms: string[] | null = null;\n private revisionGeneration: object = {};\n private absentRevisions = new Map<string, { token: object; readers: number }>();\n\n private readonly k1 = 1.2;\n private readonly b = 0.75;\n\n add(obs: CompressedObservation, layer: SearchResultLayer = \"observation\"): void {\n this.invalidateAbsentRevision(obs.id);\n if (this.entries.has(obs.id)) this.remove(obs.id);\n const terms = this.extractTerms(obs);\n const termFreq = new Map<string, number>();\n let termCount = 0;\n\n for (const term of terms) {\n termFreq.set(term, (termFreq.get(term) || 0) + 1);\n termCount++;\n }\n\n this.entries.set(obs.id, {\n obsId: obs.id,\n sessionId: obs.sessionId,\n termCount,\n layer,\n timestamp: obs.timestamp,\n });\n this.docTermCounts.set(obs.id, termFreq);\n this.totalDocLength += termCount;\n\n for (const term of termFreq.keys()) {\n if (!this.invertedIndex.has(term)) {\n this.invertedIndex.set(term, new Set());\n }\n this.invertedIndex.get(term)!.add(obs.id);\n }\n\n this.sortedTerms = null;\n }\n\n watchRevision(id: string): SearchIndexRevision {\n const generation = this.revisionGeneration;\n const entry = this.entries.get(id);\n if (entry) {\n return {\n isCurrent: () => this.revisionGeneration === generation && this.entries.get(id) === entry,\n release: () => {},\n };\n }\n // Only absent IDs need a lease: retaining deleted-ID tombstones would grow\n // forever, while one shared absent epoch would cancel unrelated writes.\n let slot = this.absentRevisions.get(id);\n if (!slot) {\n slot = { token: {}, readers: 0 };\n this.absentRevisions.set(id, slot);\n }\n slot.readers++;\n const token = slot.token;\n let released = false;\n return {\n isCurrent: () => !released && this.revisionGeneration === generation &&\n this.entries.get(id) === undefined && slot.token === token,\n release: () => {\n if (released) return;\n released = true;\n slot.readers--;\n if (slot.readers === 0 && this.absentRevisions.get(id) === slot) this.absentRevisions.delete(id);\n },\n };\n }\n\n private invalidateAbsentRevision(id: string): void {\n const slot = this.absentRevisions.get(id);\n if (slot) slot.token = {};\n }\n\n invalidateRevision(id: string): void {\n this.invalidateAbsentRevision(id);\n const entry = this.entries.get(id);\n if (entry) this.entries.set(id, { ...entry });\n }\n\n has(id: string): boolean {\n return this.entries.has(id);\n }\n\n sessionOf(id: string): string | undefined {\n return this.entries.get(id)?.sessionId;\n }\n\n layerOf(id: string): SearchResultLayer | undefined {\n return this.entries.get(id)?.layer;\n }\n\n countMissingDocuments(hasDocument: (id: string) => boolean, since?: string | null, activeIds?: ReadonlySet<string>): number {\n const cutoff = typeof since === \"string\" ? Date.parse(since) : Number.NaN;\n let missing = 0;\n for (const entry of this.entries.values()) {\n if (entry.layer !== \"observation\" && entry.layer !== \"memory\") continue;\n if (Number.isFinite(cutoff) && !(Date.parse(entry.timestamp ?? \"\") > cutoff) && !activeIds?.has(entry.obsId)) continue;\n if (!hasDocument(entry.obsId)) missing++;\n }\n return missing;\n }\n\n observationCountsBySession(): Map<string, number> {\n const counts = new Map<string, number>();\n for (const entry of this.entries.values()) {\n if (entry.layer !== \"observation\") continue;\n counts.set(entry.sessionId, (counts.get(entry.sessionId) ?? 0) + 1);\n }\n return counts;\n }\n\n documentKindCounts(): { memories: number; lessons: number } {\n let memories = 0;\n let lessons = 0;\n for (const entry of this.entries.values()) {\n if (entry.layer === \"memory\") memories++;\n else if (entry.layer === \"lesson\") lessons++;\n }\n return { memories, lessons };\n }\n\n remove(id: string): void {\n this.invalidateAbsentRevision(id);\n const entry = this.entries.get(id);\n if (!entry) return;\n\n const termFreq = this.docTermCounts.get(id);\n if (termFreq) {\n for (const term of termFreq.keys()) {\n const postingList = this.invertedIndex.get(term);\n if (postingList) {\n postingList.delete(id);\n if (postingList.size === 0) {\n this.invertedIndex.delete(term);\n }\n }\n }\n this.docTermCounts.delete(id);\n }\n\n this.totalDocLength = Math.max(0, this.totalDocLength - entry.termCount);\n this.entries.delete(id);\n this.sortedTerms = null;\n }\n\n search(\n query: string,\n limit = 20,\n targetLayer: SearchLayer = \"all\",\n ): Array<{ obsId: string; sessionId: string; score: number }> {\n const rawTerms = this.tokenize(query.toLowerCase());\n if (rawTerms.length === 0) return [];\n\n const N = this.entries.size;\n if (N === 0) return [];\n const avgDocLen = this.totalDocLength / N;\n\n const queryTerms: Array<{ term: string; weight: number }> = [];\n const seen = new Set<string>();\n for (const term of rawTerms) {\n if (!seen.has(term)) {\n seen.add(term);\n queryTerms.push({ term, weight: 1.0 });\n }\n for (const syn of getSynonyms(term)) {\n if (!seen.has(syn)) {\n seen.add(syn);\n queryTerms.push({ term: syn, weight: 0.7 });\n }\n }\n }\n\n const scores = new Map<string, number>();\n const sorted = this.getSortedTerms();\n\n for (const { term, weight } of queryTerms) {\n const matchingDocs = this.invertedIndex.get(term);\n if (matchingDocs) {\n const df = matchingDocs.size;\n const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);\n\n for (const obsId of matchingDocs) {\n const entry = this.entries.get(obsId)!;\n if (!matchesSearchLayer(obsId, entry.sessionId, targetLayer, entry.layer)) continue;\n const docTerms = this.docTermCounts.get(obsId);\n const tf = docTerms?.get(term) || 0;\n const docLen = entry.termCount;\n\n const numerator = tf * (this.k1 + 1);\n const denominator =\n tf + this.k1 * (1 - this.b + this.b * (docLen / avgDocLen));\n const bm25Score = idf * (numerator / denominator) * weight;\n\n scores.set(obsId, (scores.get(obsId) || 0) + bm25Score);\n }\n }\n\n const prefixScores = new Map<string, number>();\n const startIdx = this.lowerBound(sorted, term);\n for (let si = startIdx; si < sorted.length; si++) {\n const indexTerm = sorted[si];\n if (!indexTerm.startsWith(term)) break;\n if (indexTerm === term) continue;\n\n const obsIds = this.invertedIndex.get(indexTerm)!;\n const prefixDf = obsIds.size;\n const prefixIdf =\n Math.log((N - prefixDf + 0.5) / (prefixDf + 0.5) + 1) * 0.5;\n for (const obsId of obsIds) {\n if (matchingDocs?.has(obsId)) continue;\n const entry = this.entries.get(obsId)!;\n if (!matchesSearchLayer(obsId, entry.sessionId, targetLayer, entry.layer)) continue;\n const docTerms = this.docTermCounts.get(obsId);\n const tf = docTerms?.get(indexTerm) || 0;\n const docLen = entry.termCount;\n const numerator = tf * (this.k1 + 1);\n const denominator =\n tf + this.k1 * (1 - this.b + this.b * (docLen / avgDocLen));\n const score = prefixIdf * (numerator / denominator) * weight;\n prefixScores.set(obsId, Math.max(prefixScores.get(obsId) ?? 0, score));\n }\n }\n for (const [obsId, score] of prefixScores) {\n scores.set(obsId, (scores.get(obsId) ?? 0) + score);\n }\n }\n\n return Array.from(scores.entries())\n .map(([obsId, score]) => {\n const entry = this.entries.get(obsId)!;\n return { obsId, sessionId: entry.sessionId, score };\n })\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n }\n\n get size(): number {\n return this.entries.size;\n }\n\n clear(): void {\n this.revisionGeneration = {};\n this.absentRevisions.clear();\n this.entries.clear();\n this.invertedIndex.clear();\n this.docTermCounts.clear();\n this.totalDocLength = 0;\n this.sortedTerms = null;\n }\n\n restoreFrom(other: SearchIndex): void {\n this.revisionGeneration = {};\n this.absentRevisions.clear();\n this.entries = new Map(\n Array.from(other.entries.entries()).map(([k, v]) => [k, { ...v }]),\n );\n this.invertedIndex = new Map(\n Array.from(other.invertedIndex.entries()).map(([k, v]) => [\n k,\n new Set(v),\n ]),\n );\n this.docTermCounts = new Map(\n Array.from(other.docTermCounts.entries()).map(([k, v]) => [\n k,\n new Map(v),\n ]),\n );\n this.totalDocLength = other.totalDocLength;\n this.sortedTerms = null;\n }\n\n serialize(): string {\n const entries = Array.from(this.entries.entries());\n const inverted = Array.from(this.invertedIndex.entries()).map(\n ([term, ids]) => [term, Array.from(ids)] as [string, string[]],\n );\n const docTerms = Array.from(this.docTermCounts.entries()).map(\n ([id, counts]) =>\n [id, Array.from(counts.entries())] as [string, [string, number][]],\n );\n return JSON.stringify({\n v: 3,\n entries,\n inverted,\n docTerms,\n totalDocLength: this.totalDocLength,\n });\n }\n\n static deserialize(json: string): SearchIndex {\n try {\n const idx = new SearchIndex();\n const data = JSON.parse(json);\n if (!data?.entries || !data?.inverted || !data?.docTerms) return idx;\n for (const [key, val] of data.entries) {\n idx.entries.set(key, {\n ...val,\n layer: isSearchResultLayer(val.layer) ? val.layer : getSearchResultLayer(key, val.sessionId),\n });\n }\n for (const [term, ids] of data.inverted) {\n idx.invertedIndex.set(term, new Set(ids));\n }\n for (const [id, counts] of data.docTerms) {\n idx.docTermCounts.set(id, new Map(counts));\n }\n const rawLen = Number(data.totalDocLength);\n idx.totalDocLength =\n Number.isFinite(rawLen) && rawLen >= 0 ? Math.floor(rawLen) : 0;\n return idx;\n } catch {\n return new SearchIndex();\n }\n }\n\n private extractTerms(obs: CompressedObservation): string[] {\n const parts = [\n obs.title,\n obs.subtitle || \"\",\n obs.narrative,\n ...obs.facts,\n ...obs.concepts,\n ...obs.files,\n obs.type,\n ];\n if (obs.source?.userPrompt) {\n parts.push(obs.source.userPrompt.slice(0, USER_PROMPT_TERM_CAP));\n }\n if (obs.source?.assistantResponse) {\n parts.push(\n obs.source.assistantResponse.slice(0, ASSISTANT_RESPONSE_TERM_CAP),\n );\n }\n if (\n obs.source?.toolName === \"conversation\" &&\n typeof obs.source.toolOutput === \"string\"\n ) {\n parts.push(obs.source.toolOutput.slice(0, TOOL_OUTPUT_TERM_CAP));\n }\n return this.tokenize(parts.join(\" \").toLowerCase());\n }\n\n private tokenize(text: string): string[] {\n const cleaned = text.replace(/[^\\p{L}\\p{N}\\s/.\\\\-_]/gu, \" \");\n const out: string[] = [];\n for (const raw of cleaned.split(/\\s+/)) {\n if (raw.length < 2) continue;\n if (hasCjk(raw)) {\n for (const seg of segmentCjk(raw)) {\n if (seg.length >= 1) out.push(seg);\n }\n } else {\n out.push(stem(raw));\n }\n }\n return out;\n }\n\n private getSortedTerms(): string[] {\n if (!this.sortedTerms) {\n this.sortedTerms = Array.from(this.invertedIndex.keys()).sort();\n }\n return this.sortedTerms;\n }\n\n private lowerBound(arr: string[], target: string): number {\n let lo = 0;\n let hi = arr.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if (arr[mid] < target) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n}\n","import { KV } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { logger } from \"../logger.js\";\n\nconst RECENT_CAP = 20;\n\nexport interface AccessLog {\n memoryId: string;\n count: number;\n lastAt: string;\n recent: number[];\n}\n\nexport function emptyAccessLog(memoryId: string): AccessLog {\n return { memoryId, count: 0, lastAt: \"\", recent: [] };\n}\n\nexport function normalizeAccessLog(raw: unknown): AccessLog {\n const r = (raw ?? {}) as Partial<AccessLog>;\n const rawCount =\n typeof r.count === \"number\" && Number.isFinite(r.count) ? r.count : 0;\n const count = Math.max(0, Math.floor(rawCount));\n const rawRecent = Array.isArray(r.recent)\n ? r.recent.filter(\n (x): x is number => typeof x === \"number\" && Number.isFinite(x),\n )\n : [];\n const recent =\n rawRecent.length > RECENT_CAP ? rawRecent.slice(-RECENT_CAP) : rawRecent;\n return {\n memoryId: typeof r.memoryId === \"string\" ? r.memoryId : \"\",\n count: Math.max(count, recent.length),\n lastAt: typeof r.lastAt === \"string\" ? r.lastAt : \"\",\n recent,\n };\n}\n\nexport async function getAccessLog(\n kv: StateKV,\n memoryId: string,\n): Promise<AccessLog> {\n try {\n const raw = await kv.get<AccessLog>(KV.accessLog, memoryId);\n if (!raw) return emptyAccessLog(memoryId);\n const normalized = normalizeAccessLog(raw);\n if (!normalized.memoryId) normalized.memoryId = memoryId;\n return normalized;\n } catch {\n return emptyAccessLog(memoryId);\n }\n}\n\nexport async function recordAccess(\n kv: StateKV,\n memoryId: string,\n timestampMs?: number,\n): Promise<void> {\n if (!memoryId) return;\n const ts = timestampMs ?? Date.now();\n try {\n await withKeyedLock(`mem:access:${memoryId}`, async () => {\n const existing = await getAccessLog(kv, memoryId);\n existing.count += 1;\n existing.lastAt = new Date(ts).toISOString();\n existing.recent.push(ts);\n if (existing.recent.length > RECENT_CAP) {\n existing.recent = existing.recent.slice(-RECENT_CAP);\n }\n await kv.set(KV.accessLog, memoryId, existing);\n });\n } catch (err) {\n try {\n logger.warn(\"recordAccess failed\", {\n memoryId,\n error: err instanceof Error ? err.message : String(err),\n });\n } catch {}\n }\n}\n\nexport async function recordAccessBatch(\n kv: StateKV,\n memoryIds: string[],\n timestampMs?: number,\n): Promise<void> {\n if (!memoryIds || memoryIds.length === 0) return;\n const ts = timestampMs ?? Date.now();\n const unique = Array.from(new Set(memoryIds.filter(Boolean)));\n await Promise.allSettled(unique.map((id) => recordAccess(kv, id, ts)));\n}\n\nexport async function deleteAccessLog(\n kv: StateKV,\n memoryId: string,\n): Promise<void> {\n if (!memoryId) return;\n try {\n await withKeyedLock(`mem:access:${memoryId}`, async () => {\n await kv.delete(KV.accessLog, memoryId);\n });\n } catch {}\n}\n\n","import type { CompressedObservation, HookType, ObservationSource, RawObservation } from \"../types.js\";\nimport { stripPrivateData } from \"./privacy.js\";\n\nexport const OBSERVATION_SOURCE_MAX_BYTES = 16 * 1024;\n\nfunction sanitize(value: unknown): unknown {\n if (typeof value === \"string\") return stripPrivateData(value);\n if (Array.isArray(value)) return value.map(sanitize);\n if (value && typeof value === \"object\") {\n return Object.fromEntries(Object.entries(value).map(([key, entry]) => [stripPrivateData(key), sanitize(entry)]));\n }\n return value;\n}\n\nfunction bytes(value: unknown): number {\n return Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nfunction prefixWithinBytes(text: string, budget: number): string {\n let low = 0;\n let high = text.length;\n while (low < high) {\n const mid = Math.ceil((low + high) / 2);\n if (bytes(text.slice(0, mid)) <= budget) low = mid;\n else high = mid - 1;\n }\n if (low > 0 && /[\\uD800-\\uDBFF]/.test(text[low - 1])) low--;\n return text.slice(0, low);\n}\n\nexport function createObservationSource(\n raw: RawObservation,\n previous?: Pick<ObservationSource, \"originalBytes\" | \"truncated\">,\n maxBytes = OBSERVATION_SOURCE_MAX_BYTES,\n): ObservationSource {\n const fields: Record<string, unknown> = {\n toolName: raw.toolName,\n toolInput: raw.toolInput,\n toolOutput: raw.toolOutput,\n userPrompt: raw.userPrompt,\n assistantResponse: raw.assistantResponse,\n };\n if (Object.values(fields).every((value) => value === undefined)) fields.payload = raw.raw;\n const retained = sanitize(fields) as Record<string, unknown>;\n const hookType = prefixWithinBytes(stripPrivateData(raw.hookType), 128) as HookType;\n const dropped = raw.assistantResponseBytes === undefined\n ? 0\n : Math.max(0, raw.assistantResponseBytes - Buffer.byteLength(raw.assistantResponse ?? \"\", \"utf8\"));\n const originalBytes = Math.max(bytes({ hookType: raw.hookType, ...retained }) + dropped, previous?.originalBytes ?? 0);\n const truncated = previous?.truncated === true || hookType !== raw.hookType || dropped > 0;\n const full = { hookType, originalBytes, truncated, ...retained };\n if (bytes(full) <= maxBytes) return full;\n\n const bounded: ObservationSource = { hookType, originalBytes, truncated: true };\n for (const [key, value] of Object.entries(retained)) {\n if (value === undefined) continue;\n if (bytes({ ...bounded, [key]: value }) <= maxBytes) {\n Object.assign(bounded, { [key]: value });\n continue;\n }\n const budget = maxBytes - bytes({ ...bounded, [key]: \"\" }) + 2;\n if (budget >= 2) {\n const text = typeof value === \"string\" ? value : JSON.stringify(value);\n Object.assign(bounded, { [key]: prefixWithinBytes(text, budget) });\n }\n break;\n }\n return bounded;\n}\n\nexport function normalizeObservationSource(value: unknown, maxBytes = OBSERVATION_SOURCE_MAX_BYTES): ObservationSource | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n const source = value as Record<string, unknown>;\n if (typeof source.hookType !== \"string\" || !source.hookType) return undefined;\n return createObservationSource({\n id: \"\", sessionId: \"\", timestamp: \"\",\n hookType: source.hookType as HookType,\n toolName: typeof source.toolName === \"string\" ? source.toolName : undefined,\n toolInput: source.toolInput,\n toolOutput: source.toolOutput,\n userPrompt: typeof source.userPrompt === \"string\" ? source.userPrompt : undefined,\n assistantResponse: typeof source.assistantResponse === \"string\" ? source.assistantResponse : undefined,\n raw: source.payload,\n }, {\n originalBytes: Number.isSafeInteger(source.originalBytes) && (source.originalBytes as number) >= 0\n ? source.originalBytes as number : 0,\n truncated: source.truncated === true,\n }, maxBytes);\n}\n\nexport function withoutObservationSource<T extends CompressedObservation>(observation: T): Omit<T, \"source\"> {\n const { source: _source, ...summary } = observation;\n return summary;\n}\n\nexport function rawFromObservationSource(observation: CompressedObservation): RawObservation | null {\n const source = observation.source;\n if (!source || typeof source.hookType !== \"string\") return null;\n return {\n id: observation.id,\n sessionId: observation.sessionId,\n timestamp: observation.timestamp,\n hookType: source.hookType,\n toolName: source.toolName,\n toolInput: source.toolInput,\n toolOutput: source.toolOutput,\n userPrompt: source.userPrompt,\n assistantResponse: source.assistantResponse,\n raw: source.payload ?? {},\n modality: observation.modality,\n imageData: observation.imageRef ?? observation.imageData,\n agentId: observation.agentId,\n origin: observation.origin,\n };\n}\n","import type { IIIClient } from 'iii-sdk'\nimport type { GraphObservationAuthorization } from \"./graph-retrieval.js\";\nimport type { HybridSearchRequest } from \"../state/hybrid-search.js\";\nimport type { IndexPersistenceStatus } from \"../state/index-persistence.js\";\nimport type { CompressedObservation, Memory, SearchResult, Session } from '../types.js'\nimport { KV } from '../state/schema.js'\nimport { StateKV } from '../state/kv.js'\nimport { getSearchResultLayer, isSearchLayer, matchesSearchLayer, type SearchLayer, type SearchResultLayer } from \"../state/search-layer.js\";\nimport { SearchIndex, type SearchIndexRevision } from '../state/search-index.js'\nimport { VectorIndex } from '../state/vector-index.js'\nimport type { EmbeddingProvider } from '../types.js'\nimport { memoryToObservation, observationEmbedText } from '../state/memory-utils.js'\nimport { buildRecallResponse, type RecallFormat } from \"./recall-response.js\";\nimport { recordAccessBatch } from './access-tracker.js'\nimport { logger } from \"../logger.js\";\nimport { withoutObservationSource } from \"./observation-source.js\";\nimport {\n getAgentId,\n getVectorBackfillMax,\n isAgentScopeIsolated,\n isVectorBackfillAllEnabled,\n} from \"../config.js\";\n\nlet index: SearchIndex | null = null\nlet vectorIndex: VectorIndex | null = null\nlet currentEmbeddingProvider: EmbeddingProvider | null = null\n\n// Hybrid ranking hook for mem::search. Wired by index.ts once the\n// hybrid searcher exists (it is constructed after this module's\n// registration runs). The graph stream can retrieve evidence even when\n// embeddings are disabled or the vector index is still empty.\ntype HybridRanker = (\n query: string,\n limit: number,\n targetLayer?: SearchLayer,\n authorizeGraph?: GraphObservationAuthorization,\n request?: HybridSearchRequest,\n) => Promise<Array<{ observation: CompressedObservation; sessionId: string; combinedScore: number; layer?: SearchResultLayer }>>\nlet hybridRanker: HybridRanker | null = null\n\nexport function setHybridRanker(fn: HybridRanker | null): void {\n hybridRanker = fn\n}\n\n// Dedupes the lazy cold-start rebuild kicked off from the mem::search\n// request path. A full rebuildIndex walks every observation across every\n// session, so N concurrent queries against an empty index would each\n// launch their own rebuild and saturate the engine invocation pool. The\n// first query with an empty index starts one rebuild and shares its\n// promise; concurrent queries await the same rebuild instead of spawning\n// duplicates. The boot-time rebuild in index.ts is unaffected.\nlet rebuildPromise: Promise<number> | null = null\n\nlet memoryIndexReady = false\nexport function isMemoryIndexReady(): boolean {\n return memoryIndexReady\n}\n\nlet bm25RebuildIncomplete = false\nexport function isBm25RebuildIncomplete(): boolean {\n return bm25RebuildIncomplete\n}\n\nlet keywordRebuildPending = false\nlet keywordRebuildsRunning = 0\nlet keywordRebuildEpoch = 0\nexport function getKeywordRebuildEpoch(): number {\n return keywordRebuildEpoch\n}\nexport function markKeywordRebuildPending(): void {\n keywordRebuildPending = true\n}\nexport function isKeywordRebuildInProgress(): boolean {\n return keywordRebuildPending || keywordRebuildsRunning > 0\n}\n\nlet pendingVectorBackfill = 0\nexport type VectorBackfillState = \"idle\" | \"running\" | \"paused\" | \"waiting-for-opt-in\"\nlet vectorBackfillState: VectorBackfillState = \"idle\"\nexport function getVectorBackfillState(): VectorBackfillState {\n return vectorBackfillState\n}\nexport function setVectorBackfillState(state: VectorBackfillState): void {\n vectorBackfillState = state\n}\nexport function getPendingVectorBackfillCount(): number {\n return pendingVectorBackfill\n}\nexport function setPendingVectorBackfillCount(n: number): void {\n pendingVectorBackfill = Math.max(0, n)\n}\n\nexport function getSearchIndex(): SearchIndex {\n if (!index) index = new SearchIndex()\n return index\n}\n\nexport function setVectorIndex(idx: VectorIndex | null): void {\n vectorIndex = idx\n}\n\nexport function getVectorIndex(): VectorIndex | null {\n return vectorIndex\n}\n\nexport function setEmbeddingProvider(provider: EmbeddingProvider | null): void {\n currentEmbeddingProvider = provider\n}\n\nexport function getEmbeddingProvider(): EmbeddingProvider | null {\n return currentEmbeddingProvider\n}\n\nconst RANK_FUSION_K = 60\n\nexport async function rankMemoryIds(\n query: string,\n limit: number,\n): Promise<{ ids: string[]; mode: \"hybrid\" | \"keyword\" }> {\n const fetchLimit = Math.max(limit * 4, 50)\n const keyword = getSearchIndex()\n .search(query, fetchLimit, \"memory\")\n let semantic: Array<{ obsId: string }> = []\n if (vectorIndex && vectorIndex.size > 0 && currentEmbeddingProvider) {\n try {\n const embedding = await currentEmbeddingProvider.embed(query)\n semantic = vectorIndex\n .search(embedding, fetchLimit, \"memory\", (id) => getSearchIndex().layerOf(id))\n } catch (err) {\n logger.warn(\"memory vector ranking failed, using keyword ranking\", {\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n const scores = new Map<string, number>()\n const addRanks = (hits: Array<{ obsId: string }>) => {\n hits.forEach((hit, rank) => {\n scores.set(hit.obsId, (scores.get(hit.obsId) ?? 0) + 1 / (RANK_FUSION_K + rank + 1))\n })\n }\n addRanks(keyword)\n addRanks(semantic)\n const ids = Array.from(scores.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, limit)\n .map(([id]) => id)\n return { ids, mode: semantic.length > 0 ? \"hybrid\" : \"keyword\" }\n}\n\nexport function vectorIndexRemove(id: string): void {\n getSearchIndex().invalidateRevision(id);\n vectorIndex?.remove(id);\n}\n\n// Persistence sync hook. Without this, index removals only live in\n// memory; a crash/SIGKILL before graceful shutdown reloads a stale\n// snapshot at boot and the deleted entry resurrects in the index.\n// Wired by src/index.ts after IndexPersistence is constructed; no-op\n// until then so unit tests that exercise the delete paths in\n// isolation don't need to wire persistence.\ntype IndexPersistenceHook = {\n scheduleSave: () => void;\n save: () => Promise<void>;\n status?: () => IndexPersistenceStatus;\n};\n\nlet indexPersistence: IndexPersistenceHook | null = null;\n\nexport function setIndexPersistence(p: IndexPersistenceHook | null): void {\n indexPersistence = p;\n}\n\nexport function getIndexPersistenceStatus(): IndexPersistenceStatus | null {\n return indexPersistence?.status?.() ?? null;\n}\n\nexport function scheduleIndexSave(): void {\n indexPersistence?.scheduleSave();\n}\n\n// Synchronous flush variant for delete paths. The debounced\n// scheduleSave is fine for adds (chatty), but a hard process exit\n// inside the 5s debounce window would lose deletes and resurrect\n// removed entries on next boot. Deletes are infrequent enough that\n// awaiting a single write per operation is acceptable. save() catches\n// its own errors via IndexPersistence.logFailure, so this resolves\n// even when persistence fails — callers must not treat a failed\n// flush as a fatal error on the delete itself (the KV delete already\n// committed before this is invoked).\nexport async function flushIndexSave(): Promise<void> {\n await indexPersistence?.save();\n}\n\n// Hard cap on embedding input length. Most providers cap input around\n// 8k tokens (~32k chars at ~4 chars/token). Truncate defensively so a\n// huge memory.content can't 400 the embed call or blow context budget\n// on a single doc. 16k chars ≈ 4k tokens, safely under every provider.\nconst EMBED_MAX_CHARS = 16_000\n\nexport function clipEmbedInput(text: string): string {\n if (text.length <= EMBED_MAX_CHARS) return text\n return text.slice(0, EMBED_MAX_CHARS)\n}\n\nexport async function vectorIndexAddGuarded(\n id: string,\n sessionId: string,\n text: string,\n context: { kind: \"memory\" | \"observation\" | \"synthetic\"; logId: string },\n commit?: (embedding: Float32Array, isCurrent: () => boolean) => Promise<boolean> | boolean,\n): Promise<boolean> {\n const vi = vectorIndex\n const ep = currentEmbeddingProvider\n if (!vi || !ep) return false\n const keyword = getSearchIndex()\n const revision = keyword.watchRevision(id)\n const previous = vi.get(id)\n const isCurrent = () => vectorIndex === vi && currentEmbeddingProvider === ep &&\n revision.isCurrent() && vi.get(id) === previous\n try {\n let embedding: Float32Array\n try {\n embedding = await ep.embed(clipEmbedInput(text))\n } catch (err) {\n logger.warn(\"vector-index add: embed failed — skipping\", {\n kind: context.kind,\n id: context.logId,\n provider: ep.name,\n error: err instanceof Error ? err.message : String(err),\n })\n return false\n }\n if (!isCurrent()) return false\n if (embedding.length !== ep.dimensions) {\n logger.warn(\"vector-index add: dimension mismatch — skipping\", {\n kind: context.kind,\n id: context.logId,\n provider: ep.name,\n expected: ep.dimensions,\n received: embedding.length,\n })\n return false\n }\n if (commit) {\n try {\n const committed = await commit(embedding, isCurrent)\n if (committed) scheduleIndexSave()\n return committed\n } catch (err) {\n logger.warn(\"vector-index add: commit failed — skipping\", {\n kind: context.kind,\n id: context.logId,\n provider: ep.name,\n error: err instanceof Error ? err.message : String(err),\n })\n return false\n }\n }\n vi.add(id, sessionId, embedding)\n scheduleIndexSave()\n return true\n } finally {\n revision.release()\n }\n}\n\n// Batched variant: calls EmbeddingProvider.embedBatch ONCE for the whole\n// batch, then writes each resulting vector. Use this for bulk paths\n// (rebuildIndex, future bulk-add APIs) where per-item serial awaits\n// dominate wallclock. A batch of N has roughly the latency of a single\n// embed (network + GPU setup amortized), so backfilling a 500k-obs\n// corpus drops from days to hours on a per-batch endpoint like vLLM.\n//\n// Per-item failure shape:\n// - whole-batch network/provider error → all skipped, single warn line\n// - per-item dimension mismatch → that item skipped, others continue\nexport async function vectorIndexAddBatchGuarded(\n items: VectorBackfillJob[],\n): Promise<{ ok: number; fail: number; skipped: number }> {\n const vi = vectorIndex\n const ep = currentEmbeddingProvider\n if (!vi || !ep || items.length === 0) return { ok: 0, fail: 0, skipped: 0 }\n const keyword = getSearchIndex()\n const guarded = items.map((item) => ({ item, revision: item.revision ?? keyword.watchRevision(item.id), previous: vi.get(item.id) }))\n const isCurrent = (job: typeof guarded[number]) => vectorIndex === vi && currentEmbeddingProvider === ep &&\n job.revision.isCurrent() && vi.get(job.item.id) === job.previous\n try {\n const active = guarded.filter(isCurrent)\n let skipped = items.length - active.length\n if (!active.length) return { ok: 0, fail: 0, skipped }\n const failedBatch = () => {\n const fail = active.filter(isCurrent).length\n return { ok: 0, fail, skipped: items.length - fail }\n }\n\n let embeddings: Float32Array[]\n try {\n embeddings = await ep.embedBatch(active.map(({ item }) => clipEmbedInput(item.text)))\n } catch (err) {\n logger.warn(\"vector-index add batch: embed failed — skipping batch\", {\n batchSize: active.length,\n provider: ep.name,\n error: err instanceof Error ? err.message : String(err),\n })\n return failedBatch()\n }\n if (embeddings.length !== active.length) {\n logger.warn(\"vector-index add batch: provider returned wrong length — skipping batch\", {\n batchSize: active.length, returned: embeddings.length, provider: ep.name,\n })\n return failedBatch()\n }\n\n let ok = 0\n let fail = 0\n for (let i = 0; i < active.length; i++) {\n const job = active[i]\n if (!isCurrent(job)) { skipped++; continue }\n const item = job.item\n const embedding = embeddings[i]\n if (embedding.length !== ep.dimensions) {\n logger.warn(\"vector-index add batch: dimension mismatch — skipping item\", {\n kind: item.context.kind, id: item.context.logId, provider: ep.name,\n expected: ep.dimensions, received: embedding.length,\n })\n fail++\n continue\n }\n try {\n vi.add(item.id, item.sessionId, embedding)\n ok++\n } catch (err) {\n logger.warn(\"vector-index add batch: index write failed — skipping item\", {\n kind: item.context.kind, id: item.context.logId,\n error: err instanceof Error ? err.message : String(err),\n })\n fail++\n }\n }\n return { ok, fail, skipped }\n } finally {\n for (const job of guarded) if (!job.item.revision) job.revision.release()\n }\n}\n\n// Embed-batch size for rebuild. Each item is one /v1/embeddings call's\n// `input` array element; the provider sees the whole batch as one HTTP\n// round-trip. 32 fits comfortably under typical per-request token budgets\n// (32 × ~110 tok/item ≈ 3.5k tokens) and gets close to per-call\n// throughput for GPU-backed endpoints (vLLM, Triton, etc.). Override via\n// REBUILD_EMBED_BATCH_SIZE for endpoints that prefer smaller/larger\n// batches. Set to 1 to fall back to the legacy per-item path.\nconst DEFAULT_REBUILD_EMBED_BATCH = 32\n\nfunction getRebuildEmbedBatchSize(): number {\n const raw = process.env.REBUILD_EMBED_BATCH_SIZE\n if (!raw) return DEFAULT_REBUILD_EMBED_BATCH\n const n = parseInt(raw, 10)\n return Number.isFinite(n) && n > 0 ? n : DEFAULT_REBUILD_EMBED_BATCH\n}\n\n// Shared BM25 + batched-vector indexing for a set of records. The full\n// rebuild and every import path (export-import, jsonl replay) funnel\n// through this so they index identically and none can silently skip the\n// vector side. It does NOT clear the index — callers that rebuild clear\n// first; importers add. When no embedding provider is configured it skips\n// the vector enqueue entirely, so a keyless install never allocates embed\n// jobs it would immediately discard.\nexport async function indexRecords(\n observations: CompressedObservation[],\n memories: Memory[],\n): Promise<number> {\n const idx = getSearchIndex()\n const vectorEnabled = Boolean(vectorIndex && currentEmbeddingProvider)\n const batchSize = getRebuildEmbedBatchSize()\n const revisions = new Map<Memory | CompressedObservation, SearchIndexRevision>()\n let count = 0\n for (const memory of memories) {\n if (memory.isLatest === false || !memory.title || !memory.content) continue\n idx.add(memoryToObservation(memory), \"memory\")\n if (vectorEnabled) revisions.set(memory, idx.watchRevision(memory.id))\n count++\n }\n for (const obs of observations) {\n if (!obs.title || !obs.narrative) continue\n idx.add(obs)\n if (vectorEnabled) revisions.set(obs, idx.watchRevision(obs.id))\n count++\n }\n if (count > 0) scheduleIndexSave()\n const pending: VectorBackfillJob[] = []\n const flush = async (): Promise<void> => {\n if (pending.length === 0) return\n await vectorIndexAddBatchGuarded(pending)\n pending.length = 0\n }\n const enqueue = async (job: VectorBackfillJob): Promise<void> => {\n pending.push(job)\n if (pending.length >= batchSize) await flush()\n }\n try {\n for (const memory of memories) {\n const revision = revisions.get(memory)\n if (!revision?.isCurrent()) continue\n await enqueue({\n id: memory.id, revision,\n sessionId: memory.sessionIds?.[0] ?? 'memory',\n text: observationEmbedText({ title: memory.title, narrative: memory.content, concepts: memory.concepts }),\n context: { kind: \"memory\", logId: memory.id },\n })\n }\n for (const obs of observations) {\n const revision = revisions.get(obs)\n if (!revision?.isCurrent()) continue\n await enqueue({\n id: obs.id, revision, sessionId: obs.sessionId,\n text: observationEmbedText(obs),\n context: { kind: \"observation\", logId: obs.id },\n })\n }\n await flush()\n if (count > 0 && vectorEnabled) scheduleIndexSave()\n } finally {\n for (const revision of revisions.values()) revision.release()\n }\n return count\n}\n\nexport async function findUnindexedObservations(\n kv: StateKV,\n): Promise<{ sessions: number; missing: CompressedObservation[] }> {\n const idx = getSearchIndex()\n const sessions = await kv.list<Session>(KV.sessions)\n const indexed = idx.observationCountsBySession()\n const missing: CompressedObservation[] = []\n for (const session of sessions) {\n const known = session.observationCount ?? 0\n if (known > 0 && known <= (indexed.get(session.id) ?? 0)) continue\n const observations = await kv.list<CompressedObservation>(KV.observations(session.id))\n for (const obs of observations) {\n if (!obs.title || !obs.narrative || idx.has(obs.id)) continue\n missing.push(obs)\n }\n }\n return { sessions: sessions.length, missing }\n}\n\nexport async function reconcileIndex(kv: StateKV): Promise<number> {\n const idx = getSearchIndex()\n const { missing } = await findUnindexedObservations(kv)\n const stillMissing = missing.filter((obs) => !idx.has(obs.id))\n if (stillMissing.length === 0) return 0\n return indexRecords(stillMissing, [])\n}\n\nexport async function rebuildIndex(kv: StateKV): Promise<number> {\n const idx = getSearchIndex()\n idx.clear()\n memoryIndexReady = false\n\n // BM25 clear above wipes stale doc entries; the vector index has the\n // symmetric concern — memories/observations deleted between runs\n // would leave orphan embeddings here forever. Clear both before the\n // repopulation loops run, so BM25 and vector stay in sync.\n vectorIndex?.clear()\n\n // Memories live in their own KV scope outside per-session observation\n // scopes, so they need a separate walk. Without this, mem::remember\n // entries vanish from BM25 on every restart even after the live-write\n // fix in remember.ts.\n let memories: Memory[] = []\n let memoriesLoaded = false\n try {\n memories = await kv.list<Memory>(KV.memories)\n memoriesLoaded = true\n } catch (err) {\n logger.warn('rebuildIndex: failed to load memories', {\n error: err instanceof Error ? err.message : String(err),\n })\n }\n\n const sessions = await kv.list<Session>(KV.sessions)\n const failedSessions: string[] = []\n // Index each session chunk as it loads instead of accumulating every\n // observation first, so peak memory stays bounded to one chunk.\n let indexed = 0\n for (let batch = 0; batch < sessions.length; batch += 10) {\n const chunk = sessions.slice(batch, batch + 10)\n const results = await Promise.all(\n chunk.map(async (s) => {\n try {\n return await kv.list<CompressedObservation>(KV.observations(s.id))\n } catch {\n failedSessions.push(s.id)\n return [] as CompressedObservation[]\n }\n })\n )\n const chunkObs = results.flat()\n if (chunkObs.length > 0) {\n indexed += await indexRecords(chunkObs, [])\n }\n }\n if (failedSessions.length > 0) {\n logger.warn('rebuildIndex: failed to load observations for sessions', { failedSessions })\n }\n\n indexed += await indexRecords([], memories)\n if (memoriesLoaded) memoryIndexReady = true\n return indexed\n}\n\nexport type VectorBackfillJob = {\n id: string\n revision?: SearchIndexRevision\n sessionId: string\n text: string\n context: { kind: \"memory\" | \"observation\" | \"synthetic\"; logId: string }\n}\n\nconst LIST_RETRY_ATTEMPTS = 8\nconst LIST_RETRY_BASE_MS = 2500\nconst LIST_RETRY_BUDGET_MS = 70_000\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction isStateNotReadyError(err: unknown): boolean {\n const code = (err as { code?: unknown } | null)?.code\n if (code === \"function_not_found\" || code === \"invocation_timeout\" || code === \"timeout\" || code === \"ECONNRESET\" || code === \"ECONNREFUSED\" || code === \"EPIPE\") return true\n const message = err instanceof Error ? err.message : String(err)\n return /function_not_found|Function state::\\w+ not found|timed out|timeout|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EPIPE|socket hang up|connection (?:closed|reset)/i.test(message)\n}\n\nasync function listWithRetry<T>(kv: StateKV, scope: string, label: string, deadline: number): Promise<T[] | null> {\n let lastErr: unknown\n let attempts = 0\n while (attempts < LIST_RETRY_ATTEMPTS) {\n attempts++\n try {\n return await kv.list<T>(scope)\n } catch (err) {\n lastErr = err\n if (!isStateNotReadyError(err)) break\n const remaining = deadline - performance.now()\n const wait = LIST_RETRY_BASE_MS * attempts\n if (attempts >= LIST_RETRY_ATTEMPTS || wait >= remaining) break\n await delay(wait)\n }\n }\n logger.warn(`${label}: failed to load`, {\n attempts,\n error: lastErr instanceof Error ? lastErr.message : String(lastErr),\n })\n return null\n}\n\ntype KeywordRebuildResult = { documents: number; vectorJobs: VectorBackfillJob[]; fullBackfillPending: number }\n\nexport async function rebuildKeywordIndex(\n kv: StateKV,\n vectorBackfillSince?: string | null,\n): Promise<KeywordRebuildResult> {\n keywordRebuildsRunning++\n try {\n return await runKeywordRebuild(kv, vectorBackfillSince)\n } finally {\n keywordRebuildsRunning--\n keywordRebuildPending = false\n keywordRebuildEpoch++\n }\n}\n\nasync function runKeywordRebuild(\n kv: StateKV,\n vectorBackfillSince?: string | null,\n): Promise<KeywordRebuildResult> {\n const idx = getSearchIndex()\n idx.clear()\n memoryIndexReady = false\n bm25RebuildIncomplete = false\n const vi = vectorIndex\n const backfillEligible = Boolean(vi && currentEmbeddingProvider) && vectorBackfillSince !== undefined\n const wholeStoreBackfill = vectorBackfillSince === null\n const backfillGated = backfillEligible && wholeStoreBackfill && !isVectorBackfillAllEnabled()\n const backfillActive = backfillEligible && !backfillGated\n const cutoff = typeof vectorBackfillSince === 'string' ? Date.parse(vectorBackfillSince) : Number.NaN\n const backfillCap = backfillActive ? getVectorBackfillMax() : 0\n const vectorJobs: VectorBackfillJob[] = []\n let fullBackfillPending = 0\n const consider = (\n id: string,\n sessionId: string,\n text: string,\n timestamp: string | undefined,\n kind: \"memory\" | \"observation\",\n ): void => {\n if (!backfillEligible || vi?.has(id)) return\n if (!Number.isNaN(cutoff) && !(Date.parse(timestamp ?? '') > cutoff)) return\n if (backfillGated || (wholeStoreBackfill && vectorJobs.length >= backfillCap)) {\n fullBackfillPending++\n return\n }\n if (!backfillActive) return\n vectorJobs.push({ id, sessionId, text, revision: idx.watchRevision(id), context: { kind, logId: id } })\n }\n\n let documents = 0\n let memoriesLoaded = false\n const listDeadline = performance.now() + LIST_RETRY_BUDGET_MS\n const memories = await listWithRetry<Memory>(kv, KV.memories, 'rebuildKeywordIndex: memories', listDeadline)\n const sessions = await listWithRetry<Session>(kv, KV.sessions, 'rebuildKeywordIndex: sessions', listDeadline)\n if (memories === null) {\n bm25RebuildIncomplete = true\n } else {\n memoriesLoaded = true\n for (const memory of memories) {\n if (memory.isLatest === false) continue\n if (!memory.title || !memory.content) continue\n idx.add(memoryToObservation(memory), \"memory\")\n consider(memory.id, memory.sessionIds?.[0] ?? 'memory', observationEmbedText({ title: memory.title, narrative: memory.content, concepts: memory.concepts }), memory.createdAt, \"memory\")\n documents++\n }\n }\n\n if (sessions === null) {\n bm25RebuildIncomplete = true\n if (memoriesLoaded) memoryIndexReady = true\n return { documents, vectorJobs, fullBackfillPending }\n }\n const failedSessions: string[] = []\n for (let batch = 0; batch < sessions.length; batch += 10) {\n const chunk = sessions.slice(batch, batch + 10)\n const results = await Promise.all(\n chunk.map(async (s) => {\n try {\n return await kv.list<CompressedObservation>(KV.observations(s.id))\n } catch {\n failedSessions.push(s.id)\n return [] as CompressedObservation[]\n }\n })\n )\n for (const obs of results.flat()) {\n if (!obs.title || !obs.narrative) continue\n idx.add(obs)\n consider(obs.id, obs.sessionId, observationEmbedText(obs), obs.timestamp, \"observation\")\n documents++\n }\n }\n if (failedSessions.length > 0) {\n bm25RebuildIncomplete = true\n logger.warn('rebuildKeywordIndex: failed to load observations for sessions', { failedSessions })\n }\n if (memoriesLoaded) memoryIndexReady = true\n return { documents, vectorJobs, fullBackfillPending }\n}\n\nconst BACKFILL_SAVE_EVERY_BATCHES = 10\nconst VECTOR_BACKLOG_PAUSE_MS = 1000\n\nasync function embedBackfillJobs(\n jobs: VectorBackfillJob[],\n remainingAfter: number,\n): Promise<{ ok: number; fail: number; skipped: number }> {\n const batchSize = getRebuildEmbedBatchSize()\n const initialVector = vectorIndex\n const initialProvider = currentEmbeddingProvider\n let ok = 0\n let fail = 0\n let skipped = 0\n let batchesSinceSave = 0\n setPendingVectorBackfillCount(remainingAfter + jobs.length)\n for (let offset = 0; offset < jobs.length; offset += batchSize) {\n if (vectorIndex !== initialVector || currentEmbeddingProvider !== initialProvider) break\n const result = await vectorIndexAddBatchGuarded(jobs.slice(offset, offset + batchSize))\n ok += result.ok\n fail += result.fail\n skipped += result.skipped\n setPendingVectorBackfillCount(remainingAfter + fail + jobs.length - Math.min(jobs.length, offset + batchSize))\n batchesSinceSave++\n if (batchesSinceSave >= BACKFILL_SAVE_EVERY_BATCHES) {\n await flushIndexSave()\n batchesSinceSave = 0\n }\n }\n if (ok > 0) await flushIndexSave()\n return { ok, fail, skipped }\n}\n\nexport async function backfillVectors(jobs: VectorBackfillJob[]): Promise<number> {\n return (await embedBackfillJobs(jobs, 0)).ok\n}\n\nexport type VectorBacklogResult = { added: number; failed: number; remaining: number; complete: boolean }\n\nexport async function backfillVectorBacklog(\n jobs: VectorBackfillJob[],\n options: { batchSize?: number; pauseMs?: number; remainingAfter?: number; remainingCount?: () => number } = {},\n): Promise<VectorBacklogResult> {\n const batchSize = options.batchSize && options.batchSize > 0 ? options.batchSize : getVectorBackfillMax()\n const pauseMs = options.pauseMs ?? VECTOR_BACKLOG_PAUSE_MS\n const deferred = options.remainingAfter ?? 0\n const initialVector = vectorIndex\n const initialProvider = currentEmbeddingProvider\n const replaced = () => vectorIndex !== initialVector || currentEmbeddingProvider !== initialProvider\n const countRemaining = () => options.remainingCount?.() ?? deferred + jobs.filter((job) =>\n !vectorIndex?.has(job.id) && (!job.revision || getSearchIndex().has(job.id))).length\n const interrupted = (): VectorBacklogResult => {\n const remaining = countRemaining()\n setPendingVectorBackfillCount(remaining)\n return { added, failed, remaining, complete: false }\n }\n let added = 0\n let failed = 0\n for (let offset = 0; offset < jobs.length; offset += batchSize) {\n if (offset > 0 && pauseMs > 0) await delay(pauseMs)\n if (replaced()) return interrupted()\n const after = deferred + failed + Math.max(0, jobs.length - offset - batchSize)\n const batch = jobs.slice(offset, offset + batchSize).filter((job) => !vectorIndex?.has(job.id) && (!job.revision || job.revision.isCurrent()))\n if (batch.length === 0) {\n setPendingVectorBackfillCount(after)\n continue\n }\n const result = await embedBackfillJobs(batch, after)\n added += result.ok\n failed += result.fail\n if (replaced()) return interrupted()\n if (result.ok === 0 && (result.fail > 0 || result.skipped === 0)) {\n const remaining = countRemaining()\n setPendingVectorBackfillCount(remaining)\n return { added, failed, remaining, complete: false }\n }\n }\n const remaining = countRemaining()\n setPendingVectorBackfillCount(remaining)\n return { added, failed, remaining, complete: remaining === 0 }\n}\n\nexport function registerSearchFunction(sdk: IIIClient, kv: StateKV): void {\n sdk.registerFunction(\n 'mem::search',\n async (data: {\n query: string\n limit?: number\n project?: string\n cwd?: string\n format?: string\n token_budget?: number\n targetLayer?: SearchLayer\n agentId?: string\n }) => {\n const idx = getSearchIndex()\n\n // Input validation / normalization.\n if (typeof data?.query !== 'string' || !data.query.trim()) {\n throw new Error('mem::search: query must be a non-empty string')\n }\n const query = data.query.trim()\n if (data.targetLayer !== undefined && !isSearchLayer(data.targetLayer)) {\n throw new Error(\"mem::search: targetLayer must be one of 'all', 'memory', or 'observation'\")\n }\n const targetLayer = data.targetLayer ?? 'all'\n const MAX_LIMIT = 100\n const MAX_CANDIDATES = 1000\n let effectiveLimit = 20\n if (data.limit !== undefined) {\n if (!Number.isInteger(data.limit) || data.limit < 1) {\n throw new Error('mem::search: limit must be a positive integer')\n }\n effectiveLimit = Math.min(data.limit, MAX_LIMIT)\n }\n const projectFilter = typeof data.project === 'string' && data.project.trim().length > 0 ? data.project.trim() : undefined\n const cwdFilter = typeof data.cwd === 'string' && data.cwd.trim().length > 0 ? data.cwd.trim() : undefined\n const isolated = isAgentScopeIsolated();\n const explicitAgentId =\n typeof data.agentId === \"string\" && data.agentId.trim().length > 0\n ? data.agentId.trim()\n : undefined;\n const wildcardAgent = explicitAgentId === \"*\";\n const envAgentId = isolated ? getAgentId() : undefined;\n const filterAgentId = wildcardAgent\n ? undefined\n : explicitAgentId ?? envAgentId;\n if (\n isolated &&\n !wildcardAgent &&\n !explicitAgentId &&\n !envAgentId\n ) {\n throw new Error(\n \"mem::search: AGENTMEMORY_AGENT_SCOPE=isolated is set but no \" +\n \"agent id is available (env AGENT_ID unset and no explicit \" +\n \"agentId in the call). Refusing to read cross-agent rows. \" +\n 'Pass agentId: \"*\" to opt in to a wildcard read.',\n );\n }\n const format = typeof data.format === 'string' ? data.format : 'full'\n if (!['full', 'compact', 'narrative'].includes(format)) {\n throw new Error(\"mem::search: format must be one of 'full', 'compact', or 'narrative'\")\n }\n let tokenBudget: number | undefined\n if (data.token_budget !== undefined) {\n if (!Number.isInteger(data.token_budget) || data.token_budget < 1) {\n throw new Error('mem::search: token_budget must be a positive integer')\n }\n tokenBudget = data.token_budget\n }\n\n if (idx.size === 0) {\n // Share one rebuild across concurrent cold-start queries so they\n // don't each walk the whole corpus and saturate the pool.\n if (!rebuildPromise) {\n rebuildPromise = rebuildKeywordIndex(kv)\n .then((result) => {\n logger.info('Search index rebuilt', { entries: result.documents })\n return result.documents\n })\n .catch((err) => {\n logger.warn('Index rebuild failed', {\n error: err instanceof Error ? err.message : String(err),\n })\n return 0\n })\n .finally(() => {\n rebuildPromise = null\n })\n }\n await rebuildPromise\n }\n\n // When filtering by project/cwd, over-fetch from the index so the\n // post-filter still has a chance of returning `effectiveLimit` results.\n // Over-fetch whenever ANY post-index filter is active. agentId\n // is dropped after the observation/memory is loaded (BM25 index\n // doesn't carry it), so without the over-fetch isolated-mode\n // queries return underfilled pages when same-agent matches\n // rank lower than cross-agent ones in the hybrid score.\n const filtering = !!(projectFilter || cwdFilter || filterAgentId)\n let fetchLimit = filtering ? Math.max(effectiveLimit * 10, 100) : effectiveLimit\n // Hybrid results carry the observation the ranker already loaded,\n // so the load pass below doesn't refetch every record it just\n // enriched.\n let results: Array<{\n obsId: string\n sessionId: string\n score: number\n observation?: CompressedObservation\n layer?: SearchResultLayer\n }>\n const authorizeGraph: GraphObservationAuthorization = async (record, sessionId, read) => {\n if (filterAgentId !== undefined && record.agentId !== filterAgentId) return false\n const memoryProject = \"content\" in record ? record.project : undefined\n if (projectFilter && memoryProject !== undefined && memoryProject !== projectFilter) return false\n if (cwdFilter || (projectFilter && memoryProject === undefined)) {\n const session = await read<Session>(KV.sessions, sessionId)\n if (!session) return false\n if (cwdFilter && session.cwd !== cwdFilter) return false\n if (projectFilter && memoryProject === undefined && session.project !== projectFilter) return false\n }\n return true\n }\n // Resolve session -> project/cwd once per sessionId we touch.\n const sessionCache = new Map<string, Promise<Session | null>>()\n const loadSession = async (sessionId: string): Promise<Session | null> => {\n if (sessionCache.has(sessionId)) return sessionCache.get(sessionId)!\n const pending = kv.get<Session>(KV.sessions, sessionId).then((session) => session ?? null)\n sessionCache.set(sessionId, pending)\n return pending\n }\n\n const memoryProjectCache = new Map<string, string | null>()\n const loadMemoryProject = async (obsId: string): Promise<string | null> => {\n if (memoryProjectCache.has(obsId)) return memoryProjectCache.get(obsId)!\n const mem = await kv.get<Memory>(KV.memories, obsId)\n const proj = mem?.project ?? null\n memoryProjectCache.set(obsId, proj)\n return proj\n }\n\n const observationCache = new Map<string, Promise<{\n observation: CompressedObservation\n layer: SearchResultLayer\n } | null>>()\n const hybridRequest: HybridSearchRequest = {}\n let enriched: SearchResult[] = []\n let useHybridRanker = hybridRanker !== null\n while (true) {\n hybridRequest.candidateCount = undefined\n if (useHybridRanker && hybridRanker) {\n try {\n const hybrid = await hybridRanker(query, fetchLimit, targetLayer, authorizeGraph, hybridRequest)\n results = hybrid.map((r) => ({\n obsId: r.observation.id,\n sessionId: r.sessionId,\n score: r.combinedScore,\n observation: r.observation,\n layer: r.layer,\n }))\n } catch (err) {\n hybridRequest.candidateCount = undefined\n logger.warn(\"hybrid ranking failed\", {\n error: err instanceof Error ? err.message : String(err),\n })\n if (enriched.length > 0) break\n useHybridRanker = false\n results = idx.search(query, fetchLimit, targetLayer)\n }\n } else {\n results = idx.search(query, fetchLimit, targetLayer)\n }\n\n enriched = []\n let batchSize = Math.min(10, effectiveLimit)\n for (let offset = 0; offset < Math.min(results.length, fetchLimit) && enriched.length < effectiveLimit;) {\n const batch = results.slice(offset, Math.min(offset + batchSize, fetchLimit))\n offset += batch.length\n const obsResults = await Promise.all(\n batch.map(async (r) => {\n const layer = r.layer ?? idx.layerOf(r.obsId) ?? getSearchResultLayer(r.obsId, r.sessionId)\n if (!matchesSearchLayer(r.obsId, r.sessionId, targetLayer, layer)) return null\n if (filtering) {\n const memoryProject = projectFilter && layer === \"memory\"\n ? await loadMemoryProject(r.obsId)\n : null\n if (projectFilter && memoryProject !== null && memoryProject !== projectFilter) return null\n const session = projectFilter || cwdFilter ? await loadSession(r.sessionId) : null\n if (projectFilter && memoryProject === null && !session) return null\n if (cwdFilter && layer === \"observation\" && !session) return null\n if (session) {\n if (projectFilter && memoryProject === null && session.project !== projectFilter) return null\n if (cwdFilter && session.cwd !== cwdFilter) return null\n }\n }\n\n const key = JSON.stringify([r.obsId, r.sessionId])\n let pending = observationCache.get(key)\n if (!pending) {\n pending = (async () => {\n if (r.observation) return { observation: r.observation, layer: r.layer ?? idx.layerOf(r.obsId) ?? getSearchResultLayer(r.obsId, r.sessionId) }\n const obs = await kv\n .get<CompressedObservation>(KV.observations(r.sessionId), r.obsId)\n .catch(() => null)\n if (obs) return { observation: obs, layer: \"observation\" as const }\n const mem = await kv\n .get<Memory>(KV.memories, r.obsId)\n .catch(() => null)\n return mem ? { observation: memoryToObservation(mem), layer: \"memory\" as const } : null\n })()\n observationCache.set(key, pending)\n }\n return pending\n })\n )\n for (let i = 0; i < batch.length; i++) {\n const resolved = obsResults[i]\n if (!resolved) continue\n const obs = resolved.observation\n if (!matchesSearchLayer(obs.id, obs.sessionId, targetLayer, resolved.layer)) continue\n if (filterAgentId !== undefined && obs.agentId !== filterAgentId) continue\n if (enriched.length >= effectiveLimit) break\n enriched.push({\n observation: withoutObservationSource(obs),\n layer: resolved.layer,\n score: batch[i].score,\n sessionId: batch[i].sessionId,\n })\n }\n batchSize = Math.min(10, Math.max(effectiveLimit - enriched.length, batchSize * 2))\n }\n if (!filtering || enriched.length >= effectiveLimit || (hybridRequest.candidateCount ?? results.length) < fetchLimit || fetchLimit >= MAX_CANDIDATES) break\n fetchLimit = Math.min(fetchLimit * 2, MAX_CANDIDATES)\n }\n\n const response = buildRecallResponse(enriched, format as RecallFormat, tokenBudget)\n void recordAccessBatch(\n kv,\n enriched.slice(0, response.results.length).map((result) => result.observation.id),\n )\n\n logger.info('Search completed', {\n query,\n results: response.results.length,\n hasProjectFilter: !!projectFilter,\n hasCwdFilter: !!cwdFilter,\n })\n return response\n }\n )\n}\n","import { z } from \"zod\";\n\nconst HookTypeEnum = z.enum([\n \"session_start\",\n \"prompt_submit\",\n \"pre_tool_use\",\n \"post_tool_use\",\n \"post_tool_failure\",\n \"pre_compact\",\n \"subagent_start\",\n \"subagent_stop\",\n \"notification\",\n \"task_completed\",\n \"stop\",\n \"session_end\",\n]);\n\nconst ObservationTypeEnum = z.enum([\n \"file_read\",\n \"file_write\",\n \"file_edit\",\n \"command_run\",\n \"search\",\n \"web_fetch\",\n \"conversation\",\n \"error\",\n \"decision\",\n \"discovery\",\n \"subagent\",\n \"notification\",\n \"task\",\n \"image\",\n \"other\",\n]);\n\nexport const ObserveInputSchema = z.object({\n hookType: HookTypeEnum,\n sessionId: z.string().min(1),\n project: z.string().min(1),\n cwd: z.string().min(1),\n timestamp: z.string().min(1),\n data: z.unknown(),\n});\n\nexport const CompressOutputSchema = z.object({\n type: ObservationTypeEnum,\n title: z.string().min(1).max(120),\n subtitle: z.string().optional(),\n facts: z.array(z.string()).min(1),\n narrative: z.string().min(10),\n concepts: z.array(z.string()),\n files: z.array(z.string()),\n importance: z.number().int().min(1).max(10),\n});\n\nexport const SummaryOutputSchema = z.object({\n title: z.string().min(1),\n narrative: z.string().min(20),\n keyDecisions: z.array(z.string()),\n filesModified: z.array(z.string()),\n concepts: z.array(z.string()),\n});\n\nexport const SearchInputSchema = z.object({\n query: z.string().min(1),\n limit: z.number().int().positive().optional(),\n});\n\nexport const ContextInputSchema = z.object({\n sessionId: z.string().min(1),\n project: z.string().min(1),\n budget: z.number().positive().optional(),\n});\n\nexport const RememberInputSchema = z.object({\n content: z.string().min(1),\n type: z\n .enum([\"pattern\", \"preference\", \"architecture\", \"bug\", \"workflow\", \"fact\"])\n .optional(),\n concepts: z.array(z.string()).optional(),\n files: z.array(z.string()).optional(),\n});\n\nexport const SmartSearchInputSchema = z.object({\n query: z.string().optional(),\n expandIds: z.array(z.string()).optional(),\n limit: z.number().int().positive().optional(),\n});\n\nexport const TimelineInputSchema = z.object({\n anchor: z.string().min(1),\n project: z.string().optional(),\n before: z.number().int().nonnegative().optional(),\n after: z.number().int().nonnegative().optional(),\n});\n\nexport const ProfileInputSchema = z.object({\n project: z.string().min(1),\n refresh: z.boolean().optional(),\n});\n\nexport const RelateInputSchema = z.object({\n sourceId: z.string().min(1),\n targetId: z.string().min(1),\n type: z.enum([\"supersedes\", \"extends\", \"derives\", \"contradicts\", \"related\"]),\n});\n\nexport const EvolveInputSchema = z.object({\n memoryId: z.string().min(1),\n newContent: z.string().min(1),\n newTitle: z.string().optional(),\n});\n\nexport const ExportImportInputSchema = z.object({\n exportData: z.object({\n version: z.union([z.literal(\"0.3.0\"), z.literal(\"0.4.0\")]),\n exportedAt: z.string(),\n sessions: z.array(z.unknown()),\n observations: z.record(z.string(), z.array(z.unknown())),\n memories: z.array(z.unknown()),\n summaries: z.array(z.unknown()),\n profiles: z.array(z.unknown()).optional(),\n }),\n strategy: z.enum([\"merge\", \"replace\", \"skip\"]).optional(),\n});\n","import type { z } from \"zod\";\nimport type { EvalResult } from \"../types.js\";\n\nexport function validateInput<T>(\n schema: z.ZodType<T>,\n data: unknown,\n functionId: string,\n): { valid: true; data: T } | { valid: false; result: EvalResult } {\n const parsed = schema.safeParse(data);\n if (parsed.success) {\n return { valid: true, data: parsed.data };\n }\n return {\n valid: false,\n result: {\n valid: false,\n errors: parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`),\n qualityScore: 0,\n latencyMs: 0,\n functionId,\n },\n };\n}\n\nexport function validateOutput<T>(\n schema: z.ZodType<T>,\n data: unknown,\n functionId: string,\n): { valid: true; data: T } | { valid: false; result: EvalResult } {\n return validateInput(schema, data, functionId);\n}\n","export function scoreCompression(obs: {\n type?: string;\n title?: string;\n facts?: string[];\n narrative?: string;\n concepts?: string[];\n importance?: number;\n}): number {\n let score = 0;\n if (obs.facts && obs.facts.length > 0) score += 25;\n if (obs.facts && obs.facts.length >= 3) score += 10;\n if (obs.narrative && obs.narrative.length >= 20) score += 20;\n if (obs.narrative && obs.narrative.length >= 50) score += 5;\n if (obs.title && obs.title.length >= 5 && obs.title.length <= 120) score += 15;\n if (obs.concepts && obs.concepts.length > 0) score += 15;\n if (obs.importance && obs.importance >= 1 && obs.importance <= 10) score += 10;\n return Math.min(100, score);\n}\n\nexport function scoreSummary(summary: {\n title?: string;\n narrative?: string;\n keyDecisions?: string[];\n filesModified?: string[];\n concepts?: string[];\n}): number {\n let score = 0;\n if (summary.title && summary.title.length >= 5) score += 20;\n if (summary.narrative && summary.narrative.length >= 20) score += 25;\n if (summary.narrative && summary.narrative.length >= 100) score += 5;\n if (summary.keyDecisions && summary.keyDecisions.length > 0) score += 20;\n if (summary.filesModified && summary.filesModified.length > 0) score += 15;\n if (summary.concepts && summary.concepts.length > 0) score += 15;\n return Math.min(100, score);\n}\n\nexport function scoreContextRelevance(\n context: string,\n project: string,\n): number {\n let score = 0;\n if (context.length > 0) score += 20;\n if (project && context.toLowerCase().includes(project.toLowerCase())) score += 20;\n if (context.includes(\"<\")) score += 15;\n const sectionCount = (context.match(/<\\w+>/g) || []).length;\n if (sectionCount >= 2) score += 15;\n if (sectionCount >= 4) score += 10;\n if (context.length >= 100) score += 10;\n if (context.length >= 500) score += 10;\n return Math.min(100, score);\n}\n","import type { MemoryProvider } from \"../types.js\";\n\nconst STRICTER_SUFFIX = `\n\nIMPORTANT: Your previous response was invalid. Please ensure your output strictly follows the required XML format. Every required field must be present with valid values.`;\n\ntype ValidationResult<T> =\n | { valid: true; data: T }\n | { valid: false; errors?: string[] };\n\nexport async function compressWithRetry<T>(\n provider: MemoryProvider,\n systemPrompt: string,\n userPrompt: string,\n validator: (response: string) => ValidationResult<T>,\n maxRetries = 1,\n): Promise<ValidationResult<T> & { retried: boolean }> {\n const first = await provider.compress(systemPrompt, userPrompt);\n let result = validator(first);\n if (result.valid) return { ...result, retried: false };\n\n let retried = false;\n for (let i = 0; i < maxRetries; i++) {\n retried = true;\n const retry = await provider.compress(\n systemPrompt + STRICTER_SUFFIX,\n userPrompt,\n );\n result = validator(retry);\n if (result.valid) return { ...result, retried };\n }\n\n return { ...result, retried };\n}\n","import type { Writable } from \"node:stream\";\n\nexport interface LiveEvent {\n id: string;\n type: string;\n data: Record<string, unknown>;\n}\n\nexport interface LiveEventsStats {\n subscribers: number;\n eventsSent: number;\n dropped: number;\n lastEventAt: number | null;\n}\n\nexport interface LiveEventWriter extends Writable {\n writableLength: number;\n}\n\nconst MAX_SUBSCRIBERS = 32;\nconst MAX_BUFFERED_BYTES = 1024 * 1024;\nconst HEARTBEAT_MS = 15_000;\nconst eventListeners = new Set<(event: LiveEvent) => void>();\n\nexport function formatSseFrame(event: LiveEvent): string {\n return `id: ${event.id}\\nevent: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`;\n}\n\nexport class LiveEventsHub {\n private readonly writers = new Set<LiveEventWriter>();\n private readonly detach = new Map<LiveEventWriter, () => void>();\n private heartbeat: ReturnType<typeof setInterval> | null = null;\n private eventsSent = 0;\n private dropped = 0;\n private lastEventAt: number | null = null;\n\n subscribe(writer: LiveEventWriter): () => void {\n if (this.writers.size >= MAX_SUBSCRIBERS) {\n const oldest = this.writers.values().next().value as LiveEventWriter | undefined;\n if (oldest) this.remove(oldest, true);\n }\n this.writers.add(writer);\n const onClose = () => this.remove(writer, false);\n this.detach.set(writer, onClose);\n writer.once(\"close\", onClose);\n writer.once(\"error\", onClose);\n if (!this.heartbeat) {\n this.heartbeat = setInterval(() => this.ping(), HEARTBEAT_MS);\n this.heartbeat.unref();\n }\n return () => this.remove(writer, false);\n }\n\n emit(event: LiveEvent): void {\n this.lastEventAt = Date.now();\n for (const listener of eventListeners) {\n try { listener(event); } catch { /* observers must not break event delivery */ }\n }\n const frame = formatSseFrame(event);\n for (const writer of this.writers) {\n if (writer.destroyed || writer.writableLength > MAX_BUFFERED_BYTES) {\n this.remove(writer, true);\n continue;\n }\n try {\n writer.write(frame);\n this.eventsSent++;\n } catch {\n this.remove(writer, true);\n }\n }\n }\n\n stats(): LiveEventsStats {\n return {\n subscribers: this.writers.size,\n eventsSent: this.eventsSent,\n dropped: this.dropped,\n lastEventAt: this.lastEventAt,\n };\n }\n\n private ping(): void {\n for (const writer of this.writers) {\n if (writer.destroyed || writer.writableLength > MAX_BUFFERED_BYTES) {\n this.remove(writer, true);\n continue;\n }\n try {\n writer.write(\": ping\\n\\n\");\n } catch {\n this.remove(writer, true);\n }\n }\n }\n\n private remove(writer: LiveEventWriter, dropped: boolean): void {\n if (!this.writers.delete(writer)) return;\n const onClose = this.detach.get(writer);\n this.detach.delete(writer);\n if (onClose) {\n writer.off(\"close\", onClose);\n writer.off(\"error\", onClose);\n }\n if (dropped) {\n this.dropped++;\n if (!writer.destroyed) writer.destroy();\n }\n if (this.writers.size === 0 && this.heartbeat) {\n clearInterval(this.heartbeat);\n this.heartbeat = null;\n }\n }\n\n}\n\nexport const liveEvents = new LiveEventsHub();\nexport function emitLiveEvent(event: LiveEvent): void {\n liveEvents.emit(event);\n}\nexport function onLiveEvent(listener: (event: LiveEvent) => void): () => void {\n eventListeners.add(listener);\n return () => eventListeners.delete(listener);\n}\nexport function getLiveEventsStats(): LiveEventsStats {\n return liveEvents.stats();\n}\n","// The pinned engine rejects WebSocket frames over 16 MiB; an oversized\n// function result drops the worker and 404s every endpoint. Refuse the\n// payload as one clean error instead. The cap sits under the frame limit\n// to leave headroom for the SDK's framing overhead.\nconst FRAME_LIMIT_BYTES = 16 * 1024 * 1024;\nexport const SAFE_PAYLOAD_BYTES = 15 * 1024 * 1024;\n\nexport type OversizedPayload = {\n success: false;\n error: string;\n oversized: true;\n bytes: number;\n limitBytes: number;\n};\n\nexport function payloadByteLength(payload: unknown): number {\n return Buffer.byteLength(JSON.stringify(payload) ?? \"\", \"utf8\");\n}\n\nexport function oversizedPayloadError(\n bytes: number,\n hint: string,\n): OversizedPayload {\n const mib = (bytes / (1024 * 1024)).toFixed(1);\n return {\n success: false,\n error: `Response is ${mib} MiB, over the ~${SAFE_PAYLOAD_BYTES / (1024 * 1024)} MiB engine transport frame limit; ${hint}`,\n oversized: true,\n bytes,\n limitBytes: SAFE_PAYLOAD_BYTES,\n };\n}\n\n// Serializes once; callers that also return the payload pay a second\n// serialization, acceptable on these cold export paths.\nexport function checkPayloadFrameSize(\n payload: unknown,\n hint: string,\n): OversizedPayload | null {\n const bytes = payloadByteLength(payload);\n if (bytes <= SAFE_PAYLOAD_BYTES) return null;\n return oversizedPayloadError(bytes, hint);\n}\n\nexport const FRAME_LIMIT_BYTES_FOR_TEST = FRAME_LIMIT_BYTES;\n","import type { CompressedObservation } from \"../types.js\";\nimport { checkPayloadFrameSize, payloadByteLength, SAFE_PAYLOAD_BYTES, type OversizedPayload } from \"../state/frame-guard.js\";\nimport { normalizeObservationSource, OBSERVATION_SOURCE_MAX_BYTES, withoutObservationSource } from \"./observation-source.js\";\n\nexport const SESSION_SOURCE_MAX_BYTES = 8 * 1024 * 1024;\n\nexport function budgetLiveObservationSource(\n observation: CompressedObservation,\n existing: CompressedObservation[],\n): CompressedObservation {\n const planned = budgetImportedObservationSources([observation], existing);\n return planned.success ? planned.observations[0]! : withoutObservationSource(observation);\n}\n\nexport function budgetImportedObservationSources(\n incoming: CompressedObservation[],\n existing: CompressedObservation[] = [],\n strategy: \"merge\" | \"replace\" | \"skip\" = \"merge\",\n): { success: true; observations: CompressedObservation[]; sourceTruncated: number; sourceOmitted: number } | OversizedPayload {\n const existingById = new Map(existing.map((row) => [row.id, row]));\n const rows = incoming.map((row) => ({ ...row, source: normalizeObservationSource(row.source) }));\n const written = rows.filter((row) => strategy !== \"skip\" || !existingById.has(row.id));\n const replacedIds = new Set(written.map((row) => row.id));\n const kept = strategy === \"replace\" ? [] : existing.filter((row) => !replacedIds.has(row.id));\n const base = [...kept, ...written.map(withoutObservationSource)];\n const envelope = { message_type: \"invocation_result\", invocation_id: \"00000000-0000-0000-0000-000000000000\", result: base };\n const oversized = checkPayloadFrameSize(envelope, \"observation summaries already exceed one session response; split the import into smaller sessions\");\n if (oversized) return oversized;\n\n const existingSourceBytes = kept.reduce((sum, row) => sum + (row.source ? payloadByteLength(row.source) + 10 : 0), 0);\n const sourceRows = written.filter((row) => row.source !== undefined);\n const available = Math.max(0, Math.min(\n SESSION_SOURCE_MAX_BYTES - existingSourceBytes,\n SAFE_PAYLOAD_BYTES - payloadByteLength(envelope) - 64 * 1024,\n ));\n const incomingSourceBytes = sourceRows.reduce((sum, row) => sum + payloadByteLength(row.source) + 10, 0);\n const perSource = incomingSourceBytes <= available\n ? OBSERVATION_SOURCE_MAX_BYTES\n : Math.min(OBSERVATION_SOURCE_MAX_BYTES, Math.floor(available / Math.max(1, sourceRows.length)) - 10);\n let sourceTruncated = 0;\n let sourceOmitted = 0;\n for (const row of sourceRows) {\n const source = row.source!;\n const metadata = { hookType: source.hookType, originalBytes: source.originalBytes, truncated: true };\n if (payloadByteLength(metadata) > perSource) {\n delete row.source;\n sourceOmitted++;\n continue;\n }\n row.source = normalizeObservationSource(source, perSource);\n if (row.source?.truncated) sourceTruncated++;\n }\n return { success: true, observations: rows, sourceTruncated, sourceOmitted };\n}\n","import type {\n RawObservation,\n CompressedObservation,\n ObservationType,\n} from \"../types.js\";\nimport { createObservationSource } from \"./observation-source.js\";\n\nfunction inferType(\n toolName: string | undefined,\n hookType: string,\n): ObservationType {\n if (hookType === \"post_tool_failure\") return \"error\";\n if (hookType === \"prompt_submit\") return \"conversation\";\n if (hookType === \"subagent_stop\" || hookType === \"task_completed\")\n return \"subagent\";\n if (hookType === \"notification\") return \"notification\";\n\n if (!toolName) return \"other\";\n // Normalize camelCase and kebab-case into word chunks so we can match\n // substrings like \"WebFetch\" -> \"web\" / \"fetch\".\n const n = toolName\n .replace(/([a-z])([A-Z])/g, \"$1_$2\")\n .replace(/[-\\s]+/g, \"_\")\n .toLowerCase();\n const hasWord = (word: string) =>\n new RegExp(`(^|_)${word}(_|$)`).test(n) ||\n n === word ||\n n.endsWith(word) ||\n n.startsWith(word);\n if ([\"fetch\", \"http\", \"web\"].some(hasWord)) return \"web_fetch\";\n if ([\"grep\", \"search\", \"glob\", \"find\"].some(hasWord)) return \"search\";\n if ([\"bash\", \"shell\", \"exec\", \"run\"].some(hasWord)) return \"command_run\";\n if ([\"edit\", \"update\", \"patch\", \"replace\"].some(hasWord)) return \"file_edit\";\n if ([\"write\", \"create\"].some(hasWord)) return \"file_write\";\n if ([\"read\", \"view\"].some(hasWord)) return \"file_read\";\n if ([\"task\", \"agent\"].some(hasWord)) return \"subagent\";\n return \"other\";\n}\n\nconst SEARCH_TOOL_PATTERN = /grep|glob|search|find|^ls$|list/i;\n\nfunction extractFiles(toolName: string | undefined, input: unknown): string[] {\n if (!input || typeof input !== \"object\") return [];\n const o = input as Record<string, unknown>;\n const isSearch =\n (toolName !== undefined && SEARCH_TOOL_PATTERN.test(toolName)) ||\n typeof o[\"pattern\"] === \"string\" ||\n typeof o[\"query\"] === \"string\";\n const keys = isSearch\n ? [\"file_path\", \"filepath\", \"filePath\", \"notebook_path\"]\n : [\"file_path\", \"filepath\", \"path\", \"filePath\", \"file\", \"notebook_path\"];\n const out = new Set<string>();\n for (const key of keys) {\n const v = o[key];\n if (typeof v === \"string\" && v.length > 0 && v.length < 512) out.add(v);\n }\n return [...out];\n}\n\nfunction stringifyForNarrative(v: unknown): string {\n if (v == null) return \"\";\n if (typeof v === \"string\") return v;\n try {\n return JSON.stringify(v);\n } catch {\n return String(v);\n }\n}\n\nfunction truncate(s: string, n: number): string {\n if (s.length <= n) return s;\n const end = /[\\uD800-\\uDBFF]/.test(s[n - 2]) ? n - 2 : n - 1;\n return s.slice(0, end) + \"\\u2026\";\n}\n\nfunction keepEnds(s: string, n: number): string {\n if (s.length <= n) return s;\n let head = Math.ceil((n - 1) / 2);\n let tail = s.length - (n - 1 - head);\n if (/[\\uD800-\\uDBFF]/.test(s[head - 1])) head--;\n if (/[\\uDC00-\\uDFFF]/.test(s[tail])) tail++;\n return s.slice(0, head) + \"\\u2026\" + s.slice(tail);\n}\n\nexport function buildSyntheticCompression(\n raw: RawObservation,\n): CompressedObservation {\n const toolName = raw.toolName ?? raw.hookType;\n const inputStr = stringifyForNarrative(raw.toolInput);\n const outputStr = stringifyForNarrative(raw.toolOutput);\n const promptStr = raw.userPrompt ?? \"\";\n const responseStr = keepEnds(raw.assistantResponse ?? \"\", 400);\n const source = createObservationSource(raw);\n\n const narrativeParts = [promptStr, inputStr, outputStr, responseStr].filter(\n (s) => s.length > 0,\n );\n const payload = source.payload;\n if (narrativeParts.length === 0 && payload != null &&\n (typeof payload !== \"object\" || Object.keys(payload).length > 0)) {\n narrativeParts.push(stringifyForNarrative(payload));\n }\n\n const result: CompressedObservation = {\n id: raw.id,\n sessionId: raw.sessionId,\n timestamp: raw.timestamp,\n compressedAt: new Date().toISOString(),\n type: inferType(toolName, raw.hookType),\n title: truncate(toolName || \"observation\", 80),\n subtitle: inputStr ? truncate(inputStr, 120) : undefined,\n facts: [],\n narrative: truncate(narrativeParts.join(\" | \"), 400),\n concepts: [],\n files: extractFiles(raw.toolName, raw.toolInput),\n importance: 5,\n confidence: 0.3,\n source,\n };\n if (raw.modality) result.modality = raw.modality;\n if (raw.imageData) result.imageData = raw.imageData;\n if (raw.agentId) result.agentId = raw.agentId;\n if (raw.origin) result.origin = raw.origin;\n if (raw.captureKey) result.captureKey = raw.captureKey;\n return result;\n}\n","import { createHash } from \"node:crypto\";\n\nexport const EVENT_ID_RE = /^[A-Za-z0-9][A-Za-z0-9_.:-]{7,127}$/;\n\nconst HOST_ID_FIELDS = [\n \"event_id\",\n \"eventId\",\n \"tool_use_id\",\n \"toolUseId\",\n \"tool_call_id\",\n \"toolCallId\",\n \"call_id\",\n \"callId\",\n \"prompt_id\",\n \"promptId\",\n \"message_id\",\n \"messageId\",\n];\n\nconst HOST_TIME_FIELDS = [\"timestamp\", \"ts\", \"created_at\", \"createdAt\", \"event_time\"];\n\nexport function isValidEventId(value: unknown): value is string {\n return typeof value === \"string\" && EVENT_ID_RE.test(value);\n}\n\nexport function stableStringify(value: unknown): string {\n if (value === undefined) return \"null\";\n if (value === null || typeof value !== \"object\") {\n const encoded = JSON.stringify(value);\n return encoded === undefined ? \"null\" : encoded;\n }\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(\",\")}]`;\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj)\n .filter((k) => obj[k] !== undefined)\n .sort();\n return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(\",\")}}`;\n}\n\nfunction hostScalar(host: Record<string, unknown>, fields: string[]): string | undefined {\n for (const field of fields) {\n const v = host[field];\n if (typeof v === \"string\" && v.trim()) return v.trim();\n if (typeof v === \"number\" && Number.isFinite(v)) return String(v);\n }\n return undefined;\n}\n\nfunction digest(parts: string[]): string {\n return createHash(\"sha256\").update(parts.join(\"\\u0000\")).digest(\"hex\").slice(0, 32);\n}\n\nexport function hasHostIdentity(host: Record<string, unknown> | null | undefined): boolean {\n const source = host && typeof host === \"object\" ? host : {};\n return hostScalar(source, HOST_ID_FIELDS) !== undefined || hostScalar(source, HOST_TIME_FIELDS) !== undefined;\n}\n\nexport function deriveEventId(\n hookType: string,\n sessionId: string,\n host: Record<string, unknown> | null | undefined,\n content: unknown,\n): string {\n const source = host && typeof host === \"object\" ? host : {};\n const hostId = hostScalar(source, HOST_ID_FIELDS);\n if (hostId) return `evh_${digest([\"host\", sessionId, hookType, hostId])}`;\n const hostTime = hostScalar(source, HOST_TIME_FIELDS) ?? \"\";\n return `evc_${digest([\"content\", sessionId, hookType, hostTime, stableStringify(content)])}`;\n}\n","import { randomUUID } from \"node:crypto\";\nimport type { CompressedObservation, ObservationCompression, RawObservation } from \"../types.js\";\nimport { stableStringify } from \"../capture/event-id.js\";\nimport { fingerprintId, KV } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { rawFromObservationSource } from \"./observation-source.js\";\nimport { scrubRecord } from \"./privacy.js\";\n\nexport type StoredObservation = (RawObservation & { compression?: ObservationCompression }) | CompressedObservation;\n\nexport function pendingCompression(attempts = 0): ObservationCompression {\n return { status: \"pending\", revision: randomUUID(), attempts };\n}\n\nexport function observationRevision(observation: StoredObservation): string {\n return fingerprintId(\"compression\", stableStringify(observation));\n}\n\nexport function needsCompression(observation: StoredObservation): boolean {\n return \"title\" in observation\n ? observation.compression?.status === \"pending\" || observation.compression?.status === \"failed\"\n : typeof observation.hookType === \"string\" && Boolean(observation.hookType);\n}\n\nexport function compressionRaw(observation: StoredObservation): RawObservation | null {\n const raw = \"title\" in observation ? rawFromObservationSource(observation) : observation;\n if (!raw || !raw.id || !raw.sessionId || !raw.timestamp || !raw.hookType) return null;\n const values = [raw.toolInput, raw.toolOutput, raw.userPrompt, raw.assistantResponse, raw.raw, raw.imageData];\n const retained = values.some((value) => {\n if (value === undefined || value === null) return false;\n if (typeof value === \"string\") return value.trim().length > 0;\n if (typeof value === \"object\") return Object.keys(value).length > 0;\n return true;\n });\n return retained ? scrubRecord({ ...raw, captureKey: observation.captureKey }) : null;\n}\n\nexport async function markCompressionDispatchFailed(\n kv: StateKV,\n observation: CompressedObservation,\n): Promise<void> {\n await withKeyedLock(`obs:${observation.sessionId}`, async () => {\n const current = await kv.get<CompressedObservation>(KV.observations(observation.sessionId), observation.id);\n if (!current?.compression || current.compression.revision !== observation.compression?.revision) return;\n if (current.compression.status !== \"pending\" || current.compression.attempts !== 0) return;\n await kv.set(KV.observations(current.sessionId), current.id, {\n ...current,\n compression: { ...current.compression, status: \"failed\", error: \"dispatch_failed\" },\n });\n });\n}\n","import type { IIIClient } from \"iii-sdk\";\nimport { readFileSync } from \"node:fs\";\nimport { isManagedImagePath } from \"../utils/image-store.js\";\nimport type { RawObservation, CompressedObservation, MemoryProvider, ObservationCompression, Session } from \"../types.js\";\nimport { KV } from \"../state/schema.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { COMPRESSION_SYSTEM, buildCompressionPrompt } from \"../prompts/compression.js\";\nimport { VISION_DESCRIPTION_PROMPT } from \"../prompts/vision.js\";\nimport { parseCompressionXml } from \"../prompts/compression-output.js\";\nimport { getSearchIndex, getVectorIndex, scheduleIndexSave, vectorIndexAddGuarded } from \"./search.js\";\nimport { CompressOutputSchema } from \"../eval/schemas.js\";\nimport { validateOutput } from \"../eval/validator.js\";\nimport { scoreCompression } from \"../eval/quality.js\";\nimport { compressWithRetry } from \"../eval/self-correct.js\";\nimport type { MetricsStore } from \"../eval/metrics-store.js\";\nimport { logger } from \"../logger.js\";\nimport { emitLiveEvent } from \"../viewer/live-events.js\";\nimport { withoutObservationSource } from \"./observation-source.js\";\nimport { budgetLiveObservationSource } from \"./observation-source-budget.js\";\nimport { observationEmbedText } from \"../state/memory-utils.js\";\nimport { buildSyntheticCompression } from \"./compress-synthetic.js\";\nimport { withKeyedLock } from \"../state/keyed-mutex.js\";\nimport { scrubRecord, stripPrivateData } from \"./privacy.js\";\nimport { compressionRaw, needsCompression, observationRevision, pendingCompression, type StoredObservation } from \"./compression-state.js\";\nimport { registerCompressionRecovery } from \"./compression-recovery.js\";\n\nexport const COMPRESSION_TIMEOUT_MS = 60_000;\n\ntype CompressRequest = { observationId: string; sessionId: string; raw?: RawObservation; expectedRevision?: string; scope?: { project?: string; agentId?: string } };\nexport type CompressResult = {\n success: boolean;\n error?: string;\n skipped?: boolean;\n retryable?: boolean;\n compressed?: Omit<CompressedObservation, \"source\">;\n qualityScore?: number;\n sourceTruncated?: boolean;\n};\ntype CompressionAttempt = { revisions: Set<string>; resultRevision?: string };\ntype ActiveCompression = { promise: Promise<CompressResult>; attempt: CompressionAttempt };\nconst activeByStore = new WeakMap<StateKV, Map<string, ActiveCompression>>();\n\nexport function compressionInFlight(kv: StateKV, sessionId: string, observationId: string): boolean {\n return activeByStore.get(kv)?.has(JSON.stringify([sessionId, observationId])) ?? false;\n}\n\nfunction indexObservation(observation: CompressedObservation): void {\n getSearchIndex().add(observation);\n scheduleIndexSave();\n}\n\nexport function registerCompressFunction(\n sdk: IIIClient,\n kv: StateKV,\n provider: MemoryProvider,\n metricsStore?: MetricsStore,\n): void {\n const active = activeByStore.get(kv) ?? new Map<string, ActiveCompression>();\n activeByStore.set(kv, active);\n\n async function matchesScope(data: CompressRequest, row: StoredObservation): Promise<boolean> {\n if (!data.scope) return true;\n const session = await kv.get<Session>(KV.sessions, data.sessionId);\n return Boolean(session && (!data.scope.project || session.project === data.scope.project) &&\n (!data.scope.agentId || (row.agentId ?? session.agentId) === data.scope.agentId));\n }\n\n async function compress(data: CompressRequest, attempt: CompressionAttempt, deadline: number): Promise<CompressResult> {\n const { sessionId, observationId } = data;\n const startMs = Date.now();\n async function bounded<T>(work: () => Promise<T>): Promise<T> {\n const remaining = deadline - Date.now();\n if (remaining <= 0) throw new Error(\"compression_timeout\");\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([work(), new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(\"compression_timeout\")), remaining);\n })]);\n } finally { clearTimeout(timer); }\n }\n const prepared = await withKeyedLock(`obs:${sessionId}`, async () => {\n const stored = await kv.get<StoredObservation>(KV.observations(sessionId), observationId);\n if (!stored || typeof stored !== \"object\" || stored.id !== observationId || stored.sessionId !== sessionId) return null;\n if (!await matchesScope(data, stored)) return { skipped: true as const };\n if (data.expectedRevision && observationRevision(stored) !== data.expectedRevision) return { skipped: true as const };\n if (!needsCompression(stored) && !data.raw) return { skipped: true as const };\n const rows = await kv.list<CompressedObservation>(KV.observations(sessionId));\n const fallback = \"title\" in stored ? stored : budgetLiveObservationSource(buildSyntheticCompression(scrubRecord(stored)), rows);\n const raw = compressionRaw(fallback);\n if (!raw && !(\"title\" in stored)) return { unavailable: true as const };\n const compression: ObservationCompression = {\n ...pendingCompression((stored.compression?.attempts ?? 0) + (raw ? 1 : 0)),\n ...(raw ? { lastAttemptAt: new Date().toISOString() } : { status: \"failed\" as const, error: \"source_unavailable\" as const }),\n };\n const claimed = { ...stored, compression };\n await kv.set(KV.observations(sessionId), observationId, claimed);\n attempt.revisions.add(observationRevision(stored));\n attempt.revisions.add(observationRevision(claimed));\n if (\"title\" in claimed) indexObservation(claimed);\n return { raw, claimed, fallback, revision: observationRevision(claimed) };\n });\n if (!prepared) return { success: false, error: \"observation_not_found\", skipped: true, retryable: false };\n if (\"skipped\" in prepared) return { success: true, skipped: true };\n if (\"unavailable\" in prepared || !prepared.raw) return { success: false, error: \"source_unavailable\", retryable: false };\n const { raw, claimed, fallback, revision } = prepared;\n\n async function fail(error: NonNullable<ObservationCompression[\"error\"]>): Promise<CompressResult> {\n const changed = await withKeyedLock(`obs:${sessionId}`, async () => {\n const current = await kv.get<StoredObservation>(KV.observations(sessionId), observationId);\n if (!current || observationRevision(current) !== revision) return true;\n const failed = { ...claimed, compression: { ...claimed.compression!, status: \"failed\" as const, error } };\n await kv.set(KV.observations(sessionId), observationId, failed);\n attempt.resultRevision = observationRevision(failed);\n attempt.revisions.add(attempt.resultRevision);\n return false;\n });\n await metricsStore?.record(\"mem::compress\", Date.now() - startMs, false).catch(() => {});\n return changed\n ? { success: false, error: \"observation_changed\", skipped: true, retryable: false }\n : { success: false, error, retryable: true, ...(fallback.source?.truncated ? { sourceTruncated: true } : {}) };\n }\n\n try {\n let imageDescription: string | undefined;\n const hasImage = raw.modality === \"image\" || raw.modality === \"mixed\";\n\n if (hasImage && raw.imageData && provider.describeImage) {\n try {\n let base64Data = raw.imageData;\n let mimeType = \"image/png\";\n\n if (!raw.imageData.startsWith(\"/9j/\") && !raw.imageData.startsWith(\"iVBOR\")) {\n if (!isManagedImagePath(raw.imageData)) {\n throw new Error(`Refusing to read image outside managed store: ${raw.imageData}`);\n }\n const fileBuffer = readFileSync(raw.imageData);\n base64Data = fileBuffer.toString(\"base64\");\n if (raw.imageData.endsWith(\".jpg\") || raw.imageData.endsWith(\".jpeg\")) mimeType = \"image/jpeg\";\n else if (raw.imageData.endsWith(\".webp\")) mimeType = \"image/webp\";\n else if (raw.imageData.endsWith(\".gif\")) mimeType = \"image/gif\";\n }\n\n imageDescription = await bounded(() => provider.describeImage!(base64Data, mimeType, VISION_DESCRIPTION_PROMPT));\n logger.info(\"Image described by vision model\", { obsId: observationId });\n } catch {\n logger.warn(\"Vision model call failed, falling back to text-only compression\", { obsId: observationId });\n }\n }\n\n const retainedOutput = raw.toolOutput ?? (raw.raw && Object.keys(Object(raw.raw)).length > 0 ? raw.raw : undefined);\n const prompt = buildCompressionPrompt({\n hookType: raw.hookType,\n toolName: raw.toolName,\n toolInput: raw.toolInput,\n toolOutput: imageDescription ? `[Image Description]: ${imageDescription}\\n\\n${retainedOutput ?? \"\"}` : retainedOutput,\n userPrompt: raw.userPrompt,\n assistantResponse: raw.assistantResponse,\n timestamp: raw.timestamp,\n });\n const validator = (response: string) => {\n const parsed = parseCompressionXml(response);\n if (!parsed) return { valid: false as const, errors: [\"xml_parse_failed\"] };\n const result = validateOutput(CompressOutputSchema, scrubRecord(parsed), \"mem::compress\");\n return result.valid ? result : { valid: false as const, errors: result.result.errors };\n };\n const result = await compressWithRetry({\n ...provider,\n compress: (system, user) => bounded(() => provider.compress(system, user)),\n }, COMPRESSION_SYSTEM, prompt, validator, 1);\n if (!result.valid) {\n return fail(result.errors?.includes(\"xml_parse_failed\") ? \"parse_failed\" : \"validation_failed\");\n }\n const qualityScore = scoreCompression(result.data);\n const candidate: CompressedObservation = {\n ...fallback,\n ...result.data,\n compressedAt: new Date().toISOString(),\n confidence: qualityScore / 100,\n compression: { ...claimed.compression, status: \"complete\" },\n ...(raw.imageData ? { imageRef: raw.imageData } : {}),\n ...(imageDescription ? { imageDescription: stripPrivateData(imageDescription) } : {}),\n };\n const compressed = await withKeyedLock(`obs:${sessionId}`, async () => {\n const current = await kv.get<StoredObservation>(KV.observations(sessionId), observationId);\n if (!current || observationRevision(current) !== revision || !await matchesScope(data, current)) return null;\n const rows = await kv.list<CompressedObservation>(KV.observations(sessionId));\n const bounded = budgetLiveObservationSource(candidate, rows);\n await kv.set(KV.observations(sessionId), observationId, bounded);\n attempt.resultRevision = observationRevision(bounded);\n attempt.revisions.add(attempt.resultRevision);\n indexObservation(bounded);\n return bounded;\n });\n if (!compressed) return { success: false, error: \"observation_changed\", skipped: true, retryable: false };\n const committedRevision = observationRevision(compressed);\n await bounded(() => vectorIndexAddGuarded(\n observationId, sessionId, observationEmbedText(compressed),\n { kind: \"observation\", logId: observationId },\n (embedding, isCurrent) => withKeyedLock(`obs:${sessionId}`, async () => {\n const current = await kv.get<StoredObservation>(KV.observations(sessionId), observationId);\n if (!isCurrent() || !current || observationRevision(current) !== committedRevision) return false;\n getVectorIndex()?.add(observationId, sessionId, embedding);\n return true;\n }),\n )).catch(() => {});\n const published = await withKeyedLock(`obs:${sessionId}`, async () => {\n const current = await kv.get<StoredObservation>(KV.observations(sessionId), observationId);\n if (!current || observationRevision(current) !== committedRevision || !await matchesScope(data, current)) return false;\n emitLiveEvent({\n id: `compressed-${observationId}`,\n type: \"compressed_observation\",\n data: { type: \"compressed\", observation: withoutObservationSource(compressed), sessionId },\n });\n return true;\n });\n if (!published) return { success: false, error: \"observation_changed\", skipped: true, retryable: false };\n await metricsStore?.record(\"mem::compress\", Date.now() - startMs, true, qualityScore).catch(() => {});\n return { success: true, compressed: withoutObservationSource(compressed), qualityScore, ...(compressed.source?.truncated ? { sourceTruncated: true } : {}) };\n } catch {\n logger.warn(\"Observation retained for compression retry\", { observationId, sessionId });\n return fail(\"compression_failed\");\n }\n }\n\n async function dispatch(data: CompressRequest, deadline: number): Promise<CompressResult> {\n const key = JSON.stringify([data.sessionId, data.observationId]);\n const existing = active.get(key);\n if (existing) {\n const changed: CompressResult = { success: false, error: \"observation_changed\", skipped: true, retryable: false };\n const requestedRevision = await withKeyedLock(`obs:${data.sessionId}`, async () => {\n const current = await kv.get<StoredObservation>(KV.observations(data.sessionId), data.observationId);\n if (!current || current.id !== data.observationId || current.sessionId !== data.sessionId || !await matchesScope(data, current)) return null;\n const revision = observationRevision(current);\n if (data.expectedRevision && data.expectedRevision !== revision && !existing.attempt.revisions.has(data.expectedRevision)) return null;\n return data.expectedRevision ?? revision;\n });\n if (!requestedRevision) return changed;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const result = await Promise.race([existing.promise, new Promise<CompressResult>((resolve) => {\n timer = setTimeout(() => resolve({ success: false, error: \"compression_timeout\", retryable: true }), Math.max(0, deadline - Date.now()));\n })]).finally(() => clearTimeout(timer));\n if (result.error === \"compression_timeout\") return result;\n const shared = await withKeyedLock(`obs:${data.sessionId}`, async () => {\n const current = await kv.get<StoredObservation>(KV.observations(data.sessionId), data.observationId);\n if (!current || current.id !== data.observationId || current.sessionId !== data.sessionId || !await matchesScope(data, current)) return changed;\n const revision = observationRevision(current);\n if (revision === existing.attempt.resultRevision && existing.attempt.revisions.has(requestedRevision)) return result;\n return revision === requestedRevision && (needsCompression(current) || data.raw) ? null : changed;\n });\n return shared ?? dispatch({ ...data, expectedRevision: requestedRevision }, deadline);\n }\n if (Date.now() >= deadline) return { success: false, error: \"compression_timeout\", retryable: true };\n const attempt: CompressionAttempt = { revisions: new Set() };\n const task: ActiveCompression = { attempt, promise: compress(data, attempt, deadline).finally(() => {\n if (active.get(key) === task) active.delete(key);\n }) };\n active.set(key, task);\n return task.promise;\n }\n\n sdk.registerFunction(\"mem::compress\", (data: CompressRequest): Promise<CompressResult> => {\n if (!data || typeof data.sessionId !== \"string\" || !data.sessionId.trim() ||\n typeof data.observationId !== \"string\" || !data.observationId.trim()) {\n return Promise.resolve({ success: false, error: \"invalid_observation_identity\", retryable: false });\n }\n if (data.raw !== undefined && (!data.raw || typeof data.raw.hookType !== \"string\" || !data.raw.hookType)) {\n return Promise.resolve({ success: false, error: \"invalid_raw_observation\" });\n }\n return dispatch(data, Date.now() + COMPRESSION_TIMEOUT_MS);\n });\n registerCompressionRecovery(sdk, kv);\n}\n","import type { IIIClient } from \"iii-sdk\";\nimport type { Session } from \"../types.js\";\nimport type { StateKV } from \"../state/kv.js\";\nimport { fingerprintId, KV } from \"../state/schema.js\";\nimport { compressionInFlight, type CompressResult } from \"./compress.js\";\nimport { compressionRaw, needsCompression, observationRevision, type StoredObservation } from \"./compression-state.js\";\nimport { safeAudit } from \"./audit.js\";\nimport { checkPayloadFrameSize } from \"../state/frame-guard.js\";\n\nexport interface CompressionScope {\n sessionId?: string;\n project?: string;\n agentId?: string;\n limit: number;\n cursor?: string;\n}\n\nconst MAX_CURSOR_LENGTH = 32 * 1024;\ntype Cursor = { sessionId: string; observationId: string; hashed: boolean };\n\nexport function parseCompressionScope(input: unknown): CompressionScope {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) throw new Error(\"Expected an object\");\n const data = input as Record<string, unknown>;\n if (Object.keys(data).some((key) => ![\"sessionId\", \"project\", \"agentId\", \"limit\", \"cursor\"].includes(key))) {\n throw new Error(\"Unknown compression option\");\n }\n const scope: CompressionScope = { limit: 10 };\n for (const key of [\"sessionId\", \"project\", \"agentId\", \"cursor\"] as const) {\n const value = data[key];\n if (value === undefined || (key === \"cursor\" && value === \"\")) continue;\n if (typeof value !== \"string\" || !value.trim() || value.length > (key === \"cursor\" ? MAX_CURSOR_LENGTH : 1024)) throw new Error(`Invalid ${key}`);\n scope[key] = value;\n }\n if (!scope.sessionId && !scope.project) throw new Error(\"Specify sessionId or project\");\n if (data.limit !== undefined) {\n if ((typeof data.limit !== \"number\" && typeof data.limit !== \"string\") || !/^\\d+$/.test(String(data.limit))) {\n throw new Error(\"limit must be an integer from 1 to 100\");\n }\n scope.limit = Number(data.limit);\n if (!Number.isSafeInteger(scope.limit) || scope.limit < 1 || scope.limit > 100) throw new Error(\"limit must be an integer from 1 to 100\");\n }\n readCursor(scope);\n return scope;\n}\n\nfunction scopeKey(scope: CompressionScope): string {\n return fingerprintId(\"compression-scope\", JSON.stringify([scope.sessionId, scope.project, scope.agentId]));\n}\n\nfunction writeCursor(scope: CompressionScope, sessionId: string, observationId: string): string {\n const encode = (parts: unknown[]) => Buffer.from(JSON.stringify(parts)).toString(\"base64url\");\n const cursor = encode([scopeKey(scope), sessionId, observationId]);\n return cursor.length <= MAX_CURSOR_LENGTH ? cursor : encode([\n scopeKey(scope), fingerprintId(\"session\", sessionId), observationId ? fingerprintId(\"observation\", observationId) : \"\", \"hash\",\n ]);\n}\n\nfunction readCursor(scope: CompressionScope): Cursor | null {\n if (!scope.cursor) return null;\n try {\n const value: unknown = JSON.parse(Buffer.from(scope.cursor, \"base64url\").toString(\"utf8\"));\n if (!Array.isArray(value) || ![3, 4].includes(value.length) || value[0] !== scopeKey(scope) ||\n typeof value[1] !== \"string\" || typeof value[2] !== \"string\") throw new Error();\n const hashed = value.length === 4;\n if (hashed && (value[3] !== \"hash\" || !/^session_[a-f0-9]{16}$/.test(value[1]) ||\n (value[2] !== \"\" && !/^observation_[a-f0-9]{16}$/.test(value[2])))) throw new Error();\n return { sessionId: value[1], observationId: value[2], hashed };\n } catch { throw new Error(\"Invalid cursor for this compression scope\"); }\n}\n\nexport function registerCompressionRecovery(sdk: IIIClient, kv: StateKV): void {\n async function run(input: unknown, retry: boolean) {\n const request = input && typeof input === \"object\" && !Array.isArray(input) ? { ...input } : input;\n if (request && typeof request === \"object\") delete (request as Record<string, unknown>)._caller_worker_id;\n const scope = parseCompressionScope(request);\n const after = readCursor(scope);\n const sessions = scope.sessionId\n ? [await kv.get<Session>(KV.sessions, scope.sessionId)].filter((s): s is Session => Boolean(s))\n : await kv.list<Session>(KV.sessions);\n const eligible = sessions.filter((s) => typeof s.id === \"string\" && (!scope.project || s.project === scope.project))\n .sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);\n let anchorRows: { sessionId: string; rows: StoredObservation[] } | undefined;\n if (after?.hashed) {\n const anchors = eligible.filter((session) => fingerprintId(\"session\", session.id) === after.sessionId);\n let observationId: string | undefined = after.observationId ? undefined : \"\";\n if (anchors.length === 1 && after.observationId) {\n const rows = await kv.list<StoredObservation>(KV.observations(anchors[0].id));\n anchorRows = { sessionId: anchors[0].id, rows };\n const matches = rows.filter((row) => row && typeof row.id === \"string\" &&\n fingerprintId(\"observation\", row.id) === after.observationId);\n if (matches.length === 1) observationId = matches[0].id;\n }\n if (anchors.length !== 1 || observationId === undefined) return {\n success: false, dryRun: !retry, error: \"cursor_stale\", items: [],\n attempted: 0, recovered: 0, failed: 0, scannedSessions: 0, scannedObservations: 0,\n };\n after.sessionId = anchors[0].id;\n after.observationId = observationId;\n }\n const items: Array<{ sessionId: string; observationId: string; status: string; attempts: number; retryable: boolean;\n truncated: boolean; inFlight: boolean; error?: string; outcome?: string }> = [];\n let scannedSessions = 0;\n let scannedObservations = 0;\n let attempted = 0;\n let recovered = 0;\n let failed = 0;\n let nextCursor: string | undefined;\n let stop = false;\n const startedAt = Date.now();\n for (const session of eligible) {\n if (after && session.id < after.sessionId) continue;\n if (scannedSessions >= 20) {\n nextCursor = writeCursor(scope, session.id, \"\");\n break;\n }\n scannedSessions++;\n const observations = anchorRows?.sessionId === session.id ? anchorRows.rows : await kv.list<StoredObservation>(KV.observations(session.id));\n const rows = observations.filter((row) => row && typeof row === \"object\" && typeof row.id === \"string\")\n .sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);\n for (const row of rows) {\n if (after && session.id === after.sessionId && row.id <= after.observationId) continue;\n scannedObservations++;\n nextCursor = writeCursor(scope, session.id, row.id);\n if (row.sessionId === session.id && needsCompression(row) &&\n (!scope.agentId || (row.agentId ?? session.agentId) === scope.agentId)) {\n const source = compressionRaw(row);\n const metadata = row.compression;\n const item = {\n sessionId: session.id, observationId: row.id,\n status: metadata?.status ?? \"raw\",\n attempts: metadata?.attempts ?? 0,\n retryable: Boolean(source), truncated: \"source\" in row ? Boolean(row.source?.truncated) : false,\n inFlight: compressionInFlight(kv, session.id, row.id),\n error: (!source ? \"source_unavailable\" : metadata?.error) as string | undefined,\n outcome: undefined as string | undefined,\n };\n items.push(item);\n if (retry && source) {\n attempted++;\n let result: CompressResult;\n try {\n result = await sdk.trigger({ function_id: \"mem::compress\", payload: {\n sessionId: session.id, observationId: row.id, expectedRevision: observationRevision(row),\n scope: { project: scope.project, agentId: scope.agentId },\n } }) as CompressResult;\n } catch { result = { success: false, error: \"compression_failed\" }; }\n if (!result || typeof result.success !== \"boolean\") result = { success: false, error: \"compression_failed\" };\n item.truncated = result.sourceTruncated ?? item.truncated;\n item.retryable = result.retryable ?? item.retryable;\n if (result.success && !result.skipped) { recovered++; item.outcome = \"recovered\"; item.error = undefined; }\n else if (result.skipped) { item.outcome = \"changed\"; item.error = result.error; }\n else { failed++; item.outcome = \"failed\"; item.error = result.error ?? \"compression_failed\"; stop = true; }\n }\n }\n if (stop || items.length >= scope.limit || scannedObservations >= 1000 || Date.now() - startedAt >= 30_000) { stop = true; break; }\n }\n if (stop) break;\n nextCursor = undefined;\n }\n const result = { success: failed === 0, dryRun: !retry, items, attempted, recovered, failed, scannedSessions, scannedObservations,\n ...(nextCursor ? { nextCursor } : {}) };\n const oversized = checkPayloadFrameSize(result, \"lower limit or select one session for compression recovery\");\n if (retry && attempted > 0) {\n await safeAudit(kv, \"compress\", \"mem::compression-retry\", oversized ? [] : items.filter((i) => i.outcome === \"recovered\").map((i) => i.observationId), {\n sessionId: scope.sessionId, project: scope.project, agentId: scope.agentId, attempted, recovered, failed,\n });\n }\n return oversized ?? result;\n }\n sdk.registerFunction(\"mem::compression-status\", (input: unknown) => run(input, false));\n sdk.registerFunction(\"mem::compression-retry\", (input: unknown) => run(input, true));\n}\n"],"mappings":"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"}
|