@remnic/core 9.63.0 → 9.63.2
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.d.ts +1 -1
- package/dist/access-admin-ops-surface.js +34 -33
- package/dist/access-audit.js +2 -2
- package/dist/access-authorization-probe.d.ts +1 -1
- package/dist/access-authorization-probe.js +35 -34
- package/dist/access-boundary.d.ts +1 -1
- package/dist/access-boundary.js +34 -33
- package/dist/access-cli.js +99 -97
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +1 -1
- package/dist/access-extraction-force-flush.js +34 -33
- package/dist/access-http-lcm-compaction.d.ts +1 -1
- package/dist/access-http-lifecycle-flush.d.ts +1 -1
- package/dist/access-http-offline-stream.d.ts +1 -1
- package/dist/access-http-query.js +34 -33
- package/dist/access-http.d.ts +2 -2
- package/dist/access-http.js +47 -46
- package/dist/access-identity-continuity-surface.js +34 -33
- package/dist/access-lcm-surface.d.ts +1 -1
- package/dist/access-lcm-surface.js +34 -33
- package/dist/access-mcp.d.ts +1 -1
- package/dist/access-mcp.js +40 -39
- package/dist/access-namespace-preflight.js +34 -33
- package/dist/access-observe-write-surface.d.ts +1 -1
- package/dist/access-observe-write-surface.js +34 -33
- package/dist/access-operations-batch.js +35 -34
- package/dist/access-operations.d.ts +4 -4
- package/dist/access-operations.js +39 -38
- package/dist/access-recall-concurrency.d.ts +1 -1
- package/dist/access-recall-concurrency.js +34 -33
- package/dist/access-recall-response.d.ts +1 -1
- package/dist/access-recall-response.js +34 -33
- package/dist/access-recall-surface.d.ts +1 -1
- package/dist/access-recall-surface.js +34 -33
- package/dist/access-schema.d.ts +88 -88
- package/dist/access-schema.js +3 -3
- package/dist/access-service-helpers.d.ts +1 -1
- package/dist/access-service.d.ts +1 -1
- package/dist/access-service.js +34 -33
- package/dist/access-surface-catalog.d.ts +1 -1
- package/dist/access-surface-catalog.js +36 -35
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/registry.js +3 -3
- package/dist/{auto-sync-Z52VWMNC.js → auto-sync-BKRJDMKX.js} +3 -3
- package/dist/behavior-learner.js +2 -2
- package/dist/briefing.js +15 -15
- package/dist/buffer.js +5 -4
- package/dist/causal-behavior.js +3 -3
- package/dist/causal-chain.js +3 -3
- package/dist/causal-consolidation.js +18 -18
- package/dist/causal-retrieval.js +3 -3
- package/dist/causal-trajectory.js +2 -2
- package/dist/{chunk-5F6HMNMZ.js → chunk-2LA3H54D.js} +2 -2
- package/dist/{chunk-IRLH4NM2.js → chunk-2PSX5BJU.js} +3 -3
- package/dist/{chunk-JBPKEARU.js → chunk-2QSZNTDO.js} +7 -7
- package/dist/{chunk-IZRNVNPV.js → chunk-3LJ2L3T3.js} +2 -2
- package/dist/{chunk-CLJ5QS6J.js → chunk-44KHFMCM.js} +72 -64
- package/dist/{chunk-CLJ5QS6J.js.map → chunk-44KHFMCM.js.map} +1 -1
- package/dist/{chunk-JDI7G6EA.js → chunk-4NMVX5U7.js} +2 -2
- package/dist/{chunk-WFLBP5GC.js → chunk-4NZHHGVL.js} +25 -6
- package/dist/chunk-4NZHHGVL.js.map +1 -0
- package/dist/{chunk-ANMIOQPU.js → chunk-4XN35YQD.js} +478 -164
- package/dist/chunk-4XN35YQD.js.map +1 -0
- package/dist/{chunk-LJOIZPJH.js → chunk-5QZR2RA3.js} +2 -2
- package/dist/{chunk-FF6E6HOT.js → chunk-5UFQCU6M.js} +32 -32
- package/dist/{chunk-4HO3542O.js → chunk-5W5N7XJZ.js} +2 -2
- package/dist/{chunk-4Y2RHVCV.js → chunk-5W62VEFH.js} +4 -4
- package/dist/{chunk-DEOYTFA6.js → chunk-645WOU5I.js} +4 -52
- package/dist/chunk-645WOU5I.js.map +1 -0
- package/dist/{chunk-LTJTP5YQ.js → chunk-6D7PZKCJ.js} +10 -10
- package/dist/{chunk-BBHFAVMP.js → chunk-6F2UMP4H.js} +7 -7
- package/dist/{chunk-IIPJKCZB.js → chunk-6NAPOLRO.js} +3 -3
- package/dist/{chunk-CK3NQUSQ.js → chunk-6UZR7KEK.js} +2 -2
- package/dist/{chunk-2TYIAKU5.js → chunk-6YMEU6OQ.js} +2 -2
- package/dist/{chunk-H23GIXJC.js → chunk-A73QHOZP.js} +2 -2
- package/dist/{chunk-LLGDVG52.js → chunk-AJSZ2EK6.js} +3 -3
- package/dist/{chunk-HVKMJAEF.js → chunk-B2OOJCUX.js} +2 -2
- package/dist/chunk-BUYVPUEM.js +66 -0
- package/dist/chunk-BUYVPUEM.js.map +1 -0
- package/dist/{chunk-YTHQHH5U.js → chunk-C6WMSXCJ.js} +2 -2
- package/dist/{chunk-JKW663ZN.js → chunk-CIAI24TQ.js} +2 -2
- package/dist/{chunk-PD6O7AXF.js → chunk-CSAKJVXW.js} +14 -17
- package/dist/chunk-CSAKJVXW.js.map +1 -0
- package/dist/{chunk-EFWHCTYJ.js → chunk-DNRTKO2U.js} +2 -2
- package/dist/{chunk-QCECHYZL.js → chunk-E2GYBTSP.js} +24 -4
- package/dist/chunk-E2GYBTSP.js.map +1 -0
- package/dist/{chunk-4IZ2IT7D.js → chunk-EJLTNPRY.js} +3 -3
- package/dist/{chunk-JCJGYNIS.js → chunk-EJQXDKYK.js} +4 -4
- package/dist/{chunk-347ZR6D4.js → chunk-FKJVEW6O.js} +2 -2
- package/dist/{chunk-DROAPP6N.js → chunk-GFNS3BHV.js} +3 -3
- package/dist/{chunk-ALNZEWGN.js → chunk-GPFZFCRN.js} +2 -2
- package/dist/{chunk-KPML4Q3M.js → chunk-GTRGH4ZT.js} +3 -3
- package/dist/{chunk-TIRJV2LW.js → chunk-I6OQCT3Y.js} +2 -2
- package/dist/{chunk-CH627RRV.js → chunk-IKXUG6KC.js} +8 -8
- package/dist/{chunk-HSBQJRV2.js → chunk-IM56VPKO.js} +3 -3
- package/dist/{chunk-KQAFEZQX.js → chunk-IPLYGWQF.js} +5 -5
- package/dist/{chunk-BP6WMYLP.js → chunk-ITYAXU4S.js} +3 -3
- package/dist/{chunk-4FFROSFG.js → chunk-JJ7JW62R.js} +23 -23
- package/dist/{chunk-RFH7U5LT.js → chunk-JJX5XEIG.js} +2 -2
- package/dist/{chunk-CALURYWR.js → chunk-JWPG65LH.js} +14 -14
- package/dist/chunk-K2XUWZBM.js +417 -0
- package/dist/chunk-K2XUWZBM.js.map +1 -0
- package/dist/{chunk-G2FCSILA.js → chunk-KWIGDKM2.js} +2 -2
- package/dist/{chunk-WR2YKUIW.js → chunk-KWN6NOHQ.js} +2 -2
- package/dist/{chunk-227UFSEQ.js → chunk-LEPOP46W.js} +4 -4
- package/dist/{chunk-WMOJIOIG.js → chunk-LZCSOUJ7.js} +2 -2
- package/dist/{chunk-256FBCVX.js → chunk-M4AHBM72.js} +7 -7
- package/dist/{chunk-5PFGMO33.js → chunk-MEW53VQJ.js} +2 -2
- package/dist/{chunk-DCUMFQYM.js → chunk-ML3U4KPR.js} +2 -2
- package/dist/{chunk-X6E7TT3A.js → chunk-MR5HWQHS.js} +2 -2
- package/dist/{chunk-H7PRHUBD.js → chunk-NRLELHAY.js} +2 -2
- package/dist/{chunk-ZS4JADYY.js → chunk-OW7NVMGQ.js} +2 -2
- package/dist/{chunk-TGSMU3F2.js → chunk-PADG72LJ.js} +3 -3
- package/dist/{chunk-6GGTATZF.js → chunk-PYIR4SSB.js} +4 -4
- package/dist/chunk-PYIR4SSB.js.map +1 -0
- package/dist/{chunk-UDTME32W.js → chunk-Q35XGIEM.js} +2 -2
- package/dist/{chunk-XPRJSHNI.js → chunk-QJ622LTI.js} +6 -3
- package/dist/chunk-QJ622LTI.js.map +1 -0
- package/dist/{chunk-AYIHDC5S.js → chunk-QSIQVC32.js} +2 -2
- package/dist/{chunk-3MA7JVXN.js → chunk-R74NCKEY.js} +4 -4
- package/dist/{chunk-QCI73Z7C.js → chunk-RYGJGXL6.js} +2 -2
- package/dist/{chunk-4OW2T32G.js → chunk-SQ3EGGII.js} +2 -2
- package/dist/{chunk-ZPGHA7EO.js → chunk-TRPX6F2G.js} +10 -10
- package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
- package/dist/{chunk-7BJYTX6Q.js → chunk-VAMQU4W7.js} +2 -2
- package/dist/{chunk-YSR3DXGC.js → chunk-VN7IIQGS.js} +2 -2
- package/dist/{chunk-DTLF2SLZ.js → chunk-WDUG2CH3.js} +2 -2
- package/dist/{chunk-YIIC5IDU.js → chunk-X4MGNVOO.js} +2 -2
- package/dist/{chunk-BHO6RHE5.js → chunk-XFCQIQQU.js} +3 -3
- package/dist/{chunk-PSNN25DW.js → chunk-XZPSBGHA.js} +2 -2
- package/dist/{chunk-PMRUMGK6.js → chunk-Y7COCXY2.js} +2 -2
- package/dist/{chunk-DJ7HMNSL.js → chunk-YCVB7X56.js} +4 -2
- package/dist/chunk-YCVB7X56.js.map +1 -0
- package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
- package/dist/{chunk-JFLKSD5V.js → chunk-Z334TJRB.js} +2 -2
- package/dist/{cli-Bw9z-KqX.d.ts → cli-DJwNNDL1.d.ts} +1 -1
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +68 -67
- package/dist/coding/pre-action-gate.js +3 -3
- package/dist/compounding/engine.js +15 -15
- package/dist/connectors/codex-materialize-runner.js +15 -15
- package/dist/connectors/index.d.ts +45 -1
- package/dist/connectors/index.js +24 -16
- package/dist/convergence-refresh.js +17 -17
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-watermark.js +17 -17
- package/dist/dashboard-runtime.js +2 -2
- package/dist/direct-answer-wiring.js +3 -3
- package/dist/direct-answer.js +2 -2
- package/dist/entity-retrieval.js +15 -15
- package/dist/event-order-query.d.ts +3 -0
- package/dist/event-order-query.js +9 -0
- package/dist/event-order-query.js.map +1 -0
- package/dist/event-order-recall.d.ts +2 -2
- package/dist/event-order-recall.js +5 -2
- package/dist/external-wiki-access.d.ts +1 -1
- package/dist/external-wiki-access.js +35 -34
- package/dist/external-wiki-mcp-tools.d.ts +1 -1
- package/dist/extraction-normalization.js +2 -2
- package/dist/extraction.js +25 -24
- package/dist/harmonic-construction.js +2 -2
- package/dist/harmonic-retrieval.js +2 -2
- package/dist/index.d.ts +683 -682
- package/dist/index.js +108 -105
- package/dist/intent.js +2 -1
- package/dist/lcm/engine.js +3 -3
- package/dist/lcm/index.js +6 -6
- package/dist/maintenance/memory-governance.js +15 -15
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +15 -15
- package/dist/maintenance/rebuild-memory-projection.js +16 -16
- package/dist/mcp-memory-inspector-app.d.ts +1 -1
- package/dist/namespaces/migrate.js +16 -16
- package/dist/namespaces/search.js +10 -10
- package/dist/namespaces/storage.js +15 -15
- package/dist/operator-doctor-corpus.js +18 -18
- package/dist/operator-toolkit.js +22 -22
- package/dist/orchestration/maintenance.js +20 -20
- package/dist/orchestrator.js +101 -99
- package/dist/policy-runtime.js +3 -3
- package/dist/{public-http-DK-QwaBu.d.ts → public-http-43z1YT-k.d.ts} +1 -1
- package/dist/{qmd-D_62bYNl.d.ts → qmd-CBSxevyb.d.ts} +12 -1
- package/dist/qmd-preflight.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/qmd.js +3 -1
- package/dist/recall-planner-i18n.d.ts +31 -0
- package/dist/recall-planner-i18n.js +30 -0
- package/dist/recall-planner-i18n.js.map +1 -0
- package/dist/recall-planner-llm.js +2 -1
- package/dist/recall-planner-llm.js.map +1 -1
- package/dist/recall-query-policy.js +2 -2
- package/dist/recall-tokenization.js +1 -1
- package/dist/resume-bundles.js +3 -3
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-agents.js +2 -1
- package/dist/schemas.d.ts +117 -434
- package/dist/schemas.js +1 -1
- package/dist/search/factory.js +9 -9
- package/dist/search/index.js +15 -15
- package/dist/search/orama-backend.js +2 -2
- package/dist/semantic-consolidation.js +16 -16
- package/dist/semantic-rule-promotion.js +15 -15
- package/dist/semantic-rule-verifier.js +15 -15
- package/dist/shared-context/manager.d.ts +8 -8
- package/dist/source-agent-qualifier.js +21 -20
- package/dist/storage.js +14 -14
- package/dist/support-passport/index.d.ts +4 -4
- package/dist/support-passport/index.js +37 -36
- package/dist/transfer/autodetect.js +1 -1
- package/dist/transfer/backup.js +1 -1
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/types.d.ts +66 -66
- package/dist/trust-zones.js +2 -2
- package/dist/verified-recall.js +15 -15
- package/dist/work-product-ledger.js +2 -2
- package/package.json +2 -2
- package/src/connectors/droid-mcp.ts +434 -0
- package/src/connectors/index.ts +70 -0
- package/src/direct-answer.ts +6 -3
- package/src/event-order-query.ts +78 -0
- package/src/event-order-recall.ts +4 -90
- package/src/intent.ts +19 -19
- package/src/orchestration/turn-ingestion.ts +24 -1
- package/src/orchestrator-flush.test.ts +142 -1
- package/src/qmd-process-group.test.ts +125 -0
- package/src/qmd.ts +30 -2
- package/src/recall-planner-i18n.ts +193 -0
- package/src/recall-tokenization.ts +3 -1
- package/src/retrieval-agents.ts +6 -10
- package/src/schemas.test.ts +158 -0
- package/src/schemas.ts +45 -22
- package/dist/chunk-6GGTATZF.js.map +0 -1
- package/dist/chunk-ANMIOQPU.js.map +0 -1
- package/dist/chunk-DEOYTFA6.js.map +0 -1
- package/dist/chunk-DJ7HMNSL.js.map +0 -1
- package/dist/chunk-PD6O7AXF.js.map +0 -1
- package/dist/chunk-QCECHYZL.js.map +0 -1
- package/dist/chunk-WFLBP5GC.js.map +0 -1
- package/dist/chunk-XPRJSHNI.js.map +0 -1
- package/dist/{access-service-M4LgO141.d.ts → access-service-DBpEnlzA.d.ts} +64 -64
- /package/dist/{auto-sync-Z52VWMNC.js.map → auto-sync-BKRJDMKX.js.map} +0 -0
- /package/dist/{chunk-5F6HMNMZ.js.map → chunk-2LA3H54D.js.map} +0 -0
- /package/dist/{chunk-IRLH4NM2.js.map → chunk-2PSX5BJU.js.map} +0 -0
- /package/dist/{chunk-JBPKEARU.js.map → chunk-2QSZNTDO.js.map} +0 -0
- /package/dist/{chunk-IZRNVNPV.js.map → chunk-3LJ2L3T3.js.map} +0 -0
- /package/dist/{chunk-JDI7G6EA.js.map → chunk-4NMVX5U7.js.map} +0 -0
- /package/dist/{chunk-LJOIZPJH.js.map → chunk-5QZR2RA3.js.map} +0 -0
- /package/dist/{chunk-FF6E6HOT.js.map → chunk-5UFQCU6M.js.map} +0 -0
- /package/dist/{chunk-4HO3542O.js.map → chunk-5W5N7XJZ.js.map} +0 -0
- /package/dist/{chunk-4Y2RHVCV.js.map → chunk-5W62VEFH.js.map} +0 -0
- /package/dist/{chunk-LTJTP5YQ.js.map → chunk-6D7PZKCJ.js.map} +0 -0
- /package/dist/{chunk-BBHFAVMP.js.map → chunk-6F2UMP4H.js.map} +0 -0
- /package/dist/{chunk-IIPJKCZB.js.map → chunk-6NAPOLRO.js.map} +0 -0
- /package/dist/{chunk-CK3NQUSQ.js.map → chunk-6UZR7KEK.js.map} +0 -0
- /package/dist/{chunk-2TYIAKU5.js.map → chunk-6YMEU6OQ.js.map} +0 -0
- /package/dist/{chunk-H23GIXJC.js.map → chunk-A73QHOZP.js.map} +0 -0
- /package/dist/{chunk-LLGDVG52.js.map → chunk-AJSZ2EK6.js.map} +0 -0
- /package/dist/{chunk-HVKMJAEF.js.map → chunk-B2OOJCUX.js.map} +0 -0
- /package/dist/{chunk-YTHQHH5U.js.map → chunk-C6WMSXCJ.js.map} +0 -0
- /package/dist/{chunk-JKW663ZN.js.map → chunk-CIAI24TQ.js.map} +0 -0
- /package/dist/{chunk-EFWHCTYJ.js.map → chunk-DNRTKO2U.js.map} +0 -0
- /package/dist/{chunk-4IZ2IT7D.js.map → chunk-EJLTNPRY.js.map} +0 -0
- /package/dist/{chunk-JCJGYNIS.js.map → chunk-EJQXDKYK.js.map} +0 -0
- /package/dist/{chunk-347ZR6D4.js.map → chunk-FKJVEW6O.js.map} +0 -0
- /package/dist/{chunk-DROAPP6N.js.map → chunk-GFNS3BHV.js.map} +0 -0
- /package/dist/{chunk-ALNZEWGN.js.map → chunk-GPFZFCRN.js.map} +0 -0
- /package/dist/{chunk-KPML4Q3M.js.map → chunk-GTRGH4ZT.js.map} +0 -0
- /package/dist/{chunk-TIRJV2LW.js.map → chunk-I6OQCT3Y.js.map} +0 -0
- /package/dist/{chunk-CH627RRV.js.map → chunk-IKXUG6KC.js.map} +0 -0
- /package/dist/{chunk-HSBQJRV2.js.map → chunk-IM56VPKO.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-IPLYGWQF.js.map} +0 -0
- /package/dist/{chunk-BP6WMYLP.js.map → chunk-ITYAXU4S.js.map} +0 -0
- /package/dist/{chunk-4FFROSFG.js.map → chunk-JJ7JW62R.js.map} +0 -0
- /package/dist/{chunk-RFH7U5LT.js.map → chunk-JJX5XEIG.js.map} +0 -0
- /package/dist/{chunk-CALURYWR.js.map → chunk-JWPG65LH.js.map} +0 -0
- /package/dist/{chunk-G2FCSILA.js.map → chunk-KWIGDKM2.js.map} +0 -0
- /package/dist/{chunk-WR2YKUIW.js.map → chunk-KWN6NOHQ.js.map} +0 -0
- /package/dist/{chunk-227UFSEQ.js.map → chunk-LEPOP46W.js.map} +0 -0
- /package/dist/{chunk-WMOJIOIG.js.map → chunk-LZCSOUJ7.js.map} +0 -0
- /package/dist/{chunk-256FBCVX.js.map → chunk-M4AHBM72.js.map} +0 -0
- /package/dist/{chunk-5PFGMO33.js.map → chunk-MEW53VQJ.js.map} +0 -0
- /package/dist/{chunk-DCUMFQYM.js.map → chunk-ML3U4KPR.js.map} +0 -0
- /package/dist/{chunk-X6E7TT3A.js.map → chunk-MR5HWQHS.js.map} +0 -0
- /package/dist/{chunk-H7PRHUBD.js.map → chunk-NRLELHAY.js.map} +0 -0
- /package/dist/{chunk-ZS4JADYY.js.map → chunk-OW7NVMGQ.js.map} +0 -0
- /package/dist/{chunk-TGSMU3F2.js.map → chunk-PADG72LJ.js.map} +0 -0
- /package/dist/{chunk-UDTME32W.js.map → chunk-Q35XGIEM.js.map} +0 -0
- /package/dist/{chunk-AYIHDC5S.js.map → chunk-QSIQVC32.js.map} +0 -0
- /package/dist/{chunk-3MA7JVXN.js.map → chunk-R74NCKEY.js.map} +0 -0
- /package/dist/{chunk-QCI73Z7C.js.map → chunk-RYGJGXL6.js.map} +0 -0
- /package/dist/{chunk-4OW2T32G.js.map → chunk-SQ3EGGII.js.map} +0 -0
- /package/dist/{chunk-ZPGHA7EO.js.map → chunk-TRPX6F2G.js.map} +0 -0
- /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
- /package/dist/{chunk-7BJYTX6Q.js.map → chunk-VAMQU4W7.js.map} +0 -0
- /package/dist/{chunk-YSR3DXGC.js.map → chunk-VN7IIQGS.js.map} +0 -0
- /package/dist/{chunk-DTLF2SLZ.js.map → chunk-WDUG2CH3.js.map} +0 -0
- /package/dist/{chunk-YIIC5IDU.js.map → chunk-X4MGNVOO.js.map} +0 -0
- /package/dist/{chunk-BHO6RHE5.js.map → chunk-XFCQIQQU.js.map} +0 -0
- /package/dist/{chunk-PSNN25DW.js.map → chunk-XZPSBGHA.js.map} +0 -0
- /package/dist/{chunk-PMRUMGK6.js.map → chunk-Y7COCXY2.js.map} +0 -0
- /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
- /package/dist/{chunk-JFLKSD5V.js.map → chunk-Z334TJRB.js.map} +0 -0
|
@@ -33,9 +33,9 @@ import {
|
|
|
33
33
|
} from "./chunk-3WCASNQZ.js";
|
|
34
34
|
|
|
35
35
|
// src/connectors/index.ts
|
|
36
|
-
import
|
|
37
|
-
import
|
|
38
|
-
import
|
|
36
|
+
import fs4 from "fs";
|
|
37
|
+
import path4 from "path";
|
|
38
|
+
import os2 from "os";
|
|
39
39
|
import { createRequire } from "module";
|
|
40
40
|
import { fileURLToPath } from "url";
|
|
41
41
|
|
|
@@ -398,9 +398,265 @@ function assertConfigComponentsNotSymlinked(cfgPath) {
|
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
400
|
|
|
401
|
-
// src/connectors/
|
|
401
|
+
// src/connectors/droid-mcp.ts
|
|
402
402
|
import fs2 from "fs";
|
|
403
403
|
import path2 from "path";
|
|
404
|
+
import os from "os";
|
|
405
|
+
var DROID_CONNECTOR_MANIFEST = {
|
|
406
|
+
id: "droid",
|
|
407
|
+
name: "Factory Droid",
|
|
408
|
+
version: "1.0.0",
|
|
409
|
+
description: "Factory Droid \u2014 AI software engineering agent; memory via HTTP MCP with bearer auth",
|
|
410
|
+
capabilities: {
|
|
411
|
+
observe: true,
|
|
412
|
+
recall: true,
|
|
413
|
+
store: true,
|
|
414
|
+
search: true,
|
|
415
|
+
entities: true,
|
|
416
|
+
realtimeSync: true,
|
|
417
|
+
batch: true,
|
|
418
|
+
maxBudgetChars: 32e3,
|
|
419
|
+
connectionType: "mcp"
|
|
420
|
+
},
|
|
421
|
+
configSchema: {
|
|
422
|
+
mcpServerUrl: "URL of the MCP Remnic: server (default: http://127.0.0.1:4318/mcp)",
|
|
423
|
+
namespace: "Optional namespace"
|
|
424
|
+
},
|
|
425
|
+
homepage: "https://factory.ai",
|
|
426
|
+
author: "Remnic",
|
|
427
|
+
tags: ["official", "ai", "droid", "factory"],
|
|
428
|
+
requiresToken: true
|
|
429
|
+
};
|
|
430
|
+
function droidInstallStep(authToken, resolvedConfig, requiresToken, tokenEntry, priorTokenStore, saveTokenStoreFn) {
|
|
431
|
+
try {
|
|
432
|
+
const result = writeDroidMcpEntry(authToken, resolvedConfig);
|
|
433
|
+
return { ok: true, rollback: result.rollback, mcpPath: result.mcpPath };
|
|
434
|
+
} catch (droidErr) {
|
|
435
|
+
const errMsg = droidErr instanceof Error ? droidErr.message : String(droidErr);
|
|
436
|
+
let tokenSuffix = "";
|
|
437
|
+
if (requiresToken && tokenEntry !== null && priorTokenStore !== null) {
|
|
438
|
+
try {
|
|
439
|
+
saveTokenStoreFn(priorTokenStore);
|
|
440
|
+
tokenSuffix = " Token has been rolled back.";
|
|
441
|
+
} catch (e) {
|
|
442
|
+
tokenSuffix = ` Token rollback FAILED (${e instanceof Error ? e.message : String(e)}) \u2014 manually inspect ~/.remnic/tokens.json and reinstall.`;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
ok: false,
|
|
447
|
+
errorMessage: `Droid install aborted: ~/.factory/mcp.json write failed \u2014 ${errMsg}.${tokenSuffix} Resolve the write permission issue on ~/.factory/, then reinstall.`
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
function readDroidMcpProvenance(configPath) {
|
|
452
|
+
let mcpConfigPath = null;
|
|
453
|
+
let registryParseFailed = false;
|
|
454
|
+
if (!fs2.existsSync(configPath)) {
|
|
455
|
+
return { mcpConfigPath: null, registryParseFailed: false };
|
|
456
|
+
}
|
|
457
|
+
try {
|
|
458
|
+
const stored = JSON.parse(fs2.readFileSync(configPath, "utf8"));
|
|
459
|
+
if (typeof stored.factoryMcpPath === "string" && stored.factoryMcpPath.length > 0) {
|
|
460
|
+
mcpConfigPath = stored.factoryMcpPath;
|
|
461
|
+
}
|
|
462
|
+
} catch {
|
|
463
|
+
registryParseFailed = true;
|
|
464
|
+
}
|
|
465
|
+
if (mcpConfigPath === null && !registryParseFailed) {
|
|
466
|
+
try {
|
|
467
|
+
mcpConfigPath = resolveFactoryMcpPath();
|
|
468
|
+
} catch {
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return { mcpConfigPath, registryParseFailed };
|
|
472
|
+
}
|
|
473
|
+
function writeSecretFileSync(filePath, data) {
|
|
474
|
+
const dir = path2.dirname(filePath);
|
|
475
|
+
const base = path2.basename(filePath);
|
|
476
|
+
const tmpPath = path2.join(
|
|
477
|
+
dir,
|
|
478
|
+
`.${base}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`
|
|
479
|
+
);
|
|
480
|
+
let wroteTemp = false;
|
|
481
|
+
try {
|
|
482
|
+
fs2.writeFileSync(tmpPath, data, { mode: 384, flag: "wx" });
|
|
483
|
+
wroteTemp = true;
|
|
484
|
+
try {
|
|
485
|
+
fs2.chmodSync(tmpPath, 384);
|
|
486
|
+
} catch {
|
|
487
|
+
}
|
|
488
|
+
fs2.renameSync(tmpPath, filePath);
|
|
489
|
+
try {
|
|
490
|
+
fs2.chmodSync(filePath, 384);
|
|
491
|
+
} catch {
|
|
492
|
+
}
|
|
493
|
+
} catch (err) {
|
|
494
|
+
if (wroteTemp) {
|
|
495
|
+
try {
|
|
496
|
+
fs2.unlinkSync(tmpPath);
|
|
497
|
+
} catch {
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
throw err;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
function writeDroidMcpEntry(authToken, resolvedConfig) {
|
|
504
|
+
const mcpPath = resolveFactoryMcpPath();
|
|
505
|
+
const priorContent = readFactoryMcpIfExists(mcpPath);
|
|
506
|
+
const mcpConfig = upsertFactoryMcpRemnicEntry(priorContent, authToken, resolvedConfig);
|
|
507
|
+
fs2.mkdirSync(path2.dirname(mcpPath), { recursive: true });
|
|
508
|
+
const rollback = () => {
|
|
509
|
+
try {
|
|
510
|
+
if (priorContent === null) {
|
|
511
|
+
if (fs2.existsSync(mcpPath)) fs2.unlinkSync(mcpPath);
|
|
512
|
+
} else {
|
|
513
|
+
writeSecretFileSync(mcpPath, priorContent);
|
|
514
|
+
}
|
|
515
|
+
} catch {
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
try {
|
|
519
|
+
writeSecretFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2));
|
|
520
|
+
} catch (writeErr) {
|
|
521
|
+
try {
|
|
522
|
+
rollback();
|
|
523
|
+
} catch {
|
|
524
|
+
}
|
|
525
|
+
throw writeErr;
|
|
526
|
+
}
|
|
527
|
+
return { mcpPath, rollback };
|
|
528
|
+
}
|
|
529
|
+
function removeDroidMcpEntry(mcpPath) {
|
|
530
|
+
const expectedSuffix = path2.join(".factory", "mcp.json");
|
|
531
|
+
if (!path2.isAbsolute(mcpPath) || !mcpPath.endsWith(expectedSuffix)) {
|
|
532
|
+
throw new Error(
|
|
533
|
+
`MCP config path ${JSON.stringify(mcpPath)} failed safety validation (must be absolute and end with "${expectedSuffix}"). Refusing to modify \u2014 remove the "remnic" entry manually if it exists.`
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
const priorContent = readFactoryMcpIfExists(mcpPath);
|
|
537
|
+
if (priorContent === null) return null;
|
|
538
|
+
const updated = removeFactoryMcpRemnicEntry(priorContent);
|
|
539
|
+
if (updated === null) return null;
|
|
540
|
+
writeSecretFileSync(mcpPath, JSON.stringify(updated, null, 2));
|
|
541
|
+
return `Removed remnic entry from Droid MCP config: ${mcpPath}`;
|
|
542
|
+
}
|
|
543
|
+
function droidMcpDoctorCheck(savedPath) {
|
|
544
|
+
const mcpPath = savedPath ?? resolveFactoryMcpPath();
|
|
545
|
+
if (savedPath !== void 0) {
|
|
546
|
+
const expectedSuffix = path2.join(".factory", "mcp.json");
|
|
547
|
+
if (!path2.isAbsolute(savedPath) || !savedPath.endsWith(expectedSuffix)) {
|
|
548
|
+
return { name: "Droid MCP config", ok: false, detail: `Unsafe path in droid.json: ${savedPath}` };
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
try {
|
|
552
|
+
const raw = fs2.readFileSync(mcpPath, "utf8");
|
|
553
|
+
const parsed = JSON.parse(raw);
|
|
554
|
+
const servers = parsed.mcpServers;
|
|
555
|
+
if (typeof servers !== "object" || servers === null || !("remnic" in servers)) {
|
|
556
|
+
return { name: "Droid MCP config", ok: false, detail: `remnic entry missing in ${mcpPath} \u2014 run \`remnic connectors install droid\`` };
|
|
557
|
+
}
|
|
558
|
+
const remnic = servers.remnic;
|
|
559
|
+
if (remnic.type !== "http" || typeof remnic.url !== "string") {
|
|
560
|
+
return { name: "Droid MCP config", ok: false, detail: `remnic entry malformed in ${mcpPath}` };
|
|
561
|
+
}
|
|
562
|
+
const headers = remnic.headers;
|
|
563
|
+
const hasAuth = headers && typeof headers["Authorization"] === "string" && headers["Authorization"].startsWith("Bearer ");
|
|
564
|
+
return {
|
|
565
|
+
name: "Droid MCP config",
|
|
566
|
+
ok: !!hasAuth,
|
|
567
|
+
detail: hasAuth ? `remnic entry present in ${mcpPath}` : `remnic entry missing Authorization header in ${mcpPath} \u2014 run \`remnic connectors install droid\``
|
|
568
|
+
};
|
|
569
|
+
} catch {
|
|
570
|
+
return { name: "Droid MCP config", ok: false, detail: `Cannot read ${mcpPath} \u2014 run \`remnic connectors install droid\`` };
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
function resolveFactoryMcpPath() {
|
|
574
|
+
const envHome = readEnvVar("HOME");
|
|
575
|
+
const home = envHome && envHome.length > 0 ? envHome : os.homedir();
|
|
576
|
+
return path2.resolve(home, ".factory", "mcp.json");
|
|
577
|
+
}
|
|
578
|
+
function readFactoryMcpIfExists(mcpPath) {
|
|
579
|
+
try {
|
|
580
|
+
if (!fs2.existsSync(mcpPath)) return null;
|
|
581
|
+
return fs2.readFileSync(mcpPath, "utf8");
|
|
582
|
+
} catch {
|
|
583
|
+
return null;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
var REMNIC_DEFAULT_MCP_URL = "http://127.0.0.1:4318/mcp";
|
|
587
|
+
function upsertFactoryMcpRemnicEntry(priorContent, authToken, resolvedConfig) {
|
|
588
|
+
let config;
|
|
589
|
+
if (priorContent !== null) {
|
|
590
|
+
try {
|
|
591
|
+
const parsed = JSON.parse(priorContent);
|
|
592
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
593
|
+
config = parsed;
|
|
594
|
+
} else {
|
|
595
|
+
console.warn("[remnic/connectors] ~/.factory/mcp.json contained non-object JSON; starting fresh.");
|
|
596
|
+
config = {};
|
|
597
|
+
}
|
|
598
|
+
} catch {
|
|
599
|
+
throw new Error(
|
|
600
|
+
"~/.factory/mcp.json contains malformed JSON and cannot be parsed. Fix the file manually before reinstalling, or use --force to overwrite (this will lose existing MCP server entries)."
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
} else {
|
|
604
|
+
config = {};
|
|
605
|
+
}
|
|
606
|
+
if (typeof config.mcpServers !== "object" || config.mcpServers === null || Array.isArray(config.mcpServers)) {
|
|
607
|
+
config.mcpServers = {};
|
|
608
|
+
}
|
|
609
|
+
const servers = config.mcpServers;
|
|
610
|
+
const mcpUrl = typeof resolvedConfig.mcpServerUrl === "string" && resolvedConfig.mcpServerUrl.length > 0 ? resolvedConfig.mcpServerUrl : REMNIC_DEFAULT_MCP_URL;
|
|
611
|
+
const remnicEntry = { type: "http", url: mcpUrl };
|
|
612
|
+
const REMNIC_MANAGED_HEADERS = /* @__PURE__ */ new Set(["Authorization", "X-Engram-Namespace"]);
|
|
613
|
+
const headers = {};
|
|
614
|
+
if (typeof servers.remnic === "object" && servers.remnic !== null && typeof servers.remnic.headers === "object" && servers.remnic.headers !== null) {
|
|
615
|
+
const priorHeaders = servers.remnic.headers;
|
|
616
|
+
for (const [key, value] of Object.entries(priorHeaders)) {
|
|
617
|
+
if (!REMNIC_MANAGED_HEADERS.has(key) && typeof value === "string") {
|
|
618
|
+
headers[key] = value;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (authToken && authToken.length > 0) {
|
|
623
|
+
headers["Authorization"] = `Bearer ${authToken}`;
|
|
624
|
+
}
|
|
625
|
+
const namespace = typeof resolvedConfig.namespace === "string" && resolvedConfig.namespace.length > 0 ? resolvedConfig.namespace : void 0;
|
|
626
|
+
if (namespace) {
|
|
627
|
+
headers["X-Engram-Namespace"] = namespace;
|
|
628
|
+
}
|
|
629
|
+
if (Object.keys(headers).length > 0) {
|
|
630
|
+
remnicEntry.headers = headers;
|
|
631
|
+
}
|
|
632
|
+
servers.remnic = remnicEntry;
|
|
633
|
+
return config;
|
|
634
|
+
}
|
|
635
|
+
function removeFactoryMcpRemnicEntry(priorContent) {
|
|
636
|
+
let config;
|
|
637
|
+
try {
|
|
638
|
+
const parsed = JSON.parse(priorContent);
|
|
639
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
640
|
+
return null;
|
|
641
|
+
}
|
|
642
|
+
config = parsed;
|
|
643
|
+
} catch {
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
if (typeof config.mcpServers !== "object" || config.mcpServers === null) {
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
const servers = config.mcpServers;
|
|
650
|
+
if (!("remnic" in servers)) {
|
|
651
|
+
return null;
|
|
652
|
+
}
|
|
653
|
+
delete servers.remnic;
|
|
654
|
+
return config;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// src/connectors/codex-marketplace.ts
|
|
658
|
+
import fs3 from "fs";
|
|
659
|
+
import path3 from "path";
|
|
404
660
|
var MARKETPLACE_SCHEMA_VERSION = 1;
|
|
405
661
|
var MARKETPLACE_MANIFEST_FILENAME = "marketplace.json";
|
|
406
662
|
var VALID_INSTALL_TYPES = /* @__PURE__ */ new Set(["github", "git", "local", "url"]);
|
|
@@ -502,12 +758,12 @@ async function writeMarketplaceManifest(outputDir, manifest) {
|
|
|
502
758
|
`Refusing to write invalid manifest: ${validation.errors.join("; ")}`
|
|
503
759
|
);
|
|
504
760
|
}
|
|
505
|
-
|
|
506
|
-
const destPath =
|
|
761
|
+
fs3.mkdirSync(outputDir, { recursive: true });
|
|
762
|
+
const destPath = path3.join(outputDir, MARKETPLACE_MANIFEST_FILENAME);
|
|
507
763
|
const tmpPath = `${destPath}.tmp.${process.pid}`;
|
|
508
764
|
const content = JSON.stringify(manifest, null, 2) + "\n";
|
|
509
|
-
|
|
510
|
-
|
|
765
|
+
fs3.writeFileSync(tmpPath, content);
|
|
766
|
+
fs3.renameSync(tmpPath, destPath);
|
|
511
767
|
}
|
|
512
768
|
async function installFromMarketplace(source, sourceType, config, logger) {
|
|
513
769
|
const _log = logger ?? {
|
|
@@ -567,12 +823,12 @@ async function resolveManifest(source, sourceType, logger) {
|
|
|
567
823
|
}
|
|
568
824
|
}
|
|
569
825
|
function resolveLocal(dirPath, logger) {
|
|
570
|
-
const manifestPath =
|
|
571
|
-
if (!
|
|
826
|
+
const manifestPath = path3.join(dirPath, MARKETPLACE_MANIFEST_FILENAME);
|
|
827
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
572
828
|
throw new Error(`marketplace.json not found at ${manifestPath}`);
|
|
573
829
|
}
|
|
574
830
|
logger.debug?.(`reading local marketplace manifest: ${manifestPath}`);
|
|
575
|
-
const raw =
|
|
831
|
+
const raw = fs3.readFileSync(manifestPath, "utf-8");
|
|
576
832
|
let parsed;
|
|
577
833
|
try {
|
|
578
834
|
parsed = JSON.parse(raw);
|
|
@@ -624,15 +880,15 @@ async function resolveGit(gitUrl, logger) {
|
|
|
624
880
|
}
|
|
625
881
|
function readPackageVersion() {
|
|
626
882
|
const candidates = [
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
883
|
+
path3.resolve(import.meta.dirname ?? ".", "../../../.."),
|
|
884
|
+
path3.resolve(import.meta.dirname ?? ".", "../../../../.."),
|
|
885
|
+
path3.resolve(import.meta.dirname ?? ".", "..")
|
|
630
886
|
];
|
|
631
887
|
for (const candidate of candidates) {
|
|
632
|
-
const pkgPath =
|
|
888
|
+
const pkgPath = path3.join(candidate, "package.json");
|
|
633
889
|
try {
|
|
634
|
-
if (!
|
|
635
|
-
const raw =
|
|
890
|
+
if (!fs3.existsSync(pkgPath)) continue;
|
|
891
|
+
const raw = fs3.readFileSync(pkgPath, "utf-8");
|
|
636
892
|
const parsed = JSON.parse(raw);
|
|
637
893
|
if (typeof parsed === "object" && parsed !== null && typeof parsed.version === "string") {
|
|
638
894
|
return parsed.version;
|
|
@@ -991,7 +1247,8 @@ var BUILTIN_CONNECTORS = [
|
|
|
991
1247
|
author: "Remnic",
|
|
992
1248
|
tags: ["official", "python", "hermes"],
|
|
993
1249
|
requiresToken: true
|
|
994
|
-
}
|
|
1250
|
+
},
|
|
1251
|
+
DROID_CONNECTOR_MANIFEST
|
|
995
1252
|
];
|
|
996
1253
|
var CONNECTOR_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
997
1254
|
function isValidConnectorId(connectorId) {
|
|
@@ -1002,7 +1259,7 @@ function isConnectorManifest(value) {
|
|
|
1002
1259
|
}
|
|
1003
1260
|
function loadRegistry() {
|
|
1004
1261
|
const regPath = getRegistryPath();
|
|
1005
|
-
if (!
|
|
1262
|
+
if (!fs4.existsSync(regPath)) {
|
|
1006
1263
|
const registry = {
|
|
1007
1264
|
connectors: BUILTIN_CONNECTORS,
|
|
1008
1265
|
registryPath: regPath
|
|
@@ -1011,7 +1268,7 @@ function loadRegistry() {
|
|
|
1011
1268
|
return registry;
|
|
1012
1269
|
}
|
|
1013
1270
|
try {
|
|
1014
|
-
const raw =
|
|
1271
|
+
const raw = fs4.readFileSync(regPath, "utf8");
|
|
1015
1272
|
const parsed = JSON.parse(raw);
|
|
1016
1273
|
if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.connectors)) {
|
|
1017
1274
|
throw new Error("invalid registry schema");
|
|
@@ -1034,19 +1291,19 @@ function loadRegistry() {
|
|
|
1034
1291
|
}
|
|
1035
1292
|
function saveRegistry(registry) {
|
|
1036
1293
|
const regPath = registry.registryPath;
|
|
1037
|
-
|
|
1038
|
-
|
|
1294
|
+
fs4.mkdirSync(path4.dirname(regPath), { recursive: true });
|
|
1295
|
+
fs4.writeFileSync(regPath, JSON.stringify({ connectors: registry.connectors }, null, 2));
|
|
1039
1296
|
}
|
|
1040
1297
|
function listConnectors() {
|
|
1041
1298
|
const registry = loadRegistry();
|
|
1042
1299
|
const connectorsDir = getConnectorsDir();
|
|
1043
1300
|
const installedIds = /* @__PURE__ */ new Set();
|
|
1044
|
-
if (
|
|
1045
|
-
for (const entry of
|
|
1301
|
+
if (fs4.existsSync(connectorsDir)) {
|
|
1302
|
+
for (const entry of fs4.readdirSync(connectorsDir)) {
|
|
1046
1303
|
if (entry.endsWith(".json")) {
|
|
1047
1304
|
try {
|
|
1048
1305
|
const config = JSON.parse(
|
|
1049
|
-
|
|
1306
|
+
fs4.readFileSync(path4.join(connectorsDir, entry), "utf8")
|
|
1050
1307
|
);
|
|
1051
1308
|
if (isValidConnectorId(config.connectorId)) {
|
|
1052
1309
|
installedIds.add(config.connectorId);
|
|
@@ -1062,9 +1319,9 @@ function listConnectors() {
|
|
|
1062
1319
|
}));
|
|
1063
1320
|
const installed = [];
|
|
1064
1321
|
for (const id of installedIds) {
|
|
1065
|
-
const configPath =
|
|
1322
|
+
const configPath = path4.join(connectorsDir, `${id}.json`);
|
|
1066
1323
|
try {
|
|
1067
|
-
const raw = JSON.parse(
|
|
1324
|
+
const raw = JSON.parse(fs4.readFileSync(configPath, "utf8"));
|
|
1068
1325
|
const { token: _redacted, ...config } = raw;
|
|
1069
1326
|
installed.push({
|
|
1070
1327
|
connectorId: id,
|
|
@@ -1088,9 +1345,9 @@ function getConnectorToken(connectorId) {
|
|
|
1088
1345
|
}
|
|
1089
1346
|
}
|
|
1090
1347
|
function readSavedConnectorConfig(configPath) {
|
|
1091
|
-
if (!
|
|
1348
|
+
if (!fs4.existsSync(configPath)) return {};
|
|
1092
1349
|
try {
|
|
1093
|
-
const parsed = JSON.parse(
|
|
1350
|
+
const parsed = JSON.parse(fs4.readFileSync(configPath, "utf8"));
|
|
1094
1351
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
1095
1352
|
const {
|
|
1096
1353
|
connectorId: _connectorId,
|
|
@@ -1144,10 +1401,10 @@ function installConnector(options) {
|
|
|
1144
1401
|
let backfillNote = "";
|
|
1145
1402
|
if (options.connectorId === "hermes") {
|
|
1146
1403
|
try {
|
|
1147
|
-
const hermesJsonPath =
|
|
1404
|
+
const hermesJsonPath = path4.join(getConnectorsDir(), "hermes.json");
|
|
1148
1405
|
let parsed = null;
|
|
1149
1406
|
try {
|
|
1150
|
-
const parsedRaw = JSON.parse(
|
|
1407
|
+
const parsedRaw = JSON.parse(fs4.readFileSync(hermesJsonPath, "utf8"));
|
|
1151
1408
|
if (parsedRaw !== null && typeof parsedRaw === "object" && !Array.isArray(parsedRaw)) {
|
|
1152
1409
|
parsed = parsedRaw;
|
|
1153
1410
|
}
|
|
@@ -1163,7 +1420,7 @@ function installConnector(options) {
|
|
|
1163
1420
|
currentConfigPath = hermesConfigPath(
|
|
1164
1421
|
typeof profileRaw === "string" && profileRaw.length > 0 ? profileRaw : "default"
|
|
1165
1422
|
);
|
|
1166
|
-
activeConfigHasBlock =
|
|
1423
|
+
activeConfigHasBlock = fs4.existsSync(currentConfigPath) && /^remnic:/m.test(fs4.readFileSync(currentConfigPath, "utf8"));
|
|
1167
1424
|
} catch (resolveErr) {
|
|
1168
1425
|
configResolutionError = resolveErr instanceof Error ? resolveErr.message : String(resolveErr);
|
|
1169
1426
|
activeConfigHasBlock = false;
|
|
@@ -1226,7 +1483,7 @@ function installConnector(options) {
|
|
|
1226
1483
|
parsed.pluginShimPath = outcome.persistPath;
|
|
1227
1484
|
}
|
|
1228
1485
|
try {
|
|
1229
|
-
|
|
1486
|
+
writeSecretFileSync2(hermesJsonPath, JSON.stringify(parsed, null, 2));
|
|
1230
1487
|
} catch (persistErr) {
|
|
1231
1488
|
const rollbackFailures = [];
|
|
1232
1489
|
if (outcome.materializedAt !== null && outcome.createdNew && (priorPersisted === null || !sameShimTarget(outcome.materializedAt, priorPersisted))) {
|
|
@@ -1267,8 +1524,8 @@ function installConnector(options) {
|
|
|
1267
1524
|
};
|
|
1268
1525
|
}
|
|
1269
1526
|
const configDir = getConnectorsDir();
|
|
1270
|
-
|
|
1271
|
-
const configPath =
|
|
1527
|
+
fs4.mkdirSync(configDir, { recursive: true });
|
|
1528
|
+
const configPath = path4.join(configDir, `${options.connectorId}.json`);
|
|
1272
1529
|
const savedConnectorConfig = existing ? readSavedConnectorConfig(configPath) : {};
|
|
1273
1530
|
let hermesSavedProfile;
|
|
1274
1531
|
let hermesSavedHost;
|
|
@@ -1279,9 +1536,9 @@ function installConnector(options) {
|
|
|
1279
1536
|
let hermesResolvedPort;
|
|
1280
1537
|
let hermesResolvedAllowInsecureHttp = false;
|
|
1281
1538
|
if (options.connectorId === "hermes") {
|
|
1282
|
-
if (
|
|
1539
|
+
if (fs4.existsSync(configPath)) {
|
|
1283
1540
|
try {
|
|
1284
|
-
const prev = JSON.parse(
|
|
1541
|
+
const prev = JSON.parse(fs4.readFileSync(configPath, "utf8"));
|
|
1285
1542
|
if (prev?.profile != null) {
|
|
1286
1543
|
try {
|
|
1287
1544
|
hermesSavedProfile = sanitizeHermesProfile(String(prev.profile));
|
|
@@ -1428,7 +1685,7 @@ function installConnector(options) {
|
|
|
1428
1685
|
const envHermesHome = readEnvVar("HERMES_HOME");
|
|
1429
1686
|
if (typeof envHermesHome === "string" && envHermesHome.trim().length > 0) {
|
|
1430
1687
|
try {
|
|
1431
|
-
|
|
1688
|
+
fs4.mkdirSync(path4.dirname(hermesConfigPath(hermesProfile)), { recursive: true });
|
|
1432
1689
|
} catch {
|
|
1433
1690
|
}
|
|
1434
1691
|
}
|
|
@@ -1474,9 +1731,9 @@ function installConnector(options) {
|
|
|
1474
1731
|
let yamlRollbackErrMsg = "";
|
|
1475
1732
|
try {
|
|
1476
1733
|
if (yamlResult.priorContent === null) {
|
|
1477
|
-
|
|
1734
|
+
fs4.unlinkSync(yamlResult.configPath);
|
|
1478
1735
|
} else if (typeof yamlResult.priorContent === "string") {
|
|
1479
|
-
|
|
1736
|
+
writeSecretFileSync2(yamlResult.configPath, yamlResult.priorContent);
|
|
1480
1737
|
}
|
|
1481
1738
|
} catch (yamlRestoreErr) {
|
|
1482
1739
|
yamlRolledBack = false;
|
|
@@ -1549,7 +1806,7 @@ function installConnector(options) {
|
|
|
1549
1806
|
let fallbackDetail = "";
|
|
1550
1807
|
if (isPlausibleHermesConfigPath(priorConfigPath)) {
|
|
1551
1808
|
try {
|
|
1552
|
-
const beforeRefresh =
|
|
1809
|
+
const beforeRefresh = fs4.readFileSync(priorConfigPath, "utf8");
|
|
1553
1810
|
const refresh = upsertHermesConfigAt(priorConfigPath, {
|
|
1554
1811
|
host: hermesHost,
|
|
1555
1812
|
port: hermesPort,
|
|
@@ -1596,7 +1853,7 @@ function installConnector(options) {
|
|
|
1596
1853
|
continue;
|
|
1597
1854
|
}
|
|
1598
1855
|
try {
|
|
1599
|
-
const beforeCleanup =
|
|
1856
|
+
const beforeCleanup = fs4.readFileSync(candidate, "utf8");
|
|
1600
1857
|
const cleanup = removeHermesConfigFile(candidate);
|
|
1601
1858
|
if (cleanup.updated) {
|
|
1602
1859
|
hermesPriorConfigMutations.push({ mutatedPath: candidate, priorContent: beforeCleanup });
|
|
@@ -1619,7 +1876,7 @@ function installConnector(options) {
|
|
|
1619
1876
|
}
|
|
1620
1877
|
let blockSurvives = false;
|
|
1621
1878
|
try {
|
|
1622
|
-
blockSurvives = /^remnic:/m.test(
|
|
1879
|
+
blockSurvives = /^remnic:/m.test(fs4.readFileSync(candidate, "utf8"));
|
|
1623
1880
|
} catch {
|
|
1624
1881
|
blockSurvives = false;
|
|
1625
1882
|
}
|
|
@@ -1635,7 +1892,7 @@ function installConnector(options) {
|
|
|
1635
1892
|
delete resolvedConfig.priorHermesConfigPath;
|
|
1636
1893
|
}
|
|
1637
1894
|
try {
|
|
1638
|
-
|
|
1895
|
+
writeSecretFileSync2(configPath, JSON.stringify(resolvedConfig, null, 2));
|
|
1639
1896
|
} catch (writeErr) {
|
|
1640
1897
|
let tokenRollbackFailed = false;
|
|
1641
1898
|
let tokenRollbackMsg = "token store restored to pre-install snapshot";
|
|
@@ -1651,7 +1908,7 @@ function installConnector(options) {
|
|
|
1651
1908
|
let unlinkSucceeded = false;
|
|
1652
1909
|
let unlinkErr;
|
|
1653
1910
|
try {
|
|
1654
|
-
|
|
1911
|
+
fs4.unlinkSync(yamlResult.configPath);
|
|
1655
1912
|
unlinkSucceeded = true;
|
|
1656
1913
|
} catch (err) {
|
|
1657
1914
|
unlinkErr = err;
|
|
@@ -1663,7 +1920,7 @@ function installConnector(options) {
|
|
|
1663
1920
|
yamlRollbackMsg = `config.yaml rollback failed: could not remove newly-created file \u2014 ${unlinkMsg}`;
|
|
1664
1921
|
}
|
|
1665
1922
|
} else if (typeof yamlResult.priorContent === "string") {
|
|
1666
|
-
|
|
1923
|
+
writeSecretFileSync2(yamlResult.configPath, yamlResult.priorContent);
|
|
1667
1924
|
yamlRollbackMsg = "config.yaml restored to prior content";
|
|
1668
1925
|
}
|
|
1669
1926
|
} catch (yamlRollbackErr) {
|
|
@@ -1710,7 +1967,7 @@ function installConnector(options) {
|
|
|
1710
1967
|
const priorConfigRollbackFailures = [];
|
|
1711
1968
|
for (const mutation of [...hermesPriorConfigMutations].reverse()) {
|
|
1712
1969
|
try {
|
|
1713
|
-
|
|
1970
|
+
writeSecretFileSync2(mutation.mutatedPath, mutation.priorContent);
|
|
1714
1971
|
} catch (restoreErr) {
|
|
1715
1972
|
priorConfigRollbackFailures.push(
|
|
1716
1973
|
`could not restore ${mutation.mutatedPath} (${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)})`
|
|
@@ -1839,9 +2096,9 @@ function installConnector(options) {
|
|
|
1839
2096
|
if (options.connectorId === "weclone") {
|
|
1840
2097
|
try {
|
|
1841
2098
|
let proxyConfigPath = null;
|
|
1842
|
-
if (existing &&
|
|
2099
|
+
if (existing && fs4.existsSync(configPath)) {
|
|
1843
2100
|
try {
|
|
1844
|
-
const savedRegistryConfig = JSON.parse(
|
|
2101
|
+
const savedRegistryConfig = JSON.parse(fs4.readFileSync(configPath, "utf8"));
|
|
1845
2102
|
if (typeof savedRegistryConfig.proxyConfigPath === "string" && savedRegistryConfig.proxyConfigPath.length > 0) {
|
|
1846
2103
|
proxyConfigPath = savedRegistryConfig.proxyConfigPath;
|
|
1847
2104
|
}
|
|
@@ -1857,21 +2114,21 @@ function installConnector(options) {
|
|
|
1857
2114
|
priorConfig: prior ? safeParseJson(prior) : null,
|
|
1858
2115
|
authToken: tokenEntry?.token
|
|
1859
2116
|
});
|
|
1860
|
-
|
|
2117
|
+
fs4.mkdirSync(path4.dirname(proxyConfigPath), { recursive: true });
|
|
1861
2118
|
weCloneProxyHandleRollback = () => {
|
|
1862
2119
|
try {
|
|
1863
2120
|
if (prior === null) {
|
|
1864
|
-
if (
|
|
1865
|
-
|
|
2121
|
+
if (fs4.existsSync(proxyConfigPath)) {
|
|
2122
|
+
fs4.unlinkSync(proxyConfigPath);
|
|
1866
2123
|
}
|
|
1867
2124
|
} else {
|
|
1868
|
-
|
|
2125
|
+
writeSecretFileSync2(proxyConfigPath, prior);
|
|
1869
2126
|
}
|
|
1870
2127
|
} catch {
|
|
1871
2128
|
}
|
|
1872
2129
|
};
|
|
1873
2130
|
try {
|
|
1874
|
-
|
|
2131
|
+
writeSecretFileSync2(
|
|
1875
2132
|
proxyConfigPath,
|
|
1876
2133
|
JSON.stringify(proxyConfig, null, 2)
|
|
1877
2134
|
);
|
|
@@ -1908,6 +2165,22 @@ function installConnector(options) {
|
|
|
1908
2165
|
};
|
|
1909
2166
|
}
|
|
1910
2167
|
}
|
|
2168
|
+
let droidMcpRollback = null;
|
|
2169
|
+
if (options.connectorId === "droid") {
|
|
2170
|
+
const stepResult = droidInstallStep(
|
|
2171
|
+
tokenEntry?.token,
|
|
2172
|
+
resolvedConfig,
|
|
2173
|
+
manifest.requiresToken ?? false,
|
|
2174
|
+
tokenEntry,
|
|
2175
|
+
nonHermesPriorTokenStore,
|
|
2176
|
+
saveTokenStore
|
|
2177
|
+
);
|
|
2178
|
+
if (!stepResult.ok) {
|
|
2179
|
+
return { connectorId: options.connectorId, status: "error", message: stepResult.errorMessage };
|
|
2180
|
+
}
|
|
2181
|
+
droidMcpRollback = stepResult.rollback;
|
|
2182
|
+
resolvedConfig.factoryMcpPath = stepResult.mcpPath;
|
|
2183
|
+
}
|
|
1911
2184
|
const INTERNAL_KEYS_DENYLIST = [
|
|
1912
2185
|
"extensionSourceDir"
|
|
1913
2186
|
// test-only override for the plugin-codex source path
|
|
@@ -1916,7 +2189,7 @@ function installConnector(options) {
|
|
|
1916
2189
|
delete resolvedConfig[key];
|
|
1917
2190
|
}
|
|
1918
2191
|
try {
|
|
1919
|
-
|
|
2192
|
+
writeSecretFileSync2(configPath, JSON.stringify(resolvedConfig, null, 2));
|
|
1920
2193
|
} catch (writeErr) {
|
|
1921
2194
|
let configWriteTokenRolledBack = false;
|
|
1922
2195
|
let configWriteTokenRollbackMsg = "";
|
|
@@ -1944,6 +2217,12 @@ function installConnector(options) {
|
|
|
1944
2217
|
} catch {
|
|
1945
2218
|
}
|
|
1946
2219
|
}
|
|
2220
|
+
if (droidMcpRollback !== null) {
|
|
2221
|
+
try {
|
|
2222
|
+
droidMcpRollback();
|
|
2223
|
+
} catch {
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
1947
2226
|
const configWriteTokenSuffix = manifest.requiresToken && tokenEntry !== null ? configWriteTokenRolledBack ? " Token has been rolled back." : ` Token rollback FAILED (${configWriteTokenRollbackMsg}) \u2014 tokens.json may contain an orphaned entry. Manually inspect ~/.remnic/tokens.json and reinstall.` : "";
|
|
1948
2227
|
return {
|
|
1949
2228
|
connectorId: options.connectorId,
|
|
@@ -1972,13 +2251,13 @@ function removeConnector(connectorId) {
|
|
|
1972
2251
|
message: `Removal aborted: invalid connector ID ${JSON.stringify(connectorId)}. Connector IDs must match [A-Za-z0-9][A-Za-z0-9._-]*.`
|
|
1973
2252
|
};
|
|
1974
2253
|
}
|
|
1975
|
-
const configPath =
|
|
2254
|
+
const configPath = path4.join(configDir, `${connectorId}.json`);
|
|
1976
2255
|
let codexHomeOverride = null;
|
|
1977
2256
|
let savedInstallExtension = void 0;
|
|
1978
2257
|
let configParsed = false;
|
|
1979
|
-
if (connectorId === "codex-cli" &&
|
|
2258
|
+
if (connectorId === "codex-cli" && fs4.existsSync(configPath)) {
|
|
1980
2259
|
try {
|
|
1981
|
-
const parsed = JSON.parse(
|
|
2260
|
+
const parsed = JSON.parse(fs4.readFileSync(configPath, "utf8"));
|
|
1982
2261
|
configParsed = true;
|
|
1983
2262
|
if (typeof parsed.codexHome === "string" && parsed.codexHome.length > 0) {
|
|
1984
2263
|
codexHomeOverride = parsed.codexHome;
|
|
@@ -1997,9 +2276,9 @@ function removeConnector(connectorId) {
|
|
|
1997
2276
|
let savedHermesConfigPath = null;
|
|
1998
2277
|
const savedPriorHermesConfigPaths = [];
|
|
1999
2278
|
const savedPriorHermesShimPaths = [];
|
|
2000
|
-
if (connectorId === "hermes" &&
|
|
2279
|
+
if (connectorId === "hermes" && fs4.existsSync(configPath)) {
|
|
2001
2280
|
try {
|
|
2002
|
-
const parsedRaw = JSON.parse(
|
|
2281
|
+
const parsedRaw = JSON.parse(fs4.readFileSync(configPath, "utf8"));
|
|
2003
2282
|
if (parsedRaw === null || typeof parsedRaw !== "object" || Array.isArray(parsedRaw)) {
|
|
2004
2283
|
throw new Error("hermes.json is not a JSON object");
|
|
2005
2284
|
}
|
|
@@ -2036,7 +2315,7 @@ function removeConnector(connectorId) {
|
|
|
2036
2315
|
};
|
|
2037
2316
|
}
|
|
2038
2317
|
}
|
|
2039
|
-
if (!
|
|
2318
|
+
if (!fs4.existsSync(configPath)) {
|
|
2040
2319
|
let staleTokenRevoked = false;
|
|
2041
2320
|
try {
|
|
2042
2321
|
staleTokenRevoked = revokeToken(connectorId);
|
|
@@ -2053,7 +2332,7 @@ function removeConnector(connectorId) {
|
|
|
2053
2332
|
let storedProfile = "default";
|
|
2054
2333
|
if (connectorId === "hermes") {
|
|
2055
2334
|
try {
|
|
2056
|
-
const stored = JSON.parse(
|
|
2335
|
+
const stored = JSON.parse(fs4.readFileSync(configPath, "utf8"));
|
|
2057
2336
|
if (typeof stored?.profile === "string") storedProfile = stored.profile;
|
|
2058
2337
|
} catch {
|
|
2059
2338
|
}
|
|
@@ -2062,7 +2341,7 @@ function removeConnector(connectorId) {
|
|
|
2062
2341
|
let weCloneRegistryParseFailed = false;
|
|
2063
2342
|
if (connectorId === "weclone") {
|
|
2064
2343
|
try {
|
|
2065
|
-
const stored = JSON.parse(
|
|
2344
|
+
const stored = JSON.parse(fs4.readFileSync(configPath, "utf8"));
|
|
2066
2345
|
if (typeof stored.proxyConfigPath === "string" && stored.proxyConfigPath.length > 0) {
|
|
2067
2346
|
weCloneProxyConfigPath = stored.proxyConfigPath;
|
|
2068
2347
|
}
|
|
@@ -2076,6 +2355,17 @@ function removeConnector(connectorId) {
|
|
|
2076
2355
|
}
|
|
2077
2356
|
}
|
|
2078
2357
|
}
|
|
2358
|
+
let droidMcpConfigPath = null;
|
|
2359
|
+
let droidRegistryParseFailed = false;
|
|
2360
|
+
if (connectorId === "droid") {
|
|
2361
|
+
const prov = readDroidMcpProvenance(configPath);
|
|
2362
|
+
droidMcpConfigPath = prov.mcpConfigPath;
|
|
2363
|
+
droidRegistryParseFailed = prov.registryParseFailed;
|
|
2364
|
+
}
|
|
2365
|
+
if (connectorId === "droid" && droidRegistryParseFailed) {
|
|
2366
|
+
console.warn(`[remnic/connectors] removeConnector: droid.json malformed \u2014 aborting. Fix or delete ${configPath} manually and retry.`);
|
|
2367
|
+
return { connectorId, configPath, message: "Removal aborted: droid.json is malformed. Registry config left in place.", status: "skipped", reason: "config-parse-failed" };
|
|
2368
|
+
}
|
|
2079
2369
|
if (connectorId === "weclone" && weCloneRegistryParseFailed) {
|
|
2080
2370
|
console.warn(
|
|
2081
2371
|
"[remnic/connectors] removeConnector: weclone.json is malformed \u2014 aborting removal to preserve provenance. Fix or delete " + configPath + " manually and retry."
|
|
@@ -2088,7 +2378,7 @@ function removeConnector(connectorId) {
|
|
|
2088
2378
|
reason: "config-parse-failed"
|
|
2089
2379
|
};
|
|
2090
2380
|
}
|
|
2091
|
-
if (connectorId === "codex-cli" &&
|
|
2381
|
+
if (connectorId === "codex-cli" && fs4.existsSync(configPath) && !configParsed) {
|
|
2092
2382
|
console.warn(
|
|
2093
2383
|
"[remnic/connectors] removeConnector: codex-cli.json is malformed \u2014 aborting removal to preserve provenance. Fix or delete " + configPath + " manually and retry."
|
|
2094
2384
|
);
|
|
@@ -2131,7 +2421,7 @@ function removeConnector(connectorId) {
|
|
|
2131
2421
|
for (const candidate of uniqueCandidates) {
|
|
2132
2422
|
let needsCleanup = false;
|
|
2133
2423
|
try {
|
|
2134
|
-
needsCleanup = /^remnic:/m.test(
|
|
2424
|
+
needsCleanup = /^remnic:/m.test(fs4.readFileSync(candidate, "utf8"));
|
|
2135
2425
|
} catch {
|
|
2136
2426
|
needsCleanup = false;
|
|
2137
2427
|
}
|
|
@@ -2145,8 +2435,8 @@ function removeConnector(connectorId) {
|
|
|
2145
2435
|
continue;
|
|
2146
2436
|
}
|
|
2147
2437
|
try {
|
|
2148
|
-
|
|
2149
|
-
|
|
2438
|
+
fs4.accessSync(candidate, fs4.constants.W_OK);
|
|
2439
|
+
fs4.accessSync(path4.dirname(candidate), fs4.constants.W_OK);
|
|
2150
2440
|
} catch {
|
|
2151
2441
|
blocked.push(`${candidate} (not writable)`);
|
|
2152
2442
|
}
|
|
@@ -2161,7 +2451,7 @@ function removeConnector(connectorId) {
|
|
|
2161
2451
|
}
|
|
2162
2452
|
}
|
|
2163
2453
|
try {
|
|
2164
|
-
|
|
2454
|
+
fs4.unlinkSync(configPath);
|
|
2165
2455
|
} catch (unlinkErr) {
|
|
2166
2456
|
const sanitizedErr = unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr);
|
|
2167
2457
|
return {
|
|
@@ -2187,14 +2477,14 @@ function removeConnector(connectorId) {
|
|
|
2187
2477
|
"WeClone proxy config cleanup skipped: no persisted path found in saved config (likely a legacy install predating proxyConfigPath provenance)."
|
|
2188
2478
|
);
|
|
2189
2479
|
} else {
|
|
2190
|
-
const expectedSuffix =
|
|
2191
|
-
const isSafePath =
|
|
2480
|
+
const expectedSuffix = path4.join("connectors", "weclone.json");
|
|
2481
|
+
const isSafePath = path4.isAbsolute(weCloneProxyConfigPath) && weCloneProxyConfigPath.endsWith(expectedSuffix);
|
|
2192
2482
|
if (!isSafePath) {
|
|
2193
2483
|
weCloneProxyDeleteFailed = `Proxy config path ${JSON.stringify(weCloneProxyConfigPath)} failed safety validation (must be absolute and end with "${expectedSuffix}"). Refusing to delete \u2014 remove the file manually if it exists.`;
|
|
2194
2484
|
} else {
|
|
2195
2485
|
try {
|
|
2196
|
-
if (
|
|
2197
|
-
|
|
2486
|
+
if (fs4.existsSync(weCloneProxyConfigPath)) {
|
|
2487
|
+
fs4.unlinkSync(weCloneProxyConfigPath);
|
|
2198
2488
|
notes.push(`Removed WeClone proxy config: ${weCloneProxyConfigPath}`);
|
|
2199
2489
|
}
|
|
2200
2490
|
} catch (err) {
|
|
@@ -2212,6 +2502,23 @@ function removeConnector(connectorId) {
|
|
|
2212
2502
|
message: `WeClone remove partially succeeded: ${tokenStatus}, but the proxy config at ${weCloneProxyConfigPath} could not be deleted (${weCloneProxyDeleteFailed}). Manually remove that file \u2014 it may still contain a Remnic daemon bearer token.`
|
|
2213
2503
|
};
|
|
2214
2504
|
}
|
|
2505
|
+
let droidMcpDeleteFailed = null;
|
|
2506
|
+
if (connectorId === "droid") {
|
|
2507
|
+
if (droidMcpConfigPath === null) {
|
|
2508
|
+
notes.push("Droid MCP config cleanup skipped: no persisted path found (legacy install).");
|
|
2509
|
+
} else {
|
|
2510
|
+
try {
|
|
2511
|
+
const note = removeDroidMcpEntry(droidMcpConfigPath);
|
|
2512
|
+
if (note) notes.push(note);
|
|
2513
|
+
} catch (err) {
|
|
2514
|
+
droidMcpDeleteFailed = err instanceof Error ? err.message : String(err);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
if (droidMcpDeleteFailed !== null && droidMcpConfigPath !== null) {
|
|
2519
|
+
const ts = tokenRevoked ? "token was revoked" : "TOKEN REVOCATION ALSO FAILED \u2014 inspect ~/.remnic/tokens.json and revoke manually";
|
|
2520
|
+
return { connectorId, configPath, status: "error", message: `Droid remove partially succeeded: registry config deleted, ${ts}, but the MCP config at ${droidMcpConfigPath} could not be updated (${droidMcpDeleteFailed}). Manually remove the "remnic" entry.` };
|
|
2521
|
+
}
|
|
2215
2522
|
if (connectorId === "hermes") {
|
|
2216
2523
|
try {
|
|
2217
2524
|
const shimCandidates = [];
|
|
@@ -2286,17 +2593,17 @@ function sanitizeHermesProfile(profile) {
|
|
|
2286
2593
|
function hermesConfigPath(profile) {
|
|
2287
2594
|
const safeProfile = sanitizeHermesProfile(profile);
|
|
2288
2595
|
const hermesRoot = resolveHermesRoot();
|
|
2289
|
-
const rootConfigPath =
|
|
2290
|
-
const profilesRoot =
|
|
2596
|
+
const rootConfigPath = path4.join(hermesRoot, "config.yaml");
|
|
2597
|
+
const profilesRoot = path4.join(hermesRoot, "profiles");
|
|
2291
2598
|
if (safeProfile === "default") {
|
|
2292
|
-
const defaultProfileDir =
|
|
2293
|
-
if (isFile(rootConfigPath) || !
|
|
2599
|
+
const defaultProfileDir = path4.join(profilesRoot, safeProfile);
|
|
2600
|
+
if (isFile(rootConfigPath) || !fs4.existsSync(rootConfigPath) && !isDirectory(defaultProfileDir)) {
|
|
2294
2601
|
return rootConfigPath;
|
|
2295
2602
|
}
|
|
2296
2603
|
}
|
|
2297
|
-
const cfgPath =
|
|
2298
|
-
const rel =
|
|
2299
|
-
if (rel.startsWith("..") ||
|
|
2604
|
+
const cfgPath = path4.resolve(profilesRoot, safeProfile, "config.yaml");
|
|
2605
|
+
const rel = path4.relative(profilesRoot, cfgPath);
|
|
2606
|
+
if (rel.startsWith("..") || path4.isAbsolute(rel)) {
|
|
2300
2607
|
throw new Error(
|
|
2301
2608
|
`Invalid Hermes profile path: resolved outside ${profilesRoot}`
|
|
2302
2609
|
);
|
|
@@ -2305,30 +2612,30 @@ function hermesConfigPath(profile) {
|
|
|
2305
2612
|
}
|
|
2306
2613
|
function isDirectory(filePath) {
|
|
2307
2614
|
try {
|
|
2308
|
-
return
|
|
2615
|
+
return fs4.statSync(filePath).isDirectory();
|
|
2309
2616
|
} catch {
|
|
2310
2617
|
return false;
|
|
2311
2618
|
}
|
|
2312
2619
|
}
|
|
2313
2620
|
function isFile(filePath) {
|
|
2314
2621
|
try {
|
|
2315
|
-
return
|
|
2622
|
+
return fs4.statSync(filePath).isFile();
|
|
2316
2623
|
} catch {
|
|
2317
2624
|
return false;
|
|
2318
2625
|
}
|
|
2319
2626
|
}
|
|
2320
2627
|
function hermesConfigTarget(filePath) {
|
|
2321
2628
|
try {
|
|
2322
|
-
return
|
|
2629
|
+
return fs4.realpathSync.native(filePath);
|
|
2323
2630
|
} catch {
|
|
2324
|
-
return
|
|
2631
|
+
return path4.resolve(filePath);
|
|
2325
2632
|
}
|
|
2326
2633
|
}
|
|
2327
2634
|
function sameHermesConfigTarget(leftPath, rightPath) {
|
|
2328
2635
|
return hermesConfigTarget(leftPath) === hermesConfigTarget(rightPath);
|
|
2329
2636
|
}
|
|
2330
2637
|
function hermesDefaultProfileConfigPath() {
|
|
2331
|
-
return
|
|
2638
|
+
return path4.join(resolveHermesRoot(), "profiles", "default", "config.yaml");
|
|
2332
2639
|
}
|
|
2333
2640
|
function hermesConfigCleanupPaths(profile) {
|
|
2334
2641
|
const cfgPath = hermesConfigPath(profile);
|
|
@@ -2383,30 +2690,30 @@ function sanitizeHermesPort(port) {
|
|
|
2383
2690
|
}
|
|
2384
2691
|
return numeric;
|
|
2385
2692
|
}
|
|
2386
|
-
function
|
|
2387
|
-
const dir =
|
|
2388
|
-
const base =
|
|
2389
|
-
const tmpPath =
|
|
2693
|
+
function writeSecretFileSync2(filePath, data) {
|
|
2694
|
+
const dir = path4.dirname(filePath);
|
|
2695
|
+
const base = path4.basename(filePath);
|
|
2696
|
+
const tmpPath = path4.join(
|
|
2390
2697
|
dir,
|
|
2391
2698
|
`.${base}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`
|
|
2392
2699
|
);
|
|
2393
2700
|
let wroteTemp = false;
|
|
2394
2701
|
try {
|
|
2395
|
-
|
|
2702
|
+
fs4.writeFileSync(tmpPath, data, { mode: 384, flag: "wx" });
|
|
2396
2703
|
wroteTemp = true;
|
|
2397
2704
|
try {
|
|
2398
|
-
|
|
2705
|
+
fs4.chmodSync(tmpPath, 384);
|
|
2399
2706
|
} catch {
|
|
2400
2707
|
}
|
|
2401
|
-
|
|
2708
|
+
fs4.renameSync(tmpPath, filePath);
|
|
2402
2709
|
try {
|
|
2403
|
-
|
|
2710
|
+
fs4.chmodSync(filePath, 384);
|
|
2404
2711
|
} catch {
|
|
2405
2712
|
}
|
|
2406
2713
|
} catch (err) {
|
|
2407
2714
|
if (wroteTemp) {
|
|
2408
2715
|
try {
|
|
2409
|
-
|
|
2716
|
+
fs4.unlinkSync(tmpPath);
|
|
2410
2717
|
} catch {
|
|
2411
2718
|
}
|
|
2412
2719
|
}
|
|
@@ -2418,7 +2725,7 @@ function upsertHermesConfig(opts) {
|
|
|
2418
2725
|
}
|
|
2419
2726
|
function upsertHermesConfigAt(cfgPath, opts) {
|
|
2420
2727
|
assertConfigComponentsNotSymlinked(cfgPath);
|
|
2421
|
-
const profileDir =
|
|
2728
|
+
const profileDir = path4.dirname(cfgPath);
|
|
2422
2729
|
const safeHost = sanitizeHermesHost(opts.host);
|
|
2423
2730
|
const safePort = sanitizeHermesPort(opts.port);
|
|
2424
2731
|
const allowInsecureHttp = opts.allowInsecureHttp ?? false;
|
|
@@ -2440,15 +2747,15 @@ function upsertHermesConfigAt(cfgPath, opts) {
|
|
|
2440
2747
|
` token: "${opts.token}"`,
|
|
2441
2748
|
` allow_insecure_http: ${allowInsecureHttp}`
|
|
2442
2749
|
].join("\n");
|
|
2443
|
-
if (!
|
|
2444
|
-
|
|
2750
|
+
if (!fs4.existsSync(cfgPath)) {
|
|
2751
|
+
writeSecretFileSync2(cfgPath, block + "\n");
|
|
2445
2752
|
return { updated: true, skipped: false, configPath: cfgPath, priorContent: null };
|
|
2446
2753
|
}
|
|
2447
|
-
const raw =
|
|
2754
|
+
const raw = fs4.readFileSync(cfgPath, "utf8");
|
|
2448
2755
|
const hasRemnicBlock = /^remnic:/m.test(raw);
|
|
2449
2756
|
if (!hasRemnicBlock) {
|
|
2450
2757
|
const separator = raw.endsWith("\n") ? "\n" : "\n\n";
|
|
2451
|
-
|
|
2758
|
+
writeSecretFileSync2(cfgPath, raw + separator + block + "\n");
|
|
2452
2759
|
return { updated: true, skipped: false, configPath: cfgPath, priorContent: raw };
|
|
2453
2760
|
}
|
|
2454
2761
|
const splitLines = raw.split("\n");
|
|
@@ -2503,7 +2810,7 @@ function upsertHermesConfigAt(cfgPath, opts) {
|
|
|
2503
2810
|
if (!written.token) newLines.push(` token: "${opts.token}"`);
|
|
2504
2811
|
if (!written.allowInsecureHttp) newLines.push(` allow_insecure_http: ${allowInsecureHttp}`);
|
|
2505
2812
|
}
|
|
2506
|
-
|
|
2813
|
+
writeSecretFileSync2(cfgPath, newLines.join("\n") + "\n");
|
|
2507
2814
|
return { updated: true, skipped: false, configPath: cfgPath, priorContent: raw };
|
|
2508
2815
|
}
|
|
2509
2816
|
function removeHermesConfig(opts) {
|
|
@@ -2592,7 +2899,7 @@ function removeHermesConfigFile(cfgPath) {
|
|
|
2592
2899
|
configPath: cfgPath
|
|
2593
2900
|
};
|
|
2594
2901
|
}
|
|
2595
|
-
if (!
|
|
2902
|
+
if (!fs4.existsSync(cfgPath)) {
|
|
2596
2903
|
return {
|
|
2597
2904
|
updated: false,
|
|
2598
2905
|
skipped: true,
|
|
@@ -2600,7 +2907,7 @@ function removeHermesConfigFile(cfgPath) {
|
|
|
2600
2907
|
configPath: cfgPath
|
|
2601
2908
|
};
|
|
2602
2909
|
}
|
|
2603
|
-
const raw =
|
|
2910
|
+
const raw = fs4.readFileSync(cfgPath, "utf8");
|
|
2604
2911
|
if (!/^remnic:/m.test(raw)) {
|
|
2605
2912
|
return {
|
|
2606
2913
|
updated: false,
|
|
@@ -2629,7 +2936,7 @@ function removeHermesConfigFile(cfgPath) {
|
|
|
2629
2936
|
while (newLines.length > 0 && newLines[newLines.length - 1]?.trim() === "") {
|
|
2630
2937
|
newLines.pop();
|
|
2631
2938
|
}
|
|
2632
|
-
|
|
2939
|
+
writeSecretFileSync2(cfgPath, newLines.length > 0 ? newLines.join("\n") + "\n" : "");
|
|
2633
2940
|
return { updated: true, skipped: false, configPath: cfgPath };
|
|
2634
2941
|
}
|
|
2635
2942
|
async function doctorConnector(connectorId) {
|
|
@@ -2642,15 +2949,15 @@ async function doctorConnector(connectorId) {
|
|
|
2642
2949
|
healthy: false
|
|
2643
2950
|
};
|
|
2644
2951
|
}
|
|
2645
|
-
const configPath =
|
|
2952
|
+
const configPath = path4.join(getConnectorsDir(), `${connectorId}.json`);
|
|
2646
2953
|
const checks = [];
|
|
2647
2954
|
checks.push({
|
|
2648
2955
|
name: "Config file",
|
|
2649
|
-
ok:
|
|
2956
|
+
ok: fs4.existsSync(configPath),
|
|
2650
2957
|
detail: configPath
|
|
2651
2958
|
});
|
|
2652
2959
|
try {
|
|
2653
|
-
const raw =
|
|
2960
|
+
const raw = fs4.readFileSync(configPath, "utf8");
|
|
2654
2961
|
JSON.parse(raw);
|
|
2655
2962
|
checks.push({ name: "Config valid", ok: true, detail: "OK" });
|
|
2656
2963
|
} catch (e) {
|
|
@@ -2674,12 +2981,15 @@ async function doctorConnector(connectorId) {
|
|
|
2674
2981
|
}
|
|
2675
2982
|
const memoryDir = instance.config.memoryDir;
|
|
2676
2983
|
if (memoryDir) {
|
|
2677
|
-
if (
|
|
2984
|
+
if (fs4.existsSync(memoryDir)) {
|
|
2678
2985
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
2679
2986
|
} else {
|
|
2680
2987
|
checks.push({ name: "Memory directory", ok: false, detail: `Not found: ${memoryDir}` });
|
|
2681
2988
|
}
|
|
2682
2989
|
}
|
|
2990
|
+
if (connectorId === "droid") {
|
|
2991
|
+
checks.push(droidMcpDoctorCheck(instance.config.factoryMcpPath));
|
|
2992
|
+
}
|
|
2683
2993
|
const healthy = checks.every((c) => c.ok);
|
|
2684
2994
|
return { connectorId, checks, healthy };
|
|
2685
2995
|
}
|
|
@@ -2688,32 +2998,32 @@ var CODEX_EXTENSIONS_SUBDIR = "memories_extensions";
|
|
|
2688
2998
|
var REMNIC_EXTENSION_DIR_NAME = "remnic";
|
|
2689
2999
|
function resolveCodexHome(override) {
|
|
2690
3000
|
if (override && typeof override === "string" && override.trim().length > 0) {
|
|
2691
|
-
return
|
|
3001
|
+
return path4.resolve(override.trim());
|
|
2692
3002
|
}
|
|
2693
3003
|
const envHome = readEnvVar("CODEX_HOME");
|
|
2694
3004
|
if (envHome && envHome.trim().length > 0) {
|
|
2695
|
-
return
|
|
3005
|
+
return path4.resolve(envHome.trim());
|
|
2696
3006
|
}
|
|
2697
3007
|
const home = readEnvVar("HOME") || readEnvVar("USERPROFILE") || resolveHomeDir();
|
|
2698
|
-
return
|
|
3008
|
+
return path4.resolve(home, ".codex");
|
|
2699
3009
|
}
|
|
2700
3010
|
function resolveCodexMemoryExtensionPaths(codexHomeOverride) {
|
|
2701
3011
|
const codexHome = resolveCodexHome(codexHomeOverride);
|
|
2702
|
-
const memoriesDir =
|
|
2703
|
-
const extensionsRoot =
|
|
2704
|
-
const remnicExtensionDir =
|
|
3012
|
+
const memoriesDir = path4.join(codexHome, CODEX_MEMORIES_SUBDIR);
|
|
3013
|
+
const extensionsRoot = path4.join(path4.dirname(memoriesDir), CODEX_EXTENSIONS_SUBDIR);
|
|
3014
|
+
const remnicExtensionDir = path4.join(extensionsRoot, REMNIC_EXTENSION_DIR_NAME);
|
|
2705
3015
|
return { codexHome, memoriesDir, extensionsRoot, remnicExtensionDir };
|
|
2706
3016
|
}
|
|
2707
3017
|
function locatePluginCodexExtensionSource(override) {
|
|
2708
3018
|
if (override && typeof override === "string" && override.trim().length > 0) {
|
|
2709
|
-
const resolved =
|
|
2710
|
-
if (
|
|
3019
|
+
const resolved = path4.resolve(override.trim());
|
|
3020
|
+
if (fs4.existsSync(resolved) && fs4.statSync(resolved).isDirectory()) {
|
|
2711
3021
|
return resolved;
|
|
2712
3022
|
}
|
|
2713
3023
|
throw new Error(`Codex extension source directory not found: ${resolved}`);
|
|
2714
3024
|
}
|
|
2715
|
-
const EXTENSION_SUBPATH =
|
|
2716
|
-
const WORKSPACE_RELATIVE_PATH =
|
|
3025
|
+
const EXTENSION_SUBPATH = path4.join("memories_extensions", "remnic");
|
|
3026
|
+
const WORKSPACE_RELATIVE_PATH = path4.join(
|
|
2717
3027
|
"packages",
|
|
2718
3028
|
"plugin-codex",
|
|
2719
3029
|
"memories_extensions",
|
|
@@ -2721,15 +3031,15 @@ function locatePluginCodexExtensionSource(override) {
|
|
|
2721
3031
|
);
|
|
2722
3032
|
const searched = [];
|
|
2723
3033
|
try {
|
|
2724
|
-
const moduleDir =
|
|
2725
|
-
const bundledCandidate =
|
|
3034
|
+
const moduleDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
3035
|
+
const bundledCandidate = path4.join(moduleDir, "codex");
|
|
2726
3036
|
searched.push(bundledCandidate);
|
|
2727
|
-
if (
|
|
3037
|
+
if (fs4.existsSync(bundledCandidate) && fs4.statSync(bundledCandidate).isDirectory()) {
|
|
2728
3038
|
return bundledCandidate;
|
|
2729
3039
|
}
|
|
2730
|
-
const distConnectorsCandidate =
|
|
3040
|
+
const distConnectorsCandidate = path4.join(moduleDir, "connectors", "codex");
|
|
2731
3041
|
searched.push(distConnectorsCandidate);
|
|
2732
|
-
if (
|
|
3042
|
+
if (fs4.existsSync(distConnectorsCandidate) && fs4.statSync(distConnectorsCandidate).isDirectory()) {
|
|
2733
3043
|
return distConnectorsCandidate;
|
|
2734
3044
|
}
|
|
2735
3045
|
} catch {
|
|
@@ -2737,19 +3047,19 @@ function locatePluginCodexExtensionSource(override) {
|
|
|
2737
3047
|
try {
|
|
2738
3048
|
const requireFromHere = createRequire(import.meta.url);
|
|
2739
3049
|
const pluginPkgJsonPath = requireFromHere.resolve("@remnic/plugin-codex/package.json");
|
|
2740
|
-
const pluginPkgRoot =
|
|
2741
|
-
const candidate =
|
|
3050
|
+
const pluginPkgRoot = path4.dirname(pluginPkgJsonPath);
|
|
3051
|
+
const candidate = path4.join(pluginPkgRoot, EXTENSION_SUBPATH);
|
|
2742
3052
|
searched.push(candidate);
|
|
2743
|
-
if (
|
|
3053
|
+
if (fs4.existsSync(candidate) && fs4.statSync(candidate).isDirectory()) {
|
|
2744
3054
|
return candidate;
|
|
2745
3055
|
}
|
|
2746
3056
|
} catch {
|
|
2747
3057
|
}
|
|
2748
3058
|
try {
|
|
2749
|
-
const moduleDir =
|
|
3059
|
+
const moduleDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
2750
3060
|
let dir = moduleDir;
|
|
2751
3061
|
for (let depth = 0; depth < 8; depth += 1) {
|
|
2752
|
-
const candidate =
|
|
3062
|
+
const candidate = path4.join(
|
|
2753
3063
|
dir,
|
|
2754
3064
|
"node_modules",
|
|
2755
3065
|
"@remnic",
|
|
@@ -2757,10 +3067,10 @@ function locatePluginCodexExtensionSource(override) {
|
|
|
2757
3067
|
EXTENSION_SUBPATH
|
|
2758
3068
|
);
|
|
2759
3069
|
searched.push(candidate);
|
|
2760
|
-
if (
|
|
3070
|
+
if (fs4.existsSync(candidate) && fs4.statSync(candidate).isDirectory()) {
|
|
2761
3071
|
return candidate;
|
|
2762
3072
|
}
|
|
2763
|
-
const parent =
|
|
3073
|
+
const parent = path4.dirname(dir);
|
|
2764
3074
|
if (parent === dir) break;
|
|
2765
3075
|
dir = parent;
|
|
2766
3076
|
}
|
|
@@ -2768,19 +3078,19 @@ function locatePluginCodexExtensionSource(override) {
|
|
|
2768
3078
|
}
|
|
2769
3079
|
const anchors = [];
|
|
2770
3080
|
try {
|
|
2771
|
-
anchors.push(
|
|
3081
|
+
anchors.push(path4.dirname(fileURLToPath(import.meta.url)));
|
|
2772
3082
|
} catch {
|
|
2773
3083
|
}
|
|
2774
3084
|
anchors.push(process.cwd());
|
|
2775
3085
|
for (const anchor of anchors) {
|
|
2776
3086
|
let dir = anchor;
|
|
2777
3087
|
for (let depth = 0; depth < 12; depth += 1) {
|
|
2778
|
-
const candidate =
|
|
3088
|
+
const candidate = path4.join(dir, WORKSPACE_RELATIVE_PATH);
|
|
2779
3089
|
searched.push(candidate);
|
|
2780
|
-
if (
|
|
3090
|
+
if (fs4.existsSync(candidate) && fs4.statSync(candidate).isDirectory()) {
|
|
2781
3091
|
return candidate;
|
|
2782
3092
|
}
|
|
2783
|
-
const parent =
|
|
3093
|
+
const parent = path4.dirname(dir);
|
|
2784
3094
|
if (parent === dir) break;
|
|
2785
3095
|
dir = parent;
|
|
2786
3096
|
}
|
|
@@ -2791,15 +3101,15 @@ function locatePluginCodexExtensionSource(override) {
|
|
|
2791
3101
|
}
|
|
2792
3102
|
function copyDirRecursiveSync(src, dest) {
|
|
2793
3103
|
let count = 0;
|
|
2794
|
-
|
|
2795
|
-
const entries =
|
|
3104
|
+
fs4.mkdirSync(dest, { recursive: true });
|
|
3105
|
+
const entries = fs4.readdirSync(src, { withFileTypes: true });
|
|
2796
3106
|
for (const entry of entries) {
|
|
2797
|
-
const from =
|
|
2798
|
-
const to =
|
|
3107
|
+
const from = path4.join(src, entry.name);
|
|
3108
|
+
const to = path4.join(dest, entry.name);
|
|
2799
3109
|
if (entry.isDirectory()) {
|
|
2800
3110
|
count += copyDirRecursiveSync(from, to);
|
|
2801
3111
|
} else if (entry.isFile()) {
|
|
2802
|
-
|
|
3112
|
+
fs4.copyFileSync(from, to);
|
|
2803
3113
|
count += 1;
|
|
2804
3114
|
}
|
|
2805
3115
|
}
|
|
@@ -2808,29 +3118,29 @@ function copyDirRecursiveSync(src, dest) {
|
|
|
2808
3118
|
function installCodexMemoryExtension(options = {}) {
|
|
2809
3119
|
const paths = resolveCodexMemoryExtensionPaths(options.codexHome ?? null);
|
|
2810
3120
|
const sourceDir = locatePluginCodexExtensionSource(options.sourceDir ?? null);
|
|
2811
|
-
|
|
3121
|
+
fs4.mkdirSync(paths.extensionsRoot, { recursive: true });
|
|
2812
3122
|
const tmpPrefix = `.${REMNIC_EXTENSION_DIR_NAME}.tmp-`;
|
|
2813
3123
|
const STALE_TMP_THRESHOLD_MS = 10 * 60 * 1e3;
|
|
2814
3124
|
const now = Date.now();
|
|
2815
3125
|
try {
|
|
2816
|
-
const existingEntries =
|
|
3126
|
+
const existingEntries = fs4.readdirSync(paths.extensionsRoot);
|
|
2817
3127
|
for (const entry of existingEntries) {
|
|
2818
3128
|
if (!entry.startsWith(tmpPrefix)) continue;
|
|
2819
|
-
const stalePath =
|
|
3129
|
+
const stalePath = path4.join(paths.extensionsRoot, entry);
|
|
2820
3130
|
try {
|
|
2821
|
-
const stat =
|
|
3131
|
+
const stat = fs4.statSync(stalePath);
|
|
2822
3132
|
const ageMs = now - stat.mtimeMs;
|
|
2823
3133
|
if (ageMs < STALE_TMP_THRESHOLD_MS) {
|
|
2824
3134
|
continue;
|
|
2825
3135
|
}
|
|
2826
|
-
|
|
3136
|
+
fs4.rmSync(stalePath, { recursive: true, force: true });
|
|
2827
3137
|
} catch {
|
|
2828
3138
|
}
|
|
2829
3139
|
}
|
|
2830
3140
|
} catch {
|
|
2831
3141
|
}
|
|
2832
3142
|
const tmpName = `${tmpPrefix}${process.pid}-${Date.now()}`;
|
|
2833
|
-
const tmpDir =
|
|
3143
|
+
const tmpDir = path4.join(paths.extensionsRoot, tmpName);
|
|
2834
3144
|
let filesCopied = 0;
|
|
2835
3145
|
let commitFn = () => {
|
|
2836
3146
|
};
|
|
@@ -2839,16 +3149,16 @@ function installCodexMemoryExtension(options = {}) {
|
|
|
2839
3149
|
try {
|
|
2840
3150
|
filesCopied = copyDirRecursiveSync(sourceDir, tmpDir);
|
|
2841
3151
|
const backupDir = `${paths.remnicExtensionDir}.bak-${Date.now()}`;
|
|
2842
|
-
const hadExisting =
|
|
3152
|
+
const hadExisting = fs4.existsSync(paths.remnicExtensionDir);
|
|
2843
3153
|
if (hadExisting) {
|
|
2844
|
-
|
|
3154
|
+
fs4.renameSync(paths.remnicExtensionDir, backupDir);
|
|
2845
3155
|
}
|
|
2846
3156
|
try {
|
|
2847
|
-
|
|
3157
|
+
fs4.renameSync(tmpDir, paths.remnicExtensionDir);
|
|
2848
3158
|
} catch (renameErr) {
|
|
2849
3159
|
if (hadExisting) {
|
|
2850
3160
|
try {
|
|
2851
|
-
|
|
3161
|
+
fs4.renameSync(backupDir, paths.remnicExtensionDir);
|
|
2852
3162
|
} catch {
|
|
2853
3163
|
}
|
|
2854
3164
|
}
|
|
@@ -2857,7 +3167,7 @@ function installCodexMemoryExtension(options = {}) {
|
|
|
2857
3167
|
commitFn = () => {
|
|
2858
3168
|
if (hadExisting) {
|
|
2859
3169
|
try {
|
|
2860
|
-
|
|
3170
|
+
fs4.rmSync(backupDir, { recursive: true, force: true });
|
|
2861
3171
|
} catch {
|
|
2862
3172
|
}
|
|
2863
3173
|
}
|
|
@@ -2865,31 +3175,31 @@ function installCodexMemoryExtension(options = {}) {
|
|
|
2865
3175
|
rollbackFn = () => {
|
|
2866
3176
|
if (hadExisting) {
|
|
2867
3177
|
try {
|
|
2868
|
-
if (
|
|
2869
|
-
|
|
3178
|
+
if (fs4.existsSync(paths.remnicExtensionDir)) {
|
|
3179
|
+
fs4.rmSync(paths.remnicExtensionDir, { recursive: true, force: true });
|
|
2870
3180
|
}
|
|
2871
|
-
|
|
3181
|
+
fs4.renameSync(backupDir, paths.remnicExtensionDir);
|
|
2872
3182
|
} catch {
|
|
2873
3183
|
}
|
|
2874
3184
|
} else {
|
|
2875
3185
|
try {
|
|
2876
|
-
if (
|
|
2877
|
-
|
|
3186
|
+
if (fs4.existsSync(paths.remnicExtensionDir)) {
|
|
3187
|
+
fs4.rmSync(paths.remnicExtensionDir, { recursive: true, force: true });
|
|
2878
3188
|
}
|
|
2879
3189
|
} catch {
|
|
2880
3190
|
}
|
|
2881
3191
|
}
|
|
2882
3192
|
};
|
|
2883
3193
|
} catch (err) {
|
|
2884
|
-
if (
|
|
3194
|
+
if (fs4.existsSync(tmpDir)) {
|
|
2885
3195
|
try {
|
|
2886
|
-
|
|
3196
|
+
fs4.rmSync(tmpDir, { recursive: true, force: true });
|
|
2887
3197
|
} catch {
|
|
2888
3198
|
}
|
|
2889
3199
|
}
|
|
2890
3200
|
throw err;
|
|
2891
3201
|
}
|
|
2892
|
-
const instructionsPath =
|
|
3202
|
+
const instructionsPath = path4.join(paths.remnicExtensionDir, "instructions.md");
|
|
2893
3203
|
return {
|
|
2894
3204
|
...paths,
|
|
2895
3205
|
instructionsPath,
|
|
@@ -2901,8 +3211,8 @@ function installCodexMemoryExtension(options = {}) {
|
|
|
2901
3211
|
function removeCodexMemoryExtension(options = {}) {
|
|
2902
3212
|
const paths = resolveCodexMemoryExtensionPaths(options.codexHome ?? null);
|
|
2903
3213
|
let removed = false;
|
|
2904
|
-
if (
|
|
2905
|
-
|
|
3214
|
+
if (fs4.existsSync(paths.remnicExtensionDir)) {
|
|
3215
|
+
fs4.rmSync(paths.remnicExtensionDir, { recursive: true, force: true });
|
|
2906
3216
|
removed = true;
|
|
2907
3217
|
}
|
|
2908
3218
|
return { ...paths, removed };
|
|
@@ -2913,11 +3223,11 @@ function resolveWeCloneProxyConfigPath() {
|
|
|
2913
3223
|
const remnicHome = readEnvVar("REMNIC_HOME");
|
|
2914
3224
|
const override = remnicHome && remnicHome.length > 0 ? remnicHome : readEnvVar("ENGRAM_HOME");
|
|
2915
3225
|
if (override && override.length > 0) {
|
|
2916
|
-
return
|
|
3226
|
+
return path4.resolve(expandTildePath(override), "connectors", WECLONE_PROXY_CONFIG_FILENAME);
|
|
2917
3227
|
}
|
|
2918
3228
|
const envHome = readEnvVar("HOME");
|
|
2919
|
-
const home = envHome && envHome.length > 0 ? envHome :
|
|
2920
|
-
return
|
|
3229
|
+
const home = envHome && envHome.length > 0 ? envHome : os2.homedir();
|
|
3230
|
+
return path4.resolve(
|
|
2921
3231
|
home,
|
|
2922
3232
|
WECLONE_PROXY_CONFIG_DIRNAME,
|
|
2923
3233
|
"connectors",
|
|
@@ -2926,8 +3236,8 @@ function resolveWeCloneProxyConfigPath() {
|
|
|
2926
3236
|
}
|
|
2927
3237
|
function readWeCloneProxyConfigIfExists(configPath) {
|
|
2928
3238
|
try {
|
|
2929
|
-
if (!
|
|
2930
|
-
return
|
|
3239
|
+
if (!fs4.existsSync(configPath)) return null;
|
|
3240
|
+
return fs4.readFileSync(configPath, "utf8");
|
|
2931
3241
|
} catch {
|
|
2932
3242
|
return null;
|
|
2933
3243
|
}
|
|
@@ -3047,6 +3357,10 @@ function buildWeCloneProxyConfig(args) {
|
|
|
3047
3357
|
}
|
|
3048
3358
|
|
|
3049
3359
|
export {
|
|
3360
|
+
DROID_CONNECTOR_MANIFEST,
|
|
3361
|
+
resolveFactoryMcpPath,
|
|
3362
|
+
upsertFactoryMcpRemnicEntry,
|
|
3363
|
+
removeFactoryMcpRemnicEntry,
|
|
3050
3364
|
MARKETPLACE_SCHEMA_VERSION,
|
|
3051
3365
|
MARKETPLACE_MANIFEST_FILENAME,
|
|
3052
3366
|
generateMarketplaceManifest,
|
|
@@ -3074,4 +3388,4 @@ export {
|
|
|
3074
3388
|
resolveWeCloneProxyConfigPath,
|
|
3075
3389
|
buildWeCloneProxyConfig
|
|
3076
3390
|
};
|
|
3077
|
-
//# sourceMappingURL=chunk-
|
|
3391
|
+
//# sourceMappingURL=chunk-4XN35YQD.js.map
|