opkg 0.9.2 → 0.9.4
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/.claude/agents/code-reviewer.md +171 -0
- package/.claude/commands/commit-push-pr.md +20 -0
- package/.claude/commands/{specs/read.md → read-specs.md} +1 -1
- package/.claude/commands/{specs/update.md → update-specs.md} +4 -0
- package/.claude/skills/code-review-excellence/SKILL.md +538 -0
- package/README.md +2 -2
- package/package.json +3 -1
- package/packages/cli/dist/add-IJAPFHIX.js +624 -0
- package/packages/cli/dist/add-IJAPFHIX.js.map +7 -0
- package/packages/cli/dist/add-LLUNFLJI.js +624 -0
- package/packages/cli/dist/add-LLUNFLJI.js.map +7 -0
- package/packages/cli/dist/add-U44SL3OR.js +624 -0
- package/packages/cli/dist/add-U44SL3OR.js.map +7 -0
- package/packages/cli/dist/chunk-23VBP5L6.js +371 -0
- package/packages/cli/dist/chunk-23VBP5L6.js.map +7 -0
- package/packages/cli/dist/chunk-2SVHLF5C.js +1419 -0
- package/packages/cli/dist/chunk-2SVHLF5C.js.map +7 -0
- package/packages/cli/dist/chunk-37256POU.js +99 -0
- package/packages/cli/dist/chunk-37256POU.js.map +7 -0
- package/packages/cli/dist/chunk-3PZRVA6O.js +196 -0
- package/packages/cli/dist/chunk-3PZRVA6O.js.map +7 -0
- package/packages/cli/dist/chunk-427DCURL.js +155 -0
- package/packages/cli/dist/chunk-427DCURL.js.map +7 -0
- package/packages/cli/dist/chunk-4B5HJLP2.js +48 -0
- package/packages/cli/dist/chunk-4B5HJLP2.js.map +7 -0
- package/packages/cli/dist/chunk-4OWT3YEG.js +413 -0
- package/packages/cli/dist/chunk-4OWT3YEG.js.map +7 -0
- package/packages/cli/dist/chunk-4RIBTBXI.js +568 -0
- package/packages/cli/dist/chunk-4RIBTBXI.js.map +7 -0
- package/packages/cli/dist/chunk-4X2EJHJN.js +63 -0
- package/packages/cli/dist/chunk-4X2EJHJN.js.map +7 -0
- package/packages/cli/dist/chunk-6CYW66HD.js +1136 -0
- package/packages/cli/dist/chunk-6CYW66HD.js.map +7 -0
- package/packages/cli/dist/chunk-6DITYAFA.js +172 -0
- package/packages/cli/dist/chunk-6DITYAFA.js.map +7 -0
- package/packages/cli/dist/chunk-7KEAKEVZ.js +568 -0
- package/packages/cli/dist/chunk-7KEAKEVZ.js.map +7 -0
- package/packages/cli/dist/chunk-ABFUD25D.js +61 -0
- package/packages/cli/dist/chunk-ABFUD25D.js.map +7 -0
- package/packages/cli/dist/chunk-AR7GJCG6.js +274 -0
- package/packages/cli/dist/chunk-AR7GJCG6.js.map +7 -0
- package/packages/cli/dist/chunk-AYTGQCXH.js +86 -0
- package/packages/cli/dist/chunk-AYTGQCXH.js.map +7 -0
- package/packages/cli/dist/chunk-BROJ6OUT.js +631 -0
- package/packages/cli/dist/chunk-BROJ6OUT.js.map +7 -0
- package/packages/cli/dist/chunk-BVVSU7QD.js +23 -0
- package/packages/cli/dist/chunk-BVVSU7QD.js.map +7 -0
- package/packages/cli/dist/chunk-C6FY55UP.js +108 -0
- package/packages/cli/dist/chunk-C6FY55UP.js.map +7 -0
- package/packages/cli/dist/chunk-CVA64SXK.js +1136 -0
- package/packages/cli/dist/chunk-CVA64SXK.js.map +7 -0
- package/packages/cli/dist/chunk-D3O7LY2Q.js +1151 -0
- package/packages/cli/dist/chunk-D3O7LY2Q.js.map +7 -0
- package/packages/cli/dist/chunk-D6LEPODL.js +413 -0
- package/packages/cli/dist/chunk-D6LEPODL.js.map +7 -0
- package/packages/cli/dist/chunk-DEC24S7E.js +186 -0
- package/packages/cli/dist/chunk-DEC24S7E.js.map +7 -0
- package/packages/cli/dist/chunk-FMVVJH5M.js +371 -0
- package/packages/cli/dist/chunk-FMVVJH5M.js.map +7 -0
- package/packages/cli/dist/chunk-GDVFS3YP.js +130 -0
- package/packages/cli/dist/chunk-GDVFS3YP.js.map +7 -0
- package/packages/cli/dist/chunk-GEP2G5HF.js +31 -0
- package/packages/cli/dist/chunk-GEP2G5HF.js.map +7 -0
- package/packages/cli/dist/chunk-GSWHZBT2.js +62 -0
- package/packages/cli/dist/chunk-GSWHZBT2.js.map +7 -0
- package/packages/cli/dist/chunk-HTYHJA3B.js +61 -0
- package/packages/cli/dist/chunk-HTYHJA3B.js.map +7 -0
- package/packages/cli/dist/chunk-HYKYECAE.js +222 -0
- package/packages/cli/dist/chunk-HYKYECAE.js.map +7 -0
- package/packages/cli/dist/chunk-I7FEAHB4.js +100 -0
- package/packages/cli/dist/chunk-I7FEAHB4.js.map +7 -0
- package/packages/cli/dist/chunk-IHVZ5AUJ.js +107 -0
- package/packages/cli/dist/chunk-IHVZ5AUJ.js.map +7 -0
- package/packages/cli/dist/chunk-KI7FDU3H.js +99 -0
- package/packages/cli/dist/chunk-KI7FDU3H.js.map +7 -0
- package/packages/cli/dist/chunk-L5GRJQBS.js +32 -0
- package/packages/cli/dist/chunk-L5GRJQBS.js.map +7 -0
- package/packages/cli/dist/chunk-LHEAUDJL.js +302 -0
- package/packages/cli/dist/chunk-LHEAUDJL.js.map +7 -0
- package/packages/cli/dist/chunk-MIURCESJ.js +48 -0
- package/packages/cli/dist/chunk-MIURCESJ.js.map +7 -0
- package/packages/cli/dist/chunk-N43IXOND.js +732 -0
- package/packages/cli/dist/chunk-N43IXOND.js.map +7 -0
- package/packages/cli/dist/chunk-OUZRMGPV.js +274 -0
- package/packages/cli/dist/chunk-OUZRMGPV.js.map +7 -0
- package/packages/cli/dist/chunk-PSQXKAL4.js +371 -0
- package/packages/cli/dist/chunk-PSQXKAL4.js.map +7 -0
- package/packages/cli/dist/chunk-PUDRKDVZ.js +1419 -0
- package/packages/cli/dist/chunk-PUDRKDVZ.js.map +7 -0
- package/packages/cli/dist/chunk-RAKMX654.js +631 -0
- package/packages/cli/dist/chunk-RAKMX654.js.map +7 -0
- package/packages/cli/dist/chunk-RSFLK2TP.js +195 -0
- package/packages/cli/dist/chunk-RSFLK2TP.js.map +7 -0
- package/packages/cli/dist/chunk-S26PR2BS.js +99 -0
- package/packages/cli/dist/chunk-S26PR2BS.js.map +7 -0
- package/packages/cli/dist/chunk-U7FW7SXX.js +568 -0
- package/packages/cli/dist/chunk-U7FW7SXX.js.map +7 -0
- package/packages/cli/dist/chunk-VKM6K5TN.js +413 -0
- package/packages/cli/dist/chunk-VKM6K5TN.js.map +7 -0
- package/packages/cli/dist/chunk-VKNJG4JN.js +253 -0
- package/packages/cli/dist/chunk-VKNJG4JN.js.map +7 -0
- package/packages/cli/dist/chunk-VQ2KY6CK.js +113 -0
- package/packages/cli/dist/chunk-VQ2KY6CK.js.map +7 -0
- package/packages/cli/dist/chunk-VQDTXLOX.js +1312 -0
- package/packages/cli/dist/chunk-VQDTXLOX.js.map +7 -0
- package/packages/cli/dist/chunk-VXNS3X5O.js +60 -0
- package/packages/cli/dist/chunk-VXNS3X5O.js.map +7 -0
- package/packages/cli/dist/chunk-WF7H2YDU.js +376 -0
- package/packages/cli/dist/chunk-WF7H2YDU.js.map +7 -0
- package/packages/cli/dist/chunk-WNRXZLWW.js +266 -0
- package/packages/cli/dist/chunk-WNRXZLWW.js.map +7 -0
- package/packages/cli/dist/chunk-WT4VVCXM.js +1121 -0
- package/packages/cli/dist/chunk-WT4VVCXM.js.map +7 -0
- package/packages/cli/dist/configure-3AZUMDJZ.js +107 -0
- package/packages/cli/dist/configure-3AZUMDJZ.js.map +7 -0
- package/packages/cli/dist/configure-D722JQOD.js +107 -0
- package/packages/cli/dist/configure-D722JQOD.js.map +7 -0
- package/packages/cli/dist/configure-IU5H7XD6.js +107 -0
- package/packages/cli/dist/configure-IU5H7XD6.js.map +7 -0
- package/packages/cli/dist/file-format-detector-PXCIAKTK.js +22 -0
- package/packages/cli/dist/file-format-detector-PXCIAKTK.js.map +7 -0
- package/packages/cli/dist/index.js +17 -17
- package/packages/cli/dist/install-EZNWMLJR.js +7581 -0
- package/packages/cli/dist/install-EZNWMLJR.js.map +7 -0
- package/packages/cli/dist/install-F5ANFUBX.js +7577 -0
- package/packages/cli/dist/install-F5ANFUBX.js.map +7 -0
- package/packages/cli/dist/install-JSXEPPC2.js +7104 -0
- package/packages/cli/dist/install-JSXEPPC2.js.map +7 -0
- package/packages/cli/dist/install-QHEBX7JH.js +7101 -0
- package/packages/cli/dist/install-QHEBX7JH.js.map +7 -0
- package/packages/cli/dist/list-DMOUATYI.js +327 -0
- package/packages/cli/dist/list-DMOUATYI.js.map +7 -0
- package/packages/cli/dist/list-UESSCB7Y.js +327 -0
- package/packages/cli/dist/list-UESSCB7Y.js.map +7 -0
- package/packages/cli/dist/list-XR7RSJFS.js +327 -0
- package/packages/cli/dist/list-XR7RSJFS.js.map +7 -0
- package/packages/cli/dist/login-EYZ2SOYZ.js +150 -0
- package/packages/cli/dist/login-EYZ2SOYZ.js.map +7 -0
- package/packages/cli/dist/login-JWCSTAEU.js +150 -0
- package/packages/cli/dist/login-JWCSTAEU.js.map +7 -0
- package/packages/cli/dist/login-NRKHXZKM.js +150 -0
- package/packages/cli/dist/login-NRKHXZKM.js.map +7 -0
- package/packages/cli/dist/logout-HDMYRXIE.js +40 -0
- package/packages/cli/dist/logout-HDMYRXIE.js.map +7 -0
- package/packages/cli/dist/logout-SYHXCVCQ.js +40 -0
- package/packages/cli/dist/logout-SYHXCVCQ.js.map +7 -0
- package/packages/cli/dist/logout-X3XUUOH5.js +40 -0
- package/packages/cli/dist/logout-X3XUUOH5.js.map +7 -0
- package/packages/cli/dist/new-3LTFKDTQ.js +277 -0
- package/packages/cli/dist/new-3LTFKDTQ.js.map +7 -0
- package/packages/cli/dist/new-F46OSD72.js +277 -0
- package/packages/cli/dist/new-F46OSD72.js.map +7 -0
- package/packages/cli/dist/new-OPCCLNL2.js +277 -0
- package/packages/cli/dist/new-OPCCLNL2.js.map +7 -0
- package/packages/cli/dist/package-marker-detector-T5O5YD2E.js +80 -0
- package/packages/cli/dist/package-marker-detector-T5O5YD2E.js.map +7 -0
- package/packages/cli/dist/package-yml-QWZIJDYU.js +16 -0
- package/packages/cli/dist/package-yml-QWZIJDYU.js.map +7 -0
- package/packages/cli/dist/plugin-naming-YP2I4NPA.js +29 -0
- package/packages/cli/dist/plugin-naming-YP2I4NPA.js.map +7 -0
- package/packages/cli/dist/publish-4H43PCSG.js +619 -0
- package/packages/cli/dist/publish-4H43PCSG.js.map +7 -0
- package/packages/cli/dist/publish-RULKLNUX.js +619 -0
- package/packages/cli/dist/publish-RULKLNUX.js.map +7 -0
- package/packages/cli/dist/publish-URWY2P3E.js +619 -0
- package/packages/cli/dist/publish-URWY2P3E.js.map +7 -0
- package/packages/cli/dist/remove-BD52BHR2.js +542 -0
- package/packages/cli/dist/remove-BD52BHR2.js.map +7 -0
- package/packages/cli/dist/remove-G5NRC7LD.js +542 -0
- package/packages/cli/dist/remove-G5NRC7LD.js.map +7 -0
- package/packages/cli/dist/remove-TC3FQUYQ.js +542 -0
- package/packages/cli/dist/remove-TC3FQUYQ.js.map +7 -0
- package/packages/cli/dist/resource-discoverer-4X4RY43E.js +17 -0
- package/packages/cli/dist/resource-discoverer-4X4RY43E.js.map +7 -0
- package/packages/cli/dist/save-24TESYKI.js +1728 -0
- package/packages/cli/dist/save-24TESYKI.js.map +7 -0
- package/packages/cli/dist/save-N3QWF2WN.js +1728 -0
- package/packages/cli/dist/save-N3QWF2WN.js.map +7 -0
- package/packages/cli/dist/save-P2U67DTV.js +1728 -0
- package/packages/cli/dist/save-P2U67DTV.js.map +7 -0
- package/packages/cli/dist/search-ABROK3UO.js +157 -0
- package/packages/cli/dist/search-ABROK3UO.js.map +7 -0
- package/packages/cli/dist/search-WVFXFNAV.js +157 -0
- package/packages/cli/dist/search-WVFXFNAV.js.map +7 -0
- package/packages/cli/dist/search-YQN2Q2SO.js +157 -0
- package/packages/cli/dist/search-YQN2Q2SO.js.map +7 -0
- package/packages/cli/dist/set-DCWF73F6.js +251 -0
- package/packages/cli/dist/set-DCWF73F6.js.map +7 -0
- package/packages/cli/dist/set-GJEG2F6Y.js +251 -0
- package/packages/cli/dist/set-GJEG2F6Y.js.map +7 -0
- package/packages/cli/dist/set-NGM2FIKF.js +251 -0
- package/packages/cli/dist/set-NGM2FIKF.js.map +7 -0
- package/packages/cli/dist/uninstall-3CJQMTYH.js +539 -0
- package/packages/cli/dist/uninstall-3CJQMTYH.js.map +7 -0
- package/packages/cli/dist/uninstall-Q3CP4UN5.js +539 -0
- package/packages/cli/dist/uninstall-Q3CP4UN5.js.map +7 -0
- package/packages/cli/dist/uninstall-QU5OMEEC.js +539 -0
- package/packages/cli/dist/uninstall-QU5OMEEC.js.map +7 -0
- package/packages/cli/dist/unpublish-GHJQYC4S.js +245 -0
- package/packages/cli/dist/unpublish-GHJQYC4S.js.map +7 -0
- package/packages/cli/dist/unpublish-L2CYMK4B.js +245 -0
- package/packages/cli/dist/unpublish-L2CYMK4B.js.map +7 -0
- package/packages/cli/dist/unpublish-VBTNTMS5.js +245 -0
- package/packages/cli/dist/unpublish-VBTNTMS5.js.map +7 -0
- package/packages/cli/dist/view-MXRBMXOG.js +488 -0
- package/packages/cli/dist/view-MXRBMXOG.js.map +7 -0
- package/packages/cli/dist/view-NMND7SAW.js +488 -0
- package/packages/cli/dist/view-NMND7SAW.js.map +7 -0
- package/packages/cli/dist/view-RPQRDSYB.js +488 -0
- package/packages/cli/dist/view-RPQRDSYB.js.map +7 -0
- package/packages/cli/package.json +2 -0
- package/packages/core/dist/constants/index.d.ts +9 -0
- package/packages/core/dist/constants/index.d.ts.map +1 -1
- package/packages/core/dist/constants/index.js +12 -0
- package/packages/core/dist/constants/index.js.map +1 -1
- package/packages/core/dist/core/dependency-resolver/index.d.ts +2 -10
- package/packages/core/dist/core/dependency-resolver/index.d.ts.map +1 -1
- package/packages/core/dist/core/dependency-resolver/index.js +3 -14
- package/packages/core/dist/core/dependency-resolver/index.js.map +1 -1
- package/packages/core/dist/core/install/base-detector.d.ts +2 -1
- package/packages/core/dist/core/install/base-detector.d.ts.map +1 -1
- package/packages/core/dist/core/install/base-detector.js +54 -1
- package/packages/core/dist/core/install/base-detector.js.map +1 -1
- package/packages/core/dist/core/install/conflicts/file-conflict-resolver.d.ts +7 -5
- package/packages/core/dist/core/install/conflicts/file-conflict-resolver.d.ts.map +1 -1
- package/packages/core/dist/core/install/conflicts/file-conflict-resolver.js +25 -9
- package/packages/core/dist/core/install/conflicts/file-conflict-resolver.js.map +1 -1
- package/packages/core/dist/core/install/flow-index-installer.d.ts +2 -1
- package/packages/core/dist/core/install/flow-index-installer.d.ts.map +1 -1
- package/packages/core/dist/core/install/flow-index-installer.js +19 -4
- package/packages/core/dist/core/install/flow-index-installer.js.map +1 -1
- package/packages/core/dist/core/install/input-classifier-base.js +3 -3
- package/packages/core/dist/core/install/input-classifier-base.js.map +1 -1
- package/packages/core/dist/core/install/install-reporting.d.ts.map +1 -1
- package/packages/core/dist/core/install/install-reporting.js +7 -9
- package/packages/core/dist/core/install/install-reporting.js.map +1 -1
- package/packages/core/dist/core/install/list-handler.d.ts.map +1 -1
- package/packages/core/dist/core/install/list-handler.js +3 -0
- package/packages/core/dist/core/install/list-handler.js.map +1 -1
- package/packages/core/dist/core/install/marketplace-handler.d.ts.map +1 -1
- package/packages/core/dist/core/install/marketplace-handler.js.map +1 -1
- package/packages/core/dist/core/install/operations/conflict-handler.d.ts +2 -1
- package/packages/core/dist/core/install/operations/conflict-handler.d.ts.map +1 -1
- package/packages/core/dist/core/install/operations/conflict-handler.js +2 -2
- package/packages/core/dist/core/install/operations/conflict-handler.js.map +1 -1
- package/packages/core/dist/core/install/operations/installation-executor.d.ts +3 -0
- package/packages/core/dist/core/install/operations/installation-executor.d.ts.map +1 -1
- package/packages/core/dist/core/install/operations/installation-executor.js +39 -22
- package/packages/core/dist/core/install/operations/installation-executor.js.map +1 -1
- package/packages/core/dist/core/install/orchestrator/orchestrator.d.ts +7 -3
- package/packages/core/dist/core/install/orchestrator/orchestrator.d.ts.map +1 -1
- package/packages/core/dist/core/install/orchestrator/orchestrator.js +193 -93
- package/packages/core/dist/core/install/orchestrator/orchestrator.js.map +1 -1
- package/packages/core/dist/core/install/orchestrator/strategies/git-strategy.d.ts +1 -0
- package/packages/core/dist/core/install/orchestrator/strategies/git-strategy.d.ts.map +1 -1
- package/packages/core/dist/core/install/orchestrator/strategies/git-strategy.js +11 -24
- package/packages/core/dist/core/install/orchestrator/strategies/git-strategy.js.map +1 -1
- package/packages/core/dist/core/install/orchestrator/strategies/path-strategy.d.ts +2 -0
- package/packages/core/dist/core/install/orchestrator/strategies/path-strategy.d.ts.map +1 -1
- package/packages/core/dist/core/install/orchestrator/strategies/path-strategy.js +14 -14
- package/packages/core/dist/core/install/orchestrator/strategies/path-strategy.js.map +1 -1
- package/packages/core/dist/core/install/orchestrator/strategies/registry-strategy.d.ts +7 -0
- package/packages/core/dist/core/install/orchestrator/strategies/registry-strategy.d.ts.map +1 -1
- package/packages/core/dist/core/install/orchestrator/strategies/registry-strategy.js +28 -0
- package/packages/core/dist/core/install/orchestrator/strategies/registry-strategy.js.map +1 -1
- package/packages/core/dist/core/install/orchestrator/types.d.ts +2 -0
- package/packages/core/dist/core/install/orchestrator/types.d.ts.map +1 -1
- package/packages/core/dist/core/install/path-package-loader.d.ts.map +1 -1
- package/packages/core/dist/core/install/path-package-loader.js +20 -1
- package/packages/core/dist/core/install/path-package-loader.js.map +1 -1
- package/packages/core/dist/core/install/platform-resolution.d.ts +3 -0
- package/packages/core/dist/core/install/platform-resolution.d.ts.map +1 -1
- package/packages/core/dist/core/install/platform-resolution.js +5 -2
- package/packages/core/dist/core/install/platform-resolution.js.map +1 -1
- package/packages/core/dist/core/install/preprocessing/context-population.d.ts +18 -0
- package/packages/core/dist/core/install/preprocessing/context-population.d.ts.map +1 -0
- package/packages/core/dist/core/install/preprocessing/context-population.js +36 -0
- package/packages/core/dist/core/install/preprocessing/context-population.js.map +1 -0
- package/packages/core/dist/core/install/preprocessing/convenience-preprocessor.d.ts +23 -0
- package/packages/core/dist/core/install/preprocessing/convenience-preprocessor.d.ts.map +1 -1
- package/packages/core/dist/core/install/preprocessing/convenience-preprocessor.js +44 -0
- package/packages/core/dist/core/install/preprocessing/convenience-preprocessor.js.map +1 -1
- package/packages/core/dist/core/install/sources/git-source.d.ts.map +1 -1
- package/packages/core/dist/core/install/sources/git-source.js +67 -4
- package/packages/core/dist/core/install/sources/git-source.js.map +1 -1
- package/packages/core/dist/core/install/sources/path-source.d.ts.map +1 -1
- package/packages/core/dist/core/install/sources/path-source.js +8 -0
- package/packages/core/dist/core/install/sources/path-source.js.map +1 -1
- package/packages/core/dist/core/install/strategies/flow-based-strategy.d.ts.map +1 -1
- package/packages/core/dist/core/install/strategies/flow-based-strategy.js +12 -5
- package/packages/core/dist/core/install/strategies/flow-based-strategy.js.map +1 -1
- package/packages/core/dist/core/install/strategies/types.d.ts +11 -1
- package/packages/core/dist/core/install/strategies/types.d.ts.map +1 -1
- package/packages/core/dist/core/install/unified/context-builders.d.ts +5 -0
- package/packages/core/dist/core/install/unified/context-builders.d.ts.map +1 -1
- package/packages/core/dist/core/install/unified/context-builders.js +12 -0
- package/packages/core/dist/core/install/unified/context-builders.js.map +1 -1
- package/packages/core/dist/core/install/unified/context-helpers.d.ts +0 -4
- package/packages/core/dist/core/install/unified/context-helpers.d.ts.map +1 -1
- package/packages/core/dist/core/install/unified/context-helpers.js +0 -24
- package/packages/core/dist/core/install/unified/context-helpers.js.map +1 -1
- package/packages/core/dist/core/install/unified/index.d.ts +1 -1
- package/packages/core/dist/core/install/unified/index.d.ts.map +1 -1
- package/packages/core/dist/core/install/unified/index.js +1 -1
- package/packages/core/dist/core/install/unified/index.js.map +1 -1
- package/packages/core/dist/core/install/unified/multi-context-pipeline.d.ts +6 -0
- package/packages/core/dist/core/install/unified/multi-context-pipeline.d.ts.map +1 -1
- package/packages/core/dist/core/install/unified/multi-context-pipeline.js +11 -4
- package/packages/core/dist/core/install/unified/multi-context-pipeline.js.map +1 -1
- package/packages/core/dist/core/install/unified/phases/conflicts.d.ts.map +1 -1
- package/packages/core/dist/core/install/unified/phases/conflicts.js +1 -1
- package/packages/core/dist/core/install/unified/phases/conflicts.js.map +1 -1
- package/packages/core/dist/core/install/unified/phases/execute.d.ts.map +1 -1
- package/packages/core/dist/core/install/unified/phases/execute.js +5 -5
- package/packages/core/dist/core/install/unified/phases/execute.js.map +1 -1
- package/packages/core/dist/core/install/unified/phases/load-package.js +3 -3
- package/packages/core/dist/core/install/unified/phases/load-package.js.map +1 -1
- package/packages/core/dist/core/install/unified/phases/report.js +1 -1
- package/packages/core/dist/core/install/unified/phases/report.js.map +1 -1
- package/packages/core/dist/core/install/unified/pipeline.d.ts.map +1 -1
- package/packages/core/dist/core/install/unified/pipeline.js +7 -10
- package/packages/core/dist/core/install/unified/pipeline.js.map +1 -1
- package/packages/core/dist/core/install/wave-resolver/content-root-cache.d.ts +24 -0
- package/packages/core/dist/core/install/wave-resolver/content-root-cache.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/content-root-cache.js +71 -0
- package/packages/core/dist/core/install/wave-resolver/content-root-cache.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/context-builder.d.ts +39 -0
- package/packages/core/dist/core/install/wave-resolver/context-builder.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/context-builder.js +148 -0
- package/packages/core/dist/core/install/wave-resolver/context-builder.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/fetcher.d.ts +49 -0
- package/packages/core/dist/core/install/wave-resolver/fetcher.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/fetcher.js +221 -0
- package/packages/core/dist/core/install/wave-resolver/fetcher.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/index-updater.d.ts +23 -0
- package/packages/core/dist/core/install/wave-resolver/index-updater.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/index-updater.js +87 -0
- package/packages/core/dist/core/install/wave-resolver/index-updater.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/index-write-collector.d.ts +101 -0
- package/packages/core/dist/core/install/wave-resolver/index-write-collector.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/index-write-collector.js +194 -0
- package/packages/core/dist/core/install/wave-resolver/index-write-collector.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/index.d.ts +17 -0
- package/packages/core/dist/core/install/wave-resolver/index.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/index.js +16 -0
- package/packages/core/dist/core/install/wave-resolver/index.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/manifest-reader.d.ts +34 -0
- package/packages/core/dist/core/install/wave-resolver/manifest-reader.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/manifest-reader.js +112 -0
- package/packages/core/dist/core/install/wave-resolver/manifest-reader.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/types.d.ts +210 -0
- package/packages/core/dist/core/install/wave-resolver/types.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/types.js +6 -0
- package/packages/core/dist/core/install/wave-resolver/types.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/version-solver.d.ts +65 -0
- package/packages/core/dist/core/install/wave-resolver/version-solver.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/version-solver.js +166 -0
- package/packages/core/dist/core/install/wave-resolver/version-solver.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/wave-engine.d.ts +16 -0
- package/packages/core/dist/core/install/wave-resolver/wave-engine.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/wave-engine.js +337 -0
- package/packages/core/dist/core/install/wave-resolver/wave-engine.js.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/wave-installer.d.ts +50 -0
- package/packages/core/dist/core/install/wave-resolver/wave-installer.d.ts.map +1 -0
- package/packages/core/dist/core/install/wave-resolver/wave-installer.js +246 -0
- package/packages/core/dist/core/install/wave-resolver/wave-installer.js.map +1 -0
- package/packages/core/dist/core/ports/buffered-output.d.ts +36 -0
- package/packages/core/dist/core/ports/buffered-output.d.ts.map +1 -0
- package/packages/core/dist/core/ports/buffered-output.js +89 -0
- package/packages/core/dist/core/ports/buffered-output.js.map +1 -0
- package/packages/core/dist/core/ports/resolve.d.ts +0 -13
- package/packages/core/dist/core/ports/resolve.d.ts.map +1 -1
- package/packages/core/dist/core/ports/resolve.js +0 -28
- package/packages/core/dist/core/ports/resolve.js.map +1 -1
- package/packages/core/dist/core/remove/removal-confirmation.d.ts +4 -1
- package/packages/core/dist/core/remove/removal-confirmation.d.ts.map +1 -1
- package/packages/core/dist/core/remove/removal-confirmation.js +5 -4
- package/packages/core/dist/core/remove/removal-confirmation.js.map +1 -1
- package/packages/core/dist/core/remove/remove-from-source-pipeline.d.ts.map +1 -1
- package/packages/core/dist/core/remove/remove-from-source-pipeline.js +1 -10
- package/packages/core/dist/core/remove/remove-from-source-pipeline.js.map +1 -1
- package/packages/core/dist/core/uninstall/uninstall-executor.js +1 -1
- package/packages/core/dist/core/uninstall/uninstall-executor.js.map +1 -1
- package/packages/core/dist/core/uninstall/uninstall-reporter.d.ts +2 -2
- package/packages/core/dist/core/uninstall/uninstall-reporter.d.ts.map +1 -1
- package/packages/core/dist/core/uninstall/uninstall-reporter.js +4 -4
- package/packages/core/dist/core/uninstall/uninstall-reporter.js.map +1 -1
- package/packages/core/dist/index.d.ts +1 -1
- package/packages/core/dist/index.d.ts.map +1 -1
- package/packages/core/dist/types/execution-context.d.ts +40 -10
- package/packages/core/dist/types/execution-context.d.ts.map +1 -1
- package/packages/core/dist/utils/concurrency-pool.d.ts +34 -0
- package/packages/core/dist/utils/concurrency-pool.d.ts.map +1 -0
- package/packages/core/dist/utils/concurrency-pool.js +58 -0
- package/packages/core/dist/utils/concurrency-pool.js.map +1 -0
- package/packages/core/dist/utils/plugin-naming.d.ts +11 -3
- package/packages/core/dist/utils/plugin-naming.d.ts.map +1 -1
- package/packages/core/dist/utils/plugin-naming.js +27 -7
- package/packages/core/dist/utils/plugin-naming.js.map +1 -1
- package/plans/wave-resolver.md +254 -0
- package/.claude/agents/essentials/code-simplifier.md +0 -52
- package/.claude/commands/essentials/cleanup.md +0 -1
- package/.claude/commands/essentials/review.md +0 -8
- package/.claude/commands/git/commit.md +0 -5
|
@@ -0,0 +1,1312 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createHttpClient
|
|
4
|
+
} from "./chunk-6DITYAFA.js";
|
|
5
|
+
import {
|
|
6
|
+
authManager
|
|
7
|
+
} from "./chunk-C6FY55UP.js";
|
|
8
|
+
import {
|
|
9
|
+
classifyInputBase
|
|
10
|
+
} from "./chunk-AR7GJCG6.js";
|
|
11
|
+
import {
|
|
12
|
+
classifyPackageInput
|
|
13
|
+
} from "./chunk-OUZRMGPV.js";
|
|
14
|
+
import {
|
|
15
|
+
walkFiles
|
|
16
|
+
} from "./chunk-A6ISKBNM.js";
|
|
17
|
+
import {
|
|
18
|
+
createWorkspacePackageYml,
|
|
19
|
+
ensureLocalOpenPackageStructure,
|
|
20
|
+
loadPackageFromPath,
|
|
21
|
+
packageManager
|
|
22
|
+
} from "./chunk-D3O7LY2Q.js";
|
|
23
|
+
import {
|
|
24
|
+
detectPluginType,
|
|
25
|
+
extractPackageFromTarball,
|
|
26
|
+
formatVersionLabel,
|
|
27
|
+
verifyTarballIntegrity
|
|
28
|
+
} from "./chunk-HYKYECAE.js";
|
|
29
|
+
import {
|
|
30
|
+
getLocalOpenPackageDir,
|
|
31
|
+
getLocalPackageYmlPath
|
|
32
|
+
} from "./chunk-VXNS3X5O.js";
|
|
33
|
+
import {
|
|
34
|
+
normalizeGitUrl
|
|
35
|
+
} from "./chunk-WNRXZLWW.js";
|
|
36
|
+
import {
|
|
37
|
+
resolveDeclaredPath
|
|
38
|
+
} from "./chunk-FRYA3JAQ.js";
|
|
39
|
+
import {
|
|
40
|
+
resolveOutput
|
|
41
|
+
} from "./chunk-RAKMX654.js";
|
|
42
|
+
import {
|
|
43
|
+
ensureRegistryDirectories,
|
|
44
|
+
getPackageVersionPath
|
|
45
|
+
} from "./chunk-GDVFS3YP.js";
|
|
46
|
+
import {
|
|
47
|
+
parsePackageYml
|
|
48
|
+
} from "./chunk-427DCURL.js";
|
|
49
|
+
import {
|
|
50
|
+
splitFrontmatter
|
|
51
|
+
} from "./chunk-VQ2KY6CK.js";
|
|
52
|
+
import {
|
|
53
|
+
normalizePlatforms
|
|
54
|
+
} from "./chunk-N43IXOND.js";
|
|
55
|
+
import {
|
|
56
|
+
normalizePathForProcessing
|
|
57
|
+
} from "./chunk-YMKK4XPN.js";
|
|
58
|
+
import {
|
|
59
|
+
DIR_PATTERNS,
|
|
60
|
+
FILE_PATTERNS,
|
|
61
|
+
PACKAGE_PATHS
|
|
62
|
+
} from "./chunk-IHVZ5AUJ.js";
|
|
63
|
+
import {
|
|
64
|
+
ensureDir,
|
|
65
|
+
exists,
|
|
66
|
+
readTextFile,
|
|
67
|
+
writeTextFile
|
|
68
|
+
} from "./chunk-S47F4OG4.js";
|
|
69
|
+
import {
|
|
70
|
+
ConfigError,
|
|
71
|
+
ValidationError
|
|
72
|
+
} from "./chunk-ID4SVDQZ.js";
|
|
73
|
+
import {
|
|
74
|
+
logger
|
|
75
|
+
} from "./chunk-5EFWGD33.js";
|
|
76
|
+
|
|
77
|
+
// ../core/src/utils/resolution-mode.ts
|
|
78
|
+
function determineResolutionMode(options) {
|
|
79
|
+
return options.resolutionMode ? options.resolutionMode : options.remote ? "remote-primary" : options.local ? "local-only" : "default";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ../core/src/core/install/validators/options-validator.ts
|
|
83
|
+
function validateResolutionFlags(options) {
|
|
84
|
+
if (options.remote && options.local)
|
|
85
|
+
throw new Error("--remote and --local cannot be used together. Choose one resolution mode.");
|
|
86
|
+
}
|
|
87
|
+
function validateConflictStrategy(strategy) {
|
|
88
|
+
if (!strategy) return;
|
|
89
|
+
let normalized = strategy.toLowerCase();
|
|
90
|
+
if (![
|
|
91
|
+
"namespace",
|
|
92
|
+
"overwrite",
|
|
93
|
+
"skip",
|
|
94
|
+
"ask"
|
|
95
|
+
].includes(normalized))
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Invalid --conflicts value '${strategy}'. Use one of: namespace, overwrite, skip, ask.`
|
|
98
|
+
);
|
|
99
|
+
return normalized;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ../core/src/core/install/preprocessing/options-normalizer.ts
|
|
103
|
+
function normalizePluginsOption(value) {
|
|
104
|
+
if (!value || value.length === 0)
|
|
105
|
+
return;
|
|
106
|
+
let plugins = [...new Set(value)];
|
|
107
|
+
return plugins.length > 0 ? plugins : void 0;
|
|
108
|
+
}
|
|
109
|
+
function normalizeInstallOptions(options) {
|
|
110
|
+
let platforms = normalizePlatforms(options.platforms), plugins = normalizePluginsOption(options.plugins), rawConflictStrategy = options.conflicts ?? options.conflictStrategy, conflictStrategy = validateConflictStrategy(rawConflictStrategy) ?? "namespace", resolutionMode = determineResolutionMode(options);
|
|
111
|
+
return {
|
|
112
|
+
...options,
|
|
113
|
+
platforms,
|
|
114
|
+
plugins,
|
|
115
|
+
conflictStrategy,
|
|
116
|
+
resolutionMode,
|
|
117
|
+
agents: options.agents,
|
|
118
|
+
skills: options.skills,
|
|
119
|
+
rules: options.rules,
|
|
120
|
+
commands: options.commands,
|
|
121
|
+
interactive: options.interactive
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ../core/src/core/install/preprocessing/input-classifier.ts
|
|
126
|
+
async function classifyInput(input, options, execContext) {
|
|
127
|
+
let hasConvenienceFilters = !!(options.agents?.length || options.skills?.length || options.rules?.length || options.commands?.length), base = await classifyInputBase(input, execContext.sourceCwd);
|
|
128
|
+
return enrichWithInstallFeatures(base, hasConvenienceFilters);
|
|
129
|
+
}
|
|
130
|
+
function enrichWithInstallFeatures(base, hasConvenienceFilters) {
|
|
131
|
+
let features = {
|
|
132
|
+
hasConvenienceFilters,
|
|
133
|
+
hasResourcePath: !1
|
|
134
|
+
};
|
|
135
|
+
switch (base.type) {
|
|
136
|
+
case "bulk":
|
|
137
|
+
return { type: "bulk", features };
|
|
138
|
+
case "git":
|
|
139
|
+
return {
|
|
140
|
+
type: "git",
|
|
141
|
+
gitUrl: base.gitUrl,
|
|
142
|
+
gitRef: base.gitRef,
|
|
143
|
+
resourcePath: base.gitPath,
|
|
144
|
+
features: {
|
|
145
|
+
...features,
|
|
146
|
+
hasResourcePath: !!base.gitPath
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
case "local-path":
|
|
150
|
+
return {
|
|
151
|
+
type: "path",
|
|
152
|
+
localPath: base.absolutePath,
|
|
153
|
+
features
|
|
154
|
+
};
|
|
155
|
+
case "registry":
|
|
156
|
+
return {
|
|
157
|
+
type: "registry",
|
|
158
|
+
packageName: base.packageName,
|
|
159
|
+
version: base.version,
|
|
160
|
+
resourcePath: base.registryPath,
|
|
161
|
+
features: {
|
|
162
|
+
...features,
|
|
163
|
+
hasResourcePath: !!base.registryPath
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ../core/src/core/install/preprocessing/base-resolver.ts
|
|
170
|
+
import { join, relative } from "path";
|
|
171
|
+
import { stat } from "fs/promises";
|
|
172
|
+
async function resolveResourceScoping(repoRoot, baseAbs, resourcePath, options) {
|
|
173
|
+
let absResourcePath = join(repoRoot, resourcePath), rawRel = relative(baseAbs, absResourcePath).replace(/\\/g, "/");
|
|
174
|
+
if (rawRel.startsWith(".."))
|
|
175
|
+
return null;
|
|
176
|
+
let relToBaseRaw = rawRel.replace(/^\.\/?/, ""), isDirectory = !1;
|
|
177
|
+
try {
|
|
178
|
+
isDirectory = (await stat(absResourcePath)).isDirectory();
|
|
179
|
+
} catch {
|
|
180
|
+
if (options?.strict)
|
|
181
|
+
throw new ValidationError(
|
|
182
|
+
`The specified resource path does not exist in the repository: ${resourcePath}
|
|
183
|
+
|
|
184
|
+
Please verify the path. The file or directory may have been moved, or you may have meant a different path.`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
let prefix = relToBaseRaw.replace(/\/$/, ""), pattern = isDirectory ? prefix ? `${prefix}/**` : "**" : relToBaseRaw;
|
|
188
|
+
return { relPath: relToBaseRaw, isDirectory, pattern };
|
|
189
|
+
}
|
|
190
|
+
function applyBaseDetection(ctx, loaded) {
|
|
191
|
+
let baseDetection = loaded.sourceMetadata?.baseDetection;
|
|
192
|
+
if (!baseDetection)
|
|
193
|
+
return {};
|
|
194
|
+
if (ctx.source._baseDetectionPerformed)
|
|
195
|
+
return logger.debug("Base detection already applied, skipping redundant application"), {};
|
|
196
|
+
if (loaded.pluginMetadata?.pluginType === "marketplace")
|
|
197
|
+
return ctx.source._baseDetectionPerformed = !0, { specialHandling: "marketplace" };
|
|
198
|
+
baseDetection?.base && (ctx.detectedBase = baseDetection.base, ctx.source.detectedBase = baseDetection.base), baseDetection?.matchedPattern && !ctx.matchedPattern && (ctx.matchedPattern = baseDetection.matchedPattern), baseDetection?.matchType && (ctx.baseSource = baseDetection.matchType);
|
|
199
|
+
let effectiveContentRoot = ctx.detectedBase || loaded.contentRoot;
|
|
200
|
+
effectiveContentRoot && (ctx.source.contentRoot = effectiveContentRoot);
|
|
201
|
+
let repoRoot = loaded.sourceMetadata?.repoPath;
|
|
202
|
+
return !ctx.baseRelative && repoRoot && ctx.detectedBase ? ctx.baseRelative = relative(repoRoot, ctx.detectedBase) || "." : !ctx.baseRelative && loaded.contentRoot && ctx.detectedBase && (ctx.baseRelative = relative(loaded.contentRoot, ctx.detectedBase) || "."), ctx.source._baseDetectionPerformed = !0, baseDetection?.matchType === "marketplace" ? { specialHandling: "marketplace" } : baseDetection?.matchType === "ambiguous" && Array.isArray(baseDetection.ambiguousMatches) ? { specialHandling: "ambiguous", ambiguousMatches: baseDetection.ambiguousMatches } : {};
|
|
203
|
+
}
|
|
204
|
+
async function computePathScoping(ctx, loaded, resourcePath) {
|
|
205
|
+
if (ctx._pathScopingPerformed) {
|
|
206
|
+
logger.debug("Path scoping already computed, skipping redundant computation");
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
let repoRoot = loaded.sourceMetadata?.repoPath || loaded.contentRoot;
|
|
210
|
+
if (!repoRoot)
|
|
211
|
+
return;
|
|
212
|
+
let baseAbs = ctx.detectedBase || loaded.contentRoot;
|
|
213
|
+
if (!baseAbs)
|
|
214
|
+
return;
|
|
215
|
+
let result = await resolveResourceScoping(repoRoot, baseAbs, resourcePath, { strict: !0 });
|
|
216
|
+
if (!result)
|
|
217
|
+
throw new ValidationError(
|
|
218
|
+
`The specified resource path is outside the package base: ${resourcePath}
|
|
219
|
+
|
|
220
|
+
Please verify the path is within the package you are installing.`
|
|
221
|
+
);
|
|
222
|
+
ctx.matchedPattern = result.pattern, ctx._pathScopingPerformed = !0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ../core/src/core/install/preprocessing/convenience-preprocessor.ts
|
|
226
|
+
import { join as join4 } from "path";
|
|
227
|
+
|
|
228
|
+
// ../core/src/core/install/convenience-matchers.ts
|
|
229
|
+
import { join as join2, basename, dirname, relative as relative2, resolve, sep } from "path";
|
|
230
|
+
async function applyConvenienceFilters(basePath, repoRoot, options) {
|
|
231
|
+
let resources = [], errors = [], baseRoot = resolve(basePath), repoRootResolved = resolve(repoRoot), scopeRoots = options.pluginScope?.map((scope) => resolve(repoRootResolved, scope)) ?? [], isInScope = (absPath) => scopeRoots.length === 0 ? !0 : scopeRoots.some((scopeRoot) => absPath === scopeRoot ? !0 : absPath.startsWith(`${scopeRoot}${sep}`)), toRepoRelative = (absPath) => relative2(repoRootResolved, absPath).replace(/\\/g, "/").replace(/^\.\/?/, "");
|
|
232
|
+
if (options.agents && options.agents.length > 0) {
|
|
233
|
+
let agentResults = await matchMarkdownResources(basePath, "agents", "Agent", options.agents);
|
|
234
|
+
for (let result of agentResults)
|
|
235
|
+
if (result.found && result.path) {
|
|
236
|
+
let absPath = resolve(result.path);
|
|
237
|
+
if (!isInScope(absPath)) {
|
|
238
|
+
errors.push(`Agent '${result.name}' not found in selected plugin scope`);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
let resourcePath = toRepoRelative(absPath);
|
|
242
|
+
resources.push({
|
|
243
|
+
name: result.name,
|
|
244
|
+
resourceType: "agent",
|
|
245
|
+
resourcePath,
|
|
246
|
+
basePath: baseRoot,
|
|
247
|
+
resourceKind: "file",
|
|
248
|
+
matchedBy: result.matchedBy || "filename",
|
|
249
|
+
resourceVersion: result.version
|
|
250
|
+
});
|
|
251
|
+
} else result.error && errors.push(result.error);
|
|
252
|
+
}
|
|
253
|
+
if (options.skills && options.skills.length > 0) {
|
|
254
|
+
let skillResults = await matchSkills(basePath, options.skills);
|
|
255
|
+
for (let result of skillResults)
|
|
256
|
+
if (result.found && result.path && result.installDir) {
|
|
257
|
+
let absDir = resolve(result.installDir);
|
|
258
|
+
if (!isInScope(absDir)) {
|
|
259
|
+
errors.push(`Skill '${result.name}' not found in selected plugin scope`);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
let resourcePath = toRepoRelative(absDir);
|
|
263
|
+
resources.push({
|
|
264
|
+
name: result.name,
|
|
265
|
+
resourceType: "skill",
|
|
266
|
+
resourcePath,
|
|
267
|
+
basePath: baseRoot,
|
|
268
|
+
resourceKind: "directory",
|
|
269
|
+
matchedBy: result.matchedBy || "dirname",
|
|
270
|
+
resourceVersion: result.version
|
|
271
|
+
});
|
|
272
|
+
} else result.error && errors.push(result.error);
|
|
273
|
+
}
|
|
274
|
+
if (options.rules && options.rules.length > 0) {
|
|
275
|
+
let ruleResults = await matchMarkdownResources(basePath, "rules", "Rule", options.rules);
|
|
276
|
+
for (let result of ruleResults)
|
|
277
|
+
if (result.found && result.path) {
|
|
278
|
+
let absPath = resolve(result.path);
|
|
279
|
+
if (!isInScope(absPath)) {
|
|
280
|
+
errors.push(`Rule '${result.name}' not found in selected plugin scope`);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
let resourcePath = toRepoRelative(absPath);
|
|
284
|
+
resources.push({
|
|
285
|
+
name: result.name,
|
|
286
|
+
resourceType: "rule",
|
|
287
|
+
resourcePath,
|
|
288
|
+
basePath: baseRoot,
|
|
289
|
+
resourceKind: "file",
|
|
290
|
+
matchedBy: result.matchedBy || "filename",
|
|
291
|
+
resourceVersion: result.version
|
|
292
|
+
});
|
|
293
|
+
} else result.error && errors.push(result.error);
|
|
294
|
+
}
|
|
295
|
+
if (options.commands && options.commands.length > 0) {
|
|
296
|
+
let commandResults = await matchMarkdownResources(basePath, "commands", "Command", options.commands);
|
|
297
|
+
for (let result of commandResults)
|
|
298
|
+
if (result.found && result.path) {
|
|
299
|
+
let absPath = resolve(result.path);
|
|
300
|
+
if (!isInScope(absPath)) {
|
|
301
|
+
errors.push(`Command '${result.name}' not found in selected plugin scope`);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
let resourcePath = toRepoRelative(absPath);
|
|
305
|
+
resources.push({
|
|
306
|
+
name: result.name,
|
|
307
|
+
resourceType: "command",
|
|
308
|
+
resourcePath,
|
|
309
|
+
basePath: baseRoot,
|
|
310
|
+
resourceKind: "file",
|
|
311
|
+
matchedBy: result.matchedBy || "filename",
|
|
312
|
+
resourceVersion: result.version
|
|
313
|
+
});
|
|
314
|
+
} else result.error && errors.push(result.error);
|
|
315
|
+
}
|
|
316
|
+
return logger.info("Convenience filter results", {
|
|
317
|
+
resourceCount: resources.length,
|
|
318
|
+
errorCount: errors.length
|
|
319
|
+
}), {
|
|
320
|
+
resources,
|
|
321
|
+
errors
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
async function matchMarkdownResources(basePath, subDir, resourceLabel, requestedNames) {
|
|
325
|
+
let results = [], dir = join2(basePath, subDir), files = [];
|
|
326
|
+
if (await exists(dir))
|
|
327
|
+
for await (let file of walkFiles(dir))
|
|
328
|
+
file.endsWith(".md") && files.push(file);
|
|
329
|
+
for (let name of requestedNames) {
|
|
330
|
+
let match = await findMarkdownResourceByName(files, name);
|
|
331
|
+
match ? results.push({
|
|
332
|
+
name,
|
|
333
|
+
found: !0,
|
|
334
|
+
path: match.path,
|
|
335
|
+
matchedBy: match.matchedBy,
|
|
336
|
+
version: match.version
|
|
337
|
+
}) : results.push({
|
|
338
|
+
name,
|
|
339
|
+
found: !1,
|
|
340
|
+
error: `${resourceLabel} '${name}' not found`
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
return results;
|
|
344
|
+
}
|
|
345
|
+
async function findMarkdownResourceByName(files, name) {
|
|
346
|
+
for (let file of files)
|
|
347
|
+
try {
|
|
348
|
+
let content = await readTextFile(file), { frontmatter } = splitFrontmatter(content);
|
|
349
|
+
if (frontmatter?.name === name) {
|
|
350
|
+
let version = extractVersionFromFrontmatter(frontmatter);
|
|
351
|
+
return { path: file, matchedBy: "frontmatter", version };
|
|
352
|
+
}
|
|
353
|
+
} catch {
|
|
354
|
+
}
|
|
355
|
+
let byFilename = files.filter((f) => basename(f, ".md") === name);
|
|
356
|
+
if (byFilename.length === 1) {
|
|
357
|
+
let file = byFilename[0], version = await extractVersionFromFile(file);
|
|
358
|
+
return { path: file, matchedBy: "filename", version };
|
|
359
|
+
}
|
|
360
|
+
if (byFilename.length > 1) {
|
|
361
|
+
let deepest = byFilename.sort(
|
|
362
|
+
(a, b) => b.split("/").length - a.split("/").length
|
|
363
|
+
)[0], version = await extractVersionFromFile(deepest);
|
|
364
|
+
return { path: deepest, matchedBy: "filename", version };
|
|
365
|
+
}
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
async function matchSkills(basePath, requestedNames) {
|
|
369
|
+
let results = [], skillsDir = join2(basePath, "skills"), skillFiles = [];
|
|
370
|
+
if (await exists(skillsDir))
|
|
371
|
+
for await (let file of walkFiles(skillsDir))
|
|
372
|
+
basename(file) === "SKILL.md" && skillFiles.push(file);
|
|
373
|
+
for (let name of requestedNames) {
|
|
374
|
+
let match = await findSkillByName(skillFiles, name);
|
|
375
|
+
match ? results.push({
|
|
376
|
+
name,
|
|
377
|
+
found: !0,
|
|
378
|
+
path: match.path,
|
|
379
|
+
installDir: dirname(match.path),
|
|
380
|
+
// Install entire parent directory
|
|
381
|
+
matchedBy: match.matchedBy,
|
|
382
|
+
version: match.version
|
|
383
|
+
}) : results.push({
|
|
384
|
+
name,
|
|
385
|
+
found: !1,
|
|
386
|
+
error: `Skill '${name}' not found (requires SKILL.md)`
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
return results;
|
|
390
|
+
}
|
|
391
|
+
async function findSkillByName(skillFiles, name) {
|
|
392
|
+
for (let file of skillFiles)
|
|
393
|
+
try {
|
|
394
|
+
let content = await readTextFile(file), { frontmatter } = splitFrontmatter(content);
|
|
395
|
+
if (frontmatter?.name === name) {
|
|
396
|
+
let version = extractVersionFromFrontmatter(frontmatter);
|
|
397
|
+
return { path: file, matchedBy: "frontmatter", version };
|
|
398
|
+
}
|
|
399
|
+
} catch {
|
|
400
|
+
}
|
|
401
|
+
for (let file of skillFiles)
|
|
402
|
+
if (basename(dirname(file)) === name) {
|
|
403
|
+
let version = await extractVersionFromFile(file);
|
|
404
|
+
return { path: file, matchedBy: "dirname", version };
|
|
405
|
+
}
|
|
406
|
+
let matchingByNested = skillFiles.filter((file) => dirname(file).split("/").includes(name));
|
|
407
|
+
if (matchingByNested.length > 0) {
|
|
408
|
+
let deepest = matchingByNested.sort(
|
|
409
|
+
(a, b) => b.split("/").length - a.split("/").length
|
|
410
|
+
)[0], version = await extractVersionFromFile(deepest);
|
|
411
|
+
return { path: deepest, matchedBy: "dirname", version };
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
function displayFilterErrors(errors, output) {
|
|
416
|
+
if (errors.length === 0)
|
|
417
|
+
return;
|
|
418
|
+
let out = output ?? resolveOutput();
|
|
419
|
+
out.error(`
|
|
420
|
+
The following resources were not found:`);
|
|
421
|
+
for (let error of errors)
|
|
422
|
+
out.error(` - ${error}`);
|
|
423
|
+
}
|
|
424
|
+
function extractVersionFromFrontmatter(frontmatter) {
|
|
425
|
+
if (!frontmatter || typeof frontmatter != "object")
|
|
426
|
+
return;
|
|
427
|
+
let version = frontmatter.version ?? frontmatter.metadata?.version;
|
|
428
|
+
if (typeof version == "string") {
|
|
429
|
+
let trimmed = version.trim();
|
|
430
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
async function extractVersionFromFile(filePath) {
|
|
434
|
+
try {
|
|
435
|
+
let content = await readTextFile(filePath), { frontmatter } = splitFrontmatter(content);
|
|
436
|
+
return extractVersionFromFrontmatter(frontmatter);
|
|
437
|
+
} catch {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// ../core/src/core/install/unified/context-builders.ts
|
|
443
|
+
import { basename as basename2, join as join3, relative as relative3 } from "path";
|
|
444
|
+
async function buildRegistryInstallContext(execContext, packageName, options) {
|
|
445
|
+
let source = {
|
|
446
|
+
type: "registry",
|
|
447
|
+
packageName,
|
|
448
|
+
version: options.version,
|
|
449
|
+
registryPath: options.registryPath
|
|
450
|
+
};
|
|
451
|
+
return {
|
|
452
|
+
execution: execContext,
|
|
453
|
+
targetDir: execContext.targetDir,
|
|
454
|
+
source,
|
|
455
|
+
mode: "install",
|
|
456
|
+
options,
|
|
457
|
+
platforms: normalizePlatforms(options.platforms) || [],
|
|
458
|
+
resolvedPackages: [],
|
|
459
|
+
warnings: [],
|
|
460
|
+
errors: []
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
async function buildPathInstallContext(execContext, sourcePath, options) {
|
|
464
|
+
let source = {
|
|
465
|
+
type: "path",
|
|
466
|
+
packageName: "",
|
|
467
|
+
// Populated after loading
|
|
468
|
+
localPath: sourcePath,
|
|
469
|
+
sourceType: options.sourceType
|
|
470
|
+
};
|
|
471
|
+
return {
|
|
472
|
+
execution: execContext,
|
|
473
|
+
targetDir: execContext.targetDir,
|
|
474
|
+
source,
|
|
475
|
+
mode: "install",
|
|
476
|
+
options,
|
|
477
|
+
platforms: normalizePlatforms(options.platforms) || [],
|
|
478
|
+
resolvedPackages: [],
|
|
479
|
+
warnings: [],
|
|
480
|
+
errors: []
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
async function buildGitInstallContext(execContext, gitUrl, options) {
|
|
484
|
+
let source = {
|
|
485
|
+
type: "git",
|
|
486
|
+
packageName: "",
|
|
487
|
+
// Populated after loading
|
|
488
|
+
gitUrl,
|
|
489
|
+
gitRef: options.gitRef,
|
|
490
|
+
gitPath: options.gitPath
|
|
491
|
+
};
|
|
492
|
+
return {
|
|
493
|
+
execution: execContext,
|
|
494
|
+
targetDir: execContext.targetDir,
|
|
495
|
+
source,
|
|
496
|
+
mode: "install",
|
|
497
|
+
options,
|
|
498
|
+
platforms: normalizePlatforms(options.platforms) || [],
|
|
499
|
+
resolvedPackages: [],
|
|
500
|
+
warnings: [],
|
|
501
|
+
errors: []
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
async function buildWorkspaceRootInstallContext(execContext, options, mode = "install") {
|
|
505
|
+
let cwd = execContext.targetDir;
|
|
506
|
+
await ensureLocalOpenPackageStructure(cwd), await createWorkspacePackageYml(cwd);
|
|
507
|
+
let openpackageDir = getLocalOpenPackageDir(cwd), packageYmlPath = getLocalPackageYmlPath(cwd);
|
|
508
|
+
if (!await exists(packageYmlPath))
|
|
509
|
+
return null;
|
|
510
|
+
let config;
|
|
511
|
+
try {
|
|
512
|
+
config = await parsePackageYml(packageYmlPath);
|
|
513
|
+
} catch (error) {
|
|
514
|
+
return logger.warn(`Failed to read workspace manifest: ${error}`), null;
|
|
515
|
+
}
|
|
516
|
+
let source = {
|
|
517
|
+
type: "workspace",
|
|
518
|
+
packageName: config.name || basename2(cwd),
|
|
519
|
+
version: config.version,
|
|
520
|
+
contentRoot: openpackageDir
|
|
521
|
+
};
|
|
522
|
+
return {
|
|
523
|
+
execution: execContext,
|
|
524
|
+
targetDir: execContext.targetDir,
|
|
525
|
+
source,
|
|
526
|
+
mode,
|
|
527
|
+
options: mode === "apply" ? { ...options, force: !0 } : options,
|
|
528
|
+
platforms: normalizePlatforms(options.platforms) || [],
|
|
529
|
+
resolvedPackages: [],
|
|
530
|
+
warnings: [],
|
|
531
|
+
errors: []
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
async function buildInstallContext(execContext, packageInput, options) {
|
|
535
|
+
if (!packageInput)
|
|
536
|
+
return buildBulkInstallContexts(execContext, options);
|
|
537
|
+
let classification = await classifyPackageInput(packageInput, execContext.sourceCwd);
|
|
538
|
+
switch (classification.type) {
|
|
539
|
+
case "registry":
|
|
540
|
+
return buildRegistryInstallContext(execContext, classification.name, options);
|
|
541
|
+
case "directory":
|
|
542
|
+
case "tarball":
|
|
543
|
+
return buildPathInstallContext(execContext, classification.resolvedPath, {
|
|
544
|
+
...options,
|
|
545
|
+
sourceType: classification.type
|
|
546
|
+
});
|
|
547
|
+
case "git":
|
|
548
|
+
return buildGitInstallContext(execContext, classification.gitUrl, {
|
|
549
|
+
...options,
|
|
550
|
+
gitRef: classification.gitRef,
|
|
551
|
+
gitPath: classification.gitPath
|
|
552
|
+
});
|
|
553
|
+
default:
|
|
554
|
+
throw new Error(`Unknown package input type: ${classification.type}`);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
async function buildBulkInstallContexts(execContext, options) {
|
|
558
|
+
let cwd = execContext.targetDir, dependencyContexts = [], workspaceContext = await buildWorkspaceRootInstallContext(execContext, options, "install");
|
|
559
|
+
await createWorkspacePackageYml(cwd);
|
|
560
|
+
let opkgYmlPath = getLocalPackageYmlPath(cwd), opkgYml = await parsePackageYml(opkgYmlPath), workspacePackageName = workspaceContext?.source.packageName, deps = opkgYml.packages ?? opkgYml.dependencies ?? [], devDeps = opkgYml.devDependencies ?? opkgYml["dev-dependencies"] ?? [], allDeps = [...deps, ...devDeps].filter(Boolean), seen = /* @__PURE__ */ new Set();
|
|
561
|
+
if (allDeps.length > 0)
|
|
562
|
+
for (let dep of allDeps) {
|
|
563
|
+
let dedupeKey = JSON.stringify({
|
|
564
|
+
name: dep?.name ?? null,
|
|
565
|
+
url: dep?.url ?? dep?.git ?? null,
|
|
566
|
+
ref: dep?.ref ?? null,
|
|
567
|
+
path: dep?.path ?? null,
|
|
568
|
+
version: dep?.version ?? null,
|
|
569
|
+
base: dep?.base ?? null
|
|
570
|
+
});
|
|
571
|
+
if (seen.has(dedupeKey) || (seen.add(dedupeKey), workspacePackageName && dep.name === workspacePackageName))
|
|
572
|
+
continue;
|
|
573
|
+
let source;
|
|
574
|
+
if (dep.git || dep.url) {
|
|
575
|
+
let gitUrlRaw = dep.url || dep.git, [gitUrl, embeddedRef] = gitUrlRaw.includes("#") ? gitUrlRaw.split("#", 2) : [gitUrlRaw, void 0], gitRef = embeddedRef || dep.ref, resourcePathFromName, depName = String(dep.name ?? "");
|
|
576
|
+
if (depName.startsWith("gh@")) {
|
|
577
|
+
let parts = depName.slice(3).split("/").filter(Boolean);
|
|
578
|
+
parts.length > 2 && (resourcePathFromName = parts.slice(2).join("/"));
|
|
579
|
+
}
|
|
580
|
+
let effectiveResourcePath = dep.path || resourcePathFromName, shouldTreatPathAsResource = depName.startsWith("gh@");
|
|
581
|
+
source = {
|
|
582
|
+
type: "git",
|
|
583
|
+
packageName: dep.name,
|
|
584
|
+
gitUrl,
|
|
585
|
+
gitRef,
|
|
586
|
+
gitPath: shouldTreatPathAsResource ? void 0 : dep.path,
|
|
587
|
+
resourcePath: shouldTreatPathAsResource ? effectiveResourcePath : void 0,
|
|
588
|
+
manifestBase: dep.base
|
|
589
|
+
// Phase 5: Pass manifest base to source
|
|
590
|
+
};
|
|
591
|
+
} else if (dep.path) {
|
|
592
|
+
let resolved = resolveDeclaredPath(dep.path, cwd), isTarball = dep.path.endsWith(".tgz") || dep.path.endsWith(".tar.gz");
|
|
593
|
+
source = {
|
|
594
|
+
type: "path",
|
|
595
|
+
packageName: dep.name,
|
|
596
|
+
localPath: resolved.absolute,
|
|
597
|
+
sourceType: isTarball ? "tarball" : "directory",
|
|
598
|
+
manifestBase: dep.base
|
|
599
|
+
// Phase 5: Pass manifest base to source
|
|
600
|
+
};
|
|
601
|
+
} else
|
|
602
|
+
source = {
|
|
603
|
+
type: "registry",
|
|
604
|
+
packageName: dep.name,
|
|
605
|
+
version: dep.version,
|
|
606
|
+
manifestBase: dep.base
|
|
607
|
+
// Phase 5: Pass manifest base to source
|
|
608
|
+
};
|
|
609
|
+
let context = {
|
|
610
|
+
execution: execContext,
|
|
611
|
+
targetDir: execContext.targetDir,
|
|
612
|
+
source,
|
|
613
|
+
mode: "install",
|
|
614
|
+
options,
|
|
615
|
+
platforms: normalizePlatforms(options.platforms) || [],
|
|
616
|
+
resolvedPackages: [],
|
|
617
|
+
warnings: [],
|
|
618
|
+
errors: []
|
|
619
|
+
};
|
|
620
|
+
dep.base && (context.baseRelative = dep.base, context.baseSource = "manifest"), dependencyContexts.push(context);
|
|
621
|
+
}
|
|
622
|
+
return { workspaceContext: workspaceContext ?? null, dependencyContexts };
|
|
623
|
+
}
|
|
624
|
+
function buildResourceMatchedPattern(resourceSpec, repoRoot, basePath) {
|
|
625
|
+
let absoluteResourcePath = join3(repoRoot, resourceSpec.resourcePath), relativeToBase = relative3(basePath, absoluteResourcePath).replace(/\\/g, "/").replace(/^\.\/?/, "");
|
|
626
|
+
if (relativeToBase)
|
|
627
|
+
return resourceSpec.resourceKind === "directory" ? `${relativeToBase.replace(/\/$/, "")}/**` : relativeToBase;
|
|
628
|
+
}
|
|
629
|
+
function prepareResourceContextsForMultiInstall(contexts, repoRoot) {
|
|
630
|
+
return contexts.map((rc) => (rc.source.type === "path" && (rc.source.localPath = repoRoot), rc));
|
|
631
|
+
}
|
|
632
|
+
function buildResourceInstallContexts(baseContext, resourceSpecs, repoRoot) {
|
|
633
|
+
let detectedBase = baseContext.detectedBase ?? baseContext.source.contentRoot ?? baseContext.targetDir, baseRelative = baseContext.baseRelative ?? (relative3(repoRoot, detectedBase) || ".");
|
|
634
|
+
return resourceSpecs.map((spec) => {
|
|
635
|
+
let effectiveBase = baseContext.detectedBase ?? spec.basePath, matchedPattern = buildResourceMatchedPattern(spec, repoRoot, effectiveBase) ?? baseContext.matchedPattern, isSingleFile = !!(matchedPattern && !matchedPattern.includes("*") && !matchedPattern.includes("?") && !matchedPattern.includes("[")), baseName = baseContext.source.packageName, scopedName = isSingleFile ? `${baseName}/${matchedPattern}` : baseName, source = {
|
|
636
|
+
...baseContext.source,
|
|
637
|
+
packageName: scopedName,
|
|
638
|
+
resourcePath: spec.resourcePath,
|
|
639
|
+
resourceVersion: spec.resourceVersion
|
|
640
|
+
}, resolvedPackages = baseContext.resolvedPackages;
|
|
641
|
+
return isSingleFile && baseContext.resolvedPackages.length > 0 ? resolvedPackages = baseContext.resolvedPackages.map((pkg) => ({
|
|
642
|
+
...pkg,
|
|
643
|
+
name: pkg.isRoot ? scopedName : pkg.name
|
|
644
|
+
})) : baseContext.resolvedPackages.length === 0 && (resolvedPackages = []), {
|
|
645
|
+
...baseContext,
|
|
646
|
+
source,
|
|
647
|
+
resolvedPackages,
|
|
648
|
+
warnings: [],
|
|
649
|
+
errors: [],
|
|
650
|
+
detectedBase: effectiveBase,
|
|
651
|
+
baseRelative: baseRelative === "" ? "." : baseRelative,
|
|
652
|
+
baseSource: baseContext.baseSource,
|
|
653
|
+
matchedPattern
|
|
654
|
+
};
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// ../core/src/core/install/preprocessing/convenience-preprocessor.ts
|
|
659
|
+
async function findBaseForConvenienceFilters(contentRoot, options) {
|
|
660
|
+
let candidates = [contentRoot];
|
|
661
|
+
for (let sub of [".opencode", ".cursor", ".claude", ".claude-plugin"])
|
|
662
|
+
candidates.push(join4(contentRoot, sub));
|
|
663
|
+
for (let base of candidates)
|
|
664
|
+
if (options.agents?.length && await exists(join4(base, "agents")) || options.skills?.length && await exists(join4(base, "skills")) || options.rules?.length && await exists(join4(base, "rules")) || options.commands?.length && await exists(join4(base, "commands"))) return base;
|
|
665
|
+
return contentRoot;
|
|
666
|
+
}
|
|
667
|
+
async function resolveConvenienceResources(basePath, repoRoot, options) {
|
|
668
|
+
let filterResult = await applyConvenienceFilters(basePath, repoRoot, options);
|
|
669
|
+
if (filterResult.errors.length > 0) {
|
|
670
|
+
if (displayFilterErrors(filterResult.errors), filterResult.resources.length === 0)
|
|
671
|
+
throw new Error("None of the requested resources were found");
|
|
672
|
+
logger.debug(`Continuing with ${filterResult.resources.length} resource(s)`);
|
|
673
|
+
}
|
|
674
|
+
return filterResult.resources;
|
|
675
|
+
}
|
|
676
|
+
async function runConvenienceFilterInstall(context, loaded, options, opts) {
|
|
677
|
+
let contentRoot = loaded.contentRoot, repoRoot = loaded.sourceMetadata?.repoPath ?? contentRoot, basePath = opts?.useDetectedBase && context.detectedBase ? context.detectedBase : await findBaseForConvenienceFilters(contentRoot, options), resources = await resolveConvenienceResources(basePath, repoRoot, options), resourceContexts = buildResourceInstallContexts(context, resources, repoRoot);
|
|
678
|
+
return prepareResourceContextsForMultiInstall(resourceContexts, repoRoot);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// ../core/src/core/remote-pull.ts
|
|
682
|
+
import * as yaml2 from "js-yaml";
|
|
683
|
+
|
|
684
|
+
// ../core/src/utils/manifest-paths.ts
|
|
685
|
+
function normalizePackagePath(path) {
|
|
686
|
+
let trimmed = path.startsWith("/") ? path.slice(1) : path;
|
|
687
|
+
return normalizePathForProcessing(trimmed);
|
|
688
|
+
}
|
|
689
|
+
function isManifestPath(path) {
|
|
690
|
+
let normalized = normalizePackagePath(path);
|
|
691
|
+
return normalized === FILE_PATTERNS.OPENPACKAGE_YML || normalized === PACKAGE_PATHS.MANIFEST_RELATIVE;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// ../core/src/core/platform/registry-entry-filter.ts
|
|
695
|
+
function normalizeRegistryPath(registryPath) {
|
|
696
|
+
return normalizePathForProcessing(registryPath);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// ../core/src/utils/package-merge.ts
|
|
700
|
+
import * as yaml from "js-yaml";
|
|
701
|
+
var PACKAGE_INDEX = normalizePathForProcessing(PACKAGE_PATHS.INDEX_RELATIVE);
|
|
702
|
+
function mergePackageFiles(base, incoming) {
|
|
703
|
+
let byPath = /* @__PURE__ */ new Map(), addAll = (list) => {
|
|
704
|
+
for (let file of list) {
|
|
705
|
+
let normalized = normalizePathForProcessing(file.path) || file.path;
|
|
706
|
+
normalized !== PACKAGE_INDEX && byPath.set(normalized, { ...file, path: normalized });
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
return addAll(base), addAll(incoming), Array.from(byPath.values());
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// ../core/src/core/cache-manager.ts
|
|
713
|
+
import { homedir as homedir2 } from "os";
|
|
714
|
+
import { join as join6 } from "path";
|
|
715
|
+
|
|
716
|
+
// ../core/src/utils/git-cache.ts
|
|
717
|
+
import { createHash } from "crypto";
|
|
718
|
+
import { join as join5, basename as basename3 } from "path";
|
|
719
|
+
import { homedir } from "os";
|
|
720
|
+
function computeGitUrlHash(url) {
|
|
721
|
+
let normalized = normalizeGitUrl(url);
|
|
722
|
+
return createHash("sha256").update(normalized).digest("hex").substring(0, 12);
|
|
723
|
+
}
|
|
724
|
+
function getGitCacheDir() {
|
|
725
|
+
return join5(homedir(), ".openpackage", "cache", "git");
|
|
726
|
+
}
|
|
727
|
+
function getGitRepoCacheDir(url) {
|
|
728
|
+
let urlHash = computeGitUrlHash(url), cacheDir = getGitCacheDir();
|
|
729
|
+
return join5(cacheDir, urlHash);
|
|
730
|
+
}
|
|
731
|
+
function getGitCommitCacheDir(url, commitSha) {
|
|
732
|
+
let repoDir = getGitRepoCacheDir(url), shortSha = commitSha.substring(0, 7);
|
|
733
|
+
return join5(repoDir, shortSha);
|
|
734
|
+
}
|
|
735
|
+
function getRepoMetadataPath(repoDir) {
|
|
736
|
+
return join5(repoDir, ".opkg-repo.json");
|
|
737
|
+
}
|
|
738
|
+
function getCommitMetadataPath(commitDir) {
|
|
739
|
+
return join5(commitDir, ".opkg-commit.json");
|
|
740
|
+
}
|
|
741
|
+
async function writeRepoMetadata(repoDir, metadata) {
|
|
742
|
+
let metaPath = getRepoMetadataPath(repoDir);
|
|
743
|
+
await ensureDir(repoDir), await writeTextFile(metaPath, JSON.stringify(metadata, null, 2));
|
|
744
|
+
}
|
|
745
|
+
async function writeCommitMetadata(commitDir, metadata) {
|
|
746
|
+
let metaPath = getCommitMetadataPath(commitDir);
|
|
747
|
+
await ensureDir(commitDir), await writeTextFile(metaPath, JSON.stringify(metadata, null, 2));
|
|
748
|
+
}
|
|
749
|
+
async function readCommitMetadata(commitDir) {
|
|
750
|
+
let metaPath = getCommitMetadataPath(commitDir);
|
|
751
|
+
if (!await exists(metaPath))
|
|
752
|
+
return null;
|
|
753
|
+
try {
|
|
754
|
+
let content = await readTextFile(metaPath);
|
|
755
|
+
return JSON.parse(content);
|
|
756
|
+
} catch (error) {
|
|
757
|
+
return logger.warn(`Failed to read commit metadata at ${metaPath}`, { error }), null;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
async function touchCacheEntry(commitDir) {
|
|
761
|
+
let metadata = await readCommitMetadata(commitDir);
|
|
762
|
+
metadata && (metadata.lastAccessed = (/* @__PURE__ */ new Date()).toISOString(), await writeCommitMetadata(commitDir, metadata));
|
|
763
|
+
}
|
|
764
|
+
async function isCommitCached(url, commitSha) {
|
|
765
|
+
let commitDir = getGitCommitCacheDir(url, commitSha);
|
|
766
|
+
return await exists(commitDir);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// ../core/src/core/cache-manager.ts
|
|
770
|
+
var METADATA_TTL_MS = 600 * 1e3;
|
|
771
|
+
function getGitRefsCacheDir() {
|
|
772
|
+
return join6(homedir2(), ".openpackage", "cache", "git-refs");
|
|
773
|
+
}
|
|
774
|
+
function getMetadataCacheDir() {
|
|
775
|
+
return join6(homedir2(), ".openpackage", "cache", "metadata");
|
|
776
|
+
}
|
|
777
|
+
function getGitRefCachePath(url) {
|
|
778
|
+
let urlHash = computeGitUrlHash(url);
|
|
779
|
+
return join6(getGitRefsCacheDir(), `${urlHash}.json`);
|
|
780
|
+
}
|
|
781
|
+
function getMetadataCachePath(name) {
|
|
782
|
+
let safeName = name.replace(/\//g, "__");
|
|
783
|
+
return join6(getMetadataCacheDir(), `${safeName}.json`);
|
|
784
|
+
}
|
|
785
|
+
function isExpired(fetchedAt, ttlMs) {
|
|
786
|
+
let fetchedTime = new Date(fetchedAt).getTime();
|
|
787
|
+
return Date.now() - fetchedTime > ttlMs;
|
|
788
|
+
}
|
|
789
|
+
async function readJsonFile(filePath) {
|
|
790
|
+
if (!await exists(filePath))
|
|
791
|
+
return null;
|
|
792
|
+
try {
|
|
793
|
+
let content = await readTextFile(filePath);
|
|
794
|
+
return JSON.parse(content);
|
|
795
|
+
} catch (error) {
|
|
796
|
+
return logger.warn(`Failed to read cache file at ${filePath}`, { error }), null;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
async function writeJsonFile(filePath, data) {
|
|
800
|
+
let dir = join6(filePath, "..");
|
|
801
|
+
await ensureDir(dir), await writeTextFile(filePath, JSON.stringify(data, null, 2));
|
|
802
|
+
}
|
|
803
|
+
function createCacheManager() {
|
|
804
|
+
return {
|
|
805
|
+
async getCachedCommitForRef(url, ref) {
|
|
806
|
+
let cachePath = getGitRefCachePath(url), cache = await readJsonFile(cachePath);
|
|
807
|
+
return cache?.refs?.[ref] ? cache.refs[ref].commit : null;
|
|
808
|
+
},
|
|
809
|
+
async cacheRefCommit(url, ref, commit) {
|
|
810
|
+
let cachePath = getGitRefCachePath(url), cache = await readJsonFile(cachePath);
|
|
811
|
+
cache || (cache = { refs: {} }), cache.refs[ref] = {
|
|
812
|
+
commit,
|
|
813
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
814
|
+
}, await writeJsonFile(cachePath, cache), logger.debug(`Cached git ref ${ref} -> ${commit.substring(0, 7)}`, { url });
|
|
815
|
+
},
|
|
816
|
+
async getLocalPackagePath(name, version) {
|
|
817
|
+
let packagePath = getPackageVersionPath(name, version);
|
|
818
|
+
return await exists(packagePath) ? packagePath : null;
|
|
819
|
+
},
|
|
820
|
+
async hasLocalPackage(name, version) {
|
|
821
|
+
let packagePath = getPackageVersionPath(name, version);
|
|
822
|
+
return await exists(packagePath);
|
|
823
|
+
},
|
|
824
|
+
async getCachedMetadata(name) {
|
|
825
|
+
let cachePath = getMetadataCachePath(name), cache = await readJsonFile(cachePath);
|
|
826
|
+
return cache ? isExpired(cache.fetchedAt, METADATA_TTL_MS) ? (logger.debug(`Metadata cache expired for ${name}`, { fetchedAt: cache.fetchedAt }), null) : cache : null;
|
|
827
|
+
},
|
|
828
|
+
async cacheMetadata(name, versions, etag) {
|
|
829
|
+
let cachePath = getMetadataCachePath(name), cache = {
|
|
830
|
+
versions,
|
|
831
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
832
|
+
...etag && { etag }
|
|
833
|
+
};
|
|
834
|
+
await writeJsonFile(cachePath, cache), logger.debug(`Cached metadata for ${name}`, { versionCount: versions.length });
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// ../core/src/core/remote-pull.ts
|
|
840
|
+
var NETWORK_ERROR_PATTERN = /(fetch failed|ENOTFOUND|EAI_AGAIN|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|network)/i;
|
|
841
|
+
function matchesNetworkPattern(value) {
|
|
842
|
+
return typeof value == "string" && NETWORK_ERROR_PATTERN.test(value);
|
|
843
|
+
}
|
|
844
|
+
function isNetworkFailure(error) {
|
|
845
|
+
if (matchesNetworkPattern(error.message))
|
|
846
|
+
return !0;
|
|
847
|
+
let cause = error.cause;
|
|
848
|
+
return !!(cause && (matchesNetworkPattern(cause.message) || matchesNetworkPattern(cause.code) || matchesNetworkPattern(cause.errno)) || matchesNetworkPattern(error.code) || matchesNetworkPattern(error.errno));
|
|
849
|
+
}
|
|
850
|
+
function normalizeDownloadPaths(paths) {
|
|
851
|
+
if (!paths || paths.length === 0)
|
|
852
|
+
return [];
|
|
853
|
+
let normalized = paths.filter((path) => typeof path == "string").map((path) => path.startsWith("/") ? path.slice(1) : path).map((path) => normalizeRegistryPath(path)).filter((path) => path.length > 0);
|
|
854
|
+
return Array.from(new Set(normalized));
|
|
855
|
+
}
|
|
856
|
+
function buildPullEndpoint(name, version, options) {
|
|
857
|
+
let encodedName = encodeURIComponent(name), endpoint = version && version !== "latest" ? `/packages/pull/by-name/${encodedName}/v/${encodeURIComponent(version)}` : `/packages/pull/by-name/${encodedName}`, params = [];
|
|
858
|
+
options?.recursive && params.push("recursive=true");
|
|
859
|
+
let normalizedPaths = normalizeDownloadPaths(options?.paths);
|
|
860
|
+
if (normalizedPaths.length > 0) {
|
|
861
|
+
let encodedPaths = normalizedPaths.map((path) => encodeURIComponent(path)).join(",");
|
|
862
|
+
params.push(`paths=${encodedPaths}`), params.push("includeManifest=true");
|
|
863
|
+
}
|
|
864
|
+
if (params.length === 0)
|
|
865
|
+
return endpoint;
|
|
866
|
+
let delimiter = endpoint.includes("?") ? "&" : "?";
|
|
867
|
+
return `${endpoint}${delimiter}${params.join("&")}`;
|
|
868
|
+
}
|
|
869
|
+
function parseDownloadIdentifier(downloadName) {
|
|
870
|
+
let atIndex = -1;
|
|
871
|
+
if (downloadName.startsWith("gh@")) {
|
|
872
|
+
for (let i = downloadName.length - 1; i >= 0; i--)
|
|
873
|
+
if (downloadName[i] === "@" && i !== 2) {
|
|
874
|
+
atIndex = i;
|
|
875
|
+
break;
|
|
876
|
+
}
|
|
877
|
+
} else
|
|
878
|
+
atIndex = downloadName.lastIndexOf("@");
|
|
879
|
+
if (atIndex <= 0 || atIndex === downloadName.length - 1)
|
|
880
|
+
throw new Error(`Invalid download name '${downloadName}'. Expected format '<package>@<version>'.`);
|
|
881
|
+
let rawName = downloadName.slice(0, atIndex), rawVersion = downloadName.slice(atIndex + 1), packageName, namePath;
|
|
882
|
+
if (rawName.startsWith("gh@")) {
|
|
883
|
+
let segments = rawName.split("/");
|
|
884
|
+
if (segments.length < 2)
|
|
885
|
+
throw new Error(`Invalid GitHub package in download name '${downloadName}'.`);
|
|
886
|
+
packageName = segments.slice(0, 2).join("/"), segments.length > 2 && (namePath = segments.slice(2).join("/"));
|
|
887
|
+
} else if (rawName.startsWith("@")) {
|
|
888
|
+
let segments = rawName.split("/");
|
|
889
|
+
if (segments.length < 2)
|
|
890
|
+
throw new Error(`Invalid scoped package in download name '${downloadName}'.`);
|
|
891
|
+
packageName = segments.slice(0, 2).join("/"), namePath = segments.length > 2 ? segments.slice(2).join("/") : void 0;
|
|
892
|
+
} else {
|
|
893
|
+
let segments = rawName.split("/");
|
|
894
|
+
packageName = segments[0], namePath = segments.length > 1 ? segments.slice(1).join("/") : void 0;
|
|
895
|
+
}
|
|
896
|
+
let versionSegments = rawVersion.split("/"), version = versionSegments[0], versionPath = versionSegments.length > 1 ? versionSegments.slice(1).join("/") : void 0;
|
|
897
|
+
if (!packageName || !version)
|
|
898
|
+
throw new Error(`Invalid download name '${downloadName}'. Expected format '<package>@<version>'.`);
|
|
899
|
+
let registryPathParts = [namePath, versionPath].filter(Boolean), registryPath = registryPathParts.length > 0 ? registryPathParts.join("/") : void 0;
|
|
900
|
+
return { packageName, version, registryPath };
|
|
901
|
+
}
|
|
902
|
+
function isPartialDownload(download) {
|
|
903
|
+
return !1;
|
|
904
|
+
}
|
|
905
|
+
async function fetchRemotePackageMetadata(name, version, options = {}) {
|
|
906
|
+
try {
|
|
907
|
+
await ensureRegistryDirectories();
|
|
908
|
+
let context = await createContext(options), response = await getRemotePackage(
|
|
909
|
+
context.httpClient,
|
|
910
|
+
name,
|
|
911
|
+
version,
|
|
912
|
+
options.recursive,
|
|
913
|
+
options.paths
|
|
914
|
+
);
|
|
915
|
+
return {
|
|
916
|
+
success: !0,
|
|
917
|
+
context,
|
|
918
|
+
response
|
|
919
|
+
};
|
|
920
|
+
} catch (error) {
|
|
921
|
+
return mapErrorToFailure(error);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
async function pullPackageFromRemote(name, version, options = {}) {
|
|
925
|
+
try {
|
|
926
|
+
if (version && version !== "latest" && !options.skipLocalCheck) {
|
|
927
|
+
let localPath = await createCacheManager().getLocalPackagePath(name, version);
|
|
928
|
+
if (localPath)
|
|
929
|
+
return logger.debug("Package already exists in local registry, skipping remote pull", { name, version, localPath }), {
|
|
930
|
+
success: !0,
|
|
931
|
+
name,
|
|
932
|
+
version,
|
|
933
|
+
response: {},
|
|
934
|
+
extracted: { files: [], checksum: "" },
|
|
935
|
+
registryUrl: "",
|
|
936
|
+
profile: "",
|
|
937
|
+
downloadUrl: "",
|
|
938
|
+
tarballSize: void 0
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
let metadataResult = options.preFetchedResponse ? await createResultFromPrefetched(options) : await fetchRemotePackageMetadata(name, version, options);
|
|
942
|
+
if (!metadataResult.success)
|
|
943
|
+
return metadataResult;
|
|
944
|
+
let { context, response } = metadataResult, primaryDownload = resolvePrimaryDownload(response);
|
|
945
|
+
if (!primaryDownload?.downloadUrl)
|
|
946
|
+
return {
|
|
947
|
+
success: !1,
|
|
948
|
+
reason: "access-denied",
|
|
949
|
+
message: "Package download not available for this account"
|
|
950
|
+
};
|
|
951
|
+
let isPartial = isPartialDownload(primaryDownload), tarballBuffer = await downloadPackageTarball(context.httpClient, primaryDownload.downloadUrl), expectedSize = isPartial ? void 0 : response.version.tarballSize;
|
|
952
|
+
if (!verifyTarballIntegrity(tarballBuffer, expectedSize))
|
|
953
|
+
return {
|
|
954
|
+
success: !1,
|
|
955
|
+
reason: "integrity",
|
|
956
|
+
message: "Tarball integrity verification failed"
|
|
957
|
+
};
|
|
958
|
+
let extracted = await extractPackageFromTarball(tarballBuffer);
|
|
959
|
+
return await savePackageToLocalRegistry(response, extracted, {
|
|
960
|
+
partial: isPartial
|
|
961
|
+
}), {
|
|
962
|
+
success: !0,
|
|
963
|
+
name: response.package.name,
|
|
964
|
+
version: formatVersionLabel(response.version.version),
|
|
965
|
+
response,
|
|
966
|
+
extracted,
|
|
967
|
+
registryUrl: context.registryUrl,
|
|
968
|
+
profile: context.profile,
|
|
969
|
+
downloadUrl: primaryDownload.downloadUrl,
|
|
970
|
+
tarballSize: response.version.tarballSize
|
|
971
|
+
};
|
|
972
|
+
} catch (error) {
|
|
973
|
+
return mapErrorToFailure(error);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
function resolvePrimaryDownload(response) {
|
|
977
|
+
if (!Array.isArray(response.downloads) || response.downloads.length === 0)
|
|
978
|
+
return;
|
|
979
|
+
let primaryMatch = response.downloads.find((download) => download.name === response.package.name && download.downloadUrl);
|
|
980
|
+
return primaryMatch?.downloadUrl ? primaryMatch : response.downloads.find((download) => download.downloadUrl);
|
|
981
|
+
}
|
|
982
|
+
async function createResultFromPrefetched(options) {
|
|
983
|
+
if (!options.preFetchedResponse)
|
|
984
|
+
throw new Error("preFetchedResponse missing from options");
|
|
985
|
+
return {
|
|
986
|
+
success: !0,
|
|
987
|
+
context: await createContext(options),
|
|
988
|
+
response: options.preFetchedResponse
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
async function createContext(options) {
|
|
992
|
+
let authOptions = {
|
|
993
|
+
profile: options.profile,
|
|
994
|
+
apiKey: options.apiKey
|
|
995
|
+
}, httpClient = options.httpClient || await createHttpClient(authOptions), profile = authManager.getCurrentProfile(authOptions), registryUrl = authManager.getRegistryUrl();
|
|
996
|
+
return {
|
|
997
|
+
httpClient,
|
|
998
|
+
profile,
|
|
999
|
+
registryUrl
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
async function getRemotePackage(httpClient, name, version, recursive, paths) {
|
|
1003
|
+
let finalEndpoint = buildPullEndpoint(name, version, { recursive, paths });
|
|
1004
|
+
return logger.debug("Fetching remote package metadata", {
|
|
1005
|
+
name,
|
|
1006
|
+
version: version ?? "latest",
|
|
1007
|
+
endpoint: finalEndpoint,
|
|
1008
|
+
recursive: !!recursive,
|
|
1009
|
+
hasPaths: !!paths && paths.length > 0
|
|
1010
|
+
}), await httpClient.get(finalEndpoint);
|
|
1011
|
+
}
|
|
1012
|
+
async function downloadPackageTarball(httpClient, downloadUrl) {
|
|
1013
|
+
let downloadHost = (() => {
|
|
1014
|
+
try {
|
|
1015
|
+
return new URL(downloadUrl).host;
|
|
1016
|
+
} catch {
|
|
1017
|
+
return "";
|
|
1018
|
+
}
|
|
1019
|
+
})(), registryHost = (() => {
|
|
1020
|
+
try {
|
|
1021
|
+
return new URL(authManager.getRegistryUrl()).host;
|
|
1022
|
+
} catch {
|
|
1023
|
+
return "";
|
|
1024
|
+
}
|
|
1025
|
+
})(), shouldSkipAuth = downloadHost !== "" && registryHost !== "" && downloadHost !== registryHost, buffer = await httpClient.downloadFile(downloadUrl, { skipAuth: shouldSkipAuth });
|
|
1026
|
+
return Buffer.from(buffer);
|
|
1027
|
+
}
|
|
1028
|
+
async function savePackageToLocalRegistry(response, extracted, saveOptions = {}) {
|
|
1029
|
+
let metadata = {
|
|
1030
|
+
name: response.package.name,
|
|
1031
|
+
version: response.version.version,
|
|
1032
|
+
description: response.package.description,
|
|
1033
|
+
keywords: response.package.keywords,
|
|
1034
|
+
private: response.package.isPrivate
|
|
1035
|
+
};
|
|
1036
|
+
metadata.files = extracted.files.map((file) => file.path), metadata.created = response.version.createdAt, metadata.updated = response.version.updatedAt;
|
|
1037
|
+
let files = extracted.files;
|
|
1038
|
+
if (saveOptions.partial)
|
|
1039
|
+
try {
|
|
1040
|
+
let existing = await packageManager.loadPackage(response.package.name, response.version.version);
|
|
1041
|
+
files = mergePackageFiles(existing.files, files);
|
|
1042
|
+
} catch {
|
|
1043
|
+
}
|
|
1044
|
+
await packageManager.savePackage(
|
|
1045
|
+
{ metadata, files },
|
|
1046
|
+
{ partial: !!saveOptions.partial }
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
function mapErrorToFailure(error) {
|
|
1050
|
+
if (logger.debug("Remote pull operation failed", { error }), error instanceof ValidationError)
|
|
1051
|
+
return {
|
|
1052
|
+
success: !1,
|
|
1053
|
+
reason: "integrity",
|
|
1054
|
+
message: error.message,
|
|
1055
|
+
error
|
|
1056
|
+
};
|
|
1057
|
+
if (error instanceof ConfigError)
|
|
1058
|
+
return {
|
|
1059
|
+
success: !1,
|
|
1060
|
+
reason: "access-denied",
|
|
1061
|
+
message: error.message,
|
|
1062
|
+
error
|
|
1063
|
+
};
|
|
1064
|
+
if (error instanceof Error) {
|
|
1065
|
+
let apiError = error.apiError;
|
|
1066
|
+
return apiError?.statusCode === 404 ? {
|
|
1067
|
+
success: !1,
|
|
1068
|
+
reason: "not-found",
|
|
1069
|
+
message: error.message,
|
|
1070
|
+
statusCode: 404,
|
|
1071
|
+
error
|
|
1072
|
+
} : apiError?.statusCode === 401 || apiError?.statusCode === 403 ? {
|
|
1073
|
+
success: !1,
|
|
1074
|
+
reason: "access-denied",
|
|
1075
|
+
message: error.message,
|
|
1076
|
+
statusCode: apiError.statusCode,
|
|
1077
|
+
error
|
|
1078
|
+
} : isNetworkFailure(error) ? {
|
|
1079
|
+
success: !1,
|
|
1080
|
+
reason: "network",
|
|
1081
|
+
message: error.message,
|
|
1082
|
+
error
|
|
1083
|
+
} : {
|
|
1084
|
+
success: !1,
|
|
1085
|
+
reason: "unknown",
|
|
1086
|
+
message: error.message,
|
|
1087
|
+
error
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
return {
|
|
1091
|
+
success: !1,
|
|
1092
|
+
reason: "unknown",
|
|
1093
|
+
message: "Unknown error occurred",
|
|
1094
|
+
error
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
// ../core/src/core/git-clone.ts
|
|
1099
|
+
import { execFile } from "child_process";
|
|
1100
|
+
import { join as join7 } from "path";
|
|
1101
|
+
import { promisify } from "util";
|
|
1102
|
+
import { rm, rename } from "fs/promises";
|
|
1103
|
+
var GitSpinner = class {
|
|
1104
|
+
constructor(message) {
|
|
1105
|
+
this.message = message;
|
|
1106
|
+
}
|
|
1107
|
+
start() {
|
|
1108
|
+
logger.debug(this.message);
|
|
1109
|
+
}
|
|
1110
|
+
update(text) {
|
|
1111
|
+
this.message = text, logger.debug(text);
|
|
1112
|
+
}
|
|
1113
|
+
stop() {
|
|
1114
|
+
}
|
|
1115
|
+
}, execFileAsync = promisify(execFile), cacheManager = createCacheManager();
|
|
1116
|
+
function isSha(ref) {
|
|
1117
|
+
return /^[0-9a-f]{7,40}$/i.test(ref);
|
|
1118
|
+
}
|
|
1119
|
+
function isFullSha(ref) {
|
|
1120
|
+
return /^[0-9a-f]{40}$/i.test(ref);
|
|
1121
|
+
}
|
|
1122
|
+
async function runGit(args, cwd) {
|
|
1123
|
+
try {
|
|
1124
|
+
return (await execFileAsync("git", args, { cwd })).stdout.trim();
|
|
1125
|
+
} catch (error) {
|
|
1126
|
+
let message = error?.stderr?.toString?.().trim?.() || error?.message || String(error);
|
|
1127
|
+
throw new ValidationError(`Git command failed: ${message}`);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
async function getCurrentCommitSha(repoPath) {
|
|
1131
|
+
return (await runGit(["rev-parse", "HEAD"], repoPath)).substring(0, 7);
|
|
1132
|
+
}
|
|
1133
|
+
async function resolveRefWithLsRemote(url, ref) {
|
|
1134
|
+
try {
|
|
1135
|
+
let output = await runGit(["ls-remote", url, ref || "HEAD"]);
|
|
1136
|
+
if (!output)
|
|
1137
|
+
return null;
|
|
1138
|
+
let match = output.match(/^([0-9a-f]{40})\s/i);
|
|
1139
|
+
return match ? match[1].substring(0, 7) : null;
|
|
1140
|
+
} catch {
|
|
1141
|
+
return null;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
var SEMVER_TAG_PATTERN = /^v?\d+\.\d+\.\d+(?:[-+].*)?$/;
|
|
1145
|
+
function isImmutableRef(ref) {
|
|
1146
|
+
return isFullSha(ref) || SEMVER_TAG_PATTERN.test(ref);
|
|
1147
|
+
}
|
|
1148
|
+
async function cloneRepoToCache(options) {
|
|
1149
|
+
let { url, ref, subdir, skipCache } = options, getDisplayUrl = () => {
|
|
1150
|
+
let match = url.match(/([^/]+\/[^/]+?)(?:\.git)?$/);
|
|
1151
|
+
return match ? match[1] : url;
|
|
1152
|
+
}, tryCache = async (shortSha, source) => {
|
|
1153
|
+
if (await isCommitCached(url, shortSha)) {
|
|
1154
|
+
let commitDir = getGitCommitCacheDir(url, shortSha);
|
|
1155
|
+
await touchCacheEntry(commitDir);
|
|
1156
|
+
let finalPath = subdir ? join7(commitDir, subdir) : commitDir;
|
|
1157
|
+
if (!subdir || await exists(finalPath)) {
|
|
1158
|
+
logger.debug(`Using cached commit (${source})`, { url, ref, commit: shortSha });
|
|
1159
|
+
let refDisplay2 = ref ? `#${ref}` : "", subdirDisplay = subdir ? `/${subdir}` : "";
|
|
1160
|
+
return logger.info(`Using cached ${getDisplayUrl()}${refDisplay2}${subdirDisplay} [${shortSha}]`), { path: finalPath, commitSha: shortSha, repoPath: commitDir };
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
return null;
|
|
1164
|
+
};
|
|
1165
|
+
if (!skipCache) {
|
|
1166
|
+
if (ref && isFullSha(ref)) {
|
|
1167
|
+
let shortSha = ref.substring(0, 7), cached = await tryCache(shortSha, "full SHA");
|
|
1168
|
+
if (cached) return cached;
|
|
1169
|
+
}
|
|
1170
|
+
if (ref && isImmutableRef(ref) && !isFullSha(ref)) {
|
|
1171
|
+
let cachedCommit = await cacheManager.getCachedCommitForRef(url, ref);
|
|
1172
|
+
if (cachedCommit) {
|
|
1173
|
+
let cached = await tryCache(cachedCommit, "immutable ref cache");
|
|
1174
|
+
if (cached) return cached;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
let refDisplay2 = ref ? `#${ref}` : "", spinner2 = new GitSpinner(`Checking ${getDisplayUrl()}${refDisplay2}`);
|
|
1178
|
+
spinner2.start();
|
|
1179
|
+
let resolvedSha = await resolveRefWithLsRemote(url, ref);
|
|
1180
|
+
if (spinner2.stop(), resolvedSha) {
|
|
1181
|
+
ref && await cacheManager.cacheRefCommit(url, ref, resolvedSha);
|
|
1182
|
+
let cached = await tryCache(resolvedSha, "ls-remote");
|
|
1183
|
+
if (cached) return cached;
|
|
1184
|
+
logger.debug("Commit not cached, will clone", { url, ref, resolvedSha });
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
let repoDir = getGitRepoCacheDir(url);
|
|
1188
|
+
await ensureDir(repoDir), await writeRepoMetadata(repoDir, {
|
|
1189
|
+
url,
|
|
1190
|
+
normalized: url.toLowerCase(),
|
|
1191
|
+
lastFetched: (/* @__PURE__ */ new Date()).toISOString()
|
|
1192
|
+
});
|
|
1193
|
+
let tempClonePath = join7(
|
|
1194
|
+
repoDir,
|
|
1195
|
+
`.temp-clone-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2, 10)}`
|
|
1196
|
+
);
|
|
1197
|
+
logger.debug("Cloning repository to cache", { url, ref, subdir });
|
|
1198
|
+
let refDisplay = ref ? `#${ref}` : "", spinner = new GitSpinner(`Cloning repository from ${url}${refDisplay}`);
|
|
1199
|
+
spinner.start();
|
|
1200
|
+
try {
|
|
1201
|
+
ref && isSha(ref) ? (await runGit(["clone", "--depth", "1", url, tempClonePath]), spinner.update(`Fetching commit ${ref}`), await runGit(["fetch", "--depth", "1", "origin", ref], tempClonePath), spinner.update(`Checking out commit ${ref}`), await runGit(["checkout", ref], tempClonePath)) : ref ? await runGit(["clone", "--depth", "1", "--branch", ref, url, tempClonePath]) : await runGit(["clone", "--depth", "1", url, tempClonePath]), spinner.update("Resolving commit SHA");
|
|
1202
|
+
let commitSha = await getCurrentCommitSha(tempClonePath), commitDir = getGitCommitCacheDir(url, commitSha);
|
|
1203
|
+
if (await isCommitCached(url, commitSha)) {
|
|
1204
|
+
logger.debug("Commit already cached, using existing", { commitSha, commitDir }), spinner.stop(), await rm(tempClonePath, { recursive: !0, force: !0 }), await touchCacheEntry(commitDir);
|
|
1205
|
+
let finalPath2 = subdir ? join7(commitDir, subdir) : commitDir;
|
|
1206
|
+
if (subdir && !await exists(finalPath2))
|
|
1207
|
+
throw new ValidationError(
|
|
1208
|
+
`Subdirectory '${subdir}' does not exist in cached repository ${url}`
|
|
1209
|
+
);
|
|
1210
|
+
return {
|
|
1211
|
+
path: finalPath2,
|
|
1212
|
+
commitSha,
|
|
1213
|
+
repoPath: commitDir
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
try {
|
|
1217
|
+
await rename(tempClonePath, commitDir);
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
let code = error?.code;
|
|
1220
|
+
if (code === "EEXIST" || code === "ENOTEMPTY")
|
|
1221
|
+
await rm(tempClonePath, { recursive: !0, force: !0 });
|
|
1222
|
+
else
|
|
1223
|
+
throw error;
|
|
1224
|
+
}
|
|
1225
|
+
logger.debug("Moved clone to final cache location", { commitDir }), await isCommitCached(url, commitSha) && await touchCacheEntry(commitDir), await writeCommitMetadata(commitDir, {
|
|
1226
|
+
url,
|
|
1227
|
+
commit: commitSha,
|
|
1228
|
+
ref,
|
|
1229
|
+
subdir,
|
|
1230
|
+
clonedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1231
|
+
lastAccessed: (/* @__PURE__ */ new Date()).toISOString()
|
|
1232
|
+
}), ref && await cacheManager.cacheRefCommit(url, ref, commitSha);
|
|
1233
|
+
let finalPath = subdir ? join7(commitDir, subdir) : commitDir;
|
|
1234
|
+
if (subdir && !await exists(finalPath))
|
|
1235
|
+
throw new ValidationError(
|
|
1236
|
+
`Subdirectory '${subdir}' does not exist in cloned repository ${url}`
|
|
1237
|
+
);
|
|
1238
|
+
let manifestPath = join7(finalPath, FILE_PATTERNS.OPENPACKAGE_YML), hasManifest = await exists(manifestPath), pluginManifestPath = join7(finalPath, DIR_PATTERNS.CLAUDE_PLUGIN, FILE_PATTERNS.PLUGIN_JSON), hasPluginManifest = await exists(pluginManifestPath), marketplaceManifestPath = join7(finalPath, DIR_PATTERNS.CLAUDE_PLUGIN, FILE_PATTERNS.MARKETPLACE_JSON), hasMarketplaceManifest = await exists(marketplaceManifestPath);
|
|
1239
|
+
if (!hasManifest && !hasPluginManifest && !hasMarketplaceManifest)
|
|
1240
|
+
throw new ValidationError(
|
|
1241
|
+
`Cloned repository is not an OpenPackage or Claude Code plugin (missing ${FILE_PATTERNS.OPENPACKAGE_YML}, ${DIR_PATTERNS.CLAUDE_PLUGIN}/${FILE_PATTERNS.PLUGIN_JSON}, or ${DIR_PATTERNS.CLAUDE_PLUGIN}/${FILE_PATTERNS.MARKETPLACE_JSON} at ${subdir ? `subdir '${subdir}'` : "repository root"})`
|
|
1242
|
+
);
|
|
1243
|
+
spinner.stop();
|
|
1244
|
+
let refPart = ref ? `#${ref}` : "", subdirPart = subdir ? `&subdirectory=${subdir}` : "";
|
|
1245
|
+
return logger.info(`Cloned git repository ${url}${refPart}${subdirPart} to cache [${commitSha}]`), {
|
|
1246
|
+
path: finalPath,
|
|
1247
|
+
commitSha,
|
|
1248
|
+
repoPath: commitDir
|
|
1249
|
+
};
|
|
1250
|
+
} catch (error) {
|
|
1251
|
+
throw spinner.stop(), await exists(tempClonePath) && await rm(tempClonePath, { recursive: !0, force: !0 }), error;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
// ../core/src/core/install/git-package-loader.ts
|
|
1256
|
+
async function loadPackageFromGit(options) {
|
|
1257
|
+
let cloneResult = await cloneRepoToCache({
|
|
1258
|
+
url: options.url,
|
|
1259
|
+
ref: options.ref,
|
|
1260
|
+
subdir: options.path,
|
|
1261
|
+
skipCache: options.skipCache
|
|
1262
|
+
}), { path: sourcePath, repoPath, commitSha } = cloneResult;
|
|
1263
|
+
if (options.resourcePath)
|
|
1264
|
+
return {
|
|
1265
|
+
pkg: null,
|
|
1266
|
+
sourcePath,
|
|
1267
|
+
repoPath,
|
|
1268
|
+
commitSha,
|
|
1269
|
+
isMarketplace: !1
|
|
1270
|
+
};
|
|
1271
|
+
let pluginDetection = await detectPluginType(sourcePath);
|
|
1272
|
+
return pluginDetection.isPlugin && pluginDetection.type === "marketplace" ? {
|
|
1273
|
+
pkg: null,
|
|
1274
|
+
sourcePath,
|
|
1275
|
+
repoPath,
|
|
1276
|
+
commitSha,
|
|
1277
|
+
isMarketplace: !0
|
|
1278
|
+
} : {
|
|
1279
|
+
pkg: await loadPackageFromPath(sourcePath, {
|
|
1280
|
+
gitUrl: options.url,
|
|
1281
|
+
path: options.path,
|
|
1282
|
+
resourcePath: options.resourcePath,
|
|
1283
|
+
repoPath
|
|
1284
|
+
}),
|
|
1285
|
+
sourcePath,
|
|
1286
|
+
repoPath,
|
|
1287
|
+
commitSha,
|
|
1288
|
+
isMarketplace: !1
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
export {
|
|
1293
|
+
buildPathInstallContext,
|
|
1294
|
+
buildGitInstallContext,
|
|
1295
|
+
buildInstallContext,
|
|
1296
|
+
buildResourceInstallContexts,
|
|
1297
|
+
normalizePackagePath,
|
|
1298
|
+
isManifestPath,
|
|
1299
|
+
createCacheManager,
|
|
1300
|
+
parseDownloadIdentifier,
|
|
1301
|
+
fetchRemotePackageMetadata,
|
|
1302
|
+
pullPackageFromRemote,
|
|
1303
|
+
loadPackageFromGit,
|
|
1304
|
+
applyBaseDetection,
|
|
1305
|
+
computePathScoping,
|
|
1306
|
+
resolveConvenienceResources,
|
|
1307
|
+
runConvenienceFilterInstall,
|
|
1308
|
+
classifyInput,
|
|
1309
|
+
validateResolutionFlags,
|
|
1310
|
+
normalizeInstallOptions
|
|
1311
|
+
};
|
|
1312
|
+
//# sourceMappingURL=chunk-VQDTXLOX.js.map
|