@skaile/workspaces 5.11.0 → 5.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +193 -0
- package/README.md +4 -4
- package/dist/{asset-feeds-CXGQIDFR.js → asset-feeds-ALMTHLPV.js} +26 -23
- package/dist/asset-feeds-ALMTHLPV.js.map +1 -0
- package/dist/asset-manager/catalog-deployer.js +10 -10
- package/dist/asset-manager/fragments.js +1 -1
- package/dist/asset-manager/index.js +18 -18
- package/dist/asset-manager/installer.js +13 -13
- package/dist/asset-manager/renderers.js +11 -11
- package/dist/asset-manager/src/fragments.d.ts +5 -0
- package/dist/asset-manager/src/fragments.d.ts.map +1 -1
- package/dist/asset-manager/src/index.d.ts +140 -12
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/asset-manager/src/install-agent.d.ts +9 -1
- package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
- package/dist/asset-manager/src/installer.d.ts.map +1 -1
- package/dist/asset-manager/src/renderers.d.ts +5 -0
- package/dist/asset-manager/src/renderers.d.ts.map +1 -1
- package/dist/bridge/drivers/claude-sdk.js +21 -16
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +101 -29
- package/dist/bridge/drivers/codex.js.map +1 -1
- package/dist/bridge/drivers/continue.js +12 -12
- package/dist/bridge/drivers/echo.js +2 -2
- package/dist/bridge/drivers/gemini.js +7 -7
- package/dist/bridge/drivers/goose.js +12 -12
- package/dist/bridge/drivers/omp.js +135 -33
- package/dist/bridge/drivers/omp.js.map +1 -1
- package/dist/bridge/drivers/opencode.js +12 -12
- package/dist/bridge/drivers/qwen.js +7 -7
- package/dist/bridge/index.js +14 -14
- package/dist/bridge/src/codex/config-toml.d.ts +16 -3
- package/dist/bridge/src/codex/config-toml.d.ts.map +1 -1
- package/dist/bridge/src/codex/managed-driver.d.ts.map +1 -1
- package/dist/bridge/src/drivers/claude-sdk.d.ts +1 -1
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/bridge/src/drivers/codex.d.ts +6 -0
- package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
- package/dist/bridge/src/drivers/omp-models-yml.d.ts +32 -0
- package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +1 -1
- package/dist/bridge/src/drivers/omp.d.ts +29 -6
- package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
- package/dist/bridge/src/provider-materialize/credential-env.d.ts +15 -0
- package/dist/bridge/src/provider-materialize/credential-env.d.ts.map +1 -1
- package/dist/{chunk-T42WRQ4O.js → chunk-2BIESC6S.js} +3 -3
- package/dist/{chunk-T42WRQ4O.js.map → chunk-2BIESC6S.js.map} +1 -1
- package/dist/{chunk-CPWLNZGJ.js → chunk-4DLQESIY.js} +3 -3
- package/dist/{chunk-CPWLNZGJ.js.map → chunk-4DLQESIY.js.map} +1 -1
- package/dist/{chunk-HZXUXHIV.js → chunk-4L4R5LV3.js} +89 -12
- package/dist/chunk-4L4R5LV3.js.map +1 -0
- package/dist/{chunk-CAHB6MHA.js → chunk-4NJ3QQHZ.js} +5 -5
- package/dist/{chunk-CAHB6MHA.js.map → chunk-4NJ3QQHZ.js.map} +1 -1
- package/dist/{chunk-ZCAJZ4B2.js → chunk-57SF6W6E.js} +147 -4
- package/dist/chunk-57SF6W6E.js.map +1 -0
- package/dist/{chunk-FH7W6TJ4.js → chunk-5FYOM4RF.js} +106 -25
- package/dist/chunk-5FYOM4RF.js.map +1 -0
- package/dist/{chunk-R7NHYEJF.js → chunk-5SKVCMRC.js} +15 -7
- package/dist/chunk-5SKVCMRC.js.map +1 -0
- package/dist/{chunk-CJERAGFY.js → chunk-6GICC4RJ.js} +44 -13
- package/dist/chunk-6GICC4RJ.js.map +1 -0
- package/dist/{chunk-G4FFOV3N.js → chunk-6JKIOPT3.js} +4 -4
- package/dist/{chunk-G4FFOV3N.js.map → chunk-6JKIOPT3.js.map} +1 -1
- package/dist/{chunk-T7CTHHG7.js → chunk-6NQDDCIL.js} +3 -3
- package/dist/{chunk-T7CTHHG7.js.map → chunk-6NQDDCIL.js.map} +1 -1
- package/dist/{chunk-XUSALIEI.js → chunk-7SMP4GNW.js} +6 -6
- package/dist/{chunk-XUSALIEI.js.map → chunk-7SMP4GNW.js.map} +1 -1
- package/dist/{chunk-Y3HTGHJC.js → chunk-AHCI4V5L.js} +3 -3
- package/dist/{chunk-Y3HTGHJC.js.map → chunk-AHCI4V5L.js.map} +1 -1
- package/dist/{chunk-M3B6EIJD.js → chunk-B7CZYFB2.js} +4 -4
- package/dist/{chunk-M3B6EIJD.js.map → chunk-B7CZYFB2.js.map} +1 -1
- package/dist/{chunk-PBBPZYVG.js → chunk-BF422IDP.js} +112 -46
- package/dist/chunk-BF422IDP.js.map +1 -0
- package/dist/{chunk-47U4GZ4M.js → chunk-BVJU2GKE.js} +20 -3
- package/dist/chunk-BVJU2GKE.js.map +1 -0
- package/dist/{chunk-PMECEZK3.js → chunk-D54T2F54.js} +5 -4
- package/dist/chunk-D54T2F54.js.map +1 -0
- package/dist/{chunk-2F5AWQX5.js → chunk-DKGEV6SQ.js} +192 -42
- package/dist/chunk-DKGEV6SQ.js.map +1 -0
- package/dist/{chunk-DALV4HHP.js → chunk-DKXNKFKP.js} +3 -2
- package/dist/{chunk-DALV4HHP.js.map → chunk-DKXNKFKP.js.map} +1 -1
- package/dist/chunk-FB3NREF7.js +649 -0
- package/dist/chunk-FB3NREF7.js.map +1 -0
- package/dist/{chunk-QZNJOHN6.js → chunk-FHDK3BFD.js} +3 -3
- package/dist/{chunk-QZNJOHN6.js.map → chunk-FHDK3BFD.js.map} +1 -1
- package/dist/{chunk-3SM2DL2T.js → chunk-GMDSRSGI.js} +21 -11
- package/dist/chunk-GMDSRSGI.js.map +1 -0
- package/dist/chunk-H5U7LNTJ.js +122 -0
- package/dist/chunk-H5U7LNTJ.js.map +1 -0
- package/dist/{chunk-VLTQGE2E.js → chunk-HBZD3MIW.js} +269 -81
- package/dist/chunk-HBZD3MIW.js.map +1 -0
- package/dist/{chunk-S3O3GKB7.js → chunk-HWGYJMME.js} +4 -4
- package/dist/{chunk-S3O3GKB7.js.map → chunk-HWGYJMME.js.map} +1 -1
- package/dist/{chunk-CPSIPIX7.js → chunk-IG5LZ3WU.js} +8 -6
- package/dist/chunk-IG5LZ3WU.js.map +1 -0
- package/dist/{chunk-ZPWTOUTK.js → chunk-IY5E7Y5W.js} +61 -8
- package/dist/chunk-IY5E7Y5W.js.map +1 -0
- package/dist/{chunk-6O2X3GPW.js → chunk-J4DB5G36.js} +7 -5
- package/dist/chunk-J4DB5G36.js.map +1 -0
- package/dist/{chunk-BNMZVPYA.js → chunk-J4OYIYFQ.js} +2 -2
- package/dist/{chunk-BNMZVPYA.js.map → chunk-J4OYIYFQ.js.map} +1 -1
- package/dist/{chunk-ALEYHUC5.js → chunk-L3ZGYSWY.js} +182 -41
- package/dist/chunk-L3ZGYSWY.js.map +1 -0
- package/dist/{chunk-SBSA3IQA.js → chunk-M3P4BYRK.js} +49 -14
- package/dist/chunk-M3P4BYRK.js.map +1 -0
- package/dist/{chunk-IER3KIPH.js → chunk-NDUYFYJB.js} +5 -5
- package/dist/{chunk-IER3KIPH.js.map → chunk-NDUYFYJB.js.map} +1 -1
- package/dist/{chunk-CGYEHQOX.js → chunk-NOA6EJXE.js} +11 -2
- package/dist/chunk-NOA6EJXE.js.map +1 -0
- package/dist/{chunk-J4RBUFGM.js → chunk-NVO6WECE.js} +9 -8
- package/dist/chunk-NVO6WECE.js.map +1 -0
- package/dist/{chunk-OBYKJB4U.js → chunk-O2SYFJWP.js} +79 -5
- package/dist/chunk-O2SYFJWP.js.map +1 -0
- package/dist/{chunk-5LKOAX7I.js → chunk-OQ5MKDS3.js} +21 -5
- package/dist/chunk-OQ5MKDS3.js.map +1 -0
- package/dist/{chunk-NWDSLXOX.js → chunk-PHRNUTSG.js} +118 -118
- package/dist/chunk-PHRNUTSG.js.map +1 -0
- package/dist/chunk-PN44DOGP.js +345 -0
- package/dist/chunk-PN44DOGP.js.map +1 -0
- package/dist/{chunk-COH6FQAG.js → chunk-PXDWTJ3P.js} +5 -5
- package/dist/{chunk-COH6FQAG.js.map → chunk-PXDWTJ3P.js.map} +1 -1
- package/dist/{chunk-GV4DZ6MT.js → chunk-PYTTF754.js} +22 -6
- package/dist/chunk-PYTTF754.js.map +1 -0
- package/dist/chunk-PZOO7L26.js +64 -0
- package/dist/chunk-PZOO7L26.js.map +1 -0
- package/dist/{chunk-EDYHEMJA.js → chunk-QO7CR3KB.js} +10 -5
- package/dist/chunk-QO7CR3KB.js.map +1 -0
- package/dist/{chunk-XDKH7XSA.js → chunk-R6QHJEHE.js} +5 -5
- package/dist/{chunk-XDKH7XSA.js.map → chunk-R6QHJEHE.js.map} +1 -1
- package/dist/chunk-U27JRO5L.js +13 -0
- package/dist/chunk-U27JRO5L.js.map +1 -0
- package/dist/{chunk-X77SUM4P.js → chunk-USHB5KEY.js} +3 -3
- package/dist/{chunk-X77SUM4P.js.map → chunk-USHB5KEY.js.map} +1 -1
- package/dist/{chunk-QVFAS5IO.js → chunk-V5JHD4I2.js} +3 -3
- package/dist/{chunk-QVFAS5IO.js.map → chunk-V5JHD4I2.js.map} +1 -1
- package/dist/{chunk-PQFHMQHQ.js → chunk-VLBIME5L.js} +6 -6
- package/dist/{chunk-PQFHMQHQ.js.map → chunk-VLBIME5L.js.map} +1 -1
- package/dist/{chunk-D3B36CYC.js → chunk-X3RMRJNR.js} +4 -3
- package/dist/chunk-X3RMRJNR.js.map +1 -0
- package/dist/{chunk-TCHRMVTO.js → chunk-XBYSURMK.js} +4 -4
- package/dist/{chunk-TCHRMVTO.js.map → chunk-XBYSURMK.js.map} +1 -1
- package/dist/{chunk-MZG34MBZ.js → chunk-XJYBCDY2.js} +3 -3
- package/dist/{chunk-MZG34MBZ.js.map → chunk-XJYBCDY2.js.map} +1 -1
- package/dist/{chunk-4A4OD24G.js → chunk-Y4Z7LGSH.js} +9 -9
- package/dist/{chunk-4A4OD24G.js.map → chunk-Y4Z7LGSH.js.map} +1 -1
- package/dist/{chunk-DZMNFCWB.js → chunk-Y7WKXPWS.js} +816 -143
- package/dist/chunk-Y7WKXPWS.js.map +1 -0
- package/dist/{chunk-HCEVNYSH.js → chunk-YTZFSKWL.js} +3 -3
- package/dist/{chunk-HCEVNYSH.js.map → chunk-YTZFSKWL.js.map} +1 -1
- package/dist/{chunk-WSBKB4CJ.js → chunk-ZSMMX3JD.js} +167 -25
- package/dist/chunk-ZSMMX3JD.js.map +1 -0
- package/dist/{chunk-GCHPUTA3.js → chunk-ZU24LWBI.js} +3 -3
- package/dist/{chunk-GCHPUTA3.js.map → chunk-ZU24LWBI.js.map} +1 -1
- package/dist/cli/index.js +1427 -605
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/agent-checks.d.ts +40 -0
- package/dist/cli/src/agent-checks.d.ts.map +1 -0
- package/dist/cli/src/asset-feeds.d.ts.map +1 -1
- package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/catalog-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/catalog.d.ts +26 -0
- package/dist/cli/src/commands/catalog.d.ts.map +1 -1
- package/dist/cli/src/commands/config.d.ts.map +1 -1
- package/dist/cli/src/commands/diff.d.ts +1 -1
- package/dist/cli/src/commands/diff.d.ts.map +1 -1
- package/dist/cli/src/commands/integration.d.ts.map +1 -1
- package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/library-index.d.ts +10 -0
- package/dist/cli/src/commands/library-index.d.ts.map +1 -1
- package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
- package/dist/cli/src/commands/mcp-server.d.ts +1 -1
- package/dist/cli/src/commands/migrate-assets.d.ts +2 -1
- package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
- package/dist/cli/src/commands/migrate.d.ts.map +1 -1
- package/dist/cli/src/commands/plugin/claude-code.d.ts +1 -1
- package/dist/cli/src/commands/plugin/claude-code.d.ts.map +1 -1
- package/dist/cli/src/commands/plugin/types.d.ts +3 -1
- package/dist/cli/src/commands/plugin/types.d.ts.map +1 -1
- package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/preset-apply.d.ts.map +1 -1
- package/dist/cli/src/commands/project.d.ts +8 -0
- package/dist/cli/src/commands/project.d.ts.map +1 -1
- package/dist/cli/src/commands/publish-core.d.ts +5 -0
- package/dist/cli/src/commands/publish-core.d.ts.map +1 -1
- package/dist/cli/src/commands/run.d.ts +11 -1
- package/dist/cli/src/commands/run.d.ts.map +1 -1
- package/dist/cli/src/commands/serve-preflight.d.ts +23 -0
- package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -0
- package/dist/cli/src/commands/serve.d.ts.map +1 -1
- package/dist/cli/src/commands/source-manifest-publish.d.ts.map +1 -1
- package/dist/cli/src/commands/source-manifest.d.ts +1 -0
- package/dist/cli/src/commands/source-manifest.d.ts.map +1 -1
- package/dist/cli/src/commands/source.d.ts +9 -1
- package/dist/cli/src/commands/source.d.ts.map +1 -1
- package/dist/cli/src/commands/store.d.ts.map +1 -1
- package/dist/cli/src/commands/tree.d.ts.map +1 -1
- package/dist/cli/src/commands/update.d.ts.map +1 -1
- package/dist/cli/src/commands/validate-instances.d.ts.map +1 -1
- package/dist/cli/src/commands/validate.d.ts +3 -2
- package/dist/cli/src/commands/validate.d.ts.map +1 -1
- package/dist/cli/src/commands/why.d.ts.map +1 -1
- package/dist/cli/src/curated-manifests.d.ts +21 -0
- package/dist/cli/src/curated-manifests.d.ts.map +1 -0
- package/dist/cli/src/driver-error.d.ts +7 -0
- package/dist/cli/src/driver-error.d.ts.map +1 -1
- package/dist/cli/src/helpers.d.ts +6 -0
- package/dist/cli/src/helpers.d.ts.map +1 -1
- package/dist/cli/src/index-busy.d.ts +8 -0
- package/dist/cli/src/index-busy.d.ts.map +1 -0
- package/dist/cli/src/plugin-store/index.d.ts +1 -1
- package/dist/cli/src/plugin-store/index.d.ts.map +1 -1
- package/dist/cli/src/plugin-store/paths.d.ts +7 -3
- package/dist/cli/src/plugin-store/paths.d.ts.map +1 -1
- package/dist/cli/src/plugin-store/reconcile.d.ts +24 -4
- package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -1
- package/dist/cli/src/skill-checks.d.ts +27 -3
- package/dist/cli/src/skill-checks.d.ts.map +1 -1
- package/dist/cli/src/store-addable.d.ts +17 -0
- package/dist/cli/src/store-addable.d.ts.map +1 -0
- package/dist/connectors/config.js +6 -6
- package/dist/connectors/index.js +18 -18
- package/dist/connectors/src/config.d.ts.map +1 -1
- package/dist/{connectors-4QWAKPHB.js → connectors-GFKMKAXV.js} +21 -21
- package/dist/{connectors-4QWAKPHB.js.map → connectors-GFKMKAXV.js.map} +1 -1
- package/dist/core/driver-targets.js +1 -1
- package/dist/core/index.js +9 -9
- package/dist/core/logging.js +1 -1
- package/dist/core/manifest.js +2 -2
- package/dist/core/models.js +1 -1
- package/dist/core/publish-manifest.js +4 -2
- package/dist/core/ref.js +1 -1
- package/dist/core/runtime-assets.js +6 -6
- package/dist/core/src/agent-instances.d.ts +5 -0
- package/dist/core/src/agent-instances.d.ts.map +1 -1
- package/dist/core/src/driver-targets.d.ts.map +1 -1
- package/dist/core/src/index.d.ts +6 -5
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/lock.d.ts +15 -5
- package/dist/core/src/lock.d.ts.map +1 -1
- package/dist/core/src/logging/sinks/sqlite-sink.d.ts.map +1 -1
- package/dist/core/src/manifest.d.ts +14 -3
- package/dist/core/src/manifest.d.ts.map +1 -1
- package/dist/core/src/models.d.ts +11 -3
- package/dist/core/src/models.d.ts.map +1 -1
- package/dist/core/src/package-manager.d.ts +19 -0
- package/dist/core/src/package-manager.d.ts.map +1 -0
- package/dist/core/src/publish-manifest.d.ts +38 -1
- package/dist/core/src/publish-manifest.d.ts.map +1 -1
- package/dist/core/src/repo-manager.d.ts +19 -3
- package/dist/core/src/repo-manager.d.ts.map +1 -1
- package/dist/core/src/runtime-assets.d.ts.map +1 -1
- package/dist/core/src/settings.d.ts +26 -6
- package/dist/core/src/settings.d.ts.map +1 -1
- package/dist/core/src/store.d.ts +4 -0
- package/dist/core/src/store.d.ts.map +1 -1
- package/dist/core/src/walker.d.ts +8 -1
- package/dist/core/src/walker.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts +24 -2
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/store.js +2 -2
- package/dist/core/workspace-config.js +5 -5
- package/dist/deploy/index.js +9 -9
- package/dist/discovery/index.js +5 -5
- package/dist/discovery/src/parse-manifest.d.ts.map +1 -1
- package/dist/discovery/src/source-config.d.ts +5 -3
- package/dist/discovery/src/source-config.d.ts.map +1 -1
- package/dist/{ensure-sources-2RONZKCU.js → ensure-sources-VUKHL65L.js} +21 -21
- package/dist/{ensure-sources-2RONZKCU.js.map → ensure-sources-VUKHL65L.js.map} +1 -1
- package/dist/factory-assets/README.md +1 -1
- package/dist/factory-assets/connectors/box.js +18 -18
- package/dist/factory-assets/connectors/deploy.js +18 -18
- package/dist/factory-assets/connectors/devserver.js +18 -18
- package/dist/factory-assets/connectors/flow/adapter.js +18 -18
- package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/contract.js +1 -1
- package/dist/factory-assets/connectors/flow/engine.js +11 -11
- package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/run-flow.js +20 -20
- package/dist/factory-assets/connectors/flow.js +18 -18
- package/dist/factory-assets/connectors/git.js +18 -18
- package/dist/factory-assets/connectors/gmail.js +18 -18
- package/dist/factory-assets/connectors/googledrive.js +18 -18
- package/dist/factory-assets/connectors/local.js +18 -18
- package/dist/factory-assets/connectors/mattermost.js +18 -18
- package/dist/factory-assets/connectors/memory.js +18 -18
- package/dist/factory-assets/connectors/minio.js +18 -18
- package/dist/factory-assets/connectors/postgres.js +18 -18
- package/dist/factory-assets/connectors/s3.js +18 -18
- package/dist/factory-assets/connectors/sharepoint.js +18 -18
- package/dist/factory-assets/connectors/sqlite.js +18 -18
- package/dist/factory-assets/connectors/static-server.js +18 -18
- package/dist/factory-assets/connectors/tunnel.js +18 -18
- package/dist/factory-assets/connectors/webdav.js +18 -18
- package/dist/factory-assets/connectors/xstate-store.js +18 -18
- package/dist/factory-assets/connectors/xstate.js +18 -18
- package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +10 -8
- package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +15 -11
- package/dist/factory-assets/skills/authoring-skaile-manifests/references/dependency-standard.md +12 -9
- package/dist/factory-assets/skills/skaile-author-asset/SKILL.md +2 -2
- package/dist/flows-A4YALSZY.js +26 -0
- package/dist/{flows-EQF2CH4U.js.map → flows-A4YALSZY.js.map} +1 -1
- package/dist/helpers-53XZW7KF.js +34 -0
- package/dist/{helpers-CFK6YP6R.js.map → helpers-53XZW7KF.js.map} +1 -1
- package/dist/library/index.js +14 -14
- package/dist/library/install.js +6 -4
- package/dist/library/src/index.d.ts +2 -2
- package/dist/library/src/index.d.ts.map +1 -1
- package/dist/library/src/install/source-fetch-github.d.ts.map +1 -1
- package/dist/library/src/local/db.d.ts +2 -0
- package/dist/library/src/local/db.d.ts.map +1 -1
- package/dist/library/src/local/library-manager.d.ts +5 -0
- package/dist/library/src/local/library-manager.d.ts.map +1 -1
- package/dist/library/src/local/library.d.ts +5 -3
- package/dist/library/src/local/library.d.ts.map +1 -1
- package/dist/library/src/local/local-catalog-source.d.ts +6 -0
- package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
- package/dist/library/src/local/store-paths.d.ts +9 -0
- package/dist/library/src/local/store-paths.d.ts.map +1 -1
- package/dist/library/src/manifest-writer.d.ts +1 -1
- package/dist/library/src/manifest-writer.d.ts.map +1 -1
- package/dist/library/src/remote/index.d.ts +1 -1
- package/dist/library/src/remote/index.d.ts.map +1 -1
- package/dist/library/src/remote/remote-catalog-source.d.ts +17 -0
- package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
- package/dist/library/src/sync/git-driver.d.ts.map +1 -1
- package/dist/library/src/user-library.d.ts +2 -0
- package/dist/library/src/user-library.d.ts.map +1 -1
- package/dist/{library-publish-53UTB3MB.js → library-publish-FFIPWIRM.js} +50 -39
- package/dist/library-publish-FFIPWIRM.js.map +1 -0
- package/dist/open-library-PZAT3TJA.js +40 -0
- package/dist/{open-library-BOSPJVID.js.map → open-library-PZAT3TJA.js.map} +1 -1
- package/dist/open-registry-W46UXZ3I.js +32 -0
- package/dist/{open-registry-4FI7HKET.js.map → open-registry-W46UXZ3I.js.map} +1 -1
- package/dist/paths-KKY3NSBZ.js +22 -0
- package/dist/{paths-SUS4S4YT.js.map → paths-KKY3NSBZ.js.map} +1 -1
- package/dist/plugin-store-CK7YWRIC.js +227 -0
- package/dist/plugin-store-CK7YWRIC.js.map +1 -0
- package/dist/plugins/src/catalog-source.d.ts +6 -0
- package/dist/plugins/src/catalog-source.d.ts.map +1 -1
- package/dist/project-EZUH7PUJ.js +79 -0
- package/dist/{project-I55A4O2T.js.map → project-EZUH7PUJ.js.map} +1 -1
- package/dist/resolver/index.js +10 -10
- package/dist/runner/index.js +35 -35
- package/dist/runner/src/agent.d.ts.map +1 -1
- package/dist/runner/src/agents/in-process-host.d.ts.map +1 -1
- package/dist/runner/src/composition/index.d.ts +2 -1
- package/dist/runner/src/composition/index.d.ts.map +1 -1
- package/dist/runner/src/composition/prompt-sections.d.ts +20 -5
- package/dist/runner/src/composition/prompt-sections.d.ts.map +1 -1
- package/dist/runner/src/composition/resolve.d.ts +10 -1
- package/dist/runner/src/composition/resolve.d.ts.map +1 -1
- package/dist/runner/src/composition/verify.d.ts +29 -0
- package/dist/runner/src/composition/verify.d.ts.map +1 -0
- package/dist/runner/src/credential-notice.d.ts +14 -0
- package/dist/runner/src/credential-notice.d.ts.map +1 -0
- package/dist/runner/src/environment.d.ts.map +1 -1
- package/dist/runner/src/final-text.d.ts +17 -0
- package/dist/runner/src/final-text.d.ts.map +1 -0
- package/dist/runner/src/index.d.ts +2 -0
- package/dist/runner/src/index.d.ts.map +1 -1
- package/dist/runner/src/resource-handler.d.ts.map +1 -1
- package/dist/runner/src/serve.d.ts +13 -0
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/runner/src/session-builder.d.ts.map +1 -1
- package/dist/runner/src/session.d.ts +2 -0
- package/dist/runner/src/session.d.ts.map +1 -1
- package/dist/runner/src/ws-auth-warning.d.ts +17 -0
- package/dist/runner/src/ws-auth-warning.d.ts.map +1 -0
- package/dist/sdk/asset-manager.js +18 -18
- package/dist/sdk/bridge.js +14 -14
- package/dist/sdk/core.js +9 -9
- package/dist/sdk/flow.js +11 -11
- package/dist/sdk/index.js +38 -36
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/resolver.js +10 -10
- package/dist/sdk/runner.js +35 -35
- package/dist/sdk/src/local-runtime.d.ts.map +1 -1
- package/dist/sdk/transport/ws/client.js +1 -1
- package/dist/sdk/transport/ws/server.js +1 -1
- package/dist/sdk/transport/ws.js +2 -2
- package/dist/sdk/transport.js +2 -2
- package/dist/serve-preflight-F7MYF747.js +64 -0
- package/dist/serve-preflight-F7MYF747.js.map +1 -0
- package/dist/{setup-7DQJKHUI.js → setup-L632QIHV.js} +26 -26
- package/dist/{setup-7DQJKHUI.js.map → setup-L632QIHV.js.map} +1 -1
- package/dist/skills-OY3Y5GKA.js +26 -0
- package/dist/{skills-NUEN5NDX.js.map → skills-OY3Y5GKA.js.map} +1 -1
- package/dist/source-36FHMN5V.js +42 -0
- package/dist/{source-G2LV5LVD.js.map → source-36FHMN5V.js.map} +1 -1
- package/dist/source-fetch-github-PIO6EMMF.js +4 -0
- package/dist/{source-fetch-github-QN4LLTL5.js.map → source-fetch-github-PIO6EMMF.js.map} +1 -1
- package/dist/{source-manifest-publish-6RM7SWLZ.js → source-manifest-publish-NIXJSJ22.js} +30 -28
- package/dist/source-manifest-publish-NIXJSJ22.js.map +1 -0
- package/dist/transport/index.js +2 -2
- package/dist/transport/src/ws/client.d.ts +6 -0
- package/dist/transport/src/ws/client.d.ts.map +1 -1
- package/dist/transport/src/ws/server.d.ts +4 -0
- package/dist/transport/src/ws/server.d.ts.map +1 -1
- package/dist/transport/ws/client.js +1 -1
- package/dist/transport/ws/server.js +1 -1
- package/dist/transport/ws.js +2 -2
- package/dist/tui/index.js +77 -50
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/src/repl-session.d.ts +1 -1
- package/dist/tui/src/repl-session.d.ts.map +1 -1
- package/dist/tui/src/repl.d.ts +3 -0
- package/dist/tui/src/repl.d.ts.map +1 -1
- package/dist/types/manifests.js +1 -1
- package/dist/types/src/lifecycle.d.ts +2 -1
- package/dist/types/src/lifecycle.d.ts.map +1 -1
- package/dist/types/src/manifests/agent-composition.d.ts +20 -0
- package/dist/types/src/manifests/agent-composition.d.ts.map +1 -1
- package/dist/types/src/manifests/agent.d.ts.map +1 -1
- package/dist/types/src/manifests/cron.d.ts +15 -0
- package/dist/types/src/manifests/cron.d.ts.map +1 -0
- package/dist/types/src/manifests/index.d.ts +3 -2
- package/dist/types/src/manifests/index.d.ts.map +1 -1
- package/dist/types/src/manifests/preset.d.ts +6 -1
- package/dist/types/src/manifests/preset.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +25 -25
- package/dist/workspace-plugin/adapters/omp.js +106 -51
- package/dist/workspace-plugin/adapters/omp.js.map +1 -1
- package/dist/workspace-plugin/index.js +2 -2
- package/dist/workspace-plugin/src/adapters/claude-code.d.ts.map +1 -1
- package/dist/workspace-plugin/src/adapters/omp.d.ts +11 -2
- package/dist/workspace-plugin/src/adapters/omp.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/asset-feeds-CXGQIDFR.js.map +0 -1
- package/dist/chunk-2F5AWQX5.js.map +0 -1
- package/dist/chunk-3SM2DL2T.js.map +0 -1
- package/dist/chunk-47U4GZ4M.js.map +0 -1
- package/dist/chunk-5LKOAX7I.js.map +0 -1
- package/dist/chunk-6O2X3GPW.js.map +0 -1
- package/dist/chunk-ALEYHUC5.js.map +0 -1
- package/dist/chunk-CGYEHQOX.js.map +0 -1
- package/dist/chunk-CJERAGFY.js.map +0 -1
- package/dist/chunk-CPSIPIX7.js.map +0 -1
- package/dist/chunk-D3B36CYC.js.map +0 -1
- package/dist/chunk-DZMNFCWB.js.map +0 -1
- package/dist/chunk-EDYHEMJA.js.map +0 -1
- package/dist/chunk-FH7W6TJ4.js.map +0 -1
- package/dist/chunk-GV4DZ6MT.js.map +0 -1
- package/dist/chunk-HZXUXHIV.js.map +0 -1
- package/dist/chunk-J4RBUFGM.js.map +0 -1
- package/dist/chunk-NWDSLXOX.js.map +0 -1
- package/dist/chunk-OBYKJB4U.js.map +0 -1
- package/dist/chunk-PBBPZYVG.js.map +0 -1
- package/dist/chunk-PMECEZK3.js.map +0 -1
- package/dist/chunk-R7FOF242.js +0 -59
- package/dist/chunk-R7FOF242.js.map +0 -1
- package/dist/chunk-R7NHYEJF.js.map +0 -1
- package/dist/chunk-RYYLMBA2.js +0 -392
- package/dist/chunk-RYYLMBA2.js.map +0 -1
- package/dist/chunk-SBSA3IQA.js.map +0 -1
- package/dist/chunk-VLTQGE2E.js.map +0 -1
- package/dist/chunk-WSBKB4CJ.js.map +0 -1
- package/dist/chunk-YOH2L76X.js +0 -505
- package/dist/chunk-YOH2L76X.js.map +0 -1
- package/dist/chunk-ZCAJZ4B2.js.map +0 -1
- package/dist/chunk-ZPWTOUTK.js.map +0 -1
- package/dist/flows-EQF2CH4U.js +0 -26
- package/dist/helpers-CFK6YP6R.js +0 -34
- package/dist/library-publish-53UTB3MB.js.map +0 -1
- package/dist/open-library-BOSPJVID.js +0 -40
- package/dist/open-registry-4FI7HKET.js +0 -32
- package/dist/paths-SUS4S4YT.js +0 -22
- package/dist/plugin-store-AGQDMING.js +0 -149
- package/dist/plugin-store-AGQDMING.js.map +0 -1
- package/dist/project-I55A4O2T.js +0 -41
- package/dist/skills-NUEN5NDX.js +0 -26
- package/dist/source-G2LV5LVD.js +0 -41
- package/dist/source-fetch-github-QN4LLTL5.js +0 -4
- package/dist/source-manifest-publish-6RM7SWLZ.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,98 +1,101 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-
|
|
3
|
-
import {
|
|
4
|
-
import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportReplaced, reportRelocked, reportMoved, REF_HINT, reportInstalledSoftDeps } from '../chunk-CJERAGFY.js';
|
|
2
|
+
import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-R6QHJEHE.js';
|
|
3
|
+
import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportReplaced, reportRelocked, reportMoved, editedConventionFiles, REF_HINT, reportInstalledSoftDeps } from '../chunk-6GICC4RJ.js';
|
|
5
4
|
import { createSpinner } from '../chunk-NESV47MF.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
5
|
+
import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-ZSMMX3JD.js';
|
|
6
|
+
import { AI_RESOURCES } from '../chunk-HWGYJMME.js';
|
|
7
|
+
import { checkAsset, agentComposeRefAdvisories, findAssetManifestFile, declaredVersion, checkAssetFile, duplicateAssetMessage, readAssetBody, checkAgentFiles, invalidSemverText } from '../chunk-PN44DOGP.js';
|
|
8
|
+
import { getStoreConfig, storeFetch, isStoreAuthenticated, getStoreToken } from '../chunk-PZOO7L26.js';
|
|
9
|
+
import { unresolvedManifestDependencies, warnIgnoredDomainFiles, warnLegacyBundleFiles, removedDomainOption, rejectRemovedDomainOption, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, resolveLibraryPublisherDetailed, getStoreIdentity, warnLibraryNameFallback, indexLibrary, requireValidPublisherOrExit, exitOnManifestPublisherProblems, registerLibraryAsset, DOMAIN_REMOVED_HINT, reportLibrarySymlinks, assetEntryRef, manifestPublisherProblems, manifestRequiresProblems, manifestVersionMismatchMessage, exitOnLibrarySymlinks } from '../chunk-FB3NREF7.js';
|
|
10
|
+
import { storeNotInstallableReason } from '../chunk-U27JRO5L.js';
|
|
11
|
+
import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-VLBIME5L.js';
|
|
12
|
+
import { logErr, S, logOk, logInfo, logWarn, TARGET_DEFAULT_HINT, requireProjectConfig, deferredWarnings, logNoProject, warnLegacyClaudeCopies, kindColorPad, kindColor, colorRef, formatSoftDepSection, bareSoftDepName, formatSoftDepHint, formatRelativeTime, formatSoftDepRemovePreview, formatSoftDepAddPreview, fitWidth, KIND_COL_WIDTH } from '../chunk-PYTTF754.js';
|
|
13
|
+
import { getKindRegistry, getKnownKinds } from '../chunk-4NJ3QQHZ.js';
|
|
12
14
|
import { LocalSecretsProvider } from '../chunk-ILFGVSTJ.js';
|
|
13
|
-
import { runAgentChat, isCompositionError, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, hashAgentFiles, createCompositionContentSource, compileComposition, instanceForSession, resolveAgentInstance, describeComposition, MarkdownStreamer } from '../chunk-
|
|
14
|
-
import { buildClaudePluginFiles } from '../chunk-
|
|
15
|
-
import '../chunk-
|
|
16
|
-
import '../chunk-
|
|
15
|
+
import { runAgentChat, isCompositionError, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, hashAgentFiles, createCompositionContentSource, compileComposition, instanceForSession, resolveAgentInstance, describeComposition, MarkdownStreamer, createFinalTextFallback, resolveBinding, UnknownCompositionKindError } from '../chunk-HBZD3MIW.js';
|
|
16
|
+
import { buildClaudePluginFiles } from '../chunk-J4DB5G36.js';
|
|
17
|
+
import '../chunk-NDUYFYJB.js';
|
|
18
|
+
import '../chunk-V5JHD4I2.js';
|
|
17
19
|
import '../chunk-R6O6YWU7.js';
|
|
18
|
-
import '../chunk-
|
|
19
|
-
import '../chunk-
|
|
20
|
+
import '../chunk-6JKIOPT3.js';
|
|
21
|
+
import '../chunk-2BIESC6S.js';
|
|
20
22
|
import '../chunk-4ZTPYIBE.js';
|
|
21
|
-
import '../chunk-
|
|
23
|
+
import '../chunk-XJYBCDY2.js';
|
|
22
24
|
import '../chunk-X5YPJV4N.js';
|
|
23
25
|
import '../chunk-O7SG5PC2.js';
|
|
24
26
|
import '../chunk-7QBNJTTQ.js';
|
|
25
|
-
import '../chunk-
|
|
26
|
-
import '../chunk-
|
|
27
|
+
import '../chunk-O2SYFJWP.js';
|
|
28
|
+
import '../chunk-OQ5MKDS3.js';
|
|
27
29
|
import '../chunk-32NA4TVC.js';
|
|
28
30
|
import '../chunk-W3UDISS2.js';
|
|
29
|
-
import '../chunk-
|
|
30
|
-
import { runFlow, resumeFlow } from '../chunk-
|
|
31
|
+
import '../chunk-PHRNUTSG.js';
|
|
32
|
+
import { runFlow, resumeFlow } from '../chunk-GMDSRSGI.js';
|
|
31
33
|
import '../chunk-4R6DROGN.js';
|
|
32
|
-
import { validateFlowVersions } from '../chunk-
|
|
33
|
-
import '../chunk-
|
|
34
|
+
import { parseSkillRequirements, validateRequirements, validateFlowVersions } from '../chunk-USHB5KEY.js';
|
|
35
|
+
import '../chunk-ZU24LWBI.js';
|
|
34
36
|
import '../chunk-ISHJITXJ.js';
|
|
35
|
-
import '../chunk-
|
|
37
|
+
import '../chunk-Y4Z7LGSH.js';
|
|
36
38
|
import '../chunk-X4BAYGMT.js';
|
|
37
|
-
import '../chunk-
|
|
38
|
-
import '../chunk-
|
|
39
|
-
import '../chunk-
|
|
39
|
+
import '../chunk-5SKVCMRC.js';
|
|
40
|
+
import '../chunk-6NQDDCIL.js';
|
|
41
|
+
import '../chunk-YTZFSKWL.js';
|
|
40
42
|
import '../chunk-LOO5CB5M.js';
|
|
41
43
|
import '../chunk-2H73V6XR.js';
|
|
42
|
-
import '../chunk-
|
|
44
|
+
import '../chunk-B7CZYFB2.js';
|
|
43
45
|
import '../chunk-B4X2N7JQ.js';
|
|
44
46
|
import '../chunk-YROR332M.js';
|
|
45
|
-
import { getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-
|
|
47
|
+
import { listDrivers, getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-BVJU2GKE.js';
|
|
46
48
|
import '../chunk-6E6PKKAD.js';
|
|
47
49
|
import '../chunk-IFGTRL2I.js';
|
|
48
|
-
import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-
|
|
50
|
+
import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-XBYSURMK.js';
|
|
49
51
|
import '../chunk-LNFKL23K.js';
|
|
50
|
-
import '../chunk-
|
|
52
|
+
import '../chunk-X3RMRJNR.js';
|
|
51
53
|
import '../chunk-M3WPBTGJ.js';
|
|
52
54
|
import { nodeLabel, nodeSkillAsset, nodeIsInert, nodeIsOptional, nodeRunKind, flowSkillVersionPins } from '../chunk-7RGTAEG6.js';
|
|
53
55
|
import '../chunk-NUELZWCF.js';
|
|
54
56
|
import '../chunk-F4NJDSR7.js';
|
|
55
|
-
import { AssetManager,
|
|
56
|
-
import { libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, ensureGitRepo, conflictingAssetRoot, setManifestPublisher, LIBRARY_OWNERSHIPS,
|
|
57
|
-
import { parseManifestFile, SEMVER_RE } from '../chunk-
|
|
58
|
-
import '../chunk-
|
|
59
|
-
import '../chunk-
|
|
57
|
+
import { AssetManager, parseRefTolerant, MissingManifestError, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-Y7WKXPWS.js';
|
|
58
|
+
import { libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, isGitRepo, ensureGitRepo, conflictingAssetRoot, setManifestPublisher, LIBRARY_OWNERSHIPS, assertManifestEditable, installLibraryAsset, missingRootAssets, getStoreManifestsDir, assertValidLibraryName, syncManifestWithDisk, getDefaultValue, isSecretPlaceholder } from '../chunk-DKGEV6SQ.js';
|
|
59
|
+
import { parseManifestFile, SEMVER_RE } from '../chunk-NVO6WECE.js';
|
|
60
|
+
import '../chunk-PXDWTJ3P.js';
|
|
61
|
+
import '../chunk-H5U7LNTJ.js';
|
|
60
62
|
import '../chunk-3TXEJN4W.js';
|
|
61
|
-
import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-
|
|
62
|
-
import '../chunk-
|
|
63
|
+
import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-5FYOM4RF.js';
|
|
64
|
+
import '../chunk-NOA6EJXE.js';
|
|
63
65
|
import '../chunk-KTBKW2FI.js';
|
|
64
66
|
import '../chunk-UQ6LFBPZ.js';
|
|
65
|
-
import '../chunk-
|
|
66
|
-
import { effectiveComposes, validatePreset, composeSlotDiagnostics, agentDeprecationDiagnostics, validateAgent, SLOT_ID_PATTERN } from '../chunk-
|
|
67
|
-
import { resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, globalInstallDir, GLOBAL_INSTALL_DIR_NAME,
|
|
67
|
+
import '../chunk-4L4R5LV3.js';
|
|
68
|
+
import { effectiveComposes, validatePreset, composeSlotDiagnostics, agentDeprecationDiagnostics, validateAgent, SLOT_ID_PATTERN } from '../chunk-57SF6W6E.js';
|
|
69
|
+
import { resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, resolveSettingsWithSources, readLock, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, aiResourceRoots, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile } from '../chunk-BF422IDP.js';
|
|
68
70
|
import '../chunk-4GY63JU6.js';
|
|
69
|
-
import { factoryAssetRoots } from '../chunk-
|
|
70
|
-
import '../chunk-
|
|
71
|
+
import { resolveRuntimeAssets, factoryAssetRoots } from '../chunk-QO7CR3KB.js';
|
|
72
|
+
import { deployedDir } from '../chunk-D54T2F54.js';
|
|
71
73
|
import { DEFAULT_DRIVER_ID, DRIVER_DEFAULTS } from '../chunk-5BEFNLOR.js';
|
|
72
74
|
import { findKindDirs } from '../chunk-A2ULN3KX.js';
|
|
73
|
-
import { SourceEntryError, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir,
|
|
75
|
+
import { SourceEntryError, resolveSkWorkspaceConfig, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, decodeSkaileYaml, matchPin, coerceVersion, loadSkWorkspaceConfig, normalizeAgentInstances, agentBlockKeyDiagnostics, agentInstanceDiagnostics, storeManifestSlug, isWorkspaceConfigFilename } from '../chunk-L3ZGYSWY.js';
|
|
74
76
|
import { globalCacheRoot, globalSkaileDir, userConfigPath } from '../chunk-L5VSIPQD.js';
|
|
75
|
-
import { SUPPORTED_DRIVER_TARGETS, driverTargetForDriver } from '../chunk-
|
|
76
|
-
import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest,
|
|
77
|
+
import { SUPPORTED_DRIVER_TARGETS, driverTargetForDriver } from '../chunk-IG5LZ3WU.js';
|
|
78
|
+
import { SKAILE_MANIFEST_FILENAME, loadSkPublishManifest, decodeSkaileManifest, isNonAssetPath, isNonAssetDir, encodeSkaileManifest } from '../chunk-IY5E7Y5W.js';
|
|
77
79
|
import { pluginTitle } from '../chunk-RVRB27AN.js';
|
|
78
|
-
import { dedupeRequirements, parseFrontmatter, scanDirectory } from '../chunk-
|
|
79
|
-
import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, slugifyAssetName, parseAssetRefLoose, assetRefToStr } from '../chunk-
|
|
80
|
+
import { dedupeRequirements, parseFrontmatter, scanDirectory, parseRequires } from '../chunk-M3P4BYRK.js';
|
|
81
|
+
import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, depToStr, slugifyAssetName, parseAssetRefLoose, assetRefToStr } from '../chunk-J4OYIYFQ.js';
|
|
80
82
|
import { portableSpawn, portableSpawnSync } from '../chunk-ICSCSM5D.js';
|
|
81
|
-
import { openSqlite } from '../chunk-
|
|
83
|
+
import { openSqlite } from '../chunk-DKXNKFKP.js';
|
|
82
84
|
import { parseModelRef, resolveEntryBaseUrl } from '../chunk-MJHSLODD.js';
|
|
83
85
|
import '../chunk-C3CAXQMA.js';
|
|
84
|
-
import '../chunk-BOFL7GIF.js';
|
|
86
|
+
import { registerLogStore, LogStore, StdoutSink } from '../chunk-BOFL7GIF.js';
|
|
85
87
|
import '../chunk-NSBPE2FW.js';
|
|
86
|
-
import * as
|
|
87
|
-
import
|
|
88
|
-
import * as
|
|
89
|
-
import
|
|
88
|
+
import * as fs9 from 'fs';
|
|
89
|
+
import fs9__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
|
|
90
|
+
import * as path22 from 'path';
|
|
91
|
+
import path22__default, { resolve, join } from 'path';
|
|
90
92
|
import { fileURLToPath } from 'url';
|
|
91
93
|
import { Help, Command, Option } from 'commander';
|
|
92
94
|
import { rcompare } from 'semver';
|
|
95
|
+
import * as os from 'os';
|
|
96
|
+
import { homedir } from 'os';
|
|
93
97
|
import * as p4 from '@clack/prompts';
|
|
94
98
|
import pc5 from 'picocolors';
|
|
95
|
-
import * as os from 'os';
|
|
96
99
|
import { parse, stringify, parseDocument, isMap, isScalar, isSeq } from 'yaml';
|
|
97
100
|
import * as readline from 'readline';
|
|
98
101
|
import { createInterface } from 'readline';
|
|
@@ -128,6 +131,45 @@ function filterCatalogAssets(assets, query) {
|
|
|
128
131
|
(a) => a.name.toLowerCase().includes(q) || (a.description?.toLowerCase().includes(q) ?? false) || a.publisher.toLowerCase().includes(q)
|
|
129
132
|
);
|
|
130
133
|
}
|
|
134
|
+
var STORE_TEST_NAME_RE = /^(test|demo)(-|$)/;
|
|
135
|
+
var STORE_ROW_LIMIT = 20;
|
|
136
|
+
function selectStoreRows(matches, query, all) {
|
|
137
|
+
const q = query?.toLowerCase();
|
|
138
|
+
const rank = (a) => {
|
|
139
|
+
if (!q) return 3;
|
|
140
|
+
const n = a.name.toLowerCase();
|
|
141
|
+
if (n === q) return 0;
|
|
142
|
+
if (n.startsWith(q)) return 1;
|
|
143
|
+
if (n.includes(q)) return 2;
|
|
144
|
+
return 3;
|
|
145
|
+
};
|
|
146
|
+
const ranked = [...matches].sort(
|
|
147
|
+
(a, b) => rank(a) - rank(b) || a.name.localeCompare(b.name) || a.version.localeCompare(b.version)
|
|
148
|
+
);
|
|
149
|
+
if (all) return { shown: ranked, hidden: 0, cut: 0 };
|
|
150
|
+
const keep = ranked.filter(
|
|
151
|
+
(a) => storeNotInstallableReason(a) === void 0 && !a.demo && !STORE_TEST_NAME_RE.test(a.name)
|
|
152
|
+
);
|
|
153
|
+
return {
|
|
154
|
+
shown: keep.slice(0, STORE_ROW_LIMIT),
|
|
155
|
+
hidden: ranked.length - keep.length,
|
|
156
|
+
cut: Math.max(0, keep.length - STORE_ROW_LIMIT)
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function storeSelectionNotes(sel, indent) {
|
|
160
|
+
const notes = [];
|
|
161
|
+
if (sel.cut > 0) {
|
|
162
|
+
notes.push(
|
|
163
|
+
`${indent}${S.dim(`\u2026 ${sel.cut} more store match(es); narrow the query, or pass --all to list every one`)}`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
if (sel.hidden > 0) {
|
|
167
|
+
notes.push(
|
|
168
|
+
`${indent}${S.dim(`${sel.hidden} store entr${sel.hidden === 1 ? "y" : "ies"} hidden: names that are not valid refs, demo/internal entries; --all lists them`)}`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return notes;
|
|
172
|
+
}
|
|
131
173
|
function nearAssetKind(word) {
|
|
132
174
|
const w = word.toLowerCase();
|
|
133
175
|
let best;
|
|
@@ -175,7 +217,7 @@ async function runSearch(kind, query, opts) {
|
|
|
175
217
|
const showLocal = !opts.store;
|
|
176
218
|
const showStore = !opts.local;
|
|
177
219
|
const { resolveConfig } = await import('../library/index.js');
|
|
178
|
-
const airGapped = resolveConfig({ projectDir:
|
|
220
|
+
const airGapped = resolveConfig({ projectDir: path22__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
|
|
179
221
|
if (showLocal) {
|
|
180
222
|
await searchLocal(query, kind, opts, showStore, airGapped);
|
|
181
223
|
}
|
|
@@ -184,7 +226,7 @@ async function runSearch(kind, query, opts) {
|
|
|
184
226
|
}
|
|
185
227
|
}
|
|
186
228
|
async function searchIndex(query, kind) {
|
|
187
|
-
const { openLibrary: openLibrary2 } = await import('../open-library-
|
|
229
|
+
const { openLibrary: openLibrary2 } = await import('../open-library-PZAT3TJA.js');
|
|
188
230
|
const library = await openLibrary2();
|
|
189
231
|
try {
|
|
190
232
|
const { libraryDirMissing: libraryDirMissing2 } = await import('../library/index.js');
|
|
@@ -221,7 +263,7 @@ async function searchIndex(query, kind) {
|
|
|
221
263
|
}
|
|
222
264
|
}
|
|
223
265
|
async function searchFactory(projectDir, query, kind) {
|
|
224
|
-
const prefixes = factoryAssetRoots().map((r) => r.endsWith(
|
|
266
|
+
const prefixes = factoryAssetRoots().map((r) => r.endsWith(path22__default.sep) ? r : r + path22__default.sep);
|
|
225
267
|
const isFactoryPath = (p6) => prefixes.some((fp) => p6 === fp.slice(0, -1) || p6.startsWith(fp));
|
|
226
268
|
try {
|
|
227
269
|
const entries = await new AssetManager({ registry: getKindRegistry(), projectDir }).search(
|
|
@@ -331,11 +373,11 @@ async function expandCompetingOrigins(entries, projectDir) {
|
|
|
331
373
|
return out;
|
|
332
374
|
}
|
|
333
375
|
async function searchLocal(query, kind, opts, showStore, airGapped) {
|
|
334
|
-
const projectDir =
|
|
376
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
335
377
|
const factory = await searchFactory(projectDir, query, kind);
|
|
336
378
|
let entries = unionEntries(await searchIndex(query, kind), factory);
|
|
337
379
|
if (entries.length === 0 && !query && !kind && !airGapped) {
|
|
338
|
-
const { autoSyncForSearch } = await import('../source-
|
|
380
|
+
const { autoSyncForSearch } = await import('../source-36FHMN5V.js');
|
|
339
381
|
if (await autoSyncForSearch(projectDir)) {
|
|
340
382
|
entries = unionEntries(await searchIndex(query, kind), factory);
|
|
341
383
|
}
|
|
@@ -445,34 +487,30 @@ function formatStoreRows(assets, indent, width = terminalWidth()) {
|
|
|
445
487
|
});
|
|
446
488
|
}
|
|
447
489
|
async function searchStore(query, kind, opts, airGapped) {
|
|
448
|
-
if (airGapped) {
|
|
449
|
-
if (opts.store) {
|
|
450
|
-
logErr(
|
|
451
|
-
"air-gapped (catalog.cache_ttl: 0) \u2014 store search is disabled. Set catalog.cache_ttl > 0 to query the store."
|
|
452
|
-
);
|
|
453
|
-
process.exit(1);
|
|
454
|
-
}
|
|
490
|
+
if (airGapped && !opts.store) {
|
|
455
491
|
logInfo("air-gapped (cache_ttl: 0) \u2014 local sources only");
|
|
456
492
|
return;
|
|
457
493
|
}
|
|
458
|
-
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-
|
|
494
|
+
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-PZAT3TJA.js');
|
|
459
495
|
try {
|
|
460
|
-
const remote = await openCatalogSource2({ projectDir:
|
|
496
|
+
const remote = await openCatalogSource2({ projectDir: path22__default.resolve(opts.projectDir) });
|
|
461
497
|
const assets = await remote.listAssets(kind ? { kind } : {});
|
|
462
|
-
const
|
|
463
|
-
if (
|
|
498
|
+
const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
|
|
499
|
+
if (sel.shown.length > 0) {
|
|
464
500
|
console.log(`
|
|
465
501
|
${S.heading("Store:")}`);
|
|
466
|
-
for (const row of formatStoreRows(
|
|
502
|
+
for (const row of formatStoreRows(sel.shown, " ")) console.log(row);
|
|
467
503
|
} else if (opts.store) {
|
|
468
504
|
logInfo("No results in store");
|
|
469
505
|
}
|
|
506
|
+
for (const note of storeSelectionNotes(sel, " ")) console.log(note);
|
|
470
507
|
} catch (e) {
|
|
471
508
|
const local = e instanceof LocalCatalogDisabledError2;
|
|
472
509
|
if (opts.store) {
|
|
473
510
|
logErr(
|
|
474
|
-
local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${e.
|
|
511
|
+
local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${await describeStoreFailure(e, path22__default.resolve(opts.projectDir))}`
|
|
475
512
|
);
|
|
513
|
+
process.exit(1);
|
|
476
514
|
} else {
|
|
477
515
|
logInfo(
|
|
478
516
|
local ? "remote catalog disabled (catalog.url: local) \u2014 showing local results only" : "store unavailable \u2014 showing local results only (run with --store to see the error)"
|
|
@@ -480,8 +518,17 @@ async function searchStore(query, kind, opts, airGapped) {
|
|
|
480
518
|
}
|
|
481
519
|
}
|
|
482
520
|
}
|
|
521
|
+
async function describeStoreFailure(err2, projectDir) {
|
|
522
|
+
const { resolveConfig, describeCatalogError, CatalogHttpError } = await import('../library/index.js');
|
|
523
|
+
const { catalog } = resolveConfig({ projectDir });
|
|
524
|
+
const framingHint = catalog.framing === "rest" && err2 instanceof CatalogHttpError && (err2.status === 404 || err2.status === 405) ? ` catalog.framing is rest; if this host serves tRPC, set it with \`skaile config set catalog.framing trpc\`.` : "";
|
|
525
|
+
return `${describeCatalogError(err2, catalog.url)}.${framingHint} Check the catalog with \`skaile catalog test\`.`;
|
|
526
|
+
}
|
|
483
527
|
function makeSearchCommand() {
|
|
484
|
-
return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind (a single non-kind argument is the query)").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").
|
|
528
|
+
return new Command("search").description("Search across all repos").argument("[kind]", "Filter by asset kind (a single non-kind argument is the query)").argument("[query]", "Search query").option("--project-dir <path>", "Project directory", process.cwd()).option("--store", "Search only the store").option("--local", "Search only local repos").option(
|
|
529
|
+
"--all",
|
|
530
|
+
`Store leg: list every match (default: ${STORE_ROW_LIMIT} rows, only what add can install)`
|
|
531
|
+
).action(async (kind, query, opts) => {
|
|
485
532
|
await runSearch(kind, query, opts);
|
|
486
533
|
});
|
|
487
534
|
}
|
|
@@ -572,7 +619,10 @@ function makeAddCommand() {
|
|
|
572
619
|
).option(
|
|
573
620
|
"--with-soft-deps",
|
|
574
621
|
"also add the asset's report-only soft (body-link) deps, without prompting"
|
|
575
|
-
).option("--no-soft-deps", "skip the soft-dep prompt entirely (don't add, don't report)").
|
|
622
|
+
).option("--no-soft-deps", "skip the soft-dep prompt entirely (don't add, don't report)").option(
|
|
623
|
+
"--force",
|
|
624
|
+
"overwrite a deployed folder that no lock entry owns (a hand-made skill of the same name)"
|
|
625
|
+
).action(async (ref, opts) => {
|
|
576
626
|
if (opts.withSoftDeps && opts.softDeps === false) {
|
|
577
627
|
logErr("--with-soft-deps and --no-soft-deps are mutually exclusive.");
|
|
578
628
|
process.exit(1);
|
|
@@ -580,13 +630,17 @@ function makeAddCommand() {
|
|
|
580
630
|
const harnesses = parseHarnessFilter(opts.harness);
|
|
581
631
|
if (!opts.global && harnesses === void 0) requireProjectConfig(opts.projectDir);
|
|
582
632
|
const warnings = deferredWarnings();
|
|
633
|
+
const collisionKeys = [];
|
|
583
634
|
const am2 = new AssetManager({
|
|
584
635
|
registry: getKindRegistry(),
|
|
585
|
-
projectDir:
|
|
636
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
586
637
|
global: opts.global || harnesses !== void 0,
|
|
587
638
|
harnesses,
|
|
588
639
|
driverTarget: opts.target,
|
|
589
|
-
onLibraryCollision:
|
|
640
|
+
onLibraryCollision: (msg) => {
|
|
641
|
+
collisionKeys.push(msg.split(" exists in ")[0]);
|
|
642
|
+
warnings.push(msg);
|
|
643
|
+
}
|
|
590
644
|
});
|
|
591
645
|
const spinner = createSpinner();
|
|
592
646
|
spinner.start(`Adding ${ref}`);
|
|
@@ -597,6 +651,7 @@ function makeAddCommand() {
|
|
|
597
651
|
const skippedEnv = /* @__PURE__ */ new Set();
|
|
598
652
|
const added = await am2.add(ref, {
|
|
599
653
|
link: opts.link,
|
|
654
|
+
force: opts.force,
|
|
600
655
|
onLibraryOrigin: (deployedRef, library) => libraryOf.set(deployedRef, library),
|
|
601
656
|
onLibraryMoved: (m) => warnings.push(`${m.ref} moved from ${m.from} to ${m.to}`),
|
|
602
657
|
onPresets: (expanded) => {
|
|
@@ -644,9 +699,27 @@ function makeAddCommand() {
|
|
|
644
699
|
const library = libraryOf.get(a);
|
|
645
700
|
logOk(library ? `${a} (library ${library})` : a);
|
|
646
701
|
}
|
|
702
|
+
if (am2.global) {
|
|
703
|
+
for (const a of added) {
|
|
704
|
+
const { kind, name } = parseAssetRef(a);
|
|
705
|
+
const component = installTargetOf(getKindRegistry(), kind);
|
|
706
|
+
if (!component) continue;
|
|
707
|
+
for (const harness of am2.deployTargets()) {
|
|
708
|
+
const dir = deployedDir(component, name, harness, true);
|
|
709
|
+
if (existsSync(dir)) logInfo(S.dim(`${harness}: ${dir.replace(homedir(), "~")}`));
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
if (added.length > 1) {
|
|
714
|
+
logInfo(S.dim(`${added.length} assets deployed (${ref} and ${added.length - 1} more)`));
|
|
715
|
+
}
|
|
647
716
|
}
|
|
648
717
|
const addOrigins = await competingOriginsOf(am2, ref);
|
|
649
|
-
|
|
718
|
+
const asked = parseRefTolerant(ref);
|
|
719
|
+
const alreadyWarned = collisionKeys.some(
|
|
720
|
+
(key) => key.startsWith(`${asked?.kind}:`) && key.endsWith(`/${asked?.name}`)
|
|
721
|
+
);
|
|
722
|
+
if (addOrigins && !alreadyWarned) {
|
|
650
723
|
const [first, ...rest] = addOrigins;
|
|
651
724
|
logInfo(
|
|
652
725
|
S.dim(
|
|
@@ -673,7 +746,7 @@ function makeRemoveCommand() {
|
|
|
673
746
|
requireProjectConfig(opts.projectDir, { allowMissing: true });
|
|
674
747
|
const am2 = new AssetManager({
|
|
675
748
|
registry: getKindRegistry(),
|
|
676
|
-
projectDir:
|
|
749
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
677
750
|
global: opts.global || harnesses !== void 0,
|
|
678
751
|
harnesses,
|
|
679
752
|
driverTarget: opts.target
|
|
@@ -735,15 +808,14 @@ function makeListCommand() {
|
|
|
735
808
|
}
|
|
736
809
|
const am2 = new AssetManager({
|
|
737
810
|
registry: getKindRegistry(),
|
|
738
|
-
projectDir:
|
|
811
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
739
812
|
driverTarget: opts.target
|
|
740
813
|
});
|
|
741
814
|
let declared;
|
|
742
815
|
try {
|
|
743
816
|
declared = await am2.listDeclared(kind);
|
|
744
817
|
} catch (err2) {
|
|
745
|
-
if (err2 instanceof MissingManifestError)
|
|
746
|
-
logErr(`No ${S.cmd("skaile.yaml")} found. Run ${S.cmd("skaile init")} to create one.`);
|
|
818
|
+
if (err2 instanceof MissingManifestError) logNoProject(opts.projectDir);
|
|
747
819
|
else logErr(err2 instanceof Error ? err2.message : String(err2));
|
|
748
820
|
process.exit(1);
|
|
749
821
|
}
|
|
@@ -783,7 +855,7 @@ function makeListCommand() {
|
|
|
783
855
|
function runGlobalList(kind, opts, harnesses) {
|
|
784
856
|
const am2 = new AssetManager({
|
|
785
857
|
registry: getKindRegistry(),
|
|
786
|
-
projectDir:
|
|
858
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
787
859
|
global: true,
|
|
788
860
|
harnesses
|
|
789
861
|
});
|
|
@@ -856,7 +928,7 @@ async function resolveInfoEntry(am2, ref, opts) {
|
|
|
856
928
|
return { entry: match ?? deployed };
|
|
857
929
|
}
|
|
858
930
|
const lookup = opts.storeLookup ?? (async (filter) => {
|
|
859
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
931
|
+
const { resolveCatalogSource } = await import('../open-library-PZAT3TJA.js');
|
|
860
932
|
const { source, close } = await resolveCatalogSource({ projectDir: opts.projectDir });
|
|
861
933
|
try {
|
|
862
934
|
return await source.listAssets(filter);
|
|
@@ -872,7 +944,7 @@ async function resolveInfoEntry(am2, ref, opts) {
|
|
|
872
944
|
);
|
|
873
945
|
return { entry: hit ? catalogAssetToEntry(hit) : null };
|
|
874
946
|
} catch (err2) {
|
|
875
|
-
const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-
|
|
947
|
+
const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-PZAT3TJA.js');
|
|
876
948
|
const storeNote = err2 instanceof Error ? err2.message : String(err2);
|
|
877
949
|
const disabled = err2 instanceof LocalCatalogDisabledError2 || /catalog\.url/i.test(storeNote);
|
|
878
950
|
return { entry: null, storeNote, ...disabled ? { storeDisabled: true } : {} };
|
|
@@ -888,7 +960,8 @@ function infoNotFoundHint(ref, lookup) {
|
|
|
888
960
|
}
|
|
889
961
|
function makeInfoCommand() {
|
|
890
962
|
return new Command("info").description("Show asset metadata, deps, deploy status").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
|
|
891
|
-
const projectDir =
|
|
963
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
964
|
+
requireProjectConfig(projectDir, { allowMissing: true });
|
|
892
965
|
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
|
|
893
966
|
const lookup = await resolveInfoEntry(am2, ref, { projectDir });
|
|
894
967
|
const entry = lookup.entry;
|
|
@@ -937,7 +1010,7 @@ function makeCreateCommand() {
|
|
|
937
1010
|
new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...SCAFFOLD_KINDS])
|
|
938
1011
|
).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
|
|
939
1012
|
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
|
|
940
|
-
const destDir = opts.dir ?
|
|
1013
|
+
const destDir = opts.dir ? path22__default.resolve(opts.dir) : process.cwd();
|
|
941
1014
|
const result = am2.create(name, opts.kind, destDir);
|
|
942
1015
|
if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
|
|
943
1016
|
else {
|
|
@@ -951,14 +1024,16 @@ function makeDoctorCommand() {
|
|
|
951
1024
|
requireProjectConfig(opts.projectDir);
|
|
952
1025
|
const am2 = new AssetManager({
|
|
953
1026
|
registry: getKindRegistry(),
|
|
954
|
-
projectDir:
|
|
1027
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
955
1028
|
});
|
|
956
1029
|
const { gaps } = await am2.projectState();
|
|
957
|
-
|
|
1030
|
+
const edited = await editedConventionFiles(path22__default.resolve(opts.projectDir));
|
|
1031
|
+
if (gaps.length === 0 && edited.length === 0) {
|
|
958
1032
|
logOk("No missing dependencies.");
|
|
959
1033
|
return;
|
|
960
1034
|
}
|
|
961
1035
|
process.exitCode = 1;
|
|
1036
|
+
for (const e of edited) logErr(e);
|
|
962
1037
|
for (const g of gaps) if (g.type !== "requires") logErr(g.message);
|
|
963
1038
|
const missing = gaps.filter((g) => g.type === "requires" && g.asset !== void 0);
|
|
964
1039
|
if (missing.length === 0) return;
|
|
@@ -983,21 +1058,21 @@ function claudeSkillRoots() {
|
|
|
983
1058
|
const roots = [];
|
|
984
1059
|
const override = process.env.SKAILE_CLAUDE_SKILLS_DIR;
|
|
985
1060
|
if (override) roots.push(override);
|
|
986
|
-
roots.push(
|
|
1061
|
+
roots.push(path22.join(os.homedir(), ".claude", "skills"));
|
|
987
1062
|
return roots;
|
|
988
1063
|
}
|
|
989
1064
|
function resolveImportSource(nameOrPath) {
|
|
990
|
-
const asPath =
|
|
991
|
-
if (
|
|
992
|
-
const dir =
|
|
993
|
-
const skillFile =
|
|
994
|
-
if (
|
|
1065
|
+
const asPath = path22.resolve(nameOrPath);
|
|
1066
|
+
if (fs9.existsSync(asPath)) {
|
|
1067
|
+
const dir = fs9.statSync(asPath).isDirectory() ? asPath : path22.dirname(asPath);
|
|
1068
|
+
const skillFile = path22.join(dir, "SKILL.md");
|
|
1069
|
+
if (fs9.existsSync(skillFile)) return { dir, skillFile, via: "path" };
|
|
995
1070
|
}
|
|
996
|
-
if (!nameOrPath.includes(
|
|
1071
|
+
if (!nameOrPath.includes(path22.sep) && !nameOrPath.startsWith(".")) {
|
|
997
1072
|
for (const root of claudeSkillRoots()) {
|
|
998
|
-
const dir =
|
|
999
|
-
const skillFile =
|
|
1000
|
-
if (
|
|
1073
|
+
const dir = path22.join(root, nameOrPath);
|
|
1074
|
+
const skillFile = path22.join(dir, "SKILL.md");
|
|
1075
|
+
if (fs9.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
|
|
1001
1076
|
}
|
|
1002
1077
|
}
|
|
1003
1078
|
return null;
|
|
@@ -1052,6 +1127,12 @@ ${body}
|
|
|
1052
1127
|
}
|
|
1053
1128
|
|
|
1054
1129
|
// cli/src/commands/asset-cmd.ts
|
|
1130
|
+
function copyFilter(root) {
|
|
1131
|
+
return (src) => {
|
|
1132
|
+
const rel = path22.relative(root, src).split(path22.sep).join("/");
|
|
1133
|
+
return rel === "" || !(isNonAssetPath(rel) || isNonAssetDir(path22.basename(src)));
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1055
1136
|
async function resolveDefByRef(library, ref, opts) {
|
|
1056
1137
|
let parsed;
|
|
1057
1138
|
try {
|
|
@@ -1124,19 +1205,25 @@ function makeAssetCommand() {
|
|
|
1124
1205
|
process.exit(1);
|
|
1125
1206
|
}
|
|
1126
1207
|
exitOnManifestPublisherProblems(target.path, target.name);
|
|
1127
|
-
|
|
1208
|
+
if (reportLibrarySymlinks(src.dir, { rootIsAsset: true }) > 0) {
|
|
1209
|
+
logErr(
|
|
1210
|
+
`Not imported: ${src.dir} holds symlinks (listed above). Replace each with a copy of what it points at, or remove it, and run the import again.`
|
|
1211
|
+
);
|
|
1212
|
+
process.exit(1);
|
|
1213
|
+
}
|
|
1214
|
+
const rawSkill = fs9.readFileSync(src.skillFile, "utf8");
|
|
1128
1215
|
const norm = opts.normalize ? normalizeSkillContent(rawSkill, {
|
|
1129
|
-
fallbackName:
|
|
1216
|
+
fallbackName: path22.basename(src.dir),
|
|
1130
1217
|
version: opts.version,
|
|
1131
1218
|
stage: opts.stage
|
|
1132
|
-
}) : { content: rawSkill, name:
|
|
1219
|
+
}) : { content: rawSkill, name: path22.basename(src.dir), changed: false, notes: [] };
|
|
1133
1220
|
if (!opts.normalize && !isValidAssetName(norm.name)) {
|
|
1134
1221
|
logWarn(
|
|
1135
1222
|
`Name "${norm.name}" is not canonical (kebab-case); \`skaile validate\` will reject this manifest entry. Drop --no-normalize to slugify it.`
|
|
1136
1223
|
);
|
|
1137
1224
|
}
|
|
1138
|
-
const destDir =
|
|
1139
|
-
if (
|
|
1225
|
+
const destDir = path22.join(target.path, norm.name);
|
|
1226
|
+
if (fs9.existsSync(destDir)) {
|
|
1140
1227
|
logErr(`Destination already exists: ${destDir}`);
|
|
1141
1228
|
process.exit(1);
|
|
1142
1229
|
}
|
|
@@ -1147,8 +1234,27 @@ function makeAssetCommand() {
|
|
|
1147
1234
|
);
|
|
1148
1235
|
process.exit(1);
|
|
1149
1236
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1237
|
+
const importedFm = parseFrontmatter(norm.content);
|
|
1238
|
+
const checked = checkAsset(
|
|
1239
|
+
"skill",
|
|
1240
|
+
importedFm.data,
|
|
1241
|
+
importedFm.body,
|
|
1242
|
+
norm.name,
|
|
1243
|
+
getKindRegistry(),
|
|
1244
|
+
norm.content
|
|
1245
|
+
);
|
|
1246
|
+
if (checked.errors.length > 0) {
|
|
1247
|
+
for (const f of checked.errors) logErr(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
|
|
1248
|
+
logErr(
|
|
1249
|
+
`Not imported: ${checked.errors.length} problem(s) in SKILL.md. Fix them in ${src.skillFile} (or drop --no-normalize) and run the import again.`
|
|
1250
|
+
);
|
|
1251
|
+
process.exit(1);
|
|
1252
|
+
}
|
|
1253
|
+
for (const f of checked.advisories) {
|
|
1254
|
+
logWarn(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
|
|
1255
|
+
}
|
|
1256
|
+
fs9.cpSync(src.dir, destDir, { recursive: true, filter: copyFilter(src.dir) });
|
|
1257
|
+
fs9.writeFileSync(path22.join(destDir, "SKILL.md"), norm.content, "utf8");
|
|
1152
1258
|
for (const note of norm.notes) logInfo(` \u2022 ${note}`);
|
|
1153
1259
|
const fm = parseFrontmatter(norm.content).data;
|
|
1154
1260
|
for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
|
|
@@ -1188,7 +1294,7 @@ function makeAssetCommand() {
|
|
|
1188
1294
|
logErr(`Invalid --mode "${opts.mode}". Expected: copy | move | link.`);
|
|
1189
1295
|
process.exit(1);
|
|
1190
1296
|
}
|
|
1191
|
-
if (!
|
|
1297
|
+
if (!fs9.existsSync(srcPath)) {
|
|
1192
1298
|
logErr(`Source path does not exist: ${srcPath}`);
|
|
1193
1299
|
process.exit(1);
|
|
1194
1300
|
}
|
|
@@ -1214,23 +1320,29 @@ function makeAssetCommand() {
|
|
|
1214
1320
|
);
|
|
1215
1321
|
process.exit(1);
|
|
1216
1322
|
}
|
|
1217
|
-
const basename3 =
|
|
1323
|
+
const basename3 = path22.basename(srcPath);
|
|
1218
1324
|
const destDir = target.path;
|
|
1219
|
-
|
|
1220
|
-
const destPath =
|
|
1221
|
-
if (
|
|
1325
|
+
fs9.mkdirSync(destDir, { recursive: true });
|
|
1326
|
+
const destPath = path22.join(destDir, basename3);
|
|
1327
|
+
if (fs9.existsSync(destPath)) {
|
|
1222
1328
|
logErr(`Destination already exists: ${destPath}`);
|
|
1223
1329
|
process.exit(1);
|
|
1224
1330
|
}
|
|
1331
|
+
if (opts.mode === "copy" && reportLibrarySymlinks(srcPath, { rootIsAsset: true }) > 0) {
|
|
1332
|
+
logErr(
|
|
1333
|
+
`Not migrated: ${srcPath} holds symlinks (listed above). Replace each with a copy of what it points at, or remove it, and run the migrate again.`
|
|
1334
|
+
);
|
|
1335
|
+
process.exit(1);
|
|
1336
|
+
}
|
|
1225
1337
|
switch (opts.mode) {
|
|
1226
1338
|
case "copy":
|
|
1227
|
-
|
|
1339
|
+
fs9.cpSync(srcPath, destPath, { recursive: true, filter: copyFilter(srcPath) });
|
|
1228
1340
|
break;
|
|
1229
1341
|
case "move":
|
|
1230
|
-
|
|
1342
|
+
fs9.renameSync(srcPath, destPath);
|
|
1231
1343
|
break;
|
|
1232
1344
|
case "link":
|
|
1233
|
-
|
|
1345
|
+
fs9.symlinkSync(path22.resolve(srcPath), destPath);
|
|
1234
1346
|
break;
|
|
1235
1347
|
}
|
|
1236
1348
|
if (target.backend === "git" && opts.commit) {
|
|
@@ -1245,6 +1357,11 @@ function makeAssetCommand() {
|
|
|
1245
1357
|
}
|
|
1246
1358
|
}
|
|
1247
1359
|
logOk(`Migrated ${basename3} \u2192 ${target.name} (${opts.mode})`);
|
|
1360
|
+
const publisher = loadSkPublishManifest(target.path)?.publisher ?? "<publisher>";
|
|
1361
|
+
const migratedKind = fs9.existsSync(path22.join(destPath, "SKILL.md")) ? "skill" : "<kind>";
|
|
1362
|
+
logInfo(
|
|
1363
|
+
`Not addable yet: run ${S.cmd(`skaile library index ${target.name}`)}, then ${S.cmd(`skaile add ${migratedKind}:@${publisher.replace(/^@/, "")}/${basename3}`)}`
|
|
1364
|
+
);
|
|
1248
1365
|
if (opts.mode === "move") {
|
|
1249
1366
|
logInfo("Source moved into the library \u2014 future edits modify the library copy.");
|
|
1250
1367
|
} else if (opts.mode === "copy") {
|
|
@@ -1360,14 +1477,14 @@ function makeAuthCommand() {
|
|
|
1360
1477
|
}
|
|
1361
1478
|
function collectCacheTargets(scope) {
|
|
1362
1479
|
const out = [];
|
|
1363
|
-
out.push(
|
|
1364
|
-
out.push(
|
|
1365
|
-
out.push(
|
|
1480
|
+
out.push(path22__default.join(scope.projectDir, ".skaile", "cache"));
|
|
1481
|
+
out.push(path22__default.join(scope.projectDir, ".skaile", "store-cache"));
|
|
1482
|
+
out.push(path22__default.join(scope.projectDir, ".skaile", "repos"));
|
|
1366
1483
|
if (scope.global) {
|
|
1367
1484
|
out.push(globalCacheRoot());
|
|
1368
1485
|
const home = globalSkaileDir();
|
|
1369
|
-
out.push(
|
|
1370
|
-
out.push(
|
|
1486
|
+
out.push(path22__default.join(home, "repos"));
|
|
1487
|
+
out.push(path22__default.join(home, "catalog-cache"));
|
|
1371
1488
|
}
|
|
1372
1489
|
return out;
|
|
1373
1490
|
}
|
|
@@ -1381,7 +1498,7 @@ function dirSize(target) {
|
|
|
1381
1498
|
function dirSizeOfDir(dir) {
|
|
1382
1499
|
let total = 0;
|
|
1383
1500
|
for (const ent of readdirSync(dir, { withFileTypes: true })) {
|
|
1384
|
-
const child =
|
|
1501
|
+
const child = path22__default.join(dir, ent.name);
|
|
1385
1502
|
if (ent.isSymbolicLink()) continue;
|
|
1386
1503
|
if (ent.isDirectory()) total += dirSizeOfDir(child);
|
|
1387
1504
|
else if (ent.isFile()) total += statSync(child).size;
|
|
@@ -1407,7 +1524,7 @@ function makeCacheCommand() {
|
|
|
1407
1524
|
const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
|
|
1408
1525
|
cmd.command("clean").description("Remove the project cache (.skaile/cache); --global also clears ~/.skaile/cache").option("--global", "Also clear the global cache (sources + catalog) and legacy dirs").option("--dry-run", "Show what would be removed without doing it").option("-y, --yes", "Skip confirmation prompt").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
1409
1526
|
const targets = collectCacheTargets({
|
|
1410
|
-
projectDir:
|
|
1527
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
1411
1528
|
global: opts.global
|
|
1412
1529
|
}).filter((t) => existsSync(t));
|
|
1413
1530
|
if (targets.length === 0) {
|
|
@@ -1437,12 +1554,12 @@ function makeCacheCommand() {
|
|
|
1437
1554
|
for (const r of removed) logOk(`Removed ${r}`);
|
|
1438
1555
|
});
|
|
1439
1556
|
cmd.command("dir").description("Print the resolved cache roots").option("--global", "Include the global cache root").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
1440
|
-
console.log(
|
|
1557
|
+
console.log(path22__default.join(path22__default.resolve(opts.projectDir), ".skaile", "cache"));
|
|
1441
1558
|
if (opts.global) console.log(globalCacheRoot());
|
|
1442
1559
|
});
|
|
1443
1560
|
cmd.command("size").description("Show cache disk usage per directory").option("--global", "Include the global cache").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
1444
1561
|
const targets = collectCacheTargets({
|
|
1445
|
-
projectDir:
|
|
1562
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
1446
1563
|
global: opts.global
|
|
1447
1564
|
});
|
|
1448
1565
|
console.log();
|
|
@@ -1458,7 +1575,7 @@ function makeCatalogCommand() {
|
|
|
1458
1575
|
const catalog = new Command("catalog").description("Catalog source health and configuration");
|
|
1459
1576
|
catalog.command("test").description("Probe the configured catalog source and report status").option("--project-dir <path>", "Project directory (for project-level config overlay)").option("--url <url>", "Override the catalog URL for this probe").option("--force", "Probe the network even in air-gapped mode (cache_ttl: 0)").action(async (opts) => {
|
|
1460
1577
|
const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
|
|
1461
|
-
const projectDir = opts.projectDir ?
|
|
1578
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : void 0;
|
|
1462
1579
|
const cfg = resolveConfig({ projectDir });
|
|
1463
1580
|
const baseUrl = opts.url ?? cfg.catalog.url;
|
|
1464
1581
|
if (isLocalCatalogUrl(baseUrl)) {
|
|
@@ -1472,11 +1589,15 @@ function makeCatalogCommand() {
|
|
|
1472
1589
|
);
|
|
1473
1590
|
return;
|
|
1474
1591
|
}
|
|
1475
|
-
await runRemoteCatalogProbe(
|
|
1592
|
+
await runRemoteCatalogProbe(
|
|
1593
|
+
baseUrl,
|
|
1594
|
+
cfg.catalog.framing,
|
|
1595
|
+
trpcGetUrl(baseUrl, "catalog.listKinds", void 0)
|
|
1596
|
+
);
|
|
1476
1597
|
});
|
|
1477
1598
|
catalog.command("info").description("Print the resolved catalog configuration (url, framing, cacheTtlMs)").option("--project-dir <path>", "Project directory (for project-level config overlay)").action(async (opts) => {
|
|
1478
1599
|
const { resolveConfig } = await import('../library/index.js');
|
|
1479
|
-
const projectDir = opts.projectDir ?
|
|
1600
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : void 0;
|
|
1480
1601
|
const cfg = resolveConfig({ projectDir });
|
|
1481
1602
|
console.log(`url: ${cfg.catalog.url}`);
|
|
1482
1603
|
console.log(`framing: ${cfg.catalog.framing}`);
|
|
@@ -1485,14 +1606,16 @@ function makeCatalogCommand() {
|
|
|
1485
1606
|
return catalog;
|
|
1486
1607
|
}
|
|
1487
1608
|
async function runLocalCatalogTest(projectDir) {
|
|
1488
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
1609
|
+
const { resolveCatalogSource } = await import('../open-library-PZAT3TJA.js');
|
|
1489
1610
|
let resolved;
|
|
1490
1611
|
try {
|
|
1491
1612
|
resolved = await resolveCatalogSource({ projectDir });
|
|
1492
1613
|
const sources = await resolved.source.listSources();
|
|
1493
1614
|
logOk("Catalog mode: local");
|
|
1494
1615
|
if (sources.length === 0) {
|
|
1495
|
-
logInfo(
|
|
1616
|
+
logInfo(
|
|
1617
|
+
"No local sources registered. Run `skaile library init <name> --path <dir>` first (a git repo: `skaile source add <git-url>`)."
|
|
1618
|
+
);
|
|
1496
1619
|
} else {
|
|
1497
1620
|
for (const s of sources) {
|
|
1498
1621
|
console.log(` ${S.dim("\u2022")} ${s.type} ${S.heading(s.url)}`);
|
|
@@ -1513,7 +1636,8 @@ function isTrpcEnvelope(text) {
|
|
|
1513
1636
|
return false;
|
|
1514
1637
|
}
|
|
1515
1638
|
}
|
|
1516
|
-
async function runRemoteCatalogProbe(baseUrl,
|
|
1639
|
+
async function runRemoteCatalogProbe(baseUrl, framing, trpcProbeUrl) {
|
|
1640
|
+
const probeUrl = framing === "rest" ? `${baseUrl.replace(/\/+$/, "")}/api/catalog/list` : trpcProbeUrl;
|
|
1517
1641
|
const controller = new AbortController();
|
|
1518
1642
|
const timeout = setTimeout(() => controller.abort(), 5e3);
|
|
1519
1643
|
try {
|
|
@@ -1524,10 +1648,24 @@ async function runRemoteCatalogProbe(baseUrl, probeUrl) {
|
|
|
1524
1648
|
});
|
|
1525
1649
|
const ms = Date.now() - started;
|
|
1526
1650
|
if (!res.ok) {
|
|
1651
|
+
if (framing === "rest" && (res.status === 404 || res.status === 405)) {
|
|
1652
|
+
const trpc = await fetch(trpcProbeUrl, {
|
|
1653
|
+
signal: controller.signal,
|
|
1654
|
+
headers: { accept: "application/json" }
|
|
1655
|
+
}).catch(() => null);
|
|
1656
|
+
if (trpc?.ok && isTrpcEnvelope((await trpc.text()).trim())) {
|
|
1657
|
+
logErr(
|
|
1658
|
+
`${baseUrl} serves the tRPC catalog, but catalog.framing is rest (${probeUrl} answered ${res.status}).`
|
|
1659
|
+
);
|
|
1660
|
+
logInfo(`Set it with: skaile config set catalog.framing trpc`);
|
|
1661
|
+
process.exitCode = 1;
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1527
1665
|
logErr(`${probeUrl} responded ${res.status} ${res.statusText} (${ms}ms)`);
|
|
1528
1666
|
if (res.status === 404) {
|
|
1529
1667
|
logInfo(
|
|
1530
|
-
`Got 404 from catalog.listKinds. Check the URL prefix in ${userConfigPath()} \u2014 Skaile mirrors must expose \`/trpc/catalog.*\` at the configured baseUrl.`
|
|
1668
|
+
framing === "rest" ? `Got 404 from /api/catalog/list (catalog.framing is rest). Check the URL prefix in ${userConfigPath()}.` : `Got 404 from catalog.listKinds. Check the URL prefix in ${userConfigPath()} \u2014 Skaile mirrors must expose \`/trpc/catalog.*\` at the configured baseUrl.`
|
|
1531
1669
|
);
|
|
1532
1670
|
} else {
|
|
1533
1671
|
logInfo(
|
|
@@ -1538,17 +1676,27 @@ async function runRemoteCatalogProbe(baseUrl, probeUrl) {
|
|
|
1538
1676
|
return;
|
|
1539
1677
|
}
|
|
1540
1678
|
const text = (await res.text()).trim();
|
|
1541
|
-
if (
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1679
|
+
if (framing === "trpc") {
|
|
1680
|
+
if (!isTrpcEnvelope(text)) {
|
|
1681
|
+
logWarn(
|
|
1682
|
+
`Catalog reachable at ${baseUrl} (${ms}ms) but the response is not a valid tRPC envelope.`
|
|
1683
|
+
);
|
|
1684
|
+
logInfo(
|
|
1685
|
+
"The host responded 200 but the body is not Skaile's catalog router shape. Check that `catalog.listKinds` is mounted at the configured baseUrl."
|
|
1686
|
+
);
|
|
1687
|
+
process.exitCode = 1;
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
} else {
|
|
1691
|
+
try {
|
|
1692
|
+
JSON.parse(text);
|
|
1693
|
+
} catch {
|
|
1694
|
+
logWarn(`Catalog reachable at ${baseUrl} (${ms}ms) but /api/catalog/list is not JSON.`);
|
|
1695
|
+
process.exitCode = 1;
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1550
1698
|
}
|
|
1551
|
-
logOk(`Catalog reachable at ${S.heading(baseUrl)} (${ms}ms)`);
|
|
1699
|
+
logOk(`Catalog reachable at ${S.heading(baseUrl)} (${ms}ms, framing ${framing})`);
|
|
1552
1700
|
} catch (err2) {
|
|
1553
1701
|
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
1554
1702
|
logErr(`Timeout reaching ${probeUrl} after 5s`);
|
|
@@ -1628,7 +1776,7 @@ async function scanLibraryFlowEntries() {
|
|
|
1628
1776
|
const { LocalIndex, resolveIndexPath, scanAuthoringLibraries } = await import('../library/index.js');
|
|
1629
1777
|
const indexPath = resolveIndexPath();
|
|
1630
1778
|
if (!existsSync(indexPath)) return entries;
|
|
1631
|
-
const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-
|
|
1779
|
+
const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-W46UXZ3I.js');
|
|
1632
1780
|
const index = new LocalIndex({ indexPath });
|
|
1633
1781
|
try {
|
|
1634
1782
|
for (const { assets } of await scanAuthoringLibraries(index, getKindRegistry2())) {
|
|
@@ -1678,11 +1826,11 @@ function findSkills() {
|
|
|
1678
1826
|
return deduped;
|
|
1679
1827
|
}
|
|
1680
1828
|
function walkSkills(dir, out) {
|
|
1681
|
-
for (const entry of
|
|
1682
|
-
const full =
|
|
1829
|
+
for (const entry of fs9__default.readdirSync(dir, { withFileTypes: true })) {
|
|
1830
|
+
const full = path22__default.join(dir, entry.name);
|
|
1683
1831
|
if (entry.isDirectory()) {
|
|
1684
|
-
const skillMd =
|
|
1685
|
-
if (
|
|
1832
|
+
const skillMd = path22__default.join(full, "SKILL.md");
|
|
1833
|
+
if (fs9__default.existsSync(skillMd)) {
|
|
1686
1834
|
out.push({ name: entry.name, path: full, skillPath: skillMd });
|
|
1687
1835
|
} else {
|
|
1688
1836
|
walkSkills(full, out);
|
|
@@ -1703,10 +1851,10 @@ function resolveFlowIds() {
|
|
|
1703
1851
|
}
|
|
1704
1852
|
}
|
|
1705
1853
|
function resolveSessionIds(projectDir) {
|
|
1706
|
-
const sessionsDir =
|
|
1707
|
-
if (!
|
|
1854
|
+
const sessionsDir = path22__default.join(projectDir, ".skaile", "sessions");
|
|
1855
|
+
if (!fs9__default.existsSync(sessionsDir)) return [];
|
|
1708
1856
|
try {
|
|
1709
|
-
return
|
|
1857
|
+
return fs9__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
1710
1858
|
} catch {
|
|
1711
1859
|
return [];
|
|
1712
1860
|
}
|
|
@@ -1759,6 +1907,33 @@ function resolveDynamic(words, cword) {
|
|
|
1759
1907
|
return null;
|
|
1760
1908
|
}
|
|
1761
1909
|
var PERSONAL_KEYS = /* @__PURE__ */ new Set(["driver", "model"]);
|
|
1910
|
+
var CATALOG_KEYS = /* @__PURE__ */ new Set(["catalog.url", "catalog.cache_ttl", "catalog.framing"]);
|
|
1911
|
+
async function setCatalogKey(key, raw) {
|
|
1912
|
+
const { CatalogConfigSchema, saveConfig } = await import('../library/index.js');
|
|
1913
|
+
const { parse: parseYaml5 } = await import('yaml');
|
|
1914
|
+
const field = key.slice("catalog.".length);
|
|
1915
|
+
const value = field === "cache_ttl" ? /^\d+$/.test(raw.trim()) ? Number(raw) : raw : raw;
|
|
1916
|
+
const checked = CatalogConfigSchema.safeParse({ [field]: value });
|
|
1917
|
+
if (!checked.success) {
|
|
1918
|
+
const hint = field === "url" ? 'a http(s) URL, or "local" to turn the remote catalog off' : field === "cache_ttl" ? "a whole number of seconds (0 = air-gapped)" : '"trpc" or "rest"';
|
|
1919
|
+
logErr(`'${key}' must be ${hint}; got "${raw}".`);
|
|
1920
|
+
process.exit(1);
|
|
1921
|
+
}
|
|
1922
|
+
const filePath = userConfigPath();
|
|
1923
|
+
const fs14 = await import('fs');
|
|
1924
|
+
let existing = {};
|
|
1925
|
+
if (fs14.existsSync(filePath)) {
|
|
1926
|
+
const parsed = parseYaml5(fs14.readFileSync(filePath, "utf-8"));
|
|
1927
|
+
if (parsed && typeof parsed === "object") existing = parsed;
|
|
1928
|
+
}
|
|
1929
|
+
const catalog = {
|
|
1930
|
+
...existing.catalog ?? {},
|
|
1931
|
+
[field]: checked.data[field]
|
|
1932
|
+
};
|
|
1933
|
+
saveConfig(filePath, { ...existing, catalog });
|
|
1934
|
+
logOk(`Set ${pc5.bold(key)} = ${String(checked.data[field])}`);
|
|
1935
|
+
console.log(S.dim(` \u2192 ${filePath}`));
|
|
1936
|
+
}
|
|
1762
1937
|
var API_KEY_PREFIX = "apiKey.";
|
|
1763
1938
|
function collectWorkspaceDefaults(projectDir) {
|
|
1764
1939
|
const wsDefaults = {};
|
|
@@ -1774,14 +1949,17 @@ function collectWorkspaceDefaults(projectDir) {
|
|
|
1774
1949
|
}
|
|
1775
1950
|
return wsDefaults;
|
|
1776
1951
|
}
|
|
1777
|
-
function printEffectiveSection(config) {
|
|
1952
|
+
function printEffectiveSection(config, sources) {
|
|
1778
1953
|
console.log();
|
|
1779
1954
|
console.log(S.heading(" Effective Config"));
|
|
1780
1955
|
console.log(` ${S.rule(40)}`);
|
|
1781
1956
|
for (const key of ["driver", "model"]) {
|
|
1782
1957
|
const value = config[key];
|
|
1783
1958
|
if (value !== void 0) {
|
|
1784
|
-
|
|
1959
|
+
const origin = sources[key];
|
|
1960
|
+
console.log(
|
|
1961
|
+
` ${S.label(`${key}:`.padEnd(16))} ${value}${origin ? ` ${S.dim(`(${origin})`)}` : ""}`
|
|
1962
|
+
);
|
|
1785
1963
|
}
|
|
1786
1964
|
}
|
|
1787
1965
|
}
|
|
@@ -1845,17 +2023,18 @@ function printResolvedPathsSection(config) {
|
|
|
1845
2023
|
console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
|
|
1846
2024
|
}
|
|
1847
2025
|
async function showConfig(opts) {
|
|
1848
|
-
const projectDir = opts.projectDir ?
|
|
2026
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
|
|
1849
2027
|
let config;
|
|
2028
|
+
let sources;
|
|
1850
2029
|
let wsDefaults;
|
|
1851
2030
|
try {
|
|
1852
|
-
config = await
|
|
2031
|
+
({ settings: config, sources } = await resolveSettingsWithSources(projectDir));
|
|
1853
2032
|
wsDefaults = collectWorkspaceDefaults(projectDir);
|
|
1854
2033
|
} catch (error) {
|
|
1855
2034
|
logErr(error instanceof Error ? error.message : String(error));
|
|
1856
2035
|
process.exit(1);
|
|
1857
2036
|
}
|
|
1858
|
-
printEffectiveSection(config);
|
|
2037
|
+
printEffectiveSection(config, sources);
|
|
1859
2038
|
printWorkspaceDefaultsSection(wsDefaults);
|
|
1860
2039
|
printModelSelectionSection(config, projectDir);
|
|
1861
2040
|
printResolvedPathsSection(config);
|
|
@@ -1890,13 +2069,25 @@ function makeConfigCommand() {
|
|
|
1890
2069
|
const cmd = new Command("config").description("Manage personal config (.skaile/settings.json)");
|
|
1891
2070
|
cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
|
|
1892
2071
|
cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").action(async (key, opts) => {
|
|
1893
|
-
const projectDir = opts.projectDir ?
|
|
2072
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
|
|
2073
|
+
if (CATALOG_KEYS.has(key)) {
|
|
2074
|
+
const { resolveConfig } = await import('../library/index.js');
|
|
2075
|
+
const field = key.slice("catalog.".length);
|
|
2076
|
+
console.log(resolveConfig({ projectDir }).catalog[field]);
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
1894
2079
|
const config = await resolveSettings(projectDir);
|
|
1895
2080
|
const value = config[key];
|
|
1896
2081
|
console.log(value ?? S.dim("(not set)"));
|
|
1897
2082
|
});
|
|
1898
|
-
cmd.command("set <key> <value>").description(
|
|
1899
|
-
|
|
2083
|
+
cmd.command("set <key> <value>").description(
|
|
2084
|
+
"Set a personal config value (driver, model, apiKey.<provider>) or a catalog setting (catalog.url, catalog.cache_ttl, catalog.framing)"
|
|
2085
|
+
).option("--project-dir <path>", "Project directory").option("--global", "Write to ~/.skaile/settings.json instead of project-local").action(async (key, value, opts) => {
|
|
2086
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
|
|
2087
|
+
if (CATALOG_KEYS.has(key)) {
|
|
2088
|
+
await setCatalogKey(key, value);
|
|
2089
|
+
return;
|
|
2090
|
+
}
|
|
1900
2091
|
if (key === "provider" || key === "cloud" || key === "cloudConfig") {
|
|
1901
2092
|
logErr(
|
|
1902
2093
|
`'${key}' is no longer a setting \u2014 an endpoint is an AI provider registry entry and a session selects one with a model reference.
|
|
@@ -1923,6 +2114,14 @@ function makeConfigCommand() {
|
|
|
1923
2114
|
await saveSettings({ ...existing, [key]: value }, filePath);
|
|
1924
2115
|
logOk(`Set ${pc5.bold(key)} = ${value}`);
|
|
1925
2116
|
console.log(S.dim(` \u2192 ${filePath}`));
|
|
2117
|
+
if (key === "driver") {
|
|
2118
|
+
const projectDriver = resolveSkWorkspaceConfig(projectDir).agent_config?.default?.driver;
|
|
2119
|
+
if (projectDriver && projectDriver !== value) {
|
|
2120
|
+
logWarn(
|
|
2121
|
+
`skaile.yaml sets driver ${projectDriver}; a personal driver does not override the project harness. Change agent-config.default.driver in skaile.yaml to move the project.`
|
|
2122
|
+
);
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
1926
2125
|
if (key === "model") {
|
|
1927
2126
|
const view = loadRegistryView({ projectDir });
|
|
1928
2127
|
const resolved = parseModelRef(value, view.merged);
|
|
@@ -2236,8 +2435,8 @@ function makeConnectorCommand() {
|
|
|
2236
2435
|
async (driver, opts) => {
|
|
2237
2436
|
const { installNpmPackages } = await import('../connectors/index.js');
|
|
2238
2437
|
const { scanDirectory: scanDirectory2, factoryAssetRoots: factoryAssetRoots2, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
2239
|
-
const projectDir =
|
|
2240
|
-
const yamlPath =
|
|
2438
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2439
|
+
const yamlPath = path22__default.join(projectDir, "skaile.yaml");
|
|
2241
2440
|
if (!existsSync(yamlPath)) {
|
|
2242
2441
|
logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
|
|
2243
2442
|
process.exit(1);
|
|
@@ -2297,8 +2496,8 @@ ${installResult.output}`);
|
|
|
2297
2496
|
);
|
|
2298
2497
|
cmd.command("remove <id>").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Remove a connector from skaile.yaml by its instance ID").action(async (id, opts) => {
|
|
2299
2498
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
2300
|
-
const projectDir =
|
|
2301
|
-
const yamlPath =
|
|
2499
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2500
|
+
const yamlPath = path22__default.join(projectDir, "skaile.yaml");
|
|
2302
2501
|
if (!existsSync(yamlPath)) {
|
|
2303
2502
|
logErr("No skaile.yaml found in current directory.");
|
|
2304
2503
|
process.exit(1);
|
|
@@ -2315,7 +2514,7 @@ ${installResult.output}`);
|
|
|
2315
2514
|
cmd.command("status [id]").option("--project-dir <path>", "Workspace directory", process.cwd()).description("Connect and report health status for one or all connectors").action(async (id, opts) => {
|
|
2316
2515
|
const res = await import('../connectors/index.js');
|
|
2317
2516
|
res.registerBuiltinConnectors();
|
|
2318
|
-
const projectDir =
|
|
2517
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2319
2518
|
const declarations = res.loadConnectorDeclarations(projectDir);
|
|
2320
2519
|
if (declarations.length === 0) {
|
|
2321
2520
|
console.log("No connectors configured in skaile.yaml.");
|
|
@@ -2339,7 +2538,7 @@ ${installResult.output}`);
|
|
|
2339
2538
|
await manager.disconnectAll();
|
|
2340
2539
|
});
|
|
2341
2540
|
cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
|
|
2342
|
-
const projectDir =
|
|
2541
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2343
2542
|
const manager = await connectConnectors(projectDir);
|
|
2344
2543
|
try {
|
|
2345
2544
|
console.log(JSON.stringify(manager.listConnectors(), null, 2));
|
|
@@ -2348,7 +2547,7 @@ ${installResult.output}`);
|
|
|
2348
2547
|
}
|
|
2349
2548
|
});
|
|
2350
2549
|
cmd.command("sync [id]").description("Re-sync a filesystem-face connector or all of them (git pull, S3 refresh, etc.)").option("--all", "Sync all connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
|
|
2351
|
-
const projectDir =
|
|
2550
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2352
2551
|
const manager = await connectConnectors(projectDir);
|
|
2353
2552
|
try {
|
|
2354
2553
|
if (opts.all) {
|
|
@@ -2372,7 +2571,7 @@ ${installResult.output}`);
|
|
|
2372
2571
|
}
|
|
2373
2572
|
});
|
|
2374
2573
|
cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
|
|
2375
|
-
const projectDir =
|
|
2574
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2376
2575
|
const manager = await connectConnectors(projectDir);
|
|
2377
2576
|
try {
|
|
2378
2577
|
if (!manager.has(id)) {
|
|
@@ -2387,7 +2586,7 @@ ${installResult.output}`);
|
|
|
2387
2586
|
}
|
|
2388
2587
|
});
|
|
2389
2588
|
cmd.command("read <id> <resource-path>").description("Read content from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
|
|
2390
|
-
const projectDir =
|
|
2589
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2391
2590
|
const manager = await connectConnectors(projectDir);
|
|
2392
2591
|
try {
|
|
2393
2592
|
const content = await manager.read(id, resourcePath);
|
|
@@ -2397,7 +2596,7 @@ ${installResult.output}`);
|
|
|
2397
2596
|
}
|
|
2398
2597
|
});
|
|
2399
2598
|
cmd.command("write <id> <resource-path> <content>").description("Write content to a connector at a path").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, content, opts) => {
|
|
2400
|
-
const projectDir =
|
|
2599
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2401
2600
|
const manager = await connectConnectors(projectDir);
|
|
2402
2601
|
try {
|
|
2403
2602
|
await manager.write(id, resourcePath, { data: content });
|
|
@@ -2407,7 +2606,7 @@ ${installResult.output}`);
|
|
|
2407
2606
|
}
|
|
2408
2607
|
});
|
|
2409
2608
|
cmd.command("entries <id> [resource-path]").description("List entries in a connector (files, keys, rows, etc)").option("--project-dir <path>", "Workspace directory", process.cwd()).option("--recursive", "Include nested entries").option("--limit <n>", "Maximum entries to return", parsePositiveIntOption).action(async (id, resourcePath, opts) => {
|
|
2410
|
-
const projectDir =
|
|
2609
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2411
2610
|
const manager = await connectConnectors(projectDir);
|
|
2412
2611
|
try {
|
|
2413
2612
|
const entries = await manager.list(id, resourcePath, {
|
|
@@ -2420,7 +2619,7 @@ ${installResult.output}`);
|
|
|
2420
2619
|
}
|
|
2421
2620
|
});
|
|
2422
2621
|
cmd.command("search <id> <query>").description("Search within a connector for matching content").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, query, opts) => {
|
|
2423
|
-
const projectDir =
|
|
2622
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2424
2623
|
const manager = await connectConnectors(projectDir);
|
|
2425
2624
|
try {
|
|
2426
2625
|
const results = await manager.search(id, query);
|
|
@@ -2430,7 +2629,7 @@ ${installResult.output}`);
|
|
|
2430
2629
|
}
|
|
2431
2630
|
});
|
|
2432
2631
|
cmd.command("delete <id> <resource-path>").description("Delete an entry from a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, resourcePath, opts) => {
|
|
2433
|
-
const projectDir =
|
|
2632
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2434
2633
|
const manager = await connectConnectors(projectDir);
|
|
2435
2634
|
try {
|
|
2436
2635
|
const ok = await manager.delete(id, resourcePath);
|
|
@@ -2440,7 +2639,7 @@ ${installResult.output}`);
|
|
|
2440
2639
|
}
|
|
2441
2640
|
});
|
|
2442
2641
|
cmd.command("run <id> <op> [args...]").description("Run a custom adapter operation (e.g. git log, sqlite query)").option("--project-dir <path>", "Workspace directory", process.cwd()).allowUnknownOption().action(async (id, op, args, opts) => {
|
|
2443
|
-
const projectDir =
|
|
2642
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2444
2643
|
const manager = await connectConnectors(projectDir);
|
|
2445
2644
|
try {
|
|
2446
2645
|
if (!manager.has(id)) {
|
|
@@ -2549,7 +2748,7 @@ function envRecord() {
|
|
|
2549
2748
|
async function buildDeployContext(projectDir) {
|
|
2550
2749
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
2551
2750
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
2552
|
-
const workspaceId = config.name ??
|
|
2751
|
+
const workspaceId = config.name ?? path22__default.basename(projectDir);
|
|
2553
2752
|
let log;
|
|
2554
2753
|
try {
|
|
2555
2754
|
const { createLogger } = await import('../core/logging.js');
|
|
@@ -2581,13 +2780,13 @@ async function ensureTargetsRegistered(projectDir) {
|
|
|
2581
2780
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
2582
2781
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
2583
2782
|
if (config.plugins && config.plugins.length > 0) {
|
|
2584
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
2783
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-CK7YWRIC.js');
|
|
2585
2784
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
2586
2785
|
for (const f of result.failed) logWarn(f.error);
|
|
2587
2786
|
}
|
|
2588
2787
|
}
|
|
2589
2788
|
async function runUp(opts) {
|
|
2590
|
-
const projectDir =
|
|
2789
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2591
2790
|
await ensureTargetsRegistered(projectDir);
|
|
2592
2791
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
2593
2792
|
const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
|
|
@@ -2655,7 +2854,7 @@ async function restoreFromHandle(projectDir) {
|
|
|
2655
2854
|
return { target, handle, ctx };
|
|
2656
2855
|
}
|
|
2657
2856
|
async function runDown(opts) {
|
|
2658
|
-
const projectDir =
|
|
2857
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2659
2858
|
const restored = await restoreFromHandle(projectDir);
|
|
2660
2859
|
if (!restored) return;
|
|
2661
2860
|
await restored.handle.stop();
|
|
@@ -2664,7 +2863,7 @@ async function runDown(opts) {
|
|
|
2664
2863
|
logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
|
|
2665
2864
|
}
|
|
2666
2865
|
async function runStatus(opts) {
|
|
2667
|
-
const projectDir =
|
|
2866
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2668
2867
|
const restored = await restoreFromHandle(projectDir);
|
|
2669
2868
|
if (!restored) return;
|
|
2670
2869
|
const health = await restored.handle.health();
|
|
@@ -2678,7 +2877,7 @@ async function runStatus(opts) {
|
|
|
2678
2877
|
console.log();
|
|
2679
2878
|
}
|
|
2680
2879
|
async function runLogs(opts) {
|
|
2681
|
-
const projectDir =
|
|
2880
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2682
2881
|
const restored = await restoreFromHandle(projectDir);
|
|
2683
2882
|
if (!restored) return;
|
|
2684
2883
|
if (!restored.handle.logs) {
|
|
@@ -2706,12 +2905,28 @@ function makeDiffCommand() {
|
|
|
2706
2905
|
requireProjectConfig(opts.projectDir);
|
|
2707
2906
|
const am2 = new AssetManager({
|
|
2708
2907
|
registry: getKindRegistry(),
|
|
2709
|
-
projectDir:
|
|
2908
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
2710
2909
|
});
|
|
2910
|
+
try {
|
|
2911
|
+
parseAssetRef(ref);
|
|
2912
|
+
} catch (err2) {
|
|
2913
|
+
const plain = (err2 instanceof Error ? err2.message : String(err2)).replace(
|
|
2914
|
+
/ Run the `migrate-skaile-manifest`.*$/,
|
|
2915
|
+
""
|
|
2916
|
+
);
|
|
2917
|
+
const bare = /^([^:@/]+):([^@/#]+)$/.exec(ref.trim());
|
|
2918
|
+
const held = plain.startsWith("publisher required") && bare ? am2.lockedRefsNamed(bare[1], bare[2]) : [];
|
|
2919
|
+
if (held.length !== 1) {
|
|
2920
|
+
logErr(held.length > 1 ? `${plain} (locked: ${held.join(", ")})` : plain);
|
|
2921
|
+
process.exitCode = 1;
|
|
2922
|
+
return;
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2711
2925
|
const gaps = await am2.gapsOf(ref);
|
|
2926
|
+
const requirementGaps = await am2.requirementGapsOf(ref);
|
|
2712
2927
|
const blocking = gaps.filter((g) => !DIFF_SHOWS[g.type]);
|
|
2713
2928
|
if (blocking.length > 0) {
|
|
2714
|
-
for (const g of blocking) logErr(g.message);
|
|
2929
|
+
for (const g of [...blocking, ...requirementGaps]) logErr(g.message);
|
|
2715
2930
|
process.exitCode = 1;
|
|
2716
2931
|
return;
|
|
2717
2932
|
}
|
|
@@ -2724,27 +2939,33 @@ function makeDiffCommand() {
|
|
|
2724
2939
|
if (problems.length === 0) logErr(`Asset not found: ${ref}`);
|
|
2725
2940
|
break;
|
|
2726
2941
|
case "not-deployed":
|
|
2727
|
-
if (problems.length === 0)
|
|
2942
|
+
if (problems.length === 0) {
|
|
2943
|
+
logErr(
|
|
2944
|
+
`${ref} is not deployed \u2014 nothing in this project locks it; run skaile add ${ref}`
|
|
2945
|
+
);
|
|
2946
|
+
process.exitCode = 1;
|
|
2947
|
+
}
|
|
2728
2948
|
break;
|
|
2729
2949
|
case "no-files":
|
|
2730
|
-
if (problems.length === 0)
|
|
2950
|
+
if (problems.length === 0 && requirementGaps.length === 0)
|
|
2731
2951
|
logInfo(`${ref}: preset has no files of its own; run skaile diff on its items`);
|
|
2732
2952
|
break;
|
|
2733
2953
|
case "identical":
|
|
2734
|
-
if (problems.length === 0) logInfo("No differences.");
|
|
2954
|
+
if (problems.length === 0 && requirementGaps.length === 0) logInfo("No differences.");
|
|
2735
2955
|
break;
|
|
2736
2956
|
case "differs":
|
|
2737
2957
|
console.log(result.diff);
|
|
2738
2958
|
break;
|
|
2739
2959
|
}
|
|
2740
|
-
for (const g of problems) logErr(g.message);
|
|
2741
|
-
if (result.status === "not-found" || problems.length > 0
|
|
2960
|
+
for (const g of [...problems, ...requirementGaps]) logErr(g.message);
|
|
2961
|
+
if (result.status === "not-found" || problems.length > 0 || requirementGaps.length > 0)
|
|
2962
|
+
process.exitCode = 1;
|
|
2742
2963
|
});
|
|
2743
2964
|
}
|
|
2744
2965
|
function makeFlowCommand() {
|
|
2745
2966
|
const cmd = new Command("flow").description("Manage flows");
|
|
2746
2967
|
cmd.command("list").description("List available flows").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
2747
|
-
const flows = await discoverFlowsWithLibraries(
|
|
2968
|
+
const flows = await discoverFlowsWithLibraries(path22__default.resolve(opts.projectDir));
|
|
2748
2969
|
if (flows.length === 0) {
|
|
2749
2970
|
logInfo("No flows found.");
|
|
2750
2971
|
return;
|
|
@@ -2759,7 +2980,7 @@ function makeFlowCommand() {
|
|
|
2759
2980
|
console.log();
|
|
2760
2981
|
});
|
|
2761
2982
|
cmd.command("show <id>").description("Show flow details and node graph").option("--project-dir <path>", "Project directory", process.cwd()).action(async (id, opts) => {
|
|
2762
|
-
const flows = await discoverFlowsWithLibraries(
|
|
2983
|
+
const flows = await discoverFlowsWithLibraries(path22__default.resolve(opts.projectDir));
|
|
2763
2984
|
const flow = flows.find((f) => f.id === id);
|
|
2764
2985
|
if (!flow) {
|
|
2765
2986
|
logErr(`Flow not found: ${id}`);
|
|
@@ -2793,7 +3014,7 @@ function makeHistoryCommand() {
|
|
|
2793
3014
|
cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
|
|
2794
3015
|
const am2 = new AssetManager({
|
|
2795
3016
|
registry: getKindRegistry(),
|
|
2796
|
-
projectDir:
|
|
3017
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
2797
3018
|
});
|
|
2798
3019
|
const limit = parseInt(limitStr, 10) || 20;
|
|
2799
3020
|
const entries = am2.history(limit);
|
|
@@ -2816,7 +3037,7 @@ function makeHistoryCommand() {
|
|
|
2816
3037
|
cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
2817
3038
|
const am2 = new AssetManager({
|
|
2818
3039
|
registry: getKindRegistry(),
|
|
2819
|
-
projectDir:
|
|
3040
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
2820
3041
|
});
|
|
2821
3042
|
am2.clearHistory();
|
|
2822
3043
|
logOk("History cleared.");
|
|
@@ -2829,8 +3050,24 @@ var MCP_SERVER_ENTRY = {
|
|
|
2829
3050
|
args: ["mcp-server"],
|
|
2830
3051
|
env: {}
|
|
2831
3052
|
};
|
|
3053
|
+
function mcpFilePath(projectDir) {
|
|
3054
|
+
return path22__default.join(projectDir, ".mcp.json");
|
|
3055
|
+
}
|
|
3056
|
+
function legacyMcpFilePath(projectDir) {
|
|
3057
|
+
return path22__default.join(projectDir, ".claude", "mcp.json");
|
|
3058
|
+
}
|
|
3059
|
+
async function removeSkaileMcpEntry(mcpPath) {
|
|
3060
|
+
const mcp = await readJsonStrict(mcpPath);
|
|
3061
|
+
if (!mcp?.mcpServers || !(SKAILE_MCP_NAME in mcp.mcpServers)) return false;
|
|
3062
|
+
const { [SKAILE_MCP_NAME]: _removed, ...rest } = mcp.mcpServers;
|
|
3063
|
+
const updated = { ...mcp, mcpServers: rest };
|
|
3064
|
+
if (Object.keys(rest).length === 0) delete updated.mcpServers;
|
|
3065
|
+
if (Object.keys(updated).length === 0) await fs5.unlink(mcpPath);
|
|
3066
|
+
else await writeJson(mcpPath, updated);
|
|
3067
|
+
return true;
|
|
3068
|
+
}
|
|
2832
3069
|
function pluginDir(projectDir) {
|
|
2833
|
-
return
|
|
3070
|
+
return path22__default.join(projectDir, ".claude", "plugins", "skaile");
|
|
2834
3071
|
}
|
|
2835
3072
|
async function readJsonStrict(p6) {
|
|
2836
3073
|
let raw;
|
|
@@ -2848,7 +3085,7 @@ async function readJsonStrict(p6) {
|
|
|
2848
3085
|
}
|
|
2849
3086
|
}
|
|
2850
3087
|
async function writeJson(p6, value) {
|
|
2851
|
-
await fs5.mkdir(
|
|
3088
|
+
await fs5.mkdir(path22__default.dirname(p6), { recursive: true });
|
|
2852
3089
|
await fs5.writeFile(p6, `${JSON.stringify(value, null, 2)}
|
|
2853
3090
|
`);
|
|
2854
3091
|
}
|
|
@@ -2856,8 +3093,8 @@ async function copyDir(src, dest) {
|
|
|
2856
3093
|
await fs5.mkdir(dest, { recursive: true });
|
|
2857
3094
|
const entries = await fs5.readdir(src, { withFileTypes: true });
|
|
2858
3095
|
for (const entry of entries) {
|
|
2859
|
-
const srcPath =
|
|
2860
|
-
const destPath =
|
|
3096
|
+
const srcPath = path22__default.join(src, entry.name);
|
|
3097
|
+
const destPath = path22__default.join(dest, entry.name);
|
|
2861
3098
|
if (entry.isDirectory()) await copyDir(srcPath, destPath);
|
|
2862
3099
|
else await fs5.copyFile(srcPath, destPath);
|
|
2863
3100
|
}
|
|
@@ -2866,31 +3103,32 @@ async function install(projectDir, opts) {
|
|
|
2866
3103
|
return opts?.full ? installFullPlugin(projectDir) : installMcp(projectDir);
|
|
2867
3104
|
}
|
|
2868
3105
|
async function installMcp(projectDir) {
|
|
2869
|
-
const mcpPath =
|
|
3106
|
+
const mcpPath = mcpFilePath(projectDir);
|
|
2870
3107
|
const existing = await readJsonStrict(mcpPath) ?? {};
|
|
2871
3108
|
const mcpServers = { ...existing.mcpServers ?? {} };
|
|
2872
3109
|
const previous = mcpServers[SKAILE_MCP_NAME];
|
|
2873
3110
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(MCP_SERVER_ENTRY);
|
|
2874
3111
|
let warning;
|
|
2875
3112
|
if (previous && !matches) {
|
|
2876
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${
|
|
3113
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path22__default.relative(projectDir, mcpPath)}`;
|
|
2877
3114
|
}
|
|
2878
3115
|
mcpServers[SKAILE_MCP_NAME] = MCP_SERVER_ENTRY;
|
|
2879
3116
|
await writeJson(mcpPath, { ...existing, mcpServers });
|
|
2880
|
-
|
|
3117
|
+
const migrated = await removeSkaileMcpEntry(legacyMcpFilePath(projectDir));
|
|
3118
|
+
return { changed: !matches || migrated, method: "mcp", warning };
|
|
2881
3119
|
}
|
|
2882
3120
|
async function installFullPlugin(projectDir) {
|
|
2883
3121
|
const dir = pluginDir(projectDir);
|
|
2884
3122
|
for (const [rel, content] of Object.entries(buildClaudePluginFiles())) {
|
|
2885
|
-
const dest =
|
|
2886
|
-
await fs5.mkdir(
|
|
3123
|
+
const dest = path22__default.join(dir, rel);
|
|
3124
|
+
await fs5.mkdir(path22__default.dirname(dest), { recursive: true });
|
|
2887
3125
|
await fs5.writeFile(dest, content);
|
|
2888
3126
|
}
|
|
2889
|
-
const projectSkillsDir =
|
|
3127
|
+
const projectSkillsDir = path22__default.join(projectDir, ".skaile", "skills");
|
|
2890
3128
|
if (existsSync(projectSkillsDir)) {
|
|
2891
|
-
await copyDir(projectSkillsDir,
|
|
3129
|
+
await copyDir(projectSkillsDir, path22__default.join(dir, "skills"));
|
|
2892
3130
|
}
|
|
2893
|
-
const settingsPath =
|
|
3131
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
2894
3132
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
2895
3133
|
const plugins = settings.plugins ?? [];
|
|
2896
3134
|
if (!plugins.includes(dir)) plugins.push(dir);
|
|
@@ -2898,47 +3136,43 @@ async function installFullPlugin(projectDir) {
|
|
|
2898
3136
|
return { changed: true, method: "plugin" };
|
|
2899
3137
|
}
|
|
2900
3138
|
async function uninstall(projectDir) {
|
|
2901
|
-
const settingsPath =
|
|
2902
|
-
const mcpPath =
|
|
3139
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
3140
|
+
const mcpPath = mcpFilePath(projectDir);
|
|
2903
3141
|
const dir = pluginDir(projectDir);
|
|
2904
|
-
|
|
3142
|
+
const rel = (p6) => path22__default.relative(projectDir, p6);
|
|
3143
|
+
const files = [];
|
|
2905
3144
|
const settings = await readJsonStrict(settingsPath);
|
|
2906
3145
|
if (settings && Array.isArray(settings.plugins)) {
|
|
2907
3146
|
const next = settings.plugins.filter((p6) => p6 !== dir);
|
|
2908
3147
|
if (next.length !== settings.plugins.length) {
|
|
2909
|
-
|
|
3148
|
+
files.push(rel(settingsPath));
|
|
2910
3149
|
const updated = { ...settings, plugins: next };
|
|
2911
3150
|
if (next.length === 0) delete updated.plugins;
|
|
2912
|
-
await
|
|
3151
|
+
if (Object.keys(updated).length === 0) await fs5.unlink(settingsPath);
|
|
3152
|
+
else await writeJson(settingsPath, updated);
|
|
2913
3153
|
}
|
|
2914
3154
|
}
|
|
2915
3155
|
if (existsSync(dir)) {
|
|
2916
3156
|
await fs5.rm(dir, { recursive: true, force: true });
|
|
2917
|
-
|
|
3157
|
+
files.push(rel(dir));
|
|
2918
3158
|
}
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
if (Object.keys(rest).length === 0) delete updated.mcpServers;
|
|
2925
|
-
if (Object.keys(updated).length === 0) {
|
|
2926
|
-
await fs5.unlink(mcpPath);
|
|
2927
|
-
} else {
|
|
2928
|
-
await writeJson(mcpPath, updated);
|
|
2929
|
-
}
|
|
3159
|
+
if (await removeSkaileMcpEntry(mcpPath)) files.push(rel(mcpPath));
|
|
3160
|
+
const legacyPath = legacyMcpFilePath(projectDir);
|
|
3161
|
+
if (await removeSkaileMcpEntry(legacyPath)) files.push(rel(legacyPath));
|
|
3162
|
+
for (const emptyDir of [path22__default.dirname(dir), path22__default.join(projectDir, ".claude")]) {
|
|
3163
|
+
await fs5.rmdir(emptyDir).catch(() => void 0);
|
|
2930
3164
|
}
|
|
2931
|
-
return { changed };
|
|
3165
|
+
return { changed: files.length > 0, files };
|
|
2932
3166
|
}
|
|
2933
3167
|
async function detectInstall(projectDir) {
|
|
2934
3168
|
const dir = pluginDir(projectDir);
|
|
2935
3169
|
const settings = await readJsonStrict(
|
|
2936
|
-
|
|
3170
|
+
path22__default.join(projectDir, ".claude", "settings.json")
|
|
2937
3171
|
);
|
|
2938
|
-
if (existsSync(
|
|
3172
|
+
if (existsSync(path22__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
|
|
2939
3173
|
return { method: "plugin", pluginPath: dir };
|
|
2940
3174
|
}
|
|
2941
|
-
const mcp = await readJsonStrict(
|
|
3175
|
+
const mcp = await readJsonStrict(mcpFilePath(projectDir));
|
|
2942
3176
|
if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
|
|
2943
3177
|
return { method: "mcp" };
|
|
2944
3178
|
}
|
|
@@ -2947,7 +3181,7 @@ async function detectInstall(projectDir) {
|
|
|
2947
3181
|
async function enable(projectDir) {
|
|
2948
3182
|
const detected = await detectInstall(projectDir);
|
|
2949
3183
|
if (!detected) throw new Error("plugin not installed for claude-code");
|
|
2950
|
-
const settingsPath =
|
|
3184
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
2951
3185
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
2952
3186
|
if (detected.method === "plugin") {
|
|
2953
3187
|
const disabled2 = settings.disabledPlugins ?? [];
|
|
@@ -2969,7 +3203,7 @@ async function enable(projectDir) {
|
|
|
2969
3203
|
async function disable(projectDir) {
|
|
2970
3204
|
const detected = await detectInstall(projectDir);
|
|
2971
3205
|
if (!detected) throw new Error("plugin not installed for claude-code");
|
|
2972
|
-
const settingsPath =
|
|
3206
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
2973
3207
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
2974
3208
|
if (detected.method === "plugin") {
|
|
2975
3209
|
const list2 = settings.disabledPlugins ?? [];
|
|
@@ -2989,12 +3223,12 @@ async function disable(projectDir) {
|
|
|
2989
3223
|
return { changed: true };
|
|
2990
3224
|
}
|
|
2991
3225
|
async function status(projectDir) {
|
|
2992
|
-
const settingsPath =
|
|
2993
|
-
const mcpPath =
|
|
3226
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
3227
|
+
const mcpPath = mcpFilePath(projectDir);
|
|
2994
3228
|
const dir = pluginDir(projectDir);
|
|
2995
3229
|
const settings = await readJsonStrict(settingsPath);
|
|
2996
3230
|
const mcp = await readJsonStrict(mcpPath);
|
|
2997
|
-
const pluginInstalled = !!(existsSync(
|
|
3231
|
+
const pluginInstalled = !!(existsSync(path22__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
|
|
2998
3232
|
const mcpInstalled = !!(mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers);
|
|
2999
3233
|
if (!pluginInstalled && !mcpInstalled) {
|
|
3000
3234
|
return {
|
|
@@ -3012,7 +3246,7 @@ async function status(projectDir) {
|
|
|
3012
3246
|
installed: "yes",
|
|
3013
3247
|
enabled: disabled2 ? "no" : "yes",
|
|
3014
3248
|
method: "plugin",
|
|
3015
|
-
location:
|
|
3249
|
+
location: path22__default.relative(projectDir, dir)
|
|
3016
3250
|
};
|
|
3017
3251
|
}
|
|
3018
3252
|
const disabled = settings?.disabledMcpjsonServers?.includes(SKAILE_MCP_NAME) ?? false;
|
|
@@ -3021,7 +3255,7 @@ async function status(projectDir) {
|
|
|
3021
3255
|
installed: "yes",
|
|
3022
3256
|
enabled: disabled ? "no" : "yes",
|
|
3023
3257
|
method: "mcp",
|
|
3024
|
-
location:
|
|
3258
|
+
location: path22__default.relative(projectDir, mcpPath)
|
|
3025
3259
|
};
|
|
3026
3260
|
}
|
|
3027
3261
|
var SKAILE_MCP_NAME2 = "skaile-workspace";
|
|
@@ -3048,7 +3282,7 @@ async function readConfig(p6) {
|
|
|
3048
3282
|
}
|
|
3049
3283
|
}
|
|
3050
3284
|
async function writeConfig(p6, value) {
|
|
3051
|
-
await fs5.mkdir(
|
|
3285
|
+
await fs5.mkdir(path22__default.dirname(p6), { recursive: true });
|
|
3052
3286
|
const cleaned = {};
|
|
3053
3287
|
for (const [k, v] of Object.entries(value)) {
|
|
3054
3288
|
if (v === void 0) continue;
|
|
@@ -3057,7 +3291,7 @@ async function writeConfig(p6, value) {
|
|
|
3057
3291
|
await fs5.writeFile(p6, stringify$1(cleaned));
|
|
3058
3292
|
}
|
|
3059
3293
|
function configPath(projectDir) {
|
|
3060
|
-
return
|
|
3294
|
+
return path22__default.join(projectDir, ".codex", "config.toml");
|
|
3061
3295
|
}
|
|
3062
3296
|
async function install2(projectDir) {
|
|
3063
3297
|
const p6 = configPath(projectDir);
|
|
@@ -3068,7 +3302,7 @@ async function install2(projectDir) {
|
|
|
3068
3302
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
|
|
3069
3303
|
let warning;
|
|
3070
3304
|
if (previous && !matches) {
|
|
3071
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${
|
|
3305
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path22__default.relative(projectDir, p6)}`;
|
|
3072
3306
|
}
|
|
3073
3307
|
if (matches) return { changed: false, method: "toml" };
|
|
3074
3308
|
servers[SKAILE_MCP_NAME2] = next;
|
|
@@ -3109,12 +3343,12 @@ async function status2(projectDir) {
|
|
|
3109
3343
|
installed: "yes",
|
|
3110
3344
|
enabled: "n/a",
|
|
3111
3345
|
method: "mcp",
|
|
3112
|
-
location:
|
|
3346
|
+
location: path22__default.relative(projectDir, p6)
|
|
3113
3347
|
};
|
|
3114
3348
|
}
|
|
3115
3349
|
async function install3(projectDir) {
|
|
3116
|
-
const extDir =
|
|
3117
|
-
const extPath =
|
|
3350
|
+
const extDir = path22__default.join(projectDir, ".omp", "extensions");
|
|
3351
|
+
const extPath = path22__default.join(extDir, "skaile.ts");
|
|
3118
3352
|
await fs5.mkdir(extDir, { recursive: true });
|
|
3119
3353
|
const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
|
|
3120
3354
|
const plugin = new WorkspacePlugin({ projectDir });
|
|
@@ -3129,7 +3363,7 @@ async function install3(projectDir) {
|
|
|
3129
3363
|
return { changed: true, method: "generated" };
|
|
3130
3364
|
}
|
|
3131
3365
|
async function uninstall3(projectDir) {
|
|
3132
|
-
const extPath =
|
|
3366
|
+
const extPath = path22__default.join(projectDir, ".omp", "extensions", "skaile.ts");
|
|
3133
3367
|
try {
|
|
3134
3368
|
await fs5.unlink(extPath);
|
|
3135
3369
|
return { changed: true };
|
|
@@ -3138,14 +3372,14 @@ async function uninstall3(projectDir) {
|
|
|
3138
3372
|
}
|
|
3139
3373
|
}
|
|
3140
3374
|
async function status3(projectDir) {
|
|
3141
|
-
const extPath =
|
|
3375
|
+
const extPath = path22__default.join(projectDir, ".omp", "extensions", "skaile.ts");
|
|
3142
3376
|
if (existsSync(extPath)) {
|
|
3143
3377
|
return {
|
|
3144
3378
|
harness: "omp",
|
|
3145
3379
|
installed: "yes",
|
|
3146
3380
|
enabled: "n/a",
|
|
3147
3381
|
method: "extension",
|
|
3148
|
-
location:
|
|
3382
|
+
location: path22__default.relative(projectDir, extPath)
|
|
3149
3383
|
};
|
|
3150
3384
|
}
|
|
3151
3385
|
return {
|
|
@@ -3182,7 +3416,7 @@ async function installClaudeCode(projectDir, opts) {
|
|
|
3182
3416
|
`Generated ${S.cmd(".claude/plugins/skaile/")} and registered it in ${S.cmd(".claude/settings.json")}`
|
|
3183
3417
|
);
|
|
3184
3418
|
} else if (r.changed) {
|
|
3185
|
-
logOk(`Wrote ${S.cmd(".
|
|
3419
|
+
logOk(`Wrote ${S.cmd(".mcp.json")} (${SKAILE_MCP_LABEL})`);
|
|
3186
3420
|
} else {
|
|
3187
3421
|
logInfo(`claude-code: already installed (mcp)`);
|
|
3188
3422
|
}
|
|
@@ -3208,7 +3442,7 @@ async function installCodex(projectDir) {
|
|
|
3208
3442
|
console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
|
|
3209
3443
|
}
|
|
3210
3444
|
async function runInstall(opts) {
|
|
3211
|
-
const projectDir =
|
|
3445
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
3212
3446
|
const targets = resolveDriver(opts.driver);
|
|
3213
3447
|
let exitCode = 0;
|
|
3214
3448
|
if (targets.includes("claude-code")) {
|
|
@@ -3223,13 +3457,18 @@ async function runInstall(opts) {
|
|
|
3223
3457
|
if (targets.includes("codex")) {
|
|
3224
3458
|
exitCode |= await runHarnessStep("codex install", () => installCodex(projectDir));
|
|
3225
3459
|
}
|
|
3226
|
-
if (exitCode === 0)
|
|
3460
|
+
if (exitCode === 0) {
|
|
3461
|
+
await ignorePerMachineFiles(projectDir, targets);
|
|
3462
|
+
logOk("Plugin installed.");
|
|
3463
|
+
}
|
|
3227
3464
|
return exitCode;
|
|
3228
3465
|
}
|
|
3229
3466
|
async function uninstallClaudeCode(projectDir) {
|
|
3230
3467
|
const r = await uninstall(projectDir);
|
|
3231
|
-
if (r.changed)
|
|
3232
|
-
|
|
3468
|
+
if (r.changed) {
|
|
3469
|
+
const from = (r.files ?? []).map((f) => S.cmd(f)).join(", ");
|
|
3470
|
+
logOk(`Removed skaile entries from ${from || S.cmd(".claude/")}`);
|
|
3471
|
+
} else logInfo(`claude-code: not installed`);
|
|
3233
3472
|
}
|
|
3234
3473
|
async function uninstallOmp(projectDir) {
|
|
3235
3474
|
const r = await uninstall3(projectDir);
|
|
@@ -3242,7 +3481,7 @@ async function uninstallCodex(projectDir) {
|
|
|
3242
3481
|
else logInfo(`codex: not installed`);
|
|
3243
3482
|
}
|
|
3244
3483
|
async function runUninstall(opts) {
|
|
3245
|
-
const projectDir =
|
|
3484
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
3246
3485
|
const targets = resolveDriver(opts.driver);
|
|
3247
3486
|
let exitCode = 0;
|
|
3248
3487
|
if (targets.includes("claude-code")) {
|
|
@@ -3257,9 +3496,46 @@ async function runUninstall(opts) {
|
|
|
3257
3496
|
if (targets.includes("codex")) {
|
|
3258
3497
|
exitCode |= await runHarnessStep("codex uninstall", () => uninstallCodex(projectDir));
|
|
3259
3498
|
}
|
|
3260
|
-
if (exitCode === 0)
|
|
3499
|
+
if (exitCode === 0) {
|
|
3500
|
+
await removeEmptyPluginState(projectDir);
|
|
3501
|
+
logOk("Plugin uninstalled.");
|
|
3502
|
+
}
|
|
3261
3503
|
return exitCode;
|
|
3262
3504
|
}
|
|
3505
|
+
async function removeEmptyPluginState(projectDir) {
|
|
3506
|
+
const stateFile = path22__default.join(projectDir, ".skaile", "plugin-state.json");
|
|
3507
|
+
try {
|
|
3508
|
+
const parsed = JSON.parse(await fs5.readFile(stateFile, "utf-8"));
|
|
3509
|
+
if (typeof parsed !== "object" || parsed === null || Object.keys(parsed).length > 0) return;
|
|
3510
|
+
await fs5.unlink(stateFile);
|
|
3511
|
+
await fs5.rmdir(path22__default.dirname(stateFile)).catch(() => void 0);
|
|
3512
|
+
} catch {
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
var PER_MACHINE_FILES = {
|
|
3516
|
+
"claude-code": [".skaile/plugin-state.json"],
|
|
3517
|
+
omp: [".omp/extensions/skaile.ts", ".skaile/plugin-state.json"],
|
|
3518
|
+
codex: [".codex/config.toml", ".skaile/plugin-state.json"]
|
|
3519
|
+
};
|
|
3520
|
+
async function ignorePerMachineFiles(projectDir, targets) {
|
|
3521
|
+
const gitignore = path22__default.join(projectDir, ".gitignore");
|
|
3522
|
+
let existing = null;
|
|
3523
|
+
try {
|
|
3524
|
+
existing = await fs5.readFile(gitignore, "utf-8");
|
|
3525
|
+
} catch {
|
|
3526
|
+
if (!existsSync(path22__default.join(projectDir, ".git"))) return;
|
|
3527
|
+
}
|
|
3528
|
+
const have = new Set((existing ?? "").split("\n").map((l) => l.trim()));
|
|
3529
|
+
const wanted = [...new Set(targets.flatMap((t) => PER_MACHINE_FILES[t]))];
|
|
3530
|
+
const missing = wanted.filter((f) => !have.has(f));
|
|
3531
|
+
if (missing.length === 0) return;
|
|
3532
|
+
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
3533
|
+
await fs5.writeFile(gitignore, `${existing ?? ""}${prefix}${missing.join("\n")}
|
|
3534
|
+
`);
|
|
3535
|
+
logInfo(
|
|
3536
|
+
`Added ${missing.map((f) => S.cmd(f)).join(", ")} to ${S.cmd(".gitignore")} (per machine)`
|
|
3537
|
+
);
|
|
3538
|
+
}
|
|
3263
3539
|
function checkToggleSupported(targets, requestedAll, action3) {
|
|
3264
3540
|
if (requestedAll) return null;
|
|
3265
3541
|
const unsupported = targets.filter((t) => !TOGGLE_SUPPORTED.includes(t));
|
|
@@ -3285,7 +3561,7 @@ async function toggleTarget(t, projectDir, action3) {
|
|
|
3285
3561
|
});
|
|
3286
3562
|
}
|
|
3287
3563
|
async function runToggle(opts, action3) {
|
|
3288
|
-
const projectDir =
|
|
3564
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
3289
3565
|
const requestedAll = opts.driver === "all";
|
|
3290
3566
|
const targets = resolveDriver(opts.driver);
|
|
3291
3567
|
const usageError = checkToggleSupported(targets, requestedAll, action3);
|
|
@@ -3297,7 +3573,7 @@ async function runToggle(opts, action3) {
|
|
|
3297
3573
|
return exitCode;
|
|
3298
3574
|
}
|
|
3299
3575
|
async function runStatus2(opts) {
|
|
3300
|
-
const projectDir =
|
|
3576
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
3301
3577
|
const targets = resolveDriver(opts.driver);
|
|
3302
3578
|
const rows = [];
|
|
3303
3579
|
let exitCode = 0;
|
|
@@ -3338,12 +3614,12 @@ function printStatusTable(rows) {
|
|
|
3338
3614
|
var SKAILE_MCP_LABEL = "skaile-workspace entry";
|
|
3339
3615
|
var HOOK_EVENTS = ["session-start", "session-end", "user-prompt-submit"];
|
|
3340
3616
|
async function runHook(event) {
|
|
3341
|
-
const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
|
|
3342
|
-
|
|
3343
|
-
new
|
|
3617
|
+
const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
|
|
3618
|
+
registerLogStore2(
|
|
3619
|
+
new LogStore2({
|
|
3344
3620
|
sessionId: `hook-${event}`,
|
|
3345
3621
|
level: "info",
|
|
3346
|
-
sinks: [new
|
|
3622
|
+
sinks: [new StdoutSink2({ stream: "stderr" })]
|
|
3347
3623
|
})
|
|
3348
3624
|
);
|
|
3349
3625
|
const { WorkspacePlugin, PluginStore, resolveProjectDir } = await import('../workspace-plugin/index.js');
|
|
@@ -3368,7 +3644,7 @@ async function runHook(event) {
|
|
|
3368
3644
|
await plugin.shutdown();
|
|
3369
3645
|
return;
|
|
3370
3646
|
}
|
|
3371
|
-
const store = new PluginStore(
|
|
3647
|
+
const store = new PluginStore(path22__default.join(projectDir, ".skaile", "plugin-state.json"));
|
|
3372
3648
|
await store.load();
|
|
3373
3649
|
const status4 = store.get("connector:status");
|
|
3374
3650
|
if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
|
|
@@ -3383,6 +3659,45 @@ async function runHook(event) {
|
|
|
3383
3659
|
);
|
|
3384
3660
|
}
|
|
3385
3661
|
}
|
|
3662
|
+
async function readStdin() {
|
|
3663
|
+
if (process.stdin.isTTY) return "";
|
|
3664
|
+
const chunks = [];
|
|
3665
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
3666
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
3667
|
+
}
|
|
3668
|
+
async function runOmpExec(kind, name, projectDir) {
|
|
3669
|
+
if (kind !== "tool" && kind !== "slash") {
|
|
3670
|
+
logErr(`omp-exec: unknown kind '${kind}' (expected: tool | slash)`);
|
|
3671
|
+
return 2;
|
|
3672
|
+
}
|
|
3673
|
+
const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
|
|
3674
|
+
const plugin = new WorkspacePlugin({ projectDir, bootOwned: true });
|
|
3675
|
+
try {
|
|
3676
|
+
const raw = (await readStdin()).trim();
|
|
3677
|
+
const payload = raw ? JSON.parse(raw) : kind === "tool" ? {} : [];
|
|
3678
|
+
await plugin.boot();
|
|
3679
|
+
if (kind === "slash") {
|
|
3680
|
+
const parts = Array.isArray(payload) ? payload.map(String) : [];
|
|
3681
|
+
process.stdout.write(`${await plugin.handleSlashCommand(name, parts)}
|
|
3682
|
+
`);
|
|
3683
|
+
return 0;
|
|
3684
|
+
}
|
|
3685
|
+
const tools = await plugin.buildOmpToolSet();
|
|
3686
|
+
const tool = tools.find((t) => t.name === name);
|
|
3687
|
+
if (!tool) {
|
|
3688
|
+
logErr(`omp-exec: unknown tool '${name}'`);
|
|
3689
|
+
return 2;
|
|
3690
|
+
}
|
|
3691
|
+
process.stdout.write(`${await tool.handler(payload)}
|
|
3692
|
+
`);
|
|
3693
|
+
return 0;
|
|
3694
|
+
} catch (e) {
|
|
3695
|
+
logErr(`omp-exec ${kind} ${name}: ${e instanceof Error ? e.message : String(e)}`);
|
|
3696
|
+
return 1;
|
|
3697
|
+
} finally {
|
|
3698
|
+
await plugin.shutdown();
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3386
3701
|
function makeIntegrationCommand() {
|
|
3387
3702
|
const cmd = new Command("integration").description(
|
|
3388
3703
|
"Manage skaile agent integration / workspace-plugin adapter (Claude Code / OMP / Codex)"
|
|
@@ -3405,13 +3720,18 @@ function makeIntegrationCommand() {
|
|
|
3405
3720
|
cmd.command("status").description("Show install / enable status across harnesses").option("--driver <name>", "Target: claude-code | omp | codex | all", "all").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
3406
3721
|
process.exitCode = await runStatus2(opts);
|
|
3407
3722
|
});
|
|
3723
|
+
cmd.command("omp-exec <kind> <name>").description(
|
|
3724
|
+
"Run one tool or slash command of the omp extension (used by .omp/extensions/skaile.ts)"
|
|
3725
|
+
).option("--project-dir <path>", "Project directory", process.cwd()).action(async (kind, name, opts) => {
|
|
3726
|
+
process.exitCode = await runOmpExec(kind, name, path22__default.resolve(opts.projectDir));
|
|
3727
|
+
});
|
|
3408
3728
|
cmd.command("hook <event>").description(
|
|
3409
3729
|
"Run a Claude Code lifecycle hook (session-start | session-end | user-prompt-submit)"
|
|
3410
3730
|
).action(async (event) => {
|
|
3411
3731
|
try {
|
|
3412
3732
|
if (!HOOK_EVENTS.includes(event)) {
|
|
3413
3733
|
process.stderr.write(
|
|
3414
|
-
`
|
|
3734
|
+
`integration hook: unknown event '${event}' (expected: ${HOOK_EVENTS.join(" | ")})
|
|
3415
3735
|
`
|
|
3416
3736
|
);
|
|
3417
3737
|
} else {
|
|
@@ -3419,7 +3739,7 @@ function makeIntegrationCommand() {
|
|
|
3419
3739
|
}
|
|
3420
3740
|
} catch (err2) {
|
|
3421
3741
|
process.stderr.write(
|
|
3422
|
-
`
|
|
3742
|
+
`integration hook ${event} warning: ${err2 instanceof Error ? err2.message : String(err2)}
|
|
3423
3743
|
`
|
|
3424
3744
|
);
|
|
3425
3745
|
}
|
|
@@ -3446,13 +3766,14 @@ function unfinishedGitState(dir) {
|
|
|
3446
3766
|
for (const [entry, state2] of Object.entries(UNFINISHED_GIT_ENTRIES)) {
|
|
3447
3767
|
const p6 = spawnSync("git", ["rev-parse", "--git-path", entry], { cwd: dir, encoding: "utf-8" });
|
|
3448
3768
|
if (p6.status !== 0) return "the git directory could not be read";
|
|
3449
|
-
if (
|
|
3769
|
+
if (fs9.existsSync(path22.resolve(dir, p6.stdout.trim()))) return state2;
|
|
3450
3770
|
}
|
|
3451
3771
|
return null;
|
|
3452
3772
|
}
|
|
3453
3773
|
async function reindexLibrary(lib, library, name) {
|
|
3454
3774
|
assertManifestEditableOrExit(lib.path);
|
|
3455
3775
|
exitOnManifestPublisherProblems(lib.path, name);
|
|
3776
|
+
exitOnLibrarySymlinks(lib.path, `skaile library index ${name}`);
|
|
3456
3777
|
const badRequires = manifestRequiresProblems(lib.path);
|
|
3457
3778
|
const resolved = resolveLibraryPublisherDetailed(lib, {}, getStoreIdentity());
|
|
3458
3779
|
warnLibraryNameFallback(name, resolved);
|
|
@@ -3461,7 +3782,17 @@ async function reindexLibrary(lib, library, name) {
|
|
|
3461
3782
|
lib.path,
|
|
3462
3783
|
resolved.publisher,
|
|
3463
3784
|
registry,
|
|
3464
|
-
{
|
|
3785
|
+
{
|
|
3786
|
+
check: (e) => checkAssetFile(
|
|
3787
|
+
e.source,
|
|
3788
|
+
e.kind,
|
|
3789
|
+
registry,
|
|
3790
|
+
lib.path,
|
|
3791
|
+
(f) => logWarn(
|
|
3792
|
+
`${path22.relative(lib.path, e.source)} [${f.tag}] \u2014 body is still the scaffold placeholder; publish refuses it until you write the ${f.tag} prompt`
|
|
3793
|
+
)
|
|
3794
|
+
)
|
|
3795
|
+
}
|
|
3465
3796
|
);
|
|
3466
3797
|
const manifest = loadSkPublishManifest(lib.path);
|
|
3467
3798
|
for (const a of unknownKind) {
|
|
@@ -3473,19 +3804,25 @@ async function reindexLibrary(lib, library, name) {
|
|
|
3473
3804
|
const ref = manifest ? assetEntryRef(a, manifest) : `${a.kind}:${a.name}`;
|
|
3474
3805
|
logInfo(`Removed manifest entry ${ref} (root ${a.root} is gone)`);
|
|
3475
3806
|
}
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3807
|
+
const invalidVersion = skipped.filter((x) => x.reason === "invalid-version");
|
|
3808
|
+
for (const s of invalidVersion) {
|
|
3809
|
+
const found = checkAssetFile(path22.join(lib.path, s.file), s.kind, registry).find(
|
|
3810
|
+
(f) => f.text.startsWith("version ")
|
|
3811
|
+
);
|
|
3812
|
+
const detail = found?.text ?? s.detail;
|
|
3813
|
+
const hint = detail.includes("Write it quoted") ? "" : " Set a valid `metadata.version` (e.g. 0.1.0).";
|
|
3814
|
+
logErr(
|
|
3815
|
+
`${s.kind}:${s.name} skipped: ${detail}.${hint} Re-run \`skaile library index ${name}\` after the fix.`
|
|
3479
3816
|
);
|
|
3480
3817
|
}
|
|
3481
3818
|
const duplicates = skipped.filter((x) => x.reason === "duplicate");
|
|
3482
3819
|
for (const s of duplicates) {
|
|
3483
|
-
logErr(duplicateAssetMessage(s.kind, s.name,
|
|
3820
|
+
logErr(duplicateAssetMessage(s.kind, s.name, path22.dirname(s.file), s.detail, name));
|
|
3484
3821
|
}
|
|
3485
3822
|
for (const s of failed) {
|
|
3486
3823
|
for (const f of s.findings) logErr(`${s.file} [${f.tag}] \u2014 ${f.text}`);
|
|
3487
3824
|
}
|
|
3488
|
-
const duplicateFiles = new Set(duplicates.map((s) =>
|
|
3825
|
+
const duplicateFiles = new Set(duplicates.map((s) => path22.resolve(lib.path, s.file)));
|
|
3489
3826
|
const skippedKeys = new Set(
|
|
3490
3827
|
[
|
|
3491
3828
|
...skipped.filter((s) => s.reason !== "duplicate"),
|
|
@@ -3493,7 +3830,7 @@ async function reindexLibrary(lib, library, name) {
|
|
|
3493
3830
|
].map((s) => `${s.kind}:${s.name}`)
|
|
3494
3831
|
);
|
|
3495
3832
|
const res = await indexLibrary(lib, library, {
|
|
3496
|
-
exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(
|
|
3833
|
+
exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path22.resolve(a.manifestPath))
|
|
3497
3834
|
});
|
|
3498
3835
|
const unparsable = res.errors.filter((e) => e.includes("ManifestSchemaError:"));
|
|
3499
3836
|
for (const e of res.errors) (unparsable.includes(e) ? logErr : logWarn)(e);
|
|
@@ -3505,14 +3842,21 @@ async function reindexLibrary(lib, library, name) {
|
|
|
3505
3842
|
}
|
|
3506
3843
|
for (const p6 of badRequires) logErr(`${p6.asset}: ${p6.message}`);
|
|
3507
3844
|
for (const w of await unresolvedManifestDependencies(lib.path)) logWarn(w);
|
|
3508
|
-
|
|
3845
|
+
const skippedUnparsable = unparsable.length + syncUnparsable.length;
|
|
3846
|
+
const failing = skippedUnparsable + invalidVersion.length + badRequires.length + failed.length + duplicates.length;
|
|
3847
|
+
(failing > 0 ? logWarn : logOk)(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
|
|
3509
3848
|
warnIgnoredDomainFiles(lib.path);
|
|
3510
3849
|
warnLegacyBundleFiles(lib.path);
|
|
3511
|
-
const skippedUnparsable = unparsable.length + syncUnparsable.length;
|
|
3512
3850
|
if (skippedUnparsable > 0) {
|
|
3513
3851
|
logErr(`${skippedUnparsable} asset(s) skipped: manifest could not be parsed.`);
|
|
3514
3852
|
process.exitCode = 1;
|
|
3515
3853
|
}
|
|
3854
|
+
if (invalidVersion.length > 0) {
|
|
3855
|
+
logErr(
|
|
3856
|
+
`${invalidVersion.length} asset(s) skipped: the version is not valid semver (listed above).`
|
|
3857
|
+
);
|
|
3858
|
+
process.exitCode = 1;
|
|
3859
|
+
}
|
|
3516
3860
|
if (badRequires.length > 0) {
|
|
3517
3861
|
logErr(
|
|
3518
3862
|
`${badRequires.length} invalid requires entr${badRequires.length === 1 ? "y" : "ies"} ignored: use the \`kind:@<publisher>/name[#version]\` form.`
|
|
@@ -3536,8 +3880,16 @@ async function indexPulledLibrary(lib, library, name) {
|
|
|
3536
3880
|
const res = await indexLibrary(lib, library);
|
|
3537
3881
|
for (const e of res.errors) logWarn(e);
|
|
3538
3882
|
logOk(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
|
|
3883
|
+
warnUnlistedAssets(await countUnlistedAssets(lib.path), name);
|
|
3539
3884
|
warnIgnoredDomainFiles(lib.path);
|
|
3540
3885
|
}
|
|
3886
|
+
function warnUnlistedAssets(unlisted, name) {
|
|
3887
|
+
if (unlisted > 0) {
|
|
3888
|
+
logWarn(
|
|
3889
|
+
`${unlisted} asset(s) on disk are not in the manifest; run \`skaile library index ${name}\`.`
|
|
3890
|
+
);
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3541
3893
|
function assertManifestEditableOrExit(libraryPath) {
|
|
3542
3894
|
try {
|
|
3543
3895
|
assertManifestEditable(libraryPath);
|
|
@@ -3547,26 +3899,26 @@ function assertManifestEditableOrExit(libraryPath) {
|
|
|
3547
3899
|
}
|
|
3548
3900
|
async function assertLibraryPathFree(manager, dir, exceptId) {
|
|
3549
3901
|
const clash = (await manager.listLibraries()).find(
|
|
3550
|
-
(l) => l.id !== exceptId &&
|
|
3902
|
+
(l) => l.id !== exceptId && path22.resolve(l.path) === dir
|
|
3551
3903
|
);
|
|
3552
3904
|
if (clash) throw new Error(`${dir} is already registered as library "${clash.name}".`);
|
|
3553
3905
|
}
|
|
3554
3906
|
function canonicalDir(dir) {
|
|
3555
|
-
const abs =
|
|
3907
|
+
const abs = path22.resolve(dir);
|
|
3556
3908
|
const missing = [];
|
|
3557
3909
|
let existing = abs;
|
|
3558
|
-
while (!
|
|
3559
|
-
const parent =
|
|
3910
|
+
while (!fs9.existsSync(existing)) {
|
|
3911
|
+
const parent = path22.dirname(existing);
|
|
3560
3912
|
if (parent === existing) return abs;
|
|
3561
|
-
missing.unshift(
|
|
3913
|
+
missing.unshift(path22.basename(existing));
|
|
3562
3914
|
existing = parent;
|
|
3563
3915
|
}
|
|
3564
|
-
return
|
|
3916
|
+
return path22.join(fs9.realpathSync(existing), ...missing);
|
|
3565
3917
|
}
|
|
3566
3918
|
function refuseGlobalInstallFolder(name, dir) {
|
|
3567
3919
|
const reserved = globalInstallDir();
|
|
3568
|
-
const rel =
|
|
3569
|
-
const inside = rel === "" || !rel.startsWith("..") && !
|
|
3920
|
+
const rel = path22.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
|
|
3921
|
+
const inside = rel === "" || !rel.startsWith("..") && !path22.isAbsolute(rel);
|
|
3570
3922
|
if (name?.toLowerCase() === GLOBAL_INSTALL_DIR_NAME || inside) {
|
|
3571
3923
|
logErr(
|
|
3572
3924
|
`"${GLOBAL_INSTALL_DIR_NAME}" is reserved: ${reserved} holds assets from \`skaile install\`, not a library you author.`
|
|
@@ -3576,8 +3928,8 @@ function refuseGlobalInstallFolder(name, dir) {
|
|
|
3576
3928
|
}
|
|
3577
3929
|
async function refuseNestedLibraryPath(manager, dir, exceptId) {
|
|
3578
3930
|
const within = (parent, child) => {
|
|
3579
|
-
const rel =
|
|
3580
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
3931
|
+
const rel = path22.relative(parent, child);
|
|
3932
|
+
return rel === "" || !rel.startsWith("..") && !path22.isAbsolute(rel);
|
|
3581
3933
|
};
|
|
3582
3934
|
const target = canonicalDir(dir).toLowerCase();
|
|
3583
3935
|
const librariesDir = resolveLibraryDir();
|
|
@@ -3607,29 +3959,29 @@ async function refuseNestedLibraryPath(manager, dir, exceptId) {
|
|
|
3607
3959
|
function assertCreateDirInsideLibrary(libRoot, destDir, given) {
|
|
3608
3960
|
const exists = (p6) => {
|
|
3609
3961
|
try {
|
|
3610
|
-
|
|
3962
|
+
fs9.lstatSync(p6);
|
|
3611
3963
|
return true;
|
|
3612
3964
|
} catch {
|
|
3613
3965
|
return false;
|
|
3614
3966
|
}
|
|
3615
3967
|
};
|
|
3616
3968
|
let probe = destDir;
|
|
3617
|
-
while (!exists(probe)) probe =
|
|
3969
|
+
while (!exists(probe)) probe = path22.dirname(probe);
|
|
3618
3970
|
let realProbe;
|
|
3619
3971
|
try {
|
|
3620
|
-
realProbe =
|
|
3972
|
+
realProbe = fs9.realpathSync(probe);
|
|
3621
3973
|
} catch {
|
|
3622
3974
|
logErr(`--dir "${given}" passes through a broken symlink (${probe}).`);
|
|
3623
3975
|
process.exit(1);
|
|
3624
3976
|
}
|
|
3625
|
-
if (!
|
|
3977
|
+
if (!fs9.statSync(realProbe).isDirectory()) {
|
|
3626
3978
|
logErr(`--dir "${given}": ${probe} is not a directory.`);
|
|
3627
3979
|
process.exit(1);
|
|
3628
3980
|
}
|
|
3629
3981
|
const realRoot = canonicalDir(libRoot);
|
|
3630
|
-
const realDest =
|
|
3631
|
-
const rel =
|
|
3632
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
3982
|
+
const realDest = path22.join(realProbe, path22.relative(probe, destDir));
|
|
3983
|
+
const rel = path22.relative(realRoot, realDest);
|
|
3984
|
+
if (rel === ".." || rel.startsWith(`..${path22.sep}`) || path22.isAbsolute(rel)) {
|
|
3633
3985
|
logErr(
|
|
3634
3986
|
`--dir "${given}" must stay inside the library (${realRoot}): it resolves to ${realDest}.`
|
|
3635
3987
|
);
|
|
@@ -3637,7 +3989,7 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
|
|
|
3637
3989
|
}
|
|
3638
3990
|
}
|
|
3639
3991
|
function adoptWritesManifest(libPath) {
|
|
3640
|
-
if (!
|
|
3992
|
+
if (!fs9.existsSync(path22.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
|
|
3641
3993
|
const manifest = loadSkPublishManifest(libPath);
|
|
3642
3994
|
if (!manifest || manifest.source || (manifest.assets ?? []).length > 0) return false;
|
|
3643
3995
|
return manifestPublisherProblems(libPath).length === 0;
|
|
@@ -3691,17 +4043,26 @@ function requireValidLibraryName(name) {
|
|
|
3691
4043
|
var LOCAL_OWNERSHIP_REASON = "ownership only governs sync with a git remote, and a local library is always owned by you.";
|
|
3692
4044
|
function pruneEmptyLibraryParents(libPath) {
|
|
3693
4045
|
const root = canonicalDir(resolveLibraryDir());
|
|
3694
|
-
let dir =
|
|
4046
|
+
let dir = path22.dirname(path22.resolve(libPath));
|
|
3695
4047
|
for (; ; ) {
|
|
3696
|
-
const rel =
|
|
3697
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
3698
|
-
if (!
|
|
3699
|
-
|
|
3700
|
-
dir =
|
|
4048
|
+
const rel = path22.relative(root, canonicalDir(dir));
|
|
4049
|
+
if (rel === "" || rel.startsWith("..") || path22.isAbsolute(rel)) return;
|
|
4050
|
+
if (!fs9.existsSync(dir) || fs9.readdirSync(dir).length > 0) return;
|
|
4051
|
+
fs9.rmdirSync(dir);
|
|
4052
|
+
dir = path22.dirname(dir);
|
|
3701
4053
|
}
|
|
3702
4054
|
}
|
|
4055
|
+
function remoteBranches(url) {
|
|
4056
|
+
const r = spawnSync("git", ["ls-remote", "--heads", url], {
|
|
4057
|
+
encoding: "utf-8",
|
|
4058
|
+
timeout: 2e4,
|
|
4059
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
4060
|
+
});
|
|
4061
|
+
if (r.status !== 0) return [];
|
|
4062
|
+
return r.stdout.split("\n").map((line) => line.split(" ")[1]?.replace(/^refs\/heads\//, "")).filter((b) => !!b);
|
|
4063
|
+
}
|
|
3703
4064
|
async function warnIfNotGithubRemote(name, url) {
|
|
3704
|
-
const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-
|
|
4065
|
+
const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-FFIPWIRM.js');
|
|
3705
4066
|
if (!isGithubRemote(url)) logWarn(notGithubRemoteMessage(name, url));
|
|
3706
4067
|
}
|
|
3707
4068
|
function scaffoldLibraryFiles(dir, name) {
|
|
@@ -3733,9 +4094,9 @@ by the same ref.
|
|
|
3733
4094
|
];
|
|
3734
4095
|
const written = [];
|
|
3735
4096
|
for (const [file, content] of files) {
|
|
3736
|
-
const target =
|
|
3737
|
-
if (
|
|
3738
|
-
|
|
4097
|
+
const target = path22.join(dir, file);
|
|
4098
|
+
if (fs9.existsSync(target)) continue;
|
|
4099
|
+
fs9.writeFileSync(target, content, "utf8");
|
|
3739
4100
|
written.push(file);
|
|
3740
4101
|
}
|
|
3741
4102
|
return written;
|
|
@@ -3823,9 +4184,9 @@ function makeLibraryCommand() {
|
|
|
3823
4184
|
opts.path ??= gone.path;
|
|
3824
4185
|
}
|
|
3825
4186
|
const ownership = flagged[0] ?? gone?.ownership ?? "owner";
|
|
3826
|
-
const libPath = opts.path ?
|
|
4187
|
+
const libPath = opts.path ? path22.resolve(opts.path) : path22.join(resolveLibraryDir(), name);
|
|
3827
4188
|
refuseGlobalInstallFolder(name, libPath);
|
|
3828
|
-
if (
|
|
4189
|
+
if (fs9.existsSync(libPath) && !fs9.statSync(libPath).isDirectory()) {
|
|
3829
4190
|
logErr(`${libPath} exists and is not a directory.`);
|
|
3830
4191
|
process.exit(1);
|
|
3831
4192
|
}
|
|
@@ -3864,9 +4225,9 @@ function makeLibraryCommand() {
|
|
|
3864
4225
|
backend = "git";
|
|
3865
4226
|
backendConfig = { url: adopted.url, branch: adopted.branch, authHint: "ssh" };
|
|
3866
4227
|
} else {
|
|
3867
|
-
|
|
4228
|
+
fs9.mkdirSync(libPath, { recursive: true });
|
|
3868
4229
|
}
|
|
3869
|
-
const blank =
|
|
4230
|
+
const blank = fs9.readdirSync(libPath).every((entry) => entry === ".git");
|
|
3870
4231
|
const isDefault = !hasDefault && ownership !== "reader";
|
|
3871
4232
|
await manager.addLibrary({
|
|
3872
4233
|
name,
|
|
@@ -3911,11 +4272,7 @@ function makeLibraryCommand() {
|
|
|
3911
4272
|
const res = await indexLibrary(lib, library);
|
|
3912
4273
|
for (const e of res.errors) logWarn(e);
|
|
3913
4274
|
logOk(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
|
|
3914
|
-
|
|
3915
|
-
logWarn(
|
|
3916
|
-
`${unlisted} asset(s) on disk are not in the manifest; run \`skaile library index ${name}\`.`
|
|
3917
|
-
);
|
|
3918
|
-
}
|
|
4275
|
+
warnUnlistedAssets(unlisted, name);
|
|
3919
4276
|
warnIgnoredDomainFiles(libPath);
|
|
3920
4277
|
}
|
|
3921
4278
|
} catch (err2) {
|
|
@@ -3925,7 +4282,10 @@ function makeLibraryCommand() {
|
|
|
3925
4282
|
}
|
|
3926
4283
|
}
|
|
3927
4284
|
);
|
|
3928
|
-
cmd.command("link <name> <git-url>").description("Attach a github remote to a local library (makes it store-publishable)").option(
|
|
4285
|
+
cmd.command("link <name> <git-url>").description("Attach a github remote to a local library (makes it store-publishable)").option(
|
|
4286
|
+
"--branch <name>",
|
|
4287
|
+
"Branch to track (default: the checked-out branch of an existing repo, else main)"
|
|
4288
|
+
).action(async (name, url, opts) => {
|
|
3929
4289
|
const { manager, close } = await openLibraryManager();
|
|
3930
4290
|
try {
|
|
3931
4291
|
const lib = await manager.requireLibraryDir(name);
|
|
@@ -3935,11 +4295,25 @@ function makeLibraryCommand() {
|
|
|
3935
4295
|
);
|
|
3936
4296
|
process.exit(1);
|
|
3937
4297
|
}
|
|
3938
|
-
|
|
3939
|
-
|
|
4298
|
+
const head = isGitRepo(lib.path) ? spawnSync("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
|
|
4299
|
+
cwd: lib.path,
|
|
4300
|
+
encoding: "utf-8"
|
|
4301
|
+
}) : void 0;
|
|
4302
|
+
const branch = opts.branch ?? (head?.status === 0 && head.stdout.trim() || "main");
|
|
4303
|
+
if (opts.branch === void 0) {
|
|
4304
|
+
const theirs = remoteBranches(url);
|
|
4305
|
+
if (theirs.length > 0 && !theirs.includes(branch)) {
|
|
4306
|
+
logErr(
|
|
4307
|
+
`The remote already has ${theirs.length === 1 ? "branch" : "branches"} ${theirs.join(", ")}; pass --branch ${theirs[0]} to track ${theirs.length === 1 ? "it" : "one"}.`
|
|
4308
|
+
);
|
|
4309
|
+
process.exit(1);
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4312
|
+
ensureGitRepo(lib.path, url, branch);
|
|
4313
|
+
trackOriginBranch(lib.path, branch, { fetch: true });
|
|
3940
4314
|
await manager.updateLibrary(name, {
|
|
3941
4315
|
backend: "git",
|
|
3942
|
-
backendConfig: { url, branch
|
|
4316
|
+
backendConfig: { url, branch, authHint: "ssh" }
|
|
3943
4317
|
});
|
|
3944
4318
|
logOk(`Library "${name}" linked to ${url}.`);
|
|
3945
4319
|
await warnIfNotGithubRemote(name, url);
|
|
@@ -3980,10 +4354,10 @@ function makeLibraryCommand() {
|
|
|
3980
4354
|
exitOnManifestPublisherProblems(target.path, target.name);
|
|
3981
4355
|
const effectiveKind = opts.kind ?? kind;
|
|
3982
4356
|
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
|
|
3983
|
-
const libRoot =
|
|
3984
|
-
const destDir = opts.dir ?
|
|
3985
|
-
const relDest =
|
|
3986
|
-
if (relDest === ".." || relDest.startsWith(`..${
|
|
4357
|
+
const libRoot = path22.resolve(target.path);
|
|
4358
|
+
const destDir = opts.dir ? path22.resolve(libRoot, opts.dir) : libRoot;
|
|
4359
|
+
const relDest = path22.relative(libRoot, destDir);
|
|
4360
|
+
if (relDest === ".." || relDest.startsWith(`..${path22.sep}`) || path22.isAbsolute(relDest)) {
|
|
3987
4361
|
logErr(`--dir "${opts.dir}" must stay inside the library (${libRoot}).`);
|
|
3988
4362
|
process.exit(1);
|
|
3989
4363
|
}
|
|
@@ -3992,11 +4366,11 @@ function makeLibraryCommand() {
|
|
|
3992
4366
|
libRoot,
|
|
3993
4367
|
effectiveKind,
|
|
3994
4368
|
name,
|
|
3995
|
-
|
|
4369
|
+
path22.relative(libRoot, path22.join(destDir, name))
|
|
3996
4370
|
);
|
|
3997
4371
|
if (taken) {
|
|
3998
4372
|
logErr(
|
|
3999
|
-
`${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${
|
|
4373
|
+
`${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path22.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
|
|
4000
4374
|
);
|
|
4001
4375
|
process.exit(1);
|
|
4002
4376
|
}
|
|
@@ -4054,13 +4428,13 @@ function makeLibraryCommand() {
|
|
|
4054
4428
|
logErr(`A library named "${newName}" is already registered.`);
|
|
4055
4429
|
process.exit(1);
|
|
4056
4430
|
}
|
|
4057
|
-
const newPath =
|
|
4431
|
+
const newPath = path22.join(path22.dirname(lib.path), newName);
|
|
4058
4432
|
refuseGlobalInstallFolder(newName, newPath);
|
|
4059
|
-
if (
|
|
4433
|
+
if (fs9.existsSync(newPath)) {
|
|
4060
4434
|
logErr(`Target directory already exists: ${newPath}`);
|
|
4061
4435
|
process.exit(1);
|
|
4062
4436
|
}
|
|
4063
|
-
|
|
4437
|
+
fs9.renameSync(lib.path, newPath);
|
|
4064
4438
|
await manager.updateLibrary(lib.id, { name: newName, path: newPath });
|
|
4065
4439
|
logOk(`Renamed ${lib.name} \u2192 ${newName}`);
|
|
4066
4440
|
}
|
|
@@ -4140,8 +4514,8 @@ function makeLibraryCommand() {
|
|
|
4140
4514
|
}
|
|
4141
4515
|
patch.isDefault = false;
|
|
4142
4516
|
} else if (field === "path") {
|
|
4143
|
-
const dir =
|
|
4144
|
-
if (!
|
|
4517
|
+
const dir = path22.resolve(value);
|
|
4518
|
+
if (!fs9.existsSync(dir) || !fs9.statSync(dir).isDirectory()) {
|
|
4145
4519
|
logErr(`Directory does not exist: ${dir}. \`library set path=\` does not move files.`);
|
|
4146
4520
|
process.exit(1);
|
|
4147
4521
|
}
|
|
@@ -4352,16 +4726,16 @@ function makeLibraryCommand() {
|
|
|
4352
4726
|
"With --create-repo: create the repo private (the store only accepts public repos)"
|
|
4353
4727
|
).option("--ref <gitref>", "Git ref to ingest (default: the library branch or main)").option("--dry-run", "Print the plan; push nothing and call no store endpoint").action(
|
|
4354
4728
|
async (lib, opts) => {
|
|
4355
|
-
const { runLibraryPublish } = await import('../library-publish-
|
|
4729
|
+
const { runLibraryPublish } = await import('../library-publish-FFIPWIRM.js');
|
|
4356
4730
|
await withStoreErrorHandling(() => runLibraryPublish(lib, opts));
|
|
4357
4731
|
}
|
|
4358
4732
|
);
|
|
4359
4733
|
cmd.command("register <lib>").description("Register the library's manifest without pushing (bytes already on github)").option("--asset <ref>", "Publish only the single asset matching this ref/name").option("--ref <gitref>", "Git ref to ingest (default: the library branch or main)").option("--dry-run", "Print the plan; call no store endpoint").action(async (lib, opts) => {
|
|
4360
|
-
const { runLibraryRegister } = await import('../library-publish-
|
|
4734
|
+
const { runLibraryRegister } = await import('../library-publish-FFIPWIRM.js');
|
|
4361
4735
|
await withStoreErrorHandling(() => runLibraryRegister(lib, opts));
|
|
4362
4736
|
});
|
|
4363
4737
|
cmd.command("yank <lib>").description("Retract the library's published assets from the store").option("--asset <ref>", "Yank only the single asset matching this ref/name").action(async (lib, opts) => {
|
|
4364
|
-
const { runLibraryYank } = await import('../library-publish-
|
|
4738
|
+
const { runLibraryYank } = await import('../library-publish-FFIPWIRM.js');
|
|
4365
4739
|
await withStoreErrorHandling(() => runLibraryYank(lib, opts));
|
|
4366
4740
|
});
|
|
4367
4741
|
return cmd;
|
|
@@ -4412,9 +4786,9 @@ async function printOverallStatus(projectDir, asJson) {
|
|
|
4412
4786
|
} catch {
|
|
4413
4787
|
secretsStrategy = "unavailable";
|
|
4414
4788
|
}
|
|
4415
|
-
const resolvedProjectDir =
|
|
4416
|
-
const hasWorkspaceConfig = existsSync(
|
|
4417
|
-
const hasLockFile = existsSync(
|
|
4789
|
+
const resolvedProjectDir = path22.resolve(projectDir);
|
|
4790
|
+
const hasWorkspaceConfig = existsSync(path22.join(resolvedProjectDir, "skaile.yaml"));
|
|
4791
|
+
const hasLockFile = existsSync(path22.join(resolvedProjectDir, "skaile.lock.yaml"));
|
|
4418
4792
|
let assignments = [];
|
|
4419
4793
|
if (hasWorkspaceConfig) {
|
|
4420
4794
|
try {
|
|
@@ -5021,7 +5395,7 @@ function scheduleSoftDepPreview() {
|
|
|
5021
5395
|
}
|
|
5022
5396
|
async function loadAssets() {
|
|
5023
5397
|
softDepPreviewCache.clear();
|
|
5024
|
-
const { gatherAssetFeeds } = await import('../asset-feeds-
|
|
5398
|
+
const { gatherAssetFeeds } = await import('../asset-feeds-ALMTHLPV.js');
|
|
5025
5399
|
const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
|
|
5026
5400
|
if (notes.length > 0) {
|
|
5027
5401
|
state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
|
|
@@ -5029,7 +5403,7 @@ async function loadAssets() {
|
|
|
5029
5403
|
const installed = new Set(am.listDeployed().map((e) => `${e.kind}:${e.name}`));
|
|
5030
5404
|
let lock = null;
|
|
5031
5405
|
try {
|
|
5032
|
-
lock = readLock(
|
|
5406
|
+
lock = readLock(path22__default.join(am.projectDir, "skaile.lock.yaml"));
|
|
5033
5407
|
} catch {
|
|
5034
5408
|
}
|
|
5035
5409
|
const rows = buildAssetRows(
|
|
@@ -5051,7 +5425,7 @@ function rebuildSourceTree() {
|
|
|
5051
5425
|
rebuildVisibleSources();
|
|
5052
5426
|
}
|
|
5053
5427
|
function sourceOrgRepo(s) {
|
|
5054
|
-
const parts = s.path.split(
|
|
5428
|
+
const parts = s.path.split(path22__default.sep).filter(Boolean);
|
|
5055
5429
|
if (parts.length < 2) return null;
|
|
5056
5430
|
return { org: parts[parts.length - 2], repo: parts[parts.length - 1] };
|
|
5057
5431
|
}
|
|
@@ -5225,13 +5599,13 @@ function reconcileCollapsedSets(rows) {
|
|
|
5225
5599
|
async function loadSourcesAndLibraries() {
|
|
5226
5600
|
try {
|
|
5227
5601
|
const [{ openLibraryManager: openLibraryManager2 }, { getGlobalCacheDir: getGlobalCacheDir2, globalSkaileDir: globalSkaileDir2 }] = await Promise.all([
|
|
5228
|
-
import('../open-library-
|
|
5602
|
+
import('../open-library-PZAT3TJA.js'),
|
|
5229
5603
|
import('../core/index.js')
|
|
5230
5604
|
]);
|
|
5231
5605
|
const { manager, library, close } = await openLibraryManager2();
|
|
5232
5606
|
try {
|
|
5233
5607
|
const newRoot = getGlobalCacheDir2();
|
|
5234
|
-
const legacyRoot =
|
|
5608
|
+
const legacyRoot = path22__default.join(globalSkaileDir2(), "sources");
|
|
5235
5609
|
const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
|
|
5236
5610
|
const libs = await manager.listLibraries();
|
|
5237
5611
|
const defs = await library.listAssetDefs();
|
|
@@ -6191,19 +6565,19 @@ async function run(projectDir) {
|
|
|
6191
6565
|
}
|
|
6192
6566
|
function makeManageCommand() {
|
|
6193
6567
|
return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
6194
|
-
await run(
|
|
6568
|
+
await run(path22__default.resolve(opts.projectDir));
|
|
6195
6569
|
});
|
|
6196
6570
|
}
|
|
6197
6571
|
function makeMcpServerCommand() {
|
|
6198
6572
|
return new Command("mcp-server").description("Start skaile workspace MCP server (stdio transport)").option("--project-dir <path>", "Project directory (default: cwd)", process.cwd()).action(async (opts) => {
|
|
6199
|
-
const
|
|
6200
|
-
const projectDir =
|
|
6201
|
-
const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
|
|
6202
|
-
|
|
6203
|
-
new
|
|
6573
|
+
const path44 = await import('path');
|
|
6574
|
+
const projectDir = path44.default.resolve(opts.projectDir);
|
|
6575
|
+
const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
|
|
6576
|
+
registerLogStore2(
|
|
6577
|
+
new LogStore2({
|
|
6204
6578
|
sessionId: "mcp-server",
|
|
6205
6579
|
level: "info",
|
|
6206
|
-
sinks: [new
|
|
6580
|
+
sinks: [new StdoutSink2({ stream: "stderr" })]
|
|
6207
6581
|
})
|
|
6208
6582
|
);
|
|
6209
6583
|
const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
|
|
@@ -6244,10 +6618,10 @@ function walkFiles(root, match) {
|
|
|
6244
6618
|
return;
|
|
6245
6619
|
}
|
|
6246
6620
|
for (const entry of entries) {
|
|
6247
|
-
const full =
|
|
6621
|
+
const full = path22__default.join(dir, entry.name);
|
|
6248
6622
|
if (entry.isDirectory()) {
|
|
6249
6623
|
if (SKIPPED_DIRS.has(entry.name)) continue;
|
|
6250
|
-
if (entry.name === "cache" &&
|
|
6624
|
+
if (entry.name === "cache" && path22__default.basename(dir) === ".skaile") continue;
|
|
6251
6625
|
visit(full);
|
|
6252
6626
|
} else if (entry.isFile() && match(entry.name)) {
|
|
6253
6627
|
out.push(full);
|
|
@@ -6265,14 +6639,14 @@ function applyChanges2(changes) {
|
|
|
6265
6639
|
switch (change.type) {
|
|
6266
6640
|
case "write":
|
|
6267
6641
|
case "create":
|
|
6268
|
-
mkdirSync(
|
|
6642
|
+
mkdirSync(path22__default.dirname(change.path), { recursive: true });
|
|
6269
6643
|
writeFileSync(change.path, change.after, "utf-8");
|
|
6270
6644
|
break;
|
|
6271
6645
|
case "delete":
|
|
6272
6646
|
rmSync(change.path, { force: true });
|
|
6273
6647
|
break;
|
|
6274
6648
|
case "move":
|
|
6275
|
-
mkdirSync(
|
|
6649
|
+
mkdirSync(path22__default.dirname(change.to), { recursive: true });
|
|
6276
6650
|
writeFileSync(change.to, change.after, "utf-8");
|
|
6277
6651
|
rmSync(change.from, { force: true });
|
|
6278
6652
|
break;
|
|
@@ -6365,7 +6739,7 @@ function unifiedDiff(before, after, oldLabel, newLabel, context = 3) {
|
|
|
6365
6739
|
return `${out.join("\n")}
|
|
6366
6740
|
`;
|
|
6367
6741
|
}
|
|
6368
|
-
var posix = (p6) => p6.split(
|
|
6742
|
+
var posix = (p6) => p6.split(path22__default.sep).join("/");
|
|
6369
6743
|
function colorizeDiff(diff) {
|
|
6370
6744
|
return diff.split("\n").map((line) => {
|
|
6371
6745
|
if (line.startsWith("+++") || line.startsWith("---")) return S.bold(line);
|
|
@@ -6376,7 +6750,7 @@ function colorizeDiff(diff) {
|
|
|
6376
6750
|
}).join("\n");
|
|
6377
6751
|
}
|
|
6378
6752
|
function renderChange(change, base) {
|
|
6379
|
-
const rel = (p6) => posix(
|
|
6753
|
+
const rel = (p6) => posix(path22__default.relative(base, p6) || path22__default.basename(p6));
|
|
6380
6754
|
switch (change.type) {
|
|
6381
6755
|
case "write":
|
|
6382
6756
|
return unifiedDiff(
|
|
@@ -6403,7 +6777,7 @@ ${diff}`;
|
|
|
6403
6777
|
}
|
|
6404
6778
|
}
|
|
6405
6779
|
function changeLabel(change, base) {
|
|
6406
|
-
const rel = (p6) => posix(
|
|
6780
|
+
const rel = (p6) => posix(path22__default.relative(base, p6) || path22__default.basename(p6));
|
|
6407
6781
|
switch (change.type) {
|
|
6408
6782
|
case "write":
|
|
6409
6783
|
return `modify ${rel(change.path)}`;
|
|
@@ -6463,10 +6837,10 @@ function loadAsset(projectDir, id, ref) {
|
|
|
6463
6837
|
)
|
|
6464
6838
|
};
|
|
6465
6839
|
}
|
|
6466
|
-
const manifestPath =
|
|
6840
|
+
const manifestPath = path22__default.join(dir, AGENT_MANIFEST_FILE);
|
|
6467
6841
|
let text;
|
|
6468
6842
|
try {
|
|
6469
|
-
text =
|
|
6843
|
+
text = fs9__default.readFileSync(manifestPath, "utf-8");
|
|
6470
6844
|
} catch {
|
|
6471
6845
|
return {
|
|
6472
6846
|
diagnostic: err(
|
|
@@ -6571,6 +6945,7 @@ function checkAgentInstances(projectDir, parsed) {
|
|
|
6571
6945
|
const diagnostics = [];
|
|
6572
6946
|
const instances = normalizeAgentInstances(parsed.agents, diagnostics);
|
|
6573
6947
|
const agent = isRecord(parsed.agent) ? parsed.agent : void 0;
|
|
6948
|
+
diagnostics.push(...agentBlockKeyDiagnostics(parsed.agent));
|
|
6574
6949
|
if (agent?.subagents !== void 0) {
|
|
6575
6950
|
diagnostics.push(
|
|
6576
6951
|
err(
|
|
@@ -6645,12 +7020,12 @@ function findManifestCandidates(rootPath) {
|
|
|
6645
7020
|
function walk(dir) {
|
|
6646
7021
|
let entries;
|
|
6647
7022
|
try {
|
|
6648
|
-
entries =
|
|
7023
|
+
entries = fs9__default.readdirSync(dir, { withFileTypes: true });
|
|
6649
7024
|
} catch {
|
|
6650
7025
|
return;
|
|
6651
7026
|
}
|
|
6652
7027
|
for (const entry of entries) {
|
|
6653
|
-
const fullPath =
|
|
7028
|
+
const fullPath = path22__default.join(dir, entry.name);
|
|
6654
7029
|
if (entry.isDirectory()) {
|
|
6655
7030
|
if (!SKIP_DIRS.has(entry.name)) walk(fullPath);
|
|
6656
7031
|
} else if (entry.isFile()) {
|
|
@@ -6667,10 +7042,10 @@ function findManifestCandidates(rootPath) {
|
|
|
6667
7042
|
return candidates;
|
|
6668
7043
|
}
|
|
6669
7044
|
function parseManifestCandidate(c, absRoot) {
|
|
6670
|
-
const content =
|
|
7045
|
+
const content = fs9__default.readFileSync(c.filePath, "utf-8");
|
|
6671
7046
|
const res = parseManifestFile(c.filePath, content);
|
|
6672
7047
|
if (!res.ok) {
|
|
6673
|
-
logErr(`${
|
|
7048
|
+
logErr(`${path22__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 parse error: ${res.reason}`);
|
|
6674
7049
|
return { kind: "error" };
|
|
6675
7050
|
}
|
|
6676
7051
|
return {
|
|
@@ -6687,29 +7062,52 @@ function checkComposeKinds(parsed, registry) {
|
|
|
6687
7062
|
const diagnostics = [];
|
|
6688
7063
|
composes.forEach((item, i) => {
|
|
6689
7064
|
if (item === null || typeof item !== "object") return;
|
|
6690
|
-
const
|
|
7065
|
+
const fields = item;
|
|
7066
|
+
const kind = fields.kind;
|
|
6691
7067
|
if (typeof kind !== "string") return;
|
|
6692
|
-
if (PSEUDO_COMPOSE_KINDS.has(kind)
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
7068
|
+
if (!PSEUDO_COMPOSE_KINDS.has(kind) && !registry.getProvider(kind)) {
|
|
7069
|
+
diagnostics.push({
|
|
7070
|
+
code: "unknown_asset_kind",
|
|
7071
|
+
severity: "error",
|
|
7072
|
+
message: `composes item kind "${kind}" is not a registered asset kind (registered: ${registry.getAllKinds().join(", ")})`,
|
|
7073
|
+
path: `composes[${i}].kind`
|
|
7074
|
+
});
|
|
7075
|
+
return;
|
|
7076
|
+
}
|
|
7077
|
+
if (fields.binding !== void 0 || typeof fields.ref !== "string") return;
|
|
7078
|
+
try {
|
|
7079
|
+
resolveBinding({ kind, ref: fields.ref });
|
|
7080
|
+
} catch (err2) {
|
|
7081
|
+
if (!(err2 instanceof UnknownCompositionKindError)) throw err2;
|
|
7082
|
+
diagnostics.push({
|
|
7083
|
+
code: "unknown_asset_kind",
|
|
7084
|
+
severity: "error",
|
|
7085
|
+
message: `composes item "${fields.ref}" of kind "${kind}" has no default binding; set \`binding:\` (the session build fails without it)`,
|
|
7086
|
+
path: `composes[${i}].binding`
|
|
7087
|
+
});
|
|
7088
|
+
}
|
|
6699
7089
|
});
|
|
6700
7090
|
return diagnostics;
|
|
6701
7091
|
}
|
|
7092
|
+
function libraryRootOf(absRoot) {
|
|
7093
|
+
for (let dir = absRoot; ; dir = path22__default.dirname(dir)) {
|
|
7094
|
+
if (fs9__default.existsSync(path22__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
|
|
7095
|
+
if (path22__default.dirname(dir) === dir) return absRoot;
|
|
7096
|
+
}
|
|
7097
|
+
}
|
|
6702
7098
|
function validateManifestCandidate(c, parsed, body, absRoot, registry, strictConformance) {
|
|
6703
|
-
const relPath =
|
|
7099
|
+
const relPath = path22__default.relative(absRoot, c.filePath);
|
|
6704
7100
|
let errors = 0;
|
|
6705
7101
|
let warnings = 0;
|
|
6706
|
-
const dirName =
|
|
7102
|
+
const dirName = path22__default.basename(path22__default.dirname(c.filePath));
|
|
6707
7103
|
const checked = checkAsset(
|
|
6708
7104
|
c.kind,
|
|
6709
7105
|
parsed ?? {},
|
|
6710
7106
|
body,
|
|
6711
7107
|
dirName,
|
|
6712
|
-
registry
|
|
7108
|
+
registry,
|
|
7109
|
+
fs9__default.readFileSync(c.filePath, "utf-8"),
|
|
7110
|
+
path22__default.basename(c.filePath)
|
|
6713
7111
|
);
|
|
6714
7112
|
for (const f of checked.errors) {
|
|
6715
7113
|
logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
|
|
@@ -6717,7 +7115,7 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
|
|
|
6717
7115
|
}
|
|
6718
7116
|
for (const f of checked.advisories) {
|
|
6719
7117
|
const line = `${relPath} [${f.tag}] \u2014 ${f.text}`;
|
|
6720
|
-
if (f.conformance && strictConformance) {
|
|
7118
|
+
if (f.conformance && strictConformance || f.scaffoldBody) {
|
|
6721
7119
|
logErr(line);
|
|
6722
7120
|
errors++;
|
|
6723
7121
|
} else {
|
|
@@ -6725,7 +7123,17 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
|
|
|
6725
7123
|
warnings++;
|
|
6726
7124
|
}
|
|
6727
7125
|
}
|
|
6728
|
-
if (c.kind === "agent" &&
|
|
7126
|
+
if (c.kind === "agent" && parsed !== null && typeof parsed === "object") {
|
|
7127
|
+
for (const f of checkAgentFiles(
|
|
7128
|
+
parsed,
|
|
7129
|
+
path22__default.dirname(c.filePath),
|
|
7130
|
+
libraryRootOf(absRoot)
|
|
7131
|
+
)) {
|
|
7132
|
+
logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
|
|
7133
|
+
errors++;
|
|
7134
|
+
}
|
|
7135
|
+
}
|
|
7136
|
+
if (c.kind === "agent" && path22__default.basename(c.filePath) === "agent.yaml") {
|
|
6729
7137
|
for (const d of [
|
|
6730
7138
|
...checkComposeKinds(parsed, registry),
|
|
6731
7139
|
...composeSlotDiagnostics(parsed),
|
|
@@ -6743,17 +7151,36 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
|
|
|
6743
7151
|
}
|
|
6744
7152
|
return { errors, warnings };
|
|
6745
7153
|
}
|
|
7154
|
+
function scanIdentities(root) {
|
|
7155
|
+
const identities = /* @__PURE__ */ new Set();
|
|
7156
|
+
for (const c of findManifestCandidates(root)) {
|
|
7157
|
+
let parsed;
|
|
7158
|
+
try {
|
|
7159
|
+
const res = parseManifestFile(c.filePath, fs9__default.readFileSync(c.filePath, "utf-8"));
|
|
7160
|
+
if (!res.ok) continue;
|
|
7161
|
+
parsed = res.data;
|
|
7162
|
+
} catch {
|
|
7163
|
+
continue;
|
|
7164
|
+
}
|
|
7165
|
+
if (parsed === null || typeof parsed !== "object") continue;
|
|
7166
|
+
const identity = parsed[c.kind === "flow" ? "id" : "name"];
|
|
7167
|
+
if (typeof identity === "string" && identity.length > 0)
|
|
7168
|
+
identities.add(`${c.kind}:${identity}`);
|
|
7169
|
+
}
|
|
7170
|
+
return identities;
|
|
7171
|
+
}
|
|
6746
7172
|
function validateManifests(rootPath, strictConformance) {
|
|
6747
|
-
const absRoot =
|
|
6748
|
-
if (!
|
|
7173
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
7174
|
+
if (!fs9__default.existsSync(absRoot)) {
|
|
6749
7175
|
logErr(`Path does not exist: ${absRoot}`);
|
|
6750
7176
|
return { total: 0, errors: 1, warnings: 0 };
|
|
6751
7177
|
}
|
|
6752
7178
|
const registry = getKindRegistry();
|
|
6753
7179
|
const candidates = findManifestCandidates(absRoot);
|
|
6754
|
-
let errors =
|
|
7180
|
+
let errors = reportLibrarySymlinks(absRoot);
|
|
6755
7181
|
let warnings = 0;
|
|
6756
7182
|
const seenIdentity = /* @__PURE__ */ new Map();
|
|
7183
|
+
const agentsToResolve = [];
|
|
6757
7184
|
for (const c of candidates) {
|
|
6758
7185
|
const parseResult = parseManifestCandidate(c, absRoot);
|
|
6759
7186
|
if (parseResult.kind === "error") {
|
|
@@ -6770,22 +7197,38 @@ function validateManifests(rootPath, strictConformance) {
|
|
|
6770
7197
|
);
|
|
6771
7198
|
errors += delta.errors;
|
|
6772
7199
|
warnings += delta.warnings;
|
|
7200
|
+
if (c.kind === "agent" && parseResult.parsed !== null && typeof parseResult.parsed === "object") {
|
|
7201
|
+
agentsToResolve.push({
|
|
7202
|
+
relPath: path22__default.relative(absRoot, c.filePath),
|
|
7203
|
+
parsed: parseResult.parsed
|
|
7204
|
+
});
|
|
7205
|
+
}
|
|
6773
7206
|
const obj = parseResult.parsed;
|
|
6774
7207
|
const identity = obj && typeof obj === "object" ? obj[c.kind === "flow" ? "id" : "name"] : null;
|
|
6775
7208
|
if (typeof identity === "string" && identity.length > 0) {
|
|
6776
|
-
const dir =
|
|
7209
|
+
const dir = path22__default.dirname(c.filePath);
|
|
6777
7210
|
const key = `${c.kind}:${identity}`;
|
|
6778
7211
|
const first = seenIdentity.get(key);
|
|
6779
7212
|
if (first === void 0) {
|
|
6780
7213
|
seenIdentity.set(key, dir);
|
|
6781
7214
|
} else if (first !== dir) {
|
|
6782
7215
|
logErr(
|
|
6783
|
-
`${
|
|
7216
|
+
`${path22__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 ${key} is also defined in ${path22__default.relative(absRoot, first) || "."}; two directories cannot share a kind and name (\`skaile library index\` keeps only the first).`
|
|
6784
7217
|
);
|
|
6785
7218
|
errors++;
|
|
6786
7219
|
}
|
|
6787
7220
|
}
|
|
6788
7221
|
}
|
|
7222
|
+
const libraryRoot = libraryRootOf(absRoot);
|
|
7223
|
+
const libraryPublisher = loadSkPublishManifest(libraryRoot)?.publisher;
|
|
7224
|
+
const siblingIdentities = libraryRoot === absRoot ? /* @__PURE__ */ new Set() : scanIdentities(libraryRoot);
|
|
7225
|
+
const hasAsset = (kind, name) => seenIdentity.has(`${kind}:${name}`) || siblingIdentities.has(`${kind}:${name}`);
|
|
7226
|
+
for (const agent of agentsToResolve) {
|
|
7227
|
+
for (const f of agentComposeRefAdvisories(agent.parsed, hasAsset, libraryPublisher)) {
|
|
7228
|
+
logWarn(`${agent.relPath} [${f.tag}] \u2014 ${f.text}`);
|
|
7229
|
+
warnings++;
|
|
7230
|
+
}
|
|
7231
|
+
}
|
|
6789
7232
|
return { total: candidates.length, errors, warnings };
|
|
6790
7233
|
}
|
|
6791
7234
|
function findWorkspaceManifests(rootPath) {
|
|
@@ -6793,12 +7236,12 @@ function findWorkspaceManifests(rootPath) {
|
|
|
6793
7236
|
function walk(dir) {
|
|
6794
7237
|
let entries;
|
|
6795
7238
|
try {
|
|
6796
|
-
entries =
|
|
7239
|
+
entries = fs9__default.readdirSync(dir, { withFileTypes: true });
|
|
6797
7240
|
} catch {
|
|
6798
7241
|
return;
|
|
6799
7242
|
}
|
|
6800
7243
|
for (const entry of entries) {
|
|
6801
|
-
const full =
|
|
7244
|
+
const full = path22__default.join(dir, entry.name);
|
|
6802
7245
|
if (entry.isDirectory()) {
|
|
6803
7246
|
if (!SKIP_DIRS.has(entry.name)) walk(full);
|
|
6804
7247
|
} else if (entry.isFile() && /(^|\.)skaile\.yaml$/.test(entry.name)) {
|
|
@@ -6860,15 +7303,15 @@ function validateWorkspaceAssets(parsed, relPath) {
|
|
|
6860
7303
|
}
|
|
6861
7304
|
return errors;
|
|
6862
7305
|
}
|
|
6863
|
-
function validateWorkspaceManifests(rootPath) {
|
|
6864
|
-
const absRoot =
|
|
7306
|
+
async function validateWorkspaceManifests(rootPath) {
|
|
7307
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6865
7308
|
const files = findWorkspaceManifests(absRoot);
|
|
6866
7309
|
let errors = 0;
|
|
6867
7310
|
for (const file of files) {
|
|
6868
|
-
const relPath =
|
|
7311
|
+
const relPath = path22__default.relative(absRoot, file);
|
|
6869
7312
|
let parsed;
|
|
6870
7313
|
try {
|
|
6871
|
-
parsed = parse(
|
|
7314
|
+
parsed = parse(fs9__default.readFileSync(file, "utf-8")) ?? {};
|
|
6872
7315
|
} catch (e) {
|
|
6873
7316
|
logErr(`${relPath} \u2014 parse error: ${e instanceof Error ? e.message : String(e)}`);
|
|
6874
7317
|
errors++;
|
|
@@ -6876,7 +7319,7 @@ function validateWorkspaceManifests(rootPath) {
|
|
|
6876
7319
|
}
|
|
6877
7320
|
errors += validateWorkspaceRefs(collectWorkspaceRefFields(parsed), relPath);
|
|
6878
7321
|
errors += validateWorkspaceAssets(parsed, relPath);
|
|
6879
|
-
for (const d of checkAgentInstances(
|
|
7322
|
+
for (const d of checkAgentInstances(path22__default.dirname(file), parsed)) {
|
|
6880
7323
|
const line = `${relPath} [agents] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`;
|
|
6881
7324
|
if (d.severity === "error") {
|
|
6882
7325
|
logErr(line);
|
|
@@ -6885,11 +7328,27 @@ function validateWorkspaceManifests(rootPath) {
|
|
|
6885
7328
|
logWarn(line);
|
|
6886
7329
|
}
|
|
6887
7330
|
}
|
|
7331
|
+
const decoded = decodeSkaileYaml(fs9__default.readFileSync(file, "utf-8"));
|
|
7332
|
+
for (const d of decoded.diagnostics) {
|
|
7333
|
+
if (d.code !== "connector_missing_driver") continue;
|
|
7334
|
+
logErr(`${relPath} [connectors] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`);
|
|
7335
|
+
errors++;
|
|
7336
|
+
}
|
|
7337
|
+
if ((decoded.config?.connectors ?? []).length > 0) {
|
|
7338
|
+
const assets = await resolveRuntimeAssets(path22__default.dirname(file));
|
|
7339
|
+
if (!assets.warnings.some((w) => w.code === "repo_unavailable")) {
|
|
7340
|
+
for (const w of assets.warnings) {
|
|
7341
|
+
if (w.code !== "missing_driver" || !w.name) continue;
|
|
7342
|
+
logErr(`${relPath} [connectors] \u2014 ${w.code}: ${w.message}`);
|
|
7343
|
+
errors++;
|
|
7344
|
+
}
|
|
7345
|
+
}
|
|
7346
|
+
}
|
|
6888
7347
|
}
|
|
6889
7348
|
return { total: files.length, errors };
|
|
6890
7349
|
}
|
|
6891
7350
|
function validatePublishManifestRoots(rootPath) {
|
|
6892
|
-
const absRoot =
|
|
7351
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6893
7352
|
const manifest = loadSkPublishManifest(absRoot);
|
|
6894
7353
|
if (!manifest) return 0;
|
|
6895
7354
|
const missing = missingRootAssets(absRoot, manifest);
|
|
@@ -6901,7 +7360,7 @@ function validatePublishManifestRoots(rootPath) {
|
|
|
6901
7360
|
return missing.length;
|
|
6902
7361
|
}
|
|
6903
7362
|
function validatePublishManifestRequires(rootPath) {
|
|
6904
|
-
const problems = manifestRequiresProblems(
|
|
7363
|
+
const problems = manifestRequiresProblems(path22__default.resolve(rootPath));
|
|
6905
7364
|
for (const p6 of problems) {
|
|
6906
7365
|
logErr(
|
|
6907
7366
|
`${SKAILE_MANIFEST_FILENAME} [assets] \u2014 ${p6.asset}: ${p6.message}. Use the \`kind:@<publisher>/name[#version]\` form.`
|
|
@@ -6910,20 +7369,29 @@ function validatePublishManifestRequires(rootPath) {
|
|
|
6910
7369
|
return problems.length;
|
|
6911
7370
|
}
|
|
6912
7371
|
function validatePublishManifestPublisherSlugs(rootPath) {
|
|
6913
|
-
const problems = manifestPublisherProblems(
|
|
7372
|
+
const problems = manifestPublisherProblems(path22__default.resolve(rootPath));
|
|
6914
7373
|
for (const message of problems) logErr(message);
|
|
6915
7374
|
return problems.length;
|
|
6916
7375
|
}
|
|
7376
|
+
function validatePublishManifestParses(rootPath) {
|
|
7377
|
+
try {
|
|
7378
|
+
assertManifestEditable(path22__default.resolve(rootPath));
|
|
7379
|
+
return 0;
|
|
7380
|
+
} catch (err2) {
|
|
7381
|
+
logErr(err2 instanceof Error ? err2.message : String(err2));
|
|
7382
|
+
return 1;
|
|
7383
|
+
}
|
|
7384
|
+
}
|
|
6917
7385
|
function validatePublishManifestVersions(rootPath) {
|
|
6918
|
-
const absRoot =
|
|
7386
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6919
7387
|
const manifest = loadSkPublishManifest(absRoot);
|
|
6920
7388
|
if (!manifest || manifest.source) return 0;
|
|
6921
7389
|
let warnings = 0;
|
|
6922
7390
|
for (const a of manifest.assets ?? []) {
|
|
6923
7391
|
if (!a.root || a.source || !a.version) continue;
|
|
6924
|
-
const file = findAssetManifestFile(
|
|
7392
|
+
const file = findAssetManifestFile(path22__default.join(absRoot, a.root), a.kind, a.name);
|
|
6925
7393
|
if (!file) continue;
|
|
6926
|
-
const res = parseManifestFile(file,
|
|
7394
|
+
const res = parseManifestFile(file, fs9__default.readFileSync(file, "utf-8"));
|
|
6927
7395
|
if (!res.ok) continue;
|
|
6928
7396
|
const fileVersion = declaredVersion(res.data);
|
|
6929
7397
|
if (fileVersion === void 0 || fileVersion === a.version) continue;
|
|
@@ -6931,7 +7399,7 @@ function validatePublishManifestVersions(rootPath) {
|
|
|
6931
7399
|
manifestVersionMismatchMessage(
|
|
6932
7400
|
assetEntryRef(a, manifest),
|
|
6933
7401
|
a.version,
|
|
6934
|
-
toPosix(
|
|
7402
|
+
toPosix(path22__default.relative(absRoot, file)),
|
|
6935
7403
|
fileVersion
|
|
6936
7404
|
)
|
|
6937
7405
|
);
|
|
@@ -6940,7 +7408,7 @@ function validatePublishManifestVersions(rootPath) {
|
|
|
6940
7408
|
return warnings;
|
|
6941
7409
|
}
|
|
6942
7410
|
function validatePublishManifestPublishers(rootPath) {
|
|
6943
|
-
const absRoot =
|
|
7411
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6944
7412
|
const manifest = loadSkPublishManifest(absRoot);
|
|
6945
7413
|
if (!manifest || manifest.source) return 0;
|
|
6946
7414
|
const bare = (p6) => p6.trim().replace(/^@/, "");
|
|
@@ -6948,15 +7416,15 @@ function validatePublishManifestPublishers(rootPath) {
|
|
|
6948
7416
|
for (const a of manifest.assets ?? []) {
|
|
6949
7417
|
const resolved = a.publisher ?? manifest.publisher;
|
|
6950
7418
|
if (!a.root || a.source || !resolved) continue;
|
|
6951
|
-
const file = findAssetManifestFile(
|
|
7419
|
+
const file = findAssetManifestFile(path22__default.join(absRoot, a.root), a.kind, a.name);
|
|
6952
7420
|
if (!file) continue;
|
|
6953
|
-
const res = parseManifestFile(file,
|
|
7421
|
+
const res = parseManifestFile(file, fs9__default.readFileSync(file, "utf-8"));
|
|
6954
7422
|
if (!res.ok) continue;
|
|
6955
7423
|
const meta = res.data.metadata;
|
|
6956
7424
|
const declared = meta !== null && typeof meta === "object" ? meta.publisher : null;
|
|
6957
7425
|
if (typeof declared !== "string" || bare(declared) === bare(resolved)) continue;
|
|
6958
7426
|
logWarn(
|
|
6959
|
-
`${toPosix(
|
|
7427
|
+
`${toPosix(path22__default.relative(absRoot, file))} [publisher] \u2014 metadata.publisher "${bare(declared)}" differs from the manifest publisher "${bare(resolved)}" for ${assetEntryRef(a, manifest)}. The manifest wins and the file value is ignored: delete \`metadata.publisher\` from the file, or set the publisher in ${SKAILE_MANIFEST_FILENAME}.`
|
|
6960
7428
|
);
|
|
6961
7429
|
warnings++;
|
|
6962
7430
|
}
|
|
@@ -6964,7 +7432,7 @@ function validatePublishManifestPublishers(rootPath) {
|
|
|
6964
7432
|
}
|
|
6965
7433
|
var EXCLUDED_PATHS = ["skaileup-shared/", "external/", "docs/"];
|
|
6966
7434
|
function toPosix(p6) {
|
|
6967
|
-
return p6.split(
|
|
7435
|
+
return p6.split(path22__default.sep).join("/");
|
|
6968
7436
|
}
|
|
6969
7437
|
function isExcludedPath(relPath) {
|
|
6970
7438
|
const rel = toPosix(relPath);
|
|
@@ -6980,9 +7448,9 @@ var VERSIONED_KINDS = {
|
|
|
6980
7448
|
};
|
|
6981
7449
|
function readAssetVersion(c) {
|
|
6982
7450
|
const kind = c.kind;
|
|
6983
|
-
const fileName =
|
|
6984
|
-
const dirName =
|
|
6985
|
-
const content =
|
|
7451
|
+
const fileName = path22__default.basename(c.filePath);
|
|
7452
|
+
const dirName = path22__default.basename(path22__default.dirname(c.filePath));
|
|
7453
|
+
const content = fs9__default.readFileSync(c.filePath, "utf-8");
|
|
6986
7454
|
if (c.filePath.endsWith(".md")) {
|
|
6987
7455
|
const res = parseManifestFile(c.filePath, content);
|
|
6988
7456
|
const data = res.ok ? res.data : {};
|
|
@@ -7015,26 +7483,26 @@ function readAssetVersion(c) {
|
|
|
7015
7483
|
};
|
|
7016
7484
|
}
|
|
7017
7485
|
function collectAssetVersions(root) {
|
|
7018
|
-
if (!
|
|
7486
|
+
if (!fs9__default.existsSync(root)) return [];
|
|
7019
7487
|
const assets = [];
|
|
7020
7488
|
for (const c of findManifestCandidates(root)) {
|
|
7021
7489
|
if (!VERSIONED_KINDS[c.kind]) continue;
|
|
7022
7490
|
if (c.filePath.endsWith(".flow.json")) continue;
|
|
7023
|
-
if (isExcludedPath(
|
|
7491
|
+
if (isExcludedPath(path22__default.relative(root, c.filePath))) continue;
|
|
7024
7492
|
assets.push(readAssetVersion(c));
|
|
7025
7493
|
}
|
|
7026
7494
|
return assets;
|
|
7027
7495
|
}
|
|
7028
7496
|
function assetLocation(a, root) {
|
|
7029
|
-
return toPosix(
|
|
7497
|
+
return toPosix(path22__default.relative(root, a.filePath));
|
|
7030
7498
|
}
|
|
7031
7499
|
function findChangelogUnit(assetRelPath, root) {
|
|
7032
|
-
let dir =
|
|
7500
|
+
let dir = path22__default.posix.dirname(toPosix(assetRelPath));
|
|
7033
7501
|
for (; ; ) {
|
|
7034
7502
|
const candidate = dir === "." ? "CHANGELOG.md" : `${dir}/CHANGELOG.md`;
|
|
7035
|
-
if (
|
|
7503
|
+
if (fs9__default.existsSync(path22__default.join(root, candidate))) return candidate;
|
|
7036
7504
|
if (dir === ".") return null;
|
|
7037
|
-
dir =
|
|
7505
|
+
dir = path22__default.posix.dirname(dir);
|
|
7038
7506
|
}
|
|
7039
7507
|
}
|
|
7040
7508
|
function checkChangelogUnits(modifiedFiles, root) {
|
|
@@ -7084,7 +7552,7 @@ function checkVersionBumps(assets, root) {
|
|
|
7084
7552
|
let warnings = 0;
|
|
7085
7553
|
for (const a of assets) {
|
|
7086
7554
|
if (!a.version) continue;
|
|
7087
|
-
const relPath = toPosix(
|
|
7555
|
+
const relPath = toPosix(path22__default.relative(root, a.filePath));
|
|
7088
7556
|
try {
|
|
7089
7557
|
const headContent = execFileSync("git", ["show", `HEAD:./${relPath}`], {
|
|
7090
7558
|
cwd: root,
|
|
@@ -7117,7 +7585,7 @@ function checkFlowVersionPins(assets, root) {
|
|
|
7117
7585
|
pins = flowSkillVersionPins(loadFlow(f.filePath));
|
|
7118
7586
|
} catch (err2) {
|
|
7119
7587
|
logWarn(
|
|
7120
|
-
`flow:${f.name} (${
|
|
7588
|
+
`flow:${f.name} (${path22__default.relative(root, f.filePath)}) \u2014 could not be read: ${err2 instanceof Error ? err2.message : err2}`
|
|
7121
7589
|
);
|
|
7122
7590
|
warnings++;
|
|
7123
7591
|
continue;
|
|
@@ -7135,19 +7603,34 @@ function checkFlowVersionPins(assets, root) {
|
|
|
7135
7603
|
}
|
|
7136
7604
|
function resolveCheckRoot(pathArg) {
|
|
7137
7605
|
if (pathArg) {
|
|
7138
|
-
const abs =
|
|
7139
|
-
if (!
|
|
7606
|
+
const abs = path22__default.resolve(pathArg);
|
|
7607
|
+
if (!fs9__default.existsSync(abs)) {
|
|
7140
7608
|
logErr(`Path does not exist: ${abs}`);
|
|
7141
7609
|
return null;
|
|
7142
7610
|
}
|
|
7143
7611
|
return abs;
|
|
7144
7612
|
}
|
|
7145
|
-
for (let dir = process.cwd(); ; dir =
|
|
7146
|
-
if (
|
|
7147
|
-
if (
|
|
7613
|
+
for (let dir = process.cwd(); ; dir = path22__default.dirname(dir)) {
|
|
7614
|
+
if (fs9__default.existsSync(path22__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
|
|
7615
|
+
if (path22__default.dirname(dir) === dir) return AI_RESOURCES;
|
|
7148
7616
|
}
|
|
7149
7617
|
}
|
|
7150
|
-
function
|
|
7618
|
+
function isInGitWorkTree(root) {
|
|
7619
|
+
try {
|
|
7620
|
+
return execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
7621
|
+
cwd: root,
|
|
7622
|
+
encoding: "utf-8",
|
|
7623
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7624
|
+
}).trim() === "true";
|
|
7625
|
+
} catch {
|
|
7626
|
+
return false;
|
|
7627
|
+
}
|
|
7628
|
+
}
|
|
7629
|
+
function changedFiles(root, ref, what, opts = {}) {
|
|
7630
|
+
if (!isInGitWorkTree(root)) {
|
|
7631
|
+
logErr(`${what} needs a git repository: ${root} is not inside a git work tree.`);
|
|
7632
|
+
return null;
|
|
7633
|
+
}
|
|
7151
7634
|
try {
|
|
7152
7635
|
const out = execFileSync(
|
|
7153
7636
|
"git",
|
|
@@ -7158,7 +7641,16 @@ function changedFiles(root, ref) {
|
|
|
7158
7641
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7159
7642
|
}
|
|
7160
7643
|
);
|
|
7161
|
-
|
|
7644
|
+
const changed = out.trim().split("\n").filter(Boolean);
|
|
7645
|
+
if (opts.untracked) {
|
|
7646
|
+
const fresh = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
|
|
7647
|
+
cwd: root,
|
|
7648
|
+
encoding: "utf-8",
|
|
7649
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7650
|
+
});
|
|
7651
|
+
changed.push(...fresh.trim().split("\n").filter(Boolean));
|
|
7652
|
+
}
|
|
7653
|
+
return changed;
|
|
7162
7654
|
} catch (err2) {
|
|
7163
7655
|
const stderr = err2 instanceof Error && "stderr" in err2 ? String(err2.stderr).trim() : "";
|
|
7164
7656
|
const reason = (stderr || (err2 instanceof Error ? err2.message : String(err2))).split("\n")[0];
|
|
@@ -7166,6 +7658,22 @@ function changedFiles(root, ref) {
|
|
|
7166
7658
|
return null;
|
|
7167
7659
|
}
|
|
7168
7660
|
}
|
|
7661
|
+
function assetOwnDir(a) {
|
|
7662
|
+
const dir = path22__default.dirname(a.filePath);
|
|
7663
|
+
if (["skill", "agent", "contract"].includes(a.kind) || path22__default.basename(dir) === a.name) return dir;
|
|
7664
|
+
return null;
|
|
7665
|
+
}
|
|
7666
|
+
function assetChanged(a, changedAbs) {
|
|
7667
|
+
if (changedAbs.has(a.filePath)) return true;
|
|
7668
|
+
const dir = assetOwnDir(a);
|
|
7669
|
+
if (dir === null) return false;
|
|
7670
|
+
for (const f of changedAbs) {
|
|
7671
|
+
const rel = path22__default.relative(dir, f);
|
|
7672
|
+
if (rel.startsWith("..") || path22__default.isAbsolute(rel)) continue;
|
|
7673
|
+
if (!isNonAssetPath(toPosix(rel))) return true;
|
|
7674
|
+
}
|
|
7675
|
+
return false;
|
|
7676
|
+
}
|
|
7169
7677
|
function runVersionsCheck(pathArg, opts) {
|
|
7170
7678
|
const root = resolveCheckRoot(pathArg);
|
|
7171
7679
|
if (root === null) {
|
|
@@ -7174,13 +7682,13 @@ function runVersionsCheck(pathArg, opts) {
|
|
|
7174
7682
|
}
|
|
7175
7683
|
let assets = collectAssetVersions(root);
|
|
7176
7684
|
if (opts.changedOnly) {
|
|
7177
|
-
const changed = changedFiles(root, "HEAD");
|
|
7685
|
+
const changed = changedFiles(root, "HEAD", "--changed-only", { untracked: true });
|
|
7178
7686
|
if (changed === null) {
|
|
7179
7687
|
process.exit(1);
|
|
7180
7688
|
return;
|
|
7181
7689
|
}
|
|
7182
|
-
const changedAbs = new Set(changed.map((f) =>
|
|
7183
|
-
assets = assets.filter((a) =>
|
|
7690
|
+
const changedAbs = new Set(changed.map((f) => path22__default.resolve(root, f)));
|
|
7691
|
+
assets = assets.filter((a) => assetChanged(a, changedAbs));
|
|
7184
7692
|
}
|
|
7185
7693
|
logInfo(`Checking versions in ${root}`);
|
|
7186
7694
|
const versionCheck = checkAssetVersions(assets, root);
|
|
@@ -7212,22 +7720,23 @@ function makeValidateCommand() {
|
|
|
7212
7720
|
"--strict-conformance",
|
|
7213
7721
|
"Treat Agent Skills (agentskills.io) standard findings as errors"
|
|
7214
7722
|
).action(async (targetPath, opts) => {
|
|
7215
|
-
const absPath =
|
|
7723
|
+
const absPath = path22__default.resolve(targetPath);
|
|
7216
7724
|
logInfo(`Validating manifests in ${absPath}`);
|
|
7217
7725
|
const { total, errors, warnings } = validateManifests(
|
|
7218
7726
|
absPath,
|
|
7219
7727
|
opts.strictConformance ?? false
|
|
7220
7728
|
);
|
|
7221
|
-
const ws = validateWorkspaceManifests(absPath);
|
|
7729
|
+
const ws = await validateWorkspaceManifests(absPath);
|
|
7222
7730
|
const rootErrors = validatePublishManifestRoots(absPath);
|
|
7223
7731
|
const slugErrors = validatePublishManifestPublisherSlugs(absPath);
|
|
7732
|
+
const parseErrors = validatePublishManifestParses(absPath);
|
|
7224
7733
|
const requiresErrors = validatePublishManifestRequires(absPath);
|
|
7225
7734
|
const versionWarnings = validatePublishManifestVersions(absPath);
|
|
7226
7735
|
const publisherWarnings = validatePublishManifestPublishers(absPath);
|
|
7227
7736
|
const dependencyProblems = await unresolvedManifestDependencies(absPath);
|
|
7228
7737
|
for (const w of dependencyProblems) logWarn(w);
|
|
7229
7738
|
const dependencyWarnings = dependencyProblems.length;
|
|
7230
|
-
const totalErrors = errors + ws.errors + rootErrors + slugErrors + requiresErrors;
|
|
7739
|
+
const totalErrors = errors + ws.errors + rootErrors + slugErrors + parseErrors + requiresErrors;
|
|
7231
7740
|
console.log();
|
|
7232
7741
|
warnIgnoredDomainFiles(absPath);
|
|
7233
7742
|
warnLegacyBundleFiles(absPath);
|
|
@@ -7253,7 +7762,7 @@ function makeValidateCommand() {
|
|
|
7253
7762
|
process.exit(1);
|
|
7254
7763
|
return;
|
|
7255
7764
|
}
|
|
7256
|
-
const modifiedFiles = changedFiles(root, opts.base);
|
|
7765
|
+
const modifiedFiles = changedFiles(root, opts.base, "changelog");
|
|
7257
7766
|
if (modifiedFiles === null) {
|
|
7258
7767
|
process.exit(1);
|
|
7259
7768
|
return;
|
|
@@ -7302,7 +7811,7 @@ function itemFromRef(raw, defaultKind, ctx) {
|
|
|
7302
7811
|
return { kind: prefixed[1], ref: value };
|
|
7303
7812
|
}
|
|
7304
7813
|
if (PATH_LIKE.test(value)) return { kind: defaultKind, ref: value };
|
|
7305
|
-
if (defaultKind === "skill" && !value.includes("/") && existsSync(
|
|
7814
|
+
if (defaultKind === "skill" && !value.includes("/") && existsSync(path22__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
|
|
7306
7815
|
return { kind: "skill", ref: `./skills/${value}` };
|
|
7307
7816
|
}
|
|
7308
7817
|
return { kind: defaultKind, ref: `${defaultKind}:${value}` };
|
|
@@ -7438,7 +7947,7 @@ function migrateAgentYaml(source, options) {
|
|
|
7438
7947
|
manual.push("metadata.soul: not a string; left unchanged");
|
|
7439
7948
|
continue;
|
|
7440
7949
|
}
|
|
7441
|
-
if (
|
|
7950
|
+
if (path22__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
|
|
7442
7951
|
notes.push("metadata.soul \u2192 dropped (SOUL.md is a convention file)");
|
|
7443
7952
|
} else {
|
|
7444
7953
|
derived.push({ kind: "persona", ref: soul });
|
|
@@ -7672,7 +8181,7 @@ function migrateSubagents(skaileYamlPath, source) {
|
|
|
7672
8181
|
if (!isMap(agentNode)) return void 0;
|
|
7673
8182
|
const subNode = agentNode.get("subagents", true);
|
|
7674
8183
|
if (!isMap(subNode)) return void 0;
|
|
7675
|
-
const dir =
|
|
8184
|
+
const dir = path22__default.dirname(skaileYamlPath);
|
|
7676
8185
|
const notes = [];
|
|
7677
8186
|
const manual = [];
|
|
7678
8187
|
const changes = [];
|
|
@@ -7690,10 +8199,10 @@ function migrateSubagents(skaileYamlPath, source) {
|
|
|
7690
8199
|
continue;
|
|
7691
8200
|
}
|
|
7692
8201
|
const id = instanceId(name);
|
|
7693
|
-
const assetDir =
|
|
8202
|
+
const assetDir = path22__default.join(dir, ".skaile", "agents", id);
|
|
7694
8203
|
if (takenIds.has(id) || existsSync(assetDir)) {
|
|
7695
8204
|
manual.push(
|
|
7696
|
-
`agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${
|
|
8205
|
+
`agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path22__default.relative(dir, assetDir)} already exists`}; left in place`
|
|
7697
8206
|
);
|
|
7698
8207
|
continue;
|
|
7699
8208
|
}
|
|
@@ -7717,13 +8226,13 @@ function migrateSubagents(skaileYamlPath, source) {
|
|
|
7717
8226
|
manifest.tools = { ...allowed ? { allowed } : {}, ...denied ? { denied } : {} };
|
|
7718
8227
|
}
|
|
7719
8228
|
const text = stringify(manifest, { lineWidth: 0 });
|
|
7720
|
-
const manifestPath =
|
|
8229
|
+
const manifestPath = path22__default.join(assetDir, "agent.yaml");
|
|
7721
8230
|
changes.push({ type: "create", path: manifestPath, after: text });
|
|
7722
8231
|
assetManifests.push({ file: manifestPath, text });
|
|
7723
8232
|
if (typeof spec.prompt === "string" && spec.prompt.trim() !== "") {
|
|
7724
8233
|
changes.push({
|
|
7725
8234
|
type: "create",
|
|
7726
|
-
path:
|
|
8235
|
+
path: path22__default.join(assetDir, "SOUL.md"),
|
|
7727
8236
|
after: `${spec.prompt.replace(/\s+$/, "")}
|
|
7728
8237
|
`
|
|
7729
8238
|
});
|
|
@@ -7782,7 +8291,7 @@ function validateMigratedAgent(text, registry) {
|
|
|
7782
8291
|
function collectAgentFiles(paths) {
|
|
7783
8292
|
const files = /* @__PURE__ */ new Set();
|
|
7784
8293
|
for (const input of paths) {
|
|
7785
|
-
const abs =
|
|
8294
|
+
const abs = path22__default.resolve(input);
|
|
7786
8295
|
if (!existsSync(abs)) continue;
|
|
7787
8296
|
if (statSync(abs).isDirectory()) {
|
|
7788
8297
|
for (const f of walkFiles(abs, (b) => b === "agent.yaml" || b === "skaile.yaml"))
|
|
@@ -7799,7 +8308,7 @@ function planAgentMigration(options) {
|
|
|
7799
8308
|
const reports = [];
|
|
7800
8309
|
for (const file of collectAgentFiles(options.paths)) {
|
|
7801
8310
|
const source = readText(file);
|
|
7802
|
-
const base =
|
|
8311
|
+
const base = path22__default.basename(file);
|
|
7803
8312
|
if (base === "skaile.yaml") {
|
|
7804
8313
|
const result = migrateSubagents(file, source);
|
|
7805
8314
|
if (!result) continue;
|
|
@@ -7807,7 +8316,7 @@ function planAgentMigration(options) {
|
|
|
7807
8316
|
for (const asset of result.assetManifests) {
|
|
7808
8317
|
const v = validateMigratedAgent(asset.text, options.registry);
|
|
7809
8318
|
validation2.errors.push(
|
|
7810
|
-
...v.errors.map((e) => `${
|
|
8319
|
+
...v.errors.map((e) => `${path22__default.basename(path22__default.dirname(asset.file))}: ${e}`)
|
|
7811
8320
|
);
|
|
7812
8321
|
validation2.warnings.push(...v.warnings);
|
|
7813
8322
|
}
|
|
@@ -7835,7 +8344,7 @@ function planAgentMigration(options) {
|
|
|
7835
8344
|
});
|
|
7836
8345
|
continue;
|
|
7837
8346
|
}
|
|
7838
|
-
migration = migrateAgentYaml(source, { agentDir:
|
|
8347
|
+
migration = migrateAgentYaml(source, { agentDir: path22__default.dirname(file), knownKinds });
|
|
7839
8348
|
} catch (error) {
|
|
7840
8349
|
reports.push({
|
|
7841
8350
|
file,
|
|
@@ -7865,7 +8374,7 @@ function planAgentMigration(options) {
|
|
|
7865
8374
|
var DEFAULT_PUBLISHER = "skaile-ai";
|
|
7866
8375
|
var PRESET_DEFAULT_VERSION = "1.0.0";
|
|
7867
8376
|
var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
7868
|
-
var posix2 = (p6) => p6.split(
|
|
8377
|
+
var posix2 = (p6) => p6.split(path22__default.sep).join("/");
|
|
7869
8378
|
var MOVED_KINDS = { persona: "PERSONA.md", ruleset: "RULESET.md" };
|
|
7870
8379
|
var KIND_MANIFEST_FILES = /* @__PURE__ */ new Set(["PERSONA.md", "RULESET.md", "SKILL.md"]);
|
|
7871
8380
|
function readFrontmatterType(text) {
|
|
@@ -7896,14 +8405,14 @@ function planMarkdownMoves(root, knownKinds, manual, unknownTypes) {
|
|
|
7896
8405
|
if (!text.startsWith("---")) continue;
|
|
7897
8406
|
const found = readFrontmatterType(text);
|
|
7898
8407
|
if (!found) continue;
|
|
7899
|
-
const base =
|
|
7900
|
-
const inAgentParts = file.split(
|
|
8408
|
+
const base = path22__default.basename(file);
|
|
8409
|
+
const inAgentParts = file.split(path22__default.sep).includes("_agent-parts");
|
|
7901
8410
|
const targetName = MOVED_KINDS[found.type];
|
|
7902
8411
|
if (targetName !== void 0 && !KIND_MANIFEST_FILES.has(base)) {
|
|
7903
|
-
const to =
|
|
8412
|
+
const to = path22__default.join(path22__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
|
|
7904
8413
|
if (existsSync(to) || targets.has(to)) {
|
|
7905
8414
|
manual.push(
|
|
7906
|
-
`${posix2(
|
|
8415
|
+
`${posix2(path22__default.relative(root, file))}: ${posix2(path22__default.relative(root, to))} already exists; not moved`
|
|
7907
8416
|
);
|
|
7908
8417
|
continue;
|
|
7909
8418
|
}
|
|
@@ -7924,13 +8433,13 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
|
|
|
7924
8433
|
const changes = [];
|
|
7925
8434
|
for (const file of walkFiles(root, (b) => b === "agent.yaml")) {
|
|
7926
8435
|
const source = readText(file);
|
|
7927
|
-
const agentDir =
|
|
8436
|
+
const agentDir = path22__default.dirname(file);
|
|
7928
8437
|
let hits = 0;
|
|
7929
8438
|
const refRewrite = (_kind, ref) => {
|
|
7930
|
-
const moved = byOldPath.get(
|
|
8439
|
+
const moved = byOldPath.get(path22__default.resolve(agentDir, ref));
|
|
7931
8440
|
if (moved === void 0) return ref;
|
|
7932
8441
|
hits++;
|
|
7933
|
-
const rel = posix2(
|
|
8442
|
+
const rel = posix2(path22__default.relative(agentDir, moved));
|
|
7934
8443
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
7935
8444
|
};
|
|
7936
8445
|
let output;
|
|
@@ -7947,7 +8456,7 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
|
|
|
7947
8456
|
if (hits === 0 || output === source) continue;
|
|
7948
8457
|
changes.push({ type: "write", path: file, before: source, after: output });
|
|
7949
8458
|
notes.push(
|
|
7950
|
-
`${posix2(
|
|
8459
|
+
`${posix2(path22__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
|
|
7951
8460
|
);
|
|
7952
8461
|
}
|
|
7953
8462
|
return changes;
|
|
@@ -7958,10 +8467,9 @@ function presetItemRef(dep, publisher) {
|
|
|
7958
8467
|
const [, kind, rest] = match;
|
|
7959
8468
|
return rest.startsWith("@") ? dep.trim() : `${kind}:@${publisher}/${rest}`;
|
|
7960
8469
|
}
|
|
7961
|
-
function presetText(name, description, refs,
|
|
8470
|
+
function presetText(name, description, refs, version) {
|
|
7962
8471
|
return stringify(
|
|
7963
8472
|
{
|
|
7964
|
-
publisher,
|
|
7965
8473
|
name,
|
|
7966
8474
|
version,
|
|
7967
8475
|
description: description && description.trim() !== "" ? description : `Preset ${name}`,
|
|
@@ -7972,14 +8480,14 @@ function presetText(name, description, refs, publisher, version) {
|
|
|
7972
8480
|
}
|
|
7973
8481
|
function skillDirs(dir) {
|
|
7974
8482
|
try {
|
|
7975
|
-
return readdirSync(
|
|
8483
|
+
return readdirSync(path22__default.join(dir, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync(path22__default.join(dir, "skills", e.name, "SKILL.md"))).map((e) => e.name).sort();
|
|
7976
8484
|
} catch {
|
|
7977
8485
|
return [];
|
|
7978
8486
|
}
|
|
7979
8487
|
}
|
|
7980
8488
|
function repoPublisher(root) {
|
|
7981
8489
|
for (const name of ["skaile.manifest.yaml", "skaile.yaml"]) {
|
|
7982
|
-
const file =
|
|
8490
|
+
const file = path22__default.join(root, name);
|
|
7983
8491
|
if (!existsSync(file)) continue;
|
|
7984
8492
|
try {
|
|
7985
8493
|
const parsed = parse(readText(file));
|
|
@@ -7995,9 +8503,9 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
7995
8503
|
const changes = [];
|
|
7996
8504
|
const presets = [];
|
|
7997
8505
|
const handled = /* @__PURE__ */ new Set();
|
|
7998
|
-
const rel = (p6) => posix2(
|
|
8506
|
+
const rel = (p6) => posix2(path22__default.relative(root, p6));
|
|
7999
8507
|
const convert = (name, bundleFile, dir) => {
|
|
8000
|
-
const target =
|
|
8508
|
+
const target = path22__default.join(dir === root ? path22__default.join(dir, name) : dir, `${name}.preset.yaml`);
|
|
8001
8509
|
if (existsSync(target)) {
|
|
8002
8510
|
manual.push(`${rel(target)} already exists; bundle ${name} not converted`);
|
|
8003
8511
|
return;
|
|
@@ -8015,6 +8523,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
8015
8523
|
const declared = typeof parsed.version === "string" || typeof parsed.version === "number" ? String(parsed.version) : void 0;
|
|
8016
8524
|
if (declared !== void 0 && SEMVER_RE.test(declared)) version = declared;
|
|
8017
8525
|
else if (declared !== void 0) versionNote = `version ${declared} \u2192 ${version}`;
|
|
8526
|
+
else versionNote = `version (none) \u2192 ${version}`;
|
|
8018
8527
|
const deps = Array.isArray(parsed.dependencies) ? parsed.dependencies : [];
|
|
8019
8528
|
refs = deps.filter((d) => typeof d === "string").map((d) => presetItemRef(d, publisher));
|
|
8020
8529
|
if (refs.length !== deps.length) {
|
|
@@ -8028,11 +8537,11 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
8028
8537
|
}
|
|
8029
8538
|
if (refs.length === 0) {
|
|
8030
8539
|
manual.push(
|
|
8031
|
-
`bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(
|
|
8540
|
+
`bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path22__default.join(dir, "skills"))}`}; no preset generated`
|
|
8032
8541
|
);
|
|
8033
8542
|
return;
|
|
8034
8543
|
}
|
|
8035
|
-
const after = presetText(name, description, refs,
|
|
8544
|
+
const after = presetText(name, description, refs, version);
|
|
8036
8545
|
if (before !== void 0 && bundleFile) {
|
|
8037
8546
|
changes.push({ type: "move", from: bundleFile, to: target, before, after });
|
|
8038
8547
|
handled.add(bundleFile);
|
|
@@ -8052,18 +8561,18 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
8052
8561
|
const assets = Array.isArray(raw.assets) ? raw.assets : [];
|
|
8053
8562
|
for (const entry of assets) {
|
|
8054
8563
|
if (!isRecord(entry) || entry.kind !== "bundle" || typeof entry.name !== "string") continue;
|
|
8055
|
-
const baseDir =
|
|
8056
|
-
const entryRoot = typeof entry.root === "string" ?
|
|
8564
|
+
const baseDir = path22__default.dirname(file);
|
|
8565
|
+
const entryRoot = typeof entry.root === "string" ? path22__default.join(baseDir, entry.root) : baseDir;
|
|
8057
8566
|
const files = Array.isArray(entry.files) ? entry.files : [];
|
|
8058
8567
|
const bundleName = files.find(
|
|
8059
8568
|
(f) => typeof f === "string" && f.endsWith(".bundle.yaml")
|
|
8060
8569
|
);
|
|
8061
|
-
convert(entry.name, bundleName ?
|
|
8570
|
+
convert(entry.name, bundleName ? path22__default.join(entryRoot, bundleName) : void 0, entryRoot);
|
|
8062
8571
|
}
|
|
8063
8572
|
}
|
|
8064
8573
|
for (const bundleFile of walkFiles(root, (b) => b.endsWith(".bundle.yaml"))) {
|
|
8065
8574
|
if (handled.has(bundleFile)) continue;
|
|
8066
|
-
const base =
|
|
8575
|
+
const base = path22__default.basename(bundleFile);
|
|
8067
8576
|
let name = base.replace(/\.bundle\.yaml$/, "");
|
|
8068
8577
|
try {
|
|
8069
8578
|
const parsed = parse(readText(bundleFile));
|
|
@@ -8072,7 +8581,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
8072
8581
|
} catch {
|
|
8073
8582
|
}
|
|
8074
8583
|
if (presets.some((p6) => p6.bundleFile === bundleFile)) continue;
|
|
8075
|
-
convert(name, bundleFile,
|
|
8584
|
+
convert(name, bundleFile, path22__default.dirname(bundleFile));
|
|
8076
8585
|
}
|
|
8077
8586
|
return changes;
|
|
8078
8587
|
}
|
|
@@ -8082,8 +8591,8 @@ function planSkaileYaml(root, file, source, notes, manual) {
|
|
|
8082
8591
|
if (doc.errors.length > 0 || !isMap(doc.contents)) return [];
|
|
8083
8592
|
const map = doc.contents;
|
|
8084
8593
|
const raw = doc.toJS();
|
|
8085
|
-
const dir =
|
|
8086
|
-
const rel = (p6) => posix2(
|
|
8594
|
+
const dir = path22__default.dirname(file);
|
|
8595
|
+
const rel = (p6) => posix2(path22__default.relative(root, p6));
|
|
8087
8596
|
const changes = [];
|
|
8088
8597
|
let changed = false;
|
|
8089
8598
|
const deps = map.get("dependencies", true);
|
|
@@ -8100,7 +8609,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
|
|
|
8100
8609
|
const hasPublication = PUBLICATION_KEYS.some((k) => raw[k] !== void 0);
|
|
8101
8610
|
let remove = false;
|
|
8102
8611
|
if (hasPublication) {
|
|
8103
|
-
const manifestPath =
|
|
8612
|
+
const manifestPath = path22__default.join(dir, "skaile.manifest.yaml");
|
|
8104
8613
|
if (existsSync(manifestPath)) {
|
|
8105
8614
|
manual.push(
|
|
8106
8615
|
`${rel(file)}: publisher/version/assets left in place \u2014 ${rel(manifestPath)} already exists; merge by hand`
|
|
@@ -8157,7 +8666,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
|
|
|
8157
8666
|
return changes;
|
|
8158
8667
|
}
|
|
8159
8668
|
function planAssetMigration(options) {
|
|
8160
|
-
const root =
|
|
8669
|
+
const root = path22__default.resolve(options.root);
|
|
8161
8670
|
const knownKinds = new Set(options.registry.getAllKinds());
|
|
8162
8671
|
const notes = [];
|
|
8163
8672
|
const manual = [];
|
|
@@ -8165,7 +8674,7 @@ function planAssetMigration(options) {
|
|
|
8165
8674
|
const { moves, changes: moveChanges } = planMarkdownMoves(root, knownKinds, manual, unknownTypes);
|
|
8166
8675
|
for (const move of moves) {
|
|
8167
8676
|
notes.push(
|
|
8168
|
-
`${posix2(
|
|
8677
|
+
`${posix2(path22__default.relative(root, move.from))} \u2192 ${posix2(path22__default.relative(root, move.to))} (${move.kind})`
|
|
8169
8678
|
);
|
|
8170
8679
|
}
|
|
8171
8680
|
const agentChanges = planAgentRefRewrites(root, moves, knownKinds, notes);
|
|
@@ -8177,7 +8686,7 @@ function planAssetMigration(options) {
|
|
|
8177
8686
|
const raw = parse(source);
|
|
8178
8687
|
if (isRecord(raw)) skaileYamls.push({ file, source, raw });
|
|
8179
8688
|
} catch {
|
|
8180
|
-
manual.push(`${posix2(
|
|
8689
|
+
manual.push(`${posix2(path22__default.relative(root, file))}: invalid YAML; skipped`);
|
|
8181
8690
|
}
|
|
8182
8691
|
}
|
|
8183
8692
|
const publisher = repoPublisher(root);
|
|
@@ -8331,7 +8840,7 @@ function workspaceConfigFiles(dir) {
|
|
|
8331
8840
|
} catch {
|
|
8332
8841
|
return [];
|
|
8333
8842
|
}
|
|
8334
|
-
return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) =>
|
|
8843
|
+
return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path22__default.join(dir, name));
|
|
8335
8844
|
}
|
|
8336
8845
|
function readAgentConfigBlock(raw) {
|
|
8337
8846
|
const key = AGENT_CONFIG_KEYS.find((candidate) => raw[candidate] !== void 0);
|
|
@@ -8343,7 +8852,7 @@ function readAgentConfigBlock(raw) {
|
|
|
8343
8852
|
return flat ? { key, profiles: { default: profiles }, flat } : { key, profiles, flat };
|
|
8344
8853
|
}
|
|
8345
8854
|
function planProviderMigration(options) {
|
|
8346
|
-
const projectDir =
|
|
8855
|
+
const projectDir = path22__default.resolve(options.projectDir);
|
|
8347
8856
|
const registryPath = options.workspace ? workspaceProviderRegistryPath(projectDir) : userProviderRegistryPath();
|
|
8348
8857
|
const plan = {
|
|
8349
8858
|
registryPath,
|
|
@@ -8359,7 +8868,7 @@ function planProviderMigration(options) {
|
|
|
8359
8868
|
raw = parseDocument(readFileSync(file, "utf-8")).toJS() ?? {};
|
|
8360
8869
|
} catch (error) {
|
|
8361
8870
|
plan.warnings.push(
|
|
8362
|
-
`${
|
|
8871
|
+
`${path22__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
|
|
8363
8872
|
);
|
|
8364
8873
|
continue;
|
|
8365
8874
|
}
|
|
@@ -8408,7 +8917,7 @@ function planProviderMigration(options) {
|
|
|
8408
8917
|
});
|
|
8409
8918
|
if (!model) {
|
|
8410
8919
|
plan.warnings.push(
|
|
8411
|
-
`${
|
|
8920
|
+
`${path22__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
|
|
8412
8921
|
);
|
|
8413
8922
|
}
|
|
8414
8923
|
touched = true;
|
|
@@ -8475,7 +8984,7 @@ function printPlan(plan) {
|
|
|
8475
8984
|
for (const entry of plan.entries) {
|
|
8476
8985
|
const base = entry.entry.base_url ?? S.dim("(transport-derived)");
|
|
8477
8986
|
console.log(
|
|
8478
|
-
` ${S.label(`${
|
|
8987
|
+
` ${S.label(`${path22__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
|
|
8479
8988
|
);
|
|
8480
8989
|
console.log(` \u2192 providers.yml ${S.bold(entry.providerId)} ${base}`);
|
|
8481
8990
|
console.log(
|
|
@@ -8491,7 +9000,7 @@ function printPlan(plan) {
|
|
|
8491
9000
|
console.log();
|
|
8492
9001
|
}
|
|
8493
9002
|
async function runMigrateProviders(opts) {
|
|
8494
|
-
const projectDir = opts.projectDir ?
|
|
9003
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
|
|
8495
9004
|
const plan = planProviderMigration({ projectDir, workspace: opts.workspace });
|
|
8496
9005
|
for (const warning of plan.warnings) logWarn(warning);
|
|
8497
9006
|
if (plan.entries.length === 0 && Object.keys(plan.providers).length === 0) {
|
|
@@ -8573,7 +9082,8 @@ var ASSETS_HELP = `
|
|
|
8573
9082
|
Rewrites (run on a repo root):
|
|
8574
9083
|
type: persona|ruleset markdown <n>.md -> <n>/PERSONA.md | <n>/RULESET.md (type: dropped);
|
|
8575
9084
|
agent persona:/rules: refs to the old path become composes items
|
|
8576
|
-
*.bundle.yaml <name>.preset.yaml beside it
|
|
9085
|
+
*.bundle.yaml <name>.preset.yaml beside it, or <name>/<name>.preset.yaml
|
|
9086
|
+
for a bundle at the repo root (items: kind:@publisher/name);
|
|
8577
9087
|
kind: bundle entries of skaile.yaml#assets become kind: preset
|
|
8578
9088
|
skaile.yaml dependencies bundle:@... -> preset:@...
|
|
8579
9089
|
skaile.yaml publisher/version/assets
|
|
@@ -8622,7 +9132,7 @@ async function runMigrateAgents(paths, opts) {
|
|
|
8622
9132
|
let failures = 0;
|
|
8623
9133
|
let manualCount = 0;
|
|
8624
9134
|
for (const report of plan.reports) {
|
|
8625
|
-
const rel =
|
|
9135
|
+
const rel = path22__default.relative(base, report.file) || report.file;
|
|
8626
9136
|
for (const note of report.notes) console.log(` ${S.label(rel)} ${note}`);
|
|
8627
9137
|
for (const note of report.manual) {
|
|
8628
9138
|
manualCount++;
|
|
@@ -8649,14 +9159,14 @@ async function runMigrateAssets(root, opts) {
|
|
|
8649
9159
|
const write = resolveMode(opts);
|
|
8650
9160
|
const base = process.cwd();
|
|
8651
9161
|
const plan = planAssetMigration({
|
|
8652
|
-
root:
|
|
9162
|
+
root: path22__default.resolve(root ?? base),
|
|
8653
9163
|
registry: getKindRegistry()
|
|
8654
9164
|
});
|
|
8655
9165
|
for (const note of plan.notes) console.log(` ${note}`);
|
|
8656
9166
|
for (const note of plan.manual) logWarn(note);
|
|
8657
9167
|
for (const { file, type } of plan.unknownTypes) {
|
|
8658
9168
|
logWarn(
|
|
8659
|
-
`${
|
|
9169
|
+
`${path22__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
|
|
8660
9170
|
);
|
|
8661
9171
|
}
|
|
8662
9172
|
printChanges(plan.changes, base);
|
|
@@ -8679,8 +9189,8 @@ function makeNpxCommand() {
|
|
|
8679
9189
|
skills.command("add <url>").description(
|
|
8680
9190
|
"Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
|
|
8681
9191
|
).requiredOption("--skill <name>", "Skill name to install from the repo").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", `Agent framework (${TARGET_DEFAULT_HINT})`).option("--global", "Deploy globally").action(async (url, opts) => {
|
|
8682
|
-
const projectDir =
|
|
8683
|
-
const projYaml =
|
|
9192
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9193
|
+
const projYaml = path22__default.join(projectDir, "skaile.yaml");
|
|
8684
9194
|
if (!existsSync(projYaml)) {
|
|
8685
9195
|
logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
|
|
8686
9196
|
process.exit(1);
|
|
@@ -8693,11 +9203,11 @@ function makeNpxCommand() {
|
|
|
8693
9203
|
}
|
|
8694
9204
|
const spinner = createSpinner();
|
|
8695
9205
|
const key = sourceCacheKey(url);
|
|
8696
|
-
const clonePath =
|
|
9206
|
+
const clonePath = path22__default.join(getGlobalCacheDir(), key);
|
|
8697
9207
|
spinner.start(`Cloning ${url}`);
|
|
8698
9208
|
try {
|
|
8699
9209
|
if (!existsSync(clonePath)) {
|
|
8700
|
-
mkdirSync(
|
|
9210
|
+
mkdirSync(path22__default.dirname(clonePath), { recursive: true });
|
|
8701
9211
|
execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
|
|
8702
9212
|
}
|
|
8703
9213
|
spinner.stop(`Cloned to ${key}`);
|
|
@@ -8752,7 +9262,7 @@ function makeNpxCommand() {
|
|
|
8752
9262
|
return npx;
|
|
8753
9263
|
}
|
|
8754
9264
|
function resolvePublisher(clonePath, url) {
|
|
8755
|
-
const manifestPath =
|
|
9265
|
+
const manifestPath = path22__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
|
|
8756
9266
|
if (existsSync(manifestPath)) {
|
|
8757
9267
|
try {
|
|
8758
9268
|
const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
|
|
@@ -8765,12 +9275,12 @@ function resolvePublisher(clonePath, url) {
|
|
|
8765
9275
|
return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
|
|
8766
9276
|
}
|
|
8767
9277
|
function resolveSkillName(clonePath, requested) {
|
|
8768
|
-
const skillsDir =
|
|
8769
|
-
if (existsSync(
|
|
9278
|
+
const skillsDir = path22__default.join(clonePath, "skills");
|
|
9279
|
+
if (existsSync(path22__default.join(skillsDir, requested, "SKILL.md"))) return requested;
|
|
8770
9280
|
if (!existsSync(skillsDir)) return requested;
|
|
8771
9281
|
for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
|
|
8772
9282
|
if (!entry.isDirectory()) continue;
|
|
8773
|
-
const md =
|
|
9283
|
+
const md = path22__default.join(skillsDir, entry.name, "SKILL.md");
|
|
8774
9284
|
if (!existsSync(md)) continue;
|
|
8775
9285
|
try {
|
|
8776
9286
|
const { data } = parseFrontmatter(readFileSync(md, "utf8"));
|
|
@@ -8803,7 +9313,7 @@ function makeOutdatedCommand() {
|
|
|
8803
9313
|
requireProjectConfig(opts.projectDir);
|
|
8804
9314
|
const am2 = new AssetManager({
|
|
8805
9315
|
registry: getKindRegistry(),
|
|
8806
|
-
projectDir:
|
|
9316
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
8807
9317
|
driverTarget: opts.target
|
|
8808
9318
|
});
|
|
8809
9319
|
const entries = await am2.outdated();
|
|
@@ -8846,7 +9356,7 @@ function makePatchCommand() {
|
|
|
8846
9356
|
cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
|
|
8847
9357
|
const am2 = new AssetManager({
|
|
8848
9358
|
registry: getKindRegistry(),
|
|
8849
|
-
projectDir:
|
|
9359
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
8850
9360
|
});
|
|
8851
9361
|
try {
|
|
8852
9362
|
const dest = await am2.patch(ref);
|
|
@@ -8860,7 +9370,7 @@ function makePatchCommand() {
|
|
|
8860
9370
|
cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
|
|
8861
9371
|
const am2 = new AssetManager({
|
|
8862
9372
|
registry: getKindRegistry(),
|
|
8863
|
-
projectDir:
|
|
9373
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
8864
9374
|
});
|
|
8865
9375
|
try {
|
|
8866
9376
|
const patchFile = await am2.patchCommit(ref);
|
|
@@ -8874,7 +9384,7 @@ function makePatchCommand() {
|
|
|
8874
9384
|
cmd.command("submit <ref>").description("Apply patch to repo clone and prepare for PR").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
|
|
8875
9385
|
const am2 = new AssetManager({
|
|
8876
9386
|
registry: getKindRegistry(),
|
|
8877
|
-
projectDir:
|
|
9387
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
8878
9388
|
});
|
|
8879
9389
|
try {
|
|
8880
9390
|
await am2.patchSubmit(ref);
|
|
@@ -8890,7 +9400,7 @@ function makePatchCommand() {
|
|
|
8890
9400
|
cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
8891
9401
|
const am2 = new AssetManager({
|
|
8892
9402
|
registry: getKindRegistry(),
|
|
8893
|
-
projectDir:
|
|
9403
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
8894
9404
|
});
|
|
8895
9405
|
am2.patchRemove(ref);
|
|
8896
9406
|
logOk(`Patch removed for ${ref}`);
|
|
@@ -8908,8 +9418,8 @@ function action2(fn) {
|
|
|
8908
9418
|
}
|
|
8909
9419
|
};
|
|
8910
9420
|
}
|
|
8911
|
-
async function reconcileAndReport(projectDir, plugins) {
|
|
8912
|
-
const { reconcilePlugins } = await import('../plugin-store-
|
|
9421
|
+
async function reconcileAndReport(projectDir, plugins, opts = {}) {
|
|
9422
|
+
const { reconcilePlugins } = await import('../plugin-store-CK7YWRIC.js');
|
|
8913
9423
|
if (plugins.length === 0) {
|
|
8914
9424
|
logInfo("No plugins declared \u2014 nothing to reconcile.");
|
|
8915
9425
|
return;
|
|
@@ -8919,26 +9429,54 @@ async function reconcileAndReport(projectDir, plugins) {
|
|
|
8919
9429
|
if (result.changed) logOk(`Reconciled plugin store (${result.reason}).`);
|
|
8920
9430
|
else logInfo(`Plugin store ${result.reason}.`);
|
|
8921
9431
|
} catch (err2) {
|
|
9432
|
+
if (opts.strict) throw err2;
|
|
8922
9433
|
logWarn(`reconcile skipped: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
8923
9434
|
}
|
|
8924
9435
|
}
|
|
9436
|
+
async function verifyPluginLoads(projectDir, spec) {
|
|
9437
|
+
const { loadPlugins } = await import('../plugin-store-CK7YWRIC.js');
|
|
9438
|
+
const { createPluginRegistry } = await import('../plugin-registry/index.js');
|
|
9439
|
+
const registry = createPluginRegistry();
|
|
9440
|
+
const result = await loadPlugins(projectDir, [spec], registry);
|
|
9441
|
+
const failure = result.failed[0];
|
|
9442
|
+
if (failure) throw new Error(failure.error);
|
|
9443
|
+
const contributed = ["driver", "connector", "deployTarget"].flatMap(
|
|
9444
|
+
(kind) => registry.list(kind).map((m) => `${kind} ${m.id}`)
|
|
9445
|
+
);
|
|
9446
|
+
logOk(`Loaded ${S.cmd(spec)}${contributed.length > 0 ? ` (${contributed.join(", ")})` : ""}`);
|
|
9447
|
+
}
|
|
8925
9448
|
async function runInstall2(spec, opts) {
|
|
8926
|
-
const projectDir =
|
|
9449
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
8927
9450
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
8928
|
-
const { specName } = await import('../plugin-store-
|
|
8929
|
-
const yamlPath =
|
|
9451
|
+
const { specName, rollbackPluginStore } = await import('../plugin-store-CK7YWRIC.js');
|
|
9452
|
+
const yamlPath = path22__default.join(projectDir, "skaile.yaml");
|
|
9453
|
+
const original = existsSync(yamlPath) ? readFileSync(yamlPath, "utf8") : void 0;
|
|
8930
9454
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
9455
|
+
const previousPlugins = [...editor.getPlugins()];
|
|
8931
9456
|
const replaced = editor.addPlugin(spec, specName);
|
|
8932
9457
|
editor.save();
|
|
8933
9458
|
if (replaced) logOk(`Updated ${S.cmd(specName(spec))} \u2192 ${S.cmd(spec)} in skaile.yaml`);
|
|
8934
9459
|
else logOk(`Added ${S.cmd(spec)} to skaile.yaml plugins`);
|
|
8935
|
-
|
|
9460
|
+
try {
|
|
9461
|
+
await reconcileAndReport(projectDir, editor.getPlugins(), { strict: true });
|
|
9462
|
+
await verifyPluginLoads(projectDir, spec);
|
|
9463
|
+
} catch (err2) {
|
|
9464
|
+
if (original !== void 0) {
|
|
9465
|
+
writeFileSync(yamlPath, original);
|
|
9466
|
+
logInfo("skaile.yaml restored; the plugin was not recorded.");
|
|
9467
|
+
} else {
|
|
9468
|
+
rmSync(yamlPath, { force: true });
|
|
9469
|
+
logInfo("skaile.yaml removed; the plugin was not recorded.");
|
|
9470
|
+
}
|
|
9471
|
+
await rollbackPluginStore(projectDir, previousPlugins);
|
|
9472
|
+
throw err2;
|
|
9473
|
+
}
|
|
8936
9474
|
}
|
|
8937
9475
|
async function runRemove(name, opts) {
|
|
8938
|
-
const projectDir =
|
|
9476
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
8939
9477
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
8940
|
-
const { specName } = await import('../plugin-store-
|
|
8941
|
-
const yamlPath =
|
|
9478
|
+
const { specName } = await import('../plugin-store-CK7YWRIC.js');
|
|
9479
|
+
const yamlPath = path22__default.join(projectDir, "skaile.yaml");
|
|
8942
9480
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
8943
9481
|
const removed = editor.removePlugin(name, specName);
|
|
8944
9482
|
if (!removed) {
|
|
@@ -8950,7 +9488,7 @@ async function runRemove(name, opts) {
|
|
|
8950
9488
|
await reconcileAndReport(projectDir, editor.getPlugins());
|
|
8951
9489
|
}
|
|
8952
9490
|
async function runList(opts) {
|
|
8953
|
-
const projectDir =
|
|
9491
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
8954
9492
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
8955
9493
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
8956
9494
|
const declared = config.plugins ?? [];
|
|
@@ -8965,7 +9503,7 @@ async function runList(opts) {
|
|
|
8965
9503
|
const registry = createPluginRegistry();
|
|
8966
9504
|
if (declared.length > 0) {
|
|
8967
9505
|
try {
|
|
8968
|
-
const { loadPlugins } = await import('../plugin-store-
|
|
9506
|
+
const { loadPlugins } = await import('../plugin-store-CK7YWRIC.js');
|
|
8969
9507
|
const result = await loadPlugins(projectDir, declared, registry);
|
|
8970
9508
|
for (const f of result.failed) logWarn(f.error);
|
|
8971
9509
|
} catch (err2) {
|
|
@@ -9039,9 +9577,11 @@ function presetItemsToWorkspace(preset, values) {
|
|
|
9039
9577
|
dependencies.push(ref);
|
|
9040
9578
|
}
|
|
9041
9579
|
}
|
|
9042
|
-
const sources = (preset.sources ?? []).map(
|
|
9043
|
-
|
|
9044
|
-
|
|
9580
|
+
const sources = (preset.sources ?? []).map((s) => ({
|
|
9581
|
+
url: s.url,
|
|
9582
|
+
...s.pin ? { pin: s.pin } : {},
|
|
9583
|
+
...s.publisher ? { publisher: s.publisher } : {}
|
|
9584
|
+
}));
|
|
9045
9585
|
return { dependencies, connectors, mcpServers, sources, envVarsToSet: [...envVarsToSet] };
|
|
9046
9586
|
}
|
|
9047
9587
|
function resolveItemConfig(item, preset, values, envVarsToSet) {
|
|
@@ -9140,7 +9680,7 @@ function neededSources(config, lock) {
|
|
|
9140
9680
|
}
|
|
9141
9681
|
function sourcesWithSidecar(sources) {
|
|
9142
9682
|
const dir = getStoreManifestsDir();
|
|
9143
|
-
return sources.filter((s) => existsSync(
|
|
9683
|
+
return sources.filter((s) => existsSync(path22.join(dir, `${storeManifestSlug(s.url)}.yaml`))).map((s) => s.url);
|
|
9144
9684
|
}
|
|
9145
9685
|
function compact(obj) {
|
|
9146
9686
|
const out = {};
|
|
@@ -9232,8 +9772,8 @@ function redactSecrets(preset, findings) {
|
|
|
9232
9772
|
}
|
|
9233
9773
|
return { preset: next, keys };
|
|
9234
9774
|
}
|
|
9235
|
-
function placeholderKey(itemId,
|
|
9236
|
-
return `${itemId}_${
|
|
9775
|
+
function placeholderKey(itemId, path44) {
|
|
9776
|
+
return `${itemId}_${path44}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
9237
9777
|
}
|
|
9238
9778
|
function setAtPath(root, segments, value) {
|
|
9239
9779
|
let node = root;
|
|
@@ -9256,7 +9796,7 @@ function makePresetCommand() {
|
|
|
9256
9796
|
cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
|
|
9257
9797
|
const presetName = name ?? "my-preset";
|
|
9258
9798
|
const filename = `${presetName}.preset.yaml`;
|
|
9259
|
-
const outPath =
|
|
9799
|
+
const outPath = path22__default.join(path22__default.resolve(opts.dir), filename);
|
|
9260
9800
|
if (existsSync(outPath)) {
|
|
9261
9801
|
logErr(`File already exists: ${outPath}`);
|
|
9262
9802
|
logInfo("Choose a different name or remove the existing file.");
|
|
@@ -9289,7 +9829,7 @@ function makePresetCommand() {
|
|
|
9289
9829
|
return cmd;
|
|
9290
9830
|
}
|
|
9291
9831
|
async function runPresetExport(name, opts) {
|
|
9292
|
-
const projectDir =
|
|
9832
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9293
9833
|
const file = loadSkWorkspaceConfig(projectDir);
|
|
9294
9834
|
if (!file) {
|
|
9295
9835
|
logErr(`No skaile.yaml found in ${projectDir}`);
|
|
@@ -9299,7 +9839,7 @@ async function runPresetExport(name, opts) {
|
|
|
9299
9839
|
const presetName = name ?? file.config.name ?? "my-preset";
|
|
9300
9840
|
let lock = null;
|
|
9301
9841
|
try {
|
|
9302
|
-
lock = readLock(
|
|
9842
|
+
lock = readLock(path22__default.join(projectDir, "skaile.lock.yaml"));
|
|
9303
9843
|
} catch {
|
|
9304
9844
|
lock = null;
|
|
9305
9845
|
}
|
|
@@ -9340,7 +9880,7 @@ async function runPresetExport(name, opts) {
|
|
|
9340
9880
|
const contents = header ? `${header}
|
|
9341
9881
|
${body}` : body;
|
|
9342
9882
|
if (opts.out && opts.dir !== process.cwd()) logWarn("--dir is ignored when --out is set.");
|
|
9343
|
-
const outPath = opts.out ?
|
|
9883
|
+
const outPath = opts.out ? path22__default.resolve(opts.out) : path22__default.join(path22__default.resolve(opts.dir), `${presetName}.preset.yaml`);
|
|
9344
9884
|
if (existsSync(outPath) && !opts.force) {
|
|
9345
9885
|
logErr(`File already exists: ${outPath}`);
|
|
9346
9886
|
logInfo("Pass --force to overwrite, or choose a different --out/--dir.");
|
|
@@ -9352,7 +9892,7 @@ ${body}` : body;
|
|
|
9352
9892
|
logErr(`Failed to write ${outPath}: ${e.message}`);
|
|
9353
9893
|
process.exit(1);
|
|
9354
9894
|
}
|
|
9355
|
-
logOk(`Exported ${S.brand(
|
|
9895
|
+
logOk(`Exported ${S.brand(path22__default.basename(outPath))}`);
|
|
9356
9896
|
logInfo(`Path: ${outPath}`);
|
|
9357
9897
|
if (unresolved.length > 0) {
|
|
9358
9898
|
console.error(S.err("This file is NOT safe to share."));
|
|
@@ -9393,13 +9933,13 @@ function collectInput(value, acc) {
|
|
|
9393
9933
|
return acc;
|
|
9394
9934
|
}
|
|
9395
9935
|
async function runPresetApply(filePath, opts) {
|
|
9396
|
-
const projectDir =
|
|
9936
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9397
9937
|
const file = loadSkWorkspaceConfig(projectDir);
|
|
9398
9938
|
if (!file) {
|
|
9399
9939
|
logErr("No skaile.yaml \u2014 run `skaile init` first");
|
|
9400
9940
|
process.exit(1);
|
|
9401
9941
|
}
|
|
9402
|
-
const resolved =
|
|
9942
|
+
const resolved = path22__default.resolve(filePath);
|
|
9403
9943
|
if (!existsSync(resolved)) {
|
|
9404
9944
|
logErr(`File not found: ${resolved}`);
|
|
9405
9945
|
process.exit(1);
|
|
@@ -9615,7 +10155,7 @@ async function reportNestedPresetRefs(preset) {
|
|
|
9615
10155
|
}
|
|
9616
10156
|
async function checkPresetCycles(preset, resolved) {
|
|
9617
10157
|
const { detectCycles } = await import('../discovery/index.js');
|
|
9618
|
-
const presetRef =
|
|
10158
|
+
const presetRef = path22__default.basename(resolved, ".preset.yaml");
|
|
9619
10159
|
const edges = [];
|
|
9620
10160
|
for (const item of preset.items) {
|
|
9621
10161
|
if (item.ref) {
|
|
@@ -9667,7 +10207,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
|
|
|
9667
10207
|
}
|
|
9668
10208
|
}
|
|
9669
10209
|
async function runPresetValidate(filePath) {
|
|
9670
|
-
const resolved =
|
|
10210
|
+
const resolved = path22__default.resolve(filePath);
|
|
9671
10211
|
const preset = await loadPresetForValidation(resolved);
|
|
9672
10212
|
await reportNestedPresetRefs(preset);
|
|
9673
10213
|
await checkPresetCycles(preset, resolved);
|
|
@@ -9717,11 +10257,11 @@ items:
|
|
|
9717
10257
|
}
|
|
9718
10258
|
function makeRebuildCommand() {
|
|
9719
10259
|
return new Command("rebuild").description("Re-snapshot inline-snapshot composition items and bump prompt version").argument("[agent]", "Agent name or path (defaults to current project agent)").option("--project-dir <dir>", "Project directory", process.cwd()).action(async (agentArg, opts) => {
|
|
9720
|
-
const projectDir =
|
|
10260
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9721
10261
|
let agentDir;
|
|
9722
10262
|
if (agentArg) {
|
|
9723
10263
|
if (agentArg.includes("/") || agentArg.includes("\\")) {
|
|
9724
|
-
agentDir =
|
|
10264
|
+
agentDir = path22__default.resolve(projectDir, agentArg);
|
|
9725
10265
|
} else {
|
|
9726
10266
|
let resolved;
|
|
9727
10267
|
try {
|
|
@@ -9730,7 +10270,7 @@ function makeRebuildCommand() {
|
|
|
9730
10270
|
if (!(err2 instanceof AgentRefResolutionError)) throw err2;
|
|
9731
10271
|
logWarn(`${err2.message} \u2014 using "${agentArg}"`);
|
|
9732
10272
|
}
|
|
9733
|
-
agentDir = resolved ??
|
|
10273
|
+
agentDir = resolved ?? path22__default.resolve(projectDir, agentArg);
|
|
9734
10274
|
}
|
|
9735
10275
|
} else {
|
|
9736
10276
|
let resolved;
|
|
@@ -9796,13 +10336,23 @@ function friendlyDriverError(err2) {
|
|
|
9796
10336
|
return `${base}
|
|
9797
10337
|
Try a different harness with \`--driver claude-sdk\`.`;
|
|
9798
10338
|
}
|
|
10339
|
+
function driverErrorNotes(err2) {
|
|
10340
|
+
const e = err2;
|
|
10341
|
+
const notes = [];
|
|
10342
|
+
const category = e?.category ?? e?.detail?.category;
|
|
10343
|
+
const hint = e?.hint ?? e?.detail?.hint;
|
|
10344
|
+
if (hint && category !== "config") notes.push(hint);
|
|
10345
|
+
else if (category === "auth") notes.push("Check your API key or login.");
|
|
10346
|
+
notes.push("Full records: .skaile/logs.db (skaile session logs <session-id>).");
|
|
10347
|
+
return notes;
|
|
10348
|
+
}
|
|
9799
10349
|
|
|
9800
10350
|
// cli/src/commands/run.ts
|
|
9801
10351
|
function resolveSingleShotAgentDir(projectDir, agentDefinition) {
|
|
9802
10352
|
if (!agentDefinition) return resolveAgentDir(projectDir);
|
|
9803
|
-
const asPath = agentDefinition.endsWith("agent.yaml") ?
|
|
10353
|
+
const asPath = agentDefinition.endsWith("agent.yaml") ? path22__default.dirname(path22__default.resolve(projectDir, agentDefinition)) : agentDefinition;
|
|
9804
10354
|
const dir = resolveAgentDefinitionDir(projectDir, asPath);
|
|
9805
|
-
if (!dir || !
|
|
10355
|
+
if (!dir || !fs9__default.existsSync(path22__default.join(dir, "agent.yaml"))) {
|
|
9806
10356
|
throw new Error(
|
|
9807
10357
|
`--agent-definition "${agentDefinition}" does not resolve to an agent directory with agent.yaml${dir ? ` (looked in ${dir})` : ""}`
|
|
9808
10358
|
);
|
|
@@ -9853,10 +10403,58 @@ async function printCompositionDryRun(projectDir, agentDir, driver, model) {
|
|
|
9853
10403
|
}
|
|
9854
10404
|
for (const warning of resolved.warnings) logWarn(warning);
|
|
9855
10405
|
}
|
|
10406
|
+
async function findSkillFile(projectDir, skill) {
|
|
10407
|
+
const name = skill.trim().replace(/^skill:/, "").replace(/^@[^/]+\//, "").replace(/#.*$/, "");
|
|
10408
|
+
for (const target of SUPPORTED_DRIVER_TARGETS) {
|
|
10409
|
+
const file = path22__default.join(deployedDir("skill", name, target, false, projectDir), "SKILL.md");
|
|
10410
|
+
if (fs9__default.existsSync(file)) return file;
|
|
10411
|
+
}
|
|
10412
|
+
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
|
|
10413
|
+
const entry = await am2.info(`skill:${name}`);
|
|
10414
|
+
return entry?.source && fs9__default.existsSync(entry.source) ? entry.source : void 0;
|
|
10415
|
+
}
|
|
10416
|
+
async function printSkillDryRun(projectDir, skill) {
|
|
10417
|
+
const file = await findSkillFile(projectDir, skill);
|
|
10418
|
+
if (!file) {
|
|
10419
|
+
logErr(
|
|
10420
|
+
`Skill not found: ${skill} - not deployed in the project and not held by a registered library or source`
|
|
10421
|
+
);
|
|
10422
|
+
return false;
|
|
10423
|
+
}
|
|
10424
|
+
const content = fs9__default.readFileSync(file, "utf-8");
|
|
10425
|
+
const { data } = parseFrontmatter(content);
|
|
10426
|
+
const meta = data.metadata ?? {};
|
|
10427
|
+
console.log(` ${S.label("Skill:")} ${S.heading(String(data.name ?? skill))}`);
|
|
10428
|
+
console.log(` ${S.label("Source:")} ${file}`);
|
|
10429
|
+
if (meta.version) console.log(` ${S.label("Version:")} ${String(meta.version)}`);
|
|
10430
|
+
if (data.description) console.log(` ${S.label("About:")} ${String(data.description)}`);
|
|
10431
|
+
const requires = parseRequires(data);
|
|
10432
|
+
if (requires.length > 0) {
|
|
10433
|
+
console.log(` ${S.label("Requires:")} ${requires.map((d) => depToStr(d)).join(", ")}`);
|
|
10434
|
+
}
|
|
10435
|
+
const requirements = parseSkillRequirements(content);
|
|
10436
|
+
const report = await validateRequirements(String(data.name ?? skill), requirements, projectDir);
|
|
10437
|
+
const unmet = report.files.filter((f) => !f.exists);
|
|
10438
|
+
for (const f of report.files) {
|
|
10439
|
+
const mark = f.exists ? S.ok("present") : f.gate === "hard" ? S.err("missing") : S.warn("missing");
|
|
10440
|
+
const gate = f.gate === "soft" ? " (soft)" : "";
|
|
10441
|
+
console.log(` ${S.label("File:")} ${f.path}${gate} ${mark}`);
|
|
10442
|
+
}
|
|
10443
|
+
for (const input of report.inputs.filter((i) => i.required && !i.present)) {
|
|
10444
|
+
console.log(` ${S.label("Input:")} ${input.id} ${S.err("required, not collected")}`);
|
|
10445
|
+
}
|
|
10446
|
+
if (unmet.some((f) => f.gate === "hard")) {
|
|
10447
|
+
logWarn("Unmet hard prerequisites: the skill cannot run until those files exist.");
|
|
10448
|
+
}
|
|
10449
|
+
console.log();
|
|
10450
|
+
return true;
|
|
10451
|
+
}
|
|
9856
10452
|
function makeFlowEventHandler() {
|
|
9857
10453
|
const md = new MarkdownStreamer();
|
|
9858
10454
|
const displayed = /* @__PURE__ */ new Set();
|
|
10455
|
+
const printUnstreamed = createFinalTextFallback((text) => md.write(text));
|
|
9859
10456
|
return (event) => {
|
|
10457
|
+
printUnstreamed(event);
|
|
9860
10458
|
const e = event;
|
|
9861
10459
|
if (e.type === "state_changed" && typeof e.store === "string" && e.store.startsWith("flow:")) {
|
|
9862
10460
|
const nodes = e.state?.nodes ?? {};
|
|
@@ -9894,14 +10492,41 @@ function logAgentRunEvent(event) {
|
|
|
9894
10492
|
return;
|
|
9895
10493
|
}
|
|
9896
10494
|
const verdict = e.error ? `${e.runStatus ?? "failed"}: ${e.error.code} ${e.error.message}` : e.runStatus ?? "finished";
|
|
9897
|
-
console.error(` ${S.dim("subagent")} ${who} ${verdict}
|
|
10495
|
+
console.error(` ${S.dim("subagent")} ${who} ${verdict}${subagentOutputSuffix(e)}`);
|
|
10496
|
+
}
|
|
10497
|
+
function subagentOutputSuffix(e) {
|
|
10498
|
+
const value = e.result !== void 0 ? e.result : e.output;
|
|
10499
|
+
return value === void 0 ? "" : ` output=${JSON.stringify(value)}`;
|
|
10500
|
+
}
|
|
10501
|
+
function editDistance2(a, b) {
|
|
10502
|
+
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
10503
|
+
for (let i = 1; i <= a.length; i++) {
|
|
10504
|
+
const row = [i];
|
|
10505
|
+
for (let j = 1; j <= b.length; j++) {
|
|
10506
|
+
row[j] = Math.min(
|
|
10507
|
+
prev[j] + 1,
|
|
10508
|
+
row[j - 1] + 1,
|
|
10509
|
+
prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
|
|
10510
|
+
);
|
|
10511
|
+
}
|
|
10512
|
+
prev = row;
|
|
10513
|
+
}
|
|
10514
|
+
return prev[b.length];
|
|
10515
|
+
}
|
|
10516
|
+
function isNearFlowId(typed, id) {
|
|
10517
|
+
const a = typed.toLowerCase();
|
|
10518
|
+
const b = id.toLowerCase();
|
|
10519
|
+
return a.length >= 3 && (b.includes(a) || a.includes(b) || editDistance2(a, b) <= 2);
|
|
10520
|
+
}
|
|
10521
|
+
function driverOptionDescription() {
|
|
10522
|
+
return `Harness to run (${listDrivers().map((d) => d.id).join(", ")})`;
|
|
9898
10523
|
}
|
|
9899
10524
|
function makeRunCommand() {
|
|
9900
|
-
const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--driver <name>",
|
|
10525
|
+
const cmd = new Command("run").description("Start a flow or run a single-shot text prompt").argument("[flow-id-or-text...]", "Flow ID or text prompt").option("--project-dir <path>", "Project directory", process.cwd()).option("--driver <name>", driverOptionDescription()).option("--model <name>", "Model override").option("--label <label>", "Human-readable session label").option("--dry-run", "Print plan without executing (single-shot: resolved composition items)").option(
|
|
9901
10526
|
"--agent-definition <ref|path>",
|
|
9902
10527
|
"Agent asset for this one invocation (agent:@pub/name, ai-assets://\u2026, or a directory with agent.yaml); single-shot prompts only"
|
|
9903
10528
|
).option("--skill <name>", "Skill name (for single-shot mode)").action(async (positional, opts) => {
|
|
9904
|
-
const projectDir =
|
|
10529
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9905
10530
|
const cliDriver = opts.driver;
|
|
9906
10531
|
const dryRun = opts.dryRun ?? false;
|
|
9907
10532
|
const agentDefinition = opts.agentDefinition?.trim() || void 0;
|
|
@@ -9945,18 +10570,29 @@ function makeRunCommand() {
|
|
|
9945
10570
|
}
|
|
9946
10571
|
if (!flowPath) {
|
|
9947
10572
|
const textPrompt = positional.join(" ");
|
|
9948
|
-
|
|
10573
|
+
const promptOnlyOption = agentDefinition !== void 0 || opts.skill !== void 0;
|
|
10574
|
+
if (!textPrompt.trim() || positional.length === 1 && !/\s/.test(flowId) && !promptOnlyOption) {
|
|
9949
10575
|
logErr(`Flow not found: ${flowId}`);
|
|
9950
10576
|
const available = (await discoverFlowsWithLibraries(projectDir)).map((f) => f.id);
|
|
9951
|
-
|
|
9952
|
-
|
|
10577
|
+
const near = available.filter((id) => isNearFlowId(flowId, id));
|
|
10578
|
+
const listed = near.length > 0 ? near : available;
|
|
10579
|
+
if (listed.length > 0) {
|
|
10580
|
+
console.log(
|
|
10581
|
+
` ${S.dim(near.length > 0 ? "Did you mean:" : "Available:")} ${listed.map((id) => S.cmd(id)).join(", ")}`
|
|
10582
|
+
);
|
|
9953
10583
|
}
|
|
10584
|
+
console.log(
|
|
10585
|
+
` ${S.dim('To send it as a prompt, quote more than one word: skaile run "\u2026".')}`
|
|
10586
|
+
);
|
|
9954
10587
|
process.exit(1);
|
|
9955
10588
|
}
|
|
9956
10589
|
try {
|
|
9957
10590
|
const agentDir = resolveSingleShotAgentDir(projectDir, agentDefinition);
|
|
9958
10591
|
if (dryRun) {
|
|
9959
10592
|
await printCompositionDryRun(projectDir, agentDir, driver, model);
|
|
10593
|
+
if (opts.skill && !await printSkillDryRun(projectDir, opts.skill)) {
|
|
10594
|
+
process.exit(1);
|
|
10595
|
+
}
|
|
9960
10596
|
return;
|
|
9961
10597
|
}
|
|
9962
10598
|
await runAgentChat({
|
|
@@ -9978,6 +10614,7 @@ function makeRunCommand() {
|
|
|
9978
10614
|
logErr(friendly);
|
|
9979
10615
|
} else {
|
|
9980
10616
|
logErr(err2 instanceof Error ? err2.message : String(err2));
|
|
10617
|
+
for (const note of driverErrorNotes(err2)) console.error(` ${S.dim(note)}`);
|
|
9981
10618
|
}
|
|
9982
10619
|
process.exit(1);
|
|
9983
10620
|
}
|
|
@@ -10020,7 +10657,7 @@ function makeRunCommand() {
|
|
|
10020
10657
|
}
|
|
10021
10658
|
function makeResumeCommand() {
|
|
10022
10659
|
const cmd = new Command("resume").description("Resume current session").option("--project-dir <path>", "Project directory", process.cwd()).option("--session <run-id>", "Target session by runId").option("--dry-run", "Print plan without executing").action(async (opts) => {
|
|
10023
|
-
const projectDir =
|
|
10660
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10024
10661
|
const sessionId = opts.session;
|
|
10025
10662
|
const dryRun = opts.dryRun ?? false;
|
|
10026
10663
|
const session = sessionId ? await loadSessionById(projectDir, sessionId) : await loadSession(projectDir);
|
|
@@ -10047,7 +10684,7 @@ function makeResumeCommand() {
|
|
|
10047
10684
|
}
|
|
10048
10685
|
function makeStatusCommand() {
|
|
10049
10686
|
return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
10050
|
-
const projectDir =
|
|
10687
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10051
10688
|
const session = await loadSession(projectDir);
|
|
10052
10689
|
if (!session) {
|
|
10053
10690
|
logInfo("No active session.");
|
|
@@ -10060,6 +10697,7 @@ function makeStatusCommand() {
|
|
|
10060
10697
|
console.log(` ${S.label("Run ID:")} ${session.runId.slice(0, 8)}`);
|
|
10061
10698
|
if (session.label) console.log(` ${S.label("Label:")} ${session.label}`);
|
|
10062
10699
|
console.log(` ${S.label("Status:")} ${statusColor(session.status ?? "unknown")}`);
|
|
10700
|
+
if (session.error) console.log(` ${S.label("Error:")} ${session.error}`);
|
|
10063
10701
|
console.log(
|
|
10064
10702
|
` ${S.label("Driver:")} ${session.driver}${session.model ? S.dim(` / ${session.model}`) : ""}`
|
|
10065
10703
|
);
|
|
@@ -10072,17 +10710,17 @@ function makeStatusCommand() {
|
|
|
10072
10710
|
}
|
|
10073
10711
|
function makeClearCommand() {
|
|
10074
10712
|
return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
10075
|
-
const projectDir =
|
|
10713
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10076
10714
|
await clearSession(projectDir);
|
|
10077
10715
|
logOk("Session cleared.");
|
|
10078
10716
|
});
|
|
10079
10717
|
}
|
|
10080
10718
|
function makeReplCommand() {
|
|
10081
|
-
return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>",
|
|
10719
|
+
return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>", driverOptionDescription()).option("--model <name>", "Model override").option("--resume", "Resume last session").option("--resume-session <id>", "Resume specific session").action(async (opts) => {
|
|
10082
10720
|
const { findWorkspaceRoot } = await import('../core/index.js');
|
|
10083
10721
|
const { startRepl } = await import('../tui/index.js');
|
|
10084
10722
|
const os2 = await import('os');
|
|
10085
|
-
const userCwd =
|
|
10723
|
+
const userCwd = path22__default.resolve(opts.projectDir ?? process.cwd());
|
|
10086
10724
|
const workspaceRoot = findWorkspaceRoot(userCwd);
|
|
10087
10725
|
let projectDir;
|
|
10088
10726
|
let agentCwd;
|
|
@@ -10097,6 +10735,12 @@ function makeReplCommand() {
|
|
|
10097
10735
|
console.log();
|
|
10098
10736
|
logWarn(`No skaile.yaml found in ${S.cmd(userCwd)} or any parent directory.`);
|
|
10099
10737
|
console.log();
|
|
10738
|
+
if (!process.stdin.isTTY) {
|
|
10739
|
+
logErr(
|
|
10740
|
+
`repl needs a skaile.yaml here when stdin is not a terminal: run ${S.cmd("skaile init")} first.`
|
|
10741
|
+
);
|
|
10742
|
+
process.exit(1);
|
|
10743
|
+
}
|
|
10100
10744
|
const shouldCreate = await p4.confirm({
|
|
10101
10745
|
message: "Create a temporary workspace? (session state in /tmp/)"
|
|
10102
10746
|
});
|
|
@@ -10104,13 +10748,13 @@ function makeReplCommand() {
|
|
|
10104
10748
|
p4.cancel("Cancelled.");
|
|
10105
10749
|
process.exit(0);
|
|
10106
10750
|
}
|
|
10107
|
-
const tmpDir =
|
|
10751
|
+
const tmpDir = fs9__default.mkdtempSync(path22__default.join(os2.tmpdir(), "skaile-repl-"));
|
|
10108
10752
|
projectDir = tmpDir;
|
|
10109
10753
|
agentCwd = userCwd;
|
|
10110
10754
|
logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
|
|
10111
10755
|
if (!driverOverride) {
|
|
10112
|
-
const claudeDir =
|
|
10113
|
-
if (
|
|
10756
|
+
const claudeDir = path22__default.join(os2.homedir(), ".claude");
|
|
10757
|
+
if (fs9__default.existsSync(claudeDir)) {
|
|
10114
10758
|
driverOverride = "claude-sdk";
|
|
10115
10759
|
logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} harness`);
|
|
10116
10760
|
} else {
|
|
@@ -10139,7 +10783,10 @@ function parseProviderIds(raw) {
|
|
|
10139
10783
|
return (raw ?? "").split(",").map((id) => id.trim()).filter((id) => id.length > 0);
|
|
10140
10784
|
}
|
|
10141
10785
|
function makeServeCommand() {
|
|
10142
|
-
return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option(
|
|
10786
|
+
return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option(
|
|
10787
|
+
"--host <address>",
|
|
10788
|
+
"Address to bind (default: all interfaces; use 127.0.0.1 for local clients only)"
|
|
10789
|
+
).option("--project-dir <path>", "Project directory", process.cwd()).option(
|
|
10143
10790
|
"--managed-codex-config <path>",
|
|
10144
10791
|
"Explicit private host configuration for managed Codex"
|
|
10145
10792
|
).option("--driver <name>", "Override driver").option("--model <name>", "Override model").option("--provider <name>", "Override provider").option("--session-id <id>", "Session ID for conversation continuity").option("--resume-session-id <id>", "OMP session ID to resume (restores native OMP context)").option(
|
|
@@ -10167,32 +10814,48 @@ function makeServeCommand() {
|
|
|
10167
10814
|
await ensurePluginsLoadedForServe(opts.projectDir);
|
|
10168
10815
|
}
|
|
10169
10816
|
const providers = parseProviderIds(opts.providers);
|
|
10170
|
-
await
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
|
|
10184
|
-
|
|
10185
|
-
|
|
10817
|
+
const { checkDriverSdk } = await import('../serve-preflight-F7MYF747.js');
|
|
10818
|
+
const driverProblem = managedCodex ? null : await checkDriverSdk(opts.projectDir, opts.driver);
|
|
10819
|
+
if (driverProblem) {
|
|
10820
|
+
const { logErr: logErr2 } = await import('../helpers-53XZW7KF.js');
|
|
10821
|
+
logErr2(driverProblem);
|
|
10822
|
+
process.exitCode = 1;
|
|
10823
|
+
return;
|
|
10824
|
+
}
|
|
10825
|
+
try {
|
|
10826
|
+
await startAgentServer({
|
|
10827
|
+
port: parseInt(opts.port, 10),
|
|
10828
|
+
...opts.host ? { host: opts.host } : {},
|
|
10829
|
+
authTokenIntake: wsAuth,
|
|
10830
|
+
...managedCodex ? { managedCodex } : {},
|
|
10831
|
+
// The CLI owns its process, so a dead stdout pipe is fatal here.
|
|
10832
|
+
// `SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT=0` opts out — the `local` /
|
|
10833
|
+
// `nix` deploy targets set it for children meant to outlive them.
|
|
10834
|
+
exitOnBrokenPipe: process.env.SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT !== "0",
|
|
10835
|
+
projectDir: opts.projectDir,
|
|
10836
|
+
driver: opts.driver,
|
|
10837
|
+
model: opts.model,
|
|
10838
|
+
provider: opts.provider,
|
|
10839
|
+
sessionId: opts.sessionId,
|
|
10840
|
+
resumeSessionId: opts.resumeSessionId,
|
|
10841
|
+
...providers.length > 0 ? { providers } : {}
|
|
10842
|
+
});
|
|
10843
|
+
} catch (err2) {
|
|
10844
|
+
if (err2?.code !== "EADDRINUSE") throw err2;
|
|
10845
|
+
const { logErr: logErr2 } = await import('../helpers-53XZW7KF.js');
|
|
10846
|
+
logErr2(err2.message);
|
|
10847
|
+
process.exit(1);
|
|
10848
|
+
}
|
|
10186
10849
|
}
|
|
10187
10850
|
);
|
|
10188
10851
|
}
|
|
10189
10852
|
async function ensurePluginsLoadedForServe(projectDir) {
|
|
10190
|
-
const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-
|
|
10853
|
+
const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-53XZW7KF.js');
|
|
10191
10854
|
try {
|
|
10192
10855
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
10193
10856
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
10194
10857
|
if (!config.plugins || config.plugins.length === 0) return;
|
|
10195
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
10858
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-CK7YWRIC.js');
|
|
10196
10859
|
const { pluginRegistry } = await import('../plugin-registry/index.js');
|
|
10197
10860
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
10198
10861
|
if (result.loaded.length > 0) {
|
|
@@ -10206,21 +10869,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
10206
10869
|
}
|
|
10207
10870
|
}
|
|
10208
10871
|
async function runCompileTest(opts) {
|
|
10209
|
-
const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-
|
|
10872
|
+
const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-53XZW7KF.js');
|
|
10210
10873
|
const { tmpdir } = await import('os');
|
|
10211
|
-
const { dirname: dirname3, join:
|
|
10874
|
+
const { dirname: dirname3, join: join7, resolve: resolve5 } = await import('path');
|
|
10212
10875
|
const { fileURLToPath: fileURLToPath2 } = await import('url');
|
|
10213
|
-
const { unlinkSync, existsSync:
|
|
10876
|
+
const { unlinkSync, existsSync: existsSync21 } = await import('fs');
|
|
10214
10877
|
const { spawn } = await import('child_process');
|
|
10215
10878
|
const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
|
|
10216
|
-
const { MONOREPO_ROOT } = await import('../paths-
|
|
10879
|
+
const { MONOREPO_ROOT } = await import('../paths-KKY3NSBZ.js');
|
|
10217
10880
|
if (MONOREPO_ROOT === null) {
|
|
10218
10881
|
logErr2("--compile-test is only available inside the skaile-dev workspace.");
|
|
10219
10882
|
logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
|
|
10220
10883
|
process.exitCode = 2;
|
|
10221
10884
|
return;
|
|
10222
10885
|
}
|
|
10223
|
-
const outfile =
|
|
10886
|
+
const outfile = join7(tmpdir(), `skaile-compile-test-${Date.now()}`);
|
|
10224
10887
|
const __thisFile = fileURLToPath2(import.meta.url);
|
|
10225
10888
|
const entryPoint = resolve5(dirname3(__thisFile), "..", "index.ts");
|
|
10226
10889
|
logInfo2(`Building compiled binary...`);
|
|
@@ -10275,7 +10938,7 @@ async function runCompileTest(opts) {
|
|
|
10275
10938
|
} catch {
|
|
10276
10939
|
}
|
|
10277
10940
|
try {
|
|
10278
|
-
if (
|
|
10941
|
+
if (existsSync21(outfile)) unlinkSync(outfile);
|
|
10279
10942
|
} catch {
|
|
10280
10943
|
}
|
|
10281
10944
|
}
|
|
@@ -10696,7 +11359,7 @@ function resolveMode2(opts) {
|
|
|
10696
11359
|
if (opts.forceLocal && opts.forceRemote) {
|
|
10697
11360
|
throw new Error("Cannot use both --local and --remote");
|
|
10698
11361
|
}
|
|
10699
|
-
const startDir =
|
|
11362
|
+
const startDir = path22__default.resolve(opts.projectDir ?? process.cwd());
|
|
10700
11363
|
const localDb = findLogsDb(startDir);
|
|
10701
11364
|
if (opts.forceLocal) {
|
|
10702
11365
|
if (!localDb) {
|
|
@@ -10729,14 +11392,14 @@ function resolveMode2(opts) {
|
|
|
10729
11392
|
function findLogsDb(startDir) {
|
|
10730
11393
|
let dir = startDir;
|
|
10731
11394
|
for (let i = 0; i < MAX_WALK_LEVELS; i++) {
|
|
10732
|
-
const candidate =
|
|
11395
|
+
const candidate = path22__default.join(dir, ".skaile", "logs.db");
|
|
10733
11396
|
if (existsSync(candidate)) {
|
|
10734
11397
|
try {
|
|
10735
11398
|
if (statSync(candidate).isFile()) return candidate;
|
|
10736
11399
|
} catch {
|
|
10737
11400
|
}
|
|
10738
11401
|
}
|
|
10739
|
-
const parent =
|
|
11402
|
+
const parent = path22__default.dirname(dir);
|
|
10740
11403
|
if (parent === dir) return void 0;
|
|
10741
11404
|
dir = parent;
|
|
10742
11405
|
}
|
|
@@ -10911,7 +11574,7 @@ function parsePositiveInt(value, flag) {
|
|
|
10911
11574
|
function makeSessionCommand() {
|
|
10912
11575
|
const cmd = new Command("session").description("Manage sessions");
|
|
10913
11576
|
cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
10914
|
-
const projectDir =
|
|
11577
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10915
11578
|
const sessions = await listSessions(projectDir);
|
|
10916
11579
|
const current = await loadSession(projectDir);
|
|
10917
11580
|
if (sessions.length === 0) {
|
|
@@ -10939,7 +11602,7 @@ function makeSessionCommand() {
|
|
|
10939
11602
|
console.log();
|
|
10940
11603
|
});
|
|
10941
11604
|
cmd.command("show <run-id>").description("Show a specific session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
10942
|
-
const projectDir =
|
|
11605
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10943
11606
|
const session = await loadSessionById(projectDir, runId);
|
|
10944
11607
|
if (!session) {
|
|
10945
11608
|
logErr(`Session not found: ${runId}`);
|
|
@@ -10948,7 +11611,7 @@ function makeSessionCommand() {
|
|
|
10948
11611
|
console.log(JSON.stringify(session, null, 2));
|
|
10949
11612
|
});
|
|
10950
11613
|
cmd.command("switch <run-id>").description("Switch the current session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
10951
|
-
const projectDir =
|
|
11614
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10952
11615
|
if (!await loadSessionById(projectDir, runId)) {
|
|
10953
11616
|
logErr(`Session not found: ${runId}`);
|
|
10954
11617
|
process.exit(1);
|
|
@@ -10957,7 +11620,7 @@ function makeSessionCommand() {
|
|
|
10957
11620
|
logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
|
|
10958
11621
|
});
|
|
10959
11622
|
cmd.command("delete <run-id>").description("Delete a session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
10960
|
-
const projectDir =
|
|
11623
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10961
11624
|
if (!await loadSessionById(projectDir, runId)) {
|
|
10962
11625
|
logErr(`Session not found: ${runId}`);
|
|
10963
11626
|
process.exit(1);
|
|
@@ -11015,12 +11678,12 @@ function showOverview(am2) {
|
|
|
11015
11678
|
}
|
|
11016
11679
|
async function showAsset(am2, kind, name) {
|
|
11017
11680
|
const entry = await am2.info(`${kind}:${name}`);
|
|
11018
|
-
if (entry?.source &&
|
|
11681
|
+
if (entry?.source && fs9__default.existsSync(entry.source)) {
|
|
11019
11682
|
console.log();
|
|
11020
11683
|
console.log(` ${kindColor(entry.kind)} ${S.heading(entry.name)}`);
|
|
11021
11684
|
console.log(` ${S.rule(40)}`);
|
|
11022
11685
|
console.log();
|
|
11023
|
-
console.log(
|
|
11686
|
+
console.log(fs9__default.readFileSync(entry.source, "utf-8"));
|
|
11024
11687
|
return;
|
|
11025
11688
|
}
|
|
11026
11689
|
logErr(`Asset not found: ${kind}:${name}`);
|
|
@@ -11030,7 +11693,7 @@ function makeShowCommand() {
|
|
|
11030
11693
|
return new Command("show").description("Show deployed assets overview, or print asset content").argument("[kind]", "Asset kind (skill, agent, prompt, flow, preset, contract)").argument("[name]", "Asset name").option("--project-dir <path>", "Project directory", process.cwd()).option("--target <agent>", `Agent framework (${TARGET_DEFAULT_HINT})`).action(async (kind, name, opts) => {
|
|
11031
11694
|
const am2 = new AssetManager({
|
|
11032
11695
|
registry: getKindRegistry(),
|
|
11033
|
-
projectDir:
|
|
11696
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
11034
11697
|
driverTarget: opts.target
|
|
11035
11698
|
});
|
|
11036
11699
|
if (!kind) {
|
|
@@ -11048,6 +11711,32 @@ function makeShowCommand() {
|
|
|
11048
11711
|
}
|
|
11049
11712
|
});
|
|
11050
11713
|
}
|
|
11714
|
+
function searchCuratedManifests(query) {
|
|
11715
|
+
const dir = getStoreManifestsDir();
|
|
11716
|
+
if (!existsSync(dir)) return [];
|
|
11717
|
+
const q = query.toLowerCase();
|
|
11718
|
+
const hits = [];
|
|
11719
|
+
for (const file of readdirSync(dir).sort()) {
|
|
11720
|
+
if (!file.endsWith(".yaml")) continue;
|
|
11721
|
+
const slug = file.slice(0, -".yaml".length);
|
|
11722
|
+
let manifest;
|
|
11723
|
+
try {
|
|
11724
|
+
manifest = decodeSkaileManifest(readFileSync(path22.join(dir, file), "utf-8")).manifest;
|
|
11725
|
+
} catch {
|
|
11726
|
+
continue;
|
|
11727
|
+
}
|
|
11728
|
+
const repoPublisher2 = manifest.publisher?.replace(/^@/, "");
|
|
11729
|
+
for (const a of manifest.assets ?? []) {
|
|
11730
|
+
const publisher = (a.publisher ?? repoPublisher2 ?? "").replace(/^@/, "");
|
|
11731
|
+
const haystack = [a.name, a.description ?? "", publisher, a.kind].join(" ").toLowerCase();
|
|
11732
|
+
if (!haystack.includes(q)) continue;
|
|
11733
|
+
hits.push({ slug, kind: a.kind, publisher, name: a.name, description: a.description });
|
|
11734
|
+
}
|
|
11735
|
+
}
|
|
11736
|
+
return hits;
|
|
11737
|
+
}
|
|
11738
|
+
|
|
11739
|
+
// cli/src/commands/store.ts
|
|
11051
11740
|
async function fetchIdentity() {
|
|
11052
11741
|
const jwt = await getStoreToken();
|
|
11053
11742
|
return storeFetch({ ...getStoreConfig(), jwt }, "/api/v1/me");
|
|
@@ -11093,43 +11782,83 @@ function makeStoreCommand() {
|
|
|
11093
11782
|
});
|
|
11094
11783
|
store.command("mode <auto|local|remote>").description("Set the catalog resolution mode (not yet wired)").action((_mode) => {
|
|
11095
11784
|
logErr(
|
|
11096
|
-
`\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${
|
|
11785
|
+
`\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path22__default.join(globalSkaileDir(), "store", "config.yaml")}.`
|
|
11097
11786
|
);
|
|
11098
11787
|
process.exit(2);
|
|
11099
11788
|
});
|
|
11100
|
-
store.command("search <query>").description("Search the AI Asset Store catalog by name, description, or publisher").option("--kind <kind>", "Filter by asset kind (skill,
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11789
|
+
store.command("search <query>").description("Search the AI Asset Store catalog by name, description, or publisher").option("--kind <kind>", "Filter by asset kind (skill, prompt, flow, \u2026)").option(
|
|
11790
|
+
"--all",
|
|
11791
|
+
`List every match (default: ${STORE_ROW_LIMIT} rows, only what \`skaile add\` can install)`
|
|
11792
|
+
).option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (query, opts) => {
|
|
11793
|
+
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-PZAT3TJA.js');
|
|
11794
|
+
const { getKnownKinds: getKnownKinds2 } = await import('../open-registry-W46UXZ3I.js');
|
|
11795
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
11796
|
+
if (opts.kind && !getKnownKinds2().has(opts.kind)) {
|
|
11797
|
+
logErr(
|
|
11798
|
+
`Unknown kind "${opts.kind}". Valid kinds: ${[...getKnownKinds2()].sort().join(", ")}`
|
|
11799
|
+
);
|
|
11800
|
+
process.exit(1);
|
|
11801
|
+
}
|
|
11802
|
+
const curated = searchCuratedManifests(query).filter(
|
|
11803
|
+
(h) => !opts.kind || h.kind === opts.kind
|
|
11804
|
+
);
|
|
11805
|
+
const printCurated = () => {
|
|
11806
|
+
if (curated.length === 0) return;
|
|
11807
|
+
console.log(`
|
|
11808
|
+
${S.heading("Local curated manifests")}`);
|
|
11809
|
+
for (const h of curated) {
|
|
11810
|
+
console.log(
|
|
11811
|
+
` ${kindColorPad(h.kind)} ${h.kind}:@${h.publisher}/${h.name} ${S.dim(`(manifest ${h.slug})`)}`
|
|
11812
|
+
);
|
|
11109
11813
|
}
|
|
11110
|
-
console.log();
|
|
11111
|
-
for (const row of formatStoreRows(results, " ")) console.log(row);
|
|
11112
11814
|
console.log(
|
|
11113
11815
|
`
|
|
11114
|
-
${S.dim(
|
|
11816
|
+
${S.dim("Not published: `skaile source add <repo URL>` indexes them for `skaile add`.")}
|
|
11115
11817
|
`
|
|
11116
11818
|
);
|
|
11819
|
+
};
|
|
11820
|
+
try {
|
|
11821
|
+
const remote = await openCatalogSource2({ projectDir });
|
|
11822
|
+
const assets = await remote.listAssets(opts.kind ? { kind: opts.kind } : {});
|
|
11823
|
+
const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
|
|
11824
|
+
if (sel.shown.length === 0) {
|
|
11825
|
+
logInfo(`No store results for "${query}".`);
|
|
11826
|
+
for (const note of storeSelectionNotes(sel, "")) console.log(note);
|
|
11827
|
+
} else {
|
|
11828
|
+
console.log();
|
|
11829
|
+
for (const row of formatStoreRows(sel.shown, " ")) console.log(row);
|
|
11830
|
+
console.log(
|
|
11831
|
+
`
|
|
11832
|
+
${S.dim(`${sel.shown.length} result(s) \xB7 \`skaile store show <ref>\` for details`)}`
|
|
11833
|
+
);
|
|
11834
|
+
for (const note of storeSelectionNotes(sel, " ")) console.log(note);
|
|
11835
|
+
if (curated.length === 0) console.log();
|
|
11836
|
+
}
|
|
11837
|
+
printCurated();
|
|
11117
11838
|
} catch (e) {
|
|
11839
|
+
printCurated();
|
|
11840
|
+
if (e instanceof LocalCatalogDisabledError2 && curated.length > 0) return;
|
|
11118
11841
|
if (e instanceof LocalCatalogDisabledError2) {
|
|
11119
11842
|
logErr(
|
|
11120
11843
|
`Remote catalog disabled (catalog.url: local). Set \`catalog.url: https://skaile.store\` in ${userConfigPath()}.`
|
|
11121
11844
|
);
|
|
11122
11845
|
} else {
|
|
11123
|
-
logErr(`Store search failed: ${e
|
|
11846
|
+
logErr(`Store search failed: ${await describeStoreFailure(e, projectDir)}`);
|
|
11124
11847
|
}
|
|
11125
11848
|
process.exit(1);
|
|
11126
11849
|
}
|
|
11127
11850
|
});
|
|
11128
11851
|
store.command("show <ref>").description("Show a store asset's details + provenance (source, files, integrity)").option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (ref, opts) => {
|
|
11129
|
-
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-
|
|
11130
|
-
const { supportsInstallManifest } = await import('../project-
|
|
11852
|
+
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-PZAT3TJA.js');
|
|
11853
|
+
const { supportsInstallManifest } = await import('../project-EZUH7PUJ.js');
|
|
11131
11854
|
try {
|
|
11132
|
-
|
|
11855
|
+
parseAssetRef(ref);
|
|
11856
|
+
} catch (e) {
|
|
11857
|
+
logErr(`Invalid asset ref "${ref}": ${e instanceof Error ? e.message : String(e)}`);
|
|
11858
|
+
process.exit(1);
|
|
11859
|
+
}
|
|
11860
|
+
try {
|
|
11861
|
+
const remote = await openCatalogSource2({ projectDir: path22__default.resolve(opts.projectDir) });
|
|
11133
11862
|
const asset = await remote.resolve(ref);
|
|
11134
11863
|
if (!asset) {
|
|
11135
11864
|
logErr(`Not found in store: ${ref} (try a full ref, e.g. skill:@publisher/name#version)`);
|
|
@@ -11137,8 +11866,12 @@ function makeStoreCommand() {
|
|
|
11137
11866
|
}
|
|
11138
11867
|
const canonical = catalogAssetRef(asset);
|
|
11139
11868
|
let manifest = null;
|
|
11869
|
+
const manifestFailure = {};
|
|
11140
11870
|
if (supportsInstallManifest(remote)) {
|
|
11141
|
-
manifest = await remote.getInstallManifest(canonical).catch(() =>
|
|
11871
|
+
manifest = await remote.getInstallManifest(canonical).catch(async (err2) => {
|
|
11872
|
+
manifestFailure.text = await describeStoreFailure(err2, path22__default.resolve(opts.projectDir));
|
|
11873
|
+
return null;
|
|
11874
|
+
});
|
|
11142
11875
|
}
|
|
11143
11876
|
const field = (label, value) => ` ${S.label(label.padEnd(11))}${value}`;
|
|
11144
11877
|
console.log();
|
|
@@ -11168,13 +11901,25 @@ function makeStoreCommand() {
|
|
|
11168
11901
|
console.log(field("Repo", asset.repo));
|
|
11169
11902
|
if (asset.sha256) console.log(field("Integrity", asset.sha256));
|
|
11170
11903
|
}
|
|
11904
|
+
if (!manifest && manifestFailure.text) {
|
|
11905
|
+
console.log();
|
|
11906
|
+
console.log(field("Files", S.dim(`unavailable (${manifestFailure.text})`)));
|
|
11907
|
+
}
|
|
11908
|
+
if (asset.requires?.length) {
|
|
11909
|
+
console.log();
|
|
11910
|
+
console.log(` ${S.heading("Requires")}`);
|
|
11911
|
+
for (const dep of asset.requires) console.log(` ${S.dim("\u2192")} ${dep}`);
|
|
11912
|
+
}
|
|
11171
11913
|
if (asset.softDeps?.length) {
|
|
11172
11914
|
console.log();
|
|
11173
11915
|
console.log(` ${S.heading("Soft dependencies")}`);
|
|
11174
11916
|
for (const dep of asset.softDeps) console.log(` ${S.dim("\u2192")} ${dep}`);
|
|
11175
11917
|
}
|
|
11176
11918
|
console.log();
|
|
11177
|
-
|
|
11919
|
+
const notInstallable = storeNotInstallableReason(asset);
|
|
11920
|
+
console.log(
|
|
11921
|
+
notInstallable ? ` ${S.dim(`Not installable: ${notInstallable}`)}` : ` ${S.dim(`Install: skaile add ${canonical}`)}`
|
|
11922
|
+
);
|
|
11178
11923
|
console.log();
|
|
11179
11924
|
} catch (e) {
|
|
11180
11925
|
if (e instanceof LocalCatalogDisabledError2) {
|
|
@@ -11182,7 +11927,9 @@ function makeStoreCommand() {
|
|
|
11182
11927
|
`Remote catalog disabled (catalog.url: local). Set \`catalog.url: https://skaile.store\` in ${userConfigPath()}.`
|
|
11183
11928
|
);
|
|
11184
11929
|
} else {
|
|
11185
|
-
logErr(
|
|
11930
|
+
logErr(
|
|
11931
|
+
`Store show failed: ${await describeStoreFailure(e, path22__default.resolve(opts.projectDir))}`
|
|
11932
|
+
);
|
|
11186
11933
|
}
|
|
11187
11934
|
process.exit(1);
|
|
11188
11935
|
}
|
|
@@ -11252,9 +11999,10 @@ function treeRefs(nodes) {
|
|
|
11252
11999
|
}
|
|
11253
12000
|
function makeTreeCommand() {
|
|
11254
12001
|
return new Command("tree").description("Show full dependency tree").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
12002
|
+
requireProjectConfig(opts.projectDir);
|
|
11255
12003
|
const am2 = new AssetManager({
|
|
11256
12004
|
registry: getKindRegistry(),
|
|
11257
|
-
projectDir:
|
|
12005
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
11258
12006
|
});
|
|
11259
12007
|
const root = await am2.tree();
|
|
11260
12008
|
if (root.children.length === 0) {
|
|
@@ -11281,15 +12029,17 @@ function makeUpdateCommand() {
|
|
|
11281
12029
|
"Update only this declared asset (kind:@publisher/name, kind:name or name); exits 1 when none matches"
|
|
11282
12030
|
).option("--project-dir <path>", "Project directory", process.cwd()).option("--no-catalog", "Skip refreshing the catalog cache").option("--catalog-only", "Refresh the catalog cache only; do not re-deploy assets").option("--no-sync", "Skip syncing sources from upstream before re-deploying").option("-y, --yes", "Sync sources without the confirmation prompt").action(
|
|
11283
12031
|
async (name, opts) => {
|
|
11284
|
-
const projectDir =
|
|
12032
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
11285
12033
|
if (!opts.catalogOnly) requireProjectConfig(projectDir);
|
|
11286
12034
|
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
|
|
11287
12035
|
const target = name !== void 0 && !opts.catalogOnly ? await resolveUpdateTarget(am2, name) : void 0;
|
|
11288
|
-
if (opts.catalog !== false) {
|
|
12036
|
+
if (opts.catalog !== false && !opts.catalogOnly && onlyLibraryAssets(projectDir)) {
|
|
12037
|
+
logInfo("Catalog refresh skipped (every locked asset comes from a library)");
|
|
12038
|
+
} else if (opts.catalog !== false) {
|
|
11289
12039
|
const catalogSpinner = createSpinner();
|
|
11290
12040
|
catalogSpinner.start("Refreshing catalog cache");
|
|
11291
12041
|
try {
|
|
11292
|
-
const remote = await openCatalogSource({ projectDir:
|
|
12042
|
+
const remote = await openCatalogSource({ projectDir: path22__default.resolve(opts.projectDir) });
|
|
11293
12043
|
const result2 = await remote.refresh();
|
|
11294
12044
|
catalogSpinner.stop(
|
|
11295
12045
|
`Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
|
|
@@ -11300,7 +12050,13 @@ function makeUpdateCommand() {
|
|
|
11300
12050
|
catalogSpinner.stop("Catalog refresh skipped (catalog.url: local)");
|
|
11301
12051
|
} else {
|
|
11302
12052
|
catalogSpinner.stop("Catalog refresh failed");
|
|
11303
|
-
|
|
12053
|
+
const why = err2 instanceof Error ? err2.message : String(err2);
|
|
12054
|
+
if (opts.catalogOnly) {
|
|
12055
|
+
logErr(`Catalog refresh failed: ${why}`);
|
|
12056
|
+
logInfo("Run `skaile catalog test` to debug.");
|
|
12057
|
+
process.exit(1);
|
|
12058
|
+
}
|
|
12059
|
+
logWarn(`Catalog refresh failed: ${why}`);
|
|
11304
12060
|
logInfo("Continuing with asset re-deploy. Run `skaile catalog test` to debug.");
|
|
11305
12061
|
}
|
|
11306
12062
|
}
|
|
@@ -11402,10 +12158,29 @@ async function resolveUpdateTarget(am2, name) {
|
|
|
11402
12158
|
for (const h of hits) console.error(` ${h.ref}`);
|
|
11403
12159
|
process.exit(1);
|
|
11404
12160
|
}
|
|
12161
|
+
const chain = await am2.why(name);
|
|
12162
|
+
if (chain.length > 2 && chain[chain.length - 1] === "direct (skaile.yaml)") {
|
|
12163
|
+
const plain = (ref) => ref.replace(/#.*$/, "");
|
|
12164
|
+
const root = chain[chain.length - 2];
|
|
12165
|
+
logErr(
|
|
12166
|
+
`${plain(chain[0])} is required by ${plain(chain[1])}; run \`skaile update ${plain(root)}\`.`
|
|
12167
|
+
);
|
|
12168
|
+
process.exit(1);
|
|
12169
|
+
}
|
|
11405
12170
|
logErr(`No declared asset matches "${name}".`);
|
|
11406
12171
|
if (declared.length > 0) logInfo(`Declared: ${declared.map((d) => d.ref).join(", ")}`);
|
|
11407
12172
|
process.exit(1);
|
|
11408
12173
|
}
|
|
12174
|
+
function onlyLibraryAssets(projectDir) {
|
|
12175
|
+
let lock;
|
|
12176
|
+
try {
|
|
12177
|
+
lock = readLock(path22__default.join(projectDir, "skaile.lock.yaml"));
|
|
12178
|
+
} catch {
|
|
12179
|
+
return false;
|
|
12180
|
+
}
|
|
12181
|
+
const entries = Object.values(lock?.assets ?? {});
|
|
12182
|
+
return entries.length > 0 && entries.every((e) => e.library !== void 0);
|
|
12183
|
+
}
|
|
11409
12184
|
function readText2(file) {
|
|
11410
12185
|
try {
|
|
11411
12186
|
return readFileSync(file, "utf8");
|
|
@@ -11414,13 +12189,16 @@ function readText2(file) {
|
|
|
11414
12189
|
}
|
|
11415
12190
|
}
|
|
11416
12191
|
async function updateOne(am2, projectDir, target) {
|
|
11417
|
-
const lockPath =
|
|
12192
|
+
const lockPath = path22__default.join(projectDir, "skaile.lock.yaml");
|
|
11418
12193
|
const before = readText2(lockPath);
|
|
11419
12194
|
const spinner = createSpinner();
|
|
11420
12195
|
spinner.start(`Updating ${target.ref}`);
|
|
11421
12196
|
let deployed;
|
|
11422
12197
|
try {
|
|
11423
|
-
deployed = await am2.add(target.ref, {
|
|
12198
|
+
deployed = await am2.add(target.ref, {
|
|
12199
|
+
preferLockedLibrary: true,
|
|
12200
|
+
onLibraryMoved: (m) => reportMoved([m])
|
|
12201
|
+
});
|
|
11424
12202
|
} catch (err2) {
|
|
11425
12203
|
spinner.stop("Failed");
|
|
11426
12204
|
logErr(err2 instanceof Error ? err2.message : String(err2));
|
|
@@ -11545,9 +12323,10 @@ function whyEmptyMessage(ref, declared) {
|
|
|
11545
12323
|
}
|
|
11546
12324
|
function makeWhyCommand() {
|
|
11547
12325
|
return new Command("why").description("Show why an asset is installed (dependency chain)").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
|
|
12326
|
+
requireProjectConfig(opts.projectDir);
|
|
11548
12327
|
const am2 = new AssetManager({
|
|
11549
12328
|
registry: getKindRegistry(),
|
|
11550
|
-
projectDir:
|
|
12329
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
11551
12330
|
});
|
|
11552
12331
|
const chain = await am2.why(ref);
|
|
11553
12332
|
if (chain.length === 0) {
|
|
@@ -11588,11 +12367,38 @@ function makeWhyCommand() {
|
|
|
11588
12367
|
});
|
|
11589
12368
|
}
|
|
11590
12369
|
|
|
12370
|
+
// cli/src/index-busy.ts
|
|
12371
|
+
var INDEX_BUSY_MESSAGE = "The skaile index is busy (another skaile process holds it); retry in a moment.";
|
|
12372
|
+
function isIndexBusyError(err2) {
|
|
12373
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12374
|
+
let cur = err2;
|
|
12375
|
+
while (cur && typeof cur === "object" && !seen.has(cur)) {
|
|
12376
|
+
seen.add(cur);
|
|
12377
|
+
const { code, message, cause } = cur;
|
|
12378
|
+
if (typeof code === "string" && code.startsWith("SQLITE_BUSY")) return true;
|
|
12379
|
+
if (typeof message === "string" && /SQLITE_BUSY|database is locked/i.test(message)) return true;
|
|
12380
|
+
cur = cause;
|
|
12381
|
+
}
|
|
12382
|
+
return false;
|
|
12383
|
+
}
|
|
12384
|
+
|
|
11591
12385
|
// cli/src/index.ts
|
|
12386
|
+
{
|
|
12387
|
+
const envLevel = process.env.SKAILE_LOG_LEVEL;
|
|
12388
|
+
const level = envLevel === "debug" || envLevel === "info" || envLevel === "warn" || envLevel === "error" ? envLevel : "warn";
|
|
12389
|
+
registerLogStore(
|
|
12390
|
+
new LogStore({
|
|
12391
|
+
sessionId: "cli",
|
|
12392
|
+
level,
|
|
12393
|
+
flushIntervalMs: 0,
|
|
12394
|
+
sinks: [new StdoutSink({ stream: "stderr", format: "pretty" })]
|
|
12395
|
+
})
|
|
12396
|
+
);
|
|
12397
|
+
}
|
|
11592
12398
|
var _defaultFormatHelp = Help.prototype.formatHelp;
|
|
11593
12399
|
var pkg = JSON.parse(
|
|
11594
12400
|
readFileSync(
|
|
11595
|
-
|
|
12401
|
+
path22__default.resolve(path22__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
|
|
11596
12402
|
"utf-8"
|
|
11597
12403
|
)
|
|
11598
12404
|
);
|
|
@@ -11603,7 +12409,7 @@ for (const key of [
|
|
|
11603
12409
|
"SKAILE_CACHE_DIR"
|
|
11604
12410
|
]) {
|
|
11605
12411
|
const value = process.env[key];
|
|
11606
|
-
if (value) process.env[key] =
|
|
12412
|
+
if (value) process.env[key] = path22__default.resolve(value);
|
|
11607
12413
|
}
|
|
11608
12414
|
var program = new Command("skaile").description("AI asset manager").version(pkg.version, "-v, --version", "Show the skaile CLI version").enablePositionalOptions().configureHelp({
|
|
11609
12415
|
formatHelp(cmd, helper) {
|
|
@@ -11648,7 +12454,7 @@ Execution:
|
|
|
11648
12454
|
repl Interactive agent REPL
|
|
11649
12455
|
resume Resume last session
|
|
11650
12456
|
serve [--compile-test] Start WebSocket agent server
|
|
11651
|
-
mcp-server Start workspace MCP server (for .
|
|
12457
|
+
mcp-server Start workspace MCP server (for .mcp.json)
|
|
11652
12458
|
integration install [--driver all] Install agent integration (claude-code | omp | codex)
|
|
11653
12459
|
integration uninstall [--driver all] Uninstall agent integration
|
|
11654
12460
|
integration enable Enable integration (claude-code only)
|
|
@@ -11723,7 +12529,7 @@ program.command("init [project-dir]").description("Initialize a project director
|
|
|
11723
12529
|
(projectDir, opts) => runInit(projectDir, opts)
|
|
11724
12530
|
);
|
|
11725
12531
|
async function runInit(projectDir, opts) {
|
|
11726
|
-
const { mkdirSync: mkdirSync5, writeFileSync:
|
|
12532
|
+
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync7 } = await import('fs');
|
|
11727
12533
|
const { stringify: stringify2 } = await import('yaml');
|
|
11728
12534
|
const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
|
|
11729
12535
|
const harness = opts.harness;
|
|
@@ -11732,32 +12538,32 @@ async function runInit(projectDir, opts) {
|
|
|
11732
12538
|
process.exitCode = 1;
|
|
11733
12539
|
return;
|
|
11734
12540
|
}
|
|
11735
|
-
const resolved =
|
|
11736
|
-
const projectName =
|
|
12541
|
+
const resolved = path22__default.resolve(projectDir ?? ".");
|
|
12542
|
+
const projectName = path22__default.basename(resolved);
|
|
11737
12543
|
const created = [];
|
|
11738
|
-
const { existsSync:
|
|
11739
|
-
if (!
|
|
12544
|
+
const { existsSync: existsSync21 } = await import('fs');
|
|
12545
|
+
if (!existsSync21(resolved)) {
|
|
11740
12546
|
mkdirSync5(resolved, { recursive: true });
|
|
11741
12547
|
created.push(".");
|
|
11742
12548
|
}
|
|
11743
|
-
const skaileDir =
|
|
11744
|
-
if (!
|
|
11745
|
-
mkdirSync5(
|
|
12549
|
+
const skaileDir = path22__default.join(resolved, ".skaile");
|
|
12550
|
+
if (!existsSync21(skaileDir)) {
|
|
12551
|
+
mkdirSync5(path22__default.join(skaileDir, "sessions"), { recursive: true });
|
|
11746
12552
|
created.push(".skaile/");
|
|
11747
12553
|
}
|
|
11748
|
-
const settingsPath =
|
|
11749
|
-
if (!
|
|
11750
|
-
|
|
12554
|
+
const settingsPath = path22__default.join(skaileDir, "settings.json");
|
|
12555
|
+
if (!existsSync21(settingsPath)) {
|
|
12556
|
+
writeFileSync7(settingsPath, "{}\n");
|
|
11751
12557
|
created.push(".skaile/settings.json");
|
|
11752
12558
|
}
|
|
11753
|
-
const wsConfigPath =
|
|
11754
|
-
if (!
|
|
11755
|
-
|
|
12559
|
+
const wsConfigPath = path22__default.join(resolved, "skaile.yaml");
|
|
12560
|
+
if (!existsSync21(wsConfigPath)) {
|
|
12561
|
+
writeFileSync7(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
|
|
11756
12562
|
created.push("skaile.yaml");
|
|
11757
12563
|
}
|
|
11758
12564
|
for (const dir of new Set(Object.values(DRIVER_TARGETS[harness].local))) {
|
|
11759
|
-
const full =
|
|
11760
|
-
if (!
|
|
12565
|
+
const full = path22__default.join(resolved, dir);
|
|
12566
|
+
if (!existsSync21(full)) {
|
|
11761
12567
|
mkdirSync5(full, { recursive: true });
|
|
11762
12568
|
created.push(`${dir}/`);
|
|
11763
12569
|
}
|
|
@@ -11787,10 +12593,13 @@ function buildInitWorkspaceConfig(projectName, harness) {
|
|
|
11787
12593
|
}
|
|
11788
12594
|
async function initGitScaffold(resolved, created) {
|
|
11789
12595
|
const { execSync: execSync2 } = await import('child_process');
|
|
11790
|
-
const { existsSync:
|
|
11791
|
-
const gitignorePath =
|
|
12596
|
+
const { existsSync: existsSync21, readFileSync: readFileSync12, writeFileSync: writeFileSync7 } = await import('fs');
|
|
12597
|
+
const gitignorePath = path22__default.join(resolved, ".gitignore");
|
|
11792
12598
|
const entries = [
|
|
11793
12599
|
"node_modules/",
|
|
12600
|
+
// Python bytecode a deployed skill script leaves inside `.claude/skills` and friends.
|
|
12601
|
+
"__pycache__/",
|
|
12602
|
+
"*.pyc",
|
|
11794
12603
|
".skaile/sessions/",
|
|
11795
12604
|
".skaile/cache/",
|
|
11796
12605
|
// skaile-created artifacts that must never be committed: the per-session log
|
|
@@ -11801,20 +12610,29 @@ async function initGitScaffold(resolved, created) {
|
|
|
11801
12610
|
".skaile/settings.json",
|
|
11802
12611
|
".skaile/providers.yml",
|
|
11803
12612
|
".skaile/history.yaml",
|
|
12613
|
+
// Per-machine files a run writes into the project: the system prompt handed to the harness
|
|
12614
|
+
// (it carries the host path) and omp's session logs.
|
|
12615
|
+
".codex/skaile-session-instructions.md",
|
|
12616
|
+
".omp/system.md",
|
|
12617
|
+
".omp/sessions/",
|
|
12618
|
+
// `skaile integration install` writes the absolute project path into these.
|
|
12619
|
+
".codex/config.toml",
|
|
12620
|
+
".omp/extensions/skaile.ts",
|
|
12621
|
+
".skaile/plugin-state.json",
|
|
11804
12622
|
"*.log",
|
|
11805
12623
|
".env",
|
|
11806
12624
|
".env.local"
|
|
11807
12625
|
];
|
|
11808
|
-
const existing =
|
|
12626
|
+
const existing = existsSync21(gitignorePath) ? readFileSync12(gitignorePath, "utf-8") : "";
|
|
11809
12627
|
const have = new Set(existing.split("\n").map((l) => l.trim()));
|
|
11810
12628
|
const append = entries.filter((e) => !have.has(e));
|
|
11811
12629
|
if (append.length > 0) {
|
|
11812
12630
|
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
11813
|
-
|
|
12631
|
+
writeFileSync7(gitignorePath, `${existing + prefix}${append.join("\n")}
|
|
11814
12632
|
`);
|
|
11815
12633
|
if (!existing) created.push(".gitignore");
|
|
11816
12634
|
}
|
|
11817
|
-
if (!
|
|
12635
|
+
if (!existsSync21(path22__default.join(resolved, ".git"))) {
|
|
11818
12636
|
try {
|
|
11819
12637
|
execSync2("git init", { cwd: resolved, stdio: "pipe" });
|
|
11820
12638
|
created.push(".git/");
|
|
@@ -11826,10 +12644,10 @@ async function initGitScaffold(resolved, created) {
|
|
|
11826
12644
|
}
|
|
11827
12645
|
async function bootstrapUserConfig() {
|
|
11828
12646
|
try {
|
|
11829
|
-
const
|
|
12647
|
+
const fs14 = await import('fs');
|
|
11830
12648
|
const { userConfigPath: userConfigPath2, saveConfig, getConfigDefaults } = await import('../library/index.js');
|
|
11831
12649
|
const userCfgPath = userConfigPath2();
|
|
11832
|
-
if (!
|
|
12650
|
+
if (!fs14.existsSync(userCfgPath)) {
|
|
11833
12651
|
const defaults = getConfigDefaults();
|
|
11834
12652
|
saveConfig(userCfgPath, {
|
|
11835
12653
|
catalog: { url: defaults.catalog.url, cache_ttl: defaults.catalog.cache_ttl }
|
|
@@ -11844,7 +12662,7 @@ async function bootstrapUserConfig() {
|
|
|
11844
12662
|
}
|
|
11845
12663
|
async function hydrateInitSources(resolved, created) {
|
|
11846
12664
|
try {
|
|
11847
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
12665
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-VUKHL65L.js');
|
|
11848
12666
|
const hydrate = ensureSourcesCloned(resolved, { quiet: true });
|
|
11849
12667
|
for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
|
|
11850
12668
|
if (hydrate.failed.length > 0) {
|
|
@@ -11860,7 +12678,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
11860
12678
|
logOk(`Initialized project at ${S.heading(resolved)}`);
|
|
11861
12679
|
console.log();
|
|
11862
12680
|
console.log(S.heading(" Next steps:"));
|
|
11863
|
-
const isCurrentDir = resolved ===
|
|
12681
|
+
const isCurrentDir = resolved === path22__default.resolve(".");
|
|
11864
12682
|
let step = 1;
|
|
11865
12683
|
if (!isCurrentDir) {
|
|
11866
12684
|
console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
|
|
@@ -11884,7 +12702,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
11884
12702
|
console.log();
|
|
11885
12703
|
}
|
|
11886
12704
|
program.command("setup").description("Interactive provider setup wizard").action(async () => {
|
|
11887
|
-
const { cmdSetup } = await import('../setup-
|
|
12705
|
+
const { cmdSetup } = await import('../setup-L632QIHV.js');
|
|
11888
12706
|
await cmdSetup([], { projectDir: process.cwd() });
|
|
11889
12707
|
});
|
|
11890
12708
|
program.addCommand(makeInstallCommand());
|
|
@@ -11972,6 +12790,10 @@ try {
|
|
|
11972
12790
|
await program.parseAsync();
|
|
11973
12791
|
commandSettled = true;
|
|
11974
12792
|
} catch (err2) {
|
|
12793
|
+
if (isIndexBusyError(err2)) {
|
|
12794
|
+
logErr(INDEX_BUSY_MESSAGE);
|
|
12795
|
+
process.exit(1);
|
|
12796
|
+
}
|
|
11975
12797
|
const { LibrarySyncError } = await import('../library/index.js');
|
|
11976
12798
|
if (!(err2 instanceof LibrarySyncError || err2 instanceof SourceEntryError)) throw err2;
|
|
11977
12799
|
logErr(err2.message);
|