@skaile/workspaces 5.11.0 → 5.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +193 -0
- package/README.md +4 -4
- package/dist/{asset-feeds-CXGQIDFR.js → asset-feeds-ALMTHLPV.js} +26 -23
- package/dist/asset-feeds-ALMTHLPV.js.map +1 -0
- package/dist/asset-manager/catalog-deployer.js +10 -10
- package/dist/asset-manager/fragments.js +1 -1
- package/dist/asset-manager/index.js +18 -18
- package/dist/asset-manager/installer.js +13 -13
- package/dist/asset-manager/renderers.js +11 -11
- package/dist/asset-manager/src/fragments.d.ts +5 -0
- package/dist/asset-manager/src/fragments.d.ts.map +1 -1
- package/dist/asset-manager/src/index.d.ts +140 -12
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/asset-manager/src/install-agent.d.ts +9 -1
- package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
- package/dist/asset-manager/src/installer.d.ts.map +1 -1
- package/dist/asset-manager/src/renderers.d.ts +5 -0
- package/dist/asset-manager/src/renderers.d.ts.map +1 -1
- package/dist/bridge/drivers/claude-sdk.js +21 -16
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +101 -29
- package/dist/bridge/drivers/codex.js.map +1 -1
- package/dist/bridge/drivers/continue.js +12 -12
- package/dist/bridge/drivers/echo.js +2 -2
- package/dist/bridge/drivers/gemini.js +7 -7
- package/dist/bridge/drivers/goose.js +12 -12
- package/dist/bridge/drivers/omp.js +135 -33
- package/dist/bridge/drivers/omp.js.map +1 -1
- package/dist/bridge/drivers/opencode.js +12 -12
- package/dist/bridge/drivers/qwen.js +7 -7
- package/dist/bridge/index.js +14 -14
- package/dist/bridge/src/codex/config-toml.d.ts +16 -3
- package/dist/bridge/src/codex/config-toml.d.ts.map +1 -1
- package/dist/bridge/src/codex/managed-driver.d.ts.map +1 -1
- package/dist/bridge/src/drivers/claude-sdk.d.ts +1 -1
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/bridge/src/drivers/codex.d.ts +6 -0
- package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
- package/dist/bridge/src/drivers/omp-models-yml.d.ts +32 -0
- package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +1 -1
- package/dist/bridge/src/drivers/omp.d.ts +29 -6
- package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
- package/dist/bridge/src/provider-materialize/credential-env.d.ts +15 -0
- package/dist/bridge/src/provider-materialize/credential-env.d.ts.map +1 -1
- package/dist/{chunk-T42WRQ4O.js → chunk-2BIESC6S.js} +3 -3
- package/dist/{chunk-T42WRQ4O.js.map → chunk-2BIESC6S.js.map} +1 -1
- package/dist/{chunk-CPWLNZGJ.js → chunk-4DLQESIY.js} +3 -3
- package/dist/{chunk-CPWLNZGJ.js.map → chunk-4DLQESIY.js.map} +1 -1
- package/dist/{chunk-HZXUXHIV.js → chunk-4L4R5LV3.js} +89 -12
- package/dist/chunk-4L4R5LV3.js.map +1 -0
- package/dist/{chunk-CAHB6MHA.js → chunk-4NJ3QQHZ.js} +5 -5
- package/dist/{chunk-CAHB6MHA.js.map → chunk-4NJ3QQHZ.js.map} +1 -1
- package/dist/{chunk-ZCAJZ4B2.js → chunk-57SF6W6E.js} +147 -4
- package/dist/chunk-57SF6W6E.js.map +1 -0
- package/dist/{chunk-FH7W6TJ4.js → chunk-5FYOM4RF.js} +106 -25
- package/dist/chunk-5FYOM4RF.js.map +1 -0
- package/dist/{chunk-R7NHYEJF.js → chunk-5SKVCMRC.js} +15 -7
- package/dist/chunk-5SKVCMRC.js.map +1 -0
- package/dist/{chunk-CJERAGFY.js → chunk-6GICC4RJ.js} +44 -13
- package/dist/chunk-6GICC4RJ.js.map +1 -0
- package/dist/{chunk-G4FFOV3N.js → chunk-6JKIOPT3.js} +4 -4
- package/dist/{chunk-G4FFOV3N.js.map → chunk-6JKIOPT3.js.map} +1 -1
- package/dist/{chunk-T7CTHHG7.js → chunk-6NQDDCIL.js} +3 -3
- package/dist/{chunk-T7CTHHG7.js.map → chunk-6NQDDCIL.js.map} +1 -1
- package/dist/{chunk-XUSALIEI.js → chunk-7SMP4GNW.js} +6 -6
- package/dist/{chunk-XUSALIEI.js.map → chunk-7SMP4GNW.js.map} +1 -1
- package/dist/{chunk-Y3HTGHJC.js → chunk-AHCI4V5L.js} +3 -3
- package/dist/{chunk-Y3HTGHJC.js.map → chunk-AHCI4V5L.js.map} +1 -1
- package/dist/{chunk-M3B6EIJD.js → chunk-B7CZYFB2.js} +4 -4
- package/dist/{chunk-M3B6EIJD.js.map → chunk-B7CZYFB2.js.map} +1 -1
- package/dist/{chunk-PBBPZYVG.js → chunk-BF422IDP.js} +112 -46
- package/dist/chunk-BF422IDP.js.map +1 -0
- package/dist/{chunk-47U4GZ4M.js → chunk-BVJU2GKE.js} +20 -3
- package/dist/chunk-BVJU2GKE.js.map +1 -0
- package/dist/{chunk-PMECEZK3.js → chunk-D54T2F54.js} +5 -4
- package/dist/chunk-D54T2F54.js.map +1 -0
- package/dist/{chunk-2F5AWQX5.js → chunk-DKGEV6SQ.js} +192 -42
- package/dist/chunk-DKGEV6SQ.js.map +1 -0
- package/dist/{chunk-DALV4HHP.js → chunk-DKXNKFKP.js} +3 -2
- package/dist/{chunk-DALV4HHP.js.map → chunk-DKXNKFKP.js.map} +1 -1
- package/dist/chunk-FB3NREF7.js +649 -0
- package/dist/chunk-FB3NREF7.js.map +1 -0
- package/dist/{chunk-QZNJOHN6.js → chunk-FHDK3BFD.js} +3 -3
- package/dist/{chunk-QZNJOHN6.js.map → chunk-FHDK3BFD.js.map} +1 -1
- package/dist/{chunk-3SM2DL2T.js → chunk-GMDSRSGI.js} +21 -11
- package/dist/chunk-GMDSRSGI.js.map +1 -0
- package/dist/chunk-H5U7LNTJ.js +122 -0
- package/dist/chunk-H5U7LNTJ.js.map +1 -0
- package/dist/{chunk-VLTQGE2E.js → chunk-HBZD3MIW.js} +269 -81
- package/dist/chunk-HBZD3MIW.js.map +1 -0
- package/dist/{chunk-S3O3GKB7.js → chunk-HWGYJMME.js} +4 -4
- package/dist/{chunk-S3O3GKB7.js.map → chunk-HWGYJMME.js.map} +1 -1
- package/dist/{chunk-CPSIPIX7.js → chunk-IG5LZ3WU.js} +8 -6
- package/dist/chunk-IG5LZ3WU.js.map +1 -0
- package/dist/{chunk-ZPWTOUTK.js → chunk-IY5E7Y5W.js} +61 -8
- package/dist/chunk-IY5E7Y5W.js.map +1 -0
- package/dist/{chunk-6O2X3GPW.js → chunk-J4DB5G36.js} +7 -5
- package/dist/chunk-J4DB5G36.js.map +1 -0
- package/dist/{chunk-BNMZVPYA.js → chunk-J4OYIYFQ.js} +2 -2
- package/dist/{chunk-BNMZVPYA.js.map → chunk-J4OYIYFQ.js.map} +1 -1
- package/dist/{chunk-ALEYHUC5.js → chunk-L3ZGYSWY.js} +182 -41
- package/dist/chunk-L3ZGYSWY.js.map +1 -0
- package/dist/{chunk-SBSA3IQA.js → chunk-M3P4BYRK.js} +49 -14
- package/dist/chunk-M3P4BYRK.js.map +1 -0
- package/dist/{chunk-IER3KIPH.js → chunk-NDUYFYJB.js} +5 -5
- package/dist/{chunk-IER3KIPH.js.map → chunk-NDUYFYJB.js.map} +1 -1
- package/dist/{chunk-CGYEHQOX.js → chunk-NOA6EJXE.js} +11 -2
- package/dist/chunk-NOA6EJXE.js.map +1 -0
- package/dist/{chunk-J4RBUFGM.js → chunk-NVO6WECE.js} +9 -8
- package/dist/chunk-NVO6WECE.js.map +1 -0
- package/dist/{chunk-OBYKJB4U.js → chunk-O2SYFJWP.js} +79 -5
- package/dist/chunk-O2SYFJWP.js.map +1 -0
- package/dist/{chunk-5LKOAX7I.js → chunk-OQ5MKDS3.js} +21 -5
- package/dist/chunk-OQ5MKDS3.js.map +1 -0
- package/dist/{chunk-NWDSLXOX.js → chunk-PHRNUTSG.js} +118 -118
- package/dist/chunk-PHRNUTSG.js.map +1 -0
- package/dist/chunk-PN44DOGP.js +345 -0
- package/dist/chunk-PN44DOGP.js.map +1 -0
- package/dist/{chunk-COH6FQAG.js → chunk-PXDWTJ3P.js} +5 -5
- package/dist/{chunk-COH6FQAG.js.map → chunk-PXDWTJ3P.js.map} +1 -1
- package/dist/{chunk-GV4DZ6MT.js → chunk-PYTTF754.js} +22 -6
- package/dist/chunk-PYTTF754.js.map +1 -0
- package/dist/chunk-PZOO7L26.js +64 -0
- package/dist/chunk-PZOO7L26.js.map +1 -0
- package/dist/{chunk-EDYHEMJA.js → chunk-QO7CR3KB.js} +10 -5
- package/dist/chunk-QO7CR3KB.js.map +1 -0
- package/dist/{chunk-XDKH7XSA.js → chunk-R6QHJEHE.js} +5 -5
- package/dist/{chunk-XDKH7XSA.js.map → chunk-R6QHJEHE.js.map} +1 -1
- package/dist/chunk-U27JRO5L.js +13 -0
- package/dist/chunk-U27JRO5L.js.map +1 -0
- package/dist/{chunk-X77SUM4P.js → chunk-USHB5KEY.js} +3 -3
- package/dist/{chunk-X77SUM4P.js.map → chunk-USHB5KEY.js.map} +1 -1
- package/dist/{chunk-QVFAS5IO.js → chunk-V5JHD4I2.js} +3 -3
- package/dist/{chunk-QVFAS5IO.js.map → chunk-V5JHD4I2.js.map} +1 -1
- package/dist/{chunk-PQFHMQHQ.js → chunk-VLBIME5L.js} +6 -6
- package/dist/{chunk-PQFHMQHQ.js.map → chunk-VLBIME5L.js.map} +1 -1
- package/dist/{chunk-D3B36CYC.js → chunk-X3RMRJNR.js} +4 -3
- package/dist/chunk-X3RMRJNR.js.map +1 -0
- package/dist/{chunk-TCHRMVTO.js → chunk-XBYSURMK.js} +4 -4
- package/dist/{chunk-TCHRMVTO.js.map → chunk-XBYSURMK.js.map} +1 -1
- package/dist/{chunk-MZG34MBZ.js → chunk-XJYBCDY2.js} +3 -3
- package/dist/{chunk-MZG34MBZ.js.map → chunk-XJYBCDY2.js.map} +1 -1
- package/dist/{chunk-4A4OD24G.js → chunk-Y4Z7LGSH.js} +9 -9
- package/dist/{chunk-4A4OD24G.js.map → chunk-Y4Z7LGSH.js.map} +1 -1
- package/dist/{chunk-DZMNFCWB.js → chunk-Y7WKXPWS.js} +816 -143
- package/dist/chunk-Y7WKXPWS.js.map +1 -0
- package/dist/{chunk-HCEVNYSH.js → chunk-YTZFSKWL.js} +3 -3
- package/dist/{chunk-HCEVNYSH.js.map → chunk-YTZFSKWL.js.map} +1 -1
- package/dist/{chunk-WSBKB4CJ.js → chunk-ZSMMX3JD.js} +167 -25
- package/dist/chunk-ZSMMX3JD.js.map +1 -0
- package/dist/{chunk-GCHPUTA3.js → chunk-ZU24LWBI.js} +3 -3
- package/dist/{chunk-GCHPUTA3.js.map → chunk-ZU24LWBI.js.map} +1 -1
- package/dist/cli/index.js +1427 -605
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/agent-checks.d.ts +40 -0
- package/dist/cli/src/agent-checks.d.ts.map +1 -0
- package/dist/cli/src/asset-feeds.d.ts.map +1 -1
- package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/catalog-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/catalog.d.ts +26 -0
- package/dist/cli/src/commands/catalog.d.ts.map +1 -1
- package/dist/cli/src/commands/config.d.ts.map +1 -1
- package/dist/cli/src/commands/diff.d.ts +1 -1
- package/dist/cli/src/commands/diff.d.ts.map +1 -1
- package/dist/cli/src/commands/integration.d.ts.map +1 -1
- package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/library-index.d.ts +10 -0
- package/dist/cli/src/commands/library-index.d.ts.map +1 -1
- package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
- package/dist/cli/src/commands/mcp-server.d.ts +1 -1
- package/dist/cli/src/commands/migrate-assets.d.ts +2 -1
- package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
- package/dist/cli/src/commands/migrate.d.ts.map +1 -1
- package/dist/cli/src/commands/plugin/claude-code.d.ts +1 -1
- package/dist/cli/src/commands/plugin/claude-code.d.ts.map +1 -1
- package/dist/cli/src/commands/plugin/types.d.ts +3 -1
- package/dist/cli/src/commands/plugin/types.d.ts.map +1 -1
- package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/preset-apply.d.ts.map +1 -1
- package/dist/cli/src/commands/project.d.ts +8 -0
- package/dist/cli/src/commands/project.d.ts.map +1 -1
- package/dist/cli/src/commands/publish-core.d.ts +5 -0
- package/dist/cli/src/commands/publish-core.d.ts.map +1 -1
- package/dist/cli/src/commands/run.d.ts +11 -1
- package/dist/cli/src/commands/run.d.ts.map +1 -1
- package/dist/cli/src/commands/serve-preflight.d.ts +23 -0
- package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -0
- package/dist/cli/src/commands/serve.d.ts.map +1 -1
- package/dist/cli/src/commands/source-manifest-publish.d.ts.map +1 -1
- package/dist/cli/src/commands/source-manifest.d.ts +1 -0
- package/dist/cli/src/commands/source-manifest.d.ts.map +1 -1
- package/dist/cli/src/commands/source.d.ts +9 -1
- package/dist/cli/src/commands/source.d.ts.map +1 -1
- package/dist/cli/src/commands/store.d.ts.map +1 -1
- package/dist/cli/src/commands/tree.d.ts.map +1 -1
- package/dist/cli/src/commands/update.d.ts.map +1 -1
- package/dist/cli/src/commands/validate-instances.d.ts.map +1 -1
- package/dist/cli/src/commands/validate.d.ts +3 -2
- package/dist/cli/src/commands/validate.d.ts.map +1 -1
- package/dist/cli/src/commands/why.d.ts.map +1 -1
- package/dist/cli/src/curated-manifests.d.ts +21 -0
- package/dist/cli/src/curated-manifests.d.ts.map +1 -0
- package/dist/cli/src/driver-error.d.ts +7 -0
- package/dist/cli/src/driver-error.d.ts.map +1 -1
- package/dist/cli/src/helpers.d.ts +6 -0
- package/dist/cli/src/helpers.d.ts.map +1 -1
- package/dist/cli/src/index-busy.d.ts +8 -0
- package/dist/cli/src/index-busy.d.ts.map +1 -0
- package/dist/cli/src/plugin-store/index.d.ts +1 -1
- package/dist/cli/src/plugin-store/index.d.ts.map +1 -1
- package/dist/cli/src/plugin-store/paths.d.ts +7 -3
- package/dist/cli/src/plugin-store/paths.d.ts.map +1 -1
- package/dist/cli/src/plugin-store/reconcile.d.ts +24 -4
- package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -1
- package/dist/cli/src/skill-checks.d.ts +27 -3
- package/dist/cli/src/skill-checks.d.ts.map +1 -1
- package/dist/cli/src/store-addable.d.ts +17 -0
- package/dist/cli/src/store-addable.d.ts.map +1 -0
- package/dist/connectors/config.js +6 -6
- package/dist/connectors/index.js +18 -18
- package/dist/connectors/src/config.d.ts.map +1 -1
- package/dist/{connectors-4QWAKPHB.js → connectors-GFKMKAXV.js} +21 -21
- package/dist/{connectors-4QWAKPHB.js.map → connectors-GFKMKAXV.js.map} +1 -1
- package/dist/core/driver-targets.js +1 -1
- package/dist/core/index.js +9 -9
- package/dist/core/logging.js +1 -1
- package/dist/core/manifest.js +2 -2
- package/dist/core/models.js +1 -1
- package/dist/core/publish-manifest.js +4 -2
- package/dist/core/ref.js +1 -1
- package/dist/core/runtime-assets.js +6 -6
- package/dist/core/src/agent-instances.d.ts +5 -0
- package/dist/core/src/agent-instances.d.ts.map +1 -1
- package/dist/core/src/driver-targets.d.ts.map +1 -1
- package/dist/core/src/index.d.ts +6 -5
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/lock.d.ts +15 -5
- package/dist/core/src/lock.d.ts.map +1 -1
- package/dist/core/src/logging/sinks/sqlite-sink.d.ts.map +1 -1
- package/dist/core/src/manifest.d.ts +14 -3
- package/dist/core/src/manifest.d.ts.map +1 -1
- package/dist/core/src/models.d.ts +11 -3
- package/dist/core/src/models.d.ts.map +1 -1
- package/dist/core/src/package-manager.d.ts +19 -0
- package/dist/core/src/package-manager.d.ts.map +1 -0
- package/dist/core/src/publish-manifest.d.ts +38 -1
- package/dist/core/src/publish-manifest.d.ts.map +1 -1
- package/dist/core/src/repo-manager.d.ts +19 -3
- package/dist/core/src/repo-manager.d.ts.map +1 -1
- package/dist/core/src/runtime-assets.d.ts.map +1 -1
- package/dist/core/src/settings.d.ts +26 -6
- package/dist/core/src/settings.d.ts.map +1 -1
- package/dist/core/src/store.d.ts +4 -0
- package/dist/core/src/store.d.ts.map +1 -1
- package/dist/core/src/walker.d.ts +8 -1
- package/dist/core/src/walker.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts +24 -2
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/store.js +2 -2
- package/dist/core/workspace-config.js +5 -5
- package/dist/deploy/index.js +9 -9
- package/dist/discovery/index.js +5 -5
- package/dist/discovery/src/parse-manifest.d.ts.map +1 -1
- package/dist/discovery/src/source-config.d.ts +5 -3
- package/dist/discovery/src/source-config.d.ts.map +1 -1
- package/dist/{ensure-sources-2RONZKCU.js → ensure-sources-VUKHL65L.js} +21 -21
- package/dist/{ensure-sources-2RONZKCU.js.map → ensure-sources-VUKHL65L.js.map} +1 -1
- package/dist/factory-assets/README.md +1 -1
- package/dist/factory-assets/connectors/box.js +18 -18
- package/dist/factory-assets/connectors/deploy.js +18 -18
- package/dist/factory-assets/connectors/devserver.js +18 -18
- package/dist/factory-assets/connectors/flow/adapter.js +18 -18
- package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/contract.js +1 -1
- package/dist/factory-assets/connectors/flow/engine.js +11 -11
- package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/run-flow.js +20 -20
- package/dist/factory-assets/connectors/flow.js +18 -18
- package/dist/factory-assets/connectors/git.js +18 -18
- package/dist/factory-assets/connectors/gmail.js +18 -18
- package/dist/factory-assets/connectors/googledrive.js +18 -18
- package/dist/factory-assets/connectors/local.js +18 -18
- package/dist/factory-assets/connectors/mattermost.js +18 -18
- package/dist/factory-assets/connectors/memory.js +18 -18
- package/dist/factory-assets/connectors/minio.js +18 -18
- package/dist/factory-assets/connectors/postgres.js +18 -18
- package/dist/factory-assets/connectors/s3.js +18 -18
- package/dist/factory-assets/connectors/sharepoint.js +18 -18
- package/dist/factory-assets/connectors/sqlite.js +18 -18
- package/dist/factory-assets/connectors/static-server.js +18 -18
- package/dist/factory-assets/connectors/tunnel.js +18 -18
- package/dist/factory-assets/connectors/webdav.js +18 -18
- package/dist/factory-assets/connectors/xstate-store.js +18 -18
- package/dist/factory-assets/connectors/xstate.js +18 -18
- package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +10 -8
- package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +15 -11
- package/dist/factory-assets/skills/authoring-skaile-manifests/references/dependency-standard.md +12 -9
- package/dist/factory-assets/skills/skaile-author-asset/SKILL.md +2 -2
- package/dist/flows-A4YALSZY.js +26 -0
- package/dist/{flows-EQF2CH4U.js.map → flows-A4YALSZY.js.map} +1 -1
- package/dist/helpers-53XZW7KF.js +34 -0
- package/dist/{helpers-CFK6YP6R.js.map → helpers-53XZW7KF.js.map} +1 -1
- package/dist/library/index.js +14 -14
- package/dist/library/install.js +6 -4
- package/dist/library/src/index.d.ts +2 -2
- package/dist/library/src/index.d.ts.map +1 -1
- package/dist/library/src/install/source-fetch-github.d.ts.map +1 -1
- package/dist/library/src/local/db.d.ts +2 -0
- package/dist/library/src/local/db.d.ts.map +1 -1
- package/dist/library/src/local/library-manager.d.ts +5 -0
- package/dist/library/src/local/library-manager.d.ts.map +1 -1
- package/dist/library/src/local/library.d.ts +5 -3
- package/dist/library/src/local/library.d.ts.map +1 -1
- package/dist/library/src/local/local-catalog-source.d.ts +6 -0
- package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
- package/dist/library/src/local/store-paths.d.ts +9 -0
- package/dist/library/src/local/store-paths.d.ts.map +1 -1
- package/dist/library/src/manifest-writer.d.ts +1 -1
- package/dist/library/src/manifest-writer.d.ts.map +1 -1
- package/dist/library/src/remote/index.d.ts +1 -1
- package/dist/library/src/remote/index.d.ts.map +1 -1
- package/dist/library/src/remote/remote-catalog-source.d.ts +17 -0
- package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
- package/dist/library/src/sync/git-driver.d.ts.map +1 -1
- package/dist/library/src/user-library.d.ts +2 -0
- package/dist/library/src/user-library.d.ts.map +1 -1
- package/dist/{library-publish-53UTB3MB.js → library-publish-FFIPWIRM.js} +50 -39
- package/dist/library-publish-FFIPWIRM.js.map +1 -0
- package/dist/open-library-PZAT3TJA.js +40 -0
- package/dist/{open-library-BOSPJVID.js.map → open-library-PZAT3TJA.js.map} +1 -1
- package/dist/open-registry-W46UXZ3I.js +32 -0
- package/dist/{open-registry-4FI7HKET.js.map → open-registry-W46UXZ3I.js.map} +1 -1
- package/dist/paths-KKY3NSBZ.js +22 -0
- package/dist/{paths-SUS4S4YT.js.map → paths-KKY3NSBZ.js.map} +1 -1
- package/dist/plugin-store-CK7YWRIC.js +227 -0
- package/dist/plugin-store-CK7YWRIC.js.map +1 -0
- package/dist/plugins/src/catalog-source.d.ts +6 -0
- package/dist/plugins/src/catalog-source.d.ts.map +1 -1
- package/dist/project-EZUH7PUJ.js +79 -0
- package/dist/{project-I55A4O2T.js.map → project-EZUH7PUJ.js.map} +1 -1
- package/dist/resolver/index.js +10 -10
- package/dist/runner/index.js +35 -35
- package/dist/runner/src/agent.d.ts.map +1 -1
- package/dist/runner/src/agents/in-process-host.d.ts.map +1 -1
- package/dist/runner/src/composition/index.d.ts +2 -1
- package/dist/runner/src/composition/index.d.ts.map +1 -1
- package/dist/runner/src/composition/prompt-sections.d.ts +20 -5
- package/dist/runner/src/composition/prompt-sections.d.ts.map +1 -1
- package/dist/runner/src/composition/resolve.d.ts +10 -1
- package/dist/runner/src/composition/resolve.d.ts.map +1 -1
- package/dist/runner/src/composition/verify.d.ts +29 -0
- package/dist/runner/src/composition/verify.d.ts.map +1 -0
- package/dist/runner/src/credential-notice.d.ts +14 -0
- package/dist/runner/src/credential-notice.d.ts.map +1 -0
- package/dist/runner/src/environment.d.ts.map +1 -1
- package/dist/runner/src/final-text.d.ts +17 -0
- package/dist/runner/src/final-text.d.ts.map +1 -0
- package/dist/runner/src/index.d.ts +2 -0
- package/dist/runner/src/index.d.ts.map +1 -1
- package/dist/runner/src/resource-handler.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts +13 -0
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/runner/src/session-builder.d.ts.map +1 -1
- package/dist/runner/src/session.d.ts +2 -0
- package/dist/runner/src/session.d.ts.map +1 -1
- package/dist/runner/src/ws-auth-warning.d.ts +17 -0
- package/dist/runner/src/ws-auth-warning.d.ts.map +1 -0
- package/dist/sdk/asset-manager.js +18 -18
- package/dist/sdk/bridge.js +14 -14
- package/dist/sdk/core.js +9 -9
- package/dist/sdk/flow.js +11 -11
- package/dist/sdk/index.js +38 -36
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/resolver.js +10 -10
- package/dist/sdk/runner.js +35 -35
- package/dist/sdk/src/local-runtime.d.ts.map +1 -1
- package/dist/sdk/transport/ws/client.js +1 -1
- package/dist/sdk/transport/ws/server.js +1 -1
- package/dist/sdk/transport/ws.js +2 -2
- package/dist/sdk/transport.js +2 -2
- package/dist/serve-preflight-F7MYF747.js +64 -0
- package/dist/serve-preflight-F7MYF747.js.map +1 -0
- package/dist/{setup-7DQJKHUI.js → setup-L632QIHV.js} +26 -26
- package/dist/{setup-7DQJKHUI.js.map → setup-L632QIHV.js.map} +1 -1
- package/dist/skills-OY3Y5GKA.js +26 -0
- package/dist/{skills-NUEN5NDX.js.map → skills-OY3Y5GKA.js.map} +1 -1
- package/dist/source-36FHMN5V.js +42 -0
- package/dist/{source-G2LV5LVD.js.map → source-36FHMN5V.js.map} +1 -1
- package/dist/source-fetch-github-PIO6EMMF.js +4 -0
- package/dist/{source-fetch-github-QN4LLTL5.js.map → source-fetch-github-PIO6EMMF.js.map} +1 -1
- package/dist/{source-manifest-publish-6RM7SWLZ.js → source-manifest-publish-NIXJSJ22.js} +30 -28
- package/dist/source-manifest-publish-NIXJSJ22.js.map +1 -0
- package/dist/transport/index.js +2 -2
- package/dist/transport/src/ws/client.d.ts +6 -0
- package/dist/transport/src/ws/client.d.ts.map +1 -1
- package/dist/transport/src/ws/server.d.ts +4 -0
- package/dist/transport/src/ws/server.d.ts.map +1 -1
- package/dist/transport/ws/client.js +1 -1
- package/dist/transport/ws/server.js +1 -1
- package/dist/transport/ws.js +2 -2
- package/dist/tui/index.js +77 -50
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/src/repl-session.d.ts +1 -1
- package/dist/tui/src/repl-session.d.ts.map +1 -1
- package/dist/tui/src/repl.d.ts +3 -0
- package/dist/tui/src/repl.d.ts.map +1 -1
- package/dist/types/manifests.js +1 -1
- package/dist/types/src/lifecycle.d.ts +2 -1
- package/dist/types/src/lifecycle.d.ts.map +1 -1
- package/dist/types/src/manifests/agent-composition.d.ts +20 -0
- package/dist/types/src/manifests/agent-composition.d.ts.map +1 -1
- package/dist/types/src/manifests/agent.d.ts.map +1 -1
- package/dist/types/src/manifests/cron.d.ts +15 -0
- package/dist/types/src/manifests/cron.d.ts.map +1 -0
- package/dist/types/src/manifests/index.d.ts +3 -2
- package/dist/types/src/manifests/index.d.ts.map +1 -1
- package/dist/types/src/manifests/preset.d.ts +6 -1
- package/dist/types/src/manifests/preset.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +25 -25
- package/dist/workspace-plugin/adapters/omp.js +106 -51
- package/dist/workspace-plugin/adapters/omp.js.map +1 -1
- package/dist/workspace-plugin/index.js +2 -2
- package/dist/workspace-plugin/src/adapters/claude-code.d.ts.map +1 -1
- package/dist/workspace-plugin/src/adapters/omp.d.ts +11 -2
- package/dist/workspace-plugin/src/adapters/omp.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/asset-feeds-CXGQIDFR.js.map +0 -1
- package/dist/chunk-2F5AWQX5.js.map +0 -1
- package/dist/chunk-3SM2DL2T.js.map +0 -1
- package/dist/chunk-47U4GZ4M.js.map +0 -1
- package/dist/chunk-5LKOAX7I.js.map +0 -1
- package/dist/chunk-6O2X3GPW.js.map +0 -1
- package/dist/chunk-ALEYHUC5.js.map +0 -1
- package/dist/chunk-CGYEHQOX.js.map +0 -1
- package/dist/chunk-CJERAGFY.js.map +0 -1
- package/dist/chunk-CPSIPIX7.js.map +0 -1
- package/dist/chunk-D3B36CYC.js.map +0 -1
- package/dist/chunk-DZMNFCWB.js.map +0 -1
- package/dist/chunk-EDYHEMJA.js.map +0 -1
- package/dist/chunk-FH7W6TJ4.js.map +0 -1
- package/dist/chunk-GV4DZ6MT.js.map +0 -1
- package/dist/chunk-HZXUXHIV.js.map +0 -1
- package/dist/chunk-J4RBUFGM.js.map +0 -1
- package/dist/chunk-NWDSLXOX.js.map +0 -1
- package/dist/chunk-OBYKJB4U.js.map +0 -1
- package/dist/chunk-PBBPZYVG.js.map +0 -1
- package/dist/chunk-PMECEZK3.js.map +0 -1
- package/dist/chunk-R7FOF242.js +0 -59
- package/dist/chunk-R7FOF242.js.map +0 -1
- package/dist/chunk-R7NHYEJF.js.map +0 -1
- package/dist/chunk-RYYLMBA2.js +0 -392
- package/dist/chunk-RYYLMBA2.js.map +0 -1
- package/dist/chunk-SBSA3IQA.js.map +0 -1
- package/dist/chunk-VLTQGE2E.js.map +0 -1
- package/dist/chunk-WSBKB4CJ.js.map +0 -1
- package/dist/chunk-YOH2L76X.js +0 -505
- package/dist/chunk-YOH2L76X.js.map +0 -1
- package/dist/chunk-ZCAJZ4B2.js.map +0 -1
- package/dist/chunk-ZPWTOUTK.js.map +0 -1
- package/dist/flows-EQF2CH4U.js +0 -26
- package/dist/helpers-CFK6YP6R.js +0 -34
- package/dist/library-publish-53UTB3MB.js.map +0 -1
- package/dist/open-library-BOSPJVID.js +0 -40
- package/dist/open-registry-4FI7HKET.js +0 -32
- package/dist/paths-SUS4S4YT.js +0 -22
- package/dist/plugin-store-AGQDMING.js +0 -149
- package/dist/plugin-store-AGQDMING.js.map +0 -1
- package/dist/project-I55A4O2T.js +0 -41
- package/dist/skills-NUEN5NDX.js +0 -26
- package/dist/source-G2LV5LVD.js +0 -41
- package/dist/source-fetch-github-QN4LLTL5.js +0 -4
- package/dist/source-manifest-publish-6RM7SWLZ.js.map +0 -1
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { unregisteredLibraryNames, renamedLibraryName, scanUnlistedAssets, getStoreManifestsDir, missingLibraryDirMessage } from './chunk-
|
|
2
|
-
import { readManifestSourceConfig,
|
|
3
|
-
import { installTargetOf, canonicalEntryRef, deployAll, removeAsset, diffDeployedAgent,
|
|
1
|
+
import { unregisteredLibraryNames, renamedLibraryName, resolveConfig, RemoteCatalogSource, OfflineError, describeCatalogError, CatalogHttpError, scanUnlistedAssets, getStoreManifestsDir, missingLibraryDirMessage } from './chunk-DKGEV6SQ.js';
|
|
2
|
+
import { readManifestSourceConfig, discoverAssetsInTree, isManifestMode } from './chunk-NVO6WECE.js';
|
|
3
|
+
import { installTargetOf, canonicalEntryRef, deployedAssetDrift, deployAll, removeAsset, diffDeployedAgent, createScaffold, installAgent } from './chunk-5FYOM4RF.js';
|
|
4
4
|
import { appendHistory, getRecentHistory, clearHistory } from './chunk-KTBKW2FI.js';
|
|
5
5
|
import { commitChanges } from './chunk-UQ6LFBPZ.js';
|
|
6
|
-
import { driverTargetSupportsAgents, CODEX_IDENTITY_DIR } from './chunk-
|
|
7
|
-
import { resolveConfiguredDriverTarget, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, buildLockFile, writeLock, readLock, verifyLock, mergeLockFile, extractForPatch, generatePatch, savePatch, applyPatch,
|
|
8
|
-
import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-
|
|
9
|
-
import { deployedBase, deployedDir, isDeployed, deployedPaths } from './chunk-
|
|
10
|
-
import { resolveSkWorkspaceConfig, effectiveAgentInstances, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, resolveAll, ensureRepo, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset,
|
|
6
|
+
import { driverTargetSupportsAgents, CODEX_IDENTITY_DIR } from './chunk-4L4R5LV3.js';
|
|
7
|
+
import { resolveConfiguredDriverTarget, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, computeHash, buildLockFile, writeLock, readLock, verifyLock, mergeLockFile, extractForPatch, generatePatch, savePatch, applyPatch, LOCK_SCHEMA_VERSION } from './chunk-BF422IDP.js';
|
|
8
|
+
import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-QO7CR3KB.js';
|
|
9
|
+
import { deployedBase, deployedDir, isDeployed, deployedPaths } from './chunk-D54T2F54.js';
|
|
10
|
+
import { resolveSkWorkspaceConfig, effectiveAgentInstances, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, readLinks, isCommitOnRemote, resolveAll, agentSourceCacheDir, ensureRepo, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, MAX_PRESET_DEPTH, PresetDepthError, DEFAULT_AGENT_INSTANCE_ID, resolveAgentDefinitionDir, storeManifestSlug } from './chunk-L3ZGYSWY.js';
|
|
11
11
|
import { globalSkaileDir, globalCacheRoot, migrateLegacyDir } from './chunk-L5VSIPQD.js';
|
|
12
|
-
import { DRIVER_TARGETS } from './chunk-
|
|
13
|
-
import { loadSkPublishManifest } from './chunk-
|
|
14
|
-
import { scanDirectory, parseRequires, dedupeRequirements } from './chunk-
|
|
15
|
-
import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr } from './chunk-
|
|
12
|
+
import { DRIVER_TARGETS } from './chunk-IG5LZ3WU.js';
|
|
13
|
+
import { loadSkPublishManifest } from './chunk-IY5E7Y5W.js';
|
|
14
|
+
import { scanDirectory, parseFrontmatter, parseRequires, dedupeRequirements } from './chunk-M3P4BYRK.js';
|
|
15
|
+
import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr, parseDep } from './chunk-J4OYIYFQ.js';
|
|
16
16
|
import { spawnSync } from 'child_process';
|
|
17
|
-
import { existsSync, rmSync, readdirSync, lstatSync, unlinkSync, mkdirSync, writeFileSync
|
|
17
|
+
import { existsSync, rmSync, readdirSync, lstatSync, readFileSync, unlinkSync, mkdirSync, writeFileSync } from 'fs';
|
|
18
18
|
import path, { resolve, dirname, sep, join, relative, posix } from 'path';
|
|
19
19
|
import { gt } from 'semver';
|
|
20
20
|
import { stringify, parse } from 'yaml';
|
|
@@ -401,6 +401,19 @@ function filesUnderManifestDir(paths, manifestRel) {
|
|
|
401
401
|
const manifestDir = posix.dirname(manifestRel);
|
|
402
402
|
return paths.map((p) => posix.relative(manifestDir, p)).filter((rel) => rel !== "" && !rel.startsWith(".."));
|
|
403
403
|
}
|
|
404
|
+
function lockedAssetFiles(kind, files) {
|
|
405
|
+
const manifestRel = matchManifestPath(
|
|
406
|
+
kind,
|
|
407
|
+
files.map((f) => f.path)
|
|
408
|
+
) ?? files[0]?.path;
|
|
409
|
+
if (!manifestRel) return [];
|
|
410
|
+
const manifestDir = posix.dirname(manifestRel);
|
|
411
|
+
return files.flatMap((f) => {
|
|
412
|
+
const rel = posix.relative(manifestDir, f.path);
|
|
413
|
+
return rel === "" || rel.startsWith("..") ? [] : [{ rel, sha256: f.sha256 }];
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
var GITHUB_REPO_URL = /github\.com[/:]/i;
|
|
404
417
|
function indexLockByKindName(lock) {
|
|
405
418
|
const lockByKindName = /* @__PURE__ */ new Map();
|
|
406
419
|
for (const [key, entry] of Object.entries(lock?.assets ?? {})) {
|
|
@@ -435,6 +448,28 @@ function commitsBetween(repoDir, from, to, cache) {
|
|
|
435
448
|
return count;
|
|
436
449
|
}
|
|
437
450
|
var COMMIT_ID = /^[0-9a-f]{7,64}$/;
|
|
451
|
+
function commitsTouching(repoDir, from, to, dir, cache) {
|
|
452
|
+
if (!COMMIT_ID.test(from) || !COMMIT_ID.test(to)) return null;
|
|
453
|
+
if (from === to) return 0;
|
|
454
|
+
const key = `${from}..${to} -- ${dir}`;
|
|
455
|
+
const hit = cache.get(key);
|
|
456
|
+
if (hit !== void 0) return hit;
|
|
457
|
+
const r = spawnSync("git", ["-C", repoDir, "rev-list", "--count", `${from}..${to}`, "--", dir], {
|
|
458
|
+
encoding: "utf8",
|
|
459
|
+
stdio: "pipe"
|
|
460
|
+
});
|
|
461
|
+
const n = r.status === 0 ? Number.parseInt(r.stdout.trim(), 10) : Number.NaN;
|
|
462
|
+
if (!Number.isFinite(n) || n < 0) return null;
|
|
463
|
+
cache.set(key, n);
|
|
464
|
+
return n;
|
|
465
|
+
}
|
|
466
|
+
function lockedAssetDir(kind, files) {
|
|
467
|
+
const manifestRel = matchManifestPath(
|
|
468
|
+
kind,
|
|
469
|
+
files.map((f) => f.path)
|
|
470
|
+
) ?? files[0]?.path;
|
|
471
|
+
return manifestRel ? posix.dirname(manifestRel) : ".";
|
|
472
|
+
}
|
|
438
473
|
function libraryDiskHashes(libPath, cache, registry) {
|
|
439
474
|
let hashes = cache.get(libPath);
|
|
440
475
|
if (!hashes) {
|
|
@@ -506,7 +541,7 @@ function newestLibraryDef(snap, libraryName, id) {
|
|
|
506
541
|
}
|
|
507
542
|
return best;
|
|
508
543
|
}
|
|
509
|
-
function libraryPreference(isDefaultLib) {
|
|
544
|
+
function libraryPreference(isDefaultLib, rank) {
|
|
510
545
|
return (a, b) => {
|
|
511
546
|
const va = coerceVersion(a.entry.version ?? "");
|
|
512
547
|
const vb = coerceVersion(b.entry.version ?? "");
|
|
@@ -514,7 +549,9 @@ function libraryPreference(isDefaultLib) {
|
|
|
514
549
|
if (gt(vb, va)) return 1;
|
|
515
550
|
const da = isDefaultLib.get(a.library) ? 0 : 1;
|
|
516
551
|
const db = isDefaultLib.get(b.library) ? 0 : 1;
|
|
517
|
-
return da - db
|
|
552
|
+
if (da !== db) return da - db;
|
|
553
|
+
const byRank = rank ? rank(a) - rank(b) : 0;
|
|
554
|
+
return byRank || a.library.localeCompare(b.library);
|
|
518
555
|
};
|
|
519
556
|
}
|
|
520
557
|
function qualifyDepRef(ref, fallback) {
|
|
@@ -649,15 +686,18 @@ function withKeptLockEntries(lock, kept) {
|
|
|
649
686
|
for (const s of kept.sources) if (!sources.has(s.url)) sources.set(s.url, s);
|
|
650
687
|
return {
|
|
651
688
|
...lock,
|
|
652
|
-
|
|
653
|
-
schema_version: lock.schema_version === 4 || Object.values(kept.assets).some((e) => e.library) ? 4 : 3,
|
|
689
|
+
schema_version: LOCK_SCHEMA_VERSION,
|
|
654
690
|
assets: { ...lock.assets, ...kept.assets },
|
|
655
691
|
sources: [...sources.values()].sort((a, b) => a.url.localeCompare(b.url))
|
|
656
692
|
};
|
|
657
693
|
}
|
|
658
694
|
function relockedRefs(prev, next) {
|
|
659
695
|
if (!prev) return [];
|
|
660
|
-
const fingerprint = (e) => [
|
|
696
|
+
const fingerprint = (e, key) => [
|
|
697
|
+
e.library?.version ?? "",
|
|
698
|
+
e.library?.sha256 ?? e.sha256,
|
|
699
|
+
key.includes("#0.0.0-sha.") ? "" : e.source?.commit ?? ""
|
|
700
|
+
].join("\0");
|
|
661
701
|
const out = [];
|
|
662
702
|
for (const [key, entry] of Object.entries(next.assets)) {
|
|
663
703
|
if (entry.library?.installed) continue;
|
|
@@ -667,7 +707,8 @@ function relockedRefs(prev, next) {
|
|
|
667
707
|
return o.kind === id.kind && o.name === id.name && o.publisher === id.publisher;
|
|
668
708
|
});
|
|
669
709
|
if (!before) continue;
|
|
670
|
-
if (before[0] !== key || fingerprint(before[1]) !== fingerprint(entry
|
|
710
|
+
if (before[0] !== key || fingerprint(before[1], before[0]) !== fingerprint(entry, key))
|
|
711
|
+
out.push(key);
|
|
671
712
|
}
|
|
672
713
|
return out;
|
|
673
714
|
}
|
|
@@ -793,6 +834,17 @@ var AssetManager = class {
|
|
|
793
834
|
onLibraryCollision;
|
|
794
835
|
/** Store URLs whose failed version lookup was already reported (one warning per URL). */
|
|
795
836
|
warnedStoreVersionLookups = /* @__PURE__ */ new Set();
|
|
837
|
+
/** Stores a lookup could not reach (store URL -> one line why); `add` reports them instead of "not found". */
|
|
838
|
+
storeFailures = /* @__PURE__ */ new Map();
|
|
839
|
+
/** Sources a provenance walk had to skip (source URL → why); one warning per source. */
|
|
840
|
+
skippedSources = /* @__PURE__ */ new Map();
|
|
841
|
+
/** `onSourceError` of every provenance walk: name the source once, leave it out, go on. */
|
|
842
|
+
reportSourceError = (clone, err) => {
|
|
843
|
+
const why = err instanceof Error ? err.message : String(err);
|
|
844
|
+
if (this.skippedSources.has(clone.sourceUrl)) return;
|
|
845
|
+
this.skippedSources.set(clone.sourceUrl, why);
|
|
846
|
+
console.warn(`skaile: source ${clone.sourceUrl} skipped: ${why}`);
|
|
847
|
+
};
|
|
796
848
|
constructor(opts) {
|
|
797
849
|
this.projectDir = resolve(opts.projectDir);
|
|
798
850
|
this.global = opts.global ?? false;
|
|
@@ -827,15 +879,27 @@ var AssetManager = class {
|
|
|
827
879
|
return this.global ? globalSkaileDir() : this.projectDir;
|
|
828
880
|
}
|
|
829
881
|
/**
|
|
830
|
-
* The harnesses a global deploy fans out to: the explicit `harnesses` override
|
|
831
|
-
*
|
|
832
|
-
*
|
|
882
|
+
* The harnesses a global deploy fans out to: the explicit `harnesses` override (a `--harness`
|
|
883
|
+
* filter), else the explicit `global_harnesses:` of `~/.skaile/skaile.yaml`, else every harness
|
|
884
|
+
* whose root dir exists under `~` plus the harness the project is configured for (a project on
|
|
885
|
+
* a harness whose dir does not exist yet still gets its user-scope assets). In project mode
|
|
886
|
+
* this is exactly `[driverTarget]`, so the shared fan-out loop degenerates to the
|
|
833
887
|
* single-target path.
|
|
834
888
|
*/
|
|
835
889
|
targetHarnesses() {
|
|
836
890
|
if (!this.global) return [this.driverTarget];
|
|
837
891
|
if (this.harnessesOverride && this.harnessesOverride.length > 0) return this.harnessesOverride;
|
|
838
|
-
|
|
892
|
+
const resolved = resolveGlobalHarnesses();
|
|
893
|
+
if (resolveGlobalSkWorkspaceConfig().global_harnesses?.length) return resolved;
|
|
894
|
+
const configured = resolveConfiguredDriverTarget(this.projectDir);
|
|
895
|
+
return configured && !resolved.includes(configured) ? [...resolved, configured] : resolved;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* The harnesses `add` / `install` deploy into: `[driverTarget]` for a project, the global
|
|
899
|
+
* harness set (see {@link AssetManager.targetHarnesses}) for a global manager.
|
|
900
|
+
*/
|
|
901
|
+
deployTargets() {
|
|
902
|
+
return this.targetHarnesses();
|
|
839
903
|
}
|
|
840
904
|
get storeCacheDir() {
|
|
841
905
|
if (this.global) return join(globalCacheRoot(), "store");
|
|
@@ -942,7 +1006,11 @@ var AssetManager = class {
|
|
|
942
1006
|
for (const s of sources) {
|
|
943
1007
|
const slug = sourceCacheKey(s.url);
|
|
944
1008
|
if (repositories[slug]) continue;
|
|
945
|
-
repositories[slug] = {
|
|
1009
|
+
repositories[slug] = {
|
|
1010
|
+
path: join(sourcesDir, slug),
|
|
1011
|
+
url: s.url,
|
|
1012
|
+
...s.publisher ? { publisher: s.publisher } : {}
|
|
1013
|
+
};
|
|
946
1014
|
}
|
|
947
1015
|
const factory = resolveFactorySource();
|
|
948
1016
|
const factoryUrl = normalizeRepoUrl(FACTORY_SOURCE_URL);
|
|
@@ -970,6 +1038,7 @@ var AssetManager = class {
|
|
|
970
1038
|
sourceUrl: decl.url ?? localPath,
|
|
971
1039
|
commit,
|
|
972
1040
|
tag: decl.branch,
|
|
1041
|
+
...decl.publisher ? { publisher: decl.publisher } : {},
|
|
973
1042
|
// A curated store manifest (`source manifest init` → the flat
|
|
974
1043
|
// `~/.skaile/store/manifests/<slug>.yaml`) is the authoritative inventory
|
|
975
1044
|
// for a foreign source. Point the walker at it so `add`/resolve honor the
|
|
@@ -1039,6 +1108,31 @@ var AssetManager = class {
|
|
|
1039
1108
|
if (c.homepage != null) entry.homepage = c.homepage;
|
|
1040
1109
|
return entry;
|
|
1041
1110
|
}
|
|
1111
|
+
/**
|
|
1112
|
+
* The {@link ProvenanceCandidate} a source- or store-origin lock entry stands for: what a
|
|
1113
|
+
* deploy needs to restore the asset from the commit the lock names (`files[]` is the asset's
|
|
1114
|
+
* whole file set). `null` for a library-origin entry or a key that is not a canonical ref.
|
|
1115
|
+
* The source URL is the declared source's own spelling (the bundled factory tree and a
|
|
1116
|
+
* `sources:` entry match their declaration by it).
|
|
1117
|
+
*/
|
|
1118
|
+
lockedCandidate(key, entry, repositories) {
|
|
1119
|
+
if (!entry.source) return null;
|
|
1120
|
+
const { publisher, kind, name, version } = parseCanonicalLockKey(key);
|
|
1121
|
+
if (!publisher || !kind || !name) return null;
|
|
1122
|
+
const url = entry.source.url;
|
|
1123
|
+
const factory = Object.values(repositories).find((d) => d.factory);
|
|
1124
|
+
const declared = factory?.url !== void 0 && normalizeRepoUrl(url) === normalizeRepoUrl(factory.url) ? factory : repositories[sourceCacheKey(url)];
|
|
1125
|
+
return {
|
|
1126
|
+
publisher,
|
|
1127
|
+
kind,
|
|
1128
|
+
name,
|
|
1129
|
+
version: version ?? "",
|
|
1130
|
+
sourceUrl: declared?.url ?? url,
|
|
1131
|
+
commit: entry.source.commit,
|
|
1132
|
+
files: entry.files,
|
|
1133
|
+
sha256: entry.sha256
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1042
1136
|
/**
|
|
1043
1137
|
* Resolve refs the source/store pass could not against the user's registered
|
|
1044
1138
|
* **libraries** (local authoring places). Each library dir is scanned on disk
|
|
@@ -1071,6 +1165,7 @@ var AssetManager = class {
|
|
|
1071
1165
|
const { byKey, isDefaultLib, libraryDir } = scan;
|
|
1072
1166
|
const entries = [];
|
|
1073
1167
|
const fileSets = /* @__PURE__ */ new Map();
|
|
1168
|
+
const diskHashes = /* @__PURE__ */ new Map();
|
|
1074
1169
|
let snap;
|
|
1075
1170
|
const allCandidates = [...byKey.values()].flat();
|
|
1076
1171
|
for (const ref of missing) {
|
|
@@ -1098,23 +1193,34 @@ var AssetManager = class {
|
|
|
1098
1193
|
}
|
|
1099
1194
|
let candidates = pool.filter((c) => !pin || matchPin(pin, c.entry.version ?? ""));
|
|
1100
1195
|
let lockedLibrary;
|
|
1196
|
+
const lockedMap = opts.preferLocked?.libraries ?? opts.lockedLibraries;
|
|
1101
1197
|
if (parsed.publisher) {
|
|
1102
|
-
lockedLibrary =
|
|
1198
|
+
lockedLibrary = lockedMap?.get(
|
|
1103
1199
|
`${parsed.kind}:${parsed.publisher.replace(/^@/, "")}/${parsed.name}`
|
|
1104
1200
|
);
|
|
1105
1201
|
} else {
|
|
1106
|
-
const same = [...
|
|
1202
|
+
const same = [...lockedMap ?? []].filter(([k]) => {
|
|
1107
1203
|
const slash = k.indexOf("/");
|
|
1108
1204
|
return k.startsWith(`${parsed.kind}:`) && k.slice(slash + 1) === parsed.name;
|
|
1109
1205
|
});
|
|
1110
1206
|
if (same.length === 1) lockedLibrary = same[0][1];
|
|
1111
1207
|
}
|
|
1112
|
-
if (lockedLibrary) {
|
|
1208
|
+
if (lockedLibrary && !opts.preferLocked) {
|
|
1113
1209
|
const inLocked = candidates.filter((c) => c.library === lockedLibrary);
|
|
1114
1210
|
if (inLocked.length > 0) candidates = inLocked;
|
|
1115
1211
|
}
|
|
1116
1212
|
if (candidates.length === 0) continue;
|
|
1117
|
-
|
|
1213
|
+
const prefer = opts.preferLocked ? (c) => {
|
|
1214
|
+
if (lockedLibrary && c.library === lockedLibrary) return 0;
|
|
1215
|
+
const id = `${c.entry.kind}:${(c.entry.publisher ?? "").replace(/^@/, "")}/${c.entry.name}`;
|
|
1216
|
+
const lockedSha = opts.preferLocked?.shas.get(id);
|
|
1217
|
+
const libPath = libraryDir.get(c.library);
|
|
1218
|
+
const onDisk = lockedSha && libPath ? libraryDiskHashes(libPath, diskHashes, this.registry).get(
|
|
1219
|
+
`${c.entry.kind}:${c.entry.name}`
|
|
1220
|
+
) : void 0;
|
|
1221
|
+
return onDisk !== void 0 && onDisk === lockedSha ? 1 : 2;
|
|
1222
|
+
} : void 0;
|
|
1223
|
+
candidates.sort(libraryPreference(isDefaultLib, prefer));
|
|
1118
1224
|
const hit = candidates[0];
|
|
1119
1225
|
if (!opts.quiet && !opts.library) {
|
|
1120
1226
|
this.warnLibraryCollision(
|
|
@@ -1255,7 +1361,8 @@ var AssetManager = class {
|
|
|
1255
1361
|
const cloneDirs = new Set(clones.map((c) => resolve(c.localPath)));
|
|
1256
1362
|
const index = await buildProvenanceIndex(clones, {
|
|
1257
1363
|
projectDir: this.projectDir,
|
|
1258
|
-
knownKinds: this.knownKinds
|
|
1364
|
+
knownKinds: this.knownKinds,
|
|
1365
|
+
onSourceError: this.reportSourceError
|
|
1259
1366
|
});
|
|
1260
1367
|
const factoryUrl = normalizeRepoUrl(FACTORY_SOURCE_URL);
|
|
1261
1368
|
const hasFactory = Object.values(repositories).some((d) => d.factory);
|
|
@@ -1464,6 +1571,34 @@ var AssetManager = class {
|
|
|
1464
1571
|
publisher: ref?.publisher ?? entry.publisher?.replace(/^@/, "")
|
|
1465
1572
|
};
|
|
1466
1573
|
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Refuse to lock a source commit another machine cannot check out. A commit made in the clone
|
|
1576
|
+
* itself (or one `source sync` could not fast-forward past) is in no remote branch: the lock
|
|
1577
|
+
* would name bytes nobody else has, and `install --locked` there could not restore them.
|
|
1578
|
+
* Linked (dev-override) and user-owned local sources are never checked: their lock is
|
|
1579
|
+
* machine-local by choice.
|
|
1580
|
+
*
|
|
1581
|
+
* @param resolved - Candidates about to be locked.
|
|
1582
|
+
* @param repositories - Source declarations of the project.
|
|
1583
|
+
* @throws With `<url> clone has unpublished commit <sha>` and the way out.
|
|
1584
|
+
*/
|
|
1585
|
+
assertSourceCommitsPublished(resolved, repositories) {
|
|
1586
|
+
const links = readLinks(this.projectDir);
|
|
1587
|
+
const checked = /* @__PURE__ */ new Set();
|
|
1588
|
+
for (const c of resolved) {
|
|
1589
|
+
if (!c.commit || /^0+$/.test(c.commit) || checked.has(`${c.sourceUrl}@${c.commit}`)) continue;
|
|
1590
|
+
checked.add(`${c.sourceUrl}@${c.commit}`);
|
|
1591
|
+
const hit = Object.entries(repositories).find(
|
|
1592
|
+
([, d]) => d.url !== void 0 && !d.factory && d.url === c.sourceUrl
|
|
1593
|
+
);
|
|
1594
|
+
if (!hit || links[hit[0]]) continue;
|
|
1595
|
+
const dir = this.resolveRepoDir(hit[1], hit[0]);
|
|
1596
|
+
if (!dir || isCommitOnRemote(dir, c.commit)) continue;
|
|
1597
|
+
throw new Error(
|
|
1598
|
+
`${c.sourceUrl} clone has unpublished commit ${c.commit.slice(0, 7)} - push it, or reset the clone (git -C ${dir} reset --hard origin/${hit[1].branch ?? "main"}) - nothing was locked`
|
|
1599
|
+
);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1467
1602
|
/**
|
|
1468
1603
|
* Refuse assets of one kind and name from different publishers: they deploy into the
|
|
1469
1604
|
* same folder, so the later one would silently overwrite the earlier. Throws one line
|
|
@@ -1505,6 +1640,83 @@ var AssetManager = class {
|
|
|
1505
1640
|
);
|
|
1506
1641
|
}
|
|
1507
1642
|
}
|
|
1643
|
+
/**
|
|
1644
|
+
* Refuse to deploy over a folder (or agent file) the project did not put there: it is on disk,
|
|
1645
|
+
* but no lock entry of the same kind and name owns it, so it is the user's own work and the
|
|
1646
|
+
* deploy would replace it and `remove` would delete it. Throws one line naming the folder.
|
|
1647
|
+
*
|
|
1648
|
+
* A folder the deploy would rewrite with the same content is adopted silently (the way back
|
|
1649
|
+
* from `asset import`: the project's own copy is what the library now holds): every file in
|
|
1650
|
+
* it is shipped by the asset with the same bytes, or the same body and an asset frontmatter
|
|
1651
|
+
* that only adds to the folder's (import normalizes it). Nothing is lost then.
|
|
1652
|
+
*
|
|
1653
|
+
* @param incoming - Assets about to be deployed, with the entry whose bytes would be written
|
|
1654
|
+
* when there is one.
|
|
1655
|
+
* @param owned - Assets the lock holds; one of the same kind and name, from any publisher,
|
|
1656
|
+
* owns the folder (a publisher clash is {@link assertNoFolderCollision}'s refusal).
|
|
1657
|
+
*/
|
|
1658
|
+
assertNoUnownedFolder(incoming, owned) {
|
|
1659
|
+
for (const { id: a, entry } of incoming) {
|
|
1660
|
+
if (!a.kind || !a.name) continue;
|
|
1661
|
+
const component = installTargetOf(this.registry, a.kind);
|
|
1662
|
+
if (!component) continue;
|
|
1663
|
+
const isOwned = owned.some(
|
|
1664
|
+
(o) => !!o.kind && o.name === a.name && installTargetOf(this.registry, o.kind) === component
|
|
1665
|
+
);
|
|
1666
|
+
if (isOwned) continue;
|
|
1667
|
+
for (const target of this.targetHarnesses()) {
|
|
1668
|
+
const held = deployedPaths(component, a.name, target, this.global, this.projectDir).find(
|
|
1669
|
+
(p) => existsSync(p)
|
|
1670
|
+
);
|
|
1671
|
+
if (!held) continue;
|
|
1672
|
+
if (entry && this.deployWouldOnlyRewriteSame(entry, target)) continue;
|
|
1673
|
+
const shown = this.global ? held : relative(this.projectDir, held);
|
|
1674
|
+
throw new Error(
|
|
1675
|
+
`${assetRefToStr({ kind: a.kind, name: a.name, publisher: a.publisher })} would overwrite ${shown}, which no lock entry owns (your own files?) \u2014 move it away, or pass --force to replace it`
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Whether deploying `entry` over the folder already in `target` loses nothing: the folder
|
|
1682
|
+
* holds no file the asset does not ship, and each of its files equals the asset's, or is a
|
|
1683
|
+
* markdown file with the same body whose frontmatter the asset's only extends.
|
|
1684
|
+
*/
|
|
1685
|
+
deployWouldOnlyRewriteSame(entry, target) {
|
|
1686
|
+
const drift = deployedAssetDrift(entry, {
|
|
1687
|
+
registry: this.registry,
|
|
1688
|
+
driverTarget: target,
|
|
1689
|
+
global: this.global,
|
|
1690
|
+
cwd: this.projectDir
|
|
1691
|
+
});
|
|
1692
|
+
if (!drift || drift.extra.length > 0) return false;
|
|
1693
|
+
if (drift.modified.length === 0) return true;
|
|
1694
|
+
const component = installTargetOf(this.registry, entry.kind);
|
|
1695
|
+
if (!component) return false;
|
|
1696
|
+
const dest = deployedDir(component, entry.name, target, this.global, this.projectDir);
|
|
1697
|
+
let assetRoot;
|
|
1698
|
+
try {
|
|
1699
|
+
assetRoot = lstatSync(entry.source).isDirectory() ? entry.source : dirname(entry.source);
|
|
1700
|
+
} catch {
|
|
1701
|
+
return false;
|
|
1702
|
+
}
|
|
1703
|
+
return drift.modified.every((rel) => {
|
|
1704
|
+
if (!/\.md$/i.test(rel)) return false;
|
|
1705
|
+
try {
|
|
1706
|
+
const mine = parseFrontmatter(readFileSync(join(dest, rel), "utf8"));
|
|
1707
|
+
const theirs = parseFrontmatter(readFileSync(join(assetRoot, rel), "utf8"));
|
|
1708
|
+
if (mine.body !== theirs.body) return false;
|
|
1709
|
+
const covered = (have, want) => Object.entries(have).every(([k, v]) => {
|
|
1710
|
+
const w = want[k];
|
|
1711
|
+
if (JSON.stringify(v) === JSON.stringify(w)) return true;
|
|
1712
|
+
return k === "metadata" && !!v && typeof v === "object" && !!w && typeof w === "object" && covered(v, w);
|
|
1713
|
+
});
|
|
1714
|
+
return covered(mine.data, theirs.data);
|
|
1715
|
+
} catch {
|
|
1716
|
+
return false;
|
|
1717
|
+
}
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1508
1720
|
/**
|
|
1509
1721
|
* Open the local index and snapshot its libraries + asset definitions.
|
|
1510
1722
|
* Best-effort: no index file (never indexed), or any open/guard failure,
|
|
@@ -1771,6 +1983,14 @@ var AssetManager = class {
|
|
|
1771
1983
|
const found = this.lockedLibrary(origin, snap);
|
|
1772
1984
|
return found.state === "ok" ? found.path : null;
|
|
1773
1985
|
}
|
|
1986
|
+
/**
|
|
1987
|
+
* The `kind:@publisher/name` identities the lock holds for one `kind` and `name`, whatever
|
|
1988
|
+
* their publisher. `diff` uses it to accept a ref without a publisher only when it names
|
|
1989
|
+
* exactly one locked asset.
|
|
1990
|
+
*/
|
|
1991
|
+
lockedRefsNamed(kind, name) {
|
|
1992
|
+
return Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey).filter((id) => id.kind === kind && id.name === name).map((id) => id.publisher ? `${kind}:@${id.publisher}/${name}` : `${kind}:${name}`);
|
|
1993
|
+
}
|
|
1774
1994
|
/**
|
|
1775
1995
|
* Where each library-origin lock entry of this project resolves on this machine: identity
|
|
1776
1996
|
* `kind:publisher/name` (no scope sigil, no version) → the name the locked library is
|
|
@@ -1800,6 +2020,19 @@ var AssetManager = class {
|
|
|
1800
2020
|
}
|
|
1801
2021
|
return out;
|
|
1802
2022
|
}
|
|
2023
|
+
/**
|
|
2024
|
+
* What `update` prefers when libraries tie: the library each lock entry resolves to here
|
|
2025
|
+
* ({@link lockedLibraryNames}, a `library rename` followed) and the sha256 it locked.
|
|
2026
|
+
*/
|
|
2027
|
+
async lockedPreference() {
|
|
2028
|
+
const shas = /* @__PURE__ */ new Map();
|
|
2029
|
+
for (const [key, e] of Object.entries(this.tryReadLock()?.assets ?? {})) {
|
|
2030
|
+
if (!e.library?.sha256 || e.library.installed) continue;
|
|
2031
|
+
const { publisher, kind, name } = parseCanonicalLockKey(key);
|
|
2032
|
+
if (publisher && kind && name) shas.set(`${kind}:${publisher}/${name}`, e.library.sha256);
|
|
2033
|
+
}
|
|
2034
|
+
return { libraries: await this.lockedLibraryNames(), shas };
|
|
2035
|
+
}
|
|
1803
2036
|
// ── Store fetch-then-deploy ────────────────────────────────────────────
|
|
1804
2037
|
/** A candidate's stable identity key (`<publisher>/<kind>:<name>@<version>`). */
|
|
1805
2038
|
candidateKey(c) {
|
|
@@ -1865,6 +2098,7 @@ var AssetManager = class {
|
|
|
1865
2098
|
const resolved = [];
|
|
1866
2099
|
const overridesApplied = /* @__PURE__ */ new Set();
|
|
1867
2100
|
const presets = [];
|
|
2101
|
+
const requiredBy = /* @__PURE__ */ new Map();
|
|
1868
2102
|
const lib = { entries: [], resolved: /* @__PURE__ */ new Set(), libraryOf: /* @__PURE__ */ new Map() };
|
|
1869
2103
|
const missing = /* @__PURE__ */ new Set();
|
|
1870
2104
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -1913,6 +2147,13 @@ var AssetManager = class {
|
|
|
1913
2147
|
return depId !== null && declaredById.get(depId) || dep;
|
|
1914
2148
|
})
|
|
1915
2149
|
);
|
|
2150
|
+
if (e.kind !== "preset") {
|
|
2151
|
+
for (const dep of deps2) {
|
|
2152
|
+
const depId = refIdentity(dep);
|
|
2153
|
+
if (depId !== null && declaredById.has(depId)) continue;
|
|
2154
|
+
requiredBy.set(dep, [...requiredBy.get(dep) ?? [], canonicalEntryRef(e)]);
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
1916
2157
|
}
|
|
1917
2158
|
for (const r of hit.resolved) lib.resolved.add(r);
|
|
1918
2159
|
return next;
|
|
@@ -1937,7 +2178,8 @@ var AssetManager = class {
|
|
|
1937
2178
|
);
|
|
1938
2179
|
const hit = await this.resolveLibraryEntries([...libraryTried], {
|
|
1939
2180
|
quiet: !opts.warnCollisions,
|
|
1940
|
-
lockedLibraries: opts.lockedLibraries
|
|
2181
|
+
lockedLibraries: opts.lockedLibraries,
|
|
2182
|
+
preferLocked: opts.preferLocked
|
|
1941
2183
|
});
|
|
1942
2184
|
const next = absorb(hit);
|
|
1943
2185
|
const rest = fresh.filter((ref) => !hit.resolved.has(ref));
|
|
@@ -1954,7 +2196,11 @@ var AssetManager = class {
|
|
|
1954
2196
|
presets.push(...r.presets);
|
|
1955
2197
|
const hit2 = await this.resolveLibraryEntries(
|
|
1956
2198
|
r.missing.filter((m) => !libraryTried.has(m)),
|
|
1957
|
-
{
|
|
2199
|
+
{
|
|
2200
|
+
quiet: !opts.warnCollisions,
|
|
2201
|
+
lockedLibraries: opts.lockedLibraries,
|
|
2202
|
+
preferLocked: opts.preferLocked
|
|
2203
|
+
}
|
|
1958
2204
|
);
|
|
1959
2205
|
next.push(...absorb(hit2));
|
|
1960
2206
|
for (const m of r.missing) if (!hit2.resolved.has(m)) missing.add(m);
|
|
@@ -1965,7 +2211,37 @@ var AssetManager = class {
|
|
|
1965
2211
|
const id = refIdentity(m);
|
|
1966
2212
|
return !lib.resolved.has(m) && !(id !== null && covered.has(id));
|
|
1967
2213
|
});
|
|
1968
|
-
|
|
2214
|
+
this.keepUnchangedSourceVersions(resolved, [...deps, ...opts.declaredRefs ?? []]);
|
|
2215
|
+
return { resolved, missing: stillMissing, overridesApplied, lib, presets, requiredBy };
|
|
2216
|
+
}
|
|
2217
|
+
/**
|
|
2218
|
+
* A source asset without a declared version is keyed `0.0.0-sha.<repo commit>`, so every
|
|
2219
|
+
* commit of its repo would re-key (and re-lock, and report as updated) every asset of
|
|
2220
|
+
* that repo, changed or not. Keep the locked key and version of an asset whose files hash
|
|
2221
|
+
* to what the lock holds: `update` then re-locks only what changed, as `outdated` lists.
|
|
2222
|
+
* The commit stays the clone's, so the lock's `sources:` row still names the bytes' commit.
|
|
2223
|
+
* A ref the user pinned (`#<version>`) keeps the version it names.
|
|
2224
|
+
*/
|
|
2225
|
+
keepUnchangedSourceVersions(resolved, requested) {
|
|
2226
|
+
const prev = this.tryReadLock();
|
|
2227
|
+
if (!prev) return;
|
|
2228
|
+
const pinned = /* @__PURE__ */ new Set();
|
|
2229
|
+
for (const ref of requested) {
|
|
2230
|
+
const id = refIdentity(ref);
|
|
2231
|
+
if (id !== null && ref.includes("#")) pinned.add(id);
|
|
2232
|
+
}
|
|
2233
|
+
for (const c of resolved) {
|
|
2234
|
+
if (!c.version.startsWith("0.0.0-sha.")) continue;
|
|
2235
|
+
const id = `${c.publisher}/${c.kind}:${c.name}`;
|
|
2236
|
+
if (pinned.has(id)) continue;
|
|
2237
|
+
for (const [key, entry] of Object.entries(prev.assets)) {
|
|
2238
|
+
const o = parseCanonicalLockKey(key);
|
|
2239
|
+
if (o.kind !== c.kind || o.name !== c.name || o.publisher !== c.publisher) continue;
|
|
2240
|
+
if (!o.version?.startsWith("0.0.0-sha.")) continue;
|
|
2241
|
+
if (entry.source?.url === c.sourceUrl && entry.sha256 === c.sha256) c.version = o.version;
|
|
2242
|
+
break;
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
1969
2245
|
}
|
|
1970
2246
|
/** The catalog fetcher to use: an injected one, else built from `stores`. */
|
|
1971
2247
|
storeFetcherFor(stores) {
|
|
@@ -1980,8 +2256,8 @@ var AssetManager = class {
|
|
|
1980
2256
|
let url = this.catalogUrlOverride;
|
|
1981
2257
|
if (url === void 0) {
|
|
1982
2258
|
try {
|
|
1983
|
-
const { resolveConfig } = await import('./library/index.js');
|
|
1984
|
-
url =
|
|
2259
|
+
const { resolveConfig: resolveConfig2 } = await import('./library/index.js');
|
|
2260
|
+
url = resolveConfig2({ projectDir: this.projectDir }).catalog.url;
|
|
1985
2261
|
} catch {
|
|
1986
2262
|
return [];
|
|
1987
2263
|
}
|
|
@@ -2039,13 +2315,31 @@ var AssetManager = class {
|
|
|
2039
2315
|
// from source.url@commit and ignores it, so "" is inert.
|
|
2040
2316
|
tier: ""
|
|
2041
2317
|
};
|
|
2042
|
-
const
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2318
|
+
const root = commonDirPrefix(c.files.map((f) => f.path));
|
|
2319
|
+
const intact = c.files.every((f) => {
|
|
2320
|
+
const rel = root && f.path.startsWith(`${root}/`) ? f.path.slice(root.length + 1) : f.path;
|
|
2321
|
+
try {
|
|
2322
|
+
return computeHash(join(targetDir, rel)) === f.sha256;
|
|
2323
|
+
} catch {
|
|
2324
|
+
return false;
|
|
2325
|
+
}
|
|
2047
2326
|
});
|
|
2048
|
-
|
|
2327
|
+
if (intact) {
|
|
2328
|
+
staged.set(this.candidateKey(c), join(targetDir, this.stagedManifestRel(c)));
|
|
2329
|
+
continue;
|
|
2330
|
+
}
|
|
2331
|
+
try {
|
|
2332
|
+
const { installPath } = await installFromManifest({
|
|
2333
|
+
manifest,
|
|
2334
|
+
libraryRoot: this.storeCacheDir,
|
|
2335
|
+
targetDir,
|
|
2336
|
+
fetcher: this.injectedAssetFetcher
|
|
2337
|
+
});
|
|
2338
|
+
staged.set(this.candidateKey(c), join(installPath, this.stagedManifestRel(c)));
|
|
2339
|
+
} catch (err) {
|
|
2340
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
2341
|
+
throw new Error(`${manifest.ref} (${c.sourceUrl} at ${c.commit.slice(0, 7)}): ${reason}`);
|
|
2342
|
+
}
|
|
2049
2343
|
}
|
|
2050
2344
|
return staged;
|
|
2051
2345
|
}
|
|
@@ -2151,26 +2445,52 @@ var AssetManager = class {
|
|
|
2151
2445
|
};
|
|
2152
2446
|
}
|
|
2153
2447
|
}
|
|
2154
|
-
const cloneError = this.ensureSourceClones(
|
|
2448
|
+
const cloneError = this.ensureSourceClones(
|
|
2449
|
+
repositories,
|
|
2450
|
+
sources,
|
|
2451
|
+
opts?.moveLibraries ? void 0 : lockForLibraries
|
|
2452
|
+
);
|
|
2155
2453
|
if (cloneError) return cloneError;
|
|
2156
2454
|
const provenanceIndex = await buildProvenanceIndex(this.buildClones(repositories), {
|
|
2157
2455
|
projectDir: this.projectDir,
|
|
2158
|
-
knownKinds: this.knownKinds
|
|
2456
|
+
knownKinds: this.knownKinds,
|
|
2457
|
+
onSourceError: this.reportSourceError
|
|
2458
|
+
});
|
|
2459
|
+
const { resolved, missing, overridesApplied, lib, presets, requiredBy } = await this.resolveLibraryFirst(dependencies, {
|
|
2460
|
+
provenanceIndex,
|
|
2461
|
+
overrides,
|
|
2462
|
+
stores,
|
|
2463
|
+
declaredRefs: dependencies,
|
|
2464
|
+
// `install` restores what the lock recorded: a changed default library or a second
|
|
2465
|
+
// library holding the same ref does not move a locked asset. `update` re-resolves.
|
|
2466
|
+
...opts?.moveLibraries ? { preferLocked: await this.lockedPreference() } : { lockedLibraries: await this.lockedLibraryNames() }
|
|
2159
2467
|
});
|
|
2160
|
-
const { resolved, missing, overridesApplied, lib, presets } = await this.resolveLibraryFirst(
|
|
2161
|
-
dependencies,
|
|
2162
|
-
{
|
|
2163
|
-
provenanceIndex,
|
|
2164
|
-
overrides,
|
|
2165
|
-
stores,
|
|
2166
|
-
declaredRefs: dependencies,
|
|
2167
|
-
// `install` restores what the lock recorded: a changed default library or a second
|
|
2168
|
-
// library holding the same ref does not move a locked asset. `update` re-resolves.
|
|
2169
|
-
...opts?.moveLibraries ? {} : { lockedLibraries: await this.lockedLibraryNames() }
|
|
2170
|
-
}
|
|
2171
|
-
);
|
|
2172
2468
|
this.assertNoFolderCollision([...resolved, ...lib.entries.map((e) => this.entryIdentity(e))]);
|
|
2469
|
+
this.assertSourceCommitsPublished(resolved, repositories);
|
|
2173
2470
|
const stillMissing = missing.filter((m) => !lib.resolved.has(m));
|
|
2471
|
+
const lockedKeys = new Set(Object.keys(this.tryReadLock()?.assets ?? {}));
|
|
2472
|
+
const unmetByNew = /* @__PURE__ */ new Map();
|
|
2473
|
+
for (const m of stillMissing) {
|
|
2474
|
+
const newcomers = (requiredBy.get(m) ?? []).filter((parent) => !lockedKeys.has(parent));
|
|
2475
|
+
if (newcomers.length > 0) unmetByNew.set(m, newcomers);
|
|
2476
|
+
}
|
|
2477
|
+
if (unmetByNew.size > 0) {
|
|
2478
|
+
const hints = {};
|
|
2479
|
+
for (const [m, parents] of unmetByNew) {
|
|
2480
|
+
const requirer = parents.map((p) => p.split("#")[0]).join(", ");
|
|
2481
|
+
const unreachable = [...this.storeFailures.values()];
|
|
2482
|
+
hints[m] = unreachable.length > 0 ? ` is required by ${requirer} (store unreachable, so it was not looked up: ${unreachable.join("; ")} \u2014 check the URL with \`skaile catalog test\`) \u2014 nothing was installed` : ` is required by ${requirer} (not found \u2014 ${REGISTER_HOLDER}, or drop ${requirer} with \`skaile remove ${parents[0].split("#")[0]}\`) \u2014 nothing was installed`;
|
|
2483
|
+
}
|
|
2484
|
+
return {
|
|
2485
|
+
deployed: [],
|
|
2486
|
+
removed: [],
|
|
2487
|
+
missing: [...unmetByNew.keys()],
|
|
2488
|
+
missingHints: hints,
|
|
2489
|
+
lockWritten: false,
|
|
2490
|
+
npmInstalled: [],
|
|
2491
|
+
npmFailed: []
|
|
2492
|
+
};
|
|
2493
|
+
}
|
|
2174
2494
|
const missingHints = await this.publisherChangeHints(stillMissing);
|
|
2175
2495
|
const prevLock = this.tryReadLock();
|
|
2176
2496
|
const kept = keptLockEntries(prevLock, stillMissing);
|
|
@@ -2211,7 +2531,7 @@ var AssetManager = class {
|
|
|
2211
2531
|
let relocked = [];
|
|
2212
2532
|
let moved = [];
|
|
2213
2533
|
if (lockWanted) {
|
|
2214
|
-
const lockData = withKeptLockEntries(freshLock, kept);
|
|
2534
|
+
const lockData = this.withRenderedAgents(withKeptLockEntries(freshLock, kept));
|
|
2215
2535
|
relocked = relockedRefs(prevLock, lockData);
|
|
2216
2536
|
moved = libraryMoves(prevLock, libraryLock);
|
|
2217
2537
|
lockWritten = writeLock(this.lockPath, lockData);
|
|
@@ -2273,7 +2593,8 @@ var AssetManager = class {
|
|
|
2273
2593
|
const { kind, name, publisher } = id;
|
|
2274
2594
|
const component = kind ? this.installTarget(kind) : void 0;
|
|
2275
2595
|
if (!kind || !name || !component) return [];
|
|
2276
|
-
const
|
|
2596
|
+
const keptAgent = kind === "agent" && !this.global ? join(agentSourceCacheDir(this.projectDir), name) : null;
|
|
2597
|
+
const dir = keptAgent && existsSync(keptAgent) ? keptAgent : deployedDir(component, name, this.driverTarget, this.global, this.projectDir);
|
|
2277
2598
|
if (!existsSync(dir)) return [];
|
|
2278
2599
|
try {
|
|
2279
2600
|
const scanned = await scanDirectory(dir, publisher ?? "", { knownKinds: this.knownKinds });
|
|
@@ -2288,13 +2609,25 @@ var AssetManager = class {
|
|
|
2288
2609
|
* {@link InstallResult} describing the failed source on the first error, or
|
|
2289
2610
|
* `null` when every clone succeeds.
|
|
2290
2611
|
*/
|
|
2291
|
-
ensureSourceClones(repositories, sources) {
|
|
2612
|
+
ensureSourceClones(repositories, sources, lock) {
|
|
2292
2613
|
const pinBySlug = pinsBySlug(sources);
|
|
2614
|
+
const lockedCommit = /* @__PURE__ */ new Map();
|
|
2615
|
+
for (const s of lock?.sources ?? []) {
|
|
2616
|
+
if (!/^0*$/.test(s.commit)) lockedCommit.set(sourceCacheKey(s.url), s.commit);
|
|
2617
|
+
}
|
|
2293
2618
|
for (const [name, decl] of Object.entries(repositories)) {
|
|
2294
2619
|
try {
|
|
2620
|
+
const declaredPin = pinBySlug.get(name);
|
|
2621
|
+
let locked = decl.url && !decl.factory ? lockedCommit.get(name) : void 0;
|
|
2622
|
+
if (locked && declaredPin === void 0) {
|
|
2623
|
+
const dir = this.resolveRepoDir(decl, name);
|
|
2624
|
+
const head = dir ? getRepoCommit(dir) : void 0;
|
|
2625
|
+
if (dir && head && head !== locked && !isCommitOnRemote(dir, head)) locked = void 0;
|
|
2626
|
+
}
|
|
2295
2627
|
ensureRepo(decl, name, this.reposDir, {
|
|
2296
2628
|
projectDir: this.projectDir,
|
|
2297
|
-
pin:
|
|
2629
|
+
pin: declaredPin ?? locked,
|
|
2630
|
+
...declaredPin === void 0 && locked ? { strictPin: true } : {}
|
|
2298
2631
|
});
|
|
2299
2632
|
} catch (err) {
|
|
2300
2633
|
return {
|
|
@@ -2397,13 +2730,33 @@ var AssetManager = class {
|
|
|
2397
2730
|
return null;
|
|
2398
2731
|
}
|
|
2399
2732
|
}
|
|
2733
|
+
/**
|
|
2734
|
+
* A catalog client for `storeUrl` that honours `catalog.cache_ttl` (`0` = air-gapped: no
|
|
2735
|
+
* network, so every lookup that is not cached throws `OfflineError`).
|
|
2736
|
+
*/
|
|
2737
|
+
remoteStore(storeUrl) {
|
|
2738
|
+
let cacheTtlMs;
|
|
2739
|
+
try {
|
|
2740
|
+
cacheTtlMs = resolveConfig({ projectDir: this.projectDir }).catalog.cache_ttl * 1e3;
|
|
2741
|
+
} catch {
|
|
2742
|
+
}
|
|
2743
|
+
return new RemoteCatalogSource({ baseUrl: storeUrl, cacheTtlMs });
|
|
2744
|
+
}
|
|
2745
|
+
/**
|
|
2746
|
+
* Remember why a store could not be asked (store URL → one line without a JS error class
|
|
2747
|
+
* name), so `add` can say `store unreachable` instead of a bare `Asset not found`.
|
|
2748
|
+
*/
|
|
2749
|
+
noteStoreFailure(storeUrl, err) {
|
|
2750
|
+
const text = err instanceof OfflineError ? `${storeUrl}: air-gapped (catalog.cache_ttl: 0), the store was not asked` : describeCatalogError(err, storeUrl);
|
|
2751
|
+
this.storeFailures.set(storeUrl, text);
|
|
2752
|
+
return text;
|
|
2753
|
+
}
|
|
2400
2754
|
/** Build a store fetcher from the configured stores, or undefined when none. */
|
|
2401
2755
|
buildStoreFetcher(stores) {
|
|
2402
2756
|
if (stores.length === 0) return void 0;
|
|
2403
2757
|
return {
|
|
2404
2758
|
getInstallManifest: async (storeUrl, ref) => {
|
|
2405
|
-
const
|
|
2406
|
-
const src = new RemoteCatalogSource({ baseUrl: storeUrl });
|
|
2759
|
+
const src = this.remoteStore(storeUrl);
|
|
2407
2760
|
try {
|
|
2408
2761
|
const m = await src.getInstallManifest(ref);
|
|
2409
2762
|
let deps;
|
|
@@ -2416,7 +2769,7 @@ var AssetManager = class {
|
|
|
2416
2769
|
else if (deps === void 0)
|
|
2417
2770
|
gap = `has a cached catalog row for ${ref} without dependencies`;
|
|
2418
2771
|
} catch (err) {
|
|
2419
|
-
gap = `dependency lookup for ${ref} failed \u2014 ${err}`;
|
|
2772
|
+
gap = `dependency lookup for ${ref} failed \u2014 ${describeCatalogError(err, storeUrl)}`;
|
|
2420
2773
|
}
|
|
2421
2774
|
if (gap) {
|
|
2422
2775
|
console.warn(`skaile: store ${storeUrl} ${gap}; installing without its dependencies`);
|
|
@@ -2430,23 +2783,23 @@ var AssetManager = class {
|
|
|
2430
2783
|
};
|
|
2431
2784
|
} catch (err) {
|
|
2432
2785
|
if (err instanceof CatalogHttpError && err.status === 404) return null;
|
|
2786
|
+
this.noteStoreFailure(storeUrl, err);
|
|
2433
2787
|
throw err;
|
|
2434
2788
|
}
|
|
2435
2789
|
},
|
|
2436
2790
|
getCanonicalDigest: async (storeUrl, ref) => {
|
|
2437
|
-
const
|
|
2438
|
-
const src = new RemoteCatalogSource({ baseUrl: storeUrl });
|
|
2791
|
+
const src = this.remoteStore(storeUrl);
|
|
2439
2792
|
return src.getCanonicalDigest(ref);
|
|
2440
2793
|
},
|
|
2441
2794
|
listVersions: async (storeUrl, ref) => {
|
|
2442
|
-
const
|
|
2443
|
-
const src = new RemoteCatalogSource({ baseUrl: storeUrl });
|
|
2795
|
+
const src = this.remoteStore(storeUrl);
|
|
2444
2796
|
try {
|
|
2445
2797
|
return await src.listVersions(ref);
|
|
2446
2798
|
} catch (err) {
|
|
2799
|
+
const text = this.noteStoreFailure(storeUrl, err);
|
|
2447
2800
|
if (!this.warnedStoreVersionLookups.has(storeUrl)) {
|
|
2448
2801
|
this.warnedStoreVersionLookups.add(storeUrl);
|
|
2449
|
-
console.warn(`skaile: store
|
|
2802
|
+
console.warn(`skaile: store lookup of ${ref} failed: ${text}`);
|
|
2450
2803
|
}
|
|
2451
2804
|
return [];
|
|
2452
2805
|
}
|
|
@@ -2522,20 +2875,46 @@ var AssetManager = class {
|
|
|
2522
2875
|
this.assertNoFolderCollision(Object.keys(lock.assets).map(parseCanonicalLockKey));
|
|
2523
2876
|
const declBySlug = new Map(Object.entries(repositories));
|
|
2524
2877
|
const factoryUrl = normalizeRepoUrl(FACTORY_SOURCE_URL);
|
|
2525
|
-
const
|
|
2878
|
+
const factoryDecl = Object.values(repositories).find((d) => d.factory);
|
|
2879
|
+
const factoryDir = factoryDecl?.path ?? null;
|
|
2880
|
+
const isFactoryUrl = (url) => factoryDir !== null && normalizeRepoUrl(url) === factoryUrl;
|
|
2881
|
+
const unavailable = [];
|
|
2526
2882
|
for (const src of lock.sources) {
|
|
2527
|
-
if (
|
|
2883
|
+
if (isFactoryUrl(src.url)) continue;
|
|
2528
2884
|
const slug = sourceCacheKey(src.url);
|
|
2529
|
-
const
|
|
2530
|
-
|
|
2885
|
+
const declared = declBySlug.get(slug);
|
|
2886
|
+
if (!declared && GITHUB_REPO_URL.test(src.url)) continue;
|
|
2887
|
+
try {
|
|
2888
|
+
const dir = ensureRepo(declared ?? { url: src.url }, slug, this.reposDir, {
|
|
2889
|
+
projectDir: this.projectDir,
|
|
2890
|
+
// A lock restore deploys the pinned commit's bytes or fails: never another commit's.
|
|
2891
|
+
.../^0*$/.test(src.commit) ? {} : { pin: src.commit, strictPin: true }
|
|
2892
|
+
});
|
|
2893
|
+
if (!declared) repositories[slug] = { url: src.url, path: dir };
|
|
2894
|
+
} catch (err) {
|
|
2895
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
2896
|
+
unavailable.push(`unavailable: ${src.url} at ${src.commit.slice(0, 7)} (${reason})`);
|
|
2897
|
+
}
|
|
2531
2898
|
}
|
|
2532
|
-
|
|
2533
|
-
|
|
2899
|
+
if (unavailable.length > 0) {
|
|
2900
|
+
throw new Error(`Lock file verification failed:
|
|
2901
|
+
${unavailable.join("\n ")}`);
|
|
2902
|
+
}
|
|
2903
|
+
const candidates = [];
|
|
2904
|
+
const cloneOrigin = {};
|
|
2905
|
+
for (const [key, entry] of Object.entries(lock.assets)) {
|
|
2906
|
+
const candidate = this.lockedCandidate(key, entry, repositories);
|
|
2907
|
+
if (!candidate) continue;
|
|
2908
|
+
candidates.push(candidate);
|
|
2909
|
+
if (this.candidateHasLocalBytes(candidate, repositories)) {
|
|
2910
|
+
cloneOrigin[key] = entry;
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
const verification = verifyLock({ ...lock, assets: cloneOrigin }, (sourceUrl) => {
|
|
2914
|
+
if (isFactoryUrl(sourceUrl)) return factoryDir;
|
|
2534
2915
|
const slug = sourceCacheKey(sourceUrl);
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
};
|
|
2538
|
-
const verification = verifyLock(lock, resolveCloneDir);
|
|
2916
|
+
return this.resolveRepoDir(repositories[slug] ?? { url: sourceUrl }, slug);
|
|
2917
|
+
});
|
|
2539
2918
|
if (!verification.ok) {
|
|
2540
2919
|
const issues = [
|
|
2541
2920
|
...verification.drifted.map((r) => `drifted: ${r}`),
|
|
@@ -2554,28 +2933,13 @@ var AssetManager = class {
|
|
|
2554
2933
|
${lines.join("\n ")}`
|
|
2555
2934
|
);
|
|
2556
2935
|
}
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
const mdRel = entry.files.find((f) => /\.(md|yaml)$/i.test(f.path))?.path ?? entry.files[0]?.path ?? "";
|
|
2565
|
-
resolved.push({
|
|
2566
|
-
name,
|
|
2567
|
-
kind,
|
|
2568
|
-
description: "",
|
|
2569
|
-
source: mdRel ? join(cloneDir, mdRel) : cloneDir,
|
|
2570
|
-
// Keep the publisher label slash-free (repo name), not the full cache key.
|
|
2571
|
-
publisher: sourceShortName(entry.source.url),
|
|
2572
|
-
version: entry.source.commit,
|
|
2573
|
-
// The lock key is the canonical ref; `publisher` above is only a clone label.
|
|
2574
|
-
canonicalRef: ref,
|
|
2575
|
-
requires: [],
|
|
2576
|
-
dependencies: []
|
|
2577
|
-
});
|
|
2578
|
-
if (!repositories[slug]) repositories[slug] = { url: entry.source.url, path: cloneDir };
|
|
2936
|
+
let resolved;
|
|
2937
|
+
try {
|
|
2938
|
+
resolved = await this.buildCatalogEntries(candidates, repositories);
|
|
2939
|
+
} catch (err) {
|
|
2940
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
2941
|
+
throw new Error(`Lock file verification failed:
|
|
2942
|
+
${reason}`);
|
|
2579
2943
|
}
|
|
2580
2944
|
const library = await this.restoreLibraryLockEntries(lock);
|
|
2581
2945
|
const copyDrift = await this.lockedCopyDrift();
|
|
@@ -2664,7 +3028,8 @@ var AssetManager = class {
|
|
|
2664
3028
|
this.ensureSourceClonesQuiet(repositories, sources);
|
|
2665
3029
|
const index = await buildProvenanceIndex(this.buildClones(repositories), {
|
|
2666
3030
|
projectDir: this.projectDir,
|
|
2667
|
-
knownKinds: this.knownKinds
|
|
3031
|
+
knownKinds: this.knownKinds,
|
|
3032
|
+
onSourceError: this.reportSourceError
|
|
2668
3033
|
});
|
|
2669
3034
|
for (const candidates of index.values()) for (const c of candidates) note(c);
|
|
2670
3035
|
for (const { entry } of await this.libraryAssets()) note(entry);
|
|
@@ -2699,11 +3064,19 @@ var AssetManager = class {
|
|
|
2699
3064
|
this.ensureSourceClonesQuiet(repositories, sources);
|
|
2700
3065
|
const provenanceIndex = await buildProvenanceIndex(this.buildClones(repositories), {
|
|
2701
3066
|
projectDir: this.projectDir,
|
|
2702
|
-
knownKinds: this.knownKinds
|
|
3067
|
+
knownKinds: this.knownKinds,
|
|
3068
|
+
onSourceError: this.reportSourceError
|
|
2703
3069
|
});
|
|
2704
3070
|
const { resolved, missing, overridesApplied, lib, presets } = await this.resolveLibraryFirst(
|
|
2705
3071
|
[ref],
|
|
2706
|
-
{
|
|
3072
|
+
{
|
|
3073
|
+
provenanceIndex,
|
|
3074
|
+
overrides,
|
|
3075
|
+
stores,
|
|
3076
|
+
declaredRefs: dependencies,
|
|
3077
|
+
warnCollisions: true,
|
|
3078
|
+
...opts?.preferLockedLibrary ? { preferLocked: await this.lockedPreference() } : {}
|
|
3079
|
+
}
|
|
2707
3080
|
);
|
|
2708
3081
|
if (resolved.length === 0 && lib.entries.length === 0 && presets.length === 0) {
|
|
2709
3082
|
const snap = await this.loadLibraryIndex();
|
|
@@ -2721,6 +3094,12 @@ var AssetManager = class {
|
|
|
2721
3094
|
);
|
|
2722
3095
|
}
|
|
2723
3096
|
}
|
|
3097
|
+
const unreachable = [...this.storeFailures.values()];
|
|
3098
|
+
if (unreachable.length > 0) {
|
|
3099
|
+
throw new Error(
|
|
3100
|
+
`Store unreachable \u2014 ${ref} was not looked up: ${unreachable.join("; ")}. Check the URL with \`skaile catalog test\`; a library or source can still hold the asset.`
|
|
3101
|
+
);
|
|
3102
|
+
}
|
|
2724
3103
|
throw new Error(
|
|
2725
3104
|
`Asset not found: ${ref}${(await this.publisherChangeHints([ref]))[ref] ?? ""}${missing.length ? ` (missing: ${missing.join(", ")})` : ""}`
|
|
2726
3105
|
);
|
|
@@ -2742,6 +3121,7 @@ var AssetManager = class {
|
|
|
2742
3121
|
}
|
|
2743
3122
|
}
|
|
2744
3123
|
}
|
|
3124
|
+
this.assertSourceCommitsPublished(resolved, repositories);
|
|
2745
3125
|
this.assertNoFolderCollision(
|
|
2746
3126
|
[...resolved, ...lib.entries.map((e) => this.entryIdentity(e))],
|
|
2747
3127
|
[
|
|
@@ -2749,7 +3129,28 @@ var AssetManager = class {
|
|
|
2749
3129
|
...dependencies.map((d) => parseAssetRefLoose(d) ?? {})
|
|
2750
3130
|
]
|
|
2751
3131
|
);
|
|
3132
|
+
if (!opts?.force) {
|
|
3133
|
+
this.assertNoUnownedFolder(
|
|
3134
|
+
[
|
|
3135
|
+
...resolved.map((c) => ({
|
|
3136
|
+
id: c,
|
|
3137
|
+
entry: this.candidateToCatalogEntry(c, repositories)
|
|
3138
|
+
})),
|
|
3139
|
+
...lib.entries.map((e) => ({ id: this.entryIdentity(e), entry: e }))
|
|
3140
|
+
],
|
|
3141
|
+
[
|
|
3142
|
+
...Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey),
|
|
3143
|
+
...dependencies.map((d) => parseAssetRefLoose(d) ?? {})
|
|
3144
|
+
]
|
|
3145
|
+
);
|
|
3146
|
+
}
|
|
2752
3147
|
if (missing.length > 0) {
|
|
3148
|
+
const unreachable = [...this.storeFailures.values()];
|
|
3149
|
+
if (unreachable.length > 0) {
|
|
3150
|
+
throw new Error(
|
|
3151
|
+
`Store unreachable \u2014 ${ref.split("#")[0]} requires ${missing.join(", ")}, which was not looked up: ${unreachable.join("; ")}. Check the URL with \`skaile catalog test\`; a library or source can still hold the requirement \u2014 nothing was added`
|
|
3152
|
+
);
|
|
3153
|
+
}
|
|
2753
3154
|
throw new Error(
|
|
2754
3155
|
`${ref.split("#")[0]} requires ${missing.join(", ")} (not found \u2014 ${REGISTER_HOLDER}, or remove the requirement from the asset's manifest) \u2014 nothing was added`
|
|
2755
3156
|
);
|
|
@@ -2788,7 +3189,7 @@ var AssetManager = class {
|
|
|
2788
3189
|
if (opts?.onLibraryMoved) {
|
|
2789
3190
|
for (const m of libraryMoves(prevLock, libraryLock)) opts.onLibraryMoved(m);
|
|
2790
3191
|
}
|
|
2791
|
-
writeLock(this.lockPath, mergeLockFile(prevLock, fresh));
|
|
3192
|
+
writeLock(this.lockPath, mergeLockFile(prevLock, this.withRenderedAgents(fresh)));
|
|
2792
3193
|
}
|
|
2793
3194
|
for (const d of deployed) {
|
|
2794
3195
|
appendHistory(this.projectDir, {
|
|
@@ -3301,7 +3702,13 @@ var AssetManager = class {
|
|
|
3301
3702
|
for (const [name, decl] of Object.entries(repositories)) {
|
|
3302
3703
|
const repoDir = this.resolveRepoDir(decl, name);
|
|
3303
3704
|
if (!repoDir) continue;
|
|
3304
|
-
all = [
|
|
3705
|
+
all = [
|
|
3706
|
+
...all,
|
|
3707
|
+
...await scanRepo(repoDir, name, {
|
|
3708
|
+
knownKinds: this.knownKinds,
|
|
3709
|
+
declaredPublisher: decl.publisher
|
|
3710
|
+
})
|
|
3711
|
+
];
|
|
3305
3712
|
}
|
|
3306
3713
|
if (kind) all = all.filter((e) => e.kind === kind);
|
|
3307
3714
|
if (query) {
|
|
@@ -3346,7 +3753,10 @@ var AssetManager = class {
|
|
|
3346
3753
|
for (const [name, decl] of Object.entries(repositories)) {
|
|
3347
3754
|
const repoDir = this.resolveRepoDir(decl, name);
|
|
3348
3755
|
if (!repoDir) continue;
|
|
3349
|
-
const entries = await scanRepo(repoDir, name, {
|
|
3756
|
+
const entries = await scanRepo(repoDir, name, {
|
|
3757
|
+
knownKinds: this.knownKinds,
|
|
3758
|
+
declaredPublisher: decl.publisher
|
|
3759
|
+
});
|
|
3350
3760
|
const match = entries.find(
|
|
3351
3761
|
(e) => e.kind === parsed.kind && e.name === parsed.name && (!parsed.publisher || e.publisher === parsed.publisher)
|
|
3352
3762
|
);
|
|
@@ -3542,12 +3952,12 @@ var AssetManager = class {
|
|
|
3542
3952
|
return out;
|
|
3543
3953
|
}
|
|
3544
3954
|
/**
|
|
3545
|
-
*
|
|
3546
|
-
*
|
|
3547
|
-
*
|
|
3548
|
-
*
|
|
3549
|
-
* local edit never counts. An asset with no deployed directory is
|
|
3550
|
-
* (`listDeclared` reports it as drift); an agent is rendered, not copied, so it
|
|
3955
|
+
* Locked assets whose deployed directory lacks files the deploy writes — a deleted
|
|
3956
|
+
* `build.py` / `scripts/` helper next to an intact `SKILL.md`. The expected set is the file
|
|
3957
|
+
* set the lock covers: a library entry's files (every file under its manifest `root:`), a
|
|
3958
|
+
* source or store entry's `files[]` (the asset's whole file set at the locked commit). Only
|
|
3959
|
+
* presence is checked, so a local edit never counts. An asset with no deployed directory is
|
|
3960
|
+
* not listed (`listDeclared` reports it as drift); an agent is rendered, not copied, so it
|
|
3551
3961
|
* has no file mirror to compare. `skaile install` restores what is listed.
|
|
3552
3962
|
*
|
|
3553
3963
|
* @returns One {@link IncompleteDeploy} per affected asset; empty when healthy
|
|
@@ -3556,10 +3966,25 @@ var AssetManager = class {
|
|
|
3556
3966
|
async incompleteDeploys() {
|
|
3557
3967
|
const lock = this.tryReadLock();
|
|
3558
3968
|
if (!lock) return [];
|
|
3969
|
+
const out = [];
|
|
3970
|
+
const { patches } = this.loadConfig();
|
|
3971
|
+
for (const [key, entry] of Object.entries(lock.assets)) {
|
|
3972
|
+
if (!entry.source || entry.files.length === 0) continue;
|
|
3973
|
+
const { publisher, kind, name } = parseCanonicalLockKey(key);
|
|
3974
|
+
const component = kind ? this.installTarget(kind) : void 0;
|
|
3975
|
+
if (!publisher || !kind || !name || !component || component === "agent") continue;
|
|
3976
|
+
if (patches[`${kind}:${name}`]) continue;
|
|
3977
|
+
const dest = join(
|
|
3978
|
+
deployedBase(component, this.driverTarget, this.global, this.projectDir),
|
|
3979
|
+
name
|
|
3980
|
+
);
|
|
3981
|
+
if (!existsSync(dest) || lstatSync(dest).isSymbolicLink()) continue;
|
|
3982
|
+
const missing = lockedAssetFiles(kind, entry.files).map((f) => f.rel).filter((rel) => !existsSync(join(dest, rel)));
|
|
3983
|
+
if (missing.length > 0) out.push({ ref: `${kind}:@${publisher}/${name}`, missing });
|
|
3984
|
+
}
|
|
3559
3985
|
const locked = Object.entries(lock.assets).filter(([, e]) => e.library !== void 0 && !e.library.installed).map(([key]) => key);
|
|
3560
|
-
if (locked.length === 0) return
|
|
3986
|
+
if (locked.length === 0) return out;
|
|
3561
3987
|
const lib = await this.resolveLibraryEntries(locked, { quiet: true });
|
|
3562
|
-
const out = [];
|
|
3563
3988
|
for (const entry of lib.entries) {
|
|
3564
3989
|
const component = this.installTarget(entry.kind);
|
|
3565
3990
|
if (!entry.files || !component || component === "agent") continue;
|
|
@@ -3900,7 +4325,17 @@ var AssetManager = class {
|
|
|
3900
4325
|
if (!kind || !name) continue;
|
|
3901
4326
|
const lockedCommit = entry.source.commit || src.commit;
|
|
3902
4327
|
const moved = lockedCommit && !/^0+$/.test(lockedCommit) && lockedCommit !== status.localHead ? commitsBetween(clone, lockedCommit, status.localHead, commitCounts) : 0;
|
|
3903
|
-
|
|
4328
|
+
let behind = status.behind + moved;
|
|
4329
|
+
if (behind > 0) {
|
|
4330
|
+
const touching = commitsTouching(
|
|
4331
|
+
clone,
|
|
4332
|
+
COMMIT_ID.test(lockedCommit) && !/^0+$/.test(lockedCommit) ? lockedCommit : status.localHead,
|
|
4333
|
+
status.behind > 0 && status.remoteHead ? status.remoteHead : status.localHead,
|
|
4334
|
+
lockedAssetDir(kind, entry.files),
|
|
4335
|
+
commitCounts
|
|
4336
|
+
);
|
|
4337
|
+
if (touching !== null) behind = touching;
|
|
4338
|
+
}
|
|
3904
4339
|
if (behind <= 0) continue;
|
|
3905
4340
|
result.push({
|
|
3906
4341
|
kind,
|
|
@@ -4018,6 +4453,37 @@ var AssetManager = class {
|
|
|
4018
4453
|
}
|
|
4019
4454
|
return null;
|
|
4020
4455
|
}
|
|
4456
|
+
/**
|
|
4457
|
+
* The deploy entry of a source- or store-origin asset, carrying the file set its lock entry
|
|
4458
|
+
* lists (so a missing or edited helper shows in `diff`, not only the manifest). A source asset
|
|
4459
|
+
* reads from its clone; a store asset from the bytes `add`/`install` staged in the project
|
|
4460
|
+
* store cache. `null` when the lock has no such entry or its bytes are not on disk.
|
|
4461
|
+
*
|
|
4462
|
+
* @param want - Kind, name and optional publisher of the asset.
|
|
4463
|
+
*/
|
|
4464
|
+
lockedSourceEntry(want) {
|
|
4465
|
+
const { repositories } = this.loadConfig();
|
|
4466
|
+
for (const [key, e] of Object.entries(this.tryReadLock()?.assets ?? {})) {
|
|
4467
|
+
const id = parseCanonicalLockKey(key);
|
|
4468
|
+
if (!e.source || id.kind !== want.kind || id.name !== want.name) continue;
|
|
4469
|
+
if (want.publisher && id.publisher !== want.publisher) continue;
|
|
4470
|
+
const c = this.lockedCandidate(key, e, repositories);
|
|
4471
|
+
if (!c) continue;
|
|
4472
|
+
if (this.candidateHasLocalBytes(c, repositories)) {
|
|
4473
|
+
return this.candidateToCatalogEntry(c, repositories);
|
|
4474
|
+
}
|
|
4475
|
+
const staged = join(
|
|
4476
|
+
this.storeCacheDir,
|
|
4477
|
+
c.publisher,
|
|
4478
|
+
c.kind,
|
|
4479
|
+
c.name,
|
|
4480
|
+
c.version,
|
|
4481
|
+
this.stagedManifestRel(c)
|
|
4482
|
+
);
|
|
4483
|
+
if (existsSync(staged)) return this.stagedCandidateToEntry(c, staged);
|
|
4484
|
+
}
|
|
4485
|
+
return null;
|
|
4486
|
+
}
|
|
4021
4487
|
/**
|
|
4022
4488
|
* Produce a unified diff from the deployed asset to its catalog source: `-` lines
|
|
4023
4489
|
* are in the deployed copy only (local edits `update` would overwrite), `+` lines
|
|
@@ -4035,8 +4501,15 @@ var AssetManager = class {
|
|
|
4035
4501
|
async diff(ref) {
|
|
4036
4502
|
const parsed = parseRefTolerant(ref);
|
|
4037
4503
|
if (!parsed) return { status: "not-found" };
|
|
4038
|
-
const entry = await this.lockedLibraryEntry(parsed) ?? await this.info(ref);
|
|
4504
|
+
const entry = await this.lockedLibraryEntry(parsed) ?? this.lockedSourceEntry(parsed) ?? await this.info(ref);
|
|
4039
4505
|
if (!entry || !existsSync(entry.source)) return { status: "not-found" };
|
|
4506
|
+
const wantPublisher = parsed.publisher?.replace(/^@/, "");
|
|
4507
|
+
if (wantPublisher) {
|
|
4508
|
+
const lockedHere = Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey).filter((id) => id.kind === parsed.kind && id.name === parsed.name);
|
|
4509
|
+
if (lockedHere.length > 0 && !lockedHere.some((id) => id.publisher === wantPublisher)) {
|
|
4510
|
+
return { status: "not-deployed" };
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4040
4513
|
const component = this.installTarget(parsed.kind);
|
|
4041
4514
|
if (parsed.kind === "preset" && this.presetRecorded(parsed)) return { status: "no-files" };
|
|
4042
4515
|
if (!component) return { status: "not-deployed" };
|
|
@@ -4079,7 +4552,8 @@ var AssetManager = class {
|
|
|
4079
4552
|
this.ensureSourceClonesQuiet(repositories, sources);
|
|
4080
4553
|
const provenanceIndex = await buildProvenanceIndex(this.buildClones(repositories), {
|
|
4081
4554
|
projectDir: this.projectDir,
|
|
4082
|
-
knownKinds: this.knownKinds
|
|
4555
|
+
knownKinds: this.knownKinds,
|
|
4556
|
+
onSourceError: this.reportSourceError
|
|
4083
4557
|
});
|
|
4084
4558
|
const { resolved, overridesApplied, lib } = await this.resolveLibraryFirst(dependencies, {
|
|
4085
4559
|
provenanceIndex,
|
|
@@ -4087,8 +4561,14 @@ var AssetManager = class {
|
|
|
4087
4561
|
stores,
|
|
4088
4562
|
declaredRefs: dependencies
|
|
4089
4563
|
});
|
|
4564
|
+
this.assertSourceCommitsPublished(resolved, repositories);
|
|
4090
4565
|
const libraryLock = await this.libraryLockEntries(lib);
|
|
4091
4566
|
const lockData = buildLockFile(resolved, overridesApplied, libraryLock);
|
|
4567
|
+
const prior = this.tryReadLock();
|
|
4568
|
+
for (const [key, entry] of Object.entries(lockData.assets)) {
|
|
4569
|
+
const rendered = prior?.assets[key]?.rendered;
|
|
4570
|
+
if (rendered) entry.rendered = rendered;
|
|
4571
|
+
}
|
|
4092
4572
|
writeLock(this.lockPath, lockData);
|
|
4093
4573
|
return lockData;
|
|
4094
4574
|
}
|
|
@@ -4206,7 +4686,11 @@ var AssetManager = class {
|
|
|
4206
4686
|
const full = await this.info(
|
|
4207
4687
|
publisher ? `${entry.kind}:@${publisher}/${entry.name}` : `${entry.kind}:${entry.name}`
|
|
4208
4688
|
);
|
|
4209
|
-
|
|
4689
|
+
const restorable = !full && publisher !== void 0 && Object.entries(lock?.assets ?? {}).some(([key, e]) => {
|
|
4690
|
+
const id = parseCanonicalLockKey(key);
|
|
4691
|
+
return e.source !== void 0 && id.kind === entry.kind && id.name === entry.name && id.publisher === publisher;
|
|
4692
|
+
});
|
|
4693
|
+
if (!full && !restorable) {
|
|
4210
4694
|
if (publisher) {
|
|
4211
4695
|
const canonical = `${entry.kind}:@${publisher}/${entry.name}`;
|
|
4212
4696
|
const fix = (await this.unresolvedFixes([canonical])).get(canonical);
|
|
@@ -4222,8 +4706,9 @@ var AssetManager = class {
|
|
|
4222
4706
|
}
|
|
4223
4707
|
continue;
|
|
4224
4708
|
}
|
|
4709
|
+
const declaredRequires = full ? full.requires : (await this.deployedRequirementsOf({ ...entry, publisher })).map(parseDep);
|
|
4225
4710
|
const gaps = [];
|
|
4226
|
-
const requirements = dedupeRequirements(
|
|
4711
|
+
const requirements = dedupeRequirements(declaredRequires, publisher).map(
|
|
4227
4712
|
(r) => r.publisher || !publisher ? r : { ...r, publisher }
|
|
4228
4713
|
);
|
|
4229
4714
|
for (const req of requirements) {
|
|
@@ -4327,13 +4812,25 @@ var AssetManager = class {
|
|
|
4327
4812
|
}
|
|
4328
4813
|
const asset = lockIdentity(i.assetKind, i.assetName);
|
|
4329
4814
|
const dep = `${i.depKind}:${i.depName}`;
|
|
4330
|
-
|
|
4815
|
+
const depId = /^@([^/]+)\/(.+)$/.exec(i.depName);
|
|
4816
|
+
const lockedOnly = lockedIds.some(
|
|
4817
|
+
(id) => id.kind === i.depKind && id.name === (depId ? depId[2] : i.depName) && (!depId || id.publisher === depId[1])
|
|
4818
|
+
);
|
|
4819
|
+
if (lockedOnly) {
|
|
4331
4820
|
gaps.push({
|
|
4332
4821
|
type: "requires",
|
|
4333
4822
|
ref: dep,
|
|
4334
4823
|
asset,
|
|
4335
|
-
reason: `is required by ${asset} but
|
|
4336
|
-
message: `${asset} requires ${dep} (
|
|
4824
|
+
reason: `is required by ${asset} but locked and not deployed (run skaile install --locked)`,
|
|
4825
|
+
message: `${asset} requires ${dep} (run skaile install --locked)`
|
|
4826
|
+
});
|
|
4827
|
+
} else if (i.inRepos) {
|
|
4828
|
+
gaps.push({
|
|
4829
|
+
type: "requires",
|
|
4830
|
+
ref: dep,
|
|
4831
|
+
asset,
|
|
4832
|
+
reason: `is required by ${asset} but neither deployed nor locked (run skaile install)`,
|
|
4833
|
+
message: `${asset} requires ${dep} (run skaile install)`
|
|
4337
4834
|
});
|
|
4338
4835
|
} else {
|
|
4339
4836
|
const fix = requirementNoHolderFix(asset);
|
|
@@ -4378,6 +4875,25 @@ var AssetManager = class {
|
|
|
4378
4875
|
const reason = `is deployed without ${d.missing.join(", ")} \u2014 run \`skaile install\` to restore it`;
|
|
4379
4876
|
gaps.push({ type: "incomplete", ref: d.ref, reason, message: `${d.ref} ${reason}` });
|
|
4380
4877
|
}
|
|
4878
|
+
const skipped = [];
|
|
4879
|
+
await buildProvenanceIndex(this.buildClones(this.loadConfig().repositories), {
|
|
4880
|
+
projectDir: this.projectDir,
|
|
4881
|
+
knownKinds: this.knownKinds,
|
|
4882
|
+
onSourceError: (clone, err) => skipped.push({
|
|
4883
|
+
url: clone.sourceUrl,
|
|
4884
|
+
why: err instanceof Error ? err.message : String(err)
|
|
4885
|
+
})
|
|
4886
|
+
});
|
|
4887
|
+
for (const s of skipped) {
|
|
4888
|
+
const reason = `is skipped: ${s.why.replace(`${s.url}: `, "")} \u2014 fix it or run \`skaile source remove\``;
|
|
4889
|
+
gaps.push({
|
|
4890
|
+
type: "source",
|
|
4891
|
+
ref: s.url,
|
|
4892
|
+
reason,
|
|
4893
|
+
message: `source ${s.url} ${reason}`,
|
|
4894
|
+
manualFix: true
|
|
4895
|
+
});
|
|
4896
|
+
}
|
|
4381
4897
|
for (const u of unboundAgentInstances(this.projectDir, this.driverTarget)) {
|
|
4382
4898
|
const reason = u.ref.startsWith("agent:") ? await this.unboundAgentReason(u.id, u.ref) : `is bound by agent instance "${u.id}" but resolves to no agent.yaml \u2014 fix the path, or drop the binding from skaile.yaml`;
|
|
4383
4899
|
gaps.push({
|
|
@@ -4411,7 +4927,18 @@ var AssetManager = class {
|
|
|
4411
4927
|
*/
|
|
4412
4928
|
async unboundAgentAdvice(ref) {
|
|
4413
4929
|
const drop = "or drop the binding from skaile.yaml";
|
|
4414
|
-
const
|
|
4930
|
+
const parsedRef = parseRefTolerant(ref);
|
|
4931
|
+
const publisher = parsedRef?.publisher;
|
|
4932
|
+
const lockedAgent = Object.keys(this.tryReadLock()?.assets ?? {}).some((key) => {
|
|
4933
|
+
const k = parseCanonicalLockKey(key);
|
|
4934
|
+
return k.kind === "agent" && k.name === parsedRef?.name && (!publisher || !k.publisher || k.publisher === publisher);
|
|
4935
|
+
});
|
|
4936
|
+
if (lockedAgent) {
|
|
4937
|
+
return {
|
|
4938
|
+
lead: "the agent is locked but not restored here",
|
|
4939
|
+
advice: `run \`skaile install --locked\` first, ${drop}`
|
|
4940
|
+
};
|
|
4941
|
+
}
|
|
4415
4942
|
if (publisher && await this.info(ref) !== null) {
|
|
4416
4943
|
return {
|
|
4417
4944
|
lead: "no agent was added for it",
|
|
@@ -4458,6 +4985,52 @@ var AssetManager = class {
|
|
|
4458
4985
|
(g) => names(g.ref) || g.asset && names(g.asset)
|
|
4459
4986
|
);
|
|
4460
4987
|
}
|
|
4988
|
+
/**
|
|
4989
|
+
* The {@link ProjectState} gaps of everything `ref` requires, transitively: what `check`
|
|
4990
|
+
* says about the requirements of `ref`, so a command that answers for one asset (`diff`)
|
|
4991
|
+
* does not call it fine while a requirement of it is broken. The requirements are read from
|
|
4992
|
+
* the deployed copies (the lock records no edges), the way `remove` and `install` read them
|
|
4993
|
+
* when no library holds the asset any more. The gaps of `ref` itself are not included
|
|
4994
|
+
* ({@link gapsOf}).
|
|
4995
|
+
*
|
|
4996
|
+
* @param ref - Asset ref in `kind:name` or `kind:@publisher/name` form.
|
|
4997
|
+
*/
|
|
4998
|
+
async requirementGapsOf(ref) {
|
|
4999
|
+
const want = parseRefTolerant(ref);
|
|
5000
|
+
if (!want) return [];
|
|
5001
|
+
const gaps = (await this.projectState()).gaps;
|
|
5002
|
+
const lockedIds = Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey);
|
|
5003
|
+
const idKey = (id) => `${id.publisher ?? ""}/${id.kind}:${id.name}`;
|
|
5004
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5005
|
+
const queue = [
|
|
5006
|
+
{
|
|
5007
|
+
kind: want.kind,
|
|
5008
|
+
name: want.name,
|
|
5009
|
+
publisher: want.publisher?.replace(/^@/, "") ?? lockedIds.find((l) => l.kind === want.kind && l.name === want.name)?.publisher
|
|
5010
|
+
}
|
|
5011
|
+
];
|
|
5012
|
+
seen.add(idKey(queue[0]));
|
|
5013
|
+
const out = [];
|
|
5014
|
+
for (const asset of queue) {
|
|
5015
|
+
for (const dep of await this.deployedRequirementsOf(asset)) {
|
|
5016
|
+
const id = memberIdentity(dep);
|
|
5017
|
+
if (!id) continue;
|
|
5018
|
+
const publisher = id.publisher ?? lockedIds.find((l) => l.kind === id.kind && l.name === id.name)?.publisher;
|
|
5019
|
+
const next = { kind: id.kind, name: id.name, publisher };
|
|
5020
|
+
if (seen.has(idKey(next))) continue;
|
|
5021
|
+
seen.add(idKey(next));
|
|
5022
|
+
queue.push(next);
|
|
5023
|
+
for (const g of gaps) {
|
|
5024
|
+
if (out.includes(g)) continue;
|
|
5025
|
+
const p = parseRefTolerant(g.ref);
|
|
5026
|
+
if (p !== null && p.kind === next.kind && p.name === next.name && (!publisher || !p.publisher || p.publisher.replace(/^@/, "") === publisher)) {
|
|
5027
|
+
out.push(g);
|
|
5028
|
+
}
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
}
|
|
5032
|
+
return out;
|
|
5033
|
+
}
|
|
4461
5034
|
/**
|
|
4462
5035
|
* Locked library assets whose library cannot supply them: the library is not registered
|
|
4463
5036
|
* (renamed or removed) or no longer holds the asset. Another library holding it makes the
|
|
@@ -4523,6 +5096,55 @@ var AssetManager = class {
|
|
|
4523
5096
|
}
|
|
4524
5097
|
return gaps;
|
|
4525
5098
|
}
|
|
5099
|
+
/**
|
|
5100
|
+
* Record, on every agent entry of `lock` that has none, the files the agent's harness
|
|
5101
|
+
* rendering occupies and their sha256. Call it after the deploy, so the bytes hashed are the
|
|
5102
|
+
* ones `install` just wrote; {@link lockedCopyDrift} compares later edits with them.
|
|
5103
|
+
* Entries that carry a record (kept from an earlier lock) are left as they are.
|
|
5104
|
+
*/
|
|
5105
|
+
withRenderedAgents(lock) {
|
|
5106
|
+
if (this.global) return lock;
|
|
5107
|
+
for (const [key, entry] of Object.entries(lock.assets)) {
|
|
5108
|
+
if (entry.rendered || entry.library?.installed) continue;
|
|
5109
|
+
const { kind, name } = parseCanonicalLockKey(key);
|
|
5110
|
+
if (!kind || !name || this.installTarget(kind) !== "agent") continue;
|
|
5111
|
+
const rendered = this.renderedAgentFiles(name);
|
|
5112
|
+
if (rendered.length > 0) entry.rendered = rendered;
|
|
5113
|
+
}
|
|
5114
|
+
return lock;
|
|
5115
|
+
}
|
|
5116
|
+
/** The files of one agent's rendering for the active harness, project-relative, with sha256. */
|
|
5117
|
+
renderedAgentFiles(name) {
|
|
5118
|
+
const out = [];
|
|
5119
|
+
const walk = (path2) => {
|
|
5120
|
+
let stat;
|
|
5121
|
+
try {
|
|
5122
|
+
stat = lstatSync(path2);
|
|
5123
|
+
} catch {
|
|
5124
|
+
return;
|
|
5125
|
+
}
|
|
5126
|
+
if (stat.isSymbolicLink()) return;
|
|
5127
|
+
if (stat.isDirectory()) {
|
|
5128
|
+
for (const child of readdirSync(path2).sort()) walk(join(path2, child));
|
|
5129
|
+
} else if (stat.isFile()) {
|
|
5130
|
+
out.push({
|
|
5131
|
+
path: relative(this.projectDir, path2).split(sep).join("/"),
|
|
5132
|
+
sha256: computeHash(path2)
|
|
5133
|
+
});
|
|
5134
|
+
}
|
|
5135
|
+
};
|
|
5136
|
+
for (const path2 of deployedPaths("agent", name, this.driverTarget, false, this.projectDir)) {
|
|
5137
|
+
walk(path2);
|
|
5138
|
+
}
|
|
5139
|
+
walk(
|
|
5140
|
+
join(
|
|
5141
|
+
dirname(deployedBase("agent", this.driverTarget, false, this.projectDir)),
|
|
5142
|
+
CODEX_IDENTITY_DIR,
|
|
5143
|
+
`${name}.md`
|
|
5144
|
+
)
|
|
5145
|
+
);
|
|
5146
|
+
return out.sort((a, b) => a.path.localeCompare(b.path));
|
|
5147
|
+
}
|
|
4526
5148
|
/**
|
|
4527
5149
|
* The {@link RestoredAsset} rows for the drifted copies (see {@link lockedCopyDrift}) a
|
|
4528
5150
|
* deploy just wrote again: those whose ref is among the `deployed` canonical refs.
|
|
@@ -4532,6 +5154,10 @@ var AssetManager = class {
|
|
|
4532
5154
|
const out = [];
|
|
4533
5155
|
for (const d of drifts) {
|
|
4534
5156
|
if (!rewritten.has(d.ref)) continue;
|
|
5157
|
+
if (d.rendered) {
|
|
5158
|
+
out.push({ ref: d.key, restored: [...d.modified], removed: [] });
|
|
5159
|
+
continue;
|
|
5160
|
+
}
|
|
4535
5161
|
const { kind, name } = parseCanonicalLockKey(d.key);
|
|
4536
5162
|
const component = kind ? this.installTarget(kind) : void 0;
|
|
4537
5163
|
if (!kind || !name || !component) continue;
|
|
@@ -4559,8 +5185,10 @@ var AssetManager = class {
|
|
|
4559
5185
|
* - A source asset is compared with the per-file hashes the lock records (modified files only:
|
|
4560
5186
|
* the lock lists what the source covers, not what the deploy copies).
|
|
4561
5187
|
*
|
|
4562
|
-
*
|
|
4563
|
-
*
|
|
5188
|
+
* A `--link` deploy, an asset with a configured patch, and a copy that is missing are not
|
|
5189
|
+
* compared: other gaps cover them. An agent (rendered, not copied) is compared with the
|
|
5190
|
+
* hashes of its rendered files the lock records (`LockEntry.rendered`); its `modified` paths
|
|
5191
|
+
* are project-relative. Project mode only.
|
|
4564
5192
|
*/
|
|
4565
5193
|
async lockedCopyDrift() {
|
|
4566
5194
|
if (this.global) return [];
|
|
@@ -4601,30 +5229,37 @@ var AssetManager = class {
|
|
|
4601
5229
|
} catch {
|
|
4602
5230
|
continue;
|
|
4603
5231
|
}
|
|
4604
|
-
const dirs = entry.files.map(
|
|
4605
|
-
(f) => posix.dirname(f.path).split("/").filter((s) => s !== ".")
|
|
4606
|
-
);
|
|
4607
|
-
let common = dirs[0] ?? [];
|
|
4608
|
-
for (const d of dirs.slice(1)) {
|
|
4609
|
-
let i = 0;
|
|
4610
|
-
while (i < common.length && i < d.length && common[i] === d[i]) i++;
|
|
4611
|
-
common = common.slice(0, i);
|
|
4612
|
-
}
|
|
4613
|
-
const prefix = common.length > 0 ? `${common.join("/")}/` : "";
|
|
4614
5232
|
const modified = [];
|
|
4615
|
-
for (const f of entry.files) {
|
|
4616
|
-
const
|
|
4617
|
-
const deployedFile = join(dest, rel);
|
|
5233
|
+
for (const f of lockedAssetFiles(kind, entry.files)) {
|
|
5234
|
+
const deployedFile = join(dest, f.rel);
|
|
4618
5235
|
if (!existsSync(deployedFile)) continue;
|
|
4619
5236
|
try {
|
|
4620
|
-
if (computeHash(deployedFile) !== f.sha256) modified.push(rel);
|
|
5237
|
+
if (computeHash(deployedFile) !== f.sha256) modified.push(f.rel);
|
|
4621
5238
|
} catch {
|
|
4622
|
-
modified.push(rel);
|
|
5239
|
+
modified.push(f.rel);
|
|
4623
5240
|
}
|
|
4624
5241
|
}
|
|
4625
5242
|
if (modified.length > 0)
|
|
4626
5243
|
out.push({ ref: refOf(key), key, modified, extra: [], library: false });
|
|
4627
5244
|
}
|
|
5245
|
+
for (const [key, entry] of Object.entries(lock.assets)) {
|
|
5246
|
+
if (!entry.rendered || entry.rendered.length === 0 || entry.library?.installed) continue;
|
|
5247
|
+
const { kind, name } = parseCanonicalLockKey(key);
|
|
5248
|
+
if (!kind || !name || this.installTarget(kind) !== "agent") continue;
|
|
5249
|
+
if (patches[`${kind}:${name}`]) continue;
|
|
5250
|
+
const modified = [];
|
|
5251
|
+
for (const f of entry.rendered) {
|
|
5252
|
+
const file = join(this.projectDir, f.path);
|
|
5253
|
+
if (!existsSync(file)) continue;
|
|
5254
|
+
try {
|
|
5255
|
+
if (computeHash(file) !== f.sha256) modified.push(f.path);
|
|
5256
|
+
} catch {
|
|
5257
|
+
modified.push(f.path);
|
|
5258
|
+
}
|
|
5259
|
+
}
|
|
5260
|
+
if (modified.length > 0)
|
|
5261
|
+
out.push({ ref: refOf(key), key, modified, extra: [], library: false, rendered: true });
|
|
5262
|
+
}
|
|
4628
5263
|
return out;
|
|
4629
5264
|
}
|
|
4630
5265
|
/**
|
|
@@ -4642,7 +5277,7 @@ var AssetManager = class {
|
|
|
4642
5277
|
if (!kind || !name || !component || named.has(`${kind}:${name}`)) continue;
|
|
4643
5278
|
if (isDeployed(component, name, this.driverTarget, this.global, this.projectDir)) continue;
|
|
4644
5279
|
const ref = publisher ? `${kind}:@${publisher}/${name}` : `${kind}:${name}`;
|
|
4645
|
-
const reason = "is locked but its deployed copy is missing \u2014 run `skaile install`";
|
|
5280
|
+
const reason = "is locked but its deployed copy is missing \u2014 run `skaile install --locked`";
|
|
4646
5281
|
gaps.push({ type: "drift", ref, reason, message: `${ref} ${reason}` });
|
|
4647
5282
|
}
|
|
4648
5283
|
return gaps;
|
|
@@ -4693,7 +5328,12 @@ var AssetManager = class {
|
|
|
4693
5328
|
manualFix: true
|
|
4694
5329
|
};
|
|
4695
5330
|
} else if (await this.declaredRefResolvable(d.ref)) {
|
|
4696
|
-
|
|
5331
|
+
const unmet = await this.unmetRequirementOf(d.ref);
|
|
5332
|
+
gap = unmet ? {
|
|
5333
|
+
type: "declared",
|
|
5334
|
+
reason: `requires ${unmet} but no library or source holds it \u2014 ${REGISTER_HOLDER}, or drop ${d.ref.split("#")[0]} with \`skaile remove ${d.ref.split("#")[0]}\``,
|
|
5335
|
+
manualFix: true
|
|
5336
|
+
} : { type: "declared", reason: "is declared but not locked \u2014 run `skaile install`" };
|
|
4697
5337
|
} else {
|
|
4698
5338
|
gap = {
|
|
4699
5339
|
type: "declared",
|
|
@@ -4735,6 +5375,38 @@ var AssetManager = class {
|
|
|
4735
5375
|
return p !== null && p.kind === want.kind && p.name === want.name && (!want.publisher || !p.publisher || p.publisher === want.publisher);
|
|
4736
5376
|
});
|
|
4737
5377
|
}
|
|
5378
|
+
/**
|
|
5379
|
+
* The first requirement, direct or transitive, of the declared `ref` that no local source or
|
|
5380
|
+
* library holds and that nothing in the project already provides — the case `install` ends
|
|
5381
|
+
* with `Missing: … nothing was installed`. `undefined` when every requirement is held, when a
|
|
5382
|
+
* store is declared (it may hold the requirement and a check never goes to the network), or
|
|
5383
|
+
* when `ref` itself resolves to nothing.
|
|
5384
|
+
*/
|
|
5385
|
+
async unmetRequirementOf(ref) {
|
|
5386
|
+
if (this.loadConfig().stores.length > 0) return void 0;
|
|
5387
|
+
const lockedIds = Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey);
|
|
5388
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5389
|
+
const queue = [ref];
|
|
5390
|
+
for (let cur = queue.shift(); cur !== void 0; cur = queue.shift()) {
|
|
5391
|
+
const id = refIdentity(cur);
|
|
5392
|
+
if (id !== null) {
|
|
5393
|
+
if (seen.has(id)) continue;
|
|
5394
|
+
seen.add(id);
|
|
5395
|
+
}
|
|
5396
|
+
const entry = await this.info(cur);
|
|
5397
|
+
if (!entry) {
|
|
5398
|
+
if (cur === ref) return void 0;
|
|
5399
|
+
const want = parseRefTolerant(cur);
|
|
5400
|
+
const locked = want !== null && lockedIds.some(
|
|
5401
|
+
(l) => l.kind === want.kind && l.name === want.name && (!want.publisher || l.publisher === want.publisher)
|
|
5402
|
+
);
|
|
5403
|
+
if (!locked) return cur;
|
|
5404
|
+
continue;
|
|
5405
|
+
}
|
|
5406
|
+
queue.push(...libraryEntryDepRefs(entry));
|
|
5407
|
+
}
|
|
5408
|
+
return void 0;
|
|
5409
|
+
}
|
|
4738
5410
|
/**
|
|
4739
5411
|
* Whether `skaile install` can resolve a declared ref: a source or library holds it, or the
|
|
4740
5412
|
* project declares a store that may. The global catalog is not asked: a check never goes
|
|
@@ -4768,7 +5440,8 @@ var AssetManager = class {
|
|
|
4768
5440
|
const { repositories } = this.loadConfig();
|
|
4769
5441
|
const provenanceIndex = await buildProvenanceIndex(this.buildClones(repositories), {
|
|
4770
5442
|
projectDir: this.projectDir,
|
|
4771
|
-
knownKinds: this.knownKinds
|
|
5443
|
+
knownKinds: this.knownKinds,
|
|
5444
|
+
onSourceError: this.reportSourceError
|
|
4772
5445
|
});
|
|
4773
5446
|
const lockKeys = Object.keys(lock.assets).map(parseCanonicalLockKey);
|
|
4774
5447
|
const sourceCandidate = (ref) => {
|
|
@@ -5076,5 +5749,5 @@ var AssetManager = class {
|
|
|
5076
5749
|
};
|
|
5077
5750
|
|
|
5078
5751
|
export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, installAgentInstances, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, softDepName };
|
|
5079
|
-
//# sourceMappingURL=chunk-
|
|
5080
|
-
//# sourceMappingURL=chunk-
|
|
5752
|
+
//# sourceMappingURL=chunk-Y7WKXPWS.js.map
|
|
5753
|
+
//# sourceMappingURL=chunk-Y7WKXPWS.js.map
|