@remnic/core 10.0.27 → 10.0.29
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-admin-ops-surface.js +54 -53
- package/dist/access-authorization-probe.js +55 -54
- package/dist/access-boundary.js +54 -53
- package/dist/access-citation-namespace.js +3 -2
- package/dist/access-cli.js +106 -105
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.js +54 -53
- package/dist/access-http-briefing.js +55 -54
- package/dist/access-http-query.js +56 -55
- package/dist/access-http.js +73 -72
- package/dist/access-identity-continuity-surface.js +54 -53
- package/dist/access-lcm-surface.js +54 -53
- package/dist/access-mcp.js +65 -64
- package/dist/access-namespace-preflight.js +54 -53
- package/dist/access-observe-write-category.js +11 -11
- package/dist/access-observe-write-surface.js +54 -53
- package/dist/access-offline-manifest.js +10 -10
- package/dist/access-operations-batch.js +56 -55
- package/dist/access-operations.js +63 -62
- package/dist/access-recall-concurrency.js +54 -53
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +54 -53
- package/dist/access-recall-surface.js +54 -53
- package/dist/access-schema.js +6 -5
- package/dist/access-service.js +54 -53
- package/dist/access-surface-catalog.js +56 -55
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/active-recall.js +24 -23
- package/dist/active-recall.js.map +1 -1
- package/dist/{auto-sync-UQESPLCB.js → auto-sync-MX2AHVPQ.js} +8 -8
- package/dist/briefing.js +20 -19
- package/dist/buffer.js +8 -8
- package/dist/calibration.js +2 -2
- package/dist/{capsule-merge-LGYURS3C.js → capsule-merge-LGYZAMO4.js} +3 -3
- package/dist/causal-consolidation.js +22 -21
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-G6XEYFCO.js → chunk-27OJ5G3D.js} +14 -14
- package/dist/{chunk-5LRV557D.js → chunk-2FIJQNL7.js} +2 -2
- package/dist/{chunk-ETPIYK4J.js → chunk-2VBDSZ7U.js} +2 -2
- package/dist/{chunk-QNKEMFZY.js → chunk-2WDMUQOH.js} +2 -2
- package/dist/{chunk-W6MOLW5S.js → chunk-2XVLY424.js} +4 -4
- package/dist/{chunk-P55FACBG.js → chunk-3BOQPLCF.js} +6 -6
- package/dist/{chunk-27SAUQ5R.js → chunk-3CHHQXAR.js} +2 -2
- package/dist/{chunk-3GYSZHMT.js → chunk-3CZRBTJK.js} +2 -2
- package/dist/{chunk-FJJWA7NL.js → chunk-3EJQXF3B.js} +2 -2
- package/dist/{chunk-HFSPY26A.js → chunk-3IXNL6SK.js} +2 -2
- package/dist/{chunk-PLD6SOU7.js → chunk-3SN2D43X.js} +2 -2
- package/dist/{chunk-COGLFRXT.js → chunk-4HNINU7Q.js} +31 -31
- package/dist/{chunk-CCDHRDQ3.js → chunk-4HYP4OKH.js} +2 -2
- package/dist/{chunk-GKJJNO7C.js → chunk-4OE4UE2Y.js} +6 -6
- package/dist/{chunk-7RTNJ6M2.js → chunk-4QPW6JVI.js} +2 -2
- package/dist/{chunk-5SMR542T.js → chunk-5GT4ESLR.js} +2 -2
- package/dist/{chunk-DWL6YIZH.js → chunk-5JI3XWI2.js} +2 -2
- package/dist/{chunk-27LPB4NS.js → chunk-5NPZFXQH.js} +2 -2
- package/dist/{chunk-Y6IF6H2U.js → chunk-5SMHQW45.js} +2 -2
- package/dist/{chunk-VN3GHPBU.js → chunk-654GT5UP.js} +2 -2
- package/dist/{chunk-3E6DGSGZ.js → chunk-6MC7UQ6D.js} +2 -2
- package/dist/{chunk-655FVTCD.js → chunk-74IN6PV5.js} +2 -2
- package/dist/{chunk-WFUO7NWX.js → chunk-7FZ4YVOH.js} +2 -2
- package/dist/{chunk-MWWAQXZ6.js → chunk-7HFTCBCZ.js} +2 -2
- package/dist/{chunk-7IOB5F7Y.js → chunk-7VB3Y5OL.js} +3 -3
- package/dist/{chunk-YEF5AAWN.js → chunk-A54E2ZTD.js} +2 -2
- package/dist/{chunk-DEY7B77Y.js → chunk-AHCELJMH.js} +2 -2
- package/dist/{chunk-PIWFNPQT.js → chunk-AL3TCNSJ.js} +4 -4
- package/dist/{chunk-EET24NSB.js → chunk-AUYFUBBE.js} +6 -6
- package/dist/{chunk-L3IP56F4.js → chunk-BIE3ZH3N.js} +33 -33
- package/dist/{chunk-A3IURDU2.js → chunk-C2AOL6MK.js} +3 -3
- package/dist/{chunk-BDQMMX3M.js → chunk-C2QVDLQV.js} +2 -2
- package/dist/{chunk-H75L4ZOH.js → chunk-CKR7LXEK.js} +71 -49
- package/dist/chunk-CKR7LXEK.js.map +1 -0
- package/dist/{chunk-AWLQNLTM.js → chunk-CSGFGQBI.js} +2 -2
- package/dist/{chunk-JHQAXATW.js → chunk-D4RV54HH.js} +2 -2
- package/dist/{chunk-33UAWCBN.js → chunk-DDLRKPR2.js} +6 -6
- package/dist/{chunk-3X3PNU3T.js → chunk-DLH3ECZP.js} +5 -5
- package/dist/chunk-DNIG3JME.js +892 -0
- package/dist/chunk-DNIG3JME.js.map +1 -0
- package/dist/{chunk-SA6GMZJY.js → chunk-DP3TSAYT.js} +2 -2
- package/dist/{chunk-H2X22KZW.js → chunk-FN6OFDBZ.js} +2 -2
- package/dist/{chunk-SU5V2LWR.js → chunk-G6DAE2LT.js} +2 -2
- package/dist/{chunk-V7KGDLBC.js → chunk-GQ7VWY6N.js} +2 -2
- package/dist/{chunk-SYUNCM26.js → chunk-GSKW64NB.js} +2 -2
- package/dist/{chunk-4WT6I4VG.js → chunk-GWB7ZD2A.js} +2 -2
- package/dist/{chunk-JYZLDZ2R.js → chunk-HG2VVIKI.js} +9 -9
- package/dist/{chunk-3VRMUNWL.js → chunk-HJ444KNS.js} +15 -7
- package/dist/chunk-HJ444KNS.js.map +1 -0
- package/dist/{chunk-23ZQPP2G.js → chunk-HOSJESKO.js} +3 -3
- package/dist/{chunk-EU6IRUCY.js → chunk-IDPZCHET.js} +2 -2
- package/dist/{chunk-VMHCC7LO.js → chunk-IO2UQVR2.js} +2 -2
- package/dist/{chunk-BWXKJDDH.js → chunk-ISMZ5UNE.js} +3 -3
- package/dist/{chunk-SX4QDWXK.js → chunk-IWUFKS4J.js} +2 -2
- package/dist/{chunk-I27WOMJ7.js → chunk-IY7DGT2Z.js} +2 -2
- package/dist/{chunk-STBX5X6B.js → chunk-JAYNUYSJ.js} +2 -2
- package/dist/{chunk-N34ZW6E4.js → chunk-K2REHR42.js} +2 -2
- package/dist/{chunk-UJPGQCXD.js → chunk-KFKFK6G6.js} +10 -10
- package/dist/{chunk-2HLMFRZ7.js → chunk-LDEKVBVO.js} +4 -4
- package/dist/{chunk-42KSEX6C.js → chunk-LDXNKEYB.js} +1 -1
- package/dist/chunk-LDXNKEYB.js.map +1 -0
- package/dist/{chunk-MPZYCRC6.js → chunk-M236YHUH.js} +5 -5
- package/dist/{chunk-L5VCT7LU.js → chunk-MCLZM5G7.js} +2 -2
- package/dist/{chunk-7Z3DLNSD.js → chunk-MGKH5KO3.js} +2 -2
- package/dist/{chunk-PUDYANAX.js → chunk-MMBLOJJB.js} +2 -2
- package/dist/{chunk-EFHNFTWB.js → chunk-MND4YJSX.js} +2 -2
- package/dist/{chunk-HJQXHLQQ.js → chunk-MROA6OFU.js} +2 -2
- package/dist/{chunk-BQOGQULP.js → chunk-MZZEMPCI.js} +2 -2
- package/dist/{chunk-ERAVI25Z.js → chunk-NAPHQ2MG.js} +2 -2
- package/dist/{chunk-L5TJWQEF.js → chunk-NB2YX6X2.js} +6 -6
- package/dist/{chunk-IHGLQJW6.js → chunk-NCPR2FOJ.js} +3 -3
- package/dist/{chunk-UKWRCQWT.js → chunk-NOMHXZD7.js} +2 -2
- package/dist/{chunk-DF2G4IXN.js → chunk-NPO4ZQFY.js} +3 -3
- package/dist/{chunk-LWFWZTWX.js → chunk-NQV6G6MU.js} +2 -2
- package/dist/{chunk-5HT35H4L.js → chunk-NRLWHZVS.js} +2 -2
- package/dist/{chunk-GCZHKBY2.js → chunk-OANSZGAG.js} +2 -2
- package/dist/{chunk-BHQPOCQE.js → chunk-OIIAIY7J.js} +3 -3
- package/dist/{chunk-FFGHFU7A.js → chunk-OXX4ORRL.js} +17 -17
- package/dist/{chunk-RTTPBBAN.js → chunk-OXYXMGRH.js} +4 -4
- package/dist/{chunk-K7BN34IA.js → chunk-PL26BCRN.js} +5 -5
- package/dist/{chunk-PM72NSEW.js → chunk-PYCTZ2HX.js} +2 -2
- package/dist/{chunk-AQ52ZFBC.js → chunk-PZEADMX4.js} +2 -2
- package/dist/{chunk-QPH52AZB.js → chunk-QNDOTDJK.js} +2 -2
- package/dist/{chunk-LZACDIM2.js → chunk-RBGRQEW3.js} +4 -4
- package/dist/{chunk-H3AW6QZF.js → chunk-RRJ462HP.js} +2 -2
- package/dist/{chunk-V4JZCTMK.js → chunk-TKBW4YLS.js} +2 -2
- package/dist/{chunk-4D2YH47Z.js → chunk-TRW7N4FS.js} +2 -2
- package/dist/{chunk-IHS2UGYM.js → chunk-TTIEXXL3.js} +366 -1109
- package/dist/chunk-TTIEXXL3.js.map +1 -0
- package/dist/{chunk-OQJKY3Z5.js → chunk-UAAAXSKQ.js} +2 -2
- package/dist/{chunk-S36KJNQH.js → chunk-UM73Q46J.js} +2 -2
- package/dist/{chunk-7EJCAFMS.js → chunk-UTXYOWDR.js} +2 -2
- package/dist/{chunk-AYHPSYZI.js → chunk-UUYAW3JH.js} +2 -2
- package/dist/{chunk-MSMGQDVW.js → chunk-UVUBLLM3.js} +3 -3
- package/dist/{chunk-JZIZBJCW.js → chunk-V4FI2TG6.js} +3 -3
- package/dist/{chunk-MO6N4QYY.js → chunk-VARNSLUW.js} +4 -4
- package/dist/{chunk-WJAGO5LL.js → chunk-VEB7NEON.js} +4 -4
- package/dist/{chunk-GMZNJZRP.js → chunk-VLBFSD7B.js} +2 -2
- package/dist/{chunk-NZFFGO5O.js → chunk-VXWOJPSY.js} +36 -3
- package/dist/chunk-VXWOJPSY.js.map +1 -0
- package/dist/{chunk-JNIVZNIB.js → chunk-WKVL2G7X.js} +4 -4
- package/dist/{chunk-KJXP6RUG.js → chunk-WNEVEMJ3.js} +4 -4
- package/dist/{chunk-HNEOLXRF.js → chunk-WQIYGYY6.js} +2 -2
- package/dist/{chunk-GQJKVQJR.js → chunk-WYLBEJQI.js} +2 -2
- package/dist/{chunk-36DZ242S.js → chunk-XNROYP5E.js} +2 -2
- package/dist/{chunk-XNAOCY67.js → chunk-XVZIBMSY.js} +3 -3
- package/dist/{chunk-PXTLPC3P.js → chunk-YGVZ4QOZ.js} +4 -4
- package/dist/{chunk-JX32ROLZ.js → chunk-YZTFQBYY.js} +4 -4
- package/dist/{chunk-XSXM5LYZ.js → chunk-ZCRDYQL6.js} +2 -2
- package/dist/{chunk-MAAL6OZV.js → chunk-ZG3HZZ6K.js} +90 -36
- package/dist/chunk-ZG3HZZ6K.js.map +1 -0
- package/dist/{chunk-Z3XVYXQ3.js → chunk-ZXTAHSQU.js} +2 -2
- package/dist/cli.js +89 -88
- package/dist/coding/export-okf-codegraph.js +21 -20
- package/dist/coding/export-okf-codegraph.js.map +1 -1
- package/dist/compounding/engine.js +23 -22
- package/dist/config.js +24 -23
- package/dist/connectors/codex-materialize-runner.js +21 -20
- package/dist/connectors/codex-materialize.js +2 -2
- package/dist/connectors/index.js +21 -20
- package/dist/consolidation-provenance-check.js +3 -3
- package/dist/consolidation-undo.js +2 -2
- package/dist/contradiction/index.js +6 -5
- package/dist/convergence-refresh.js +22 -21
- package/dist/corpus-watermark.js +22 -21
- package/dist/deep-recall-http-glue.js +7 -6
- package/dist/entity-canonical-id-migration-GD5MPFUF.js +28 -0
- package/dist/entity-retrieval.js +20 -19
- package/dist/explicit-capture.js +8 -7
- package/dist/external-wiki-access.js +55 -54
- package/dist/extraction.js +27 -26
- package/dist/harmonic-retrieval.js +21 -20
- package/dist/harmonic-source-lookup.js +3 -2
- package/dist/index.js +106 -105
- package/dist/local-llm-rate-limit.d.ts +3 -1
- package/dist/local-llm-rate-limit.d.ts.map +1 -1
- package/dist/local-llm-rate-limit.js +1 -1
- package/dist/local-llm.js +2 -2
- package/dist/location/index.js +23 -22
- package/dist/maintenance/memory-governance.js +20 -19
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +20 -19
- package/dist/maintenance/rebuild-memory-projection-runner.js +22 -21
- package/dist/maintenance/rebuild-memory-projection.js +21 -20
- package/dist/memory-browse-operations.js +55 -54
- package/dist/memory-subject.js +4 -3
- package/dist/namespaces/migrate.js +21 -20
- package/dist/namespaces/search.js +7 -7
- package/dist/namespaces/storage.js +20 -19
- package/dist/offline-sync-file-io.js +3 -2
- package/dist/offline-sync-impression-drain.js +4 -4
- package/dist/offline-sync-snapshot-stream.js +6 -5
- package/dist/offline-sync-upload-staging.js +4 -3
- package/dist/offline-sync.js +5 -4
- package/dist/operator-doctor-corpus.js +23 -22
- package/dist/operator-toolkit.js +34 -33
- package/dist/orchestration/maintenance.js +35 -34
- package/dist/orchestration/orchestrator-init.d.ts +3 -0
- package/dist/orchestration/orchestrator-init.d.ts.map +1 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +106 -105
- package/dist/page-versioning.js +2 -2
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.js +2 -2
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-navigation-operations.js +55 -54
- package/dist/recall-navigation.js +54 -53
- package/dist/recall-state.js +2 -2
- 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/reconcile/manifest.js +4 -3
- package/dist/{resolution-ZU5BIAJA.js → resolution-AMYTPT5X.js} +7 -6
- package/dist/resolution-AMYTPT5X.js.map +1 -0
- package/dist/resume-bundles.js +25 -24
- package/dist/retrieval-agents.js +3 -2
- package/dist/salvage-envelope.js +6 -5
- package/dist/search/document-scanner.js +2 -2
- package/dist/search/factory.js +6 -6
- package/dist/search/index.js +6 -6
- package/dist/search/lancedb-backend.js +3 -3
- package/dist/search/meilisearch-backend.js +3 -3
- package/dist/search/orama-backend.js +3 -3
- package/dist/secure-store/entity-file-read.d.ts +9 -0
- package/dist/secure-store/entity-file-read.d.ts.map +1 -0
- package/dist/secure-store/index.js +3 -2
- package/dist/secure-store/secure-fs.d.ts.map +1 -1
- package/dist/semantic-consolidation.js +22 -21
- package/dist/semantic-rule-promotion.js +20 -19
- package/dist/semantic-rule-verifier.js +20 -19
- package/dist/shared-context/manager.js +2 -2
- package/dist/source-agent-qualifier.js +24 -23
- package/dist/standup/build.js +20 -19
- package/dist/storage/entity-canonical-id-migration-runner.d.ts +12 -0
- package/dist/storage/entity-canonical-id-migration-runner.d.ts.map +1 -1
- package/dist/storage/entity-canonical-id-migration.d.ts +1 -0
- package/dist/storage/entity-canonical-id-migration.d.ts.map +1 -1
- package/dist/storage/entity-canonical-id-references.d.ts +14 -0
- package/dist/storage/entity-canonical-id-references.d.ts.map +1 -1
- package/dist/storage/entity-store.d.ts +4 -0
- package/dist/storage/entity-store.d.ts.map +1 -1
- package/dist/storage.d.ts +7 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +19 -18
- package/dist/subject-config.js +5 -4
- package/dist/summarizer.js +3 -3
- package/dist/support-passport/index.js +57 -56
- package/dist/transfer/capsule-import.js +3 -3
- package/dist/transfer/export-okf.js +21 -20
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +20 -19
- package/dist/who-knows-cli.js +21 -20
- package/dist/who-knows.js +20 -19
- package/dist/write-envelope.js +5 -4
- package/package.json +2 -2
- package/src/local-llm-rate-limit.test.ts +59 -1
- package/src/local-llm-rate-limit.ts +22 -7
- package/src/orchestration/orchestrator-init.ts +26 -3
- package/src/orchestrator.ts +1 -0
- package/src/secure-store/entity-file-read.ts +55 -0
- package/src/secure-store/secure-fs.ts +2 -1
- package/src/storage/entity-canonical-id-migration-runner.ts +36 -0
- package/src/storage/entity-canonical-id-migration.ts +1 -1
- package/src/storage/entity-canonical-id-references.ts +57 -2
- package/src/storage/entity-store.ts +138 -25
- package/src/storage.ts +15 -15
- package/src/types.ts +1 -1
- package/dist/chunk-3VRMUNWL.js.map +0 -1
- package/dist/chunk-42KSEX6C.js.map +0 -1
- package/dist/chunk-H75L4ZOH.js.map +0 -1
- package/dist/chunk-IHS2UGYM.js.map +0 -1
- package/dist/chunk-MAAL6OZV.js.map +0 -1
- package/dist/chunk-NZFFGO5O.js.map +0 -1
- /package/dist/{auto-sync-UQESPLCB.js.map → auto-sync-MX2AHVPQ.js.map} +0 -0
- /package/dist/{capsule-merge-LGYURS3C.js.map → capsule-merge-LGYZAMO4.js.map} +0 -0
- /package/dist/{chunk-G6XEYFCO.js.map → chunk-27OJ5G3D.js.map} +0 -0
- /package/dist/{chunk-5LRV557D.js.map → chunk-2FIJQNL7.js.map} +0 -0
- /package/dist/{chunk-ETPIYK4J.js.map → chunk-2VBDSZ7U.js.map} +0 -0
- /package/dist/{chunk-QNKEMFZY.js.map → chunk-2WDMUQOH.js.map} +0 -0
- /package/dist/{chunk-W6MOLW5S.js.map → chunk-2XVLY424.js.map} +0 -0
- /package/dist/{chunk-P55FACBG.js.map → chunk-3BOQPLCF.js.map} +0 -0
- /package/dist/{chunk-27SAUQ5R.js.map → chunk-3CHHQXAR.js.map} +0 -0
- /package/dist/{chunk-3GYSZHMT.js.map → chunk-3CZRBTJK.js.map} +0 -0
- /package/dist/{chunk-FJJWA7NL.js.map → chunk-3EJQXF3B.js.map} +0 -0
- /package/dist/{chunk-HFSPY26A.js.map → chunk-3IXNL6SK.js.map} +0 -0
- /package/dist/{chunk-PLD6SOU7.js.map → chunk-3SN2D43X.js.map} +0 -0
- /package/dist/{chunk-COGLFRXT.js.map → chunk-4HNINU7Q.js.map} +0 -0
- /package/dist/{chunk-CCDHRDQ3.js.map → chunk-4HYP4OKH.js.map} +0 -0
- /package/dist/{chunk-GKJJNO7C.js.map → chunk-4OE4UE2Y.js.map} +0 -0
- /package/dist/{chunk-7RTNJ6M2.js.map → chunk-4QPW6JVI.js.map} +0 -0
- /package/dist/{chunk-5SMR542T.js.map → chunk-5GT4ESLR.js.map} +0 -0
- /package/dist/{chunk-DWL6YIZH.js.map → chunk-5JI3XWI2.js.map} +0 -0
- /package/dist/{chunk-27LPB4NS.js.map → chunk-5NPZFXQH.js.map} +0 -0
- /package/dist/{chunk-Y6IF6H2U.js.map → chunk-5SMHQW45.js.map} +0 -0
- /package/dist/{chunk-VN3GHPBU.js.map → chunk-654GT5UP.js.map} +0 -0
- /package/dist/{chunk-3E6DGSGZ.js.map → chunk-6MC7UQ6D.js.map} +0 -0
- /package/dist/{chunk-655FVTCD.js.map → chunk-74IN6PV5.js.map} +0 -0
- /package/dist/{chunk-WFUO7NWX.js.map → chunk-7FZ4YVOH.js.map} +0 -0
- /package/dist/{chunk-MWWAQXZ6.js.map → chunk-7HFTCBCZ.js.map} +0 -0
- /package/dist/{chunk-7IOB5F7Y.js.map → chunk-7VB3Y5OL.js.map} +0 -0
- /package/dist/{chunk-YEF5AAWN.js.map → chunk-A54E2ZTD.js.map} +0 -0
- /package/dist/{chunk-DEY7B77Y.js.map → chunk-AHCELJMH.js.map} +0 -0
- /package/dist/{chunk-PIWFNPQT.js.map → chunk-AL3TCNSJ.js.map} +0 -0
- /package/dist/{chunk-EET24NSB.js.map → chunk-AUYFUBBE.js.map} +0 -0
- /package/dist/{chunk-L3IP56F4.js.map → chunk-BIE3ZH3N.js.map} +0 -0
- /package/dist/{chunk-A3IURDU2.js.map → chunk-C2AOL6MK.js.map} +0 -0
- /package/dist/{chunk-BDQMMX3M.js.map → chunk-C2QVDLQV.js.map} +0 -0
- /package/dist/{chunk-AWLQNLTM.js.map → chunk-CSGFGQBI.js.map} +0 -0
- /package/dist/{chunk-JHQAXATW.js.map → chunk-D4RV54HH.js.map} +0 -0
- /package/dist/{chunk-33UAWCBN.js.map → chunk-DDLRKPR2.js.map} +0 -0
- /package/dist/{chunk-3X3PNU3T.js.map → chunk-DLH3ECZP.js.map} +0 -0
- /package/dist/{chunk-SA6GMZJY.js.map → chunk-DP3TSAYT.js.map} +0 -0
- /package/dist/{chunk-H2X22KZW.js.map → chunk-FN6OFDBZ.js.map} +0 -0
- /package/dist/{chunk-SU5V2LWR.js.map → chunk-G6DAE2LT.js.map} +0 -0
- /package/dist/{chunk-V7KGDLBC.js.map → chunk-GQ7VWY6N.js.map} +0 -0
- /package/dist/{chunk-SYUNCM26.js.map → chunk-GSKW64NB.js.map} +0 -0
- /package/dist/{chunk-4WT6I4VG.js.map → chunk-GWB7ZD2A.js.map} +0 -0
- /package/dist/{chunk-JYZLDZ2R.js.map → chunk-HG2VVIKI.js.map} +0 -0
- /package/dist/{chunk-23ZQPP2G.js.map → chunk-HOSJESKO.js.map} +0 -0
- /package/dist/{chunk-EU6IRUCY.js.map → chunk-IDPZCHET.js.map} +0 -0
- /package/dist/{chunk-VMHCC7LO.js.map → chunk-IO2UQVR2.js.map} +0 -0
- /package/dist/{chunk-BWXKJDDH.js.map → chunk-ISMZ5UNE.js.map} +0 -0
- /package/dist/{chunk-SX4QDWXK.js.map → chunk-IWUFKS4J.js.map} +0 -0
- /package/dist/{chunk-I27WOMJ7.js.map → chunk-IY7DGT2Z.js.map} +0 -0
- /package/dist/{chunk-STBX5X6B.js.map → chunk-JAYNUYSJ.js.map} +0 -0
- /package/dist/{chunk-N34ZW6E4.js.map → chunk-K2REHR42.js.map} +0 -0
- /package/dist/{chunk-UJPGQCXD.js.map → chunk-KFKFK6G6.js.map} +0 -0
- /package/dist/{chunk-2HLMFRZ7.js.map → chunk-LDEKVBVO.js.map} +0 -0
- /package/dist/{chunk-MPZYCRC6.js.map → chunk-M236YHUH.js.map} +0 -0
- /package/dist/{chunk-L5VCT7LU.js.map → chunk-MCLZM5G7.js.map} +0 -0
- /package/dist/{chunk-7Z3DLNSD.js.map → chunk-MGKH5KO3.js.map} +0 -0
- /package/dist/{chunk-PUDYANAX.js.map → chunk-MMBLOJJB.js.map} +0 -0
- /package/dist/{chunk-EFHNFTWB.js.map → chunk-MND4YJSX.js.map} +0 -0
- /package/dist/{chunk-HJQXHLQQ.js.map → chunk-MROA6OFU.js.map} +0 -0
- /package/dist/{chunk-BQOGQULP.js.map → chunk-MZZEMPCI.js.map} +0 -0
- /package/dist/{chunk-ERAVI25Z.js.map → chunk-NAPHQ2MG.js.map} +0 -0
- /package/dist/{chunk-L5TJWQEF.js.map → chunk-NB2YX6X2.js.map} +0 -0
- /package/dist/{chunk-IHGLQJW6.js.map → chunk-NCPR2FOJ.js.map} +0 -0
- /package/dist/{chunk-UKWRCQWT.js.map → chunk-NOMHXZD7.js.map} +0 -0
- /package/dist/{chunk-DF2G4IXN.js.map → chunk-NPO4ZQFY.js.map} +0 -0
- /package/dist/{chunk-LWFWZTWX.js.map → chunk-NQV6G6MU.js.map} +0 -0
- /package/dist/{chunk-5HT35H4L.js.map → chunk-NRLWHZVS.js.map} +0 -0
- /package/dist/{chunk-GCZHKBY2.js.map → chunk-OANSZGAG.js.map} +0 -0
- /package/dist/{chunk-BHQPOCQE.js.map → chunk-OIIAIY7J.js.map} +0 -0
- /package/dist/{chunk-FFGHFU7A.js.map → chunk-OXX4ORRL.js.map} +0 -0
- /package/dist/{chunk-RTTPBBAN.js.map → chunk-OXYXMGRH.js.map} +0 -0
- /package/dist/{chunk-K7BN34IA.js.map → chunk-PL26BCRN.js.map} +0 -0
- /package/dist/{chunk-PM72NSEW.js.map → chunk-PYCTZ2HX.js.map} +0 -0
- /package/dist/{chunk-AQ52ZFBC.js.map → chunk-PZEADMX4.js.map} +0 -0
- /package/dist/{chunk-QPH52AZB.js.map → chunk-QNDOTDJK.js.map} +0 -0
- /package/dist/{chunk-LZACDIM2.js.map → chunk-RBGRQEW3.js.map} +0 -0
- /package/dist/{chunk-H3AW6QZF.js.map → chunk-RRJ462HP.js.map} +0 -0
- /package/dist/{chunk-V4JZCTMK.js.map → chunk-TKBW4YLS.js.map} +0 -0
- /package/dist/{chunk-4D2YH47Z.js.map → chunk-TRW7N4FS.js.map} +0 -0
- /package/dist/{chunk-OQJKY3Z5.js.map → chunk-UAAAXSKQ.js.map} +0 -0
- /package/dist/{chunk-S36KJNQH.js.map → chunk-UM73Q46J.js.map} +0 -0
- /package/dist/{chunk-7EJCAFMS.js.map → chunk-UTXYOWDR.js.map} +0 -0
- /package/dist/{chunk-AYHPSYZI.js.map → chunk-UUYAW3JH.js.map} +0 -0
- /package/dist/{chunk-MSMGQDVW.js.map → chunk-UVUBLLM3.js.map} +0 -0
- /package/dist/{chunk-JZIZBJCW.js.map → chunk-V4FI2TG6.js.map} +0 -0
- /package/dist/{chunk-MO6N4QYY.js.map → chunk-VARNSLUW.js.map} +0 -0
- /package/dist/{chunk-WJAGO5LL.js.map → chunk-VEB7NEON.js.map} +0 -0
- /package/dist/{chunk-GMZNJZRP.js.map → chunk-VLBFSD7B.js.map} +0 -0
- /package/dist/{chunk-JNIVZNIB.js.map → chunk-WKVL2G7X.js.map} +0 -0
- /package/dist/{chunk-KJXP6RUG.js.map → chunk-WNEVEMJ3.js.map} +0 -0
- /package/dist/{chunk-HNEOLXRF.js.map → chunk-WQIYGYY6.js.map} +0 -0
- /package/dist/{chunk-GQJKVQJR.js.map → chunk-WYLBEJQI.js.map} +0 -0
- /package/dist/{chunk-36DZ242S.js.map → chunk-XNROYP5E.js.map} +0 -0
- /package/dist/{chunk-XNAOCY67.js.map → chunk-XVZIBMSY.js.map} +0 -0
- /package/dist/{chunk-PXTLPC3P.js.map → chunk-YGVZ4QOZ.js.map} +0 -0
- /package/dist/{chunk-JX32ROLZ.js.map → chunk-YZTFQBYY.js.map} +0 -0
- /package/dist/{chunk-XSXM5LYZ.js.map → chunk-ZCRDYQL6.js.map} +0 -0
- /package/dist/{chunk-Z3XVYXQ3.js.map → chunk-ZXTAHSQU.js.map} +0 -0
- /package/dist/{resolution-ZU5BIAJA.js.map → entity-canonical-id-migration-GD5MPFUF.js.map} +0 -0
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "../utils/macos-replication-junk.js";
|
|
24
24
|
import { getCachedEntities, setCachedEntities } from "../memory-cache.js";
|
|
25
25
|
import type { VersionTrigger } from "../page-versioning.js";
|
|
26
|
-
import { SecureStoreLockedError } from "../secure-store/secure-fs.js";
|
|
26
|
+
import { SecureStoreDecryptError, SecureStoreLockedError } from "../secure-store/secure-fs.js";
|
|
27
27
|
import type {
|
|
28
28
|
EntityActivityEntry,
|
|
29
29
|
EntityFile,
|
|
@@ -67,6 +67,8 @@ export interface EntityStoreDeps {
|
|
|
67
67
|
readonly entitiesDir: string;
|
|
68
68
|
readonly entitySchemas: PluginConfig["entitySchemas"] | undefined;
|
|
69
69
|
currentHistoricalIds(): Readonly<Record<string, string>>;
|
|
70
|
+
/** True when the entity canonical-id journal says migration completed. */
|
|
71
|
+
entityCanonicalMigrationComplete(): boolean;
|
|
70
72
|
findMatchingEntity(proposedName: string, type: string): Promise<string | null>;
|
|
71
73
|
getEntityCacheSecureStoreKey(): string;
|
|
72
74
|
getEntityMutationVersion(): number;
|
|
@@ -373,18 +375,56 @@ export class EntityStore {
|
|
|
373
375
|
return normalized;
|
|
374
376
|
}
|
|
375
377
|
|
|
376
|
-
async
|
|
377
|
-
const filePath = this.deps.resolveEntityFilePath(name);
|
|
378
|
-
if (filePath === null) {
|
|
379
|
-
return "";
|
|
380
|
-
}
|
|
378
|
+
private async readEntityFileResolvingRename(firstPath: string, entityId: string) {
|
|
381
379
|
try {
|
|
382
|
-
return await this.deps.readStorageSecureFile(
|
|
380
|
+
return { id: entityId, content: await this.deps.readStorageSecureFile(firstPath) };
|
|
383
381
|
} catch (err) {
|
|
384
382
|
if (err instanceof SecureStoreLockedError) throw err;
|
|
383
|
+
// ENOENT: renamed away (retry below). ELOOP: planted symlink — skip.
|
|
384
|
+
if (isErrnoCode(err, "ELOOP")) return null;
|
|
385
385
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
386
|
+
}
|
|
387
|
+
const historicalIds = this.deps.currentHistoricalIds();
|
|
388
|
+
const canonical = resolveHistoricalEntityCanonicalId(entityId, historicalIds);
|
|
389
|
+
const candidates = new Set([canonical]);
|
|
390
|
+
for (const legacy of Object.keys(historicalIds)) {
|
|
391
|
+
if (resolveHistoricalEntityCanonicalId(legacy, historicalIds) === canonical) candidates.add(legacy);
|
|
392
|
+
}
|
|
393
|
+
candidates.delete(entityId);
|
|
394
|
+
for (const candidate of candidates) {
|
|
395
|
+
try {
|
|
396
|
+
return { id: candidate, content: await this.deps.readStorageSecureFile(
|
|
397
|
+
path.join(this.deps.entitiesDir, `${candidate}.md`),
|
|
398
|
+
) };
|
|
399
|
+
} catch (err) {
|
|
400
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
401
|
+
// ENOENT/ELOOP: gone or a planted symlink — try the next candidate.
|
|
402
|
+
if (isErrnoCode(err, "ENOENT") || isErrnoCode(err, "ELOOP")) continue;
|
|
403
|
+
throw err;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async readEntity(name: string): Promise<string> {
|
|
410
|
+
const filePath = this.deps.resolveEntityFilePath(name);
|
|
411
|
+
if (filePath === null) {
|
|
386
412
|
return "";
|
|
387
413
|
}
|
|
414
|
+
// Batch reads retry renames unconditionally (a listed file that ENOENTs
|
|
415
|
+
// is definitionally a race), but a DIRECT lookup of a legacy id must stop
|
|
416
|
+
// resolving once the journal says migration completed and its file is gone.
|
|
417
|
+
if (this.deps.entityCanonicalMigrationComplete()) {
|
|
418
|
+
try {
|
|
419
|
+
return await this.deps.readStorageSecureFile(filePath);
|
|
420
|
+
} catch (err) {
|
|
421
|
+
if (err instanceof SecureStoreLockedError) throw err;
|
|
422
|
+
// ENOENT: gone. ELOOP: a planted symlink the open refused to follow.
|
|
423
|
+
if (isErrnoCode(err, "ENOENT") || isErrnoCode(err, "ELOOP")) return "";
|
|
424
|
+
throw err;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return (await this.readEntityFileResolvingRename(filePath, name))?.content ?? "";
|
|
388
428
|
}
|
|
389
429
|
|
|
390
430
|
/**
|
|
@@ -434,6 +474,16 @@ export class EntityStore {
|
|
|
434
474
|
* Symlinks, FIFOs, and devices are skipped before any read. The entities
|
|
435
475
|
* root is refused separately, before the directory is listed.
|
|
436
476
|
*/
|
|
477
|
+
private async isMissingEntry(file: string): Promise<boolean> {
|
|
478
|
+
try {
|
|
479
|
+
await lstat(path.join(this.deps.entitiesDir, file));
|
|
480
|
+
return false;
|
|
481
|
+
} catch (err) {
|
|
482
|
+
if (isErrnoCode(err, "ENOENT")) return true;
|
|
483
|
+
throw err;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
437
487
|
private async isContainedRegularEntityFile(file: string): Promise<boolean> {
|
|
438
488
|
const filePath = path.join(this.deps.entitiesDir, file);
|
|
439
489
|
let entryStat;
|
|
@@ -491,23 +541,54 @@ export class EntityStore {
|
|
|
491
541
|
const names: string[] = [];
|
|
492
542
|
const batchSize = 100;
|
|
493
543
|
for (let i = 0; i < mdFiles.length; i += batchSize) {
|
|
544
|
+
// Journal table snapshot once per call (per-entry reads are quadratic).
|
|
545
|
+
const historicalIds = this.deps.currentHistoricalIds();
|
|
546
|
+
const snapshotIds = new Set(mdFiles.map((file) => file.slice(0, -3)));
|
|
547
|
+
const journalComplete = this.deps.entityCanonicalMigrationComplete();
|
|
548
|
+
const resolveCanonical = (entityId: string): string => {
|
|
549
|
+
const canonical = resolveHistoricalEntityCanonicalId(entityId, historicalIds);
|
|
550
|
+
if (canonical === entityId) return entityId;
|
|
551
|
+
// Completed journal: the on-disk filename is authoritative; a
|
|
552
|
+
// late legacy file stays under its own readable name.
|
|
553
|
+
if (journalComplete) return entityId;
|
|
554
|
+
// Both claimants coexisting (copy-before-unlink) keep both names.
|
|
555
|
+
if (snapshotIds.has(canonical)) return entityId;
|
|
556
|
+
return canonical;
|
|
557
|
+
};
|
|
494
558
|
const resolved = await Promise.all(mdFiles.slice(i, i + batchSize).map(async (file) => {
|
|
559
|
+
const entityId = file.slice(0, -3);
|
|
495
560
|
try {
|
|
496
|
-
|
|
561
|
+
// Report the canonical id for every indexable file so legacy
|
|
562
|
+
// names surface as their canonical identity from the start.
|
|
563
|
+
if (await this.isIndexableEntityMarkdown(file)) {
|
|
564
|
+
return resolveCanonical(entityId);
|
|
565
|
+
}
|
|
497
566
|
} catch (err) {
|
|
498
|
-
|
|
499
|
-
|
|
567
|
+
// Lock and decrypt errors abort the listing; anything else
|
|
568
|
+
// (EACCES) fails only this entry — one unhealthy file must not
|
|
569
|
+
// empty it.
|
|
570
|
+
if (err instanceof SecureStoreLockedError || err instanceof SecureStoreDecryptError) throw err;
|
|
571
|
+
}
|
|
572
|
+
// Vanished listed entry: resolve through the journal (rename
|
|
573
|
+
// race); lstat failures stay within this entry.
|
|
574
|
+
try {
|
|
575
|
+
if (await this.isMissingEntry(file)) {
|
|
576
|
+
const canonical = resolveHistoricalEntityCanonicalId(entityId, this.deps.currentHistoricalIds());
|
|
577
|
+
if (canonical !== entityId) return canonical;
|
|
578
|
+
}
|
|
579
|
+
} catch (err) {
|
|
580
|
+
if (err instanceof SecureStoreLockedError || err instanceof SecureStoreDecryptError) throw err;
|
|
500
581
|
}
|
|
501
|
-
return
|
|
582
|
+
return null;
|
|
502
583
|
}));
|
|
503
|
-
|
|
504
|
-
if (name) names.push(name);
|
|
505
|
-
}
|
|
584
|
+
names.push(...resolved.filter((name): name is string => name !== null));
|
|
506
585
|
}
|
|
507
|
-
|
|
508
|
-
|
|
586
|
+
// The copy-before-unlink migration window can snapshot both the legacy
|
|
587
|
+
// and canonical names; the legacy fallback then resolves to the same
|
|
588
|
+
// canonical id. Deduplicate so the total stays correct.
|
|
589
|
+
return [...new Set(names)].sort();
|
|
509
590
|
} catch (err) {
|
|
510
|
-
if (err instanceof SecureStoreLockedError) throw err;
|
|
591
|
+
if (err instanceof SecureStoreLockedError || err instanceof SecureStoreDecryptError) throw err;
|
|
511
592
|
return [];
|
|
512
593
|
}
|
|
513
594
|
}
|
|
@@ -636,10 +717,22 @@ export class EntityStore {
|
|
|
636
717
|
if (cached) return cached;
|
|
637
718
|
|
|
638
719
|
try {
|
|
639
|
-
|
|
720
|
+
// A symlinked/replaced entities root has no readable entries (merged
|
|
721
|
+
// #3207 semantics): resolve empty rather than following it. Within a
|
|
722
|
+
// trusted root, readdir directly so planted entries reach the secure
|
|
723
|
+
// read instead of being swallowed by the listing guards.
|
|
724
|
+
if (!(await this.isTrustedEntitiesRoot())) return [];
|
|
725
|
+
const listed = await readdir(this.deps.entitiesDir);
|
|
726
|
+
const { kept: entries, ignored } = withoutMacOsReplicationJunk(listed, (name) => name);
|
|
727
|
+
warnIgnoredMacOsReplicationJunk(this.deps.entitiesDir, ignored, (message) => {
|
|
728
|
+
log.warn(`entity load ${message}`);
|
|
729
|
+
});
|
|
640
730
|
const mdFiles = entries.filter((e) => e.endsWith(".md"));
|
|
641
731
|
if (mdFiles.length === 0) return [];
|
|
642
732
|
|
|
733
|
+
const historicalIds = this.deps.currentHistoricalIds();
|
|
734
|
+
const seen = new Map<string, Set<string>>();
|
|
735
|
+
|
|
643
736
|
// Read all entity files in parallel batches to avoid O(N) sequential I/O.
|
|
644
737
|
// With 3000+ entity files, sequential reads can take 15-20s under load.
|
|
645
738
|
// Batching at 100 keeps file-descriptor pressure manageable while staying fast.
|
|
@@ -652,19 +745,39 @@ export class EntityStore {
|
|
|
652
745
|
const batch = mdFiles.slice(i, i + BATCH_SIZE);
|
|
653
746
|
const results = await Promise.all(
|
|
654
747
|
batch.map(async (entry) => {
|
|
748
|
+
const entityId = entry.slice(0, -".md".length);
|
|
749
|
+
const entryPath = path.join(this.deps.entitiesDir, entry);
|
|
655
750
|
try {
|
|
656
|
-
if (!(await this.isContainedRegularEntityFile(entry)))
|
|
657
|
-
|
|
751
|
+
if (!(await this.isContainedRegularEntityFile(entry))) {
|
|
752
|
+
// A listed entry that vanished races a background migration
|
|
753
|
+
// rename: resolve through historical ids like a direct read.
|
|
754
|
+
// Still-present symlinks/dirs stay skipped.
|
|
755
|
+
if (await this.isMissingEntry(entry)) {
|
|
756
|
+
return await this.readEntityFileResolvingRename(entryPath, entityId);
|
|
757
|
+
}
|
|
758
|
+
return null;
|
|
759
|
+
}
|
|
760
|
+
return await this.readEntityFileResolvingRename(entryPath, entityId);
|
|
658
761
|
} catch (err) {
|
|
659
|
-
|
|
660
|
-
|
|
762
|
+
// Lock and decrypt failures abort the corpus read (the store
|
|
763
|
+
// is unusable or tampered); anything else isolates to this entry.
|
|
764
|
+
if (err instanceof SecureStoreLockedError || err instanceof SecureStoreDecryptError) throw err;
|
|
765
|
+
log.warn(`entity read isolated failure for ${entry}: ${err instanceof Error ? err.message : String(err)}`);
|
|
661
766
|
return null;
|
|
662
767
|
}
|
|
663
768
|
}),
|
|
664
769
|
);
|
|
665
|
-
for (const
|
|
666
|
-
if (
|
|
667
|
-
const
|
|
770
|
+
for (const result of results) {
|
|
771
|
+
if (result === null) continue;
|
|
772
|
+
const canonical = resolveHistoricalEntityCanonicalId(result.id, historicalIds);
|
|
773
|
+
let contents = seen.get(canonical);
|
|
774
|
+
if (contents?.has(result.content)) continue;
|
|
775
|
+
if (!contents) {
|
|
776
|
+
contents = new Set();
|
|
777
|
+
seen.set(canonical, contents);
|
|
778
|
+
}
|
|
779
|
+
contents.add(result.content);
|
|
780
|
+
const entity = parseEntityFile(result.content, this.deps.entitySchemas);
|
|
668
781
|
if (!entity.name.trim() || !entity.type.trim()) continue;
|
|
669
782
|
entities.push(entity);
|
|
670
783
|
}
|
package/src/storage.ts
CHANGED
|
@@ -2323,10 +2323,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
2323
2323
|
private _entityStore: EntityStore | undefined;
|
|
2324
2324
|
|
|
2325
2325
|
private get entityStore(): EntityStore {
|
|
2326
|
-
|
|
2327
|
-
this._entityStore = new EntityStore(selfDeps<ConstructorParameters<typeof EntityStore>[0]>(this));
|
|
2328
|
-
}
|
|
2329
|
-
return this._entityStore;
|
|
2326
|
+
return (this._entityStore ??= new EntityStore(selfDeps<ConstructorParameters<typeof EntityStore>[0]>(this)));
|
|
2330
2327
|
}
|
|
2331
2328
|
|
|
2332
2329
|
/** IdentityContinuityStore (storage.ts decomposition). Lazy; selfDeps live wiring. */
|
|
@@ -3537,6 +3534,16 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3537
3534
|
private currentHistoricalIds(): Readonly<Record<string, string>> {
|
|
3538
3535
|
return this.historicalEntityCanonicalIds.get(this.stateDir);
|
|
3539
3536
|
}
|
|
3537
|
+
|
|
3538
|
+
/** Journal completion for EntityStore's legacy-id retry gate (live view). */
|
|
3539
|
+
entityCanonicalMigrationComplete = entityRefs.memoizedJournalCompletion(this.historicalEntityCanonicalIds, () => this.stateDir);
|
|
3540
|
+
|
|
3541
|
+
normalizeEntityName(raw: string, type: string): string {
|
|
3542
|
+
return entityRefs.resolveHistoricalEntityCanonicalId(
|
|
3543
|
+
this.entityStore.normalizeEntityName(raw, type),
|
|
3544
|
+
this.currentHistoricalIds()
|
|
3545
|
+
);
|
|
3546
|
+
}
|
|
3540
3547
|
/** Post-persist repair subsystem (issue #2213) — storage/entity-ref-repair.ts. */
|
|
3541
3548
|
private _entityRefRepair: EntityRefRepair | undefined;
|
|
3542
3549
|
private get entityRefRepair(): EntityRefRepair {
|
|
@@ -3561,12 +3568,6 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3561
3568
|
() => this.runLegacyEntityCanonicalIdMigration(),
|
|
3562
3569
|
() => entityMigration.getFingerprint(this.baseDir, this.entitiesDir, () => String(this.getEntityMutationVersion()))
|
|
3563
3570
|
);
|
|
3564
|
-
normalizeEntityName(raw: string, type: string): string {
|
|
3565
|
-
return entityRefs.resolveHistoricalEntityCanonicalId(
|
|
3566
|
-
this.entityStore.normalizeEntityName(raw, type),
|
|
3567
|
-
this.currentHistoricalIds()
|
|
3568
|
-
);
|
|
3569
|
-
}
|
|
3570
3571
|
|
|
3571
3572
|
/**
|
|
3572
3573
|
* Read-only view of this store's user alias table, for call sites that
|
|
@@ -3623,7 +3624,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3623
3624
|
return completionFingerprint;
|
|
3624
3625
|
}
|
|
3625
3626
|
|
|
3626
|
-
async ensureDirectories(): Promise<void> {
|
|
3627
|
+
async ensureDirectories(options: { waitForEntityMigration?: boolean } = {}): Promise<void> {
|
|
3627
3628
|
await mkdir(this.baseDir, { recursive: true });
|
|
3628
3629
|
await entityMigration.validateRoots(this.baseDir, this.entitiesDir, this.stateDir, this.archiveDir);
|
|
3629
3630
|
const today = new Date().toISOString().slice(0, 10);
|
|
@@ -3640,7 +3641,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3640
3641
|
await mkdir(this.identityAuditsWeeklyDir, { recursive: true });
|
|
3641
3642
|
await mkdir(this.identityAuditsMonthlyDir, { recursive: true });
|
|
3642
3643
|
await mkdir(path.join(this.baseDir, "config"), { recursive: true });
|
|
3643
|
-
await this.entityCanonicalIdMigration.
|
|
3644
|
+
await this.entityCanonicalIdMigration.begin(options.waitForEntityMigration !== false, this.entitiesDir);
|
|
3644
3645
|
// Activate the corpus sentinel at setup (issue #1902, Cursor Medium): an
|
|
3645
3646
|
// existing corpus predating this feature has a size-0/absent sentinel, which
|
|
3646
3647
|
// getCachedMemories treats as a miss — so a read-heavy workload would never
|
|
@@ -3654,9 +3655,9 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
3654
3655
|
if (this.hotMemoriesCacheEnabled && this.getMemoryCorpusVersion() === 0) {
|
|
3655
3656
|
this.bumpMemoryCorpusVersion();
|
|
3656
3657
|
}
|
|
3657
|
-
|
|
3658
|
+
return this.entityCanonicalIdMigration.finishBegin(options.waitForEntityMigration !== false);
|
|
3658
3659
|
}
|
|
3659
|
-
|
|
3660
|
+
drainEntityCanonicalIdMigration = (): Promise<void> => this.entityCanonicalIdMigration.drain();
|
|
3660
3661
|
/**
|
|
3661
3662
|
* Resolve the on-disk write path for a memory of the given category, creating
|
|
3662
3663
|
* the target directory. Category routing goes through the shared
|
|
@@ -4079,7 +4080,6 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4079
4080
|
await this.addActiveFactContentHash(memory);
|
|
4080
4081
|
}
|
|
4081
4082
|
|
|
4082
|
-
|
|
4083
4083
|
private async syncFactHashIndexAfterRewrite(before: MemoryFile, after: MemoryFile): Promise<void> {
|
|
4084
4084
|
if (before.frontmatter.category !== "fact" && after.frontmatter.category !== "fact") return;
|
|
4085
4085
|
|
package/src/types.ts
CHANGED
|
@@ -1654,7 +1654,7 @@ export interface PluginConfig
|
|
|
1654
1654
|
localLlmRateLimitBackoffBaseMs?: number;
|
|
1655
1655
|
/** COS-447: ceiling for rate-limit backoff; longer server hints skip the retry (ms). Default 60000. */
|
|
1656
1656
|
localLlmRateLimitBackoffMaxMs?: number;
|
|
1657
|
-
/**
|
|
1657
|
+
/** Process-wide local LLM HTTP cap; above 1, reserves one permit for recall-critical work. 0 = unlimited. Default 4. */
|
|
1658
1658
|
localLlmMaxConcurrency?: number;
|
|
1659
1659
|
/** Ollama-backend thinking suppression: `reasoning_effort` value injected on
|
|
1660
1660
|
* `/v1/chat/completions` for THINKING_SUPPRESSED_OPERATIONS ("none" | "low" |
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/local-llm-rate-limit.ts"],"sourcesContent":["/**\n * Process-wide rate-limit handling for the local LLM client (COS-447).\n *\n * A LiteLLM proxy in front of the local models answers `429 No deployments\n * available` (and `503`/`408`) when every deployment is busy or in cooldown.\n * Before this module the client returned on the first 429 and the caller\n * loop immediately issued the next request, so one daemon could hammer the\n * proxy with thousands of calls per hour while it was saturated.\n *\n * This module provides three pieces that the client composes:\n *\n * - classification of rate-limit responses and of the retry hint\n * (`Retry-After` header as delta-seconds or HTTP-date, falling back to\n * LiteLLM's `Try again in N seconds` body text);\n * - exponential backoff with full jitter;\n * - process-wide state shared by every `LocalLlmClient` instance: a\n * concurrency semaphore for in-flight HTTP attempts and a per-endpoint\n * \"do not call before\" deadline, so one client's 429 slows every client\n * pointed at the same endpoint.\n *\n * State lives on `globalThis` so duplicated module copies in bundled output\n * still share one limiter.\n */\n\nexport const RATE_LIMIT_STATUSES: ReadonlySet<number> = new Set([408, 429, 503]);\n\nconst RATE_LIMIT_BODY_PATTERN = /no deployments available|cooldown_list|all deployments.*cooldown/i;\nconst TRY_AGAIN_PATTERN = /try again in (\\d+(?:\\.\\d+)?) ?(seconds?|secs?|s|milliseconds?|ms|minutes?|mins?)\\b/i;\n\n/** Upper bound on any server-provided wait we will record (sanity clamp). */\nexport const MAX_RECORDED_BACKOFF_MS = 10 * 60_000;\n\nexport const DEFAULT_RATE_LIMIT_RETRY_COUNT = 3;\nexport const DEFAULT_RATE_LIMIT_BACKOFF_BASE_MS = 1_000;\nexport const DEFAULT_RATE_LIMIT_BACKOFF_MAX_MS = 60_000;\nexport const DEFAULT_MAX_CONCURRENCY = 4;\n\nexport interface LocalLlmRateLimitSettings {\n retryCount: number;\n backoffBaseMs: number;\n backoffMaxMs: number;\n /** 0 disables the process-wide concurrency cap. */\n maxConcurrency: number;\n}\n\nfunction nonNegativeInt(value: number | undefined, fallback: number): number {\n if (value === undefined || !Number.isFinite(value) || value < 0) return fallback;\n return Math.floor(value);\n}\n\nexport function resolveRateLimitSettings(config: {\n localLlmRateLimitRetryCount?: number;\n localLlmRateLimitBackoffBaseMs?: number;\n localLlmRateLimitBackoffMaxMs?: number;\n localLlmMaxConcurrency?: number;\n}): LocalLlmRateLimitSettings {\n const backoffBaseMs = Math.max(\n 1,\n nonNegativeInt(config.localLlmRateLimitBackoffBaseMs, DEFAULT_RATE_LIMIT_BACKOFF_BASE_MS)\n );\n const backoffMaxMs = Math.max(\n backoffBaseMs,\n nonNegativeInt(config.localLlmRateLimitBackoffMaxMs, DEFAULT_RATE_LIMIT_BACKOFF_MAX_MS)\n );\n return {\n retryCount: nonNegativeInt(config.localLlmRateLimitRetryCount, DEFAULT_RATE_LIMIT_RETRY_COUNT),\n backoffBaseMs,\n backoffMaxMs,\n maxConcurrency: nonNegativeInt(config.localLlmMaxConcurrency, DEFAULT_MAX_CONCURRENCY),\n };\n}\n\n/**\n * True for responses that mean \"the endpoint is saturated, slow down\":\n * 408/429/503, or a 5xx whose body carries LiteLLM's cooldown wording.\n * 400s are never rate limits (context-window errors mention fallbacks).\n */\nexport function isRateLimitedResponse(status: number, bodyText: string): boolean {\n if (RATE_LIMIT_STATUSES.has(status)) return true;\n return status >= 500 && RATE_LIMIT_BODY_PATTERN.test(bodyText);\n}\n\n/**\n * Parse an HTTP `Retry-After` value (RFC 9110: delta-seconds or HTTP-date).\n * Returns milliseconds to wait, or null when absent/invalid.\n */\nexport function parseRetryAfterMs(value: string | null | undefined, nowMs: number = Date.now()): number | null {\n if (value === null || value === undefined) return null;\n const trimmed = value.trim();\n if (!trimmed) return null;\n if (/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n return Math.min(MAX_RECORDED_BACKOFF_MS, Math.round(Number(trimmed) * 1000));\n }\n const dateMs = Date.parse(trimmed);\n if (Number.isNaN(dateMs)) return null;\n return Math.min(MAX_RECORDED_BACKOFF_MS, Math.max(0, dateMs - nowMs));\n}\n\n/** Parse LiteLLM's `Try again in N seconds` hint from an error body. */\nexport function parseTryAgainHintMs(bodyText: string): number | null {\n const match = bodyText.match(TRY_AGAIN_PATTERN);\n if (!match) return null;\n const amount = Number(match[1]);\n if (!Number.isFinite(amount)) return null;\n const unit = match[2].toLowerCase();\n let ms: number;\n if (unit.startsWith(\"ms\") || unit.startsWith(\"milli\")) ms = amount;\n else if (unit.startsWith(\"min\")) ms = amount * 60_000;\n else ms = amount * 1000;\n return Math.min(MAX_RECORDED_BACKOFF_MS, Math.round(ms));\n}\n\n/** Server-provided wait: `Retry-After` header first, then the body hint. */\nexport function serverRetryHintMs(\n retryAfterHeader: string | null | undefined,\n bodyText: string,\n nowMs: number = Date.now()\n): number | null {\n return parseRetryAfterMs(retryAfterHeader, nowMs) ?? parseTryAgainHintMs(bodyText);\n}\n\n/**\n * Exponential backoff with full jitter: uniform in [0, min(max, base * 2^(n-1))].\n * `attempt` is 1-based (the number of consecutive rate-limit responses).\n */\nexport function computeFullJitterBackoffMs(\n attempt: number,\n baseMs: number,\n maxMs: number,\n random: () => number = Math.random\n): number {\n const exponent = Math.max(0, Math.min(30, attempt - 1));\n const ceiling = Math.min(maxMs, baseMs * 2 ** exponent);\n return Math.floor(random() * ceiling);\n}\n\n/**\n * Delay before the next attempt after a rate-limit response. A server hint\n * is a floor (never call earlier than asked); jitter is added on top of the\n * exponential term so synchronized callers spread out.\n */\nexport function computeRateLimitDelayMs(\n attempt: number,\n settings: Pick<LocalLlmRateLimitSettings, \"backoffBaseMs\" | \"backoffMaxMs\">,\n serverHintMs: number | null,\n random: () => number = Math.random\n): number {\n const jittered = computeFullJitterBackoffMs(attempt, settings.backoffBaseMs, settings.backoffMaxMs, random);\n return serverHintMs === null ? jittered : Math.max(serverHintMs, jittered);\n}\n\ntype Waiter = { highPriority: boolean; grant: () => void };\n\n/** FIFO counting semaphore with a high-priority lane (recall-critical first). */\nexport class LocalLlmConcurrencyLimiter {\n private active = 0;\n private max: number;\n private readonly waiters: Waiter[] = [];\n\n constructor(max: number) {\n this.max = max;\n }\n\n setMax(max: number): void {\n this.max = max;\n this.pump();\n }\n\n get inFlight(): number {\n return this.active;\n }\n\n get queued(): number {\n return this.waiters.length;\n }\n\n /**\n * Wait for a slot. Resolves to a release function, or null when the\n * signal aborts first. `max <= 0` means unlimited.\n */\n acquire(\n options: { highPriority?: boolean; signal?: AbortSignal; timeoutMs?: number } = {}\n ): Promise<(() => void) | null> {\n const { signal, timeoutMs } = options;\n if (signal?.aborted) return Promise.resolve(null);\n if (this.max <= 0 || (this.active < this.max && this.waiters.length === 0)) {\n this.active += 1;\n return Promise.resolve(this.releaser());\n }\n if (timeoutMs !== undefined && timeoutMs <= 0) return Promise.resolve(null);\n return new Promise((resolve) => {\n let timer: NodeJS.Timeout | undefined;\n const waiter: Waiter = {\n highPriority: options.highPriority === true,\n grant: () => {\n signal?.removeEventListener(\"abort\", onAbort);\n if (timer) clearTimeout(timer);\n resolve(this.releaser());\n },\n };\n const onAbort = (): void => {\n const index = this.waiters.indexOf(waiter);\n if (index >= 0) this.waiters.splice(index, 1);\n signal?.removeEventListener(\"abort\", onAbort);\n if (timer) clearTimeout(timer);\n resolve(null);\n };\n if (waiter.highPriority) {\n const firstLow = this.waiters.findIndex((w) => !w.highPriority);\n if (firstLow < 0) this.waiters.push(waiter);\n else this.waiters.splice(firstLow, 0, waiter);\n } else {\n this.waiters.push(waiter);\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (timeoutMs !== undefined) timer = setTimeout(onAbort, timeoutMs);\n });\n }\n\n private releaser(): () => void {\n let released = false;\n return () => {\n if (released) return;\n released = true;\n this.active -= 1;\n this.pump();\n };\n }\n\n private pump(): void {\n while (this.waiters.length > 0 && (this.max <= 0 || this.active < this.max)) {\n const next = this.waiters.shift();\n if (!next) break;\n this.active += 1;\n next.grant();\n }\n }\n}\n\ninterface EndpointBackoffState {\n untilMs: number;\n consecutiveRateLimits: number;\n}\n\ninterface RateLimitGlobalState {\n limiter: LocalLlmConcurrencyLimiter;\n endpoints: Map<string, EndpointBackoffState>;\n}\n\ndeclare global {\n // Shared across duplicated module copies in bundled output.\n var __remnicLocalLlmRateLimitState: RateLimitGlobalState | undefined;\n}\n\nfunction globalState(): RateLimitGlobalState {\n globalThis.__remnicLocalLlmRateLimitState ??= {\n limiter: new LocalLlmConcurrencyLimiter(DEFAULT_MAX_CONCURRENCY),\n endpoints: new Map(),\n };\n return globalThis.__remnicLocalLlmRateLimitState;\n}\n\n/** Process-wide limiter, resized to the caller's configured cap. */\nexport function getLocalLlmConcurrencyLimiter(maxConcurrency: number): LocalLlmConcurrencyLimiter {\n const { limiter } = globalState();\n limiter.setMax(maxConcurrency);\n return limiter;\n}\n\n/** Milliseconds until `endpoint` may be called again (0 when clear). */\nexport function endpointBackoffRemainingMs(endpoint: string, nowMs: number = Date.now()): number {\n const entry = globalState().endpoints.get(endpoint);\n return entry ? Math.max(0, entry.untilMs - nowMs) : 0;\n}\n\n/**\n * Record a rate-limit response for `endpoint`. Returns the consecutive\n * rate-limit count (1-based) to feed the backoff exponent.\n */\nexport function noteEndpointRateLimited(endpoint: string): number {\n const { endpoints } = globalState();\n const entry = endpoints.get(endpoint) ?? { untilMs: 0, consecutiveRateLimits: 0 };\n entry.consecutiveRateLimits += 1;\n endpoints.set(endpoint, entry);\n return entry.consecutiveRateLimits;\n}\n\n/** Push the endpoint's \"do not call before\" deadline out to at least `nowMs + delayMs`. */\nexport function extendEndpointBackoff(endpoint: string, delayMs: number, nowMs: number = Date.now()): void {\n const { endpoints } = globalState();\n const entry = endpoints.get(endpoint) ?? { untilMs: 0, consecutiveRateLimits: 0 };\n const bounded = Math.min(MAX_RECORDED_BACKOFF_MS, Math.max(0, delayMs));\n entry.untilMs = Math.max(entry.untilMs, nowMs + bounded);\n endpoints.set(endpoint, entry);\n}\n\n/**\n * Reset the backoff exponent after a non-rate-limited response. An already\n * recorded deadline is left to expire so concurrent callers that saw the\n * 429 still wait it out.\n */\nexport function noteEndpointRecovered(endpoint: string): void {\n const entry = globalState().endpoints.get(endpoint);\n if (entry) entry.consecutiveRateLimits = 0;\n}\n\n/** Test seam: drop all process-wide state. */\nexport function resetLocalLlmRateLimitStateForTests(): void {\n const state = globalState();\n state.endpoints.clear();\n state.limiter = new LocalLlmConcurrencyLimiter(DEFAULT_MAX_CONCURRENCY);\n}\n\nexport type RateLimitAttemptGate =\n | { kind: \"go\"; release: () => void }\n | { kind: \"aborted\" }\n | { kind: \"skip\"; reason: \"backoff\" | \"queue\"; remainingMs: number };\n\nexport type RateLimitDecision =\n | { kind: \"not-rate-limited\" }\n | { kind: \"retry\"; delayMs: number; hintMs: number | null; consecutive: number; retry: number }\n | { kind: \"give-up\"; delayMs: number; retries: number };\n\n/**\n * Per-request driver for the rate-limit policy. The client calls\n * `beforeAttempt` ahead of every HTTP attempt (waits out the shared endpoint\n * deadline, then takes a concurrency slot) and `onResponse` after every\n * non-ok response.\n */\nexport class LocalLlmRateLimitSession {\n private retries = 0;\n private readonly limiter: LocalLlmConcurrencyLimiter;\n readonly settings: LocalLlmRateLimitSettings;\n\n /**\n * @param waitBudgetMs the caller's per-attempt time budget. Waiting for the\n * endpoint backoff or a concurrency slot never exceeds it, and a backoff\n * longer than it skips the request instead (fail open to the caller).\n */\n constructor(\n private readonly endpoint: string,\n settings: LocalLlmRateLimitSettings,\n private readonly highPriority: boolean,\n private readonly waitBudgetMs: number = settings.backoffMaxMs\n ) {\n this.settings = settings;\n this.limiter = getLocalLlmConcurrencyLimiter(settings.maxConcurrency);\n }\n\n get retryCount(): number {\n return this.retries;\n }\n\n async beforeAttempt(signal?: AbortSignal): Promise<RateLimitAttemptGate> {\n const deadlineMs = Date.now() + Math.max(0, this.waitBudgetMs);\n // Recheck the shared deadline after every async wait: another attempt may\n // have recorded or extended a cooldown while this one slept or queued.\n for (;;) {\n const remainingMs = endpointBackoffRemainingMs(this.endpoint);\n if (remainingMs > 0) {\n if (remainingMs > Math.min(this.settings.backoffMaxMs, deadlineMs - Date.now())) {\n return { kind: \"skip\", reason: \"backoff\", remainingMs };\n }\n if (!(await waitWithSignal(remainingMs, signal))) return { kind: \"aborted\" };\n continue;\n }\n const release = await this.limiter.acquire({\n highPriority: this.highPriority,\n signal,\n timeoutMs: deadlineMs - Date.now(),\n });\n if (!release) return signal?.aborted ? { kind: \"aborted\" } : { kind: \"skip\", reason: \"queue\", remainingMs: 0 };\n if (endpointBackoffRemainingMs(this.endpoint) > 0) {\n release();\n continue;\n }\n return { kind: \"go\", release };\n }\n }\n\n onSuccess(): void {\n noteEndpointRecovered(this.endpoint);\n }\n\n onResponse(status: number, retryAfterHeader: string | null | undefined, bodyText: string): RateLimitDecision {\n if (!isRateLimitedResponse(status, bodyText)) {\n noteEndpointRecovered(this.endpoint);\n return { kind: \"not-rate-limited\" };\n }\n const consecutive = noteEndpointRateLimited(this.endpoint);\n const hintMs = serverRetryHintMs(retryAfterHeader, bodyText);\n const delayMs = computeRateLimitDelayMs(consecutive, this.settings, hintMs);\n extendEndpointBackoff(this.endpoint, delayMs);\n if (this.retries >= this.settings.retryCount || delayMs > Math.min(this.settings.backoffMaxMs, this.waitBudgetMs)) {\n return { kind: \"give-up\", delayMs, retries: this.retries };\n }\n this.retries += 1;\n return { kind: \"retry\", delayMs, hintMs, consecutive, retry: this.retries };\n }\n}\n\nfunction waitWithSignal(ms: number, signal?: AbortSignal): Promise<boolean> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve(false);\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n resolve(false);\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(true);\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n"],"mappings":"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","names":[]}
|