@remnic/core 1.1.12 → 1.1.13
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/access-cli.d.ts +2 -1
- package/dist/access-cli.js +263 -82
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +26 -60
- package/dist/access-http.js +43 -29
- package/dist/access-mcp.d.ts +24 -6
- package/dist/access-mcp.js +35 -28
- package/dist/access-schema.d.ts +9 -6
- package/dist/access-schema.js +7 -5
- package/dist/access-service-DcCDmNYC.d.ts +1542 -0
- package/dist/access-service.d.ts +25 -7
- package/dist/access-service.js +33 -26
- package/dist/active-memory-bridge.js +2 -2
- package/dist/active-recall.js +11 -3
- package/dist/active-recall.js.map +1 -1
- package/dist/adapters/claude-code.d.ts +24 -0
- package/dist/adapters/claude-code.js +9 -0
- package/dist/adapters/codex.d.ts +25 -0
- package/dist/adapters/codex.js +9 -0
- package/dist/adapters/hermes.d.ts +35 -0
- package/dist/adapters/hermes.js +9 -0
- package/dist/adapters/index.d.ts +6 -0
- package/dist/adapters/index.js +26 -0
- package/dist/adapters/registry.d.ts +20 -0
- package/dist/adapters/registry.js +13 -0
- package/dist/adapters/replit.d.ts +28 -0
- package/dist/adapters/replit.js +9 -0
- package/dist/adapters/types.d.ts +43 -0
- package/dist/adapters/types.js +8 -0
- package/dist/bootstrap.d.ts +20 -5
- package/dist/boxes.d.ts +7 -0
- package/dist/boxes.js +1 -1
- package/dist/briefing.d.ts +5 -3
- package/dist/briefing.js +9 -6
- package/dist/buffer-surprise-report.js +1 -1
- package/dist/buffer.d.ts +18 -4
- package/dist/buffer.js +1 -1
- package/dist/calibration.js +4 -4
- package/dist/capsule-cli.d.ts +4 -4
- package/dist/capsule-cli.js +1 -1
- package/dist/capsule-crypto-5CYAGVC5.js +18 -0
- package/dist/capsule-merge-4MGKE7C5.js +189 -0
- package/dist/causal-behavior.d.ts +8 -28
- package/dist/causal-behavior.js +6 -3
- package/dist/causal-behavior.js.map +1 -1
- package/dist/causal-chain.js +3 -2
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +24 -13
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +3 -3
- package/dist/causal-trajectory.js +1 -1
- package/dist/chunk-25MQ7IHJ.js +427 -0
- package/dist/chunk-25MQ7IHJ.js.map +1 -0
- package/dist/chunk-2F2W355T.js +256 -0
- package/dist/chunk-2F2W355T.js.map +1 -0
- package/dist/chunk-2KI4QFHU.js +228 -0
- package/dist/chunk-2KI4QFHU.js.map +1 -0
- package/dist/chunk-2PRQG7PV.js +86 -0
- package/dist/chunk-2PRQG7PV.js.map +1 -0
- package/dist/chunk-2QR3XXIC.js +2272 -0
- package/dist/chunk-2QR3XXIC.js.map +1 -0
- package/dist/chunk-2WWLHTZY.js +121 -0
- package/dist/chunk-326G7DJK.js +2185 -0
- package/dist/chunk-326G7DJK.js.map +1 -0
- package/dist/chunk-34DQE4KF.js +174 -0
- package/dist/chunk-34DQE4KF.js.map +1 -0
- package/dist/chunk-3APJ5EVB.js +601 -0
- package/dist/chunk-3APJ5EVB.js.map +1 -0
- package/dist/chunk-3HPAPHUK.js +51 -0
- package/dist/chunk-3HPAPHUK.js.map +1 -0
- package/dist/chunk-3JXBXXM2.js +69 -0
- package/dist/chunk-3JXBXXM2.js.map +1 -0
- package/dist/chunk-3KW65B36.js +681 -0
- package/dist/chunk-3KW65B36.js.map +1 -0
- package/dist/chunk-3UXOZBHV.js +20 -0
- package/dist/chunk-3UXOZBHV.js.map +1 -0
- package/dist/chunk-3VAL7ZL2.js +266 -0
- package/dist/chunk-3VAL7ZL2.js.map +1 -0
- package/dist/chunk-3Y4P7RXM.js +31 -0
- package/dist/chunk-3Y4P7RXM.js.map +1 -0
- package/dist/chunk-47VWKCAF.js +273 -0
- package/dist/chunk-47VWKCAF.js.map +1 -0
- package/dist/chunk-4CRG46BG.js +271 -0
- package/dist/chunk-5375UYTQ.js +914 -0
- package/dist/chunk-5375UYTQ.js.map +1 -0
- package/dist/chunk-56K5QLHX.js +506 -0
- package/dist/chunk-56K5QLHX.js.map +1 -0
- package/dist/chunk-5RGLBDQF.js +596 -0
- package/dist/chunk-5RGLBDQF.js.map +1 -0
- package/dist/chunk-5UZXUTVO.js +9 -0
- package/dist/chunk-5UZXUTVO.js.map +1 -0
- package/dist/chunk-65PG43EQ.js +105 -0
- package/dist/chunk-65PG43EQ.js.map +1 -0
- package/dist/chunk-66DHUKLO.js +57 -0
- package/dist/chunk-66DHUKLO.js.map +1 -0
- package/dist/chunk-6FC5EGNV.js +46 -0
- package/dist/chunk-6FC5EGNV.js.map +1 -0
- package/dist/chunk-6H2TESSP.js +62 -0
- package/dist/chunk-6H2TESSP.js.map +1 -0
- package/dist/chunk-6LVVDPJ4.js +32 -0
- package/dist/chunk-6LVVDPJ4.js.map +1 -0
- package/dist/chunk-6RVI47ZR.js +159 -0
- package/dist/chunk-6RVI47ZR.js.map +1 -0
- package/dist/chunk-7AAT6G4Q.js +5117 -0
- package/dist/chunk-7AAT6G4Q.js.map +1 -0
- package/dist/chunk-7DTASS5T.js +29 -0
- package/dist/chunk-7DTASS5T.js.map +1 -0
- package/dist/chunk-7IASACLB.js +596 -0
- package/dist/chunk-7MNMYOFP.js +32 -0
- package/dist/chunk-7MNMYOFP.js.map +1 -0
- package/dist/chunk-7N4KAIGN.js +133 -0
- package/dist/chunk-7N4KAIGN.js.map +1 -0
- package/dist/chunk-7OZ53EXP.js +101 -0
- package/dist/chunk-7OZ53EXP.js.map +1 -0
- package/dist/chunk-7XYTQGCC.js +134 -0
- package/dist/chunk-7XYTQGCC.js.map +1 -0
- package/dist/chunk-A2XUIMJ3.js +341 -0
- package/dist/chunk-A2XUIMJ3.js.map +1 -0
- package/dist/chunk-AGZQD76C.js +201 -0
- package/dist/chunk-AGZQD76C.js.map +1 -0
- package/dist/chunk-APO3DCMU.js +361 -0
- package/dist/chunk-APO3DCMU.js.map +1 -0
- package/dist/chunk-BFBF3XEF.js +283 -0
- package/dist/chunk-BFBF3XEF.js.map +1 -0
- package/dist/chunk-BJ3KMYTB.js +1974 -0
- package/dist/chunk-BJ3KMYTB.js.map +1 -0
- package/dist/chunk-CHEL3SKB.js +6758 -0
- package/dist/chunk-CHEL3SKB.js.map +1 -0
- package/dist/chunk-CQZRLNMV.js +1491 -0
- package/dist/chunk-CQZRLNMV.js.map +1 -0
- package/dist/chunk-D46YSIYX.js +892 -0
- package/dist/chunk-D46YSIYX.js.map +1 -0
- package/dist/chunk-DINWEURR.js +648 -0
- package/dist/chunk-DINWEURR.js.map +1 -0
- package/dist/chunk-DK5LDEQM.js +530 -0
- package/dist/chunk-DK5LDEQM.js.map +1 -0
- package/dist/chunk-DOM4GKSW.js +34 -0
- package/dist/chunk-DOM4GKSW.js.map +1 -0
- package/dist/chunk-EDTHC6UD.js +1075 -0
- package/dist/chunk-EFJ3MQ4V.js +721 -0
- package/dist/chunk-EHRTFRWW.js +89 -0
- package/dist/chunk-EHRTFRWW.js.map +1 -0
- package/dist/chunk-FAJ7FZYM.js +11 -0
- package/dist/chunk-FAJ7FZYM.js.map +1 -0
- package/dist/chunk-FBYESMQ2.js +570 -0
- package/dist/chunk-FDU6HUUL.js +147 -0
- package/dist/chunk-FF4KLI5W.js +99 -0
- package/dist/chunk-FF4KLI5W.js.map +1 -0
- package/dist/chunk-FIT6DMX6.js +310 -0
- package/dist/chunk-FIT6DMX6.js.map +1 -0
- package/dist/chunk-FJ43PRLT.js +272 -0
- package/dist/chunk-FJ43PRLT.js.map +1 -0
- package/dist/chunk-FKFMOY3N.js +32 -0
- package/dist/chunk-FKFMOY3N.js.map +1 -0
- package/dist/chunk-FLTNHQK6.js +262 -0
- package/dist/chunk-FLTNHQK6.js.map +1 -0
- package/dist/chunk-GA454ALV.js +12436 -0
- package/dist/chunk-GA454ALV.js.map +1 -0
- package/dist/chunk-GGKRUQOO.js +228 -0
- package/dist/chunk-GIF42EW3.js +63 -0
- package/dist/chunk-GIF42EW3.js.map +1 -0
- package/dist/chunk-GL6I6MEQ.js +647 -0
- package/dist/chunk-H3ME6L6D.js +709 -0
- package/dist/chunk-H3ME6L6D.js.map +1 -0
- package/dist/chunk-HHLLAQGZ.js +1 -0
- package/dist/chunk-HXXBL2KD.js +2040 -0
- package/dist/chunk-I5V2VDIW.js +219 -0
- package/dist/chunk-I5V2VDIW.js.map +1 -0
- package/dist/chunk-I6K5FBRQ.js +35 -0
- package/dist/chunk-I6K5FBRQ.js.map +1 -0
- package/dist/chunk-ICRIXAP2.js +121 -0
- package/dist/chunk-ICRIXAP2.js.map +1 -0
- package/dist/chunk-J4EB7DNW.js +11 -0
- package/dist/chunk-J4EB7DNW.js.map +1 -0
- package/dist/chunk-JLFA7DQG.js +62 -0
- package/dist/chunk-JLFA7DQG.js.map +1 -0
- package/dist/chunk-KJTKLXTH.js +9 -0
- package/dist/chunk-KJTKLXTH.js.map +1 -0
- package/dist/chunk-KLAO5DGL.js +917 -0
- package/dist/chunk-KLAO5DGL.js.map +1 -0
- package/dist/chunk-KNKUID7G.js +183 -0
- package/dist/chunk-KOSORCJG.js +624 -0
- package/dist/chunk-KOSORCJG.js.map +1 -0
- package/dist/chunk-KUJVMMZQ.js +1262 -0
- package/dist/chunk-KUJVMMZQ.js.map +1 -0
- package/dist/chunk-LCR46JY5.js +123 -0
- package/dist/chunk-LCR46JY5.js.map +1 -0
- package/dist/chunk-LLQ2LLWF.js +148 -0
- package/dist/chunk-LLQ2LLWF.js.map +1 -0
- package/dist/chunk-LPMVBPA3.js +236 -0
- package/dist/chunk-LT3NLYSI.js +50 -0
- package/dist/chunk-LT3NLYSI.js.map +1 -0
- package/dist/chunk-LUDTDZLK.js +287 -0
- package/dist/chunk-LUDTDZLK.js.map +1 -0
- package/dist/chunk-M23FSH32.js +3963 -0
- package/dist/chunk-M23FSH32.js.map +1 -0
- package/dist/chunk-MC26UJIM.js +118 -0
- package/dist/chunk-ME6ESPZU.js +119 -0
- package/dist/chunk-ME6ESPZU.js.map +1 -0
- package/dist/chunk-MGKYQQYF.js +272 -0
- package/dist/chunk-MJFNCJXV.js +66 -0
- package/dist/chunk-MJFNCJXV.js.map +1 -0
- package/dist/chunk-MSWG7JI6.js +237 -0
- package/dist/chunk-MSWG7JI6.js.map +1 -0
- package/dist/chunk-MT25YHYH.js +141 -0
- package/dist/chunk-MT25YHYH.js.map +1 -0
- package/dist/chunk-MT4HVDUZ.js +53 -0
- package/dist/chunk-MY6TPVXW.js +219 -0
- package/dist/chunk-N2D6GXBM.js +267 -0
- package/dist/chunk-N2D6GXBM.js.map +1 -0
- package/dist/chunk-NJ3MJQZX.js +46 -0
- package/dist/chunk-NJ3MJQZX.js.map +1 -0
- package/dist/chunk-NMZY542O.js +335 -0
- package/dist/chunk-NMZY542O.js.map +1 -0
- package/dist/chunk-NNVTUXEB.js +23 -0
- package/dist/chunk-NZL6GGQE.js +375 -0
- package/dist/chunk-NZL6GGQE.js.map +1 -0
- package/dist/chunk-P4NEIHUT.js +108 -0
- package/dist/chunk-P7FMDTKL.js +103 -0
- package/dist/chunk-P7FMDTKL.js.map +1 -0
- package/dist/chunk-PHK3HARR.js +32 -0
- package/dist/chunk-PHK3HARR.js.map +1 -0
- package/dist/chunk-PIRJPV5T.js +98 -0
- package/dist/chunk-PIRJPV5T.js.map +1 -0
- package/dist/chunk-PK7H5L6Y.js +159 -0
- package/dist/chunk-PK7H5L6Y.js.map +1 -0
- package/dist/chunk-PR5FBTFU.js +233 -0
- package/dist/chunk-PR5FBTFU.js.map +1 -0
- package/dist/chunk-PU63GXWS.js +174 -0
- package/dist/chunk-PU63GXWS.js.map +1 -0
- package/dist/chunk-PZIAX57I.js +124 -0
- package/dist/chunk-PZIAX57I.js.map +1 -0
- package/dist/chunk-Q7P4WJDP.js +26 -0
- package/dist/chunk-Q7P4WJDP.js.map +1 -0
- package/dist/chunk-QQUAB63I.js +63 -0
- package/dist/chunk-QQUAB63I.js.map +1 -0
- package/dist/chunk-QRNI5JBH.js +18 -0
- package/dist/chunk-RHY3HH7P.js +601 -0
- package/dist/chunk-RHY3HH7P.js.map +1 -0
- package/dist/chunk-RRF5UOBJ.js +91 -0
- package/dist/chunk-RXDLTSWT.js +124 -0
- package/dist/chunk-RXDLTSWT.js.map +1 -0
- package/dist/chunk-RYED3SPJ.js +42 -0
- package/dist/chunk-RYED3SPJ.js.map +1 -0
- package/dist/chunk-S7KDBTWT.js +106 -0
- package/dist/chunk-S7KDBTWT.js.map +1 -0
- package/dist/chunk-SEDEKFYQ.js +1 -0
- package/dist/chunk-TECVW3JP.js +36 -0
- package/dist/chunk-TECVW3JP.js.map +1 -0
- package/dist/chunk-TFO23QT4.js +88 -0
- package/dist/chunk-TFO23QT4.js.map +1 -0
- package/dist/chunk-TK4UEOSK.js +76 -0
- package/dist/chunk-TK4UEOSK.js.map +1 -0
- package/dist/chunk-TKWGAOLV.js +122 -0
- package/dist/chunk-TKWGAOLV.js.map +1 -0
- package/dist/chunk-TMM4S4IJ.js +597 -0
- package/dist/chunk-TMM4S4IJ.js.map +1 -0
- package/dist/chunk-TMQLARTH.js +188 -0
- package/dist/chunk-TMQLARTH.js.map +1 -0
- package/dist/chunk-TPDBFYEG.js +130 -0
- package/dist/chunk-TPDBFYEG.js.map +1 -0
- package/dist/chunk-TPMQ3G6Z.js +145 -0
- package/dist/chunk-TPMQ3G6Z.js.map +1 -0
- package/dist/chunk-TZOLIGIG.js +61 -0
- package/dist/chunk-TZOLIGIG.js.map +1 -0
- package/dist/chunk-U3PN77QT.js +113 -0
- package/dist/chunk-U3WSW6PZ.js +277 -0
- package/dist/chunk-U4SCL7B7.js +640 -0
- package/dist/chunk-U4SCL7B7.js.map +1 -0
- package/dist/chunk-UWK5OXUJ.js +156 -0
- package/dist/chunk-UWK5OXUJ.js.map +1 -0
- package/dist/chunk-UWVJF25J.js +74 -0
- package/dist/chunk-UXHQAFNA.js +1317 -0
- package/dist/chunk-UXHQAFNA.js.map +1 -0
- package/dist/chunk-V5OCT34X.js +1 -0
- package/dist/chunk-VLXA6PI2.js +304 -0
- package/dist/chunk-VLXA6PI2.js.map +1 -0
- package/dist/chunk-VNO6ZJ35.js +500 -0
- package/dist/chunk-VNO6ZJ35.js.map +1 -0
- package/dist/chunk-VW676BEI.js +827 -0
- package/dist/chunk-VW676BEI.js.map +1 -0
- package/dist/chunk-W3LR522O.js +2296 -0
- package/dist/chunk-W4L6CZKA.js +96 -0
- package/dist/chunk-W4L6CZKA.js.map +1 -0
- package/dist/chunk-W4RVMTHR.js +372 -0
- package/dist/chunk-W4RVMTHR.js.map +1 -0
- package/dist/chunk-WEHSQBFR.js +188 -0
- package/dist/chunk-WEHSQBFR.js.map +1 -0
- package/dist/chunk-WELDCG6C.js +380 -0
- package/dist/chunk-WELDCG6C.js.map +1 -0
- package/dist/chunk-WZYKANL3.js +2800 -0
- package/dist/chunk-WZYKANL3.js.map +1 -0
- package/dist/chunk-XIG5PDM7.js +48 -0
- package/dist/chunk-XJNBEDFE.js +193 -0
- package/dist/chunk-XJNBEDFE.js.map +1 -0
- package/dist/chunk-XVVIG67A.js +291 -0
- package/dist/chunk-XVVIG67A.js.map +1 -0
- package/dist/chunk-XVZ7B3HG.js +135 -0
- package/dist/chunk-YBPYIAA5.js +73 -0
- package/dist/chunk-YBPYIAA5.js.map +1 -0
- package/dist/chunk-Z734BLO3.js +21 -0
- package/dist/chunk-Z734BLO3.js.map +1 -0
- package/dist/chunk-ZKSK55RC.js +269 -0
- package/dist/chunk-ZKSK55RC.js.map +1 -0
- package/dist/chunk-ZTFCYYEZ.js +69 -0
- package/dist/chunk-ZTFCYYEZ.js.map +1 -0
- package/dist/chunk-ZY2MNJR6.js +329 -0
- package/dist/chunk-ZY2MNJR6.js.map +1 -0
- package/dist/cli-D3VpkVwB.d.ts +1136 -0
- package/dist/cli.d.ts +39 -10
- package/dist/cli.js +108 -49
- package/dist/commitment-ledger.js +1 -1
- package/dist/compat/checks.d.ts +5 -0
- package/dist/compat/checks.js +11 -0
- package/dist/compat/checks.js.map +1 -0
- package/dist/compat/types.d.ts +30 -0
- package/dist/compat/types.js +1 -0
- package/dist/compat/types.js.map +1 -0
- package/dist/compounding/engine.d.ts +221 -0
- package/dist/compounding/engine.js +32 -0
- package/dist/compounding/engine.js.map +1 -0
- package/dist/compounding/preference-consolidator.d.ts +92 -0
- package/dist/compounding/preference-consolidator.js +553 -0
- package/dist/compounding/preference-consolidator.js.map +1 -0
- package/dist/config.d.ts +4 -2
- package/dist/config.js +9 -4
- package/dist/conflict-policy-DyJ2wd-h.d.ts +4 -0
- package/dist/connectors/codex-materialize-runner.d.ts +64 -0
- package/dist/connectors/codex-materialize-runner.js +33 -0
- package/dist/connectors/codex-materialize-runner.js.map +1 -0
- package/dist/connectors/codex-materialize.d.ts +195 -0
- package/dist/connectors/codex-materialize.js +38 -0
- package/dist/connectors/codex-materialize.js.map +1 -0
- package/dist/connectors/index.d.ts +444 -0
- package/dist/connectors/index.js +115 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors-cli-CwbyjGR7.d.ts +257 -0
- package/dist/connectors-cli.d.ts +1 -1
- package/dist/consolidation-provenance-check.d.ts +3 -1
- package/dist/consolidation-undo.d.ts +3 -1
- package/dist/contradiction/index.d.ts +258 -0
- package/dist/contradiction/index.js +43 -0
- package/dist/contradiction/index.js.map +1 -0
- package/dist/contradiction-review-ATP4S6IC.js +30 -0
- package/dist/contradiction-review-ATP4S6IC.js.map +1 -0
- package/dist/contradiction-scan-5A4IDZV5.js +13 -0
- package/dist/contradiction-scan-5A4IDZV5.js.map +1 -0
- package/dist/conversation-index/backend.d.ts +97 -0
- package/dist/conversation-index/backend.js +13 -0
- package/dist/conversation-index/backend.js.map +1 -0
- package/dist/conversation-index/chunker.d.ts +16 -0
- package/dist/conversation-index/chunker.js +8 -0
- package/dist/conversation-index/chunker.js.map +1 -0
- package/dist/conversation-index/cleanup.d.ts +11 -0
- package/dist/conversation-index/cleanup.js +9 -0
- package/dist/conversation-index/cleanup.js.map +1 -0
- package/dist/conversation-index/faiss-adapter.d.ts +6 -0
- package/dist/conversation-index/faiss-adapter.js +16 -0
- package/dist/conversation-index/faiss-adapter.js.map +1 -0
- package/dist/conversation-index/indexer.d.ts +23 -0
- package/dist/conversation-index/indexer.js +15 -0
- package/dist/conversation-index/indexer.js.map +1 -0
- package/dist/conversation-index/search.d.ts +6 -0
- package/dist/conversation-index/search.js +11 -0
- package/dist/conversation-index/search.js.map +1 -0
- package/dist/embedding-fallback.js +2 -2
- package/dist/enrichment/index.d.ts +163 -0
- package/dist/enrichment/index.js +18 -0
- package/dist/enrichment/index.js.map +1 -0
- package/dist/entity-retrieval.d.ts +4 -2
- package/dist/entity-retrieval.js +8 -5
- package/dist/evals.js +1 -1
- package/dist/explicit-capture.d.ts +20 -5
- package/dist/explicit-capture.js +2 -2
- package/dist/extraction-judge-training.js +1 -1
- package/dist/extraction.js +8 -8
- package/dist/faiss-adapter-CzPghc4C.d.ts +70 -0
- package/dist/fallback-llm.d.ts +2 -0
- package/dist/fallback-llm.js +4 -4
- package/dist/graph-edge-decay-5DI5GUNL.js +207 -0
- package/dist/index.d.ts +66 -711
- package/dist/index.js +556 -2680
- package/dist/index.js.map +1 -1
- package/dist/lcm/archive.d.ts +89 -0
- package/dist/lcm/archive.js +12 -0
- package/dist/lcm/archive.js.map +1 -0
- package/dist/lcm/dag.d.ts +48 -0
- package/dist/lcm/dag.js +8 -0
- package/dist/lcm/dag.js.map +1 -0
- package/dist/lcm/engine.d.ts +116 -0
- package/dist/lcm/engine.js +20 -0
- package/dist/lcm/engine.js.map +1 -0
- package/dist/lcm/index.d.ts +12 -0
- package/dist/lcm/index.js +44 -0
- package/dist/lcm/index.js.map +1 -0
- package/dist/lcm/queue.d.ts +62 -0
- package/dist/lcm/queue.js +8 -0
- package/dist/lcm/queue.js.map +1 -0
- package/dist/lcm/recall.d.ts +20 -0
- package/dist/lcm/recall.js +8 -0
- package/dist/lcm/recall.js.map +1 -0
- package/dist/lcm/schema.d.ts +16 -0
- package/dist/lcm/schema.js +14 -0
- package/dist/lcm/schema.js.map +1 -0
- package/dist/lcm/summarizer.d.ts +38 -0
- package/dist/lcm/summarizer.js +12 -0
- package/dist/lcm/summarizer.js.map +1 -0
- package/dist/lcm/tools.d.ts +29 -0
- package/dist/lcm/tools.js +8 -0
- package/dist/lcm/tools.js.map +1 -0
- package/dist/live-connectors-runner.js +5 -5
- package/dist/local-llm.js +3 -3
- package/dist/maintenance/archive-observations.d.ts +18 -0
- package/dist/maintenance/archive-observations.js +8 -0
- package/dist/maintenance/archive-observations.js.map +1 -0
- package/dist/maintenance/backup-stamp.d.ts +3 -0
- package/dist/maintenance/backup-stamp.js +8 -0
- package/dist/maintenance/backup-stamp.js.map +1 -0
- package/dist/maintenance/memory-governance-cron.d.ts +85 -0
- package/dist/maintenance/memory-governance-cron.js +22 -0
- package/dist/maintenance/memory-governance-cron.js.map +1 -0
- package/dist/maintenance/memory-governance.d.ts +137 -0
- package/dist/maintenance/memory-governance.js +40 -0
- package/dist/maintenance/memory-governance.js.map +1 -0
- package/dist/maintenance/migrate-observations.d.ts +18 -0
- package/dist/maintenance/migrate-observations.js +9 -0
- package/dist/maintenance/migrate-observations.js.map +1 -0
- package/dist/maintenance/observation-ledger-utils.d.ts +10 -0
- package/dist/maintenance/observation-ledger-utils.js +10 -0
- package/dist/maintenance/observation-ledger-utils.js.map +1 -0
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +15 -0
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +28 -0
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js.map +1 -0
- package/dist/maintenance/rebuild-memory-projection.d.ts +77 -0
- package/dist/maintenance/rebuild-memory-projection.js +35 -0
- package/dist/maintenance/rebuild-memory-projection.js.map +1 -0
- package/dist/maintenance/rebuild-observations.d.ts +17 -0
- package/dist/maintenance/rebuild-observations.js +9 -0
- package/dist/maintenance/rebuild-observations.js.map +1 -0
- package/dist/mcp-memory-inspector-app.d.ts +24 -6
- package/dist/memory-projection-store.d.ts +108 -3
- package/dist/memory-projection-store.js +2 -1
- package/dist/memory-worth-outcomes.d.ts +4 -2
- package/dist/migrate/from-engram.d.ts +24 -0
- package/dist/migrate/from-engram.js +12 -0
- package/dist/migrate/from-engram.js.map +1 -0
- package/dist/namespaces/migrate.d.ts +50 -0
- package/dist/namespaces/migrate.js +50 -0
- package/dist/namespaces/migrate.js.map +1 -0
- package/dist/namespaces/principal.d.ts +17 -0
- package/dist/namespaces/principal.js +16 -0
- package/dist/namespaces/principal.js.map +1 -0
- package/dist/namespaces/search.d.ts +46 -0
- package/dist/namespaces/search.js +28 -0
- package/dist/namespaces/search.js.map +1 -0
- package/dist/namespaces/storage.d.ts +32 -0
- package/dist/namespaces/storage.js +28 -0
- package/dist/namespaces/storage.js.map +1 -0
- package/dist/network/tailscale.d.ts +41 -0
- package/dist/network/tailscale.js +9 -0
- package/dist/network/tailscale.js.map +1 -0
- package/dist/network/webdav.d.ts +39 -0
- package/dist/network/webdav.js +10 -0
- package/dist/network/webdav.js.map +1 -0
- package/dist/objective-state-writers.js +2 -2
- package/dist/operator-toolkit.d.ts +4 -2
- package/dist/operator-toolkit.js +32 -14
- package/dist/opik-exporter.js +2 -2
- package/dist/opik-exporter.js.map +1 -1
- package/dist/orchestrator-DuWl9Hwx.d.ts +1244 -0
- package/dist/orchestrator.d.ts +22 -7
- package/dist/orchestrator.js +79 -44
- package/dist/path-MR5JPYOP.js +9 -0
- package/dist/path-MR5JPYOP.js.map +1 -0
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +102 -3
- package/dist/qmd.js +23 -5
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.js +2 -2
- package/dist/replay/normalizers/chatgpt.d.ts +6 -0
- package/dist/replay/normalizers/chatgpt.js +11 -0
- package/dist/replay/normalizers/chatgpt.js.map +1 -0
- package/dist/replay/normalizers/claude.d.ts +6 -0
- package/dist/replay/normalizers/claude.js +11 -0
- package/dist/replay/normalizers/claude.js.map +1 -0
- package/dist/replay/normalizers/openclaw.d.ts +6 -0
- package/dist/replay/normalizers/openclaw.js +11 -0
- package/dist/replay/normalizers/openclaw.js.map +1 -0
- package/dist/replay/normalizers/shared.d.ts +16 -0
- package/dist/replay/normalizers/shared.js +14 -0
- package/dist/replay/normalizers/shared.js.map +1 -0
- package/dist/replay/runner.d.ts +35 -0
- package/dist/replay/runner.js +16 -0
- package/dist/replay/runner.js.map +1 -0
- package/dist/replay/types.d.ts +57 -0
- package/dist/replay/types.js +19 -0
- package/dist/replay/types.js.map +1 -0
- package/dist/resolution-B7FNQSSP.js +12 -0
- package/dist/resolution-B7FNQSSP.js.map +1 -0
- package/dist/resolve-provider-secret.js +2 -2
- package/dist/resume-bundles.js +8 -6
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/routing/engine.d.ts +35 -0
- package/dist/routing/engine.js +16 -0
- package/dist/routing/engine.js.map +1 -0
- package/dist/routing/store.d.ts +27 -0
- package/dist/routing/store.js +10 -0
- package/dist/routing/store.js.map +1 -0
- package/dist/runtime/better-sqlite.d.ts +8 -0
- package/dist/runtime/better-sqlite.js +10 -0
- package/dist/runtime/better-sqlite.js.map +1 -0
- package/dist/runtime/child-process.d.ts +32 -0
- package/dist/runtime/child-process.js +10 -0
- package/dist/runtime/child-process.js.map +1 -0
- package/dist/runtime/env.d.ts +5 -0
- package/dist/runtime/env.js +12 -0
- package/dist/runtime/env.js.map +1 -0
- package/dist/schemas.d.ts +22 -22
- package/dist/sdk-compat.js +1 -1
- package/dist/search/document-scanner.d.ts +22 -0
- package/dist/search/document-scanner.js +8 -0
- package/dist/search/document-scanner.js.map +1 -0
- package/dist/search/embed-helper.d.ts +35 -0
- package/dist/search/embed-helper.js +9 -0
- package/dist/search/embed-helper.js.map +1 -0
- package/dist/search/factory.d.ts +32 -0
- package/dist/search/factory.js +29 -0
- package/dist/search/factory.js.map +1 -0
- package/dist/search/index.d.ts +15 -0
- package/dist/search/index.js +50 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/lancedb-backend.d.ts +51 -0
- package/dist/search/lancedb-backend.js +10 -0
- package/dist/search/lancedb-backend.js.map +1 -0
- package/dist/search/meilisearch-backend.d.ts +48 -0
- package/dist/search/meilisearch-backend.js +10 -0
- package/dist/search/meilisearch-backend.js.map +1 -0
- package/dist/search/noop-backend.d.ts +26 -0
- package/dist/search/noop-backend.js +8 -0
- package/dist/search/noop-backend.js.map +1 -0
- package/dist/search/orama-backend.d.ts +53 -0
- package/dist/search/orama-backend.js +10 -0
- package/dist/search/orama-backend.js.map +1 -0
- package/dist/search/port.d.ts +61 -0
- package/dist/search/port.js +1 -0
- package/dist/search/port.js.map +1 -0
- package/dist/search/remote-backend.d.ts +39 -0
- package/dist/search/remote-backend.js +9 -0
- package/dist/search/remote-backend.js.map +1 -0
- package/dist/secure-store/index.d.ts +890 -0
- package/dist/secure-store/index.js +156 -0
- package/dist/secure-store/index.js.map +1 -0
- package/dist/semantic-VwGI14Ok.d.ts +69 -0
- package/dist/semantic-consolidation-4HkHWgeI.d.ts +180 -0
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +13 -6
- package/dist/semantic-rule-promotion.js +8 -5
- package/dist/semantic-rule-verifier.js +8 -5
- package/dist/shared-context/manager.d.ts +131 -0
- package/dist/shared-context/manager.js +15 -0
- package/dist/shared-context/manager.js.map +1 -0
- package/dist/skills-registry.js +13 -1
- package/dist/skills-registry.js.map +1 -1
- package/dist/state-store-VZU2IA53.js +16 -0
- package/dist/state-store-VZU2IA53.js.map +1 -0
- package/dist/storage-paths.d.ts +9 -0
- package/dist/storage-paths.js +20 -0
- package/dist/storage-paths.js.map +1 -0
- package/dist/storage.d.ts +3 -1
- package/dist/storage.js +7 -4
- package/dist/summarizer.d.ts +5 -0
- package/dist/summarizer.js +9 -8
- package/dist/summary-snapshot.js +2 -1
- package/dist/surfaces/dreams.d.ts +16 -0
- package/dist/surfaces/dreams.js +282 -0
- package/dist/surfaces/dreams.js.map +1 -0
- package/dist/surfaces/heartbeat.d.ts +17 -0
- package/dist/surfaces/heartbeat.js +265 -0
- package/dist/surfaces/heartbeat.js.map +1 -0
- package/dist/temporal-supersession.d.ts +3 -1
- package/dist/threading.d.ts +5 -0
- package/dist/threading.js +2 -1
- package/dist/tier-migration.d.ts +4 -2
- package/dist/tokens.js +2 -2
- package/dist/transcript.d.ts +15 -1
- package/dist/transcript.js +2 -1
- package/dist/transfer/autodetect.d.ts +4 -0
- package/dist/transfer/autodetect.js +15 -0
- package/dist/transfer/autodetect.js.map +1 -0
- package/dist/transfer/backup.d.ts +21 -0
- package/dist/transfer/backup.js +17 -0
- package/dist/transfer/backup.js.map +1 -0
- package/dist/transfer/capsule-export.d.ts +113 -0
- package/dist/transfer/capsule-export.js +19 -0
- package/dist/transfer/capsule-export.js.map +1 -0
- package/dist/transfer/capsule-import.d.ts +124 -0
- package/dist/transfer/capsule-import.js +16 -0
- package/dist/transfer/capsule-import.js.map +1 -0
- package/dist/transfer/constants.d.ts +13 -0
- package/dist/transfer/constants.js +12 -0
- package/dist/transfer/constants.js.map +1 -0
- package/dist/transfer/export-json.d.ts +11 -0
- package/dist/transfer/export-json.js +11 -0
- package/dist/transfer/export-json.js.map +1 -0
- package/dist/transfer/export-md.d.ts +10 -0
- package/dist/transfer/export-md.js +13 -0
- package/dist/transfer/export-md.js.map +1 -0
- package/dist/transfer/export-sqlite.d.ts +9 -0
- package/dist/transfer/export-sqlite.js +12 -0
- package/dist/transfer/export-sqlite.js.map +1 -0
- package/dist/transfer/fs-utils.d.ts +61 -0
- package/dist/transfer/fs-utils.js +40 -0
- package/dist/transfer/fs-utils.js.map +1 -0
- package/dist/transfer/import-json.d.ts +16 -0
- package/dist/transfer/import-json.js +13 -0
- package/dist/transfer/import-json.js.map +1 -0
- package/dist/transfer/import-md.d.ts +14 -0
- package/dist/transfer/import-md.js +11 -0
- package/dist/transfer/import-md.js.map +1 -0
- package/dist/transfer/import-sqlite.d.ts +14 -0
- package/dist/transfer/import-sqlite.js +12 -0
- package/dist/transfer/import-sqlite.js.map +1 -0
- package/dist/transfer/sqlite-schema.d.ts +4 -0
- package/dist/transfer/sqlite-schema.js +10 -0
- package/dist/transfer/sqlite-schema.js.map +1 -0
- package/dist/transfer/types.d.ts +916 -0
- package/dist/transfer/types.js +30 -0
- package/dist/transfer/types.js.map +1 -0
- package/dist/types.d.ts +28 -1
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +9 -6
- package/dist/work/board.d.ts +43 -0
- package/dist/work/board.js +14 -0
- package/dist/work/board.js.map +1 -0
- package/dist/work/boundary.d.ts +8 -0
- package/dist/work/boundary.js +14 -0
- package/dist/work/boundary.js.map +1 -0
- package/dist/work/storage.d.ts +39 -0
- package/dist/work/storage.js +11 -0
- package/dist/work/storage.js.map +1 -0
- package/dist/work/types.d.ts +75 -0
- package/dist/work/types.js +1 -0
- package/dist/work/types.js.map +1 -0
- package/package.json +2767 -6
- package/scripts/faiss_index.py +816 -0
- package/scripts/faiss_requirements.txt +3 -0
- package/skills/remnic-entities/SKILL.md +51 -0
- package/skills/remnic-memory-workflow/SKILL.md +61 -0
- package/skills/remnic-recall/SKILL.md +51 -0
- package/skills/remnic-remember/SKILL.md +56 -0
- package/skills/remnic-search/SKILL.md +51 -0
- package/skills/remnic-status/SKILL.md +51 -0
- package/src/abort-error.test.ts +49 -0
- package/src/abort-error.ts +46 -0
- package/src/abstraction-nodes.ts +162 -0
- package/src/access-audit.test.ts +178 -0
- package/src/access-audit.ts +125 -0
- package/src/access-cli.test.ts +439 -0
- package/src/access-cli.ts +438 -0
- package/src/access-http.test.ts +225 -0
- package/src/access-http.ts +1899 -0
- package/src/access-idempotency.ts +232 -0
- package/src/access-mcp.test.ts +568 -0
- package/src/access-mcp.ts +3056 -0
- package/src/access-schema-pi.test.ts +60 -0
- package/src/access-schema.ts +522 -0
- package/src/access-service-namespace.test.ts +123 -0
- package/src/access-service.ts +5629 -0
- package/src/action-confidence.test.ts +206 -0
- package/src/action-confidence.ts +466 -0
- package/src/active-memory-bridge.test.ts +285 -0
- package/src/active-memory-bridge.ts +217 -0
- package/src/active-recall.test.ts +484 -0
- package/src/active-recall.ts +459 -0
- package/src/adapters/claude-code.ts +56 -0
- package/src/adapters/codex.ts +57 -0
- package/src/adapters/hermes.ts +64 -0
- package/src/adapters/index.ts +6 -0
- package/src/adapters/registry.ts +41 -0
- package/src/adapters/replit.ts +55 -0
- package/src/adapters/types.ts +51 -0
- package/src/behavior-learner.ts +144 -0
- package/src/behavior-signals.ts +73 -0
- package/src/binary-lifecycle/backend.ts +117 -0
- package/src/binary-lifecycle/index.ts +35 -0
- package/src/binary-lifecycle/manifest.ts +79 -0
- package/src/binary-lifecycle/pipeline.ts +352 -0
- package/src/binary-lifecycle/scanner.ts +89 -0
- package/src/binary-lifecycle/types.ts +89 -0
- package/src/bootstrap.ts +178 -0
- package/src/boxes.ts +521 -0
- package/src/briefing.test.ts +1535 -0
- package/src/briefing.ts +1382 -0
- package/src/buffer-session.test.ts +443 -0
- package/src/buffer-surprise-report.ts +176 -0
- package/src/buffer-surprise-telemetry.test.ts +606 -0
- package/src/buffer-surprise-trigger.test.ts +766 -0
- package/src/buffer-surprise.test.ts +339 -0
- package/src/buffer-surprise.ts +203 -0
- package/src/buffer.ts +900 -0
- package/src/bulk-import/cli-command.test.ts +204 -0
- package/src/bulk-import/index.ts +34 -0
- package/src/bulk-import/pipeline.test.ts +445 -0
- package/src/bulk-import/pipeline.ts +178 -0
- package/src/bulk-import/registry.test.ts +151 -0
- package/src/bulk-import/registry.ts +72 -0
- package/src/bulk-import/types.test.ts +272 -0
- package/src/bulk-import/types.ts +145 -0
- package/src/calibration.ts +394 -0
- package/src/capsule-cli.test.ts +398 -0
- package/src/capsule-cli.ts +565 -0
- package/src/causal-behavior.ts +308 -0
- package/src/causal-chain.ts +419 -0
- package/src/causal-consolidation.ts +370 -0
- package/src/causal-retrieval.ts +286 -0
- package/src/causal-trajectory-graph.ts +60 -0
- package/src/causal-trajectory.ts +303 -0
- package/src/chunking.ts +220 -0
- package/src/citations.ts +232 -0
- package/src/cli.ts +9403 -0
- package/src/codex-cli-fallback.ts +162 -0
- package/src/codex-thread-key.ts +1 -0
- package/src/coding/access-coding-context.test.ts +197 -0
- package/src/coding/coding-branch-scope.test.ts +281 -0
- package/src/coding/coding-namespace.test.ts +360 -0
- package/src/coding/coding-namespace.ts +412 -0
- package/src/coding/coding-orchestrator.test.ts +249 -0
- package/src/coding/git-context.test.ts +507 -0
- package/src/coding/git-context.ts +336 -0
- package/src/coding/mcp-set-coding-context.test.ts +174 -0
- package/src/coding/review-context.test.ts +316 -0
- package/src/coding/review-context.ts +349 -0
- package/src/coding/wire-coding-context.test.ts +468 -0
- package/src/commitment-ledger.test.ts +78 -0
- package/src/commitment-ledger.ts +337 -0
- package/src/compat/checks.test.ts +206 -0
- package/src/compat/checks.ts +716 -0
- package/src/compat/types.ts +33 -0
- package/src/compounding/engine.ts +1686 -0
- package/src/compounding/preference-consolidator.ts +778 -0
- package/src/compression-optimizer.ts +312 -0
- package/src/config.test.ts +930 -0
- package/src/config.ts +3807 -0
- package/src/connectors/codex/instructions.md +160 -0
- package/src/connectors/codex/resources/namespace-cheatsheet.md +48 -0
- package/src/connectors/codex-marketplace.ts +500 -0
- package/src/connectors/codex-materialize-runner.ts +212 -0
- package/src/connectors/codex-materialize.ts +983 -0
- package/src/connectors/coerce.ts +62 -0
- package/src/connectors/index.test.ts +1570 -0
- package/src/connectors/index.ts +3222 -0
- package/src/connectors/live/framework.ts +164 -0
- package/src/connectors/live/github.test.ts +1218 -0
- package/src/connectors/live/github.ts +1068 -0
- package/src/connectors/live/gmail.test.ts +1706 -0
- package/src/connectors/live/gmail.ts +1293 -0
- package/src/connectors/live/google-drive.test.ts +696 -0
- package/src/connectors/live/google-drive.ts +724 -0
- package/src/connectors/live/index.ts +101 -0
- package/src/connectors/live/live-connectors.test.ts +689 -0
- package/src/connectors/live/notion.test.ts +1109 -0
- package/src/connectors/live/notion.ts +978 -0
- package/src/connectors/live/registry.ts +103 -0
- package/src/connectors/live/state-store.ts +399 -0
- package/src/connectors/live/transient-errors.ts +150 -0
- package/src/connectors/weclone-installer.test.ts +850 -0
- package/src/connectors-cli.ts +513 -0
- package/src/console/state.test.ts +224 -0
- package/src/console/state.ts +514 -0
- package/src/console/trace.test.ts +813 -0
- package/src/console/trace.ts +603 -0
- package/src/console/tui.test.ts +582 -0
- package/src/console/tui.ts +508 -0
- package/src/consolidation-operator.ts +182 -0
- package/src/consolidation-provenance-check.ts +551 -0
- package/src/consolidation-undo.ts +718 -0
- package/src/contradiction/contradiction-judge.test.ts +189 -0
- package/src/contradiction/contradiction-judge.ts +333 -0
- package/src/contradiction/contradiction-review.ts +574 -0
- package/src/contradiction/contradiction-scan.ts +504 -0
- package/src/contradiction/contradiction.test.ts +2230 -0
- package/src/contradiction/index.ts +37 -0
- package/src/contradiction/resolution.ts +383 -0
- package/src/conversation-index/backend.ts +323 -0
- package/src/conversation-index/chunker.ts +47 -0
- package/src/conversation-index/cleanup.ts +53 -0
- package/src/conversation-index/faiss-adapter.ts +384 -0
- package/src/conversation-index/indexer.test.ts +164 -0
- package/src/conversation-index/indexer.ts +192 -0
- package/src/conversation-index/search.ts +37 -0
- package/src/cross-namespace-budget.test.ts +275 -0
- package/src/cross-namespace-budget.ts +365 -0
- package/src/cue-anchors.ts +163 -0
- package/src/curation/index.ts +544 -0
- package/src/dashboard-runtime.ts +337 -0
- package/src/day-summary.ts +122 -0
- package/src/dedup/index.ts +330 -0
- package/src/dedup/semantic.test.ts +1577 -0
- package/src/dedup/semantic.ts +148 -0
- package/src/delinearize.ts +193 -0
- package/src/direct-answer-wiring.test.ts +473 -0
- package/src/direct-answer-wiring.ts +180 -0
- package/src/direct-answer.test.ts +484 -0
- package/src/direct-answer.ts +273 -0
- package/src/embedding-fallback.ts +565 -0
- package/src/enrichment/audit.ts +89 -0
- package/src/enrichment/index.ts +27 -0
- package/src/enrichment/pipeline.ts +197 -0
- package/src/enrichment/provider-registry.ts +85 -0
- package/src/enrichment/types.ts +100 -0
- package/src/enrichment/web-search-provider.ts +63 -0
- package/src/entity-retrieval.ts +774 -0
- package/src/entity-schema.ts +239 -0
- package/src/evals.ts +1312 -0
- package/src/event-order-recall.test.ts +4164 -0
- package/src/event-order-recall.ts +2802 -0
- package/src/evidence-pack.test.ts +89 -0
- package/src/evidence-pack.ts +388 -0
- package/src/explicit-capture.ts +530 -0
- package/src/explicit-cue-recall.test.ts +3019 -0
- package/src/explicit-cue-recall.ts +5545 -0
- package/src/extraction-judge-telemetry.ts +234 -0
- package/src/extraction-judge-training.ts +221 -0
- package/src/extraction-judge.ts +846 -0
- package/src/extraction-timeout.test.ts +265 -0
- package/src/extraction.ts +2719 -0
- package/src/fallback-llm.test.ts +1060 -0
- package/src/fallback-llm.ts +918 -0
- package/src/focused-list-recall.test.ts +734 -0
- package/src/focused-list-recall.ts +1160 -0
- package/src/graph-dashboard-diff.ts +35 -0
- package/src/graph-dashboard-key.ts +5 -0
- package/src/graph-dashboard-parser.ts +104 -0
- package/src/graph-edge-reinforcement.ts +192 -0
- package/src/graph-events.ts +151 -0
- package/src/graph-recall.test.ts +164 -0
- package/src/graph-recall.ts +189 -0
- package/src/graph-retrieval.test.ts +809 -0
- package/src/graph-retrieval.ts +823 -0
- package/src/graph-snapshot.ts +329 -0
- package/src/graph.ts +813 -0
- package/src/harmonic-retrieval.ts +223 -0
- package/src/himem.ts +154 -0
- package/src/hygiene.ts +87 -0
- package/src/identity-continuity.ts +333 -0
- package/src/importance.ts +328 -0
- package/src/importers/base.test.ts +294 -0
- package/src/importers/base.ts +436 -0
- package/src/importers/index.ts +21 -0
- package/src/index.ts +1204 -0
- package/src/intent.ts +154 -0
- package/src/json-extract.ts +85 -0
- package/src/json-store.ts +42 -0
- package/src/lcm/archive.ts +617 -0
- package/src/lcm/dag.ts +199 -0
- package/src/lcm/engine.ts +645 -0
- package/src/lcm/index.ts +7 -0
- package/src/lcm/queue.test.ts +178 -0
- package/src/lcm/queue.ts +200 -0
- package/src/lcm/recall.ts +117 -0
- package/src/lcm/schema.ts +154 -0
- package/src/lcm/summarizer.ts +235 -0
- package/src/lcm/tools.ts +191 -0
- package/src/lcm-engine.test.ts +660 -0
- package/src/legacy-hook-compat.test.ts +20 -0
- package/src/legacy-hook-compat.ts +45 -0
- package/src/lifecycle.ts +289 -0
- package/src/live-connectors-runner.ts +385 -0
- package/src/local-llm-qos.test.ts +303 -0
- package/src/local-llm-thinking.test.ts +292 -0
- package/src/local-llm.ts +1464 -0
- package/src/logger.ts +49 -0
- package/src/maintenance/archive-observations.ts +147 -0
- package/src/maintenance/backup-stamp.ts +3 -0
- package/src/maintenance/dreams-ledger.ts +516 -0
- package/src/maintenance/first-start-migration.ts +362 -0
- package/src/maintenance/forget.test.ts +206 -0
- package/src/maintenance/forget.ts +126 -0
- package/src/maintenance/graph-edge-decay.test.ts +409 -0
- package/src/maintenance/graph-edge-decay.ts +394 -0
- package/src/maintenance/memory-governance-cron.ts +447 -0
- package/src/maintenance/memory-governance.ts +1039 -0
- package/src/maintenance/migrate-observations.ts +216 -0
- package/src/maintenance/observation-ledger-utils.ts +54 -0
- package/src/maintenance/pattern-reinforcement.test.ts +875 -0
- package/src/maintenance/pattern-reinforcement.ts +369 -0
- package/src/maintenance/purge.ts +334 -0
- package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +78 -0
- package/src/maintenance/rebuild-memory-projection.ts +1234 -0
- package/src/maintenance/rebuild-observations.ts +178 -0
- package/src/maintenance/tier-stats.test.ts +378 -0
- package/src/maintenance/tier-stats.ts +222 -0
- package/src/mcp-memory-inspector-app.ts +421 -0
- package/src/memory-action-policy.ts +80 -0
- package/src/memory-cache.ts +208 -0
- package/src/memory-extension/claude-code-publisher.ts +51 -0
- package/src/memory-extension/codex-publisher.ts +149 -0
- package/src/memory-extension/hermes-publisher.ts +51 -0
- package/src/memory-extension/index.ts +100 -0
- package/src/memory-extension/shared-instructions.ts +133 -0
- package/src/memory-extension/types.ts +86 -0
- package/src/memory-extension-host/host-discovery.ts +276 -0
- package/src/memory-extension-host/index.ts +14 -0
- package/src/memory-extension-host/render-extensions-block.ts +73 -0
- package/src/memory-extension-host/types.ts +21 -0
- package/src/memory-lifecycle-ledger-utils.ts +116 -0
- package/src/memory-projection-format.ts +11 -0
- package/src/memory-projection-store.ts +951 -0
- package/src/memory-provenance.test.ts +196 -0
- package/src/memory-provenance.ts +484 -0
- package/src/memory-worth-bench.test.ts +71 -0
- package/src/memory-worth-bench.ts +265 -0
- package/src/memory-worth-filter.test.ts +209 -0
- package/src/memory-worth-filter.ts +204 -0
- package/src/memory-worth-frontmatter.test.ts +311 -0
- package/src/memory-worth-outcomes.test.ts +316 -0
- package/src/memory-worth-outcomes.ts +286 -0
- package/src/memory-worth.test.ts +317 -0
- package/src/memory-worth.ts +215 -0
- package/src/message-parts/index.ts +806 -0
- package/src/message-parts/message-parts.test.ts +421 -0
- package/src/migrate/from-engram.ts +789 -0
- package/src/model-registry.ts +313 -0
- package/src/models-json.ts +76 -0
- package/src/namespaces/migrate.ts +187 -0
- package/src/namespaces/path.ts +25 -0
- package/src/namespaces/principal.test.ts +195 -0
- package/src/namespaces/principal.ts +86 -0
- package/src/namespaces/search.test.ts +105 -0
- package/src/namespaces/search.ts +233 -0
- package/src/namespaces/storage.ts +74 -0
- package/src/native-knowledge.ts +1823 -0
- package/src/negative.ts +72 -0
- package/src/network/tailscale.ts +179 -0
- package/src/network/webdav.ts +385 -0
- package/src/objective-state-writers.ts +951 -0
- package/src/objective-state.ts +320 -0
- package/src/onboarding/index.ts +529 -0
- package/src/openai-chat-compat.ts +56 -0
- package/src/operator-toolkit.ts +2132 -0
- package/src/opik-exporter.test.ts +72 -0
- package/src/opik-exporter.ts +587 -0
- package/src/orchestrator-extraction-queue.test.ts +197 -0
- package/src/orchestrator-flush.test.ts +1171 -0
- package/src/orchestrator-pattern-reinforcement.test.ts +128 -0
- package/src/orchestrator-source-attribution.test.ts +701 -0
- package/src/orchestrator.ts +16368 -0
- package/src/page-versioning.ts +450 -0
- package/src/patterns-cli.ts +574 -0
- package/src/peers/index.ts +54 -0
- package/src/peers/migrate-from-identity-anchor.test.ts +291 -0
- package/src/peers/migrate-from-identity-anchor.ts +350 -0
- package/src/peers/peers.test.ts +419 -0
- package/src/peers/profile-reasoner.ts +694 -0
- package/src/peers/storage.ts +1350 -0
- package/src/peers/types.ts +138 -0
- package/src/plugin-id.ts +84 -0
- package/src/policy-runtime.ts +209 -0
- package/src/procedural/procedure-miner.ts +150 -0
- package/src/procedural/procedure-recall.ts +93 -0
- package/src/procedural/procedure-stats.ts +213 -0
- package/src/procedural/procedure-types.ts +132 -0
- package/src/procedural/reinforcement-core.test.ts +132 -0
- package/src/procedural/reinforcement-core.ts +73 -0
- package/src/profiling.test.ts +263 -0
- package/src/profiling.ts +435 -0
- package/src/projection/index.ts +398 -0
- package/src/qmd-recall-cache.test.ts +138 -0
- package/src/qmd-recall-cache.ts +111 -0
- package/src/qmd.test.ts +257 -0
- package/src/qmd.ts +2614 -0
- package/src/reasoning-trace-recall.ts +201 -0
- package/src/reasoning-trace-types.ts +235 -0
- package/src/recall-audit-anomaly.test.ts +246 -0
- package/src/recall-audit-anomaly.ts +297 -0
- package/src/recall-audit.test.ts +51 -0
- package/src/recall-audit.ts +72 -0
- package/src/recall-budget-config.test.ts +87 -0
- package/src/recall-disclosure-escalation.test.ts +196 -0
- package/src/recall-disclosure-escalation.ts +158 -0
- package/src/recall-disclosure-shaping.test.ts +146 -0
- package/src/recall-disclosure.test.ts +214 -0
- package/src/recall-explain-renderer.test.ts +140 -0
- package/src/recall-explain-renderer.ts +356 -0
- package/src/recall-mmr.test.ts +808 -0
- package/src/recall-mmr.ts +607 -0
- package/src/recall-qos.test.ts +85 -0
- package/src/recall-qos.ts +82 -0
- package/src/recall-query-policy.ts +221 -0
- package/src/recall-state.test.ts +233 -0
- package/src/recall-state.ts +456 -0
- package/src/recall-tag-filter.ts +143 -0
- package/src/recall-tokenization.ts +35 -0
- package/src/recall-xray-cli.test.ts +118 -0
- package/src/recall-xray-cli.ts +100 -0
- package/src/recall-xray-disclosure-telemetry.test.ts +183 -0
- package/src/recall-xray-renderer.test.ts +539 -0
- package/src/recall-xray-renderer.ts +487 -0
- package/src/recall-xray.test.ts +503 -0
- package/src/recall-xray.ts +621 -0
- package/src/reconstruct.ts +41 -0
- package/src/release-changelog.ts +35 -0
- package/src/relevance.ts +67 -0
- package/src/replay/normalizers/chatgpt.ts +133 -0
- package/src/replay/normalizers/claude.ts +102 -0
- package/src/replay/normalizers/openclaw.ts +119 -0
- package/src/replay/normalizers/shared.ts +69 -0
- package/src/replay/runner.ts +197 -0
- package/src/replay/types.ts +143 -0
- package/src/rerank.test.ts +48 -0
- package/src/rerank.ts +176 -0
- package/src/resolve-auth-token.test.ts +226 -0
- package/src/resolve-auth-token.ts +151 -0
- package/src/resolve-provider-secret.test.ts +187 -0
- package/src/resolve-provider-secret.ts +410 -0
- package/src/response-guidance-recall.test.ts +3952 -0
- package/src/response-guidance-recall.ts +4431 -0
- package/src/resume-bundles.ts +415 -0
- package/src/retrieval-agents.ts +623 -0
- package/src/retrieval-tiers.ts +25 -0
- package/src/retrieval.ts +104 -0
- package/src/review/index.test.ts +201 -0
- package/src/review/index.ts +536 -0
- package/src/routing/engine.ts +162 -0
- package/src/routing/store.ts +321 -0
- package/src/runtime/better-sqlite.test.ts +32 -0
- package/src/runtime/better-sqlite.ts +76 -0
- package/src/runtime/child-process.ts +67 -0
- package/src/runtime/env.ts +48 -0
- package/src/sanitize.ts +58 -0
- package/src/schemas.ts +449 -0
- package/src/sdk-compat.ts +87 -0
- package/src/search/document-scanner.ts +96 -0
- package/src/search/embed-helper.ts +142 -0
- package/src/search/factory.ts +189 -0
- package/src/search/index.ts +10 -0
- package/src/search/lancedb-backend.ts +342 -0
- package/src/search/meilisearch-backend.ts +232 -0
- package/src/search/noop-backend.ts +57 -0
- package/src/search/orama-backend.ts +358 -0
- package/src/search/port.ts +86 -0
- package/src/search/remote-backend.ts +124 -0
- package/src/secure-store/cipher.ts +271 -0
- package/src/secure-store/cli-handlers.ts +355 -0
- package/src/secure-store/cli-renderer.ts +131 -0
- package/src/secure-store/header.ts +373 -0
- package/src/secure-store/index.ts +137 -0
- package/src/secure-store/kdf.ts +263 -0
- package/src/secure-store/keyring.ts +106 -0
- package/src/secure-store/metadata.ts +394 -0
- package/src/secure-store/passphrase-reader.ts +252 -0
- package/src/secure-store/secure-fs.ts +571 -0
- package/src/secure-store/secure-store.test.ts +755 -0
- package/src/semantic-chunking.ts +545 -0
- package/src/semantic-consolidation.test.ts +182 -0
- package/src/semantic-consolidation.ts +432 -0
- package/src/semantic-rule-promotion.ts +183 -0
- package/src/semantic-rule-verifier.ts +160 -0
- package/src/session-integrity.ts +569 -0
- package/src/session-observer-bands.ts +11 -0
- package/src/session-observer-state.ts +346 -0
- package/src/session-toggles.test.ts +96 -0
- package/src/session-toggles.ts +159 -0
- package/src/shared-context/manager.ts +810 -0
- package/src/signal.ts +84 -0
- package/src/skills-registry.test.ts +277 -0
- package/src/skills-registry.ts +120 -0
- package/src/source-attribution-roundtrip.test.ts +215 -0
- package/src/source-attribution.test.ts +1425 -0
- package/src/source-attribution.ts +639 -0
- package/src/spaces/index.ts +627 -0
- package/src/storage-paths.ts +117 -0
- package/src/storage.ts +6657 -0
- package/src/store-contract.ts +55 -0
- package/src/summarizer.ts +844 -0
- package/src/summary-snapshot.test.ts +681 -0
- package/src/summary-snapshot.ts +238 -0
- package/src/surfaces/dreams.test.ts +394 -0
- package/src/surfaces/dreams.ts +346 -0
- package/src/surfaces/heartbeat.test.ts +415 -0
- package/src/surfaces/heartbeat.ts +325 -0
- package/src/sync/index.ts +308 -0
- package/src/targeted-fact-recall.test.ts +1694 -0
- package/src/targeted-fact-recall.ts +2905 -0
- package/src/taxonomy/default-taxonomy.ts +87 -0
- package/src/taxonomy/index.ts +26 -0
- package/src/taxonomy/resolver-doc-generator.ts +57 -0
- package/src/taxonomy/resolver.ts +184 -0
- package/src/taxonomy/taxonomy-loader.ts +186 -0
- package/src/taxonomy/types.ts +48 -0
- package/src/telemetry-transcript.ts +70 -0
- package/src/temporal-index.ts +890 -0
- package/src/temporal-supersession.test.ts +2703 -0
- package/src/temporal-supersession.ts +493 -0
- package/src/temporal-validity.test.ts +448 -0
- package/src/temporal-validity.ts +123 -0
- package/src/threading.ts +395 -0
- package/src/tier-migration.ts +124 -0
- package/src/tier-routing.ts +102 -0
- package/src/tmt.ts +462 -0
- package/src/tokens.test.ts +178 -0
- package/src/tokens.ts +279 -0
- package/src/topics.ts +147 -0
- package/src/training-export/cli-date-validation.test.ts +258 -0
- package/src/training-export/converter.test.ts +452 -0
- package/src/training-export/converter.ts +319 -0
- package/src/training-export/date-parse.ts +117 -0
- package/src/training-export/index.ts +26 -0
- package/src/training-export/registry.test.ts +85 -0
- package/src/training-export/registry.ts +57 -0
- package/src/training-export/types.ts +31 -0
- package/src/transcript.ts +1179 -0
- package/src/transfer/autodetect.ts +30 -0
- package/src/transfer/backup.ts +138 -0
- package/src/transfer/capsule-crypto.ts +485 -0
- package/src/transfer/capsule-encrypt.test.ts +690 -0
- package/src/transfer/capsule-export.ts +543 -0
- package/src/transfer/capsule-fork.ts +375 -0
- package/src/transfer/capsule-import.ts +564 -0
- package/src/transfer/capsule-merge.ts +433 -0
- package/src/transfer/conflict-policy.ts +16 -0
- package/src/transfer/constants.ts +13 -0
- package/src/transfer/exclusions.ts +37 -0
- package/src/transfer/export-json.ts +65 -0
- package/src/transfer/export-md.ts +59 -0
- package/src/transfer/export-sqlite.ts +52 -0
- package/src/transfer/fs-utils.ts +269 -0
- package/src/transfer/import-json.ts +108 -0
- package/src/transfer/import-md.ts +84 -0
- package/src/transfer/import-sqlite.ts +100 -0
- package/src/transfer/integrity.ts +71 -0
- package/src/transfer/sqlite-schema.ts +16 -0
- package/src/transfer/types.ts +297 -0
- package/src/trust-zones.ts +1186 -0
- package/src/types.ts +3074 -0
- package/src/user-model.test.ts +124 -0
- package/src/user-model.ts +162 -0
- package/src/utility-learner.ts +353 -0
- package/src/utility-runtime.ts +88 -0
- package/src/utility-telemetry.ts +215 -0
- package/src/utils/category-dir.ts +44 -0
- package/src/utils/errno.ts +6 -0
- package/src/utils/iso-timestamp.test.ts +37 -0
- package/src/utils/iso-timestamp.ts +164 -0
- package/src/utils/path.ts +26 -0
- package/src/verified-recall.ts +138 -0
- package/src/version-utils.test.ts +10 -0
- package/src/version-utils.ts +9 -0
- package/src/whitespace.ts +10 -0
- package/src/work/board.ts +359 -0
- package/src/work/boundary.ts +107 -0
- package/src/work/storage.ts +436 -0
- package/src/work/types.ts +82 -0
- package/src/work-product-ledger.ts +265 -0
- package/dist/access-service-DDjzFALq.d.ts +0 -2088
- package/dist/capsule-crypto-SJS5VVAP.js +0 -18
- package/dist/capsule-export-7QNCBZOQ.js +0 -17
- package/dist/capsule-import-EPBHD2EN.js +0 -16
- package/dist/capsule-merge-DI7PNQ2H.js +0 -189
- package/dist/chunk-23ZZK64Y.js +0 -26
- package/dist/chunk-23ZZK64Y.js.map +0 -1
- package/dist/chunk-242S3I2A.js +0 -647
- package/dist/chunk-2LGMW3DJ.js +0 -111
- package/dist/chunk-3B6KIRBH.js +0 -5213
- package/dist/chunk-3B6KIRBH.js.map +0 -1
- package/dist/chunk-457A4P3L.js +0 -119
- package/dist/chunk-457A4P3L.js.map +0 -1
- package/dist/chunk-4IS4SXIQ.js +0 -2040
- package/dist/chunk-4YM32CRU.js +0 -721
- package/dist/chunk-6TBWYBJ3.js +0 -236
- package/dist/chunk-74EMIVE4.js +0 -329
- package/dist/chunk-74EMIVE4.js.map +0 -1
- package/dist/chunk-767ODGE6.js +0 -183
- package/dist/chunk-7V22HTMD.js +0 -623
- package/dist/chunk-7V22HTMD.js.map +0 -1
- package/dist/chunk-7ZM3BFKK.js +0 -9705
- package/dist/chunk-7ZM3BFKK.js.map +0 -1
- package/dist/chunk-AQJNPMOA.js +0 -643
- package/dist/chunk-AQJNPMOA.js.map +0 -1
- package/dist/chunk-ASAITVLA.js +0 -64
- package/dist/chunk-ASAITVLA.js.map +0 -1
- package/dist/chunk-BBE34QBJ.js +0 -275
- package/dist/chunk-BBE34QBJ.js.map +0 -1
- package/dist/chunk-BZSQEPRW.js +0 -14710
- package/dist/chunk-BZSQEPRW.js.map +0 -1
- package/dist/chunk-CPKTBRS2.js +0 -891
- package/dist/chunk-CPKTBRS2.js.map +0 -1
- package/dist/chunk-D4GAOFF6.js +0 -562
- package/dist/chunk-D4GAOFF6.js.map +0 -1
- package/dist/chunk-D54LZC5L.js +0 -147
- package/dist/chunk-DF3RVK3X.js +0 -119
- package/dist/chunk-DF3RVK3X.js.map +0 -1
- package/dist/chunk-DZZPC36E.js +0 -1451
- package/dist/chunk-DZZPC36E.js.map +0 -1
- package/dist/chunk-E2UCDP5S.js +0 -570
- package/dist/chunk-E6K4NIEU.js +0 -747
- package/dist/chunk-E6K4NIEU.js.map +0 -1
- package/dist/chunk-EEQLFRUM.js +0 -89
- package/dist/chunk-ETOW6ACV.js +0 -158
- package/dist/chunk-ETOW6ACV.js.map +0 -1
- package/dist/chunk-FMEBPEAO.js +0 -347
- package/dist/chunk-FMEBPEAO.js.map +0 -1
- package/dist/chunk-FQDPCE3I.js +0 -1837
- package/dist/chunk-FQDPCE3I.js.map +0 -1
- package/dist/chunk-FYIYMQ5N.js +0 -221
- package/dist/chunk-FYIYMQ5N.js.map +0 -1
- package/dist/chunk-G2WADRQ3.js +0 -219
- package/dist/chunk-G4SK7DSQ.js +0 -121
- package/dist/chunk-GVPWB7EY.js +0 -390
- package/dist/chunk-GVPWB7EY.js.map +0 -1
- package/dist/chunk-HELQZFZO.js +0 -1075
- package/dist/chunk-HL5LRPNA.js +0 -1914
- package/dist/chunk-HL5LRPNA.js.map +0 -1
- package/dist/chunk-HQZVVSVB.js +0 -147
- package/dist/chunk-HQZVVSVB.js.map +0 -1
- package/dist/chunk-HY3L4WKC.js +0 -2195
- package/dist/chunk-HY3L4WKC.js.map +0 -1
- package/dist/chunk-IB3BFHGN.js +0 -228
- package/dist/chunk-IXEJRKCZ.js +0 -18
- package/dist/chunk-JBMSGZEQ.js +0 -441
- package/dist/chunk-JBMSGZEQ.js.map +0 -1
- package/dist/chunk-JESOB2HO.js +0 -108
- package/dist/chunk-JKDVIE52.js +0 -272
- package/dist/chunk-JRNQ3RNA.js +0 -284
- package/dist/chunk-JRNQ3RNA.js.map +0 -1
- package/dist/chunk-K6WK37A6.js +0 -865
- package/dist/chunk-K6WK37A6.js.map +0 -1
- package/dist/chunk-MARWOCVP.js +0 -48
- package/dist/chunk-MNU6ZBWT.js +0 -4454
- package/dist/chunk-MNU6ZBWT.js.map +0 -1
- package/dist/chunk-N5AKDXAI.js +0 -74
- package/dist/chunk-OA3L7BFR.js +0 -183
- package/dist/chunk-OA3L7BFR.js.map +0 -1
- package/dist/chunk-OR64ZGRZ.js +0 -23
- package/dist/chunk-P77UEOU2.js +0 -1521
- package/dist/chunk-P77UEOU2.js.map +0 -1
- package/dist/chunk-PH4C2U43.js +0 -239
- package/dist/chunk-PH4C2U43.js.map +0 -1
- package/dist/chunk-RVPLBATS.js +0 -1586
- package/dist/chunk-RVPLBATS.js.map +0 -1
- package/dist/chunk-U5JMRGKX.js +0 -340
- package/dist/chunk-U5JMRGKX.js.map +0 -1
- package/dist/chunk-URB2WSKZ.js +0 -350
- package/dist/chunk-URB2WSKZ.js.map +0 -1
- package/dist/chunk-UVMUAWVT.js +0 -596
- package/dist/chunk-WEJG4TB5.js +0 -118
- package/dist/chunk-X7HPGUVG.js +0 -271
- package/dist/chunk-XAMBKFQS.js +0 -2777
- package/dist/chunk-XAMBKFQS.js.map +0 -1
- package/dist/chunk-XJKFSSDW.js +0 -726
- package/dist/chunk-XJKFSSDW.js.map +0 -1
- package/dist/chunk-XMHBH5H6.js +0 -283
- package/dist/chunk-XMHBH5H6.js.map +0 -1
- package/dist/chunk-XMVFHBHT.js +0 -277
- package/dist/chunk-Y3VMVTYX.js +0 -53
- package/dist/chunk-YNB73F22.js +0 -137
- package/dist/chunk-YNB73F22.js.map +0 -1
- package/dist/chunk-Z2E7VW55.js +0 -335
- package/dist/chunk-Z2E7VW55.js.map +0 -1
- package/dist/chunk-ZG7PTKBK.js +0 -2296
- package/dist/chunk-ZNQN6ZTA.js +0 -135
- package/dist/chunk-ZVTKDVVM.js +0 -827
- package/dist/chunk-ZVTKDVVM.js.map +0 -1
- package/dist/cli-BR8KpIU0.d.ts +0 -1259
- package/dist/codex-materialize-CQlLTzke.d.ts +0 -139
- package/dist/connectors-cli-DFGtY2DB.d.ts +0 -257
- package/dist/contradiction-review-5LTTVDQV.js +0 -22
- package/dist/contradiction-scan-QTXAMBUA.js +0 -414
- package/dist/contradiction-scan-QTXAMBUA.js.map +0 -1
- package/dist/engine-35M5BKQ7.js +0 -28
- package/dist/fs-utils-IRVUFB6G.js +0 -30
- package/dist/graph-edge-decay-PWB63GRE.js +0 -207
- package/dist/memory-governance-IMPQZXFC.js +0 -37
- package/dist/memory-projection-store-CY8TU40w.d.ts +0 -222
- package/dist/orchestrator-DDMPqU6R.d.ts +0 -1792
- package/dist/path-RMTY5Y5A.js +0 -9
- package/dist/port-B6VEDIkC.d.ts +0 -53
- package/dist/resolution-YGIBORXI.js +0 -101
- package/dist/resolution-YGIBORXI.js.map +0 -1
- package/dist/secure-store-4R2GSO7S.js +0 -156
- package/dist/semantic-consolidation-ByBXb-sf.d.ts +0 -180
- package/dist/state-store-3EH7HYIN.js +0 -16
- package/dist/types-V3FJ26TF.js +0 -30
- /package/dist/{capsule-crypto-SJS5VVAP.js.map → adapters/claude-code.js.map} +0 -0
- /package/dist/{capsule-export-7QNCBZOQ.js.map → adapters/codex.js.map} +0 -0
- /package/dist/{capsule-import-EPBHD2EN.js.map → adapters/hermes.js.map} +0 -0
- /package/dist/{contradiction-review-5LTTVDQV.js.map → adapters/index.js.map} +0 -0
- /package/dist/{engine-35M5BKQ7.js.map → adapters/registry.js.map} +0 -0
- /package/dist/{fs-utils-IRVUFB6G.js.map → adapters/replit.js.map} +0 -0
- /package/dist/{memory-governance-IMPQZXFC.js.map → adapters/types.js.map} +0 -0
- /package/dist/{path-RMTY5Y5A.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
- /package/dist/{capsule-merge-DI7PNQ2H.js.map → capsule-merge-4MGKE7C5.js.map} +0 -0
- /package/dist/{chunk-G4SK7DSQ.js.map → chunk-2WWLHTZY.js.map} +0 -0
- /package/dist/{chunk-X7HPGUVG.js.map → chunk-4CRG46BG.js.map} +0 -0
- /package/dist/{chunk-UVMUAWVT.js.map → chunk-7IASACLB.js.map} +0 -0
- /package/dist/{chunk-HELQZFZO.js.map → chunk-EDTHC6UD.js.map} +0 -0
- /package/dist/{chunk-4YM32CRU.js.map → chunk-EFJ3MQ4V.js.map} +0 -0
- /package/dist/{chunk-E2UCDP5S.js.map → chunk-FBYESMQ2.js.map} +0 -0
- /package/dist/{chunk-D54LZC5L.js.map → chunk-FDU6HUUL.js.map} +0 -0
- /package/dist/{chunk-IB3BFHGN.js.map → chunk-GGKRUQOO.js.map} +0 -0
- /package/dist/{chunk-242S3I2A.js.map → chunk-GL6I6MEQ.js.map} +0 -0
- /package/dist/{secure-store-4R2GSO7S.js.map → chunk-HHLLAQGZ.js.map} +0 -0
- /package/dist/{chunk-4IS4SXIQ.js.map → chunk-HXXBL2KD.js.map} +0 -0
- /package/dist/{chunk-767ODGE6.js.map → chunk-KNKUID7G.js.map} +0 -0
- /package/dist/{chunk-6TBWYBJ3.js.map → chunk-LPMVBPA3.js.map} +0 -0
- /package/dist/{chunk-WEJG4TB5.js.map → chunk-MC26UJIM.js.map} +0 -0
- /package/dist/{chunk-JKDVIE52.js.map → chunk-MGKYQQYF.js.map} +0 -0
- /package/dist/{chunk-Y3VMVTYX.js.map → chunk-MT4HVDUZ.js.map} +0 -0
- /package/dist/{chunk-G2WADRQ3.js.map → chunk-MY6TPVXW.js.map} +0 -0
- /package/dist/{chunk-OR64ZGRZ.js.map → chunk-NNVTUXEB.js.map} +0 -0
- /package/dist/{chunk-JESOB2HO.js.map → chunk-P4NEIHUT.js.map} +0 -0
- /package/dist/{chunk-IXEJRKCZ.js.map → chunk-QRNI5JBH.js.map} +0 -0
- /package/dist/{chunk-EEQLFRUM.js.map → chunk-RRF5UOBJ.js.map} +0 -0
- /package/dist/{state-store-3EH7HYIN.js.map → chunk-SEDEKFYQ.js.map} +0 -0
- /package/dist/{chunk-2LGMW3DJ.js.map → chunk-U3PN77QT.js.map} +0 -0
- /package/dist/{chunk-XMVFHBHT.js.map → chunk-U3WSW6PZ.js.map} +0 -0
- /package/dist/{chunk-N5AKDXAI.js.map → chunk-UWVJF25J.js.map} +0 -0
- /package/dist/{types-V3FJ26TF.js.map → chunk-V5OCT34X.js.map} +0 -0
- /package/dist/{chunk-ZG7PTKBK.js.map → chunk-W3LR522O.js.map} +0 -0
- /package/dist/{chunk-MARWOCVP.js.map → chunk-XIG5PDM7.js.map} +0 -0
- /package/dist/{chunk-ZNQN6ZTA.js.map → chunk-XVZ7B3HG.js.map} +0 -0
- /package/dist/{graph-edge-decay-PWB63GRE.js.map → graph-edge-decay-5DI5GUNL.js.map} +0 -0
|
@@ -0,0 +1,978 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @remnic/core — Notion live connector (issue #683 PR 3/N)
|
|
3
|
+
*
|
|
4
|
+
* Concrete `LiveConnector` implementation that incrementally imports text
|
|
5
|
+
* content from Notion database pages into Remnic. Built on top of the
|
|
6
|
+
* framework shipped in PR 1/N (`framework.ts` / `registry.ts` /
|
|
7
|
+
* `state-store.ts`) and mirrors the structure of the Google Drive connector
|
|
8
|
+
* (PR 2/N).
|
|
9
|
+
*
|
|
10
|
+
* Design notes:
|
|
11
|
+
*
|
|
12
|
+
* - **Auth.** Integration token from config (`connectors.notion.token`).
|
|
13
|
+
* The token is accepted at config-parse time but never logged. Operators
|
|
14
|
+
* must populate it from a secret store; per the repo-wide privacy policy
|
|
15
|
+
* no real value may appear in tests or comments.
|
|
16
|
+
*
|
|
17
|
+
* - **Scope.** `databaseIds` in config limits the import to the listed
|
|
18
|
+
* Notion databases. The connector queries each database for pages whose
|
|
19
|
+
* `last_edited_time` is after a per-page high-water mark stored in the
|
|
20
|
+
* cursor. When `databaseIds` is empty the connector does nothing (safe
|
|
21
|
+
* default — no credentials → no import).
|
|
22
|
+
*
|
|
23
|
+
* - **Cursor semantics.** The cursor is a JSON string encoding a
|
|
24
|
+
* `NotionCursorPayload`: a map from page-id to last-seen
|
|
25
|
+
* `last_edited_time` ISO string. On the first sync (cursor=null) we
|
|
26
|
+
* seed the payload from the current state of each database WITHOUT
|
|
27
|
+
* importing any content, so "first install" doesn't re-ingest history.
|
|
28
|
+
* Each subsequent pass only imports pages edited after the stored
|
|
29
|
+
* watermark.
|
|
30
|
+
*
|
|
31
|
+
* - **Block extraction.** Page content is fetched via
|
|
32
|
+
* `blocks.children.list` recursively up to `MAX_BLOCK_DEPTH` levels.
|
|
33
|
+
* Block text is extracted to Markdown-ish plain text (no raw JSON blobs).
|
|
34
|
+
* Only text-bearing block types are included; unsupported types are
|
|
35
|
+
* silently skipped.
|
|
36
|
+
*
|
|
37
|
+
* - **Raw `fetch`.** We call the Notion REST API directly rather than using
|
|
38
|
+
* `@notionhq/client` — there is no optional-peer-dep machinery needed and
|
|
39
|
+
* the API surface we consume is tiny. The `fetchFn` argument is the test
|
|
40
|
+
* hook allowing stubbing without network access.
|
|
41
|
+
*
|
|
42
|
+
* - **Idempotency.** `ConnectorDocument.source.externalId` is the page id
|
|
43
|
+
* and `externalRevision` is `last_edited_time`, so downstream dedup can
|
|
44
|
+
* recognise repeat fetches if the cursor is rewound.
|
|
45
|
+
*
|
|
46
|
+
* - **Privacy.** No page content is ever logged. Database ids and counts
|
|
47
|
+
* may be logged. The integration token is never exposed in logs, state,
|
|
48
|
+
* or error messages.
|
|
49
|
+
*
|
|
50
|
+
* - **Read-only.** This connector only reads. It never modifies pages,
|
|
51
|
+
* databases, or any other Notion resource.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
import type {
|
|
55
|
+
ConnectorConfig,
|
|
56
|
+
ConnectorCursor,
|
|
57
|
+
ConnectorDocument,
|
|
58
|
+
LiveConnector,
|
|
59
|
+
SyncIncrementalArgs,
|
|
60
|
+
SyncIncrementalResult,
|
|
61
|
+
} from "./framework.js";
|
|
62
|
+
import { isTransientHttpError } from "./transient-errors.js";
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Public constants
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
/** Stable connector id. Lives in the registry under this exact string. */
|
|
69
|
+
export const NOTION_CONNECTOR_ID = "notion";
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Cursor `kind` we emit. Opaque to the framework; documented here so
|
|
73
|
+
* tests can assert on it.
|
|
74
|
+
*/
|
|
75
|
+
export const NOTION_CURSOR_KIND = "notionWatermark";
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Default poll interval (5 minutes). Notion's API has no push capability;
|
|
79
|
+
* polling sub-minute wastes quota for a personal memory layer.
|
|
80
|
+
*/
|
|
81
|
+
export const NOTION_DEFAULT_POLL_INTERVAL_MS = 5 * 60 * 1000;
|
|
82
|
+
|
|
83
|
+
/** Hard cap on poll interval: 24 hours. */
|
|
84
|
+
const NOTION_MAX_POLL_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Hard cap on individual page text size. Notion pages can be very long;
|
|
88
|
+
* we skip rather than blow the importer's heap.
|
|
89
|
+
*/
|
|
90
|
+
const MAX_TEXT_BYTES = 5 * 1024 * 1024;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Maximum recursion depth when fetching block children. Notion pages can
|
|
94
|
+
* nest blocks (e.g. toggle → bulleted list → quote). We cap depth so a
|
|
95
|
+
* pathologically deep page doesn't exhaust the call stack or quota.
|
|
96
|
+
*/
|
|
97
|
+
const MAX_BLOCK_DEPTH = 5;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Maximum number of pages we import in a single `syncIncremental` pass
|
|
101
|
+
* across all databases. Prevents one runaway pass from monopolising the
|
|
102
|
+
* scheduler.
|
|
103
|
+
*/
|
|
104
|
+
const MAX_PAGES_PER_PASS = 200;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Notion integration tokens always start with `secret_`. We validate this
|
|
108
|
+
* prefix so a typo (e.g. pasting an OAuth token instead) is caught early.
|
|
109
|
+
*/
|
|
110
|
+
const NOTION_TOKEN_PREFIX = "secret_";
|
|
111
|
+
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// Config types
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Validated, frozen view of `connectors.notion.*`.
|
|
118
|
+
*/
|
|
119
|
+
export interface NotionConnectorConfig {
|
|
120
|
+
/** Notion integration token. Starts with `secret_`. */
|
|
121
|
+
readonly token: string;
|
|
122
|
+
/** Database ids to import pages from. Empty = connector is a no-op. */
|
|
123
|
+
readonly databaseIds: readonly string[];
|
|
124
|
+
/** Poll interval surfaced to the scheduler (ms). */
|
|
125
|
+
readonly pollIntervalMs: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The JSON payload we encode into `ConnectorCursor.value`. Maps each
|
|
130
|
+
* page id to the ISO 8601 `last_edited_time` we have already ingested.
|
|
131
|
+
* Also tracks the ISO 8601 high-water mark per database (used for the
|
|
132
|
+
* initial `filter.timestamp` query to skip unchanged pages).
|
|
133
|
+
*/
|
|
134
|
+
interface NotionCursorPayload {
|
|
135
|
+
/** pageId → last_edited_time (ISO 8601). */
|
|
136
|
+
pages: Record<string, string>;
|
|
137
|
+
/** databaseId → latest last_edited_time seen in that DB. */
|
|
138
|
+
databases: Record<string, string>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// Notion API response shapes (only the fields we consume)
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
/** Minimal Notion page shape from `databases/{id}/query`. */
|
|
146
|
+
export interface NotionPage {
|
|
147
|
+
readonly id: string;
|
|
148
|
+
readonly last_edited_time: string;
|
|
149
|
+
readonly url?: string;
|
|
150
|
+
readonly properties?: Record<
|
|
151
|
+
string,
|
|
152
|
+
{
|
|
153
|
+
type?: string;
|
|
154
|
+
title?: Array<{ plain_text?: string }>;
|
|
155
|
+
}
|
|
156
|
+
>;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Minimal block shape from `blocks/{id}/children`. */
|
|
160
|
+
export interface NotionBlock {
|
|
161
|
+
readonly id: string;
|
|
162
|
+
readonly type: string;
|
|
163
|
+
readonly has_children?: boolean;
|
|
164
|
+
// We index by `type` to extract text.
|
|
165
|
+
readonly [key: string]: unknown;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Minimal Notion API error shape. */
|
|
169
|
+
interface NotionApiError {
|
|
170
|
+
readonly object: "error";
|
|
171
|
+
readonly status: number;
|
|
172
|
+
readonly code: string;
|
|
173
|
+
readonly message: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
// Fetch abstraction (test hook)
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Minimal fetch-compatible surface we use. The real connector delegates to
|
|
182
|
+
* the global `fetch`; tests inject a stub factory.
|
|
183
|
+
*/
|
|
184
|
+
export type NotionFetchFn = (
|
|
185
|
+
url: string,
|
|
186
|
+
init: {
|
|
187
|
+
method: string;
|
|
188
|
+
headers: Record<string, string>;
|
|
189
|
+
body?: string;
|
|
190
|
+
signal?: AbortSignal;
|
|
191
|
+
},
|
|
192
|
+
) => Promise<{
|
|
193
|
+
ok: boolean;
|
|
194
|
+
status: number;
|
|
195
|
+
json(): Promise<unknown>;
|
|
196
|
+
}>;
|
|
197
|
+
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
// Config validation
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Validate and normalise raw config. Throws with a concrete message on any
|
|
204
|
+
* malformed input — never silently defaults (CLAUDE.md gotcha #51).
|
|
205
|
+
*/
|
|
206
|
+
export function validateNotionConfig(raw: unknown): NotionConnectorConfig {
|
|
207
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
208
|
+
throw new TypeError(
|
|
209
|
+
`notion: config must be an object, got ${raw === null ? "null" : Array.isArray(raw) ? "array" : typeof raw}`,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
const r = raw as Record<string, unknown>;
|
|
213
|
+
|
|
214
|
+
// token
|
|
215
|
+
if (typeof r.token !== "string") {
|
|
216
|
+
throw new TypeError(`notion: token must be a string (got ${typeof r.token})`);
|
|
217
|
+
}
|
|
218
|
+
const token = r.token.trim();
|
|
219
|
+
if (token.length === 0) {
|
|
220
|
+
throw new RangeError("notion: token must be non-empty");
|
|
221
|
+
}
|
|
222
|
+
if (!token.startsWith(NOTION_TOKEN_PREFIX)) {
|
|
223
|
+
throw new RangeError(
|
|
224
|
+
`notion: token must start with "${NOTION_TOKEN_PREFIX}" (looks like a non-integration token)`,
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// pollIntervalMs
|
|
229
|
+
let pollIntervalMs: number;
|
|
230
|
+
if (r.pollIntervalMs === undefined) {
|
|
231
|
+
pollIntervalMs = NOTION_DEFAULT_POLL_INTERVAL_MS;
|
|
232
|
+
} else if (typeof r.pollIntervalMs !== "number" || !Number.isFinite(r.pollIntervalMs)) {
|
|
233
|
+
throw new TypeError(
|
|
234
|
+
`notion: pollIntervalMs must be a finite number (got ${JSON.stringify(r.pollIntervalMs)})`,
|
|
235
|
+
);
|
|
236
|
+
} else if (!Number.isInteger(r.pollIntervalMs)) {
|
|
237
|
+
throw new TypeError(`notion: pollIntervalMs must be an integer (got ${r.pollIntervalMs})`);
|
|
238
|
+
} else if (r.pollIntervalMs < 1_000) {
|
|
239
|
+
throw new RangeError(`notion: pollIntervalMs must be ≥1000ms; got ${r.pollIntervalMs}`);
|
|
240
|
+
} else if (r.pollIntervalMs > NOTION_MAX_POLL_INTERVAL_MS) {
|
|
241
|
+
throw new RangeError(
|
|
242
|
+
`notion: pollIntervalMs must be ≤${NOTION_MAX_POLL_INTERVAL_MS} (24h); got ${r.pollIntervalMs}`,
|
|
243
|
+
);
|
|
244
|
+
} else {
|
|
245
|
+
pollIntervalMs = r.pollIntervalMs;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// databaseIds
|
|
249
|
+
let databaseIds: readonly string[] = [];
|
|
250
|
+
if (r.databaseIds !== undefined) {
|
|
251
|
+
if (!Array.isArray(r.databaseIds)) {
|
|
252
|
+
throw new TypeError(
|
|
253
|
+
`notion: databaseIds must be an array of strings (got ${typeof r.databaseIds})`,
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
const seen = new Set<string>();
|
|
257
|
+
const out: string[] = [];
|
|
258
|
+
for (const value of r.databaseIds) {
|
|
259
|
+
if (typeof value !== "string") {
|
|
260
|
+
throw new TypeError(
|
|
261
|
+
`notion: databaseIds entries must be strings; found ${typeof value}`,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
const trimmed = value.trim();
|
|
265
|
+
if (!isValidNotionId(trimmed)) {
|
|
266
|
+
throw new RangeError(
|
|
267
|
+
`notion: databaseIds entry ${JSON.stringify(value)} is not a valid Notion id`,
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
// Dedupe per CLAUDE.md gotcha #49.
|
|
271
|
+
if (seen.has(trimmed)) continue;
|
|
272
|
+
seen.add(trimmed);
|
|
273
|
+
out.push(trimmed);
|
|
274
|
+
}
|
|
275
|
+
databaseIds = Object.freeze(out);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return Object.freeze({ token, databaseIds, pollIntervalMs });
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Notion UUIDs look like `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` (32 hex, no
|
|
283
|
+
* dashes) or `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` (standard UUID). We
|
|
284
|
+
* accept both and reject everything else to surface config typos.
|
|
285
|
+
*/
|
|
286
|
+
function isValidNotionId(value: string): boolean {
|
|
287
|
+
// Standard UUID with dashes.
|
|
288
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) {
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
// Notion's compact form (32 hex chars, no dashes).
|
|
292
|
+
if (/^[0-9a-f]{32}$/i.test(value)) {
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
// Cursor helpers
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
|
|
302
|
+
function makeCursor(payload: NotionCursorPayload): ConnectorCursor {
|
|
303
|
+
return {
|
|
304
|
+
kind: NOTION_CURSOR_KIND,
|
|
305
|
+
value: JSON.stringify(payload),
|
|
306
|
+
updatedAt: new Date().toISOString(),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function parseCursorPayload(cursor: ConnectorCursor): NotionCursorPayload {
|
|
311
|
+
if (cursor.kind !== NOTION_CURSOR_KIND) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
`notion: unexpected cursor kind ${JSON.stringify(cursor.kind)}; expected ${NOTION_CURSOR_KIND}`,
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
// CLAUDE.md gotcha #18: validate after parse.
|
|
317
|
+
let parsed: unknown;
|
|
318
|
+
try {
|
|
319
|
+
parsed = JSON.parse(cursor.value);
|
|
320
|
+
} catch {
|
|
321
|
+
throw new Error(`notion: cursor value is not valid JSON`);
|
|
322
|
+
}
|
|
323
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
324
|
+
throw new Error(`notion: cursor value does not match NotionCursorPayload shape`);
|
|
325
|
+
}
|
|
326
|
+
const p = parsed as Record<string, unknown>;
|
|
327
|
+
const pages = typeof p.pages === "object" && p.pages !== null && !Array.isArray(p.pages)
|
|
328
|
+
? (p.pages as Record<string, string>)
|
|
329
|
+
: {};
|
|
330
|
+
const databases = typeof p.databases === "object" && p.databases !== null && !Array.isArray(p.databases)
|
|
331
|
+
? (p.databases as Record<string, string>)
|
|
332
|
+
: {};
|
|
333
|
+
return { pages, databases };
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ---------------------------------------------------------------------------
|
|
337
|
+
// Error classification
|
|
338
|
+
// ---------------------------------------------------------------------------
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Classify a per-page fetch error as transient (re-throw to caller so the
|
|
342
|
+
* sync stops without advancing the cursor and the next poll retries) or
|
|
343
|
+
* terminal (skip the page and continue).
|
|
344
|
+
*
|
|
345
|
+
* We use raw `fetch`, so errors arrive either as network-layer `Error`
|
|
346
|
+
* instances (no `.status`) or we detect them ourselves by inspecting the
|
|
347
|
+
* HTTP status code from the parsed JSON body (attached as `notionStatus`).
|
|
348
|
+
*
|
|
349
|
+
* Delegates to the shared `isTransientHttpError` helper in
|
|
350
|
+
* `transient-errors.ts` (Thread 3 — Cursor PRRT_kwDORJXyws59sdH4). The
|
|
351
|
+
* Notion-specific `notionStatus` property is passed as an extra lookup key
|
|
352
|
+
* so the shared resolver finds it before the generic `status` field.
|
|
353
|
+
*/
|
|
354
|
+
export function isTransientNotionError(err: unknown): boolean {
|
|
355
|
+
return isTransientHttpError(err, ["notionStatus"]);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// ---------------------------------------------------------------------------
|
|
359
|
+
// Notion API client helpers
|
|
360
|
+
// ---------------------------------------------------------------------------
|
|
361
|
+
|
|
362
|
+
const NOTION_BASE_URL = "https://api.notion.com/v1";
|
|
363
|
+
const NOTION_API_VERSION = "2022-06-28";
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Throw if aborted (cooperative cancellation).
|
|
367
|
+
*/
|
|
368
|
+
function throwIfAborted(signal: AbortSignal | undefined): void {
|
|
369
|
+
if (signal?.aborted) {
|
|
370
|
+
const err = new Error("notion: sync aborted");
|
|
371
|
+
err.name = "AbortError";
|
|
372
|
+
throw err;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Build a Notion API error with the HTTP status attached for classification.
|
|
378
|
+
*/
|
|
379
|
+
function makeNotionApiError(apiErr: NotionApiError): Error & { notionStatus: number } {
|
|
380
|
+
const err = new Error(
|
|
381
|
+
`notion: API error ${apiErr.status} (${apiErr.code}): ${apiErr.message}`,
|
|
382
|
+
) as Error & { notionStatus: number };
|
|
383
|
+
err.notionStatus = apiErr.status;
|
|
384
|
+
return err;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Helper to call a Notion API endpoint. Throws a structured error on
|
|
389
|
+
* non-2xx responses and propagates network errors unchanged so the
|
|
390
|
+
* transient/terminal classifier can inspect them.
|
|
391
|
+
*/
|
|
392
|
+
async function notionFetch(
|
|
393
|
+
fetchFn: NotionFetchFn,
|
|
394
|
+
token: string,
|
|
395
|
+
path: string,
|
|
396
|
+
body: unknown,
|
|
397
|
+
signal: AbortSignal | undefined,
|
|
398
|
+
): Promise<unknown> {
|
|
399
|
+
const url = `${NOTION_BASE_URL}${path}`;
|
|
400
|
+
const res = await fetchFn(url, {
|
|
401
|
+
method: "POST",
|
|
402
|
+
headers: {
|
|
403
|
+
Authorization: `Bearer ${token}`,
|
|
404
|
+
"Notion-Version": NOTION_API_VERSION,
|
|
405
|
+
"Content-Type": "application/json",
|
|
406
|
+
},
|
|
407
|
+
body: JSON.stringify(body),
|
|
408
|
+
signal,
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
const data = await res.json();
|
|
412
|
+
if (!res.ok) {
|
|
413
|
+
// Notion error responses carry `{object: "error", status, code, message}`.
|
|
414
|
+
if (
|
|
415
|
+
typeof data === "object" &&
|
|
416
|
+
data !== null &&
|
|
417
|
+
(data as Record<string, unknown>).object === "error"
|
|
418
|
+
) {
|
|
419
|
+
throw makeNotionApiError(data as NotionApiError);
|
|
420
|
+
}
|
|
421
|
+
// Unexpected non-error-shaped body.
|
|
422
|
+
const err = new Error(`notion: HTTP ${res.status}`) as Error & { notionStatus: number };
|
|
423
|
+
err.notionStatus = res.status;
|
|
424
|
+
throw err;
|
|
425
|
+
}
|
|
426
|
+
return data;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* GET helper — used for block children (GET endpoint, no body).
|
|
431
|
+
*/
|
|
432
|
+
async function notionGet(
|
|
433
|
+
fetchFn: NotionFetchFn,
|
|
434
|
+
token: string,
|
|
435
|
+
path: string,
|
|
436
|
+
signal: AbortSignal | undefined,
|
|
437
|
+
): Promise<unknown> {
|
|
438
|
+
const url = `${NOTION_BASE_URL}${path}`;
|
|
439
|
+
const res = await fetchFn(url, {
|
|
440
|
+
method: "GET",
|
|
441
|
+
headers: {
|
|
442
|
+
Authorization: `Bearer ${token}`,
|
|
443
|
+
"Notion-Version": NOTION_API_VERSION,
|
|
444
|
+
},
|
|
445
|
+
signal,
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
const data = await res.json();
|
|
449
|
+
if (!res.ok) {
|
|
450
|
+
if (
|
|
451
|
+
typeof data === "object" &&
|
|
452
|
+
data !== null &&
|
|
453
|
+
(data as Record<string, unknown>).object === "error"
|
|
454
|
+
) {
|
|
455
|
+
throw makeNotionApiError(data as NotionApiError);
|
|
456
|
+
}
|
|
457
|
+
const err = new Error(`notion: HTTP ${res.status}`) as Error & { notionStatus: number };
|
|
458
|
+
err.notionStatus = res.status;
|
|
459
|
+
throw err;
|
|
460
|
+
}
|
|
461
|
+
return data;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// ---------------------------------------------------------------------------
|
|
465
|
+
// Block text extraction
|
|
466
|
+
// ---------------------------------------------------------------------------
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Extract all `rich_text[].plain_text` segments from a rich-text array.
|
|
470
|
+
*/
|
|
471
|
+
function extractRichText(richText: unknown): string {
|
|
472
|
+
if (!Array.isArray(richText)) return "";
|
|
473
|
+
return richText
|
|
474
|
+
.map((span) => {
|
|
475
|
+
if (typeof span !== "object" || span === null) return "";
|
|
476
|
+
return typeof (span as Record<string, unknown>).plain_text === "string"
|
|
477
|
+
? ((span as Record<string, unknown>).plain_text as string)
|
|
478
|
+
: "";
|
|
479
|
+
})
|
|
480
|
+
.join("");
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Extract the text portion of a single block. Returns an empty string for
|
|
485
|
+
* block types we don't recognize.
|
|
486
|
+
*/
|
|
487
|
+
function extractBlockText(block: NotionBlock): string {
|
|
488
|
+
const type = block.type;
|
|
489
|
+
const blockData = block[type];
|
|
490
|
+
if (typeof blockData !== "object" || blockData === null) return "";
|
|
491
|
+
const data = blockData as Record<string, unknown>;
|
|
492
|
+
|
|
493
|
+
// Most text-bearing blocks have a `rich_text` array.
|
|
494
|
+
if (Array.isArray(data.rich_text)) {
|
|
495
|
+
const text = extractRichText(data.rich_text);
|
|
496
|
+
if (text.length > 0) {
|
|
497
|
+
// Prefix heading blocks with Markdown syntax.
|
|
498
|
+
if (type === "heading_1") return `# ${text}`;
|
|
499
|
+
if (type === "heading_2") return `## ${text}`;
|
|
500
|
+
if (type === "heading_3") return `### ${text}`;
|
|
501
|
+
if (type === "to_do") {
|
|
502
|
+
const checked = data.checked === true;
|
|
503
|
+
return `- [${checked ? "x" : " "}] ${text}`;
|
|
504
|
+
}
|
|
505
|
+
if (type === "bulleted_list_item" || type === "numbered_list_item") {
|
|
506
|
+
return `- ${text}`;
|
|
507
|
+
}
|
|
508
|
+
return text;
|
|
509
|
+
}
|
|
510
|
+
return "";
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Code block has `rich_text` plus an optional `language` field.
|
|
514
|
+
if (type === "code" && Array.isArray(data.rich_text)) {
|
|
515
|
+
return extractRichText(data.rich_text);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return "";
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Recursively fetch all block children for a page (or block with children)
|
|
523
|
+
* and extract plain text. Bounded by `MAX_BLOCK_DEPTH` and `MAX_TEXT_BYTES`
|
|
524
|
+
* to prevent runaway recursion or OOM on huge pages.
|
|
525
|
+
*/
|
|
526
|
+
async function fetchPageText(
|
|
527
|
+
fetchFn: NotionFetchFn,
|
|
528
|
+
token: string,
|
|
529
|
+
blockId: string,
|
|
530
|
+
depth: number,
|
|
531
|
+
signal: AbortSignal | undefined,
|
|
532
|
+
): Promise<string> {
|
|
533
|
+
if (depth > MAX_BLOCK_DEPTH) return "";
|
|
534
|
+
throwIfAborted(signal);
|
|
535
|
+
|
|
536
|
+
const lines: string[] = [];
|
|
537
|
+
let cursor: string | undefined = undefined;
|
|
538
|
+
|
|
539
|
+
// Page through block children.
|
|
540
|
+
while (true) {
|
|
541
|
+
throwIfAborted(signal);
|
|
542
|
+
const pathQuery = cursor
|
|
543
|
+
? `/blocks/${blockId}/children?page_size=100&start_cursor=${encodeURIComponent(cursor)}`
|
|
544
|
+
: `/blocks/${blockId}/children?page_size=100`;
|
|
545
|
+
const data = await notionGet(fetchFn, token, pathQuery, signal);
|
|
546
|
+
|
|
547
|
+
if (typeof data !== "object" || data === null) break;
|
|
548
|
+
const page = data as {
|
|
549
|
+
results?: NotionBlock[];
|
|
550
|
+
next_cursor?: string | null;
|
|
551
|
+
has_more?: boolean;
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
for (const block of page.results ?? []) {
|
|
555
|
+
throwIfAborted(signal);
|
|
556
|
+
const text = extractBlockText(block);
|
|
557
|
+
if (text.length > 0) lines.push(text);
|
|
558
|
+
|
|
559
|
+
// Recurse into nested blocks.
|
|
560
|
+
if (block.has_children && depth < MAX_BLOCK_DEPTH) {
|
|
561
|
+
const childText = await fetchPageText(
|
|
562
|
+
fetchFn,
|
|
563
|
+
token,
|
|
564
|
+
block.id,
|
|
565
|
+
depth + 1,
|
|
566
|
+
signal,
|
|
567
|
+
);
|
|
568
|
+
if (childText.length > 0) lines.push(childText);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Guard against oversized pages.
|
|
572
|
+
const currentSize = lines.reduce((acc, l) => acc + l.length + 1, 0);
|
|
573
|
+
if (currentSize >= MAX_TEXT_BYTES) break;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (!page.has_more || typeof page.next_cursor !== "string" || page.next_cursor === null) {
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
cursor = page.next_cursor;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
return lines.join("\n");
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// ---------------------------------------------------------------------------
|
|
586
|
+
// Page title extraction
|
|
587
|
+
// ---------------------------------------------------------------------------
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Extract the page title from the page properties. Notion stores the title
|
|
591
|
+
* under a property of type `"title"` — typically named "Name" but the name
|
|
592
|
+
* can vary. We look for the first `type: "title"` property we find.
|
|
593
|
+
*/
|
|
594
|
+
function extractPageTitle(page: NotionPage): string | undefined {
|
|
595
|
+
if (typeof page.properties !== "object" || page.properties === null) return undefined;
|
|
596
|
+
for (const prop of Object.values(page.properties)) {
|
|
597
|
+
if (prop.type === "title" && Array.isArray(prop.title)) {
|
|
598
|
+
const text = prop.title.map((t) => t.plain_text ?? "").join("");
|
|
599
|
+
if (text.trim().length > 0) return text.trim();
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return undefined;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// ---------------------------------------------------------------------------
|
|
606
|
+
// Sync result type
|
|
607
|
+
// ---------------------------------------------------------------------------
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Result of a single sync pass. Superset of `SyncIncrementalResult` for
|
|
611
|
+
* richer test assertions.
|
|
612
|
+
*/
|
|
613
|
+
export interface NotionSyncResult extends SyncIncrementalResult {
|
|
614
|
+
readonly skippedUnchanged: number;
|
|
615
|
+
readonly skippedTooLarge: number;
|
|
616
|
+
readonly skippedEmpty: number;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// ---------------------------------------------------------------------------
|
|
620
|
+
// Connector factory
|
|
621
|
+
// ---------------------------------------------------------------------------
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Construct the connector. The `fetchFn` argument is the test hook —
|
|
625
|
+
* production callers omit it and the connector uses the global `fetch`.
|
|
626
|
+
*/
|
|
627
|
+
export function createNotionConnector(
|
|
628
|
+
options: { fetchFn?: NotionFetchFn } = {},
|
|
629
|
+
): LiveConnector {
|
|
630
|
+
const fetchFn: NotionFetchFn =
|
|
631
|
+
options.fetchFn ??
|
|
632
|
+
// Use global fetch (available in Node.js 18+). The cast is safe — we
|
|
633
|
+
// only use the subset defined in `NotionFetchFn`.
|
|
634
|
+
(globalThis.fetch as unknown as NotionFetchFn);
|
|
635
|
+
|
|
636
|
+
return {
|
|
637
|
+
id: NOTION_CONNECTOR_ID,
|
|
638
|
+
displayName: "Notion",
|
|
639
|
+
description:
|
|
640
|
+
"Imports text content from Notion database pages into Remnic on a poll schedule.",
|
|
641
|
+
|
|
642
|
+
validateConfig(raw: unknown): ConnectorConfig {
|
|
643
|
+
return validateNotionConfig(raw) as unknown as ConnectorConfig;
|
|
644
|
+
},
|
|
645
|
+
|
|
646
|
+
async syncIncremental(args: SyncIncrementalArgs): Promise<SyncIncrementalResult> {
|
|
647
|
+
const config = validateNotionConfig(args.config);
|
|
648
|
+
throwIfAborted(args.abortSignal);
|
|
649
|
+
|
|
650
|
+
// Short-circuit: if no databases are configured, there is nothing to do.
|
|
651
|
+
// We still return a valid cursor so the framework has something to
|
|
652
|
+
// persist (avoids a null-cursor on the next pass).
|
|
653
|
+
if (config.databaseIds.length === 0) {
|
|
654
|
+
const emptyPayload: NotionCursorPayload = { pages: {}, databases: {} };
|
|
655
|
+
const result: NotionSyncResult = {
|
|
656
|
+
newDocs: [],
|
|
657
|
+
nextCursor: makeCursor(emptyPayload),
|
|
658
|
+
skippedUnchanged: 0,
|
|
659
|
+
skippedTooLarge: 0,
|
|
660
|
+
skippedEmpty: 0,
|
|
661
|
+
};
|
|
662
|
+
return result;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// Parse or seed the cursor.
|
|
666
|
+
const isFirstSync = args.cursor === null;
|
|
667
|
+
const payload: NotionCursorPayload = isFirstSync
|
|
668
|
+
? { pages: {}, databases: {} }
|
|
669
|
+
: parseCursorPayload(args.cursor);
|
|
670
|
+
|
|
671
|
+
// On first sync we seed the watermark WITHOUT importing any content
|
|
672
|
+
// (mirrors Drive's getStartPageToken bootstrap pattern).
|
|
673
|
+
if (isFirstSync) {
|
|
674
|
+
const seedPayload = await seedWatermark(
|
|
675
|
+
fetchFn,
|
|
676
|
+
config,
|
|
677
|
+
payload,
|
|
678
|
+
args.abortSignal,
|
|
679
|
+
);
|
|
680
|
+
return {
|
|
681
|
+
newDocs: [],
|
|
682
|
+
nextCursor: makeCursor(seedPayload),
|
|
683
|
+
skippedUnchanged: 0,
|
|
684
|
+
skippedTooLarge: 0,
|
|
685
|
+
skippedEmpty: 0,
|
|
686
|
+
} as NotionSyncResult;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// Incremental pass.
|
|
690
|
+
return await incrementalSync(fetchFn, config, payload, args.abortSignal);
|
|
691
|
+
},
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// ---------------------------------------------------------------------------
|
|
696
|
+
// First-sync seeding
|
|
697
|
+
// ---------------------------------------------------------------------------
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Seed the watermark from the current state of every configured database.
|
|
701
|
+
* We record the latest `last_edited_time` we see per page and per database
|
|
702
|
+
* so the next pass only imports future edits.
|
|
703
|
+
*/
|
|
704
|
+
async function seedWatermark(
|
|
705
|
+
fetchFn: NotionFetchFn,
|
|
706
|
+
config: NotionConnectorConfig,
|
|
707
|
+
payload: NotionCursorPayload,
|
|
708
|
+
signal: AbortSignal | undefined,
|
|
709
|
+
): Promise<NotionCursorPayload> {
|
|
710
|
+
const pages = { ...payload.pages };
|
|
711
|
+
const databases = { ...payload.databases };
|
|
712
|
+
|
|
713
|
+
for (const dbId of config.databaseIds) {
|
|
714
|
+
throwIfAborted(signal);
|
|
715
|
+
let notionCursor: string | undefined = undefined;
|
|
716
|
+
let latestInDb = "";
|
|
717
|
+
|
|
718
|
+
while (true) {
|
|
719
|
+
throwIfAborted(signal);
|
|
720
|
+
const body: Record<string, unknown> = { page_size: 100, sorts: [] };
|
|
721
|
+
if (notionCursor) body.start_cursor = notionCursor;
|
|
722
|
+
|
|
723
|
+
const data = await notionFetch(
|
|
724
|
+
fetchFn,
|
|
725
|
+
config.token,
|
|
726
|
+
`/databases/${dbId}/query`,
|
|
727
|
+
body,
|
|
728
|
+
signal,
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
if (typeof data !== "object" || data === null) break;
|
|
732
|
+
const page = data as {
|
|
733
|
+
results?: NotionPage[];
|
|
734
|
+
next_cursor?: string | null;
|
|
735
|
+
has_more?: boolean;
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
for (const p of page.results ?? []) {
|
|
739
|
+
if (typeof p.id === "string" && typeof p.last_edited_time === "string") {
|
|
740
|
+
pages[p.id] = p.last_edited_time;
|
|
741
|
+
if (!latestInDb || p.last_edited_time > latestInDb) {
|
|
742
|
+
latestInDb = p.last_edited_time;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
if (!page.has_more || typeof page.next_cursor !== "string" || page.next_cursor === null) {
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
notionCursor = page.next_cursor;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
if (latestInDb) databases[dbId] = latestInDb;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
return { pages, databases };
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// ---------------------------------------------------------------------------
|
|
760
|
+
// Incremental sync
|
|
761
|
+
// ---------------------------------------------------------------------------
|
|
762
|
+
|
|
763
|
+
async function incrementalSync(
|
|
764
|
+
fetchFn: NotionFetchFn,
|
|
765
|
+
config: NotionConnectorConfig,
|
|
766
|
+
payload: NotionCursorPayload,
|
|
767
|
+
signal: AbortSignal | undefined,
|
|
768
|
+
): Promise<NotionSyncResult> {
|
|
769
|
+
const fetchedAt = new Date().toISOString();
|
|
770
|
+
const newDocs: ConnectorDocument[] = [];
|
|
771
|
+
const updatedPages = { ...payload.pages };
|
|
772
|
+
const updatedDatabases = { ...payload.databases };
|
|
773
|
+
let skippedUnchanged = 0;
|
|
774
|
+
let skippedTooLarge = 0;
|
|
775
|
+
let skippedEmpty = 0;
|
|
776
|
+
let totalConsumed = 0;
|
|
777
|
+
|
|
778
|
+
for (const dbId of config.databaseIds) {
|
|
779
|
+
throwIfAborted(signal);
|
|
780
|
+
if (totalConsumed >= MAX_PAGES_PER_PASS) break;
|
|
781
|
+
|
|
782
|
+
const dbWatermark = payload.databases[dbId];
|
|
783
|
+
let notionCursor: string | undefined = undefined;
|
|
784
|
+
let latestInDb = dbWatermark ?? "";
|
|
785
|
+
// Track whether we fully drained this database during the pass.
|
|
786
|
+
//
|
|
787
|
+
// Why this matters (codex review P1): we sort the query descending by
|
|
788
|
+
// `last_edited_time` and filter `after: dbWatermark`. If we hit
|
|
789
|
+
// MAX_PAGES_PER_PASS or get aborted mid-database, the pages we
|
|
790
|
+
// *haven't* seen yet are *older* than the ones we have seen. Advancing
|
|
791
|
+
// `databases[dbId]` to the highest `last_edited_time` we saw would set
|
|
792
|
+
// the next pass's `after` filter past those still-pending older pages
|
|
793
|
+
// and skip them forever (they only resurface if re-edited).
|
|
794
|
+
//
|
|
795
|
+
// Solution: only persist the new database watermark when the database
|
|
796
|
+
// was fully drained for this pass. If we cut off early, leave
|
|
797
|
+
// `databases[dbId]` at its previous value so the next pass re-queries
|
|
798
|
+
// the same `after` filter and finishes the leftovers.
|
|
799
|
+
let databaseFullyDrained = false;
|
|
800
|
+
|
|
801
|
+
while (true) {
|
|
802
|
+
throwIfAborted(signal);
|
|
803
|
+
if (totalConsumed >= MAX_PAGES_PER_PASS) break;
|
|
804
|
+
|
|
805
|
+
const body: Record<string, unknown> = {
|
|
806
|
+
page_size: 100,
|
|
807
|
+
sorts: [
|
|
808
|
+
{
|
|
809
|
+
timestamp: "last_edited_time",
|
|
810
|
+
direction: "descending",
|
|
811
|
+
},
|
|
812
|
+
],
|
|
813
|
+
};
|
|
814
|
+
// Filter to pages edited after the database watermark.
|
|
815
|
+
if (dbWatermark) {
|
|
816
|
+
body.filter = {
|
|
817
|
+
timestamp: "last_edited_time",
|
|
818
|
+
last_edited_time: { after: dbWatermark },
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
if (notionCursor) body.start_cursor = notionCursor;
|
|
822
|
+
|
|
823
|
+
const data = await notionFetch(
|
|
824
|
+
fetchFn,
|
|
825
|
+
config.token,
|
|
826
|
+
`/databases/${dbId}/query`,
|
|
827
|
+
body,
|
|
828
|
+
signal,
|
|
829
|
+
);
|
|
830
|
+
|
|
831
|
+
if (typeof data !== "object" || data === null) break;
|
|
832
|
+
const pageResp = data as {
|
|
833
|
+
results?: NotionPage[];
|
|
834
|
+
next_cursor?: string | null;
|
|
835
|
+
has_more?: boolean;
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
let cutoffMidPage = false;
|
|
839
|
+
for (const notionPage of pageResp.results ?? []) {
|
|
840
|
+
throwIfAborted(signal);
|
|
841
|
+
totalConsumed++;
|
|
842
|
+
|
|
843
|
+
const pageId = notionPage.id;
|
|
844
|
+
const lastEdited = notionPage.last_edited_time;
|
|
845
|
+
|
|
846
|
+
if (typeof pageId !== "string" || typeof lastEdited !== "string") continue;
|
|
847
|
+
|
|
848
|
+
// Skip pages that haven't changed since we last saw them.
|
|
849
|
+
const knownRevision = payload.pages[pageId];
|
|
850
|
+
if (knownRevision && knownRevision >= lastEdited) {
|
|
851
|
+
skippedUnchanged++;
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// Fetch and build the document.
|
|
856
|
+
const doc = await fetchPageDocument(
|
|
857
|
+
fetchFn,
|
|
858
|
+
config.token,
|
|
859
|
+
notionPage,
|
|
860
|
+
fetchedAt,
|
|
861
|
+
signal,
|
|
862
|
+
);
|
|
863
|
+
|
|
864
|
+
if (doc === "too-large") {
|
|
865
|
+
skippedTooLarge++;
|
|
866
|
+
// Codex review P2: record the revision so we don't re-fetch this
|
|
867
|
+
// oversized page on every subsequent poll. If the page shrinks
|
|
868
|
+
// below the limit on a future edit, `last_edited_time` will
|
|
869
|
+
// advance and the watermark check above will let it through.
|
|
870
|
+
updatedPages[pageId] = lastEdited;
|
|
871
|
+
} else if (doc === "empty") {
|
|
872
|
+
skippedEmpty++;
|
|
873
|
+
// Codex review P2: same reasoning as too-large — record the
|
|
874
|
+
// revision so we don't re-fetch an empty page indefinitely.
|
|
875
|
+
updatedPages[pageId] = lastEdited;
|
|
876
|
+
} else if (doc !== null) {
|
|
877
|
+
newDocs.push(doc);
|
|
878
|
+
// Advance watermarks.
|
|
879
|
+
updatedPages[pageId] = lastEdited;
|
|
880
|
+
if (!latestInDb || lastEdited > latestInDb) {
|
|
881
|
+
latestInDb = lastEdited;
|
|
882
|
+
}
|
|
883
|
+
} else {
|
|
884
|
+
// null = terminal skip (404/403). Record the version so we
|
|
885
|
+
// don't repeatedly attempt a permanently-inaccessible page.
|
|
886
|
+
updatedPages[pageId] = lastEdited;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
if (totalConsumed >= MAX_PAGES_PER_PASS) {
|
|
890
|
+
cutoffMidPage = true;
|
|
891
|
+
break;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (cutoffMidPage) {
|
|
896
|
+
// Hit the per-pass cap inside this database's results. The
|
|
897
|
+
// database is NOT fully drained; leave its watermark intact so
|
|
898
|
+
// the next pass re-queries the same `after` filter.
|
|
899
|
+
break;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (pageResp.has_more === true) {
|
|
903
|
+
// Notion claims there are more pages.
|
|
904
|
+
if (typeof pageResp.next_cursor === "string" && pageResp.next_cursor.length > 0) {
|
|
905
|
+
// Continue paging.
|
|
906
|
+
notionCursor = pageResp.next_cursor;
|
|
907
|
+
continue;
|
|
908
|
+
}
|
|
909
|
+
// Defensive bail: has_more=true but no usable next_cursor. We do
|
|
910
|
+
// NOT mark the database fully drained — the next pass must retry
|
|
911
|
+
// the same `after` filter and pick up whatever we missed.
|
|
912
|
+
break;
|
|
913
|
+
}
|
|
914
|
+
// has_more is false (or absent): the database is fully drained for
|
|
915
|
+
// this pass. Safe to advance the database watermark below.
|
|
916
|
+
databaseFullyDrained = true;
|
|
917
|
+
break;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// Only advance the database watermark when we fully drained the
|
|
921
|
+
// database. See the long comment above on `databaseFullyDrained`.
|
|
922
|
+
if (databaseFullyDrained && latestInDb) {
|
|
923
|
+
updatedDatabases[dbId] = latestInDb;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
const nextCursor = makeCursor({ pages: updatedPages, databases: updatedDatabases });
|
|
928
|
+
return {
|
|
929
|
+
newDocs,
|
|
930
|
+
nextCursor,
|
|
931
|
+
skippedUnchanged,
|
|
932
|
+
skippedTooLarge,
|
|
933
|
+
skippedEmpty,
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// ---------------------------------------------------------------------------
|
|
938
|
+
// Per-page document fetch
|
|
939
|
+
// ---------------------------------------------------------------------------
|
|
940
|
+
|
|
941
|
+
async function fetchPageDocument(
|
|
942
|
+
fetchFn: NotionFetchFn,
|
|
943
|
+
token: string,
|
|
944
|
+
notionPage: NotionPage,
|
|
945
|
+
fetchedAt: string,
|
|
946
|
+
signal: AbortSignal | undefined,
|
|
947
|
+
): Promise<ConnectorDocument | "too-large" | "empty" | null> {
|
|
948
|
+
throwIfAborted(signal);
|
|
949
|
+
|
|
950
|
+
let text: string;
|
|
951
|
+
try {
|
|
952
|
+
text = await fetchPageText(fetchFn, token, notionPage.id, 0, signal);
|
|
953
|
+
} catch (err) {
|
|
954
|
+
if (isTransientNotionError(err)) {
|
|
955
|
+
throw err;
|
|
956
|
+
}
|
|
957
|
+
// Terminal (404/403/400): skip this page.
|
|
958
|
+
return null;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (typeof text !== "string" || text.trim().length === 0) return "empty";
|
|
962
|
+
if (text.length > MAX_TEXT_BYTES) return "too-large";
|
|
963
|
+
|
|
964
|
+
const title = extractPageTitle(notionPage);
|
|
965
|
+
|
|
966
|
+
return {
|
|
967
|
+
id: notionPage.id,
|
|
968
|
+
title,
|
|
969
|
+
content: text,
|
|
970
|
+
source: {
|
|
971
|
+
connector: NOTION_CONNECTOR_ID,
|
|
972
|
+
externalId: notionPage.id,
|
|
973
|
+
externalRevision: notionPage.last_edited_time,
|
|
974
|
+
externalUrl: typeof notionPage.url === "string" ? notionPage.url : undefined,
|
|
975
|
+
fetchedAt,
|
|
976
|
+
},
|
|
977
|
+
};
|
|
978
|
+
}
|