@remnic/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abstraction-nodes.d.ts +52 -0
- package/dist/abstraction-nodes.js +15 -0
- package/dist/abstraction-nodes.js.map +1 -0
- package/dist/access-cli.d.ts +5 -0
- package/dist/access-cli.js +308 -0
- package/dist/access-cli.js.map +1 -0
- package/dist/access-http.d.ts +158 -0
- package/dist/access-http.js +32 -0
- package/dist/access-http.js.map +1 -0
- package/dist/access-idempotency.d.ts +31 -0
- package/dist/access-idempotency.js +11 -0
- package/dist/access-idempotency.js.map +1 -0
- package/dist/access-mcp.d.ts +76 -0
- package/dist/access-mcp.js +8 -0
- package/dist/access-mcp.js.map +1 -0
- package/dist/access-schema.d.ts +266 -0
- package/dist/access-schema.js +29 -0
- package/dist/access-schema.js.map +1 -0
- package/dist/access-service.d.ts +614 -0
- package/dist/access-service.js +32 -0
- package/dist/access-service.js.map +1 -0
- package/dist/behavior-learner.d.ts +16 -0
- package/dist/behavior-learner.js +124 -0
- package/dist/behavior-learner.js.map +1 -0
- package/dist/behavior-signals.d.ts +15 -0
- package/dist/behavior-signals.js +11 -0
- package/dist/behavior-signals.js.map +1 -0
- package/dist/bootstrap.d.ts +46 -0
- package/dist/bootstrap.js +9 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/boxes.d.ts +93 -0
- package/dist/boxes.js +14 -0
- package/dist/boxes.js.map +1 -0
- package/dist/buffer.d.ts +22 -0
- package/dist/buffer.js +9 -0
- package/dist/buffer.js.map +1 -0
- package/dist/calibration.d.ts +81 -0
- package/dist/calibration.js +239 -0
- package/dist/calibration.js.map +1 -0
- package/dist/causal-behavior.d.ts +79 -0
- package/dist/causal-behavior.js +190 -0
- package/dist/causal-behavior.js.map +1 -0
- package/dist/causal-chain.d.ts +61 -0
- package/dist/causal-chain.js +24 -0
- package/dist/causal-chain.js.map +1 -0
- package/dist/causal-consolidation.d.ts +71 -0
- package/dist/causal-consolidation.js +211 -0
- package/dist/causal-consolidation.js.map +1 -0
- package/dist/causal-retrieval.d.ts +44 -0
- package/dist/causal-retrieval.js +184 -0
- package/dist/causal-retrieval.js.map +1 -0
- package/dist/causal-trajectory-graph.d.ts +13 -0
- package/dist/causal-trajectory-graph.js +59 -0
- package/dist/causal-trajectory-graph.js.map +1 -0
- package/dist/causal-trajectory.d.ts +68 -0
- package/dist/causal-trajectory.js +18 -0
- package/dist/causal-trajectory.js.map +1 -0
- package/dist/chunk-2CJCWDMR.js +87 -0
- package/dist/chunk-2CJCWDMR.js.map +1 -0
- package/dist/chunk-2NMMFZ5T.js +216 -0
- package/dist/chunk-2NMMFZ5T.js.map +1 -0
- package/dist/chunk-2PO5ZRKV.js +103 -0
- package/dist/chunk-2PO5ZRKV.js.map +1 -0
- package/dist/chunk-3QKK7QOS.js +154 -0
- package/dist/chunk-3QKK7QOS.js.map +1 -0
- package/dist/chunk-3SLRNYNG.js +26 -0
- package/dist/chunk-3SLRNYNG.js.map +1 -0
- package/dist/chunk-4A24LIM2.js +68 -0
- package/dist/chunk-4A24LIM2.js.map +1 -0
- package/dist/chunk-6HZ6AO2P.js +164 -0
- package/dist/chunk-6HZ6AO2P.js.map +1 -0
- package/dist/chunk-763GUIOU.js +302 -0
- package/dist/chunk-763GUIOU.js.map +1 -0
- package/dist/chunk-AAI7JARD.js +173 -0
- package/dist/chunk-AAI7JARD.js.map +1 -0
- package/dist/chunk-B7LOFDVE.js +112 -0
- package/dist/chunk-B7LOFDVE.js.map +1 -0
- package/dist/chunk-BDFZXRSO.js +318 -0
- package/dist/chunk-BDFZXRSO.js.map +1 -0
- package/dist/chunk-BOUYNNYD.js +707 -0
- package/dist/chunk-BOUYNNYD.js.map +1 -0
- package/dist/chunk-BRK4ODMI.js +60 -0
- package/dist/chunk-BRK4ODMI.js.map +1 -0
- package/dist/chunk-C6QPK5GG.js +111 -0
- package/dist/chunk-C6QPK5GG.js.map +1 -0
- package/dist/chunk-C7VW7C3F.js +117 -0
- package/dist/chunk-C7VW7C3F.js.map +1 -0
- package/dist/chunk-CDW777AI.js +621 -0
- package/dist/chunk-CDW777AI.js.map +1 -0
- package/dist/chunk-CULXMQJH.js +185 -0
- package/dist/chunk-CULXMQJH.js.map +1 -0
- package/dist/chunk-CXWFUJR2.js +1203 -0
- package/dist/chunk-CXWFUJR2.js.map +1 -0
- package/dist/chunk-DGXUHMOV.js +61 -0
- package/dist/chunk-DGXUHMOV.js.map +1 -0
- package/dist/chunk-DM2T26WE.js +61 -0
- package/dist/chunk-DM2T26WE.js.map +1 -0
- package/dist/chunk-DORBM6OB.js +81 -0
- package/dist/chunk-DORBM6OB.js.map +1 -0
- package/dist/chunk-DT5TVLJE.js +32 -0
- package/dist/chunk-DT5TVLJE.js.map +1 -0
- package/dist/chunk-EEQLFRUM.js +89 -0
- package/dist/chunk-EEQLFRUM.js.map +1 -0
- package/dist/chunk-EQINRHYR.js +672 -0
- package/dist/chunk-EQINRHYR.js.map +1 -0
- package/dist/chunk-ESSMF2FR.js +146 -0
- package/dist/chunk-ESSMF2FR.js.map +1 -0
- package/dist/chunk-ETOW6ACV.js +158 -0
- package/dist/chunk-ETOW6ACV.js.map +1 -0
- package/dist/chunk-FYIYMQ5N.js +221 -0
- package/dist/chunk-FYIYMQ5N.js.map +1 -0
- package/dist/chunk-G3AG3KZN.js +78 -0
- package/dist/chunk-G3AG3KZN.js.map +1 -0
- package/dist/chunk-GJR6D6KC.js +61 -0
- package/dist/chunk-GJR6D6KC.js.map +1 -0
- package/dist/chunk-GPGBSNKM.js +380 -0
- package/dist/chunk-GPGBSNKM.js.map +1 -0
- package/dist/chunk-H63EDPFJ.js +57 -0
- package/dist/chunk-H63EDPFJ.js.map +1 -0
- package/dist/chunk-HG2NKWR2.js +185 -0
- package/dist/chunk-HG2NKWR2.js.map +1 -0
- package/dist/chunk-HL4DB7TO.js +13 -0
- package/dist/chunk-HL4DB7TO.js.map +1 -0
- package/dist/chunk-HLBYLYRD.js +346 -0
- package/dist/chunk-HLBYLYRD.js.map +1 -0
- package/dist/chunk-HLXVTBF3.js +109 -0
- package/dist/chunk-HLXVTBF3.js.map +1 -0
- package/dist/chunk-IFFFR3MR.js +68 -0
- package/dist/chunk-IFFFR3MR.js.map +1 -0
- package/dist/chunk-ISY75RLM.js +1027 -0
- package/dist/chunk-ISY75RLM.js.map +1 -0
- package/dist/chunk-IZME7KW2.js +1886 -0
- package/dist/chunk-IZME7KW2.js.map +1 -0
- package/dist/chunk-J3BT33K7.js +720 -0
- package/dist/chunk-J3BT33K7.js.map +1 -0
- package/dist/chunk-J47FNDR7.js +113 -0
- package/dist/chunk-J47FNDR7.js.map +1 -0
- package/dist/chunk-JWPLJLDU.js +63 -0
- package/dist/chunk-JWPLJLDU.js.map +1 -0
- package/dist/chunk-K6WK37A6.js +865 -0
- package/dist/chunk-K6WK37A6.js.map +1 -0
- package/dist/chunk-KL4CP4SB.js +130 -0
- package/dist/chunk-KL4CP4SB.js.map +1 -0
- package/dist/chunk-KT4NEUNF.js +315 -0
- package/dist/chunk-KT4NEUNF.js.map +1 -0
- package/dist/chunk-KWBU5S5U.js +42 -0
- package/dist/chunk-KWBU5S5U.js.map +1 -0
- package/dist/chunk-L5RPWGFK.js +59 -0
- package/dist/chunk-L5RPWGFK.js.map +1 -0
- package/dist/chunk-L7WO3MZ4.js +128 -0
- package/dist/chunk-L7WO3MZ4.js.map +1 -0
- package/dist/chunk-LIRZNNUP.js +74 -0
- package/dist/chunk-LIRZNNUP.js.map +1 -0
- package/dist/chunk-LK6SGL53.js +22 -0
- package/dist/chunk-LK6SGL53.js.map +1 -0
- package/dist/chunk-LOBRX7VD.js +200 -0
- package/dist/chunk-LOBRX7VD.js.map +1 -0
- package/dist/chunk-LPSF4OQH.js +47 -0
- package/dist/chunk-LPSF4OQH.js.map +1 -0
- package/dist/chunk-LU3GQNDQ.js +152 -0
- package/dist/chunk-LU3GQNDQ.js.map +1 -0
- package/dist/chunk-M5KEYE5E.js +350 -0
- package/dist/chunk-M5KEYE5E.js.map +1 -0
- package/dist/chunk-M62O4P4T.js +41 -0
- package/dist/chunk-M62O4P4T.js.map +1 -0
- package/dist/chunk-MARWOCVP.js +48 -0
- package/dist/chunk-MARWOCVP.js.map +1 -0
- package/dist/chunk-MDDAA2AO.js +925 -0
- package/dist/chunk-MDDAA2AO.js.map +1 -0
- package/dist/chunk-MWGVGUIS.js +198 -0
- package/dist/chunk-MWGVGUIS.js.map +1 -0
- package/dist/chunk-N5AKDXAI.js +74 -0
- package/dist/chunk-N5AKDXAI.js.map +1 -0
- package/dist/chunk-NGAVDO7E.js +115 -0
- package/dist/chunk-NGAVDO7E.js.map +1 -0
- package/dist/chunk-NTTLPF7F.js +283 -0
- package/dist/chunk-NTTLPF7F.js.map +1 -0
- package/dist/chunk-ONRU4L2N.js +240 -0
- package/dist/chunk-ONRU4L2N.js.map +1 -0
- package/dist/chunk-ORZMT74A.js +209 -0
- package/dist/chunk-ORZMT74A.js.map +1 -0
- package/dist/chunk-OTAVQCSF.js +268 -0
- package/dist/chunk-OTAVQCSF.js.map +1 -0
- package/dist/chunk-PGK3VUHN.js +160 -0
- package/dist/chunk-PGK3VUHN.js.map +1 -0
- package/dist/chunk-Q6FETXJA.js +1362 -0
- package/dist/chunk-Q6FETXJA.js.map +1 -0
- package/dist/chunk-QANCTXQF.js +271 -0
- package/dist/chunk-QANCTXQF.js.map +1 -0
- package/dist/chunk-QCCCQT3O.js +189 -0
- package/dist/chunk-QCCCQT3O.js.map +1 -0
- package/dist/chunk-QDOSNLB4.js +1048 -0
- package/dist/chunk-QDOSNLB4.js.map +1 -0
- package/dist/chunk-QFQVZOGA.js +2168 -0
- package/dist/chunk-QFQVZOGA.js.map +1 -0
- package/dist/chunk-QPKFPHOO.js +178 -0
- package/dist/chunk-QPKFPHOO.js.map +1 -0
- package/dist/chunk-QSVPYQPG.js +268 -0
- package/dist/chunk-QSVPYQPG.js.map +1 -0
- package/dist/chunk-QWUUMMIK.js +3045 -0
- package/dist/chunk-QWUUMMIK.js.map +1 -0
- package/dist/chunk-QY2BHY5O.js +2378 -0
- package/dist/chunk-QY2BHY5O.js.map +1 -0
- package/dist/chunk-SCHEKPYH.js +349 -0
- package/dist/chunk-SCHEKPYH.js.map +1 -0
- package/dist/chunk-SCU65EZI.js +15 -0
- package/dist/chunk-SCU65EZI.js.map +1 -0
- package/dist/chunk-T4WRIV2C.js +170 -0
- package/dist/chunk-T4WRIV2C.js.map +1 -0
- package/dist/chunk-TKO4HZCK.js +1852 -0
- package/dist/chunk-TKO4HZCK.js.map +1 -0
- package/dist/chunk-TP4FZJIZ.js +93 -0
- package/dist/chunk-TP4FZJIZ.js.map +1 -0
- package/dist/chunk-TPB3I2AC.js +403 -0
- package/dist/chunk-TPB3I2AC.js.map +1 -0
- package/dist/chunk-TVVVQQAK.js +1431 -0
- package/dist/chunk-TVVVQQAK.js.map +1 -0
- package/dist/chunk-U4PV25RD.js +14 -0
- package/dist/chunk-U4PV25RD.js.map +1 -0
- package/dist/chunk-UCYSTFZR.js +284 -0
- package/dist/chunk-UCYSTFZR.js.map +1 -0
- package/dist/chunk-UHGBNIOS.js +205 -0
- package/dist/chunk-UHGBNIOS.js.map +1 -0
- package/dist/chunk-UIYZ5T3I.js +108 -0
- package/dist/chunk-UIYZ5T3I.js.map +1 -0
- package/dist/chunk-UV2FO7J4.js +747 -0
- package/dist/chunk-UV2FO7J4.js.map +1 -0
- package/dist/chunk-UZB5KHKX.js +63 -0
- package/dist/chunk-UZB5KHKX.js.map +1 -0
- package/dist/chunk-V3RXWQIE.js +626 -0
- package/dist/chunk-V3RXWQIE.js.map +1 -0
- package/dist/chunk-V4YC4LUK.js +444 -0
- package/dist/chunk-V4YC4LUK.js.map +1 -0
- package/dist/chunk-VEWZZM3H.js +133 -0
- package/dist/chunk-VEWZZM3H.js.map +1 -0
- package/dist/chunk-WWIQTB2Y.js +98 -0
- package/dist/chunk-WWIQTB2Y.js.map +1 -0
- package/dist/chunk-X7XN6YU4.js +24 -0
- package/dist/chunk-X7XN6YU4.js.map +1 -0
- package/dist/chunk-XKECPATV.js +202 -0
- package/dist/chunk-XKECPATV.js.map +1 -0
- package/dist/chunk-XYIK4LF6.js +75 -0
- package/dist/chunk-XYIK4LF6.js.map +1 -0
- package/dist/chunk-Y27UJK6V.js +39 -0
- package/dist/chunk-Y27UJK6V.js.map +1 -0
- package/dist/chunk-Y4Z4I6WK.js +9 -0
- package/dist/chunk-Y4Z4I6WK.js.map +1 -0
- package/dist/chunk-YAPUAHAY.js +10761 -0
- package/dist/chunk-YAPUAHAY.js.map +1 -0
- package/dist/chunk-YAZNBMNF.js +92 -0
- package/dist/chunk-YAZNBMNF.js.map +1 -0
- package/dist/chunk-YCN4BVDK.js +66 -0
- package/dist/chunk-YCN4BVDK.js.map +1 -0
- package/dist/chunk-YNCQ7E4M.js +388 -0
- package/dist/chunk-YNCQ7E4M.js.map +1 -0
- package/dist/chunk-YNI4S5WT.js +143 -0
- package/dist/chunk-YNI4S5WT.js.map +1 -0
- package/dist/chunk-YRMVARQP.js +406 -0
- package/dist/chunk-YRMVARQP.js.map +1 -0
- package/dist/chunk-Z5AAYHUC.js +79 -0
- package/dist/chunk-Z5AAYHUC.js.map +1 -0
- package/dist/chunk-Z5LAYHGJ.js +15 -0
- package/dist/chunk-Z5LAYHGJ.js.map +1 -0
- package/dist/chunk-ZJLY4QSU.js +823 -0
- package/dist/chunk-ZJLY4QSU.js.map +1 -0
- package/dist/chunk-ZKYI7UVO.js +276 -0
- package/dist/chunk-ZKYI7UVO.js.map +1 -0
- package/dist/chunk-ZPKBYX2F.js +297 -0
- package/dist/chunk-ZPKBYX2F.js.map +1 -0
- package/dist/chunking.d.ts +48 -0
- package/dist/chunking.js +11 -0
- package/dist/chunking.js.map +1 -0
- package/dist/cli.d.ts +1162 -0
- package/dist/cli.js +7187 -0
- package/dist/cli.js.map +1 -0
- package/dist/commitment-ledger.d.ts +83 -0
- package/dist/commitment-ledger.js +19 -0
- package/dist/commitment-ledger.js.map +1 -0
- package/dist/compression-optimizer.d.ts +37 -0
- package/dist/compression-optimizer.js +13 -0
- package/dist/compression-optimizer.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -0
- package/dist/cue-anchors.d.ts +50 -0
- package/dist/cue-anchors.js +15 -0
- package/dist/cue-anchors.js.map +1 -0
- package/dist/dashboard-runtime.d.ts +46 -0
- package/dist/dashboard-runtime.js +10 -0
- package/dist/dashboard-runtime.js.map +1 -0
- package/dist/day-summary.d.ts +6 -0
- package/dist/day-summary.js +10 -0
- package/dist/day-summary.js.map +1 -0
- package/dist/delinearize.d.ts +34 -0
- package/dist/delinearize.js +11 -0
- package/dist/delinearize.js.map +1 -0
- package/dist/embedding-fallback.d.ts +22 -0
- package/dist/embedding-fallback.js +8 -0
- package/dist/embedding-fallback.js.map +1 -0
- package/dist/engine-P26JFSVY.js +19 -0
- package/dist/engine-P26JFSVY.js.map +1 -0
- package/dist/entity-retrieval.d.ts +23 -0
- package/dist/entity-retrieval.js +24 -0
- package/dist/entity-retrieval.js.map +1 -0
- package/dist/evals.d.ts +282 -0
- package/dist/evals.js +32 -0
- package/dist/evals.js.map +1 -0
- package/dist/explicit-capture.d.ts +60 -0
- package/dist/explicit-capture.js +23 -0
- package/dist/explicit-capture.js.map +1 -0
- package/dist/extraction.d.ts +141 -0
- package/dist/extraction.js +22 -0
- package/dist/extraction.js.map +1 -0
- package/dist/fallback-llm.d.ts +95 -0
- package/dist/fallback-llm.js +12 -0
- package/dist/fallback-llm.js.map +1 -0
- package/dist/graph-dashboard-diff.d.ts +12 -0
- package/dist/graph-dashboard-diff.js +8 -0
- package/dist/graph-dashboard-diff.js.map +1 -0
- package/dist/graph-dashboard-key.d.ts +5 -0
- package/dist/graph-dashboard-key.js +7 -0
- package/dist/graph-dashboard-key.js.map +1 -0
- package/dist/graph-dashboard-parser.d.ts +20 -0
- package/dist/graph-dashboard-parser.js +8 -0
- package/dist/graph-dashboard-parser.js.map +1 -0
- package/dist/graph.d.ts +157 -0
- package/dist/graph.js +27 -0
- package/dist/graph.js.map +1 -0
- package/dist/harmonic-retrieval.d.ts +27 -0
- package/dist/harmonic-retrieval.js +12 -0
- package/dist/harmonic-retrieval.js.map +1 -0
- package/dist/himem.d.ts +23 -0
- package/dist/himem.js +7 -0
- package/dist/himem.js.map +1 -0
- package/dist/hygiene.d.ts +24 -0
- package/dist/hygiene.js +9 -0
- package/dist/hygiene.js.map +1 -0
- package/dist/identity-continuity.d.ts +17 -0
- package/dist/identity-continuity.js +19 -0
- package/dist/identity-continuity.js.map +1 -0
- package/dist/importance.d.ts +25 -0
- package/dist/importance.js +11 -0
- package/dist/importance.js.map +1 -0
- package/dist/index.d.ts +923 -0
- package/dist/index.js +2512 -0
- package/dist/index.js.map +1 -0
- package/dist/intent.d.ts +8 -0
- package/dist/intent.js +13 -0
- package/dist/intent.js.map +1 -0
- package/dist/json-extract.d.ts +14 -0
- package/dist/json-extract.js +9 -0
- package/dist/json-extract.js.map +1 -0
- package/dist/json-store.d.ts +5 -0
- package/dist/json-store.js +11 -0
- package/dist/json-store.js.map +1 -0
- package/dist/legacy-hook-compat.d.ts +3 -0
- package/dist/legacy-hook-compat.js +35 -0
- package/dist/legacy-hook-compat.js.map +1 -0
- package/dist/lifecycle.d.ts +52 -0
- package/dist/lifecycle.js +21 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/local-llm.d.ts +154 -0
- package/dist/local-llm.js +10 -0
- package/dist/local-llm.js.map +1 -0
- package/dist/logger.d.ts +15 -0
- package/dist/logger.js +9 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory-action-policy.d.ts +13 -0
- package/dist/memory-action-policy.js +7 -0
- package/dist/memory-action-policy.js.map +1 -0
- package/dist/memory-cache.d.ts +35 -0
- package/dist/memory-cache.js +37 -0
- package/dist/memory-cache.js.map +1 -0
- package/dist/memory-lifecycle-ledger-utils.d.ts +13 -0
- package/dist/memory-lifecycle-ledger-utils.js +23 -0
- package/dist/memory-lifecycle-ledger-utils.js.map +1 -0
- package/dist/memory-projection-format.d.ts +4 -0
- package/dist/memory-projection-format.js +9 -0
- package/dist/memory-projection-format.js.map +1 -0
- package/dist/memory-projection-store-NxMkbocT.d.ts +221 -0
- package/dist/memory-projection-store.d.ts +3 -0
- package/dist/memory-projection-store.js +31 -0
- package/dist/memory-projection-store.js.map +1 -0
- package/dist/model-registry.d.ts +60 -0
- package/dist/model-registry.js +8 -0
- package/dist/model-registry.js.map +1 -0
- package/dist/native-knowledge.d.ts +94 -0
- package/dist/native-knowledge.js +26 -0
- package/dist/native-knowledge.js.map +1 -0
- package/dist/negative.d.ts +26 -0
- package/dist/negative.js +8 -0
- package/dist/negative.js.map +1 -0
- package/dist/objective-state-writers.d.ts +22 -0
- package/dist/objective-state-writers.js +313 -0
- package/dist/objective-state-writers.js.map +1 -0
- package/dist/objective-state.d.ts +75 -0
- package/dist/objective-state.js +17 -0
- package/dist/objective-state.js.map +1 -0
- package/dist/openai-chat-compat.d.ts +13 -0
- package/dist/openai-chat-compat.js +11 -0
- package/dist/openai-chat-compat.js.map +1 -0
- package/dist/operator-toolkit.d.ts +304 -0
- package/dist/operator-toolkit.js +41 -0
- package/dist/operator-toolkit.js.map +1 -0
- package/dist/opik-exporter.d.ts +72 -0
- package/dist/opik-exporter.js +361 -0
- package/dist/opik-exporter.js.map +1 -0
- package/dist/orchestrator-zTa-Qo-1.d.ts +1104 -0
- package/dist/orchestrator.d.ts +21 -0
- package/dist/orchestrator.js +145 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/policy-runtime.d.ts +37 -0
- package/dist/policy-runtime.js +13 -0
- package/dist/policy-runtime.js.map +1 -0
- package/dist/port-C1GZFv8h.d.ts +41 -0
- package/dist/profiling.d.ts +80 -0
- package/dist/profiling.js +10 -0
- package/dist/profiling.js.map +1 -0
- package/dist/qmd-recall-cache.d.ts +29 -0
- package/dist/qmd-recall-cache.js +13 -0
- package/dist/qmd-recall-cache.js.map +1 -0
- package/dist/qmd.d.ts +105 -0
- package/dist/qmd.js +13 -0
- package/dist/qmd.js.map +1 -0
- package/dist/recall-qos.d.ts +33 -0
- package/dist/recall-qos.js +10 -0
- package/dist/recall-qos.js.map +1 -0
- package/dist/recall-query-policy.d.ts +20 -0
- package/dist/recall-query-policy.js +11 -0
- package/dist/recall-query-policy.js.map +1 -0
- package/dist/recall-state.d.ts +113 -0
- package/dist/recall-state.js +12 -0
- package/dist/recall-state.js.map +1 -0
- package/dist/recall-tokenization.d.ts +4 -0
- package/dist/recall-tokenization.js +9 -0
- package/dist/recall-tokenization.js.map +1 -0
- package/dist/reconstruct.d.ts +16 -0
- package/dist/reconstruct.js +7 -0
- package/dist/reconstruct.js.map +1 -0
- package/dist/release-changelog.d.ts +7 -0
- package/dist/release-changelog.js +30 -0
- package/dist/release-changelog.js.map +1 -0
- package/dist/relevance.d.ts +18 -0
- package/dist/relevance.js +8 -0
- package/dist/relevance.js.map +1 -0
- package/dist/rerank.d.ts +57 -0
- package/dist/rerank.js +11 -0
- package/dist/rerank.js.map +1 -0
- package/dist/resolve-provider-secret.d.ts +16 -0
- package/dist/resolve-provider-secret.js +11 -0
- package/dist/resolve-provider-secret.js.map +1 -0
- package/dist/resume-bundles.d.ts +66 -0
- package/dist/resume-bundles.js +27 -0
- package/dist/resume-bundles.js.map +1 -0
- package/dist/retrieval-agents.d.ts +129 -0
- package/dist/retrieval-agents.js +23 -0
- package/dist/retrieval-agents.js.map +1 -0
- package/dist/retrieval.d.ts +19 -0
- package/dist/retrieval.js +10 -0
- package/dist/retrieval.js.map +1 -0
- package/dist/sanitize.d.ts +9 -0
- package/dist/sanitize.js +9 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/schemas.d.ts +688 -0
- package/dist/schemas.js +51 -0
- package/dist/schemas.js.map +1 -0
- package/dist/sdk-compat.d.ts +21 -0
- package/dist/sdk-compat.js +28 -0
- package/dist/sdk-compat.js.map +1 -0
- package/dist/semantic-consolidation.d.ts +42 -0
- package/dist/semantic-consolidation.js +12 -0
- package/dist/semantic-consolidation.js.map +1 -0
- package/dist/semantic-rule-promotion.d.ts +28 -0
- package/dist/semantic-rule-promotion.js +17 -0
- package/dist/semantic-rule-promotion.js.map +1 -0
- package/dist/semantic-rule-verifier.d.ts +19 -0
- package/dist/semantic-rule-verifier.js +18 -0
- package/dist/semantic-rule-verifier.js.map +1 -0
- package/dist/session-integrity.d.ts +67 -0
- package/dist/session-integrity.js +11 -0
- package/dist/session-integrity.js.map +1 -0
- package/dist/session-observer-bands.d.ts +6 -0
- package/dist/session-observer-bands.js +9 -0
- package/dist/session-observer-bands.js.map +1 -0
- package/dist/session-observer-state.d.ts +40 -0
- package/dist/session-observer-state.js +11 -0
- package/dist/session-observer-state.js.map +1 -0
- package/dist/signal.d.ts +6 -0
- package/dist/signal.js +9 -0
- package/dist/signal.js.map +1 -0
- package/dist/storage.d.ts +453 -0
- package/dist/storage.js +24 -0
- package/dist/storage.js.map +1 -0
- package/dist/store-contract.d.ts +10 -0
- package/dist/store-contract.js +21 -0
- package/dist/store-contract.js.map +1 -0
- package/dist/summarizer.d.ts +35 -0
- package/dist/summarizer.js +17 -0
- package/dist/summarizer.js.map +1 -0
- package/dist/summary-snapshot.d.ts +8 -0
- package/dist/summary-snapshot.js +13 -0
- package/dist/summary-snapshot.js.map +1 -0
- package/dist/temporal-index.d.ts +139 -0
- package/dist/temporal-index.js +29 -0
- package/dist/temporal-index.js.map +1 -0
- package/dist/threading.d.ts +62 -0
- package/dist/threading.js +8 -0
- package/dist/threading.js.map +1 -0
- package/dist/tier-migration.d.ts +44 -0
- package/dist/tier-migration.js +7 -0
- package/dist/tier-migration.js.map +1 -0
- package/dist/tier-routing.d.ts +21 -0
- package/dist/tier-routing.js +10 -0
- package/dist/tier-routing.js.map +1 -0
- package/dist/tmt.d.ts +79 -0
- package/dist/tmt.js +29 -0
- package/dist/tmt.js.map +1 -0
- package/dist/tokens.d.ts +24 -0
- package/dist/tokens.js +21 -0
- package/dist/tokens.js.map +1 -0
- package/dist/topics.d.ts +29 -0
- package/dist/topics.js +9 -0
- package/dist/topics.js.map +1 -0
- package/dist/transcript.d.ts +171 -0
- package/dist/transcript.js +9 -0
- package/dist/transcript.js.map +1 -0
- package/dist/trust-zones.d.ts +170 -0
- package/dist/trust-zones.js +32 -0
- package/dist/trust-zones.js.map +1 -0
- package/dist/types.d.ts +1243 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/utility-learner.d.ts +59 -0
- package/dist/utility-learner.js +17 -0
- package/dist/utility-learner.js.map +1 -0
- package/dist/utility-runtime.d.ts +21 -0
- package/dist/utility-runtime.js +16 -0
- package/dist/utility-runtime.js.map +1 -0
- package/dist/utility-telemetry.d.ts +68 -0
- package/dist/utility-telemetry.js +17 -0
- package/dist/utility-telemetry.js.map +1 -0
- package/dist/verified-recall.d.ts +17 -0
- package/dist/verified-recall.js +19 -0
- package/dist/verified-recall.js.map +1 -0
- package/dist/version-utils.d.ts +4 -0
- package/dist/version-utils.js +7 -0
- package/dist/version-utils.js.map +1 -0
- package/dist/work-product-ledger.d.ts +65 -0
- package/dist/work-product-ledger.js +18 -0
- package/dist/work-product-ledger.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,1362 @@
|
|
|
1
|
+
import {
|
|
2
|
+
log
|
|
3
|
+
} from "./chunk-KWBU5S5U.js";
|
|
4
|
+
|
|
5
|
+
// src/native-knowledge.ts
|
|
6
|
+
import { createHash } from "crypto";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import { mkdir, readFile, readdir, stat, writeFile } from "fs/promises";
|
|
9
|
+
var PERSISTED_NATIVE_KNOWLEDGE_STATE_FILES = /* @__PURE__ */ new Set([
|
|
10
|
+
"obsidian-sync.json",
|
|
11
|
+
"curated-include-sync.json",
|
|
12
|
+
"openclaw-workspace-sync.json"
|
|
13
|
+
]);
|
|
14
|
+
function normalizeText(value) {
|
|
15
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
16
|
+
}
|
|
17
|
+
function tokenize(value) {
|
|
18
|
+
return normalizeText(value).split(/\s+/).filter((token) => token.length >= 2);
|
|
19
|
+
}
|
|
20
|
+
function uniqueSorted(values) {
|
|
21
|
+
return [...new Set(values.filter((value) => value.trim().length > 0).map((value) => value.trim()))].sort();
|
|
22
|
+
}
|
|
23
|
+
function detectSourceKind(filePath) {
|
|
24
|
+
const base = path.basename(filePath).toLowerCase();
|
|
25
|
+
if (base.startsWith("identity")) return "identity";
|
|
26
|
+
if (base === "memory.md") return "memory";
|
|
27
|
+
return "workspace_doc";
|
|
28
|
+
}
|
|
29
|
+
function parseInlineArray(raw) {
|
|
30
|
+
const trimmed = raw.trim();
|
|
31
|
+
if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) return [];
|
|
32
|
+
return trimmed.slice(1, -1).split(",").map((value) => value.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean);
|
|
33
|
+
}
|
|
34
|
+
function parseFrontmatter(content) {
|
|
35
|
+
const normalized = content.replace(/\r\n/g, "\n");
|
|
36
|
+
if (!normalized.startsWith("---\n")) return { body: normalized, bodyStartLine: 1, data: {} };
|
|
37
|
+
const closing = normalized.indexOf("\n---\n", 4);
|
|
38
|
+
if (closing === -1) return { body: normalized, bodyStartLine: 1, data: {} };
|
|
39
|
+
const data = {};
|
|
40
|
+
const lines = normalized.slice(4, closing).split("\n");
|
|
41
|
+
let index = 0;
|
|
42
|
+
while (index < lines.length) {
|
|
43
|
+
const line = lines[index] ?? "";
|
|
44
|
+
const match = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line);
|
|
45
|
+
if (!match) {
|
|
46
|
+
index += 1;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const [, key, rawValue] = match;
|
|
50
|
+
if (rawValue.trim().length > 0) {
|
|
51
|
+
const inlineArray = parseInlineArray(rawValue);
|
|
52
|
+
data[key] = inlineArray.length > 0 ? inlineArray : rawValue.trim().replace(/^['"]|['"]$/g, "");
|
|
53
|
+
index += 1;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const items = [];
|
|
57
|
+
let cursor = index + 1;
|
|
58
|
+
while (cursor < lines.length) {
|
|
59
|
+
const next = lines[cursor] ?? "";
|
|
60
|
+
const itemMatch = /^\s*-\s*(.+)$/.exec(next);
|
|
61
|
+
if (!itemMatch) break;
|
|
62
|
+
items.push(itemMatch[1].trim().replace(/^['"]|['"]$/g, ""));
|
|
63
|
+
cursor += 1;
|
|
64
|
+
}
|
|
65
|
+
data[key] = items;
|
|
66
|
+
index = cursor;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
body: normalized.slice(closing + 5),
|
|
70
|
+
bodyStartLine: normalized.slice(0, closing + 5).split("\n").length,
|
|
71
|
+
data
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function firstStringValue(data, keys) {
|
|
75
|
+
for (const key of keys) {
|
|
76
|
+
const value = data[key];
|
|
77
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
78
|
+
}
|
|
79
|
+
return void 0;
|
|
80
|
+
}
|
|
81
|
+
function normalizeIsoDate(value) {
|
|
82
|
+
if (!value) return void 0;
|
|
83
|
+
const trimmed = value.trim();
|
|
84
|
+
const isoDateMatch = /^(\d{4}-\d{2}-\d{2})/.exec(trimmed);
|
|
85
|
+
if (isoDateMatch) return isoDateMatch[1];
|
|
86
|
+
const slashDateMatch = /^(\d{4})[\/_](\d{2})[\/_](\d{2})$/.exec(trimmed);
|
|
87
|
+
if (slashDateMatch) return `${slashDateMatch[1]}-${slashDateMatch[2]}-${slashDateMatch[3]}`;
|
|
88
|
+
return void 0;
|
|
89
|
+
}
|
|
90
|
+
function deriveDateFromPath(filePath) {
|
|
91
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
92
|
+
const hyphenated = /(\d{4}-\d{2}-\d{2})/.exec(normalized);
|
|
93
|
+
if (hyphenated) return hyphenated[1];
|
|
94
|
+
const split = /(^|\/)(\d{4})\/(\d{2})\/(\d{2})(?=\/|[^/\n]*\.md$)/.exec(normalized);
|
|
95
|
+
if (split) return `${split[2]}-${split[3]}-${split[4]}`;
|
|
96
|
+
return void 0;
|
|
97
|
+
}
|
|
98
|
+
function deriveArtifactDate(filePath, parsed) {
|
|
99
|
+
return normalizeIsoDate(firstStringValue(parsed.data, ["date", "recordedAt", "generatedAt", "summaryDate", "day"])) ?? deriveDateFromPath(filePath);
|
|
100
|
+
}
|
|
101
|
+
function deriveNamespaceFromIncludePath(sourcePath) {
|
|
102
|
+
const basename = path.basename(sourcePath);
|
|
103
|
+
const match = /^identity\.([^.\/]+)\.md$/i.exec(basename);
|
|
104
|
+
return match?.[1];
|
|
105
|
+
}
|
|
106
|
+
function compileDailyNotePattern(pattern) {
|
|
107
|
+
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
108
|
+
const regex = escaped.replace(/YYYY/g, "(?<year>\\d{4})").replace(/MM/g, "(?<month>\\d{2})").replace(/DD/g, "(?<day>\\d{2})");
|
|
109
|
+
return new RegExp(`^${regex}$`);
|
|
110
|
+
}
|
|
111
|
+
function deriveDailyNoteDate(notePath, patterns) {
|
|
112
|
+
const withoutExt = notePath.replace(/\.md$/i, "");
|
|
113
|
+
for (const pattern of patterns) {
|
|
114
|
+
const match = compileDailyNotePattern(pattern).exec(withoutExt);
|
|
115
|
+
if (!match?.groups) continue;
|
|
116
|
+
const { year, month, day } = match.groups;
|
|
117
|
+
if (!year || !month || !day) continue;
|
|
118
|
+
return `${year}-${month}-${day}`;
|
|
119
|
+
}
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
function extractInlineTags(content) {
|
|
123
|
+
const matches = [...content.matchAll(/(^|\s)#([a-z0-9/_-]+)/gi)];
|
|
124
|
+
return uniqueSorted(matches.map((match) => match[2] ?? ""));
|
|
125
|
+
}
|
|
126
|
+
function extractWikilinks(content) {
|
|
127
|
+
const targets = [];
|
|
128
|
+
const aliases = [];
|
|
129
|
+
const regex = /\[\[([^\]|#]+)(?:#[^\]|]+)?(?:\|([^\]]+))?\]\]/g;
|
|
130
|
+
for (const match of content.matchAll(regex)) {
|
|
131
|
+
const target = (match[1] ?? "").trim();
|
|
132
|
+
const alias = (match[2] ?? "").trim();
|
|
133
|
+
if (target) targets.push(target);
|
|
134
|
+
if (alias) aliases.push(alias);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
targets: uniqueSorted(targets),
|
|
138
|
+
aliases: uniqueSorted(aliases)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function normalizePathPrefix(prefix) {
|
|
142
|
+
const fwd = prefix.replace(/\\/g, "/");
|
|
143
|
+
let start = 0;
|
|
144
|
+
while (start < fwd.length && fwd[start] === "/") start++;
|
|
145
|
+
let end = fwd.length;
|
|
146
|
+
while (end > start && fwd[end - 1] === "/") end--;
|
|
147
|
+
return fwd.substring(start, end);
|
|
148
|
+
}
|
|
149
|
+
function classifyObsidianNote(notePath, vault) {
|
|
150
|
+
let namespace = vault.namespace;
|
|
151
|
+
let privacyClass = vault.privacyClass;
|
|
152
|
+
const normalizedPath = notePath.replace(/\\/g, "/");
|
|
153
|
+
const rules = [...vault.folderRules].sort(
|
|
154
|
+
(a, b) => normalizePathPrefix(b.pathPrefix).length - normalizePathPrefix(a.pathPrefix).length
|
|
155
|
+
);
|
|
156
|
+
for (const rule of rules) {
|
|
157
|
+
const prefix = normalizePathPrefix(rule.pathPrefix);
|
|
158
|
+
if (!prefix) continue;
|
|
159
|
+
if (normalizedPath === prefix || normalizedPath.startsWith(`${prefix}/`)) {
|
|
160
|
+
namespace = rule.namespace ?? namespace;
|
|
161
|
+
privacyClass = rule.privacyClass ?? privacyClass;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return { namespace, privacyClass };
|
|
166
|
+
}
|
|
167
|
+
function chunkHeadingAware(options) {
|
|
168
|
+
const lines = options.content.replace(/\r\n/g, "\n").split("\n");
|
|
169
|
+
const chunks = [];
|
|
170
|
+
let currentTitle = path.basename(options.sourcePath);
|
|
171
|
+
let currentLines = [];
|
|
172
|
+
let startLine = 1 + (options.startLineOffset ?? 0);
|
|
173
|
+
const flush = () => {
|
|
174
|
+
const paragraphs = [];
|
|
175
|
+
let paragraphLines = [];
|
|
176
|
+
let paragraphStartOffset = null;
|
|
177
|
+
const pushParagraph = (lineOffsetExclusive) => {
|
|
178
|
+
if (paragraphLines.length === 0 || paragraphStartOffset === null) return;
|
|
179
|
+
paragraphs.push({
|
|
180
|
+
content: paragraphLines.join("\n").trim(),
|
|
181
|
+
startLine: startLine + paragraphStartOffset,
|
|
182
|
+
endLine: startLine + lineOffsetExclusive - 1
|
|
183
|
+
});
|
|
184
|
+
paragraphLines = [];
|
|
185
|
+
paragraphStartOffset = null;
|
|
186
|
+
};
|
|
187
|
+
for (let index = 0; index < currentLines.length; index += 1) {
|
|
188
|
+
const line = currentLines[index] ?? "";
|
|
189
|
+
const isListLine = /^\s*(?:[-*+]|\d+\.)\s+/.test(line);
|
|
190
|
+
const previousLine = index > 0 ? currentLines[index - 1] ?? "" : "";
|
|
191
|
+
const previousWasList = /^\s*(?:[-*+]|\d+\.)\s+/.test(previousLine);
|
|
192
|
+
if (line.trim().length === 0) {
|
|
193
|
+
pushParagraph(index);
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (isListLine && paragraphLines.length > 0 && !previousWasList) {
|
|
197
|
+
pushParagraph(index);
|
|
198
|
+
}
|
|
199
|
+
if (paragraphStartOffset === null) paragraphStartOffset = index;
|
|
200
|
+
paragraphLines.push(line);
|
|
201
|
+
}
|
|
202
|
+
pushParagraph(currentLines.length);
|
|
203
|
+
if (paragraphs.length === 0) return;
|
|
204
|
+
const body = paragraphs.map((paragraph) => paragraph.content).join("\n\n");
|
|
205
|
+
if (body.length <= options.maxChunkChars) {
|
|
206
|
+
chunks.push(options.createChunk({
|
|
207
|
+
title: currentTitle,
|
|
208
|
+
startLine: paragraphs[0].startLine,
|
|
209
|
+
endLine: paragraphs[paragraphs.length - 1].endLine,
|
|
210
|
+
content: body
|
|
211
|
+
}));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
let buffer = "";
|
|
215
|
+
let bufferStartLine = paragraphs[0].startLine;
|
|
216
|
+
let bufferEndLine = paragraphs[0].endLine;
|
|
217
|
+
for (const paragraph of paragraphs) {
|
|
218
|
+
const next = buffer.length > 0 ? `${buffer}
|
|
219
|
+
|
|
220
|
+
${paragraph.content}` : paragraph.content;
|
|
221
|
+
if (next.length > options.maxChunkChars && buffer.length > 0) {
|
|
222
|
+
chunks.push(options.createChunk({
|
|
223
|
+
title: currentTitle,
|
|
224
|
+
startLine: bufferStartLine,
|
|
225
|
+
endLine: bufferEndLine,
|
|
226
|
+
content: buffer
|
|
227
|
+
}));
|
|
228
|
+
buffer = paragraph.content;
|
|
229
|
+
bufferStartLine = paragraph.startLine;
|
|
230
|
+
bufferEndLine = paragraph.endLine;
|
|
231
|
+
} else {
|
|
232
|
+
buffer = next;
|
|
233
|
+
bufferEndLine = paragraph.endLine;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (buffer.length > 0) {
|
|
237
|
+
chunks.push(options.createChunk({
|
|
238
|
+
title: currentTitle,
|
|
239
|
+
startLine: bufferStartLine,
|
|
240
|
+
endLine: bufferEndLine,
|
|
241
|
+
content: buffer
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
246
|
+
const line = lines[index] ?? "";
|
|
247
|
+
if (/^#{1,6}\s+/.test(line) && currentLines.length > 0) {
|
|
248
|
+
flush();
|
|
249
|
+
currentLines = [];
|
|
250
|
+
currentTitle = line.replace(/^#{1,6}\s+/, "").trim() || currentTitle;
|
|
251
|
+
startLine = index + 2 + (options.startLineOffset ?? 0);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (/^#{1,6}\s+/.test(line)) {
|
|
255
|
+
currentTitle = line.replace(/^#{1,6}\s+/, "").trim() || currentTitle;
|
|
256
|
+
startLine = index + 2 + (options.startLineOffset ?? 0);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
currentLines.push(line);
|
|
260
|
+
}
|
|
261
|
+
flush();
|
|
262
|
+
return chunks;
|
|
263
|
+
}
|
|
264
|
+
async function readableFile(filePath) {
|
|
265
|
+
try {
|
|
266
|
+
const info = await stat(filePath);
|
|
267
|
+
return info.isFile();
|
|
268
|
+
} catch {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function resolveCandidatePaths(options) {
|
|
273
|
+
const out = /* @__PURE__ */ new Set();
|
|
274
|
+
for (const rel of options.includeFiles) {
|
|
275
|
+
const trimmed = rel.trim();
|
|
276
|
+
if (!trimmed) continue;
|
|
277
|
+
const candidatePath = path.join(options.workspaceDir, trimmed);
|
|
278
|
+
out.add(candidatePath);
|
|
279
|
+
if (path.basename(trimmed).toLowerCase() !== "identity.md") continue;
|
|
280
|
+
const relativeDir = path.dirname(trimmed);
|
|
281
|
+
if (options.identityVariantMode === "recall") {
|
|
282
|
+
if (!Array.isArray(options.recallNamespaces)) continue;
|
|
283
|
+
for (const namespace of options.recallNamespaces) {
|
|
284
|
+
if (!namespace || namespace === options.defaultNamespace) continue;
|
|
285
|
+
out.add(path.join(options.workspaceDir, relativeDir, `IDENTITY.${namespace}.md`));
|
|
286
|
+
}
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const absoluteDir = path.dirname(candidatePath);
|
|
290
|
+
let entries = [];
|
|
291
|
+
try {
|
|
292
|
+
entries = await readdir(absoluteDir);
|
|
293
|
+
} catch {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
for (const entry of entries) {
|
|
297
|
+
if (!/^identity\.[^.\/]+\.md$/i.test(entry)) continue;
|
|
298
|
+
out.add(path.join(options.workspaceDir, relativeDir, entry));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return Array.from(out);
|
|
302
|
+
}
|
|
303
|
+
function resolveNoteTitle(notePath, parsed) {
|
|
304
|
+
const rawTitle = parsed.data.title;
|
|
305
|
+
if (typeof rawTitle === "string" && rawTitle.trim().length > 0) return rawTitle.trim();
|
|
306
|
+
const heading = parsed.body.match(/^#{1,6}\s+(.+)$/m)?.[1]?.trim();
|
|
307
|
+
if (heading) return heading;
|
|
308
|
+
return path.basename(notePath, path.extname(notePath));
|
|
309
|
+
}
|
|
310
|
+
function parseFrontmatterList(value) {
|
|
311
|
+
if (Array.isArray(value)) return uniqueSorted(value);
|
|
312
|
+
if (typeof value === "string" && value.trim().length > 0) return [value.trim()];
|
|
313
|
+
return [];
|
|
314
|
+
}
|
|
315
|
+
function toPosixRelative(rootDir, filePath) {
|
|
316
|
+
return path.relative(rootDir, filePath).split(path.sep).join("/");
|
|
317
|
+
}
|
|
318
|
+
function globToRegExp(glob) {
|
|
319
|
+
let regex = "^";
|
|
320
|
+
for (let index = 0; index < glob.length; index += 1) {
|
|
321
|
+
const char = glob[index];
|
|
322
|
+
const next = glob[index + 1];
|
|
323
|
+
if (char === "*") {
|
|
324
|
+
if (next === "*") {
|
|
325
|
+
if (glob[index + 2] === "/") {
|
|
326
|
+
regex += "(?:.*/)?";
|
|
327
|
+
index += 2;
|
|
328
|
+
} else {
|
|
329
|
+
regex += ".*";
|
|
330
|
+
index += 1;
|
|
331
|
+
}
|
|
332
|
+
} else {
|
|
333
|
+
regex += "[^/]*";
|
|
334
|
+
}
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (char === "?") {
|
|
338
|
+
regex += ".";
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (char === "/") {
|
|
342
|
+
regex += "/";
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
regex += char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
346
|
+
}
|
|
347
|
+
regex += "$";
|
|
348
|
+
return new RegExp(regex);
|
|
349
|
+
}
|
|
350
|
+
function compileGlobs(patterns) {
|
|
351
|
+
return patterns.map((pattern) => globToRegExp(pattern));
|
|
352
|
+
}
|
|
353
|
+
function matchesCompiledGlobs(notePath, patterns) {
|
|
354
|
+
if (patterns.length === 0) return false;
|
|
355
|
+
return patterns.some((pattern) => pattern.test(notePath));
|
|
356
|
+
}
|
|
357
|
+
async function listMarkdownFiles(rootDir) {
|
|
358
|
+
const results = [];
|
|
359
|
+
async function walk(currentDir) {
|
|
360
|
+
const entries = await readdir(currentDir, { withFileTypes: true }).catch(() => []);
|
|
361
|
+
for (const entry of entries) {
|
|
362
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
363
|
+
if (entry.isDirectory()) {
|
|
364
|
+
await walk(fullPath);
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (!entry.isFile() || !entry.name.toLowerCase().endsWith(".md")) continue;
|
|
368
|
+
results.push(toPosixRelative(rootDir, fullPath));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const rootInfo = await stat(rootDir).catch(() => null);
|
|
372
|
+
if (!rootInfo?.isDirectory()) return null;
|
|
373
|
+
await walk(rootDir);
|
|
374
|
+
return results.sort();
|
|
375
|
+
}
|
|
376
|
+
function resolveFileCandidates(options) {
|
|
377
|
+
const out = /* @__PURE__ */ new Map();
|
|
378
|
+
const excludes = compileGlobs(options.excludeGlobs);
|
|
379
|
+
const handoff = compileGlobs(options.handoffGlobs);
|
|
380
|
+
const dailySummary = compileGlobs(options.dailySummaryGlobs);
|
|
381
|
+
const automation = compileGlobs(options.automationNoteGlobs);
|
|
382
|
+
const workspaceDocs = compileGlobs(options.workspaceDocGlobs);
|
|
383
|
+
const listedFiles = new Set(options.listedFiles.map((value) => value.replace(/\\/g, "/")));
|
|
384
|
+
for (const file of options.bootstrapFiles.map((value) => value.replace(/\\/g, "/"))) {
|
|
385
|
+
if (listedFiles.has(file) && !matchesCompiledGlobs(file, excludes)) out.set(file, "bootstrap_doc");
|
|
386
|
+
}
|
|
387
|
+
for (const sourcePath of listedFiles) {
|
|
388
|
+
if (matchesCompiledGlobs(sourcePath, excludes)) continue;
|
|
389
|
+
if (out.has(sourcePath)) continue;
|
|
390
|
+
if (matchesCompiledGlobs(sourcePath, handoff)) {
|
|
391
|
+
out.set(sourcePath, "handoff");
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
if (matchesCompiledGlobs(sourcePath, dailySummary)) {
|
|
395
|
+
out.set(sourcePath, "daily_summary");
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
if (matchesCompiledGlobs(sourcePath, automation)) {
|
|
399
|
+
out.set(sourcePath, "automation_note");
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
if (matchesCompiledGlobs(sourcePath, workspaceDocs)) {
|
|
403
|
+
out.set(sourcePath, "workspace_doc");
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return [...out.entries()].map(([sourcePath, sourceKind]) => ({ sourcePath, sourceKind })).sort((left, right) => left.sourcePath.localeCompare(right.sourcePath));
|
|
407
|
+
}
|
|
408
|
+
function resolveNativeKnowledgeStatePath(memoryDir, config) {
|
|
409
|
+
return path.join(memoryDir, config.stateDir, "obsidian-sync.json");
|
|
410
|
+
}
|
|
411
|
+
function resolveCuratedIncludeFilesStatePath(memoryDir, config) {
|
|
412
|
+
return path.join(memoryDir, config.stateDir, "curated-include-sync.json");
|
|
413
|
+
}
|
|
414
|
+
function resolveOpenClawWorkspaceStatePath(memoryDir, config) {
|
|
415
|
+
return path.join(memoryDir, config.stateDir, "openclaw-workspace-sync.json");
|
|
416
|
+
}
|
|
417
|
+
async function loadSyncState(memoryDir, config) {
|
|
418
|
+
const statePath = resolveNativeKnowledgeStatePath(memoryDir, config);
|
|
419
|
+
try {
|
|
420
|
+
const raw = JSON.parse(await readFile(statePath, "utf-8"));
|
|
421
|
+
if (raw.version !== 1 || typeof raw.vaults !== "object" || !raw.vaults) {
|
|
422
|
+
throw new Error("invalid obsidian native knowledge state");
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
version: 1,
|
|
426
|
+
updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
427
|
+
vaults: raw.vaults
|
|
428
|
+
};
|
|
429
|
+
} catch {
|
|
430
|
+
return {
|
|
431
|
+
version: 1,
|
|
432
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
433
|
+
vaults: {}
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
async function loadOpenClawWorkspaceState(memoryDir, config) {
|
|
438
|
+
const statePath = resolveOpenClawWorkspaceStatePath(memoryDir, config);
|
|
439
|
+
try {
|
|
440
|
+
const raw = JSON.parse(await readFile(statePath, "utf-8"));
|
|
441
|
+
if (raw.version !== 1 || typeof raw.files !== "object" || !raw.files) {
|
|
442
|
+
throw new Error("invalid openclaw workspace native knowledge state");
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
version: 1,
|
|
446
|
+
updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
447
|
+
files: raw.files
|
|
448
|
+
};
|
|
449
|
+
} catch {
|
|
450
|
+
return {
|
|
451
|
+
version: 1,
|
|
452
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
453
|
+
files: {}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
async function loadCuratedIncludeFilesState(memoryDir, config) {
|
|
458
|
+
const statePath = resolveCuratedIncludeFilesStatePath(memoryDir, config);
|
|
459
|
+
try {
|
|
460
|
+
const raw = JSON.parse(await readFile(statePath, "utf-8"));
|
|
461
|
+
if (raw.version !== 1 || typeof raw.files !== "object" || !raw.files) {
|
|
462
|
+
throw new Error("invalid curated include native knowledge state");
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
version: 1,
|
|
466
|
+
updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
467
|
+
files: raw.files
|
|
468
|
+
};
|
|
469
|
+
} catch {
|
|
470
|
+
return {
|
|
471
|
+
version: 1,
|
|
472
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
473
|
+
files: {}
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function deriveOpenClawArtifactMetadata(options) {
|
|
478
|
+
const sharedSafe = compileGlobs(options.sharedSafeGlobs);
|
|
479
|
+
return {
|
|
480
|
+
derivedDate: deriveArtifactDate(options.sourcePath, options.parsed),
|
|
481
|
+
sessionKey: firstStringValue(options.parsed.data, ["sessionKey", "session"]),
|
|
482
|
+
workflowKey: firstStringValue(options.parsed.data, ["workflowKey", "workflow"]),
|
|
483
|
+
author: firstStringValue(options.parsed.data, ["author"]),
|
|
484
|
+
agent: firstStringValue(options.parsed.data, ["agent"]),
|
|
485
|
+
namespace: firstStringValue(options.parsed.data, ["namespace"]),
|
|
486
|
+
privacyClass: firstStringValue(options.parsed.data, ["privacyClass", "privacy"]) ?? (matchesCompiledGlobs(options.sourcePath, sharedSafe) ? "shared_safe" : void 0)
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function buildOpenClawWorkspaceChunks(options) {
|
|
490
|
+
return chunkHeadingAware({
|
|
491
|
+
sourcePath: options.sourcePath,
|
|
492
|
+
content: options.body,
|
|
493
|
+
maxChunkChars: options.maxChunkChars,
|
|
494
|
+
startLineOffset: options.bodyStartLine - 1,
|
|
495
|
+
createChunk: ({ title, startLine, endLine, content }) => ({
|
|
496
|
+
chunkId: `${options.sourceKind}:${options.sourcePath}:${startLine}-${endLine}`,
|
|
497
|
+
sourcePath: options.sourcePath,
|
|
498
|
+
title,
|
|
499
|
+
sourceKind: options.sourceKind,
|
|
500
|
+
startLine,
|
|
501
|
+
endLine,
|
|
502
|
+
content,
|
|
503
|
+
derivedDate: options.metadata.derivedDate,
|
|
504
|
+
sessionKey: options.metadata.sessionKey,
|
|
505
|
+
workflowKey: options.metadata.workflowKey,
|
|
506
|
+
author: options.metadata.author,
|
|
507
|
+
agent: options.metadata.agent,
|
|
508
|
+
namespace: options.metadata.namespace,
|
|
509
|
+
privacyClass: options.metadata.privacyClass,
|
|
510
|
+
sourceHash: options.sourceHash,
|
|
511
|
+
mtimeMs: options.mtimeMs
|
|
512
|
+
})
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
function buildObsidianChunks(options) {
|
|
516
|
+
const noteKey = `${options.vault.id}:${options.notePath}`;
|
|
517
|
+
return chunkHeadingAware({
|
|
518
|
+
sourcePath: options.notePath,
|
|
519
|
+
content: options.content,
|
|
520
|
+
maxChunkChars: options.maxChunkChars,
|
|
521
|
+
startLineOffset: options.startLineOffset,
|
|
522
|
+
createChunk: ({ title, startLine, endLine, content }) => ({
|
|
523
|
+
chunkId: `${noteKey}:${startLine}-${endLine}`,
|
|
524
|
+
sourcePath: `${options.vault.id}/${options.notePath}`,
|
|
525
|
+
title,
|
|
526
|
+
sourceKind: "obsidian_note",
|
|
527
|
+
startLine,
|
|
528
|
+
endLine,
|
|
529
|
+
content,
|
|
530
|
+
vaultId: options.vault.id,
|
|
531
|
+
notePath: options.notePath,
|
|
532
|
+
noteKey,
|
|
533
|
+
derivedDate: options.derivedDate,
|
|
534
|
+
tags: options.tags,
|
|
535
|
+
aliases: options.aliases,
|
|
536
|
+
wikilinks: options.wikilinks,
|
|
537
|
+
backlinks: options.backlinks ?? [],
|
|
538
|
+
namespace: options.namespace,
|
|
539
|
+
privacyClass: options.privacyClass,
|
|
540
|
+
sourceHash: options.sourceHash,
|
|
541
|
+
mtimeMs: options.mtimeMs
|
|
542
|
+
})
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
function buildAliasIndex(notes) {
|
|
546
|
+
const index = /* @__PURE__ */ new Map();
|
|
547
|
+
for (const note of Object.values(notes)) {
|
|
548
|
+
if (note.deleted) continue;
|
|
549
|
+
const candidates = [
|
|
550
|
+
note.title,
|
|
551
|
+
path.basename(note.notePath, path.extname(note.notePath)),
|
|
552
|
+
note.notePath.replace(/\.md$/i, ""),
|
|
553
|
+
...note.aliases
|
|
554
|
+
];
|
|
555
|
+
for (const candidate of candidates) {
|
|
556
|
+
const key = normalizeText(candidate);
|
|
557
|
+
if (!key) continue;
|
|
558
|
+
const existing = index.get(key) ?? [];
|
|
559
|
+
existing.push(note.noteKey);
|
|
560
|
+
index.set(key, uniqueSorted(existing));
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return index;
|
|
564
|
+
}
|
|
565
|
+
function materializeBacklinks(notes) {
|
|
566
|
+
const backlinks = /* @__PURE__ */ new Map();
|
|
567
|
+
const aliasIndex = buildAliasIndex(notes);
|
|
568
|
+
for (const note of Object.values(notes)) {
|
|
569
|
+
if (note.deleted) continue;
|
|
570
|
+
for (const target of note.wikilinks) {
|
|
571
|
+
const matches = aliasIndex.get(normalizeText(target)) ?? [];
|
|
572
|
+
for (const match of matches) {
|
|
573
|
+
if (match === note.noteKey) continue;
|
|
574
|
+
const bucket = backlinks.get(match) ?? /* @__PURE__ */ new Set();
|
|
575
|
+
bucket.add(note.notePath);
|
|
576
|
+
backlinks.set(match, bucket);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return Object.fromEntries(
|
|
581
|
+
[...backlinks.entries()].map(([noteKey, refs]) => [noteKey, [...refs].sort()])
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
async function syncObsidianVaults(options) {
|
|
585
|
+
if (options.config.obsidianVaults.length === 0) {
|
|
586
|
+
return {
|
|
587
|
+
statePath: resolveNativeKnowledgeStatePath(options.memoryDir, options.config),
|
|
588
|
+
vaultCount: 0,
|
|
589
|
+
touchedNotes: 0,
|
|
590
|
+
deletedNotes: 0,
|
|
591
|
+
chunkCount: 0,
|
|
592
|
+
activeChunks: []
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
const state = await loadSyncState(options.memoryDir, options.config);
|
|
596
|
+
const nextVaults = {};
|
|
597
|
+
let touchedNotes = 0;
|
|
598
|
+
let deletedNotes = 0;
|
|
599
|
+
let chunkCount = 0;
|
|
600
|
+
for (const vault of options.config.obsidianVaults) {
|
|
601
|
+
const previousVault = state.vaults[vault.id];
|
|
602
|
+
const previousNotes = previousVault?.notes ?? {};
|
|
603
|
+
const notePaths = await listMarkdownFiles(vault.rootDir);
|
|
604
|
+
if (notePaths === null) {
|
|
605
|
+
nextVaults[vault.id] = previousVault ?? {
|
|
606
|
+
vaultId: vault.id,
|
|
607
|
+
rootDir: vault.rootDir,
|
|
608
|
+
syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
609
|
+
notes: previousNotes
|
|
610
|
+
};
|
|
611
|
+
chunkCount += Object.values(previousNotes).filter((note) => !note.deleted).reduce((total, note) => total + note.chunks.length, 0);
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
const includePatterns = compileGlobs(vault.includeGlobs);
|
|
615
|
+
const excludePatterns = compileGlobs(vault.excludeGlobs);
|
|
616
|
+
const includedNotePaths = notePaths.filter((notePath) => {
|
|
617
|
+
if (!matchesCompiledGlobs(notePath, includePatterns)) return false;
|
|
618
|
+
if (matchesCompiledGlobs(notePath, excludePatterns)) return false;
|
|
619
|
+
return true;
|
|
620
|
+
});
|
|
621
|
+
const nextNotes = {};
|
|
622
|
+
const seenNoteKeys = /* @__PURE__ */ new Set();
|
|
623
|
+
for (const notePath of includedNotePaths) {
|
|
624
|
+
const absPath = path.join(vault.rootDir, notePath);
|
|
625
|
+
const content = await readFile(absPath, "utf-8").catch(() => null);
|
|
626
|
+
if (content === null) continue;
|
|
627
|
+
const info = await stat(absPath).catch(() => null);
|
|
628
|
+
if (!info?.isFile()) continue;
|
|
629
|
+
const sourceHash = createHash("sha256").update(content).digest("hex");
|
|
630
|
+
const noteKey = `${vault.id}:${notePath}`;
|
|
631
|
+
seenNoteKeys.add(noteKey);
|
|
632
|
+
const previous = previousNotes[noteKey];
|
|
633
|
+
if (previous && previous.deleted !== true && previous.sourceHash === sourceHash && previous.mtimeMs === info.mtimeMs) {
|
|
634
|
+
nextNotes[noteKey] = {
|
|
635
|
+
...previous,
|
|
636
|
+
deleted: false,
|
|
637
|
+
deletedAt: void 0
|
|
638
|
+
};
|
|
639
|
+
chunkCount += previous.chunks.length;
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
const parsed = parseFrontmatter(content);
|
|
643
|
+
const { targets } = extractWikilinks(parsed.body);
|
|
644
|
+
const tags = uniqueSorted([
|
|
645
|
+
...parseFrontmatterList(parsed.data.tags),
|
|
646
|
+
...extractInlineTags(parsed.body)
|
|
647
|
+
]);
|
|
648
|
+
const aliases = parseFrontmatterList(parsed.data.aliases);
|
|
649
|
+
const { namespace, privacyClass } = classifyObsidianNote(notePath, vault);
|
|
650
|
+
const title = resolveNoteTitle(notePath, parsed);
|
|
651
|
+
const derivedDate = deriveDailyNoteDate(notePath, vault.dailyNotePatterns);
|
|
652
|
+
const chunks = buildObsidianChunks({
|
|
653
|
+
vault,
|
|
654
|
+
notePath,
|
|
655
|
+
title,
|
|
656
|
+
content: parsed.body,
|
|
657
|
+
startLineOffset: parsed.bodyStartLine - 1,
|
|
658
|
+
derivedDate,
|
|
659
|
+
tags,
|
|
660
|
+
aliases,
|
|
661
|
+
wikilinks: targets,
|
|
662
|
+
namespace,
|
|
663
|
+
privacyClass,
|
|
664
|
+
sourceHash,
|
|
665
|
+
mtimeMs: info.mtimeMs,
|
|
666
|
+
maxChunkChars: options.config.maxChunkChars
|
|
667
|
+
});
|
|
668
|
+
nextNotes[noteKey] = {
|
|
669
|
+
noteKey,
|
|
670
|
+
notePath,
|
|
671
|
+
title,
|
|
672
|
+
derivedDate,
|
|
673
|
+
tags,
|
|
674
|
+
aliases,
|
|
675
|
+
wikilinks: targets,
|
|
676
|
+
backlinks: [],
|
|
677
|
+
namespace,
|
|
678
|
+
privacyClass,
|
|
679
|
+
sourceHash,
|
|
680
|
+
mtimeMs: info.mtimeMs,
|
|
681
|
+
deleted: false,
|
|
682
|
+
chunks
|
|
683
|
+
};
|
|
684
|
+
touchedNotes += 1;
|
|
685
|
+
chunkCount += chunks.length;
|
|
686
|
+
}
|
|
687
|
+
for (const [noteKey, previous] of Object.entries(previousNotes)) {
|
|
688
|
+
if (seenNoteKeys.has(noteKey)) continue;
|
|
689
|
+
nextNotes[noteKey] = {
|
|
690
|
+
...previous,
|
|
691
|
+
deleted: true,
|
|
692
|
+
deletedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
693
|
+
chunks: []
|
|
694
|
+
};
|
|
695
|
+
deletedNotes += 1;
|
|
696
|
+
}
|
|
697
|
+
if (vault.materializeBacklinks) {
|
|
698
|
+
const backlinks = materializeBacklinks(nextNotes);
|
|
699
|
+
for (const note of Object.values(nextNotes)) {
|
|
700
|
+
if (note.deleted) continue;
|
|
701
|
+
note.backlinks = backlinks[note.noteKey] ?? [];
|
|
702
|
+
note.chunks = note.chunks.map((chunk) => ({
|
|
703
|
+
...chunk,
|
|
704
|
+
backlinks: note.backlinks
|
|
705
|
+
}));
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
nextVaults[vault.id] = {
|
|
709
|
+
vaultId: vault.id,
|
|
710
|
+
rootDir: vault.rootDir,
|
|
711
|
+
syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
712
|
+
notes: nextNotes
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
const nextState = {
|
|
716
|
+
version: 1,
|
|
717
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
718
|
+
vaults: nextVaults
|
|
719
|
+
};
|
|
720
|
+
const activeChunks = loadActiveObsidianChunks({
|
|
721
|
+
state: nextState,
|
|
722
|
+
defaultNamespace: "default"
|
|
723
|
+
});
|
|
724
|
+
const statePath = resolveNativeKnowledgeStatePath(options.memoryDir, options.config);
|
|
725
|
+
try {
|
|
726
|
+
await mkdir(path.dirname(statePath), { recursive: true });
|
|
727
|
+
await writeFile(statePath, `${JSON.stringify(nextState, null, 2)}
|
|
728
|
+
`, "utf-8");
|
|
729
|
+
} catch (error) {
|
|
730
|
+
log.warn(`native knowledge: failed to persist obsidian sync state (fail-open): ${String(error)}`);
|
|
731
|
+
}
|
|
732
|
+
return {
|
|
733
|
+
statePath,
|
|
734
|
+
vaultCount: options.config.obsidianVaults.length,
|
|
735
|
+
touchedNotes,
|
|
736
|
+
deletedNotes,
|
|
737
|
+
chunkCount,
|
|
738
|
+
activeChunks
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
function loadActiveObsidianChunks(options) {
|
|
742
|
+
const out = [];
|
|
743
|
+
for (const vault of Object.values(options.state.vaults)) {
|
|
744
|
+
for (const note of Object.values(vault.notes)) {
|
|
745
|
+
if (note.deleted) continue;
|
|
746
|
+
if (!isChunkAllowedForRecall(note, options.recallNamespaces, options.defaultNamespace)) continue;
|
|
747
|
+
out.push(...note.chunks);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
return out;
|
|
751
|
+
}
|
|
752
|
+
function isChunkAllowedForRecall(chunk, recallNamespaces, defaultNamespace) {
|
|
753
|
+
const namespace = chunk.namespace?.trim() || defaultNamespace;
|
|
754
|
+
if (Array.isArray(recallNamespaces) && namespace !== defaultNamespace && !recallNamespaces.includes(namespace)) {
|
|
755
|
+
return false;
|
|
756
|
+
}
|
|
757
|
+
const privacyClass = chunk.privacyClass?.trim().toLowerCase();
|
|
758
|
+
if (privacyClass === "private" && Array.isArray(recallNamespaces) && (namespace !== defaultNamespace || !recallNamespaces.includes(defaultNamespace))) {
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
return true;
|
|
762
|
+
}
|
|
763
|
+
function loadActiveOpenClawWorkspaceChunks(options) {
|
|
764
|
+
const out = [];
|
|
765
|
+
for (const file of Object.values(options.state.files)) {
|
|
766
|
+
if (file.deleted) continue;
|
|
767
|
+
if (!isChunkAllowedForRecall(file, options.recallNamespaces, options.defaultNamespace)) continue;
|
|
768
|
+
out.push(...file.chunks);
|
|
769
|
+
}
|
|
770
|
+
return out;
|
|
771
|
+
}
|
|
772
|
+
function deriveCuratedFileMetadata(options) {
|
|
773
|
+
return {
|
|
774
|
+
derivedDate: deriveArtifactDate(options.sourcePath, options.parsed),
|
|
775
|
+
namespace: firstStringValue(options.parsed.data, ["namespace"]) ?? deriveNamespaceFromIncludePath(options.sourcePath),
|
|
776
|
+
privacyClass: firstStringValue(options.parsed.data, ["privacyClass", "privacy"])
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
function buildCuratedIncludeChunks(options) {
|
|
780
|
+
return chunkHeadingAware({
|
|
781
|
+
sourcePath: options.sourcePath,
|
|
782
|
+
content: options.body,
|
|
783
|
+
maxChunkChars: options.maxChunkChars,
|
|
784
|
+
startLineOffset: options.bodyStartLine - 1,
|
|
785
|
+
createChunk: ({ title, startLine, endLine, content }) => ({
|
|
786
|
+
chunkId: `${options.sourcePath}:${startLine}-${endLine}`,
|
|
787
|
+
sourcePath: options.sourcePath,
|
|
788
|
+
title,
|
|
789
|
+
sourceKind: detectSourceKind(options.sourcePath),
|
|
790
|
+
startLine,
|
|
791
|
+
endLine,
|
|
792
|
+
content,
|
|
793
|
+
derivedDate: options.metadata.derivedDate,
|
|
794
|
+
namespace: options.metadata.namespace,
|
|
795
|
+
privacyClass: options.metadata.privacyClass,
|
|
796
|
+
sourceHash: options.sourceHash,
|
|
797
|
+
mtimeMs: options.mtimeMs
|
|
798
|
+
})
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
function loadActiveCuratedIncludeChunks(options) {
|
|
802
|
+
const out = [];
|
|
803
|
+
for (const file of Object.values(options.state.files)) {
|
|
804
|
+
if (file.deleted) continue;
|
|
805
|
+
if (!isChunkAllowedForRecall(file, options.recallNamespaces, options.defaultNamespace)) continue;
|
|
806
|
+
out.push(...file.chunks);
|
|
807
|
+
}
|
|
808
|
+
return out;
|
|
809
|
+
}
|
|
810
|
+
function dedupeNativeKnowledgeChunks(chunks) {
|
|
811
|
+
const seen = /* @__PURE__ */ new Set();
|
|
812
|
+
const priority = /* @__PURE__ */ new Map([
|
|
813
|
+
["handoff", 1],
|
|
814
|
+
["daily_summary", 2],
|
|
815
|
+
["bootstrap_doc", 3],
|
|
816
|
+
["automation_note", 4],
|
|
817
|
+
["workspace_doc", 5],
|
|
818
|
+
["identity", 6],
|
|
819
|
+
["memory", 7],
|
|
820
|
+
["obsidian_note", 8]
|
|
821
|
+
]);
|
|
822
|
+
return [...chunks].sort((left, right) => {
|
|
823
|
+
const leftPriority = priority.get(left.sourceKind) ?? 99;
|
|
824
|
+
const rightPriority = priority.get(right.sourceKind) ?? 99;
|
|
825
|
+
return leftPriority - rightPriority || left.sourcePath.localeCompare(right.sourcePath) || left.startLine - right.startLine;
|
|
826
|
+
}).filter((chunk) => {
|
|
827
|
+
const key = [
|
|
828
|
+
chunk.sourcePath,
|
|
829
|
+
chunk.startLine,
|
|
830
|
+
chunk.endLine,
|
|
831
|
+
chunk.content
|
|
832
|
+
].join("::");
|
|
833
|
+
if (seen.has(key)) return false;
|
|
834
|
+
seen.add(key);
|
|
835
|
+
return true;
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
async function findPersistedNativeKnowledgeStateFiles(rootDir, maxDepth, currentDepth = 0) {
|
|
839
|
+
if (currentDepth > maxDepth) return [];
|
|
840
|
+
const entries = await readdir(rootDir, { withFileTypes: true }).catch(() => []);
|
|
841
|
+
const out = [];
|
|
842
|
+
for (const entry of entries) {
|
|
843
|
+
const fullPath = path.join(rootDir, entry.name);
|
|
844
|
+
if (entry.isFile() && PERSISTED_NATIVE_KNOWLEDGE_STATE_FILES.has(entry.name)) {
|
|
845
|
+
out.push(fullPath);
|
|
846
|
+
continue;
|
|
847
|
+
}
|
|
848
|
+
if (!entry.isDirectory()) continue;
|
|
849
|
+
out.push(...await findPersistedNativeKnowledgeStateFiles(fullPath, maxDepth, currentDepth + 1));
|
|
850
|
+
}
|
|
851
|
+
return out;
|
|
852
|
+
}
|
|
853
|
+
async function loadPersistedNativeKnowledgeChunks(options) {
|
|
854
|
+
const stateFiles = await findPersistedNativeKnowledgeStateFiles(options.memoryDir, 4);
|
|
855
|
+
if (stateFiles.length === 0) return [];
|
|
856
|
+
const chunks = [];
|
|
857
|
+
for (const statePath of stateFiles.sort()) {
|
|
858
|
+
const raw = await readFile(statePath, "utf-8").catch(() => "");
|
|
859
|
+
if (!raw) continue;
|
|
860
|
+
try {
|
|
861
|
+
const parsed = JSON.parse(raw);
|
|
862
|
+
if (typeof parsed.vaults === "object" && parsed.vaults) {
|
|
863
|
+
const state = {
|
|
864
|
+
version: 1,
|
|
865
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
866
|
+
vaults: parsed.vaults
|
|
867
|
+
};
|
|
868
|
+
chunks.push(...loadActiveObsidianChunks({
|
|
869
|
+
state,
|
|
870
|
+
recallNamespaces: options.recallNamespaces,
|
|
871
|
+
defaultNamespace: options.defaultNamespace
|
|
872
|
+
}).map((chunk) => {
|
|
873
|
+
const note = Object.values(state.vaults).flatMap((vault) => Object.values(vault.notes)).find((entry) => entry.chunks.some((candidate) => candidate.chunkId === chunk.chunkId));
|
|
874
|
+
if (!note) return chunk;
|
|
875
|
+
return {
|
|
876
|
+
...chunk,
|
|
877
|
+
derivedDate: chunk.derivedDate ?? note.derivedDate,
|
|
878
|
+
namespace: chunk.namespace ?? note.namespace,
|
|
879
|
+
privacyClass: chunk.privacyClass ?? note.privacyClass,
|
|
880
|
+
aliases: chunk.aliases ?? note.aliases,
|
|
881
|
+
tags: chunk.tags ?? note.tags,
|
|
882
|
+
wikilinks: chunk.wikilinks ?? note.wikilinks,
|
|
883
|
+
backlinks: chunk.backlinks ?? note.backlinks
|
|
884
|
+
};
|
|
885
|
+
}));
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
if (typeof parsed.files === "object" && parsed.files) {
|
|
889
|
+
if (path.basename(statePath) === "openclaw-workspace-sync.json") {
|
|
890
|
+
const state2 = {
|
|
891
|
+
version: 1,
|
|
892
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
893
|
+
files: parsed.files
|
|
894
|
+
};
|
|
895
|
+
chunks.push(...loadActiveOpenClawWorkspaceChunks({
|
|
896
|
+
state: state2,
|
|
897
|
+
recallNamespaces: options.recallNamespaces,
|
|
898
|
+
defaultNamespace: options.defaultNamespace
|
|
899
|
+
}).map((chunk) => {
|
|
900
|
+
const file = state2.files[chunk.sourcePath];
|
|
901
|
+
if (!file) return chunk;
|
|
902
|
+
return {
|
|
903
|
+
...chunk,
|
|
904
|
+
derivedDate: chunk.derivedDate ?? file.derivedDate,
|
|
905
|
+
namespace: chunk.namespace ?? file.namespace,
|
|
906
|
+
privacyClass: chunk.privacyClass ?? file.privacyClass,
|
|
907
|
+
sessionKey: chunk.sessionKey ?? file.sessionKey,
|
|
908
|
+
workflowKey: chunk.workflowKey ?? file.workflowKey,
|
|
909
|
+
author: chunk.author ?? file.author,
|
|
910
|
+
agent: chunk.agent ?? file.agent
|
|
911
|
+
};
|
|
912
|
+
}));
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
const state = {
|
|
916
|
+
version: 1,
|
|
917
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
918
|
+
files: parsed.files
|
|
919
|
+
};
|
|
920
|
+
chunks.push(...loadActiveCuratedIncludeChunks({
|
|
921
|
+
state,
|
|
922
|
+
recallNamespaces: options.recallNamespaces,
|
|
923
|
+
defaultNamespace: options.defaultNamespace
|
|
924
|
+
}).map((chunk) => {
|
|
925
|
+
const file = state.files[chunk.sourcePath];
|
|
926
|
+
if (!file) return chunk;
|
|
927
|
+
return {
|
|
928
|
+
...chunk,
|
|
929
|
+
derivedDate: chunk.derivedDate ?? file.derivedDate,
|
|
930
|
+
namespace: chunk.namespace ?? file.namespace,
|
|
931
|
+
privacyClass: chunk.privacyClass ?? file.privacyClass
|
|
932
|
+
};
|
|
933
|
+
}));
|
|
934
|
+
}
|
|
935
|
+
} catch {
|
|
936
|
+
continue;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return dedupeNativeKnowledgeChunks(chunks);
|
|
940
|
+
}
|
|
941
|
+
async function syncOpenClawWorkspaceArtifacts(options) {
|
|
942
|
+
const adapter = options.config.openclawWorkspace;
|
|
943
|
+
const statePath = resolveOpenClawWorkspaceStatePath(options.memoryDir, options.config);
|
|
944
|
+
if (!adapter?.enabled) {
|
|
945
|
+
return { statePath, touchedFiles: 0, deletedFiles: 0, chunkCount: 0, activeChunks: [] };
|
|
946
|
+
}
|
|
947
|
+
const previousState = await loadOpenClawWorkspaceState(options.memoryDir, options.config);
|
|
948
|
+
const listedFiles = await listMarkdownFiles(options.workspaceDir);
|
|
949
|
+
if (listedFiles === null) {
|
|
950
|
+
return {
|
|
951
|
+
statePath,
|
|
952
|
+
touchedFiles: 0,
|
|
953
|
+
deletedFiles: 0,
|
|
954
|
+
chunkCount: Object.values(previousState.files).filter((file) => !file.deleted).reduce((total, file) => total + file.chunks.length, 0),
|
|
955
|
+
activeChunks: loadActiveOpenClawWorkspaceChunks({
|
|
956
|
+
state: previousState,
|
|
957
|
+
defaultNamespace: "default"
|
|
958
|
+
})
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
const candidates = resolveFileCandidates({
|
|
962
|
+
listedFiles,
|
|
963
|
+
bootstrapFiles: adapter.bootstrapFiles,
|
|
964
|
+
handoffGlobs: adapter.handoffGlobs,
|
|
965
|
+
dailySummaryGlobs: adapter.dailySummaryGlobs,
|
|
966
|
+
automationNoteGlobs: adapter.automationNoteGlobs,
|
|
967
|
+
workspaceDocGlobs: adapter.workspaceDocGlobs,
|
|
968
|
+
excludeGlobs: adapter.excludeGlobs
|
|
969
|
+
});
|
|
970
|
+
const nextFiles = {};
|
|
971
|
+
const seen = /* @__PURE__ */ new Set();
|
|
972
|
+
let touchedFiles = 0;
|
|
973
|
+
let deletedFiles = 0;
|
|
974
|
+
for (const candidate of candidates) {
|
|
975
|
+
const absPath = path.join(options.workspaceDir, candidate.sourcePath);
|
|
976
|
+
const content = await readFile(absPath, "utf-8").catch(() => null);
|
|
977
|
+
if (content === null) continue;
|
|
978
|
+
const info = await stat(absPath).catch(() => null);
|
|
979
|
+
if (!info?.isFile()) continue;
|
|
980
|
+
const sourceHash = createHash("sha256").update(content).digest("hex");
|
|
981
|
+
const parsed = parseFrontmatter(content);
|
|
982
|
+
const metadata = deriveOpenClawArtifactMetadata({
|
|
983
|
+
sourcePath: candidate.sourcePath,
|
|
984
|
+
parsed,
|
|
985
|
+
sharedSafeGlobs: adapter.sharedSafeGlobs
|
|
986
|
+
});
|
|
987
|
+
const title = resolveNoteTitle(candidate.sourcePath, parsed);
|
|
988
|
+
const syncConfigHash = createHash("sha256").update(JSON.stringify({
|
|
989
|
+
sourceKind: candidate.sourceKind,
|
|
990
|
+
maxChunkChars: options.config.maxChunkChars,
|
|
991
|
+
metadata
|
|
992
|
+
})).digest("hex");
|
|
993
|
+
const previous = previousState.files[candidate.sourcePath];
|
|
994
|
+
if (previous && previous.deleted !== true && previous.sourceHash === sourceHash && previous.mtimeMs === info.mtimeMs && previous.syncConfigHash === syncConfigHash) {
|
|
995
|
+
nextFiles[candidate.sourcePath] = {
|
|
996
|
+
...previous,
|
|
997
|
+
deleted: false,
|
|
998
|
+
deletedAt: void 0
|
|
999
|
+
};
|
|
1000
|
+
seen.add(candidate.sourcePath);
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
const chunks = buildOpenClawWorkspaceChunks({
|
|
1004
|
+
sourcePath: candidate.sourcePath,
|
|
1005
|
+
sourceKind: candidate.sourceKind,
|
|
1006
|
+
body: parsed.body,
|
|
1007
|
+
bodyStartLine: parsed.bodyStartLine,
|
|
1008
|
+
maxChunkChars: options.config.maxChunkChars,
|
|
1009
|
+
sourceHash,
|
|
1010
|
+
mtimeMs: info.mtimeMs,
|
|
1011
|
+
metadata
|
|
1012
|
+
});
|
|
1013
|
+
nextFiles[candidate.sourcePath] = {
|
|
1014
|
+
sourcePath: candidate.sourcePath,
|
|
1015
|
+
sourceKind: candidate.sourceKind,
|
|
1016
|
+
title,
|
|
1017
|
+
namespace: metadata.namespace,
|
|
1018
|
+
privacyClass: metadata.privacyClass,
|
|
1019
|
+
derivedDate: metadata.derivedDate,
|
|
1020
|
+
sessionKey: metadata.sessionKey,
|
|
1021
|
+
workflowKey: metadata.workflowKey,
|
|
1022
|
+
author: metadata.author,
|
|
1023
|
+
agent: metadata.agent,
|
|
1024
|
+
sourceHash,
|
|
1025
|
+
syncConfigHash,
|
|
1026
|
+
mtimeMs: info.mtimeMs,
|
|
1027
|
+
deleted: false,
|
|
1028
|
+
chunks
|
|
1029
|
+
};
|
|
1030
|
+
touchedFiles += 1;
|
|
1031
|
+
seen.add(candidate.sourcePath);
|
|
1032
|
+
}
|
|
1033
|
+
for (const [sourcePath, previous] of Object.entries(previousState.files)) {
|
|
1034
|
+
if (seen.has(sourcePath)) continue;
|
|
1035
|
+
nextFiles[sourcePath] = {
|
|
1036
|
+
...previous,
|
|
1037
|
+
deleted: true,
|
|
1038
|
+
deletedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1039
|
+
chunks: []
|
|
1040
|
+
};
|
|
1041
|
+
deletedFiles += 1;
|
|
1042
|
+
}
|
|
1043
|
+
const nextState = {
|
|
1044
|
+
version: 1,
|
|
1045
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1046
|
+
files: nextFiles
|
|
1047
|
+
};
|
|
1048
|
+
const activeChunks = loadActiveOpenClawWorkspaceChunks({
|
|
1049
|
+
state: nextState,
|
|
1050
|
+
defaultNamespace: "default"
|
|
1051
|
+
});
|
|
1052
|
+
const chunkCount = activeChunks.length;
|
|
1053
|
+
try {
|
|
1054
|
+
await mkdir(path.dirname(statePath), { recursive: true });
|
|
1055
|
+
await writeFile(statePath, `${JSON.stringify(nextState, null, 2)}
|
|
1056
|
+
`, "utf-8");
|
|
1057
|
+
} catch (error) {
|
|
1058
|
+
log.warn(`native knowledge: failed to persist openclaw workspace sync state (fail-open): ${String(error)}`);
|
|
1059
|
+
}
|
|
1060
|
+
return {
|
|
1061
|
+
statePath,
|
|
1062
|
+
touchedFiles,
|
|
1063
|
+
deletedFiles,
|
|
1064
|
+
chunkCount,
|
|
1065
|
+
activeChunks
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
async function syncCuratedIncludeFiles(options) {
|
|
1069
|
+
const statePath = resolveCuratedIncludeFilesStatePath(options.memoryDir, options.config);
|
|
1070
|
+
const previousState = await loadCuratedIncludeFilesState(options.memoryDir, options.config);
|
|
1071
|
+
const workspaceInfo = await stat(options.workspaceDir).catch(() => null);
|
|
1072
|
+
if (!workspaceInfo?.isDirectory()) {
|
|
1073
|
+
return {
|
|
1074
|
+
statePath,
|
|
1075
|
+
touchedFiles: 0,
|
|
1076
|
+
deletedFiles: 0,
|
|
1077
|
+
chunkCount: Object.values(previousState.files).filter((file) => !file.deleted).reduce((total, file) => total + file.chunks.length, 0),
|
|
1078
|
+
activeChunks: loadActiveCuratedIncludeChunks({
|
|
1079
|
+
state: previousState,
|
|
1080
|
+
recallNamespaces: options.recallNamespaces,
|
|
1081
|
+
defaultNamespace: options.defaultNamespace
|
|
1082
|
+
})
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
const skipped = new Set((options.skipSourcePaths ?? []).map((value) => value.replace(/\\/g, "/")));
|
|
1086
|
+
const candidatePaths = await resolveCandidatePaths({
|
|
1087
|
+
workspaceDir: options.workspaceDir,
|
|
1088
|
+
includeFiles: options.config.includeFiles,
|
|
1089
|
+
defaultNamespace: options.defaultNamespace,
|
|
1090
|
+
identityVariantMode: "disk"
|
|
1091
|
+
});
|
|
1092
|
+
const nextFiles = {};
|
|
1093
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1094
|
+
let touchedFiles = 0;
|
|
1095
|
+
let deletedFiles = 0;
|
|
1096
|
+
for (const filePath of candidatePaths) {
|
|
1097
|
+
if (!await readableFile(filePath)) continue;
|
|
1098
|
+
const content = await readFile(filePath, "utf-8").catch(() => null);
|
|
1099
|
+
if (content === null) continue;
|
|
1100
|
+
const info = await stat(filePath).catch(() => null);
|
|
1101
|
+
if (!info?.isFile()) continue;
|
|
1102
|
+
const sourcePath = path.relative(options.workspaceDir, filePath).replace(/\\/g, "/");
|
|
1103
|
+
if (skipped.has(sourcePath)) continue;
|
|
1104
|
+
const parsed = parseFrontmatter(content);
|
|
1105
|
+
const metadata = deriveCuratedFileMetadata({
|
|
1106
|
+
sourcePath,
|
|
1107
|
+
parsed
|
|
1108
|
+
});
|
|
1109
|
+
const sourceKind = detectSourceKind(sourcePath);
|
|
1110
|
+
const sourceHash = createHash("sha256").update(content).digest("hex");
|
|
1111
|
+
const title = resolveNoteTitle(sourcePath, parsed);
|
|
1112
|
+
const syncConfigHash = createHash("sha256").update(JSON.stringify({
|
|
1113
|
+
sourceKind,
|
|
1114
|
+
maxChunkChars: options.config.maxChunkChars,
|
|
1115
|
+
metadata
|
|
1116
|
+
})).digest("hex");
|
|
1117
|
+
const previous = previousState.files[sourcePath];
|
|
1118
|
+
if (previous && previous.deleted !== true && previous.sourceHash === sourceHash && previous.mtimeMs === info.mtimeMs && previous.syncConfigHash === syncConfigHash) {
|
|
1119
|
+
nextFiles[sourcePath] = {
|
|
1120
|
+
...previous,
|
|
1121
|
+
deleted: false,
|
|
1122
|
+
deletedAt: void 0
|
|
1123
|
+
};
|
|
1124
|
+
seen.add(sourcePath);
|
|
1125
|
+
continue;
|
|
1126
|
+
}
|
|
1127
|
+
const chunks = buildCuratedIncludeChunks({
|
|
1128
|
+
sourcePath,
|
|
1129
|
+
body: parsed.body,
|
|
1130
|
+
bodyStartLine: parsed.bodyStartLine,
|
|
1131
|
+
maxChunkChars: options.config.maxChunkChars,
|
|
1132
|
+
sourceHash,
|
|
1133
|
+
mtimeMs: info.mtimeMs,
|
|
1134
|
+
metadata
|
|
1135
|
+
});
|
|
1136
|
+
nextFiles[sourcePath] = {
|
|
1137
|
+
sourcePath,
|
|
1138
|
+
sourceKind,
|
|
1139
|
+
title,
|
|
1140
|
+
namespace: metadata.namespace,
|
|
1141
|
+
privacyClass: metadata.privacyClass,
|
|
1142
|
+
derivedDate: metadata.derivedDate,
|
|
1143
|
+
sourceHash,
|
|
1144
|
+
syncConfigHash,
|
|
1145
|
+
mtimeMs: info.mtimeMs,
|
|
1146
|
+
deleted: false,
|
|
1147
|
+
chunks
|
|
1148
|
+
};
|
|
1149
|
+
touchedFiles += 1;
|
|
1150
|
+
seen.add(sourcePath);
|
|
1151
|
+
}
|
|
1152
|
+
for (const [sourcePath, previous] of Object.entries(previousState.files)) {
|
|
1153
|
+
if (seen.has(sourcePath) || skipped.has(sourcePath)) continue;
|
|
1154
|
+
if (previous.deleted) {
|
|
1155
|
+
nextFiles[sourcePath] = previous;
|
|
1156
|
+
continue;
|
|
1157
|
+
}
|
|
1158
|
+
nextFiles[sourcePath] = {
|
|
1159
|
+
...previous,
|
|
1160
|
+
deleted: true,
|
|
1161
|
+
deletedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1162
|
+
chunks: []
|
|
1163
|
+
};
|
|
1164
|
+
deletedFiles += 1;
|
|
1165
|
+
}
|
|
1166
|
+
const nextState = {
|
|
1167
|
+
version: 1,
|
|
1168
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1169
|
+
files: nextFiles
|
|
1170
|
+
};
|
|
1171
|
+
const activeChunks = loadActiveCuratedIncludeChunks({
|
|
1172
|
+
state: nextState,
|
|
1173
|
+
recallNamespaces: options.recallNamespaces,
|
|
1174
|
+
defaultNamespace: options.defaultNamespace
|
|
1175
|
+
});
|
|
1176
|
+
const chunkCount = Object.values(nextFiles).filter((file) => !file.deleted).reduce((total, file) => total + file.chunks.length, 0);
|
|
1177
|
+
try {
|
|
1178
|
+
await mkdir(path.dirname(statePath), { recursive: true });
|
|
1179
|
+
await writeFile(statePath, `${JSON.stringify(nextState, null, 2)}
|
|
1180
|
+
`, "utf-8");
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
log.warn(`native knowledge: failed to persist curated include sync state (fail-open): ${String(error)}`);
|
|
1183
|
+
}
|
|
1184
|
+
return {
|
|
1185
|
+
statePath,
|
|
1186
|
+
touchedFiles,
|
|
1187
|
+
deletedFiles,
|
|
1188
|
+
chunkCount,
|
|
1189
|
+
activeChunks
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
async function collectNativeKnowledgeChunks(options) {
|
|
1193
|
+
throwIfNativeKnowledgeAborted(options.abortSignal);
|
|
1194
|
+
if (!options.config.enabled) return [];
|
|
1195
|
+
const chunks = [];
|
|
1196
|
+
const openclawBootstrapFiles = new Set(
|
|
1197
|
+
(options.memoryDir && options.config.openclawWorkspace?.enabled ? options.config.openclawWorkspace.bootstrapFiles : []).map((value) => value.replace(/\\/g, "/"))
|
|
1198
|
+
);
|
|
1199
|
+
if (options.memoryDir) {
|
|
1200
|
+
throwIfNativeKnowledgeAborted(options.abortSignal);
|
|
1201
|
+
const syncResult = await syncCuratedIncludeFiles({
|
|
1202
|
+
workspaceDir: options.workspaceDir,
|
|
1203
|
+
memoryDir: options.memoryDir,
|
|
1204
|
+
config: options.config,
|
|
1205
|
+
recallNamespaces: options.recallNamespaces,
|
|
1206
|
+
defaultNamespace: options.defaultNamespace,
|
|
1207
|
+
skipSourcePaths: [...openclawBootstrapFiles]
|
|
1208
|
+
});
|
|
1209
|
+
chunks.push(...syncResult.activeChunks);
|
|
1210
|
+
} else {
|
|
1211
|
+
throwIfNativeKnowledgeAborted(options.abortSignal);
|
|
1212
|
+
const candidatePaths = await resolveCandidatePaths({
|
|
1213
|
+
workspaceDir: options.workspaceDir,
|
|
1214
|
+
includeFiles: options.config.includeFiles,
|
|
1215
|
+
recallNamespaces: options.recallNamespaces,
|
|
1216
|
+
defaultNamespace: options.defaultNamespace,
|
|
1217
|
+
identityVariantMode: "recall"
|
|
1218
|
+
});
|
|
1219
|
+
for (const filePath of candidatePaths) {
|
|
1220
|
+
throwIfNativeKnowledgeAborted(options.abortSignal);
|
|
1221
|
+
if (!await readableFile(filePath)) continue;
|
|
1222
|
+
const content = await readFile(filePath, "utf-8").catch(() => null);
|
|
1223
|
+
if (!content) continue;
|
|
1224
|
+
const sourcePath = path.relative(options.workspaceDir, filePath).replace(/\\/g, "/");
|
|
1225
|
+
if (openclawBootstrapFiles.has(sourcePath)) continue;
|
|
1226
|
+
const parsed = parseFrontmatter(content);
|
|
1227
|
+
const metadata = deriveCuratedFileMetadata({
|
|
1228
|
+
sourcePath,
|
|
1229
|
+
parsed
|
|
1230
|
+
});
|
|
1231
|
+
const directChunks = buildCuratedIncludeChunks({
|
|
1232
|
+
sourcePath,
|
|
1233
|
+
body: parsed.body,
|
|
1234
|
+
bodyStartLine: parsed.bodyStartLine,
|
|
1235
|
+
maxChunkChars: options.config.maxChunkChars,
|
|
1236
|
+
sourceHash: createHash("sha256").update(content).digest("hex"),
|
|
1237
|
+
mtimeMs: 0,
|
|
1238
|
+
metadata
|
|
1239
|
+
}).filter((chunk) => isChunkAllowedForRecall(chunk, options.recallNamespaces, options.defaultNamespace));
|
|
1240
|
+
chunks.push(...directChunks);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
if (options.memoryDir && options.config.openclawWorkspace?.enabled) {
|
|
1244
|
+
throwIfNativeKnowledgeAborted(options.abortSignal);
|
|
1245
|
+
const syncResult = await syncOpenClawWorkspaceArtifacts({
|
|
1246
|
+
workspaceDir: options.workspaceDir,
|
|
1247
|
+
memoryDir: options.memoryDir,
|
|
1248
|
+
config: options.config
|
|
1249
|
+
});
|
|
1250
|
+
chunks.push(
|
|
1251
|
+
...syncResult.activeChunks.filter(
|
|
1252
|
+
(chunk) => isChunkAllowedForRecall(chunk, options.recallNamespaces, options.defaultNamespace)
|
|
1253
|
+
)
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
1256
|
+
if (options.memoryDir && options.config.obsidianVaults.length > 0) {
|
|
1257
|
+
throwIfNativeKnowledgeAborted(options.abortSignal);
|
|
1258
|
+
const syncResult = await syncObsidianVaults({
|
|
1259
|
+
memoryDir: options.memoryDir,
|
|
1260
|
+
config: options.config
|
|
1261
|
+
});
|
|
1262
|
+
chunks.push(
|
|
1263
|
+
...syncResult.activeChunks.filter(
|
|
1264
|
+
(chunk) => isChunkAllowedForRecall(chunk, options.recallNamespaces, options.defaultNamespace)
|
|
1265
|
+
)
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
return dedupeNativeKnowledgeChunks(chunks);
|
|
1269
|
+
}
|
|
1270
|
+
function throwIfNativeKnowledgeAborted(signal) {
|
|
1271
|
+
if (!signal?.aborted) return;
|
|
1272
|
+
const err = new Error("native knowledge collection aborted");
|
|
1273
|
+
Object.defineProperty(err, "name", { value: "AbortError" });
|
|
1274
|
+
throw err;
|
|
1275
|
+
}
|
|
1276
|
+
function searchNativeKnowledge(options) {
|
|
1277
|
+
const normalizedQuery = normalizeText(options.query);
|
|
1278
|
+
const queryTokens = new Set(tokenize(options.query));
|
|
1279
|
+
if (!normalizedQuery || queryTokens.size === 0 || options.maxResults <= 0) return [];
|
|
1280
|
+
const temporalQuery = /\b(today|yesterday|recent|latest|current|next|handoff|summary)\b/i.test(options.query);
|
|
1281
|
+
const now = Date.now();
|
|
1282
|
+
return options.chunks.map((chunk) => {
|
|
1283
|
+
const metadataText = [
|
|
1284
|
+
chunk.title,
|
|
1285
|
+
chunk.content,
|
|
1286
|
+
chunk.sourcePath,
|
|
1287
|
+
chunk.notePath,
|
|
1288
|
+
chunk.derivedDate,
|
|
1289
|
+
chunk.sessionKey,
|
|
1290
|
+
chunk.workflowKey,
|
|
1291
|
+
chunk.author,
|
|
1292
|
+
chunk.agent,
|
|
1293
|
+
...chunk.tags ?? [],
|
|
1294
|
+
...chunk.aliases ?? [],
|
|
1295
|
+
...chunk.wikilinks ?? [],
|
|
1296
|
+
...chunk.backlinks ?? []
|
|
1297
|
+
].filter((value) => typeof value === "string" && value.length > 0).join("\n");
|
|
1298
|
+
const normalizedContent = normalizeText(metadataText);
|
|
1299
|
+
const contentTokens = new Set(tokenize(normalizedContent));
|
|
1300
|
+
let overlap = 0;
|
|
1301
|
+
for (const token of queryTokens) {
|
|
1302
|
+
if (contentTokens.has(token)) overlap += 1;
|
|
1303
|
+
}
|
|
1304
|
+
if (overlap === 0 && !normalizedContent.includes(normalizedQuery)) return null;
|
|
1305
|
+
const kindBoost = chunk.sourceKind === "handoff" ? 0.2 : chunk.sourceKind === "daily_summary" ? 0.16 : chunk.sourceKind === "bootstrap_doc" || chunk.sourceKind === "identity" ? 0.15 : chunk.sourceKind === "memory" ? 0.1 : chunk.sourceKind === "obsidian_note" ? 0.08 : chunk.sourceKind === "automation_note" ? 0.06 : 0.05;
|
|
1306
|
+
const phraseBoost = normalizedContent.includes(normalizedQuery) ? 0.35 : 0;
|
|
1307
|
+
const metadataBoost = (chunk.aliases?.some((alias) => normalizeText(alias).includes(normalizedQuery)) ? 0.12 : 0) + (chunk.tags?.some((tag) => normalizeText(tag).includes(normalizedQuery)) ? 0.08 : 0) + (chunk.derivedDate && normalizeText(chunk.derivedDate).includes(normalizedQuery) ? 0.08 : 0) + (chunk.sessionKey && normalizeText(chunk.sessionKey).includes(normalizedQuery) ? 0.1 : 0) + (chunk.workflowKey && normalizeText(chunk.workflowKey).includes(normalizedQuery) ? 0.08 : 0) + (chunk.agent && normalizeText(chunk.agent).includes(normalizedQuery) ? 0.06 : 0) + (chunk.author && normalizeText(chunk.author).includes(normalizedQuery) ? 0.05 : 0);
|
|
1308
|
+
let temporalBoost = 0;
|
|
1309
|
+
if (chunk.derivedDate) {
|
|
1310
|
+
const parsed = Date.parse(`${chunk.derivedDate}T00:00:00Z`);
|
|
1311
|
+
if (Number.isFinite(parsed)) {
|
|
1312
|
+
const ageDays = Math.max(0, Math.floor((now - parsed) / (24 * 60 * 60 * 1e3)));
|
|
1313
|
+
if (ageDays <= 1) temporalBoost += temporalQuery ? 0.12 : 0.04;
|
|
1314
|
+
else if (ageDays <= 7) temporalBoost += temporalQuery ? 0.08 : 0.02;
|
|
1315
|
+
else if (temporalQuery && ageDays >= 90) temporalBoost -= 0.08;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
return {
|
|
1319
|
+
...chunk,
|
|
1320
|
+
score: overlap / Math.max(queryTokens.size, 1) + kindBoost + phraseBoost + metadataBoost + temporalBoost
|
|
1321
|
+
};
|
|
1322
|
+
}).filter((chunk) => chunk !== null).sort((a, b) => b.score - a.score || a.sourcePath.localeCompare(b.sourcePath) || a.startLine - b.startLine).slice(0, options.maxResults);
|
|
1323
|
+
}
|
|
1324
|
+
function formatNativeKnowledgeSection(options) {
|
|
1325
|
+
if (options.results.length === 0 || options.maxChars <= 0) return null;
|
|
1326
|
+
const lines = ["## Curated Workspace Knowledge", ""];
|
|
1327
|
+
let used = lines.join("\n").length;
|
|
1328
|
+
for (const result of options.results) {
|
|
1329
|
+
const snippet = result.content.length > 500 ? `${result.content.slice(0, 497)}...` : result.content;
|
|
1330
|
+
const meta = [
|
|
1331
|
+
`kind=${result.sourceKind}`,
|
|
1332
|
+
result.derivedDate ? `date=${result.derivedDate}` : null,
|
|
1333
|
+
result.sessionKey ? `session=${result.sessionKey}` : null,
|
|
1334
|
+
result.workflowKey ? `workflow=${result.workflowKey}` : null,
|
|
1335
|
+
result.agent ? `agent=${result.agent}` : null,
|
|
1336
|
+
result.author ? `author=${result.author}` : null,
|
|
1337
|
+
result.tags && result.tags.length > 0 ? `tags=${result.tags.join(",")}` : null,
|
|
1338
|
+
result.vaultId ? `vault=${result.vaultId}` : null
|
|
1339
|
+
].filter((value) => value !== null).join(" ");
|
|
1340
|
+
const block = `- ${result.sourcePath}:${result.startLine}-${result.endLine} [${result.title}] (score: ${result.score.toFixed(3)}${meta ? `; ${meta}` : ""})
|
|
1341
|
+
${snippet.replace(/\n/g, "\n ")}`;
|
|
1342
|
+
if (used + block.length > options.maxChars && lines.length > 2) break;
|
|
1343
|
+
if (used + block.length > options.maxChars) return null;
|
|
1344
|
+
lines.push(block);
|
|
1345
|
+
used += block.length + 1;
|
|
1346
|
+
}
|
|
1347
|
+
return lines.length > 2 ? lines.join("\n") : null;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
export {
|
|
1351
|
+
resolveNativeKnowledgeStatePath,
|
|
1352
|
+
resolveCuratedIncludeFilesStatePath,
|
|
1353
|
+
resolveOpenClawWorkspaceStatePath,
|
|
1354
|
+
syncObsidianVaults,
|
|
1355
|
+
loadPersistedNativeKnowledgeChunks,
|
|
1356
|
+
syncOpenClawWorkspaceArtifacts,
|
|
1357
|
+
syncCuratedIncludeFiles,
|
|
1358
|
+
collectNativeKnowledgeChunks,
|
|
1359
|
+
searchNativeKnowledge,
|
|
1360
|
+
formatNativeKnowledgeSection
|
|
1361
|
+
};
|
|
1362
|
+
//# sourceMappingURL=chunk-Q6FETXJA.js.map
|