@remnic/core 1.0.2 → 1.0.3
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/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/access-cli.d.ts +13 -3
- package/dist/access-cli.js +90 -75
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +10 -3
- package/dist/access-http.js +25 -18
- package/dist/access-mcp.d.ts +30 -3
- package/dist/access-mcp.js +16 -1
- package/dist/access-schema.d.ts +12 -12
- package/dist/access-schema.js +1 -1
- package/dist/access-service.d.ts +65 -4
- package/dist/access-service.js +21 -15
- package/dist/active-memory-bridge.d.ts +66 -0
- package/dist/active-memory-bridge.js +11 -0
- package/dist/active-recall.d.ts +96 -0
- package/dist/active-recall.js +308 -0
- package/dist/active-recall.js.map +1 -0
- package/dist/behavior-learner.js +1 -1
- package/dist/bootstrap.d.ts +6 -3
- package/dist/bootstrap.js +2 -2
- package/dist/boxes.js +2 -2
- package/dist/briefing.d.ts +169 -0
- package/dist/briefing.js +52 -0
- package/dist/briefing.js.map +1 -0
- package/dist/buffer.d.ts +19 -5
- package/dist/buffer.js +2 -2
- package/dist/calibration.js +6 -6
- package/dist/causal-behavior.js +5 -5
- package/dist/causal-chain.js +3 -3
- package/dist/causal-consolidation.d.ts +22 -2
- package/dist/causal-consolidation.js +36 -9
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +6 -6
- package/dist/causal-trajectory-graph.js +1 -1
- package/dist/causal-trajectory.d.ts +14 -1
- package/dist/causal-trajectory.js +5 -1
- package/dist/{chunk-KWBU5S5U.js → chunk-2ODBA7MQ.js} +9 -3
- package/dist/chunk-2ODBA7MQ.js.map +1 -0
- package/dist/{chunk-6UJQNRIO.js → chunk-2VFW5K5U.js} +93 -36
- package/dist/chunk-2VFW5K5U.js.map +1 -0
- package/dist/chunk-3PG3H5TD.js +7 -0
- package/dist/chunk-3PG3H5TD.js.map +1 -0
- package/dist/{chunk-NTTLPF7F.js → chunk-3QFQGRHO.js} +5 -5
- package/dist/chunk-4DJQYKMN.js +187 -0
- package/dist/chunk-4DJQYKMN.js.map +1 -0
- package/dist/chunk-4KAN3GZ3.js +225 -0
- package/dist/chunk-4KAN3GZ3.js.map +1 -0
- package/dist/{chunk-ORZMT74A.js → chunk-4NRAJUDS.js} +11 -1
- package/dist/chunk-4NRAJUDS.js.map +1 -0
- package/dist/{chunk-B7LOFDVE.js → chunk-4WMCPJWX.js} +8 -3
- package/dist/chunk-4WMCPJWX.js.map +1 -0
- package/dist/{chunk-G3AG3KZN.js → chunk-5IZL4DCV.js} +2 -2
- package/dist/{chunk-BRK4ODMI.js → chunk-5NPGSAVB.js} +2 -2
- package/dist/chunk-6MKAMLQL.js +16 -0
- package/dist/chunk-6MKAMLQL.js.map +1 -0
- package/dist/{chunk-ESSMF2FR.js → chunk-6PFRXT4K.js} +15 -6
- package/dist/chunk-6PFRXT4K.js.map +1 -0
- package/dist/chunk-6ZH4TU6I.js +245 -0
- package/dist/chunk-6ZH4TU6I.js.map +1 -0
- package/dist/{chunk-V4YC4LUK.js → chunk-74JR4N5J.js} +175 -63
- package/dist/chunk-74JR4N5J.js.map +1 -0
- package/dist/{chunk-L5RPWGFK.js → chunk-7DHTMOND.js} +2 -2
- package/dist/{chunk-TVVVQQAK.js → chunk-7PA4OZEU.js} +53 -11
- package/dist/chunk-7PA4OZEU.js.map +1 -0
- package/dist/{chunk-Q6FETXJA.js → chunk-7SEAZFFB.js} +2 -2
- package/dist/chunk-ALXMCZEU.js +332 -0
- package/dist/chunk-ALXMCZEU.js.map +1 -0
- package/dist/{chunk-QANCTXQF.js → chunk-AYPYCLR7.js} +3 -3
- package/dist/{chunk-WWIQTB2Y.js → chunk-BKQJBXXX.js} +9 -2
- package/dist/chunk-BKQJBXXX.js.map +1 -0
- package/dist/{chunk-LP47L3ZX.js → chunk-BTY5RRRF.js} +7 -7
- package/dist/{chunk-SCHEKPYH.js → chunk-C2EFFULQ.js} +1 -1
- package/dist/{chunk-GJR6D6KC.js → chunk-D654IBA6.js} +2 -2
- package/dist/{chunk-UV2FO7J4.js → chunk-E6K4NIEU.js} +2 -2
- package/dist/{chunk-T4WRIV2C.js → chunk-EABGC2TL.js} +2 -2
- package/dist/chunk-ECKDIK5F.js +813 -0
- package/dist/chunk-ECKDIK5F.js.map +1 -0
- package/dist/chunk-EJI5XIBB.js +232 -0
- package/dist/chunk-EJI5XIBB.js.map +1 -0
- package/dist/{chunk-ONRU4L2N.js → chunk-FEMOX5AD.js} +2 -2
- package/dist/{chunk-IFFFR3MR.js → chunk-FSFEQI74.js} +3 -3
- package/dist/chunk-G4SK7DSQ.js +121 -0
- package/dist/chunk-G4SK7DSQ.js.map +1 -0
- package/dist/{chunk-UIYZ5T3I.js → chunk-GJQPH5G3.js} +8 -8
- package/dist/{chunk-2PO5ZRKV.js → chunk-GZCUW5IC.js} +16 -3
- package/dist/chunk-GZCUW5IC.js.map +1 -0
- package/dist/{chunk-IZME7KW2.js → chunk-HITJFT7E.js} +24 -10
- package/dist/{chunk-IZME7KW2.js.map → chunk-HITJFT7E.js.map} +1 -1
- package/dist/chunk-IQT3XTKW.js +121 -0
- package/dist/chunk-IQT3XTKW.js.map +1 -0
- package/dist/{chunk-BDFZXRSO.js → chunk-J4IYOZZ5.js} +15 -2
- package/dist/chunk-J4IYOZZ5.js.map +1 -0
- package/dist/{chunk-ZKYI7UVO.js → chunk-JR4ZC3G4.js} +2 -2
- package/dist/{chunk-UCYSTFZR.js → chunk-JRNQ3RNA.js} +2 -2
- package/dist/{chunk-UYSKNO6E.js → chunk-JROGC36Y.js} +15 -4
- package/dist/chunk-JROGC36Y.js.map +1 -0
- package/dist/{chunk-GPGBSNKM.js → chunk-K4FLSOR5.js} +2 -2
- package/dist/{chunk-M5ZBBBJI.js → chunk-KEG4GNGI.js} +2 -2
- package/dist/chunk-KVE7R4CG.js +320 -0
- package/dist/chunk-KVE7R4CG.js.map +1 -0
- package/dist/{chunk-L7WO3MZ4.js → chunk-KWP7T3DP.js} +2 -2
- package/dist/chunk-LAYN4LDC.js +267 -0
- package/dist/chunk-LAYN4LDC.js.map +1 -0
- package/dist/{chunk-PGK3VUHN.js → chunk-MTLYEMJB.js} +3 -2
- package/dist/chunk-MTLYEMJB.js.map +1 -0
- package/dist/{chunk-J47FNDR7.js → chunk-MYQWXITD.js} +7 -7
- package/dist/{chunk-YNI4S5WT.js → chunk-N53K2EXC.js} +2 -2
- package/dist/{chunk-763GUIOU.js → chunk-NBNN5GOB.js} +2 -2
- package/dist/{chunk-CXWFUJR2.js → chunk-NSB3WSYS.js} +125 -6
- package/dist/chunk-NSB3WSYS.js.map +1 -0
- package/dist/{chunk-KL4CP4SB.js → chunk-O5ETUNBT.js} +17 -5
- package/dist/chunk-O5ETUNBT.js.map +1 -0
- package/dist/{chunk-OOSWAUYB.js → chunk-ODWDQNRE.js} +2 -2
- package/dist/{chunk-ISY75RLM.js → chunk-OJFGVJS6.js} +288 -7
- package/dist/chunk-OJFGVJS6.js.map +1 -0
- package/dist/{chunk-HLBYLYRD.js → chunk-PAORGQRI.js} +70 -13
- package/dist/chunk-PAORGQRI.js.map +1 -0
- package/dist/{chunk-ZJLY4QSU.js → chunk-PMB3WGDL.js} +69 -6
- package/dist/chunk-PMB3WGDL.js.map +1 -0
- package/dist/{chunk-J3BT33K7.js → chunk-POBPGDWI.js} +5 -5
- package/dist/{chunk-QWUUMMIK.js → chunk-POMSFKTB.js} +1351 -76
- package/dist/chunk-POMSFKTB.js.map +1 -0
- package/dist/{chunk-OTAVQCSF.js → chunk-PYXS46O7.js} +2 -2
- package/dist/chunk-QDW3E4RD.js +108 -0
- package/dist/chunk-QDW3E4RD.js.map +1 -0
- package/dist/{chunk-YNCQ7E4M.js → chunk-QDYXG4CS.js} +4 -3
- package/dist/chunk-QDYXG4CS.js.map +1 -0
- package/dist/{chunk-XUHI52HK.js → chunk-QKAH5B6E.js} +4 -4
- package/dist/{chunk-HLXVTBF3.js → chunk-QNJMBKFK.js} +3 -2
- package/dist/chunk-QNJMBKFK.js.map +1 -0
- package/dist/chunk-RCICHSHL.js +789 -0
- package/dist/chunk-RCICHSHL.js.map +1 -0
- package/dist/{chunk-HG2NKWR2.js → chunk-S4LX5EBI.js} +2 -2
- package/dist/{chunk-4A24LIM2.js → chunk-S75M5ZRK.js} +2 -2
- package/dist/{chunk-QCCCQT3O.js → chunk-TBBDFYXW.js} +2 -2
- package/dist/chunk-TBBDFYXW.js.map +1 -0
- package/dist/{chunk-U4PV25RD.js → chunk-U2IQTSBY.js} +1 -1
- package/dist/chunk-U2IQTSBY.js.map +1 -0
- package/dist/chunk-U66YHYC7.js +31 -0
- package/dist/chunk-U66YHYC7.js.map +1 -0
- package/dist/{chunk-MWGVGUIS.js → chunk-UEYA6UC7.js} +36 -4
- package/dist/chunk-UEYA6UC7.js.map +1 -0
- package/dist/{chunk-MDDAA2AO.js → chunk-UPMD5XND.js} +2 -2
- package/dist/{chunk-M5KEYE5E.js → chunk-URB2WSKZ.js} +2 -2
- package/dist/chunk-UVJFDP7P.js +202 -0
- package/dist/chunk-UVJFDP7P.js.map +1 -0
- package/dist/{chunk-QY2BHY5O.js → chunk-V7XCAHIB.js} +265 -25
- package/dist/chunk-V7XCAHIB.js.map +1 -0
- package/dist/chunk-W6SL7OFG.js +180 -0
- package/dist/chunk-W6SL7OFG.js.map +1 -0
- package/dist/{chunk-QDOSNLB4.js → chunk-X4WESCKA.js} +17 -15
- package/dist/chunk-X4WESCKA.js.map +1 -0
- package/dist/{chunk-OTFNI3OO.js → chunk-XMGSSBFX.js} +1738 -383
- package/dist/chunk-XMGSSBFX.js.map +1 -0
- package/dist/chunk-YDBIWGNI.js +298 -0
- package/dist/chunk-YDBIWGNI.js.map +1 -0
- package/dist/chunk-YFYL2SIJ.js +7857 -0
- package/dist/chunk-YFYL2SIJ.js.map +1 -0
- package/dist/chunking.js +1 -1
- package/dist/citations.d.ts +67 -0
- package/dist/citations.js +13 -0
- package/dist/citations.js.map +1 -0
- package/dist/cli-DwIBnp2g.d.ts +1240 -0
- package/dist/cli.d.ts +31 -1147
- package/dist/cli.js +149 -7092
- package/dist/cli.js.map +1 -1
- package/dist/codex-materialize-CQlLTzke.d.ts +139 -0
- package/dist/codex-thread-key.d.ts +3 -0
- package/dist/codex-thread-key.js +7 -0
- package/dist/codex-thread-key.js.map +1 -0
- package/dist/config.js +3 -2
- package/dist/connectors/codex/instructions.md +160 -0
- package/dist/connectors/codex/resources/namespace-cheatsheet.md +48 -0
- package/dist/day-summary.d.ts +7 -2
- package/dist/day-summary.js +5 -2
- package/dist/embedding-fallback.d.ts +96 -2
- package/dist/embedding-fallback.js +6 -4
- package/dist/{engine-2A6J4XEX.js → engine-X7X3AAG3.js} +10 -7
- package/dist/engine-X7X3AAG3.js.map +1 -0
- package/dist/entity-retrieval.d.ts +3 -2
- package/dist/entity-retrieval.js +10 -7
- package/dist/entity-schema.d.ts +11 -0
- package/dist/entity-schema.js +19 -0
- package/dist/entity-schema.js.map +1 -0
- package/dist/explicit-capture.d.ts +6 -3
- package/dist/explicit-capture.js +2 -2
- package/dist/extraction-judge.d.ts +66 -0
- package/dist/extraction-judge.js +18 -0
- package/dist/extraction-judge.js.map +1 -0
- package/dist/extraction.d.ts +1 -0
- package/dist/extraction.js +12 -10
- package/dist/fallback-llm.js +4 -4
- package/dist/graph.js +1 -1
- package/dist/importance.d.ts +11 -1
- package/dist/importance.js +3 -1
- package/dist/index.d.ts +1140 -8
- package/dist/index.js +3350 -333
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +2 -1
- package/dist/intent.js +3 -1
- package/dist/lifecycle.js +1 -1
- package/dist/local-llm.js +2 -2
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +1 -1
- package/dist/memory-cache.d.ts +2 -2
- package/dist/memory-cache.js +1 -1
- package/dist/{memory-projection-store-NxMkbocT.d.ts → memory-projection-store-DeSXPh1j.d.ts} +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/model-registry.js +2 -2
- package/dist/models-json.js +2 -2
- package/dist/native-knowledge.js +2 -2
- package/dist/negative.js +2 -2
- package/dist/operator-toolkit.js +20 -16
- package/dist/{orchestrator-zTa-Qo-1.d.ts → orchestrator-B9kwlCep.d.ts} +252 -7
- package/dist/orchestrator.d.ts +6 -3
- package/dist/orchestrator.js +70 -58
- package/dist/page-versioning.d.ts +77 -0
- package/dist/page-versioning.js +15 -0
- package/dist/page-versioning.js.map +1 -0
- package/dist/plugin-id.d.ts +37 -0
- package/dist/plugin-id.js +11 -0
- package/dist/plugin-id.js.map +1 -0
- package/dist/policy-runtime.js +2 -2
- package/dist/profiling.js +2 -2
- package/dist/qmd.d.ts +5 -2
- package/dist/qmd.js +3 -3
- package/dist/recall-audit.d.ts +20 -0
- package/dist/recall-audit.js +50 -0
- package/dist/recall-audit.js.map +1 -0
- package/dist/recall-mmr.d.ts +152 -0
- package/dist/recall-mmr.js +17 -0
- package/dist/recall-mmr.js.map +1 -0
- package/dist/recall-qos.js +2 -2
- package/dist/recall-state.js +2 -2
- package/dist/relevance.js +2 -2
- package/dist/resolve-provider-secret.js +2 -2
- package/dist/resume-bundles.js +5 -4
- package/dist/retrieval-agents.js +2 -2
- package/dist/retrieval.js +2 -2
- package/dist/schemas.d.ts +398 -40
- package/dist/schemas.js +3 -1
- package/dist/sdk-compat.d.ts +2 -0
- package/dist/sdk-compat.js +6 -3
- package/dist/sdk-compat.js.map +1 -1
- package/dist/semantic-chunking.d.ts +87 -0
- package/dist/semantic-chunking.js +20 -0
- package/dist/semantic-chunking.js.map +1 -0
- package/dist/semantic-consolidation-DrvSYRdB.d.ts +119 -0
- package/dist/semantic-consolidation.d.ts +4 -42
- package/dist/semantic-consolidation.js +23 -2
- package/dist/semantic-rule-promotion.js +9 -6
- package/dist/semantic-rule-verifier.js +10 -7
- package/dist/session-observer-state.js +2 -2
- package/dist/session-toggles.d.ts +22 -0
- package/dist/session-toggles.js +116 -0
- package/dist/session-toggles.js.map +1 -0
- package/dist/skills-registry.d.ts +47 -0
- package/dist/skills-registry.js +48 -0
- package/dist/skills-registry.js.map +1 -0
- package/dist/source-attribution.d.ts +169 -0
- package/dist/source-attribution.js +27 -0
- package/dist/source-attribution.js.map +1 -0
- package/dist/storage.d.ts +171 -10
- package/dist/storage.js +16 -5
- package/dist/summarizer.js +7 -7
- package/dist/temporal-supersession.d.ts +127 -0
- package/dist/temporal-supersession.js +20 -0
- package/dist/temporal-supersession.js.map +1 -0
- package/dist/threading.js +2 -2
- package/dist/tier-migration.d.ts +2 -1
- package/dist/tier-routing.js +2 -2
- package/dist/tokens.d.ts +21 -1
- package/dist/tokens.js +5 -1
- package/dist/transcript.js +2 -2
- package/dist/types.d.ts +497 -3
- package/dist/types.js +1 -1
- package/dist/utility-learner.js +2 -2
- package/dist/utility-runtime.js +3 -3
- package/dist/verified-recall.js +11 -8
- package/dist/whitespace.d.ts +4 -0
- package/dist/whitespace.js +9 -0
- package/dist/whitespace.js.map +1 -0
- package/package.json +14 -8
- package/dist/chunk-2CJCWDMR.js +0 -87
- package/dist/chunk-2CJCWDMR.js.map +0 -1
- package/dist/chunk-2PO5ZRKV.js.map +0 -1
- package/dist/chunk-6UJQNRIO.js.map +0 -1
- package/dist/chunk-B7LOFDVE.js.map +0 -1
- package/dist/chunk-BDFZXRSO.js.map +0 -1
- package/dist/chunk-CXWFUJR2.js.map +0 -1
- package/dist/chunk-DORBM6OB.js +0 -81
- package/dist/chunk-DORBM6OB.js.map +0 -1
- package/dist/chunk-ESSMF2FR.js.map +0 -1
- package/dist/chunk-HLBYLYRD.js.map +0 -1
- package/dist/chunk-HLXVTBF3.js.map +0 -1
- package/dist/chunk-ISY75RLM.js.map +0 -1
- package/dist/chunk-KL4CP4SB.js.map +0 -1
- package/dist/chunk-KWBU5S5U.js.map +0 -1
- package/dist/chunk-MWGVGUIS.js.map +0 -1
- package/dist/chunk-ORZMT74A.js.map +0 -1
- package/dist/chunk-OTFNI3OO.js.map +0 -1
- package/dist/chunk-PGK3VUHN.js.map +0 -1
- package/dist/chunk-QCCCQT3O.js.map +0 -1
- package/dist/chunk-QDOSNLB4.js.map +0 -1
- package/dist/chunk-QPKFPHOO.js +0 -178
- package/dist/chunk-QPKFPHOO.js.map +0 -1
- package/dist/chunk-QWUUMMIK.js.map +0 -1
- package/dist/chunk-QY2BHY5O.js.map +0 -1
- package/dist/chunk-TVVVQQAK.js.map +0 -1
- package/dist/chunk-U4PV25RD.js.map +0 -1
- package/dist/chunk-UYSKNO6E.js.map +0 -1
- package/dist/chunk-V4YC4LUK.js.map +0 -1
- package/dist/chunk-WWIQTB2Y.js.map +0 -1
- package/dist/chunk-YNCQ7E4M.js.map +0 -1
- package/dist/chunk-ZJLY4QSU.js.map +0 -1
- /package/dist/{engine-2A6J4XEX.js.map → active-memory-bridge.js.map} +0 -0
- /package/dist/{chunk-NTTLPF7F.js.map → chunk-3QFQGRHO.js.map} +0 -0
- /package/dist/{chunk-G3AG3KZN.js.map → chunk-5IZL4DCV.js.map} +0 -0
- /package/dist/{chunk-BRK4ODMI.js.map → chunk-5NPGSAVB.js.map} +0 -0
- /package/dist/{chunk-L5RPWGFK.js.map → chunk-7DHTMOND.js.map} +0 -0
- /package/dist/{chunk-Q6FETXJA.js.map → chunk-7SEAZFFB.js.map} +0 -0
- /package/dist/{chunk-QANCTXQF.js.map → chunk-AYPYCLR7.js.map} +0 -0
- /package/dist/{chunk-LP47L3ZX.js.map → chunk-BTY5RRRF.js.map} +0 -0
- /package/dist/{chunk-SCHEKPYH.js.map → chunk-C2EFFULQ.js.map} +0 -0
- /package/dist/{chunk-GJR6D6KC.js.map → chunk-D654IBA6.js.map} +0 -0
- /package/dist/{chunk-UV2FO7J4.js.map → chunk-E6K4NIEU.js.map} +0 -0
- /package/dist/{chunk-T4WRIV2C.js.map → chunk-EABGC2TL.js.map} +0 -0
- /package/dist/{chunk-ONRU4L2N.js.map → chunk-FEMOX5AD.js.map} +0 -0
- /package/dist/{chunk-IFFFR3MR.js.map → chunk-FSFEQI74.js.map} +0 -0
- /package/dist/{chunk-UIYZ5T3I.js.map → chunk-GJQPH5G3.js.map} +0 -0
- /package/dist/{chunk-ZKYI7UVO.js.map → chunk-JR4ZC3G4.js.map} +0 -0
- /package/dist/{chunk-UCYSTFZR.js.map → chunk-JRNQ3RNA.js.map} +0 -0
- /package/dist/{chunk-GPGBSNKM.js.map → chunk-K4FLSOR5.js.map} +0 -0
- /package/dist/{chunk-M5ZBBBJI.js.map → chunk-KEG4GNGI.js.map} +0 -0
- /package/dist/{chunk-L7WO3MZ4.js.map → chunk-KWP7T3DP.js.map} +0 -0
- /package/dist/{chunk-J47FNDR7.js.map → chunk-MYQWXITD.js.map} +0 -0
- /package/dist/{chunk-YNI4S5WT.js.map → chunk-N53K2EXC.js.map} +0 -0
- /package/dist/{chunk-763GUIOU.js.map → chunk-NBNN5GOB.js.map} +0 -0
- /package/dist/{chunk-OOSWAUYB.js.map → chunk-ODWDQNRE.js.map} +0 -0
- /package/dist/{chunk-J3BT33K7.js.map → chunk-POBPGDWI.js.map} +0 -0
- /package/dist/{chunk-OTAVQCSF.js.map → chunk-PYXS46O7.js.map} +0 -0
- /package/dist/{chunk-XUHI52HK.js.map → chunk-QKAH5B6E.js.map} +0 -0
- /package/dist/{chunk-HG2NKWR2.js.map → chunk-S4LX5EBI.js.map} +0 -0
- /package/dist/{chunk-4A24LIM2.js.map → chunk-S75M5ZRK.js.map} +0 -0
- /package/dist/{chunk-MDDAA2AO.js.map → chunk-UPMD5XND.js.map} +0 -0
- /package/dist/{chunk-M5KEYE5E.js.map → chunk-URB2WSKZ.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/qmd.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\nimport { getCachedQmdSearch, setCachedQmdSearch } from \"./memory-cache.js\";\nimport type { QmdSearchExplain, QmdSearchResult } from \"./types.js\";\nimport type { SearchBackend, SearchExecutionOptions, SearchQueryOptions } from \"./search/port.js\";\nimport { launchProcess, type CommandChildProcess } from \"./runtime/child-process.js\";\nimport { mergeEnv } from \"./runtime/env.js\";\n\nexport interface QmdClientOptions {\n slowLog?: { enabled: boolean; thresholdMs: number };\n updateTimeoutMs?: number;\n updateMinIntervalMs?: number;\n qmdPath?: string;\n daemonUrl?: string;\n daemonRecheckIntervalMs?: number;\n}\n\nconst QMD_TIMEOUT_MS = 30_000;\n// Daemon timeout for individual search calls. Keep well under RECALL_TIMEOUT_MS (75s) so a\n// slow/loading daemon fails fast and the caller can return early rather than hanging.\n// After the daemon has loaded its index (~90s for 75K files), actual searches complete in <3s.\n// During the loading window, searches will timeout/return [] quickly — this is preferable to\n// blocking the full 75s on every recall request.\n// Note: keep this ≥ 5s to allow normal searches (post-load) to complete reliably.\nconst QMD_DAEMON_TIMEOUT_MS = 8_000;\nconst QMD_PROBE_TIMEOUT_MS = 8_000;\nconst QMD_UPDATE_BACKOFF_MS = 15 * 60 * 1000; // 15m\nconst QMD_EMBED_BACKOFF_MS = 60 * 60 * 1000; // 60m\nconst QMD_CLI_WARN_THROTTLE_MS = 15 * 60 * 1000; // 15m\nconst QMD_FALLBACK_PATHS = [\n path.join(os.homedir(), \".bun\", \"bin\", \"qmd\"),\n \"/usr/local/bin/qmd\",\n \"/opt/homebrew/bin/qmd\",\n];\nconst QMD_GLOBAL_STATE_KEY = \"__openclawEngramQmdGlobalState\";\n\ntype QmdGlobalState = {\n warnedGlobalUpdateBehavior: boolean;\n lastGlobalUpdateRunAtMs: number | null;\n lastGlobalUpdateFailAtMs: number | null;\n lastGlobalEmbedRunAtMs: number | null;\n lastGlobalEmbedFailAtMs: number | null;\n lastCliWarnAtMs: number | null;\n lastUpdateByCollectionMs: Record<string, number>;\n lastUpdateFailByCollectionMs: Record<string, number>;\n lastEmbedByCollectionMs: Record<string, number>;\n lastEmbedFailByCollectionMs: Record<string, number>;\n};\n\nfunction getGlobalQmdState(): QmdGlobalState {\n const g = globalThis as any;\n if (!g[QMD_GLOBAL_STATE_KEY]) {\n g[QMD_GLOBAL_STATE_KEY] = {\n warnedGlobalUpdateBehavior: false,\n lastGlobalUpdateRunAtMs: null,\n lastGlobalUpdateFailAtMs: null,\n lastGlobalEmbedRunAtMs: null,\n lastGlobalEmbedFailAtMs: null,\n lastCliWarnAtMs: null,\n lastUpdateByCollectionMs: {},\n lastUpdateFailByCollectionMs: {},\n lastEmbedByCollectionMs: {},\n lastEmbedFailByCollectionMs: {},\n } satisfies QmdGlobalState;\n }\n return g[QMD_GLOBAL_STATE_KEY] as QmdGlobalState;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction abortError(message: string): Error {\n const err = new Error(message);\n Object.defineProperty(err, \"name\", { value: \"AbortError\" });\n return err;\n}\n\nfunction isAbortError(err: unknown): boolean {\n return err instanceof Error && err.name === \"AbortError\";\n}\n\nfunction errorMessage(err: unknown): string {\n if (typeof err === \"string\") return err;\n if (err instanceof Error) return err.message;\n if (err && typeof err === \"object\" && \"message\" in err && typeof (err as { message?: unknown }).message === \"string\") {\n return (err as { message: string }).message;\n }\n return String(err);\n}\n\nfunction isCallerCancellation(err: unknown, signal?: AbortSignal): boolean {\n if (signal?.aborted) return true;\n if (isAbortError(err)) return true;\n if (err && typeof err === \"object\") {\n const code = \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (code === \"ABORT_ERR\" || code === \"ERR_CANCELED\") return true;\n }\n return false;\n}\n\nfunction isDaemonTimeoutError(err: unknown): boolean {\n return /timed out/i.test(errorMessage(err));\n}\n\nfunction throwIfAborted(signal?: AbortSignal, message = \"operation aborted\"): void {\n if (signal?.aborted) {\n throw abortError(message);\n }\n}\n\nfunction sleepWithSignal(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal);\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n cleanup();\n reject(abortError(\"operation aborted while waiting\"));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction isSqliteBusyError(msg: string): boolean {\n const lower = msg.toLowerCase();\n return (\n lower.includes(\"database is locked\") ||\n lower.includes(\"sqlite_busy\") ||\n lower.includes(\"sqlite_busy_recovery\") ||\n lower.includes(\"sqliterror: database is locked\")\n );\n}\n\nfunction stripControlChars(s: string): string {\n // Remove ANSI escapes and other control characters that explode logs.\n return s.replace(/\\x1b\\[[0-9;]*[A-Za-z]/g, \"\").replace(/[\\u0000-\\u001f\\u007f]/g, \"\");\n}\n\nfunction truncateForLog(s: string, max = 2000): string {\n const cleaned = stripControlChars(s);\n return cleaned.length > max ? cleaned.slice(0, max) + \"…(truncated)\" : cleaned;\n}\n\nfunction isVectorDimensionMismatchError(err: unknown): boolean {\n const msg = err instanceof Error ? err.message : String(err);\n return (\n /dimension mismatch/i.test(msg) ||\n (/vectors?_vec/i.test(msg) && /float\\[\\d+\\]/i.test(msg)) ||\n (/embedding/i.test(msg) && /dimensions?/i.test(msg))\n );\n}\n\nfunction parseQmdVersion(version: string | null): [number, number, number] | null {\n if (!version) return null;\n const match = version.match(/v?(\\d{1,10})\\.(\\d{1,10})\\.(\\d{1,10})/i);\n if (!match) return null;\n return [\n Number.parseInt(match[1] ?? \"0\", 10),\n Number.parseInt(match[2] ?? \"0\", 10),\n Number.parseInt(match[3] ?? \"0\", 10),\n ];\n}\n\nfunction versionAtLeast(\n current: [number, number, number] | null,\n target: [number, number, number],\n): boolean {\n if (!current) return false;\n for (let i = 0; i < 3; i += 1) {\n if ((current[i] ?? 0) > target[i]) return true;\n if ((current[i] ?? 0) < target[i]) return false;\n }\n return true;\n}\n\nfunction normalizeSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n if (!options) return undefined;\n const intent = typeof options.intent === \"string\" ? options.intent.trim() : \"\";\n const normalized: SearchQueryOptions = {};\n if (intent.length > 0) {\n normalized.intent = intent;\n }\n if (options.explain === true) {\n normalized.explain = true;\n }\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\nfunction parseExplainScores(value: unknown): number[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const scores = value.filter((entry): entry is number => typeof entry === \"number\");\n return scores.length > 0 ? scores : undefined;\n}\n\nexport function parseQmdExplain(value: unknown): QmdSearchExplain | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const candidate = value as Record<string, unknown>;\n const parsed: QmdSearchExplain = {\n ftsScores: parseExplainScores(candidate.ftsScores),\n vectorScores: parseExplainScores(candidate.vectorScores),\n rrf: typeof candidate.rrf === \"number\" ? candidate.rrf : undefined,\n rerankScore: typeof candidate.rerankScore === \"number\" ? candidate.rerankScore : undefined,\n blendedScore: typeof candidate.blendedScore === \"number\" ? candidate.blendedScore : undefined,\n };\n return Object.values(parsed).some((entry) => entry !== undefined) ? parsed : undefined;\n}\n\nclass AsyncMutex {\n private locked = false;\n private queue: Array<{\n resolve: (release: () => void) => void;\n reject: (reason: Error) => void;\n signal?: AbortSignal;\n onAbort: () => void;\n }> = [];\n\n async runExclusive<T>(fn: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n const release = await this.acquire(signal);\n try {\n throwIfAborted(signal);\n return await fn();\n } finally {\n release();\n }\n }\n\n private acquire(signal?: AbortSignal): Promise<() => void> {\n throwIfAborted(signal);\n if (!this.locked) {\n this.locked = true;\n return Promise.resolve(() => this.release());\n }\n\n return new Promise((resolve, reject) => {\n const waiter = {\n resolve: (release: () => void) => {\n signal?.removeEventListener(\"abort\", waiter.onAbort);\n resolve(release);\n },\n reject: (reason: Error) => {\n signal?.removeEventListener(\"abort\", waiter.onAbort);\n reject(reason);\n },\n signal,\n onAbort: () => {\n this.queue = this.queue.filter((entry) => entry !== waiter);\n reject(abortError(\"operation aborted while waiting for qmd mutex\"));\n },\n };\n signal?.addEventListener(\"abort\", waiter.onAbort, { once: true });\n this.queue.push(waiter);\n });\n }\n\n private release(): void {\n while (this.queue.length > 0) {\n const next = this.queue.shift();\n if (!next) break;\n if (next.signal?.aborted) {\n next.reject(abortError(\"operation aborted while waiting for qmd mutex\"));\n continue;\n }\n this.locked = true;\n next.resolve(() => this.release());\n return;\n }\n this.locked = false;\n }\n}\n\nconst QMD_MUTEX = new AsyncMutex();\n\nfunction runQmd(\n args: string[],\n timeoutMs: number = QMD_TIMEOUT_MS,\n qmdPath: string = \"qmd\",\n signal?: AbortSignal,\n): Promise<{ stdout: string; stderr: string }> {\n // Serialize all qmd calls. This avoids SQLite lock contention when multiple\n // channels/agents trigger QMD operations at nearly the same time.\n return QMD_MUTEX.runExclusive(async () => {\n throwIfAborted(signal, `qmd ${args.join(\" \")} aborted before start`);\n const maxAttempts = isLikelyWriteCommand(args) ? 3 : 1;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await runQmdOnce(args, timeoutMs, qmdPath, signal);\n } catch (err) {\n if (isAbortError(err)) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n if (attempt < maxAttempts && isSqliteBusyError(msg)) {\n // Another qmd call (or an external qmd process) currently holds the DB.\n // Back off briefly and retry.\n await sleepWithSignal(1500 * attempt, signal);\n continue;\n }\n throw err;\n }\n }\n // unreachable\n throw new Error(\"qmd command failed\");\n }, signal);\n}\n\nfunction isLikelyWriteCommand(args: string[]): boolean {\n const cmd = args[0] ?? \"\";\n return cmd === \"update\" || cmd === \"embed\" || cmd === \"cleanup\" || cmd === \"collection\";\n}\n\nfunction runQmdOnce(\n args: string[],\n timeoutMs: number,\n qmdPath: string,\n signal?: AbortSignal,\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal, `qmd ${args.join(\" \")} aborted before spawn`);\n const child = launchProcess(qmdPath, args, {\n env: mergeEnv({ NO_COLOR: \"1\" }),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n if (!child.stdout || !child.stderr) {\n reject(new Error(`qmd ${args.join(\" \")} failed to open stdio pipes`));\n return;\n }\n\n let stdout = \"\";\n let stderr = \"\";\n let settled = false;\n\n const timer = setTimeout(() => {\n settled = true;\n cleanup();\n child.kill(\"SIGKILL\");\n reject(new Error(`qmd ${args.join(\" \")} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n const onAbort = () => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n child.kill(\"SIGKILL\");\n reject(abortError(`qmd ${args.join(\" \")} aborted`));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n child.stdout.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n child.stderr.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n child.on(\"error\", (err) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n reject(err);\n });\n child.on(\"close\", (code) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n // QMD returns exit code 1 for --version (shows usage), but that's ok\n const isVersionCheck = args.length === 1 && args[0] === \"--version\";\n if (code === 0 || (isVersionCheck && code === 1)) {\n resolve({ stdout, stderr });\n } else {\n reject(\n new Error(\n `qmd ${args.join(\" \")} failed (code ${code}): ${truncateForLog(stderr || stdout)}`,\n ),\n );\n }\n });\n });\n}\n\n// ---------------------------------------------------------------------------\n// QMD Stdio Daemon Session (MCP over stdio child process)\n// ---------------------------------------------------------------------------\n\nlet nextJsonRpcId = 1;\n\nclass QmdDaemonSession {\n private child: CommandChildProcess | null = null;\n private initialized = false;\n private buffer = \"\";\n private startPromise: Promise<boolean> | null = null;\n private pendingRequests = new Map<\n number,\n {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n cleanup: () => void;\n }\n >();\n private readonly qmdPath: string;\n\n constructor(qmdPath: string) {\n this.qmdPath = qmdPath;\n }\n\n /** Spawn the qmd mcp child process and perform MCP handshake. */\n async start(): Promise<boolean> {\n if (this.child && !this.child.killed && this.initialized) {\n return true;\n }\n if (this.startPromise) {\n return this.startPromise;\n }\n this.startPromise = (async () => {\n // If the process is already running but not yet initialized (e.g. it is still\n // loading its index after a previous handshake timeout), reuse it instead of\n // killing and re-spawning. This prevents accumulating zombie qmd-mcp processes\n // when the daemon takes >15s to load a large collection.\n const processAlreadyRunning = this.child != null && !this.child.killed;\n if (!processAlreadyRunning) {\n if (this.child) {\n this.cleanup({ killChild: true });\n }\n try {\n const child = launchProcess(this.qmdPath, [\"mcp\"], {\n env: mergeEnv({ NO_COLOR: \"1\" }),\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n this.child = child;\n this.buffer = \"\";\n\n child.stdout?.on(\"data\", (data: Buffer) => {\n if (this.child !== child) return;\n this.handleStdoutData(data);\n });\n child.stderr?.on(\"data\", (data: Buffer) => {\n if (this.child !== child) return;\n const msg = data.toString().trim();\n if (msg) log.debug(`QMD mcp stderr: ${stripControlChars(msg)}`);\n });\n child.stdin?.on(\"error\", (err) => {\n // Swallow EPIPE/ERR_STREAM_DESTROYED — these happen when the child\n // process is killed (e.g. due to recall timeout) and a write arrives\n // after the pipe is broken. Without this handler Node.js would throw\n // an uncaught exception and crash the process.\n log.debug(`QMD mcp stdin error (suppressed): ${err.message}`);\n });\n child.on(\"error\", (err) => {\n if (this.child !== child) return;\n log.debug(`QMD mcp process error: ${err.message}`);\n this.cleanup({ child });\n });\n child.on(\"close\", (code) => {\n if (this.child !== child) return;\n log.debug(`QMD mcp process exited (code ${code})`);\n this.cleanup({ child });\n });\n } catch (err) {\n log.debug(`QMD mcp: failed to spawn process: ${err}`);\n this.cleanup({ killChild: true });\n return false;\n }\n } else {\n log.debug(\"QMD mcp: process already running, retrying handshake\");\n }\n\n try {\n // Use a generous timeout — large collections (75K+ files) can take 60-90s\n // to load their vector index. We keep the process alive across retries so\n // only one mcp instance is running at a time.\n const result = await this.sendRequest(\n \"initialize\",\n {\n protocolVersion: \"2024-11-05\",\n capabilities: {},\n clientInfo: { name: \"openclaw-engram\", version: \"1.0.0\" },\n },\n 60_000,\n );\n if (!result) {\n // Null result (non-timeout failure) — kill and let the next probe respawn.\n this.cleanup({ killChild: true });\n return false;\n }\n this.sendNotification(\"notifications/initialized\");\n this.initialized = true;\n log.info(\"QMD mcp: stdio session initialized\");\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (/timed out/i.test(msg)) {\n // Handshake timeout — process is still loading. Keep it alive for the\n // next retry (daemonRecheckIntervalMs). Do NOT kill and respawn.\n log.debug(`QMD mcp: handshake timed out — process still loading, will retry later`);\n // Reset initialized flag but leave child running.\n this.initialized = false;\n } else {\n log.debug(`QMD mcp: failed to start stdio session: ${err}`);\n this.cleanup({ killChild: true });\n }\n return false;\n } finally {\n this.startPromise = null;\n }\n })();\n return this.startPromise;\n }\n\n /** Call an MCP tool and return the parsed result. */\n async callTool(\n name: string,\n args: Record<string, unknown>,\n timeoutMs: number = 30_000,\n signal?: AbortSignal,\n ): Promise<unknown> {\n if (!this.child || this.child.killed || !this.initialized) {\n throw new Error(\"QMD mcp process not running\");\n }\n return this.sendRequest(\"tools/call\", { name, arguments: args }, timeoutMs, signal);\n }\n\n /** Kill stdio process and clear state so the next probe can restart. */\n invalidate(): void {\n this.cleanup({ killChild: true });\n }\n\n isActive(): boolean {\n return this.child !== null && !this.child.killed && this.initialized;\n }\n\n /** True while the process is spawned but the MCP handshake has not yet completed. */\n isLoading(): boolean {\n return this.child !== null && !this.child.killed && !this.initialized;\n }\n\n private sendRequest(\n method: string,\n params: Record<string, unknown>,\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal, `QMD mcp ${method} aborted before request`);\n if (!this.child || !this.child.stdin || this.child.killed) {\n reject(new Error(\"QMD mcp process not available\"));\n return;\n }\n\n const id = nextJsonRpcId++;\n const timer = setTimeout(() => {\n this.pendingRequests.delete(id);\n cleanup();\n reject(new Error(`QMD mcp ${method} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n const onAbort = () => {\n clearTimeout(timer);\n this.pendingRequests.delete(id);\n cleanup();\n reject(abortError(`QMD mcp ${method} aborted`));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n\n this.pendingRequests.set(id, { resolve, reject, timer, cleanup });\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n const message = JSON.stringify({ jsonrpc: \"2.0\", id, method, params }) + \"\\n\";\n this.child.stdin.write(message, (err) => {\n if (err) {\n clearTimeout(timer);\n this.pendingRequests.delete(id);\n cleanup();\n reject(new Error(`Failed to write to QMD mcp stdin: ${err.message}`));\n }\n });\n });\n }\n\n private sendNotification(method: string, params?: Record<string, unknown>): void {\n if (!this.child || !this.child.stdin || this.child.killed) return;\n if (this.child.stdin.destroyed) return;\n const msg: Record<string, unknown> = { jsonrpc: \"2.0\", method };\n if (params) msg.params = params;\n try {\n this.child.stdin.write(JSON.stringify(msg) + \"\\n\");\n } catch {\n // Ignore EPIPE / write-after-close\n }\n }\n\n private handleStdoutData(data: Buffer): void {\n this.buffer += data.toString();\n let newlineIdx: number;\n while ((newlineIdx = this.buffer.indexOf(\"\\n\")) !== -1) {\n const line = this.buffer.slice(0, newlineIdx).trim();\n this.buffer = this.buffer.slice(newlineIdx + 1);\n if (!line) continue;\n try {\n const msg = JSON.parse(line);\n this.handleMessage(msg);\n } catch {\n log.debug(`QMD mcp: unparseable stdout: ${truncateForLog(line, 200)}`);\n }\n }\n }\n\n private handleMessage(msg: Record<string, unknown>): void {\n if (msg.id !== undefined && msg.id !== null) {\n const pending = this.pendingRequests.get(msg.id as number);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingRequests.delete(msg.id as number);\n pending.cleanup();\n if (msg.error) {\n pending.reject(new Error(JSON.stringify(msg.error)));\n } else {\n pending.resolve(msg.result);\n }\n }\n return;\n }\n if (msg.method) {\n log.debug(`QMD mcp notification: ${msg.method}`);\n }\n }\n\n private cleanup(opts?: { killChild?: boolean; child?: CommandChildProcess | null }): void {\n const target = opts?.child ?? this.child;\n if (!target) return;\n if (opts?.child && this.child !== opts.child) {\n return;\n }\n if (opts?.killChild && !target.killed) {\n target.kill(\"SIGTERM\");\n }\n this.initialized = false;\n for (const [, pending] of this.pendingRequests) {\n clearTimeout(pending.timer);\n pending.cleanup();\n pending.reject(new Error(\"QMD mcp process terminated\"));\n }\n this.pendingRequests.clear();\n this.startPromise = null;\n this.child = null;\n this.buffer = \"\";\n }\n}\n\nfunction parseMcpSearchResult(\n result: unknown,\n transport: QmdSearchResult[\"transport\"] = \"daemon\",\n): QmdSearchResult[] {\n const resultObj = result as Record<string, unknown> | null;\n if (!resultObj) return [];\n const results: QmdSearchResult[] = [];\n const pushDocs = (docs: unknown[]) => {\n for (const doc of docs) {\n const d = doc as Record<string, unknown>;\n results.push({\n docid: typeof d.docid === \"string\" ? d.docid.replace(/^#/, \"\") : \"\",\n path: typeof d.file === \"string\"\n ? d.file\n : typeof d.path === \"string\"\n ? d.path\n : (typeof d.docid === \"string\" ? d.docid.replace(/^#/, \"\") : \"unknown\"),\n snippet: typeof d.snippet === \"string\" ? d.snippet : \"\",\n score: typeof d.score === \"number\" ? d.score : 0,\n explain: parseQmdExplain(d.explain),\n transport,\n });\n }\n };\n const topStructured = resultObj.structuredContent as Record<string, unknown> | undefined;\n const topDocs = topStructured?.results ?? topStructured?.documents;\n if (Array.isArray(topDocs)) pushDocs(topDocs);\n const content = resultObj.content;\n if (Array.isArray(content)) {\n for (const item of content) {\n const structured = item?.structuredContent;\n const docResults = structured?.results ?? structured?.documents;\n if (Array.isArray(docResults)) pushDocs(docResults);\n if (typeof item?.text === \"string\") {\n try {\n const parsed = JSON.parse(item.text);\n const textResults = parsed?.results ?? parsed?.documents;\n if (Array.isArray(textResults)) pushDocs(textResults);\n } catch {\n // ignore non-json text\n }\n }\n }\n }\n return results;\n}\n\nfunction parseQmdSearchStdout(\n stdout: string,\n transport: QmdSearchResult[\"transport\"] = \"subprocess\",\n): QmdSearchResult[] {\n const trimmedOut = stdout.trim();\n if (!trimmedOut || trimmedOut === \"No results found.\") return [];\n const parsed = JSON.parse(trimmedOut);\n if (!Array.isArray(parsed)) return [];\n return parsed.map(\n (entry: Record<string, unknown>): QmdSearchResult => ({\n docid: (entry.docid as string) ?? \"\",\n path:\n (entry.file as string) ??\n (entry.path as string) ??\n (entry.docid as string) ??\n \"unknown\",\n snippet: (entry.snippet as string) ?? \"\",\n score: typeof entry.score === \"number\" ? entry.score : 0,\n explain: parseQmdExplain(entry.explain),\n transport,\n }),\n );\n}\n\nlet _sharedDaemonSession: QmdDaemonSession | null = null;\nlet _sharedDaemonSessionPath: string | null = null;\n\nfunction getSharedDaemonSession(qmdPath: string): QmdDaemonSession {\n const normalizedPath = qmdPath.trim() || \"qmd\";\n if (_sharedDaemonSession && _sharedDaemonSessionPath !== normalizedPath) {\n _sharedDaemonSession.invalidate();\n _sharedDaemonSession = null;\n _sharedDaemonSessionPath = null;\n }\n if (!_sharedDaemonSession) {\n _sharedDaemonSession = new QmdDaemonSession(normalizedPath);\n _sharedDaemonSessionPath = normalizedPath;\n }\n return _sharedDaemonSession;\n}\n\n// ---------------------------------------------------------------------------\n// QmdClient\n// ---------------------------------------------------------------------------\n\nexport class QmdClient implements SearchBackend {\n private available: boolean | null = null;\n private lastUpdateFailAtMs: number | null = null;\n private lastEmbedFailAtMs: number | null = null;\n private lastUpdateRunAtMs: number | null = null;\n private readonly updateTimeoutMs: number;\n private readonly updateMinIntervalMs: number;\n private readonly slowLog?: { enabled: boolean; thresholdMs: number };\n private readonly configuredQmdPath?: string;\n private qmdPathSource: \"auto-path\" | \"auto-fallback\" | \"configured\" = \"auto-path\";\n private cliVersion: string | null = null;\n private lastCliProbeError: string | null = null;\n\n // Daemon mode fields\n private daemonSession: QmdDaemonSession | null = null;\n private daemonAvailable = false;\n private lastDaemonCheckAtMs = 0;\n private readonly daemonEnabled: boolean;\n private readonly daemonRecheckIntervalMs: number;\n /** Consecutive transient daemon failures before invalidating the session. */\n private daemonTransientFailures = 0;\n private static readonly DAEMON_MAX_TRANSIENT_FAILURES = 3;\n\n constructor(\n private readonly collection: string,\n private readonly maxResults: number,\n opts?: QmdClientOptions,\n ) {\n this.slowLog = opts?.slowLog;\n this.updateTimeoutMs = opts?.updateTimeoutMs ?? 120_000;\n this.updateMinIntervalMs = Math.max(0, opts?.updateMinIntervalMs ?? 15 * 60_000);\n this.configuredQmdPath = opts?.qmdPath?.trim() ? opts.qmdPath.trim() : undefined;\n if (this.configuredQmdPath) {\n this.qmdPath = this.configuredQmdPath;\n this.qmdPathSource = \"configured\";\n }\n this.daemonEnabled = Boolean(opts?.daemonUrl);\n this.daemonRecheckIntervalMs = opts?.daemonRecheckIntervalMs ?? 15_000;\n }\n\n private qmdPath: string = \"qmd\";\n\n async probe(): Promise<boolean> {\n const cliOk = await this.probeCli();\n if (this.daemonEnabled) {\n await this.probeDaemon();\n }\n return cliOk || this.daemonAvailable;\n }\n\n private async probeDaemon(): Promise<boolean> {\n this.lastDaemonCheckAtMs = Date.now();\n this.daemonSession = getSharedDaemonSession(this.qmdPath);\n try {\n // Race start() against a short window: if the session is already initialized\n // this returns instantly; if the process is still loading its index we fail\n // fast and let the caller fall back gracefully. The underlying start() promise\n // continues running in the background so the process is NOT killed. On the\n // next recheck cycle (daemonRecheckIntervalMs=15s) start() returns true\n // immediately once the handshake has completed.\n const PROBE_QUICK_TIMEOUT_MS = 3_000;\n const ok = await Promise.race([\n this.daemonSession.start(),\n new Promise<false>((resolve) => setTimeout(() => resolve(false), PROBE_QUICK_TIMEOUT_MS)),\n ]);\n if (!ok) {\n const loading = this.daemonSession.isLoading();\n log.debug(`QMD daemon: stdio session not ready within ${PROBE_QUICK_TIMEOUT_MS}ms probe window${loading ? \" (still loading)\" : \"\"}`);\n this.daemonAvailable = false;\n return false;\n }\n log.info(`QMD daemon: stdio session active (collection=${this.collection})`);\n this.daemonAvailable = true;\n this.daemonTransientFailures = 0;\n return true;\n } catch (err) {\n log.debug(`QMD daemon: probe failed: ${err}`);\n this.daemonAvailable = false;\n return false;\n }\n }\n\n private async probeCli(): Promise<boolean> {\n const parseVersion = (stdout: string, stderr: string): string | null => {\n const lines = `${stdout}\\n${stderr}`\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n if (lines.length === 0) return null;\n const semanticLines = lines.filter((line) => parseQmdVersion(line) !== null);\n if (semanticLines.length === 0) return lines[0] ?? null;\n return semanticLines.find((line) => /\\bqmd\\b/i.test(line)) ?? semanticLines[0] ?? null;\n };\n const markProbeFailure = (err: unknown): void => {\n this.lastCliProbeError = err instanceof Error ? err.message : String(err);\n };\n\n if (this.configuredQmdPath) {\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, this.configuredQmdPath);\n this.available = true;\n this.qmdPath = this.configuredQmdPath;\n this.qmdPathSource = \"configured\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n return true;\n } catch (err) {\n markProbeFailure(err);\n // Do not hard-fail here: fall through to PATH/fallback probing.\n // This keeps recall healthy even when configured path is stale.\n this.logCliProbeWarning(\n `QMD: configured qmdPath failed (${this.configuredQmdPath}): ${this.lastCliProbeError}`,\n );\n }\n }\n\n // Try PATH first\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, \"qmd\");\n this.available = true;\n this.qmdPath = \"qmd\";\n this.qmdPathSource = \"auto-path\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n return true;\n } catch (err) {\n markProbeFailure(err);\n // Try fallback paths\n for (const fallbackPath of QMD_FALLBACK_PATHS) {\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, fallbackPath);\n this.available = true;\n this.qmdPath = fallbackPath;\n this.qmdPathSource = \"auto-fallback\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n log.info(`QMD: found at ${fallbackPath}`);\n return true;\n } catch (fallbackErr) {\n markProbeFailure(fallbackErr);\n // Continue to next fallback\n }\n }\n this.available = false;\n return false;\n }\n }\n\n private logCliProbeWarning(message: string): void {\n const state = getGlobalQmdState();\n const now = Date.now();\n const canWarn =\n state.lastCliWarnAtMs === null || now - state.lastCliWarnAtMs >= QMD_CLI_WARN_THROTTLE_MS;\n if (!canWarn) {\n log.debug(message);\n return;\n }\n state.lastCliWarnAtMs = now;\n if (this.daemonAvailable) {\n // Daemon mode is healthy; keep this as debug noise rather than warning.\n log.debug(message);\n return;\n }\n log.warn(message);\n }\n\n /** Re-probe daemon if it was down and recheck interval has elapsed. */\n private async maybeProbeDaemon(): Promise<void> {\n if (!this.daemonEnabled) return;\n // If daemon is marked healthy and session is active, nothing to do.\n if (this.daemonAvailable && this.daemonSession?.isActive()) return;\n // If recently checked and failed, respect the recheck interval.\n if (this.daemonAvailable === false) {\n const elapsed = Date.now() - this.lastDaemonCheckAtMs;\n if (elapsed < this.daemonRecheckIntervalMs) return;\n }\n this.daemonAvailable = false;\n await this.probeDaemon();\n }\n\n isAvailable(): boolean {\n return this.available === true || this.daemonAvailable;\n }\n\n /** Debug string for troubleshooting availability issues. */\n debugStatus(): string {\n const cliPath = this.available ? this.qmdPath : (this.configuredQmdPath ?? \"unavailable\");\n const cliVersion = this.cliVersion ?? \"unknown\";\n const probeError = this.lastCliProbeError ? ` cliProbeError=${this.lastCliProbeError}` : \"\";\n return `cli=${this.available} daemon=${this.daemonAvailable} session=${!!this.daemonSession} cliPath=${cliPath} cliPathSource=${this.qmdPathSource} cliVersion=${cliVersion}${probeError}`;\n }\n\n isDaemonMode(): boolean {\n return this.daemonAvailable;\n }\n\n /**\n * Record a daemon search success — resets the transient failure counter.\n */\n private recordDaemonSuccess(): void {\n this.daemonTransientFailures = 0;\n }\n\n /**\n * Handle a non-timeout, non-cancellation daemon error.\n * Tolerates up to DAEMON_MAX_TRANSIENT_FAILURES consecutive failures\n * before invalidating the session. This prevents a single transient\n * error from pushing all concurrent searches through the subprocess\n * mutex for the full recheck interval.\n */\n private handleDaemonTransientError(label: string, err: unknown, durationMs: number): void {\n // If daemon was already marked unavailable by a concurrent call, don't\n // increment further — the counter will reset on the next successful probe.\n if (!this.daemonAvailable) {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (daemon already unavailable, ignoring): ${err}`);\n return;\n }\n this.daemonTransientFailures += 1;\n if (this.daemonTransientFailures >= QmdClient.DAEMON_MAX_TRANSIENT_FAILURES) {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (${this.daemonTransientFailures} consecutive failures, invalidating): ${err}`);\n this.daemonSession?.invalidate();\n this.daemonAvailable = false;\n this.daemonTransientFailures = 0;\n } else {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (transient ${this.daemonTransientFailures}/${QmdClient.DAEMON_MAX_TRANSIENT_FAILURES}): ${err}`);\n }\n }\n\n private async runQmdCommand(\n args: string[],\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<{ stdout: string; stderr: string }> {\n return runQmd(args, timeoutMs, this.qmdPath, signal);\n }\n\n private supportsIntentHints(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [1, 1, 5]);\n }\n\n private supportsExplainTraces(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [1, 1, 2]);\n }\n\n /**\n * QMD v2 (>= 2.0.0) uses a new MCP tool API:\n * - `search` and `vsearch` tools removed; only `query` tool exists\n * - `query` accepts `{ searches: [{ type, query }], collections?: string[] }`\n * instead of `{ query: string, collection?: string }`\n * - `collection` (singular) → `collections` (plural array)\n */\n private isQmdV2(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [2, 0, 0]);\n }\n\n private resolveSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n const normalized = normalizeSearchOptions(options);\n if (!normalized) return undefined;\n const resolved: SearchQueryOptions = {};\n if (normalized.intent && this.supportsIntentHints()) {\n resolved.intent = normalized.intent;\n }\n if (normalized.explain === true && this.supportsExplainTraces()) {\n resolved.explain = true;\n }\n return Object.keys(resolved).length > 0 ? resolved : undefined;\n }\n\n resolveSupportedSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n return this.resolveSearchOptions(options);\n }\n\n async search(\n query: string,\n collection?: string,\n maxResults?: number,\n options?: SearchQueryOptions,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n const searchOptions = this.resolveSearchOptions(options);\n\n // Short-lived search result cache — avoids redundant daemon calls for\n // repeated queries within the same recall cycle (e.g., primary + hybrid\n // top-up, or conversation recall using the same collection).\n const optionsFingerprint = searchOptions ? JSON.stringify(searchOptions) : \"\";\n const cacheKey = createHash(\"sha256\").update(`${col}:${n}:${optionsFingerprint}:${trimmed}`).digest(\"hex\");\n const cached = getCachedQmdSearch(cacheKey);\n if (cached) {\n log.debug(`QMD search cache hit (${cached.length} results)`);\n return cached as QmdSearchResult[];\n }\n\n // Try daemon first (bypasses QMD_MUTEX — daemon handles its own concurrency)\n await this.maybeProbeDaemon();\n if (this.daemonAvailable) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.searchViaDaemon(trimmed, col, n, searchOptions, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon search aborted\");\n }\n throw err;\n }\n // When the daemon is available, trust its outcome and skip the subprocess.\n // The subprocess runs `qmd query` (BM25 + LLM expansion) which hangs at\n // 99% CPU on large collections (75K+ files) making it strictly worse than\n // the daemon for this workload. Specifically:\n // results !== null → daemon succeeded (even with 0 hits) → return as-is\n // results === null → daemon timed-out or errored → still skip subprocess\n // because subprocess will also hang or timeout\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon search returned 0 results; skipping subprocess\");\n }\n setCachedQmdSearch(cacheKey, results);\n return results;\n }\n // Daemon timed out or had a transient error — skip subprocess for large\n // collections. Return empty rather than hanging the caller.\n log.debug(\"QMD daemon search timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n\n // If the daemon process is spawned but still loading (handshake not yet complete),\n // skip subprocess — it would add load and block under QMD_MUTEX without helping.\n // Return empty and let the next recheck cycle pick up the daemon once ready.\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD search: daemon loading, skipping subprocess\");\n return [];\n }\n\n // Subprocess fallback (only reached when daemon is unavailable and not loading)\n const subprocessResults = await this.searchViaSubprocess(trimmed, col, n, searchOptions, execution?.signal);\n setCachedQmdSearch(cacheKey, subprocessResults);\n return subprocessResults;\n }\n\n async searchGlobal(\n query: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const n = maxResults ?? 6;\n\n // Try daemon first\n await this.maybeProbeDaemon();\n if (this.daemonAvailable) {\n // Global search: no collection filter\n let results: QmdSearchResult[] | null;\n try {\n results = await this.searchViaDaemon(trimmed, undefined, n, undefined, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon global search aborted\");\n }\n throw err;\n }\n // Same rationale as search() — trust daemon outcome, skip subprocess.\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon global search returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon global search timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n\n // If the daemon is spawned but still loading, skip subprocess — same as search().\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD searchGlobal: daemon loading, skipping subprocess\");\n return [];\n }\n\n // Subprocess fallback (only reached when daemon is unavailable and not loading)\n return this.searchGlobalViaSubprocess(trimmed, n, execution?.signal);\n }\n\n /**\n * BM25 keyword search (fast, ~0.3s). Uses `qmd search`.\n */\n async bm25Search(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n\n // Try daemon first — BM25 via daemon is much faster than subprocess.\n await this.maybeProbeDaemon();\n if (this.daemonAvailable && this.daemonSession) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.bm25SearchViaDaemon(trimmed, col, n, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon bm25 aborted\");\n }\n throw err;\n }\n // When daemon is available, trust its outcome and skip subprocess (same\n // rationale as search() — subprocess hangs at 99% CPU on 75K+ files).\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon bm25 returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon bm25 timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD bm25: daemon loading, skipping subprocess\");\n return [];\n }\n return this.bm25SearchViaSubprocess(trimmed, col, n, execution?.signal);\n }\n\n /**\n * Vector similarity search (~3-4s). Uses `qmd vsearch`.\n */\n async vectorSearch(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n\n // Try daemon first — keeps models warm, avoids cold subprocess loads.\n await this.maybeProbeDaemon();\n if (this.daemonAvailable && this.daemonSession) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.vsearchViaDaemon(trimmed, col, n, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon vsearch aborted\");\n }\n throw err;\n }\n // When daemon is available, trust its outcome and skip subprocess (same\n // rationale as search() — subprocess hangs at 99% CPU on 75K+ files).\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon vsearch returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon vsearch timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD vsearch: daemon loading, skipping subprocess\");\n return [];\n }\n return this.vsearchViaSubprocess(trimmed, col, n, execution?.signal);\n }\n\n /**\n * Hybrid search: runs BM25 + vector in parallel, merges/dedupes by path\n * keeping the best score and first non-empty snippet.\n */\n async hybridSearch(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n const n = maxResults ?? this.maxResults;\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const [bm25Results, vectorResults] = await Promise.all([\n this.bm25Search(trimmed, collection, n, execution),\n this.vectorSearch(trimmed, collection, n, execution),\n ]);\n\n // Merge by path, keeping best score\n const merged = new Map<string, QmdSearchResult>();\n for (const r of [...bm25Results, ...vectorResults]) {\n const key = r.path || r.docid;\n const existing = merged.get(key);\n if (!existing || r.score > existing.score) {\n merged.set(key, {\n ...r,\n snippet: r.snippet || existing?.snippet || \"\",\n });\n }\n }\n\n // Sort by score descending, take top N\n return [...merged.values()]\n .sort((a, b) => b.score - a.score)\n .slice(0, n);\n }\n\n private async searchViaDaemon(\n query: string,\n collection: string | undefined,\n maxResults: number,\n options?: SearchQueryOptions,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let args: Record<string, unknown>;\n if (v2) {\n // QMD v2: query tool expects { searches: [...], collections?: [...] }\n // A plain query without type prefix uses LLM auto-expansion on the daemon side\n const searches: Array<{ type: string; query: string }> = [{ type: \"lex\", query }];\n // Add a vec sub-query for hybrid recall (mirrors v1 behavior)\n searches.push({ type: \"vec\", query });\n args = { searches, limit: maxResults };\n if (collection) {\n args.collections = [collection];\n }\n if (options?.intent) {\n args.intent = options.intent;\n }\n if (options?.explain === true) {\n args.explain = true;\n }\n } else {\n // QMD v1: query tool accepts { query, collection?, limit }\n args = { query, limit: maxResults };\n if (collection) {\n args.collection = collection;\n }\n if (options?.intent) {\n args.intent = options.intent;\n }\n if (options?.explain === true) {\n args.explain = true;\n }\n }\n\n const result = await this.daemonSession.callTool(\"query\", args, QMD_DAEMON_TIMEOUT_MS, signal);\n const durationMs = Date.now() - startedAtMs;\n\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD daemon query: durationMs=${durationMs} collection=${collection ?? \"global\"} maxResults=${maxResults} queryChars=${query.length} v2=${v2}`,\n );\n }\n\n const results = parseMcpSearchResult(result, \"daemon\");\n\n log.debug(`QMD daemon search: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon search aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon search aborted\");\n }\n // Timeout: don't invalidate session — daemon is still running, just slow.\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon search timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n // Transient error: tolerate a few before invalidating.\n this.handleDaemonTransientError(\"search\", err, durationMs);\n return null;\n }\n }\n\n private async bm25SearchViaDaemon(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let result: unknown;\n if (v2) {\n // QMD v2: no `search` tool — use `query` with lex-only sub-query\n result = await this.daemonSession.callTool(\n \"query\",\n {\n searches: [{ type: \"lex\", query }],\n collections: [collection],\n limit: maxResults,\n },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n } else {\n // QMD v1: dedicated `search` tool for BM25\n result = await this.daemonSession.callTool(\n \"search\",\n { query, limit: maxResults, collection },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n }\n const durationMs = Date.now() - startedAtMs;\n const results = parseMcpSearchResult(result);\n log.debug(`QMD daemon bm25: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon bm25 aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon bm25 aborted\");\n }\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon bm25 timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n this.handleDaemonTransientError(\"bm25\", err, durationMs);\n return null;\n }\n }\n\n private async vsearchViaDaemon(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let result: unknown;\n if (v2) {\n // QMD v2: no `vsearch` tool — use `query` with vec-only sub-query\n result = await this.daemonSession.callTool(\n \"query\",\n {\n searches: [{ type: \"vec\", query }],\n collections: [collection],\n limit: maxResults,\n },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n } else {\n // QMD v1: dedicated `vsearch` tool for vector search\n result = await this.daemonSession.callTool(\n \"vsearch\",\n { query, limit: maxResults, collection },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n }\n const durationMs = Date.now() - startedAtMs;\n const results = parseMcpSearchResult(result);\n log.debug(`QMD daemon vsearch: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon vsearch aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon vsearch aborted\");\n }\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon vsearch timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n this.handleDaemonTransientError(\"vsearch\", err, durationMs);\n return null;\n }\n }\n\n private async searchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n options?: SearchQueryOptions,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n\n const startedAtMs = Date.now();\n try {\n const args = [\"query\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)];\n if (options?.intent) {\n args.push(\"--intent\", options.intent);\n }\n if (options?.explain === true) {\n args.push(\"--explain\");\n }\n const { stdout } = await runQmd(\n args,\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD query: durationMs=${durationMs} collection=${collection} maxResults=${maxResults} queryChars=${query.length}`,\n );\n }\n\n return parseQmdSearchStdout(stdout, \"subprocess\");\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess search aborted\");\n }\n log.debug(`QMD search failed: ${err}`);\n return [];\n }\n }\n\n private async bm25SearchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"search\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n log.debug(`QMD bm25: ${Date.now() - startedAtMs}ms`);\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess bm25 aborted\");\n }\n log.debug(`QMD bm25 search failed: ${err}`);\n return [];\n }\n }\n\n private async vsearchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"vsearch\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n log.debug(`QMD vsearch: ${Date.now() - startedAtMs}ms`);\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess vsearch aborted\");\n }\n log.debug(`QMD vsearch failed: ${err}`);\n return [];\n }\n }\n\n private async searchGlobalViaSubprocess(\n query: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"query\", query, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD global query: durationMs=${durationMs} maxResults=${maxResults} queryChars=${query.length}`,\n );\n }\n\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess global search aborted\");\n }\n log.debug(`QMD global search failed: ${err}`);\n return [];\n }\n }\n\n async update(): Promise<void> {\n await this.runUpdateForCollection(this.collection, { perCollectionThrottle: false });\n }\n\n async updateCollection(collection: string): Promise<void> {\n await this.runUpdateForCollection(collection, { perCollectionThrottle: true });\n }\n\n private async runUpdateForCollection(\n collection: string,\n options: { perCollectionThrottle: boolean },\n ): Promise<void> {\n if (this.available === false) return;\n const name = collection.trim();\n if (!name) return;\n const globalState = getGlobalQmdState();\n const now = Date.now();\n if (options.perCollectionThrottle) {\n if (\n globalState.lastGlobalUpdateFailAtMs &&\n now - globalState.lastGlobalUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed by global failure backoff\");\n return;\n }\n const lastCollectionRun = globalState.lastUpdateByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionRun) &&\n now - lastCollectionRun < this.updateMinIntervalMs\n ) {\n log.debug(`QMD update: suppressed by per-collection min-interval gate (${name})`);\n return;\n }\n const lastCollectionFail = globalState.lastUpdateFailByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionFail) &&\n now - lastCollectionFail < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(`QMD update: suppressed by per-collection failure backoff (${name})`);\n return;\n }\n } else {\n if (\n this.lastUpdateRunAtMs &&\n now - this.lastUpdateRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD update: suppressed due to min-interval gate\");\n return;\n }\n if (\n this.lastUpdateFailAtMs &&\n now - this.lastUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed due to recent failures (backoff)\");\n return;\n }\n if (\n globalState.lastGlobalUpdateRunAtMs &&\n now - globalState.lastGlobalUpdateRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD update: suppressed by global min-interval gate\");\n return;\n }\n if (\n globalState.lastGlobalUpdateFailAtMs &&\n now - globalState.lastGlobalUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed by global failure backoff\");\n return;\n }\n }\n try {\n if (!globalState.warnedGlobalUpdateBehavior) {\n globalState.warnedGlobalUpdateBehavior = true;\n log.warn(\n \"QMD update runs globally across collections in current CLI versions; Engram now rate-limits update calls to reduce gateway load.\",\n );\n }\n const startedAtMs = Date.now();\n await this.runQmdCommand([\"update\", \"-c\", name], this.updateTimeoutMs);\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(`SLOW QMD update: durationMs=${durationMs}`);\n }\n const at = Date.now();\n if (options.perCollectionThrottle) {\n globalState.lastUpdateByCollectionMs[name] = at;\n globalState.lastGlobalUpdateRunAtMs = at;\n } else {\n this.lastUpdateRunAtMs = at;\n globalState.lastGlobalUpdateRunAtMs = at;\n }\n log.debug(`QMD update completed for collection=${name}`);\n } catch (err) {\n const at = Date.now();\n if (options.perCollectionThrottle) {\n globalState.lastUpdateFailByCollectionMs[name] = at;\n globalState.lastGlobalUpdateFailAtMs = at;\n } else {\n this.lastUpdateFailAtMs = at;\n globalState.lastGlobalUpdateFailAtMs = at;\n }\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD update failed for collection ${name}: ${msg}`);\n }\n }\n\n async embed(): Promise<void> {\n if (this.available === false) return;\n const globalState = getGlobalQmdState();\n if (\n this.lastEmbedFailAtMs &&\n Date.now() - this.lastEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(\"QMD embed: suppressed due to recent failures (backoff)\");\n return;\n }\n if (\n globalState.lastGlobalEmbedRunAtMs &&\n Date.now() - globalState.lastGlobalEmbedRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD embed: suppressed by global min-interval gate\");\n return;\n }\n if (\n globalState.lastGlobalEmbedFailAtMs &&\n Date.now() - globalState.lastGlobalEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(\"QMD embed: suppressed by global failure backoff\");\n return;\n }\n try {\n const startedAtMs = Date.now();\n await this.runQmdCommand([\"embed\", \"-c\", this.collection], 300_000);\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(`SLOW QMD embed: durationMs=${durationMs}`);\n }\n globalState.lastGlobalEmbedRunAtMs = Date.now();\n log.debug(\"QMD embed completed\");\n } catch (err) {\n if (isVectorDimensionMismatchError(err)) {\n try {\n log.warn(\"QMD embed hit a vector dimension mismatch; retrying with force re-embed\");\n await this.runQmdCommand([\"embed\", \"-f\", \"-c\", this.collection], 300_000);\n globalState.lastGlobalEmbedRunAtMs = Date.now();\n this.lastEmbedFailAtMs = null;\n globalState.lastGlobalEmbedFailAtMs = null;\n log.warn(\"QMD embed recovered by forcing a full vector rebuild\");\n return;\n } catch (retryErr) {\n const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);\n log.warn(`QMD force re-embed failed after dimension mismatch: ${retryMsg}`);\n }\n }\n const now = Date.now();\n this.lastEmbedFailAtMs = now;\n globalState.lastGlobalEmbedFailAtMs = now;\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD embed failed: ${msg}`);\n }\n }\n\n async embedCollection(collection: string): Promise<void> {\n if (this.available === false) return;\n const name = collection.trim();\n if (!name) return;\n const globalState = getGlobalQmdState();\n const now = Date.now();\n if (\n globalState.lastGlobalEmbedFailAtMs &&\n now - globalState.lastGlobalEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(`QMD embed: suppressed by global failure backoff (${name})`);\n return;\n }\n const lastCollectionRun = globalState.lastEmbedByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionRun) &&\n now - lastCollectionRun < this.updateMinIntervalMs\n ) {\n log.debug(`QMD embed: suppressed by per-collection min-interval gate (${name})`);\n return;\n }\n const lastCollectionFail = globalState.lastEmbedFailByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionFail) &&\n now - lastCollectionFail < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(`QMD embed: suppressed by per-collection failure backoff (${name})`);\n return;\n }\n try {\n await this.runQmdCommand([\"embed\", \"-c\", name], 300_000);\n const at = Date.now();\n globalState.lastEmbedByCollectionMs[name] = at;\n globalState.lastGlobalEmbedRunAtMs = at;\n } catch (err) {\n if (isVectorDimensionMismatchError(err)) {\n try {\n log.warn(`QMD embed for collection ${name} hit a vector dimension mismatch; retrying with force re-embed`);\n await this.runQmdCommand([\"embed\", \"-f\", \"-c\", name], 300_000);\n const recoveredAt = Date.now();\n globalState.lastEmbedByCollectionMs[name] = recoveredAt;\n globalState.lastGlobalEmbedRunAtMs = recoveredAt;\n delete globalState.lastEmbedFailByCollectionMs[name];\n globalState.lastGlobalEmbedFailAtMs = null;\n log.warn(`QMD embed for collection ${name} recovered by forcing a full vector rebuild`);\n return;\n } catch (retryErr) {\n const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);\n log.warn(`QMD force re-embed failed for collection ${name}: ${retryMsg}`);\n }\n }\n const at = Date.now();\n globalState.lastEmbedFailByCollectionMs[name] = at;\n globalState.lastGlobalEmbedFailAtMs = at;\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD embed failed for collection ${name}: ${msg}`);\n }\n }\n\n async ensureCollection(memoryDir: string): Promise<\"present\" | \"missing\" | \"unknown\" | \"skipped\"> {\n if (this.available === false && !this.daemonAvailable) return \"unknown\";\n // If only daemon is available (no CLI), skip collection check\n if (this.available === false) return \"skipped\";\n try {\n const { stdout } = await runQmd(\n [\"collection\", \"list\"],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n );\n // Parse text output: \"openclaw-engram (qmd://openclaw-engram/)\"\n const collectionRegex = new RegExp(\n `^${this.collection}\\\\s+\\\\(qmd://`,\n \"m\",\n );\n if (collectionRegex.test(stdout)) {\n return \"present\";\n }\n } catch (err) {\n // Treat command/probe failures as unknown so callers do not disable features\n // permanently after a transient CLI or daemon hiccup.\n log.debug(\n `QMD collection check unavailable for \"${this.collection}\" (will not disable features): ${err instanceof Error ? err.message : String(err)}`,\n );\n return \"unknown\";\n }\n\n log.info(\n `QMD collection \"${this.collection}\" not found. ` +\n `Add it to ~/.config/qmd/index.yml pointing at ${memoryDir}`,\n );\n return \"missing\";\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type ReasoningEffort = \"none\" | \"low\" | \"medium\" | \"high\";\nexport type TriggerMode = \"smart\" | \"every_n\" | \"time_based\";\nexport type SignalLevel = \"none\" | \"low\" | \"medium\" | \"high\";\nexport type MemoryCategory = \"fact\" | \"preference\" | \"correction\" | \"entity\" | \"decision\" | \"relationship\" | \"principle\" | \"commitment\" | \"moment\" | \"skill\" | \"rule\";\nexport type ConsolidationAction = \"ADD\" | \"MERGE\" | \"UPDATE\" | \"INVALIDATE\" | \"SKIP\";\nexport type ConfidenceTier = \"explicit\" | \"implied\" | \"inferred\" | \"speculative\";\nexport type PrincipalFromSessionKeyMode = \"map\" | \"prefix\" | \"regex\";\nexport type RecallPlanMode = \"no_recall\" | \"minimal\" | \"full\" | \"graph_mode\";\nexport type CronRecallMode = \"all\" | \"none\" | \"allowlist\";\nexport type CronConversationRecallMode = \"auto\" | \"always\" | \"never\";\nexport type IdentityInjectionMode = \"recovery_only\" | \"minimal\" | \"full\";\nexport type CaptureMode = \"implicit\" | \"explicit\" | \"hybrid\";\nexport type MemoryOsPresetName = \"conservative\" | \"balanced\" | \"research-max\" | \"local-llm-heavy\";\nexport type ExtractionPassSource = \"base\" | \"proactive\";\n\nexport interface RecallSectionConfig {\n id: string;\n enabled?: boolean;\n maxChars?: number | null;\n maxHints?: number;\n maxSupportingFacts?: number;\n maxRelatedEntities?: number;\n consolidateTriggerLines?: number;\n consolidateTargetLines?: number;\n maxEntities?: number;\n maxResults?: number;\n recentTurns?: number;\n maxTurns?: number;\n maxTokens?: number;\n lookbackHours?: number;\n maxCount?: number;\n topK?: number;\n timeoutMs?: number;\n maxPatterns?: number;\n maxRubrics?: number;\n}\n\nexport interface RecallPipelineConfig {\n recallBudgetChars: number;\n pipeline: RecallSectionConfig[];\n}\n\nexport interface SessionObserverBandConfig {\n maxBytes: number;\n triggerDeltaBytes: number;\n triggerDeltaTokens: number;\n}\n\nexport interface FileHygieneConfig {\n enabled: boolean;\n // Lint (warn before truncation risk)\n lintEnabled: boolean;\n lintBudgetBytes: number;\n lintWarnRatio: number;\n lintPaths: string[];\n // Rotation/splitting\n rotateEnabled: boolean;\n rotateMaxBytes: number;\n rotateKeepTailChars: number;\n rotatePaths: string[];\n archiveDir: string;\n // Cadence\n runMinIntervalMs: number;\n // Optional warnings log (future-proofed)\n warningsLogEnabled: boolean;\n warningsLogPath: string;\n // Optional index file (future-proofed)\n indexEnabled: boolean;\n indexPath: string;\n}\n\nexport interface NativeKnowledgeConfig {\n enabled: boolean;\n includeFiles: string[];\n maxChunkChars: number;\n maxResults: number;\n maxChars: number;\n stateDir: string;\n obsidianVaults: NativeKnowledgeObsidianVaultConfig[];\n openclawWorkspace?: NativeKnowledgeOpenClawWorkspaceConfig;\n}\n\nexport interface NativeKnowledgeFolderRuleConfig {\n pathPrefix: string;\n namespace?: string;\n privacyClass?: string;\n}\n\nexport interface NativeKnowledgeObsidianVaultConfig {\n id: string;\n rootDir: string;\n includeGlobs: string[];\n excludeGlobs: string[];\n namespace?: string;\n privacyClass?: string;\n folderRules: NativeKnowledgeFolderRuleConfig[];\n dailyNotePatterns: string[];\n materializeBacklinks: boolean;\n}\n\nexport interface NativeKnowledgeOpenClawWorkspaceConfig {\n enabled: boolean;\n bootstrapFiles: string[];\n handoffGlobs: string[];\n dailySummaryGlobs: string[];\n automationNoteGlobs: string[];\n workspaceDocGlobs: string[];\n excludeGlobs: string[];\n sharedSafeGlobs: string[];\n}\n\nexport interface AgentAccessHttpConfig {\n enabled: boolean;\n host: string;\n port: number;\n authToken?: string;\n principal?: string;\n maxBodyBytes: number;\n}\n\nexport function confidenceTier(score: number): ConfidenceTier {\n if (score >= 0.95) return \"explicit\";\n if (score >= 0.70) return \"implied\";\n if (score >= 0.40) return \"inferred\";\n return \"speculative\";\n}\n\n/** Default TTL in days for speculative memories (auto-expire if unconfirmed) */\nexport const SPECULATIVE_TTL_DAYS = 30;\n\nexport interface PluginConfig {\n openaiApiKey: string | undefined;\n openaiBaseUrl: string | undefined;\n model: string;\n reasoningEffort: ReasoningEffort;\n triggerMode: TriggerMode;\n bufferMaxTurns: number;\n bufferMaxMinutes: number;\n consolidateEveryN: number;\n highSignalPatterns: string[];\n maxMemoryTokens: number;\n memoryOsPreset?: MemoryOsPresetName;\n qmdEnabled: boolean;\n qmdCollection: string;\n qmdMaxResults: number;\n qmdColdTierEnabled?: boolean;\n qmdColdCollection?: string;\n qmdColdMaxResults?: number;\n qmdTierMigrationEnabled: boolean;\n qmdTierDemotionMinAgeDays: number;\n qmdTierDemotionValueThreshold: number;\n qmdTierPromotionValueThreshold: number;\n qmdTierParityGraphEnabled: boolean;\n qmdTierParityHiMemEnabled: boolean;\n qmdTierAutoBackfillEnabled: boolean;\n embeddingFallbackEnabled: boolean;\n embeddingFallbackProvider: \"auto\" | \"openai\" | \"local\";\n /** Optional absolute path to qmd binary. If unset, PATH/fallback discovery is used. */\n qmdPath?: string;\n memoryDir: string;\n debug: boolean;\n identityEnabled: boolean;\n identityContinuityEnabled: boolean;\n identityInjectionMode: IdentityInjectionMode;\n identityMaxInjectChars: number;\n continuityIncidentLoggingEnabled: boolean;\n continuityAuditEnabled: boolean;\n sessionObserverEnabled?: boolean;\n sessionObserverDebounceMs?: number;\n sessionObserverBands?: SessionObserverBandConfig[];\n injectQuestions: boolean;\n commitmentDecayDays: number;\n workspaceDir: string;\n captureMode: CaptureMode;\n fileHygiene?: FileHygieneConfig;\n nativeKnowledge?: NativeKnowledgeConfig;\n agentAccessHttp: AgentAccessHttpConfig;\n // Access tracking (Phase 1A)\n accessTrackingEnabled: boolean;\n accessTrackingBufferMaxSize: number;\n // Retrieval options\n recencyWeight: number;\n boostAccessCount: boolean;\n /** Record empty recall impressions (memoryIds: []) when no memories are injected. Disabled by default. */\n recordEmptyRecallImpressions: boolean;\n // v2.2 Advanced Retrieval\n queryExpansionEnabled: boolean;\n queryExpansionMaxQueries: number;\n /** Minimum token length to consider for query expansion. */\n queryExpansionMinTokenLen: number;\n rerankEnabled: boolean;\n /** Rerank provider. \"local\" uses Local LLM only; \"cloud\" uses gateway fallback chain. */\n rerankProvider: \"local\" | \"cloud\";\n rerankMaxCandidates: number;\n rerankTimeoutMs: number;\n rerankCacheEnabled: boolean;\n rerankCacheTtlMs: number;\n feedbackEnabled: boolean;\n // v2.2 Negative Examples (safe defaults: off unless enabled)\n /** If true, allow recording negative examples and apply a soft penalty during ranking. */\n negativeExamplesEnabled: boolean;\n /** Score penalty per \"not useful\" hit (typical QMD scores ~0-1). Keep small. */\n negativeExamplesPenaltyPerHit: number;\n /** Maximum penalty applied from negative examples. */\n negativeExamplesPenaltyCap: number;\n // Chunking (Phase 2A)\n chunkingEnabled: boolean;\n chunkingTargetTokens: number;\n chunkingMinTokens: number;\n chunkingOverlapSentences: number;\n // Contradiction Detection (Phase 2B)\n contradictionDetectionEnabled: boolean;\n contradictionSimilarityThreshold: number;\n contradictionMinConfidence: number;\n contradictionAutoResolve: boolean;\n // Memory Linking (Phase 3A)\n memoryLinkingEnabled: boolean;\n // Conversation Threading (Phase 3B)\n threadingEnabled: boolean;\n threadingGapMinutes: number;\n // Memory Summarization (Phase 4A)\n summarizationEnabled: boolean;\n summarizationTriggerCount: number;\n summarizationRecentToKeep: number;\n summarizationImportanceThreshold: number;\n summarizationProtectedTags: string[];\n // Topic Extraction (Phase 4B)\n topicExtractionEnabled: boolean;\n topicExtractionTopN: number;\n // Transcript & Context Preservation (v2.0)\n // Transcript archive\n transcriptEnabled: boolean;\n transcriptRetentionDays: number;\n /** Channel types to skip from transcript logging (e.g., [\"cron\"]) */\n transcriptSkipChannelTypes: string[];\n // Transcript injection\n transcriptRecallHours: number;\n maxTranscriptTurns: number;\n maxTranscriptTokens: number;\n // Checkpoint\n checkpointEnabled: boolean;\n checkpointTurns: number;\n // Compaction reset: trigger session reset after compaction instead of continuing degraded.\n // Requires OC fork with PR #29985 (api.resetSession).\n compactionResetEnabled: boolean;\n // Hourly summaries\n hourlySummariesEnabled: boolean;\n daySummaryEnabled: boolean;\n /** If true, Engram may attempt to auto-register an hourly summary cron job (default off). */\n hourlySummaryCronAutoRegister: boolean;\n /** If true, Engram may attempt to auto-register the nightly governance cron job (default off). */\n nightlyGovernanceCronAutoRegister: boolean;\n summaryRecallHours: number;\n maxSummaryCount: number;\n summaryModel: string;\n // v2.4 Extended hourly summaries\n hourlySummariesExtendedEnabled: boolean;\n hourlySummariesIncludeToolStats: boolean;\n hourlySummariesIncludeSystemMessages: boolean;\n hourlySummariesMaxTurnsPerRun: number;\n // v2.4 Conversation index (optional)\n conversationIndexEnabled: boolean;\n conversationIndexBackend: \"qmd\" | \"faiss\";\n conversationIndexQmdCollection: string;\n conversationIndexRetentionDays: number;\n conversationIndexMinUpdateIntervalMs: number;\n conversationIndexEmbedOnUpdate: boolean;\n conversationIndexFaissScriptPath?: string;\n conversationIndexFaissPythonBin?: string;\n conversationIndexFaissModelId: string;\n conversationIndexFaissIndexDir: string;\n conversationIndexFaissUpsertTimeoutMs: number;\n conversationIndexFaissSearchTimeoutMs: number;\n conversationIndexFaissHealthTimeoutMs: number;\n conversationIndexFaissMaxBatchSize: number;\n conversationIndexFaissMaxSearchK: number;\n conversationRecallTopK: number;\n conversationRecallMaxChars: number;\n conversationRecallTimeoutMs: number;\n // Evaluation harness foundation\n evalHarnessEnabled: boolean;\n evalShadowModeEnabled: boolean;\n benchmarkBaselineSnapshotsEnabled: boolean;\n benchmarkDeltaReporterEnabled: boolean;\n benchmarkStoredBaselineEnabled: boolean;\n evalStoreDir: string;\n // Objective-state memory foundation\n objectiveStateMemoryEnabled: boolean;\n objectiveStateSnapshotWritesEnabled: boolean;\n objectiveStateRecallEnabled: boolean;\n objectiveStateStoreDir: string;\n // Causal trajectory memory foundation\n causalTrajectoryMemoryEnabled: boolean;\n causalTrajectoryStoreDir: string;\n causalTrajectoryRecallEnabled: boolean;\n actionGraphRecallEnabled: boolean;\n // Trust-zone memory foundation\n trustZonesEnabled: boolean;\n quarantinePromotionEnabled: boolean;\n trustZoneStoreDir: string;\n trustZoneRecallEnabled: boolean;\n memoryPoisoningDefenseEnabled: boolean;\n memoryRedTeamBenchEnabled: boolean;\n // Harmonic retrieval foundation\n harmonicRetrievalEnabled: boolean;\n abstractionAnchorsEnabled: boolean;\n abstractionNodeStoreDir: string;\n // Episodic/semantic split foundation\n verifiedRecallEnabled: boolean;\n semanticRulePromotionEnabled: boolean;\n semanticRuleVerificationEnabled: boolean;\n semanticConsolidationEnabled: boolean;\n semanticConsolidationModel: string;\n semanticConsolidationThreshold: number;\n semanticConsolidationMinClusterSize: number;\n semanticConsolidationExcludeCategories: string[];\n semanticConsolidationIntervalHours: number;\n semanticConsolidationMaxPerRun: number;\n // Creation-memory foundation\n creationMemoryEnabled: boolean;\n memoryUtilityLearningEnabled: boolean;\n promotionByOutcomeEnabled: boolean;\n commitmentLedgerEnabled: boolean;\n commitmentLifecycleEnabled: boolean;\n commitmentStaleDays: number;\n commitmentLedgerDir: string;\n resumeBundlesEnabled: boolean;\n resumeBundleDir: string;\n workProductRecallEnabled: boolean;\n workProductLedgerDir: string;\n workTasksEnabled: boolean;\n workProjectsEnabled: boolean;\n workTasksDir: string;\n workProjectsDir: string;\n workIndexEnabled: boolean;\n workIndexDir: string;\n workTaskIndexEnabled: boolean;\n workProjectIndexEnabled: boolean;\n workIndexAutoRebuildEnabled: boolean;\n workIndexAutoRebuildDebounceMs: number;\n // Local LLM Provider (v2.1)\n localLlmEnabled: boolean;\n localLlmUrl: string;\n localLlmModel: string;\n /** Optional API key for authenticated OpenAI-compatible endpoints. */\n localLlmApiKey?: string;\n /** Additional headers for local/compatible endpoint requests. */\n localLlmHeaders?: Record<string, string>;\n /** If false, do not send Authorization header even when localLlmApiKey is set. */\n localLlmAuthHeader: boolean;\n localLlmFallback: boolean;\n /** Optional home directory override for local LLM helpers (LM Studio settings, CLI PATH). */\n localLlmHomeDir?: string;\n /** Optional absolute path to LMS CLI binary (preferred over auto-detection). */\n localLmsCliPath?: string;\n /** Optional bin directory prepended to PATH for LMS CLI execution. */\n localLmsBinDir?: string;\n /** Hard timeout for local LLM requests (ms). */\n localLlmTimeoutMs: number;\n /** Max context window for local LLM (override auto-detection). Set lower if your LLM server defaults to smaller contexts. */\n localLlmMaxContext?: number;\n // Observability\n /** If true, log slow operations (local LLM + related I/O) with durations and metadata (no content). */\n slowLogEnabled: boolean;\n /**\n * If true, include the full recalled memory text in `RecallTraceEvent.recalledContent`.\n * Disabled by default — enable only when you want external trace subscribers (e.g. Langfuse)\n * to see the exact memory context injected into each conversation turn.\n * This adds payload to trace events but does not log to files or the gateway log.\n */\n traceRecallContent: boolean;\n /** Threshold for slow operation logging (ms). */\n slowLogThresholdMs: number;\n // Performance profiling (opt-in)\n /** If true, collect and persist timing traces for recall and extraction pipelines. */\n profilingEnabled: boolean;\n /** Directory for profiling trace JSONL files. Defaults to <memoryDir>/profiling. */\n profilingStorageDir: string;\n /** Maximum number of trace files to keep (rolling window). */\n profilingMaxTraces: number;\n // Extraction stability guards (P0/P1)\n extractionDedupeEnabled: boolean;\n extractionDedupeWindowMs: number;\n extractionMinChars: number;\n extractionMinUserTurns: number;\n extractionMaxTurnChars: number;\n extractionMaxFactsPerRun: number;\n extractionMaxEntitiesPerRun: number;\n extractionMaxQuestionsPerRun: number;\n extractionMaxProfileUpdatesPerRun: number;\n consolidationRequireNonZeroExtraction: boolean;\n consolidationMinIntervalMs: number;\n // QMD maintenance (debounced singleflight)\n qmdMaintenanceEnabled: boolean;\n qmdMaintenanceDebounceMs: number;\n qmdAutoEmbedEnabled: boolean;\n qmdEmbedMinIntervalMs: number;\n qmdUpdateTimeoutMs: number;\n qmdUpdateMinIntervalMs: number;\n // Local LLM resilience\n localLlmRetry5xxCount: number;\n localLlmRetryBackoffMs: number;\n localLlm400TripThreshold: number;\n localLlm400CooldownMs: number;\n // Local LLM fast tier (v9.1) — smaller model for quick ops\n localLlmFastEnabled: boolean;\n localLlmFastModel: string;\n localLlmFastUrl: string;\n localLlmFastTimeoutMs: number;\n // Gateway config for fallback AI\n gatewayConfig?: GatewayConfig;\n // Gateway model source (v9.2) — route LLM calls through gateway agent model chain\n modelSource: \"plugin\" | \"gateway\";\n gatewayAgentId: string;\n fastGatewayAgentId: string;\n\n // v3.0 Multi-agent memory (namespaces)\n namespacesEnabled: boolean;\n defaultNamespace: string;\n sharedNamespace: string;\n principalFromSessionKeyMode: PrincipalFromSessionKeyMode;\n principalFromSessionKeyRules: PrincipalRule[];\n namespacePolicies: NamespacePolicy[];\n defaultRecallNamespaces: Array<\"self\" | \"shared\">;\n cronRecallMode: CronRecallMode;\n cronRecallAllowlist: string[];\n cronRecallPolicyEnabled: boolean;\n cronRecallNormalizedQueryMaxChars: number;\n cronRecallInstructionHeavyTokenCap: number;\n cronConversationRecallMode: CronConversationRecallMode;\n autoPromoteToSharedEnabled: boolean;\n autoPromoteToSharedCategories: Array<\"fact\" | \"correction\" | \"decision\" | \"preference\">;\n autoPromoteMinConfidenceTier: ConfidenceTier;\n routingRulesEnabled: boolean;\n routingRulesStateFile: string;\n\n // v4.0 Shared-context (cross-agent shared intelligence)\n sharedContextEnabled: boolean;\n sharedContextDir?: string;\n sharedContextMaxInjectChars: number;\n crossSignalsSemanticEnabled: boolean;\n crossSignalsSemanticTimeoutMs: number;\n sharedCrossSignalSemanticEnabled?: boolean;\n sharedCrossSignalSemanticTimeoutMs?: number;\n sharedCrossSignalSemanticMaxCandidates?: number;\n\n // v5.0 Compounding engine\n compoundingEnabled: boolean;\n compoundingWeeklyCronEnabled: boolean;\n compoundingSemanticEnabled: boolean;\n compoundingSynthesisTimeoutMs: number;\n compoundingInjectEnabled: boolean;\n\n // IRC (Inductive Rule Consolidation) — preference synthesis\n ircEnabled: boolean;\n ircMaxPreferences: number;\n ircIncludeCorrections: boolean;\n ircMinConfidence: number;\n\n // CMC (Causal Memory Consolidation) — cross-session causal reasoning\n cmcEnabled: boolean;\n cmcStitchLookbackDays: number;\n cmcStitchMinScore: number;\n cmcStitchMaxEdgesPerTrajectory: number;\n cmcConsolidationEnabled: boolean;\n cmcConsolidationMinRecurrence: number;\n cmcConsolidationMinSessions: number;\n cmcConsolidationSuccessThreshold: number;\n cmcRetrievalEnabled: boolean;\n cmcRetrievalMaxDepth: number;\n cmcRetrievalMaxChars: number;\n cmcRetrievalCounterfactualBoost: number;\n cmcBehaviorLearningEnabled: boolean;\n cmcBehaviorMinFrequency: number;\n cmcBehaviorMinSessions: number;\n cmcBehaviorConfidenceThreshold: number;\n cmcLifecycleCausalImpactWeight: number;\n\n // PEDC (Prediction-Error-Driven Calibration) — model-user alignment\n calibrationEnabled: boolean;\n calibrationMaxRulesPerRecall: number;\n calibrationMaxChars: number;\n\n // Search backend abstraction\n searchBackend?: \"qmd\" | \"remote\" | \"noop\" | \"lancedb\" | \"meilisearch\" | \"orama\";\n remoteSearchBaseUrl?: string;\n remoteSearchApiKey?: string;\n remoteSearchTimeoutMs?: number;\n\n // LanceDB backend\n lancedbEnabled: boolean;\n lanceDbPath?: string;\n lanceEmbeddingDimension?: number;\n\n // Meilisearch backend\n meilisearchEnabled: boolean;\n meilisearchHost?: string;\n meilisearchApiKey?: string;\n meilisearchTimeoutMs?: number;\n meilisearchAutoIndex?: boolean;\n\n // Orama backend\n oramaEnabled: boolean;\n oramaDbPath?: string;\n oramaEmbeddingDimension?: number;\n\n // QMD daemon mode\n qmdDaemonEnabled: boolean;\n qmdDaemonUrl: string;\n qmdDaemonRecheckIntervalMs: number;\n qmdIntentHintsEnabled: boolean;\n qmdExplainEnabled: boolean;\n\n // v7.0 Knowledge Graph Enhancement\n knowledgeIndexEnabled: boolean;\n knowledgeIndexMaxEntities: number;\n knowledgeIndexMaxChars: number;\n entityRetrievalEnabled: boolean;\n entityRetrievalMaxChars: number;\n entityRetrievalMaxHints: number;\n entityRetrievalMaxSupportingFacts: number;\n entityRetrievalMaxRelatedEntities: number;\n entityRetrievalRecentTurns: number;\n // Recall assembly controls\n recallBudgetChars: number;\n recallOuterTimeoutMs: number;\n recallCoreDeadlineMs: number;\n recallEnrichmentDeadlineMs: number;\n recallPipeline: RecallSectionConfig[];\n qmdRecallCacheTtlMs: number;\n qmdRecallCacheStaleTtlMs: number;\n qmdRecallCacheMaxEntries: number;\n entityRelationshipsEnabled: boolean;\n entityActivityLogEnabled: boolean;\n entityActivityLogMaxEntries: number;\n entityAliasesEnabled: boolean;\n entitySummaryEnabled: boolean;\n\n // v6.0 Fact deduplication & archival\n /** Enable content-hash deduplication to prevent storing semantically identical facts. */\n factDeduplicationEnabled: boolean;\n /** Enable automatic archival of old, low-importance, rarely-accessed facts. */\n factArchivalEnabled: boolean;\n /** Minimum age in days before a fact is eligible for archival. */\n factArchivalAgeDays: number;\n /** Maximum importance score for archival eligibility (0-1). Only facts below this are archived. */\n factArchivalMaxImportance: number;\n /** Maximum access count for archival eligibility. Only rarely-accessed facts are archived. */\n factArchivalMaxAccessCount: number;\n /** Tags that protect a fact from archival regardless of other criteria. */\n factArchivalProtectedCategories: string[];\n // v8.3 Lifecycle policy engine\n lifecyclePolicyEnabled: boolean;\n lifecycleFilterStaleEnabled: boolean;\n lifecyclePromoteHeatThreshold: number;\n lifecycleStaleDecayThreshold: number;\n lifecycleArchiveDecayThreshold: number;\n lifecycleProtectedCategories: MemoryCategory[];\n lifecycleMetricsEnabled: boolean;\n // v8.3 proactive + policy learning\n proactiveExtractionEnabled: boolean;\n contextCompressionActionsEnabled: boolean;\n compressionGuidelineLearningEnabled: boolean;\n compressionGuidelineSemanticRefinementEnabled: boolean;\n compressionGuidelineSemanticTimeoutMs: number;\n maxProactiveQuestionsPerExtraction: number;\n proactiveExtractionTimeoutMs: number;\n proactiveExtractionMaxTokens: number;\n extractionMaxOutputTokens: number;\n proactiveExtractionCategoryAllowlist?: MemoryCategory[];\n maxCompressionTokensPerHour: number;\n behaviorLoopAutoTuneEnabled: boolean;\n behaviorLoopLearningWindowDays: number;\n behaviorLoopMinSignalCount: number;\n behaviorLoopMaxDeltaPerCycle: number;\n behaviorLoopProtectedParams: string[];\n // v8.0 Phase 1: recall planner + intent routing + verbatim artifacts\n recallPlannerEnabled: boolean;\n recallPlannerModel: string;\n recallPlannerTimeoutMs: number;\n recallPlannerUseResponsesApi: boolean;\n recallPlannerMaxPromptChars: number;\n recallPlannerMaxMemoryHints: number;\n recallPlannerShadowMode: boolean;\n recallPlannerTelemetryEnabled: boolean;\n recallPlannerMaxQmdResultsMinimal: number;\n recallPlannerMaxQmdResultsFull: number;\n intentRoutingEnabled: boolean;\n intentRoutingBoost: number;\n verbatimArtifactsEnabled: boolean;\n verbatimArtifactsMinConfidence: number;\n verbatimArtifactsMaxRecall: number;\n verbatimArtifactCategories: MemoryCategory[];\n // v8.0 Phase 2A: Memory Boxes + Trace Weaving\n memoryBoxesEnabled: boolean;\n /** Jaccard overlap threshold below which a topic shift triggers box sealing (0-1, default 0.35) */\n boxTopicShiftThreshold: number;\n /** Time gap in ms before an open box is sealed (default 30 min) */\n boxTimeGapMs: number;\n /** Max memories per box before forced seal */\n boxMaxMemories: number;\n traceWeaverEnabled: boolean;\n /** Days back to search for trace links */\n traceWeaverLookbackDays: number;\n /** Minimum Jaccard overlap to assign the same traceId (0-1, default 0.4) */\n traceWeaverOverlapThreshold: number;\n /** Number of recent days of boxes to inject during recall */\n boxRecallDays: number;\n // v8.0 Phase 2B: Episode/Note dual store (HiMem)\n /** Classify extracted memories as episode or note and tag with memoryKind */\n episodeNoteModeEnabled: boolean;\n // v8.1 Temporal + Tag Indexes (SwiftMem-inspired)\n /** Build and maintain temporal (state/index_time.json) and tag (state/index_tags.json) indexes */\n queryAwareIndexingEnabled: boolean;\n /** Max candidate paths returned from index prefilter (0 = no cap) */\n queryAwareIndexingMaxCandidates: number;\n temporalIndexWindowDays: number;\n temporalIndexMaxEntries: number;\n temporalBoostRecentDays: number;\n temporalBoostScore: number;\n temporalDecayEnabled: boolean;\n tagMemoryEnabled: boolean;\n tagMaxPerMemory: number;\n tagIndexMaxEntries: number;\n tagRecallBoost: number;\n tagRecallMaxMatches: number;\n // v8.2 multi-graph memory (PR 18)\n multiGraphMemoryEnabled: boolean;\n // v8.2 PR 19A: graph recall planner gating\n graphRecallEnabled: boolean;\n graphRecallMaxExpansions: number;\n graphRecallMaxPerSeed: number;\n graphRecallMinEdgeWeight: number;\n graphRecallShadowEnabled: boolean;\n graphRecallSnapshotEnabled: boolean;\n graphRecallShadowSampleRate: number;\n graphRecallExplainToolEnabled: boolean;\n graphRecallStoreColdMirror: boolean;\n graphRecallColdMirrorCollection?: string;\n graphRecallColdMirrorMinAgeDays: number;\n graphRecallUseEntityPriors: boolean;\n graphRecallEntityPriorBoost: number;\n graphRecallPreferHubSeeds: boolean;\n graphRecallHubBias: number;\n graphRecallRecencyHalfLifeDays: number;\n graphRecallDampingFactor: number;\n graphRecallMaxSeedNodes: number;\n graphRecallMaxExpandedNodes: number;\n graphRecallMaxTrailPerNode: number;\n graphRecallMinSeedScore: number;\n graphRecallExpansionScoreThreshold: number;\n graphRecallExplainMaxPaths: number;\n graphRecallExplainMaxChars: number;\n graphRecallExplainEdgeLimit: number;\n graphRecallExplainEnabled: boolean;\n graphRecallEntityHintsEnabled: boolean;\n graphRecallEntityHintMax: number;\n graphRecallEntityHintMaxChars: number;\n graphRecallSnapshotDir: string;\n graphRecallEnableTrace: boolean;\n graphRecallEnableDebug: boolean;\n /** Allow graph_mode escalation for broader causal/timeline phrasing beyond strict keywords. */\n graphExpandedIntentEnabled?: boolean;\n /** Run bounded graph expansion in full mode when enough recall seeds exist. */\n graphAssistInFullModeEnabled?: boolean;\n /** In full mode, compute graph assist for telemetry/snapshotting but do not inject merged results. */\n graphAssistShadowEvalEnabled?: boolean;\n /** Minimum seed results required before full-mode graph assist runs. */\n graphAssistMinSeedResults?: number;\n entityGraphEnabled: boolean;\n timeGraphEnabled: boolean;\n /** When true, write fallback temporal adjacency edges for consecutive extracted memories. */\n graphWriteSessionAdjacencyEnabled?: boolean;\n causalGraphEnabled: boolean;\n maxGraphTraversalSteps: number;\n graphActivationDecay: number;\n /** Weight of graph activation score when blending with seed QMD score (0-1). */\n graphExpansionActivationWeight: number;\n /** Lower bound for blended graph-expanded recall scores (0-1). */\n graphExpansionBlendMin: number;\n /** Upper bound for blended graph-expanded recall scores (0-1). */\n graphExpansionBlendMax: number;\n maxEntityGraphEdgesPerMemory: number;\n /** SimpleMem-inspired de-linearization: resolve pronouns and anchor relative dates after extraction. */\n delinearizeEnabled: boolean;\n /** Synapse-inspired confidence gate — skip memory injection when top score is below threshold. */\n recallConfidenceGateEnabled: boolean;\n recallConfidenceGateThreshold: number;\n /** PlugMem-inspired causal rule extraction: mine IF→THEN rules during consolidation. */\n causalRuleExtractionEnabled: boolean;\n /** E-Mem-inspired memory reconstruction: targeted retrieval for missing entity context. */\n memoryReconstructionEnabled: boolean;\n /** Maximum number of entity expansions per recall. */\n memoryReconstructionMaxExpansions: number;\n /** Synapse-inspired lateral inhibition to suppress hub-node dominance. */\n graphLateralInhibitionEnabled: boolean;\n /** Inhibition strength (default 0.15). Higher = more suppression. */\n graphLateralInhibitionBeta: number;\n /** Number of top competing nodes considered for inhibition (default 7). */\n graphLateralInhibitionTopM: number;\n // v8.2: Temporal Memory Tree\n temporalMemoryTreeEnabled: boolean;\n tmtHourlyMinMemories: number;\n tmtSummaryMaxTokens: number;\n // Lossless Context Management (LCM)\n lcmEnabled: boolean;\n lcmLeafBatchSize: number;\n lcmRollupFanIn: number;\n lcmFreshTailTurns: number;\n lcmMaxDepth: number;\n lcmRecallBudgetShare: number;\n lcmDeterministicMaxTokens: number;\n lcmArchiveRetentionDays: number;\n\n // v9.1 Parallel Specialized Retrieval (ASMR-inspired)\n /** Enable three-agent parallel retrieval (DirectFact + Contextual + Temporal). Default false. */\n parallelRetrievalEnabled: boolean;\n /** Per-agent source weights for score blending during merge. */\n parallelAgentWeights: { direct: number; contextual: number; temporal: number };\n /** Max results fetched per agent before merge. */\n parallelMaxResultsPerAgent: number;\n}\n\nexport interface BootstrapOptions {\n dryRun?: boolean;\n sessionsDir?: string;\n limit?: number;\n since?: Date;\n}\n\nexport interface BootstrapResult {\n sessionsScanned: number;\n turnsProcessed: number;\n highSignalTurns: number;\n memoriesCreated: number;\n skipped: number;\n}\n\nexport interface PrincipalRule {\n match: string;\n principal: string;\n}\n\nexport interface NamespacePolicy {\n name: string;\n readPrincipals: string[];\n writePrincipals: string[];\n includeInRecallByDefault?: boolean;\n}\n\nexport interface RelevanceFeedback {\n up: number;\n down: number;\n lastUpdatedAt: string;\n notes?: string[];\n}\n\nexport interface BufferTurn {\n role: \"user\" | \"assistant\";\n content: string;\n timestamp: string;\n sessionKey?: string;\n}\n\nexport interface BufferState {\n turns: BufferTurn[];\n lastExtractionAt: string | null;\n extractionCount: number;\n}\n\nexport interface BehaviorLoopAdjustment {\n parameter: string;\n previousValue: number;\n nextValue: number;\n delta: number;\n evidenceCount: number;\n confidence: number;\n reason: string;\n appliedAt: string;\n}\n\nexport interface BehaviorLoopPolicyState {\n version: number;\n windowDays: number;\n minSignalCount: number;\n maxDeltaPerCycle: number;\n protectedParams: string[];\n adjustments: BehaviorLoopAdjustment[];\n updatedAt: string;\n}\n\nexport type BehaviorSignalType = \"correction_override\" | \"preference_affinity\" | \"topic_revisitation\" | \"action_pattern\" | \"outcome_preference\" | \"phrasing_style\";\nexport type BehaviorSignalDirection = \"positive\" | \"negative\";\n\nexport interface BehaviorSignalEvent {\n timestamp: string;\n namespace: string;\n memoryId: string;\n category: Extract<MemoryCategory, \"correction\" | \"preference\">;\n signalType: BehaviorSignalType;\n direction: BehaviorSignalDirection;\n confidence: number;\n signalHash: string;\n source: \"extraction\" | \"correction\";\n}\n\n/** Memory status for lifecycle management */\nexport type MemoryStatus = \"active\" | \"pending_review\" | \"rejected\" | \"quarantined\" | \"superseded\" | \"archived\";\nexport type LifecycleState = \"candidate\" | \"validated\" | \"active\" | \"stale\" | \"archived\";\nexport type VerificationState = \"unverified\" | \"user_confirmed\" | \"system_inferred\" | \"disputed\";\nexport type PolicyClass = \"ephemeral\" | \"durable\" | \"protected\";\n\n/** Importance level tiers */\nexport type ImportanceLevel = \"critical\" | \"high\" | \"normal\" | \"low\" | \"trivial\";\n\n/** Importance scoring result */\nexport interface ImportanceScore {\n /** Numeric score 0-1 */\n score: number;\n /** Tier level */\n level: ImportanceLevel;\n /** Reasons for this score */\n reasons: string[];\n /** Salient keywords extracted */\n keywords: string[];\n}\n\nexport interface MemoryFrontmatter {\n id: string;\n category: MemoryCategory;\n created: string;\n updated: string;\n source: string;\n confidence: number;\n confidenceTier: ConfidenceTier;\n tags: string[];\n entityRef?: string;\n supersedes?: string;\n /** ISO 8601 date — memory expires and gets cleaned up after this date */\n expiresAt?: string;\n /** IDs of parent memories this was derived from (lineage tracking) */\n lineage?: string[];\n /** Memory status: active (default), pending_review, rejected, quarantined, superseded, or archived */\n status?: MemoryStatus;\n /** ID of memory that superseded this one */\n supersededBy?: string;\n /** Timestamp when superseded */\n supersededAt?: string;\n /** Timestamp when archived */\n archivedAt?: string;\n /** Policy-driven lifecycle state used for retrieval eligibility/ranking. */\n lifecycleState?: LifecycleState;\n /** Verification provenance used by lifecycle policy. */\n verificationState?: VerificationState;\n /** Policy class used by lifecycle guardrails. */\n policyClass?: PolicyClass;\n /** Last lifecycle validation timestamp (ISO 8601). */\n lastValidatedAt?: string;\n /** Lifecycle decay score in [0,1]. */\n decayScore?: number;\n /** Lifecycle heat score in [0,1]. */\n heatScore?: number;\n // Access tracking (Phase 1A)\n /** Number of times this memory has been retrieved */\n accessCount?: number;\n /** Last time this memory was accessed (ISO 8601) */\n lastAccessed?: string;\n // Importance scoring (Phase 1B)\n /** Importance score with level, reasons, and keywords */\n importance?: ImportanceScore;\n // Chunking (Phase 2A)\n /** Parent memory ID if this is a chunk */\n parentId?: string;\n /** Chunk index within parent (0-based) */\n chunkIndex?: number;\n /** Total number of chunks for this parent */\n chunkTotal?: number;\n // Memory Linking (Phase 3A)\n /** Links to other memories */\n links?: MemoryLink[];\n // Intent-grounded memory routing (v8.0 phase 1)\n intentGoal?: string;\n intentActionType?: string;\n intentEntityTypes?: string[];\n // Verbatim artifact lineage (v8.0 phase 1)\n artifactType?: \"decision\" | \"constraint\" | \"todo\" | \"definition\" | \"commitment\" | \"correction\" | \"fact\";\n sourceMemoryId?: string;\n sourceTurnId?: string;\n // v8.0 Phase 2B: HiMem episode/note classification\n /** episode = time-specific event; note = stable belief/preference/decision */\n memoryKind?: \"episode\" | \"note\";\n /** Structured key-value attributes extracted from the content (e.g., product attributes, dates, quantities). */\n structuredAttributes?: Record<string, string>;\n}\n\n/** Memory link relationship types */\nexport type MemoryLinkType = \"follows\" | \"references\" | \"contradicts\" | \"supports\" | \"related\";\n\n/** A link between memories */\nexport interface MemoryLink {\n targetId: string;\n linkType: MemoryLinkType;\n strength: number;\n reason?: string;\n}\n\n// Conversation Threading (Phase 3B)\nexport interface ConversationThread {\n id: string;\n title: string;\n createdAt: string;\n updatedAt: string;\n sessionKey?: string;\n episodeIds: string[];\n linkedThreadIds: string[];\n}\n\n// Memory Summarization (Phase 4A)\nexport interface MemorySummary {\n id: string;\n createdAt: string;\n timeRangeStart: string;\n timeRangeEnd: string;\n summaryText: string;\n keyFacts: string[];\n keyEntities: string[];\n sourceEpisodeIds: string[];\n}\n\nexport interface DaySummaryResult {\n summary: string;\n bullets: string[];\n next_actions: string[];\n risks_or_open_loops: string[];\n}\n\n// Topic Extraction (Phase 4B)\nexport interface TopicScore {\n term: string;\n score: number;\n count: number;\n}\n\nexport interface MemoryFile {\n path: string;\n frontmatter: MemoryFrontmatter;\n content: string;\n}\n\nexport interface ExtractedFact {\n category: MemoryCategory;\n content: string;\n confidence: number;\n tags: string[];\n entityRef?: string;\n source?: ExtractionPassSource;\n promptedByQuestion?: string;\n /** Structured key-value attributes extracted from the content (e.g., product attributes, dates, quantities). */\n structuredAttributes?: Record<string, string>;\n}\n\nexport interface MemoryIntent {\n goal: string;\n actionType: string;\n entityTypes: string[];\n}\n\nexport interface ExtractedQuestion {\n question: string;\n context: string;\n priority: number;\n}\n\nexport interface QuestionEntry {\n id: string;\n question: string;\n context: string;\n priority: number; // 0-1, higher = more important\n created: string;\n resolved: boolean;\n resolvedAt?: string;\n}\n\nexport interface ExtractionResult {\n facts: ExtractedFact[];\n profileUpdates: string[];\n entities: EntityMention[];\n questions: ExtractedQuestion[];\n identityReflection?: string;\n relationships?: ExtractedRelationship[];\n}\n\nexport interface EntityMention {\n name: string;\n type: \"person\" | \"project\" | \"tool\" | \"company\" | \"place\" | \"other\";\n facts: string[];\n source?: ExtractionPassSource;\n promptedByQuestion?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Knowledge Graph Enhancement (Entity Relationships, Activity, Scoring)\n// ---------------------------------------------------------------------------\n\nexport interface EntityRelationship {\n target: string;\n label: string;\n}\n\nexport interface EntityActivityEntry {\n date: string;\n note: string;\n}\n\nexport interface EntityFile {\n name: string;\n type: string;\n updated: string;\n facts: string[];\n summary?: string;\n relationships: EntityRelationship[];\n activity: EntityActivityEntry[];\n aliases: string[];\n}\n\nexport interface ScoredEntity {\n name: string;\n type: string;\n score: number;\n factCount: number;\n summary?: string;\n topRelationships: string[];\n}\n\nexport interface ExtractedRelationship {\n source: string;\n target: string;\n label: string;\n extractionSource?: ExtractionPassSource;\n promptedByQuestion?: string;\n}\n\nexport interface ConsolidationItem {\n existingId: string;\n action: ConsolidationAction;\n mergeWith?: string;\n updatedContent?: string;\n reason: string;\n}\n\nexport interface ConsolidationResult {\n items: ConsolidationItem[];\n profileUpdates: string[];\n entityUpdates: EntityMention[];\n}\n\nexport interface QmdSearchResult {\n docid: string;\n path: string;\n snippet: string;\n score: number;\n explain?: QmdSearchExplain;\n transport?: \"daemon\" | \"subprocess\" | \"hybrid\" | \"scoped_prefilter\";\n}\n\nexport interface QmdSearchExplain {\n ftsScores?: number[];\n vectorScores?: number[];\n rrf?: number;\n rerankScore?: number;\n blendedScore?: number;\n}\n\nexport interface MetaState {\n extractionCount: number;\n lastExtractionAt: string | null;\n lastConsolidationAt: string | null;\n totalMemories: number;\n totalEntities: number;\n}\n\nexport type MemoryActionType =\n | \"store_episode\"\n | \"store_note\"\n | \"update_note\"\n | \"create_artifact\"\n | \"summarize_node\"\n | \"discard\"\n | \"link_graph\";\n\nexport type MemoryActionOutcome = \"applied\" | \"skipped\" | \"failed\";\n\nexport type MemoryActionPolicyDecision = \"allow\" | \"defer\" | \"deny\";\n\nexport type MemoryActionStatus = \"validated\" | \"applied\" | \"rejected\";\n\nexport type MemoryActionEligibilitySource =\n | \"extraction\"\n | \"consolidation\"\n | \"replay\"\n | \"manual\"\n | \"unknown\";\n\nexport interface MemoryActionEligibilityContext {\n confidence: number;\n lifecycleState: LifecycleState;\n importance: number;\n source: MemoryActionEligibilitySource;\n}\n\nexport interface MemoryActionPolicyResult {\n action: MemoryActionType;\n decision: MemoryActionPolicyDecision;\n rationale: string;\n eligibility: MemoryActionEligibilityContext;\n}\n\nexport interface MemoryActionEvent {\n schemaVersion?: number;\n actionId?: string;\n timestamp: string;\n action: MemoryActionType;\n outcome: MemoryActionOutcome;\n status?: MemoryActionStatus;\n actor?: string;\n subsystem?: string;\n reason?: string;\n memoryId?: string;\n namespace?: string;\n sessionKey?: string;\n sourceSessionKey?: string;\n checkpointCapturedAt?: string;\n checkpointTtl?: string;\n checkpointTurnCount?: number;\n inputSummary?: string;\n outputMemoryIds?: string[];\n dryRun?: boolean;\n policyVersion?: string;\n promptHash?: string;\n policyDecision?: MemoryActionPolicyDecision;\n policyRationale?: string;\n policyEligibility?: MemoryActionEligibilityContext;\n}\n\nexport type MemoryLifecycleEventType =\n | \"created\"\n | \"updated\"\n | \"superseded\"\n | \"archived\"\n | \"rejected\"\n | \"restored\"\n | \"merged\"\n | \"imported\"\n | \"promoted\"\n | \"explicit_capture_accepted\"\n | \"explicit_capture_queued\";\n\nexport interface MemoryLifecycleStateSummary {\n category?: MemoryCategory;\n path?: string;\n status?: MemoryStatus;\n lifecycleState?: LifecycleState;\n}\n\nexport interface MemoryLifecycleEvent {\n eventId: string;\n memoryId: string;\n eventType: MemoryLifecycleEventType;\n timestamp: string;\n actor: string;\n reasonCode?: string;\n ruleVersion: string;\n relatedMemoryIds?: string[];\n before?: MemoryLifecycleStateSummary;\n after?: MemoryLifecycleStateSummary;\n correlationId?: string;\n}\n\nexport interface MemoryProjectionCurrentState {\n memoryId: string;\n category: MemoryCategory;\n status: MemoryStatus;\n lifecycleState?: LifecycleState;\n path: string;\n pathRel: string;\n created: string;\n updated: string;\n archivedAt?: string;\n supersededAt?: string;\n entityRef?: string;\n source: string;\n confidence: number;\n confidenceTier: ConfidenceTier;\n memoryKind?: MemoryFrontmatter[\"memoryKind\"];\n accessCount?: number;\n lastAccessed?: string;\n tags?: string[];\n preview?: string;\n}\n\nexport interface CompressionGuidelineOptimizerSourceWindow {\n from: string;\n to: string;\n}\n\nexport interface CompressionGuidelineOptimizerEventCounts {\n total: number;\n applied: number;\n skipped: number;\n failed: number;\n}\n\nexport type CompressionGuidelineActivationState = \"draft\" | \"active\";\n\nexport interface CompressionGuidelineOptimizerActionSummary {\n action: MemoryActionType;\n total: number;\n outcomes: Record<MemoryActionOutcome, number>;\n quality: {\n good: number;\n poor: number;\n unknown: number;\n };\n}\n\nexport interface CompressionGuidelineOptimizerRuleUpdate {\n action: MemoryActionType;\n delta: number;\n direction: \"increase\" | \"decrease\" | \"hold\";\n confidence: \"low\" | \"medium\" | \"high\";\n notes: string[];\n}\n\nexport interface CompressionGuidelineOptimizerState {\n version: number;\n updatedAt: string;\n sourceWindow: CompressionGuidelineOptimizerSourceWindow;\n eventCounts: CompressionGuidelineOptimizerEventCounts;\n guidelineVersion: number;\n contentHash?: string;\n activationState?: CompressionGuidelineActivationState;\n actionSummaries?: CompressionGuidelineOptimizerActionSummary[];\n ruleUpdates?: CompressionGuidelineOptimizerRuleUpdate[];\n}\n\nexport type ContinuityIncidentState = \"open\" | \"closed\";\n\nexport interface ContinuityIncidentRecord {\n id: string;\n state: ContinuityIncidentState;\n openedAt: string;\n updatedAt: string;\n triggerWindow?: string;\n symptom: string;\n suspectedCause?: string;\n fixApplied?: string;\n verificationResult?: string;\n preventiveRule?: string;\n closedAt?: string;\n filePath?: string;\n}\n\nexport interface ContinuityIncidentOpenInput {\n triggerWindow?: string;\n symptom: string;\n suspectedCause?: string;\n}\n\nexport interface ContinuityIncidentCloseInput {\n fixApplied: string;\n verificationResult: string;\n preventiveRule?: string;\n}\n\nexport type ContinuityLoopCadence = \"daily\" | \"weekly\" | \"monthly\" | \"quarterly\";\nexport type ContinuityLoopStatus = \"active\" | \"paused\" | \"retired\";\n\nexport interface ContinuityImprovementLoop {\n id: string;\n cadence: ContinuityLoopCadence;\n purpose: string;\n status: ContinuityLoopStatus;\n killCondition: string;\n lastReviewed: string;\n notes?: string;\n}\n\nexport interface ContinuityLoopUpsertInput {\n id: string;\n cadence: ContinuityLoopCadence;\n purpose: string;\n status: ContinuityLoopStatus;\n killCondition: string;\n lastReviewed?: string;\n notes?: string;\n}\n\nexport interface ContinuityLoopReviewInput {\n status?: ContinuityLoopStatus;\n notes?: string;\n reviewedAt?: string;\n}\n\n/** Entry in the access tracking buffer (batched updates) */\nexport interface AccessTrackingEntry {\n memoryId: string;\n newCount: number;\n lastAccessed: string;\n}\n\nexport interface SignalScanResult {\n level: SignalLevel;\n patterns: string[];\n}\n\n// ============================================================================\n// LLM Trace Callback (for external observability plugins)\n// ============================================================================\n\nexport interface LlmTraceEvent {\n kind: \"llm_start\" | \"llm_end\" | \"llm_error\";\n traceId: string;\n model: string;\n operation: \"extraction\" | \"consolidation\" | \"profile_consolidation\" | \"identity_consolidation\" | \"day_summary\";\n input?: string;\n output?: string;\n durationMs?: number;\n error?: string;\n tokenUsage?: { input?: number; output?: number; total?: number };\n}\n\nexport interface RecallTraceEvent {\n kind: \"recall_summary\";\n traceId: string;\n operation: \"recall\";\n sessionKey?: string;\n promptHash: string;\n promptLength: number;\n retrievalQueryHash: string;\n retrievalQueryLength: number;\n recallMode: RecallPlanMode;\n recallResultLimit: number;\n qmdEnabled: boolean;\n qmdAvailable: boolean;\n recallNamespaces: string[];\n source: \"none\" | \"hot_qmd\" | \"hot_embedding\" | \"cold_fallback\" | \"recent_scan\";\n recalledMemoryCount: number;\n injected: boolean;\n contextChars: number;\n policyVersion?: string;\n identityInjectionMode?: IdentityInjectionMode | \"none\";\n identityInjectedChars?: number;\n identityInjectionTruncated?: boolean;\n durationMs: number;\n timings?: Record<string, string>;\n /**\n * The full recalled memory context injected into the system prompt.\n * Only populated when `traceRecallContent` config option is `true`.\n * Omitted by default to avoid sending potentially sensitive memory content\n * to external trace collectors unless explicitly opted in.\n */\n recalledContent?: string;\n}\n\nexport type EngramTraceEvent = LlmTraceEvent | RecallTraceEvent;\nexport type LlmTraceCallback = (event: EngramTraceEvent) => void;\n\n// ============================================================================\n// Gateway Configuration Types (for fallback AI)\n// ============================================================================\n\nexport type ModelApi = \"openai-completions\" | \"anthropic-messages\" | \"google-generative\" | string;\n\nexport type ModelProviderAuthMode = \"bearer\" | \"header\" | \"query\";\n\nexport interface ModelDefinitionConfig {\n id: string;\n name?: string;\n contextWindow?: number;\n maxOutputTokens?: number;\n costPer1MInput?: number;\n costPer1MOutput?: number;\n aliases?: string[];\n}\n\nexport interface ModelProviderConfig {\n baseUrl: string;\n apiKey?: string | Record<string, unknown>;\n auth?: ModelProviderAuthMode;\n api?: ModelApi;\n headers?: Record<string, string>;\n authHeader?: boolean;\n models: ModelDefinitionConfig[];\n}\n\nexport interface AgentDefaultsConfig {\n model?: {\n primary?: string;\n backup?: string;\n fallbacks?: string[];\n };\n thinking?: {\n mode?: \"off\" | \"on\" | \"adaptive\";\n budget?: number;\n };\n}\n\nexport interface AgentPersonaModelConfig {\n primary?: string;\n fallbacks?: string[];\n}\n\nexport interface AgentPersona {\n id: string;\n name?: string;\n model?: AgentPersonaModelConfig;\n}\n\nexport interface GatewayConfig {\n agents?: {\n defaults?: AgentDefaultsConfig;\n list?: AgentPersona[];\n };\n models?: {\n providers?: Record<string, ModelProviderConfig>;\n };\n}\n\n// ============================================================================\n// Transcript & Context Preservation (v2.0)\n// ============================================================================\n\nexport interface TranscriptEntry {\n timestamp: string;\n role: \"user\" | \"assistant\";\n content: string;\n sessionKey: string;\n turnId: string;\n metadata?: {\n compactAfter?: boolean;\n compactionId?: string | null;\n };\n}\n\nexport interface Checkpoint {\n sessionKey: string;\n capturedAt: string;\n turns: TranscriptEntry[];\n ttl: string; // ISO timestamp when checkpoint expires\n}\n\nexport interface HourlySummary {\n hour: string; // \"2026-02-08T14:00:00Z\"\n sessionKey: string;\n bullets: string[];\n turnCount: number;\n generatedAt: string;\n}\n"],"mappings":";AAwHO,SAAS,eAAe,OAA+B;AAC5D,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,SAAS,IAAM,QAAO;AAC1B,MAAI,SAAS,IAAM,QAAO;AAC1B,SAAO;AACT;AAGO,IAAM,uBAAuB;","names":[]}
|