@romiluz/clawmongo 2026.3.27 → 2026.3.28
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/README.md +72 -49
- package/dist/{accounts-boH28BFM.js → accounts-lL2y51Ag.js} +46 -46
- package/dist/{acp-cli-DLaTb29R.js → acp-cli-BZvVHRY8.js} +46 -46
- package/dist/{action-runtime-Bk-7pvN2.js → action-runtime-DMYRUL4q.js} +10 -10
- package/dist/{actions.runtime-Y529miLb.js → actions.runtime-Bd-NMAq6.js} +46 -46
- package/dist/{actions.runtime-DVQ4pmcp.js → actions.runtime-gPSeXscW.js} +49 -49
- package/dist/{agent-scope-BROpmzKv.js → agent-scope-DXZH506l.js} +1 -1
- package/dist/{agents-DZqtbDMD.js → agents-Bt25bmDR.js} +13 -13
- package/dist/{agents-BbO-i90j.js → agents-CyJmttnS.js} +114 -114
- package/dist/{agents.config-CDS6iAat.js → agents.config-BWm70Hr6.js} +2 -2
- package/dist/{agents.config-iY500LY-.js → agents.config-UsCw0kOR.js} +4 -4
- package/dist/{audit-Cmj7BNcZ.js → audit-Dg8ZiJrJ.js} +9 -9
- package/dist/{audit-DmXeao7s.js → audit-DhXhWoiv.js} +1 -1
- package/dist/{audit-channel.collect.runtime-DhP09fjv.js → audit-channel.collect.runtime-CvPUHy1X.js} +2 -2
- package/dist/{audit-channel.runtime-C-watgwg.js → audit-channel.runtime-B6ZnOPFc.js} +46 -46
- package/dist/{audit-extra.async-B-7dzgcz.js → audit-extra.async-826UZZhJ.js} +3 -3
- package/dist/{audit-membership-runtime-CbLi3-5b.js → audit-membership-runtime-DLQrV7Rr.js} +46 -46
- package/dist/{audit.deep.runtime-D5VgrTOT.js → audit.deep.runtime-DQDtV7Bc.js} +4 -4
- package/dist/{audit.nondeep.runtime-B7M0-7FZ.js → audit.nondeep.runtime-H6B-2xal.js} +4 -4
- package/dist/{audit.runtime-BUknqGaP.js → audit.runtime-D2ZRC2A_.js} +47 -47
- package/dist/{auth-choice-DfJRosb4.js → auth-choice-CEowrO66.js} +57 -57
- package/dist/{auth-choice-CpB99A-L.js → auth-choice-DiufM1b8.js} +55 -55
- package/dist/{auth-choice-Bnnngmkx.js → auth-choice-YrGxwB9A.js} +5 -5
- package/dist/{auth-choice-options-DvqJHFOp.js → auth-choice-options-n3_uFdT5.js} +2 -2
- package/dist/{auth-choice-prompt-DtTjWfPT.js → auth-choice-prompt-DYFzoWa6.js} +50 -50
- package/dist/{auth-choice-prompt-Cxz8du6E.js → auth-choice-prompt-sLET2Bkw.js} +1 -1
- package/dist/{auth-choice.apply-helpers-Bm5p2ZX7.js → auth-choice.apply-helpers-GU6nZntg.js} +1 -1
- package/dist/{auth-choice.plugin-providers.runtime-Dsu6-vb8.js → auth-choice.plugin-providers.runtime-BNqOEEtb.js} +47 -47
- package/dist/{auth-profiles-2-OV37OF.js → auth-profiles-BWBQJ6X_.js} +67 -76
- package/dist/{auth-profiles.runtime-HcQMBs3K.js → auth-profiles.runtime-DfKRAmQR.js} +46 -46
- package/dist/{backend-config-avgzgS5Z.js → backend-config--L236wE2.js} +26 -1
- package/dist/{backup-create-B9F0M7-J.js → backup-create-Bll6DgoT.js} +2 -2
- package/dist/{base-session-key-DyLtSGkj.js → base-session-key-CA4SoGLF.js} +1 -1
- package/dist/{bluebubbles-BTR7u4zE.js → bluebubbles-BsX68JOY.js} +6 -6
- package/dist/{browser-cli-tmytvFaa.js → browser-cli-B5euA0cQ.js} +8 -8
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +46 -46
- package/dist/bundled/bootstrap-extra-files/handler.js +1 -1
- package/dist/bundled/session-memory/handler.js +47 -47
- package/dist/{call-Cqem-bCB.js → call-C-_XQxw5.js} +1 -1
- package/dist/{call-CxVOiYz-.js → call-lPTaDgAg.js} +6 -6
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/{channel-Br8MF00M.js → channel-5o-oIU2B.js} +1 -1
- package/dist/{channel-BvRm4jSj.js → channel-C1zZg_8b.js} +2 -2
- package/dist/{channel-CqkxOhz2.js → channel-CEytBPH-.js} +4 -4
- package/dist/{channel-D_h7IfYK.js → channel-Cm65A1lo.js} +7 -7
- package/dist/{channel-ngZRDeE3.js → channel-D4K0MVgr.js} +5 -5
- package/dist/{channel-account-context-DZhZw4oo.js → channel-account-context-CNZZPDSe.js} +1 -1
- package/dist/{channel-plugin-resolution-CXm5HIcm.js → channel-plugin-resolution-WWO690RK.js} +3 -3
- package/dist/{channel-reply-pipeline-DdDsf-Lc.js → channel-reply-pipeline-B17-tBLU.js} +1 -1
- package/dist/{channel-shared-VIRIADYn.js → channel-shared-RH6YsZ0I.js} +1 -1
- package/dist/{channel-summary-BTJxLPN8.js → channel-summary-Cy7WDRjQ.js} +7 -7
- package/dist/{channel-summary-DdJtHlvH.js → channel-summary-DV4_b3HZ.js} +2 -2
- package/dist/{channel-tFDEkWt9.js → channel-yCiI29Ju.js} +6 -6
- package/dist/{channel.runtime-DGnRryi2.js → channel.runtime-C3m1vacV.js} +47 -47
- package/dist/{channel.runtime-CdPEA_wb.js → channel.runtime-CUSE7Dn0.js} +47 -47
- package/dist/{channel.runtime-0n3_Hz_Y.js → channel.runtime-CtWi36oj.js} +49 -49
- package/dist/{channel.runtime-CkHcsWQ3.js → channel.runtime-LUpQZiWg.js} +49 -49
- package/dist/{channel.runtime-msXRrVzC.js → channel.runtime-QOkM4mJV.js} +51 -51
- package/dist/{channel.runtime-khqV1QRG.js → channel.runtime-rYuUs2po.js} +4 -4
- package/dist/{channels-DNza27NY.js → channels-4VTbN2Gt.js} +103 -103
- package/dist/{channels-CLZoq3SY.js → channels-BUMnLXLQ.js} +1 -1
- package/dist/{channels-cli-Bhsnjsix.js → channels-cli-BYmLj8zw.js} +55 -55
- package/dist/{clawbot-cli-9YJNF9pF.js → clawbot-cli-CIYY1u-6.js} +47 -47
- package/dist/cli/daemon-cli.js +1 -1
- package/dist/{cli-FF5823nM.js → cli-DUA0FvhM.js} +46 -46
- package/dist/{command-registry-Bow_kWfU.js → command-registry-B1ECZip_.js} +13 -13
- package/dist/{command-registry-BEExVzem.js → command-registry-DOAwIs0Y.js} +2 -2
- package/dist/{command-secret-gateway-CzHSHmXG.js → command-secret-gateway-Big-n6JY.js} +46 -46
- package/dist/{compact.runtime-Bye-pm7Z.js → compact.runtime-BKnPPv9X.js} +46 -46
- package/dist/{completion-cli-B4hJ8HjW.js → completion-cli-BeLNvVTI.js} +3 -3
- package/dist/{completion-cli-DQrts0Ip.js → completion-cli-CHwHDPuI.js} +2 -2
- package/dist/{config-Ca7pLyBD.js → config-BOWZMmDA.js} +1 -1
- package/dist/{config-GKOWhVMv.js → config-C68iwvDj.js} +5 -5
- package/dist/{config-cli-CxPspN-S.js → config-cli-BnC336Lu.js} +48 -48
- package/dist/{config-guard-BK2hWyPi.js → config-guard-Bn6rZnzK.js} +6 -6
- package/dist/{config-validation-DO6o_Kt_.js → config-validation-BBuJZ-WH.js} +2 -2
- package/dist/{configure-CODqvxU-.js → configure-CHJDsjOD.js} +120 -120
- package/dist/{configure-Dg65gBEw.js → configure-Cctw7tyJ.js} +19 -23
- package/dist/{connection-auth-zhL6PVn0.js → connection-auth-C2XaPpF5.js} +1 -1
- package/dist/{control-ui-shared-_VwcOcc_.js → control-ui-shared-BC-g150y.js} +1 -1
- package/dist/{core-CzwQmKcn.js → core-Cb3XxL6S.js} +1 -1
- package/dist/{cron-cli-Dp_EQt2v.js → cron-cli-C10feOtH.js} +7 -7
- package/dist/{daemon-cli-Dgpv6Y0R.js → daemon-cli-Ds8mu2VZ.js} +4 -4
- package/dist/{daemon-install-Dq1Ix-FO.js → daemon-install-B__sP_7j.js} +49 -49
- package/dist/{delegate-BVapk4rY.js → delegate-ByCLviVI.js} +1 -1
- package/dist/{deliver-runtime-DPzMjhNU.js → deliver-Co7G5ubS.js} +46 -46
- package/dist/{deliver-C32Gg-xU.js → deliver-runtime-2svrtAf1.js} +46 -46
- package/dist/{devices-cli-3WN_wB1C.js → devices-cli-CH8nWgcU.js} +6 -6
- package/dist/{diagnostic-BbXfhLMi.js → diagnostic-DHTG43d_.js} +1 -1
- package/dist/{directory-cli-D_5BYdXm.js → directory-cli-B0REFlKo.js} +48 -48
- package/dist/{directory.static-CsajbHw1.js → directory.static-wnw_R8dE.js} +1 -1
- package/dist/{discord-C-4y9vOT.js → discord-Cws9MsXn.js} +4 -4
- package/dist/{discord-B3mmVXuG.js → discord-b8Ff_BKB.js} +46 -46
- package/dist/{dns-cli-CdAnUzRi.js → dns-cli-aRTleL5e.js} +5 -5
- package/dist/{doctor-completion-Dk8sgMOd.js → doctor-completion-KQWBMnEi.js} +1 -1
- package/dist/{doctor-config-preflight-BJ0lGLTO.js → doctor-config-preflight-BDYe5di1.js} +2 -2
- package/dist/{doctor-config-preflight-D32oVOWD.js → doctor-config-preflight-Dn5a_Dbr.js} +6 -6
- package/dist/{doctor-state-migrations-BklDIib1.js → doctor-state-migrations-BI6HzFyq.js} +47 -47
- package/dist/{doctor-state-migrations-Cdk3ep_f.js → doctor-state-migrations-DUPe9zNr.js} +2 -2
- package/dist/entry.js +1 -1
- package/dist/{exec-approvals-D8OOtgGc.js → exec-approvals-CZz2LqIW.js} +1 -1
- package/dist/{exec-approvals-cli-dGISWHE3.js → exec-approvals-cli-KbFpgd-p.js} +9 -9
- package/dist/extensionAPI.js +46 -46
- package/dist/extensions/amazon-bedrock/index.js +46 -46
- package/dist/extensions/anthropic/index.js +46 -46
- package/dist/extensions/bluebubbles/index.js +50 -50
- package/dist/extensions/bluebubbles/setup-entry.js +48 -48
- package/dist/extensions/byteplus/index.js +46 -46
- package/dist/extensions/chutes/index.js +48 -48
- package/dist/extensions/cloudflare-ai-gateway/index.js +47 -47
- package/dist/extensions/device-pair/index.js +46 -46
- package/dist/extensions/discord/index.js +48 -48
- package/dist/extensions/discord/node_modules/.package-lock.json +3 -3
- package/dist/extensions/discord/node_modules/hono/dist/adapter/service-worker/index.js +1 -3
- package/dist/extensions/discord/node_modules/hono/dist/cjs/adapter/service-worker/index.js +1 -3
- package/dist/extensions/discord/node_modules/hono/dist/cjs/helper/ssg/ssg.js +1 -1
- package/dist/extensions/discord/node_modules/hono/dist/cjs/middleware/cors/index.js +5 -2
- package/dist/extensions/discord/node_modules/hono/dist/cjs/request.js +1 -1
- package/dist/extensions/discord/node_modules/hono/dist/helper/ssg/ssg.js +1 -1
- package/dist/extensions/discord/node_modules/hono/dist/middleware/cors/index.js +5 -2
- package/dist/extensions/discord/node_modules/hono/dist/request.js +1 -1
- package/dist/extensions/discord/node_modules/hono/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/extensions/discord/node_modules/hono/dist/types/client/index.d.ts +1 -1
- package/dist/extensions/discord/node_modules/hono/dist/types/client/types.d.ts +20 -0
- package/dist/extensions/discord/node_modules/hono/dist/types/request.d.ts +1 -3
- package/dist/extensions/discord/node_modules/hono/package.json +1 -1
- package/dist/extensions/discord/setup-entry.js +48 -48
- package/dist/extensions/elevenlabs/index.js +46 -46
- package/dist/extensions/fal/index.js +46 -46
- package/dist/extensions/feishu/index.js +55 -55
- package/dist/extensions/feishu/setup-entry.js +51 -51
- package/dist/extensions/firecrawl/index.js +46 -46
- package/dist/extensions/github-copilot/index.js +47 -47
- package/dist/extensions/google/index.js +46 -46
- package/dist/extensions/huggingface/index.js +47 -47
- package/dist/extensions/imessage/index.js +49 -49
- package/dist/extensions/imessage/setup-entry.js +49 -49
- package/dist/extensions/irc/index.js +49 -49
- package/dist/extensions/irc/setup-entry.js +48 -48
- package/dist/extensions/kilocode/index.js +47 -47
- package/dist/extensions/kimi-coding/index.js +47 -47
- package/dist/extensions/line/index.js +9 -9
- package/dist/extensions/line/setup-entry.js +8 -8
- package/dist/extensions/llm-task/index.js +46 -46
- package/dist/extensions/lobster/index.js +5 -5
- package/dist/extensions/mattermost/index.js +49 -49
- package/dist/extensions/mattermost/setup-entry.js +48 -48
- package/dist/extensions/microsoft/index.js +46 -46
- package/dist/extensions/minimax/index.js +48 -48
- package/dist/extensions/mistral/index.js +47 -47
- package/dist/extensions/modelstudio/index.js +47 -47
- package/dist/extensions/moonshot/index.js +46 -46
- package/dist/extensions/nextcloud-talk/index.js +50 -50
- package/dist/extensions/nextcloud-talk/setup-entry.js +49 -49
- package/dist/extensions/ollama/index.js +5 -5
- package/dist/extensions/openai/index.js +47 -47
- package/dist/extensions/opencode/index.js +47 -47
- package/dist/extensions/opencode-go/index.js +47 -47
- package/dist/extensions/openrouter/index.js +47 -47
- package/dist/extensions/openshell/index.js +46 -46
- package/dist/extensions/qianfan/index.js +47 -47
- package/dist/extensions/qwen-portal-auth/index.js +47 -47
- package/dist/extensions/sglang/index.js +46 -46
- package/dist/extensions/signal/index.js +49 -49
- package/dist/extensions/signal/setup-entry.js +49 -49
- package/dist/extensions/slack/index.js +50 -50
- package/dist/extensions/slack/setup-entry.js +50 -50
- package/dist/extensions/synology-chat/index.js +9 -9
- package/dist/extensions/synology-chat/setup-entry.js +8 -8
- package/dist/extensions/synthetic/index.js +47 -47
- package/dist/extensions/talk-voice/index.js +46 -46
- package/dist/extensions/tavily/index.js +46 -46
- package/dist/extensions/telegram/index.js +48 -48
- package/dist/extensions/telegram/setup-entry.js +48 -48
- package/dist/extensions/together/index.js +47 -47
- package/dist/extensions/venice/index.js +47 -47
- package/dist/extensions/vercel-ai-gateway/index.js +47 -47
- package/dist/extensions/vllm/index.js +46 -46
- package/dist/extensions/voice-call/index.js +46 -46
- package/dist/extensions/volcengine/index.js +46 -46
- package/dist/extensions/xai/index.js +46 -46
- package/dist/extensions/xiaomi/index.js +47 -47
- package/dist/extensions/zai/index.js +47 -47
- package/dist/extensions/zalo/index.js +49 -49
- package/dist/extensions/zalo/setup-entry.js +48 -48
- package/dist/{feishu-C637DYYe.js → feishu-D2fuiOiy.js} +4 -4
- package/dist/{gateway-cli-BAueAYsk.js → gateway-cli-nOgyXtih.js} +72 -106
- package/dist/{gateway-install-token-DlcVm1rP.js → gateway-install-token-nvsTK8KN.js} +4 -4
- package/dist/{gateway-rpc-siKa8KpM.js → gateway-rpc-DrH142-v.js} +1 -1
- package/dist/{gateway-runtime-roiTaOKO.js → gateway-runtime-CQXKGzrv.js} +2 -2
- package/dist/{github-copilot-auth-DJljh3gq.js → github-copilot-auth-C4z2AAd8.js} +3 -3
- package/dist/{health-DU_pBiid.js → health-DEgLPyA9.js} +7 -7
- package/dist/{health-B1OK1kJg.js → health-H5nbiXvA.js} +48 -48
- package/dist/{heartbeat-summary-CMwt9qam.js → heartbeat-summary-CNCptWmA.js} +1 -1
- package/dist/{hooks-cli-D42hQEUb.js → hooks-cli-jBhsJaOg.js} +46 -46
- package/dist/{identity-file-8MUyIAOy.js → identity-file-CYQnH12I.js} +1 -1
- package/dist/{imessage-zqZjecTU.js → imessage-DYqgZpLc.js} +6 -6
- package/dist/{imessage-CZb_pS8U.js → imessage-Dau6WdE3.js} +46 -46
- package/dist/{inbound-reply-dispatch-B73AkQh4.js → inbound-reply-dispatch-BFE3xy1S.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/{internal-Bg_k56Pk.js → internal-DLE9baj7.js} +0 -24
- package/dist/{io-DE9vm7Eo.js → io-Du0b8gMO.js} +2 -2
- package/dist/{io-B7rO2wud.js → io-dJgqp8U8.js} +4 -4
- package/dist/{irc-BWzsfr2V.js → irc-BRaOVUse.js} +2 -2
- package/dist/{kb-cli-BOPGkNfJ.js → kb-cli-Cdif_vwn.js} +12 -12
- package/dist/{library-i-2ymInt.js → library-BwjFIWw3.js} +46 -46
- package/dist/{lifecycle-core-DwIo1PfK.js → lifecycle-core-DNO4MItg.js} +1 -1
- package/dist/line/send.js +6 -6
- package/dist/{line-DbTKdVgY.js → line-BCXUGrVz.js} +2 -2
- package/dist/{llm-slug-generator-Dm30OM2W.js → llm-slug-generator-B55FZ1aG.js} +3 -3
- package/dist/llm-slug-generator.js +47 -47
- package/dist/{logging-BM4mQ53W.js → logging-BvOzg0cM.js} +1 -1
- package/dist/{logging-0tvlVvFG.js → logging-nWyKsj9d.js} +5 -5
- package/dist/{login-qr-DQPSabxI.js → login-qr-C0QA3j4x.js} +46 -46
- package/dist/{logs-cli-ZnHk5eku.js → logs-cli-thlXBA9n.js} +7 -7
- package/dist/{manager.runtime-D3vjUOZF.js → manager.runtime-SoTq-tT4.js} +46 -46
- package/dist/{matrix-migration-snapshot-CRKiHq6Y.js → matrix-migration-snapshot-_6Rg-iLO.js} +2 -2
- package/dist/{mattermost-Bqn7Fd5U.js → mattermost-2nv5O_jQ.js} +2 -2
- package/dist/{mcp-cli-7aN2vJv-.js → mcp-cli-1vpy_yti.js} +5 -5
- package/dist/{mcp-config-NVrqojpu.js → mcp-config-Bmi2GUum.js} +1 -1
- package/dist/{media-understanding.runtime-DesF8Xhs.js → media-understanding.runtime-Wh-_SFK_.js} +46 -46
- package/dist/{memory-cli-CWqIJQS5.js → memory-cli-COJRHkaJ.js} +46 -46
- package/dist/{memory-search-DyxoUpq2.js → memory-search-CGmdrdM1.js} +1 -1
- package/dist/{memory-search-CgoWYj0V.js → memory-search-Cy36nO15.js} +3 -3
- package/dist/{model-picker-DX9P5pDr.js → model-picker-CYWvoS3z.js} +48 -48
- package/dist/{model-picker-Ds7-VqDS.js → model-picker-_32ihKqK.js} +4 -4
- package/dist/{model-picker.runtime-DqDt4s3S.js → model-picker.runtime-DBT5uEFi.js} +49 -49
- package/dist/{model-selection-DXFVauys.js → model-selection-014eeYCV.js} +1 -1
- package/dist/{model-suppression.runtime-8mU0VJs6.js → model-suppression.runtime-GTI9Rm85.js} +46 -46
- package/dist/{models-GXQSWyBX.js → models-Be9EWpVm.js} +54 -54
- package/dist/{models-CVG-VMBa.js → models-CX35daXC.js} +14 -14
- package/dist/{models-cli-Cvy8rGqU.js → models-cli-BYjac3oq.js} +54 -54
- package/dist/{models-config-BdanqM9X.js → models-config-Agv-ThDH.js} +46 -46
- package/dist/{models-config.providers.discovery-BHZ3WglC.js → models-config.providers.discovery-BJwjDHsg.js} +1 -1
- package/dist/{mongodb-analytics-BszyEhsq.js → mongodb-analytics-HJKYeseb.js} +2 -2
- package/dist/{mongodb-analytics-CcSYo_ae.js → mongodb-analytics-mnKJih5x.js} +1 -1
- package/dist/{mongodb-auto-setup-QcwgZSN9.js → mongodb-auto-setup-CCElSwNy.js} +2 -2
- package/dist/{mongodb-kb-C-VmGOq7.js → mongodb-kb-1tSOXXb9.js} +3 -3
- package/dist/{mongodb-kb-BotgVda9.js → mongodb-kb-CdSvNe3w.js} +2 -2
- package/dist/{mongodb-kb-search-CoIAFX8n.js → mongodb-kb-search-Dq6E746K.js} +1 -1
- package/dist/{mongodb-kb-search-BBYY_d_r.js → mongodb-kb-search-DvsXIUy6.js} +3 -3
- package/dist/{mongodb-manager-BVfTfpHf.js → mongodb-manager-DEZIQXuo.js} +10 -10
- package/dist/{mongodb-manager-BJ0PAYF_.js → mongodb-manager-NkerSpvH.js} +1183 -331
- package/dist/{mongodb-procedures-DNPmmW5r.js → mongodb-procedures-DI-_Dakz.js} +7 -3
- package/dist/{mongodb-procedures-D3M2Ph8E.js → mongodb-procedures-tjhGdBV7.js} +3 -3
- package/dist/{mongodb-schema-JpDXcAUV.js → mongodb-schema-DN3aspLa.js} +1 -1
- package/dist/{mongodb-schema-BI4Ze_ZV.js → mongodb-schema-Dt6jxcPL.js} +298 -4
- package/dist/{mongodb-search-VFKd72IZ.js → mongodb-search-DMsUyfpa.js} +2 -2
- package/dist/{mongodb-structured-memory-DnwUJ6SA.js → mongodb-structured-memory-D-3SEfTu.js} +58 -2
- package/dist/{mongodb-structured-memory-BySGexcm.js → mongodb-structured-memory-lpyyW0kn.js} +3 -3
- package/dist/{monitor-DGE0bx3s.js → monitor-BZFy1RTb.js} +47 -47
- package/dist/{monitor-Dfc0KXMD.js → monitor-DPYGxeY_.js} +5 -5
- package/dist/{monitor-CZZlkQUU.js → monitor-Duykki-j.js} +51 -51
- package/dist/{monitor-B61bVnMW.js → monitor-gq31SALd.js} +8 -8
- package/dist/{nextcloud-talk-CnwOv1rG.js → nextcloud-talk-C_-LfGeq.js} +2 -2
- package/dist/{node-cli-Avub0RKe.js → node-cli-NpJzvfQW.js} +12 -12
- package/dist/{nodes-cli-qSE-cmgX.js → nodes-cli-O5HciXeP.js} +10 -10
- package/dist/{nodes-screen-DQw8F5rA.js → nodes-screen-BIwiB35h.js} +1 -1
- package/dist/{oauth.runtime-825pMCgB.js → oauth.runtime-BxjW8DFO.js} +46 -46
- package/dist/{oauth.runtime-BCwH9-Yl.js → oauth.runtime-DKU2STuA.js} +46 -46
- package/dist/{oauth.runtime-BSddaUzc.js → oauth.runtime-mFizWM72.js} +46 -46
- package/dist/{onboard-CUbnVxXL.js → onboard-B6H0qDtg.js} +1 -1
- package/dist/{onboard-BF8cNljJ.js → onboard-C1AmXQ6f.js} +8 -8
- package/dist/{onboard-Cw65XmEU.js → onboard-DPdj0IBu.js} +2 -2
- package/dist/{onboard-channels-BYNDTtRI.js → onboard-channels-Cmj_5qXQ.js} +24 -24
- package/dist/{onboard-channels-CIR1ZSii.js → onboard-channels-Wf3nY9Bf.js} +97 -97
- package/dist/{onboard-custom-FImARgQC.js → onboard-custom-DILgXkiq.js} +50 -50
- package/dist/{onboard-custom-C4qOVxtG.js → onboard-custom-DlDCjvIw.js} +4 -4
- package/dist/{onboard-helpers-DW9Mskds.js → onboard-helpers-CqpD9TVU.js} +48 -48
- package/dist/{onboard-helpers-D3xV_T96.js → onboard-helpers-D-PLdtHT.js} +3 -3
- package/dist/{onboard-hooks-B0gJVtBY.js → onboard-hooks-MQ8QOguv.js} +2 -2
- package/dist/{onboard-remote-BMLo6WKH.js → onboard-remote-BZKWgKVw.js} +50 -50
- package/dist/{onboard-remote-XUah3N3G.js → onboard-remote-Bnad5LMv.js} +2 -2
- package/dist/{onboard-search-DHCzqxgq.js → onboard-search-Dyv1IuQ4.js} +46 -46
- package/dist/{onboard-skills-LXCIpyir.js → onboard-skills-DdCu1_hE.js} +1 -1
- package/dist/{onboard-skills-CH6q90Pf.js → onboard-skills-W_252asS.js} +49 -49
- package/dist/{onboarding-memory-CTB-Vkbl.js → onboarding-memory-BRHSmwx3.js} +6 -6
- package/dist/{outbound-media-CqfP0r4a.js → outbound-media-CHc08Sj8.js} +1 -1
- package/dist/{pairing-cli-BdCkQG2S.js → pairing-cli-oNWkjwCt.js} +5 -5
- package/dist/{persistent-dedupe-DNnh7hrR.js → persistent-dedupe-CS_uyVoq.js} +1 -1
- package/dist/{pi-model-discovery-runtime-DyT9C3Ap.js → pi-model-discovery-runtime-BJVREOXf.js} +46 -46
- package/dist/{pi-tools.before-tool-call.runtime-CA2js1Ig.js → pi-tools.before-tool-call.runtime-w-Q4HA_S.js} +6 -6
- package/dist/{plugin-install-DgvJfz7X.js → plugin-install-BysMw7Sl.js} +47 -47
- package/dist/{plugin-install-BKuy_--2.js → plugin-install-EyES0vGP.js} +2 -2
- package/dist/{plugin-registry-D-6OBqUU.js → plugin-registry-BenF9SYR.js} +47 -47
- package/dist/{plugin-registry-Dsx_6z3N.js → plugin-registry-CRV_Bc8K.js} +3 -3
- package/dist/plugin-sdk/account-resolution.js +46 -46
- package/dist/plugin-sdk/acp-runtime.js +46 -46
- package/dist/plugin-sdk/agent-runtime.js +46 -46
- package/dist/plugin-sdk/channel-inbound.js +46 -46
- package/dist/plugin-sdk/channel-reply-pipeline.js +3 -3
- package/dist/plugin-sdk/channel-runtime.js +46 -46
- package/dist/plugin-sdk/channel-setup.js +1 -1
- package/dist/plugin-sdk/command-auth.js +46 -46
- package/dist/plugin-sdk/compat.js +5 -5
- package/dist/plugin-sdk/config-runtime.js +46 -46
- package/dist/plugin-sdk/conversation-runtime.js +46 -46
- package/dist/plugin-sdk/core.js +5 -5
- package/dist/plugin-sdk/directory-runtime.js +1 -1
- package/dist/plugin-sdk/discord.js +46 -46
- package/dist/plugin-sdk/gateway-runtime.js +8 -8
- package/dist/plugin-sdk/image-generation.js +46 -46
- package/dist/plugin-sdk/index.js +46 -46
- package/dist/plugin-sdk/infra-runtime.js +46 -46
- package/dist/plugin-sdk/llm-task.js +46 -46
- package/dist/plugin-sdk/matrix-runtime-heavy.js +50 -50
- package/dist/plugin-sdk/media-runtime.js +46 -46
- package/dist/plugin-sdk/media-understanding-runtime.js +46 -46
- package/dist/plugin-sdk/media-understanding.js +46 -46
- package/dist/plugin-sdk/ollama-setup.js +8 -8
- package/dist/plugin-sdk/plugin-runtime.js +46 -46
- package/dist/plugin-sdk/provider-auth-api-key.js +46 -46
- package/dist/plugin-sdk/provider-auth-login.js +1 -1
- package/dist/plugin-sdk/provider-auth.js +46 -46
- package/dist/plugin-sdk/provider-models.js +5 -5
- package/dist/plugin-sdk/provider-onboard.js +5 -5
- package/dist/plugin-sdk/provider-setup.js +49 -49
- package/dist/plugin-sdk/provider-stream.js +46 -46
- package/dist/plugin-sdk/provider-usage.js +4 -4
- package/dist/plugin-sdk/reply-history.js +3 -3
- package/dist/plugin-sdk/reply-runtime.js +46 -46
- package/dist/plugin-sdk/routing.js +3 -3
- package/dist/plugin-sdk/sandbox.js +46 -46
- package/dist/plugin-sdk/self-hosted-provider-setup.js +48 -48
- package/dist/plugin-sdk/setup-runtime.js +1 -1
- package/dist/plugin-sdk/setup.js +1 -1
- package/dist/plugin-sdk/speech-runtime.js +46 -46
- package/dist/plugin-sdk/speech.js +46 -46
- package/dist/plugin-sdk/src/agents/workspace.d.ts +1 -3
- package/dist/plugin-sdk/src/config/types.memory.d.ts +44 -0
- package/dist/plugin-sdk/src/memory/backend-config.d.ts +24 -0
- package/dist/plugin-sdk/src/memory/index.d.ts +12 -4
- package/dist/plugin-sdk/src/memory/mongodb-entity-extractor.d.ts +33 -0
- package/dist/plugin-sdk/src/memory/mongodb-episodes.d.ts +16 -0
- package/dist/plugin-sdk/src/memory/mongodb-events.d.ts +9 -0
- package/dist/plugin-sdk/src/memory/mongodb-graph.d.ts +30 -3
- package/dist/plugin-sdk/src/memory/mongodb-manager.d.ts +18 -0
- package/dist/plugin-sdk/src/memory/mongodb-mutations.d.ts +38 -0
- package/dist/plugin-sdk/src/memory/mongodb-procedures.d.ts +32 -0
- package/dist/plugin-sdk/src/memory/mongodb-profile.d.ts +71 -0
- package/dist/plugin-sdk/src/memory/mongodb-query-cache.d.ts +68 -0
- package/dist/plugin-sdk/src/memory/mongodb-query-rewriter.d.ts +39 -0
- package/dist/plugin-sdk/src/memory/mongodb-reranker.d.ts +32 -0
- package/dist/plugin-sdk/src/memory/mongodb-schema.d.ts +3 -0
- package/dist/plugin-sdk/src/memory/mongodb-telemetry.d.ts +69 -0
- package/dist/plugin-sdk/text-runtime.js +6 -6
- package/dist/plugin-sdk/web-media.js +3 -3
- package/dist/plugin-sdk/zalo.js +47 -47
- package/dist/plugin-sdk/zalouser.js +47 -47
- package/dist/plugins/build-smoke-entry.js +46 -46
- package/dist/plugins/runtime/index.js +46 -46
- package/dist/{plugins-cli-C6wGAkD9.js → plugins-cli-BUiP4x7l.js} +46 -46
- package/dist/{policy-CcgojW9R.js → policy-DnUfJkOZ.js} +1 -1
- package/dist/{preflight-audio.runtime-Cyz9Zu89.js → preflight-audio.runtime-D3_iaSgF.js} +46 -46
- package/dist/{probe-auth-BmluVNJZ.js → probe-auth-BbNdYwb0.js} +1 -1
- package/dist/{probe-auth-DrgTJ7ki.js → probe-auth-CB9y2dLl.js} +7 -7
- package/dist/{program-BjkVOzbF.js → program-uHYlUP3c.js} +4 -4
- package/dist/{prompt-select-styled-6vDD4Gjv.js → prompt-select-styled-DoTAWghe.js} +25 -51
- package/dist/{provider-api-key-auth.runtime-AT16DTa8.js → provider-api-key-auth.runtime-B3H0dODg.js} +46 -46
- package/dist/{provider-auth-choice-UhIkLc6q.js → provider-auth-choice-HRfxXEHk.js} +6 -6
- package/dist/{provider-auth-choice-helpers-CXWmWOdR.js → provider-auth-choice-helpers-2jZnBKMm.js} +1 -1
- package/dist/{provider-auth-choice-preference-TgulgKlz.js → provider-auth-choice-preference-CqKryjBB.js} +6 -6
- package/dist/{provider-auth-choice.runtime-FTNgi8Yh.js → provider-auth-choice.runtime-BaFSZgQG.js} +48 -48
- package/dist/{provider-auth-choice.runtime-CP91b3vK.js → provider-auth-choice.runtime-DPHuj1_l.js} +2 -2
- package/dist/{provider-auth-choices-BfWvatIg.js → provider-auth-choices-CqFh00uK.js} +1 -1
- package/dist/{provider-auth-guidance-D4-q7IHl.js → provider-auth-guidance-DmdBoDfS.js} +2 -2
- package/dist/{provider-auth-input-DnQ-RiX5.js → provider-auth-input-FZYEJh19.js} +46 -46
- package/dist/{provider-auth-login-D7eLUZwy.js → provider-auth-login-B-XedaK5.js} +1 -1
- package/dist/{provider-auth-login.runtime-BG_qqxZk.js → provider-auth-login.runtime-f9dxfJUB.js} +49 -49
- package/dist/{provider-model-allowlist-CC0lIQ6w.js → provider-model-allowlist-C16pn0B8.js} +1 -1
- package/dist/{provider-models-DbK6xrje.js → provider-models-PaymKOme.js} +1 -1
- package/dist/{provider-ollama-setup-B4RWr9oj.js → provider-ollama-setup-k5ozCUi2.js} +3 -3
- package/dist/{provider-onboarding-config-W5sF0oD8.js → provider-onboarding-config-qCltsaVl.js} +1 -1
- package/dist/{provider-runtime.runtime-Cva8S4wx.js → provider-runtime.runtime-CzVe0WBb.js} +46 -46
- package/dist/{provider-self-hosted-setup-jAzqLaqv.js → provider-self-hosted-setup-zxYnIftX.js} +3 -3
- package/dist/{provider-usage-CEgSCMW4.js → provider-usage-C9KdAhuS.js} +46 -46
- package/dist/{provider-usage-CCIC3SdY.js → provider-usage-DexJNI_0.js} +1 -1
- package/dist/{provider-wizard-DQd5eYhX.js → provider-wizard-D4RbMR2D.js} +2 -2
- package/dist/{push-apns-DQN5pcl6.js → push-apns-BAc0-Jy5.js} +1 -1
- package/dist/{pw-ai-BiXz8un2.js → pw-ai-C8v0s5wH.js} +6 -6
- package/dist/{qr-cli-B8bBpCd2.js → qr-cli-BpqLcmYC.js} +47 -47
- package/dist/{qr-cli-DOuhqzho.js → qr-cli-D0zqiQMl.js} +4 -4
- package/dist/{reactions-BkyHqIw4.js → reactions-CjJbniYK.js} +1 -1
- package/dist/{read-only-account-inspect-Cfaj7PFb.js → read-only-account-inspect-CEJ1r7AW.js} +3 -3
- package/dist/{read-only-account-inspect.discord.runtime-kreMwVgq.js → read-only-account-inspect.discord.runtime-C1n8r_Kj.js} +46 -46
- package/dist/{read-only-account-inspect.slack.runtime-DgV5VZ-n.js → read-only-account-inspect.slack.runtime-DAOzA9ke.js} +46 -46
- package/dist/{read-only-account-inspect.telegram.runtime-BQaHHCIS.js → read-only-account-inspect.telegram.runtime-CfNlnogC.js} +46 -46
- package/dist/{redact-snapshot-PisBVQFW.js → redact-snapshot-qQFn3bz8.js} +3 -3
- package/dist/{register.agent-CXTssAWM.js → register.agent-DC5QbIE7.js} +114 -114
- package/dist/{register.backup-MRTb86c6.js → register.backup-BRxspFkM.js} +6 -6
- package/dist/{register.configure-BfE3p-3h.js → register.configure-B7zhRBla.js} +120 -120
- package/dist/{register.maintenance-CjOZ-w_0.js → register.maintenance-CCmppLW1.js} +65 -65
- package/dist/{register.message-s1z2QSP2.js → register.message-DSBPJS4x.js} +47 -47
- package/dist/{register.onboard-GSGJTcJk.js → register.onboard-C4D9pjf7.js} +54 -54
- package/dist/{register.setup-BD774nEM.js → register.setup-C4pDa0HW.js} +52 -52
- package/dist/{register.status-health-sessions-D-Xp8ae7.js → register.status-health-sessions-ClxLTjC5.js} +55 -55
- package/dist/{register.subclis-BlqPR8UO.js → register.subclis-BauDruMA.js} +30 -30
- package/dist/{register.subclis-CeG9qCbt.js → register.subclis-WyYRaoa-.js} +1 -1
- package/dist/{replies-DQwDaTBP.js → replies-CZGcXYVE.js} +1 -1
- package/dist/{reply-history-DVLrt4Es.js → reply-history-1yT9Tzib.js} +1 -1
- package/dist/{routes-CBWjQBhD.js → routes-D8CYDLDF.js} +5 -5
- package/dist/{rpc-O719GSVf.js → rpc-D8I_Qzen.js} +1 -1
- package/dist/{run-main-C4Box4Zo.js → run-main-BwEbDjI-.js} +19 -19
- package/dist/{runtime-COpSaRtb.js → runtime-CmSMHqwN.js} +1 -1
- package/dist/{runtime-PbP8BVEV.js → runtime-DQaeo-1L.js} +2 -2
- package/dist/{runtime-discord-ops.runtime-CmStqYK4.js → runtime-discord-ops.runtime-8w-055sR.js} +46 -46
- package/dist/{runtime-slack-ops.runtime-Cm1935hR.js → runtime-slack-ops.runtime-XJJrByCY.js} +48 -48
- package/dist/{runtime-telegram-ops.runtime-CKozoVxf.js → runtime-telegram-ops.runtime-wOdrd2eH.js} +46 -46
- package/dist/{sandbox-cli-BIyJ-1r-.js → sandbox-cli-CvFmY6Kq.js} +46 -46
- package/dist/{search-manager-BVE1EPHv.js → search-manager-ZNiamJHa.js} +6 -6
- package/dist/{search-manager-DMTYqpmg.js → search-manager-zaZ4tAYz.js} +5 -5
- package/dist/{secrets-cli-CMMtWzst.js → secrets-cli-D5a_lvAP.js} +47 -47
- package/dist/{security-cli-Bw4cVkTN.js → security-cli-DJovxmST.js} +47 -47
- package/dist/{send-CfI8y11o.js → send-C3KhjjcU.js} +1 -1
- package/dist/{send-C8HDmafP.js → send-CIkS5fLj.js} +2 -2
- package/dist/{server-0n2tu0ff.js → server-B1z10Ohi.js} +6 -6
- package/dist/{server-node-events-J5-mGOea.js → server-node-events-D3_b2nU-.js} +47 -47
- package/dist/{server-startup-matrix-migration-CMBUtdN2.js → server-startup-matrix-migration-DDRaKUPQ.js} +3 -3
- package/dist/{session-cost-usage-CrPCO4HN.js → session-cost-usage-BwIud0lY.js} +46 -46
- package/dist/{sessions-n_Z6bcbr.js → sessions-B5Pffwj6.js} +3 -3
- package/dist/{sessions-BK_M3Nu1.js → sessions-ClamZkvP.js} +47 -47
- package/dist/{setup-CjQJLNqB.js → setup-B8gsbmH4.js} +18 -18
- package/dist/{setup-core-BVBCTInv.js → setup-core-B6csKf5s.js} +2 -2
- package/dist/{setup-core-z8Q1sgUU.js → setup-core-DkgiVKzw.js} +2 -2
- package/dist/{setup-entry-CvuaW-4I.js → setup-entry-C8XH3da9.js} +2 -2
- package/dist/{setup-entry-Jf6V23s6.js → setup-entry-CMSlnfft.js} +3 -3
- package/dist/{setup-entry-Bo3chgoG.js → setup-entry-CZVAwPKZ.js} +2 -2
- package/dist/{setup-entry-Co-YP41_.js → setup-entry-Duh-ewBV.js} +3 -3
- package/dist/{setup-entry-BnSZlMP1.js → setup-entry-ksUWY45r.js} +2 -2
- package/dist/{setup-entry-BNSYJMzp.js → setup-entry-vQgAuveW.js} +2 -2
- package/dist/{setup-group-access-BYV3O8yu.js → setup-group-access-CTlnq-M9.js} +1 -1
- package/dist/{setup-surface-B6XBqyMJ.js → setup-surface-B7uYEI9F.js} +2 -2
- package/dist/{setup-surface-fixjWejm.js → setup-surface-CMgQr2R9.js} +5 -5
- package/dist/{setup-surface-CzzV3QV6.js → setup-surface-Yd-YLGfa.js} +46 -46
- package/dist/{setup-wizard-proxy-DFDQV7FN.js → setup-wizard-proxy-CHGAY6ob.js} +1 -1
- package/dist/{setup.finalize-ChczeW6V.js → setup.finalize-C2bq4D8j.js} +58 -58
- package/dist/{setup.gateway-config-Bp50kjo3.js → setup.gateway-config-BGgVOvQf.js} +48 -48
- package/dist/{shared-CyR3Ki--.js → shared-BEMZg0vb.js} +5 -5
- package/dist/{shared-DXzPv5D7.js → shared-BYRyVoVx.js} +5 -5
- package/dist/{shared-DCOVJ3QB.js → shared-Bj3fwdyM.js} +4 -4
- package/dist/{shared-B8_JHpU2.js → shared-CSydqOgE.js} +4 -4
- package/dist/{shared-C3fKAUbw.js → shared-DLAg-pKT.js} +3 -3
- package/dist/{signal-D16eMrBf.js → signal-Dh6z2uaT.js} +5 -5
- package/dist/{signal-oGrspg1k.js → signal-FEtxekyc.js} +46 -46
- package/dist/{skills-cli-CY6lUTRv.js → skills-cli-9NuRJd3Z.js} +5 -5
- package/dist/{slack-ueYeeNF7.js → slack-Ci1VArkq.js} +48 -48
- package/dist/{slack-B1GgT1_u.js → slack-CjslLjTc.js} +5 -5
- package/dist/{slash-commands.runtime-1q-llUpe.js → slash-commands.runtime-COXzcGjL.js} +46 -46
- package/dist/{slash-dispatch.runtime-BqJ1FZZ6.js → slash-dispatch.runtime-D5j8d7dg.js} +47 -47
- package/dist/{slash-skill-commands.runtime-D-BEZgQ1.js → slash-skill-commands.runtime-6U65Nany.js} +46 -46
- package/dist/{status-CnKcjD2h.js → status-BWUft8B5.js} +16 -16
- package/dist/{status-C1BR9Hft.js → status-BjV1ysoW.js} +50 -50
- package/dist/{status-D_1nxvoi.js → status-CM77XYRR.js} +4 -4
- package/dist/{status-Dp3OriYl.js → status-D7XHAzLz.js} +46 -46
- package/dist/{status-DoSH4nEL.js → status-DwO4xEHI.js} +54 -54
- package/dist/{status-json-DwNPzoCk.js → status-json-BYDBfkr3.js} +19 -19
- package/dist/{status-B45v-A8b.js → status-yoA_KX2O.js} +1 -1
- package/dist/{status.link-channel-Cz8GoHZ2.js → status.link-channel-DkISMfW8.js} +2 -2
- package/dist/{status.scan.deps.runtime-BQGei2B_.js → status.scan.deps.runtime-B6__B0kL.js} +14 -14
- package/dist/{status.scan.runtime-D4HkKTZu.js → status.scan.runtime-BAkcX3vO.js} +2 -2
- package/dist/{status.summary-Dxo5qDuD.js → status.summary-DNaMhaXy.js} +8 -8
- package/dist/{subagent-orphan-recovery-BPa7yoId.js → subagent-orphan-recovery-DtK8inah.js} +46 -46
- package/dist/{subagent-registry-runtime-B6homy_H.js → subagent-registry-runtime-02s7QJo3.js} +46 -46
- package/dist/{synology-chat-DY8xNv_g.js → synology-chat-QURTpvMf.js} +2 -2
- package/dist/{system-cli-CkWRbLu4.js → system-cli-BXd7evEt.js} +7 -7
- package/dist/{system-run-command-jY6Is_ri.js → system-run-command-CQCx0f24.js} +1 -1
- package/dist/telegram/audit.js +1 -1
- package/dist/telegram/token.js +46 -46
- package/dist/{telegram-uQdpyLeS.js → telegram-Btwvg0PX.js} +46 -46
- package/dist/{telegram-Bnigf1Qe.js → telegram-Dh5gM1mc.js} +7 -7
- package/dist/{tool-policy-match-BLASiL8y.js → tool-policy-match-B6J0bSfQ.js} +1 -1
- package/dist/{tui-Dj52JiFV.js → tui-CKGcNyM8.js} +6 -6
- package/dist/{tui-cli-B4SN4wzX.js → tui-cli-D3CLnnB9.js} +47 -47
- package/dist/{update-cli-mBB0aHxZ.js → update-cli-DQ4j_nIh.js} +69 -69
- package/dist/{update-offset-store-Bp1RjZK2.js → update-offset-store-RxVdgbyo.js} +46 -46
- package/dist/{upsert-with-lock-CFIy4b7I.js → upsert-with-lock-BqkAnFym.js} +1 -1
- package/dist/{web-media-BJ-azd7j.js → web-media-BM1Mg6AN.js} +1 -1
- package/dist/{webhook-shared-DYKTXPVw.js → webhook-shared-UDKLpQnU.js} +1 -1
- package/dist/{webhooks-cli-CEBJbLqS.js → webhooks-cli-Ca3PlK8h.js} +5 -5
- package/dist/{whatsapp-63jqHVrE.js → whatsapp-CHEvDa2g.js} +46 -46
- package/dist/{with-timeout-CvaBvNie.js → with-timeout-CvBH67nj.js} +2 -2
- package/dist/{workspace-DuH1agxz.js → workspace-uCYzunu4.js} +5 -33
- package/dist/{zalo-CTrI2C4i.js → zalo-Dr4ysJLW.js} +1 -1
- package/dist/{zalo-Sw_XHo3-.js → zalo-keqX1Wnx.js} +2 -2
- package/docs/concepts/agent-workspace.md +0 -5
- package/docs/concepts/memory.md +6 -12
- package/docs/plans/2026-03-22-semantic-cache-telemetry-docs-plan.md +1431 -0
- package/docs/plans/2026-03-22-supermemory-steals-plan.md +1679 -0
- package/docs/plans/2026-03-23-almost-perfect-sprint-plan.md +1080 -0
- package/docs/plans/2026-03-23-master-steal-list.md +224 -0
- package/docs/plans/2026-03-23-memory-md-deprecation-plan.md +632 -0
- package/docs/plans/2026-03-23-production-readiness-e2e-plan.md +659 -0
- package/docs/plans/2026-03-23-supermemory-audit-fixes-plan.md +1291 -0
- package/docs/reference/clawmongo-vs-default-memory.md +2 -2
- package/docs/reference/heart-brain-boundary.md +8 -10
- package/docs/reference/memory-config.md +3 -4
- package/docs/reference/mongodb-capabilities.md +246 -9
- package/docs/reference/templates/AGENTS.md +5 -10
- package/docs/research/2026-03-22-atlas-local-preview-web.md +41 -31
- package/docs/research/2026-03-23-agent-management-ui-github.md +482 -0
- package/docs/research/2026-03-23-almost-perfect-mongodb-docs.md +255 -0
- package/docs/research/2026-03-23-company-os-agent-ui-web.md +511 -0
- package/docs/research/2026-03-23-supermemory-audit-fixes-mongodb-research.md +995 -0
- package/docs/start/clawmongo-getting-started.md +1 -1
- package/package.json +1 -1
- /package/dist/{memory-BAVM2Jxh.js → memory-CcbELE82.js} +0 -0
|
@@ -0,0 +1,1431 @@
|
|
|
1
|
+
# Semantic Query Cache + Time Series Observability + Docs Update
|
|
2
|
+
|
|
3
|
+
> **For Claude:** REQUIRED: Follow this plan task-by-task using TDD.
|
|
4
|
+
> **Design:** Pre-answered requirements in user request; no separate design doc.
|
|
5
|
+
|
|
6
|
+
**Goal:** Add two final pre-launch features to ClawMongo v2 (semantic query cache, time series observability) and update documentation, bringing the total to 22 collections, 58 standard indexes, and 9 search indexes.
|
|
7
|
+
|
|
8
|
+
**Architecture:** Feature 1 adds a `query_cache` regular collection with $jsonSchema validation, a unique compound index for exact-match (Tier 1), and a vector search index with autoEmbed for semantic match (Tier 2). Feature 2 adds a `memory_telemetry` time series collection with fire-and-forget emission from 5 code paths. Feature 3 updates README and docs to reflect the new capabilities.
|
|
9
|
+
|
|
10
|
+
**Tech Stack:** MongoDB Community + mongot, TypeScript ESM, Vitest, autoEmbed (voyage-4-large), time series collections.
|
|
11
|
+
|
|
12
|
+
**Prerequisites:** All v2 base + enhancements + consolidation + upstream syncs complete. Published @romiluz/clawmongo@2026.3.22.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Relevant Codebase Files
|
|
17
|
+
|
|
18
|
+
### Patterns to Follow
|
|
19
|
+
|
|
20
|
+
- `src/memory/mongodb-schema.ts` (lines 457-674) — $jsonSchema validators (EVENTS_SCHEMA, ENTITIES_SCHEMA as patterns)
|
|
21
|
+
- `src/memory/mongodb-schema.ts` (lines 1145-1450) — ensureSearchIndexes with autoEmbed index creation pattern
|
|
22
|
+
- `src/memory/mongodb-schema.ts` (lines 756-960) — ensureStandardIndexes with TTL index pattern
|
|
23
|
+
- `src/memory/mongodb-schema.ts` (lines 676-723) — ensureCollections with validator application
|
|
24
|
+
- `src/memory/mongodb-search.ts` (lines 200-230) — buildVectorSearchStage with autoEmbed queryText
|
|
25
|
+
- `src/memory/mongodb-ops.ts` (lines 1-80) — standalone function pattern (db, prefix, ...)
|
|
26
|
+
- `src/memory/mongodb-manager.ts` (lines 730-790) — search() entry point where cache hooks in
|
|
27
|
+
- `src/memory/mongodb-manager.ts` (lines 2511-2550) — searchV2 function signature
|
|
28
|
+
- `src/memory/mongodb-manager.ts` (lines 2301-2400) — writeEventAndProject (telemetry emission point)
|
|
29
|
+
- `src/memory/mongodb-graph.ts` (lines 1-50) — expandGraph (telemetry emission point)
|
|
30
|
+
- `src/memory/backend-config.ts` (lines 26-80) — ResolvedMongoDBConfig type
|
|
31
|
+
|
|
32
|
+
### Configuration Files
|
|
33
|
+
|
|
34
|
+
- `src/config/types.memory.ts` — MemoryMongoDBConfig type (where cache config goes)
|
|
35
|
+
- `src/memory/index.ts` — barrel exports
|
|
36
|
+
|
|
37
|
+
### Existing Index/Collection Counts
|
|
38
|
+
|
|
39
|
+
- Collections: 20 (becomes 22 with query_cache + memory_telemetry)
|
|
40
|
+
- Standard indexes: 53 (becomes 58 with 5 new: 3 query_cache + 2 telemetry meta)
|
|
41
|
+
- Search indexes: 8 (becomes 9 with query_cache vector)
|
|
42
|
+
- Note: The telemetry TTL is handled by the time series `expireAfterSeconds` option, not a standard index
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Validated MongoDB Syntax (from existing codebase patterns)
|
|
47
|
+
|
|
48
|
+
### autoEmbed Vector Index Definition (mongodb-schema.ts:1224-1234)
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
const vectorDef: Document = {
|
|
52
|
+
fields: [
|
|
53
|
+
{ type: "autoEmbed", modality: "text", path: "queryNorm", model: "voyage-4-large" },
|
|
54
|
+
{ type: "filter", path: "agentId" },
|
|
55
|
+
{ type: "filter", path: "scope" },
|
|
56
|
+
{ type: "filter", path: "scopeRef" },
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
await collection.createSearchIndex({
|
|
60
|
+
name: `${prefix}query_cache_vector`,
|
|
61
|
+
type: "vectorSearch",
|
|
62
|
+
definition: vectorDef,
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### $vectorSearch with autoEmbed queryText (mongodb-search.ts:222-224)
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// For automated embedding mode:
|
|
70
|
+
base.query = { text: input.queryText };
|
|
71
|
+
base.path = "queryNorm"; // field path that autoEmbed indexes
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### findOneAndUpdate with $inc (MongoDB driver pattern)
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
await collection.findOneAndUpdate(
|
|
78
|
+
{ queryHash, agentId, scope, scopeRef },
|
|
79
|
+
{ $inc: { hitCount: 1 }, $set: { lastHitAt: new Date() } },
|
|
80
|
+
{ returnDocument: "before" }, // return cached doc before update
|
|
81
|
+
);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Time Series Collection Creation (MongoDB driver pattern)
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
await db.createCollection(`${prefix}memory_telemetry`, {
|
|
88
|
+
timeseries: {
|
|
89
|
+
timeField: "ts",
|
|
90
|
+
metaField: "meta",
|
|
91
|
+
granularity: "seconds",
|
|
92
|
+
},
|
|
93
|
+
expireAfterSeconds: 604800, // 7 days
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**CRITICAL:** Time series collections do NOT support $jsonSchema validators. Use runtime TypeScript types only.
|
|
98
|
+
|
|
99
|
+
### Fire-and-Forget insertOne (mongodb-ops.ts:57 pattern)
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
collection.insertOne(doc).catch((err) => {
|
|
103
|
+
log.warn("telemetry emit failed", { error: err });
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Phase 1: Semantic Query Cache Collection and Schema
|
|
110
|
+
|
|
111
|
+
> **Exit Criteria:** `query_cache` collection created with $jsonSchema, unique compound index, TTL index, and vector search index. Collection accessor exported. 18+ tests pass.
|
|
112
|
+
|
|
113
|
+
### Task 1.1: Add query_cache collection accessor to mongodb-schema.ts
|
|
114
|
+
|
|
115
|
+
**Files:**
|
|
116
|
+
|
|
117
|
+
- Modify: `src/memory/mongodb-schema.ts` (add collection accessor after line ~116)
|
|
118
|
+
|
|
119
|
+
**Step 1:** Add collection accessor function (follows existing pattern: `col(db, prefix, name)`)
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
export function queryCacheCollection(db: Db, prefix: string): Collection {
|
|
123
|
+
return col(db, prefix, "query_cache");
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Step 2:** Add to ensureCollections needed array (after "projection_runs" at line ~703)
|
|
128
|
+
|
|
129
|
+
Add `"query_cache"` to the `needed` array.
|
|
130
|
+
|
|
131
|
+
**Step 3:** Verify by running schema tests
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
pnpm test -- src/memory/mongodb-schema.test.ts
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Task 1.2: Add QUERY_CACHE_SCHEMA $jsonSchema validator
|
|
138
|
+
|
|
139
|
+
**Files:**
|
|
140
|
+
|
|
141
|
+
- Modify: `src/memory/mongodb-schema.ts` (add schema constant before VALIDATED_COLLECTIONS)
|
|
142
|
+
|
|
143
|
+
**Schema definition:**
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const QUERY_CACHE_SCHEMA: Document = {
|
|
147
|
+
$jsonSchema: {
|
|
148
|
+
bsonType: "object",
|
|
149
|
+
required: [
|
|
150
|
+
"queryHash",
|
|
151
|
+
"queryNorm",
|
|
152
|
+
"agentId",
|
|
153
|
+
"scope",
|
|
154
|
+
"scopeRef",
|
|
155
|
+
"results",
|
|
156
|
+
"pathUsed",
|
|
157
|
+
"sourceScope",
|
|
158
|
+
"createdAt",
|
|
159
|
+
"expiresAt",
|
|
160
|
+
"hitCount",
|
|
161
|
+
"lastHitAt",
|
|
162
|
+
],
|
|
163
|
+
properties: {
|
|
164
|
+
queryHash: { bsonType: "string", description: "SHA-256 of normalized query" },
|
|
165
|
+
queryNorm: { bsonType: "string", description: "Normalized query text (autoEmbed source)" },
|
|
166
|
+
agentId: { bsonType: "string", description: "Agent that generated this cache entry" },
|
|
167
|
+
scope: { enum: SCOPE_ENUM, description: "Memory scope" },
|
|
168
|
+
scopeRef: { bsonType: "string", description: "Resolved scope namespace" },
|
|
169
|
+
results: { bsonType: "array", description: "Cached MemorySearchResult[]" },
|
|
170
|
+
pathUsed: { bsonType: "string", description: "Retrieval path that produced results" },
|
|
171
|
+
sourceScope: { bsonType: "string", description: "Source scope for cache partitioning" },
|
|
172
|
+
createdAt: { bsonType: "date" },
|
|
173
|
+
expiresAt: { bsonType: "date", description: "Per-document TTL expiry" },
|
|
174
|
+
hitCount: { bsonType: "number", minimum: 0 },
|
|
175
|
+
lastHitAt: { bsonType: "date" },
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Step 2:** Add to VALIDATED_COLLECTIONS map
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
query_cache: QUERY_CACHE_SCHEMA,
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Task 1.3: Add query_cache standard indexes to ensureStandardIndexes
|
|
188
|
+
|
|
189
|
+
**Files:**
|
|
190
|
+
|
|
191
|
+
- Modify: `src/memory/mongodb-schema.ts` (add after entity_links indexes section, before `return applied`)
|
|
192
|
+
|
|
193
|
+
**Indexes:**
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// Query Cache indexes
|
|
197
|
+
const queryCache = queryCacheCollection(db, prefix);
|
|
198
|
+
await queryCache.createIndex(
|
|
199
|
+
{ queryHash: 1, agentId: 1, scope: 1, scopeRef: 1 },
|
|
200
|
+
{ name: "uq_query_cache_hash_agent_scope_scoperef", unique: true },
|
|
201
|
+
);
|
|
202
|
+
applied++;
|
|
203
|
+
await queryCache.createIndex(
|
|
204
|
+
{ expiresAt: 1 },
|
|
205
|
+
{ name: "idx_query_cache_ttl", expireAfterSeconds: 0 },
|
|
206
|
+
);
|
|
207
|
+
applied++;
|
|
208
|
+
await queryCache.createIndex(
|
|
209
|
+
{ agentId: 1, hitCount: -1 },
|
|
210
|
+
{ name: "idx_query_cache_agent_hitcount" },
|
|
211
|
+
);
|
|
212
|
+
applied++;
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Note:** `expireAfterSeconds: 0` on `expiresAt` field means MongoDB uses the document's `expiresAt` value as the absolute expiration time. This is the per-document TTL pattern.
|
|
216
|
+
|
|
217
|
+
### Task 1.4: Add query_cache vector search index to ensureSearchIndexes
|
|
218
|
+
|
|
219
|
+
**Files:**
|
|
220
|
+
|
|
221
|
+
- Modify: `src/memory/mongodb-schema.ts` (add after procedures search indexes, before `return` at end)
|
|
222
|
+
|
|
223
|
+
**Vector search index (autoEmbed on queryNorm field):**
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
// Query Cache search indexes
|
|
227
|
+
const queryCache = queryCacheCollection(db, prefix);
|
|
228
|
+
try {
|
|
229
|
+
const cacheVectorDef: Document = {
|
|
230
|
+
fields: [
|
|
231
|
+
{ type: "autoEmbed", modality: "text", path: "queryNorm", model: "voyage-4-large" },
|
|
232
|
+
{ type: "filter", path: "agentId" },
|
|
233
|
+
{ type: "filter", path: "scope" },
|
|
234
|
+
{ type: "filter", path: "scopeRef" },
|
|
235
|
+
],
|
|
236
|
+
};
|
|
237
|
+
await queryCache.createSearchIndex({
|
|
238
|
+
name: `${prefix}query_cache_vector`,
|
|
239
|
+
type: "vectorSearch",
|
|
240
|
+
definition: cacheVectorDef,
|
|
241
|
+
});
|
|
242
|
+
} catch (err) {
|
|
243
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
244
|
+
if (isSearchIndexManagementUnavailable(msg)) {
|
|
245
|
+
log.warn(`search index management unavailable: ${msg}`);
|
|
246
|
+
return { text: textCreated, vector: vectorCreated };
|
|
247
|
+
}
|
|
248
|
+
if (!msg.includes("already exists") && !msg.includes("duplicate")) {
|
|
249
|
+
log.warn(`query_cache vector search index creation failed: ${msg}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Update budget:** Change `assertIndexBudget(profile, 8)` to `assertIndexBudget(profile, 9)` (adding 1 vector index).
|
|
255
|
+
|
|
256
|
+
### Task 1.5: Write schema tests for query_cache
|
|
257
|
+
|
|
258
|
+
**Files:**
|
|
259
|
+
|
|
260
|
+
- Modify: `src/memory/mongodb-schema.test.ts` (add test block)
|
|
261
|
+
|
|
262
|
+
**Tests to write:**
|
|
263
|
+
|
|
264
|
+
1. `queryCacheCollection returns prefixed collection`
|
|
265
|
+
2. `QUERY_CACHE_SCHEMA validates required fields` (via ensureSchemaValidation mock)
|
|
266
|
+
3. `unique index on (queryHash, agentId, scope, scopeRef)` — verify createIndex call
|
|
267
|
+
4. `TTL index on expiresAt with expireAfterSeconds: 0` — verify createIndex call
|
|
268
|
+
5. `hitCount index on (agentId, hitCount)` — verify createIndex call
|
|
269
|
+
6. `vector search index with autoEmbed on queryNorm` — verify createSearchIndex call
|
|
270
|
+
|
|
271
|
+
**Step:** Run tests
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
pnpm test -- src/memory/mongodb-schema.test.ts
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Task 1.6: Update EXPECTED_COLLECTION_SUFFIXES and EXPECTED_STANDARD_INDEX_COUNT
|
|
278
|
+
|
|
279
|
+
**Files:**
|
|
280
|
+
|
|
281
|
+
- Modify: `src/memory/mongodb-e2e.e2e.test.ts` — add `"query_cache"` and `"memory_telemetry"` to `EXPECTED_COLLECTION_SUFFIXES` array (20 becomes 22)
|
|
282
|
+
- Modify: `src/memory/mongodb-e2e.e2e.test.ts` — update `EXPECTED_STANDARD_INDEX_COUNT` from 53 to 58 (3 query_cache + 2 telemetry meta indexes)
|
|
283
|
+
|
|
284
|
+
**Note:** The time series collection `memory_telemetry` is created inside `ensureCollections` (separate from the regular loop), so it will appear in `db.listCollections()` and must be in the expected suffixes array.
|
|
285
|
+
|
|
286
|
+
**Step:** Verify in existing e2e test
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
pnpm test -- src/memory/mongodb-e2e.e2e.test.ts -t "collection suffixes"
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Task 1.7: Update barrel exports in index.ts
|
|
293
|
+
|
|
294
|
+
**Files:**
|
|
295
|
+
|
|
296
|
+
- Modify: `src/memory/index.ts` — add export for `queryCacheCollection` from `./mongodb-schema.js`
|
|
297
|
+
|
|
298
|
+
**Step:** Verify build
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
pnpm build
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Commit after Phase 1:**
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
Feat: add query_cache collection with $jsonSchema, indexes, and autoEmbed vector search
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Phase 2: Semantic Query Cache Implementation
|
|
313
|
+
|
|
314
|
+
> **Exit Criteria:** `mongodb-query-cache.ts` module with checkCache, writeCache functions. Two-tier lookup (exact hash + semantic), fire-and-forget write, hit counting. 20+ tests pass.
|
|
315
|
+
|
|
316
|
+
### Task 2.1: Create mongodb-query-cache.ts with types
|
|
317
|
+
|
|
318
|
+
**Files:**
|
|
319
|
+
|
|
320
|
+
- Create: `src/memory/mongodb-query-cache.ts`
|
|
321
|
+
|
|
322
|
+
**Types:**
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
import { createHash } from "node:crypto";
|
|
326
|
+
import type { Db, Document } from "mongodb";
|
|
327
|
+
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
328
|
+
import type { MemoryScope } from "../config/types.memory.js";
|
|
329
|
+
import { queryCacheCollection } from "./mongodb-schema.js";
|
|
330
|
+
import { buildVectorSearchStage } from "./mongodb-search.js";
|
|
331
|
+
import type { MemorySearchResult } from "./types.js";
|
|
332
|
+
|
|
333
|
+
const log = createSubsystemLogger("memory:mongodb:query-cache");
|
|
334
|
+
|
|
335
|
+
export type QueryCacheEntry = {
|
|
336
|
+
queryHash: string;
|
|
337
|
+
queryNorm: string;
|
|
338
|
+
agentId: string;
|
|
339
|
+
scope: MemoryScope;
|
|
340
|
+
scopeRef: string;
|
|
341
|
+
results: MemorySearchResult[];
|
|
342
|
+
pathUsed: string;
|
|
343
|
+
sourceScope: string;
|
|
344
|
+
createdAt: Date;
|
|
345
|
+
expiresAt: Date;
|
|
346
|
+
hitCount: number;
|
|
347
|
+
lastHitAt: Date;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
export type QueryCacheConfig = {
|
|
351
|
+
enabled: boolean;
|
|
352
|
+
conversationTtlSec: number;
|
|
353
|
+
kbTtlSec: number;
|
|
354
|
+
similarityThreshold: number;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
export const DEFAULT_CACHE_CONFIG: QueryCacheConfig = {
|
|
358
|
+
enabled: true,
|
|
359
|
+
conversationTtlSec: 300, // 5 minutes
|
|
360
|
+
kbTtlSec: 3600, // 1 hour
|
|
361
|
+
similarityThreshold: 0.95,
|
|
362
|
+
};
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Task 2.2: Implement normalizeQuery and hashQuery helpers
|
|
366
|
+
|
|
367
|
+
**Files:**
|
|
368
|
+
|
|
369
|
+
- Modify: `src/memory/mongodb-query-cache.ts`
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
/** Normalize query for consistent hashing: lowercase, collapse whitespace, trim. */
|
|
373
|
+
export function normalizeQuery(query: string): string {
|
|
374
|
+
return query.toLowerCase().replace(/\s+/g, " ").trim();
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** SHA-256 hash of normalized query string. */
|
|
378
|
+
export function hashQuery(normalizedQuery: string): string {
|
|
379
|
+
return createHash("sha256").update(normalizedQuery).digest("hex");
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Task 2.3: Implement checkCache (two-tier lookup)
|
|
384
|
+
|
|
385
|
+
**Files:**
|
|
386
|
+
|
|
387
|
+
- Modify: `src/memory/mongodb-query-cache.ts`
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
export type CacheCheckResult = {
|
|
391
|
+
hit: boolean;
|
|
392
|
+
tier: "exact" | "semantic" | "miss";
|
|
393
|
+
results: MemorySearchResult[];
|
|
394
|
+
pathUsed?: string;
|
|
395
|
+
sourceScope?: string;
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Two-tier cache check:
|
|
400
|
+
* Tier 1: Exact SHA-256 hash match via findOne on unique index.
|
|
401
|
+
* Tier 2: $vectorSearch with autoEmbed on queryNorm field, cosine ≥ threshold.
|
|
402
|
+
*
|
|
403
|
+
* On hit: increments hitCount and updates lastHitAt (fire-and-forget).
|
|
404
|
+
*/
|
|
405
|
+
export async function checkCache(params: {
|
|
406
|
+
db: Db;
|
|
407
|
+
prefix: string;
|
|
408
|
+
query: string;
|
|
409
|
+
agentId: string;
|
|
410
|
+
scope: MemoryScope;
|
|
411
|
+
scopeRef: string;
|
|
412
|
+
config: QueryCacheConfig;
|
|
413
|
+
vectorIndexName?: string;
|
|
414
|
+
}): Promise<CacheCheckResult> {
|
|
415
|
+
const { db, prefix, query, agentId, scope, scopeRef, config } = params;
|
|
416
|
+
|
|
417
|
+
if (!config.enabled) {
|
|
418
|
+
return { hit: false, tier: "miss", results: [] };
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const normalized = normalizeQuery(query);
|
|
422
|
+
if (!normalized) {
|
|
423
|
+
return { hit: false, tier: "miss", results: [] };
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const col = queryCacheCollection(db, prefix);
|
|
427
|
+
const qHash = hashQuery(normalized);
|
|
428
|
+
const now = new Date();
|
|
429
|
+
|
|
430
|
+
// Tier 1: Exact match
|
|
431
|
+
try {
|
|
432
|
+
const exact = await col.findOne({
|
|
433
|
+
queryHash: qHash,
|
|
434
|
+
agentId,
|
|
435
|
+
scope,
|
|
436
|
+
scopeRef,
|
|
437
|
+
expiresAt: { $gt: now },
|
|
438
|
+
});
|
|
439
|
+
if (exact) {
|
|
440
|
+
// Fire-and-forget hit count increment
|
|
441
|
+
col
|
|
442
|
+
.findOneAndUpdate({ _id: exact._id }, { $inc: { hitCount: 1 }, $set: { lastHitAt: now } })
|
|
443
|
+
.catch((err) => {
|
|
444
|
+
log.warn("cache hit count update failed", { error: err });
|
|
445
|
+
});
|
|
446
|
+
return {
|
|
447
|
+
hit: true,
|
|
448
|
+
tier: "exact",
|
|
449
|
+
results: exact.results as MemorySearchResult[],
|
|
450
|
+
pathUsed: exact.pathUsed as string,
|
|
451
|
+
sourceScope: exact.sourceScope as string,
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
} catch (err) {
|
|
455
|
+
log.warn("cache exact lookup failed", { error: err });
|
|
456
|
+
return { hit: false, tier: "miss", results: [] };
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Tier 2: Semantic similarity via $vectorSearch with autoEmbed
|
|
460
|
+
try {
|
|
461
|
+
const indexName = params.vectorIndexName ?? `${prefix}query_cache_vector`;
|
|
462
|
+
const vsStage = buildVectorSearchStage({
|
|
463
|
+
queryVector: null,
|
|
464
|
+
queryText: normalized,
|
|
465
|
+
embeddingMode: "automated",
|
|
466
|
+
indexName,
|
|
467
|
+
numCandidates: 20,
|
|
468
|
+
limit: 1,
|
|
469
|
+
filter: { agentId, scope, scopeRef },
|
|
470
|
+
textFieldPath: "queryNorm",
|
|
471
|
+
});
|
|
472
|
+
if (!vsStage) {
|
|
473
|
+
return { hit: false, tier: "miss", results: [] };
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const pipeline: Document[] = [
|
|
477
|
+
{ $vectorSearch: vsStage },
|
|
478
|
+
{ $limit: 1 },
|
|
479
|
+
{
|
|
480
|
+
$project: {
|
|
481
|
+
_id: 1,
|
|
482
|
+
results: 1,
|
|
483
|
+
pathUsed: 1,
|
|
484
|
+
sourceScope: 1,
|
|
485
|
+
expiresAt: 1,
|
|
486
|
+
score: { $meta: "vectorSearchScore" },
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
];
|
|
490
|
+
|
|
491
|
+
const candidates = await col.aggregate(pipeline).toArray();
|
|
492
|
+
if (
|
|
493
|
+
candidates.length > 0 &&
|
|
494
|
+
candidates[0].score >= config.similarityThreshold &&
|
|
495
|
+
candidates[0].expiresAt > now
|
|
496
|
+
) {
|
|
497
|
+
const match = candidates[0];
|
|
498
|
+
// Fire-and-forget hit count increment
|
|
499
|
+
col
|
|
500
|
+
.findOneAndUpdate({ _id: match._id }, { $inc: { hitCount: 1 }, $set: { lastHitAt: now } })
|
|
501
|
+
.catch((err) => {
|
|
502
|
+
log.warn("cache hit count update failed (semantic)", { error: err });
|
|
503
|
+
});
|
|
504
|
+
return {
|
|
505
|
+
hit: true,
|
|
506
|
+
tier: "semantic",
|
|
507
|
+
results: match.results as MemorySearchResult[],
|
|
508
|
+
pathUsed: match.pathUsed as string,
|
|
509
|
+
sourceScope: match.sourceScope as string,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
} catch (err) {
|
|
513
|
+
// Semantic tier failure is non-fatal — degrade to cache miss
|
|
514
|
+
log.warn("cache semantic lookup failed", { error: err });
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return { hit: false, tier: "miss", results: [] };
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Task 2.4: Implement writeCache (fire-and-forget)
|
|
522
|
+
|
|
523
|
+
**Files:**
|
|
524
|
+
|
|
525
|
+
- Modify: `src/memory/mongodb-query-cache.ts`
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
/**
|
|
529
|
+
* Write search results to cache. Fire-and-forget: does not block caller.
|
|
530
|
+
* Uses upsert to handle race conditions (two identical queries completing simultaneously).
|
|
531
|
+
*/
|
|
532
|
+
export function writeCache(params: {
|
|
533
|
+
db: Db;
|
|
534
|
+
prefix: string;
|
|
535
|
+
query: string;
|
|
536
|
+
agentId: string;
|
|
537
|
+
scope: MemoryScope;
|
|
538
|
+
scopeRef: string;
|
|
539
|
+
results: MemorySearchResult[];
|
|
540
|
+
pathUsed: string;
|
|
541
|
+
sourceScope: string;
|
|
542
|
+
ttlSec: number;
|
|
543
|
+
}): void {
|
|
544
|
+
const { db, prefix, query, agentId, scope, scopeRef, results, pathUsed, sourceScope, ttlSec } =
|
|
545
|
+
params;
|
|
546
|
+
|
|
547
|
+
const normalized = normalizeQuery(query);
|
|
548
|
+
if (!normalized || results.length === 0) return;
|
|
549
|
+
|
|
550
|
+
const now = new Date();
|
|
551
|
+
const expiresAt = new Date(now.getTime() + ttlSec * 1000);
|
|
552
|
+
const qHash = hashQuery(normalized);
|
|
553
|
+
const col = queryCacheCollection(db, prefix);
|
|
554
|
+
|
|
555
|
+
col
|
|
556
|
+
.updateOne(
|
|
557
|
+
{ queryHash: qHash, agentId, scope, scopeRef },
|
|
558
|
+
{
|
|
559
|
+
$setOnInsert: {
|
|
560
|
+
queryNorm: normalized,
|
|
561
|
+
createdAt: now,
|
|
562
|
+
hitCount: 0,
|
|
563
|
+
},
|
|
564
|
+
$set: {
|
|
565
|
+
results,
|
|
566
|
+
pathUsed,
|
|
567
|
+
sourceScope,
|
|
568
|
+
expiresAt,
|
|
569
|
+
lastHitAt: now,
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
{ upsert: true },
|
|
573
|
+
)
|
|
574
|
+
.catch((err) => {
|
|
575
|
+
log.warn("cache write failed", { error: err });
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Task 2.5: Write tests for mongodb-query-cache.ts
|
|
581
|
+
|
|
582
|
+
**Files:**
|
|
583
|
+
|
|
584
|
+
- Create: `src/memory/mongodb-query-cache.test.ts`
|
|
585
|
+
|
|
586
|
+
**Tests to write (20+ tests):**
|
|
587
|
+
|
|
588
|
+
1. `normalizeQuery lowercases input`
|
|
589
|
+
2. `normalizeQuery collapses whitespace`
|
|
590
|
+
3. `normalizeQuery trims`
|
|
591
|
+
4. `normalizeQuery handles empty string`
|
|
592
|
+
5. `hashQuery returns consistent SHA-256`
|
|
593
|
+
6. `hashQuery returns different hashes for different queries`
|
|
594
|
+
7. `checkCache returns miss when disabled`
|
|
595
|
+
8. `checkCache returns miss for empty query`
|
|
596
|
+
9. `checkCache Tier 1 returns exact match`
|
|
597
|
+
10. `checkCache Tier 1 skips expired entries`
|
|
598
|
+
11. `checkCache Tier 1 increments hitCount on hit (fire-and-forget)`
|
|
599
|
+
12. `checkCache Tier 2 returns semantic match above threshold`
|
|
600
|
+
13. `checkCache Tier 2 rejects match below threshold`
|
|
601
|
+
14. `checkCache Tier 2 rejects expired semantic match`
|
|
602
|
+
15. `checkCache returns miss when both tiers miss`
|
|
603
|
+
16. `checkCache handles Tier 1 error gracefully`
|
|
604
|
+
17. `checkCache handles Tier 2 error gracefully (degrades to miss)`
|
|
605
|
+
18. `writeCache writes entry with correct fields`
|
|
606
|
+
19. `writeCache skips empty query`
|
|
607
|
+
20. `writeCache skips empty results`
|
|
608
|
+
21. `writeCache uses upsert (handles race condition)`
|
|
609
|
+
22. `writeCache is fire-and-forget (does not throw)`
|
|
610
|
+
23. `writeCache sets correct expiresAt from ttlSec`
|
|
611
|
+
|
|
612
|
+
**Mock pattern:** Follow mongodb-ops.test.ts pattern — mock collection with vi.fn() for findOne, findOneAndUpdate, aggregate, updateOne.
|
|
613
|
+
|
|
614
|
+
**Step:** Run tests
|
|
615
|
+
|
|
616
|
+
```bash
|
|
617
|
+
pnpm test -- src/memory/mongodb-query-cache.test.ts
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
**Commit after Task 2.5:**
|
|
621
|
+
|
|
622
|
+
```
|
|
623
|
+
Feat: implement semantic query cache with two-tier lookup
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
---
|
|
627
|
+
|
|
628
|
+
## Phase 3: Wire Cache into Search Path
|
|
629
|
+
|
|
630
|
+
> **Exit Criteria:** Cache check runs BEFORE search pipeline construction. Cache write runs AFTER search returns. Config section added. 8+ additional tests pass.
|
|
631
|
+
|
|
632
|
+
### Task 3.1: Add cache config to MemoryMongoDBConfig
|
|
633
|
+
|
|
634
|
+
**Files:**
|
|
635
|
+
|
|
636
|
+
- Modify: `src/config/types.memory.ts` (add inside MemoryMongoDBConfig type)
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
/** Semantic query cache configuration */
|
|
640
|
+
cache?: {
|
|
641
|
+
/** Enable query caching. Default: true */
|
|
642
|
+
enabled?: boolean;
|
|
643
|
+
/** TTL for conversation scope cache entries in seconds. Default: 300 (5 min) */
|
|
644
|
+
conversationTtlSec?: number;
|
|
645
|
+
/** TTL for KB scope cache entries in seconds. Default: 3600 (1 hour) */
|
|
646
|
+
kbTtlSec?: number;
|
|
647
|
+
/** Cosine similarity threshold for semantic cache hits. Default: 0.95 */
|
|
648
|
+
similarityThreshold?: number;
|
|
649
|
+
};
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### Task 3.2: Add cache to ResolvedMongoDBConfig
|
|
653
|
+
|
|
654
|
+
**Files:**
|
|
655
|
+
|
|
656
|
+
- Modify: `src/memory/backend-config.ts`
|
|
657
|
+
|
|
658
|
+
Add to `ResolvedMongoDBConfig` type (after `graph` field):
|
|
659
|
+
|
|
660
|
+
```typescript
|
|
661
|
+
cache: {
|
|
662
|
+
enabled: boolean;
|
|
663
|
+
conversationTtlSec: number;
|
|
664
|
+
kbTtlSec: number;
|
|
665
|
+
similarityThreshold: number;
|
|
666
|
+
}
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
Add defaults in the resolve function (follow existing `!== false` pattern for default-enable):
|
|
670
|
+
|
|
671
|
+
```typescript
|
|
672
|
+
cache: {
|
|
673
|
+
enabled: mongo.cache?.enabled !== false,
|
|
674
|
+
conversationTtlSec: mongo.cache?.conversationTtlSec ?? 300,
|
|
675
|
+
kbTtlSec: mongo.cache?.kbTtlSec ?? 3600,
|
|
676
|
+
similarityThreshold: mongo.cache?.similarityThreshold ?? 0.95,
|
|
677
|
+
},
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Task 3.3: Wire checkCache BEFORE searchV2 in MongoDBMemoryManager.search()
|
|
681
|
+
|
|
682
|
+
**Files:**
|
|
683
|
+
|
|
684
|
+
- Modify: `src/memory/mongodb-manager.ts` (in the `search()` method, ~line 730)
|
|
685
|
+
|
|
686
|
+
**Hook location:** After `const cleaned = query.trim()` and before the `searchV2` call.
|
|
687
|
+
|
|
688
|
+
```typescript
|
|
689
|
+
// Cache check: BEFORE search pipeline
|
|
690
|
+
if (mongoCfg.cache.enabled) {
|
|
691
|
+
const cacheResult = await checkCache({
|
|
692
|
+
db: this.db,
|
|
693
|
+
prefix: this.prefix,
|
|
694
|
+
query: cleaned,
|
|
695
|
+
agentId: this.agentId,
|
|
696
|
+
scope: "agent",
|
|
697
|
+
scopeRef: this.agentScopeRef,
|
|
698
|
+
config: mongoCfg.cache,
|
|
699
|
+
});
|
|
700
|
+
if (cacheResult.hit) {
|
|
701
|
+
this.setLastSearchMode(`v2:cache:${cacheResult.tier}`, {
|
|
702
|
+
pathUsed: cacheResult.pathUsed,
|
|
703
|
+
sourceScope: cacheResult.sourceScope,
|
|
704
|
+
});
|
|
705
|
+
return cacheResult.results;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
### Task 3.4: Wire writeCache AFTER searchV2 returns results
|
|
711
|
+
|
|
712
|
+
**Files:**
|
|
713
|
+
|
|
714
|
+
- Modify: `src/memory/mongodb-manager.ts` (after `return v2.results` in search(), ~line 777)
|
|
715
|
+
|
|
716
|
+
**Hook location:** After `if (v2.results.length > 0)` block, before the return.
|
|
717
|
+
|
|
718
|
+
```typescript
|
|
719
|
+
if (v2.results.length > 0) {
|
|
720
|
+
this.setLastSearchMode("v2", v2Details);
|
|
721
|
+
// Fire-and-forget cache write
|
|
722
|
+
if (mongoCfg.cache.enabled) {
|
|
723
|
+
const ttlSec = mongoCfg.kb.enabled
|
|
724
|
+
? mongoCfg.cache.kbTtlSec
|
|
725
|
+
: mongoCfg.cache.conversationTtlSec;
|
|
726
|
+
writeCache({
|
|
727
|
+
db: this.db,
|
|
728
|
+
prefix: this.prefix,
|
|
729
|
+
query: cleaned,
|
|
730
|
+
agentId: this.agentId,
|
|
731
|
+
scope: "agent",
|
|
732
|
+
scopeRef: this.agentScopeRef,
|
|
733
|
+
results: v2.results,
|
|
734
|
+
pathUsed: v2.metadata.pathsExecuted.join(","),
|
|
735
|
+
sourceScope: "conversation",
|
|
736
|
+
ttlSec,
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
return v2.results;
|
|
740
|
+
}
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
### Task 3.5: Add imports to mongodb-manager.ts
|
|
744
|
+
|
|
745
|
+
**Files:**
|
|
746
|
+
|
|
747
|
+
- Modify: `src/memory/mongodb-manager.ts` (add imports at top)
|
|
748
|
+
|
|
749
|
+
```typescript
|
|
750
|
+
import { checkCache, writeCache } from "./mongodb-query-cache.js";
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
### Task 3.6: Write integration tests for cache wiring
|
|
754
|
+
|
|
755
|
+
**Files:**
|
|
756
|
+
|
|
757
|
+
- Modify: `src/memory/mongodb-manager.test.ts` (add test block)
|
|
758
|
+
|
|
759
|
+
**Tests to write:**
|
|
760
|
+
|
|
761
|
+
1. `search() checks cache before searchV2 when cache enabled`
|
|
762
|
+
2. `search() returns cache hit without calling searchV2`
|
|
763
|
+
3. `search() sets searchMode to v2:cache:exact on exact cache hit`
|
|
764
|
+
4. `search() sets searchMode to v2:cache:semantic on semantic cache hit`
|
|
765
|
+
5. `search() calls searchV2 when cache misses`
|
|
766
|
+
6. `search() writes to cache after successful searchV2`
|
|
767
|
+
7. `search() skips cache when cache disabled`
|
|
768
|
+
8. `search() uses correct TTL for conversation vs KB`
|
|
769
|
+
|
|
770
|
+
**Step:** Run tests
|
|
771
|
+
|
|
772
|
+
```bash
|
|
773
|
+
pnpm test -- src/memory/mongodb-manager.test.ts
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### Task 3.7: Export cache types and functions from barrel
|
|
777
|
+
|
|
778
|
+
**Files:**
|
|
779
|
+
|
|
780
|
+
- Modify: `src/memory/index.ts`
|
|
781
|
+
|
|
782
|
+
```typescript
|
|
783
|
+
export {
|
|
784
|
+
checkCache,
|
|
785
|
+
writeCache,
|
|
786
|
+
normalizeQuery,
|
|
787
|
+
hashQuery,
|
|
788
|
+
type QueryCacheEntry,
|
|
789
|
+
type QueryCacheConfig,
|
|
790
|
+
type CacheCheckResult,
|
|
791
|
+
DEFAULT_CACHE_CONFIG,
|
|
792
|
+
} from "./mongodb-query-cache.js";
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
**Step:** Verify build
|
|
796
|
+
|
|
797
|
+
```bash
|
|
798
|
+
pnpm build
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
**Commit after Phase 3:**
|
|
802
|
+
|
|
803
|
+
```
|
|
804
|
+
Feat: wire semantic query cache into search pipeline with two-tier lookup
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
---
|
|
808
|
+
|
|
809
|
+
## Phase 4: Time Series Observability Collection
|
|
810
|
+
|
|
811
|
+
> **Exit Criteria:** `memory_telemetry` time series collection created with 7-day TTL. Thin emitTelemetry function. 12+ tests pass.
|
|
812
|
+
|
|
813
|
+
### Task 4.1: Add memory_telemetry time series collection to ensureCollections
|
|
814
|
+
|
|
815
|
+
**Files:**
|
|
816
|
+
|
|
817
|
+
- Modify: `src/memory/mongodb-schema.ts` (in ensureCollections function)
|
|
818
|
+
|
|
819
|
+
**CRITICAL:** Time series collections cannot use $jsonSchema validators. They must be created with `timeseries` options using `db.createCollection()` directly.
|
|
820
|
+
|
|
821
|
+
Add a separate block AFTER the regular collection loop:
|
|
822
|
+
|
|
823
|
+
```typescript
|
|
824
|
+
// Time series collection — created separately (no $jsonSchema support)
|
|
825
|
+
const telemetryName = `${prefix}memory_telemetry`;
|
|
826
|
+
if (!existing.has(telemetryName)) {
|
|
827
|
+
try {
|
|
828
|
+
await db.createCollection(telemetryName, {
|
|
829
|
+
timeseries: {
|
|
830
|
+
timeField: "ts",
|
|
831
|
+
metaField: "meta",
|
|
832
|
+
granularity: "seconds",
|
|
833
|
+
},
|
|
834
|
+
expireAfterSeconds: 604800, // 7 days
|
|
835
|
+
});
|
|
836
|
+
log.info(`created time series collection ${telemetryName}`);
|
|
837
|
+
} catch (err) {
|
|
838
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
839
|
+
// Collection may already exist or time series not supported
|
|
840
|
+
if (!msg.includes("already exists") && !msg.includes("Collection already exists")) {
|
|
841
|
+
log.warn(`time series collection creation failed: ${msg}`);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
**Do NOT add to `needed` array** — time series collections cannot be created with `validator` option.
|
|
848
|
+
|
|
849
|
+
### Task 4.2: Add telemetryCollection accessor
|
|
850
|
+
|
|
851
|
+
**Files:**
|
|
852
|
+
|
|
853
|
+
- Modify: `src/memory/mongodb-schema.ts`
|
|
854
|
+
|
|
855
|
+
```typescript
|
|
856
|
+
export function telemetryCollection(db: Db, prefix: string): Collection {
|
|
857
|
+
return col(db, prefix, "memory_telemetry");
|
|
858
|
+
}
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
### Task 4.3: Add standard indexes for telemetry meta queries
|
|
862
|
+
|
|
863
|
+
**Files:**
|
|
864
|
+
|
|
865
|
+
- Modify: `src/memory/mongodb-schema.ts` (in ensureStandardIndexes, after query_cache indexes)
|
|
866
|
+
|
|
867
|
+
```typescript
|
|
868
|
+
// Telemetry indexes (time series collection — meta field compound indexes)
|
|
869
|
+
const telemetry = telemetryCollection(db, prefix);
|
|
870
|
+
try {
|
|
871
|
+
await telemetry.createIndex({ "meta.agentId": 1, ts: -1 }, { name: "idx_telemetry_agent_ts" });
|
|
872
|
+
applied++;
|
|
873
|
+
await telemetry.createIndex({ "meta.operation": 1, ts: -1 }, { name: "idx_telemetry_op_ts" });
|
|
874
|
+
applied++;
|
|
875
|
+
} catch (err) {
|
|
876
|
+
// Time series collection may not exist (creation failed in ensureCollections)
|
|
877
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
878
|
+
log.warn(`telemetry index creation skipped: ${msg}`);
|
|
879
|
+
}
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
### Task 4.4: Create mongodb-telemetry.ts with types and emitTelemetry
|
|
883
|
+
|
|
884
|
+
**Files:**
|
|
885
|
+
|
|
886
|
+
- Create: `src/memory/mongodb-telemetry.ts`
|
|
887
|
+
|
|
888
|
+
```typescript
|
|
889
|
+
import type { Db } from "mongodb";
|
|
890
|
+
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
891
|
+
import { telemetryCollection } from "./mongodb-schema.js";
|
|
892
|
+
|
|
893
|
+
const log = createSubsystemLogger("memory:mongodb:telemetry");
|
|
894
|
+
|
|
895
|
+
// ---------------------------------------------------------------------------
|
|
896
|
+
// Types
|
|
897
|
+
// ---------------------------------------------------------------------------
|
|
898
|
+
|
|
899
|
+
export type TelemetryOperation =
|
|
900
|
+
| "search"
|
|
901
|
+
| "event-write"
|
|
902
|
+
| "projection-run"
|
|
903
|
+
| "cache-check"
|
|
904
|
+
| "graph-expansion";
|
|
905
|
+
|
|
906
|
+
export type TelemetryMeta = {
|
|
907
|
+
agentId: string;
|
|
908
|
+
operation: TelemetryOperation;
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
export type TelemetryDocument = {
|
|
912
|
+
ts: Date;
|
|
913
|
+
meta: TelemetryMeta;
|
|
914
|
+
durationMs: number;
|
|
915
|
+
ok: boolean;
|
|
916
|
+
pathUsed?: string;
|
|
917
|
+
resultCount?: number;
|
|
918
|
+
topScore?: number;
|
|
919
|
+
fusionMethod?: string;
|
|
920
|
+
cacheHit?: boolean;
|
|
921
|
+
latencySavedMs?: number;
|
|
922
|
+
itemCount?: number;
|
|
923
|
+
eventType?: string;
|
|
924
|
+
projectionTriggered?: boolean;
|
|
925
|
+
};
|
|
926
|
+
|
|
927
|
+
// ---------------------------------------------------------------------------
|
|
928
|
+
// Emit (fire-and-forget, error-swallowing, non-blocking)
|
|
929
|
+
// ---------------------------------------------------------------------------
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Emit a telemetry document to the memory_telemetry time series collection.
|
|
933
|
+
* Fire-and-forget: never blocks the caller, never throws.
|
|
934
|
+
* Uses insertOne with .catch() for error-swallowing.
|
|
935
|
+
*/
|
|
936
|
+
export function emitTelemetry(db: Db, prefix: string, doc: Omit<TelemetryDocument, "ts">): void {
|
|
937
|
+
const entry: TelemetryDocument = { ...doc, ts: new Date() };
|
|
938
|
+
telemetryCollection(db, prefix)
|
|
939
|
+
.insertOne(entry)
|
|
940
|
+
.catch((err) => {
|
|
941
|
+
log.warn("telemetry emit failed", { operation: doc.meta.operation, error: err });
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// ---------------------------------------------------------------------------
|
|
946
|
+
// Aggregation helpers (dashboard metrics)
|
|
947
|
+
// ---------------------------------------------------------------------------
|
|
948
|
+
|
|
949
|
+
/** Get P50/P95/P99 latency stats for a given operation over a time window. */
|
|
950
|
+
export async function getLatencyStats(params: {
|
|
951
|
+
db: Db;
|
|
952
|
+
prefix: string;
|
|
953
|
+
agentId: string;
|
|
954
|
+
operation?: TelemetryOperation;
|
|
955
|
+
windowMs?: number;
|
|
956
|
+
}): Promise<{ p50: number; p95: number; p99: number; count: number }> {
|
|
957
|
+
const { db, prefix, agentId, operation, windowMs = 3600000 } = params;
|
|
958
|
+
const since = new Date(Date.now() - windowMs);
|
|
959
|
+
const matchStage: Record<string, unknown> = {
|
|
960
|
+
"meta.agentId": agentId,
|
|
961
|
+
ts: { $gte: since },
|
|
962
|
+
};
|
|
963
|
+
if (operation) {
|
|
964
|
+
matchStage["meta.operation"] = operation;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
const pipeline = [
|
|
968
|
+
{ $match: matchStage },
|
|
969
|
+
{
|
|
970
|
+
$group: {
|
|
971
|
+
_id: null,
|
|
972
|
+
durations: { $push: "$durationMs" },
|
|
973
|
+
count: { $sum: 1 },
|
|
974
|
+
},
|
|
975
|
+
},
|
|
976
|
+
];
|
|
977
|
+
|
|
978
|
+
const results = await telemetryCollection(db, prefix).aggregate(pipeline).toArray();
|
|
979
|
+
if (results.length === 0 || results[0].count === 0) {
|
|
980
|
+
return { p50: 0, p95: 0, p99: 0, count: 0 };
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
const sorted = (results[0].durations as number[]).sort((a, b) => a - b);
|
|
984
|
+
const n = sorted.length;
|
|
985
|
+
return {
|
|
986
|
+
p50: sorted[Math.floor(n * 0.5)] ?? 0,
|
|
987
|
+
p95: sorted[Math.floor(n * 0.95)] ?? 0,
|
|
988
|
+
p99: sorted[Math.floor(n * 0.99)] ?? 0,
|
|
989
|
+
count: n,
|
|
990
|
+
};
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/** Get cache hit rate over a time window. */
|
|
994
|
+
export async function getCacheHitRate(params: {
|
|
995
|
+
db: Db;
|
|
996
|
+
prefix: string;
|
|
997
|
+
agentId: string;
|
|
998
|
+
windowMs?: number;
|
|
999
|
+
}): Promise<{ hitRate: number; hits: number; misses: number; total: number }> {
|
|
1000
|
+
const { db, prefix, agentId, windowMs = 3600000 } = params;
|
|
1001
|
+
const since = new Date(Date.now() - windowMs);
|
|
1002
|
+
|
|
1003
|
+
const pipeline = [
|
|
1004
|
+
{
|
|
1005
|
+
$match: {
|
|
1006
|
+
"meta.agentId": agentId,
|
|
1007
|
+
"meta.operation": "cache-check",
|
|
1008
|
+
ts: { $gte: since },
|
|
1009
|
+
},
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
$group: {
|
|
1013
|
+
_id: "$cacheHit",
|
|
1014
|
+
count: { $sum: 1 },
|
|
1015
|
+
},
|
|
1016
|
+
},
|
|
1017
|
+
];
|
|
1018
|
+
|
|
1019
|
+
const results = await telemetryCollection(db, prefix).aggregate(pipeline).toArray();
|
|
1020
|
+
let hits = 0;
|
|
1021
|
+
let misses = 0;
|
|
1022
|
+
for (const r of results) {
|
|
1023
|
+
if (r._id === true) hits = r.count;
|
|
1024
|
+
else misses = r.count;
|
|
1025
|
+
}
|
|
1026
|
+
const total = hits + misses;
|
|
1027
|
+
return { hitRate: total > 0 ? hits / total : 0, hits, misses, total };
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/** Get operation distribution over a time window. */
|
|
1031
|
+
export async function getOperationDistribution(params: {
|
|
1032
|
+
db: Db;
|
|
1033
|
+
prefix: string;
|
|
1034
|
+
agentId: string;
|
|
1035
|
+
windowMs?: number;
|
|
1036
|
+
}): Promise<Array<{ operation: TelemetryOperation; count: number; avgDurationMs: number }>> {
|
|
1037
|
+
const { db, prefix, agentId, windowMs = 3600000 } = params;
|
|
1038
|
+
const since = new Date(Date.now() - windowMs);
|
|
1039
|
+
|
|
1040
|
+
const pipeline = [
|
|
1041
|
+
{
|
|
1042
|
+
$match: {
|
|
1043
|
+
"meta.agentId": agentId,
|
|
1044
|
+
ts: { $gte: since },
|
|
1045
|
+
},
|
|
1046
|
+
},
|
|
1047
|
+
{
|
|
1048
|
+
$group: {
|
|
1049
|
+
_id: "$meta.operation",
|
|
1050
|
+
count: { $sum: 1 },
|
|
1051
|
+
avgDurationMs: { $avg: "$durationMs" },
|
|
1052
|
+
},
|
|
1053
|
+
},
|
|
1054
|
+
{ $sort: { count: -1 } },
|
|
1055
|
+
];
|
|
1056
|
+
|
|
1057
|
+
const results = await telemetryCollection(db, prefix).aggregate(pipeline).toArray();
|
|
1058
|
+
return results.map((r) => ({
|
|
1059
|
+
operation: r._id as TelemetryOperation,
|
|
1060
|
+
count: r.count as number,
|
|
1061
|
+
avgDurationMs: Math.round(r.avgDurationMs as number),
|
|
1062
|
+
}));
|
|
1063
|
+
}
|
|
1064
|
+
```
|
|
1065
|
+
|
|
1066
|
+
### Task 4.5: Write tests for mongodb-telemetry.ts
|
|
1067
|
+
|
|
1068
|
+
**Files:**
|
|
1069
|
+
|
|
1070
|
+
- Create: `src/memory/mongodb-telemetry.test.ts`
|
|
1071
|
+
|
|
1072
|
+
**Tests to write (14+ tests):**
|
|
1073
|
+
|
|
1074
|
+
1. `emitTelemetry calls insertOne with correct document shape`
|
|
1075
|
+
2. `emitTelemetry adds ts field automatically`
|
|
1076
|
+
3. `emitTelemetry does not throw on insertOne failure`
|
|
1077
|
+
4. `emitTelemetry logs warning on failure`
|
|
1078
|
+
5. `emitTelemetry includes optional fields when provided`
|
|
1079
|
+
6. `emitTelemetry omits optional fields when not provided`
|
|
1080
|
+
7. `getLatencyStats returns percentiles for matching documents`
|
|
1081
|
+
8. `getLatencyStats returns zeros when no documents match`
|
|
1082
|
+
9. `getLatencyStats filters by operation when provided`
|
|
1083
|
+
10. `getLatencyStats respects windowMs parameter`
|
|
1084
|
+
11. `getCacheHitRate calculates correct hit rate`
|
|
1085
|
+
12. `getCacheHitRate returns zero rate when no data`
|
|
1086
|
+
13. `getOperationDistribution groups by operation`
|
|
1087
|
+
14. `getOperationDistribution returns empty array when no data`
|
|
1088
|
+
|
|
1089
|
+
**Mock pattern:** Mock telemetryCollection with vi.fn() for insertOne and aggregate.
|
|
1090
|
+
|
|
1091
|
+
**Step:** Run tests
|
|
1092
|
+
|
|
1093
|
+
```bash
|
|
1094
|
+
pnpm test -- src/memory/mongodb-telemetry.test.ts
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
**Commit after Phase 4:**
|
|
1098
|
+
|
|
1099
|
+
```
|
|
1100
|
+
Feat: add memory_telemetry time series collection with emitTelemetry and dashboard helpers
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
---
|
|
1104
|
+
|
|
1105
|
+
## Phase 5: Wire Telemetry Emission into 5 Code Paths
|
|
1106
|
+
|
|
1107
|
+
> **Exit Criteria:** emitTelemetry called from search, event write, projection run, cache check, and graph expansion. Each emission is fire-and-forget. 10+ additional tests pass.
|
|
1108
|
+
|
|
1109
|
+
### Task 5.1: Emit from search path (mongodb-manager.ts)
|
|
1110
|
+
|
|
1111
|
+
**Files:**
|
|
1112
|
+
|
|
1113
|
+
- Modify: `src/memory/mongodb-manager.ts` (in search() method, after searchV2 returns)
|
|
1114
|
+
|
|
1115
|
+
Add import:
|
|
1116
|
+
|
|
1117
|
+
```typescript
|
|
1118
|
+
import { emitTelemetry } from "./mongodb-telemetry.js";
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
After `const v2 = await searchV2(...)` and before the return:
|
|
1122
|
+
|
|
1123
|
+
```typescript
|
|
1124
|
+
const searchDurationMs = Date.now() - searchStart; // Add const searchStart = Date.now() before searchV2 call
|
|
1125
|
+
emitTelemetry(this.db, this.prefix, {
|
|
1126
|
+
meta: { agentId: this.agentId, operation: "search" },
|
|
1127
|
+
durationMs: searchDurationMs,
|
|
1128
|
+
ok: v2.results.length > 0,
|
|
1129
|
+
pathUsed: v2.metadata.pathsExecuted.join(","),
|
|
1130
|
+
resultCount: v2.results.length,
|
|
1131
|
+
topScore: v2.results[0]?.score ?? 0,
|
|
1132
|
+
fusionMethod: mongoCfg.fusionMethod,
|
|
1133
|
+
});
|
|
1134
|
+
```
|
|
1135
|
+
|
|
1136
|
+
### Task 5.2: Emit from event write (mongodb-manager.ts writeEventAndProject)
|
|
1137
|
+
|
|
1138
|
+
**Files:**
|
|
1139
|
+
|
|
1140
|
+
- Modify: `src/memory/mongodb-manager.ts` (in writeEventAndProject function)
|
|
1141
|
+
|
|
1142
|
+
After the event write and projections complete:
|
|
1143
|
+
|
|
1144
|
+
```typescript
|
|
1145
|
+
emitTelemetry(db, prefix, {
|
|
1146
|
+
meta: { agentId, operation: "event-write" },
|
|
1147
|
+
durationMs: Date.now() - writeStart, // Add const writeStart = Date.now() at function start
|
|
1148
|
+
ok: true,
|
|
1149
|
+
eventType: event.role,
|
|
1150
|
+
projectionTriggered: true,
|
|
1151
|
+
});
|
|
1152
|
+
```
|
|
1153
|
+
|
|
1154
|
+
### Task 5.3: Emit from projection run (mongodb-ops.ts)
|
|
1155
|
+
|
|
1156
|
+
**Files:**
|
|
1157
|
+
|
|
1158
|
+
- Modify: `src/memory/mongodb-ops.ts` (in recordProjectionRun)
|
|
1159
|
+
|
|
1160
|
+
Add import and emit after the insertOne:
|
|
1161
|
+
|
|
1162
|
+
```typescript
|
|
1163
|
+
import { emitTelemetry } from "./mongodb-telemetry.js";
|
|
1164
|
+
|
|
1165
|
+
// After insertOne succeeds:
|
|
1166
|
+
emitTelemetry(db, prefix, {
|
|
1167
|
+
meta: { agentId: run.agentId, operation: "projection-run" },
|
|
1168
|
+
durationMs: run.durationMs,
|
|
1169
|
+
ok: run.status === "ok",
|
|
1170
|
+
itemCount: run.itemsProjected,
|
|
1171
|
+
});
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
### Task 5.4: Emit from cache check (mongodb-query-cache.ts)
|
|
1175
|
+
|
|
1176
|
+
**Files:**
|
|
1177
|
+
|
|
1178
|
+
- Modify: `src/memory/mongodb-query-cache.ts` (in checkCache function)
|
|
1179
|
+
|
|
1180
|
+
Add import and emit at each return point:
|
|
1181
|
+
|
|
1182
|
+
```typescript
|
|
1183
|
+
import { emitTelemetry } from "./mongodb-telemetry.js";
|
|
1184
|
+
|
|
1185
|
+
// At top of checkCache: const cacheStart = Date.now();
|
|
1186
|
+
// Before each return:
|
|
1187
|
+
emitTelemetry(db, prefix, {
|
|
1188
|
+
meta: { agentId, operation: "cache-check" },
|
|
1189
|
+
durationMs: Date.now() - cacheStart,
|
|
1190
|
+
ok: true,
|
|
1191
|
+
cacheHit: cacheResult.hit,
|
|
1192
|
+
});
|
|
1193
|
+
```
|
|
1194
|
+
|
|
1195
|
+
**Note:** Only emit on the final return, not on early exits (disabled, empty query).
|
|
1196
|
+
|
|
1197
|
+
### Task 5.5: Emit from graph expansion (mongodb-graph.ts)
|
|
1198
|
+
|
|
1199
|
+
**Files:**
|
|
1200
|
+
|
|
1201
|
+
- Modify: `src/memory/mongodb-graph.ts` (in expandGraph function)
|
|
1202
|
+
|
|
1203
|
+
Add import and emit after expansion completes:
|
|
1204
|
+
|
|
1205
|
+
```typescript
|
|
1206
|
+
import { emitTelemetry } from "./mongodb-telemetry.js";
|
|
1207
|
+
|
|
1208
|
+
// After $graphLookup pipeline completes:
|
|
1209
|
+
emitTelemetry(db, prefix, {
|
|
1210
|
+
meta: { agentId, operation: "graph-expansion" },
|
|
1211
|
+
durationMs: Date.now() - graphStart, // Add const graphStart = Date.now() at function start
|
|
1212
|
+
ok: true,
|
|
1213
|
+
resultCount: result.entities.length + result.relations.length,
|
|
1214
|
+
});
|
|
1215
|
+
```
|
|
1216
|
+
|
|
1217
|
+
### Task 5.6: Write tests for telemetry emission wiring
|
|
1218
|
+
|
|
1219
|
+
**Files:**
|
|
1220
|
+
|
|
1221
|
+
- Modify: `src/memory/mongodb-manager.test.ts` (add telemetry test block)
|
|
1222
|
+
- Modify: `src/memory/mongodb-ops.test.ts` (add telemetry test)
|
|
1223
|
+
- Modify: `src/memory/mongodb-query-cache.test.ts` (add telemetry test)
|
|
1224
|
+
- Modify: `src/memory/mongodb-graph.test.ts` (add telemetry test)
|
|
1225
|
+
|
|
1226
|
+
**Tests per file:**
|
|
1227
|
+
|
|
1228
|
+
- mongodb-manager.test.ts: `search() emits search telemetry after searchV2`, `writeEventAndProject emits event-write telemetry`
|
|
1229
|
+
- mongodb-ops.test.ts: `recordProjectionRun emits projection-run telemetry`
|
|
1230
|
+
- mongodb-query-cache.test.ts: `checkCache emits cache-check telemetry`
|
|
1231
|
+
- mongodb-graph.test.ts: `expandGraph emits graph-expansion telemetry`
|
|
1232
|
+
|
|
1233
|
+
**Mock pattern:** Use vi.mock("./mongodb-telemetry.js") to spy on emitTelemetry calls.
|
|
1234
|
+
|
|
1235
|
+
**Step:** Run all affected test files
|
|
1236
|
+
|
|
1237
|
+
```bash
|
|
1238
|
+
pnpm test -- src/memory/mongodb-manager.test.ts src/memory/mongodb-ops.test.ts src/memory/mongodb-query-cache.test.ts src/memory/mongodb-graph.test.ts
|
|
1239
|
+
```
|
|
1240
|
+
|
|
1241
|
+
### Task 5.7: Export telemetry types and functions from barrel
|
|
1242
|
+
|
|
1243
|
+
**Files:**
|
|
1244
|
+
|
|
1245
|
+
- Modify: `src/memory/index.ts`
|
|
1246
|
+
|
|
1247
|
+
```typescript
|
|
1248
|
+
export {
|
|
1249
|
+
emitTelemetry,
|
|
1250
|
+
getLatencyStats,
|
|
1251
|
+
getCacheHitRate,
|
|
1252
|
+
getOperationDistribution,
|
|
1253
|
+
type TelemetryDocument,
|
|
1254
|
+
type TelemetryOperation,
|
|
1255
|
+
type TelemetryMeta,
|
|
1256
|
+
} from "./mongodb-telemetry.js";
|
|
1257
|
+
```
|
|
1258
|
+
|
|
1259
|
+
**Step:** Verify build
|
|
1260
|
+
|
|
1261
|
+
```bash
|
|
1262
|
+
pnpm build
|
|
1263
|
+
```
|
|
1264
|
+
|
|
1265
|
+
**Commit after Phase 5:**
|
|
1266
|
+
|
|
1267
|
+
```
|
|
1268
|
+
Feat: wire telemetry emission into search, event write, projection, cache, and graph paths
|
|
1269
|
+
```
|
|
1270
|
+
|
|
1271
|
+
---
|
|
1272
|
+
|
|
1273
|
+
## Phase 6: Documentation Update
|
|
1274
|
+
|
|
1275
|
+
> **Exit Criteria:** README updated with 22 collections, 14 MongoDB capabilities table, cache + telemetry rows. Build passes.
|
|
1276
|
+
|
|
1277
|
+
### Task 6.1: Update README.md capabilities table
|
|
1278
|
+
|
|
1279
|
+
**Files:**
|
|
1280
|
+
|
|
1281
|
+
- Modify: `README.md` (capabilities table at lines ~47-61)
|
|
1282
|
+
|
|
1283
|
+
Add two new rows to the 12-capability table (making it 14):
|
|
1284
|
+
|
|
1285
|
+
```markdown
|
|
1286
|
+
| 13 | **Semantic Query Cache** | Identical or near-identical queries skip the full retrieval pipeline | SHA-256 exact match + `$vectorSearch` cosine ≥ 0.95, per-document TTL, fire-and-forget writes |
|
|
1287
|
+
| 14 | **Time Series Telemetry** | Operational visibility into every memory operation with automatic 7-day retention | Time series collection with `granularity: "seconds"`, P50/P95/P99 latency, cache hit rates |
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1290
|
+
### Task 6.2: Update README.md collection count and table
|
|
1291
|
+
|
|
1292
|
+
**Files:**
|
|
1293
|
+
|
|
1294
|
+
- Modify: `README.md`
|
|
1295
|
+
|
|
1296
|
+
Update collection count from "20" to "22" everywhere it appears.
|
|
1297
|
+
Update index counts from "53 standard indexes" to "58 standard indexes" and "8 search indexes" to "9 search indexes".
|
|
1298
|
+
|
|
1299
|
+
Add to the 20 Collections table:
|
|
1300
|
+
|
|
1301
|
+
```markdown
|
|
1302
|
+
| Query cache | `query_cache` |
|
|
1303
|
+
| Observability | `memory_telemetry` (time series) |
|
|
1304
|
+
```
|
|
1305
|
+
|
|
1306
|
+
### Task 6.3: Update README.md comparison table
|
|
1307
|
+
|
|
1308
|
+
**Files:**
|
|
1309
|
+
|
|
1310
|
+
- Modify: `README.md` (comparison table at lines ~68-84)
|
|
1311
|
+
|
|
1312
|
+
Update "Operational visibility" row:
|
|
1313
|
+
|
|
1314
|
+
```markdown
|
|
1315
|
+
| Operational visibility | Limited | Ingest runs, projection runs, relevance telemetry, time series observability |
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
Add row:
|
|
1319
|
+
|
|
1320
|
+
```markdown
|
|
1321
|
+
| Query caching | None | Two-tier semantic cache (SHA-256 exact + cosine similarity) |
|
|
1322
|
+
```
|
|
1323
|
+
|
|
1324
|
+
Update "Data model" row:
|
|
1325
|
+
|
|
1326
|
+
```markdown
|
|
1327
|
+
| Data model | Flat files + SQLite rows | 22 collections, 58 indexes |
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
### Task 6.4: Update README.md architecture diagram
|
|
1331
|
+
|
|
1332
|
+
**Files:**
|
|
1333
|
+
|
|
1334
|
+
- Modify: `README.md` (architecture diagram at lines ~96-119)
|
|
1335
|
+
|
|
1336
|
+
Add cache to retrieval path:
|
|
1337
|
+
|
|
1338
|
+
```
|
|
1339
|
+
Retrieval Path:
|
|
1340
|
+
Query -> checkCache() -> HIT? return cached results
|
|
1341
|
+
-> MISS -> planRetrieval() -> score 8 paths ...
|
|
1342
|
+
-> writeCache() (fire-and-forget on results)
|
|
1343
|
+
```
|
|
1344
|
+
|
|
1345
|
+
Add telemetry emission note:
|
|
1346
|
+
|
|
1347
|
+
```
|
|
1348
|
+
Observability:
|
|
1349
|
+
All paths emit to memory_telemetry (time series, fire-and-forget)
|
|
1350
|
+
```
|
|
1351
|
+
|
|
1352
|
+
### Task 6.5: Final validation
|
|
1353
|
+
|
|
1354
|
+
**Step 1:** Run type check
|
|
1355
|
+
|
|
1356
|
+
```bash
|
|
1357
|
+
pnpm build
|
|
1358
|
+
```
|
|
1359
|
+
|
|
1360
|
+
**Step 2:** Run all memory tests
|
|
1361
|
+
|
|
1362
|
+
```bash
|
|
1363
|
+
pnpm test -- src/memory/
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
**Step 3:** Run full test suite
|
|
1367
|
+
|
|
1368
|
+
```bash
|
|
1369
|
+
pnpm test
|
|
1370
|
+
```
|
|
1371
|
+
|
|
1372
|
+
**Commit after Phase 6:**
|
|
1373
|
+
|
|
1374
|
+
```
|
|
1375
|
+
Docs: update README with semantic cache, time series telemetry, and 22-collection architecture
|
|
1376
|
+
```
|
|
1377
|
+
|
|
1378
|
+
---
|
|
1379
|
+
|
|
1380
|
+
## Risks
|
|
1381
|
+
|
|
1382
|
+
| Risk | P (1-5) | I (1-5) | Score | Mitigation |
|
|
1383
|
+
| ------------------------------------------------------------- | ------- | ------- | ----- | -------------------------------------------------------------------------------- |
|
|
1384
|
+
| Time series collection creation fails on older MongoDB | 2 | 3 | 6 | Try/catch with log.warn, degrade to no telemetry |
|
|
1385
|
+
| autoEmbed vector index on query_cache not ready at query time | 3 | 2 | 6 | Tier 2 semantic check wrapped in try/catch, degrades to Tier 1 only |
|
|
1386
|
+
| Cache TTL too short/long for real-world use | 2 | 2 | 4 | Configurable via MemoryMongoDBConfig.cache section |
|
|
1387
|
+
| Fire-and-forget writes create backpressure | 1 | 3 | 3 | insertOne is lightweight; log.warn on error provides visibility |
|
|
1388
|
+
| $vectorSearch on query_cache hits cold index (no data) | 2 | 1 | 2 | Returns empty results, Tier 2 skipped, cache miss returned |
|
|
1389
|
+
| Existing test count changes break e2e assertions | 3 | 2 | 6 | Update EXPECTED_COLLECTION_SUFFIXES and EXPECTED_STANDARD_INDEX_COUNT in Phase 1 |
|
|
1390
|
+
|
|
1391
|
+
---
|
|
1392
|
+
|
|
1393
|
+
## Success Criteria
|
|
1394
|
+
|
|
1395
|
+
- [ ] `query_cache` collection with $jsonSchema, unique index, TTL index, and autoEmbed vector index
|
|
1396
|
+
- [ ] Two-tier cache check (exact hash + semantic similarity) before search pipeline
|
|
1397
|
+
- [ ] Fire-and-forget cache write after search results
|
|
1398
|
+
- [ ] `memory_telemetry` time series collection with 7-day TTL
|
|
1399
|
+
- [ ] emitTelemetry called from 5 code paths (search, event write, projection, cache, graph)
|
|
1400
|
+
- [ ] Dashboard aggregation helpers (latency percentiles, cache hit rate, operation distribution)
|
|
1401
|
+
- [ ] Cache and telemetry config sections in MemoryMongoDBConfig
|
|
1402
|
+
- [ ] All new types and functions exported from barrel (index.ts)
|
|
1403
|
+
- [ ] README updated with 14 capabilities, 22 collections, cache + telemetry
|
|
1404
|
+
- [ ] 50+ new tests pass
|
|
1405
|
+
- [ ] `pnpm build` exit 0
|
|
1406
|
+
- [ ] `pnpm test` — no regressions
|
|
1407
|
+
|
|
1408
|
+
---
|
|
1409
|
+
|
|
1410
|
+
## Acceptance Checks
|
|
1411
|
+
|
|
1412
|
+
```bash
|
|
1413
|
+
# Phase 1: Schema tests pass
|
|
1414
|
+
pnpm test -- src/memory/mongodb-schema.test.ts
|
|
1415
|
+
|
|
1416
|
+
# Phase 2: Cache module tests pass
|
|
1417
|
+
pnpm test -- src/memory/mongodb-query-cache.test.ts
|
|
1418
|
+
|
|
1419
|
+
# Phase 3: Manager integration tests pass
|
|
1420
|
+
pnpm test -- src/memory/mongodb-manager.test.ts
|
|
1421
|
+
|
|
1422
|
+
# Phase 4: Telemetry module tests pass
|
|
1423
|
+
pnpm test -- src/memory/mongodb-telemetry.test.ts
|
|
1424
|
+
|
|
1425
|
+
# Phase 5: All affected files pass
|
|
1426
|
+
pnpm test -- src/memory/mongodb-manager.test.ts src/memory/mongodb-ops.test.ts src/memory/mongodb-query-cache.test.ts src/memory/mongodb-graph.test.ts
|
|
1427
|
+
|
|
1428
|
+
# Phase 6: Full suite + build
|
|
1429
|
+
pnpm build
|
|
1430
|
+
pnpm test
|
|
1431
|
+
```
|