@skaile/workspaces 5.12.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 +96 -0
- package/README.md +2 -2
- package/dist/{asset-feeds-AM6PSSGM.js → asset-feeds-ALMTHLPV.js} +20 -20
- package/dist/{asset-feeds-AM6PSSGM.js.map → asset-feeds-ALMTHLPV.js.map} +1 -1
- package/dist/asset-manager/catalog-deployer.js +9 -9
- package/dist/asset-manager/index.js +15 -15
- package/dist/asset-manager/installer.js +11 -11
- package/dist/asset-manager/renderers.js +10 -10
- package/dist/asset-manager/src/index.d.ts +53 -10
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/asset-manager/src/installer.d.ts +0 -10
- package/dist/asset-manager/src/installer.d.ts.map +1 -1
- package/dist/bridge/drivers/claude-sdk.js +15 -13
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +72 -27
- package/dist/bridge/drivers/codex.js.map +1 -1
- package/dist/bridge/drivers/continue.js +11 -11
- package/dist/bridge/drivers/echo.js +1 -1
- package/dist/bridge/drivers/gemini.js +6 -6
- package/dist/bridge/drivers/goose.js +11 -11
- package/dist/bridge/drivers/omp.js +102 -27
- package/dist/bridge/drivers/omp.js.map +1 -1
- package/dist/bridge/drivers/opencode.js +11 -11
- package/dist/bridge/drivers/qwen.js +6 -6
- package/dist/bridge/index.js +13 -13
- package/dist/bridge/src/codex/config-toml.d.ts +8 -0
- package/dist/bridge/src/codex/config-toml.d.ts.map +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 +20 -6
- package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
- package/dist/{chunk-QCEKGYHF.js → chunk-2BIESC6S.js} +3 -3
- package/dist/{chunk-QCEKGYHF.js.map → chunk-2BIESC6S.js.map} +1 -1
- package/dist/{chunk-NGJIVDDD.js → chunk-4DLQESIY.js} +3 -3
- package/dist/{chunk-NGJIVDDD.js.map → chunk-4DLQESIY.js.map} +1 -1
- package/dist/{chunk-7QWQTA5S.js → chunk-4L4R5LV3.js} +4 -4
- package/dist/{chunk-7QWQTA5S.js.map → chunk-4L4R5LV3.js.map} +1 -1
- package/dist/{chunk-GWD3QNVS.js → chunk-4NJ3QQHZ.js} +5 -5
- package/dist/{chunk-GWD3QNVS.js.map → chunk-4NJ3QQHZ.js.map} +1 -1
- package/dist/{chunk-6VLHITAM.js → chunk-57SF6W6E.js} +4 -3
- package/dist/chunk-57SF6W6E.js.map +1 -0
- package/dist/{chunk-NJV5SLEK.js → chunk-5FYOM4RF.js} +46 -46
- package/dist/chunk-5FYOM4RF.js.map +1 -0
- package/dist/{chunk-ICIYSJBQ.js → chunk-5SKVCMRC.js} +15 -7
- package/dist/chunk-5SKVCMRC.js.map +1 -0
- package/dist/{chunk-P23WJCH2.js → chunk-6GICC4RJ.js} +23 -18
- package/dist/chunk-6GICC4RJ.js.map +1 -0
- package/dist/{chunk-3HUV2LJF.js → chunk-6JKIOPT3.js} +4 -4
- package/dist/{chunk-3HUV2LJF.js.map → chunk-6JKIOPT3.js.map} +1 -1
- package/dist/{chunk-NDF24LYP.js → chunk-6NQDDCIL.js} +3 -3
- package/dist/{chunk-NDF24LYP.js.map → chunk-6NQDDCIL.js.map} +1 -1
- package/dist/{chunk-VRLKHL74.js → chunk-7SMP4GNW.js} +6 -6
- package/dist/{chunk-VRLKHL74.js.map → chunk-7SMP4GNW.js.map} +1 -1
- package/dist/{chunk-XMAJJPA4.js → chunk-AHCI4V5L.js} +3 -3
- package/dist/{chunk-XMAJJPA4.js.map → chunk-AHCI4V5L.js.map} +1 -1
- package/dist/{chunk-NJXR5OAM.js → chunk-B7CZYFB2.js} +4 -4
- package/dist/{chunk-NJXR5OAM.js.map → chunk-B7CZYFB2.js.map} +1 -1
- package/dist/{chunk-T5TSLSRO.js → chunk-BF422IDP.js} +8 -8
- package/dist/{chunk-T5TSLSRO.js.map → chunk-BF422IDP.js.map} +1 -1
- package/dist/{chunk-MF54ZHWT.js → chunk-BVJU2GKE.js} +2 -2
- package/dist/{chunk-MF54ZHWT.js.map → chunk-BVJU2GKE.js.map} +1 -1
- package/dist/{chunk-PMECEZK3.js → chunk-D54T2F54.js} +5 -4
- package/dist/chunk-D54T2F54.js.map +1 -0
- package/dist/{chunk-C3BMXXTN.js → chunk-DKGEV6SQ.js} +68 -24
- package/dist/chunk-DKGEV6SQ.js.map +1 -0
- package/dist/chunk-FB3NREF7.js +649 -0
- package/dist/chunk-FB3NREF7.js.map +1 -0
- package/dist/{chunk-3LVB3HGH.js → chunk-FHDK3BFD.js} +3 -3
- package/dist/{chunk-3LVB3HGH.js.map → chunk-FHDK3BFD.js.map} +1 -1
- package/dist/{chunk-2X3JBVGD.js → chunk-GMDSRSGI.js} +18 -9
- package/dist/chunk-GMDSRSGI.js.map +1 -0
- package/dist/{chunk-N5M2EISA.js → chunk-HBZD3MIW.js} +97 -54
- package/dist/chunk-HBZD3MIW.js.map +1 -0
- package/dist/{chunk-SMT3LNAG.js → chunk-HWGYJMME.js} +4 -4
- package/dist/{chunk-SMT3LNAG.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-CTP3XBMF.js → chunk-IY5E7Y5W.js} +57 -7
- package/dist/chunk-IY5E7Y5W.js.map +1 -0
- package/dist/{chunk-YQU2BPQD.js → chunk-J4DB5G36.js} +2 -2
- package/dist/{chunk-YQU2BPQD.js.map → chunk-J4DB5G36.js.map} +1 -1
- package/dist/{chunk-PNTXHTBC.js → chunk-J4OYIYFQ.js} +2 -2
- package/dist/{chunk-PNTXHTBC.js.map → chunk-J4OYIYFQ.js.map} +1 -1
- package/dist/{chunk-PNOGX36L.js → chunk-L3ZGYSWY.js} +85 -24
- package/dist/chunk-L3ZGYSWY.js.map +1 -0
- package/dist/{chunk-XTVSNWLL.js → chunk-M3P4BYRK.js} +34 -11
- package/dist/chunk-M3P4BYRK.js.map +1 -0
- package/dist/{chunk-X6LKA3TJ.js → chunk-NDUYFYJB.js} +5 -5
- package/dist/{chunk-X6LKA3TJ.js.map → chunk-NDUYFYJB.js.map} +1 -1
- package/dist/{chunk-7CR2OZPA.js → chunk-NVO6WECE.js} +9 -8
- package/dist/chunk-NVO6WECE.js.map +1 -0
- package/dist/chunk-PN44DOGP.js +345 -0
- package/dist/chunk-PN44DOGP.js.map +1 -0
- package/dist/{chunk-UTKENBB6.js → chunk-PXDWTJ3P.js} +4 -4
- package/dist/{chunk-UTKENBB6.js.map → chunk-PXDWTJ3P.js.map} +1 -1
- package/dist/{chunk-POQ6PGNE.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-SHQMPGOL.js → chunk-QO7CR3KB.js} +10 -5
- package/dist/chunk-QO7CR3KB.js.map +1 -0
- package/dist/{chunk-KVSDRB35.js → chunk-R6QHJEHE.js} +5 -5
- package/dist/{chunk-KVSDRB35.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-G3X4MLDB.js → chunk-USHB5KEY.js} +3 -3
- package/dist/{chunk-G3X4MLDB.js.map → chunk-USHB5KEY.js.map} +1 -1
- package/dist/{chunk-HYMERG57.js → chunk-V5JHD4I2.js} +3 -3
- package/dist/{chunk-HYMERG57.js.map → chunk-V5JHD4I2.js.map} +1 -1
- package/dist/{chunk-JQ3DXNQV.js → chunk-VLBIME5L.js} +6 -6
- package/dist/{chunk-JQ3DXNQV.js.map → chunk-VLBIME5L.js.map} +1 -1
- package/dist/{chunk-7XWUJC3A.js → chunk-XBYSURMK.js} +3 -3
- package/dist/{chunk-7XWUJC3A.js.map → chunk-XBYSURMK.js.map} +1 -1
- package/dist/{chunk-XZY6SBGU.js → chunk-XJYBCDY2.js} +3 -3
- package/dist/{chunk-XZY6SBGU.js.map → chunk-XJYBCDY2.js.map} +1 -1
- package/dist/{chunk-27L6BBAT.js → chunk-Y4Z7LGSH.js} +8 -8
- package/dist/{chunk-27L6BBAT.js.map → chunk-Y4Z7LGSH.js.map} +1 -1
- package/dist/{chunk-TVAR4JHA.js → chunk-Y7WKXPWS.js} +320 -51
- package/dist/chunk-Y7WKXPWS.js.map +1 -0
- package/dist/{chunk-2JFIFDDO.js → chunk-YTZFSKWL.js} +3 -3
- package/dist/{chunk-2JFIFDDO.js.map → chunk-YTZFSKWL.js.map} +1 -1
- package/dist/{chunk-WI4T3KIS.js → chunk-ZSMMX3JD.js} +130 -23
- package/dist/chunk-ZSMMX3JD.js.map +1 -0
- package/dist/{chunk-DCHQ6BAZ.js → chunk-ZU24LWBI.js} +3 -3
- package/dist/{chunk-DCHQ6BAZ.js.map → chunk-ZU24LWBI.js.map} +1 -1
- package/dist/cli/index.js +469 -227
- package/dist/cli/index.js.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 +2 -0
- package/dist/cli/src/commands/catalog.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/plugin/claude-code.d.ts.map +1 -1
- package/dist/cli/src/commands/plugin/types.d.ts +2 -0
- 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/run.d.ts +9 -0
- package/dist/cli/src/commands/run.d.ts.map +1 -1
- package/dist/cli/src/commands/serve-preflight.d.ts +2 -1
- package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
- package/dist/cli/src/commands/serve.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/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/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/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/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 +15 -4
- package/dist/cli/src/skill-checks.d.ts.map +1 -1
- package/dist/cli/src/store-addable.d.ts +7 -8
- package/dist/cli/src/store-addable.d.ts.map +1 -1
- package/dist/connectors/config.js +6 -6
- package/dist/connectors/index.js +16 -16
- package/dist/connectors/src/config.d.ts.map +1 -1
- package/dist/{connectors-UNKUKEPG.js → connectors-GFKMKAXV.js} +19 -19
- package/dist/{connectors-UNKUKEPG.js.map → connectors-GFKMKAXV.js.map} +1 -1
- package/dist/core/driver-targets.js +1 -1
- package/dist/core/index.js +8 -8
- 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 +1 -1
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/manifest.d.ts +9 -3
- package/dist/core/src/manifest.d.ts.map +1 -1
- package/dist/core/src/models.d.ts +8 -0
- package/dist/core/src/models.d.ts.map +1 -1
- 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 +8 -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/store.d.ts +4 -0
- package/dist/core/src/store.d.ts.map +1 -1
- package/dist/core/src/walker.d.ts +2 -0
- 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 +8 -8
- 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-POMEQSTM.js → ensure-sources-VUKHL65L.js} +18 -18
- package/dist/{ensure-sources-POMEQSTM.js.map → ensure-sources-VUKHL65L.js.map} +1 -1
- package/dist/factory-assets/README.md +1 -1
- package/dist/factory-assets/connectors/box.js +16 -16
- package/dist/factory-assets/connectors/deploy.js +16 -16
- package/dist/factory-assets/connectors/devserver.js +16 -16
- package/dist/factory-assets/connectors/flow/adapter.js +16 -16
- package/dist/factory-assets/connectors/flow/engine.js +9 -9
- package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/run-flow.js +18 -18
- package/dist/factory-assets/connectors/flow.js +16 -16
- package/dist/factory-assets/connectors/git.js +16 -16
- package/dist/factory-assets/connectors/gmail.js +16 -16
- package/dist/factory-assets/connectors/googledrive.js +16 -16
- package/dist/factory-assets/connectors/local.js +16 -16
- package/dist/factory-assets/connectors/mattermost.js +16 -16
- package/dist/factory-assets/connectors/memory.js +16 -16
- package/dist/factory-assets/connectors/minio.js +16 -16
- package/dist/factory-assets/connectors/postgres.js +16 -16
- package/dist/factory-assets/connectors/s3.js +16 -16
- package/dist/factory-assets/connectors/sharepoint.js +16 -16
- package/dist/factory-assets/connectors/sqlite.js +16 -16
- package/dist/factory-assets/connectors/static-server.js +16 -16
- package/dist/factory-assets/connectors/tunnel.js +16 -16
- package/dist/factory-assets/connectors/webdav.js +16 -16
- package/dist/factory-assets/connectors/xstate-store.js +16 -16
- package/dist/factory-assets/connectors/xstate.js +16 -16
- package/dist/{flows-DVKMZKM4.js → flows-A4YALSZY.js} +13 -13
- package/dist/{flows-DVKMZKM4.js.map → flows-A4YALSZY.js.map} +1 -1
- package/dist/{helpers-Y4OT7VIS.js → helpers-53XZW7KF.js} +18 -18
- package/dist/{helpers-Y4OT7VIS.js.map → helpers-53XZW7KF.js.map} +1 -1
- package/dist/library/index.js +12 -12
- package/dist/library/install.js +5 -3
- 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/manifest-writer.d.ts +1 -1
- package/dist/library/src/manifest-writer.d.ts.map +1 -1
- package/dist/library/src/remote/remote-catalog-source.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-DI4Q5UOG.js → library-publish-FFIPWIRM.js} +28 -25
- package/dist/library-publish-FFIPWIRM.js.map +1 -0
- package/dist/open-library-PZAT3TJA.js +40 -0
- package/dist/{open-library-N6ESO6IK.js.map → open-library-PZAT3TJA.js.map} +1 -1
- package/dist/open-registry-W46UXZ3I.js +32 -0
- package/dist/{open-registry-CBZ5MWTT.js.map → open-registry-W46UXZ3I.js.map} +1 -1
- package/dist/paths-KKY3NSBZ.js +22 -0
- package/dist/{paths-U6W6MQNQ.js.map → paths-KKY3NSBZ.js.map} +1 -1
- package/dist/{plugin-store-XMZSPVBF.js → plugin-store-CK7YWRIC.js} +62 -20
- 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-UP52HEHC.js.map → project-EZUH7PUJ.js.map} +1 -1
- package/dist/resolver/index.js +9 -9
- package/dist/runner/index.js +29 -29
- package/dist/runner/src/agent.d.ts.map +1 -1
- package/dist/runner/src/composition/index.d.ts +1 -1
- package/dist/runner/src/composition/index.d.ts.map +1 -1
- package/dist/runner/src/composition/prompt-sections.d.ts +18 -6
- package/dist/runner/src/composition/prompt-sections.d.ts.map +1 -1
- 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 +15 -15
- package/dist/sdk/bridge.js +13 -13
- package/dist/sdk/core.js +8 -8
- package/dist/sdk/flow.js +9 -9
- package/dist/sdk/index.js +29 -29
- package/dist/sdk/resolver.js +9 -9
- package/dist/sdk/runner.js +29 -29
- package/dist/serve-preflight-F7MYF747.js +64 -0
- package/dist/serve-preflight-F7MYF747.js.map +1 -0
- package/dist/{setup-5IRUH5OS.js → setup-L632QIHV.js} +23 -23
- package/dist/{setup-5IRUH5OS.js.map → setup-L632QIHV.js.map} +1 -1
- package/dist/skills-OY3Y5GKA.js +26 -0
- package/dist/{skills-HA36RFNM.js.map → skills-OY3Y5GKA.js.map} +1 -1
- package/dist/source-36FHMN5V.js +42 -0
- package/dist/{source-DX5SGWEI.js.map → source-36FHMN5V.js.map} +1 -1
- package/dist/{source-manifest-publish-NMRLXWVW.js → source-manifest-publish-NIXJSJ22.js} +25 -24
- package/dist/source-manifest-publish-NIXJSJ22.js.map +1 -0
- package/dist/tui/index.js +46 -36
- package/dist/tui/index.js.map +1 -1
- 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/preset.d.ts +6 -1
- package/dist/types/src/manifests/preset.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +23 -23
- package/dist/workspace-plugin/adapters/omp.js +14 -14
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2X3JBVGD.js.map +0 -1
- package/dist/chunk-6VLHITAM.js.map +0 -1
- package/dist/chunk-7CR2OZPA.js.map +0 -1
- package/dist/chunk-C3BMXXTN.js.map +0 -1
- package/dist/chunk-CPSIPIX7.js.map +0 -1
- package/dist/chunk-CTP3XBMF.js.map +0 -1
- package/dist/chunk-ICIYSJBQ.js.map +0 -1
- package/dist/chunk-ID745F3R.js +0 -625
- package/dist/chunk-ID745F3R.js.map +0 -1
- package/dist/chunk-K4VOEYOR.js +0 -21
- package/dist/chunk-K4VOEYOR.js.map +0 -1
- package/dist/chunk-N5M2EISA.js.map +0 -1
- package/dist/chunk-NJV5SLEK.js.map +0 -1
- package/dist/chunk-NR7H7ZJP.js +0 -400
- package/dist/chunk-NR7H7ZJP.js.map +0 -1
- package/dist/chunk-P23WJCH2.js.map +0 -1
- package/dist/chunk-PMECEZK3.js.map +0 -1
- package/dist/chunk-PNOGX36L.js.map +0 -1
- package/dist/chunk-POQ6PGNE.js.map +0 -1
- package/dist/chunk-SHQMPGOL.js.map +0 -1
- package/dist/chunk-TVAR4JHA.js.map +0 -1
- package/dist/chunk-WI4T3KIS.js.map +0 -1
- package/dist/chunk-XTVSNWLL.js.map +0 -1
- package/dist/library-publish-DI4Q5UOG.js.map +0 -1
- package/dist/open-library-N6ESO6IK.js +0 -40
- package/dist/open-registry-CBZ5MWTT.js +0 -32
- package/dist/paths-U6W6MQNQ.js +0 -22
- package/dist/plugin-store-XMZSPVBF.js.map +0 -1
- package/dist/project-UP52HEHC.js +0 -79
- package/dist/serve-preflight-6P2JJEJ3.js +0 -47
- package/dist/serve-preflight-6P2JJEJ3.js.map +0 -1
- package/dist/skills-HA36RFNM.js +0 -26
- package/dist/source-DX5SGWEI.js +0 -41
- package/dist/source-manifest-publish-NMRLXWVW.js.map +0 -1
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { parseFlowDefinition } from './chunk-X3RMRJNR.js';
|
|
2
|
+
import { SEMVER_RE, parseManifestFile } from './chunk-NVO6WECE.js';
|
|
3
|
+
import { composeRefTarget, SKILL_DESCRIPTION_PLACEHOLDER_PREFIX, PRESET_DESCRIPTION_PLACEHOLDER, PRESET_ITEM_PLACEHOLDER_REF, SKILL_BODY_PLACEHOLDER, CONTRACT_BODY_PLACEHOLDER, PROMPT_BODY_PLACEHOLDER, AGENT_BODY_PLACEHOLDER } from './chunk-57SF6W6E.js';
|
|
4
|
+
import { checkAgentSkillConformance } from './chunk-BF422IDP.js';
|
|
5
|
+
import { parseFrontmatter } from './chunk-M3P4BYRK.js';
|
|
6
|
+
import { parseAssetRef, isValidAssetName, ASSET_NAME_HINT } from './chunk-J4OYIYFQ.js';
|
|
7
|
+
import * as fs2 from 'fs';
|
|
8
|
+
import * as path2 from 'path';
|
|
9
|
+
|
|
10
|
+
var error = (text) => ({ tag: "agent", text, conformance: false });
|
|
11
|
+
function isInside(parent, child) {
|
|
12
|
+
const rel = path2.relative(parent, child);
|
|
13
|
+
return rel === "" || !rel.startsWith("..") && !path2.isAbsolute(rel);
|
|
14
|
+
}
|
|
15
|
+
function records(value) {
|
|
16
|
+
return Array.isArray(value) ? value.filter((v) => v !== null && typeof v === "object") : [];
|
|
17
|
+
}
|
|
18
|
+
function checkAgentFiles(parsed, agentDir, libraryRoot) {
|
|
19
|
+
const out = [];
|
|
20
|
+
records(parsed.composes).forEach((item, i) => {
|
|
21
|
+
if (typeof item.kind !== "string" || typeof item.ref !== "string") return;
|
|
22
|
+
const target = composeRefTarget({ kind: item.kind, ref: item.ref });
|
|
23
|
+
if (target?.type !== "local") return;
|
|
24
|
+
const where = `composes[${i}].ref`;
|
|
25
|
+
const resolved = path2.resolve(agentDir, target.path);
|
|
26
|
+
if (!fs2.existsSync(resolved)) {
|
|
27
|
+
out.push(
|
|
28
|
+
error(`${where}: local path "${item.ref}" does not exist (resolved from ${agentDir})`)
|
|
29
|
+
);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (!isInside(libraryRoot, resolved)) {
|
|
33
|
+
out.push(
|
|
34
|
+
error(`${where}: local path "${item.ref}" leaves the library and cannot be published`)
|
|
35
|
+
);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const ownManifests = [
|
|
39
|
+
agentDir,
|
|
40
|
+
path2.join(agentDir, "agent.yaml"),
|
|
41
|
+
path2.join(agentDir, "AGENT.md")
|
|
42
|
+
];
|
|
43
|
+
if (item.kind === "agent" && ownManifests.includes(resolved)) {
|
|
44
|
+
out.push(
|
|
45
|
+
error(
|
|
46
|
+
`${where}: agent composes itself (${item.ref}); an agent cannot be its own sub-agent`
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
const blocks = records(
|
|
52
|
+
parsed.memory !== null && typeof parsed.memory === "object" ? parsed.memory.blocks : void 0
|
|
53
|
+
);
|
|
54
|
+
blocks.forEach((block, i) => {
|
|
55
|
+
if (typeof block.source !== "string" || block.source === "") return;
|
|
56
|
+
const where = `memory.blocks[${i}].source`;
|
|
57
|
+
const resolved = path2.resolve(agentDir, block.source);
|
|
58
|
+
if (!isInside(agentDir, resolved)) {
|
|
59
|
+
out.push(error(`${where}: "${block.source}" leaves the agent directory`));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
let stat;
|
|
63
|
+
try {
|
|
64
|
+
stat = fs2.statSync(resolved);
|
|
65
|
+
} catch {
|
|
66
|
+
out.push(error(`${where}: file "${block.source}" does not exist in ${agentDir}`));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (!stat.isFile()) {
|
|
70
|
+
out.push(error(`${where}: "${block.source}" is not a file`));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const max = block.max_chars;
|
|
74
|
+
if (typeof max !== "number") return;
|
|
75
|
+
const length = [...fs2.readFileSync(resolved, "utf-8").trim()].length;
|
|
76
|
+
if (length > max) {
|
|
77
|
+
out.push(
|
|
78
|
+
error(
|
|
79
|
+
`${where}: "${block.source}" holds ${length} characters, more than memory block "${String(block.name)}" max_chars ${max}`
|
|
80
|
+
)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
function agentComposeRefAdvisories(parsed, hasAsset, libraryPublisher) {
|
|
87
|
+
const out = [];
|
|
88
|
+
records(parsed.composes).forEach((item, i) => {
|
|
89
|
+
if (typeof item.kind !== "string" || typeof item.ref !== "string") return;
|
|
90
|
+
const target = composeRefTarget({ kind: item.kind, ref: item.ref });
|
|
91
|
+
if (target?.type !== "asset" || target.kind === "soul") return;
|
|
92
|
+
if (target.publisher !== void 0 && libraryPublisher !== void 0 && target.publisher !== libraryPublisher) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (target.publisher !== void 0 && libraryPublisher === void 0) return;
|
|
96
|
+
if (hasAsset(target.kind, target.name)) return;
|
|
97
|
+
out.push({
|
|
98
|
+
tag: "agent",
|
|
99
|
+
text: `composes[${i}].ref: ${item.ref} is not in this library; \`skaile add\` fails with "requires \u2026 not found" unless the asset is published elsewhere`,
|
|
100
|
+
conformance: false
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
var BODY_PLACEHOLDER_BY_KIND = {
|
|
106
|
+
skill: SKILL_BODY_PLACEHOLDER,
|
|
107
|
+
agent: AGENT_BODY_PLACEHOLDER,
|
|
108
|
+
prompt: PROMPT_BODY_PLACEHOLDER,
|
|
109
|
+
contract: CONTRACT_BODY_PLACEHOLDER
|
|
110
|
+
};
|
|
111
|
+
var MARKDOWN_SCAFFOLD_KINDS = {
|
|
112
|
+
skill: true,
|
|
113
|
+
agent: true,
|
|
114
|
+
prompt: true,
|
|
115
|
+
contract: true
|
|
116
|
+
};
|
|
117
|
+
var FLOW_DESCRIPTION_PLACEHOLDER = "Flow description";
|
|
118
|
+
function checkAssetManifest(kind, parsed, body, dirName) {
|
|
119
|
+
const out = [];
|
|
120
|
+
if (kind === "skill") {
|
|
121
|
+
for (const f of checkAgentSkillConformance(parsed, { dirName })) {
|
|
122
|
+
out.push({ tag: "skill conformance", text: `${f.field}: ${f.message}`, conformance: true });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (MARKDOWN_SCAFFOLD_KINDS[kind]) {
|
|
126
|
+
const bodyText = body?.replace(/^#[^\n]*\n+/, "");
|
|
127
|
+
const isPlaceholder = bodyText === SKILL_BODY_PLACEHOLDER || bodyText === BODY_PLACEHOLDER_BY_KIND[kind];
|
|
128
|
+
if (isPlaceholder) {
|
|
129
|
+
const noun = kind === "skill" ? "skill prompt" : kind;
|
|
130
|
+
out.push({
|
|
131
|
+
tag: kind,
|
|
132
|
+
text: `body is still the scaffold placeholder; write the ${noun}`,
|
|
133
|
+
conformance: false,
|
|
134
|
+
scaffoldBody: true
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
function declaredVersion(parsed) {
|
|
141
|
+
const scalar = (v) => typeof v === "string" ? v : typeof v === "number" ? String(v) : void 0;
|
|
142
|
+
const meta = parsed.metadata;
|
|
143
|
+
const nested = meta !== null && typeof meta === "object" ? scalar(meta.version) : void 0;
|
|
144
|
+
return scalar(parsed.version) ?? nested;
|
|
145
|
+
}
|
|
146
|
+
function invalidSemverText(version) {
|
|
147
|
+
return SEMVER_RE.test(version) ? void 0 : `version "${version}" is not valid semver`;
|
|
148
|
+
}
|
|
149
|
+
function rawVersionScalar(text) {
|
|
150
|
+
const front = text.startsWith("---") ? text.split(/\n---/, 1)[0] ?? text : text;
|
|
151
|
+
const m = /^[ \t]*version:[ \t]*([^\s#][^#\n]*?)[ \t]*(?:#.*)?$/m.exec(front);
|
|
152
|
+
return m?.[1];
|
|
153
|
+
}
|
|
154
|
+
function versionProblemText(parsed, rawText) {
|
|
155
|
+
const version = declaredVersion(parsed);
|
|
156
|
+
const text = version === void 0 ? void 0 : invalidSemverText(version);
|
|
157
|
+
if (text === void 0) return void 0;
|
|
158
|
+
const meta = parsed.metadata;
|
|
159
|
+
const nested = meta !== null && typeof meta === "object" ? meta.version : void 0;
|
|
160
|
+
const key = parsed.version === void 0 || parsed.version === null ? "metadata.version" : "version";
|
|
161
|
+
const written = key === "version" ? parsed.version : nested;
|
|
162
|
+
if (typeof written !== "number") return text;
|
|
163
|
+
const raw = (rawText === void 0 ? void 0 : rawVersionScalar(rawText)) ?? String(written);
|
|
164
|
+
const fix = /^\d+(\.\d+)?$/.test(raw) ? `${raw}${raw.includes(".") ? "" : ".0"}.0` : DEFAULT_VERSION;
|
|
165
|
+
return `version ${raw} is not valid semver: yaml reads an unquoted number as a number, not a string. Write it quoted with three parts: ${key}: "${fix}"`;
|
|
166
|
+
}
|
|
167
|
+
function duplicateAssetMessage(kind, name, dir, detail, library) {
|
|
168
|
+
return `${kind}:${name} found in ${dir} but ${detail}. Rename or delete one of the two directories, then re-run \`skaile library index ${library}\`.`;
|
|
169
|
+
}
|
|
170
|
+
var DEFAULT_VERSION = "0.1.0";
|
|
171
|
+
var SCAFFOLD_KINDS = {
|
|
172
|
+
skill: true,
|
|
173
|
+
agent: true,
|
|
174
|
+
prompt: true,
|
|
175
|
+
contract: true,
|
|
176
|
+
flow: true,
|
|
177
|
+
preset: true
|
|
178
|
+
};
|
|
179
|
+
function withManifestDefaults(kind, parsed) {
|
|
180
|
+
if (!SCAFFOLD_KINDS[kind]) return parsed;
|
|
181
|
+
const out = { ...parsed };
|
|
182
|
+
if (out.metadata === null) delete out.metadata;
|
|
183
|
+
const meta = out.metadata;
|
|
184
|
+
const nested = typeof meta === "object" && meta !== null && "version" in meta ? meta.version : void 0;
|
|
185
|
+
if (out.version == null && nested == null) out.version = DEFAULT_VERSION;
|
|
186
|
+
return out;
|
|
187
|
+
}
|
|
188
|
+
function flowFileNameError(parsed, fileName) {
|
|
189
|
+
const id = parsed.id;
|
|
190
|
+
if (fileName === void 0 || typeof id !== "string" || id.length === 0) return void 0;
|
|
191
|
+
const stem = fileName.replace(/\.flow\.(yaml|yml|json)$/, "");
|
|
192
|
+
if (stem === fileName || stem === id) return void 0;
|
|
193
|
+
return `flow id "${id}" does not match the file name "${fileName}"; a flow asset is named by its id and the flow engine loads it only from "${id}.flow.yaml". Rename the file to "${id}.flow.yaml" or set id: ${stem}`;
|
|
194
|
+
}
|
|
195
|
+
function manifestIdentityError(kind, parsed) {
|
|
196
|
+
const identity = kind === "flow" ? parsed.id : parsed.name;
|
|
197
|
+
if (typeof identity !== "string" || identity.length === 0) return void 0;
|
|
198
|
+
const publisher = typeof parsed.publisher === "string" ? parsed.publisher : void 0;
|
|
199
|
+
if (publisher !== void 0) {
|
|
200
|
+
try {
|
|
201
|
+
parseAssetRef(`${kind}:@${publisher}/${identity}`);
|
|
202
|
+
return void 0;
|
|
203
|
+
} catch (e) {
|
|
204
|
+
return e instanceof Error ? e.message : String(e);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (!isValidAssetName(identity)) {
|
|
208
|
+
return `invalid asset ${kind === "flow" ? "id" : "name"} "${identity}" \u2014 ${ASSET_NAME_HINT}`;
|
|
209
|
+
}
|
|
210
|
+
return void 0;
|
|
211
|
+
}
|
|
212
|
+
function scaffoldDefinitionErrors(kind, parsed) {
|
|
213
|
+
const out = [];
|
|
214
|
+
if (kind === "flow") {
|
|
215
|
+
if (parsed.description === FLOW_DESCRIPTION_PLACEHOLDER) {
|
|
216
|
+
out.push("description is still the scaffold placeholder; say what the flow does");
|
|
217
|
+
}
|
|
218
|
+
if (parsed.nodes === void 0) {
|
|
219
|
+
out.push("nodes is missing; a flow needs at least one node");
|
|
220
|
+
} else if (Array.isArray(parsed.nodes) && parsed.nodes.length === 0) {
|
|
221
|
+
out.push("nodes is still the scaffold placeholder (nodes: []); add the flow's nodes");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (kind === "preset") {
|
|
225
|
+
if (parsed.description === PRESET_DESCRIPTION_PLACEHOLDER) {
|
|
226
|
+
out.push(
|
|
227
|
+
`description is still the scaffold placeholder ("${PRESET_DESCRIPTION_PLACEHOLDER}"); say what the preset does`
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
const items = Array.isArray(parsed.items) ? parsed.items : [];
|
|
231
|
+
const placeholderItem = items.some((item) => {
|
|
232
|
+
const ref = typeof item === "string" ? item : item?.ref;
|
|
233
|
+
return typeof ref === "string" && ref.trim() === PRESET_ITEM_PLACEHOLDER_REF;
|
|
234
|
+
});
|
|
235
|
+
if (placeholderItem) {
|
|
236
|
+
out.push(
|
|
237
|
+
`item ${PRESET_ITEM_PLACEHOLDER_REF} is still the scaffold placeholder; replace it with the preset's real items`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return out;
|
|
242
|
+
}
|
|
243
|
+
function checkAsset(kind, parsed, body, dirName, registry, rawText, fileName) {
|
|
244
|
+
const errors = [];
|
|
245
|
+
const error2 = (text) => {
|
|
246
|
+
errors.push({ tag: kind, text, conformance: false });
|
|
247
|
+
};
|
|
248
|
+
const identity = manifestIdentityError(kind, parsed);
|
|
249
|
+
if (identity) error2(identity);
|
|
250
|
+
const flowFileError = kind === "flow" ? flowFileNameError(parsed, fileName) : void 0;
|
|
251
|
+
if (flowFileError) error2(flowFileError);
|
|
252
|
+
const semver = versionProblemText(parsed, rawText);
|
|
253
|
+
if (semver) error2(semver);
|
|
254
|
+
const effective = withManifestDefaults(kind, parsed);
|
|
255
|
+
const versionKey = ["skill", "prompt", "contract"].includes(kind) ? "metadata.version" : "version";
|
|
256
|
+
const provider = registry.getProvider(kind);
|
|
257
|
+
if (!provider) {
|
|
258
|
+
error2(`unknown_asset_kind: kind "${kind}" is not registered`);
|
|
259
|
+
} else {
|
|
260
|
+
const result = provider.validateManifest(effective);
|
|
261
|
+
if (!result.ok) {
|
|
262
|
+
for (const e of result.errors) {
|
|
263
|
+
if (e.path === "version" || e.path === "metadata.version") {
|
|
264
|
+
if (!semver) {
|
|
265
|
+
error2(`${e.path}: must be a semver string \u2014 set ${versionKey}: ${DEFAULT_VERSION}`);
|
|
266
|
+
}
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
error2(`${e.path ? `${e.path}: ` : ""}${e.message}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const description = parsed.description;
|
|
274
|
+
if (kind !== "skill" && typeof description === "string" && description.trim().startsWith(SKILL_DESCRIPTION_PLACEHOLDER_PREFIX)) {
|
|
275
|
+
error2(
|
|
276
|
+
`description: description is still the scaffold placeholder (${SKILL_DESCRIPTION_PLACEHOLDER_PREFIX} \u2026) \u2014 say what the ${kind} does and when to use it`
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
for (const text of scaffoldDefinitionErrors(kind, parsed)) error2(text);
|
|
280
|
+
if (kind === "flow") {
|
|
281
|
+
const flow = parseFlowDefinition(effective);
|
|
282
|
+
if (!flow.ok) {
|
|
283
|
+
for (const e of flow.errors) {
|
|
284
|
+
error2(`invalid flow definition: ${e.path || "<root>"}: ${e.message}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return { errors, advisories: checkAssetManifest(kind, parsed, body, dirName) };
|
|
289
|
+
}
|
|
290
|
+
function findAssetManifestFile(dir, kind, name) {
|
|
291
|
+
const candidates = [];
|
|
292
|
+
if (kind === "skill") candidates.push("SKILL.md");
|
|
293
|
+
else if (kind === "agent") candidates.push("agent.yaml", "AGENT.md");
|
|
294
|
+
else if (kind === "contract") candidates.push("CONTRACT.md");
|
|
295
|
+
else if (kind === "prompt") candidates.push(`${name}.prompt.md`);
|
|
296
|
+
else if (kind === "flow") candidates.push(`${name}.flow.yaml`, `${name}.flow.json`);
|
|
297
|
+
else if (kind === "preset") candidates.push(`${name}.preset.yaml`);
|
|
298
|
+
for (const c of candidates) {
|
|
299
|
+
const file = path2.join(dir, c);
|
|
300
|
+
if (fs2.existsSync(file)) return file;
|
|
301
|
+
}
|
|
302
|
+
const suffix = kind === "prompt" ? ".prompt.md" : kind === "flow" ? ".flow.yaml" : kind === "preset" ? ".preset.yaml" : null;
|
|
303
|
+
if (suffix && fs2.existsSync(dir)) {
|
|
304
|
+
const matches = fs2.readdirSync(dir).filter((f) => f.endsWith(suffix));
|
|
305
|
+
if (matches.length === 1) return path2.join(dir, matches[0]);
|
|
306
|
+
}
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
function readAssetBody(file, text) {
|
|
310
|
+
if (file.endsWith(".md")) return parseFrontmatter(text).body;
|
|
311
|
+
if (path2.basename(file) !== "agent.yaml") return void 0;
|
|
312
|
+
const soul = path2.join(path2.dirname(file), "SOUL.md");
|
|
313
|
+
return fs2.existsSync(soul) ? fs2.readFileSync(soul, "utf8").trim() : void 0;
|
|
314
|
+
}
|
|
315
|
+
function checkAssetFile(file, kind, registry, libraryRoot, onScaffoldBody) {
|
|
316
|
+
let text;
|
|
317
|
+
try {
|
|
318
|
+
text = fs2.readFileSync(file, "utf8");
|
|
319
|
+
} catch {
|
|
320
|
+
return [];
|
|
321
|
+
}
|
|
322
|
+
const res = parseManifestFile(file, text);
|
|
323
|
+
if (!res.ok) return [];
|
|
324
|
+
const checked = checkAsset(
|
|
325
|
+
kind,
|
|
326
|
+
res.data,
|
|
327
|
+
readAssetBody(file, text),
|
|
328
|
+
path2.basename(path2.dirname(file)),
|
|
329
|
+
registry,
|
|
330
|
+
text,
|
|
331
|
+
path2.basename(file)
|
|
332
|
+
);
|
|
333
|
+
const errors = checked.errors;
|
|
334
|
+
if (onScaffoldBody) {
|
|
335
|
+
for (const f of checked.advisories) if (f.scaffoldBody) onScaffoldBody(f);
|
|
336
|
+
}
|
|
337
|
+
if (kind === "agent" && libraryRoot !== void 0) {
|
|
338
|
+
errors.push(...checkAgentFiles(res.data, path2.dirname(file), libraryRoot));
|
|
339
|
+
}
|
|
340
|
+
return errors;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export { agentComposeRefAdvisories, checkAgentFiles, checkAsset, checkAssetFile, declaredVersion, duplicateAssetMessage, findAssetManifestFile, invalidSemverText, readAssetBody };
|
|
344
|
+
//# sourceMappingURL=chunk-PN44DOGP.js.map
|
|
345
|
+
//# sourceMappingURL=chunk-PN44DOGP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../cli/src/agent-checks.ts","../cli/src/skill-checks.ts"],"names":["path","fs","error"],"mappings":"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","file":"chunk-PN44DOGP.js","sourcesContent":["/**\n * Agent checks that need the filesystem or the library's asset list. The schema\n * refinement (`AgentManifestSchema`) already refuses what the manifest alone can\n * show: a bad cron, an unknown capability slot, an agent composing itself by name.\n * This file adds the rest: local `composes:` paths and `memory.blocks[].source`\n * files (resolved against the agent's own directory), and `composes:` refs that name\n * an asset the library does not hold.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { composeRefTarget } from \"@skaile/workspaces/types/manifests\";\nimport type { AssetFinding } from \"./skill-checks.ts\";\n\nconst error = (text: string): AssetFinding => ({ tag: \"agent\", text, conformance: false });\n\n/** `child` is `parent` or lies inside it. */\nfunction isInside(parent: string, child: string): boolean {\n const rel = path.relative(parent, child);\n return rel === \"\" || (!rel.startsWith(\"..\") && !path.isAbsolute(rel));\n}\n\nfunction records(value: unknown): Array<Record<string, unknown>> {\n return Array.isArray(value)\n ? value.filter((v): v is Record<string, unknown> => v !== null && typeof v === \"object\")\n : [];\n}\n\n/**\n * The errors an agent's files add: a local `composes[].ref` path that does not exist,\n * leaves the library or points at the agent itself, and a `memory.blocks[].source`\n * that is missing, leaves the agent directory, or holds more characters than the\n * block's `max_chars`. Paths resolve against `agentDir`.\n *\n * `library index`, `library publish` and `skaile validate` run it for an agent\n * manifest whose directory is known.\n *\n * @param parsed Parsed agent manifest (`agent.yaml` document or `AGENT.md` frontmatter).\n * @param agentDir Absolute directory of the agent manifest.\n * @param libraryRoot Absolute root of the library holding the agent; a local compose\n * path outside it cannot be published.\n * @returns One error finding per problem; empty when the agent's files are consistent.\n */\nexport function checkAgentFiles(\n parsed: Record<string, unknown>,\n agentDir: string,\n libraryRoot: string,\n): AssetFinding[] {\n const out: AssetFinding[] = [];\n\n records(parsed.composes).forEach((item, i) => {\n if (typeof item.kind !== \"string\" || typeof item.ref !== \"string\") return;\n const target = composeRefTarget({ kind: item.kind, ref: item.ref });\n if (target?.type !== \"local\") return;\n const where = `composes[${i}].ref`;\n const resolved = path.resolve(agentDir, target.path);\n if (!fs.existsSync(resolved)) {\n out.push(\n error(`${where}: local path \"${item.ref}\" does not exist (resolved from ${agentDir})`),\n );\n return;\n }\n if (!isInside(libraryRoot, resolved)) {\n out.push(\n error(`${where}: local path \"${item.ref}\" leaves the library and cannot be published`),\n );\n return;\n }\n const ownManifests = [\n agentDir,\n path.join(agentDir, \"agent.yaml\"),\n path.join(agentDir, \"AGENT.md\"),\n ];\n if (item.kind === \"agent\" && ownManifests.includes(resolved)) {\n out.push(\n error(\n `${where}: agent composes itself (${item.ref}); an agent cannot be its own sub-agent`,\n ),\n );\n }\n });\n\n const blocks = records(\n parsed.memory !== null && typeof parsed.memory === \"object\"\n ? (parsed.memory as Record<string, unknown>).blocks\n : undefined,\n );\n blocks.forEach((block, i) => {\n if (typeof block.source !== \"string\" || block.source === \"\") return;\n const where = `memory.blocks[${i}].source`;\n const resolved = path.resolve(agentDir, block.source);\n if (!isInside(agentDir, resolved)) {\n out.push(error(`${where}: \"${block.source}\" leaves the agent directory`));\n return;\n }\n let stat: fs.Stats;\n try {\n stat = fs.statSync(resolved);\n } catch {\n out.push(error(`${where}: file \"${block.source}\" does not exist in ${agentDir}`));\n return;\n }\n if (!stat.isFile()) {\n out.push(error(`${where}: \"${block.source}\" is not a file`));\n return;\n }\n const max = block.max_chars;\n if (typeof max !== \"number\") return;\n const length = [...fs.readFileSync(resolved, \"utf-8\").trim()].length;\n if (length > max) {\n out.push(\n error(\n `${where}: \"${block.source}\" holds ${length} characters, more than memory block \"${String(block.name)}\" max_chars ${max}`,\n ),\n );\n }\n });\n\n return out;\n}\n\n/**\n * Advisories for `composes[]` items that name a library asset the library does not\n * hold (`kind:name` is not an asset of the library being validated). A ref that names\n * another publisher is external and cannot be judged here. A bare ref (`skill:sea-lore`)\n * inherits the agent's publisher, so it must be in the library; `add` fails on it\n * otherwise (`requires … not found`).\n *\n * @param parsed Parsed agent manifest.\n * @param hasAsset Whether the library being validated holds `kind:name`.\n * @param libraryPublisher The library's publisher, when known; refs naming another\n * publisher are skipped.\n * @returns One finding per unresolved ref, to print as warnings.\n */\nexport function agentComposeRefAdvisories(\n parsed: Record<string, unknown>,\n hasAsset: (kind: string, name: string) => boolean,\n libraryPublisher: string | undefined,\n): AssetFinding[] {\n const out: AssetFinding[] = [];\n records(parsed.composes).forEach((item, i) => {\n if (typeof item.kind !== \"string\" || typeof item.ref !== \"string\") return;\n const target = composeRefTarget({ kind: item.kind, ref: item.ref });\n if (target?.type !== \"asset\" || target.kind === \"soul\") return;\n if (\n target.publisher !== undefined &&\n libraryPublisher !== undefined &&\n target.publisher !== libraryPublisher\n ) {\n return;\n }\n if (target.publisher !== undefined && libraryPublisher === undefined) return;\n if (hasAsset(target.kind, target.name)) return;\n out.push({\n tag: \"agent\",\n text: `composes[${i}].ref: ${item.ref} is not in this library; \\`skaile add\\` fails with \"requires … not found\" unless the asset is published elsewhere`,\n conformance: false,\n });\n });\n return out;\n}\n","/**\n * Per-asset checks shared by `skaile validate`, `skaile library index` and the\n * `library publish` plan, so all three give the same verdict for the same asset\n * file: {@link checkAsset} returns the errors (semver, kind schema, flow\n * definition) and the advisories (agentskills.io conformance, untouched scaffold).\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n ASSET_NAME_HINT,\n checkAgentSkillConformance,\n isValidAssetName,\n parseAssetRef,\n parseFrontmatter,\n} from \"@skaile/workspaces/core\";\nimport { parseManifestFile, SEMVER_RE } from \"@skaile/workspaces/discovery\";\nimport { parseFlowDefinition } from \"@skaile/workspaces/factory-assets/connectors/flow/contract\";\nimport type { IAssetKindRegistry } from \"@skaile/workspaces/plugins\";\nimport { checkAgentFiles } from \"./agent-checks.ts\";\nimport {\n AGENT_BODY_PLACEHOLDER,\n CONTRACT_BODY_PLACEHOLDER,\n PRESET_DESCRIPTION_PLACEHOLDER,\n PRESET_ITEM_PLACEHOLDER_REF,\n PROMPT_BODY_PLACEHOLDER,\n SKILL_BODY_PLACEHOLDER,\n SKILL_DESCRIPTION_PLACEHOLDER_PREFIX,\n} from \"@skaile/workspaces/types/manifests\";\n\n/** One advisory finding, printed as `<file> [<tag>] — <text>`. */\nexport interface AssetFinding {\n /** `skill conformance` for agentskills.io findings, else the asset kind. */\n tag: string;\n text: string;\n /** `true` for an agentskills.io conformance finding (`--strict-conformance` escalates these). */\n conformance: boolean;\n /** `true` for the untouched `library create` body: an error in `validate` and the publish plan, a warning in `library index`. */\n scaffoldBody?: true;\n}\n\n/** The body `library create` writes per markdown kind (the skill wording is the legacy fallback). */\nconst BODY_PLACEHOLDER_BY_KIND: Record<string, string> = {\n skill: SKILL_BODY_PLACEHOLDER,\n agent: AGENT_BODY_PLACEHOLDER,\n prompt: PROMPT_BODY_PLACEHOLDER,\n contract: CONTRACT_BODY_PLACEHOLDER,\n};\n\n/** Kinds whose `library create` scaffold is `---frontmatter--- + # <name> + placeholder body`. */\nconst MARKDOWN_SCAFFOLD_KINDS: Record<string, true> = {\n skill: true,\n agent: true,\n prompt: true,\n contract: true,\n};\n\n/** The `description:` `library create flow` writes when `--description` is omitted. */\nconst FLOW_DESCRIPTION_PLACEHOLDER = \"Flow description\";\n\n/**\n * Run the advisory checks for one parsed asset manifest: agentskills.io conformance\n * (skills only) and the untouched `library create` body (skill, agent, prompt, contract).\n * The flow and preset scaffolds are errors, see {@link checkAsset}. Other kinds yield no findings.\n *\n * @param kind Asset kind of the manifest.\n * @param parsed Parsed manifest (frontmatter for markdown kinds, the document for YAML).\n * @param body The markdown body after the frontmatter (`undefined` for YAML kinds).\n * @param dirName The manifest's parent folder name (enables the skill name==dir rule).\n */\nexport function checkAssetManifest(\n kind: string,\n parsed: Record<string, unknown>,\n body: string | undefined,\n dirName: string,\n): AssetFinding[] {\n const out: AssetFinding[] = [];\n if (kind === \"skill\") {\n for (const f of checkAgentSkillConformance(parsed, { dirName })) {\n out.push({ tag: \"skill conformance\", text: `${f.field}: ${f.message}`, conformance: true });\n }\n }\n if (MARKDOWN_SCAFFOLD_KINDS[kind]) {\n // `library create` writes a placeholder body under a `# <name>` heading;\n // shipping it untouched is never intended.\n const bodyText = body?.replace(/^#[^\\n]*\\n+/, \"\");\n // A prompt, contract or agent scaffolded by an older CLI carries the skill wording; it is\n // the same untouched scaffold.\n const isPlaceholder =\n bodyText === SKILL_BODY_PLACEHOLDER || bodyText === BODY_PLACEHOLDER_BY_KIND[kind];\n if (isPlaceholder) {\n const noun = kind === \"skill\" ? \"skill prompt\" : kind;\n out.push({\n tag: kind,\n text: `body is still the scaffold placeholder; write the ${noun}`,\n conformance: false,\n scaffoldBody: true,\n });\n }\n }\n return out;\n}\n\n/** The version `library index` records for a parsed manifest: top-level `version`, else `metadata.version`. */\nexport function declaredVersion(parsed: Record<string, unknown>): string | undefined {\n const scalar = (v: unknown): string | undefined =>\n typeof v === \"string\" ? v : typeof v === \"number\" ? String(v) : undefined;\n const meta = parsed.metadata;\n const nested =\n meta !== null && typeof meta === \"object\"\n ? scalar((meta as Record<string, unknown>).version)\n : undefined;\n return scalar(parsed.version) ?? nested;\n}\n\n/** The refusal text for a version that is not semver, `undefined` when it is. */\nexport function invalidSemverText(version: string): string | undefined {\n return SEMVER_RE.test(version) ? undefined : `version \"${version}\" is not valid semver`;\n}\n\n/**\n * The version scalar exactly as written in the manifest text (`1.0`, not the `1` yaml reads),\n * `undefined` when the text has no `version:` line. Markdown manifests are searched in their\n * frontmatter only.\n */\nfunction rawVersionScalar(text: string): string | undefined {\n const front = text.startsWith(\"---\") ? (text.split(/\\n---/, 1)[0] ?? text) : text;\n const m = /^[ \\t]*version:[ \\t]*([^\\s#][^#\\n]*?)[ \\t]*(?:#.*)?$/m.exec(front);\n return m?.[1];\n}\n\n/**\n * The refusal for a manifest version that is not semver: {@link invalidSemverText}, and for a yaml\n * number (`version: 1.0` is read as the number 1) the scalar as written plus the quoted fix.\n * `undefined` when the version is absent or valid.\n *\n * @param parsed Parsed manifest.\n * @param rawText The manifest file text, to show the scalar the author wrote.\n */\nexport function versionProblemText(\n parsed: Record<string, unknown>,\n rawText?: string,\n): string | undefined {\n const version = declaredVersion(parsed);\n const text = version === undefined ? undefined : invalidSemverText(version);\n if (text === undefined) return undefined;\n const meta = parsed.metadata;\n const nested =\n meta !== null && typeof meta === \"object\"\n ? (meta as Record<string, unknown>).version\n : undefined;\n const key =\n parsed.version === undefined || parsed.version === null ? \"metadata.version\" : \"version\";\n const written = key === \"version\" ? parsed.version : nested;\n if (typeof written !== \"number\") return text;\n const raw = (rawText === undefined ? undefined : rawVersionScalar(rawText)) ?? String(written);\n // `1` → `1.0.0`, `1.5` → `1.5.0`: the number the author meant, in three parts.\n const fix = /^\\d+(\\.\\d+)?$/.test(raw)\n ? `${raw}${raw.includes(\".\") ? \"\" : \".0\"}.0`\n : DEFAULT_VERSION;\n return `version ${raw} is not valid semver: yaml reads an unquoted number as a number, not a string. Write it quoted with three parts: ${key}: \"${fix}\"`;\n}\n\n/**\n * The refusal for a directory that holds a kind + name another directory already holds.\n * `library index` and the publish plan print it, so both name the directory and the fix alike.\n *\n * @param dir The duplicate directory, relative to the library root.\n * @param detail Why it is a duplicate, e.g. `already registered at \"fun/skills/x\"`.\n * @param library The registered library name, for the re-run hint.\n */\nexport function duplicateAssetMessage(\n kind: string,\n name: string,\n dir: string,\n detail: string,\n library: string,\n): string {\n return `${kind}:${name} found in ${dir} but ${detail}. Rename or delete one of the two directories, then re-run \\`skaile library index ${library}\\`.`;\n}\n\n/** Result of {@link checkAsset}: what fails the asset, and what only warns. */\nexport interface AssetCheckResult {\n /** Findings that fail `validate`, make `library index` exit 1 and the publish plan refuse the asset. */\n errors: AssetFinding[];\n /** Advisories ({@link checkAssetManifest}): printed as warnings, exit code unchanged. */\n advisories: AssetFinding[];\n}\n\n/** The version a manifest without one is read at: the default `library index` records. */\nconst DEFAULT_VERSION = \"0.1.0\";\n\n/** The kinds `library create` scaffolds; a missing version and an empty `metadata:` are handled alike for all. */\nconst SCAFFOLD_KINDS: Record<string, true> = {\n skill: true,\n agent: true,\n prompt: true,\n contract: true,\n flow: true,\n preset: true,\n};\n\n/**\n * The manifest the kind schema and the flow parser see: a missing version reads as\n * {@link DEFAULT_VERSION} and an empty `metadata:` as absent, for every scaffolded kind, so no\n * kind refuses what another accepts.\n */\nfunction withManifestDefaults(\n kind: string,\n parsed: Record<string, unknown>,\n): Record<string, unknown> {\n if (!SCAFFOLD_KINDS[kind]) return parsed;\n const out = { ...parsed };\n if (out.metadata === null) delete out.metadata;\n // Only an absent version is defaulted; a present but wrong one (an object, a list) stays an error.\n const meta = out.metadata;\n const nested =\n typeof meta === \"object\" && meta !== null && \"version\" in meta ? meta.version : undefined;\n if (out.version == null && nested == null) out.version = DEFAULT_VERSION;\n return out;\n}\n\n/**\n * The refusal for a flow whose `id:` differs from its file name. A flow asset is named by its `id:`,\n * and the flow engine loads a deployed flow only from `<id>/<id>.flow.yaml` (or `.flow.yml` /\n * `.flow.json`), so a mismatch indexes fine but can never run. `undefined` when they agree, the\n * id is absent (the schema owns that) or the file name is unknown.\n */\nexport function flowFileNameError(\n parsed: Record<string, unknown>,\n fileName: string | undefined,\n): string | undefined {\n const id = parsed.id;\n if (fileName === undefined || typeof id !== \"string\" || id.length === 0) return undefined;\n const stem = fileName.replace(/\\.flow\\.(yaml|yml|json)$/, \"\");\n if (stem === fileName || stem === id) return undefined;\n return `flow id \"${id}\" does not match the file name \"${fileName}\"; a flow asset is named by its id and the flow engine loads it only from \"${id}.flow.yaml\". Rename the file to \"${id}.flow.yaml\" or set id: ${stem}`;\n}\n\n/**\n * The refusal for an asset name or id that breaks the canonical rule (lowercase kebab-case,\n * at most 64 characters), `undefined` when the identity is absent (the schema owns that) or valid.\n * An explicit `publisher:` in the manifest is checked as part of the ref it forms.\n */\nexport function manifestIdentityError(\n kind: string,\n parsed: Record<string, unknown>,\n): string | undefined {\n const identity = kind === \"flow\" ? parsed.id : parsed.name;\n if (typeof identity !== \"string\" || identity.length === 0) return undefined;\n\n const publisher = typeof parsed.publisher === \"string\" ? parsed.publisher : undefined;\n if (publisher !== undefined) {\n try {\n parseAssetRef(`${kind}:@${publisher}/${identity}`);\n return undefined;\n } catch (e) {\n return e instanceof Error ? e.message : String(e);\n }\n }\n if (!isValidAssetName(identity)) {\n return `invalid asset ${kind === \"flow\" ? \"id\" : \"name\"} \"${identity}\" — ${ASSET_NAME_HINT}`;\n }\n return undefined;\n}\n\n/**\n * The untouched `library create flow` / `library create preset` content: a flow with no nodes\n * and the example preset item can never be consumed, so they fail like the `TODO:` description\n * of every other kind. Also matches the generic descriptions older releases scaffolded.\n */\nfunction scaffoldDefinitionErrors(kind: string, parsed: Record<string, unknown>): string[] {\n const out: string[] = [];\n if (kind === \"flow\") {\n if (parsed.description === FLOW_DESCRIPTION_PLACEHOLDER) {\n out.push(\"description is still the scaffold placeholder; say what the flow does\");\n }\n if (parsed.nodes === undefined) {\n out.push(\"nodes is missing; a flow needs at least one node\");\n } else if (Array.isArray(parsed.nodes) && parsed.nodes.length === 0) {\n out.push(\"nodes is still the scaffold placeholder (nodes: []); add the flow's nodes\");\n }\n }\n if (kind === \"preset\") {\n if (parsed.description === PRESET_DESCRIPTION_PLACEHOLDER) {\n out.push(\n `description is still the scaffold placeholder (\"${PRESET_DESCRIPTION_PLACEHOLDER}\"); say what the preset does`,\n );\n }\n const items = Array.isArray(parsed.items) ? parsed.items : [];\n const placeholderItem = items.some((item) => {\n const ref = typeof item === \"string\" ? item : (item as { ref?: unknown } | null)?.ref;\n return typeof ref === \"string\" && ref.trim() === PRESET_ITEM_PLACEHOLDER_REF;\n });\n if (placeholderItem) {\n out.push(\n `item ${PRESET_ITEM_PLACEHOLDER_REF} is still the scaffold placeholder; replace it with the preset's real items`,\n );\n }\n }\n return out;\n}\n\n/**\n * The one per-asset check list behind `skaile validate`, `skaile library index`\n * and `skaile library publish`. Errors: an asset name that is not canonical (kebab-case,\n * at most 64 characters), a declared version that is not semver, the kind's manifest schema,\n * a `TODO:` scaffold description (every kind; the skill schema already refuses it), the\n * untouched flow/preset scaffold, and for flows the flow engine's own definition parser —\n * a flow the engine cannot load is no flow. A missing version reads as 0.1.0 and an empty\n * `metadata:` as absent for every scaffolded kind. Advisories (the untouched `library create` body,\n * agentskills.io conformance): {@link checkAssetManifest}.\n *\n * @param kind Asset kind of the manifest.\n * @param parsed Parsed manifest (frontmatter for markdown kinds, the document for YAML).\n * @param body The markdown body after the frontmatter (`undefined` for YAML kinds).\n * @param dirName The manifest's parent folder name (enables the skill name==dir rule).\n * @param registry The kind registry that owns each kind's manifest schema.\n * @param rawText The manifest file text, to show a yaml-number version as the author wrote it.\n * @param fileName Base name of the manifest file; a flow's `id:` must match its stem (p670).\n */\nexport function checkAsset(\n kind: string,\n parsed: Record<string, unknown>,\n body: string | undefined,\n dirName: string,\n registry: IAssetKindRegistry,\n rawText?: string,\n fileName?: string,\n): AssetCheckResult {\n const errors: AssetFinding[] = [];\n const error = (text: string): void => {\n errors.push({ tag: kind, text, conformance: false });\n };\n\n const identity = manifestIdentityError(kind, parsed);\n if (identity) error(identity);\n const flowFileError = kind === \"flow\" ? flowFileNameError(parsed, fileName) : undefined;\n if (flowFileError) error(flowFileError);\n\n const semver = versionProblemText(parsed, rawText);\n if (semver) error(semver);\n\n const effective = withManifestDefaults(kind, parsed);\n // A markdown kind carries its version in the `metadata:` block, every other kind at the top level.\n const versionKey = [\"skill\", \"prompt\", \"contract\"].includes(kind)\n ? \"metadata.version\"\n : \"version\";\n const provider = registry.getProvider(kind);\n if (!provider) {\n error(`unknown_asset_kind: kind \"${kind}\" is not registered`);\n } else {\n const result = provider.validateManifest(effective);\n if (!result.ok) {\n for (const e of result.errors) {\n if (e.path === \"version\" || e.path === \"metadata.version\") {\n // The semver text above already names a version that is present but wrong.\n if (!semver) {\n error(`${e.path}: must be a semver string — set ${versionKey}: ${DEFAULT_VERSION}`);\n }\n continue;\n }\n error(`${e.path ? `${e.path}: ` : \"\"}${e.message}`);\n }\n }\n }\n\n // The skill schema refuses the scaffold description itself; every other kind says so here,\n // in the same words, so no kind ships `TODO: describe this …`.\n const description = parsed.description;\n if (\n kind !== \"skill\" &&\n typeof description === \"string\" &&\n description.trim().startsWith(SKILL_DESCRIPTION_PLACEHOLDER_PREFIX)\n ) {\n error(\n `description: description is still the scaffold placeholder (${SKILL_DESCRIPTION_PLACEHOLDER_PREFIX} …) — say what the ${kind} does and when to use it`,\n );\n }\n for (const text of scaffoldDefinitionErrors(kind, parsed)) error(text);\n\n if (kind === \"flow\") {\n const flow = parseFlowDefinition(effective);\n if (!flow.ok) {\n for (const e of flow.errors) {\n error(`invalid flow definition: ${e.path || \"<root>\"}: ${e.message}`);\n }\n }\n }\n\n // The untouched `library create` body is flagged as an advisory carrying `scaffoldBody`: an error\n // in `validate` and the publish plan (a passing `validate` means the asset can be published), a\n // warning in `library index` (the local dev loop) that says publish refuses it (p675).\n return { errors, advisories: checkAssetManifest(kind, parsed, body, dirName) };\n}\n\n/**\n * Locate the manifest file of a first-party asset inside its `root` directory:\n * `SKILL.md`, `agent.yaml` / `AGENT.md`, `CONTRACT.md`, `<name>.prompt.md`,\n * `<name>.flow.yaml` / `.flow.json` or `<name>.preset.yaml`. `null` when none exists.\n */\nexport function findAssetManifestFile(dir: string, kind: string, name: string): string | null {\n const candidates: string[] = [];\n if (kind === \"skill\") candidates.push(\"SKILL.md\");\n else if (kind === \"agent\") candidates.push(\"agent.yaml\", \"AGENT.md\");\n else if (kind === \"contract\") candidates.push(\"CONTRACT.md\");\n else if (kind === \"prompt\") candidates.push(`${name}.prompt.md`);\n else if (kind === \"flow\") candidates.push(`${name}.flow.yaml`, `${name}.flow.json`);\n else if (kind === \"preset\") candidates.push(`${name}.preset.yaml`);\n for (const c of candidates) {\n const file = path.join(dir, c);\n if (fs.existsSync(file)) return file;\n }\n // A single prompt/flow/preset file whose name differs from the entry name.\n const suffix =\n kind === \"prompt\"\n ? \".prompt.md\"\n : kind === \"flow\"\n ? \".flow.yaml\"\n : kind === \"preset\"\n ? \".preset.yaml\"\n : null;\n if (suffix && fs.existsSync(dir)) {\n const matches = fs.readdirSync(dir).filter((f) => f.endsWith(suffix));\n if (matches.length === 1) return path.join(dir, matches[0]);\n }\n return null;\n}\n\n/**\n * The prompt text of a manifest file, as {@link checkAssetManifest} wants it: the\n * markdown body of a `.md` marker (`SKILL.md`, `AGENT.md`, …), the `SOUL.md` next to\n * an `agent.yaml` agent, `undefined` for every other YAML manifest.\n *\n * @param file Absolute path of the manifest file.\n * @param text The file's content.\n */\nexport function readAssetBody(file: string, text: string): string | undefined {\n if (file.endsWith(\".md\")) return parseFrontmatter(text).body;\n if (path.basename(file) !== \"agent.yaml\") return undefined;\n const soul = path.join(path.dirname(file), \"SOUL.md\");\n return fs.existsSync(soul) ? fs.readFileSync(soul, \"utf8\").trim() : undefined;\n}\n\n/**\n * The {@link checkAsset} errors of one manifest file on disk — what `library index`\n * asks of each asset before it writes it into the manifest. A file that cannot be\n * read or parsed yields none: the parse failure is reported by whoever owns it.\n *\n * @param file Absolute path of the manifest file.\n * @param kind Asset kind of the manifest.\n * @param registry The kind registry that owns each kind's manifest schema.\n * @param libraryRoot The library holding the asset; an agent's local files are checked against it.\n * @param onScaffoldBody Called when the body is still the untouched `library create` scaffold: for\n * `library index` a warning, not an error (`validate` and the publish plan fail it).\n */\nexport function checkAssetFile(\n file: string,\n kind: string,\n registry: IAssetKindRegistry,\n libraryRoot?: string,\n onScaffoldBody?: (finding: AssetFinding) => void,\n): AssetFinding[] {\n let text: string;\n try {\n text = fs.readFileSync(file, \"utf8\");\n } catch {\n return [];\n }\n const res = parseManifestFile(file, text);\n if (!res.ok) return [];\n const checked = checkAsset(\n kind,\n res.data,\n readAssetBody(file, text),\n path.basename(path.dirname(file)),\n registry,\n text,\n path.basename(file),\n );\n const errors = checked.errors;\n if (onScaffoldBody) {\n for (const f of checked.advisories) if (f.scaffoldBody) onScaffoldBody(f);\n }\n if (kind === \"agent\" && libraryRoot !== undefined) {\n errors.push(...checkAgentFiles(res.data, path.dirname(file), libraryRoot));\n }\n return errors;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { compositeSha256 } from './chunk-
|
|
2
|
-
import { parseAssetRef } from './chunk-
|
|
1
|
+
import { compositeSha256 } from './chunk-IY5E7Y5W.js';
|
|
2
|
+
import { parseAssetRef } from './chunk-J4OYIYFQ.js';
|
|
3
3
|
import { createHash } from 'crypto';
|
|
4
4
|
import { rm, mkdir, writeFile } from 'fs/promises';
|
|
5
5
|
import { isAbsolute, resolve, sep, join, dirname } from 'path';
|
|
@@ -123,5 +123,5 @@ async function installFlat(manifest, targetDir, fetcher) {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
export { assertSafeManifestPath, installFromManifest, longestCommonDirPrefix };
|
|
126
|
-
//# sourceMappingURL=chunk-
|
|
127
|
-
//# sourceMappingURL=chunk-
|
|
126
|
+
//# sourceMappingURL=chunk-PXDWTJ3P.js.map
|
|
127
|
+
//# sourceMappingURL=chunk-PXDWTJ3P.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../library/src/install/install-from-manifest.ts"],"names":[],"mappings":"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","file":"chunk-UTKENBB6.js","sourcesContent":["/**\n * Pointer-only install path.\n *\n * Given an {@link InstallManifest} (the Pointer Triple the Catalog hands\n * clients), this:\n *\n * 1. fetches the asset bytes directly from the upstream repo at the pinned\n * commit (via an injectable fetcher, default {@link fetchAssetFilesFromGitHub});\n * 2. verifies EVERY per-file SHA256 against `manifest.files[].sha256`;\n * 3. verifies the composite SHA256 rollup over the sorted\n * `<path>:<sha256>\\n` lines against `manifest.sha256`;\n * 4. writes the verified bytes under `<libraryRoot>/@<publisher>/<name>/<version>`.\n *\n * Any hash mismatch is a hard failure — bytes are not written if per-file\n * verification fails, and the composite check is the second gate.\n *\n * @docLink packages/library/concepts#install\n */\n\nimport { createHash } from \"node:crypto\";\nimport { mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve, sep } from \"node:path\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\n// Narrow module, not the `core` barrel: the barrel's chunks carry `import.meta`,\n// which breaks consumers that transpile this entry to CommonJS.\nimport { parseAssetRef } from \"../../../core/src/models.js\";\nimport { compositeSha256 } from \"../../../core/src/publish-manifest.js\";\n\n/**\n * Validate a single manifest-supplied file path against path traversal.\n *\n * `manifest.files[].path` comes off the network — the attacker controls the\n * entire manifest (and therefore every hash in it), so hash verification can\n * NEVER mitigate a malicious *destination*. A path like\n * `../../../../home/user/.bashrc` or an absolute path would escape\n * `installPath` and yield an arbitrary file write. Every path is checked\n * BEFORE any fetch or write happens; the first bad path aborts the entire\n * install with a hard throw.\n *\n * A path is rejected if ANY of:\n * - it is empty;\n * - it is absolute (`path.isAbsolute`) or has a leading slash;\n * - it contains a `..` segment;\n * - `path.resolve(installPath, p)` is not `installPath` itself and does not\n * start with `installPath + path.sep` (escapes the install dir).\n *\n * @throws An error matching `/unsafe path in manifest/` on the first bad path.\n */\nexport function assertSafeManifestPath(installPath: string, p: string): void {\n const bad = (): never => {\n throw new Error(`unsafe path in manifest: ${p}`);\n };\n if (!p || p.length === 0) bad();\n if (isAbsolute(p) || p.startsWith(\"/\") || p.startsWith(\"\\\\\")) bad();\n const segments = p.split(/[/\\\\]/);\n if (segments.some((s) => s === \"..\")) bad();\n const resolved = resolve(installPath, p);\n if (resolved !== installPath && !resolved.startsWith(installPath + sep)) bad();\n}\n\n/**\n * Validate one component (publisher / name / version) of the attacker-controlled\n * `manifest.ref`.\n *\n * `installPath` is built by joining these components onto `libraryRoot`. A\n * component containing a path separator or a `..` / leading-dot segment would\n * let `installPath` itself escape `libraryRoot` — yielding an arbitrary file\n * write AND, via the pre-write `rm(installPath, { recursive })`, an arbitrary\n * recursive delete. The per-file `assertSafeManifestPath` guard cannot catch\n * this: it only validates each `f.path` *relative to* `installPath`, never\n * `installPath` itself. Components must be plain identifier-like strings.\n *\n * @throws An error matching `/unsafe ref/` on a bad component.\n */\nfunction assertSafeRefComponent(kind: string, value: string): void {\n // Reject empty, leading-dot (covers `.` and `..`), path separators, and\n // ASCII control characters (NUL et al.) — fails a malformed segment fast\n // with a domain-specific error rather than a raw EINVAL deeper in.\n const hasControlChar = [...value].some((c) => c.charCodeAt(0) < 0x20);\n if (!value || value.startsWith(\".\") || /[/\\\\]/.test(value) || hasControlChar) {\n throw new Error(`unsafe ref ${kind} component in manifest: '${value}'`);\n }\n}\n\n/**\n * Longest common **directory** prefix across manifest paths, compared by whole\n * slash-delimited segments (never raw-string — so `app/` and `app-data/` never\n * collide). Each path's basename is excluded, so the result is always a\n * directory prefix and every path keeps a non-empty remainder after stripping.\n *\n * Used by flat mode to reproduce the platform pointer-installer's asset-rooting:\n * the store persists repo-root-relative paths (e.g. `skaile-platform/mcpo/xls/MCP.md`)\n * but the runner scans `.skaile/assets/<kind>/<name>/` for immediate-child files,\n * so this prefix is stripped from the WRITE path while the fetch keeps the full\n * repo path. Returns `''` when there is no common directory (a no-op strip).\n */\nexport function longestCommonDirPrefix(paths: readonly string[]): string {\n if (paths.length === 0) return \"\";\n const dirSegments = paths.map((p) => p.split(\"/\").slice(0, -1));\n let common = dirSegments[0]!;\n for (let i = 1; i < dirSegments.length && common.length > 0; i++) {\n const segs = dirSegments[i]!;\n let n = 0;\n while (n < common.length && n < segs.length && common[n] === segs[n]) n++;\n common = common.slice(0, n);\n }\n return common.join(\"/\");\n}\n\n/**\n * Fetcher signature — fetches `{ path → Buffer }` for the requested paths at\n * a pinned upstream commit. {@link fetchAssetFilesFromGitHub} is the default\n * production implementation; tests inject a mock.\n */\nexport type AssetFetcher = (opts: {\n url: string;\n commitSha: string;\n paths: string[];\n}) => Promise<Record<string, Buffer>>;\n\n/**\n * Options for {@link installFromManifest}.\n */\nexport interface InstallOpts {\n /** The pointer-only install manifest from the Catalog. */\n manifest: InstallManifest;\n /** Filesystem root the asset is installed under (ref-derived mode). */\n libraryRoot: string;\n /**\n * Pluggable fetcher so tests can inject mock data. Defaults to\n * {@link fetchAssetFilesFromGitHub} in production.\n */\n fetcher?: AssetFetcher;\n /**\n * Flat-layout mode. When set, install-core reproduces the platform\n * pointer-installer's behavior: it ignores `libraryRoot`/ref-derivation, does\n * NOT parse `manifest.ref` and does NOT verify the composite sha256, strips\n * the longest-common-dir prefix from each path, per-file sha256-verifies, and\n * writes the stripped paths as immediate children of `targetDir` (what the\n * runner's `.skaile/assets/<kind>/<name>/` scan requires). `installPath` is\n * `targetDir`. Absent → unchanged ref-derived `@<pub>/name/version/<path>`\n * layout with composite verify.\n */\n targetDir?: string;\n}\n\n/**\n * Result of a successful {@link installFromManifest} call.\n */\nexport interface InstallResult {\n /** Absolute path the asset files were written to. */\n installPath: string;\n}\n\n/**\n * Fetch, verify, and write an asset's files per its {@link InstallManifest}.\n *\n * @throws An error matching `/hash mismatch/i` if any per-file SHA256 differs.\n * @throws An error matching `/composite hash mismatch/i` if the rollup differs.\n * @throws An error if the ref is malformed or the fetcher omits a file.\n */\nexport async function installFromManifest(opts: InstallOpts): Promise<InstallResult> {\n const { manifest, libraryRoot } = opts;\n const fetcher =\n opts.fetcher ?? (await import(\"./source-fetch-github.js\")).fetchAssetFilesFromGitHub;\n\n // Flat mode: reproduce the platform pointer-installer's asset-rooted layout.\n // No ref parse, no composite verify — the platform store may not satisfy a\n // ref-grammar or composite, and the runner only needs immediate-child files.\n if (opts.targetDir !== undefined) {\n return installFlat(manifest, opts.targetDir, fetcher);\n }\n\n // 1. Parse ref into install path: `skill:@x/git#1.0.0` → `<root>/@x/git/1.0.0`.\n // Done first so the C1 path-traversal guard can resolve against installPath\n // BEFORE any network fetch happens. The ref is attacker-controlled, so each\n // segment is further validated as a safe path component (H1) after parsing.\n // `parseAssetRef` is the single canonical grammar (`kind:@publisher/name#version`);\n // the legacy trailing-`@version` shape was removed in core and is rejected here.\n let parsed: ReturnType<typeof parseAssetRef>;\n try {\n parsed = parseAssetRef(manifest.ref);\n } catch (e) {\n throw new Error(`invalid ref: ${manifest.ref}: ${e instanceof Error ? e.message : String(e)}`);\n }\n const publisher = parsed.publisher;\n const name = parsed.name;\n const version = parsed.pin;\n if (!publisher) throw new Error(`invalid ref: ${manifest.ref} (missing publisher)`);\n if (!version) throw new Error(`invalid ref: ${manifest.ref} (missing version pin)`);\n assertSafeRefComponent(\"publisher\", publisher);\n assertSafeRefComponent(\"name\", name);\n assertSafeRefComponent(\"version\", version);\n const root = resolve(libraryRoot);\n const installPath = resolve(join(root, `@${publisher}`, name, version));\n // Defense in depth: even with the segment guards above, assert the built\n // installPath stays strictly inside libraryRoot before any write or `rm`.\n if (installPath !== root && !installPath.startsWith(root + sep)) {\n throw new Error(`unsafe install path: ref '${manifest.ref}' resolves outside the library root`);\n }\n\n // 2. [C1] Validate EVERY manifest path against traversal BEFORE fetching.\n // The attacker controls the manifest (and thus all hashes) — hashes verify\n // content, never destination. Reject the whole install on the first bad path.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n }\n\n // 3. Fetch all files at the pinned commit.\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // 4. Verify per-file SHA256 — hard fail before writing anything. The path\n // key used to read from the fetcher result is re-guarded as defense in depth.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n }\n\n // 5. Verify composite SHA256 over the sorted `<path>:<sha256>\\n` lines.\n const actualComposite = compositeSha256(manifest.files);\n if (actualComposite !== manifest.sha256) {\n throw new Error(`composite hash mismatch: expected ${manifest.sha256}, got ${actualComposite}`);\n }\n\n // 6. [M1] Write all verified files. A failed install must leave NO partial\n // directory: any prior `installPath` is removed first (clean overwrite), and\n // a mid-loop write failure removes the partially-written tree before\n // rethrowing.\n await rm(installPath, { recursive: true, force: true });\n try {\n for (const f of manifest.files) {\n const target = join(installPath, f.path);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, bytes[f.path]!);\n }\n } catch (e) {\n await rm(installPath, { recursive: true, force: true }).catch(() => {});\n throw e;\n }\n\n return { installPath };\n}\n\n/**\n * Flat-layout install — the platform pointer-installer's behavior, made canonical\n * in install-core. Validates every path, fetches with the FULL repo paths, per-file\n * sha256-verifies, then strips the longest-common-dir prefix and writes each file\n * as `join(targetDir, path.slice(assetRoot.length + 1))` — immediate children of\n * `targetDir`. No ref parse, no composite check.\n */\nasync function installFlat(\n manifest: InstallManifest,\n targetDir: string,\n fetcher: AssetFetcher,\n): Promise<InstallResult> {\n const target = resolve(targetDir);\n\n // Gate every path before any fetch — the attacker controls the whole manifest.\n for (const f of manifest.files) {\n assertSafeManifestPath(target, f.path);\n }\n\n // Fetch keys off the FULL repo path (matches the upstream tree).\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // Strip the asset-root dir prefix from the WRITE path only — the fetch above\n // still keyed off the full repo path. Stripping removes leading whole segments\n // (never the basename), so a non-empty remainder always survives.\n const assetRoot = longestCommonDirPrefix(paths);\n\n for (const f of manifest.files) {\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n const relPath = assetRoot ? f.path.slice(assetRoot.length + 1) : f.path;\n // Re-guard the post-strip destination — it is what we actually write.\n assertSafeManifestPath(target, relPath);\n const dest = join(target, relPath);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, buf);\n }\n\n return { installPath: target };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../library/src/install/install-from-manifest.ts"],"names":[],"mappings":"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","file":"chunk-PXDWTJ3P.js","sourcesContent":["/**\n * Pointer-only install path.\n *\n * Given an {@link InstallManifest} (the Pointer Triple the Catalog hands\n * clients), this:\n *\n * 1. fetches the asset bytes directly from the upstream repo at the pinned\n * commit (via an injectable fetcher, default {@link fetchAssetFilesFromGitHub});\n * 2. verifies EVERY per-file SHA256 against `manifest.files[].sha256`;\n * 3. verifies the composite SHA256 rollup over the sorted\n * `<path>:<sha256>\\n` lines against `manifest.sha256`;\n * 4. writes the verified bytes under `<libraryRoot>/@<publisher>/<name>/<version>`.\n *\n * Any hash mismatch is a hard failure — bytes are not written if per-file\n * verification fails, and the composite check is the second gate.\n *\n * @docLink packages/library/concepts#install\n */\n\nimport { createHash } from \"node:crypto\";\nimport { mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve, sep } from \"node:path\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\n// Narrow module, not the `core` barrel: the barrel's chunks carry `import.meta`,\n// which breaks consumers that transpile this entry to CommonJS.\nimport { parseAssetRef } from \"../../../core/src/models.js\";\nimport { compositeSha256 } from \"../../../core/src/publish-manifest.js\";\n\n/**\n * Validate a single manifest-supplied file path against path traversal.\n *\n * `manifest.files[].path` comes off the network — the attacker controls the\n * entire manifest (and therefore every hash in it), so hash verification can\n * NEVER mitigate a malicious *destination*. A path like\n * `../../../../home/user/.bashrc` or an absolute path would escape\n * `installPath` and yield an arbitrary file write. Every path is checked\n * BEFORE any fetch or write happens; the first bad path aborts the entire\n * install with a hard throw.\n *\n * A path is rejected if ANY of:\n * - it is empty;\n * - it is absolute (`path.isAbsolute`) or has a leading slash;\n * - it contains a `..` segment;\n * - `path.resolve(installPath, p)` is not `installPath` itself and does not\n * start with `installPath + path.sep` (escapes the install dir).\n *\n * @throws An error matching `/unsafe path in manifest/` on the first bad path.\n */\nexport function assertSafeManifestPath(installPath: string, p: string): void {\n const bad = (): never => {\n throw new Error(`unsafe path in manifest: ${p}`);\n };\n if (!p || p.length === 0) bad();\n if (isAbsolute(p) || p.startsWith(\"/\") || p.startsWith(\"\\\\\")) bad();\n const segments = p.split(/[/\\\\]/);\n if (segments.some((s) => s === \"..\")) bad();\n const resolved = resolve(installPath, p);\n if (resolved !== installPath && !resolved.startsWith(installPath + sep)) bad();\n}\n\n/**\n * Validate one component (publisher / name / version) of the attacker-controlled\n * `manifest.ref`.\n *\n * `installPath` is built by joining these components onto `libraryRoot`. A\n * component containing a path separator or a `..` / leading-dot segment would\n * let `installPath` itself escape `libraryRoot` — yielding an arbitrary file\n * write AND, via the pre-write `rm(installPath, { recursive })`, an arbitrary\n * recursive delete. The per-file `assertSafeManifestPath` guard cannot catch\n * this: it only validates each `f.path` *relative to* `installPath`, never\n * `installPath` itself. Components must be plain identifier-like strings.\n *\n * @throws An error matching `/unsafe ref/` on a bad component.\n */\nfunction assertSafeRefComponent(kind: string, value: string): void {\n // Reject empty, leading-dot (covers `.` and `..`), path separators, and\n // ASCII control characters (NUL et al.) — fails a malformed segment fast\n // with a domain-specific error rather than a raw EINVAL deeper in.\n const hasControlChar = [...value].some((c) => c.charCodeAt(0) < 0x20);\n if (!value || value.startsWith(\".\") || /[/\\\\]/.test(value) || hasControlChar) {\n throw new Error(`unsafe ref ${kind} component in manifest: '${value}'`);\n }\n}\n\n/**\n * Longest common **directory** prefix across manifest paths, compared by whole\n * slash-delimited segments (never raw-string — so `app/` and `app-data/` never\n * collide). Each path's basename is excluded, so the result is always a\n * directory prefix and every path keeps a non-empty remainder after stripping.\n *\n * Used by flat mode to reproduce the platform pointer-installer's asset-rooting:\n * the store persists repo-root-relative paths (e.g. `skaile-platform/mcpo/xls/MCP.md`)\n * but the runner scans `.skaile/assets/<kind>/<name>/` for immediate-child files,\n * so this prefix is stripped from the WRITE path while the fetch keeps the full\n * repo path. Returns `''` when there is no common directory (a no-op strip).\n */\nexport function longestCommonDirPrefix(paths: readonly string[]): string {\n if (paths.length === 0) return \"\";\n const dirSegments = paths.map((p) => p.split(\"/\").slice(0, -1));\n let common = dirSegments[0]!;\n for (let i = 1; i < dirSegments.length && common.length > 0; i++) {\n const segs = dirSegments[i]!;\n let n = 0;\n while (n < common.length && n < segs.length && common[n] === segs[n]) n++;\n common = common.slice(0, n);\n }\n return common.join(\"/\");\n}\n\n/**\n * Fetcher signature — fetches `{ path → Buffer }` for the requested paths at\n * a pinned upstream commit. {@link fetchAssetFilesFromGitHub} is the default\n * production implementation; tests inject a mock.\n */\nexport type AssetFetcher = (opts: {\n url: string;\n commitSha: string;\n paths: string[];\n}) => Promise<Record<string, Buffer>>;\n\n/**\n * Options for {@link installFromManifest}.\n */\nexport interface InstallOpts {\n /** The pointer-only install manifest from the Catalog. */\n manifest: InstallManifest;\n /** Filesystem root the asset is installed under (ref-derived mode). */\n libraryRoot: string;\n /**\n * Pluggable fetcher so tests can inject mock data. Defaults to\n * {@link fetchAssetFilesFromGitHub} in production.\n */\n fetcher?: AssetFetcher;\n /**\n * Flat-layout mode. When set, install-core reproduces the platform\n * pointer-installer's behavior: it ignores `libraryRoot`/ref-derivation, does\n * NOT parse `manifest.ref` and does NOT verify the composite sha256, strips\n * the longest-common-dir prefix from each path, per-file sha256-verifies, and\n * writes the stripped paths as immediate children of `targetDir` (what the\n * runner's `.skaile/assets/<kind>/<name>/` scan requires). `installPath` is\n * `targetDir`. Absent → unchanged ref-derived `@<pub>/name/version/<path>`\n * layout with composite verify.\n */\n targetDir?: string;\n}\n\n/**\n * Result of a successful {@link installFromManifest} call.\n */\nexport interface InstallResult {\n /** Absolute path the asset files were written to. */\n installPath: string;\n}\n\n/**\n * Fetch, verify, and write an asset's files per its {@link InstallManifest}.\n *\n * @throws An error matching `/hash mismatch/i` if any per-file SHA256 differs.\n * @throws An error matching `/composite hash mismatch/i` if the rollup differs.\n * @throws An error if the ref is malformed or the fetcher omits a file.\n */\nexport async function installFromManifest(opts: InstallOpts): Promise<InstallResult> {\n const { manifest, libraryRoot } = opts;\n const fetcher =\n opts.fetcher ?? (await import(\"./source-fetch-github.js\")).fetchAssetFilesFromGitHub;\n\n // Flat mode: reproduce the platform pointer-installer's asset-rooted layout.\n // No ref parse, no composite verify — the platform store may not satisfy a\n // ref-grammar or composite, and the runner only needs immediate-child files.\n if (opts.targetDir !== undefined) {\n return installFlat(manifest, opts.targetDir, fetcher);\n }\n\n // 1. Parse ref into install path: `skill:@x/git#1.0.0` → `<root>/@x/git/1.0.0`.\n // Done first so the C1 path-traversal guard can resolve against installPath\n // BEFORE any network fetch happens. The ref is attacker-controlled, so each\n // segment is further validated as a safe path component (H1) after parsing.\n // `parseAssetRef` is the single canonical grammar (`kind:@publisher/name#version`);\n // the legacy trailing-`@version` shape was removed in core and is rejected here.\n let parsed: ReturnType<typeof parseAssetRef>;\n try {\n parsed = parseAssetRef(manifest.ref);\n } catch (e) {\n throw new Error(`invalid ref: ${manifest.ref}: ${e instanceof Error ? e.message : String(e)}`);\n }\n const publisher = parsed.publisher;\n const name = parsed.name;\n const version = parsed.pin;\n if (!publisher) throw new Error(`invalid ref: ${manifest.ref} (missing publisher)`);\n if (!version) throw new Error(`invalid ref: ${manifest.ref} (missing version pin)`);\n assertSafeRefComponent(\"publisher\", publisher);\n assertSafeRefComponent(\"name\", name);\n assertSafeRefComponent(\"version\", version);\n const root = resolve(libraryRoot);\n const installPath = resolve(join(root, `@${publisher}`, name, version));\n // Defense in depth: even with the segment guards above, assert the built\n // installPath stays strictly inside libraryRoot before any write or `rm`.\n if (installPath !== root && !installPath.startsWith(root + sep)) {\n throw new Error(`unsafe install path: ref '${manifest.ref}' resolves outside the library root`);\n }\n\n // 2. [C1] Validate EVERY manifest path against traversal BEFORE fetching.\n // The attacker controls the manifest (and thus all hashes) — hashes verify\n // content, never destination. Reject the whole install on the first bad path.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n }\n\n // 3. Fetch all files at the pinned commit.\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // 4. Verify per-file SHA256 — hard fail before writing anything. The path\n // key used to read from the fetcher result is re-guarded as defense in depth.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n }\n\n // 5. Verify composite SHA256 over the sorted `<path>:<sha256>\\n` lines.\n const actualComposite = compositeSha256(manifest.files);\n if (actualComposite !== manifest.sha256) {\n throw new Error(`composite hash mismatch: expected ${manifest.sha256}, got ${actualComposite}`);\n }\n\n // 6. [M1] Write all verified files. A failed install must leave NO partial\n // directory: any prior `installPath` is removed first (clean overwrite), and\n // a mid-loop write failure removes the partially-written tree before\n // rethrowing.\n await rm(installPath, { recursive: true, force: true });\n try {\n for (const f of manifest.files) {\n const target = join(installPath, f.path);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, bytes[f.path]!);\n }\n } catch (e) {\n await rm(installPath, { recursive: true, force: true }).catch(() => {});\n throw e;\n }\n\n return { installPath };\n}\n\n/**\n * Flat-layout install — the platform pointer-installer's behavior, made canonical\n * in install-core. Validates every path, fetches with the FULL repo paths, per-file\n * sha256-verifies, then strips the longest-common-dir prefix and writes each file\n * as `join(targetDir, path.slice(assetRoot.length + 1))` — immediate children of\n * `targetDir`. No ref parse, no composite check.\n */\nasync function installFlat(\n manifest: InstallManifest,\n targetDir: string,\n fetcher: AssetFetcher,\n): Promise<InstallResult> {\n const target = resolve(targetDir);\n\n // Gate every path before any fetch — the attacker controls the whole manifest.\n for (const f of manifest.files) {\n assertSafeManifestPath(target, f.path);\n }\n\n // Fetch keys off the FULL repo path (matches the upstream tree).\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // Strip the asset-root dir prefix from the WRITE path only — the fetch above\n // still keyed off the full repo path. Stripping removes leading whole segments\n // (never the basename), so a non-empty remainder always survives.\n const assetRoot = longestCommonDirPrefix(paths);\n\n for (const f of manifest.files) {\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n const relPath = assetRoot ? f.path.slice(assetRoot.length + 1) : f.path;\n // Re-guard the post-strip destination — it is what we actually write.\n assertSafeManifestPath(target, relPath);\n const dest = join(target, relPath);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, buf);\n }\n\n return { installPath: target };\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { softDepName } from './chunk-
|
|
2
|
-
import { SKAILE_YAML_DEFAULT, resolveSkWorkspaceConfig } from './chunk-
|
|
1
|
+
import { softDepName } from './chunk-Y7WKXPWS.js';
|
|
2
|
+
import { SKAILE_YAML_DEFAULT, resolveSkWorkspaceConfig } from './chunk-L3ZGYSWY.js';
|
|
3
3
|
import { existsSync } from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import pc from 'picocolors';
|
|
@@ -63,11 +63,27 @@ function logWarn(msg) {
|
|
|
63
63
|
function logInfo(msg) {
|
|
64
64
|
console.log(` ${pc.dim("\xB7")} ${msg}`);
|
|
65
65
|
}
|
|
66
|
+
function nearestParentProject(dir) {
|
|
67
|
+
for (let up = path.dirname(dir); up !== dir; dir = up, up = path.dirname(dir)) {
|
|
68
|
+
if (existsSync(path.join(up, SKAILE_YAML_DEFAULT))) return up;
|
|
69
|
+
}
|
|
70
|
+
return void 0;
|
|
71
|
+
}
|
|
72
|
+
function logNoProject(projectDir) {
|
|
73
|
+
const dir = path.resolve(projectDir);
|
|
74
|
+
logErr(`No ${S.cmd("skaile.yaml")} found. Run ${S.cmd("skaile init")} to create one.`);
|
|
75
|
+
const parent = nearestParentProject(dir);
|
|
76
|
+
if (parent) {
|
|
77
|
+
logErr(
|
|
78
|
+
`${S.cmd(parent)} holds a ${S.cmd("skaile.yaml")}: run from there or pass ${S.cmd(`--project-dir ${parent}`)}.`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
66
82
|
function requireProjectConfig(projectDir, opts = {}) {
|
|
67
83
|
const dir = path.resolve(projectDir);
|
|
68
84
|
if (!existsSync(path.join(dir, SKAILE_YAML_DEFAULT))) {
|
|
69
85
|
if (opts.allowMissing) return;
|
|
70
|
-
|
|
86
|
+
logNoProject(dir);
|
|
71
87
|
process.exit(1);
|
|
72
88
|
}
|
|
73
89
|
try {
|
|
@@ -140,6 +156,6 @@ function formatRelativeTime(date) {
|
|
|
140
156
|
return `${days}d ago`;
|
|
141
157
|
}
|
|
142
158
|
|
|
143
|
-
export { KIND_COL_WIDTH, S, TARGET_DEFAULT_HINT, bareSoftDepName, colorRef, deferredWarnings, fitWidth, formatRelativeTime, formatSoftDepAddPreview, formatSoftDepHint, formatSoftDepRemovePreview, formatSoftDepSection, kindColor, kindColorPad, logErr, logInfo, logOk, logWarn, requireProjectConfig, warnLegacyClaudeCopies };
|
|
144
|
-
//# sourceMappingURL=chunk-
|
|
145
|
-
//# sourceMappingURL=chunk-
|
|
159
|
+
export { KIND_COL_WIDTH, S, TARGET_DEFAULT_HINT, bareSoftDepName, colorRef, deferredWarnings, fitWidth, formatRelativeTime, formatSoftDepAddPreview, formatSoftDepHint, formatSoftDepRemovePreview, formatSoftDepSection, kindColor, kindColorPad, logErr, logInfo, logNoProject, logOk, logWarn, requireProjectConfig, warnLegacyClaudeCopies };
|
|
160
|
+
//# sourceMappingURL=chunk-PYTTF754.js.map
|
|
161
|
+
//# sourceMappingURL=chunk-PYTTF754.js.map
|