@remnic/core 1.1.31 → 9.3.516
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/dist/abstraction-nodes.js +2 -2
- package/dist/access-cli.d.ts +1 -1
- package/dist/access-cli.js +158 -121
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +9 -5
- package/dist/access-http.js +51 -51
- package/dist/access-idempotency.d.ts +2 -0
- package/dist/access-idempotency.js +1 -1
- package/dist/access-mcp.d.ts +16 -9
- package/dist/access-mcp.js +44 -44
- package/dist/access-schema.d.ts +45 -13
- package/dist/access-schema.js +8 -8
- package/dist/{access-service-CkZyb35d.d.ts → access-service-CZfksQuS.d.ts} +11 -130
- package/dist/access-service.d.ts +7 -4
- package/dist/access-service.js +40 -40
- package/dist/action-confidence.d.ts +1 -0
- package/dist/active-memory-bridge.d.ts +1 -0
- package/dist/active-memory-bridge.js +3 -2
- package/dist/active-recall.d.ts +1 -0
- package/dist/active-recall.js +14 -9
- package/dist/active-recall.js.map +1 -1
- package/dist/adapters/claude-code.d.ts +6 -2
- package/dist/adapters/claude-code.js +2 -2
- package/dist/adapters/codex.d.ts +5 -1
- package/dist/adapters/codex.js +2 -2
- package/dist/adapters/hermes.js +2 -2
- package/dist/adapters/index.js +6 -6
- package/dist/adapters/registry.js +6 -6
- package/dist/adapters/replit.d.ts +4 -2
- package/dist/adapters/replit.js +2 -2
- package/dist/adapters/types.d.ts +4 -0
- package/dist/adapters/types.js +1 -1
- package/dist/behavior-learner.d.ts +1 -0
- package/dist/behavior-signals.d.ts +1 -0
- package/dist/behavior-signals.js +1 -1
- package/dist/bootstrap.d.ts +5 -3
- package/dist/bootstrap.js +2 -2
- package/dist/boxes.d.ts +1 -0
- package/dist/boxes.js +1 -1
- package/dist/briefing.d.ts +1 -0
- package/dist/briefing.js +9 -9
- package/dist/buffer-surprise-report.d.ts +1 -0
- package/dist/buffer.d.ts +1 -0
- package/dist/buffer.js +2 -2
- package/dist/bulk-import/index.d.ts +28 -0
- package/dist/bulk-import/index.js +31 -0
- package/dist/calibration.d.ts +2 -0
- package/dist/calibration.js +50 -17
- package/dist/calibration.js.map +1 -1
- package/dist/{capsule-crypto-5CYAGVC5.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/{capsule-merge-4MGKE7C5.js → capsule-merge-T2JRE46P.js} +3 -3
- package/dist/causal-behavior.d.ts +1 -0
- package/dist/causal-behavior.js +4 -4
- package/dist/causal-chain.js +4 -4
- package/dist/causal-consolidation.d.ts +16 -1
- package/dist/causal-consolidation.js +115 -32
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +14 -6
- package/dist/causal-retrieval.js.map +1 -1
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +2 -2
- package/dist/{chunk-SAZS2QZB.js → chunk-23UORJ4S.js} +3 -3
- package/dist/{chunk-76FLAAUC.js → chunk-2AN2L4NL.js} +17 -6
- package/dist/chunk-2AN2L4NL.js.map +1 -0
- package/dist/{chunk-W4L6CZKA.js → chunk-2DL3OFLD.js} +15 -10
- package/dist/chunk-2DL3OFLD.js.map +1 -0
- package/dist/{chunk-NJ3MJQZX.js → chunk-2I5JGH3M.js} +2 -2
- package/dist/{chunk-NJ3MJQZX.js.map → chunk-2I5JGH3M.js.map} +1 -1
- package/dist/{chunk-7OZ53EXP.js → chunk-2NLLXCJG.js} +21 -10
- package/dist/chunk-2NLLXCJG.js.map +1 -0
- package/dist/{chunk-PK7H5L6Y.js → chunk-2NM43EWN.js} +2 -2
- package/dist/{chunk-PYXS46O7.js → chunk-3BP57I6J.js} +2 -2
- package/dist/{chunk-FBYESMQ2.js → chunk-3C5RPJAX.js} +2 -2
- package/dist/{chunk-FKFMOY3N.js → chunk-42NQ7AVG.js} +3 -4
- package/dist/{chunk-FKFMOY3N.js.map → chunk-42NQ7AVG.js.map} +1 -1
- package/dist/chunk-4426WSWL.js +73 -0
- package/dist/chunk-4426WSWL.js.map +1 -0
- package/dist/{chunk-LIRZNNUP.js → chunk-44442YCH.js} +5 -2
- package/dist/chunk-44442YCH.js.map +1 -0
- package/dist/{chunk-H3ME6L6D.js → chunk-46GJIW5M.js} +23 -20
- package/dist/chunk-46GJIW5M.js.map +1 -0
- package/dist/{chunk-QDZ2RLEC.js → chunk-472U7RDF.js} +3 -3
- package/dist/chunk-472U7RDF.js.map +1 -0
- package/dist/{chunk-NN2DKE4T.js → chunk-4H5ZJHEN.js} +16 -3
- package/dist/{chunk-NN2DKE4T.js.map → chunk-4H5ZJHEN.js.map} +1 -1
- package/dist/{chunk-56K5QLHX.js → chunk-4HP7HIE3.js} +56 -13
- package/dist/chunk-4HP7HIE3.js.map +1 -0
- package/dist/{chunk-RK2Y4XOM.js → chunk-4JRRISLU.js} +9 -6
- package/dist/chunk-4JRRISLU.js.map +1 -0
- package/dist/{chunk-XKLD5OK4.js → chunk-4RR6ROTB.js} +10 -11
- package/dist/chunk-4RR6ROTB.js.map +1 -0
- package/dist/{chunk-YROHKYBY.js → chunk-5UHVGNZD.js} +22 -6
- package/dist/chunk-5UHVGNZD.js.map +1 -0
- package/dist/{chunk-ZAVUCJ4H.js → chunk-5V456VRV.js} +154 -69
- package/dist/chunk-5V456VRV.js.map +1 -0
- package/dist/{chunk-77H5NU3M.js → chunk-6BR7L222.js} +82 -18
- package/dist/chunk-6BR7L222.js.map +1 -0
- package/dist/{chunk-4KGVTPGD.js → chunk-6F6BXB7A.js} +9 -8
- package/dist/chunk-6F6BXB7A.js.map +1 -0
- package/dist/{chunk-NMZY542O.js → chunk-6URPAY2D.js} +41 -17
- package/dist/chunk-6URPAY2D.js.map +1 -0
- package/dist/{chunk-N53K2EXC.js → chunk-6VF75M3X.js} +2 -2
- package/dist/{chunk-XSZEP4SF.js → chunk-6XSPNR6L.js} +6 -5
- package/dist/chunk-6XSPNR6L.js.map +1 -0
- package/dist/{chunk-6H2TESSP.js → chunk-765K3SAT.js} +3 -3
- package/dist/{chunk-EDTHC6UD.js → chunk-77NAFXUD.js} +2 -2
- package/dist/{chunk-S7KDBTWT.js → chunk-7F7Z6MOS.js} +29 -14
- package/dist/chunk-7F7Z6MOS.js.map +1 -0
- package/dist/{chunk-MZH6EHNR.js → chunk-7H6CFEBJ.js} +41 -14
- package/dist/chunk-7H6CFEBJ.js.map +1 -0
- package/dist/{chunk-MGKYQQYF.js → chunk-7Q3RCKAQ.js} +2 -2
- package/dist/chunk-7RXCMVFQ.js +27 -0
- package/dist/chunk-7RXCMVFQ.js.map +1 -0
- package/dist/{chunk-DGXUHMOV.js → chunk-A2IYSXDQ.js} +25 -6
- package/dist/chunk-A2IYSXDQ.js.map +1 -0
- package/dist/{chunk-EABGC2TL.js → chunk-A2Z6UCWT.js} +26 -4
- package/dist/chunk-A2Z6UCWT.js.map +1 -0
- package/dist/{chunk-5375UYTQ.js → chunk-A6D7A2FW.js} +4 -4
- package/dist/chunk-A6D7A2FW.js.map +1 -0
- package/dist/{chunk-FAAFWE4G.js → chunk-ALEPI75L.js} +24 -6
- package/dist/chunk-ALEPI75L.js.map +1 -0
- package/dist/{chunk-3SLRNYNG.js → chunk-AUDJPF4N.js} +15 -4
- package/dist/chunk-AUDJPF4N.js.map +1 -0
- package/dist/chunk-B5XMS73R.js +145 -0
- package/dist/chunk-B5XMS73R.js.map +1 -0
- package/dist/{chunk-HXXBL2KD.js → chunk-BECQDWBA.js} +44 -4
- package/dist/chunk-BECQDWBA.js.map +1 -0
- package/dist/{chunk-7SEAZFFB.js → chunk-BEUDU7Y4.js} +24 -4
- package/dist/chunk-BEUDU7Y4.js.map +1 -0
- package/dist/chunk-CHBI22MI.js +159 -0
- package/dist/chunk-CHBI22MI.js.map +1 -0
- package/dist/{chunk-GDFS42HT.js → chunk-CHCA44C3.js} +15 -8
- package/dist/chunk-CHCA44C3.js.map +1 -0
- package/dist/chunk-CINZGPSJ.js +22 -0
- package/dist/chunk-CINZGPSJ.js.map +1 -0
- package/dist/chunk-CMTINOFS.js +36 -0
- package/dist/chunk-CMTINOFS.js.map +1 -0
- package/dist/{chunk-34DQE4KF.js → chunk-CO7ZO4TU.js} +2 -2
- package/dist/{chunk-PFV5C235.js → chunk-CPPS65WS.js} +2 -1
- package/dist/{chunk-PFV5C235.js.map → chunk-CPPS65WS.js.map} +1 -1
- package/dist/{chunk-DINWEURR.js → chunk-CSKLPDN6.js} +20 -6
- package/dist/chunk-CSKLPDN6.js.map +1 -0
- package/dist/chunk-CWWMTTQE.js +566 -0
- package/dist/chunk-CWWMTTQE.js.map +1 -0
- package/dist/{chunk-IQT3XTKW.js → chunk-D24OXEPB.js} +13 -7
- package/dist/chunk-D24OXEPB.js.map +1 -0
- package/dist/{chunk-WIICJPET.js → chunk-DEUNUKTD.js} +6 -4
- package/dist/{chunk-WIICJPET.js.map → chunk-DEUNUKTD.js.map} +1 -1
- package/dist/{chunk-ZYVPLJ4T.js → chunk-DHGSZ3UD.js} +9 -7
- package/dist/chunk-DHGSZ3UD.js.map +1 -0
- package/dist/{chunk-JR4ZC3G4.js → chunk-DLJ4IR6M.js} +91 -41
- package/dist/chunk-DLJ4IR6M.js.map +1 -0
- package/dist/{chunk-U4SCL7B7.js → chunk-DRD2Q7HQ.js} +82 -18
- package/dist/chunk-DRD2Q7HQ.js.map +1 -0
- package/dist/{chunk-2IWUMAES.js → chunk-E62SBGQ3.js} +28 -13
- package/dist/chunk-E62SBGQ3.js.map +1 -0
- package/dist/{chunk-C5BCH4ZS.js → chunk-EAZGEEG2.js} +21 -3
- package/dist/chunk-EAZGEEG2.js.map +1 -0
- package/dist/{chunk-TPB3I2AC.js → chunk-ECZU5BJH.js} +31 -10
- package/dist/chunk-ECZU5BJH.js.map +1 -0
- package/dist/chunk-EDQVAMQI.js +308 -0
- package/dist/chunk-EDQVAMQI.js.map +1 -0
- package/dist/{chunk-RRF5UOBJ.js → chunk-EI6V5UXY.js} +22 -15
- package/dist/chunk-EI6V5UXY.js.map +1 -0
- package/dist/{chunk-ZKSK55RC.js → chunk-ETUPBUHB.js} +2 -2
- package/dist/{chunk-25MQ7IHJ.js → chunk-EUML3N6B.js} +17 -6
- package/dist/chunk-EUML3N6B.js.map +1 -0
- package/dist/{chunk-5RGLBDQF.js → chunk-EVZFIAPG.js} +12 -12
- package/dist/chunk-EVZFIAPG.js.map +1 -0
- package/dist/{chunk-QRNI5JBH.js → chunk-EYIEWJNI.js} +2 -2
- package/dist/{chunk-TPU5L5EY.js → chunk-FCOQXV3T.js} +272 -411
- package/dist/chunk-FCOQXV3T.js.map +1 -0
- package/dist/{chunk-TMQLARTH.js → chunk-FK556DDH.js} +34 -15
- package/dist/chunk-FK556DDH.js.map +1 -0
- package/dist/{chunk-43PJZYGL.js → chunk-FPGE5NVO.js} +45 -10
- package/dist/chunk-FPGE5NVO.js.map +1 -0
- package/dist/{chunk-3VAL7ZL2.js → chunk-FUC4LZMD.js} +60 -25
- package/dist/chunk-FUC4LZMD.js.map +1 -0
- package/dist/{chunk-C6QPK5GG.js → chunk-FZZ2QTJI.js} +2 -2
- package/dist/{chunk-D46YSIYX.js → chunk-G3Z3QEF5.js} +19 -11
- package/dist/{chunk-D46YSIYX.js.map → chunk-G3Z3QEF5.js.map} +1 -1
- package/dist/{chunk-3JXBXXM2.js → chunk-G4IAEX6D.js} +2 -2
- package/dist/{chunk-MSWG7JI6.js → chunk-G56P5RLD.js} +8 -2
- package/dist/chunk-G56P5RLD.js.map +1 -0
- package/dist/{chunk-AGZQD76C.js → chunk-GCGJW34D.js} +48 -2
- package/dist/chunk-GCGJW34D.js.map +1 -0
- package/dist/chunk-H2NCNXMS.js +159 -0
- package/dist/chunk-H2NCNXMS.js.map +1 -0
- package/dist/{chunk-XYIK4LF6.js → chunk-H3FZVNRN.js} +8 -2
- package/dist/chunk-H3FZVNRN.js.map +1 -0
- package/dist/{chunk-YU5KIWYQ.js → chunk-HC6EKOID.js} +94 -43
- package/dist/chunk-HC6EKOID.js.map +1 -0
- package/dist/{chunk-TK4UEOSK.js → chunk-HDDRVXX4.js} +8 -8
- package/dist/chunk-HDDRVXX4.js.map +1 -0
- package/dist/{chunk-LLQ2LLWF.js → chunk-HENLZHIT.js} +15 -5
- package/dist/chunk-HENLZHIT.js.map +1 -0
- package/dist/{chunk-N2D6GXBM.js → chunk-HINSGUA7.js} +28 -20
- package/dist/chunk-HINSGUA7.js.map +1 -0
- package/dist/{chunk-APO3DCMU.js → chunk-HLAVGJ62.js} +30 -8
- package/dist/chunk-HLAVGJ62.js.map +1 -0
- package/dist/{chunk-TPMQ3G6Z.js → chunk-HOJZMQ4J.js} +2 -2
- package/dist/chunk-HOJZMQ4J.js.map +1 -0
- package/dist/{chunk-LUDTDZLK.js → chunk-HPWVAEET.js} +33 -7
- package/dist/chunk-HPWVAEET.js.map +1 -0
- package/dist/{chunk-NZL6GGQE.js → chunk-HQ6NIBL6.js} +92 -30
- package/dist/chunk-HQ6NIBL6.js.map +1 -0
- package/dist/{chunk-UWVJF25J.js → chunk-HWVTS5NO.js} +20 -6
- package/dist/chunk-HWVTS5NO.js.map +1 -0
- package/dist/{chunk-2WWLHTZY.js → chunk-IC4GELZE.js} +2 -2
- package/dist/{chunk-QA2ZAPBU.js → chunk-IPLYGWQF.js} +28 -20
- package/dist/chunk-IPLYGWQF.js.map +1 -0
- package/dist/{chunk-A6KTB5R6.js → chunk-IQ3OI2RR.js} +3 -3
- package/dist/chunk-IQ3OI2RR.js.map +1 -0
- package/dist/{chunk-6LVVDPJ4.js → chunk-J64TK33U.js} +3 -4
- package/dist/chunk-J64TK33U.js.map +1 -0
- package/dist/{chunk-6FC5EGNV.js → chunk-JBPKEARU.js} +15 -5
- package/dist/{chunk-6FC5EGNV.js.map → chunk-JBPKEARU.js.map} +1 -1
- package/dist/{chunk-RHY3HH7P.js → chunk-JFEKNTX7.js} +125 -33
- package/dist/chunk-JFEKNTX7.js.map +1 -0
- package/dist/{chunk-TZOLIGIG.js → chunk-JJEJJ7RK.js} +4 -2
- package/dist/chunk-JJEJJ7RK.js.map +1 -0
- package/dist/{chunk-PCUKNJAZ.js → chunk-JKV57BTN.js} +2 -2
- package/dist/{chunk-EJI5XIBB.js → chunk-JLNBQWZ2.js} +55 -7
- package/dist/chunk-JLNBQWZ2.js.map +1 -0
- package/dist/{chunk-PIRJPV5T.js → chunk-JNANKJLN.js} +2 -2
- package/dist/chunk-JNANKJLN.js.map +1 -0
- package/dist/{chunk-XIG5PDM7.js → chunk-JUC24CTX.js} +8 -12
- package/dist/chunk-JUC24CTX.js.map +1 -0
- package/dist/{chunk-OIGNEXKZ.js → chunk-K5O2QY6T.js} +5 -1
- package/dist/{chunk-OIGNEXKZ.js.map → chunk-K5O2QY6T.js.map} +1 -1
- package/dist/{chunk-ZTFCYYEZ.js → chunk-KCYE2MZM.js} +3 -3
- package/dist/chunk-KCYE2MZM.js.map +1 -0
- package/dist/{chunk-JWPLJLDU.js → chunk-KD3QD3A5.js} +2 -2
- package/dist/{chunk-JWPLJLDU.js.map → chunk-KD3QD3A5.js.map} +1 -1
- package/dist/{chunk-YRMVARQP.js → chunk-KFY3SGN7.js} +49 -2
- package/dist/chunk-KFY3SGN7.js.map +1 -0
- package/dist/{chunk-CYFQJMUV.js → chunk-KIB7SDIJ.js} +15 -10
- package/dist/chunk-KIB7SDIJ.js.map +1 -0
- package/dist/{chunk-3KW65B36.js → chunk-KILOTVIF.js} +95 -48
- package/dist/chunk-KILOTVIF.js.map +1 -0
- package/dist/{chunk-MXFBBHJU.js → chunk-KJMYHC7K.js} +10 -5
- package/dist/chunk-KJMYHC7K.js.map +1 -0
- package/dist/{chunk-W3LR522O.js → chunk-KM2A35EO.js} +36 -34
- package/dist/chunk-KM2A35EO.js.map +1 -0
- package/dist/{chunk-575RMLWN.js → chunk-KXULCVOC.js} +30 -24
- package/dist/chunk-KXULCVOC.js.map +1 -0
- package/dist/{chunk-WELDCG6C.js → chunk-L227SKTB.js} +109 -36
- package/dist/chunk-L227SKTB.js.map +1 -0
- package/dist/{chunk-BVF3AGJP.js → chunk-LJBOVCQG.js} +26 -11
- package/dist/chunk-LJBOVCQG.js.map +1 -0
- package/dist/{chunk-2KI4QFHU.js → chunk-LMDRGRJ2.js} +2 -2
- package/dist/{chunk-MY6TPVXW.js → chunk-LMPHTYJC.js} +2 -2
- package/dist/{chunk-EHRTFRWW.js → chunk-LQHDIS7L.js} +10 -5
- package/dist/chunk-LQHDIS7L.js.map +1 -0
- package/dist/chunk-LUDUFZTV.js +170 -0
- package/dist/chunk-LUDUFZTV.js.map +1 -0
- package/dist/{chunk-5HRY2WRF.js → chunk-LZ3VEOU5.js} +2 -2
- package/dist/{chunk-Q7P4WJDP.js → chunk-M5T4Q2ZU.js} +1 -1
- package/dist/chunk-M5T4Q2ZU.js.map +1 -0
- package/dist/{chunk-ICRIXAP2.js → chunk-MC4FJXPA.js} +16 -6
- package/dist/chunk-MC4FJXPA.js.map +1 -0
- package/dist/{chunk-WPGJYVUH.js → chunk-MGVIEM2O.js} +23 -6
- package/dist/chunk-MGVIEM2O.js.map +1 -0
- package/dist/{chunk-NGAVDO7E.js → chunk-OADWQ5CR.js} +2 -2
- package/dist/{chunk-2NMMFZ5T.js → chunk-OD4FM2U7.js} +6 -3
- package/dist/chunk-OD4FM2U7.js.map +1 -0
- package/dist/{chunk-OZHRDTDX.js → chunk-OKTXM5H4.js} +11 -1
- package/dist/chunk-OKTXM5H4.js.map +1 -0
- package/dist/{chunk-RXDLTSWT.js → chunk-ONPLNAPX.js} +16 -7
- package/dist/chunk-ONPLNAPX.js.map +1 -0
- package/dist/{chunk-FJ43PRLT.js → chunk-ORFGK3XI.js} +20 -14
- package/dist/chunk-ORFGK3XI.js.map +1 -0
- package/dist/{chunk-DOM4GKSW.js → chunk-OZKVVUJB.js} +3 -3
- package/dist/{chunk-3TNBOMQT.js → chunk-PCI747N2.js} +13 -13
- package/dist/{chunk-3TNBOMQT.js.map → chunk-PCI747N2.js.map} +1 -1
- package/dist/{chunk-MT4HVDUZ.js → chunk-PM3QHTFT.js} +3 -3
- package/dist/{chunk-4DWOBS2A.js → chunk-PRQJ5ESM.js} +27 -2
- package/dist/{chunk-4DWOBS2A.js.map → chunk-PRQJ5ESM.js.map} +1 -1
- package/dist/chunk-PU44GBL4.js +52 -0
- package/dist/chunk-PU44GBL4.js.map +1 -0
- package/dist/{chunk-MJFNCJXV.js → chunk-Q4CAQGKQ.js} +47 -9
- package/dist/chunk-Q4CAQGKQ.js.map +1 -0
- package/dist/{chunk-U3WSW6PZ.js → chunk-QMYXNM4P.js} +90 -35
- package/dist/chunk-QMYXNM4P.js.map +1 -0
- package/dist/{chunk-XVVIG67A.js → chunk-QVJ4NWL2.js} +62 -18
- package/dist/chunk-QVJ4NWL2.js.map +1 -0
- package/dist/{chunk-NBNN5GOB.js → chunk-QY7YA7OL.js} +11 -2
- package/dist/chunk-QY7YA7OL.js.map +1 -0
- package/dist/{chunk-ZK7I7JYV.js → chunk-R3PS27B4.js} +7 -7
- package/dist/{chunk-2PRLKQAH.js → chunk-RLV3PQGH.js} +35 -19
- package/dist/chunk-RLV3PQGH.js.map +1 -0
- package/dist/{chunk-WW3QQF4H.js → chunk-ROZJACKP.js} +16 -1
- package/dist/chunk-ROZJACKP.js.map +1 -0
- package/dist/{chunk-7MNMYOFP.js → chunk-RSUYKGGZ.js} +3 -4
- package/dist/chunk-RSUYKGGZ.js.map +1 -0
- package/dist/{chunk-LT3NLYSI.js → chunk-RUZOJKNF.js} +10 -7
- package/dist/chunk-RUZOJKNF.js.map +1 -0
- package/dist/{chunk-326G7DJK.js → chunk-RW5DGAGO.js} +67 -13
- package/dist/chunk-RW5DGAGO.js.map +1 -0
- package/dist/{chunk-KOSORCJG.js → chunk-S53PKKWK.js} +63 -24
- package/dist/chunk-S53PKKWK.js.map +1 -0
- package/dist/{chunk-65PG43EQ.js → chunk-S7WU3Y3D.js} +21 -4
- package/dist/chunk-S7WU3Y3D.js.map +1 -0
- package/dist/{chunk-SKE7JYKA.js → chunk-SFXKHM7P.js} +2 -2
- package/dist/{chunk-HMDCOMYU.js → chunk-SKGV326D.js} +3 -3
- package/dist/{chunk-I5GLV3VE.js → chunk-SML26KED.js} +33 -26
- package/dist/{chunk-I5GLV3VE.js.map → chunk-SML26KED.js.map} +1 -1
- package/dist/chunk-T2PO5MUF.js +62 -0
- package/dist/chunk-T2PO5MUF.js.map +1 -0
- package/dist/{chunk-C7VW7C3F.js → chunk-TDKQGLJW.js} +3 -3
- package/dist/chunk-TDKQGLJW.js.map +1 -0
- package/dist/{chunk-3QKK7QOS.js → chunk-TERNBNJB.js} +3 -3
- package/dist/chunk-TERNBNJB.js.map +1 -0
- package/dist/{chunk-MXC3AP5I.js → chunk-TGQ2NTWH.js} +12 -7
- package/dist/chunk-TGQ2NTWH.js.map +1 -0
- package/dist/{chunk-3Y4P7RXM.js → chunk-TMSXWOBZ.js} +3 -4
- package/dist/chunk-TMSXWOBZ.js.map +1 -0
- package/dist/{chunk-3ZLVGM76.js → chunk-TTGZV5R3.js} +106 -44
- package/dist/chunk-TTGZV5R3.js.map +1 -0
- package/dist/{chunk-5UM2VJ6D.js → chunk-UEY3VB6W.js} +2 -2
- package/dist/{chunk-I6K5FBRQ.js → chunk-UI3NYK34.js} +4 -1
- package/dist/{chunk-I6K5FBRQ.js.map → chunk-UI3NYK34.js.map} +1 -1
- package/dist/{chunk-VBJ7V5SK.js → chunk-UIPDNLXA.js} +21 -8
- package/dist/chunk-UIPDNLXA.js.map +1 -0
- package/dist/{chunk-GIF42EW3.js → chunk-UP6MOYCB.js} +3 -3
- package/dist/{chunk-K4FLSOR5.js → chunk-USYGGIJZ.js} +44 -15
- package/dist/chunk-USYGGIJZ.js.map +1 -0
- package/dist/{chunk-FIT6DMX6.js → chunk-UWY7GIVS.js} +152 -54
- package/dist/chunk-UWY7GIVS.js.map +1 -0
- package/dist/{chunk-MRILGULB.js → chunk-V2RCP53Q.js} +2 -2
- package/dist/{chunk-XKECPATV.js → chunk-VFUEZZBS.js} +113 -4
- package/dist/chunk-VFUEZZBS.js.map +1 -0
- package/dist/{chunk-FSFEQI74.js → chunk-W7L6HXUC.js} +2 -2
- package/dist/{chunk-3IQ2TR4N.js → chunk-WLEB7WCG.js} +2 -2
- package/dist/{chunk-GL6I6MEQ.js → chunk-WSGF57U2.js} +3 -3
- package/dist/{chunk-KNKUID7G.js → chunk-X7Y7WX73.js} +72 -6
- package/dist/chunk-X7Y7WX73.js.map +1 -0
- package/dist/{chunk-5NPGSAVB.js → chunk-XEKAG3FM.js} +23 -5
- package/dist/chunk-XEKAG3FM.js.map +1 -0
- package/dist/{chunk-3APJ5EVB.js → chunk-XKIQZXUB.js} +41 -26
- package/dist/chunk-XKIQZXUB.js.map +1 -0
- package/dist/chunk-XKXKSQU7.js +92 -0
- package/dist/chunk-XKXKSQU7.js.map +1 -0
- package/dist/{chunk-JA3AK3PT.js → chunk-XNLXAWHX.js} +4 -4
- package/dist/{chunk-CULXMQJH.js → chunk-XPXEJRUB.js} +3 -3
- package/dist/chunk-XPXEJRUB.js.map +1 -0
- package/dist/{chunk-PZIAX57I.js → chunk-XR6DNK4U.js} +7 -4
- package/dist/chunk-XR6DNK4U.js.map +1 -0
- package/dist/{chunk-47VWKCAF.js → chunk-XSQ4SGM5.js} +33 -4
- package/dist/chunk-XSQ4SGM5.js.map +1 -0
- package/dist/{chunk-66DHUKLO.js → chunk-XSWKORGM.js} +16 -14
- package/dist/chunk-XSWKORGM.js.map +1 -0
- package/dist/{chunk-QR3C7BKQ.js → chunk-XZ4WBBB5.js} +7 -8
- package/dist/chunk-XZ4WBBB5.js.map +1 -0
- package/dist/{chunk-WNARATI3.js → chunk-Y2SXZ5KZ.js} +59 -11
- package/dist/chunk-Y2SXZ5KZ.js.map +1 -0
- package/dist/{chunk-QLLBRHAT.js → chunk-YDMVYYD2.js} +229 -264
- package/dist/chunk-YDMVYYD2.js.map +1 -0
- package/dist/{chunk-SIC6U3GZ.js → chunk-YHV3KRKS.js} +3 -3
- package/dist/{chunk-ZPKBYX2F.js → chunk-YNDLCWXS.js} +85 -9
- package/dist/chunk-YNDLCWXS.js.map +1 -0
- package/dist/{chunk-W6AQJ2PY.js → chunk-YNXOKMJP.js} +35 -16
- package/dist/chunk-YNXOKMJP.js.map +1 -0
- package/dist/{chunk-VLXA6PI2.js → chunk-YQMZ7IH2.js} +4 -4
- package/dist/{chunk-TMM4S4IJ.js → chunk-YR6GIWWY.js} +58 -8
- package/dist/chunk-YR6GIWWY.js.map +1 -0
- package/dist/{chunk-DK5LDEQM.js → chunk-YR7XMOWK.js} +39 -23
- package/dist/chunk-YR7XMOWK.js.map +1 -0
- package/dist/{chunk-U7EJOMFC.js → chunk-ZEY4KYRQ.js} +41 -14
- package/dist/chunk-ZEY4KYRQ.js.map +1 -0
- package/dist/chunk-ZFXCQPNO.js +27 -0
- package/dist/chunk-ZFXCQPNO.js.map +1 -0
- package/dist/citations.js +1 -1
- package/dist/{cli-kuh9PwZ5.d.ts → cli-CPe_2KB1.d.ts} +8 -31
- package/dist/cli.d.ts +10 -6
- package/dist/cli.js +124 -119
- package/dist/commitment-ledger.js +2 -2
- package/dist/compat/checks.js +1 -2
- package/dist/compounding/engine.d.ts +3 -2
- package/dist/compounding/engine.js +11 -11
- package/dist/compounding/preference-consolidator.d.ts +1 -0
- package/dist/compounding/preference-consolidator.js +8 -8
- package/dist/compounding/preference-consolidator.js.map +1 -1
- package/dist/compression-optimizer.d.ts +1 -0
- package/dist/compression-optimizer.js +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +3 -2
- package/dist/connectors/codex-materialize-runner.d.ts +1 -0
- package/dist/connectors/codex-materialize-runner.js +12 -11
- package/dist/connectors/codex-materialize.d.ts +1 -0
- package/dist/connectors/codex-materialize.js +3 -2
- package/dist/connectors/index.d.ts +1 -0
- package/dist/connectors/index.js +14 -14
- package/dist/{connectors-cli-CwbyjGR7.d.ts → connectors-cli-DbTPNj2H.d.ts} +7 -1
- package/dist/connectors-cli.d.ts +1 -1
- package/dist/connectors-cli.js +3 -1
- package/dist/consolidation-provenance-check.d.ts +1 -0
- package/dist/consolidation-provenance-check.js +2 -2
- package/dist/consolidation-undo.d.ts +1 -0
- package/dist/consolidation-undo.js +1 -1
- package/dist/contradiction/index.d.ts +3 -1
- package/dist/contradiction/index.js +3 -3
- package/dist/{contradiction-review-ATP4S6IC.js → contradiction-review-6V2LXXK6.js} +2 -2
- package/dist/{contradiction-scan-5A4IDZV5.js → contradiction-scan-GIRVC4C7.js} +3 -3
- package/dist/conversation-index/backend.d.ts +3 -1
- package/dist/conversation-index/backend.js +3 -3
- package/dist/conversation-index/chunker.d.ts +1 -0
- package/dist/conversation-index/cleanup.js +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +2 -1
- package/dist/conversation-index/faiss-adapter.js +1 -1
- package/dist/conversation-index/indexer.d.ts +5 -2
- package/dist/conversation-index/indexer.js +1 -1
- package/dist/conversation-index/search.d.ts +2 -1
- package/dist/cross-namespace-budget.js +1 -1
- package/dist/cue-anchors.js +2 -2
- package/dist/dashboard-runtime.d.ts +6 -0
- package/dist/dashboard-runtime.js +3 -3
- package/dist/day-summary.d.ts +1 -0
- package/dist/day-summary.js +2 -2
- package/dist/delinearize.d.ts +1 -0
- package/dist/direct-answer-wiring.d.ts +1 -0
- package/dist/direct-answer.d.ts +1 -0
- package/dist/{dreams-ledger-LR2NBAZE.js → dreams-ledger-3WSCI5V4.js} +5 -4
- package/dist/{dreams-ledger-LR2NBAZE.js.map → dreams-ledger-3WSCI5V4.js.map} +1 -1
- package/dist/embedding-fallback.d.ts +3 -0
- package/dist/embedding-fallback.js +2 -2
- package/dist/enrichment/index.d.ts +1 -0
- package/dist/enrichment/index.js +1 -1
- package/dist/entity-retrieval.d.ts +2 -0
- package/dist/entity-retrieval.js +9 -9
- package/dist/entity-schema.d.ts +1 -0
- package/dist/evals.js +1 -1
- package/dist/explicit-capture.d.ts +5 -3
- package/dist/explicit-capture.js +2 -2
- package/dist/extraction-judge-telemetry.d.ts +2 -0
- package/dist/extraction-judge-training.d.ts +2 -0
- package/dist/extraction-judge.d.ts +2 -0
- package/dist/extraction.d.ts +2 -0
- package/dist/extraction.js +12 -12
- package/dist/{faiss-adapter-CzPghc4C.d.ts → faiss-adapter-BHecI1fF.d.ts} +4 -1
- package/dist/fallback-llm.d.ts +11 -1
- package/dist/fallback-llm.js +8 -6
- package/dist/{first-start-migration-4MHQEOSD.js → first-start-migration-CKTCTCQI.js} +5 -5
- package/dist/graph-dashboard-diff.d.ts +4 -0
- package/dist/graph-dashboard-diff.js +1 -1
- package/dist/graph-dashboard-parser.js +1 -1
- package/dist/{graph-edge-decay-5DI5GUNL.js → graph-edge-decay-MUP5J7CC.js} +6 -6
- package/dist/graph-events.js +1 -1
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.js +2 -2
- package/dist/harmonic-retrieval.js +4 -4
- package/dist/identity-continuity.d.ts +1 -0
- package/dist/importance.d.ts +1 -0
- package/dist/importers/index.d.ts +244 -0
- package/dist/importers/index.js +20 -0
- package/dist/index.d.ts +20 -350
- package/dist/index.js +885 -562
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +1 -0
- package/dist/lcm/archive.d.ts +2 -2
- package/dist/lcm/archive.js +2 -2
- package/dist/lcm/engine.d.ts +3 -2
- package/dist/lcm/engine.js +6 -6
- package/dist/lcm/index.d.ts +1 -0
- package/dist/lcm/index.js +8 -8
- package/dist/lcm/recall.js +1 -1
- package/dist/lcm/summarizer.js +3 -3
- package/dist/lcm/tools.d.ts +1 -0
- package/dist/lifecycle.d.ts +1 -0
- package/dist/live-connectors-runner.d.ts +1 -0
- package/dist/live-connectors-runner.js +6 -6
- package/dist/local-llm.d.ts +1 -0
- package/dist/local-llm.js +2 -2
- package/dist/maintenance/archive-observations.js +1 -1
- package/dist/maintenance/memory-governance.d.ts +3 -1
- package/dist/maintenance/memory-governance.js +10 -8
- package/dist/maintenance/migrate-observations.js +3 -2
- package/dist/maintenance/observation-ledger-utils.d.ts +3 -0
- package/dist/maintenance/observation-ledger-utils.js +2 -1
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -1
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +11 -8
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -1
- package/dist/maintenance/rebuild-memory-projection.js +13 -10
- package/dist/maintenance/rebuild-observations.d.ts +1 -0
- package/dist/maintenance/rebuild-observations.js +3 -2
- package/dist/mcp-memory-inspector-app.d.ts +7 -4
- package/dist/mcp-memory-inspector-app.js +1 -1
- package/dist/memory-action-policy.d.ts +1 -0
- package/dist/memory-cache.d.ts +1 -0
- package/dist/memory-cache.js +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -0
- package/dist/memory-projection-store.d.ts +1 -0
- package/dist/memory-projection-store.js +1 -1
- package/dist/memory-provenance.d.ts +1 -0
- package/dist/memory-worth-outcomes.d.ts +1 -0
- package/dist/migrate/from-engram.js +2 -2
- package/dist/{migrate-from-identity-anchor-G27MCD6A.js → migrate-from-identity-anchor-EB4XI4Q2.js} +2 -2
- package/dist/model-registry.js +1 -1
- package/dist/models-json.d.ts +1 -0
- package/dist/namespaces/migrate.d.ts +3 -0
- package/dist/namespaces/migrate.js +26 -24
- package/dist/namespaces/principal.d.ts +1 -0
- package/dist/namespaces/principal.js +2 -1
- package/dist/namespaces/search.d.ts +2 -1
- package/dist/namespaces/search.js +17 -15
- package/dist/namespaces/storage.d.ts +4 -2
- package/dist/namespaces/storage.js +10 -9
- package/dist/native-knowledge.d.ts +1 -0
- package/dist/native-knowledge.js +1 -1
- package/dist/negative.js +1 -1
- package/dist/network/webdav.d.ts +16 -1
- package/dist/network/webdav.js +5 -3
- package/dist/objective-state-writers.js +4 -4
- package/dist/objective-state.js +2 -2
- package/dist/offline-sync.d.ts +4 -0
- package/dist/offline-sync.js +4 -4
- package/dist/operator-toolkit.d.ts +4 -1
- package/dist/operator-toolkit.js +37 -34
- package/dist/opik-exporter.js +1 -1
- package/dist/{orchestrator-DuWl9Hwx.d.ts → orchestrator-Co9nxRLF.d.ts} +4 -74
- package/dist/orchestrator.d.ts +5 -3
- package/dist/orchestrator.js +101 -98
- package/dist/page-versioning.js +1 -1
- package/dist/path-X2K5XCHL.js +9 -0
- package/dist/patterns-cli.d.ts +1 -0
- package/dist/peers/index.d.ts +328 -0
- package/dist/{peers-HCVGHMAE.js → peers/index.js} +4 -4
- package/dist/pipeline-D18UAKlN.d.ts +32 -0
- package/dist/plugin-entry-resolver.d.ts +9 -0
- package/dist/plugin-entry-resolver.js +8 -0
- package/dist/plugin-entry-resolver.js.map +1 -0
- package/dist/plugin-id.d.ts +2 -21
- package/dist/plugin-id.js +33 -4
- package/dist/plugin-id.js.map +1 -1
- package/dist/policy-runtime.d.ts +4 -0
- package/dist/policy-runtime.js +1 -1
- package/dist/profiling.js +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -0
- package/dist/qmd.d.ts +2 -1
- package/dist/qmd.js +3 -3
- package/dist/recall-disclosure-escalation.d.ts +1 -0
- package/dist/recall-explain-renderer.d.ts +1 -0
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-state.d.ts +8 -1
- package/dist/recall-state.js +2 -1
- package/dist/recall-tag-filter.d.ts +1 -0
- package/dist/recall-xray-cli.d.ts +1 -0
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -0
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -0
- package/dist/recall-xray.js +2 -2
- package/dist/relevance.d.ts +7 -1
- package/dist/relevance.js +2 -1
- package/dist/replay/normalizers/chatgpt.js +2 -2
- package/dist/replay/normalizers/claude.js +2 -2
- package/dist/replay/normalizers/openclaw.js +2 -2
- package/dist/replay/normalizers/shared.js +1 -1
- package/dist/replay/runner.js +1 -1
- package/dist/rerank.js +1 -1
- package/dist/{resolution-B7FNQSSP.js → resolution-ZY7VM6WS.js} +3 -3
- package/dist/resolution-ZY7VM6WS.js.map +1 -0
- package/dist/resolve-auth-token.d.ts +1 -0
- package/dist/resolve-auth-token.js +1 -1
- package/dist/resolve-provider-secret.d.ts +19 -29
- package/dist/resolve-provider-secret.js +2 -6
- package/dist/resume-bundles.js +10 -9
- package/dist/retrieval-agents.d.ts +2 -1
- package/dist/retrieval-agents.js +2 -1
- package/dist/retrieval-tiers.d.ts +1 -0
- package/dist/routing/engine.d.ts +1 -0
- package/dist/routing/store.d.ts +3 -0
- package/dist/routing/store.js +1 -1
- package/dist/runtime/env.js +1 -1
- package/dist/schemas.d.ts +191 -17
- package/dist/schemas.js +1 -1
- package/dist/sdk-compat.js +1 -1
- package/dist/search/document-scanner.js +1 -1
- package/dist/search/embed-helper.d.ts +7 -2
- package/dist/search/embed-helper.js +3 -1
- package/dist/search/factory.d.ts +2 -1
- package/dist/search/factory.js +15 -14
- package/dist/search/index.d.ts +2 -1
- package/dist/search/index.js +21 -20
- package/dist/search/lancedb-backend.d.ts +8 -7
- package/dist/search/lancedb-backend.js +4 -2
- package/dist/search/meilisearch-backend.d.ts +8 -7
- package/dist/search/meilisearch-backend.js +4 -2
- package/dist/search/noop-backend.d.ts +2 -1
- package/dist/search/noop-backend.js +1 -1
- package/dist/search/orama-backend.d.ts +10 -8
- package/dist/search/orama-backend.js +8 -4
- package/dist/search/port.d.ts +2 -1
- package/dist/search/remote-backend.d.ts +2 -1
- package/dist/search/remote-backend.js +1 -1
- package/dist/secure-store/index.d.ts +16 -3
- package/dist/secure-store/index.js +2 -2
- package/dist/{semantic-VwGI14Ok.d.ts → semantic-SLAa_prH.d.ts} +5 -3
- package/dist/semantic-consolidation.d.ts +1 -0
- package/dist/semantic-consolidation.js +14 -13
- package/dist/semantic-rule-promotion.js +8 -8
- package/dist/semantic-rule-verifier.d.ts +1 -0
- package/dist/semantic-rule-verifier.js +8 -8
- package/dist/session-integrity.d.ts +1 -0
- package/dist/session-integrity.js +1 -1
- package/dist/session-observer-bands.d.ts +1 -0
- package/dist/session-observer-state.d.ts +6 -1
- package/dist/session-observer-state.js +1 -1
- package/dist/shared-context/manager.d.ts +5 -0
- package/dist/shared-context/manager.js +3 -3
- package/dist/signal.d.ts +1 -0
- package/dist/signal.js +1 -1
- package/dist/source-attribution.js +1 -1
- package/dist/state-store-4QZISH3J.js +30 -0
- package/dist/state-store-4QZISH3J.js.map +1 -0
- package/dist/storage-C4DX8CuG.d.ts +157 -0
- package/dist/storage.d.ts +2 -0
- package/dist/storage.js +7 -7
- package/dist/store-contract.js +1 -1
- package/dist/summarizer.d.ts +1 -0
- package/dist/summarizer.js +7 -7
- package/dist/summary-snapshot.d.ts +1 -0
- package/dist/surfaces/dreams.js +48 -17
- package/dist/surfaces/dreams.js.map +1 -1
- package/dist/temporal-supersession.d.ts +1 -0
- package/dist/temporal-supersession.js +1 -1
- package/dist/temporal-validity.d.ts +1 -0
- package/dist/threading.d.ts +1 -0
- package/dist/tier-migration.d.ts +1 -0
- package/dist/tier-routing.d.ts +1 -0
- package/dist/{tier-stats-62ZVDFKS.js → tier-stats-SKML2OSF.js} +5 -5
- package/dist/tmt.js +1 -1
- package/dist/tokens.js +2 -2
- package/dist/topics.d.ts +1 -0
- package/dist/{trace-C5ETWBEF.js → trace-WM7V4CKI.js} +31 -1
- package/dist/trace-WM7V4CKI.js.map +1 -0
- package/dist/transcript.d.ts +1 -0
- package/dist/transcript.js +2 -2
- package/dist/transfer/autodetect.js +7 -7
- package/dist/transfer/backup.js +5 -5
- package/dist/transfer/capsule-export.js +5 -5
- package/dist/transfer/capsule-import.d.ts +6 -0
- package/dist/transfer/capsule-import.js +4 -4
- package/dist/transfer/export-json.js +3 -3
- package/dist/transfer/export-md.js +3 -3
- package/dist/transfer/export-sqlite.js +3 -3
- package/dist/transfer/fs-utils.d.ts +2 -1
- package/dist/transfer/fs-utils.js +5 -3
- package/dist/transfer/import-json.js +3 -3
- package/dist/transfer/import-md.js +3 -3
- package/dist/transfer/import-sqlite.js +3 -3
- package/dist/trust-zones.js +2 -2
- package/dist/types-B1VHaf2w.d.ts +126 -0
- package/dist/types-BliCnURB.d.ts +83 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.js +1 -1
- package/dist/utility-learner.js +3 -3
- package/dist/utility-runtime.d.ts +1 -0
- package/dist/utility-runtime.js +4 -4
- package/dist/utility-telemetry.js +2 -2
- package/dist/verified-recall.js +9 -9
- package/dist/work/board.js +2 -2
- package/dist/work/boundary.js +1 -1
- package/dist/work/storage.d.ts +5 -0
- package/dist/work/storage.js +1 -1
- package/dist/work-product-ledger.js +2 -2
- package/package.json +74 -3
- package/scripts/ensure-better-sqlite3.mjs +8 -7
- package/scripts/faiss_index.py +141 -29
- package/src/access-cli.test.ts +87 -2
- package/src/access-cli.ts +59 -5
- package/src/access-http.test.ts +150 -0
- package/src/access-http.ts +103 -34
- package/src/access-idempotency.ts +136 -3
- package/src/access-mcp.test.ts +155 -0
- package/src/access-mcp.ts +116 -30
- package/src/access-schema.ts +22 -4
- package/src/access-service-namespace.test.ts +9 -9
- package/src/access-service-project-tag.test.ts +37 -0
- package/src/access-service.ts +15 -14
- package/src/active-recall.test.ts +29 -1
- package/src/active-recall.ts +11 -7
- package/src/adapters/claude-code.ts +7 -8
- package/src/adapters/codex.ts +6 -7
- package/src/adapters/hermes.ts +1 -5
- package/src/adapters/registry.test.ts +63 -0
- package/src/adapters/registry.ts +10 -0
- package/src/adapters/replit.ts +5 -7
- package/src/adapters/types.ts +24 -1
- package/src/behavior-signals.ts +1 -1
- package/src/binary-lifecycle/backend.ts +16 -4
- package/src/binary-lifecycle/pipeline.test.ts +149 -0
- package/src/binary-lifecycle/pipeline.ts +49 -7
- package/src/binary-lifecycle/scanner.ts +19 -4
- package/src/boxes.ts +119 -32
- package/src/buffer-session.test.ts +28 -0
- package/src/buffer.ts +10 -14
- package/src/bulk-import/types.ts +10 -0
- package/src/calibration.test.ts +99 -0
- package/src/calibration.ts +57 -13
- package/src/causal-consolidation.test.ts +214 -0
- package/src/causal-consolidation.ts +131 -14
- package/src/causal-retrieval.ts +16 -3
- package/src/citations.test.ts +75 -0
- package/src/citations.ts +19 -6
- package/src/cli.ts +134 -109
- package/src/coding/coding-namespace.test.ts +7 -0
- package/src/coding/coding-namespace.ts +8 -0
- package/src/coding/review-context.test.ts +30 -0
- package/src/coding/review-context.ts +79 -9
- package/src/coding/wire-coding-context.test.ts +16 -0
- package/src/compat/checks.test.ts +33 -0
- package/src/compat/checks.ts +64 -4
- package/src/compounding/engine.ts +2 -2
- package/src/compounding/preference-consolidator.test.ts +47 -0
- package/src/compounding/preference-consolidator.ts +8 -8
- package/src/compression-optimizer.ts +5 -2
- package/src/config.test.ts +34 -2
- package/src/config.ts +62 -18
- package/src/connectors/codex-materialize-runner.ts +4 -3
- package/src/connectors/codex-materialize.ts +149 -34
- package/src/connectors/index.test.ts +144 -7
- package/src/connectors/index.ts +86 -15
- package/src/connectors/live/github.test.ts +47 -0
- package/src/connectors/live/github.ts +29 -1
- package/src/connectors/live/index.ts +2 -0
- package/src/connectors/live/live-connectors.test.ts +359 -73
- package/src/connectors/live/notion.test.ts +84 -0
- package/src/connectors/live/notion.ts +18 -1
- package/src/connectors/live/state-store.ts +419 -38
- package/src/connectors/weclone-installer.test.ts +16 -18
- package/src/connectors-cli.ts +19 -0
- package/src/console/trace.test.ts +28 -0
- package/src/console/trace.ts +42 -5
- package/src/contradiction/contradiction-judge.test.ts +49 -0
- package/src/contradiction/contradiction-judge.ts +15 -5
- package/src/contradiction/contradiction-review.ts +31 -7
- package/src/contradiction/contradiction-scan.ts +28 -18
- package/src/contradiction/contradiction.test.ts +237 -1
- package/src/contradiction/resolution.ts +43 -4
- package/src/conversation-index/backend.ts +13 -5
- package/src/conversation-index/cleanup.ts +25 -4
- package/src/conversation-index/faiss-adapter.ts +24 -15
- package/src/conversation-index/indexer.test.ts +71 -10
- package/src/conversation-index/indexer.ts +22 -3
- package/src/cross-namespace-budget.test.ts +59 -0
- package/src/cross-namespace-budget.ts +15 -7
- package/src/curation/index.ts +18 -17
- package/src/dashboard-runtime.test.ts +98 -0
- package/src/dashboard-runtime.ts +96 -6
- package/src/dedup/index.test.ts +133 -0
- package/src/dedup/index.ts +73 -10
- package/src/dedup/semantic.test.ts +77 -2
- package/src/dedup/semantic.ts +26 -6
- package/src/embedding-fallback.ts +47 -15
- package/src/enrichment/audit.ts +8 -1
- package/src/enrichment/pipeline.ts +21 -13
- package/src/enrichment/web-search-provider.ts +1 -6
- package/src/entity-retrieval.ts +57 -6
- package/src/evals.ts +22 -13
- package/src/explicit-capture.test.ts +40 -0
- package/src/explicit-capture.ts +14 -2
- package/src/extraction.ts +42 -30
- package/src/fallback-llm.ts +35 -2
- package/src/graph-dashboard-diff.test.ts +57 -0
- package/src/graph-dashboard-diff.ts +24 -2
- package/src/graph-dashboard-parser.test.ts +31 -0
- package/src/graph-dashboard-parser.ts +4 -1
- package/src/graph-events.ts +6 -4
- package/src/graph.test.ts +69 -0
- package/src/graph.ts +7 -4
- package/src/importers/base.test.ts +70 -0
- package/src/importers/base.ts +56 -7
- package/src/index.ts +5 -2
- package/src/lcm/archive.ts +65 -16
- package/src/lcm/engine.ts +27 -8
- package/src/lcm/recall.ts +5 -5
- package/src/lcm-engine.test.ts +87 -1
- package/src/lcm-recall.test.ts +71 -0
- package/src/live-connectors-runner.ts +100 -36
- package/src/maintenance/archive-observations.ts +24 -3
- package/src/maintenance/atomic-file.ts +85 -0
- package/src/maintenance/dreams-ledger.ts +15 -8
- package/src/maintenance/memory-governance.test.ts +53 -0
- package/src/maintenance/memory-governance.ts +15 -5
- package/src/maintenance/observation-ledger-utils.ts +6 -5
- package/src/maintenance/purge.test.ts +64 -0
- package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +22 -9
- package/src/maintenance/rebuild-memory-projection.ts +22 -9
- package/src/maintenance/rebuild-observations.ts +7 -3
- package/src/mcp-memory-inspector-app.ts +26 -3
- package/src/memory-cache.test.ts +19 -0
- package/src/memory-cache.ts +1 -0
- package/src/memory-extension/codex-publisher.ts +25 -4
- package/src/memory-extension-host/host-discovery.test.ts +69 -0
- package/src/memory-extension-host/host-discovery.ts +63 -6
- package/src/memory-projection-store.ts +114 -62
- package/src/message-parts/index.ts +46 -31
- package/src/message-parts/message-parts.test.ts +77 -0
- package/src/migrate/from-engram.ts +68 -14
- package/src/model-registry.test.ts +38 -0
- package/src/model-registry.ts +12 -7
- package/src/namespaces/identity.test.ts +66 -0
- package/src/namespaces/identity.ts +23 -0
- package/src/namespaces/migrate.test.ts +62 -0
- package/src/namespaces/migrate.ts +82 -14
- package/src/namespaces/principal.test.ts +37 -1
- package/src/namespaces/principal.ts +18 -7
- package/src/namespaces/search.test.ts +96 -7
- package/src/namespaces/search.ts +32 -25
- package/src/namespaces/storage.ts +93 -11
- package/src/native-knowledge.ts +23 -3
- package/src/negative.ts +50 -5
- package/src/network/webdav.ts +177 -58
- package/src/offline-sync.test.ts +128 -18
- package/src/offline-sync.ts +41 -7
- package/src/onboarding/index.test.ts +105 -0
- package/src/onboarding/index.ts +17 -5
- package/src/operator-toolkit.ts +43 -5
- package/src/orchestrator.ts +120 -27
- package/src/page-versioning.ts +31 -5
- package/src/peers/peers.test.ts +70 -0
- package/src/peers/storage.ts +32 -3
- package/src/plugin-entry-resolver.test.ts +60 -0
- package/src/plugin-entry-resolver.ts +48 -0
- package/src/plugin-id.test.ts +38 -0
- package/src/plugin-id.ts +31 -64
- package/src/policy-runtime.test.ts +75 -0
- package/src/policy-runtime.ts +32 -3
- package/src/procedural/procedure-miner.test.ts +152 -0
- package/src/procedural/procedure-miner.ts +124 -19
- package/src/profiling.test.ts +23 -0
- package/src/profiling.ts +10 -1
- package/src/projection/index.test.ts +253 -0
- package/src/projection/index.ts +159 -18
- package/src/qmd-client.test.ts +45 -0
- package/src/qmd.ts +13 -10
- package/src/recall-disclosure.test.ts +15 -1
- package/src/recall-state.ts +24 -5
- package/src/relevance.ts +24 -5
- package/src/replay/normalizers/chatgpt.ts +14 -4
- package/src/replay/normalizers/claude.ts +8 -3
- package/src/replay/normalizers/openclaw.ts +35 -12
- package/src/replay/normalizers/replay-normalizers.test.ts +65 -0
- package/src/replay/normalizers/shared.ts +4 -1
- package/src/replay/runner.ts +1 -1
- package/src/rerank.test.ts +41 -1
- package/src/rerank.ts +2 -2
- package/src/resolve-auth-token.test.ts +29 -0
- package/src/resolve-auth-token.ts +12 -7
- package/src/resolve-provider-secret.test.ts +78 -22
- package/src/resolve-provider-secret.ts +55 -223
- package/src/retrieval-agents.ts +51 -14
- package/src/review/index.test.ts +75 -1
- package/src/review/index.ts +88 -30
- package/src/routing/store.ts +36 -6
- package/src/runtime/env.test.ts +73 -0
- package/src/runtime/env.ts +7 -11
- package/src/schemas.ts +16 -1
- package/src/search/abort.ts +18 -0
- package/src/search/document-scanner.test.ts +80 -0
- package/src/search/document-scanner.ts +51 -9
- package/src/search/embed-helper.ts +19 -6
- package/src/search/factory.ts +9 -5
- package/src/search/lancedb-backend.ts +66 -23
- package/src/search/meilisearch-backend.ts +39 -13
- package/src/search/noop-backend.ts +1 -1
- package/src/search/orama-backend.test.ts +27 -0
- package/src/search/orama-backend.ts +69 -16
- package/src/search/port.ts +4 -1
- package/src/search/remote-backend.ts +1 -1
- package/src/secure-store/cli-handlers.ts +70 -6
- package/src/secure-store/cli-renderer.ts +13 -7
- package/src/secure-store/secure-fs.ts +11 -5
- package/src/secure-store/secure-store.test.ts +70 -0
- package/src/semantic-consolidation.test.ts +45 -0
- package/src/semantic-consolidation.ts +3 -3
- package/src/session-integrity.test.ts +98 -0
- package/src/session-integrity.ts +51 -1
- package/src/session-observer-state.ts +108 -41
- package/src/shared-context/manager.ts +93 -15
- package/src/signal.test.ts +14 -0
- package/src/signal.ts +8 -1
- package/src/source-attribution.test.ts +8 -0
- package/src/source-attribution.ts +24 -2
- package/src/spaces/index.test.ts +93 -0
- package/src/spaces/index.ts +75 -9
- package/src/storage.ts +14 -1
- package/src/store-contract.test.ts +35 -0
- package/src/store-contract.ts +39 -5
- package/src/summarizer.ts +24 -18
- package/src/summary-snapshot.test.ts +77 -0
- package/src/surfaces/dreams.test.ts +73 -0
- package/src/surfaces/dreams.ts +53 -19
- package/src/sync/index.ts +42 -17
- package/src/taxonomy/taxonomy-loader.ts +43 -4
- package/src/temporal-supersession.test.ts +67 -0
- package/src/temporal-supersession.ts +8 -0
- package/src/tmt.test.ts +50 -0
- package/src/tmt.ts +35 -11
- package/src/tokens.test.ts +18 -0
- package/src/tokens.ts +7 -0
- package/src/training-export/converter.test.ts +55 -2
- package/src/training-export/converter.ts +36 -10
- package/src/training-export/registry.test.ts +17 -0
- package/src/training-export/registry.ts +19 -1
- package/src/transcript.ts +2 -2
- package/src/transfer/backup.ts +18 -7
- package/src/transfer/capsule-crypto.ts +105 -21
- package/src/transfer/capsule-encrypt.test.ts +106 -7
- package/src/transfer/capsule-export.ts +23 -14
- package/src/transfer/capsule-import.ts +11 -2
- package/src/transfer/exclusions.ts +7 -0
- package/src/transfer/export-sqlite.ts +14 -13
- package/src/transfer/fs-utils.ts +52 -1
- package/src/transfer/import-json.ts +12 -7
- package/src/transfer/import-md.ts +5 -5
- package/src/transfer/import-sqlite.ts +4 -5
- package/src/trust-zones.ts +1 -1
- package/src/types.ts +25 -0
- package/src/utility-telemetry.ts +1 -1
- package/src/utils/category-dir.test.ts +15 -0
- package/src/utils/category-dir.ts +3 -1
- package/src/work/boundary.ts +30 -18
- package/src/work/storage.ts +116 -38
- package/src/work-product-ledger.ts +1 -1
- package/dist/chunk-25MQ7IHJ.js.map +0 -1
- package/dist/chunk-2IWUMAES.js.map +0 -1
- package/dist/chunk-2NMMFZ5T.js.map +0 -1
- package/dist/chunk-2PRLKQAH.js.map +0 -1
- package/dist/chunk-326G7DJK.js.map +0 -1
- package/dist/chunk-3APJ5EVB.js.map +0 -1
- package/dist/chunk-3KW65B36.js.map +0 -1
- package/dist/chunk-3QKK7QOS.js.map +0 -1
- package/dist/chunk-3SLRNYNG.js.map +0 -1
- package/dist/chunk-3VAL7ZL2.js.map +0 -1
- package/dist/chunk-3Y4P7RXM.js.map +0 -1
- package/dist/chunk-3ZLVGM76.js.map +0 -1
- package/dist/chunk-43PJZYGL.js.map +0 -1
- package/dist/chunk-47VWKCAF.js.map +0 -1
- package/dist/chunk-4KGVTPGD.js.map +0 -1
- package/dist/chunk-5375UYTQ.js.map +0 -1
- package/dist/chunk-56K5QLHX.js.map +0 -1
- package/dist/chunk-575RMLWN.js.map +0 -1
- package/dist/chunk-5NPGSAVB.js.map +0 -1
- package/dist/chunk-5RGLBDQF.js.map +0 -1
- package/dist/chunk-65PG43EQ.js.map +0 -1
- package/dist/chunk-66DHUKLO.js.map +0 -1
- package/dist/chunk-6LVVDPJ4.js.map +0 -1
- package/dist/chunk-76FLAAUC.js.map +0 -1
- package/dist/chunk-77H5NU3M.js.map +0 -1
- package/dist/chunk-7MNMYOFP.js.map +0 -1
- package/dist/chunk-7OZ53EXP.js.map +0 -1
- package/dist/chunk-7SEAZFFB.js.map +0 -1
- package/dist/chunk-A6KTB5R6.js.map +0 -1
- package/dist/chunk-AGZQD76C.js.map +0 -1
- package/dist/chunk-APO3DCMU.js.map +0 -1
- package/dist/chunk-BVF3AGJP.js.map +0 -1
- package/dist/chunk-C5BCH4ZS.js.map +0 -1
- package/dist/chunk-C7VW7C3F.js.map +0 -1
- package/dist/chunk-CULXMQJH.js.map +0 -1
- package/dist/chunk-CYFQJMUV.js.map +0 -1
- package/dist/chunk-D654IBA6.js +0 -61
- package/dist/chunk-D654IBA6.js.map +0 -1
- package/dist/chunk-DGXUHMOV.js.map +0 -1
- package/dist/chunk-DINWEURR.js.map +0 -1
- package/dist/chunk-DK5LDEQM.js.map +0 -1
- package/dist/chunk-EABGC2TL.js.map +0 -1
- package/dist/chunk-EHRTFRWW.js.map +0 -1
- package/dist/chunk-EJI5XIBB.js.map +0 -1
- package/dist/chunk-FAAFWE4G.js.map +0 -1
- package/dist/chunk-FAJ7FZYM.js +0 -11
- package/dist/chunk-FAJ7FZYM.js.map +0 -1
- package/dist/chunk-FDU6HUUL.js +0 -147
- package/dist/chunk-FDU6HUUL.js.map +0 -1
- package/dist/chunk-FIT6DMX6.js.map +0 -1
- package/dist/chunk-FJ43PRLT.js.map +0 -1
- package/dist/chunk-FLTNHQK6.js +0 -262
- package/dist/chunk-FLTNHQK6.js.map +0 -1
- package/dist/chunk-GDFS42HT.js.map +0 -1
- package/dist/chunk-H3ME6L6D.js.map +0 -1
- package/dist/chunk-HXXBL2KD.js.map +0 -1
- package/dist/chunk-ICRIXAP2.js.map +0 -1
- package/dist/chunk-IQT3XTKW.js.map +0 -1
- package/dist/chunk-JR4ZC3G4.js.map +0 -1
- package/dist/chunk-K4FLSOR5.js.map +0 -1
- package/dist/chunk-KNKUID7G.js.map +0 -1
- package/dist/chunk-KOSORCJG.js.map +0 -1
- package/dist/chunk-LIRZNNUP.js.map +0 -1
- package/dist/chunk-LLQ2LLWF.js.map +0 -1
- package/dist/chunk-LPMVBPA3.js +0 -236
- package/dist/chunk-LPMVBPA3.js.map +0 -1
- package/dist/chunk-LT3NLYSI.js.map +0 -1
- package/dist/chunk-LUDTDZLK.js.map +0 -1
- package/dist/chunk-MJFNCJXV.js.map +0 -1
- package/dist/chunk-MSWG7JI6.js.map +0 -1
- package/dist/chunk-MXC3AP5I.js.map +0 -1
- package/dist/chunk-MXFBBHJU.js.map +0 -1
- package/dist/chunk-MZH6EHNR.js.map +0 -1
- package/dist/chunk-N2D6GXBM.js.map +0 -1
- package/dist/chunk-NBNN5GOB.js.map +0 -1
- package/dist/chunk-NMZY542O.js.map +0 -1
- package/dist/chunk-NZL6GGQE.js.map +0 -1
- package/dist/chunk-OZHRDTDX.js.map +0 -1
- package/dist/chunk-PIRJPV5T.js.map +0 -1
- package/dist/chunk-PZIAX57I.js.map +0 -1
- package/dist/chunk-Q7P4WJDP.js.map +0 -1
- package/dist/chunk-QA2ZAPBU.js.map +0 -1
- package/dist/chunk-QDZ2RLEC.js.map +0 -1
- package/dist/chunk-QLLBRHAT.js.map +0 -1
- package/dist/chunk-QR3C7BKQ.js.map +0 -1
- package/dist/chunk-RHY3HH7P.js.map +0 -1
- package/dist/chunk-RK2Y4XOM.js.map +0 -1
- package/dist/chunk-RR2PKP3I.js +0 -63
- package/dist/chunk-RR2PKP3I.js.map +0 -1
- package/dist/chunk-RRF5UOBJ.js.map +0 -1
- package/dist/chunk-RXDLTSWT.js.map +0 -1
- package/dist/chunk-RYED3SPJ.js +0 -42
- package/dist/chunk-RYED3SPJ.js.map +0 -1
- package/dist/chunk-S7KDBTWT.js.map +0 -1
- package/dist/chunk-TK4UEOSK.js.map +0 -1
- package/dist/chunk-TMM4S4IJ.js.map +0 -1
- package/dist/chunk-TMQLARTH.js.map +0 -1
- package/dist/chunk-TPB3I2AC.js.map +0 -1
- package/dist/chunk-TPMQ3G6Z.js.map +0 -1
- package/dist/chunk-TPU5L5EY.js.map +0 -1
- package/dist/chunk-TZOLIGIG.js.map +0 -1
- package/dist/chunk-U3WSW6PZ.js.map +0 -1
- package/dist/chunk-U4SCL7B7.js.map +0 -1
- package/dist/chunk-U66YHYC7.js +0 -31
- package/dist/chunk-U66YHYC7.js.map +0 -1
- package/dist/chunk-U7EJOMFC.js.map +0 -1
- package/dist/chunk-UWVJF25J.js.map +0 -1
- package/dist/chunk-VBJ7V5SK.js.map +0 -1
- package/dist/chunk-W3LR522O.js.map +0 -1
- package/dist/chunk-W4L6CZKA.js.map +0 -1
- package/dist/chunk-W6AQJ2PY.js.map +0 -1
- package/dist/chunk-WELDCG6C.js.map +0 -1
- package/dist/chunk-WNARATI3.js.map +0 -1
- package/dist/chunk-WPGJYVUH.js.map +0 -1
- package/dist/chunk-WW3QQF4H.js.map +0 -1
- package/dist/chunk-XIG5PDM7.js.map +0 -1
- package/dist/chunk-XKECPATV.js.map +0 -1
- package/dist/chunk-XKLD5OK4.js.map +0 -1
- package/dist/chunk-XSZEP4SF.js.map +0 -1
- package/dist/chunk-XVVIG67A.js.map +0 -1
- package/dist/chunk-XYIK4LF6.js.map +0 -1
- package/dist/chunk-YRMVARQP.js.map +0 -1
- package/dist/chunk-YROHKYBY.js.map +0 -1
- package/dist/chunk-YU5KIWYQ.js.map +0 -1
- package/dist/chunk-ZAVUCJ4H.js.map +0 -1
- package/dist/chunk-ZPKBYX2F.js.map +0 -1
- package/dist/chunk-ZTFCYYEZ.js.map +0 -1
- package/dist/chunk-ZYVPLJ4T.js.map +0 -1
- package/dist/path-MR5JPYOP.js +0 -9
- package/dist/state-store-VZU2IA53.js +0 -16
- package/dist/trace-C5ETWBEF.js.map +0 -1
- /package/dist/{capsule-crypto-5CYAGVC5.js.map → bulk-import/index.js.map} +0 -0
- /package/dist/{contradiction-review-ATP4S6IC.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
- /package/dist/{capsule-merge-4MGKE7C5.js.map → capsule-merge-T2JRE46P.js.map} +0 -0
- /package/dist/{chunk-SAZS2QZB.js.map → chunk-23UORJ4S.js.map} +0 -0
- /package/dist/{chunk-PK7H5L6Y.js.map → chunk-2NM43EWN.js.map} +0 -0
- /package/dist/{chunk-PYXS46O7.js.map → chunk-3BP57I6J.js.map} +0 -0
- /package/dist/{chunk-FBYESMQ2.js.map → chunk-3C5RPJAX.js.map} +0 -0
- /package/dist/{chunk-N53K2EXC.js.map → chunk-6VF75M3X.js.map} +0 -0
- /package/dist/{chunk-6H2TESSP.js.map → chunk-765K3SAT.js.map} +0 -0
- /package/dist/{chunk-EDTHC6UD.js.map → chunk-77NAFXUD.js.map} +0 -0
- /package/dist/{chunk-MGKYQQYF.js.map → chunk-7Q3RCKAQ.js.map} +0 -0
- /package/dist/{chunk-34DQE4KF.js.map → chunk-CO7ZO4TU.js.map} +0 -0
- /package/dist/{chunk-ZKSK55RC.js.map → chunk-ETUPBUHB.js.map} +0 -0
- /package/dist/{chunk-QRNI5JBH.js.map → chunk-EYIEWJNI.js.map} +0 -0
- /package/dist/{chunk-C6QPK5GG.js.map → chunk-FZZ2QTJI.js.map} +0 -0
- /package/dist/{chunk-3JXBXXM2.js.map → chunk-G4IAEX6D.js.map} +0 -0
- /package/dist/{chunk-2WWLHTZY.js.map → chunk-IC4GELZE.js.map} +0 -0
- /package/dist/{chunk-PCUKNJAZ.js.map → chunk-JKV57BTN.js.map} +0 -0
- /package/dist/{chunk-2KI4QFHU.js.map → chunk-LMDRGRJ2.js.map} +0 -0
- /package/dist/{chunk-MY6TPVXW.js.map → chunk-LMPHTYJC.js.map} +0 -0
- /package/dist/{chunk-5HRY2WRF.js.map → chunk-LZ3VEOU5.js.map} +0 -0
- /package/dist/{chunk-NGAVDO7E.js.map → chunk-OADWQ5CR.js.map} +0 -0
- /package/dist/{chunk-DOM4GKSW.js.map → chunk-OZKVVUJB.js.map} +0 -0
- /package/dist/{chunk-MT4HVDUZ.js.map → chunk-PM3QHTFT.js.map} +0 -0
- /package/dist/{chunk-ZK7I7JYV.js.map → chunk-R3PS27B4.js.map} +0 -0
- /package/dist/{chunk-SKE7JYKA.js.map → chunk-SFXKHM7P.js.map} +0 -0
- /package/dist/{chunk-HMDCOMYU.js.map → chunk-SKGV326D.js.map} +0 -0
- /package/dist/{chunk-5UM2VJ6D.js.map → chunk-UEY3VB6W.js.map} +0 -0
- /package/dist/{chunk-GIF42EW3.js.map → chunk-UP6MOYCB.js.map} +0 -0
- /package/dist/{chunk-MRILGULB.js.map → chunk-V2RCP53Q.js.map} +0 -0
- /package/dist/{chunk-FSFEQI74.js.map → chunk-W7L6HXUC.js.map} +0 -0
- /package/dist/{chunk-3IQ2TR4N.js.map → chunk-WLEB7WCG.js.map} +0 -0
- /package/dist/{chunk-GL6I6MEQ.js.map → chunk-WSGF57U2.js.map} +0 -0
- /package/dist/{chunk-JA3AK3PT.js.map → chunk-XNLXAWHX.js.map} +0 -0
- /package/dist/{chunk-SIC6U3GZ.js.map → chunk-YHV3KRKS.js.map} +0 -0
- /package/dist/{chunk-VLXA6PI2.js.map → chunk-YQMZ7IH2.js.map} +0 -0
- /package/dist/{contradiction-scan-5A4IDZV5.js.map → contradiction-review-6V2LXXK6.js.map} +0 -0
- /package/dist/{migrate-from-identity-anchor-G27MCD6A.js.map → contradiction-scan-GIRVC4C7.js.map} +0 -0
- /package/dist/{first-start-migration-4MHQEOSD.js.map → first-start-migration-CKTCTCQI.js.map} +0 -0
- /package/dist/{graph-edge-decay-5DI5GUNL.js.map → graph-edge-decay-MUP5J7CC.js.map} +0 -0
- /package/dist/{path-MR5JPYOP.js.map → importers/index.js.map} +0 -0
- /package/dist/{peers-HCVGHMAE.js.map → migrate-from-identity-anchor-EB4XI4Q2.js.map} +0 -0
- /package/dist/{resolution-B7FNQSSP.js.map → path-X2K5XCHL.js.map} +0 -0
- /package/dist/{state-store-VZU2IA53.js.map → peers/index.js.map} +0 -0
- /package/dist/{tier-stats-62ZVDFKS.js.map → tier-stats-SKML2OSF.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isRecallDisclosure
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-M5T4Q2ZU.js";
|
|
4
4
|
import {
|
|
5
5
|
normalizeRetrievedMemoryProvenance
|
|
6
6
|
} from "./chunk-AC5LO7IU.js";
|
|
@@ -269,4 +269,4 @@ export {
|
|
|
269
269
|
RecallXrayBuilder,
|
|
270
270
|
summarizeDisclosureTokens
|
|
271
271
|
};
|
|
272
|
-
//# sourceMappingURL=chunk-
|
|
272
|
+
//# sourceMappingURL=chunk-7Q3RCKAQ.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/adapters/types.ts
|
|
2
|
+
function headerValue(headers, key) {
|
|
3
|
+
const exactValue = normalizeHeaderValue(headers[key]);
|
|
4
|
+
if (exactValue !== void 0) {
|
|
5
|
+
return exactValue;
|
|
6
|
+
}
|
|
7
|
+
const normalizedKey = key.toLowerCase();
|
|
8
|
+
for (const [headerKey, raw] of Object.entries(headers)) {
|
|
9
|
+
if (headerKey.toLowerCase() !== normalizedKey) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const value = normalizeHeaderValue(raw);
|
|
13
|
+
if (value !== void 0) {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return void 0;
|
|
18
|
+
}
|
|
19
|
+
function normalizeHeaderValue(raw) {
|
|
20
|
+
const value = Array.isArray(raw) ? raw[0] : raw;
|
|
21
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
headerValue
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=chunk-7RXCMVFQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/types.ts"],"sourcesContent":["/**\n * Adapter interface for external system identity resolution.\n *\n * Each adapter maps an external system's session/identity conventions\n * to Engram's namespace + principal model. Adapters are stateless and\n * lightweight — they don't manage lifecycles or load plugins.\n */\n\nexport interface AdapterContext {\n /** Raw HTTP headers from the incoming request */\n headers: Record<string, string | string[] | undefined>;\n /** MCP client info (from initialize handshake, if available) */\n clientInfo?: { name: string; version?: string };\n /** Explicit session key from request args */\n sessionKey?: string;\n /** Explicit namespace from already-validated request args */\n namespace?: string;\n /** Explicit principal from already-validated request args */\n principal?: string;\n}\n\nexport interface ResolvedIdentity {\n /** Engram namespace (scopes memory access) */\n namespace: string;\n /** Engram principal (authorization subject) */\n principal: string;\n /** Session key for continuity tracking */\n sessionKey?: string;\n /** Which adapter resolved this identity */\n adapterId: string;\n}\n\nexport interface EngramAdapter {\n /** Adapter identifier (e.g., \"claude-code\", \"codex\", \"hermes\", \"replit\") */\n readonly id: string;\n\n /** Whether this adapter recognizes the given request context */\n matches(context: AdapterContext): boolean;\n\n /** Map external session/identity to Engram namespace + principal */\n resolveIdentity(context: AdapterContext): ResolvedIdentity;\n}\n\n/**\n * Extract and trim a single header value from a headers record.\n * Returns undefined if the header is missing, empty, or all whitespace.\n */\nexport function headerValue(\n headers: Record<string, string | string[] | undefined>,\n key: string,\n): string | undefined {\n const exactValue = normalizeHeaderValue(headers[key]);\n if (exactValue !== undefined) {\n return exactValue;\n }\n\n const normalizedKey = key.toLowerCase();\n for (const [headerKey, raw] of Object.entries(headers)) {\n if (headerKey.toLowerCase() !== normalizedKey) {\n continue;\n }\n const value = normalizeHeaderValue(raw);\n if (value !== undefined) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction normalizeHeaderValue(raw: string | string[] | undefined): string | undefined {\n const value = Array.isArray(raw) ? raw[0] : raw;\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n"],"mappings":";AA+CO,SAAS,YACd,SACA,KACoB;AACpB,QAAM,aAAa,qBAAqB,QAAQ,GAAG,CAAC;AACpD,MAAI,eAAe,QAAW;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,IAAI,YAAY;AACtC,aAAW,CAAC,WAAW,GAAG,KAAK,OAAO,QAAQ,OAAO,GAAG;AACtD,QAAI,UAAU,YAAY,MAAM,eAAe;AAC7C;AAAA,IACF;AACA,UAAM,QAAQ,qBAAqB,GAAG;AACtC,QAAI,UAAU,QAAW;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,qBAAqB,KAAwD;AACpF,QAAM,QAAQ,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI;AAC5C,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,IAAI,MAAM,KAAK,IAAI;AAC/E;","names":[]}
|
|
@@ -19,17 +19,36 @@ function assertSafePathSegment(value, field) {
|
|
|
19
19
|
return value;
|
|
20
20
|
}
|
|
21
21
|
function assertIsoRecordedAt(value, field = "recordedAt") {
|
|
22
|
-
|
|
22
|
+
const parsed = parseIsoRecordedAt(value);
|
|
23
|
+
if (!parsed) {
|
|
23
24
|
throw new Error(`${field} must be an ISO timestamp`);
|
|
24
25
|
}
|
|
25
26
|
return value;
|
|
26
27
|
}
|
|
27
28
|
function recordStoreDay(recordedAt) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
assertIsoRecordedAt(recordedAt);
|
|
30
|
+
return recordedAt.slice(0, 10);
|
|
31
|
+
}
|
|
32
|
+
var ISO_RECORDED_AT_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
33
|
+
function parseIsoRecordedAt(value) {
|
|
34
|
+
const match = value.match(ISO_RECORDED_AT_RE);
|
|
35
|
+
if (!match) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const year = Number(match[1]);
|
|
39
|
+
const month = Number(match[2]);
|
|
40
|
+
const day = Number(match[3]);
|
|
41
|
+
const hour = Number(match[4]);
|
|
42
|
+
const minute = Number(match[5]);
|
|
43
|
+
const second = Number(match[6]);
|
|
44
|
+
if (!Number.isInteger(year) || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
const calendarDate = new Date(Date.UTC(year, month - 1, day));
|
|
48
|
+
if (calendarDate.getUTCFullYear() !== year || calendarDate.getUTCMonth() !== month - 1 || calendarDate.getUTCDate() !== day) {
|
|
49
|
+
return false;
|
|
31
50
|
}
|
|
32
|
-
return
|
|
51
|
+
return Number.isFinite(Date.parse(value));
|
|
33
52
|
}
|
|
34
53
|
function optionalStringArray(value, field) {
|
|
35
54
|
if (value === void 0) return void 0;
|
|
@@ -58,4 +77,4 @@ export {
|
|
|
58
77
|
optionalStringArray,
|
|
59
78
|
validateStringRecord
|
|
60
79
|
};
|
|
61
|
-
//# sourceMappingURL=chunk-
|
|
80
|
+
//# sourceMappingURL=chunk-A2IYSXDQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/store-contract.ts"],"sourcesContent":["export function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function assertString(value: unknown, field: string): string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new Error(`${field} must be a non-empty string`);\n }\n return value.trim();\n}\n\nexport function optionalString(value: unknown): string | undefined {\n if (typeof value !== \"string\" || value.trim().length === 0) return undefined;\n return value.trim();\n}\n\nexport function assertSafePathSegment(value: string, field: string): string {\n if (value === \".\" || value === \"..\" || value.includes(\"/\") || value.includes(\"\\\\\")) {\n throw new Error(`${field} must be a safe path segment`);\n }\n return value;\n}\n\nexport function assertIsoRecordedAt(value: string, field = \"recordedAt\"): string {\n const parsed = parseIsoRecordedAt(value);\n if (!parsed) {\n throw new Error(`${field} must be an ISO timestamp`);\n }\n return value;\n}\n\nexport function recordStoreDay(recordedAt: string): string {\n assertIsoRecordedAt(recordedAt);\n return recordedAt.slice(0, 10);\n}\n\nconst ISO_RECORDED_AT_RE = /^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseIsoRecordedAt(value: string): boolean {\n const match = value.match(ISO_RECORDED_AT_RE);\n if (!match) {\n return false;\n }\n const year = Number(match[1]);\n const month = Number(match[2]);\n const day = Number(match[3]);\n const hour = Number(match[4]);\n const minute = Number(match[5]);\n const second = Number(match[6]);\n if (\n !Number.isInteger(year) ||\n month < 1 ||\n month > 12 ||\n day < 1 ||\n day > 31 ||\n hour > 23 ||\n minute > 59 ||\n second > 59\n ) {\n return false;\n }\n const calendarDate = new Date(Date.UTC(year, month - 1, day));\n if (\n calendarDate.getUTCFullYear() !== year ||\n calendarDate.getUTCMonth() !== month - 1 ||\n calendarDate.getUTCDate() !== day\n ) {\n return false;\n }\n return Number.isFinite(Date.parse(value));\n}\n\nexport function optionalStringArray(value: unknown, field: string): string[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value)) throw new Error(`${field} must be an array of strings`);\n const items = value.map((item, index) => assertString(item, `${field}[${index}]`));\n return items.length > 0 ? items : undefined;\n}\n\nexport function validateStringRecord(raw: unknown, field = \"metadata\"): Record<string, string> | undefined {\n if (raw === undefined) return undefined;\n if (!isRecord(raw)) throw new Error(`${field} must be an object of strings`);\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(raw)) {\n if (typeof value !== \"string\") throw new Error(`${field} must be an object of strings`);\n out[key] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n"],"mappings":";AAAO,SAAS,SAAS,OAAkD;AACzE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEO,SAAS,aAAa,OAAgB,OAAuB;AAClE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,WAAW,GAAG;AAC1D,UAAM,IAAI,MAAM,GAAG,KAAK,6BAA6B;AAAA,EACvD;AACA,SAAO,MAAM,KAAK;AACpB;AAEO,SAAS,eAAe,OAAoC;AACjE,MAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,WAAW,EAAG,QAAO;AACnE,SAAO,MAAM,KAAK;AACpB;AAEO,SAAS,sBAAsB,OAAe,OAAuB;AAC1E,MAAI,UAAU,OAAO,UAAU,QAAQ,MAAM,SAAS,GAAG,KAAK,MAAM,SAAS,IAAI,GAAG;AAClF,UAAM,IAAI,MAAM,GAAG,KAAK,8BAA8B;AAAA,EACxD;AACA,SAAO;AACT;AAEO,SAAS,oBAAoB,OAAe,QAAQ,cAAsB;AAC/E,QAAM,SAAS,mBAAmB,KAAK;AACvC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,GAAG,KAAK,2BAA2B;AAAA,EACrD;AACA,SAAO;AACT;AAEO,SAAS,eAAe,YAA4B;AACzD,sBAAoB,UAAU;AAC9B,SAAO,WAAW,MAAM,GAAG,EAAE;AAC/B;AAEA,IAAM,qBAAqB;AAE3B,SAAS,mBAAmB,OAAwB;AAClD,QAAM,QAAQ,MAAM,MAAM,kBAAkB;AAC5C,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,QAAM,OAAO,OAAO,MAAM,CAAC,CAAC;AAC5B,QAAM,QAAQ,OAAO,MAAM,CAAC,CAAC;AAC7B,QAAM,MAAM,OAAO,MAAM,CAAC,CAAC;AAC3B,QAAM,OAAO,OAAO,MAAM,CAAC,CAAC;AAC5B,QAAM,SAAS,OAAO,MAAM,CAAC,CAAC;AAC9B,QAAM,SAAS,OAAO,MAAM,CAAC,CAAC;AAC9B,MACE,CAAC,OAAO,UAAU,IAAI,KACtB,QAAQ,KACR,QAAQ,MACR,MAAM,KACN,MAAM,MACN,OAAO,MACP,SAAS,MACT,SAAS,IACT;AACA,WAAO;AAAA,EACT;AACA,QAAM,eAAe,IAAI,KAAK,KAAK,IAAI,MAAM,QAAQ,GAAG,GAAG,CAAC;AAC5D,MACE,aAAa,eAAe,MAAM,QAClC,aAAa,YAAY,MAAM,QAAQ,KACvC,aAAa,WAAW,MAAM,KAC9B;AACA,WAAO;AAAA,EACT;AACA,SAAO,OAAO,SAAS,KAAK,MAAM,KAAK,CAAC;AAC1C;AAEO,SAAS,oBAAoB,OAAgB,OAAqC;AACvF,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,OAAM,IAAI,MAAM,GAAG,KAAK,8BAA8B;AACjF,QAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,UAAU,aAAa,MAAM,GAAG,KAAK,IAAI,KAAK,GAAG,CAAC;AACjF,SAAO,MAAM,SAAS,IAAI,QAAQ;AACpC;AAEO,SAAS,qBAAqB,KAAc,QAAQ,YAAgD;AACzG,MAAI,QAAQ,OAAW,QAAO;AAC9B,MAAI,CAAC,SAAS,GAAG,EAAG,OAAM,IAAI,MAAM,GAAG,KAAK,+BAA+B;AAC3E,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,QAAI,OAAO,UAAU,SAAU,OAAM,IAAI,MAAM,GAAG,KAAK,+BAA+B;AACtF,QAAI,GAAG,IAAI;AAAA,EACb;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAC7C;","names":[]}
|
|
@@ -8,10 +8,12 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// src/policy-runtime.ts
|
|
10
10
|
import path from "path";
|
|
11
|
+
import { randomUUID } from "crypto";
|
|
11
12
|
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
12
13
|
var RUNTIME_POLICY_VERSION = 1;
|
|
13
14
|
var RUNTIME_POLICY_FILE = "policy-runtime.json";
|
|
14
15
|
var RUNTIME_POLICY_PREV_FILE = "policy-runtime.prev.json";
|
|
16
|
+
var mutationQueues = /* @__PURE__ */ new Map();
|
|
15
17
|
function sanitizeRuntimePolicyValues(values, options) {
|
|
16
18
|
const out = {};
|
|
17
19
|
if (typeof values.recencyWeight === "number") {
|
|
@@ -55,12 +57,24 @@ async function readRuntimePolicySnapshot(filePath, options) {
|
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
async function writeSnapshotAtomic(filePath, snapshot) {
|
|
58
|
-
const tempPath = `${filePath}.tmp`;
|
|
60
|
+
const tempPath = `${filePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;
|
|
59
61
|
await mkdir(path.dirname(filePath), { recursive: true });
|
|
60
62
|
await writeFile(tempPath, `${JSON.stringify(snapshot, null, 2)}
|
|
61
63
|
`, "utf-8");
|
|
62
64
|
await rename(tempPath, filePath);
|
|
63
65
|
}
|
|
66
|
+
function enqueuePolicyMutation(key, fn) {
|
|
67
|
+
const previous = mutationQueues.get(key) ?? Promise.resolve();
|
|
68
|
+
const operation = previous.catch(() => void 0).then(fn);
|
|
69
|
+
mutationQueues.set(
|
|
70
|
+
key,
|
|
71
|
+
operation.then(
|
|
72
|
+
() => void 0,
|
|
73
|
+
() => void 0
|
|
74
|
+
)
|
|
75
|
+
);
|
|
76
|
+
return operation;
|
|
77
|
+
}
|
|
64
78
|
var PolicyRuntimeManager = class {
|
|
65
79
|
constructor(memoryDir, config) {
|
|
66
80
|
this.memoryDir = memoryDir;
|
|
@@ -68,11 +82,13 @@ var PolicyRuntimeManager = class {
|
|
|
68
82
|
const stateDir = path.join(memoryDir, "state");
|
|
69
83
|
this.runtimePath = path.join(stateDir, RUNTIME_POLICY_FILE);
|
|
70
84
|
this.runtimePrevPath = path.join(stateDir, RUNTIME_POLICY_PREV_FILE);
|
|
85
|
+
this.mutationKey = path.resolve(memoryDir);
|
|
71
86
|
}
|
|
72
87
|
memoryDir;
|
|
73
88
|
config;
|
|
74
89
|
runtimePath;
|
|
75
90
|
runtimePrevPath;
|
|
91
|
+
mutationKey;
|
|
76
92
|
async loadRuntimeValues() {
|
|
77
93
|
const snapshot = await readRuntimePolicySnapshot(this.runtimePath, {
|
|
78
94
|
maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold
|
|
@@ -81,6 +97,9 @@ var PolicyRuntimeManager = class {
|
|
|
81
97
|
return snapshot.values;
|
|
82
98
|
}
|
|
83
99
|
async rollback() {
|
|
100
|
+
return enqueuePolicyMutation(this.mutationKey, () => this.rollbackUnlocked());
|
|
101
|
+
}
|
|
102
|
+
async rollbackUnlocked() {
|
|
84
103
|
const previous = await readRuntimePolicySnapshot(this.runtimePrevPath, {
|
|
85
104
|
maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold
|
|
86
105
|
});
|
|
@@ -92,6 +111,9 @@ var PolicyRuntimeManager = class {
|
|
|
92
111
|
return true;
|
|
93
112
|
}
|
|
94
113
|
async applyFromBehaviorState(state) {
|
|
114
|
+
return enqueuePolicyMutation(this.mutationKey, () => this.applyFromBehaviorStateUnlocked(state));
|
|
115
|
+
}
|
|
116
|
+
async applyFromBehaviorStateUnlocked(state) {
|
|
95
117
|
const adjustmentCount = state.adjustments.length;
|
|
96
118
|
if (adjustmentCount === 0) {
|
|
97
119
|
return { applied: false, rolledBack: false, values: await this.loadRuntimeValues(), reason: "no_adjustments" };
|
|
@@ -116,7 +138,7 @@ var PolicyRuntimeManager = class {
|
|
|
116
138
|
await writeSnapshotAtomic(this.runtimePath, existing);
|
|
117
139
|
rolledBack = true;
|
|
118
140
|
} else {
|
|
119
|
-
rolledBack = await this.
|
|
141
|
+
rolledBack = await this.rollbackUnlocked();
|
|
120
142
|
}
|
|
121
143
|
return {
|
|
122
144
|
applied: false,
|
|
@@ -134,7 +156,7 @@ var PolicyRuntimeManager = class {
|
|
|
134
156
|
await writeSnapshotAtomic(this.runtimePath, existing);
|
|
135
157
|
rolledBack = true;
|
|
136
158
|
} else {
|
|
137
|
-
rolledBack = await this.
|
|
159
|
+
rolledBack = await this.rollbackUnlocked();
|
|
138
160
|
}
|
|
139
161
|
return {
|
|
140
162
|
applied: false,
|
|
@@ -167,4 +189,4 @@ export {
|
|
|
167
189
|
readRuntimePolicySnapshot,
|
|
168
190
|
PolicyRuntimeManager
|
|
169
191
|
};
|
|
170
|
-
//# sourceMappingURL=chunk-
|
|
192
|
+
//# sourceMappingURL=chunk-A2Z6UCWT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/policy-runtime.ts"],"sourcesContent":["import path from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { clamp01, clampLifecycleThreshold } from \"./lifecycle.js\";\nimport { clampInstructionHeavyTokenCap } from \"./recall-query-policy.js\";\nimport type { BehaviorLoopPolicyState, PluginConfig } from \"./types.js\";\n\nexport interface RuntimePolicyValues {\n recencyWeight?: number;\n lifecyclePromoteHeatThreshold?: number;\n lifecycleStaleDecayThreshold?: number;\n cronRecallInstructionHeavyTokenCap?: number;\n}\n\nexport interface RuntimePolicySnapshot {\n version: number;\n updatedAt: string;\n values: RuntimePolicyValues;\n sourceAdjustmentCount: number;\n}\n\nconst RUNTIME_POLICY_VERSION = 1;\nconst RUNTIME_POLICY_FILE = \"policy-runtime.json\";\nconst RUNTIME_POLICY_PREV_FILE = \"policy-runtime.prev.json\";\nconst mutationQueues = new Map<string, Promise<void>>();\n\nexport function sanitizeRuntimePolicyValues(\n values: RuntimePolicyValues,\n options?: { maxStaleDecayThreshold?: number },\n): RuntimePolicyValues {\n const out: RuntimePolicyValues = {};\n if (typeof values.recencyWeight === \"number\") {\n out.recencyWeight = clamp01(values.recencyWeight);\n }\n if (typeof values.lifecyclePromoteHeatThreshold === \"number\") {\n out.lifecyclePromoteHeatThreshold = clampLifecycleThreshold(values.lifecyclePromoteHeatThreshold);\n }\n if (typeof values.lifecycleStaleDecayThreshold === \"number\") {\n const staleDecayThreshold = clampLifecycleThreshold(values.lifecycleStaleDecayThreshold);\n const maxStaleDecayThreshold = typeof options?.maxStaleDecayThreshold === \"number\"\n ? clampLifecycleThreshold(options.maxStaleDecayThreshold)\n : 1;\n out.lifecycleStaleDecayThreshold = Math.min(staleDecayThreshold, maxStaleDecayThreshold);\n }\n if (typeof values.cronRecallInstructionHeavyTokenCap === \"number\") {\n out.cronRecallInstructionHeavyTokenCap = clampInstructionHeavyTokenCap(\n values.cronRecallInstructionHeavyTokenCap,\n );\n }\n return out;\n}\n\nfunction isRuntimeParameter(parameter: string): parameter is keyof RuntimePolicyValues {\n return (\n parameter === \"recencyWeight\" ||\n parameter === \"lifecyclePromoteHeatThreshold\" ||\n parameter === \"lifecycleStaleDecayThreshold\" ||\n parameter === \"cronRecallInstructionHeavyTokenCap\"\n );\n}\n\nexport async function readRuntimePolicySnapshot(\n filePath: string,\n options?: { maxStaleDecayThreshold?: number },\n): Promise<RuntimePolicySnapshot | null> {\n try {\n const raw = await readFile(filePath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<RuntimePolicySnapshot>;\n if (\n !parsed ||\n typeof parsed.version !== \"number\" ||\n parsed.version < 1 ||\n typeof parsed.updatedAt !== \"string\" ||\n !parsed.values ||\n typeof parsed.values !== \"object\" ||\n typeof parsed.sourceAdjustmentCount !== \"number\" ||\n parsed.sourceAdjustmentCount < 0\n ) {\n return null;\n }\n return {\n version: parsed.version,\n updatedAt: parsed.updatedAt,\n values: sanitizeRuntimePolicyValues(parsed.values, {\n maxStaleDecayThreshold: options?.maxStaleDecayThreshold,\n }),\n sourceAdjustmentCount: parsed.sourceAdjustmentCount,\n };\n } catch {\n return null;\n }\n}\n\nasync function writeSnapshotAtomic(filePath: string, snapshot: RuntimePolicySnapshot): Promise<void> {\n const tempPath = `${filePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(tempPath, `${JSON.stringify(snapshot, null, 2)}\\n`, \"utf-8\");\n await rename(tempPath, filePath);\n}\n\nfunction enqueuePolicyMutation<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const previous = mutationQueues.get(key) ?? Promise.resolve();\n const operation = previous\n .catch(() => undefined)\n .then(fn);\n mutationQueues.set(\n key,\n operation.then(\n () => undefined,\n () => undefined,\n ),\n );\n return operation;\n}\n\nexport class PolicyRuntimeManager {\n private readonly runtimePath: string;\n private readonly runtimePrevPath: string;\n private readonly mutationKey: string;\n\n constructor(\n private readonly memoryDir: string,\n private readonly config: PluginConfig,\n ) {\n const stateDir = path.join(memoryDir, \"state\");\n this.runtimePath = path.join(stateDir, RUNTIME_POLICY_FILE);\n this.runtimePrevPath = path.join(stateDir, RUNTIME_POLICY_PREV_FILE);\n this.mutationKey = path.resolve(memoryDir);\n }\n\n async loadRuntimeValues(): Promise<RuntimePolicyValues | null> {\n const snapshot = await readRuntimePolicySnapshot(this.runtimePath, {\n maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold,\n });\n if (!snapshot) return null;\n return snapshot.values;\n }\n\n async rollback(): Promise<boolean> {\n return enqueuePolicyMutation(this.mutationKey, () => this.rollbackUnlocked());\n }\n\n private async rollbackUnlocked(): Promise<boolean> {\n const previous = await readRuntimePolicySnapshot(this.runtimePrevPath, {\n maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold,\n });\n if (!previous) return false;\n await writeSnapshotAtomic(this.runtimePath, {\n ...previous,\n updatedAt: new Date().toISOString(),\n });\n return true;\n }\n\n async applyFromBehaviorState(\n state: BehaviorLoopPolicyState,\n ): Promise<{ applied: boolean; rolledBack: boolean; values: RuntimePolicyValues | null; reason: string }> {\n return enqueuePolicyMutation(this.mutationKey, () => this.applyFromBehaviorStateUnlocked(state));\n }\n\n private async applyFromBehaviorStateUnlocked(\n state: BehaviorLoopPolicyState,\n ): Promise<{ applied: boolean; rolledBack: boolean; values: RuntimePolicyValues | null; reason: string }> {\n const adjustmentCount = state.adjustments.length;\n if (adjustmentCount === 0) {\n return { applied: false, rolledBack: false, values: await this.loadRuntimeValues(), reason: \"no_adjustments\" };\n }\n\n const protectedSet = new Set<string>([\n ...this.config.behaviorLoopProtectedParams,\n ...state.protectedParams,\n ]);\n const existing = await readRuntimePolicySnapshot(this.runtimePath, {\n maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold,\n });\n const candidate: RuntimePolicyValues = {\n recencyWeight: existing?.values.recencyWeight ?? this.config.recencyWeight,\n lifecyclePromoteHeatThreshold:\n existing?.values.lifecyclePromoteHeatThreshold ?? this.config.lifecyclePromoteHeatThreshold,\n lifecycleStaleDecayThreshold:\n existing?.values.lifecycleStaleDecayThreshold ?? this.config.lifecycleStaleDecayThreshold,\n cronRecallInstructionHeavyTokenCap:\n existing?.values.cronRecallInstructionHeavyTokenCap ?? this.config.cronRecallInstructionHeavyTokenCap,\n };\n\n for (const adjustment of state.adjustments) {\n if (!isRuntimeParameter(adjustment.parameter)) {\n let rolledBack = false;\n if (existing) {\n await writeSnapshotAtomic(this.runtimePath, existing);\n rolledBack = true;\n } else {\n rolledBack = await this.rollbackUnlocked();\n }\n return {\n applied: false,\n rolledBack,\n values: await this.loadRuntimeValues(),\n reason: `invalid_parameter:${adjustment.parameter}`,\n };\n }\n if (protectedSet.has(adjustment.parameter)) {\n continue;\n }\n if (!Number.isFinite(adjustment.nextValue)) {\n let rolledBack = false;\n if (existing) {\n await writeSnapshotAtomic(this.runtimePath, existing);\n rolledBack = true;\n } else {\n rolledBack = await this.rollbackUnlocked();\n }\n return {\n applied: false,\n rolledBack,\n values: await this.loadRuntimeValues(),\n reason: `invalid_value:${adjustment.parameter}`,\n };\n }\n candidate[adjustment.parameter] = adjustment.nextValue;\n }\n\n const sanitized = sanitizeRuntimePolicyValues(candidate, {\n maxStaleDecayThreshold: this.config.lifecycleArchiveDecayThreshold,\n });\n if (existing) {\n await writeSnapshotAtomic(this.runtimePrevPath, existing);\n }\n const nextSnapshot: RuntimePolicySnapshot = {\n version: RUNTIME_POLICY_VERSION,\n updatedAt: new Date().toISOString(),\n values: sanitized,\n sourceAdjustmentCount: adjustmentCount,\n };\n await writeSnapshotAtomic(this.runtimePath, nextSnapshot);\n return { applied: true, rolledBack: false, values: sanitized, reason: \"applied\" };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-FF4KLI5W.js";
|
|
8
8
|
import {
|
|
9
9
|
analyzeSessionIntegrity
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KFY3SGN7.js";
|
|
11
11
|
import {
|
|
12
12
|
log
|
|
13
13
|
} from "./chunk-2ODBA7MQ.js";
|
|
@@ -505,7 +505,7 @@ var TranscriptManager = class _TranscriptManager {
|
|
|
505
505
|
try {
|
|
506
506
|
const entry = JSON.parse(line);
|
|
507
507
|
const entryTime = new Date(entry.timestamp);
|
|
508
|
-
if (entryTime >= start && entryTime
|
|
508
|
+
if (entryTime >= start && entryTime < end) {
|
|
509
509
|
if (!sessionKey || entry.sessionKey === sessionKey) {
|
|
510
510
|
entries.push(entry);
|
|
511
511
|
}
|
|
@@ -564,7 +564,7 @@ var TranscriptManager = class _TranscriptManager {
|
|
|
564
564
|
try {
|
|
565
565
|
const entry = JSON.parse(line);
|
|
566
566
|
const ts = new Date(entry.timestamp);
|
|
567
|
-
if (ts >= start && ts
|
|
567
|
+
if (ts >= start && ts < end && entry.sessionKey === sessionKey) {
|
|
568
568
|
entries.push(entry);
|
|
569
569
|
}
|
|
570
570
|
} catch {
|
|
@@ -911,4 +911,4 @@ var TranscriptManager = class _TranscriptManager {
|
|
|
911
911
|
export {
|
|
912
912
|
TranscriptManager
|
|
913
913
|
};
|
|
914
|
-
//# sourceMappingURL=chunk-
|
|
914
|
+
//# sourceMappingURL=chunk-A6D7A2FW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/transcript.ts"],"sourcesContent":["import { appendFile, mkdir, readdir, readFile, stat, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\nimport type { TranscriptEntry, Checkpoint, PluginConfig } from \"./types.js\";\nimport { analyzeSessionIntegrity, type SessionIntegrityReport } from \"./session-integrity.js\";\nimport {\n encodeStoragePathSegment,\n encodeStoragePathSegmentWithHash,\n isSafeLegacyPathSegment,\n resolveSafeStoragePath,\n storagePathHash,\n} from \"./storage-paths.js\";\n\ntype DirectorySessionStatus = \"missing\" | \"empty\" | \"matches\" | \"occupied\";\ntype DirectoryOwnershipCacheEntry = {\n status: \"empty\" | \"matches\";\n fileSizes: Map<string, number>;\n};\n\nfunction legacyTranscriptDirFor(\n channelType: string,\n channelId: string,\n encodedDir: string,\n): string | undefined {\n if (!isSafeLegacyPathSegment(channelType) || !isSafeLegacyPathSegment(channelId)) {\n return undefined;\n }\n const legacyDir = path.join(channelType, channelId);\n return legacyDir === encodedDir ? undefined : legacyDir;\n}\n\n/**\n * Manages conversation transcript storage, checkpointing, and recall formatting.\n *\n * Transcripts are stored as JSONL files in a hierarchical structure:\n * transcripts/{channelType}/{channelId}.jsonl\n *\n * Channel types are extracted from sessionKey (discord, slack, cron, main, etc.)\n * Checkpoints are used to preserve conversation context across compaction events.\n */\nexport class TranscriptManager {\n private transcriptsDir: string;\n private checkpointPath: string;\n private stateDir: string;\n private toolUsageDir: string;\n private config: PluginConfig;\n private sessionFootprintCache = new Map<\n string,\n { totalBytes: number; fileBytes: Map<string, number>; fileSizes: Map<string, number> }\n >();\n private directoryOwnershipCache = new Map<string, DirectoryOwnershipCacheEntry>();\n\n /** Default checkpoint TTL in hours */\n private static readonly DEFAULT_CHECKPOINT_TTL_HOURS = 24;\n /** Approximate characters per token for rough estimation */\n private static readonly CHARS_PER_TOKEN = 4;\n\n constructor(config: PluginConfig) {\n this.config = config;\n this.transcriptsDir = path.join(config.memoryDir, \"transcripts\");\n this.stateDir = path.join(config.memoryDir, \"state\");\n this.checkpointPath = path.join(this.stateDir, \"checkpoint.json\");\n this.toolUsageDir = path.join(this.stateDir, \"tool-usage\");\n }\n\n /**\n * Parse a sessionKey to extract channel type and ID.\n *\n * SessionKey patterns:\n * - agent:<agent-id>:main → type=\"main\", id=\"default\"\n * - agent:<agent-id>:discord:channel:<channel-id> → type=\"discord\", id=\"<channel-id>\"\n * - agent:<agent-id>:cron:<job-id> → type=\"cron\", id=\"<job-id>\"\n * - agent:<agent-id>:slack:channel:<channel-id> → type=\"slack\", id=\"<channel-id>\"\n *\n * @returns Object with raw channel identifiers and encoded storage path pieces.\n */\n getTranscriptPath(sessionKey: string): {\n dir: string;\n file: string;\n channelType: string;\n channelId: string;\n alternateDir: string;\n legacyDir?: string;\n } {\n const parts = sessionKey.split(\":\");\n\n // Default fallback\n let channelType = \"other\";\n let channelId = \"default\";\n\n if (parts.length >= 3) {\n // parts[0] = \"agent\", parts[1] = agent name, parts[2] = channel type\n channelType = parts[2];\n\n // Extract channel ID based on pattern\n if (channelType === \"main\") {\n channelId = \"default\";\n } else if (channelType === \"discord\" && parts.length >= 5 && parts[3] === \"channel\") {\n channelId = parts[4];\n } else if (channelType === \"slack\" && parts.length >= 5 && parts[3] === \"channel\") {\n channelId = parts[4];\n } else if (channelType === \"cron\" && parts.length >= 4) {\n channelId = parts[3];\n } else if (parts.length >= 4) {\n // For other types, use the 4th part as ID if available\n channelId = parts[3];\n }\n }\n\n // Daily rotation: transcripts/{channelType}/{channelId}/YYYY-MM-DD.jsonl\n const today = new Date().toISOString().slice(0, 10);\n const dir = path.join(\n encodeStoragePathSegment(channelType),\n encodeStoragePathSegment(channelId),\n );\n const alternateDir = path.join(\n encodeStoragePathSegmentWithHash(channelType),\n `${encodeStoragePathSegmentWithHash(channelId)}--session-${storagePathHash(sessionKey)}`,\n );\n return {\n dir,\n file: `${today}.jsonl`,\n channelType,\n channelId,\n alternateDir,\n legacyDir: legacyTranscriptDirFor(channelType, channelId, dir),\n };\n }\n\n /**\n * Initialize the transcript manager by ensuring directories exist.\n */\n async initialize(): Promise<void> {\n await mkdir(this.transcriptsDir, { recursive: true });\n await mkdir(this.stateDir, { recursive: true });\n await mkdir(this.toolUsageDir, { recursive: true });\n log.info(\"transcript manager initialized\");\n }\n\n /**\n * Best-effort list of sessionKeys that have transcript files on disk.\n * This is used by cron-style tooling (hourly summaries, conversation indexing)\n * to iterate across \"active\" sessions.\n */\n async listSessionKeys(): Promise<string[]> {\n const transcriptDir = this.transcriptsDir;\n const sessionKeys = new Set<string>();\n\n try {\n const typeEntries = await readdir(transcriptDir, { withFileTypes: true });\n for (const typeEnt of typeEntries) {\n if (!typeEnt.isDirectory()) continue;\n const typeDir = path.join(transcriptDir, typeEnt.name);\n const idEntries = await readdir(typeDir, { withFileTypes: true });\n for (const idEnt of idEntries) {\n if (!idEnt.isDirectory()) continue;\n const chanDir = path.join(typeDir, idEnt.name);\n const files = (await readdir(chanDir)).filter((f) => f.endsWith(\".jsonl\")).sort();\n const last = files[files.length - 1];\n if (!last) continue;\n try {\n const raw = await readFile(path.join(chanDir, last), \"utf-8\");\n const firstLine = raw.split(\"\\n\").find((l) => l.trim().length > 0);\n if (!firstLine) continue;\n const entry = JSON.parse(firstLine) as TranscriptEntry;\n if (typeof entry.sessionKey === \"string\" && entry.sessionKey.length > 0) {\n sessionKeys.add(entry.sessionKey);\n }\n } catch {\n // ignore\n }\n }\n }\n } catch {\n return [];\n }\n\n return Array.from(sessionKeys);\n }\n\n getToolUsagePath(sessionKey: string): {\n dir: string;\n file: string;\n alternateDir: string;\n legacyDir?: string;\n } {\n const p = this.getTranscriptPath(sessionKey);\n return { dir: p.dir, file: p.file, alternateDir: p.alternateDir, legacyDir: p.legacyDir };\n }\n\n private async selectStorageDirForWrite(\n root: string,\n dir: string,\n legacyDir?: string,\n sessionKey?: string,\n alternateDir?: string,\n ): Promise<{ dir: string; channelDir: string }> {\n const channelDir = await resolveSafeStoragePath(root, dir);\n const encodedStatus = await this.directorySessionStatus(root, dir, sessionKey);\n if (encodedStatus === \"matches\" || encodedStatus === \"empty\") return { dir, channelDir };\n\n if (legacyDir) {\n const legacyChannelDir = await resolveSafeStoragePath(root, legacyDir);\n if ((await this.directorySessionStatus(root, legacyDir, sessionKey)) === \"matches\") {\n return { dir: legacyDir, channelDir: legacyChannelDir };\n }\n }\n\n if (encodedStatus === \"missing\") return { dir, channelDir };\n\n if (alternateDir) {\n const alternateChannelDir = await resolveSafeStoragePath(root, alternateDir);\n const alternateStatus = await this.directorySessionStatus(root, alternateDir, sessionKey);\n if (\n alternateStatus === \"missing\" ||\n alternateStatus === \"empty\" ||\n alternateStatus === \"matches\"\n ) {\n return { dir: alternateDir, channelDir: alternateChannelDir };\n }\n }\n\n throw new Error(`transcript storage path collision for session: ${sessionKey ?? \"(unknown)\"}`);\n }\n\n private async directorySessionStatus(\n root: string,\n dir: string,\n sessionKey?: string,\n ): Promise<DirectorySessionStatus> {\n let channelDir: string;\n try {\n channelDir = await resolveSafeStoragePath(root, dir);\n if (!(await stat(channelDir)).isDirectory()) return \"occupied\";\n } catch (err) {\n const code =\n err && typeof err === \"object\" && \"code\" in err\n ? (err as { code?: string }).code\n : undefined;\n if (code === \"ENOENT\") return \"missing\";\n throw err;\n }\n\n let names: string[];\n try {\n names = (await readdir(channelDir)).filter((file) => file.endsWith(\".jsonl\"));\n } catch {\n return \"occupied\";\n }\n\n const fileSizes = await this.directoryJsonlFileSizes(root, dir, names);\n if (!fileSizes) return \"occupied\";\n\n if (!sessionKey) return \"matches\";\n const cacheKey = this.directoryOwnershipCacheKey(root, dir, sessionKey);\n const cached = this.directoryOwnershipCache.get(cacheKey);\n if (cached && this.sameFileSizes(cached.fileSizes, fileSizes)) {\n return cached.status;\n }\n\n let hasEntries = false;\n let hasMatchingEntry = false;\n\n for (const name of names) {\n const filePath = await resolveSafeStoragePath(root, dir, name).catch(() => null);\n if (filePath === null) return \"occupied\";\n try {\n const raw = await readFile(filePath, \"utf-8\");\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n hasEntries = true;\n try {\n const obj = JSON.parse(line) as { sessionKey?: string };\n if (obj.sessionKey === sessionKey) {\n hasMatchingEntry = true;\n } else {\n return \"occupied\";\n }\n } catch {\n return \"occupied\";\n }\n }\n } catch {\n return \"occupied\";\n }\n }\n\n const status = hasMatchingEntry ? \"matches\" : hasEntries ? \"occupied\" : \"empty\";\n if (status === \"matches\" || status === \"empty\") {\n this.directoryOwnershipCache.set(cacheKey, { status, fileSizes });\n }\n return status;\n }\n\n private directoryOwnershipCacheKey(root: string, dir: string, sessionKey: string): string {\n return `${path.resolve(root)}\\0${dir}\\0${sessionKey}`;\n }\n\n private sameFileSizes(left: Map<string, number>, right: Map<string, number>): boolean {\n if (left.size !== right.size) return false;\n for (const [name, size] of left) {\n if (right.get(name) !== size) return false;\n }\n return true;\n }\n\n private async directoryJsonlFileSizes(\n root: string,\n dir: string,\n names: string[],\n ): Promise<Map<string, number> | null> {\n const fileSizes = new Map<string, number>();\n for (const name of names) {\n const filePath = await resolveSafeStoragePath(root, dir, name).catch(() => null);\n if (filePath === null) return null;\n const fileInfo = await stat(filePath).catch(() => null);\n if (!fileInfo?.isFile()) return null;\n fileSizes.set(name, Math.max(0, fileInfo.size));\n }\n return fileSizes;\n }\n\n private async rememberDirectoryOwnership(\n root: string,\n dir: string,\n sessionKey: string,\n ): Promise<void> {\n try {\n const channelDir = await resolveSafeStoragePath(root, dir);\n const names = (await readdir(channelDir)).filter((file) => file.endsWith(\".jsonl\"));\n const fileSizes = await this.directoryJsonlFileSizes(root, dir, names);\n if (!fileSizes) return;\n this.directoryOwnershipCache.set(\n this.directoryOwnershipCacheKey(root, dir, sessionKey),\n { status: \"matches\", fileSizes },\n );\n } catch {\n // Cache refresh is best-effort; write path correctness does not depend on it.\n }\n }\n\n private async getSessionStorageFiles(\n root: string,\n dir: string,\n legacyDir?: string,\n alternateDir?: string,\n ): Promise<Array<{ cacheKey: string; name: string; path: string }>> {\n const files: Array<{ cacheKey: string; name: string; path: string }> = [];\n const seenDirs = new Set<string>();\n\n for (const candidateDir of [dir, alternateDir, legacyDir]) {\n if (!candidateDir || seenDirs.has(candidateDir)) continue;\n seenDirs.add(candidateDir);\n\n let channelDir: string;\n try {\n channelDir = await resolveSafeStoragePath(root, candidateDir);\n } catch {\n continue;\n }\n\n let names: string[];\n try {\n names = (await readdir(channelDir)).filter((file) => file.endsWith(\".jsonl\")).sort();\n } catch {\n continue;\n }\n\n for (const name of names) {\n const filePath = await resolveSafeStoragePath(root, candidateDir, name).catch(() => null);\n if (filePath === null) continue;\n files.push({\n cacheKey: path.join(candidateDir, name),\n name,\n path: filePath,\n });\n }\n }\n\n return files.sort((a, b) => a.cacheKey.localeCompare(b.cacheKey));\n }\n\n async appendToolUse(entry: { timestamp: string; sessionKey: string; tool: string }): Promise<void> {\n const { dir, file, alternateDir, legacyDir } = this.getToolUsagePath(entry.sessionKey);\n const { dir: writeDir, channelDir } = await this.selectStorageDirForWrite(\n this.toolUsageDir,\n dir,\n legacyDir,\n entry.sessionKey,\n alternateDir,\n );\n await mkdir(channelDir, { recursive: true });\n const filePath = await resolveSafeStoragePath(this.toolUsageDir, writeDir, file);\n await appendFile(filePath, JSON.stringify(entry) + \"\\n\", \"utf-8\");\n await this.rememberDirectoryOwnership(this.toolUsageDir, writeDir, entry.sessionKey);\n }\n\n async readToolUse(\n sessionKey: string,\n startTime: Date,\n endTime: Date,\n ): Promise<Array<{ timestamp: string; sessionKey: string; tool: string }>> {\n const { dir, alternateDir, legacyDir } = this.getToolUsagePath(sessionKey);\n try {\n const files = await this.getSessionStorageFiles(this.toolUsageDir, dir, legacyDir, alternateDir);\n const out: Array<{ timestamp: string; sessionKey: string; tool: string }> = [];\n for (const file of files) {\n const raw = await readFile(file.path, \"utf-8\");\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const obj = JSON.parse(line) as any;\n const ts = new Date(String(obj.timestamp ?? \"\")).getTime();\n if (!Number.isFinite(ts)) continue;\n if (ts >= startTime.getTime() && ts < endTime.getTime()) {\n if (typeof obj.tool === \"string\" && typeof obj.sessionKey === \"string\") {\n if (obj.sessionKey === sessionKey) {\n out.push({ timestamp: obj.timestamp, sessionKey: obj.sessionKey, tool: obj.tool });\n }\n }\n }\n } catch {\n // ignore\n }\n }\n }\n return out;\n } catch {\n return [];\n }\n }\n\n async estimateSessionFootprint(sessionKey: string): Promise<{ bytes: number; tokens: number }> {\n const { dir, alternateDir, legacyDir } = this.getTranscriptPath(sessionKey);\n let bytes = 0;\n\n try {\n const files = await this.getSessionStorageFiles(this.transcriptsDir, dir, legacyDir, alternateDir);\n const cached = this.sessionFootprintCache.get(sessionKey);\n if (!cached) {\n const fileBytes = new Map<string, number>();\n const fileSizes = new Map<string, number>();\n for (const file of files) {\n try {\n const fileInfo = await stat(file.path);\n const sessionBytes = await this.estimateSessionBytesInFile(\n file.path,\n sessionKey,\n );\n fileBytes.set(file.cacheKey, sessionBytes);\n fileSizes.set(file.cacheKey, Math.max(0, fileInfo.size));\n bytes += sessionBytes;\n } catch {\n // fail-open\n }\n }\n this.sessionFootprintCache.set(sessionKey, { totalBytes: bytes, fileBytes, fileSizes });\n } else {\n bytes = cached.totalBytes;\n const seen = new Set(files.map((file) => file.cacheKey));\n\n // Drop removed files from the cached total.\n for (const [cachedFile, cachedSessionBytes] of cached.fileBytes.entries()) {\n if (!seen.has(cachedFile)) {\n bytes -= cachedSessionBytes;\n cached.fileBytes.delete(cachedFile);\n cached.fileSizes.delete(cachedFile);\n }\n }\n\n // Read only newly discovered files.\n for (const file of files) {\n if (cached.fileBytes.has(file.cacheKey)) continue;\n try {\n const fileInfo = await stat(file.path);\n const sessionBytes = await this.estimateSessionBytesInFile(file.path, sessionKey);\n cached.fileBytes.set(file.cacheKey, sessionBytes);\n cached.fileSizes.set(file.cacheKey, Math.max(0, fileInfo.size));\n bytes += sessionBytes;\n } catch {\n // fail-open\n }\n }\n\n // Recompute any shard whose file size changed. A session can have both\n // encoded and legacy directories during migration, so path ordering does\n // not reliably identify the file that can grow.\n for (const file of files) {\n try {\n const fileInfo = await stat(file.path);\n const size = Math.max(0, fileInfo.size);\n const previousSessionBytes = cached.fileBytes.get(file.cacheKey) ?? 0;\n const previousSize = cached.fileSizes.get(file.cacheKey) ?? -1;\n if (size !== previousSize) {\n const sessionBytes = await this.estimateSessionBytesInFile(file.path, sessionKey);\n cached.fileBytes.set(file.cacheKey, sessionBytes);\n cached.fileSizes.set(file.cacheKey, size);\n bytes += sessionBytes - previousSessionBytes;\n }\n } catch {\n // fail-open\n }\n }\n\n if (bytes < 0) bytes = 0;\n cached.totalBytes = bytes;\n }\n } catch {\n // fail-open\n this.sessionFootprintCache.delete(sessionKey);\n }\n\n return {\n bytes,\n tokens: Math.floor(bytes / TranscriptManager.CHARS_PER_TOKEN),\n };\n }\n\n private async estimateSessionBytesInFile(filePath: string, sessionKey: string): Promise<number> {\n try {\n const raw = await readFile(filePath, \"utf-8\");\n let total = 0;\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const parsed = JSON.parse(line) as { sessionKey?: string };\n if (parsed.sessionKey === sessionKey) {\n total += Buffer.byteLength(`${line}\\n`, \"utf-8\");\n }\n } catch {\n // fail-open for malformed lines\n }\n }\n return total;\n } catch {\n return 0;\n }\n }\n\n /**\n * Check if a file is a legacy flat transcript file (YYYY-MM-DD.jsonl format).\n */\n private isLegacyTranscriptFile(filename: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}\\.jsonl$/.test(filename);\n }\n\n /**\n * Append a turn to the appropriate transcript file.\n * Files are stored hierarchically: transcripts/{channelType}/{channelId}.jsonl\n *\n * Skips channel types in config.transcriptSkipChannelTypes (e.g., \"cron\").\n */\n async append(entry: TranscriptEntry): Promise<void> {\n try {\n const { dir, file, channelType, alternateDir, legacyDir } = this.getTranscriptPath(entry.sessionKey);\n\n // Skip if this channel type is in the skip list\n if (this.config.transcriptSkipChannelTypes.includes(channelType)) {\n return;\n }\n\n const { dir: writeDir, channelDir } = await this.selectStorageDirForWrite(\n this.transcriptsDir,\n dir,\n legacyDir,\n entry.sessionKey,\n alternateDir,\n );\n const filePath = await resolveSafeStoragePath(this.transcriptsDir, writeDir, file);\n\n // Ensure channel directory exists\n await mkdir(channelDir, { recursive: true });\n\n const line = JSON.stringify(entry) + \"\\n\";\n await appendFile(filePath, line, \"utf-8\");\n await this.rememberDirectoryOwnership(this.transcriptsDir, writeDir, entry.sessionKey);\n log.debug(`appended transcript entry for ${entry.sessionKey}: ${entry.turnId}`);\n } catch (err) {\n log.error(\"failed to append transcript entry:\", err);\n throw err;\n }\n }\n\n /**\n * Get all transcript files from the hierarchical directory structure.\n * Recursively finds all .jsonl files in transcripts/{channelType}/{channelId}/ subdirectories.\n */\n private async getAllTranscriptFiles(): Promise<string[]> {\n const files: string[] = [];\n\n try {\n const entries = await readdir(this.transcriptsDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n // This is a channel type directory (discord, slack, cron, main, etc.)\n const channelTypeDir = path.join(this.transcriptsDir, entry.name);\n try {\n const channelTypeEntries = await readdir(channelTypeDir, { withFileTypes: true });\n\n for (const channelTypeEntry of channelTypeEntries) {\n if (channelTypeEntry.isDirectory()) {\n // This is a channel ID directory - contains daily transcript files\n const channelDir = path.join(channelTypeDir, channelTypeEntry.name);\n try {\n const channelFiles = await readdir(channelDir);\n for (const file of channelFiles) {\n if (file.endsWith(\".jsonl\")) {\n files.push(path.join(entry.name, channelTypeEntry.name, file));\n }\n }\n } catch {\n // Skip unreadable directories\n }\n } else if (channelTypeEntry.isFile() && channelTypeEntry.name.endsWith(\".jsonl\")) {\n // Legacy: channel type dir contains .jsonl files directly\n files.push(path.join(entry.name, channelTypeEntry.name));\n }\n }\n } catch {\n // Skip unreadable directories\n }\n } else if (entry.isFile() && entry.name.endsWith(\".jsonl\")) {\n // Legacy flat file - still include for backward compatibility\n files.push(entry.name);\n }\n }\n } catch {\n // Directory doesn't exist or is unreadable\n }\n\n return files;\n }\n\n /**\n * Read transcript entries for a date range.\n * Returns entries within the time range, optionally filtered by sessionKey.\n * Reads from all channel subdirectories in the hierarchical structure.\n */\n async readRange(startTime: string, endTime: string, sessionKey?: string): Promise<TranscriptEntry[]> {\n const start = new Date(startTime);\n const end = new Date(endTime);\n const entries: TranscriptEntry[] = [];\n\n try {\n // Get all transcript files from the hierarchical structure\n const transcriptFiles = await this.getAllTranscriptFiles();\n\n // Read each relevant file\n for (const relativePath of transcriptFiles) {\n const filePath = path.join(this.transcriptsDir, relativePath);\n try {\n const content = await readFile(filePath, \"utf-8\");\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as TranscriptEntry;\n const entryTime = new Date(entry.timestamp);\n\n // Check if entry is within time range\n if (entryTime >= start && entryTime < end) {\n // Filter by sessionKey if provided\n if (!sessionKey || entry.sessionKey === sessionKey) {\n entries.push(entry);\n }\n }\n } catch {\n // Skip malformed lines\n log.debug(`skipped malformed transcript line in ${relativePath}`);\n }\n }\n } catch {\n // File doesn't exist or is unreadable - skip\n }\n }\n\n // Sort by timestamp\n entries.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());\n\n log.debug(`read ${entries.length} transcript entries from ${transcriptFiles.length} file(s)`);\n return entries;\n } catch (err) {\n log.error(\"failed to read transcript range:\", err);\n return [];\n }\n }\n\n /**\n * Read the last N hours of transcript.\n *\n * Fast path: when sessionKey is given, reads only the 1-2 daily files for that\n * specific channel instead of scanning all 95+ transcript files across all channels.\n */\n async readRecent(hours: number, sessionKey?: string): Promise<TranscriptEntry[]> {\n const end = new Date();\n const start = new Date(end.getTime() - hours * 60 * 60 * 1000);\n\n if (sessionKey) {\n return this.readRecentForSession(start, end, sessionKey);\n }\n return this.readRange(start.toISOString(), end.toISOString(), undefined);\n }\n\n /**\n * Optimized read for a specific session: only looks in that session's channel\n * directory and only reads files whose date falls within the lookback window.\n */\n private async readRecentForSession(\n start: Date,\n end: Date,\n sessionKey: string,\n ): Promise<TranscriptEntry[]> {\n const { dir, alternateDir, legacyDir } = this.getTranscriptPath(sessionKey);\n\n // Build set of date strings that overlap with [start, end].\n // Always include end's date to handle midnight-crossing lookbacks\n // (e.g. start=23:30 yesterday, end=00:30 today).\n const dateStrings = new Set<string>();\n const cursor = new Date(start);\n while (cursor <= end) {\n dateStrings.add(cursor.toISOString().slice(0, 10));\n cursor.setDate(cursor.getDate() + 1);\n }\n dateStrings.add(end.toISOString().slice(0, 10));\n\n const entries: TranscriptEntry[] = [];\n const files = await this.getSessionStorageFiles(this.transcriptsDir, dir, legacyDir, alternateDir);\n\n for (const file of files) {\n // Only read files whose date is within the window\n const dateStr = file.name.slice(0, 10);\n if (!dateStrings.has(dateStr)) continue;\n\n try {\n const content = await readFile(file.path, \"utf-8\");\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const entry = JSON.parse(line) as TranscriptEntry;\n const ts = new Date(entry.timestamp);\n if (ts >= start && ts < end && entry.sessionKey === sessionKey) {\n entries.push(entry);\n }\n } catch {\n // skip malformed line\n }\n }\n } catch {\n // skip unreadable file\n }\n }\n\n entries.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());\n log.debug(`readRecentForSession: ${entries.length} entries from ${files.length} file(s) in ${dir}`);\n return entries;\n }\n\n /**\n * Cleanup old transcript entries that are older than retentionDays.\n * For hierarchical structure, reads each file and rewrites without old entries.\n * Legacy flat files are deleted if their date is older than retentionDays.\n * Returns the number of files processed (cleaned or deleted).\n */\n async cleanup(retentionDays: number): Promise<number> {\n if (retentionDays <= 0) {\n log.warn(\"cleanup called with invalid retentionDays:\", retentionDays);\n return 0;\n }\n\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - retentionDays);\n cutoff.setHours(0, 0, 0, 0);\n\n let processed = 0;\n\n try {\n const entries = await readdir(this.transcriptsDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n // This is a channel type directory (discord, slack, cron, main, etc.)\n const channelTypeDir = path.join(this.transcriptsDir, entry.name);\n try {\n const channelTypeEntries = await readdir(channelTypeDir, { withFileTypes: true });\n\n for (const channelTypeEntry of channelTypeEntries) {\n if (channelTypeEntry.isDirectory()) {\n // This is a channel ID directory - contains daily transcript files\n const channelDir = path.join(channelTypeDir, channelTypeEntry.name);\n try {\n const channelFiles = await readdir(channelDir);\n for (const file of channelFiles) {\n if (!file.endsWith(\".jsonl\")) continue;\n\n const filePath = path.join(channelDir, file);\n\n // Check if file is a daily transcript file (YYYY-MM-DD.jsonl)\n if (this.isLegacyTranscriptFile(file)) {\n const dateStr = file.slice(0, 10);\n const fileDate = new Date(dateStr);\n\n if (!isNaN(fileDate.getTime()) && fileDate < cutoff) {\n try {\n await unlink(filePath);\n processed++;\n log.debug(`deleted old daily transcript file: ${entry.name}/${channelTypeEntry.name}/${file}`);\n } catch (err) {\n log.error(`failed to delete transcript file ${filePath}:`, err);\n }\n }\n } else {\n // Legacy file in new structure - clean up old entries\n const cleaned = await this.cleanupTranscriptFile(filePath, cutoff);\n if (cleaned) {\n processed++;\n }\n }\n }\n } catch (err) {\n log.debug(`failed to process channel directory ${entry.name}/${channelTypeEntry.name}:`, err);\n }\n } else if (channelTypeEntry.isFile() && channelTypeEntry.name.endsWith(\".jsonl\")) {\n // Legacy: channel type dir contains .jsonl files directly\n const filePath = path.join(channelTypeDir, channelTypeEntry.name);\n const cleaned = await this.cleanupTranscriptFile(filePath, cutoff);\n if (cleaned) {\n processed++;\n }\n }\n }\n } catch (err) {\n log.debug(`failed to process channel type directory ${entry.name}:`, err);\n }\n } else if (entry.isFile() && entry.name.endsWith(\".jsonl\")) {\n // Handle legacy flat files - delete if older than retentionDays\n if (this.isLegacyTranscriptFile(entry.name)) {\n const dateStr = entry.name.slice(0, 10);\n const fileDate = new Date(dateStr);\n\n if (!isNaN(fileDate.getTime()) && fileDate < cutoff) {\n const filePath = path.join(this.transcriptsDir, entry.name);\n try {\n await unlink(filePath);\n processed++;\n log.debug(`deleted old legacy transcript file: ${entry.name}`);\n } catch (err) {\n log.error(`failed to delete legacy transcript file ${entry.name}:`, err);\n }\n }\n }\n }\n }\n\n if (processed > 0) {\n log.info(`cleaned up ${processed} transcript file(s) older than ${retentionDays} days`);\n }\n\n return processed;\n } catch (err) {\n log.error(\"failed to cleanup old transcripts:\", err);\n return 0;\n }\n }\n\n /**\n * Clean up old entries from a single transcript file.\n * Reads the file, filters out entries older than cutoff, and rewrites if needed.\n * Returns true if the file was processed (cleaned or deleted).\n */\n private async cleanupTranscriptFile(filePath: string, cutoff: Date): Promise<boolean> {\n try {\n const content = await readFile(filePath, \"utf-8\");\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n\n const validLines: string[] = [];\n let hasOldEntries = false;\n\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as TranscriptEntry;\n const entryTime = new Date(entry.timestamp);\n\n if (entryTime >= cutoff) {\n validLines.push(line);\n } else {\n hasOldEntries = true;\n }\n } catch {\n // Keep malformed lines to avoid data loss\n validLines.push(line);\n }\n }\n\n if (validLines.length === 0) {\n // No valid entries left, delete the file\n try {\n await unlink(filePath);\n log.debug(`deleted empty transcript file: ${filePath}`);\n return true;\n } catch (err) {\n log.error(`failed to delete empty transcript file ${filePath}:`, err);\n return false;\n }\n }\n\n if (hasOldEntries) {\n // Rewrite file without old entries\n await writeFile(filePath, validLines.join(\"\\n\") + \"\\n\", \"utf-8\");\n log.debug(`cleaned old entries from transcript file: ${filePath}`);\n return true;\n }\n\n // No old entries found, no action needed\n return false;\n } catch (err) {\n // File doesn't exist or is unreadable\n return false;\n }\n }\n\n /**\n * Save a checkpoint to preserve conversation context.\n * Called when compaction is detected.\n */\n async saveCheckpoint(checkpoint: Checkpoint): Promise<void> {\n try {\n await writeFile(this.checkpointPath, JSON.stringify(checkpoint, null, 2), \"utf-8\");\n log.info(`saved checkpoint for session ${checkpoint.sessionKey} with ${checkpoint.turns.length} turn(s)`);\n } catch (err) {\n log.error(\"failed to save checkpoint:\", err);\n throw err;\n }\n }\n\n /**\n * Load a checkpoint if one exists and is not expired.\n * Returns null if no checkpoint exists or if it has expired.\n */\n async loadCheckpoint(sessionKey?: string): Promise<Checkpoint | null> {\n try {\n const raw = await readFile(this.checkpointPath, \"utf-8\");\n const checkpoint = JSON.parse(raw) as Checkpoint;\n\n // Validate checkpoint structure\n if (!checkpoint.sessionKey || !checkpoint.capturedAt || !checkpoint.ttl || !Array.isArray(checkpoint.turns)) {\n log.warn(\"checkpoint file has invalid structure\");\n return null;\n }\n\n // Check if checkpoint is for the requested session (if specified)\n if (sessionKey && checkpoint.sessionKey !== sessionKey) {\n log.debug(`checkpoint session mismatch: ${checkpoint.sessionKey} vs ${sessionKey}`);\n return null;\n }\n\n // Check if checkpoint has expired\n const ttl = new Date(checkpoint.ttl);\n if (isNaN(ttl.getTime())) {\n log.warn(\"checkpoint has invalid TTL format\");\n return null;\n }\n\n if (ttl < new Date()) {\n log.info(`checkpoint expired at ${checkpoint.ttl}`);\n return null;\n }\n\n log.info(`loaded checkpoint with ${checkpoint.turns.length} turn(s), expires at ${checkpoint.ttl}`);\n return checkpoint;\n } catch (err) {\n // File doesn't exist or is unreadable - that's fine\n log.debug(\"no valid checkpoint found\");\n return null;\n }\n }\n\n /**\n * Clear (delete) the checkpoint file.\n * Called after successful injection of checkpoint context.\n */\n async clearCheckpoint(): Promise<void> {\n try {\n await unlink(this.checkpointPath);\n log.info(\"cleared checkpoint\");\n } catch (err) {\n // File doesn't exist - that's fine\n log.debug(\"no checkpoint to clear\");\n }\n }\n\n /**\n * Format entries for recall injection.\n * Returns a formatted string suitable for injecting into agent context.\n *\n * Format:\n * ## Recent Conversation (last X hours)\n * [10:32] User: message content\n * [10:33] Assistant: response content\n *\n * Content is trimmed to approximately maxTokens.\n */\n formatForRecall(entries: TranscriptEntry[], maxTokens: number): string {\n if (entries.length === 0) {\n return \"\";\n }\n\n const maxChars = maxTokens * TranscriptManager.CHARS_PER_TOKEN;\n const lines: string[] = [];\n\n // Calculate time range for header\n const firstEntry = new Date(entries[0].timestamp);\n const lastEntry = new Date(entries[entries.length - 1].timestamp);\n const hoursDiff = Math.round((lastEntry.getTime() - firstEntry.getTime()) / (60 * 60 * 1000));\n\n // Add header\n if (hoursDiff < 1) {\n lines.push(\"## Recent Conversation (last few minutes)\");\n } else {\n lines.push(`## Recent Conversation (last ${hoursDiff} hour${hoursDiff === 1 ? \"\" : \"s\"})`);\n }\n lines.push(\"\");\n\n // Format each entry\n const formattedEntries: string[] = [];\n for (const entry of entries) {\n const time = new Date(entry.timestamp);\n const timeStr = time.toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n });\n const roleLabel = entry.role === \"user\" ? \"User\" : \"Assistant\";\n formattedEntries.push(`[${timeStr}] ${roleLabel}: ${entry.content}`);\n }\n\n // Build output, trimming from the beginning if too long\n // (we want to keep the most recent context)\n let totalChars = lines.join(\"\\n\").length;\n const selectedEntries: string[] = [];\n\n for (let i = formattedEntries.length - 1; i >= 0; i--) {\n const entry = formattedEntries[i];\n const entryChars = entry.length + 1; // +1 for newline\n\n if (totalChars + entryChars > maxChars && selectedEntries.length > 0) {\n // Adding this entry would exceed limit, and we have some entries already\n break;\n }\n\n selectedEntries.unshift(entry);\n totalChars += entryChars;\n }\n\n lines.push(...selectedEntries);\n lines.push(\"\"); // Trailing newline\n\n const result = lines.join(\"\\n\");\n log.debug(`formatted ${selectedEntries.length}/${entries.length} transcript entries for recall (~${result.length} chars)`);\n\n return result;\n }\n\n /**\n * Create a checkpoint from the current buffer state.\n * Helper method for creating checkpoints before compaction.\n */\n createCheckpoint(sessionKey: string, turns: TranscriptEntry[], ttlHours?: number): Checkpoint {\n const ttl = ttlHours ?? TranscriptManager.DEFAULT_CHECKPOINT_TTL_HOURS;\n const expiresAt = new Date();\n expiresAt.setHours(expiresAt.getHours() + ttl);\n\n return {\n sessionKey,\n capturedAt: new Date().toISOString(),\n turns: [...turns], // Copy turns to avoid mutation\n ttl: expiresAt.toISOString(),\n };\n }\n\n /**\n * Get statistics about stored transcripts.\n * Returns counts from the hierarchical directory structure.\n */\n async getStats(): Promise<{\n totalFiles: number;\n totalEntries: number;\n oldestFile: string | null;\n newestFile: string | null;\n channelTypes: Record<string, number>;\n }> {\n try {\n const allFiles = await this.getAllTranscriptFiles();\n\n if (allFiles.length === 0) {\n return {\n totalFiles: 0,\n totalEntries: 0,\n oldestFile: null,\n newestFile: null,\n channelTypes: {},\n };\n }\n\n // Sort files by path\n const sortedFiles = allFiles.sort();\n\n let totalEntries = 0;\n const channelTypes: Record<string, number> = {};\n\n for (const relativePath of allFiles) {\n const filePath = path.join(this.transcriptsDir, relativePath);\n try {\n const content = await readFile(filePath, \"utf-8\");\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n totalEntries += lines.length;\n\n // Count by channel type (first directory in path)\n const channelType = relativePath.includes(path.sep)\n ? relativePath.split(path.sep)[0]\n : \"legacy\";\n channelTypes[channelType] = (channelTypes[channelType] || 0) + 1;\n } catch {\n // Skip unreadable files\n }\n }\n\n return {\n totalFiles: allFiles.length,\n totalEntries,\n oldestFile: sortedFiles[0],\n newestFile: sortedFiles[sortedFiles.length - 1],\n channelTypes,\n };\n } catch (err) {\n log.error(\"failed to get transcript stats:\", err);\n return {\n totalFiles: 0,\n totalEntries: 0,\n oldestFile: null,\n newestFile: null,\n channelTypes: {},\n };\n }\n }\n\n async analyzeIntegrity(): Promise<SessionIntegrityReport> {\n return analyzeSessionIntegrity({ memoryDir: this.config.memoryDir });\n }\n\n async getRecoverySummary(sessionKey?: string): Promise<{\n generatedAt: string;\n sessionKey?: string;\n healthy: boolean;\n issueCount: number;\n incompleteTurns: number;\n brokenChains: number;\n checkpointHealthy: boolean;\n }> {\n const report = await this.analyzeIntegrity();\n const selectedSessions = sessionKey\n ? report.sessions.filter((session) => session.sessionKey === sessionKey)\n : report.sessions;\n const incompleteTurns = selectedSessions.reduce((sum, session) => sum + session.incompleteTurns, 0);\n const brokenChains = selectedSessions.reduce((sum, session) => sum + session.brokenChains, 0);\n const filteredIssues = report.issues.filter((issue) => !sessionKey || issue.sessionKey === sessionKey);\n const issueCount = filteredIssues.length;\n const severeIssueCount = filteredIssues.filter((issue) => issue.severity !== \"info\").length;\n return {\n generatedAt: report.generatedAt,\n sessionKey,\n healthy: sessionKey ? severeIssueCount === 0 && report.checkpoint.healthy : report.healthy,\n issueCount,\n incompleteTurns,\n brokenChains,\n checkpointHealthy: report.checkpoint.healthy,\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -46,18 +46,36 @@ async function fileExists(p) {
|
|
|
46
46
|
}
|
|
47
47
|
async function readManifest(memoryDir, sidecar, pagePath) {
|
|
48
48
|
const mp = manifestPath(memoryDir, sidecar, pagePath);
|
|
49
|
+
if (!await fileExists(mp)) {
|
|
50
|
+
return { pagePath, versions: [], currentVersion: "0" };
|
|
51
|
+
}
|
|
49
52
|
try {
|
|
50
53
|
const raw = await readFile(mp, "utf-8");
|
|
51
54
|
const parsed = JSON.parse(raw);
|
|
52
55
|
if (typeof parsed !== "object" || parsed === null) {
|
|
53
|
-
|
|
56
|
+
throw new Error("manifest root must be an object");
|
|
54
57
|
}
|
|
55
58
|
const obj = parsed;
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
if (!Array.isArray(obj.versions)) {
|
|
60
|
+
throw new Error("manifest versions must be an array");
|
|
61
|
+
}
|
|
62
|
+
const versions = obj.versions.map((entry, index) => {
|
|
63
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
64
|
+
throw new Error(`manifest version ${index} must be an object`);
|
|
65
|
+
}
|
|
66
|
+
const version = entry;
|
|
67
|
+
if (typeof version.versionId !== "string" || !/^\d+$/.test(version.versionId) || typeof version.timestamp !== "string" || typeof version.contentHash !== "string" || typeof version.sizeBytes !== "number" || !Number.isFinite(version.sizeBytes) || !["write", "consolidation", "revert", "manual"].includes(String(version.trigger))) {
|
|
68
|
+
throw new Error(`manifest version ${index} has invalid shape`);
|
|
69
|
+
}
|
|
70
|
+
return version;
|
|
71
|
+
});
|
|
72
|
+
if (typeof obj.currentVersion !== "string" || !/^\d+$/.test(obj.currentVersion)) {
|
|
73
|
+
throw new Error("manifest currentVersion must be a numeric string");
|
|
74
|
+
}
|
|
75
|
+
const currentVersion = obj.currentVersion;
|
|
58
76
|
return { pagePath: typeof obj.pagePath === "string" ? obj.pagePath : pagePath, versions, currentVersion };
|
|
59
|
-
} catch {
|
|
60
|
-
|
|
77
|
+
} catch (error) {
|
|
78
|
+
throw new Error(`page-versioning: invalid manifest ${mp}: ${error instanceof Error ? error.message : String(error)}`);
|
|
61
79
|
}
|
|
62
80
|
}
|
|
63
81
|
async function writeManifest(memoryDir, sidecar, pagePath, history) {
|
|
@@ -243,4 +261,4 @@ export {
|
|
|
243
261
|
revertToVersion,
|
|
244
262
|
diffVersions
|
|
245
263
|
};
|
|
246
|
-
//# sourceMappingURL=chunk-
|
|
264
|
+
//# sourceMappingURL=chunk-ALEPI75L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/page-versioning.ts"],"sourcesContent":["/**\n * Page-level versioning with history and revert (issue #371).\n *\n * Provides snapshot-based versioning for memory files using a sidecar\n * directory layout. Each memory page gets a `.versions/<pageName>/`\n * subdirectory containing numbered snapshots and a `manifest.json` that\n * records the version history.\n *\n * Storage layout:\n * memoryDir/\n * facts/preferences.md <- current file\n * .versions/\n * facts__preferences/\n * manifest.json <- VersionHistory\n * 1.md <- version 1 snapshot\n * 2.md <- version 2 snapshot\n */\n\nimport { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n access,\n mkdir,\n readFile,\n writeFile,\n unlink,\n} from \"node:fs/promises\";\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\nexport interface PageVersion {\n versionId: string;\n timestamp: string;\n contentHash: string;\n sizeBytes: number;\n trigger: VersionTrigger;\n note?: string;\n}\n\nexport type VersionTrigger = \"write\" | \"consolidation\" | \"revert\" | \"manual\";\n\nexport interface VersionHistory {\n pagePath: string;\n versions: PageVersion[];\n currentVersion: string;\n}\n\nexport interface VersioningConfig {\n enabled: boolean;\n maxVersionsPerPage: number;\n sidecarDir: string;\n}\n\n// ---------------------------------------------------------------------------\n// Logger interface (minimal, avoids coupling to the host logger)\n// ---------------------------------------------------------------------------\n\nexport interface VersioningLogger {\n debug(msg: string): void;\n warn(msg: string): void;\n}\n\nconst NOOP_LOGGER: VersioningLogger = {\n debug: () => {},\n warn: () => {},\n};\n\n// ---------------------------------------------------------------------------\n// Per-page write lock (promise-chain pattern, see gotcha #40)\n// ---------------------------------------------------------------------------\n\nconst writeLocks = new Map<string, Promise<void>>();\n\nfunction withPageLock<T>(pageKey: string, fn: () => Promise<T>): Promise<T> {\n const prev = writeLocks.get(pageKey) ?? Promise.resolve();\n const next = prev.then(fn, fn); // run fn after previous completes, even if previous failed\n writeLocks.set(pageKey, next.then(() => {}, () => {})); // recover chain per gotcha #40\n return next;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction contentHash(content: string): string {\n return createHash(\"sha256\").update(content, \"utf-8\").digest(\"hex\");\n}\n\n/**\n * Derive a filesystem-safe sidecar key from a page path relative to memoryDir.\n *\n * `facts/2026-01-15/pref-001.md` -> `facts__2026-01-15__pref-001`\n *\n * Exported so the `remnic doctor` consolidation-provenance check (issue\n * #561 PR 4) resolves snapshot locations using the canonical algorithm\n * without re-implementing it — preventing silent drift if the key\n * format ever changes.\n */\nexport function sidecarKey(pagePath: string): string {\n const withoutExt = pagePath.replace(/\\.md$/i, \"\");\n return withoutExt.replace(/[\\\\/]/g, \"__\");\n}\n\nfunction sidecarDir(memoryDir: string, sidecar: string, pagePath: string): string {\n return path.join(memoryDir, sidecar, sidecarKey(pagePath));\n}\n\nfunction manifestPath(memoryDir: string, sidecar: string, pagePath: string): string {\n return path.join(sidecarDir(memoryDir, sidecar, pagePath), \"manifest.json\");\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readManifest(\n memoryDir: string,\n sidecar: string,\n pagePath: string,\n): Promise<VersionHistory> {\n const mp = manifestPath(memoryDir, sidecar, pagePath);\n if (!(await fileExists(mp))) {\n return { pagePath, versions: [], currentVersion: \"0\" };\n }\n try {\n const raw = await readFile(mp, \"utf-8\");\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) {\n throw new Error(\"manifest root must be an object\");\n }\n const obj = parsed as Record<string, unknown>;\n if (!Array.isArray(obj.versions)) {\n throw new Error(\"manifest versions must be an array\");\n }\n const versions = obj.versions.map((entry, index) => {\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) {\n throw new Error(`manifest version ${index} must be an object`);\n }\n const version = entry as Record<string, unknown>;\n if (\n typeof version.versionId !== \"string\" ||\n !/^\\d+$/.test(version.versionId) ||\n typeof version.timestamp !== \"string\" ||\n typeof version.contentHash !== \"string\" ||\n typeof version.sizeBytes !== \"number\" ||\n !Number.isFinite(version.sizeBytes) ||\n ![\"write\", \"consolidation\", \"revert\", \"manual\"].includes(String(version.trigger))\n ) {\n throw new Error(`manifest version ${index} has invalid shape`);\n }\n return version as unknown as PageVersion;\n });\n if (typeof obj.currentVersion !== \"string\" || !/^\\d+$/.test(obj.currentVersion)) {\n throw new Error(\"manifest currentVersion must be a numeric string\");\n }\n const currentVersion = obj.currentVersion;\n return { pagePath: typeof obj.pagePath === \"string\" ? obj.pagePath : pagePath, versions, currentVersion };\n } catch (error) {\n throw new Error(`page-versioning: invalid manifest ${mp}: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\nasync function writeManifest(\n memoryDir: string,\n sidecar: string,\n pagePath: string,\n history: VersionHistory,\n): Promise<void> {\n const dir = sidecarDir(memoryDir, sidecar, pagePath);\n await mkdir(dir, { recursive: true });\n const mp = manifestPath(memoryDir, sidecar, pagePath);\n await writeFile(mp, JSON.stringify(history, null, 2) + \"\\n\", \"utf-8\");\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new version snapshot for a page.\n *\n * Call this BEFORE overwriting the current file so the previous content is\n * preserved. If the file does not exist yet (first write), the provided\n * `content` is snapshotted as version 1.\n *\n * Pruning: when the number of versions exceeds `config.maxVersionsPerPage`,\n * the oldest snapshots (and their files) are removed.\n */\nexport async function createVersion(\n pagePath: string,\n content: string,\n trigger: VersionTrigger,\n config: VersioningConfig,\n log: VersioningLogger = NOOP_LOGGER,\n note?: string,\n memoryDir?: string,\n): Promise<PageVersion> {\n const { sidecarDir: sidecar, maxVersionsPerPage } = config;\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const mPath = manifestPath(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n\n return withPageLock(mPath, async () => {\n const history = await readManifest(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n const nextId = String(history.versions.length > 0\n ? Math.max(...history.versions.map((v) => Number(v.versionId))) + 1\n : 1);\n\n const hash = contentHash(content);\n const version: PageVersion = {\n versionId: nextId,\n timestamp: new Date().toISOString(),\n contentHash: hash,\n sizeBytes: Buffer.byteLength(content, \"utf-8\"),\n trigger,\n ...(note !== undefined ? { note } : {}),\n };\n\n // Write snapshot file\n const dir = sidecarDir(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n await mkdir(dir, { recursive: true });\n const ext = path.extname(pagePath) || \".md\";\n const snapshotPath = path.join(dir, `${nextId}${ext}`);\n await writeFile(snapshotPath, content, \"utf-8\");\n\n history.versions.push(version);\n history.currentVersion = nextId;\n\n // Prune old versions if exceeding max\n if (maxVersionsPerPage > 0 && history.versions.length > maxVersionsPerPage) {\n const toRemove = history.versions.splice(0, history.versions.length - maxVersionsPerPage);\n for (const old of toRemove) {\n const oldPath = path.join(dir, `${old.versionId}${ext}`);\n try {\n await unlink(oldPath);\n } catch {\n log.debug(`page-versioning: could not remove old snapshot ${oldPath}`);\n }\n }\n }\n\n await writeManifest(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir), history);\n log.debug(`page-versioning: created version ${nextId} for ${pagePath} (trigger=${trigger})`);\n\n return version;\n });\n}\n\n/**\n * List all versions for a page.\n */\nexport async function listVersions(\n pagePath: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<VersionHistory> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const rel = relPath(pagePath, resolvedMemoryDir);\n const history = await readManifest(resolvedMemoryDir, config.sidecarDir, rel);\n // Sort ascending by versionId (numeric)\n history.versions.sort((a, b) => Number(a.versionId) - Number(b.versionId));\n return history;\n}\n\n/**\n * Read the content of a specific version.\n */\nexport async function getVersion(\n pagePath: string,\n versionId: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<string> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const rel = relPath(pagePath, resolvedMemoryDir);\n const ext = path.extname(pagePath) || \".md\";\n const dir = sidecarDir(resolvedMemoryDir, config.sidecarDir, rel);\n const snapshotPath = path.join(dir, `${versionId}${ext}`);\n\n if (!(await fileExists(snapshotPath))) {\n throw new Error(`Version ${versionId} not found for ${pagePath}`);\n }\n\n return readFile(snapshotPath, \"utf-8\");\n}\n\n/**\n * Revert a page to a previous version.\n *\n * 1. Reads the target version's content.\n * 2. Snapshots the CURRENT content as a new version (trigger: \"revert\").\n * 3. Writes the reverted content to the page file.\n *\n * Returns the newly created version entry for the revert snapshot.\n */\nexport async function revertToVersion(\n pagePath: string,\n versionId: string,\n config: VersioningConfig,\n log: VersioningLogger = NOOP_LOGGER,\n memoryDir?: string,\n): Promise<PageVersion> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n\n // Read target version content\n const targetContent = await getVersion(pagePath, versionId, config, resolvedMemoryDir);\n\n // Snapshot current content before overwriting\n let currentContent = \"\";\n try {\n currentContent = await readFile(pagePath, \"utf-8\");\n } catch {\n // File may not exist; that's okay\n }\n\n const version = await createVersion(\n pagePath,\n currentContent,\n \"revert\",\n config,\n log,\n `reverted to version ${versionId}`,\n resolvedMemoryDir,\n );\n\n // Write the reverted content to the actual page\n await writeFile(pagePath, targetContent, \"utf-8\");\n log.debug(`page-versioning: reverted ${pagePath} to version ${versionId}`);\n\n return version;\n}\n\n/**\n * Simple line-based diff between two versions.\n *\n * Returns a unified-style diff string showing added (+) and removed (-) lines.\n */\nexport async function diffVersions(\n pagePath: string,\n v1: string,\n v2: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<string> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const content1 = await getVersion(pagePath, v1, config, resolvedMemoryDir);\n const content2 = await getVersion(pagePath, v2, config, resolvedMemoryDir);\n\n const lines1 = content1.split(\"\\n\");\n const lines2 = content2.split(\"\\n\");\n\n const result: string[] = [];\n result.push(`--- version ${v1}`);\n result.push(`+++ version ${v2}`);\n\n // Simple LCS-based diff\n const lcs = computeLCS(lines1, lines2);\n let i = 0;\n let j = 0;\n let k = 0;\n\n while (k < lcs.length) {\n // Emit removed lines before the next common line\n while (i < lines1.length && lines1[i] !== lcs[k]) {\n result.push(`-${lines1[i]}`);\n i++;\n }\n // Emit added lines before the next common line\n while (j < lines2.length && lines2[j] !== lcs[k]) {\n result.push(`+${lines2[j]}`);\n j++;\n }\n // Common line\n result.push(` ${lcs[k]}`);\n i++;\n j++;\n k++;\n }\n // Remaining removed lines\n while (i < lines1.length) {\n result.push(`-${lines1[i]}`);\n i++;\n }\n // Remaining added lines\n while (j < lines2.length) {\n result.push(`+${lines2[j]}`);\n j++;\n }\n\n return result.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// LCS helper for diffVersions\n// ---------------------------------------------------------------------------\n\nfunction computeLCS(a: string[], b: string[]): string[] {\n const m = a.length;\n const n = b.length;\n // Build DP table\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array<number>(n + 1).fill(0));\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (a[i - 1] === b[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n } else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n }\n // Backtrack to build LCS\n const result: string[] = [];\n let i = m;\n let j = n;\n while (i > 0 && j > 0) {\n if (a[i - 1] === b[j - 1]) {\n result.unshift(a[i - 1]);\n i--;\n j--;\n } else if (dp[i - 1][j] > dp[i][j - 1]) {\n i--;\n } else {\n j--;\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Path helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy fallback: given an absolute page path, heuristically resolve the\n * memory directory by walking up past known subdirectory names.\n *\n * Callers should always pass an explicit `memoryDir` instead of relying on\n * this heuristic. It is retained only for backward compatibility when the\n * optional `memoryDir` parameter is omitted.\n */\nfunction resolveMemoryDir(pagePath: string): string {\n const knownSubdirs = new Set([\n \"facts\",\n \"corrections\",\n \"entities\",\n \"state\",\n \"artifacts\",\n \"questions\",\n \"profiles\",\n ]);\n\n let dir = path.dirname(pagePath);\n // Walk up past date directories (YYYY-MM-DD) and known subdirs\n for (let depth = 0; depth < 5; depth++) {\n const base = path.basename(dir);\n if (knownSubdirs.has(base) || /^\\d{4}-\\d{2}-\\d{2}$/.test(base)) {\n dir = path.dirname(dir);\n } else {\n break;\n }\n }\n return dir;\n}\n\n/**\n * Compute relative path of a page within its memory directory.\n */\nfunction relPath(pagePath: string, memoryDir: string): string {\n return path.relative(memoryDir, pagePath);\n}\n"],"mappings":";AAkBA,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AACjB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAsCP,IAAM,cAAgC;AAAA,EACpC,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,MAAM,MAAM;AAAA,EAAC;AACf;AAMA,IAAM,aAAa,oBAAI,IAA2B;AAElD,SAAS,aAAgB,SAAiB,IAAkC;AAC1E,QAAM,OAAO,WAAW,IAAI,OAAO,KAAK,QAAQ,QAAQ;AACxD,QAAM,OAAO,KAAK,KAAK,IAAI,EAAE;AAC7B,aAAW,IAAI,SAAS,KAAK,KAAK,MAAM;AAAA,EAAC,GAAG,MAAM;AAAA,EAAC,CAAC,CAAC;AACrD,SAAO;AACT;AAMA,SAAS,YAAY,SAAyB;AAC5C,SAAO,WAAW,QAAQ,EAAE,OAAO,SAAS,OAAO,EAAE,OAAO,KAAK;AACnE;AAYO,SAAS,WAAW,UAA0B;AACnD,QAAM,aAAa,SAAS,QAAQ,UAAU,EAAE;AAChD,SAAO,WAAW,QAAQ,UAAU,IAAI;AAC1C;AAEA,SAAS,WAAW,WAAmB,SAAiB,UAA0B;AAChF,SAAO,KAAK,KAAK,WAAW,SAAS,WAAW,QAAQ,CAAC;AAC3D;AAEA,SAAS,aAAa,WAAmB,SAAiB,UAA0B;AAClF,SAAO,KAAK,KAAK,WAAW,WAAW,SAAS,QAAQ,GAAG,eAAe;AAC5E;AAEA,eAAe,WAAW,GAA6B;AACrD,MAAI;AACF,UAAM,OAAO,CAAC;AACd,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,aACb,WACA,SACA,UACyB;AACzB,QAAM,KAAK,aAAa,WAAW,SAAS,QAAQ;AACpD,MAAI,CAAE,MAAM,WAAW,EAAE,GAAI;AAC3B,WAAO,EAAE,UAAU,UAAU,CAAC,GAAG,gBAAgB,IAAI;AAAA,EACvD;AACA,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,IAAI,OAAO;AACtC,UAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,QAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AACA,UAAM,MAAM;AACZ,QAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAChC,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AACA,UAAM,WAAW,IAAI,SAAS,IAAI,CAAC,OAAO,UAAU;AAClD,UAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,cAAM,IAAI,MAAM,oBAAoB,KAAK,oBAAoB;AAAA,MAC/D;AACA,YAAM,UAAU;AAChB,UACE,OAAO,QAAQ,cAAc,YAC7B,CAAC,QAAQ,KAAK,QAAQ,SAAS,KAC/B,OAAO,QAAQ,cAAc,YAC7B,OAAO,QAAQ,gBAAgB,YAC/B,OAAO,QAAQ,cAAc,YAC7B,CAAC,OAAO,SAAS,QAAQ,SAAS,KAClC,CAAC,CAAC,SAAS,iBAAiB,UAAU,QAAQ,EAAE,SAAS,OAAO,QAAQ,OAAO,CAAC,GAChF;AACA,cAAM,IAAI,MAAM,oBAAoB,KAAK,oBAAoB;AAAA,MAC/D;AACA,aAAO;AAAA,IACT,CAAC;AACD,QAAI,OAAO,IAAI,mBAAmB,YAAY,CAAC,QAAQ,KAAK,IAAI,cAAc,GAAG;AAC/E,YAAM,IAAI,MAAM,kDAAkD;AAAA,IACpE;AACA,UAAM,iBAAiB,IAAI;AAC3B,WAAO,EAAE,UAAU,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW,UAAU,UAAU,eAAe;AAAA,EAC1G,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,qCAAqC,EAAE,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAAA,EACtH;AACF;AAEA,eAAe,cACb,WACA,SACA,UACA,SACe;AACf,QAAM,MAAM,WAAW,WAAW,SAAS,QAAQ;AACnD,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,KAAK,aAAa,WAAW,SAAS,QAAQ;AACpD,QAAM,UAAU,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI,MAAM,OAAO;AACtE;AAgBA,eAAsB,cACpB,UACA,SACA,SACA,QACA,MAAwB,aACxB,MACA,WACsB;AACtB,QAAM,EAAE,YAAY,SAAS,mBAAmB,IAAI;AACpD,QAAM,oBAAoB,aAAa,iBAAiB,QAAQ;AAChE,QAAM,QAAQ,aAAa,mBAAmB,SAAS,QAAQ,UAAU,iBAAiB,CAAC;AAE3F,SAAO,aAAa,OAAO,YAAY;AACrC,UAAM,UAAU,MAAM,aAAa,mBAAmB,SAAS,QAAQ,UAAU,iBAAiB,CAAC;AACnG,UAAM,SAAS,OAAO,QAAQ,SAAS,SAAS,IAC5C,KAAK,IAAI,GAAG,QAAQ,SAAS,IAAI,CAAC,MAAM,OAAO,EAAE,SAAS,CAAC,CAAC,IAAI,IAChE,CAAC;AAEL,UAAM,OAAO,YAAY,OAAO;AAChC,UAAM,UAAuB;AAAA,MAC3B,WAAW;AAAA,MACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,aAAa;AAAA,MACb,WAAW,OAAO,WAAW,SAAS,OAAO;AAAA,MAC7C;AAAA,MACA,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IACvC;AAGA,UAAM,MAAM,WAAW,mBAAmB,SAAS,QAAQ,UAAU,iBAAiB,CAAC;AACvF,UAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,UAAM,MAAM,KAAK,QAAQ,QAAQ,KAAK;AACtC,UAAM,eAAe,KAAK,KAAK,KAAK,GAAG,MAAM,GAAG,GAAG,EAAE;AACrD,UAAM,UAAU,cAAc,SAAS,OAAO;AAE9C,YAAQ,SAAS,KAAK,OAAO;AAC7B,YAAQ,iBAAiB;AAGzB,QAAI,qBAAqB,KAAK,QAAQ,SAAS,SAAS,oBAAoB;AAC1E,YAAM,WAAW,QAAQ,SAAS,OAAO,GAAG,QAAQ,SAAS,SAAS,kBAAkB;AACxF,iBAAW,OAAO,UAAU;AAC1B,cAAM,UAAU,KAAK,KAAK,KAAK,GAAG,IAAI,SAAS,GAAG,GAAG,EAAE;AACvD,YAAI;AACF,gBAAM,OAAO,OAAO;AAAA,QACtB,QAAQ;AACN,cAAI,MAAM,kDAAkD,OAAO,EAAE;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc,mBAAmB,SAAS,QAAQ,UAAU,iBAAiB,GAAG,OAAO;AAC7F,QAAI,MAAM,oCAAoC,MAAM,QAAQ,QAAQ,aAAa,OAAO,GAAG;AAE3F,WAAO;AAAA,EACT,CAAC;AACH;AAKA,eAAsB,aACpB,UACA,QACA,WACyB;AACzB,QAAM,oBAAoB,aAAa,iBAAiB,QAAQ;AAChE,QAAM,MAAM,QAAQ,UAAU,iBAAiB;AAC/C,QAAM,UAAU,MAAM,aAAa,mBAAmB,OAAO,YAAY,GAAG;AAE5E,UAAQ,SAAS,KAAK,CAAC,GAAG,MAAM,OAAO,EAAE,SAAS,IAAI,OAAO,EAAE,SAAS,CAAC;AACzE,SAAO;AACT;AAKA,eAAsB,WACpB,UACA,WACA,QACA,WACiB;AACjB,QAAM,oBAAoB,aAAa,iBAAiB,QAAQ;AAChE,QAAM,MAAM,QAAQ,UAAU,iBAAiB;AAC/C,QAAM,MAAM,KAAK,QAAQ,QAAQ,KAAK;AACtC,QAAM,MAAM,WAAW,mBAAmB,OAAO,YAAY,GAAG;AAChE,QAAM,eAAe,KAAK,KAAK,KAAK,GAAG,SAAS,GAAG,GAAG,EAAE;AAExD,MAAI,CAAE,MAAM,WAAW,YAAY,GAAI;AACrC,UAAM,IAAI,MAAM,WAAW,SAAS,kBAAkB,QAAQ,EAAE;AAAA,EAClE;AAEA,SAAO,SAAS,cAAc,OAAO;AACvC;AAWA,eAAsB,gBACpB,UACA,WACA,QACA,MAAwB,aACxB,WACsB;AACtB,QAAM,oBAAoB,aAAa,iBAAiB,QAAQ;AAGhE,QAAM,gBAAgB,MAAM,WAAW,UAAU,WAAW,QAAQ,iBAAiB;AAGrF,MAAI,iBAAiB;AACrB,MAAI;AACF,qBAAiB,MAAM,SAAS,UAAU,OAAO;AAAA,EACnD,QAAQ;AAAA,EAER;AAEA,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,uBAAuB,SAAS;AAAA,IAChC;AAAA,EACF;AAGA,QAAM,UAAU,UAAU,eAAe,OAAO;AAChD,MAAI,MAAM,6BAA6B,QAAQ,eAAe,SAAS,EAAE;AAEzE,SAAO;AACT;AAOA,eAAsB,aACpB,UACA,IACA,IACA,QACA,WACiB;AACjB,QAAM,oBAAoB,aAAa,iBAAiB,QAAQ;AAChE,QAAM,WAAW,MAAM,WAAW,UAAU,IAAI,QAAQ,iBAAiB;AACzE,QAAM,WAAW,MAAM,WAAW,UAAU,IAAI,QAAQ,iBAAiB;AAEzE,QAAM,SAAS,SAAS,MAAM,IAAI;AAClC,QAAM,SAAS,SAAS,MAAM,IAAI;AAElC,QAAM,SAAmB,CAAC;AAC1B,SAAO,KAAK,eAAe,EAAE,EAAE;AAC/B,SAAO,KAAK,eAAe,EAAE,EAAE;AAG/B,QAAM,MAAM,WAAW,QAAQ,MAAM;AACrC,MAAI,IAAI;AACR,MAAI,IAAI;AACR,MAAI,IAAI;AAER,SAAO,IAAI,IAAI,QAAQ;AAErB,WAAO,IAAI,OAAO,UAAU,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG;AAChD,aAAO,KAAK,IAAI,OAAO,CAAC,CAAC,EAAE;AAC3B;AAAA,IACF;AAEA,WAAO,IAAI,OAAO,UAAU,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG;AAChD,aAAO,KAAK,IAAI,OAAO,CAAC,CAAC,EAAE;AAC3B;AAAA,IACF;AAEA,WAAO,KAAK,IAAI,IAAI,CAAC,CAAC,EAAE;AACxB;AACA;AACA;AAAA,EACF;AAEA,SAAO,IAAI,OAAO,QAAQ;AACxB,WAAO,KAAK,IAAI,OAAO,CAAC,CAAC,EAAE;AAC3B;AAAA,EACF;AAEA,SAAO,IAAI,OAAO,QAAQ;AACxB,WAAO,KAAK,IAAI,OAAO,CAAC,CAAC,EAAE;AAC3B;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,IAAI;AACzB;AAMA,SAAS,WAAW,GAAa,GAAuB;AACtD,QAAM,IAAI,EAAE;AACZ,QAAM,IAAI,EAAE;AAEZ,QAAM,KAAiB,MAAM,KAAK,EAAE,QAAQ,IAAI,EAAE,GAAG,MAAM,IAAI,MAAc,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;AAC3F,WAASA,KAAI,GAAGA,MAAK,GAAGA,MAAK;AAC3B,aAASC,KAAI,GAAGA,MAAK,GAAGA,MAAK;AAC3B,UAAI,EAAED,KAAI,CAAC,MAAM,EAAEC,KAAI,CAAC,GAAG;AACzB,WAAGD,EAAC,EAAEC,EAAC,IAAI,GAAGD,KAAI,CAAC,EAAEC,KAAI,CAAC,IAAI;AAAA,MAChC,OAAO;AACL,WAAGD,EAAC,EAAEC,EAAC,IAAI,KAAK,IAAI,GAAGD,KAAI,CAAC,EAAEC,EAAC,GAAG,GAAGD,EAAC,EAAEC,KAAI,CAAC,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAmB,CAAC;AAC1B,MAAI,IAAI;AACR,MAAI,IAAI;AACR,SAAO,IAAI,KAAK,IAAI,GAAG;AACrB,QAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG;AACzB,aAAO,QAAQ,EAAE,IAAI,CAAC,CAAC;AACvB;AACA;AAAA,IACF,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG;AACtC;AAAA,IACF,OAAO;AACL;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAcA,SAAS,iBAAiB,UAA0B;AAClD,QAAM,eAAe,oBAAI,IAAI;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,MAAM,KAAK,QAAQ,QAAQ;AAE/B,WAAS,QAAQ,GAAG,QAAQ,GAAG,SAAS;AACtC,UAAM,OAAO,KAAK,SAAS,GAAG;AAC9B,QAAI,aAAa,IAAI,IAAI,KAAK,sBAAsB,KAAK,IAAI,GAAG;AAC9D,YAAM,KAAK,QAAQ,GAAG;AAAA,IACxB,OAAO;AACL;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,QAAQ,UAAkB,WAA2B;AAC5D,SAAO,KAAK,SAAS,WAAW,QAAQ;AAC1C;","names":["i","j"]}
|
|
@@ -3,6 +3,12 @@ import {
|
|
|
3
3
|
} from "./chunk-Y4Z4I6WK.js";
|
|
4
4
|
|
|
5
5
|
// src/graph-dashboard-diff.ts
|
|
6
|
+
function compareGraphEdges(a, b) {
|
|
7
|
+
return a.type.localeCompare(b.type) || a.from.localeCompare(b.from) || a.to.localeCompare(b.to);
|
|
8
|
+
}
|
|
9
|
+
function edgeFieldsChanged(previous, next) {
|
|
10
|
+
return previous.weight !== next.weight || (previous.confidence ?? 1) !== (next.confidence ?? 1) || (previous.lastReinforcedAt ?? null) !== (next.lastReinforcedAt ?? null);
|
|
11
|
+
}
|
|
6
12
|
function diffGraphSnapshots(previous, next) {
|
|
7
13
|
const prevNodeSet = new Set(previous.nodes.map((node) => node.id));
|
|
8
14
|
const nextNodeSet = new Set(next.nodes.map((node) => node.id));
|
|
@@ -10,17 +16,22 @@ function diffGraphSnapshots(previous, next) {
|
|
|
10
16
|
const nextEdges = new Map(next.edges.map((edge) => [graphEdgeKey(edge), edge]));
|
|
11
17
|
const addedNodes = [...nextNodeSet].filter((id) => !prevNodeSet.has(id)).sort((a, b) => a.localeCompare(b));
|
|
12
18
|
const removedNodes = [...prevNodeSet].filter((id) => !nextNodeSet.has(id)).sort((a, b) => a.localeCompare(b));
|
|
13
|
-
const addedEdges = [...nextEdges.entries()].filter(([key]) => !prevEdges.has(key)).map(([, edge]) => edge).sort(
|
|
14
|
-
const removedEdges = [...prevEdges.entries()].filter(([key]) => !nextEdges.has(key)).map(([, edge]) => edge).sort(
|
|
19
|
+
const addedEdges = [...nextEdges.entries()].filter(([key]) => !prevEdges.has(key)).map(([, edge]) => edge).sort(compareGraphEdges);
|
|
20
|
+
const removedEdges = [...prevEdges.entries()].filter(([key]) => !nextEdges.has(key)).map(([, edge]) => edge).sort(compareGraphEdges);
|
|
21
|
+
const updatedEdges = [...nextEdges.entries()].flatMap(([key, nextEdge]) => {
|
|
22
|
+
const previousEdge = prevEdges.get(key);
|
|
23
|
+
return previousEdge && edgeFieldsChanged(previousEdge, nextEdge) ? [{ previous: previousEdge, next: nextEdge }] : [];
|
|
24
|
+
}).sort((a, b) => compareGraphEdges(a.next, b.next));
|
|
15
25
|
return {
|
|
16
26
|
addedNodes,
|
|
17
27
|
removedNodes,
|
|
18
28
|
addedEdges,
|
|
19
|
-
removedEdges
|
|
29
|
+
removedEdges,
|
|
30
|
+
updatedEdges
|
|
20
31
|
};
|
|
21
32
|
}
|
|
22
33
|
|
|
23
34
|
export {
|
|
24
35
|
diffGraphSnapshots
|
|
25
36
|
};
|
|
26
|
-
//# sourceMappingURL=chunk-
|
|
37
|
+
//# sourceMappingURL=chunk-AUDJPF4N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graph-dashboard-diff.ts"],"sourcesContent":["import type { GraphEdge } from \"./graph.js\";\nimport { graphEdgeKey } from \"./graph-dashboard-key.js\";\nimport type { GraphSnapshot } from \"./graph-dashboard-parser.js\";\n\nexport interface GraphPatch {\n addedNodes: string[];\n removedNodes: string[];\n addedEdges: GraphEdge[];\n removedEdges: GraphEdge[];\n updatedEdges: Array<{ previous: GraphEdge; next: GraphEdge }>;\n}\n\nfunction compareGraphEdges(a: GraphEdge, b: GraphEdge): number {\n return a.type.localeCompare(b.type) || a.from.localeCompare(b.from) || a.to.localeCompare(b.to);\n}\n\nfunction edgeFieldsChanged(previous: GraphEdge, next: GraphEdge): boolean {\n return (\n previous.weight !== next.weight ||\n (previous.confidence ?? 1) !== (next.confidence ?? 1) ||\n (previous.lastReinforcedAt ?? null) !== (next.lastReinforcedAt ?? null)\n );\n}\n\nexport function diffGraphSnapshots(previous: GraphSnapshot, next: GraphSnapshot): GraphPatch {\n const prevNodeSet = new Set(previous.nodes.map((node) => node.id));\n const nextNodeSet = new Set(next.nodes.map((node) => node.id));\n const prevEdges = new Map(previous.edges.map((edge) => [graphEdgeKey(edge), edge]));\n const nextEdges = new Map(next.edges.map((edge) => [graphEdgeKey(edge), edge]));\n\n const addedNodes = [...nextNodeSet].filter((id) => !prevNodeSet.has(id)).sort((a, b) => a.localeCompare(b));\n const removedNodes = [...prevNodeSet].filter((id) => !nextNodeSet.has(id)).sort((a, b) => a.localeCompare(b));\n const addedEdges = [...nextEdges.entries()]\n .filter(([key]) => !prevEdges.has(key))\n .map(([, edge]) => edge)\n .sort(compareGraphEdges);\n const removedEdges = [...prevEdges.entries()]\n .filter(([key]) => !nextEdges.has(key))\n .map(([, edge]) => edge)\n .sort(compareGraphEdges);\n const updatedEdges = [...nextEdges.entries()]\n .flatMap(([key, nextEdge]) => {\n const previousEdge = prevEdges.get(key);\n return previousEdge && edgeFieldsChanged(previousEdge, nextEdge)\n ? [{ previous: previousEdge, next: nextEdge }]\n : [];\n })\n .sort((a, b) => compareGraphEdges(a.next, b.next));\n\n return {\n addedNodes,\n removedNodes,\n addedEdges,\n removedEdges,\n updatedEdges,\n };\n}\n"],"mappings":";;;;;AAYA,SAAS,kBAAkB,GAAc,GAAsB;AAC7D,SAAO,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,KAAK,cAAc,EAAE,IAAI,KAAK,EAAE,GAAG,cAAc,EAAE,EAAE;AAChG;AAEA,SAAS,kBAAkB,UAAqB,MAA0B;AACxE,SACE,SAAS,WAAW,KAAK,WACxB,SAAS,cAAc,QAAQ,KAAK,cAAc,OAClD,SAAS,oBAAoB,WAAW,KAAK,oBAAoB;AAEtE;AAEO,SAAS,mBAAmB,UAAyB,MAAiC;AAC3F,QAAM,cAAc,IAAI,IAAI,SAAS,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AACjE,QAAM,cAAc,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAC7D,QAAM,YAAY,IAAI,IAAI,SAAS,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,GAAG,IAAI,CAAC,CAAC;AAClF,QAAM,YAAY,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,GAAG,IAAI,CAAC,CAAC;AAE9E,QAAM,aAAa,CAAC,GAAG,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAC1G,QAAM,eAAe,CAAC,GAAG,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAC5G,QAAM,aAAa,CAAC,GAAG,UAAU,QAAQ,CAAC,EACvC,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,IAAI,GAAG,CAAC,EACrC,IAAI,CAAC,CAAC,EAAE,IAAI,MAAM,IAAI,EACtB,KAAK,iBAAiB;AACzB,QAAM,eAAe,CAAC,GAAG,UAAU,QAAQ,CAAC,EACzC,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,IAAI,GAAG,CAAC,EACrC,IAAI,CAAC,CAAC,EAAE,IAAI,MAAM,IAAI,EACtB,KAAK,iBAAiB;AACzB,QAAM,eAAe,CAAC,GAAG,UAAU,QAAQ,CAAC,EACzC,QAAQ,CAAC,CAAC,KAAK,QAAQ,MAAM;AAC5B,UAAM,eAAe,UAAU,IAAI,GAAG;AACtC,WAAO,gBAAgB,kBAAkB,cAAc,QAAQ,IAC3D,CAAC,EAAE,UAAU,cAAc,MAAM,SAAS,CAAC,IAC3C,CAAC;AAAA,EACP,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,kBAAkB,EAAE,MAAM,EAAE,IAAI,CAAC;AAEnD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|