@skaile/workspaces 5.10.0 → 5.12.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 +146 -0
- package/README.md +14 -2
- package/dist/{asset-feeds-ELEBTNUS.js → asset-feeds-AM6PSSGM.js} +24 -21
- package/dist/asset-feeds-AM6PSSGM.js.map +1 -0
- package/dist/asset-manager/catalog-deployer.js +8 -8
- package/dist/asset-manager/fragments.js +1 -1
- package/dist/asset-manager/index.js +16 -16
- package/dist/asset-manager/installer.js +11 -11
- package/dist/asset-manager/renderers.js +9 -9
- 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 +197 -11
- 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/install-instances.d.ts.map +1 -1
- package/dist/asset-manager/src/installer.d.ts +33 -3
- 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 +16 -13
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +43 -16
- package/dist/bridge/drivers/codex.js.map +1 -1
- package/dist/bridge/drivers/continue.js +10 -10
- package/dist/bridge/drivers/echo.js +2 -2
- package/dist/bridge/drivers/gemini.js +7 -7
- package/dist/bridge/drivers/goose.js +10 -10
- package/dist/bridge/drivers/omp.js +52 -9
- package/dist/bridge/drivers/omp.js.map +1 -1
- package/dist/bridge/drivers/opencode.js +10 -10
- package/dist/bridge/drivers/qwen.js +7 -7
- package/dist/bridge/index.js +12 -12
- package/dist/bridge/src/codex/config-toml.d.ts +8 -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.map +1 -1
- package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +1 -1
- package/dist/bridge/src/drivers/omp.d.ts +9 -0
- 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-7CR6HT2X.js → chunk-27L6BBAT.js} +9 -9
- package/dist/{chunk-7CR6HT2X.js.map → chunk-27L6BBAT.js.map} +1 -1
- package/dist/{chunk-QG3HOJEK.js → chunk-2JFIFDDO.js} +3 -3
- package/dist/{chunk-QG3HOJEK.js.map → chunk-2JFIFDDO.js.map} +1 -1
- package/dist/{chunk-IJHH4DSW.js → chunk-2X3JBVGD.js} +11 -10
- package/dist/chunk-2X3JBVGD.js.map +1 -0
- package/dist/{chunk-G54USEUP.js → chunk-3HUV2LJF.js} +4 -4
- package/dist/{chunk-G54USEUP.js.map → chunk-3HUV2LJF.js.map} +1 -1
- package/dist/{chunk-JFXQEVLF.js → chunk-3LVB3HGH.js} +3 -3
- package/dist/{chunk-JFXQEVLF.js.map → chunk-3LVB3HGH.js.map} +1 -1
- package/dist/{chunk-32XKCNCL.js → chunk-6VLHITAM.js} +146 -4
- package/dist/chunk-6VLHITAM.js.map +1 -0
- package/dist/{chunk-GEWAIQZ5.js → chunk-7CR2OZPA.js} +10 -12
- package/dist/chunk-7CR2OZPA.js.map +1 -0
- package/dist/{chunk-6HHE63CO.js → chunk-7QWQTA5S.js} +89 -12
- package/dist/chunk-7QWQTA5S.js.map +1 -0
- package/dist/{chunk-7I5VRVDP.js → chunk-7XWUJC3A.js} +4 -4
- package/dist/{chunk-7I5VRVDP.js.map → chunk-7XWUJC3A.js.map} +1 -1
- package/dist/{chunk-3BEY4WK3.js → chunk-C3BMXXTN.js} +203 -31
- package/dist/chunk-C3BMXXTN.js.map +1 -0
- package/dist/{chunk-IXWODEED.js → chunk-CTP3XBMF.js} +47 -8
- package/dist/chunk-CTP3XBMF.js.map +1 -0
- package/dist/{chunk-HOHUEKES.js → chunk-DCHQ6BAZ.js} +3 -3
- package/dist/{chunk-HOHUEKES.js.map → chunk-DCHQ6BAZ.js.map} +1 -1
- 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-3MKPZZRE.js → chunk-G3X4MLDB.js} +3 -3
- package/dist/{chunk-3MKPZZRE.js.map → chunk-G3X4MLDB.js.map} +1 -1
- package/dist/{chunk-SBFW3CJH.js → chunk-GWD3QNVS.js} +5 -5
- package/dist/{chunk-SBFW3CJH.js.map → chunk-GWD3QNVS.js.map} +1 -1
- package/dist/chunk-H5U7LNTJ.js +122 -0
- package/dist/chunk-H5U7LNTJ.js.map +1 -0
- package/dist/{chunk-SX5U422E.js → chunk-HYMERG57.js} +3 -3
- package/dist/{chunk-SX5U422E.js.map → chunk-HYMERG57.js.map} +1 -1
- package/dist/{chunk-V5TZH4GF.js → chunk-ICIYSJBQ.js} +4 -4
- package/dist/{chunk-V5TZH4GF.js.map → chunk-ICIYSJBQ.js.map} +1 -1
- package/dist/{chunk-YBQONMH2.js → chunk-ID745F3R.js} +353 -193
- package/dist/chunk-ID745F3R.js.map +1 -0
- package/dist/{chunk-CLTHEKHR.js → chunk-JQ3DXNQV.js} +4 -4
- package/dist/{chunk-CLTHEKHR.js.map → chunk-JQ3DXNQV.js.map} +1 -1
- package/dist/chunk-K4VOEYOR.js +21 -0
- package/dist/chunk-K4VOEYOR.js.map +1 -0
- package/dist/{chunk-XCNK4UE5.js → chunk-KVSDRB35.js} +5 -5
- package/dist/{chunk-XCNK4UE5.js.map → chunk-KVSDRB35.js.map} +1 -1
- package/dist/{chunk-HJ5MCB3L.js → chunk-MF54ZHWT.js} +20 -3
- package/dist/chunk-MF54ZHWT.js.map +1 -0
- package/dist/{chunk-NRDSGLCQ.js → chunk-N5M2EISA.js} +240 -52
- package/dist/chunk-N5M2EISA.js.map +1 -0
- package/dist/{chunk-OBVJ7RPW.js → chunk-NDF24LYP.js} +3 -3
- package/dist/{chunk-OBVJ7RPW.js.map → chunk-NDF24LYP.js.map} +1 -1
- package/dist/{chunk-ZGQTS3Y4.js → chunk-NGJIVDDD.js} +3 -3
- package/dist/{chunk-ZGQTS3Y4.js.map → chunk-NGJIVDDD.js.map} +1 -1
- package/dist/{chunk-PE36IF2D.js → chunk-NJV5SLEK.js} +159 -44
- package/dist/chunk-NJV5SLEK.js.map +1 -0
- package/dist/{chunk-OOWHXOK6.js → chunk-NJXR5OAM.js} +4 -4
- package/dist/{chunk-OOWHXOK6.js.map → chunk-NJXR5OAM.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-V7PQZOBR.js → chunk-NR7H7ZJP.js} +14 -6
- package/dist/chunk-NR7H7ZJP.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-4P3KTUZH.js → chunk-P23WJCH2.js} +51 -14
- package/dist/chunk-P23WJCH2.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-JZCSNEHK.js → chunk-PNOGX36L.js} +141 -39
- package/dist/chunk-PNOGX36L.js.map +1 -0
- package/dist/{chunk-4OV5DSBB.js → chunk-PNTXHTBC.js} +5 -5
- package/dist/chunk-PNTXHTBC.js.map +1 -0
- package/dist/{chunk-TRSQP3JD.js → chunk-POQ6PGNE.js} +20 -4
- package/dist/chunk-POQ6PGNE.js.map +1 -0
- package/dist/{chunk-Y63UQZ7P.js → chunk-QCEKGYHF.js} +3 -3
- package/dist/{chunk-Y63UQZ7P.js.map → chunk-QCEKGYHF.js.map} +1 -1
- package/dist/{chunk-GFCXNFTW.js → chunk-SHQMPGOL.js} +4 -4
- package/dist/{chunk-GFCXNFTW.js.map → chunk-SHQMPGOL.js.map} +1 -1
- package/dist/{chunk-WBYDAL6X.js → chunk-SMT3LNAG.js} +4 -4
- package/dist/{chunk-WBYDAL6X.js.map → chunk-SMT3LNAG.js.map} +1 -1
- package/dist/{chunk-2FMEGSBN.js → chunk-T5TSLSRO.js} +135 -47
- package/dist/chunk-T5TSLSRO.js.map +1 -0
- package/dist/{chunk-2JMLDZLP.js → chunk-TVAR4JHA.js} +903 -138
- package/dist/chunk-TVAR4JHA.js.map +1 -0
- package/dist/{chunk-MVQ3Q2HM.js → chunk-UTKENBB6.js} +5 -5
- package/dist/{chunk-MVQ3Q2HM.js.map → chunk-UTKENBB6.js.map} +1 -1
- package/dist/{chunk-TH4CTXHX.js → chunk-VRLKHL74.js} +6 -6
- package/dist/{chunk-TH4CTXHX.js.map → chunk-VRLKHL74.js.map} +1 -1
- package/dist/{chunk-Z2K6BGUR.js → chunk-WI4T3KIS.js} +51 -16
- package/dist/chunk-WI4T3KIS.js.map +1 -0
- package/dist/{chunk-MGGFBZWA.js → chunk-X3RMRJNR.js} +6 -4
- package/dist/chunk-X3RMRJNR.js.map +1 -0
- package/dist/{chunk-FRPBSUFH.js → chunk-X6LKA3TJ.js} +5 -5
- package/dist/{chunk-FRPBSUFH.js.map → chunk-X6LKA3TJ.js.map} +1 -1
- package/dist/{chunk-3KHYGOEY.js → chunk-XMAJJPA4.js} +3 -3
- package/dist/{chunk-3KHYGOEY.js.map → chunk-XMAJJPA4.js.map} +1 -1
- package/dist/{chunk-Y34MSWEZ.js → chunk-XTVSNWLL.js} +19 -7
- package/dist/chunk-XTVSNWLL.js.map +1 -0
- package/dist/{chunk-VLXDXRRX.js → chunk-XZY6SBGU.js} +3 -3
- package/dist/{chunk-VLXDXRRX.js.map → chunk-XZY6SBGU.js.map} +1 -1
- package/dist/{chunk-5QI2JYJC.js → chunk-YQU2BPQD.js} +7 -5
- package/dist/chunk-YQU2BPQD.js.map +1 -0
- package/dist/cli/index.js +1207 -580
- 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.d.ts +24 -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-publish.d.ts.map +1 -1
- package/dist/cli/src/commands/manage.d.ts +6 -0
- package/dist/cli/src/commands/manage.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/outdated.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 +1 -1
- package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/project.d.ts +3 -1
- 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 +2 -1
- package/dist/cli/src/commands/run.d.ts.map +1 -1
- package/dist/cli/src/commands/serve-preflight.d.ts +22 -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.map +1 -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.d.ts.map +1 -1
- package/dist/cli/src/commands/why.d.ts +1 -0
- 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/helpers.d.ts +12 -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/paths.d.ts +7 -3
- package/dist/cli/src/plugin-store/paths.d.ts.map +1 -1
- package/dist/cli/src/skill-checks.d.ts +29 -8
- package/dist/cli/src/skill-checks.d.ts.map +1 -1
- package/dist/cli/src/store-addable.d.ts +18 -0
- package/dist/cli/src/store-addable.d.ts.map +1 -0
- package/dist/connectors/config.js +5 -5
- package/dist/connectors/index.js +16 -16
- package/dist/{connectors-OXP2JBGI.js → connectors-UNKUKEPG.js} +19 -19
- package/dist/{connectors-OXP2JBGI.js.map → connectors-UNKUKEPG.js.map} +1 -1
- package/dist/core/index.js +7 -7
- 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 +2 -2
- package/dist/core/ref.js +1 -1
- package/dist/core/runtime-assets.js +5 -5
- package/dist/core/src/index.d.ts +5 -4
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/lock.d.ts +19 -8
- 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 +5 -0
- package/dist/core/src/manifest.d.ts.map +1 -1
- package/dist/core/src/models.d.ts +4 -4
- 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 +11 -1
- package/dist/core/src/publish-manifest.d.ts.map +1 -1
- package/dist/core/src/repo-manager.d.ts +11 -0
- package/dist/core/src/repo-manager.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/walker.d.ts +6 -1
- package/dist/core/src/walker.d.ts.map +1 -1
- package/dist/core/src/workspace-config.d.ts +4 -1
- package/dist/core/src/workspace-config.d.ts.map +1 -1
- package/dist/core/workspace-config.js +4 -4
- package/dist/deploy/index.js +7 -7
- package/dist/discovery/index.js +5 -5
- package/dist/discovery/src/source-config.d.ts.map +1 -1
- package/dist/{ensure-sources-5ISVIA4T.js → ensure-sources-POMEQSTM.js} +19 -19
- package/dist/{ensure-sources-5ISVIA4T.js.map → ensure-sources-POMEQSTM.js.map} +1 -1
- package/dist/factory-assets/connectors/box.js +16 -16
- package/dist/factory-assets/connectors/deploy.js +16 -16
- package/dist/factory-assets/connectors/devserver.js +16 -16
- package/dist/factory-assets/connectors/flow/adapter.js +16 -16
- package/dist/factory-assets/connectors/flow/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 +9 -9
- package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/run-flow.js +18 -18
- package/dist/factory-assets/connectors/flow.js +16 -16
- package/dist/factory-assets/connectors/git.js +16 -16
- package/dist/factory-assets/connectors/gmail.js +16 -16
- package/dist/factory-assets/connectors/googledrive.js +16 -16
- package/dist/factory-assets/connectors/local.js +16 -16
- package/dist/factory-assets/connectors/mattermost.js +16 -16
- package/dist/factory-assets/connectors/memory.js +16 -16
- package/dist/factory-assets/connectors/minio.js +16 -16
- package/dist/factory-assets/connectors/postgres.js +16 -16
- package/dist/factory-assets/connectors/s3.js +16 -16
- package/dist/factory-assets/connectors/sharepoint.js +16 -16
- package/dist/factory-assets/connectors/sqlite.js +16 -16
- package/dist/factory-assets/connectors/static-server.js +16 -16
- package/dist/factory-assets/connectors/tunnel.js +16 -16
- package/dist/factory-assets/connectors/webdav.js +16 -16
- package/dist/factory-assets/connectors/xstate-store.js +16 -16
- package/dist/factory-assets/connectors/xstate.js +16 -16
- package/dist/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 +16 -11
- package/dist/factory-assets/skills/skaile-author-asset/SKILL.md +2 -2
- package/dist/{flows-HMSE76PO.js → flows-DVKMZKM4.js} +12 -12
- package/dist/{flows-HMSE76PO.js.map → flows-DVKMZKM4.js.map} +1 -1
- package/dist/{helpers-X6URBGSF.js → helpers-Y4OT7VIS.js} +19 -19
- package/dist/{helpers-X6URBGSF.js.map → helpers-Y4OT7VIS.js.map} +1 -1
- package/dist/library/index.js +12 -12
- package/dist/library/install.js +4 -4
- package/dist/library/src/index.d.ts +3 -3
- 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-dir.d.ts +26 -0
- package/dist/library/src/local/library-dir.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.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.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 +2 -0
- package/dist/library/src/sync/git-driver.d.ts.map +1 -1
- package/dist/{library-publish-OS3JDW4S.js → library-publish-DI4Q5UOG.js} +73 -38
- package/dist/library-publish-DI4Q5UOG.js.map +1 -0
- package/dist/open-library-N6ESO6IK.js +40 -0
- package/dist/{open-library-4QSUORI6.js.map → open-library-N6ESO6IK.js.map} +1 -1
- package/dist/open-registry-CBZ5MWTT.js +32 -0
- package/dist/{open-registry-VCKS3MP5.js.map → open-registry-CBZ5MWTT.js.map} +1 -1
- package/dist/paths-U6W6MQNQ.js +22 -0
- package/dist/{paths-BVO56A25.js.map → paths-U6W6MQNQ.js.map} +1 -1
- package/dist/{plugin-store-X7GPWGBG.js → plugin-store-XMZSPVBF.js} +48 -12
- package/dist/plugin-store-XMZSPVBF.js.map +1 -0
- package/dist/project-UP52HEHC.js +79 -0
- package/dist/{project-PAXP46RD.js.map → project-UP52HEHC.js.map} +1 -1
- package/dist/resolver/index.js +8 -8
- package/dist/runner/index.js +33 -33
- 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 +1 -0
- package/dist/runner/src/composition/index.d.ts.map +1 -1
- package/dist/runner/src/composition/prompt-sections.d.ts +7 -4
- 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/usage-limit-turn-hold.d.ts +51 -0
- package/dist/runner/src/usage-limit-turn-hold.d.ts.map +1 -0
- package/dist/sdk/asset-manager.js +16 -16
- package/dist/sdk/bridge.js +12 -12
- package/dist/sdk/core.js +7 -7
- package/dist/sdk/flow.js +9 -9
- package/dist/sdk/index.js +36 -34
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/resolver.js +8 -8
- package/dist/sdk/runner.js +33 -33
- 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-6P2JJEJ3.js +47 -0
- package/dist/serve-preflight-6P2JJEJ3.js.map +1 -0
- package/dist/{setup-BV55VHWC.js → setup-5IRUH5OS.js} +24 -24
- package/dist/{setup-BV55VHWC.js.map → setup-5IRUH5OS.js.map} +1 -1
- package/dist/{skills-EDFUCJPX.js → skills-HA36RFNM.js} +13 -13
- package/dist/{skills-EDFUCJPX.js.map → skills-HA36RFNM.js.map} +1 -1
- package/dist/source-DX5SGWEI.js +41 -0
- package/dist/{source-E4VAT5RZ.js.map → source-DX5SGWEI.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-CLEE6TNH.js → source-manifest-publish-NMRLXWVW.js} +27 -26
- package/dist/source-manifest-publish-NMRLXWVW.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 +89 -52
- 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/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 +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +23 -23
- 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-ELEBTNUS.js.map +0 -1
- package/dist/chunk-2FMEGSBN.js.map +0 -1
- package/dist/chunk-2JMLDZLP.js.map +0 -1
- package/dist/chunk-32XKCNCL.js.map +0 -1
- package/dist/chunk-3BEY4WK3.js.map +0 -1
- package/dist/chunk-4OV5DSBB.js.map +0 -1
- package/dist/chunk-4P3KTUZH.js.map +0 -1
- package/dist/chunk-5LKOAX7I.js.map +0 -1
- package/dist/chunk-5QI2JYJC.js.map +0 -1
- package/dist/chunk-6HHE63CO.js.map +0 -1
- package/dist/chunk-CGYEHQOX.js.map +0 -1
- package/dist/chunk-GEWAIQZ5.js.map +0 -1
- package/dist/chunk-HJ5MCB3L.js.map +0 -1
- package/dist/chunk-IJHH4DSW.js.map +0 -1
- package/dist/chunk-IXWODEED.js.map +0 -1
- package/dist/chunk-JZCSNEHK.js.map +0 -1
- package/dist/chunk-MGGFBZWA.js.map +0 -1
- package/dist/chunk-NRDSGLCQ.js.map +0 -1
- package/dist/chunk-NWDSLXOX.js.map +0 -1
- package/dist/chunk-OBYKJB4U.js.map +0 -1
- package/dist/chunk-PE36IF2D.js.map +0 -1
- package/dist/chunk-R7FOF242.js +0 -59
- package/dist/chunk-R7FOF242.js.map +0 -1
- package/dist/chunk-TRSQP3JD.js.map +0 -1
- package/dist/chunk-V7PQZOBR.js.map +0 -1
- package/dist/chunk-Y34MSWEZ.js.map +0 -1
- package/dist/chunk-YBQONMH2.js.map +0 -1
- package/dist/chunk-Z2K6BGUR.js.map +0 -1
- package/dist/library-publish-OS3JDW4S.js.map +0 -1
- package/dist/open-library-4QSUORI6.js +0 -40
- package/dist/open-registry-VCKS3MP5.js +0 -32
- package/dist/paths-BVO56A25.js +0 -22
- package/dist/plugin-store-X7GPWGBG.js.map +0 -1
- package/dist/project-PAXP46RD.js +0 -41
- package/dist/source-E4VAT5RZ.js +0 -41
- package/dist/source-fetch-github-QN4LLTL5.js +0 -4
- package/dist/source-manifest-publish-CLEE6TNH.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,98 +1,100 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-
|
|
3
|
-
import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-
|
|
4
|
-
import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportReplaced, reportRelocked, REF_HINT, reportInstalledSoftDeps } from '../chunk-
|
|
2
|
+
import { makeProvidersCommand, loadRegistryView, addProviderEntry, ProviderRegistryWriteError } from '../chunk-KVSDRB35.js';
|
|
3
|
+
import { makeSourceCommand, syncProjectSources, divergedSourceClones } from '../chunk-WI4T3KIS.js';
|
|
4
|
+
import { makeInstallCommand, makeCheckCommand, makeCleanCommand, reportReplaced, reportRelocked, reportMoved, REF_HINT, reportInstalledSoftDeps } from '../chunk-P23WJCH2.js';
|
|
5
5
|
import { createSpinner } from '../chunk-NESV47MF.js';
|
|
6
|
-
import { AI_RESOURCES } from '../chunk-
|
|
7
|
-
import { unresolvedManifestDependencies, warnIgnoredDomainFiles, warnLegacyBundleFiles, removedDomainOption, rejectRemovedDomainOption, resolveLibraryPublisherDetailed, warnLibraryNameFallback, indexLibrary, requireValidPublisherOrExit, exitOnManifestPublisherProblems, registerLibraryAsset, DOMAIN_REMOVED_HINT, manifestPublisherProblems, manifestRequiresProblems, findAssetManifestFile, declaredVersion, checkAssetFile, duplicateAssetMessage, readAssetBody,
|
|
8
|
-
import { getStoreConfig, storeFetch, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, isStoreAuthenticated, getStoreToken, getStoreIdentity, assetEntryRef, manifestVersionMismatchMessage } from '../chunk-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
6
|
+
import { AI_RESOURCES } from '../chunk-SMT3LNAG.js';
|
|
7
|
+
import { unresolvedManifestDependencies, warnIgnoredDomainFiles, warnLegacyBundleFiles, removedDomainOption, rejectRemovedDomainOption, resolveLibraryPublisherDetailed, warnLibraryNameFallback, indexLibrary, requireValidPublisherOrExit, exitOnManifestPublisherProblems, registerLibraryAsset, DOMAIN_REMOVED_HINT, checkAsset, agentComposeRefAdvisories, manifestPublisherProblems, manifestRequiresProblems, findAssetManifestFile, declaredVersion, checkAssetFile, duplicateAssetMessage, readAssetBody, checkAgentFiles, invalidSemverText } from '../chunk-ID745F3R.js';
|
|
8
|
+
import { getStoreConfig, storeFetch, deviceLogin, loadStoreAuthConfig, logout, hasStoredAuth, isStoreAuthenticated, getStoreToken, getStoreIdentity, assetEntryRef, manifestVersionMismatchMessage } from '../chunk-NR7H7ZJP.js';
|
|
9
|
+
import { storeNotInstallableReason, STORE_UNADDABLE_KINDS } from '../chunk-K4VOEYOR.js';
|
|
10
|
+
import { openCatalogSource, LocalCatalogDisabledError, openLibraryManager, openLibrary } from '../chunk-JQ3DXNQV.js';
|
|
11
|
+
import { logErr, S, logOk, logInfo, logWarn, TARGET_DEFAULT_HINT, requireProjectConfig, deferredWarnings, warnLegacyClaudeCopies, kindColorPad, kindColor, colorRef, formatSoftDepSection, bareSoftDepName, formatSoftDepHint, formatRelativeTime, formatSoftDepRemovePreview, formatSoftDepAddPreview, fitWidth, KIND_COL_WIDTH } from '../chunk-POQ6PGNE.js';
|
|
12
|
+
import { getKindRegistry, getKnownKinds } from '../chunk-GWD3QNVS.js';
|
|
12
13
|
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-
|
|
14
|
+
import { runAgentChat, isCompositionError, loadSessionById, loadSession, listSessions, setCurrentSession, deleteSession, clearSession, loadAgentManifest, hashAgentFiles, createCompositionContentSource, compileComposition, instanceForSession, resolveAgentInstance, describeComposition, MarkdownStreamer, createFinalTextFallback } from '../chunk-N5M2EISA.js';
|
|
15
|
+
import { buildClaudePluginFiles } from '../chunk-YQU2BPQD.js';
|
|
16
|
+
import '../chunk-X6LKA3TJ.js';
|
|
17
|
+
import '../chunk-HYMERG57.js';
|
|
17
18
|
import '../chunk-R6O6YWU7.js';
|
|
18
|
-
import '../chunk-
|
|
19
|
-
import '../chunk-
|
|
19
|
+
import '../chunk-3HUV2LJF.js';
|
|
20
|
+
import '../chunk-QCEKGYHF.js';
|
|
20
21
|
import '../chunk-4ZTPYIBE.js';
|
|
21
|
-
import '../chunk-
|
|
22
|
+
import '../chunk-XZY6SBGU.js';
|
|
22
23
|
import '../chunk-X5YPJV4N.js';
|
|
23
24
|
import '../chunk-O7SG5PC2.js';
|
|
24
25
|
import '../chunk-7QBNJTTQ.js';
|
|
25
|
-
import '../chunk-
|
|
26
|
-
import '../chunk-
|
|
26
|
+
import '../chunk-O2SYFJWP.js';
|
|
27
|
+
import '../chunk-OQ5MKDS3.js';
|
|
27
28
|
import '../chunk-32NA4TVC.js';
|
|
28
29
|
import '../chunk-W3UDISS2.js';
|
|
29
|
-
import '../chunk-
|
|
30
|
-
import { runFlow, resumeFlow } from '../chunk-
|
|
30
|
+
import '../chunk-PHRNUTSG.js';
|
|
31
|
+
import { runFlow, resumeFlow } from '../chunk-2X3JBVGD.js';
|
|
31
32
|
import '../chunk-4R6DROGN.js';
|
|
32
|
-
import { validateFlowVersions } from '../chunk-
|
|
33
|
-
import '../chunk-
|
|
33
|
+
import { parseSkillRequirements, validateRequirements, validateFlowVersions } from '../chunk-G3X4MLDB.js';
|
|
34
|
+
import '../chunk-DCHQ6BAZ.js';
|
|
34
35
|
import '../chunk-ISHJITXJ.js';
|
|
35
|
-
import '../chunk-
|
|
36
|
+
import '../chunk-27L6BBAT.js';
|
|
36
37
|
import '../chunk-X4BAYGMT.js';
|
|
37
|
-
import '../chunk-
|
|
38
|
-
import '../chunk-
|
|
39
|
-
import '../chunk-
|
|
38
|
+
import '../chunk-ICIYSJBQ.js';
|
|
39
|
+
import '../chunk-NDF24LYP.js';
|
|
40
|
+
import '../chunk-2JFIFDDO.js';
|
|
40
41
|
import '../chunk-LOO5CB5M.js';
|
|
41
42
|
import '../chunk-2H73V6XR.js';
|
|
42
|
-
import '../chunk-
|
|
43
|
+
import '../chunk-NJXR5OAM.js';
|
|
43
44
|
import '../chunk-B4X2N7JQ.js';
|
|
44
45
|
import '../chunk-YROR332M.js';
|
|
45
|
-
import { getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-
|
|
46
|
+
import { listDrivers, getProviderPreset, AI_PROVIDER_PRESETS } from '../chunk-MF54ZHWT.js';
|
|
46
47
|
import '../chunk-6E6PKKAD.js';
|
|
47
48
|
import '../chunk-IFGTRL2I.js';
|
|
48
|
-
import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-
|
|
49
|
+
import { projectAiAssetsRoots, loadFlow, loadAllFlowEntries, findFlowFileInRoots } from '../chunk-7XWUJC3A.js';
|
|
49
50
|
import '../chunk-LNFKL23K.js';
|
|
50
|
-
import '../chunk-
|
|
51
|
+
import '../chunk-X3RMRJNR.js';
|
|
51
52
|
import '../chunk-M3WPBTGJ.js';
|
|
52
53
|
import { nodeLabel, nodeSkillAsset, nodeIsInert, nodeIsOptional, nodeRunKind, flowSkillVersionPins } from '../chunk-7RGTAEG6.js';
|
|
53
54
|
import '../chunk-NUELZWCF.js';
|
|
54
55
|
import '../chunk-F4NJDSR7.js';
|
|
55
|
-
import { AssetManager, MissingManifestError, parseRefTolerant, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-
|
|
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-
|
|
56
|
+
import { AssetManager, MissingManifestError, parseRefTolerant, normalizeRepoUrl, FACTORY_SOURCE_URL } from '../chunk-TVAR4JHA.js';
|
|
57
|
+
import { libraryDirMissing, missingLibraryDirMessage, cloneOrInitGitRepo, trackOriginBranch, stampManifestPublisher, isGitRepo, ensureGitRepo, conflictingAssetRoot, setManifestPublisher, LIBRARY_OWNERSHIPS, assertManifestEditable, installLibraryAsset, missingRootAssets, getStoreManifestsDir, assertValidLibraryName, syncManifestWithDisk, getDefaultValue, isSecretPlaceholder } from '../chunk-C3BMXXTN.js';
|
|
58
|
+
import { parseManifestFile, SEMVER_RE } from '../chunk-7CR2OZPA.js';
|
|
59
|
+
import '../chunk-UTKENBB6.js';
|
|
60
|
+
import '../chunk-H5U7LNTJ.js';
|
|
60
61
|
import '../chunk-3TXEJN4W.js';
|
|
61
|
-
import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-
|
|
62
|
-
import '../chunk-
|
|
62
|
+
import { installTargetOf, SCAFFOLD_KINDS } from '../chunk-NJV5SLEK.js';
|
|
63
|
+
import '../chunk-NOA6EJXE.js';
|
|
63
64
|
import '../chunk-KTBKW2FI.js';
|
|
64
65
|
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, readLock, aiResourceRoots, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile } from '../chunk-
|
|
66
|
+
import '../chunk-7QWQTA5S.js';
|
|
67
|
+
import { effectiveComposes, validatePreset, composeSlotDiagnostics, agentDeprecationDiagnostics, validateAgent, SLOT_ID_PATTERN } from '../chunk-6VLHITAM.js';
|
|
68
|
+
import { resolveSettings, globalSettingsPath, projectSettingsPath, loadSettings, saveSettings, WorkspaceYamlEditor, resolveLibraryDir, checkAgentSkillConformance, resolveSettingsWithSources, globalInstallDir, GLOBAL_INSTALL_DIR_NAME, readLock, aiResourceRoots, workspaceProviderRegistryPath, userProviderRegistryPath, loadProviderRegistryFile } from '../chunk-T5TSLSRO.js';
|
|
68
69
|
import '../chunk-4GY63JU6.js';
|
|
69
|
-
import { factoryAssetRoots } from '../chunk-
|
|
70
|
-
import '../chunk-PMECEZK3.js';
|
|
70
|
+
import { factoryAssetRoots } from '../chunk-SHQMPGOL.js';
|
|
71
|
+
import { deployedDir } from '../chunk-PMECEZK3.js';
|
|
71
72
|
import { DEFAULT_DRIVER_ID, DRIVER_DEFAULTS } from '../chunk-5BEFNLOR.js';
|
|
72
73
|
import { findKindDirs } from '../chunk-A2ULN3KX.js';
|
|
73
|
-
import { SourceEntryError,
|
|
74
|
+
import { SourceEntryError, resolveSkWorkspaceConfig, sourceCacheKey, getGlobalCacheDir, resolveAgentDir, AgentRefResolutionError, resolveAgentDefinitionDir, decodeSkaileYaml, matchPin, coerceVersion, loadSkWorkspaceConfig, normalizeAgentInstances, agentInstanceDiagnostics, storeManifestSlug, isWorkspaceConfigFilename } from '../chunk-PNOGX36L.js';
|
|
74
75
|
import { globalCacheRoot, globalSkaileDir, userConfigPath } from '../chunk-L5VSIPQD.js';
|
|
75
76
|
import { SUPPORTED_DRIVER_TARGETS, driverTargetForDriver } from '../chunk-CPSIPIX7.js';
|
|
76
|
-
import { SKAILE_MANIFEST_FILENAME, decodeSkaileManifest,
|
|
77
|
+
import { SKAILE_MANIFEST_FILENAME, loadSkPublishManifest, decodeSkaileManifest, isNonAssetPath, isNonAssetDir, encodeSkaileManifest } from '../chunk-CTP3XBMF.js';
|
|
77
78
|
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-
|
|
79
|
+
import { dedupeRequirements, parseFrontmatter, scanDirectory, parseRequires } from '../chunk-XTVSNWLL.js';
|
|
80
|
+
import { parseAssetRef, isValidPublisher, PUBLISHER_HINT, isValidAssetName, ASSET_NAME_HINT, depToStr, slugifyAssetName, parseAssetRefLoose, assetRefToStr } from '../chunk-PNTXHTBC.js';
|
|
80
81
|
import { portableSpawn, portableSpawnSync } from '../chunk-ICSCSM5D.js';
|
|
81
|
-
import { openSqlite } from '../chunk-
|
|
82
|
+
import { openSqlite } from '../chunk-DKXNKFKP.js';
|
|
82
83
|
import { parseModelRef, resolveEntryBaseUrl } from '../chunk-MJHSLODD.js';
|
|
83
84
|
import '../chunk-C3CAXQMA.js';
|
|
84
|
-
import '../chunk-BOFL7GIF.js';
|
|
85
|
+
import { registerLogStore, LogStore, StdoutSink } from '../chunk-BOFL7GIF.js';
|
|
85
86
|
import '../chunk-NSBPE2FW.js';
|
|
86
87
|
import * as fs8 from 'fs';
|
|
87
88
|
import fs8__default, { readFileSync, existsSync, mkdirSync, writeFileSync, lstatSync, rmSync, readdirSync, statSync } from 'fs';
|
|
88
|
-
import * as
|
|
89
|
-
import
|
|
89
|
+
import * as path22 from 'path';
|
|
90
|
+
import path22__default, { resolve, join } from 'path';
|
|
90
91
|
import { fileURLToPath } from 'url';
|
|
91
92
|
import { Help, Command, Option } from 'commander';
|
|
92
93
|
import { rcompare } from 'semver';
|
|
94
|
+
import * as os from 'os';
|
|
95
|
+
import { homedir } from 'os';
|
|
93
96
|
import * as p4 from '@clack/prompts';
|
|
94
97
|
import pc5 from 'picocolors';
|
|
95
|
-
import * as os from 'os';
|
|
96
98
|
import { parse, stringify, parseDocument, isMap, isScalar, isSeq } from 'yaml';
|
|
97
99
|
import * as readline from 'readline';
|
|
98
100
|
import { createInterface } from 'readline';
|
|
@@ -128,6 +130,45 @@ function filterCatalogAssets(assets, query) {
|
|
|
128
130
|
(a) => a.name.toLowerCase().includes(q) || (a.description?.toLowerCase().includes(q) ?? false) || a.publisher.toLowerCase().includes(q)
|
|
129
131
|
);
|
|
130
132
|
}
|
|
133
|
+
var STORE_TEST_NAME_RE = /^(test|demo)(-|$)/;
|
|
134
|
+
var STORE_ROW_LIMIT = 20;
|
|
135
|
+
function selectStoreRows(matches, query, all) {
|
|
136
|
+
const q = query?.toLowerCase();
|
|
137
|
+
const rank = (a) => {
|
|
138
|
+
if (!q) return 3;
|
|
139
|
+
const n = a.name.toLowerCase();
|
|
140
|
+
if (n === q) return 0;
|
|
141
|
+
if (n.startsWith(q)) return 1;
|
|
142
|
+
if (n.includes(q)) return 2;
|
|
143
|
+
return 3;
|
|
144
|
+
};
|
|
145
|
+
const ranked = [...matches].sort(
|
|
146
|
+
(a, b) => rank(a) - rank(b) || a.name.localeCompare(b.name) || a.version.localeCompare(b.version)
|
|
147
|
+
);
|
|
148
|
+
if (all) return { shown: ranked, hidden: 0, cut: 0 };
|
|
149
|
+
const keep = ranked.filter(
|
|
150
|
+
(a) => storeNotInstallableReason(a) === void 0 && !STORE_TEST_NAME_RE.test(a.name)
|
|
151
|
+
);
|
|
152
|
+
return {
|
|
153
|
+
shown: keep.slice(0, STORE_ROW_LIMIT),
|
|
154
|
+
hidden: ranked.length - keep.length,
|
|
155
|
+
cut: Math.max(0, keep.length - STORE_ROW_LIMIT)
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function storeSelectionNotes(sel, indent) {
|
|
159
|
+
const notes = [];
|
|
160
|
+
if (sel.cut > 0) {
|
|
161
|
+
notes.push(
|
|
162
|
+
`${indent}${S.dim(`\u2026 ${sel.cut} more store match(es); narrow the query, or pass --all to list every one`)}`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
if (sel.hidden > 0) {
|
|
166
|
+
notes.push(
|
|
167
|
+
`${indent}${S.dim(`${sel.hidden} store entr${sel.hidden === 1 ? "y" : "ies"} hidden: kinds \`add\` cannot install yet (${[...STORE_UNADDABLE_KINDS].join(", ")}), names that are not valid refs, test/demo entries; --all lists them`)}`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return notes;
|
|
171
|
+
}
|
|
131
172
|
function nearAssetKind(word) {
|
|
132
173
|
const w = word.toLowerCase();
|
|
133
174
|
let best;
|
|
@@ -175,7 +216,7 @@ async function runSearch(kind, query, opts) {
|
|
|
175
216
|
const showLocal = !opts.store;
|
|
176
217
|
const showStore = !opts.local;
|
|
177
218
|
const { resolveConfig } = await import('../library/index.js');
|
|
178
|
-
const airGapped = resolveConfig({ projectDir:
|
|
219
|
+
const airGapped = resolveConfig({ projectDir: path22__default.resolve(opts.projectDir) }).catalog.cache_ttl === 0;
|
|
179
220
|
if (showLocal) {
|
|
180
221
|
await searchLocal(query, kind, opts, showStore, airGapped);
|
|
181
222
|
}
|
|
@@ -184,7 +225,7 @@ async function runSearch(kind, query, opts) {
|
|
|
184
225
|
}
|
|
185
226
|
}
|
|
186
227
|
async function searchIndex(query, kind) {
|
|
187
|
-
const { openLibrary: openLibrary2 } = await import('../open-library-
|
|
228
|
+
const { openLibrary: openLibrary2 } = await import('../open-library-N6ESO6IK.js');
|
|
188
229
|
const library = await openLibrary2();
|
|
189
230
|
try {
|
|
190
231
|
const { libraryDirMissing: libraryDirMissing2 } = await import('../library/index.js');
|
|
@@ -221,7 +262,7 @@ async function searchIndex(query, kind) {
|
|
|
221
262
|
}
|
|
222
263
|
}
|
|
223
264
|
async function searchFactory(projectDir, query, kind) {
|
|
224
|
-
const prefixes = factoryAssetRoots().map((r) => r.endsWith(
|
|
265
|
+
const prefixes = factoryAssetRoots().map((r) => r.endsWith(path22__default.sep) ? r : r + path22__default.sep);
|
|
225
266
|
const isFactoryPath = (p6) => prefixes.some((fp) => p6 === fp.slice(0, -1) || p6.startsWith(fp));
|
|
226
267
|
try {
|
|
227
268
|
const entries = await new AssetManager({ registry: getKindRegistry(), projectDir }).search(
|
|
@@ -331,11 +372,11 @@ async function expandCompetingOrigins(entries, projectDir) {
|
|
|
331
372
|
return out;
|
|
332
373
|
}
|
|
333
374
|
async function searchLocal(query, kind, opts, showStore, airGapped) {
|
|
334
|
-
const projectDir =
|
|
375
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
335
376
|
const factory = await searchFactory(projectDir, query, kind);
|
|
336
377
|
let entries = unionEntries(await searchIndex(query, kind), factory);
|
|
337
378
|
if (entries.length === 0 && !query && !kind && !airGapped) {
|
|
338
|
-
const { autoSyncForSearch } = await import('../source-
|
|
379
|
+
const { autoSyncForSearch } = await import('../source-DX5SGWEI.js');
|
|
339
380
|
if (await autoSyncForSearch(projectDir)) {
|
|
340
381
|
entries = unionEntries(await searchIndex(query, kind), factory);
|
|
341
382
|
}
|
|
@@ -455,24 +496,26 @@ async function searchStore(query, kind, opts, airGapped) {
|
|
|
455
496
|
logInfo("air-gapped (cache_ttl: 0) \u2014 local sources only");
|
|
456
497
|
return;
|
|
457
498
|
}
|
|
458
|
-
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-
|
|
499
|
+
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-N6ESO6IK.js');
|
|
459
500
|
try {
|
|
460
|
-
const remote = await openCatalogSource2({ projectDir:
|
|
501
|
+
const remote = await openCatalogSource2({ projectDir: path22__default.resolve(opts.projectDir) });
|
|
461
502
|
const assets = await remote.listAssets(kind ? { kind } : {});
|
|
462
|
-
const
|
|
463
|
-
if (
|
|
503
|
+
const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
|
|
504
|
+
if (sel.shown.length > 0) {
|
|
464
505
|
console.log(`
|
|
465
506
|
${S.heading("Store:")}`);
|
|
466
|
-
for (const row of formatStoreRows(
|
|
507
|
+
for (const row of formatStoreRows(sel.shown, " ")) console.log(row);
|
|
467
508
|
} else if (opts.store) {
|
|
468
509
|
logInfo("No results in store");
|
|
469
510
|
}
|
|
511
|
+
for (const note of storeSelectionNotes(sel, " ")) console.log(note);
|
|
470
512
|
} catch (e) {
|
|
471
513
|
const local = e instanceof LocalCatalogDisabledError2;
|
|
472
514
|
if (opts.store) {
|
|
473
515
|
logErr(
|
|
474
|
-
local ? "remote catalog disabled (catalog.url: local) \u2014 set catalog.url: https://skaile.store to search the store" : `Store search failed: ${e.
|
|
516
|
+
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
517
|
);
|
|
518
|
+
process.exit(1);
|
|
476
519
|
} else {
|
|
477
520
|
logInfo(
|
|
478
521
|
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 +523,16 @@ async function searchStore(query, kind, opts, airGapped) {
|
|
|
480
523
|
}
|
|
481
524
|
}
|
|
482
525
|
}
|
|
526
|
+
async function describeStoreFailure(err2, projectDir) {
|
|
527
|
+
const { resolveConfig, describeCatalogError } = await import('../library/index.js');
|
|
528
|
+
const url = resolveConfig({ projectDir }).catalog.url;
|
|
529
|
+
return `${describeCatalogError(err2, url)}. Check the catalog with \`skaile catalog test\`.`;
|
|
530
|
+
}
|
|
483
531
|
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").
|
|
532
|
+
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(
|
|
533
|
+
"--all",
|
|
534
|
+
`Store leg: list every match (default: ${STORE_ROW_LIMIT} rows, only what add can install)`
|
|
535
|
+
).action(async (kind, query, opts) => {
|
|
485
536
|
await runSearch(kind, query, opts);
|
|
486
537
|
});
|
|
487
538
|
}
|
|
@@ -578,17 +629,11 @@ function makeAddCommand() {
|
|
|
578
629
|
process.exit(1);
|
|
579
630
|
}
|
|
580
631
|
const harnesses = parseHarnessFilter(opts.harness);
|
|
581
|
-
if (!opts.global && harnesses === void 0)
|
|
582
|
-
const projectDir = path18__default.resolve(opts.projectDir);
|
|
583
|
-
if (!existsSync(path18__default.join(projectDir, SKAILE_YAML_DEFAULT))) {
|
|
584
|
-
logErr(`No ${S.cmd("skaile.yaml")} found. Run ${S.cmd("skaile init")} to create one.`);
|
|
585
|
-
process.exit(1);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
632
|
+
if (!opts.global && harnesses === void 0) requireProjectConfig(opts.projectDir);
|
|
588
633
|
const warnings = deferredWarnings();
|
|
589
634
|
const am2 = new AssetManager({
|
|
590
635
|
registry: getKindRegistry(),
|
|
591
|
-
projectDir:
|
|
636
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
592
637
|
global: opts.global || harnesses !== void 0,
|
|
593
638
|
harnesses,
|
|
594
639
|
driverTarget: opts.target,
|
|
@@ -600,9 +645,11 @@ function makeAddCommand() {
|
|
|
600
645
|
const libraryOf = /* @__PURE__ */ new Map();
|
|
601
646
|
let presets = [];
|
|
602
647
|
const skippedLinks = /* @__PURE__ */ new Set();
|
|
648
|
+
const skippedEnv = /* @__PURE__ */ new Set();
|
|
603
649
|
const added = await am2.add(ref, {
|
|
604
650
|
link: opts.link,
|
|
605
651
|
onLibraryOrigin: (deployedRef, library) => libraryOf.set(deployedRef, library),
|
|
652
|
+
onLibraryMoved: (m) => warnings.push(`${m.ref} moved from ${m.from} to ${m.to}`),
|
|
606
653
|
onPresets: (expanded) => {
|
|
607
654
|
presets = expanded;
|
|
608
655
|
},
|
|
@@ -611,6 +658,14 @@ function makeAddCommand() {
|
|
|
611
658
|
if (skippedLinks.has(linkPath)) return;
|
|
612
659
|
skippedLinks.add(linkPath);
|
|
613
660
|
warnings.push(`skipped symlink ${linkPath}`);
|
|
661
|
+
},
|
|
662
|
+
// A `.env` in an asset root is never deployed or hashed: say so once per file.
|
|
663
|
+
onEnvFile: (_assetRef, envPath) => {
|
|
664
|
+
if (skippedEnv.has(envPath)) return;
|
|
665
|
+
skippedEnv.add(envPath);
|
|
666
|
+
warnings.push(
|
|
667
|
+
`${envPath} is a .env file: it is not deployed or hashed with the asset. Keep secrets out of an asset root`
|
|
668
|
+
);
|
|
614
669
|
}
|
|
615
670
|
});
|
|
616
671
|
spinner.stop("Done");
|
|
@@ -640,6 +695,20 @@ function makeAddCommand() {
|
|
|
640
695
|
const library = libraryOf.get(a);
|
|
641
696
|
logOk(library ? `${a} (library ${library})` : a);
|
|
642
697
|
}
|
|
698
|
+
if (am2.global) {
|
|
699
|
+
for (const a of added) {
|
|
700
|
+
const { kind, name } = parseAssetRef(a);
|
|
701
|
+
const component = installTargetOf(getKindRegistry(), kind);
|
|
702
|
+
if (!component) continue;
|
|
703
|
+
for (const harness of am2.deployTargets()) {
|
|
704
|
+
const dir = deployedDir(component, name, harness, true);
|
|
705
|
+
if (existsSync(dir)) logInfo(S.dim(`${harness}: ${dir.replace(homedir(), "~")}`));
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
if (added.length > 1) {
|
|
710
|
+
logInfo(S.dim(`${added.length} assets deployed (${ref} and ${added.length - 1} more)`));
|
|
711
|
+
}
|
|
643
712
|
}
|
|
644
713
|
const addOrigins = await competingOriginsOf(am2, ref);
|
|
645
714
|
if (addOrigins) {
|
|
@@ -665,9 +734,11 @@ function makeRemoveCommand() {
|
|
|
665
734
|
"Comma-separated global harnesses to undeploy from (default: all resolved); implies --global"
|
|
666
735
|
).option("--target <agent>", `Driver target (${TARGET_DEFAULT_HINT})`).option("--force", "Remove even when another installed asset requires it").option("--no-soft-deps", "skip the orphaned-soft-dep prompt (don't remove, don't report)").action(async (ref, opts) => {
|
|
667
736
|
const harnesses = parseHarnessFilter(opts.harness);
|
|
737
|
+
if (!opts.global && harnesses === void 0)
|
|
738
|
+
requireProjectConfig(opts.projectDir, { allowMissing: true });
|
|
668
739
|
const am2 = new AssetManager({
|
|
669
740
|
registry: getKindRegistry(),
|
|
670
|
-
projectDir:
|
|
741
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
671
742
|
global: opts.global || harnesses !== void 0,
|
|
672
743
|
harnesses,
|
|
673
744
|
driverTarget: opts.target
|
|
@@ -729,7 +800,7 @@ function makeListCommand() {
|
|
|
729
800
|
}
|
|
730
801
|
const am2 = new AssetManager({
|
|
731
802
|
registry: getKindRegistry(),
|
|
732
|
-
projectDir:
|
|
803
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
733
804
|
driverTarget: opts.target
|
|
734
805
|
});
|
|
735
806
|
let declared;
|
|
@@ -777,7 +848,7 @@ function makeListCommand() {
|
|
|
777
848
|
function runGlobalList(kind, opts, harnesses) {
|
|
778
849
|
const am2 = new AssetManager({
|
|
779
850
|
registry: getKindRegistry(),
|
|
780
|
-
projectDir:
|
|
851
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
781
852
|
global: true,
|
|
782
853
|
harnesses
|
|
783
854
|
});
|
|
@@ -850,7 +921,7 @@ async function resolveInfoEntry(am2, ref, opts) {
|
|
|
850
921
|
return { entry: match ?? deployed };
|
|
851
922
|
}
|
|
852
923
|
const lookup = opts.storeLookup ?? (async (filter) => {
|
|
853
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
924
|
+
const { resolveCatalogSource } = await import('../open-library-N6ESO6IK.js');
|
|
854
925
|
const { source, close } = await resolveCatalogSource({ projectDir: opts.projectDir });
|
|
855
926
|
try {
|
|
856
927
|
return await source.listAssets(filter);
|
|
@@ -866,7 +937,7 @@ async function resolveInfoEntry(am2, ref, opts) {
|
|
|
866
937
|
);
|
|
867
938
|
return { entry: hit ? catalogAssetToEntry(hit) : null };
|
|
868
939
|
} catch (err2) {
|
|
869
|
-
const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-
|
|
940
|
+
const { LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-N6ESO6IK.js');
|
|
870
941
|
const storeNote = err2 instanceof Error ? err2.message : String(err2);
|
|
871
942
|
const disabled = err2 instanceof LocalCatalogDisabledError2 || /catalog\.url/i.test(storeNote);
|
|
872
943
|
return { entry: null, storeNote, ...disabled ? { storeDisabled: true } : {} };
|
|
@@ -882,7 +953,8 @@ function infoNotFoundHint(ref, lookup) {
|
|
|
882
953
|
}
|
|
883
954
|
function makeInfoCommand() {
|
|
884
955
|
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) => {
|
|
885
|
-
const projectDir =
|
|
956
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
957
|
+
requireProjectConfig(projectDir, { allowMissing: true });
|
|
886
958
|
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
|
|
887
959
|
const lookup = await resolveInfoEntry(am2, ref, { projectDir });
|
|
888
960
|
const entry = lookup.entry;
|
|
@@ -931,7 +1003,7 @@ function makeCreateCommand() {
|
|
|
931
1003
|
new Option("-k, --kind <kind>", "Asset kind").default("skill").choices([...SCAFFOLD_KINDS])
|
|
932
1004
|
).option("-d, --dir <dir>", "Target directory (default: cwd)").action((name, opts) => {
|
|
933
1005
|
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
|
|
934
|
-
const destDir = opts.dir ?
|
|
1006
|
+
const destDir = opts.dir ? path22__default.resolve(opts.dir) : process.cwd();
|
|
935
1007
|
const result = am2.create(name, opts.kind, destDir);
|
|
936
1008
|
if (result.ok) logOk(`Created ${kindColor(opts.kind)}: ${pc5.dim(result.path)}`);
|
|
937
1009
|
else {
|
|
@@ -942,31 +1014,31 @@ function makeCreateCommand() {
|
|
|
942
1014
|
}
|
|
943
1015
|
function makeDoctorCommand() {
|
|
944
1016
|
return new Command("doctor").description("Scan for missing dependency chains").argument("[name]", "Check a specific asset (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (name, opts) => {
|
|
1017
|
+
requireProjectConfig(opts.projectDir);
|
|
945
1018
|
const am2 = new AssetManager({
|
|
946
1019
|
registry: getKindRegistry(),
|
|
947
|
-
projectDir:
|
|
1020
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
948
1021
|
});
|
|
949
|
-
const { gaps
|
|
1022
|
+
const { gaps } = await am2.projectState();
|
|
950
1023
|
if (gaps.length === 0) {
|
|
951
1024
|
logOk("No missing dependencies.");
|
|
952
1025
|
return;
|
|
953
1026
|
}
|
|
954
1027
|
process.exitCode = 1;
|
|
955
1028
|
for (const g of gaps) if (g.type !== "requires") logErr(g.message);
|
|
956
|
-
const missing =
|
|
1029
|
+
const missing = gaps.filter((g) => g.type === "requires" && g.asset !== void 0);
|
|
957
1030
|
if (missing.length === 0) return;
|
|
958
|
-
const assetW = Math.max(5, ...missing.map((
|
|
959
|
-
const depW = Math.max(11, ...missing.map((
|
|
1031
|
+
const assetW = Math.max(5, ...missing.map((g) => (g.asset ?? "").length));
|
|
1032
|
+
const depW = Math.max(11, ...missing.map((g) => g.ref.length));
|
|
960
1033
|
console.log();
|
|
961
1034
|
console.log(
|
|
962
1035
|
` ${S.dim("ASSET".padEnd(assetW))} ${S.dim("MISSING DEP".padEnd(depW))} ${S.dim("IN REPOS")}`
|
|
963
1036
|
);
|
|
964
1037
|
console.log(` ${S.rule(assetW + depW + 15)}`);
|
|
965
|
-
for (const
|
|
966
|
-
const asset =
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
console.log(` ${asset.padEnd(assetW)} ${dep.padEnd(depW)} ${status4}`);
|
|
1038
|
+
for (const g of missing) {
|
|
1039
|
+
const asset = g.asset ?? "";
|
|
1040
|
+
const status4 = g.manualFix ? S.err("not found") : S.warn("fixable");
|
|
1041
|
+
console.log(` ${asset.padEnd(assetW)} ${g.ref.padEnd(depW)} ${status4}`);
|
|
970
1042
|
}
|
|
971
1043
|
console.log();
|
|
972
1044
|
});
|
|
@@ -977,20 +1049,20 @@ function claudeSkillRoots() {
|
|
|
977
1049
|
const roots = [];
|
|
978
1050
|
const override = process.env.SKAILE_CLAUDE_SKILLS_DIR;
|
|
979
1051
|
if (override) roots.push(override);
|
|
980
|
-
roots.push(
|
|
1052
|
+
roots.push(path22.join(os.homedir(), ".claude", "skills"));
|
|
981
1053
|
return roots;
|
|
982
1054
|
}
|
|
983
1055
|
function resolveImportSource(nameOrPath) {
|
|
984
|
-
const asPath =
|
|
1056
|
+
const asPath = path22.resolve(nameOrPath);
|
|
985
1057
|
if (fs8.existsSync(asPath)) {
|
|
986
|
-
const dir = fs8.statSync(asPath).isDirectory() ? asPath :
|
|
987
|
-
const skillFile =
|
|
1058
|
+
const dir = fs8.statSync(asPath).isDirectory() ? asPath : path22.dirname(asPath);
|
|
1059
|
+
const skillFile = path22.join(dir, "SKILL.md");
|
|
988
1060
|
if (fs8.existsSync(skillFile)) return { dir, skillFile, via: "path" };
|
|
989
1061
|
}
|
|
990
|
-
if (!nameOrPath.includes(
|
|
1062
|
+
if (!nameOrPath.includes(path22.sep) && !nameOrPath.startsWith(".")) {
|
|
991
1063
|
for (const root of claudeSkillRoots()) {
|
|
992
|
-
const dir =
|
|
993
|
-
const skillFile =
|
|
1064
|
+
const dir = path22.join(root, nameOrPath);
|
|
1065
|
+
const skillFile = path22.join(dir, "SKILL.md");
|
|
994
1066
|
if (fs8.existsSync(skillFile)) return { dir, skillFile, via: "claude-skills" };
|
|
995
1067
|
}
|
|
996
1068
|
}
|
|
@@ -1046,6 +1118,12 @@ ${body}
|
|
|
1046
1118
|
}
|
|
1047
1119
|
|
|
1048
1120
|
// cli/src/commands/asset-cmd.ts
|
|
1121
|
+
function copyFilter(root) {
|
|
1122
|
+
return (src) => {
|
|
1123
|
+
const rel = path22.relative(root, src).split(path22.sep).join("/");
|
|
1124
|
+
return rel === "" || !(isNonAssetPath(rel) || isNonAssetDir(path22.basename(src)));
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1049
1127
|
async function resolveDefByRef(library, ref, opts) {
|
|
1050
1128
|
let parsed;
|
|
1051
1129
|
try {
|
|
@@ -1120,16 +1198,16 @@ function makeAssetCommand() {
|
|
|
1120
1198
|
exitOnManifestPublisherProblems(target.path, target.name);
|
|
1121
1199
|
const rawSkill = fs8.readFileSync(src.skillFile, "utf8");
|
|
1122
1200
|
const norm = opts.normalize ? normalizeSkillContent(rawSkill, {
|
|
1123
|
-
fallbackName:
|
|
1201
|
+
fallbackName: path22.basename(src.dir),
|
|
1124
1202
|
version: opts.version,
|
|
1125
1203
|
stage: opts.stage
|
|
1126
|
-
}) : { content: rawSkill, name:
|
|
1204
|
+
}) : { content: rawSkill, name: path22.basename(src.dir), changed: false, notes: [] };
|
|
1127
1205
|
if (!opts.normalize && !isValidAssetName(norm.name)) {
|
|
1128
1206
|
logWarn(
|
|
1129
1207
|
`Name "${norm.name}" is not canonical (kebab-case); \`skaile validate\` will reject this manifest entry. Drop --no-normalize to slugify it.`
|
|
1130
1208
|
);
|
|
1131
1209
|
}
|
|
1132
|
-
const destDir =
|
|
1210
|
+
const destDir = path22.join(target.path, norm.name);
|
|
1133
1211
|
if (fs8.existsSync(destDir)) {
|
|
1134
1212
|
logErr(`Destination already exists: ${destDir}`);
|
|
1135
1213
|
process.exit(1);
|
|
@@ -1141,8 +1219,27 @@ function makeAssetCommand() {
|
|
|
1141
1219
|
);
|
|
1142
1220
|
process.exit(1);
|
|
1143
1221
|
}
|
|
1144
|
-
|
|
1145
|
-
|
|
1222
|
+
const importedFm = parseFrontmatter(norm.content);
|
|
1223
|
+
const checked = checkAsset(
|
|
1224
|
+
"skill",
|
|
1225
|
+
importedFm.data,
|
|
1226
|
+
importedFm.body,
|
|
1227
|
+
norm.name,
|
|
1228
|
+
getKindRegistry(),
|
|
1229
|
+
norm.content
|
|
1230
|
+
);
|
|
1231
|
+
if (checked.errors.length > 0) {
|
|
1232
|
+
for (const f of checked.errors) logErr(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
|
|
1233
|
+
logErr(
|
|
1234
|
+
`Not imported: ${checked.errors.length} problem(s) in SKILL.md. Fix them in ${src.skillFile} (or drop --no-normalize) and run the import again.`
|
|
1235
|
+
);
|
|
1236
|
+
process.exit(1);
|
|
1237
|
+
}
|
|
1238
|
+
for (const f of checked.advisories) {
|
|
1239
|
+
logWarn(`${norm.name}/SKILL.md [${f.tag}] \u2014 ${f.text}`);
|
|
1240
|
+
}
|
|
1241
|
+
fs8.cpSync(src.dir, destDir, { recursive: true, filter: copyFilter(src.dir) });
|
|
1242
|
+
fs8.writeFileSync(path22.join(destDir, "SKILL.md"), norm.content, "utf8");
|
|
1146
1243
|
for (const note of norm.notes) logInfo(` \u2022 ${note}`);
|
|
1147
1244
|
const fm = parseFrontmatter(norm.content).data;
|
|
1148
1245
|
for (const f of checkAgentSkillConformance(fm, { dirName: norm.name })) {
|
|
@@ -1208,23 +1305,23 @@ function makeAssetCommand() {
|
|
|
1208
1305
|
);
|
|
1209
1306
|
process.exit(1);
|
|
1210
1307
|
}
|
|
1211
|
-
const basename3 =
|
|
1308
|
+
const basename3 = path22.basename(srcPath);
|
|
1212
1309
|
const destDir = target.path;
|
|
1213
1310
|
fs8.mkdirSync(destDir, { recursive: true });
|
|
1214
|
-
const destPath =
|
|
1311
|
+
const destPath = path22.join(destDir, basename3);
|
|
1215
1312
|
if (fs8.existsSync(destPath)) {
|
|
1216
1313
|
logErr(`Destination already exists: ${destPath}`);
|
|
1217
1314
|
process.exit(1);
|
|
1218
1315
|
}
|
|
1219
1316
|
switch (opts.mode) {
|
|
1220
1317
|
case "copy":
|
|
1221
|
-
fs8.cpSync(srcPath, destPath, { recursive: true });
|
|
1318
|
+
fs8.cpSync(srcPath, destPath, { recursive: true, filter: copyFilter(srcPath) });
|
|
1222
1319
|
break;
|
|
1223
1320
|
case "move":
|
|
1224
1321
|
fs8.renameSync(srcPath, destPath);
|
|
1225
1322
|
break;
|
|
1226
1323
|
case "link":
|
|
1227
|
-
fs8.symlinkSync(
|
|
1324
|
+
fs8.symlinkSync(path22.resolve(srcPath), destPath);
|
|
1228
1325
|
break;
|
|
1229
1326
|
}
|
|
1230
1327
|
if (target.backend === "git" && opts.commit) {
|
|
@@ -1239,6 +1336,11 @@ function makeAssetCommand() {
|
|
|
1239
1336
|
}
|
|
1240
1337
|
}
|
|
1241
1338
|
logOk(`Migrated ${basename3} \u2192 ${target.name} (${opts.mode})`);
|
|
1339
|
+
const publisher = loadSkPublishManifest(target.path)?.publisher ?? "<publisher>";
|
|
1340
|
+
const migratedKind = fs8.existsSync(path22.join(destPath, "SKILL.md")) ? "skill" : "<kind>";
|
|
1341
|
+
logInfo(
|
|
1342
|
+
`Not addable yet: run ${S.cmd(`skaile library index ${target.name}`)}, then ${S.cmd(`skaile add ${migratedKind}:@${publisher.replace(/^@/, "")}/${basename3}`)}`
|
|
1343
|
+
);
|
|
1242
1344
|
if (opts.mode === "move") {
|
|
1243
1345
|
logInfo("Source moved into the library \u2014 future edits modify the library copy.");
|
|
1244
1346
|
} else if (opts.mode === "copy") {
|
|
@@ -1354,14 +1456,14 @@ function makeAuthCommand() {
|
|
|
1354
1456
|
}
|
|
1355
1457
|
function collectCacheTargets(scope) {
|
|
1356
1458
|
const out = [];
|
|
1357
|
-
out.push(
|
|
1358
|
-
out.push(
|
|
1359
|
-
out.push(
|
|
1459
|
+
out.push(path22__default.join(scope.projectDir, ".skaile", "cache"));
|
|
1460
|
+
out.push(path22__default.join(scope.projectDir, ".skaile", "store-cache"));
|
|
1461
|
+
out.push(path22__default.join(scope.projectDir, ".skaile", "repos"));
|
|
1360
1462
|
if (scope.global) {
|
|
1361
1463
|
out.push(globalCacheRoot());
|
|
1362
1464
|
const home = globalSkaileDir();
|
|
1363
|
-
out.push(
|
|
1364
|
-
out.push(
|
|
1465
|
+
out.push(path22__default.join(home, "repos"));
|
|
1466
|
+
out.push(path22__default.join(home, "catalog-cache"));
|
|
1365
1467
|
}
|
|
1366
1468
|
return out;
|
|
1367
1469
|
}
|
|
@@ -1375,7 +1477,7 @@ function dirSize(target) {
|
|
|
1375
1477
|
function dirSizeOfDir(dir) {
|
|
1376
1478
|
let total = 0;
|
|
1377
1479
|
for (const ent of readdirSync(dir, { withFileTypes: true })) {
|
|
1378
|
-
const child =
|
|
1480
|
+
const child = path22__default.join(dir, ent.name);
|
|
1379
1481
|
if (ent.isSymbolicLink()) continue;
|
|
1380
1482
|
if (ent.isDirectory()) total += dirSizeOfDir(child);
|
|
1381
1483
|
else if (ent.isFile()) total += statSync(child).size;
|
|
@@ -1401,7 +1503,7 @@ function makeCacheCommand() {
|
|
|
1401
1503
|
const cmd = new Command("cache").description("Inspect and reclaim the re-derivable cache");
|
|
1402
1504
|
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) => {
|
|
1403
1505
|
const targets = collectCacheTargets({
|
|
1404
|
-
projectDir:
|
|
1506
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
1405
1507
|
global: opts.global
|
|
1406
1508
|
}).filter((t) => existsSync(t));
|
|
1407
1509
|
if (targets.length === 0) {
|
|
@@ -1431,12 +1533,12 @@ function makeCacheCommand() {
|
|
|
1431
1533
|
for (const r of removed) logOk(`Removed ${r}`);
|
|
1432
1534
|
});
|
|
1433
1535
|
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) => {
|
|
1434
|
-
console.log(
|
|
1536
|
+
console.log(path22__default.join(path22__default.resolve(opts.projectDir), ".skaile", "cache"));
|
|
1435
1537
|
if (opts.global) console.log(globalCacheRoot());
|
|
1436
1538
|
});
|
|
1437
1539
|
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) => {
|
|
1438
1540
|
const targets = collectCacheTargets({
|
|
1439
|
-
projectDir:
|
|
1541
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
1440
1542
|
global: opts.global
|
|
1441
1543
|
});
|
|
1442
1544
|
console.log();
|
|
@@ -1452,7 +1554,7 @@ function makeCatalogCommand() {
|
|
|
1452
1554
|
const catalog = new Command("catalog").description("Catalog source health and configuration");
|
|
1453
1555
|
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) => {
|
|
1454
1556
|
const { resolveConfig, isLocalCatalogUrl, trpcGetUrl } = await import('../library/index.js');
|
|
1455
|
-
const projectDir = opts.projectDir ?
|
|
1557
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : void 0;
|
|
1456
1558
|
const cfg = resolveConfig({ projectDir });
|
|
1457
1559
|
const baseUrl = opts.url ?? cfg.catalog.url;
|
|
1458
1560
|
if (isLocalCatalogUrl(baseUrl)) {
|
|
@@ -1470,7 +1572,7 @@ function makeCatalogCommand() {
|
|
|
1470
1572
|
});
|
|
1471
1573
|
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) => {
|
|
1472
1574
|
const { resolveConfig } = await import('../library/index.js');
|
|
1473
|
-
const projectDir = opts.projectDir ?
|
|
1575
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : void 0;
|
|
1474
1576
|
const cfg = resolveConfig({ projectDir });
|
|
1475
1577
|
console.log(`url: ${cfg.catalog.url}`);
|
|
1476
1578
|
console.log(`framing: ${cfg.catalog.framing}`);
|
|
@@ -1479,7 +1581,7 @@ function makeCatalogCommand() {
|
|
|
1479
1581
|
return catalog;
|
|
1480
1582
|
}
|
|
1481
1583
|
async function runLocalCatalogTest(projectDir) {
|
|
1482
|
-
const { resolveCatalogSource } = await import('../open-library-
|
|
1584
|
+
const { resolveCatalogSource } = await import('../open-library-N6ESO6IK.js');
|
|
1483
1585
|
let resolved;
|
|
1484
1586
|
try {
|
|
1485
1587
|
resolved = await resolveCatalogSource({ projectDir });
|
|
@@ -1622,7 +1724,7 @@ async function scanLibraryFlowEntries() {
|
|
|
1622
1724
|
const { LocalIndex, resolveIndexPath, scanAuthoringLibraries } = await import('../library/index.js');
|
|
1623
1725
|
const indexPath = resolveIndexPath();
|
|
1624
1726
|
if (!existsSync(indexPath)) return entries;
|
|
1625
|
-
const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-
|
|
1727
|
+
const { getKindRegistry: getKindRegistry2 } = await import('../open-registry-CBZ5MWTT.js');
|
|
1626
1728
|
const index = new LocalIndex({ indexPath });
|
|
1627
1729
|
try {
|
|
1628
1730
|
for (const { assets } of await scanAuthoringLibraries(index, getKindRegistry2())) {
|
|
@@ -1673,9 +1775,9 @@ function findSkills() {
|
|
|
1673
1775
|
}
|
|
1674
1776
|
function walkSkills(dir, out) {
|
|
1675
1777
|
for (const entry of fs8__default.readdirSync(dir, { withFileTypes: true })) {
|
|
1676
|
-
const full =
|
|
1778
|
+
const full = path22__default.join(dir, entry.name);
|
|
1677
1779
|
if (entry.isDirectory()) {
|
|
1678
|
-
const skillMd =
|
|
1780
|
+
const skillMd = path22__default.join(full, "SKILL.md");
|
|
1679
1781
|
if (fs8__default.existsSync(skillMd)) {
|
|
1680
1782
|
out.push({ name: entry.name, path: full, skillPath: skillMd });
|
|
1681
1783
|
} else {
|
|
@@ -1697,7 +1799,7 @@ function resolveFlowIds() {
|
|
|
1697
1799
|
}
|
|
1698
1800
|
}
|
|
1699
1801
|
function resolveSessionIds(projectDir) {
|
|
1700
|
-
const sessionsDir =
|
|
1802
|
+
const sessionsDir = path22__default.join(projectDir, ".skaile", "sessions");
|
|
1701
1803
|
if (!fs8__default.existsSync(sessionsDir)) return [];
|
|
1702
1804
|
try {
|
|
1703
1805
|
return fs8__default.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
@@ -1753,6 +1855,33 @@ function resolveDynamic(words, cword) {
|
|
|
1753
1855
|
return null;
|
|
1754
1856
|
}
|
|
1755
1857
|
var PERSONAL_KEYS = /* @__PURE__ */ new Set(["driver", "model"]);
|
|
1858
|
+
var CATALOG_KEYS = /* @__PURE__ */ new Set(["catalog.url", "catalog.cache_ttl", "catalog.framing"]);
|
|
1859
|
+
async function setCatalogKey(key, raw) {
|
|
1860
|
+
const { CatalogConfigSchema, saveConfig } = await import('../library/index.js');
|
|
1861
|
+
const { parse: parseYaml5 } = await import('yaml');
|
|
1862
|
+
const field = key.slice("catalog.".length);
|
|
1863
|
+
const value = field === "cache_ttl" ? /^\d+$/.test(raw.trim()) ? Number(raw) : raw : raw;
|
|
1864
|
+
const checked = CatalogConfigSchema.safeParse({ [field]: value });
|
|
1865
|
+
if (!checked.success) {
|
|
1866
|
+
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"';
|
|
1867
|
+
logErr(`'${key}' must be ${hint}; got "${raw}".`);
|
|
1868
|
+
process.exit(1);
|
|
1869
|
+
}
|
|
1870
|
+
const filePath = userConfigPath();
|
|
1871
|
+
const fs13 = await import('fs');
|
|
1872
|
+
let existing = {};
|
|
1873
|
+
if (fs13.existsSync(filePath)) {
|
|
1874
|
+
const parsed = parseYaml5(fs13.readFileSync(filePath, "utf-8"));
|
|
1875
|
+
if (parsed && typeof parsed === "object") existing = parsed;
|
|
1876
|
+
}
|
|
1877
|
+
const catalog = {
|
|
1878
|
+
...existing.catalog ?? {},
|
|
1879
|
+
[field]: checked.data[field]
|
|
1880
|
+
};
|
|
1881
|
+
saveConfig(filePath, { ...existing, catalog });
|
|
1882
|
+
logOk(`Set ${pc5.bold(key)} = ${String(checked.data[field])}`);
|
|
1883
|
+
console.log(S.dim(` \u2192 ${filePath}`));
|
|
1884
|
+
}
|
|
1756
1885
|
var API_KEY_PREFIX = "apiKey.";
|
|
1757
1886
|
function collectWorkspaceDefaults(projectDir) {
|
|
1758
1887
|
const wsDefaults = {};
|
|
@@ -1768,14 +1897,17 @@ function collectWorkspaceDefaults(projectDir) {
|
|
|
1768
1897
|
}
|
|
1769
1898
|
return wsDefaults;
|
|
1770
1899
|
}
|
|
1771
|
-
function printEffectiveSection(config) {
|
|
1900
|
+
function printEffectiveSection(config, sources) {
|
|
1772
1901
|
console.log();
|
|
1773
1902
|
console.log(S.heading(" Effective Config"));
|
|
1774
1903
|
console.log(` ${S.rule(40)}`);
|
|
1775
1904
|
for (const key of ["driver", "model"]) {
|
|
1776
1905
|
const value = config[key];
|
|
1777
1906
|
if (value !== void 0) {
|
|
1778
|
-
|
|
1907
|
+
const origin = sources[key];
|
|
1908
|
+
console.log(
|
|
1909
|
+
` ${S.label(`${key}:`.padEnd(16))} ${value}${origin ? ` ${S.dim(`(${origin})`)}` : ""}`
|
|
1910
|
+
);
|
|
1779
1911
|
}
|
|
1780
1912
|
}
|
|
1781
1913
|
}
|
|
@@ -1839,17 +1971,18 @@ function printResolvedPathsSection(config) {
|
|
|
1839
1971
|
console.log(` ${S.label("prompts:".padEnd(16))} ${config.promptsDir ?? paths.promptsDir}`);
|
|
1840
1972
|
}
|
|
1841
1973
|
async function showConfig(opts) {
|
|
1842
|
-
const projectDir = opts.projectDir ?
|
|
1974
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
|
|
1843
1975
|
let config;
|
|
1976
|
+
let sources;
|
|
1844
1977
|
let wsDefaults;
|
|
1845
1978
|
try {
|
|
1846
|
-
config = await
|
|
1979
|
+
({ settings: config, sources } = await resolveSettingsWithSources(projectDir));
|
|
1847
1980
|
wsDefaults = collectWorkspaceDefaults(projectDir);
|
|
1848
1981
|
} catch (error) {
|
|
1849
1982
|
logErr(error instanceof Error ? error.message : String(error));
|
|
1850
1983
|
process.exit(1);
|
|
1851
1984
|
}
|
|
1852
|
-
printEffectiveSection(config);
|
|
1985
|
+
printEffectiveSection(config, sources);
|
|
1853
1986
|
printWorkspaceDefaultsSection(wsDefaults);
|
|
1854
1987
|
printModelSelectionSection(config, projectDir);
|
|
1855
1988
|
printResolvedPathsSection(config);
|
|
@@ -1884,13 +2017,25 @@ function makeConfigCommand() {
|
|
|
1884
2017
|
const cmd = new Command("config").description("Manage personal config (.skaile/settings.json)");
|
|
1885
2018
|
cmd.command("show").description("Show effective config with sources").option("--project-dir <path>", "Project directory").action((opts) => showConfig(opts));
|
|
1886
2019
|
cmd.command("get <key>").description("Get an effective config value").option("--project-dir <path>", "Project directory").action(async (key, opts) => {
|
|
1887
|
-
const projectDir = opts.projectDir ?
|
|
2020
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
|
|
2021
|
+
if (CATALOG_KEYS.has(key)) {
|
|
2022
|
+
const { resolveConfig } = await import('../library/index.js');
|
|
2023
|
+
const field = key.slice("catalog.".length);
|
|
2024
|
+
console.log(resolveConfig({ projectDir }).catalog[field]);
|
|
2025
|
+
return;
|
|
2026
|
+
}
|
|
1888
2027
|
const config = await resolveSettings(projectDir);
|
|
1889
2028
|
const value = config[key];
|
|
1890
2029
|
console.log(value ?? S.dim("(not set)"));
|
|
1891
2030
|
});
|
|
1892
|
-
cmd.command("set <key> <value>").description(
|
|
1893
|
-
|
|
2031
|
+
cmd.command("set <key> <value>").description(
|
|
2032
|
+
"Set a personal config value (driver, model, apiKey.<provider>) or a catalog setting (catalog.url, catalog.cache_ttl, catalog.framing)"
|
|
2033
|
+
).option("--project-dir <path>", "Project directory").option("--global", "Write to ~/.skaile/settings.json instead of project-local").action(async (key, value, opts) => {
|
|
2034
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
|
|
2035
|
+
if (CATALOG_KEYS.has(key)) {
|
|
2036
|
+
await setCatalogKey(key, value);
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
1894
2039
|
if (key === "provider" || key === "cloud" || key === "cloudConfig") {
|
|
1895
2040
|
logErr(
|
|
1896
2041
|
`'${key}' is no longer a setting \u2014 an endpoint is an AI provider registry entry and a session selects one with a model reference.
|
|
@@ -1917,6 +2062,14 @@ function makeConfigCommand() {
|
|
|
1917
2062
|
await saveSettings({ ...existing, [key]: value }, filePath);
|
|
1918
2063
|
logOk(`Set ${pc5.bold(key)} = ${value}`);
|
|
1919
2064
|
console.log(S.dim(` \u2192 ${filePath}`));
|
|
2065
|
+
if (key === "driver") {
|
|
2066
|
+
const projectDriver = resolveSkWorkspaceConfig(projectDir).agent_config?.default?.driver;
|
|
2067
|
+
if (projectDriver && projectDriver !== value) {
|
|
2068
|
+
logWarn(
|
|
2069
|
+
`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.`
|
|
2070
|
+
);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
1920
2073
|
if (key === "model") {
|
|
1921
2074
|
const view = loadRegistryView({ projectDir });
|
|
1922
2075
|
const resolved = parseModelRef(value, view.merged);
|
|
@@ -2230,8 +2383,8 @@ function makeConnectorCommand() {
|
|
|
2230
2383
|
async (driver, opts) => {
|
|
2231
2384
|
const { installNpmPackages } = await import('../connectors/index.js');
|
|
2232
2385
|
const { scanDirectory: scanDirectory2, factoryAssetRoots: factoryAssetRoots2, WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
2233
|
-
const projectDir =
|
|
2234
|
-
const yamlPath =
|
|
2386
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2387
|
+
const yamlPath = path22__default.join(projectDir, "skaile.yaml");
|
|
2235
2388
|
if (!existsSync(yamlPath)) {
|
|
2236
2389
|
logErr("No skaile.yaml found in current directory. Run 'skaile init' first.");
|
|
2237
2390
|
process.exit(1);
|
|
@@ -2291,8 +2444,8 @@ ${installResult.output}`);
|
|
|
2291
2444
|
);
|
|
2292
2445
|
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) => {
|
|
2293
2446
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
2294
|
-
const projectDir =
|
|
2295
|
-
const yamlPath =
|
|
2447
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2448
|
+
const yamlPath = path22__default.join(projectDir, "skaile.yaml");
|
|
2296
2449
|
if (!existsSync(yamlPath)) {
|
|
2297
2450
|
logErr("No skaile.yaml found in current directory.");
|
|
2298
2451
|
process.exit(1);
|
|
@@ -2309,7 +2462,7 @@ ${installResult.output}`);
|
|
|
2309
2462
|
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) => {
|
|
2310
2463
|
const res = await import('../connectors/index.js');
|
|
2311
2464
|
res.registerBuiltinConnectors();
|
|
2312
|
-
const projectDir =
|
|
2465
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2313
2466
|
const declarations = res.loadConnectorDeclarations(projectDir);
|
|
2314
2467
|
if (declarations.length === 0) {
|
|
2315
2468
|
console.log("No connectors configured in skaile.yaml.");
|
|
@@ -2333,7 +2486,7 @@ ${installResult.output}`);
|
|
|
2333
2486
|
await manager.disconnectAll();
|
|
2334
2487
|
});
|
|
2335
2488
|
cmd.command("list").description("List all configured connectors").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (opts) => {
|
|
2336
|
-
const projectDir =
|
|
2489
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2337
2490
|
const manager = await connectConnectors(projectDir);
|
|
2338
2491
|
try {
|
|
2339
2492
|
console.log(JSON.stringify(manager.listConnectors(), null, 2));
|
|
@@ -2342,7 +2495,7 @@ ${installResult.output}`);
|
|
|
2342
2495
|
}
|
|
2343
2496
|
});
|
|
2344
2497
|
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) => {
|
|
2345
|
-
const projectDir =
|
|
2498
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2346
2499
|
const manager = await connectConnectors(projectDir);
|
|
2347
2500
|
try {
|
|
2348
2501
|
if (opts.all) {
|
|
@@ -2366,7 +2519,7 @@ ${installResult.output}`);
|
|
|
2366
2519
|
}
|
|
2367
2520
|
});
|
|
2368
2521
|
cmd.command("ops <id>").description("List available operations for a connector").option("--project-dir <path>", "Workspace directory", process.cwd()).action(async (id, opts) => {
|
|
2369
|
-
const projectDir =
|
|
2522
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2370
2523
|
const manager = await connectConnectors(projectDir);
|
|
2371
2524
|
try {
|
|
2372
2525
|
if (!manager.has(id)) {
|
|
@@ -2381,7 +2534,7 @@ ${installResult.output}`);
|
|
|
2381
2534
|
}
|
|
2382
2535
|
});
|
|
2383
2536
|
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) => {
|
|
2384
|
-
const projectDir =
|
|
2537
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2385
2538
|
const manager = await connectConnectors(projectDir);
|
|
2386
2539
|
try {
|
|
2387
2540
|
const content = await manager.read(id, resourcePath);
|
|
@@ -2391,7 +2544,7 @@ ${installResult.output}`);
|
|
|
2391
2544
|
}
|
|
2392
2545
|
});
|
|
2393
2546
|
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) => {
|
|
2394
|
-
const projectDir =
|
|
2547
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2395
2548
|
const manager = await connectConnectors(projectDir);
|
|
2396
2549
|
try {
|
|
2397
2550
|
await manager.write(id, resourcePath, { data: content });
|
|
@@ -2401,7 +2554,7 @@ ${installResult.output}`);
|
|
|
2401
2554
|
}
|
|
2402
2555
|
});
|
|
2403
2556
|
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) => {
|
|
2404
|
-
const projectDir =
|
|
2557
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2405
2558
|
const manager = await connectConnectors(projectDir);
|
|
2406
2559
|
try {
|
|
2407
2560
|
const entries = await manager.list(id, resourcePath, {
|
|
@@ -2414,7 +2567,7 @@ ${installResult.output}`);
|
|
|
2414
2567
|
}
|
|
2415
2568
|
});
|
|
2416
2569
|
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) => {
|
|
2417
|
-
const projectDir =
|
|
2570
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2418
2571
|
const manager = await connectConnectors(projectDir);
|
|
2419
2572
|
try {
|
|
2420
2573
|
const results = await manager.search(id, query);
|
|
@@ -2424,7 +2577,7 @@ ${installResult.output}`);
|
|
|
2424
2577
|
}
|
|
2425
2578
|
});
|
|
2426
2579
|
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) => {
|
|
2427
|
-
const projectDir =
|
|
2580
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2428
2581
|
const manager = await connectConnectors(projectDir);
|
|
2429
2582
|
try {
|
|
2430
2583
|
const ok = await manager.delete(id, resourcePath);
|
|
@@ -2434,7 +2587,7 @@ ${installResult.output}`);
|
|
|
2434
2587
|
}
|
|
2435
2588
|
});
|
|
2436
2589
|
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) => {
|
|
2437
|
-
const projectDir =
|
|
2590
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2438
2591
|
const manager = await connectConnectors(projectDir);
|
|
2439
2592
|
try {
|
|
2440
2593
|
if (!manager.has(id)) {
|
|
@@ -2543,7 +2696,7 @@ function envRecord() {
|
|
|
2543
2696
|
async function buildDeployContext(projectDir) {
|
|
2544
2697
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
2545
2698
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
2546
|
-
const workspaceId = config.name ??
|
|
2699
|
+
const workspaceId = config.name ?? path22__default.basename(projectDir);
|
|
2547
2700
|
let log;
|
|
2548
2701
|
try {
|
|
2549
2702
|
const { createLogger } = await import('../core/logging.js');
|
|
@@ -2575,13 +2728,13 @@ async function ensureTargetsRegistered(projectDir) {
|
|
|
2575
2728
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
2576
2729
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
2577
2730
|
if (config.plugins && config.plugins.length > 0) {
|
|
2578
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
2731
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-XMZSPVBF.js');
|
|
2579
2732
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
2580
2733
|
for (const f of result.failed) logWarn(f.error);
|
|
2581
2734
|
}
|
|
2582
2735
|
}
|
|
2583
2736
|
async function runUp(opts) {
|
|
2584
|
-
const projectDir =
|
|
2737
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2585
2738
|
await ensureTargetsRegistered(projectDir);
|
|
2586
2739
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
2587
2740
|
const { resolveDeployTarget, pluginRegistry } = await import('../plugin-registry/index.js');
|
|
@@ -2649,7 +2802,7 @@ async function restoreFromHandle(projectDir) {
|
|
|
2649
2802
|
return { target, handle, ctx };
|
|
2650
2803
|
}
|
|
2651
2804
|
async function runDown(opts) {
|
|
2652
|
-
const projectDir =
|
|
2805
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2653
2806
|
const restored = await restoreFromHandle(projectDir);
|
|
2654
2807
|
if (!restored) return;
|
|
2655
2808
|
await restored.handle.stop();
|
|
@@ -2658,7 +2811,7 @@ async function runDown(opts) {
|
|
|
2658
2811
|
logOk(`Stopped ${S.cmd(restored.target.id)} and cleared the handle.`);
|
|
2659
2812
|
}
|
|
2660
2813
|
async function runStatus(opts) {
|
|
2661
|
-
const projectDir =
|
|
2814
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2662
2815
|
const restored = await restoreFromHandle(projectDir);
|
|
2663
2816
|
if (!restored) return;
|
|
2664
2817
|
const health = await restored.handle.health();
|
|
@@ -2672,7 +2825,7 @@ async function runStatus(opts) {
|
|
|
2672
2825
|
console.log();
|
|
2673
2826
|
}
|
|
2674
2827
|
async function runLogs(opts) {
|
|
2675
|
-
const projectDir =
|
|
2828
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
2676
2829
|
const restored = await restoreFromHandle(projectDir);
|
|
2677
2830
|
if (!restored) return;
|
|
2678
2831
|
if (!restored.handle.logs) {
|
|
@@ -2694,25 +2847,59 @@ function makeDeployCommand() {
|
|
|
2694
2847
|
cmd.action(() => cmd.help());
|
|
2695
2848
|
return cmd;
|
|
2696
2849
|
}
|
|
2850
|
+
var DIFF_SHOWS = { content: true, modified: true, incomplete: true };
|
|
2697
2851
|
function makeDiffCommand() {
|
|
2698
2852
|
return new Command("diff").description("Show changes between deployed and source versions").argument("<ref>", "Asset reference (kind:name)").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
|
|
2853
|
+
requireProjectConfig(opts.projectDir);
|
|
2699
2854
|
const am2 = new AssetManager({
|
|
2700
2855
|
registry: getKindRegistry(),
|
|
2701
|
-
projectDir:
|
|
2856
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
2702
2857
|
});
|
|
2858
|
+
try {
|
|
2859
|
+
parseAssetRef(ref);
|
|
2860
|
+
} catch (err2) {
|
|
2861
|
+
const plain = (err2 instanceof Error ? err2.message : String(err2)).replace(
|
|
2862
|
+
/ Run the `migrate-skaile-manifest`.*$/,
|
|
2863
|
+
""
|
|
2864
|
+
);
|
|
2865
|
+
const bare = /^([^:@/]+):([^@/#]+)$/.exec(ref.trim());
|
|
2866
|
+
const held = plain.startsWith("publisher required") && bare ? am2.lockedRefsNamed(bare[1], bare[2]) : [];
|
|
2867
|
+
if (held.length !== 1) {
|
|
2868
|
+
logErr(held.length > 1 ? `${plain} (locked: ${held.join(", ")})` : plain);
|
|
2869
|
+
process.exitCode = 1;
|
|
2870
|
+
return;
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
const gaps = await am2.gapsOf(ref);
|
|
2874
|
+
const requirementGaps = await am2.requirementGapsOf(ref);
|
|
2875
|
+
const blocking = [...gaps.filter((g) => !DIFF_SHOWS[g.type]), ...requirementGaps];
|
|
2876
|
+
if (blocking.length > 0) {
|
|
2877
|
+
for (const g of blocking) logErr(g.message);
|
|
2878
|
+
process.exitCode = 1;
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2703
2881
|
const result = await am2.diff(ref);
|
|
2704
|
-
const problems =
|
|
2705
|
-
(g) => !(g.type === "content"
|
|
2882
|
+
const problems = gaps.filter(
|
|
2883
|
+
(g) => !(result.status === "differs" && (g.type === "content" || g.type === "modified"))
|
|
2706
2884
|
);
|
|
2707
2885
|
switch (result.status) {
|
|
2708
2886
|
case "not-found":
|
|
2709
2887
|
if (problems.length === 0) logErr(`Asset not found: ${ref}`);
|
|
2710
2888
|
break;
|
|
2711
2889
|
case "not-deployed":
|
|
2712
|
-
if (problems.length === 0)
|
|
2890
|
+
if (problems.length === 0) {
|
|
2891
|
+
logErr(
|
|
2892
|
+
`${ref} is not deployed \u2014 nothing in this project locks it; run skaile add ${ref}`
|
|
2893
|
+
);
|
|
2894
|
+
process.exitCode = 1;
|
|
2895
|
+
}
|
|
2896
|
+
break;
|
|
2897
|
+
case "no-files":
|
|
2898
|
+
if (problems.length === 0)
|
|
2899
|
+
logInfo(`${ref}: preset has no files of its own; run skaile diff on its items`);
|
|
2713
2900
|
break;
|
|
2714
2901
|
case "identical":
|
|
2715
|
-
logInfo("No differences.");
|
|
2902
|
+
if (problems.length === 0) logInfo("No differences.");
|
|
2716
2903
|
break;
|
|
2717
2904
|
case "differs":
|
|
2718
2905
|
console.log(result.diff);
|
|
@@ -2725,7 +2912,7 @@ function makeDiffCommand() {
|
|
|
2725
2912
|
function makeFlowCommand() {
|
|
2726
2913
|
const cmd = new Command("flow").description("Manage flows");
|
|
2727
2914
|
cmd.command("list").description("List available flows").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
2728
|
-
const flows = await discoverFlowsWithLibraries(
|
|
2915
|
+
const flows = await discoverFlowsWithLibraries(path22__default.resolve(opts.projectDir));
|
|
2729
2916
|
if (flows.length === 0) {
|
|
2730
2917
|
logInfo("No flows found.");
|
|
2731
2918
|
return;
|
|
@@ -2740,7 +2927,7 @@ function makeFlowCommand() {
|
|
|
2740
2927
|
console.log();
|
|
2741
2928
|
});
|
|
2742
2929
|
cmd.command("show <id>").description("Show flow details and node graph").option("--project-dir <path>", "Project directory", process.cwd()).action(async (id, opts) => {
|
|
2743
|
-
const flows = await discoverFlowsWithLibraries(
|
|
2930
|
+
const flows = await discoverFlowsWithLibraries(path22__default.resolve(opts.projectDir));
|
|
2744
2931
|
const flow = flows.find((f) => f.id === id);
|
|
2745
2932
|
if (!flow) {
|
|
2746
2933
|
logErr(`Flow not found: ${id}`);
|
|
@@ -2774,7 +2961,7 @@ function makeHistoryCommand() {
|
|
|
2774
2961
|
cmd.argument("[limit]", "Number of entries to show", "20").option("--project-dir <path>", "Project directory", process.cwd()).action((limitStr, opts) => {
|
|
2775
2962
|
const am2 = new AssetManager({
|
|
2776
2963
|
registry: getKindRegistry(),
|
|
2777
|
-
projectDir:
|
|
2964
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
2778
2965
|
});
|
|
2779
2966
|
const limit = parseInt(limitStr, 10) || 20;
|
|
2780
2967
|
const entries = am2.history(limit);
|
|
@@ -2797,7 +2984,7 @@ function makeHistoryCommand() {
|
|
|
2797
2984
|
cmd.command("clear").description("Clear action history").option("--project-dir <path>", "Project directory", process.cwd()).action((opts) => {
|
|
2798
2985
|
const am2 = new AssetManager({
|
|
2799
2986
|
registry: getKindRegistry(),
|
|
2800
|
-
projectDir:
|
|
2987
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
2801
2988
|
});
|
|
2802
2989
|
am2.clearHistory();
|
|
2803
2990
|
logOk("History cleared.");
|
|
@@ -2810,8 +2997,24 @@ var MCP_SERVER_ENTRY = {
|
|
|
2810
2997
|
args: ["mcp-server"],
|
|
2811
2998
|
env: {}
|
|
2812
2999
|
};
|
|
3000
|
+
function mcpFilePath(projectDir) {
|
|
3001
|
+
return path22__default.join(projectDir, ".mcp.json");
|
|
3002
|
+
}
|
|
3003
|
+
function legacyMcpFilePath(projectDir) {
|
|
3004
|
+
return path22__default.join(projectDir, ".claude", "mcp.json");
|
|
3005
|
+
}
|
|
3006
|
+
async function removeSkaileMcpEntry(mcpPath) {
|
|
3007
|
+
const mcp = await readJsonStrict(mcpPath);
|
|
3008
|
+
if (!mcp?.mcpServers || !(SKAILE_MCP_NAME in mcp.mcpServers)) return false;
|
|
3009
|
+
const { [SKAILE_MCP_NAME]: _removed, ...rest } = mcp.mcpServers;
|
|
3010
|
+
const updated = { ...mcp, mcpServers: rest };
|
|
3011
|
+
if (Object.keys(rest).length === 0) delete updated.mcpServers;
|
|
3012
|
+
if (Object.keys(updated).length === 0) await fs5.unlink(mcpPath);
|
|
3013
|
+
else await writeJson(mcpPath, updated);
|
|
3014
|
+
return true;
|
|
3015
|
+
}
|
|
2813
3016
|
function pluginDir(projectDir) {
|
|
2814
|
-
return
|
|
3017
|
+
return path22__default.join(projectDir, ".claude", "plugins", "skaile");
|
|
2815
3018
|
}
|
|
2816
3019
|
async function readJsonStrict(p6) {
|
|
2817
3020
|
let raw;
|
|
@@ -2829,7 +3032,7 @@ async function readJsonStrict(p6) {
|
|
|
2829
3032
|
}
|
|
2830
3033
|
}
|
|
2831
3034
|
async function writeJson(p6, value) {
|
|
2832
|
-
await fs5.mkdir(
|
|
3035
|
+
await fs5.mkdir(path22__default.dirname(p6), { recursive: true });
|
|
2833
3036
|
await fs5.writeFile(p6, `${JSON.stringify(value, null, 2)}
|
|
2834
3037
|
`);
|
|
2835
3038
|
}
|
|
@@ -2837,8 +3040,8 @@ async function copyDir(src, dest) {
|
|
|
2837
3040
|
await fs5.mkdir(dest, { recursive: true });
|
|
2838
3041
|
const entries = await fs5.readdir(src, { withFileTypes: true });
|
|
2839
3042
|
for (const entry of entries) {
|
|
2840
|
-
const srcPath =
|
|
2841
|
-
const destPath =
|
|
3043
|
+
const srcPath = path22__default.join(src, entry.name);
|
|
3044
|
+
const destPath = path22__default.join(dest, entry.name);
|
|
2842
3045
|
if (entry.isDirectory()) await copyDir(srcPath, destPath);
|
|
2843
3046
|
else await fs5.copyFile(srcPath, destPath);
|
|
2844
3047
|
}
|
|
@@ -2847,31 +3050,32 @@ async function install(projectDir, opts) {
|
|
|
2847
3050
|
return opts?.full ? installFullPlugin(projectDir) : installMcp(projectDir);
|
|
2848
3051
|
}
|
|
2849
3052
|
async function installMcp(projectDir) {
|
|
2850
|
-
const mcpPath =
|
|
3053
|
+
const mcpPath = mcpFilePath(projectDir);
|
|
2851
3054
|
const existing = await readJsonStrict(mcpPath) ?? {};
|
|
2852
3055
|
const mcpServers = { ...existing.mcpServers ?? {} };
|
|
2853
3056
|
const previous = mcpServers[SKAILE_MCP_NAME];
|
|
2854
3057
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(MCP_SERVER_ENTRY);
|
|
2855
3058
|
let warning;
|
|
2856
3059
|
if (previous && !matches) {
|
|
2857
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${
|
|
3060
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME} entry in ${path22__default.relative(projectDir, mcpPath)}`;
|
|
2858
3061
|
}
|
|
2859
3062
|
mcpServers[SKAILE_MCP_NAME] = MCP_SERVER_ENTRY;
|
|
2860
3063
|
await writeJson(mcpPath, { ...existing, mcpServers });
|
|
2861
|
-
|
|
3064
|
+
const migrated = await removeSkaileMcpEntry(legacyMcpFilePath(projectDir));
|
|
3065
|
+
return { changed: !matches || migrated, method: "mcp", warning };
|
|
2862
3066
|
}
|
|
2863
3067
|
async function installFullPlugin(projectDir) {
|
|
2864
3068
|
const dir = pluginDir(projectDir);
|
|
2865
3069
|
for (const [rel, content] of Object.entries(buildClaudePluginFiles())) {
|
|
2866
|
-
const dest =
|
|
2867
|
-
await fs5.mkdir(
|
|
3070
|
+
const dest = path22__default.join(dir, rel);
|
|
3071
|
+
await fs5.mkdir(path22__default.dirname(dest), { recursive: true });
|
|
2868
3072
|
await fs5.writeFile(dest, content);
|
|
2869
3073
|
}
|
|
2870
|
-
const projectSkillsDir =
|
|
3074
|
+
const projectSkillsDir = path22__default.join(projectDir, ".skaile", "skills");
|
|
2871
3075
|
if (existsSync(projectSkillsDir)) {
|
|
2872
|
-
await copyDir(projectSkillsDir,
|
|
3076
|
+
await copyDir(projectSkillsDir, path22__default.join(dir, "skills"));
|
|
2873
3077
|
}
|
|
2874
|
-
const settingsPath =
|
|
3078
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
2875
3079
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
2876
3080
|
const plugins = settings.plugins ?? [];
|
|
2877
3081
|
if (!plugins.includes(dir)) plugins.push(dir);
|
|
@@ -2879,8 +3083,8 @@ async function installFullPlugin(projectDir) {
|
|
|
2879
3083
|
return { changed: true, method: "plugin" };
|
|
2880
3084
|
}
|
|
2881
3085
|
async function uninstall(projectDir) {
|
|
2882
|
-
const settingsPath =
|
|
2883
|
-
const mcpPath =
|
|
3086
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
3087
|
+
const mcpPath = mcpFilePath(projectDir);
|
|
2884
3088
|
const dir = pluginDir(projectDir);
|
|
2885
3089
|
let changed = false;
|
|
2886
3090
|
const settings = await readJsonStrict(settingsPath);
|
|
@@ -2897,29 +3101,19 @@ async function uninstall(projectDir) {
|
|
|
2897
3101
|
await fs5.rm(dir, { recursive: true, force: true });
|
|
2898
3102
|
changed = true;
|
|
2899
3103
|
}
|
|
2900
|
-
|
|
2901
|
-
if (
|
|
2902
|
-
changed = true;
|
|
2903
|
-
const { [SKAILE_MCP_NAME]: _removed, ...rest } = mcp.mcpServers;
|
|
2904
|
-
const updated = { ...mcp, mcpServers: rest };
|
|
2905
|
-
if (Object.keys(rest).length === 0) delete updated.mcpServers;
|
|
2906
|
-
if (Object.keys(updated).length === 0) {
|
|
2907
|
-
await fs5.unlink(mcpPath);
|
|
2908
|
-
} else {
|
|
2909
|
-
await writeJson(mcpPath, updated);
|
|
2910
|
-
}
|
|
2911
|
-
}
|
|
3104
|
+
if (await removeSkaileMcpEntry(mcpPath)) changed = true;
|
|
3105
|
+
if (await removeSkaileMcpEntry(legacyMcpFilePath(projectDir))) changed = true;
|
|
2912
3106
|
return { changed };
|
|
2913
3107
|
}
|
|
2914
3108
|
async function detectInstall(projectDir) {
|
|
2915
3109
|
const dir = pluginDir(projectDir);
|
|
2916
3110
|
const settings = await readJsonStrict(
|
|
2917
|
-
|
|
3111
|
+
path22__default.join(projectDir, ".claude", "settings.json")
|
|
2918
3112
|
);
|
|
2919
|
-
if (existsSync(
|
|
3113
|
+
if (existsSync(path22__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir)) {
|
|
2920
3114
|
return { method: "plugin", pluginPath: dir };
|
|
2921
3115
|
}
|
|
2922
|
-
const mcp = await readJsonStrict(
|
|
3116
|
+
const mcp = await readJsonStrict(mcpFilePath(projectDir));
|
|
2923
3117
|
if (mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers) {
|
|
2924
3118
|
return { method: "mcp" };
|
|
2925
3119
|
}
|
|
@@ -2928,7 +3122,7 @@ async function detectInstall(projectDir) {
|
|
|
2928
3122
|
async function enable(projectDir) {
|
|
2929
3123
|
const detected = await detectInstall(projectDir);
|
|
2930
3124
|
if (!detected) throw new Error("plugin not installed for claude-code");
|
|
2931
|
-
const settingsPath =
|
|
3125
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
2932
3126
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
2933
3127
|
if (detected.method === "plugin") {
|
|
2934
3128
|
const disabled2 = settings.disabledPlugins ?? [];
|
|
@@ -2950,7 +3144,7 @@ async function enable(projectDir) {
|
|
|
2950
3144
|
async function disable(projectDir) {
|
|
2951
3145
|
const detected = await detectInstall(projectDir);
|
|
2952
3146
|
if (!detected) throw new Error("plugin not installed for claude-code");
|
|
2953
|
-
const settingsPath =
|
|
3147
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
2954
3148
|
const settings = await readJsonStrict(settingsPath) ?? {};
|
|
2955
3149
|
if (detected.method === "plugin") {
|
|
2956
3150
|
const list2 = settings.disabledPlugins ?? [];
|
|
@@ -2970,12 +3164,12 @@ async function disable(projectDir) {
|
|
|
2970
3164
|
return { changed: true };
|
|
2971
3165
|
}
|
|
2972
3166
|
async function status(projectDir) {
|
|
2973
|
-
const settingsPath =
|
|
2974
|
-
const mcpPath =
|
|
3167
|
+
const settingsPath = path22__default.join(projectDir, ".claude", "settings.json");
|
|
3168
|
+
const mcpPath = mcpFilePath(projectDir);
|
|
2975
3169
|
const dir = pluginDir(projectDir);
|
|
2976
3170
|
const settings = await readJsonStrict(settingsPath);
|
|
2977
3171
|
const mcp = await readJsonStrict(mcpPath);
|
|
2978
|
-
const pluginInstalled = !!(existsSync(
|
|
3172
|
+
const pluginInstalled = !!(existsSync(path22__default.join(dir, ".claude-plugin", "plugin.json")) && settings?.plugins?.includes(dir));
|
|
2979
3173
|
const mcpInstalled = !!(mcp?.mcpServers && SKAILE_MCP_NAME in mcp.mcpServers);
|
|
2980
3174
|
if (!pluginInstalled && !mcpInstalled) {
|
|
2981
3175
|
return {
|
|
@@ -2993,7 +3187,7 @@ async function status(projectDir) {
|
|
|
2993
3187
|
installed: "yes",
|
|
2994
3188
|
enabled: disabled2 ? "no" : "yes",
|
|
2995
3189
|
method: "plugin",
|
|
2996
|
-
location:
|
|
3190
|
+
location: path22__default.relative(projectDir, dir)
|
|
2997
3191
|
};
|
|
2998
3192
|
}
|
|
2999
3193
|
const disabled = settings?.disabledMcpjsonServers?.includes(SKAILE_MCP_NAME) ?? false;
|
|
@@ -3002,7 +3196,7 @@ async function status(projectDir) {
|
|
|
3002
3196
|
installed: "yes",
|
|
3003
3197
|
enabled: disabled ? "no" : "yes",
|
|
3004
3198
|
method: "mcp",
|
|
3005
|
-
location:
|
|
3199
|
+
location: path22__default.relative(projectDir, mcpPath)
|
|
3006
3200
|
};
|
|
3007
3201
|
}
|
|
3008
3202
|
var SKAILE_MCP_NAME2 = "skaile-workspace";
|
|
@@ -3029,7 +3223,7 @@ async function readConfig(p6) {
|
|
|
3029
3223
|
}
|
|
3030
3224
|
}
|
|
3031
3225
|
async function writeConfig(p6, value) {
|
|
3032
|
-
await fs5.mkdir(
|
|
3226
|
+
await fs5.mkdir(path22__default.dirname(p6), { recursive: true });
|
|
3033
3227
|
const cleaned = {};
|
|
3034
3228
|
for (const [k, v] of Object.entries(value)) {
|
|
3035
3229
|
if (v === void 0) continue;
|
|
@@ -3038,7 +3232,7 @@ async function writeConfig(p6, value) {
|
|
|
3038
3232
|
await fs5.writeFile(p6, stringify$1(cleaned));
|
|
3039
3233
|
}
|
|
3040
3234
|
function configPath(projectDir) {
|
|
3041
|
-
return
|
|
3235
|
+
return path22__default.join(projectDir, ".codex", "config.toml");
|
|
3042
3236
|
}
|
|
3043
3237
|
async function install2(projectDir) {
|
|
3044
3238
|
const p6 = configPath(projectDir);
|
|
@@ -3049,7 +3243,7 @@ async function install2(projectDir) {
|
|
|
3049
3243
|
const matches = previous && JSON.stringify(previous) === JSON.stringify(next);
|
|
3050
3244
|
let warning;
|
|
3051
3245
|
if (previous && !matches) {
|
|
3052
|
-
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${
|
|
3246
|
+
warning = `overwrote existing ${SKAILE_MCP_NAME2} entry in ${path22__default.relative(projectDir, p6)}`;
|
|
3053
3247
|
}
|
|
3054
3248
|
if (matches) return { changed: false, method: "toml" };
|
|
3055
3249
|
servers[SKAILE_MCP_NAME2] = next;
|
|
@@ -3090,12 +3284,12 @@ async function status2(projectDir) {
|
|
|
3090
3284
|
installed: "yes",
|
|
3091
3285
|
enabled: "n/a",
|
|
3092
3286
|
method: "mcp",
|
|
3093
|
-
location:
|
|
3287
|
+
location: path22__default.relative(projectDir, p6)
|
|
3094
3288
|
};
|
|
3095
3289
|
}
|
|
3096
3290
|
async function install3(projectDir) {
|
|
3097
|
-
const extDir =
|
|
3098
|
-
const extPath =
|
|
3291
|
+
const extDir = path22__default.join(projectDir, ".omp", "extensions");
|
|
3292
|
+
const extPath = path22__default.join(extDir, "skaile.ts");
|
|
3099
3293
|
await fs5.mkdir(extDir, { recursive: true });
|
|
3100
3294
|
const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
|
|
3101
3295
|
const plugin = new WorkspacePlugin({ projectDir });
|
|
@@ -3110,7 +3304,7 @@ async function install3(projectDir) {
|
|
|
3110
3304
|
return { changed: true, method: "generated" };
|
|
3111
3305
|
}
|
|
3112
3306
|
async function uninstall3(projectDir) {
|
|
3113
|
-
const extPath =
|
|
3307
|
+
const extPath = path22__default.join(projectDir, ".omp", "extensions", "skaile.ts");
|
|
3114
3308
|
try {
|
|
3115
3309
|
await fs5.unlink(extPath);
|
|
3116
3310
|
return { changed: true };
|
|
@@ -3119,14 +3313,14 @@ async function uninstall3(projectDir) {
|
|
|
3119
3313
|
}
|
|
3120
3314
|
}
|
|
3121
3315
|
async function status3(projectDir) {
|
|
3122
|
-
const extPath =
|
|
3316
|
+
const extPath = path22__default.join(projectDir, ".omp", "extensions", "skaile.ts");
|
|
3123
3317
|
if (existsSync(extPath)) {
|
|
3124
3318
|
return {
|
|
3125
3319
|
harness: "omp",
|
|
3126
3320
|
installed: "yes",
|
|
3127
3321
|
enabled: "n/a",
|
|
3128
3322
|
method: "extension",
|
|
3129
|
-
location:
|
|
3323
|
+
location: path22__default.relative(projectDir, extPath)
|
|
3130
3324
|
};
|
|
3131
3325
|
}
|
|
3132
3326
|
return {
|
|
@@ -3163,7 +3357,7 @@ async function installClaudeCode(projectDir, opts) {
|
|
|
3163
3357
|
`Generated ${S.cmd(".claude/plugins/skaile/")} and registered it in ${S.cmd(".claude/settings.json")}`
|
|
3164
3358
|
);
|
|
3165
3359
|
} else if (r.changed) {
|
|
3166
|
-
logOk(`Wrote ${S.cmd(".
|
|
3360
|
+
logOk(`Wrote ${S.cmd(".mcp.json")} (${SKAILE_MCP_LABEL})`);
|
|
3167
3361
|
} else {
|
|
3168
3362
|
logInfo(`claude-code: already installed (mcp)`);
|
|
3169
3363
|
}
|
|
@@ -3189,7 +3383,7 @@ async function installCodex(projectDir) {
|
|
|
3189
3383
|
console.log(` ${S.dim("\u2192")} Restart Codex CLI to pick up the change.`);
|
|
3190
3384
|
}
|
|
3191
3385
|
async function runInstall(opts) {
|
|
3192
|
-
const projectDir =
|
|
3386
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
3193
3387
|
const targets = resolveDriver(opts.driver);
|
|
3194
3388
|
let exitCode = 0;
|
|
3195
3389
|
if (targets.includes("claude-code")) {
|
|
@@ -3223,7 +3417,7 @@ async function uninstallCodex(projectDir) {
|
|
|
3223
3417
|
else logInfo(`codex: not installed`);
|
|
3224
3418
|
}
|
|
3225
3419
|
async function runUninstall(opts) {
|
|
3226
|
-
const projectDir =
|
|
3420
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
3227
3421
|
const targets = resolveDriver(opts.driver);
|
|
3228
3422
|
let exitCode = 0;
|
|
3229
3423
|
if (targets.includes("claude-code")) {
|
|
@@ -3266,7 +3460,7 @@ async function toggleTarget(t, projectDir, action3) {
|
|
|
3266
3460
|
});
|
|
3267
3461
|
}
|
|
3268
3462
|
async function runToggle(opts, action3) {
|
|
3269
|
-
const projectDir =
|
|
3463
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
3270
3464
|
const requestedAll = opts.driver === "all";
|
|
3271
3465
|
const targets = resolveDriver(opts.driver);
|
|
3272
3466
|
const usageError = checkToggleSupported(targets, requestedAll, action3);
|
|
@@ -3278,7 +3472,7 @@ async function runToggle(opts, action3) {
|
|
|
3278
3472
|
return exitCode;
|
|
3279
3473
|
}
|
|
3280
3474
|
async function runStatus2(opts) {
|
|
3281
|
-
const projectDir =
|
|
3475
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
3282
3476
|
const targets = resolveDriver(opts.driver);
|
|
3283
3477
|
const rows = [];
|
|
3284
3478
|
let exitCode = 0;
|
|
@@ -3319,12 +3513,12 @@ function printStatusTable(rows) {
|
|
|
3319
3513
|
var SKAILE_MCP_LABEL = "skaile-workspace entry";
|
|
3320
3514
|
var HOOK_EVENTS = ["session-start", "session-end", "user-prompt-submit"];
|
|
3321
3515
|
async function runHook(event) {
|
|
3322
|
-
const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
|
|
3323
|
-
|
|
3324
|
-
new
|
|
3516
|
+
const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
|
|
3517
|
+
registerLogStore2(
|
|
3518
|
+
new LogStore2({
|
|
3325
3519
|
sessionId: `hook-${event}`,
|
|
3326
3520
|
level: "info",
|
|
3327
|
-
sinks: [new
|
|
3521
|
+
sinks: [new StdoutSink2({ stream: "stderr" })]
|
|
3328
3522
|
})
|
|
3329
3523
|
);
|
|
3330
3524
|
const { WorkspacePlugin, PluginStore, resolveProjectDir } = await import('../workspace-plugin/index.js');
|
|
@@ -3349,7 +3543,7 @@ async function runHook(event) {
|
|
|
3349
3543
|
await plugin.shutdown();
|
|
3350
3544
|
return;
|
|
3351
3545
|
}
|
|
3352
|
-
const store = new PluginStore(
|
|
3546
|
+
const store = new PluginStore(path22__default.join(projectDir, ".skaile", "plugin-state.json"));
|
|
3353
3547
|
await store.load();
|
|
3354
3548
|
const status4 = store.get("connector:status");
|
|
3355
3549
|
if (status4 && typeof status4 === "object" && Object.keys(status4).length > 0) {
|
|
@@ -3364,6 +3558,45 @@ async function runHook(event) {
|
|
|
3364
3558
|
);
|
|
3365
3559
|
}
|
|
3366
3560
|
}
|
|
3561
|
+
async function readStdin() {
|
|
3562
|
+
if (process.stdin.isTTY) return "";
|
|
3563
|
+
const chunks = [];
|
|
3564
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
3565
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
3566
|
+
}
|
|
3567
|
+
async function runOmpExec(kind, name, projectDir) {
|
|
3568
|
+
if (kind !== "tool" && kind !== "slash") {
|
|
3569
|
+
logErr(`omp-exec: unknown kind '${kind}' (expected: tool | slash)`);
|
|
3570
|
+
return 2;
|
|
3571
|
+
}
|
|
3572
|
+
const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
|
|
3573
|
+
const plugin = new WorkspacePlugin({ projectDir, bootOwned: true });
|
|
3574
|
+
try {
|
|
3575
|
+
const raw = (await readStdin()).trim();
|
|
3576
|
+
const payload = raw ? JSON.parse(raw) : kind === "tool" ? {} : [];
|
|
3577
|
+
await plugin.boot();
|
|
3578
|
+
if (kind === "slash") {
|
|
3579
|
+
const parts = Array.isArray(payload) ? payload.map(String) : [];
|
|
3580
|
+
process.stdout.write(`${await plugin.handleSlashCommand(name, parts)}
|
|
3581
|
+
`);
|
|
3582
|
+
return 0;
|
|
3583
|
+
}
|
|
3584
|
+
const tools = await plugin.buildOmpToolSet();
|
|
3585
|
+
const tool = tools.find((t) => t.name === name);
|
|
3586
|
+
if (!tool) {
|
|
3587
|
+
logErr(`omp-exec: unknown tool '${name}'`);
|
|
3588
|
+
return 2;
|
|
3589
|
+
}
|
|
3590
|
+
process.stdout.write(`${await tool.handler(payload)}
|
|
3591
|
+
`);
|
|
3592
|
+
return 0;
|
|
3593
|
+
} catch (e) {
|
|
3594
|
+
logErr(`omp-exec ${kind} ${name}: ${e instanceof Error ? e.message : String(e)}`);
|
|
3595
|
+
return 1;
|
|
3596
|
+
} finally {
|
|
3597
|
+
await plugin.shutdown();
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3367
3600
|
function makeIntegrationCommand() {
|
|
3368
3601
|
const cmd = new Command("integration").description(
|
|
3369
3602
|
"Manage skaile agent integration / workspace-plugin adapter (Claude Code / OMP / Codex)"
|
|
@@ -3386,13 +3619,18 @@ function makeIntegrationCommand() {
|
|
|
3386
3619
|
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) => {
|
|
3387
3620
|
process.exitCode = await runStatus2(opts);
|
|
3388
3621
|
});
|
|
3622
|
+
cmd.command("omp-exec <kind> <name>").description(
|
|
3623
|
+
"Run one tool or slash command of the omp extension (used by .omp/extensions/skaile.ts)"
|
|
3624
|
+
).option("--project-dir <path>", "Project directory", process.cwd()).action(async (kind, name, opts) => {
|
|
3625
|
+
process.exitCode = await runOmpExec(kind, name, path22__default.resolve(opts.projectDir));
|
|
3626
|
+
});
|
|
3389
3627
|
cmd.command("hook <event>").description(
|
|
3390
3628
|
"Run a Claude Code lifecycle hook (session-start | session-end | user-prompt-submit)"
|
|
3391
3629
|
).action(async (event) => {
|
|
3392
3630
|
try {
|
|
3393
3631
|
if (!HOOK_EVENTS.includes(event)) {
|
|
3394
3632
|
process.stderr.write(
|
|
3395
|
-
`
|
|
3633
|
+
`integration hook: unknown event '${event}' (expected: ${HOOK_EVENTS.join(" | ")})
|
|
3396
3634
|
`
|
|
3397
3635
|
);
|
|
3398
3636
|
} else {
|
|
@@ -3400,7 +3638,7 @@ function makeIntegrationCommand() {
|
|
|
3400
3638
|
}
|
|
3401
3639
|
} catch (err2) {
|
|
3402
3640
|
process.stderr.write(
|
|
3403
|
-
`
|
|
3641
|
+
`integration hook ${event} warning: ${err2 instanceof Error ? err2.message : String(err2)}
|
|
3404
3642
|
`
|
|
3405
3643
|
);
|
|
3406
3644
|
}
|
|
@@ -3427,7 +3665,7 @@ function unfinishedGitState(dir) {
|
|
|
3427
3665
|
for (const [entry, state2] of Object.entries(UNFINISHED_GIT_ENTRIES)) {
|
|
3428
3666
|
const p6 = spawnSync("git", ["rev-parse", "--git-path", entry], { cwd: dir, encoding: "utf-8" });
|
|
3429
3667
|
if (p6.status !== 0) return "the git directory could not be read";
|
|
3430
|
-
if (fs8.existsSync(
|
|
3668
|
+
if (fs8.existsSync(path22.resolve(dir, p6.stdout.trim()))) return state2;
|
|
3431
3669
|
}
|
|
3432
3670
|
return null;
|
|
3433
3671
|
}
|
|
@@ -3442,7 +3680,7 @@ async function reindexLibrary(lib, library, name) {
|
|
|
3442
3680
|
lib.path,
|
|
3443
3681
|
resolved.publisher,
|
|
3444
3682
|
registry,
|
|
3445
|
-
{ check: (e) => checkAssetFile(e.source, e.kind, registry) }
|
|
3683
|
+
{ check: (e) => checkAssetFile(e.source, e.kind, registry, lib.path) }
|
|
3446
3684
|
);
|
|
3447
3685
|
const manifest = loadSkPublishManifest(lib.path);
|
|
3448
3686
|
for (const a of unknownKind) {
|
|
@@ -3454,19 +3692,25 @@ async function reindexLibrary(lib, library, name) {
|
|
|
3454
3692
|
const ref = manifest ? assetEntryRef(a, manifest) : `${a.kind}:${a.name}`;
|
|
3455
3693
|
logInfo(`Removed manifest entry ${ref} (root ${a.root} is gone)`);
|
|
3456
3694
|
}
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3695
|
+
const invalidVersion = skipped.filter((x) => x.reason === "invalid-version");
|
|
3696
|
+
for (const s of invalidVersion) {
|
|
3697
|
+
const found = checkAssetFile(path22.join(lib.path, s.file), s.kind, registry).find(
|
|
3698
|
+
(f) => f.text.startsWith("version ")
|
|
3699
|
+
);
|
|
3700
|
+
const detail = found?.text ?? s.detail;
|
|
3701
|
+
const hint = detail.includes("Write it quoted") ? "" : " Set a valid `metadata.version` (e.g. 0.1.0).";
|
|
3702
|
+
logErr(
|
|
3703
|
+
`${s.kind}:${s.name} skipped: ${detail}.${hint} Re-run \`skaile library index ${name}\` after the fix.`
|
|
3460
3704
|
);
|
|
3461
3705
|
}
|
|
3462
3706
|
const duplicates = skipped.filter((x) => x.reason === "duplicate");
|
|
3463
3707
|
for (const s of duplicates) {
|
|
3464
|
-
logErr(duplicateAssetMessage(s.kind, s.name,
|
|
3708
|
+
logErr(duplicateAssetMessage(s.kind, s.name, path22.dirname(s.file), s.detail, name));
|
|
3465
3709
|
}
|
|
3466
3710
|
for (const s of failed) {
|
|
3467
3711
|
for (const f of s.findings) logErr(`${s.file} [${f.tag}] \u2014 ${f.text}`);
|
|
3468
3712
|
}
|
|
3469
|
-
const duplicateFiles = new Set(duplicates.map((s) =>
|
|
3713
|
+
const duplicateFiles = new Set(duplicates.map((s) => path22.resolve(lib.path, s.file)));
|
|
3470
3714
|
const skippedKeys = new Set(
|
|
3471
3715
|
[
|
|
3472
3716
|
...skipped.filter((s) => s.reason !== "duplicate"),
|
|
@@ -3474,7 +3718,7 @@ async function reindexLibrary(lib, library, name) {
|
|
|
3474
3718
|
].map((s) => `${s.kind}:${s.name}`)
|
|
3475
3719
|
);
|
|
3476
3720
|
const res = await indexLibrary(lib, library, {
|
|
3477
|
-
exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(
|
|
3721
|
+
exclude: (a) => skippedKeys.has(`${a.kind}:${a.name}`) || duplicateFiles.has(path22.resolve(a.manifestPath))
|
|
3478
3722
|
});
|
|
3479
3723
|
const unparsable = res.errors.filter((e) => e.includes("ManifestSchemaError:"));
|
|
3480
3724
|
for (const e of res.errors) (unparsable.includes(e) ? logErr : logWarn)(e);
|
|
@@ -3486,14 +3730,21 @@ async function reindexLibrary(lib, library, name) {
|
|
|
3486
3730
|
}
|
|
3487
3731
|
for (const p6 of badRequires) logErr(`${p6.asset}: ${p6.message}`);
|
|
3488
3732
|
for (const w of await unresolvedManifestDependencies(lib.path)) logWarn(w);
|
|
3489
|
-
|
|
3733
|
+
const skippedUnparsable = unparsable.length + syncUnparsable.length;
|
|
3734
|
+
const failing = skippedUnparsable + invalidVersion.length + badRequires.length + failed.length + duplicates.length;
|
|
3735
|
+
(failing > 0 ? logWarn : logOk)(`Indexed ${res.assetsUpdated} asset(s) from ${name}.`);
|
|
3490
3736
|
warnIgnoredDomainFiles(lib.path);
|
|
3491
3737
|
warnLegacyBundleFiles(lib.path);
|
|
3492
|
-
const skippedUnparsable = unparsable.length + syncUnparsable.length;
|
|
3493
3738
|
if (skippedUnparsable > 0) {
|
|
3494
3739
|
logErr(`${skippedUnparsable} asset(s) skipped: manifest could not be parsed.`);
|
|
3495
3740
|
process.exitCode = 1;
|
|
3496
3741
|
}
|
|
3742
|
+
if (invalidVersion.length > 0) {
|
|
3743
|
+
logErr(
|
|
3744
|
+
`${invalidVersion.length} asset(s) skipped: the version is not valid semver (listed above).`
|
|
3745
|
+
);
|
|
3746
|
+
process.exitCode = 1;
|
|
3747
|
+
}
|
|
3497
3748
|
if (badRequires.length > 0) {
|
|
3498
3749
|
logErr(
|
|
3499
3750
|
`${badRequires.length} invalid requires entr${badRequires.length === 1 ? "y" : "ies"} ignored: use the \`kind:@<publisher>/name[#version]\` form.`
|
|
@@ -3528,26 +3779,26 @@ function assertManifestEditableOrExit(libraryPath) {
|
|
|
3528
3779
|
}
|
|
3529
3780
|
async function assertLibraryPathFree(manager, dir, exceptId) {
|
|
3530
3781
|
const clash = (await manager.listLibraries()).find(
|
|
3531
|
-
(l) => l.id !== exceptId &&
|
|
3782
|
+
(l) => l.id !== exceptId && path22.resolve(l.path) === dir
|
|
3532
3783
|
);
|
|
3533
3784
|
if (clash) throw new Error(`${dir} is already registered as library "${clash.name}".`);
|
|
3534
3785
|
}
|
|
3535
3786
|
function canonicalDir(dir) {
|
|
3536
|
-
const abs =
|
|
3787
|
+
const abs = path22.resolve(dir);
|
|
3537
3788
|
const missing = [];
|
|
3538
3789
|
let existing = abs;
|
|
3539
3790
|
while (!fs8.existsSync(existing)) {
|
|
3540
|
-
const parent =
|
|
3791
|
+
const parent = path22.dirname(existing);
|
|
3541
3792
|
if (parent === existing) return abs;
|
|
3542
|
-
missing.unshift(
|
|
3793
|
+
missing.unshift(path22.basename(existing));
|
|
3543
3794
|
existing = parent;
|
|
3544
3795
|
}
|
|
3545
|
-
return
|
|
3796
|
+
return path22.join(fs8.realpathSync(existing), ...missing);
|
|
3546
3797
|
}
|
|
3547
3798
|
function refuseGlobalInstallFolder(name, dir) {
|
|
3548
3799
|
const reserved = globalInstallDir();
|
|
3549
|
-
const rel =
|
|
3550
|
-
const inside = rel === "" || !rel.startsWith("..") && !
|
|
3800
|
+
const rel = path22.relative(canonicalDir(reserved).toLowerCase(), canonicalDir(dir).toLowerCase());
|
|
3801
|
+
const inside = rel === "" || !rel.startsWith("..") && !path22.isAbsolute(rel);
|
|
3551
3802
|
if (name?.toLowerCase() === GLOBAL_INSTALL_DIR_NAME || inside) {
|
|
3552
3803
|
logErr(
|
|
3553
3804
|
`"${GLOBAL_INSTALL_DIR_NAME}" is reserved: ${reserved} holds assets from \`skaile install\`, not a library you author.`
|
|
@@ -3557,8 +3808,8 @@ function refuseGlobalInstallFolder(name, dir) {
|
|
|
3557
3808
|
}
|
|
3558
3809
|
async function refuseNestedLibraryPath(manager, dir, exceptId) {
|
|
3559
3810
|
const within = (parent, child) => {
|
|
3560
|
-
const rel =
|
|
3561
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
3811
|
+
const rel = path22.relative(parent, child);
|
|
3812
|
+
return rel === "" || !rel.startsWith("..") && !path22.isAbsolute(rel);
|
|
3562
3813
|
};
|
|
3563
3814
|
const target = canonicalDir(dir).toLowerCase();
|
|
3564
3815
|
const librariesDir = resolveLibraryDir();
|
|
@@ -3595,7 +3846,7 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
|
|
|
3595
3846
|
}
|
|
3596
3847
|
};
|
|
3597
3848
|
let probe = destDir;
|
|
3598
|
-
while (!exists(probe)) probe =
|
|
3849
|
+
while (!exists(probe)) probe = path22.dirname(probe);
|
|
3599
3850
|
let realProbe;
|
|
3600
3851
|
try {
|
|
3601
3852
|
realProbe = fs8.realpathSync(probe);
|
|
@@ -3608,9 +3859,9 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
|
|
|
3608
3859
|
process.exit(1);
|
|
3609
3860
|
}
|
|
3610
3861
|
const realRoot = canonicalDir(libRoot);
|
|
3611
|
-
const realDest =
|
|
3612
|
-
const rel =
|
|
3613
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
3862
|
+
const realDest = path22.join(realProbe, path22.relative(probe, destDir));
|
|
3863
|
+
const rel = path22.relative(realRoot, realDest);
|
|
3864
|
+
if (rel === ".." || rel.startsWith(`..${path22.sep}`) || path22.isAbsolute(rel)) {
|
|
3614
3865
|
logErr(
|
|
3615
3866
|
`--dir "${given}" must stay inside the library (${realRoot}): it resolves to ${realDest}.`
|
|
3616
3867
|
);
|
|
@@ -3618,7 +3869,7 @@ function assertCreateDirInsideLibrary(libRoot, destDir, given) {
|
|
|
3618
3869
|
}
|
|
3619
3870
|
}
|
|
3620
3871
|
function adoptWritesManifest(libPath) {
|
|
3621
|
-
if (!fs8.existsSync(
|
|
3872
|
+
if (!fs8.existsSync(path22.join(libPath, SKAILE_MANIFEST_FILENAME))) return true;
|
|
3622
3873
|
const manifest = loadSkPublishManifest(libPath);
|
|
3623
3874
|
if (!manifest || manifest.source || (manifest.assets ?? []).length > 0) return false;
|
|
3624
3875
|
return manifestPublisherProblems(libPath).length === 0;
|
|
@@ -3672,17 +3923,17 @@ function requireValidLibraryName(name) {
|
|
|
3672
3923
|
var LOCAL_OWNERSHIP_REASON = "ownership only governs sync with a git remote, and a local library is always owned by you.";
|
|
3673
3924
|
function pruneEmptyLibraryParents(libPath) {
|
|
3674
3925
|
const root = canonicalDir(resolveLibraryDir());
|
|
3675
|
-
let dir =
|
|
3926
|
+
let dir = path22.dirname(path22.resolve(libPath));
|
|
3676
3927
|
for (; ; ) {
|
|
3677
|
-
const rel =
|
|
3678
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
3928
|
+
const rel = path22.relative(root, canonicalDir(dir));
|
|
3929
|
+
if (rel === "" || rel.startsWith("..") || path22.isAbsolute(rel)) return;
|
|
3679
3930
|
if (!fs8.existsSync(dir) || fs8.readdirSync(dir).length > 0) return;
|
|
3680
3931
|
fs8.rmdirSync(dir);
|
|
3681
|
-
dir =
|
|
3932
|
+
dir = path22.dirname(dir);
|
|
3682
3933
|
}
|
|
3683
3934
|
}
|
|
3684
3935
|
async function warnIfNotGithubRemote(name, url) {
|
|
3685
|
-
const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-
|
|
3936
|
+
const { isGithubRemote, notGithubRemoteMessage } = await import('../library-publish-DI4Q5UOG.js');
|
|
3686
3937
|
if (!isGithubRemote(url)) logWarn(notGithubRemoteMessage(name, url));
|
|
3687
3938
|
}
|
|
3688
3939
|
function scaffoldLibraryFiles(dir, name) {
|
|
@@ -3714,7 +3965,7 @@ by the same ref.
|
|
|
3714
3965
|
];
|
|
3715
3966
|
const written = [];
|
|
3716
3967
|
for (const [file, content] of files) {
|
|
3717
|
-
const target =
|
|
3968
|
+
const target = path22.join(dir, file);
|
|
3718
3969
|
if (fs8.existsSync(target)) continue;
|
|
3719
3970
|
fs8.writeFileSync(target, content, "utf8");
|
|
3720
3971
|
written.push(file);
|
|
@@ -3782,7 +4033,10 @@ function makeLibraryCommand() {
|
|
|
3782
4033
|
console.log(` ${S.label("manifestGen")} ${l.manifestGenerated}`);
|
|
3783
4034
|
console.log(` ${S.label("backendConfig")} ${JSON.stringify(l.backendConfig)}`);
|
|
3784
4035
|
console.log();
|
|
3785
|
-
if (libraryDirMissing(l))
|
|
4036
|
+
if (libraryDirMissing(l)) {
|
|
4037
|
+
logErr(missingLibraryDirMessage(l));
|
|
4038
|
+
process.exitCode = 1;
|
|
4039
|
+
}
|
|
3786
4040
|
} finally {
|
|
3787
4041
|
close();
|
|
3788
4042
|
}
|
|
@@ -3801,7 +4055,7 @@ function makeLibraryCommand() {
|
|
|
3801
4055
|
opts.path ??= gone.path;
|
|
3802
4056
|
}
|
|
3803
4057
|
const ownership = flagged[0] ?? gone?.ownership ?? "owner";
|
|
3804
|
-
const libPath = opts.path ?
|
|
4058
|
+
const libPath = opts.path ? path22.resolve(opts.path) : path22.join(resolveLibraryDir(), name);
|
|
3805
4059
|
refuseGlobalInstallFolder(name, libPath);
|
|
3806
4060
|
if (fs8.existsSync(libPath) && !fs8.statSync(libPath).isDirectory()) {
|
|
3807
4061
|
logErr(`${libPath} exists and is not a directory.`);
|
|
@@ -3903,7 +4157,10 @@ function makeLibraryCommand() {
|
|
|
3903
4157
|
}
|
|
3904
4158
|
}
|
|
3905
4159
|
);
|
|
3906
|
-
cmd.command("link <name> <git-url>").description("Attach a github remote to a local library (makes it store-publishable)").option(
|
|
4160
|
+
cmd.command("link <name> <git-url>").description("Attach a github remote to a local library (makes it store-publishable)").option(
|
|
4161
|
+
"--branch <name>",
|
|
4162
|
+
"Branch to track (default: the checked-out branch of an existing repo, else main)"
|
|
4163
|
+
).action(async (name, url, opts) => {
|
|
3907
4164
|
const { manager, close } = await openLibraryManager();
|
|
3908
4165
|
try {
|
|
3909
4166
|
const lib = await manager.requireLibraryDir(name);
|
|
@@ -3913,11 +4170,16 @@ function makeLibraryCommand() {
|
|
|
3913
4170
|
);
|
|
3914
4171
|
process.exit(1);
|
|
3915
4172
|
}
|
|
3916
|
-
|
|
3917
|
-
|
|
4173
|
+
const head = isGitRepo(lib.path) ? spawnSync("git", ["symbolic-ref", "--short", "-q", "HEAD"], {
|
|
4174
|
+
cwd: lib.path,
|
|
4175
|
+
encoding: "utf-8"
|
|
4176
|
+
}) : void 0;
|
|
4177
|
+
const branch = opts.branch ?? (head?.status === 0 && head.stdout.trim() || "main");
|
|
4178
|
+
ensureGitRepo(lib.path, url, branch);
|
|
4179
|
+
trackOriginBranch(lib.path, branch, { fetch: true });
|
|
3918
4180
|
await manager.updateLibrary(name, {
|
|
3919
4181
|
backend: "git",
|
|
3920
|
-
backendConfig: { url, branch
|
|
4182
|
+
backendConfig: { url, branch, authHint: "ssh" }
|
|
3921
4183
|
});
|
|
3922
4184
|
logOk(`Library "${name}" linked to ${url}.`);
|
|
3923
4185
|
await warnIfNotGithubRemote(name, url);
|
|
@@ -3958,10 +4220,10 @@ function makeLibraryCommand() {
|
|
|
3958
4220
|
exitOnManifestPublisherProblems(target.path, target.name);
|
|
3959
4221
|
const effectiveKind = opts.kind ?? kind;
|
|
3960
4222
|
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir: process.cwd() });
|
|
3961
|
-
const libRoot =
|
|
3962
|
-
const destDir = opts.dir ?
|
|
3963
|
-
const relDest =
|
|
3964
|
-
if (relDest === ".." || relDest.startsWith(`..${
|
|
4223
|
+
const libRoot = path22.resolve(target.path);
|
|
4224
|
+
const destDir = opts.dir ? path22.resolve(libRoot, opts.dir) : libRoot;
|
|
4225
|
+
const relDest = path22.relative(libRoot, destDir);
|
|
4226
|
+
if (relDest === ".." || relDest.startsWith(`..${path22.sep}`) || path22.isAbsolute(relDest)) {
|
|
3965
4227
|
logErr(`--dir "${opts.dir}" must stay inside the library (${libRoot}).`);
|
|
3966
4228
|
process.exit(1);
|
|
3967
4229
|
}
|
|
@@ -3970,11 +4232,11 @@ function makeLibraryCommand() {
|
|
|
3970
4232
|
libRoot,
|
|
3971
4233
|
effectiveKind,
|
|
3972
4234
|
name,
|
|
3973
|
-
|
|
4235
|
+
path22.relative(libRoot, path22.join(destDir, name))
|
|
3974
4236
|
);
|
|
3975
4237
|
if (taken) {
|
|
3976
4238
|
logErr(
|
|
3977
|
-
`${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${
|
|
4239
|
+
`${effectiveKind}:${name} already exists at "${taken}" \u2014 creating it again under "${path22.relative(libRoot, destDir) || "."}" would re-point the manifest entry. Pick another name.`
|
|
3978
4240
|
);
|
|
3979
4241
|
process.exit(1);
|
|
3980
4242
|
}
|
|
@@ -3984,7 +4246,7 @@ function makeLibraryCommand() {
|
|
|
3984
4246
|
process.exit(1);
|
|
3985
4247
|
}
|
|
3986
4248
|
logOk(`Created ${effectiveKind}: ${pc5.dim(res.path)}`);
|
|
3987
|
-
if (opts.description === void 0
|
|
4249
|
+
if (opts.description === void 0) {
|
|
3988
4250
|
logWarn(
|
|
3989
4251
|
`Description is a TODO placeholder \u2014 edit it (what the ${effectiveKind} does and when to use it) or \`skaile validate\` will fail.`
|
|
3990
4252
|
);
|
|
@@ -4023,12 +4285,16 @@ function makeLibraryCommand() {
|
|
|
4023
4285
|
}
|
|
4024
4286
|
});
|
|
4025
4287
|
async function renameLibrary(manager, lib, newName) {
|
|
4288
|
+
if (libraryDirMissing(lib)) {
|
|
4289
|
+
logErr(missingLibraryDirMessage(lib));
|
|
4290
|
+
process.exit(1);
|
|
4291
|
+
}
|
|
4026
4292
|
requireValidLibraryName(newName);
|
|
4027
4293
|
if (await manager.getLibrary(newName)) {
|
|
4028
4294
|
logErr(`A library named "${newName}" is already registered.`);
|
|
4029
4295
|
process.exit(1);
|
|
4030
4296
|
}
|
|
4031
|
-
const newPath =
|
|
4297
|
+
const newPath = path22.join(path22.dirname(lib.path), newName);
|
|
4032
4298
|
refuseGlobalInstallFolder(newName, newPath);
|
|
4033
4299
|
if (fs8.existsSync(newPath)) {
|
|
4034
4300
|
logErr(`Target directory already exists: ${newPath}`);
|
|
@@ -4114,7 +4380,7 @@ function makeLibraryCommand() {
|
|
|
4114
4380
|
}
|
|
4115
4381
|
patch.isDefault = false;
|
|
4116
4382
|
} else if (field === "path") {
|
|
4117
|
-
const dir =
|
|
4383
|
+
const dir = path22.resolve(value);
|
|
4118
4384
|
if (!fs8.existsSync(dir) || !fs8.statSync(dir).isDirectory()) {
|
|
4119
4385
|
logErr(`Directory does not exist: ${dir}. \`library set path=\` does not move files.`);
|
|
4120
4386
|
process.exit(1);
|
|
@@ -4326,16 +4592,16 @@ function makeLibraryCommand() {
|
|
|
4326
4592
|
"With --create-repo: create the repo private (the store only accepts public repos)"
|
|
4327
4593
|
).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(
|
|
4328
4594
|
async (lib, opts) => {
|
|
4329
|
-
const { runLibraryPublish } = await import('../library-publish-
|
|
4595
|
+
const { runLibraryPublish } = await import('../library-publish-DI4Q5UOG.js');
|
|
4330
4596
|
await withStoreErrorHandling(() => runLibraryPublish(lib, opts));
|
|
4331
4597
|
}
|
|
4332
4598
|
);
|
|
4333
4599
|
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) => {
|
|
4334
|
-
const { runLibraryRegister } = await import('../library-publish-
|
|
4600
|
+
const { runLibraryRegister } = await import('../library-publish-DI4Q5UOG.js');
|
|
4335
4601
|
await withStoreErrorHandling(() => runLibraryRegister(lib, opts));
|
|
4336
4602
|
});
|
|
4337
4603
|
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) => {
|
|
4338
|
-
const { runLibraryYank } = await import('../library-publish-
|
|
4604
|
+
const { runLibraryYank } = await import('../library-publish-DI4Q5UOG.js');
|
|
4339
4605
|
await withStoreErrorHandling(() => runLibraryYank(lib, opts));
|
|
4340
4606
|
});
|
|
4341
4607
|
return cmd;
|
|
@@ -4386,9 +4652,9 @@ async function printOverallStatus(projectDir, asJson) {
|
|
|
4386
4652
|
} catch {
|
|
4387
4653
|
secretsStrategy = "unavailable";
|
|
4388
4654
|
}
|
|
4389
|
-
const resolvedProjectDir =
|
|
4390
|
-
const hasWorkspaceConfig = existsSync(
|
|
4391
|
-
const hasLockFile = existsSync(
|
|
4655
|
+
const resolvedProjectDir = path22.resolve(projectDir);
|
|
4656
|
+
const hasWorkspaceConfig = existsSync(path22.join(resolvedProjectDir, "skaile.yaml"));
|
|
4657
|
+
const hasLockFile = existsSync(path22.join(resolvedProjectDir, "skaile.lock.yaml"));
|
|
4392
4658
|
let assignments = [];
|
|
4393
4659
|
if (hasWorkspaceConfig) {
|
|
4394
4660
|
try {
|
|
@@ -4995,7 +5261,7 @@ function scheduleSoftDepPreview() {
|
|
|
4995
5261
|
}
|
|
4996
5262
|
async function loadAssets() {
|
|
4997
5263
|
softDepPreviewCache.clear();
|
|
4998
|
-
const { gatherAssetFeeds } = await import('../asset-feeds-
|
|
5264
|
+
const { gatherAssetFeeds } = await import('../asset-feeds-AM6PSSGM.js');
|
|
4999
5265
|
const { entries, notes } = await gatherAssetFeeds(am, am.projectDir);
|
|
5000
5266
|
if (notes.length > 0) {
|
|
5001
5267
|
state.message = notes.map((n) => `[${n.feed}] ${n.message}`).join(" \u2022 ");
|
|
@@ -5003,7 +5269,7 @@ async function loadAssets() {
|
|
|
5003
5269
|
const installed = new Set(am.listDeployed().map((e) => `${e.kind}:${e.name}`));
|
|
5004
5270
|
let lock = null;
|
|
5005
5271
|
try {
|
|
5006
|
-
lock = readLock(
|
|
5272
|
+
lock = readLock(path22__default.join(am.projectDir, "skaile.lock.yaml"));
|
|
5007
5273
|
} catch {
|
|
5008
5274
|
}
|
|
5009
5275
|
const rows = buildAssetRows(
|
|
@@ -5025,7 +5291,7 @@ function rebuildSourceTree() {
|
|
|
5025
5291
|
rebuildVisibleSources();
|
|
5026
5292
|
}
|
|
5027
5293
|
function sourceOrgRepo(s) {
|
|
5028
|
-
const parts = s.path.split(
|
|
5294
|
+
const parts = s.path.split(path22__default.sep).filter(Boolean);
|
|
5029
5295
|
if (parts.length < 2) return null;
|
|
5030
5296
|
return { org: parts[parts.length - 2], repo: parts[parts.length - 1] };
|
|
5031
5297
|
}
|
|
@@ -5199,13 +5465,13 @@ function reconcileCollapsedSets(rows) {
|
|
|
5199
5465
|
async function loadSourcesAndLibraries() {
|
|
5200
5466
|
try {
|
|
5201
5467
|
const [{ openLibraryManager: openLibraryManager2 }, { getGlobalCacheDir: getGlobalCacheDir2, globalSkaileDir: globalSkaileDir2 }] = await Promise.all([
|
|
5202
|
-
import('../open-library-
|
|
5468
|
+
import('../open-library-N6ESO6IK.js'),
|
|
5203
5469
|
import('../core/index.js')
|
|
5204
5470
|
]);
|
|
5205
5471
|
const { manager, library, close } = await openLibraryManager2();
|
|
5206
5472
|
try {
|
|
5207
5473
|
const newRoot = getGlobalCacheDir2();
|
|
5208
|
-
const legacyRoot =
|
|
5474
|
+
const legacyRoot = path22__default.join(globalSkaileDir2(), "sources");
|
|
5209
5475
|
const isSourceRow = (l) => l.path.startsWith(newRoot) || l.path.startsWith(legacyRoot);
|
|
5210
5476
|
const libs = await manager.listLibraries();
|
|
5211
5477
|
const defs = await library.listAssetDefs();
|
|
@@ -5331,12 +5597,25 @@ function pendingCountsFor(match) {
|
|
|
5331
5597
|
}
|
|
5332
5598
|
return [add, remove];
|
|
5333
5599
|
}
|
|
5334
|
-
function
|
|
5335
|
-
|
|
5336
|
-
if (
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5600
|
+
function groupSelectionState(rows, pendingAdds, pendingRemoves) {
|
|
5601
|
+
const own = rows.filter((r) => assetRefOf(r) !== null);
|
|
5602
|
+
if (own.length === 0) return "empty";
|
|
5603
|
+
const refs = refsOf(own);
|
|
5604
|
+
if (refs.some((r) => pendingAdds.has(r))) return "add";
|
|
5605
|
+
if (refs.some((r) => pendingRemoves.has(r))) return "remove";
|
|
5606
|
+
return own.every((r) => r.installed) ? "installed" : "none";
|
|
5607
|
+
}
|
|
5608
|
+
function groupStatus(rows) {
|
|
5609
|
+
switch (groupSelectionState(rows, state.pendingAdds, state.pendingRemoves)) {
|
|
5610
|
+
case "add":
|
|
5611
|
+
return pc5.blue("+ ");
|
|
5612
|
+
case "remove":
|
|
5613
|
+
return pc5.red("- ");
|
|
5614
|
+
case "installed":
|
|
5615
|
+
return pc5.green("\u2713 ");
|
|
5616
|
+
default:
|
|
5617
|
+
return pc5.dim("\xB7 ");
|
|
5618
|
+
}
|
|
5340
5619
|
}
|
|
5341
5620
|
function renderHeaderLine(opts) {
|
|
5342
5621
|
const indicator = opts.collapsed ? "\u25B6" : "\u25BC";
|
|
@@ -5348,7 +5627,7 @@ function renderHeaderLine(opts) {
|
|
|
5348
5627
|
if (add > 0) count += pc5.green(`+${add}`);
|
|
5349
5628
|
if (remove > 0) count += pc5.red(`-${remove}`);
|
|
5350
5629
|
count += `/${total}`;
|
|
5351
|
-
const status4 = groupStatus(opts.
|
|
5630
|
+
const status4 = groupStatus(countRows.filter(opts.match));
|
|
5352
5631
|
const line = `${opts.indent}${status4}${indicator} ${opts.label} (${count} assets)`;
|
|
5353
5632
|
return opts.selected ? pc5.bgWhite(pc5.black(`${line} `.padEnd(state.cols))) : line;
|
|
5354
5633
|
}
|
|
@@ -5360,7 +5639,6 @@ function renderAssetRow(row, selected) {
|
|
|
5360
5639
|
indent: " ",
|
|
5361
5640
|
collapsed: state.collapsedOrigins.has(origin),
|
|
5362
5641
|
match: (r) => isAsset(r) && rowOrigin(r) === origin,
|
|
5363
|
-
refs: originAssetRefs(state.assetRows, origin),
|
|
5364
5642
|
label: `${meta.icon} ${pc5.bold(pc5.cyan(meta.label))}`,
|
|
5365
5643
|
selected
|
|
5366
5644
|
});
|
|
@@ -5371,7 +5649,6 @@ function renderAssetRow(row, selected) {
|
|
|
5371
5649
|
indent: " ".repeat(3),
|
|
5372
5650
|
collapsed: state.collapsedSources.has(srcKey(origin, row.source)),
|
|
5373
5651
|
match: (r) => isAsset(r) && inSource(r, origin, row.source),
|
|
5374
|
-
refs: sourceAssetRefs(state.assetRows, origin, row.source),
|
|
5375
5652
|
label: pc5.bold(pc5.cyan(row.source)),
|
|
5376
5653
|
selected
|
|
5377
5654
|
});
|
|
@@ -5383,7 +5660,6 @@ function renderAssetRow(row, selected) {
|
|
|
5383
5660
|
indent: " ".repeat(5),
|
|
5384
5661
|
collapsed: state.collapsedPlugins.has(pluginKey(origin, row.source, plugin)),
|
|
5385
5662
|
match: (r) => isAsset(r) && inPlugin(r, origin, row.source, plugin),
|
|
5386
|
-
refs: pluginAssetRefs(state.assetRows, origin, row.source, plugin),
|
|
5387
5663
|
label: pluginHeaderLabel(plugin),
|
|
5388
5664
|
selected
|
|
5389
5665
|
});
|
|
@@ -5426,7 +5702,6 @@ function renderSourceTreeRow(row, selected) {
|
|
|
5426
5702
|
indent: " ".repeat(3),
|
|
5427
5703
|
collapsed: state.collapsedSourceOrgs.has(org),
|
|
5428
5704
|
match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org,
|
|
5429
|
-
refs: sourceOrgRefs(state.sourceTreeRows, org),
|
|
5430
5705
|
label: pc5.bold(pc5.cyan(org)),
|
|
5431
5706
|
selected,
|
|
5432
5707
|
rows: state.sourceTreeRows
|
|
@@ -5439,7 +5714,6 @@ function renderSourceTreeRow(row, selected) {
|
|
|
5439
5714
|
indent: " ".repeat(5),
|
|
5440
5715
|
collapsed: state.collapsedSourceRepos.has(repoKey(org, repo)),
|
|
5441
5716
|
match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo,
|
|
5442
|
-
refs: sourceRepoRefs(state.sourceTreeRows, org, repo),
|
|
5443
5717
|
label: pc5.bold(repo),
|
|
5444
5718
|
selected,
|
|
5445
5719
|
rows: state.sourceTreeRows
|
|
@@ -5453,7 +5727,6 @@ function renderSourceTreeRow(row, selected) {
|
|
|
5453
5727
|
indent: " ".repeat(7),
|
|
5454
5728
|
collapsed: state.collapsedSourcePlugins.has(srcPluginKey(org, repo, plugin)),
|
|
5455
5729
|
match: (r) => isAsset(r) && rowOrigin(r) === "source" && rowOrg(r) === org && rowGroup(r) === repo && r.plugin === plugin,
|
|
5456
|
-
refs: sourcePluginRefs(state.sourceTreeRows, org, repo, plugin),
|
|
5457
5730
|
label: pluginHeaderLabel(plugin),
|
|
5458
5731
|
selected,
|
|
5459
5732
|
rows: state.sourceTreeRows
|
|
@@ -5474,7 +5747,6 @@ function renderLibraryTreeRow(row, selected) {
|
|
|
5474
5747
|
indent: " ".repeat(3),
|
|
5475
5748
|
collapsed: state.collapsedLibraryGroups.has(group),
|
|
5476
5749
|
match: (r) => isAsset(r) && rowOrigin(r) === "library" && rowGroup(r) === group,
|
|
5477
|
-
refs: libraryGroupRefs(state.libraryTreeRows, group),
|
|
5478
5750
|
label: pc5.bold(pc5.cyan(group)),
|
|
5479
5751
|
selected,
|
|
5480
5752
|
rows: state.libraryTreeRows
|
|
@@ -5487,7 +5759,6 @@ function renderLibraryTreeRow(row, selected) {
|
|
|
5487
5759
|
indent: " ".repeat(5),
|
|
5488
5760
|
collapsed: state.collapsedLibraryPlugins.has(libPluginKey(group, plugin)),
|
|
5489
5761
|
match: (r) => isAsset(r) && inPlugin(r, "library", group, plugin),
|
|
5490
|
-
refs: pluginAssetRefs(state.libraryTreeRows, "library", group, plugin),
|
|
5491
5762
|
label: pluginHeaderLabel(plugin),
|
|
5492
5763
|
selected,
|
|
5493
5764
|
rows: state.libraryTreeRows
|
|
@@ -6160,19 +6431,19 @@ async function run(projectDir) {
|
|
|
6160
6431
|
}
|
|
6161
6432
|
function makeManageCommand() {
|
|
6162
6433
|
return new Command("manage").description("Interactive TUI for managing assets, sources, and libraries").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
6163
|
-
await run(
|
|
6434
|
+
await run(path22__default.resolve(opts.projectDir));
|
|
6164
6435
|
});
|
|
6165
6436
|
}
|
|
6166
6437
|
function makeMcpServerCommand() {
|
|
6167
6438
|
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) => {
|
|
6168
|
-
const
|
|
6169
|
-
const projectDir =
|
|
6170
|
-
const { LogStore, StdoutSink, registerLogStore } = await import('../core/logging.js');
|
|
6171
|
-
|
|
6172
|
-
new
|
|
6439
|
+
const path44 = await import('path');
|
|
6440
|
+
const projectDir = path44.default.resolve(opts.projectDir);
|
|
6441
|
+
const { LogStore: LogStore2, StdoutSink: StdoutSink2, registerLogStore: registerLogStore2 } = await import('../core/logging.js');
|
|
6442
|
+
registerLogStore2(
|
|
6443
|
+
new LogStore2({
|
|
6173
6444
|
sessionId: "mcp-server",
|
|
6174
6445
|
level: "info",
|
|
6175
|
-
sinks: [new
|
|
6446
|
+
sinks: [new StdoutSink2({ stream: "stderr" })]
|
|
6176
6447
|
})
|
|
6177
6448
|
);
|
|
6178
6449
|
const { WorkspacePlugin } = await import('../workspace-plugin/index.js');
|
|
@@ -6213,10 +6484,10 @@ function walkFiles(root, match) {
|
|
|
6213
6484
|
return;
|
|
6214
6485
|
}
|
|
6215
6486
|
for (const entry of entries) {
|
|
6216
|
-
const full =
|
|
6487
|
+
const full = path22__default.join(dir, entry.name);
|
|
6217
6488
|
if (entry.isDirectory()) {
|
|
6218
6489
|
if (SKIPPED_DIRS.has(entry.name)) continue;
|
|
6219
|
-
if (entry.name === "cache" &&
|
|
6490
|
+
if (entry.name === "cache" && path22__default.basename(dir) === ".skaile") continue;
|
|
6220
6491
|
visit(full);
|
|
6221
6492
|
} else if (entry.isFile() && match(entry.name)) {
|
|
6222
6493
|
out.push(full);
|
|
@@ -6234,14 +6505,14 @@ function applyChanges2(changes) {
|
|
|
6234
6505
|
switch (change.type) {
|
|
6235
6506
|
case "write":
|
|
6236
6507
|
case "create":
|
|
6237
|
-
mkdirSync(
|
|
6508
|
+
mkdirSync(path22__default.dirname(change.path), { recursive: true });
|
|
6238
6509
|
writeFileSync(change.path, change.after, "utf-8");
|
|
6239
6510
|
break;
|
|
6240
6511
|
case "delete":
|
|
6241
6512
|
rmSync(change.path, { force: true });
|
|
6242
6513
|
break;
|
|
6243
6514
|
case "move":
|
|
6244
|
-
mkdirSync(
|
|
6515
|
+
mkdirSync(path22__default.dirname(change.to), { recursive: true });
|
|
6245
6516
|
writeFileSync(change.to, change.after, "utf-8");
|
|
6246
6517
|
rmSync(change.from, { force: true });
|
|
6247
6518
|
break;
|
|
@@ -6334,7 +6605,7 @@ function unifiedDiff(before, after, oldLabel, newLabel, context = 3) {
|
|
|
6334
6605
|
return `${out.join("\n")}
|
|
6335
6606
|
`;
|
|
6336
6607
|
}
|
|
6337
|
-
var posix = (p6) => p6.split(
|
|
6608
|
+
var posix = (p6) => p6.split(path22__default.sep).join("/");
|
|
6338
6609
|
function colorizeDiff(diff) {
|
|
6339
6610
|
return diff.split("\n").map((line) => {
|
|
6340
6611
|
if (line.startsWith("+++") || line.startsWith("---")) return S.bold(line);
|
|
@@ -6345,7 +6616,7 @@ function colorizeDiff(diff) {
|
|
|
6345
6616
|
}).join("\n");
|
|
6346
6617
|
}
|
|
6347
6618
|
function renderChange(change, base) {
|
|
6348
|
-
const rel = (p6) => posix(
|
|
6619
|
+
const rel = (p6) => posix(path22__default.relative(base, p6) || path22__default.basename(p6));
|
|
6349
6620
|
switch (change.type) {
|
|
6350
6621
|
case "write":
|
|
6351
6622
|
return unifiedDiff(
|
|
@@ -6372,7 +6643,7 @@ ${diff}`;
|
|
|
6372
6643
|
}
|
|
6373
6644
|
}
|
|
6374
6645
|
function changeLabel(change, base) {
|
|
6375
|
-
const rel = (p6) => posix(
|
|
6646
|
+
const rel = (p6) => posix(path22__default.relative(base, p6) || path22__default.basename(p6));
|
|
6376
6647
|
switch (change.type) {
|
|
6377
6648
|
case "write":
|
|
6378
6649
|
return `modify ${rel(change.path)}`;
|
|
@@ -6432,7 +6703,7 @@ function loadAsset(projectDir, id, ref) {
|
|
|
6432
6703
|
)
|
|
6433
6704
|
};
|
|
6434
6705
|
}
|
|
6435
|
-
const manifestPath =
|
|
6706
|
+
const manifestPath = path22__default.join(dir, AGENT_MANIFEST_FILE);
|
|
6436
6707
|
let text;
|
|
6437
6708
|
try {
|
|
6438
6709
|
text = fs8__default.readFileSync(manifestPath, "utf-8");
|
|
@@ -6619,7 +6890,7 @@ function findManifestCandidates(rootPath) {
|
|
|
6619
6890
|
return;
|
|
6620
6891
|
}
|
|
6621
6892
|
for (const entry of entries) {
|
|
6622
|
-
const fullPath =
|
|
6893
|
+
const fullPath = path22__default.join(dir, entry.name);
|
|
6623
6894
|
if (entry.isDirectory()) {
|
|
6624
6895
|
if (!SKIP_DIRS.has(entry.name)) walk(fullPath);
|
|
6625
6896
|
} else if (entry.isFile()) {
|
|
@@ -6635,30 +6906,11 @@ function findManifestCandidates(rootPath) {
|
|
|
6635
6906
|
walk(rootPath);
|
|
6636
6907
|
return candidates;
|
|
6637
6908
|
}
|
|
6638
|
-
function checkManifestIdentity(kind, parsed) {
|
|
6639
|
-
if (parsed === null || typeof parsed !== "object") return null;
|
|
6640
|
-
const obj = parsed;
|
|
6641
|
-
const identity = kind === "flow" ? obj.id : obj.name;
|
|
6642
|
-
if (typeof identity !== "string" || identity.length === 0) return null;
|
|
6643
|
-
const publisher = typeof obj.publisher === "string" ? obj.publisher : void 0;
|
|
6644
|
-
if (publisher !== void 0) {
|
|
6645
|
-
try {
|
|
6646
|
-
parseAssetRef(`${kind}:@${publisher}/${identity}`);
|
|
6647
|
-
return null;
|
|
6648
|
-
} catch (e) {
|
|
6649
|
-
return e instanceof Error ? e.message : String(e);
|
|
6650
|
-
}
|
|
6651
|
-
}
|
|
6652
|
-
if (!isValidAssetName(identity)) {
|
|
6653
|
-
return `invalid asset ${kind === "flow" ? "id" : "name"} "${identity}" \u2014 ${ASSET_NAME_HINT}`;
|
|
6654
|
-
}
|
|
6655
|
-
return null;
|
|
6656
|
-
}
|
|
6657
6909
|
function parseManifestCandidate(c, absRoot) {
|
|
6658
6910
|
const content = fs8__default.readFileSync(c.filePath, "utf-8");
|
|
6659
6911
|
const res = parseManifestFile(c.filePath, content);
|
|
6660
6912
|
if (!res.ok) {
|
|
6661
|
-
logErr(`${
|
|
6913
|
+
logErr(`${path22__default.relative(absRoot, c.filePath)} [${c.kind}] \u2014 parse error: ${res.reason}`);
|
|
6662
6914
|
return { kind: "error" };
|
|
6663
6915
|
}
|
|
6664
6916
|
return {
|
|
@@ -6687,22 +6939,24 @@ function checkComposeKinds(parsed, registry) {
|
|
|
6687
6939
|
});
|
|
6688
6940
|
return diagnostics;
|
|
6689
6941
|
}
|
|
6942
|
+
function libraryRootOf(absRoot) {
|
|
6943
|
+
for (let dir = absRoot; ; dir = path22__default.dirname(dir)) {
|
|
6944
|
+
if (fs8__default.existsSync(path22__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
|
|
6945
|
+
if (path22__default.dirname(dir) === dir) return absRoot;
|
|
6946
|
+
}
|
|
6947
|
+
}
|
|
6690
6948
|
function validateManifestCandidate(c, parsed, body, absRoot, registry, strictConformance) {
|
|
6691
|
-
const relPath =
|
|
6949
|
+
const relPath = path22__default.relative(absRoot, c.filePath);
|
|
6692
6950
|
let errors = 0;
|
|
6693
6951
|
let warnings = 0;
|
|
6694
|
-
const
|
|
6695
|
-
if (identityError) {
|
|
6696
|
-
logErr(`${relPath} [${c.kind}] \u2014 ${identityError}`);
|
|
6697
|
-
errors++;
|
|
6698
|
-
}
|
|
6699
|
-
const dirName = path18__default.basename(path18__default.dirname(c.filePath));
|
|
6952
|
+
const dirName = path22__default.basename(path22__default.dirname(c.filePath));
|
|
6700
6953
|
const checked = checkAsset(
|
|
6701
6954
|
c.kind,
|
|
6702
6955
|
parsed ?? {},
|
|
6703
6956
|
body,
|
|
6704
6957
|
dirName,
|
|
6705
|
-
registry
|
|
6958
|
+
registry,
|
|
6959
|
+
fs8__default.readFileSync(c.filePath, "utf-8")
|
|
6706
6960
|
);
|
|
6707
6961
|
for (const f of checked.errors) {
|
|
6708
6962
|
logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
|
|
@@ -6718,7 +6972,17 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
|
|
|
6718
6972
|
warnings++;
|
|
6719
6973
|
}
|
|
6720
6974
|
}
|
|
6721
|
-
if (c.kind === "agent" &&
|
|
6975
|
+
if (c.kind === "agent" && parsed !== null && typeof parsed === "object") {
|
|
6976
|
+
for (const f of checkAgentFiles(
|
|
6977
|
+
parsed,
|
|
6978
|
+
path22__default.dirname(c.filePath),
|
|
6979
|
+
libraryRootOf(absRoot)
|
|
6980
|
+
)) {
|
|
6981
|
+
logErr(`${relPath} [${f.tag}] \u2014 ${f.text}`);
|
|
6982
|
+
errors++;
|
|
6983
|
+
}
|
|
6984
|
+
}
|
|
6985
|
+
if (c.kind === "agent" && path22__default.basename(c.filePath) === "agent.yaml") {
|
|
6722
6986
|
for (const d of [
|
|
6723
6987
|
...checkComposeKinds(parsed, registry),
|
|
6724
6988
|
...composeSlotDiagnostics(parsed),
|
|
@@ -6737,7 +7001,7 @@ function validateManifestCandidate(c, parsed, body, absRoot, registry, strictCon
|
|
|
6737
7001
|
return { errors, warnings };
|
|
6738
7002
|
}
|
|
6739
7003
|
function validateManifests(rootPath, strictConformance) {
|
|
6740
|
-
const absRoot =
|
|
7004
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6741
7005
|
if (!fs8__default.existsSync(absRoot)) {
|
|
6742
7006
|
logErr(`Path does not exist: ${absRoot}`);
|
|
6743
7007
|
return { total: 0, errors: 1, warnings: 0 };
|
|
@@ -6747,6 +7011,7 @@ function validateManifests(rootPath, strictConformance) {
|
|
|
6747
7011
|
let errors = 0;
|
|
6748
7012
|
let warnings = 0;
|
|
6749
7013
|
const seenIdentity = /* @__PURE__ */ new Map();
|
|
7014
|
+
const agentsToResolve = [];
|
|
6750
7015
|
for (const c of candidates) {
|
|
6751
7016
|
const parseResult = parseManifestCandidate(c, absRoot);
|
|
6752
7017
|
if (parseResult.kind === "error") {
|
|
@@ -6763,22 +7028,36 @@ function validateManifests(rootPath, strictConformance) {
|
|
|
6763
7028
|
);
|
|
6764
7029
|
errors += delta.errors;
|
|
6765
7030
|
warnings += delta.warnings;
|
|
7031
|
+
if (c.kind === "agent" && parseResult.parsed !== null && typeof parseResult.parsed === "object") {
|
|
7032
|
+
agentsToResolve.push({
|
|
7033
|
+
relPath: path22__default.relative(absRoot, c.filePath),
|
|
7034
|
+
parsed: parseResult.parsed
|
|
7035
|
+
});
|
|
7036
|
+
}
|
|
6766
7037
|
const obj = parseResult.parsed;
|
|
6767
7038
|
const identity = obj && typeof obj === "object" ? obj[c.kind === "flow" ? "id" : "name"] : null;
|
|
6768
7039
|
if (typeof identity === "string" && identity.length > 0) {
|
|
6769
|
-
const dir =
|
|
7040
|
+
const dir = path22__default.dirname(c.filePath);
|
|
6770
7041
|
const key = `${c.kind}:${identity}`;
|
|
6771
7042
|
const first = seenIdentity.get(key);
|
|
6772
7043
|
if (first === void 0) {
|
|
6773
7044
|
seenIdentity.set(key, dir);
|
|
6774
7045
|
} else if (first !== dir) {
|
|
6775
7046
|
logErr(
|
|
6776
|
-
`${
|
|
7047
|
+
`${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).`
|
|
6777
7048
|
);
|
|
6778
7049
|
errors++;
|
|
6779
7050
|
}
|
|
6780
7051
|
}
|
|
6781
7052
|
}
|
|
7053
|
+
const libraryPublisher = loadSkPublishManifest(libraryRootOf(absRoot))?.publisher;
|
|
7054
|
+
const hasAsset = (kind, name) => seenIdentity.has(`${kind}:${name}`);
|
|
7055
|
+
for (const agent of agentsToResolve) {
|
|
7056
|
+
for (const f of agentComposeRefAdvisories(agent.parsed, hasAsset, libraryPublisher)) {
|
|
7057
|
+
logWarn(`${agent.relPath} [${f.tag}] \u2014 ${f.text}`);
|
|
7058
|
+
warnings++;
|
|
7059
|
+
}
|
|
7060
|
+
}
|
|
6782
7061
|
return { total: candidates.length, errors, warnings };
|
|
6783
7062
|
}
|
|
6784
7063
|
function findWorkspaceManifests(rootPath) {
|
|
@@ -6791,7 +7070,7 @@ function findWorkspaceManifests(rootPath) {
|
|
|
6791
7070
|
return;
|
|
6792
7071
|
}
|
|
6793
7072
|
for (const entry of entries) {
|
|
6794
|
-
const full =
|
|
7073
|
+
const full = path22__default.join(dir, entry.name);
|
|
6795
7074
|
if (entry.isDirectory()) {
|
|
6796
7075
|
if (!SKIP_DIRS.has(entry.name)) walk(full);
|
|
6797
7076
|
} else if (entry.isFile() && /(^|\.)skaile\.yaml$/.test(entry.name)) {
|
|
@@ -6854,11 +7133,11 @@ function validateWorkspaceAssets(parsed, relPath) {
|
|
|
6854
7133
|
return errors;
|
|
6855
7134
|
}
|
|
6856
7135
|
function validateWorkspaceManifests(rootPath) {
|
|
6857
|
-
const absRoot =
|
|
7136
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6858
7137
|
const files = findWorkspaceManifests(absRoot);
|
|
6859
7138
|
let errors = 0;
|
|
6860
7139
|
for (const file of files) {
|
|
6861
|
-
const relPath =
|
|
7140
|
+
const relPath = path22__default.relative(absRoot, file);
|
|
6862
7141
|
let parsed;
|
|
6863
7142
|
try {
|
|
6864
7143
|
parsed = parse(fs8__default.readFileSync(file, "utf-8")) ?? {};
|
|
@@ -6869,7 +7148,7 @@ function validateWorkspaceManifests(rootPath) {
|
|
|
6869
7148
|
}
|
|
6870
7149
|
errors += validateWorkspaceRefs(collectWorkspaceRefFields(parsed), relPath);
|
|
6871
7150
|
errors += validateWorkspaceAssets(parsed, relPath);
|
|
6872
|
-
for (const d of checkAgentInstances(
|
|
7151
|
+
for (const d of checkAgentInstances(path22__default.dirname(file), parsed)) {
|
|
6873
7152
|
const line = `${relPath} [agents] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`;
|
|
6874
7153
|
if (d.severity === "error") {
|
|
6875
7154
|
logErr(line);
|
|
@@ -6878,11 +7157,16 @@ function validateWorkspaceManifests(rootPath) {
|
|
|
6878
7157
|
logWarn(line);
|
|
6879
7158
|
}
|
|
6880
7159
|
}
|
|
7160
|
+
for (const d of decodeSkaileYaml(fs8__default.readFileSync(file, "utf-8")).diagnostics) {
|
|
7161
|
+
if (d.code !== "connector_missing_driver") continue;
|
|
7162
|
+
logErr(`${relPath} [connectors] \u2014 ${d.code}: ${d.path ? `${d.path}: ` : ""}${d.message}`);
|
|
7163
|
+
errors++;
|
|
7164
|
+
}
|
|
6881
7165
|
}
|
|
6882
7166
|
return { total: files.length, errors };
|
|
6883
7167
|
}
|
|
6884
7168
|
function validatePublishManifestRoots(rootPath) {
|
|
6885
|
-
const absRoot =
|
|
7169
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6886
7170
|
const manifest = loadSkPublishManifest(absRoot);
|
|
6887
7171
|
if (!manifest) return 0;
|
|
6888
7172
|
const missing = missingRootAssets(absRoot, manifest);
|
|
@@ -6894,7 +7178,7 @@ function validatePublishManifestRoots(rootPath) {
|
|
|
6894
7178
|
return missing.length;
|
|
6895
7179
|
}
|
|
6896
7180
|
function validatePublishManifestRequires(rootPath) {
|
|
6897
|
-
const problems = manifestRequiresProblems(
|
|
7181
|
+
const problems = manifestRequiresProblems(path22__default.resolve(rootPath));
|
|
6898
7182
|
for (const p6 of problems) {
|
|
6899
7183
|
logErr(
|
|
6900
7184
|
`${SKAILE_MANIFEST_FILENAME} [assets] \u2014 ${p6.asset}: ${p6.message}. Use the \`kind:@<publisher>/name[#version]\` form.`
|
|
@@ -6903,18 +7187,27 @@ function validatePublishManifestRequires(rootPath) {
|
|
|
6903
7187
|
return problems.length;
|
|
6904
7188
|
}
|
|
6905
7189
|
function validatePublishManifestPublisherSlugs(rootPath) {
|
|
6906
|
-
const problems = manifestPublisherProblems(
|
|
7190
|
+
const problems = manifestPublisherProblems(path22__default.resolve(rootPath));
|
|
6907
7191
|
for (const message of problems) logErr(message);
|
|
6908
7192
|
return problems.length;
|
|
6909
7193
|
}
|
|
7194
|
+
function validatePublishManifestParses(rootPath) {
|
|
7195
|
+
try {
|
|
7196
|
+
assertManifestEditable(path22__default.resolve(rootPath));
|
|
7197
|
+
return 0;
|
|
7198
|
+
} catch (err2) {
|
|
7199
|
+
logErr(err2 instanceof Error ? err2.message : String(err2));
|
|
7200
|
+
return 1;
|
|
7201
|
+
}
|
|
7202
|
+
}
|
|
6910
7203
|
function validatePublishManifestVersions(rootPath) {
|
|
6911
|
-
const absRoot =
|
|
7204
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6912
7205
|
const manifest = loadSkPublishManifest(absRoot);
|
|
6913
7206
|
if (!manifest || manifest.source) return 0;
|
|
6914
7207
|
let warnings = 0;
|
|
6915
7208
|
for (const a of manifest.assets ?? []) {
|
|
6916
7209
|
if (!a.root || a.source || !a.version) continue;
|
|
6917
|
-
const file = findAssetManifestFile(
|
|
7210
|
+
const file = findAssetManifestFile(path22__default.join(absRoot, a.root), a.kind, a.name);
|
|
6918
7211
|
if (!file) continue;
|
|
6919
7212
|
const res = parseManifestFile(file, fs8__default.readFileSync(file, "utf-8"));
|
|
6920
7213
|
if (!res.ok) continue;
|
|
@@ -6924,7 +7217,7 @@ function validatePublishManifestVersions(rootPath) {
|
|
|
6924
7217
|
manifestVersionMismatchMessage(
|
|
6925
7218
|
assetEntryRef(a, manifest),
|
|
6926
7219
|
a.version,
|
|
6927
|
-
toPosix(
|
|
7220
|
+
toPosix(path22__default.relative(absRoot, file)),
|
|
6928
7221
|
fileVersion
|
|
6929
7222
|
)
|
|
6930
7223
|
);
|
|
@@ -6933,7 +7226,7 @@ function validatePublishManifestVersions(rootPath) {
|
|
|
6933
7226
|
return warnings;
|
|
6934
7227
|
}
|
|
6935
7228
|
function validatePublishManifestPublishers(rootPath) {
|
|
6936
|
-
const absRoot =
|
|
7229
|
+
const absRoot = path22__default.resolve(rootPath);
|
|
6937
7230
|
const manifest = loadSkPublishManifest(absRoot);
|
|
6938
7231
|
if (!manifest || manifest.source) return 0;
|
|
6939
7232
|
const bare = (p6) => p6.trim().replace(/^@/, "");
|
|
@@ -6941,7 +7234,7 @@ function validatePublishManifestPublishers(rootPath) {
|
|
|
6941
7234
|
for (const a of manifest.assets ?? []) {
|
|
6942
7235
|
const resolved = a.publisher ?? manifest.publisher;
|
|
6943
7236
|
if (!a.root || a.source || !resolved) continue;
|
|
6944
|
-
const file = findAssetManifestFile(
|
|
7237
|
+
const file = findAssetManifestFile(path22__default.join(absRoot, a.root), a.kind, a.name);
|
|
6945
7238
|
if (!file) continue;
|
|
6946
7239
|
const res = parseManifestFile(file, fs8__default.readFileSync(file, "utf-8"));
|
|
6947
7240
|
if (!res.ok) continue;
|
|
@@ -6949,7 +7242,7 @@ function validatePublishManifestPublishers(rootPath) {
|
|
|
6949
7242
|
const declared = meta !== null && typeof meta === "object" ? meta.publisher : null;
|
|
6950
7243
|
if (typeof declared !== "string" || bare(declared) === bare(resolved)) continue;
|
|
6951
7244
|
logWarn(
|
|
6952
|
-
`${toPosix(
|
|
7245
|
+
`${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}.`
|
|
6953
7246
|
);
|
|
6954
7247
|
warnings++;
|
|
6955
7248
|
}
|
|
@@ -6957,7 +7250,7 @@ function validatePublishManifestPublishers(rootPath) {
|
|
|
6957
7250
|
}
|
|
6958
7251
|
var EXCLUDED_PATHS = ["skaileup-shared/", "external/", "docs/"];
|
|
6959
7252
|
function toPosix(p6) {
|
|
6960
|
-
return p6.split(
|
|
7253
|
+
return p6.split(path22__default.sep).join("/");
|
|
6961
7254
|
}
|
|
6962
7255
|
function isExcludedPath(relPath) {
|
|
6963
7256
|
const rel = toPosix(relPath);
|
|
@@ -6973,8 +7266,8 @@ var VERSIONED_KINDS = {
|
|
|
6973
7266
|
};
|
|
6974
7267
|
function readAssetVersion(c) {
|
|
6975
7268
|
const kind = c.kind;
|
|
6976
|
-
const fileName =
|
|
6977
|
-
const dirName =
|
|
7269
|
+
const fileName = path22__default.basename(c.filePath);
|
|
7270
|
+
const dirName = path22__default.basename(path22__default.dirname(c.filePath));
|
|
6978
7271
|
const content = fs8__default.readFileSync(c.filePath, "utf-8");
|
|
6979
7272
|
if (c.filePath.endsWith(".md")) {
|
|
6980
7273
|
const res = parseManifestFile(c.filePath, content);
|
|
@@ -7013,21 +7306,21 @@ function collectAssetVersions(root) {
|
|
|
7013
7306
|
for (const c of findManifestCandidates(root)) {
|
|
7014
7307
|
if (!VERSIONED_KINDS[c.kind]) continue;
|
|
7015
7308
|
if (c.filePath.endsWith(".flow.json")) continue;
|
|
7016
|
-
if (isExcludedPath(
|
|
7309
|
+
if (isExcludedPath(path22__default.relative(root, c.filePath))) continue;
|
|
7017
7310
|
assets.push(readAssetVersion(c));
|
|
7018
7311
|
}
|
|
7019
7312
|
return assets;
|
|
7020
7313
|
}
|
|
7021
7314
|
function assetLocation(a, root) {
|
|
7022
|
-
return toPosix(
|
|
7315
|
+
return toPosix(path22__default.relative(root, a.filePath));
|
|
7023
7316
|
}
|
|
7024
7317
|
function findChangelogUnit(assetRelPath, root) {
|
|
7025
|
-
let dir =
|
|
7318
|
+
let dir = path22__default.posix.dirname(toPosix(assetRelPath));
|
|
7026
7319
|
for (; ; ) {
|
|
7027
7320
|
const candidate = dir === "." ? "CHANGELOG.md" : `${dir}/CHANGELOG.md`;
|
|
7028
|
-
if (fs8__default.existsSync(
|
|
7321
|
+
if (fs8__default.existsSync(path22__default.join(root, candidate))) return candidate;
|
|
7029
7322
|
if (dir === ".") return null;
|
|
7030
|
-
dir =
|
|
7323
|
+
dir = path22__default.posix.dirname(dir);
|
|
7031
7324
|
}
|
|
7032
7325
|
}
|
|
7033
7326
|
function checkChangelogUnits(modifiedFiles, root) {
|
|
@@ -7077,7 +7370,7 @@ function checkVersionBumps(assets, root) {
|
|
|
7077
7370
|
let warnings = 0;
|
|
7078
7371
|
for (const a of assets) {
|
|
7079
7372
|
if (!a.version) continue;
|
|
7080
|
-
const relPath = toPosix(
|
|
7373
|
+
const relPath = toPosix(path22__default.relative(root, a.filePath));
|
|
7081
7374
|
try {
|
|
7082
7375
|
const headContent = execFileSync("git", ["show", `HEAD:./${relPath}`], {
|
|
7083
7376
|
cwd: root,
|
|
@@ -7110,7 +7403,7 @@ function checkFlowVersionPins(assets, root) {
|
|
|
7110
7403
|
pins = flowSkillVersionPins(loadFlow(f.filePath));
|
|
7111
7404
|
} catch (err2) {
|
|
7112
7405
|
logWarn(
|
|
7113
|
-
`flow:${f.name} (${
|
|
7406
|
+
`flow:${f.name} (${path22__default.relative(root, f.filePath)}) \u2014 could not be read: ${err2 instanceof Error ? err2.message : err2}`
|
|
7114
7407
|
);
|
|
7115
7408
|
warnings++;
|
|
7116
7409
|
continue;
|
|
@@ -7128,19 +7421,34 @@ function checkFlowVersionPins(assets, root) {
|
|
|
7128
7421
|
}
|
|
7129
7422
|
function resolveCheckRoot(pathArg) {
|
|
7130
7423
|
if (pathArg) {
|
|
7131
|
-
const abs =
|
|
7424
|
+
const abs = path22__default.resolve(pathArg);
|
|
7132
7425
|
if (!fs8__default.existsSync(abs)) {
|
|
7133
7426
|
logErr(`Path does not exist: ${abs}`);
|
|
7134
7427
|
return null;
|
|
7135
7428
|
}
|
|
7136
7429
|
return abs;
|
|
7137
7430
|
}
|
|
7138
|
-
for (let dir = process.cwd(); ; dir =
|
|
7139
|
-
if (fs8__default.existsSync(
|
|
7140
|
-
if (
|
|
7431
|
+
for (let dir = process.cwd(); ; dir = path22__default.dirname(dir)) {
|
|
7432
|
+
if (fs8__default.existsSync(path22__default.join(dir, SKAILE_MANIFEST_FILENAME))) return dir;
|
|
7433
|
+
if (path22__default.dirname(dir) === dir) return AI_RESOURCES;
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
function isInGitWorkTree(root) {
|
|
7437
|
+
try {
|
|
7438
|
+
return execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
7439
|
+
cwd: root,
|
|
7440
|
+
encoding: "utf-8",
|
|
7441
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7442
|
+
}).trim() === "true";
|
|
7443
|
+
} catch {
|
|
7444
|
+
return false;
|
|
7141
7445
|
}
|
|
7142
7446
|
}
|
|
7143
|
-
function changedFiles(root, ref) {
|
|
7447
|
+
function changedFiles(root, ref, what, opts = {}) {
|
|
7448
|
+
if (!isInGitWorkTree(root)) {
|
|
7449
|
+
logErr(`${what} needs a git repository: ${root} is not inside a git work tree.`);
|
|
7450
|
+
return null;
|
|
7451
|
+
}
|
|
7144
7452
|
try {
|
|
7145
7453
|
const out = execFileSync(
|
|
7146
7454
|
"git",
|
|
@@ -7151,7 +7459,16 @@ function changedFiles(root, ref) {
|
|
|
7151
7459
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7152
7460
|
}
|
|
7153
7461
|
);
|
|
7154
|
-
|
|
7462
|
+
const changed = out.trim().split("\n").filter(Boolean);
|
|
7463
|
+
if (opts.untracked) {
|
|
7464
|
+
const fresh = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
|
|
7465
|
+
cwd: root,
|
|
7466
|
+
encoding: "utf-8",
|
|
7467
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7468
|
+
});
|
|
7469
|
+
changed.push(...fresh.trim().split("\n").filter(Boolean));
|
|
7470
|
+
}
|
|
7471
|
+
return changed;
|
|
7155
7472
|
} catch (err2) {
|
|
7156
7473
|
const stderr = err2 instanceof Error && "stderr" in err2 ? String(err2.stderr).trim() : "";
|
|
7157
7474
|
const reason = (stderr || (err2 instanceof Error ? err2.message : String(err2))).split("\n")[0];
|
|
@@ -7159,6 +7476,22 @@ function changedFiles(root, ref) {
|
|
|
7159
7476
|
return null;
|
|
7160
7477
|
}
|
|
7161
7478
|
}
|
|
7479
|
+
function assetOwnDir(a) {
|
|
7480
|
+
const dir = path22__default.dirname(a.filePath);
|
|
7481
|
+
if (["skill", "agent", "contract"].includes(a.kind) || path22__default.basename(dir) === a.name) return dir;
|
|
7482
|
+
return null;
|
|
7483
|
+
}
|
|
7484
|
+
function assetChanged(a, changedAbs) {
|
|
7485
|
+
if (changedAbs.has(a.filePath)) return true;
|
|
7486
|
+
const dir = assetOwnDir(a);
|
|
7487
|
+
if (dir === null) return false;
|
|
7488
|
+
for (const f of changedAbs) {
|
|
7489
|
+
const rel = path22__default.relative(dir, f);
|
|
7490
|
+
if (rel.startsWith("..") || path22__default.isAbsolute(rel)) continue;
|
|
7491
|
+
if (!isNonAssetPath(toPosix(rel))) return true;
|
|
7492
|
+
}
|
|
7493
|
+
return false;
|
|
7494
|
+
}
|
|
7162
7495
|
function runVersionsCheck(pathArg, opts) {
|
|
7163
7496
|
const root = resolveCheckRoot(pathArg);
|
|
7164
7497
|
if (root === null) {
|
|
@@ -7167,13 +7500,13 @@ function runVersionsCheck(pathArg, opts) {
|
|
|
7167
7500
|
}
|
|
7168
7501
|
let assets = collectAssetVersions(root);
|
|
7169
7502
|
if (opts.changedOnly) {
|
|
7170
|
-
const changed = changedFiles(root, "HEAD");
|
|
7503
|
+
const changed = changedFiles(root, "HEAD", "--changed-only", { untracked: true });
|
|
7171
7504
|
if (changed === null) {
|
|
7172
7505
|
process.exit(1);
|
|
7173
7506
|
return;
|
|
7174
7507
|
}
|
|
7175
|
-
const changedAbs = new Set(changed.map((f) =>
|
|
7176
|
-
assets = assets.filter((a) =>
|
|
7508
|
+
const changedAbs = new Set(changed.map((f) => path22__default.resolve(root, f)));
|
|
7509
|
+
assets = assets.filter((a) => assetChanged(a, changedAbs));
|
|
7177
7510
|
}
|
|
7178
7511
|
logInfo(`Checking versions in ${root}`);
|
|
7179
7512
|
const versionCheck = checkAssetVersions(assets, root);
|
|
@@ -7205,7 +7538,7 @@ function makeValidateCommand() {
|
|
|
7205
7538
|
"--strict-conformance",
|
|
7206
7539
|
"Treat Agent Skills (agentskills.io) standard findings as errors"
|
|
7207
7540
|
).action(async (targetPath, opts) => {
|
|
7208
|
-
const absPath =
|
|
7541
|
+
const absPath = path22__default.resolve(targetPath);
|
|
7209
7542
|
logInfo(`Validating manifests in ${absPath}`);
|
|
7210
7543
|
const { total, errors, warnings } = validateManifests(
|
|
7211
7544
|
absPath,
|
|
@@ -7214,13 +7547,14 @@ function makeValidateCommand() {
|
|
|
7214
7547
|
const ws = validateWorkspaceManifests(absPath);
|
|
7215
7548
|
const rootErrors = validatePublishManifestRoots(absPath);
|
|
7216
7549
|
const slugErrors = validatePublishManifestPublisherSlugs(absPath);
|
|
7550
|
+
const parseErrors = validatePublishManifestParses(absPath);
|
|
7217
7551
|
const requiresErrors = validatePublishManifestRequires(absPath);
|
|
7218
7552
|
const versionWarnings = validatePublishManifestVersions(absPath);
|
|
7219
7553
|
const publisherWarnings = validatePublishManifestPublishers(absPath);
|
|
7220
7554
|
const dependencyProblems = await unresolvedManifestDependencies(absPath);
|
|
7221
7555
|
for (const w of dependencyProblems) logWarn(w);
|
|
7222
7556
|
const dependencyWarnings = dependencyProblems.length;
|
|
7223
|
-
const totalErrors = errors + ws.errors + rootErrors + slugErrors + requiresErrors;
|
|
7557
|
+
const totalErrors = errors + ws.errors + rootErrors + slugErrors + parseErrors + requiresErrors;
|
|
7224
7558
|
console.log();
|
|
7225
7559
|
warnIgnoredDomainFiles(absPath);
|
|
7226
7560
|
warnLegacyBundleFiles(absPath);
|
|
@@ -7246,7 +7580,7 @@ function makeValidateCommand() {
|
|
|
7246
7580
|
process.exit(1);
|
|
7247
7581
|
return;
|
|
7248
7582
|
}
|
|
7249
|
-
const modifiedFiles = changedFiles(root, opts.base);
|
|
7583
|
+
const modifiedFiles = changedFiles(root, opts.base, "changelog");
|
|
7250
7584
|
if (modifiedFiles === null) {
|
|
7251
7585
|
process.exit(1);
|
|
7252
7586
|
return;
|
|
@@ -7295,7 +7629,7 @@ function itemFromRef(raw, defaultKind, ctx) {
|
|
|
7295
7629
|
return { kind: prefixed[1], ref: value };
|
|
7296
7630
|
}
|
|
7297
7631
|
if (PATH_LIKE.test(value)) return { kind: defaultKind, ref: value };
|
|
7298
|
-
if (defaultKind === "skill" && !value.includes("/") && existsSync(
|
|
7632
|
+
if (defaultKind === "skill" && !value.includes("/") && existsSync(path22__default.join(ctx.agentDir, "skills", value, "SKILL.md"))) {
|
|
7299
7633
|
return { kind: "skill", ref: `./skills/${value}` };
|
|
7300
7634
|
}
|
|
7301
7635
|
return { kind: defaultKind, ref: `${defaultKind}:${value}` };
|
|
@@ -7431,7 +7765,7 @@ function migrateAgentYaml(source, options) {
|
|
|
7431
7765
|
manual.push("metadata.soul: not a string; left unchanged");
|
|
7432
7766
|
continue;
|
|
7433
7767
|
}
|
|
7434
|
-
if (
|
|
7768
|
+
if (path22__default.posix.basename(soul.replace(/\\/g, "/")).toLowerCase() === "soul.md") {
|
|
7435
7769
|
notes.push("metadata.soul \u2192 dropped (SOUL.md is a convention file)");
|
|
7436
7770
|
} else {
|
|
7437
7771
|
derived.push({ kind: "persona", ref: soul });
|
|
@@ -7665,7 +7999,7 @@ function migrateSubagents(skaileYamlPath, source) {
|
|
|
7665
7999
|
if (!isMap(agentNode)) return void 0;
|
|
7666
8000
|
const subNode = agentNode.get("subagents", true);
|
|
7667
8001
|
if (!isMap(subNode)) return void 0;
|
|
7668
|
-
const dir =
|
|
8002
|
+
const dir = path22__default.dirname(skaileYamlPath);
|
|
7669
8003
|
const notes = [];
|
|
7670
8004
|
const manual = [];
|
|
7671
8005
|
const changes = [];
|
|
@@ -7683,10 +8017,10 @@ function migrateSubagents(skaileYamlPath, source) {
|
|
|
7683
8017
|
continue;
|
|
7684
8018
|
}
|
|
7685
8019
|
const id = instanceId(name);
|
|
7686
|
-
const assetDir =
|
|
8020
|
+
const assetDir = path22__default.join(dir, ".skaile", "agents", id);
|
|
7687
8021
|
if (takenIds.has(id) || existsSync(assetDir)) {
|
|
7688
8022
|
manual.push(
|
|
7689
|
-
`agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${
|
|
8023
|
+
`agent.subagents.${name}: ${takenIds.has(id) ? `agents.${id} already exists` : `${path22__default.relative(dir, assetDir)} already exists`}; left in place`
|
|
7690
8024
|
);
|
|
7691
8025
|
continue;
|
|
7692
8026
|
}
|
|
@@ -7710,13 +8044,13 @@ function migrateSubagents(skaileYamlPath, source) {
|
|
|
7710
8044
|
manifest.tools = { ...allowed ? { allowed } : {}, ...denied ? { denied } : {} };
|
|
7711
8045
|
}
|
|
7712
8046
|
const text = stringify(manifest, { lineWidth: 0 });
|
|
7713
|
-
const manifestPath =
|
|
8047
|
+
const manifestPath = path22__default.join(assetDir, "agent.yaml");
|
|
7714
8048
|
changes.push({ type: "create", path: manifestPath, after: text });
|
|
7715
8049
|
assetManifests.push({ file: manifestPath, text });
|
|
7716
8050
|
if (typeof spec.prompt === "string" && spec.prompt.trim() !== "") {
|
|
7717
8051
|
changes.push({
|
|
7718
8052
|
type: "create",
|
|
7719
|
-
path:
|
|
8053
|
+
path: path22__default.join(assetDir, "SOUL.md"),
|
|
7720
8054
|
after: `${spec.prompt.replace(/\s+$/, "")}
|
|
7721
8055
|
`
|
|
7722
8056
|
});
|
|
@@ -7775,7 +8109,7 @@ function validateMigratedAgent(text, registry) {
|
|
|
7775
8109
|
function collectAgentFiles(paths) {
|
|
7776
8110
|
const files = /* @__PURE__ */ new Set();
|
|
7777
8111
|
for (const input of paths) {
|
|
7778
|
-
const abs =
|
|
8112
|
+
const abs = path22__default.resolve(input);
|
|
7779
8113
|
if (!existsSync(abs)) continue;
|
|
7780
8114
|
if (statSync(abs).isDirectory()) {
|
|
7781
8115
|
for (const f of walkFiles(abs, (b) => b === "agent.yaml" || b === "skaile.yaml"))
|
|
@@ -7792,7 +8126,7 @@ function planAgentMigration(options) {
|
|
|
7792
8126
|
const reports = [];
|
|
7793
8127
|
for (const file of collectAgentFiles(options.paths)) {
|
|
7794
8128
|
const source = readText(file);
|
|
7795
|
-
const base =
|
|
8129
|
+
const base = path22__default.basename(file);
|
|
7796
8130
|
if (base === "skaile.yaml") {
|
|
7797
8131
|
const result = migrateSubagents(file, source);
|
|
7798
8132
|
if (!result) continue;
|
|
@@ -7800,7 +8134,7 @@ function planAgentMigration(options) {
|
|
|
7800
8134
|
for (const asset of result.assetManifests) {
|
|
7801
8135
|
const v = validateMigratedAgent(asset.text, options.registry);
|
|
7802
8136
|
validation2.errors.push(
|
|
7803
|
-
...v.errors.map((e) => `${
|
|
8137
|
+
...v.errors.map((e) => `${path22__default.basename(path22__default.dirname(asset.file))}: ${e}`)
|
|
7804
8138
|
);
|
|
7805
8139
|
validation2.warnings.push(...v.warnings);
|
|
7806
8140
|
}
|
|
@@ -7828,7 +8162,7 @@ function planAgentMigration(options) {
|
|
|
7828
8162
|
});
|
|
7829
8163
|
continue;
|
|
7830
8164
|
}
|
|
7831
|
-
migration = migrateAgentYaml(source, { agentDir:
|
|
8165
|
+
migration = migrateAgentYaml(source, { agentDir: path22__default.dirname(file), knownKinds });
|
|
7832
8166
|
} catch (error) {
|
|
7833
8167
|
reports.push({
|
|
7834
8168
|
file,
|
|
@@ -7858,7 +8192,7 @@ function planAgentMigration(options) {
|
|
|
7858
8192
|
var DEFAULT_PUBLISHER = "skaile-ai";
|
|
7859
8193
|
var PRESET_DEFAULT_VERSION = "1.0.0";
|
|
7860
8194
|
var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
7861
|
-
var posix2 = (p6) => p6.split(
|
|
8195
|
+
var posix2 = (p6) => p6.split(path22__default.sep).join("/");
|
|
7862
8196
|
var MOVED_KINDS = { persona: "PERSONA.md", ruleset: "RULESET.md" };
|
|
7863
8197
|
var KIND_MANIFEST_FILES = /* @__PURE__ */ new Set(["PERSONA.md", "RULESET.md", "SKILL.md"]);
|
|
7864
8198
|
function readFrontmatterType(text) {
|
|
@@ -7889,14 +8223,14 @@ function planMarkdownMoves(root, knownKinds, manual, unknownTypes) {
|
|
|
7889
8223
|
if (!text.startsWith("---")) continue;
|
|
7890
8224
|
const found = readFrontmatterType(text);
|
|
7891
8225
|
if (!found) continue;
|
|
7892
|
-
const base =
|
|
7893
|
-
const inAgentParts = file.split(
|
|
8226
|
+
const base = path22__default.basename(file);
|
|
8227
|
+
const inAgentParts = file.split(path22__default.sep).includes("_agent-parts");
|
|
7894
8228
|
const targetName = MOVED_KINDS[found.type];
|
|
7895
8229
|
if (targetName !== void 0 && !KIND_MANIFEST_FILES.has(base)) {
|
|
7896
|
-
const to =
|
|
8230
|
+
const to = path22__default.join(path22__default.dirname(file), base.replace(/\.md$/i, ""), targetName);
|
|
7897
8231
|
if (existsSync(to) || targets.has(to)) {
|
|
7898
8232
|
manual.push(
|
|
7899
|
-
`${posix2(
|
|
8233
|
+
`${posix2(path22__default.relative(root, file))}: ${posix2(path22__default.relative(root, to))} already exists; not moved`
|
|
7900
8234
|
);
|
|
7901
8235
|
continue;
|
|
7902
8236
|
}
|
|
@@ -7917,13 +8251,13 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
|
|
|
7917
8251
|
const changes = [];
|
|
7918
8252
|
for (const file of walkFiles(root, (b) => b === "agent.yaml")) {
|
|
7919
8253
|
const source = readText(file);
|
|
7920
|
-
const agentDir =
|
|
8254
|
+
const agentDir = path22__default.dirname(file);
|
|
7921
8255
|
let hits = 0;
|
|
7922
8256
|
const refRewrite = (_kind, ref) => {
|
|
7923
|
-
const moved = byOldPath.get(
|
|
8257
|
+
const moved = byOldPath.get(path22__default.resolve(agentDir, ref));
|
|
7924
8258
|
if (moved === void 0) return ref;
|
|
7925
8259
|
hits++;
|
|
7926
|
-
const rel = posix2(
|
|
8260
|
+
const rel = posix2(path22__default.relative(agentDir, moved));
|
|
7927
8261
|
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
7928
8262
|
};
|
|
7929
8263
|
let output;
|
|
@@ -7940,7 +8274,7 @@ function planAgentRefRewrites(root, moves, knownKinds, notes) {
|
|
|
7940
8274
|
if (hits === 0 || output === source) continue;
|
|
7941
8275
|
changes.push({ type: "write", path: file, before: source, after: output });
|
|
7942
8276
|
notes.push(
|
|
7943
|
-
`${posix2(
|
|
8277
|
+
`${posix2(path22__default.relative(root, file))}: persona/ruleset refs \u2192 composes items at the new paths`
|
|
7944
8278
|
);
|
|
7945
8279
|
}
|
|
7946
8280
|
return changes;
|
|
@@ -7951,10 +8285,9 @@ function presetItemRef(dep, publisher) {
|
|
|
7951
8285
|
const [, kind, rest] = match;
|
|
7952
8286
|
return rest.startsWith("@") ? dep.trim() : `${kind}:@${publisher}/${rest}`;
|
|
7953
8287
|
}
|
|
7954
|
-
function presetText(name, description, refs,
|
|
8288
|
+
function presetText(name, description, refs, version) {
|
|
7955
8289
|
return stringify(
|
|
7956
8290
|
{
|
|
7957
|
-
publisher,
|
|
7958
8291
|
name,
|
|
7959
8292
|
version,
|
|
7960
8293
|
description: description && description.trim() !== "" ? description : `Preset ${name}`,
|
|
@@ -7965,14 +8298,14 @@ function presetText(name, description, refs, publisher, version) {
|
|
|
7965
8298
|
}
|
|
7966
8299
|
function skillDirs(dir) {
|
|
7967
8300
|
try {
|
|
7968
|
-
return readdirSync(
|
|
8301
|
+
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();
|
|
7969
8302
|
} catch {
|
|
7970
8303
|
return [];
|
|
7971
8304
|
}
|
|
7972
8305
|
}
|
|
7973
8306
|
function repoPublisher(root) {
|
|
7974
8307
|
for (const name of ["skaile.manifest.yaml", "skaile.yaml"]) {
|
|
7975
|
-
const file =
|
|
8308
|
+
const file = path22__default.join(root, name);
|
|
7976
8309
|
if (!existsSync(file)) continue;
|
|
7977
8310
|
try {
|
|
7978
8311
|
const parsed = parse(readText(file));
|
|
@@ -7988,9 +8321,9 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
7988
8321
|
const changes = [];
|
|
7989
8322
|
const presets = [];
|
|
7990
8323
|
const handled = /* @__PURE__ */ new Set();
|
|
7991
|
-
const rel = (p6) => posix2(
|
|
8324
|
+
const rel = (p6) => posix2(path22__default.relative(root, p6));
|
|
7992
8325
|
const convert = (name, bundleFile, dir) => {
|
|
7993
|
-
const target =
|
|
8326
|
+
const target = path22__default.join(dir === root ? path22__default.join(dir, name) : dir, `${name}.preset.yaml`);
|
|
7994
8327
|
if (existsSync(target)) {
|
|
7995
8328
|
manual.push(`${rel(target)} already exists; bundle ${name} not converted`);
|
|
7996
8329
|
return;
|
|
@@ -8008,6 +8341,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
8008
8341
|
const declared = typeof parsed.version === "string" || typeof parsed.version === "number" ? String(parsed.version) : void 0;
|
|
8009
8342
|
if (declared !== void 0 && SEMVER_RE.test(declared)) version = declared;
|
|
8010
8343
|
else if (declared !== void 0) versionNote = `version ${declared} \u2192 ${version}`;
|
|
8344
|
+
else versionNote = `version (none) \u2192 ${version}`;
|
|
8011
8345
|
const deps = Array.isArray(parsed.dependencies) ? parsed.dependencies : [];
|
|
8012
8346
|
refs = deps.filter((d) => typeof d === "string").map((d) => presetItemRef(d, publisher));
|
|
8013
8347
|
if (refs.length !== deps.length) {
|
|
@@ -8021,11 +8355,11 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
8021
8355
|
}
|
|
8022
8356
|
if (refs.length === 0) {
|
|
8023
8357
|
manual.push(
|
|
8024
|
-
`bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(
|
|
8358
|
+
`bundle ${name}: no dependencies found${bundleFile ? ` in ${rel(bundleFile)}` : ` and no skills under ${rel(path22__default.join(dir, "skills"))}`}; no preset generated`
|
|
8025
8359
|
);
|
|
8026
8360
|
return;
|
|
8027
8361
|
}
|
|
8028
|
-
const after = presetText(name, description, refs,
|
|
8362
|
+
const after = presetText(name, description, refs, version);
|
|
8029
8363
|
if (before !== void 0 && bundleFile) {
|
|
8030
8364
|
changes.push({ type: "move", from: bundleFile, to: target, before, after });
|
|
8031
8365
|
handled.add(bundleFile);
|
|
@@ -8045,18 +8379,18 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
8045
8379
|
const assets = Array.isArray(raw.assets) ? raw.assets : [];
|
|
8046
8380
|
for (const entry of assets) {
|
|
8047
8381
|
if (!isRecord(entry) || entry.kind !== "bundle" || typeof entry.name !== "string") continue;
|
|
8048
|
-
const baseDir =
|
|
8049
|
-
const entryRoot = typeof entry.root === "string" ?
|
|
8382
|
+
const baseDir = path22__default.dirname(file);
|
|
8383
|
+
const entryRoot = typeof entry.root === "string" ? path22__default.join(baseDir, entry.root) : baseDir;
|
|
8050
8384
|
const files = Array.isArray(entry.files) ? entry.files : [];
|
|
8051
8385
|
const bundleName = files.find(
|
|
8052
8386
|
(f) => typeof f === "string" && f.endsWith(".bundle.yaml")
|
|
8053
8387
|
);
|
|
8054
|
-
convert(entry.name, bundleName ?
|
|
8388
|
+
convert(entry.name, bundleName ? path22__default.join(entryRoot, bundleName) : void 0, entryRoot);
|
|
8055
8389
|
}
|
|
8056
8390
|
}
|
|
8057
8391
|
for (const bundleFile of walkFiles(root, (b) => b.endsWith(".bundle.yaml"))) {
|
|
8058
8392
|
if (handled.has(bundleFile)) continue;
|
|
8059
|
-
const base =
|
|
8393
|
+
const base = path22__default.basename(bundleFile);
|
|
8060
8394
|
let name = base.replace(/\.bundle\.yaml$/, "");
|
|
8061
8395
|
try {
|
|
8062
8396
|
const parsed = parse(readText(bundleFile));
|
|
@@ -8065,7 +8399,7 @@ function planBundles(root, skaileYamls, publisher, notes, manual) {
|
|
|
8065
8399
|
} catch {
|
|
8066
8400
|
}
|
|
8067
8401
|
if (presets.some((p6) => p6.bundleFile === bundleFile)) continue;
|
|
8068
|
-
convert(name, bundleFile,
|
|
8402
|
+
convert(name, bundleFile, path22__default.dirname(bundleFile));
|
|
8069
8403
|
}
|
|
8070
8404
|
return changes;
|
|
8071
8405
|
}
|
|
@@ -8075,8 +8409,8 @@ function planSkaileYaml(root, file, source, notes, manual) {
|
|
|
8075
8409
|
if (doc.errors.length > 0 || !isMap(doc.contents)) return [];
|
|
8076
8410
|
const map = doc.contents;
|
|
8077
8411
|
const raw = doc.toJS();
|
|
8078
|
-
const dir =
|
|
8079
|
-
const rel = (p6) => posix2(
|
|
8412
|
+
const dir = path22__default.dirname(file);
|
|
8413
|
+
const rel = (p6) => posix2(path22__default.relative(root, p6));
|
|
8080
8414
|
const changes = [];
|
|
8081
8415
|
let changed = false;
|
|
8082
8416
|
const deps = map.get("dependencies", true);
|
|
@@ -8093,7 +8427,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
|
|
|
8093
8427
|
const hasPublication = PUBLICATION_KEYS.some((k) => raw[k] !== void 0);
|
|
8094
8428
|
let remove = false;
|
|
8095
8429
|
if (hasPublication) {
|
|
8096
|
-
const manifestPath =
|
|
8430
|
+
const manifestPath = path22__default.join(dir, "skaile.manifest.yaml");
|
|
8097
8431
|
if (existsSync(manifestPath)) {
|
|
8098
8432
|
manual.push(
|
|
8099
8433
|
`${rel(file)}: publisher/version/assets left in place \u2014 ${rel(manifestPath)} already exists; merge by hand`
|
|
@@ -8150,7 +8484,7 @@ function planSkaileYaml(root, file, source, notes, manual) {
|
|
|
8150
8484
|
return changes;
|
|
8151
8485
|
}
|
|
8152
8486
|
function planAssetMigration(options) {
|
|
8153
|
-
const root =
|
|
8487
|
+
const root = path22__default.resolve(options.root);
|
|
8154
8488
|
const knownKinds = new Set(options.registry.getAllKinds());
|
|
8155
8489
|
const notes = [];
|
|
8156
8490
|
const manual = [];
|
|
@@ -8158,7 +8492,7 @@ function planAssetMigration(options) {
|
|
|
8158
8492
|
const { moves, changes: moveChanges } = planMarkdownMoves(root, knownKinds, manual, unknownTypes);
|
|
8159
8493
|
for (const move of moves) {
|
|
8160
8494
|
notes.push(
|
|
8161
|
-
`${posix2(
|
|
8495
|
+
`${posix2(path22__default.relative(root, move.from))} \u2192 ${posix2(path22__default.relative(root, move.to))} (${move.kind})`
|
|
8162
8496
|
);
|
|
8163
8497
|
}
|
|
8164
8498
|
const agentChanges = planAgentRefRewrites(root, moves, knownKinds, notes);
|
|
@@ -8170,7 +8504,7 @@ function planAssetMigration(options) {
|
|
|
8170
8504
|
const raw = parse(source);
|
|
8171
8505
|
if (isRecord(raw)) skaileYamls.push({ file, source, raw });
|
|
8172
8506
|
} catch {
|
|
8173
|
-
manual.push(`${posix2(
|
|
8507
|
+
manual.push(`${posix2(path22__default.relative(root, file))}: invalid YAML; skipped`);
|
|
8174
8508
|
}
|
|
8175
8509
|
}
|
|
8176
8510
|
const publisher = repoPublisher(root);
|
|
@@ -8324,7 +8658,7 @@ function workspaceConfigFiles(dir) {
|
|
|
8324
8658
|
} catch {
|
|
8325
8659
|
return [];
|
|
8326
8660
|
}
|
|
8327
|
-
return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) =>
|
|
8661
|
+
return names.filter((name) => isWorkspaceConfigFilename(name)).sort().map((name) => path22__default.join(dir, name));
|
|
8328
8662
|
}
|
|
8329
8663
|
function readAgentConfigBlock(raw) {
|
|
8330
8664
|
const key = AGENT_CONFIG_KEYS.find((candidate) => raw[candidate] !== void 0);
|
|
@@ -8336,7 +8670,7 @@ function readAgentConfigBlock(raw) {
|
|
|
8336
8670
|
return flat ? { key, profiles: { default: profiles }, flat } : { key, profiles, flat };
|
|
8337
8671
|
}
|
|
8338
8672
|
function planProviderMigration(options) {
|
|
8339
|
-
const projectDir =
|
|
8673
|
+
const projectDir = path22__default.resolve(options.projectDir);
|
|
8340
8674
|
const registryPath = options.workspace ? workspaceProviderRegistryPath(projectDir) : userProviderRegistryPath();
|
|
8341
8675
|
const plan = {
|
|
8342
8676
|
registryPath,
|
|
@@ -8352,7 +8686,7 @@ function planProviderMigration(options) {
|
|
|
8352
8686
|
raw = parseDocument(readFileSync(file, "utf-8")).toJS() ?? {};
|
|
8353
8687
|
} catch (error) {
|
|
8354
8688
|
plan.warnings.push(
|
|
8355
|
-
`${
|
|
8689
|
+
`${path22__default.basename(file)}: not valid YAML (${error instanceof Error ? error.message : String(error)}) \u2014 skipped`
|
|
8356
8690
|
);
|
|
8357
8691
|
continue;
|
|
8358
8692
|
}
|
|
@@ -8401,7 +8735,7 @@ function planProviderMigration(options) {
|
|
|
8401
8735
|
});
|
|
8402
8736
|
if (!model) {
|
|
8403
8737
|
plan.warnings.push(
|
|
8404
|
-
`${
|
|
8738
|
+
`${path22__default.basename(file)}: profile '${profile}' had no model: \u2014 it now resolves against registry order. Pin it with 'model: ${providerId}/<modelId>'.`
|
|
8405
8739
|
);
|
|
8406
8740
|
}
|
|
8407
8741
|
touched = true;
|
|
@@ -8468,7 +8802,7 @@ function printPlan(plan) {
|
|
|
8468
8802
|
for (const entry of plan.entries) {
|
|
8469
8803
|
const base = entry.entry.base_url ?? S.dim("(transport-derived)");
|
|
8470
8804
|
console.log(
|
|
8471
|
-
` ${S.label(`${
|
|
8805
|
+
` ${S.label(`${path22__default.basename(entry.file)} ${entry.profile}`)} provider: ${entry.legacy.provider}, cloud: ${entry.legacy.cloud}`
|
|
8472
8806
|
);
|
|
8473
8807
|
console.log(` \u2192 providers.yml ${S.bold(entry.providerId)} ${base}`);
|
|
8474
8808
|
console.log(
|
|
@@ -8484,7 +8818,7 @@ function printPlan(plan) {
|
|
|
8484
8818
|
console.log();
|
|
8485
8819
|
}
|
|
8486
8820
|
async function runMigrateProviders(opts) {
|
|
8487
|
-
const projectDir = opts.projectDir ?
|
|
8821
|
+
const projectDir = opts.projectDir ? path22__default.resolve(opts.projectDir) : process.cwd();
|
|
8488
8822
|
const plan = planProviderMigration({ projectDir, workspace: opts.workspace });
|
|
8489
8823
|
for (const warning of plan.warnings) logWarn(warning);
|
|
8490
8824
|
if (plan.entries.length === 0 && Object.keys(plan.providers).length === 0) {
|
|
@@ -8566,7 +8900,8 @@ var ASSETS_HELP = `
|
|
|
8566
8900
|
Rewrites (run on a repo root):
|
|
8567
8901
|
type: persona|ruleset markdown <n>.md -> <n>/PERSONA.md | <n>/RULESET.md (type: dropped);
|
|
8568
8902
|
agent persona:/rules: refs to the old path become composes items
|
|
8569
|
-
*.bundle.yaml <name>.preset.yaml beside it
|
|
8903
|
+
*.bundle.yaml <name>.preset.yaml beside it, or <name>/<name>.preset.yaml
|
|
8904
|
+
for a bundle at the repo root (items: kind:@publisher/name);
|
|
8570
8905
|
kind: bundle entries of skaile.yaml#assets become kind: preset
|
|
8571
8906
|
skaile.yaml dependencies bundle:@... -> preset:@...
|
|
8572
8907
|
skaile.yaml publisher/version/assets
|
|
@@ -8615,7 +8950,7 @@ async function runMigrateAgents(paths, opts) {
|
|
|
8615
8950
|
let failures = 0;
|
|
8616
8951
|
let manualCount = 0;
|
|
8617
8952
|
for (const report of plan.reports) {
|
|
8618
|
-
const rel =
|
|
8953
|
+
const rel = path22__default.relative(base, report.file) || report.file;
|
|
8619
8954
|
for (const note of report.notes) console.log(` ${S.label(rel)} ${note}`);
|
|
8620
8955
|
for (const note of report.manual) {
|
|
8621
8956
|
manualCount++;
|
|
@@ -8642,14 +8977,14 @@ async function runMigrateAssets(root, opts) {
|
|
|
8642
8977
|
const write = resolveMode(opts);
|
|
8643
8978
|
const base = process.cwd();
|
|
8644
8979
|
const plan = planAssetMigration({
|
|
8645
|
-
root:
|
|
8980
|
+
root: path22__default.resolve(root ?? base),
|
|
8646
8981
|
registry: getKindRegistry()
|
|
8647
8982
|
});
|
|
8648
8983
|
for (const note of plan.notes) console.log(` ${note}`);
|
|
8649
8984
|
for (const note of plan.manual) logWarn(note);
|
|
8650
8985
|
for (const { file, type } of plan.unknownTypes) {
|
|
8651
8986
|
logWarn(
|
|
8652
|
-
`${
|
|
8987
|
+
`${path22__default.relative(base, file) || file}: frontmatter type "${type}" is not a registered asset kind (reported, not rewritten)`
|
|
8653
8988
|
);
|
|
8654
8989
|
}
|
|
8655
8990
|
printChanges(plan.changes, base);
|
|
@@ -8672,8 +9007,8 @@ function makeNpxCommand() {
|
|
|
8672
9007
|
skills.command("add <url>").description(
|
|
8673
9008
|
"Clone a repo, register it in the project's skaile.yaml sources[], and install a skill from it"
|
|
8674
9009
|
).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) => {
|
|
8675
|
-
const projectDir =
|
|
8676
|
-
const projYaml =
|
|
9010
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9011
|
+
const projYaml = path22__default.join(projectDir, "skaile.yaml");
|
|
8677
9012
|
if (!existsSync(projYaml)) {
|
|
8678
9013
|
logErr(`No skaile.yaml in ${projectDir} \u2014 run \`skaile init\` first.`);
|
|
8679
9014
|
process.exit(1);
|
|
@@ -8686,11 +9021,11 @@ function makeNpxCommand() {
|
|
|
8686
9021
|
}
|
|
8687
9022
|
const spinner = createSpinner();
|
|
8688
9023
|
const key = sourceCacheKey(url);
|
|
8689
|
-
const clonePath =
|
|
9024
|
+
const clonePath = path22__default.join(getGlobalCacheDir(), key);
|
|
8690
9025
|
spinner.start(`Cloning ${url}`);
|
|
8691
9026
|
try {
|
|
8692
9027
|
if (!existsSync(clonePath)) {
|
|
8693
|
-
mkdirSync(
|
|
9028
|
+
mkdirSync(path22__default.dirname(clonePath), { recursive: true });
|
|
8694
9029
|
execSync(`git clone ${url} ${clonePath}`, { stdio: "ignore" });
|
|
8695
9030
|
}
|
|
8696
9031
|
spinner.stop(`Cloned to ${key}`);
|
|
@@ -8745,7 +9080,7 @@ function makeNpxCommand() {
|
|
|
8745
9080
|
return npx;
|
|
8746
9081
|
}
|
|
8747
9082
|
function resolvePublisher(clonePath, url) {
|
|
8748
|
-
const manifestPath =
|
|
9083
|
+
const manifestPath = path22__default.join(clonePath, SKAILE_MANIFEST_FILENAME);
|
|
8749
9084
|
if (existsSync(manifestPath)) {
|
|
8750
9085
|
try {
|
|
8751
9086
|
const { manifest } = decodeSkaileManifest(readFileSync(manifestPath, "utf8"));
|
|
@@ -8758,12 +9093,12 @@ function resolvePublisher(clonePath, url) {
|
|
|
8758
9093
|
return url.match(/github\.com[/:]([^/]+)\/[^/]+/)?.[1];
|
|
8759
9094
|
}
|
|
8760
9095
|
function resolveSkillName(clonePath, requested) {
|
|
8761
|
-
const skillsDir =
|
|
8762
|
-
if (existsSync(
|
|
9096
|
+
const skillsDir = path22__default.join(clonePath, "skills");
|
|
9097
|
+
if (existsSync(path22__default.join(skillsDir, requested, "SKILL.md"))) return requested;
|
|
8763
9098
|
if (!existsSync(skillsDir)) return requested;
|
|
8764
9099
|
for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
|
|
8765
9100
|
if (!entry.isDirectory()) continue;
|
|
8766
|
-
const md =
|
|
9101
|
+
const md = path22__default.join(skillsDir, entry.name, "SKILL.md");
|
|
8767
9102
|
if (!existsSync(md)) continue;
|
|
8768
9103
|
try {
|
|
8769
9104
|
const { data } = parseFrontmatter(readFileSync(md, "utf8"));
|
|
@@ -8793,9 +9128,10 @@ function makeOutdatedCommand() {
|
|
|
8793
9128
|
SUPPORTED_DRIVER_TARGETS
|
|
8794
9129
|
)
|
|
8795
9130
|
).action(async (filter, opts) => {
|
|
9131
|
+
requireProjectConfig(opts.projectDir);
|
|
8796
9132
|
const am2 = new AssetManager({
|
|
8797
9133
|
registry: getKindRegistry(),
|
|
8798
|
-
projectDir:
|
|
9134
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
8799
9135
|
driverTarget: opts.target
|
|
8800
9136
|
});
|
|
8801
9137
|
const entries = await am2.outdated();
|
|
@@ -8838,7 +9174,7 @@ function makePatchCommand() {
|
|
|
8838
9174
|
cmd.command("extract <ref>").alias("start").description("Extract asset for local editing").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
|
|
8839
9175
|
const am2 = new AssetManager({
|
|
8840
9176
|
registry: getKindRegistry(),
|
|
8841
|
-
projectDir:
|
|
9177
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
8842
9178
|
});
|
|
8843
9179
|
try {
|
|
8844
9180
|
const dest = await am2.patch(ref);
|
|
@@ -8852,7 +9188,7 @@ function makePatchCommand() {
|
|
|
8852
9188
|
cmd.command("commit <ref>").description("Generate .patch file from edits").option("--project-dir <path>", "Project directory", process.cwd()).action(async (ref, opts) => {
|
|
8853
9189
|
const am2 = new AssetManager({
|
|
8854
9190
|
registry: getKindRegistry(),
|
|
8855
|
-
projectDir:
|
|
9191
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
8856
9192
|
});
|
|
8857
9193
|
try {
|
|
8858
9194
|
const patchFile = await am2.patchCommit(ref);
|
|
@@ -8866,7 +9202,7 @@ function makePatchCommand() {
|
|
|
8866
9202
|
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) => {
|
|
8867
9203
|
const am2 = new AssetManager({
|
|
8868
9204
|
registry: getKindRegistry(),
|
|
8869
|
-
projectDir:
|
|
9205
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
8870
9206
|
});
|
|
8871
9207
|
try {
|
|
8872
9208
|
await am2.patchSubmit(ref);
|
|
@@ -8882,7 +9218,7 @@ function makePatchCommand() {
|
|
|
8882
9218
|
cmd.command("remove <ref>").description("Remove local patch after upstream merge").option("--project-dir <path>", "Project directory", process.cwd()).action((ref, opts) => {
|
|
8883
9219
|
const am2 = new AssetManager({
|
|
8884
9220
|
registry: getKindRegistry(),
|
|
8885
|
-
projectDir:
|
|
9221
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
8886
9222
|
});
|
|
8887
9223
|
am2.patchRemove(ref);
|
|
8888
9224
|
logOk(`Patch removed for ${ref}`);
|
|
@@ -8900,8 +9236,8 @@ function action2(fn) {
|
|
|
8900
9236
|
}
|
|
8901
9237
|
};
|
|
8902
9238
|
}
|
|
8903
|
-
async function reconcileAndReport(projectDir, plugins) {
|
|
8904
|
-
const { reconcilePlugins } = await import('../plugin-store-
|
|
9239
|
+
async function reconcileAndReport(projectDir, plugins, opts = {}) {
|
|
9240
|
+
const { reconcilePlugins } = await import('../plugin-store-XMZSPVBF.js');
|
|
8905
9241
|
if (plugins.length === 0) {
|
|
8906
9242
|
logInfo("No plugins declared \u2014 nothing to reconcile.");
|
|
8907
9243
|
return;
|
|
@@ -8911,26 +9247,52 @@ async function reconcileAndReport(projectDir, plugins) {
|
|
|
8911
9247
|
if (result.changed) logOk(`Reconciled plugin store (${result.reason}).`);
|
|
8912
9248
|
else logInfo(`Plugin store ${result.reason}.`);
|
|
8913
9249
|
} catch (err2) {
|
|
9250
|
+
if (opts.strict) throw err2;
|
|
8914
9251
|
logWarn(`reconcile skipped: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
8915
9252
|
}
|
|
8916
9253
|
}
|
|
9254
|
+
async function verifyPluginLoads(projectDir, spec) {
|
|
9255
|
+
const { loadPlugins } = await import('../plugin-store-XMZSPVBF.js');
|
|
9256
|
+
const { createPluginRegistry } = await import('../plugin-registry/index.js');
|
|
9257
|
+
const registry = createPluginRegistry();
|
|
9258
|
+
const result = await loadPlugins(projectDir, [spec], registry);
|
|
9259
|
+
const failure = result.failed[0];
|
|
9260
|
+
if (failure) throw new Error(failure.error);
|
|
9261
|
+
const contributed = ["driver", "connector", "deployTarget"].flatMap(
|
|
9262
|
+
(kind) => registry.list(kind).map((m) => `${kind} ${m.id}`)
|
|
9263
|
+
);
|
|
9264
|
+
logOk(`Loaded ${S.cmd(spec)}${contributed.length > 0 ? ` (${contributed.join(", ")})` : ""}`);
|
|
9265
|
+
}
|
|
8917
9266
|
async function runInstall2(spec, opts) {
|
|
8918
|
-
const projectDir =
|
|
9267
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
8919
9268
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
8920
|
-
const { specName } = await import('../plugin-store-
|
|
8921
|
-
const yamlPath =
|
|
9269
|
+
const { specName } = await import('../plugin-store-XMZSPVBF.js');
|
|
9270
|
+
const yamlPath = path22__default.join(projectDir, "skaile.yaml");
|
|
9271
|
+
const original = existsSync(yamlPath) ? readFileSync(yamlPath, "utf8") : void 0;
|
|
8922
9272
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
8923
9273
|
const replaced = editor.addPlugin(spec, specName);
|
|
8924
9274
|
editor.save();
|
|
8925
9275
|
if (replaced) logOk(`Updated ${S.cmd(specName(spec))} \u2192 ${S.cmd(spec)} in skaile.yaml`);
|
|
8926
9276
|
else logOk(`Added ${S.cmd(spec)} to skaile.yaml plugins`);
|
|
8927
|
-
|
|
9277
|
+
try {
|
|
9278
|
+
await reconcileAndReport(projectDir, editor.getPlugins(), { strict: true });
|
|
9279
|
+
await verifyPluginLoads(projectDir, spec);
|
|
9280
|
+
} catch (err2) {
|
|
9281
|
+
if (original !== void 0) {
|
|
9282
|
+
writeFileSync(yamlPath, original);
|
|
9283
|
+
logInfo("skaile.yaml restored; the plugin was not recorded.");
|
|
9284
|
+
} else {
|
|
9285
|
+
rmSync(yamlPath, { force: true });
|
|
9286
|
+
logInfo("skaile.yaml removed; the plugin was not recorded.");
|
|
9287
|
+
}
|
|
9288
|
+
throw err2;
|
|
9289
|
+
}
|
|
8928
9290
|
}
|
|
8929
9291
|
async function runRemove(name, opts) {
|
|
8930
|
-
const projectDir =
|
|
9292
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
8931
9293
|
const { WorkspaceYamlEditor: WorkspaceYamlEditor2 } = await import('../core/index.js');
|
|
8932
|
-
const { specName } = await import('../plugin-store-
|
|
8933
|
-
const yamlPath =
|
|
9294
|
+
const { specName } = await import('../plugin-store-XMZSPVBF.js');
|
|
9295
|
+
const yamlPath = path22__default.join(projectDir, "skaile.yaml");
|
|
8934
9296
|
const editor = WorkspaceYamlEditor2.load(yamlPath);
|
|
8935
9297
|
const removed = editor.removePlugin(name, specName);
|
|
8936
9298
|
if (!removed) {
|
|
@@ -8942,7 +9304,7 @@ async function runRemove(name, opts) {
|
|
|
8942
9304
|
await reconcileAndReport(projectDir, editor.getPlugins());
|
|
8943
9305
|
}
|
|
8944
9306
|
async function runList(opts) {
|
|
8945
|
-
const projectDir =
|
|
9307
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
8946
9308
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
8947
9309
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
8948
9310
|
const declared = config.plugins ?? [];
|
|
@@ -8957,7 +9319,7 @@ async function runList(opts) {
|
|
|
8957
9319
|
const registry = createPluginRegistry();
|
|
8958
9320
|
if (declared.length > 0) {
|
|
8959
9321
|
try {
|
|
8960
|
-
const { loadPlugins } = await import('../plugin-store-
|
|
9322
|
+
const { loadPlugins } = await import('../plugin-store-XMZSPVBF.js');
|
|
8961
9323
|
const result = await loadPlugins(projectDir, declared, registry);
|
|
8962
9324
|
for (const f of result.failed) logWarn(f.error);
|
|
8963
9325
|
} catch (err2) {
|
|
@@ -9132,7 +9494,7 @@ function neededSources(config, lock) {
|
|
|
9132
9494
|
}
|
|
9133
9495
|
function sourcesWithSidecar(sources) {
|
|
9134
9496
|
const dir = getStoreManifestsDir();
|
|
9135
|
-
return sources.filter((s) => existsSync(
|
|
9497
|
+
return sources.filter((s) => existsSync(path22.join(dir, `${storeManifestSlug(s.url)}.yaml`))).map((s) => s.url);
|
|
9136
9498
|
}
|
|
9137
9499
|
function compact(obj) {
|
|
9138
9500
|
const out = {};
|
|
@@ -9224,8 +9586,8 @@ function redactSecrets(preset, findings) {
|
|
|
9224
9586
|
}
|
|
9225
9587
|
return { preset: next, keys };
|
|
9226
9588
|
}
|
|
9227
|
-
function placeholderKey(itemId,
|
|
9228
|
-
return `${itemId}_${
|
|
9589
|
+
function placeholderKey(itemId, path44) {
|
|
9590
|
+
return `${itemId}_${path44}`.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
9229
9591
|
}
|
|
9230
9592
|
function setAtPath(root, segments, value) {
|
|
9231
9593
|
let node = root;
|
|
@@ -9248,7 +9610,7 @@ function makePresetCommand() {
|
|
|
9248
9610
|
cmd.command("init [name]").description("Scaffold a new .preset.yaml file").option("--dir <path>", "Output directory", process.cwd()).action(async (name, opts) => {
|
|
9249
9611
|
const presetName = name ?? "my-preset";
|
|
9250
9612
|
const filename = `${presetName}.preset.yaml`;
|
|
9251
|
-
const outPath =
|
|
9613
|
+
const outPath = path22__default.join(path22__default.resolve(opts.dir), filename);
|
|
9252
9614
|
if (existsSync(outPath)) {
|
|
9253
9615
|
logErr(`File already exists: ${outPath}`);
|
|
9254
9616
|
logInfo("Choose a different name or remove the existing file.");
|
|
@@ -9281,7 +9643,7 @@ function makePresetCommand() {
|
|
|
9281
9643
|
return cmd;
|
|
9282
9644
|
}
|
|
9283
9645
|
async function runPresetExport(name, opts) {
|
|
9284
|
-
const projectDir =
|
|
9646
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9285
9647
|
const file = loadSkWorkspaceConfig(projectDir);
|
|
9286
9648
|
if (!file) {
|
|
9287
9649
|
logErr(`No skaile.yaml found in ${projectDir}`);
|
|
@@ -9291,7 +9653,7 @@ async function runPresetExport(name, opts) {
|
|
|
9291
9653
|
const presetName = name ?? file.config.name ?? "my-preset";
|
|
9292
9654
|
let lock = null;
|
|
9293
9655
|
try {
|
|
9294
|
-
lock = readLock(
|
|
9656
|
+
lock = readLock(path22__default.join(projectDir, "skaile.lock.yaml"));
|
|
9295
9657
|
} catch {
|
|
9296
9658
|
lock = null;
|
|
9297
9659
|
}
|
|
@@ -9332,7 +9694,7 @@ async function runPresetExport(name, opts) {
|
|
|
9332
9694
|
const contents = header ? `${header}
|
|
9333
9695
|
${body}` : body;
|
|
9334
9696
|
if (opts.out && opts.dir !== process.cwd()) logWarn("--dir is ignored when --out is set.");
|
|
9335
|
-
const outPath = opts.out ?
|
|
9697
|
+
const outPath = opts.out ? path22__default.resolve(opts.out) : path22__default.join(path22__default.resolve(opts.dir), `${presetName}.preset.yaml`);
|
|
9336
9698
|
if (existsSync(outPath) && !opts.force) {
|
|
9337
9699
|
logErr(`File already exists: ${outPath}`);
|
|
9338
9700
|
logInfo("Pass --force to overwrite, or choose a different --out/--dir.");
|
|
@@ -9344,7 +9706,7 @@ ${body}` : body;
|
|
|
9344
9706
|
logErr(`Failed to write ${outPath}: ${e.message}`);
|
|
9345
9707
|
process.exit(1);
|
|
9346
9708
|
}
|
|
9347
|
-
logOk(`Exported ${S.brand(
|
|
9709
|
+
logOk(`Exported ${S.brand(path22__default.basename(outPath))}`);
|
|
9348
9710
|
logInfo(`Path: ${outPath}`);
|
|
9349
9711
|
if (unresolved.length > 0) {
|
|
9350
9712
|
console.error(S.err("This file is NOT safe to share."));
|
|
@@ -9385,13 +9747,13 @@ function collectInput(value, acc) {
|
|
|
9385
9747
|
return acc;
|
|
9386
9748
|
}
|
|
9387
9749
|
async function runPresetApply(filePath, opts) {
|
|
9388
|
-
const projectDir =
|
|
9750
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9389
9751
|
const file = loadSkWorkspaceConfig(projectDir);
|
|
9390
9752
|
if (!file) {
|
|
9391
9753
|
logErr("No skaile.yaml \u2014 run `skaile init` first");
|
|
9392
9754
|
process.exit(1);
|
|
9393
9755
|
}
|
|
9394
|
-
const resolved =
|
|
9756
|
+
const resolved = path22__default.resolve(filePath);
|
|
9395
9757
|
if (!existsSync(resolved)) {
|
|
9396
9758
|
logErr(`File not found: ${resolved}`);
|
|
9397
9759
|
process.exit(1);
|
|
@@ -9607,7 +9969,7 @@ async function reportNestedPresetRefs(preset) {
|
|
|
9607
9969
|
}
|
|
9608
9970
|
async function checkPresetCycles(preset, resolved) {
|
|
9609
9971
|
const { detectCycles } = await import('../discovery/index.js');
|
|
9610
|
-
const presetRef =
|
|
9972
|
+
const presetRef = path22__default.basename(resolved, ".preset.yaml");
|
|
9611
9973
|
const edges = [];
|
|
9612
9974
|
for (const item of preset.items) {
|
|
9613
9975
|
if (item.ref) {
|
|
@@ -9659,7 +10021,7 @@ function printPresetSummary(preset, placeholderCount, hasWarnings) {
|
|
|
9659
10021
|
}
|
|
9660
10022
|
}
|
|
9661
10023
|
async function runPresetValidate(filePath) {
|
|
9662
|
-
const resolved =
|
|
10024
|
+
const resolved = path22__default.resolve(filePath);
|
|
9663
10025
|
const preset = await loadPresetForValidation(resolved);
|
|
9664
10026
|
await reportNestedPresetRefs(preset);
|
|
9665
10027
|
await checkPresetCycles(preset, resolved);
|
|
@@ -9709,11 +10071,11 @@ items:
|
|
|
9709
10071
|
}
|
|
9710
10072
|
function makeRebuildCommand() {
|
|
9711
10073
|
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) => {
|
|
9712
|
-
const projectDir =
|
|
10074
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9713
10075
|
let agentDir;
|
|
9714
10076
|
if (agentArg) {
|
|
9715
10077
|
if (agentArg.includes("/") || agentArg.includes("\\")) {
|
|
9716
|
-
agentDir =
|
|
10078
|
+
agentDir = path22__default.resolve(projectDir, agentArg);
|
|
9717
10079
|
} else {
|
|
9718
10080
|
let resolved;
|
|
9719
10081
|
try {
|
|
@@ -9722,7 +10084,7 @@ function makeRebuildCommand() {
|
|
|
9722
10084
|
if (!(err2 instanceof AgentRefResolutionError)) throw err2;
|
|
9723
10085
|
logWarn(`${err2.message} \u2014 using "${agentArg}"`);
|
|
9724
10086
|
}
|
|
9725
|
-
agentDir = resolved ??
|
|
10087
|
+
agentDir = resolved ?? path22__default.resolve(projectDir, agentArg);
|
|
9726
10088
|
}
|
|
9727
10089
|
} else {
|
|
9728
10090
|
let resolved;
|
|
@@ -9792,9 +10154,9 @@ Try a different harness with \`--driver claude-sdk\`.`;
|
|
|
9792
10154
|
// cli/src/commands/run.ts
|
|
9793
10155
|
function resolveSingleShotAgentDir(projectDir, agentDefinition) {
|
|
9794
10156
|
if (!agentDefinition) return resolveAgentDir(projectDir);
|
|
9795
|
-
const asPath = agentDefinition.endsWith("agent.yaml") ?
|
|
10157
|
+
const asPath = agentDefinition.endsWith("agent.yaml") ? path22__default.dirname(path22__default.resolve(projectDir, agentDefinition)) : agentDefinition;
|
|
9796
10158
|
const dir = resolveAgentDefinitionDir(projectDir, asPath);
|
|
9797
|
-
if (!dir || !fs8__default.existsSync(
|
|
10159
|
+
if (!dir || !fs8__default.existsSync(path22__default.join(dir, "agent.yaml"))) {
|
|
9798
10160
|
throw new Error(
|
|
9799
10161
|
`--agent-definition "${agentDefinition}" does not resolve to an agent directory with agent.yaml${dir ? ` (looked in ${dir})` : ""}`
|
|
9800
10162
|
);
|
|
@@ -9845,10 +10207,58 @@ async function printCompositionDryRun(projectDir, agentDir, driver, model) {
|
|
|
9845
10207
|
}
|
|
9846
10208
|
for (const warning of resolved.warnings) logWarn(warning);
|
|
9847
10209
|
}
|
|
10210
|
+
async function findSkillFile(projectDir, skill) {
|
|
10211
|
+
const name = skill.trim().replace(/^skill:/, "").replace(/^@[^/]+\//, "").replace(/#.*$/, "");
|
|
10212
|
+
for (const target of SUPPORTED_DRIVER_TARGETS) {
|
|
10213
|
+
const file = path22__default.join(deployedDir("skill", name, target, false, projectDir), "SKILL.md");
|
|
10214
|
+
if (fs8__default.existsSync(file)) return file;
|
|
10215
|
+
}
|
|
10216
|
+
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
|
|
10217
|
+
const entry = await am2.info(`skill:${name}`);
|
|
10218
|
+
return entry?.source && fs8__default.existsSync(entry.source) ? entry.source : void 0;
|
|
10219
|
+
}
|
|
10220
|
+
async function printSkillDryRun(projectDir, skill) {
|
|
10221
|
+
const file = await findSkillFile(projectDir, skill);
|
|
10222
|
+
if (!file) {
|
|
10223
|
+
logErr(
|
|
10224
|
+
`Skill not found: ${skill} - not deployed in the project and not held by a registered library or source`
|
|
10225
|
+
);
|
|
10226
|
+
return false;
|
|
10227
|
+
}
|
|
10228
|
+
const content = fs8__default.readFileSync(file, "utf-8");
|
|
10229
|
+
const { data } = parseFrontmatter(content);
|
|
10230
|
+
const meta = data.metadata ?? {};
|
|
10231
|
+
console.log(` ${S.label("Skill:")} ${S.heading(String(data.name ?? skill))}`);
|
|
10232
|
+
console.log(` ${S.label("Source:")} ${file}`);
|
|
10233
|
+
if (meta.version) console.log(` ${S.label("Version:")} ${String(meta.version)}`);
|
|
10234
|
+
if (data.description) console.log(` ${S.label("About:")} ${String(data.description)}`);
|
|
10235
|
+
const requires = parseRequires(data);
|
|
10236
|
+
if (requires.length > 0) {
|
|
10237
|
+
console.log(` ${S.label("Requires:")} ${requires.map((d) => depToStr(d)).join(", ")}`);
|
|
10238
|
+
}
|
|
10239
|
+
const requirements = parseSkillRequirements(content);
|
|
10240
|
+
const report = await validateRequirements(String(data.name ?? skill), requirements, projectDir);
|
|
10241
|
+
const unmet = report.files.filter((f) => !f.exists);
|
|
10242
|
+
for (const f of report.files) {
|
|
10243
|
+
const mark = f.exists ? S.ok("present") : f.gate === "hard" ? S.err("missing") : S.warn("missing");
|
|
10244
|
+
const gate = f.gate === "soft" ? " (soft)" : "";
|
|
10245
|
+
console.log(` ${S.label("File:")} ${f.path}${gate} ${mark}`);
|
|
10246
|
+
}
|
|
10247
|
+
for (const input of report.inputs.filter((i) => i.required && !i.present)) {
|
|
10248
|
+
console.log(` ${S.label("Input:")} ${input.id} ${S.err("required, not collected")}`);
|
|
10249
|
+
}
|
|
10250
|
+
if (unmet.some((f) => f.gate === "hard")) {
|
|
10251
|
+
logWarn("Unmet hard prerequisites: the skill cannot run until those files exist.");
|
|
10252
|
+
}
|
|
10253
|
+
console.log();
|
|
10254
|
+
return true;
|
|
10255
|
+
}
|
|
9848
10256
|
function makeFlowEventHandler() {
|
|
9849
10257
|
const md = new MarkdownStreamer();
|
|
9850
10258
|
const displayed = /* @__PURE__ */ new Set();
|
|
10259
|
+
const printUnstreamed = createFinalTextFallback((text) => md.write(text));
|
|
9851
10260
|
return (event) => {
|
|
10261
|
+
printUnstreamed(event);
|
|
9852
10262
|
const e = event;
|
|
9853
10263
|
if (e.type === "state_changed" && typeof e.store === "string" && e.store.startsWith("flow:")) {
|
|
9854
10264
|
const nodes = e.state?.nodes ?? {};
|
|
@@ -9888,12 +10298,35 @@ function logAgentRunEvent(event) {
|
|
|
9888
10298
|
const verdict = e.error ? `${e.runStatus ?? "failed"}: ${e.error.code} ${e.error.message}` : e.runStatus ?? "finished";
|
|
9889
10299
|
console.error(` ${S.dim("subagent")} ${who} ${verdict} output=${JSON.stringify(e.output)}`);
|
|
9890
10300
|
}
|
|
10301
|
+
function editDistance2(a, b) {
|
|
10302
|
+
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
10303
|
+
for (let i = 1; i <= a.length; i++) {
|
|
10304
|
+
const row = [i];
|
|
10305
|
+
for (let j = 1; j <= b.length; j++) {
|
|
10306
|
+
row[j] = Math.min(
|
|
10307
|
+
prev[j] + 1,
|
|
10308
|
+
row[j - 1] + 1,
|
|
10309
|
+
prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
|
|
10310
|
+
);
|
|
10311
|
+
}
|
|
10312
|
+
prev = row;
|
|
10313
|
+
}
|
|
10314
|
+
return prev[b.length];
|
|
10315
|
+
}
|
|
10316
|
+
function isNearFlowId(typed, id) {
|
|
10317
|
+
const a = typed.toLowerCase();
|
|
10318
|
+
const b = id.toLowerCase();
|
|
10319
|
+
return a.length >= 3 && (b.includes(a) || a.includes(b) || editDistance2(a, b) <= 2);
|
|
10320
|
+
}
|
|
10321
|
+
function driverOptionDescription() {
|
|
10322
|
+
return `Harness to run (${listDrivers().map((d) => d.id).join(", ")})`;
|
|
10323
|
+
}
|
|
9891
10324
|
function makeRunCommand() {
|
|
9892
|
-
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>",
|
|
10325
|
+
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(
|
|
9893
10326
|
"--agent-definition <ref|path>",
|
|
9894
10327
|
"Agent asset for this one invocation (agent:@pub/name, ai-assets://\u2026, or a directory with agent.yaml); single-shot prompts only"
|
|
9895
10328
|
).option("--skill <name>", "Skill name (for single-shot mode)").action(async (positional, opts) => {
|
|
9896
|
-
const projectDir =
|
|
10329
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
9897
10330
|
const cliDriver = opts.driver;
|
|
9898
10331
|
const dryRun = opts.dryRun ?? false;
|
|
9899
10332
|
const agentDefinition = opts.agentDefinition?.trim() || void 0;
|
|
@@ -9937,18 +10370,29 @@ function makeRunCommand() {
|
|
|
9937
10370
|
}
|
|
9938
10371
|
if (!flowPath) {
|
|
9939
10372
|
const textPrompt = positional.join(" ");
|
|
9940
|
-
|
|
10373
|
+
const promptOnlyOption = agentDefinition !== void 0 || opts.skill !== void 0;
|
|
10374
|
+
if (!textPrompt.trim() || positional.length === 1 && !/\s/.test(flowId) && !promptOnlyOption) {
|
|
9941
10375
|
logErr(`Flow not found: ${flowId}`);
|
|
9942
10376
|
const available = (await discoverFlowsWithLibraries(projectDir)).map((f) => f.id);
|
|
9943
|
-
|
|
9944
|
-
|
|
10377
|
+
const near = available.filter((id) => isNearFlowId(flowId, id));
|
|
10378
|
+
const listed = near.length > 0 ? near : available;
|
|
10379
|
+
if (listed.length > 0) {
|
|
10380
|
+
console.log(
|
|
10381
|
+
` ${S.dim(near.length > 0 ? "Did you mean:" : "Available:")} ${listed.map((id) => S.cmd(id)).join(", ")}`
|
|
10382
|
+
);
|
|
9945
10383
|
}
|
|
10384
|
+
console.log(
|
|
10385
|
+
` ${S.dim('To send it as a prompt, quote more than one word: skaile run "\u2026".')}`
|
|
10386
|
+
);
|
|
9946
10387
|
process.exit(1);
|
|
9947
10388
|
}
|
|
9948
10389
|
try {
|
|
9949
10390
|
const agentDir = resolveSingleShotAgentDir(projectDir, agentDefinition);
|
|
9950
10391
|
if (dryRun) {
|
|
9951
10392
|
await printCompositionDryRun(projectDir, agentDir, driver, model);
|
|
10393
|
+
if (opts.skill && !await printSkillDryRun(projectDir, opts.skill)) {
|
|
10394
|
+
process.exit(1);
|
|
10395
|
+
}
|
|
9952
10396
|
return;
|
|
9953
10397
|
}
|
|
9954
10398
|
await runAgentChat({
|
|
@@ -10012,7 +10456,7 @@ function makeRunCommand() {
|
|
|
10012
10456
|
}
|
|
10013
10457
|
function makeResumeCommand() {
|
|
10014
10458
|
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) => {
|
|
10015
|
-
const projectDir =
|
|
10459
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10016
10460
|
const sessionId = opts.session;
|
|
10017
10461
|
const dryRun = opts.dryRun ?? false;
|
|
10018
10462
|
const session = sessionId ? await loadSessionById(projectDir, sessionId) : await loadSession(projectDir);
|
|
@@ -10039,7 +10483,7 @@ function makeResumeCommand() {
|
|
|
10039
10483
|
}
|
|
10040
10484
|
function makeStatusCommand() {
|
|
10041
10485
|
return new Command("status").description("Show current session state").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
10042
|
-
const projectDir =
|
|
10486
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10043
10487
|
const session = await loadSession(projectDir);
|
|
10044
10488
|
if (!session) {
|
|
10045
10489
|
logInfo("No active session.");
|
|
@@ -10064,17 +10508,17 @@ function makeStatusCommand() {
|
|
|
10064
10508
|
}
|
|
10065
10509
|
function makeClearCommand() {
|
|
10066
10510
|
return new Command("clear").description("Unset current session pointer").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
10067
|
-
const projectDir =
|
|
10511
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10068
10512
|
await clearSession(projectDir);
|
|
10069
10513
|
logOk("Session cleared.");
|
|
10070
10514
|
});
|
|
10071
10515
|
}
|
|
10072
10516
|
function makeReplCommand() {
|
|
10073
|
-
return new Command("repl").description("Start an interactive agent session").option("--project-dir <path>", "Project directory").option("--driver <name>",
|
|
10517
|
+
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) => {
|
|
10074
10518
|
const { findWorkspaceRoot } = await import('../core/index.js');
|
|
10075
10519
|
const { startRepl } = await import('../tui/index.js');
|
|
10076
10520
|
const os2 = await import('os');
|
|
10077
|
-
const userCwd =
|
|
10521
|
+
const userCwd = path22__default.resolve(opts.projectDir ?? process.cwd());
|
|
10078
10522
|
const workspaceRoot = findWorkspaceRoot(userCwd);
|
|
10079
10523
|
let projectDir;
|
|
10080
10524
|
let agentCwd;
|
|
@@ -10089,6 +10533,12 @@ function makeReplCommand() {
|
|
|
10089
10533
|
console.log();
|
|
10090
10534
|
logWarn(`No skaile.yaml found in ${S.cmd(userCwd)} or any parent directory.`);
|
|
10091
10535
|
console.log();
|
|
10536
|
+
if (!process.stdin.isTTY) {
|
|
10537
|
+
logErr(
|
|
10538
|
+
`repl needs a skaile.yaml here when stdin is not a terminal: run ${S.cmd("skaile init")} first.`
|
|
10539
|
+
);
|
|
10540
|
+
process.exit(1);
|
|
10541
|
+
}
|
|
10092
10542
|
const shouldCreate = await p4.confirm({
|
|
10093
10543
|
message: "Create a temporary workspace? (session state in /tmp/)"
|
|
10094
10544
|
});
|
|
@@ -10096,12 +10546,12 @@ function makeReplCommand() {
|
|
|
10096
10546
|
p4.cancel("Cancelled.");
|
|
10097
10547
|
process.exit(0);
|
|
10098
10548
|
}
|
|
10099
|
-
const tmpDir = fs8__default.mkdtempSync(
|
|
10549
|
+
const tmpDir = fs8__default.mkdtempSync(path22__default.join(os2.tmpdir(), "skaile-repl-"));
|
|
10100
10550
|
projectDir = tmpDir;
|
|
10101
10551
|
agentCwd = userCwd;
|
|
10102
10552
|
logOk(`Temporary workspace: ${S.cmd(tmpDir)}`);
|
|
10103
10553
|
if (!driverOverride) {
|
|
10104
|
-
const claudeDir =
|
|
10554
|
+
const claudeDir = path22__default.join(os2.homedir(), ".claude");
|
|
10105
10555
|
if (fs8__default.existsSync(claudeDir)) {
|
|
10106
10556
|
driverOverride = "claude-sdk";
|
|
10107
10557
|
logInfo(`Detected ${S.cmd("~/.claude")} \u2192 using ${S.cmd("claude-sdk")} harness`);
|
|
@@ -10112,21 +10562,29 @@ function makeReplCommand() {
|
|
|
10112
10562
|
}
|
|
10113
10563
|
console.log();
|
|
10114
10564
|
}
|
|
10115
|
-
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10565
|
+
try {
|
|
10566
|
+
await startRepl({
|
|
10567
|
+
projectDir,
|
|
10568
|
+
cwd: agentCwd !== projectDir ? agentCwd : void 0,
|
|
10569
|
+
driver: driverOverride,
|
|
10570
|
+
model: opts.model,
|
|
10571
|
+
resume: opts.resume,
|
|
10572
|
+
resumeSessionId: opts.resumeSession
|
|
10573
|
+
});
|
|
10574
|
+
} catch (err2) {
|
|
10575
|
+
logErr(friendlyDriverError(err2) ?? (err2 instanceof Error ? err2.message : String(err2)));
|
|
10576
|
+
process.exit(1);
|
|
10577
|
+
}
|
|
10123
10578
|
});
|
|
10124
10579
|
}
|
|
10125
10580
|
function parseProviderIds(raw) {
|
|
10126
10581
|
return (raw ?? "").split(",").map((id) => id.trim()).filter((id) => id.length > 0);
|
|
10127
10582
|
}
|
|
10128
10583
|
function makeServeCommand() {
|
|
10129
|
-
return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option(
|
|
10584
|
+
return new Command("serve").description("Start a WebSocket agent server (for platform integration)").option("--port <port>", "WebSocket server port", "8080").option(
|
|
10585
|
+
"--host <address>",
|
|
10586
|
+
"Address to bind (default: all interfaces; use 127.0.0.1 for local clients only)"
|
|
10587
|
+
).option("--project-dir <path>", "Project directory", process.cwd()).option(
|
|
10130
10588
|
"--managed-codex-config <path>",
|
|
10131
10589
|
"Explicit private host configuration for managed Codex"
|
|
10132
10590
|
).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(
|
|
@@ -10154,32 +10612,48 @@ function makeServeCommand() {
|
|
|
10154
10612
|
await ensurePluginsLoadedForServe(opts.projectDir);
|
|
10155
10613
|
}
|
|
10156
10614
|
const providers = parseProviderIds(opts.providers);
|
|
10157
|
-
await
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
|
|
10162
|
-
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10171
|
-
|
|
10172
|
-
|
|
10615
|
+
const { checkDriverSdk } = await import('../serve-preflight-6P2JJEJ3.js');
|
|
10616
|
+
const driverProblem = managedCodex ? null : await checkDriverSdk(opts.projectDir, opts.driver);
|
|
10617
|
+
if (driverProblem) {
|
|
10618
|
+
const { logErr: logErr2 } = await import('../helpers-Y4OT7VIS.js');
|
|
10619
|
+
logErr2(driverProblem);
|
|
10620
|
+
process.exitCode = 1;
|
|
10621
|
+
return;
|
|
10622
|
+
}
|
|
10623
|
+
try {
|
|
10624
|
+
await startAgentServer({
|
|
10625
|
+
port: parseInt(opts.port, 10),
|
|
10626
|
+
...opts.host ? { host: opts.host } : {},
|
|
10627
|
+
authTokenIntake: wsAuth,
|
|
10628
|
+
...managedCodex ? { managedCodex } : {},
|
|
10629
|
+
// The CLI owns its process, so a dead stdout pipe is fatal here.
|
|
10630
|
+
// `SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT=0` opts out — the `local` /
|
|
10631
|
+
// `nix` deploy targets set it for children meant to outlive them.
|
|
10632
|
+
exitOnBrokenPipe: process.env.SKAILE_SERVE_EXIT_ON_BROKEN_STDOUT !== "0",
|
|
10633
|
+
projectDir: opts.projectDir,
|
|
10634
|
+
driver: opts.driver,
|
|
10635
|
+
model: opts.model,
|
|
10636
|
+
provider: opts.provider,
|
|
10637
|
+
sessionId: opts.sessionId,
|
|
10638
|
+
resumeSessionId: opts.resumeSessionId,
|
|
10639
|
+
...providers.length > 0 ? { providers } : {}
|
|
10640
|
+
});
|
|
10641
|
+
} catch (err2) {
|
|
10642
|
+
if (err2?.code !== "EADDRINUSE") throw err2;
|
|
10643
|
+
const { logErr: logErr2 } = await import('../helpers-Y4OT7VIS.js');
|
|
10644
|
+
logErr2(err2.message);
|
|
10645
|
+
process.exitCode = 1;
|
|
10646
|
+
}
|
|
10173
10647
|
}
|
|
10174
10648
|
);
|
|
10175
10649
|
}
|
|
10176
10650
|
async function ensurePluginsLoadedForServe(projectDir) {
|
|
10177
|
-
const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-
|
|
10651
|
+
const { logInfo: logInfo2, logWarn: logWarn2 } = await import('../helpers-Y4OT7VIS.js');
|
|
10178
10652
|
try {
|
|
10179
10653
|
const { resolveSkWorkspaceConfig: resolveSkWorkspaceConfig2 } = await import('../core/index.js');
|
|
10180
10654
|
const config = resolveSkWorkspaceConfig2(projectDir);
|
|
10181
10655
|
if (!config.plugins || config.plugins.length === 0) return;
|
|
10182
|
-
const { ensurePluginsLoaded } = await import('../plugin-store-
|
|
10656
|
+
const { ensurePluginsLoaded } = await import('../plugin-store-XMZSPVBF.js');
|
|
10183
10657
|
const { pluginRegistry } = await import('../plugin-registry/index.js');
|
|
10184
10658
|
const result = await ensurePluginsLoaded(projectDir, config.plugins, pluginRegistry);
|
|
10185
10659
|
if (result.loaded.length > 0) {
|
|
@@ -10193,21 +10667,21 @@ async function ensurePluginsLoadedForServe(projectDir) {
|
|
|
10193
10667
|
}
|
|
10194
10668
|
}
|
|
10195
10669
|
async function runCompileTest(opts) {
|
|
10196
|
-
const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-
|
|
10670
|
+
const { logOk: logOk2, logErr: logErr2, logInfo: logInfo2, S: S2 } = await import('../helpers-Y4OT7VIS.js');
|
|
10197
10671
|
const { tmpdir } = await import('os');
|
|
10198
|
-
const { dirname: dirname3, join:
|
|
10672
|
+
const { dirname: dirname3, join: join7, resolve: resolve5 } = await import('path');
|
|
10199
10673
|
const { fileURLToPath: fileURLToPath2 } = await import('url');
|
|
10200
|
-
const { unlinkSync, existsSync:
|
|
10674
|
+
const { unlinkSync, existsSync: existsSync20 } = await import('fs');
|
|
10201
10675
|
const { spawn } = await import('child_process');
|
|
10202
10676
|
const { portableSpawnSync: portableSpawnSync2 } = await import('../core/index.js');
|
|
10203
|
-
const { MONOREPO_ROOT } = await import('../paths-
|
|
10677
|
+
const { MONOREPO_ROOT } = await import('../paths-U6W6MQNQ.js');
|
|
10204
10678
|
if (MONOREPO_ROOT === null) {
|
|
10205
10679
|
logErr2("--compile-test is only available inside the skaile-dev workspace.");
|
|
10206
10680
|
logInfo2("Run it from a checkout of skaile-ai/skaile-dev (the monorepo shell).");
|
|
10207
10681
|
process.exitCode = 2;
|
|
10208
10682
|
return;
|
|
10209
10683
|
}
|
|
10210
|
-
const outfile =
|
|
10684
|
+
const outfile = join7(tmpdir(), `skaile-compile-test-${Date.now()}`);
|
|
10211
10685
|
const __thisFile = fileURLToPath2(import.meta.url);
|
|
10212
10686
|
const entryPoint = resolve5(dirname3(__thisFile), "..", "index.ts");
|
|
10213
10687
|
logInfo2(`Building compiled binary...`);
|
|
@@ -10262,7 +10736,7 @@ async function runCompileTest(opts) {
|
|
|
10262
10736
|
} catch {
|
|
10263
10737
|
}
|
|
10264
10738
|
try {
|
|
10265
|
-
if (
|
|
10739
|
+
if (existsSync20(outfile)) unlinkSync(outfile);
|
|
10266
10740
|
} catch {
|
|
10267
10741
|
}
|
|
10268
10742
|
}
|
|
@@ -10683,7 +11157,7 @@ function resolveMode2(opts) {
|
|
|
10683
11157
|
if (opts.forceLocal && opts.forceRemote) {
|
|
10684
11158
|
throw new Error("Cannot use both --local and --remote");
|
|
10685
11159
|
}
|
|
10686
|
-
const startDir =
|
|
11160
|
+
const startDir = path22__default.resolve(opts.projectDir ?? process.cwd());
|
|
10687
11161
|
const localDb = findLogsDb(startDir);
|
|
10688
11162
|
if (opts.forceLocal) {
|
|
10689
11163
|
if (!localDb) {
|
|
@@ -10716,14 +11190,14 @@ function resolveMode2(opts) {
|
|
|
10716
11190
|
function findLogsDb(startDir) {
|
|
10717
11191
|
let dir = startDir;
|
|
10718
11192
|
for (let i = 0; i < MAX_WALK_LEVELS; i++) {
|
|
10719
|
-
const candidate =
|
|
11193
|
+
const candidate = path22__default.join(dir, ".skaile", "logs.db");
|
|
10720
11194
|
if (existsSync(candidate)) {
|
|
10721
11195
|
try {
|
|
10722
11196
|
if (statSync(candidate).isFile()) return candidate;
|
|
10723
11197
|
} catch {
|
|
10724
11198
|
}
|
|
10725
11199
|
}
|
|
10726
|
-
const parent =
|
|
11200
|
+
const parent = path22__default.dirname(dir);
|
|
10727
11201
|
if (parent === dir) return void 0;
|
|
10728
11202
|
dir = parent;
|
|
10729
11203
|
}
|
|
@@ -10898,7 +11372,7 @@ function parsePositiveInt(value, flag) {
|
|
|
10898
11372
|
function makeSessionCommand() {
|
|
10899
11373
|
const cmd = new Command("session").description("Manage sessions");
|
|
10900
11374
|
cmd.command("list").description("List all sessions for a project").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
10901
|
-
const projectDir =
|
|
11375
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10902
11376
|
const sessions = await listSessions(projectDir);
|
|
10903
11377
|
const current = await loadSession(projectDir);
|
|
10904
11378
|
if (sessions.length === 0) {
|
|
@@ -10926,7 +11400,7 @@ function makeSessionCommand() {
|
|
|
10926
11400
|
console.log();
|
|
10927
11401
|
});
|
|
10928
11402
|
cmd.command("show <run-id>").description("Show a specific session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
10929
|
-
const projectDir =
|
|
11403
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10930
11404
|
const session = await loadSessionById(projectDir, runId);
|
|
10931
11405
|
if (!session) {
|
|
10932
11406
|
logErr(`Session not found: ${runId}`);
|
|
@@ -10935,7 +11409,7 @@ function makeSessionCommand() {
|
|
|
10935
11409
|
console.log(JSON.stringify(session, null, 2));
|
|
10936
11410
|
});
|
|
10937
11411
|
cmd.command("switch <run-id>").description("Switch the current session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
10938
|
-
const projectDir =
|
|
11412
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10939
11413
|
if (!await loadSessionById(projectDir, runId)) {
|
|
10940
11414
|
logErr(`Session not found: ${runId}`);
|
|
10941
11415
|
process.exit(1);
|
|
@@ -10944,7 +11418,7 @@ function makeSessionCommand() {
|
|
|
10944
11418
|
logOk(`Switched to session: ${S.dim(runId.slice(0, 8))}`);
|
|
10945
11419
|
});
|
|
10946
11420
|
cmd.command("delete <run-id>").description("Delete a session").option("--project-dir <path>", "Project directory", process.cwd()).action(async (runId, opts) => {
|
|
10947
|
-
const projectDir =
|
|
11421
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
10948
11422
|
if (!await loadSessionById(projectDir, runId)) {
|
|
10949
11423
|
logErr(`Session not found: ${runId}`);
|
|
10950
11424
|
process.exit(1);
|
|
@@ -11017,7 +11491,7 @@ function makeShowCommand() {
|
|
|
11017
11491
|
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) => {
|
|
11018
11492
|
const am2 = new AssetManager({
|
|
11019
11493
|
registry: getKindRegistry(),
|
|
11020
|
-
projectDir:
|
|
11494
|
+
projectDir: path22__default.resolve(opts.projectDir),
|
|
11021
11495
|
driverTarget: opts.target
|
|
11022
11496
|
});
|
|
11023
11497
|
if (!kind) {
|
|
@@ -11035,6 +11509,32 @@ function makeShowCommand() {
|
|
|
11035
11509
|
}
|
|
11036
11510
|
});
|
|
11037
11511
|
}
|
|
11512
|
+
function searchCuratedManifests(query) {
|
|
11513
|
+
const dir = getStoreManifestsDir();
|
|
11514
|
+
if (!existsSync(dir)) return [];
|
|
11515
|
+
const q = query.toLowerCase();
|
|
11516
|
+
const hits = [];
|
|
11517
|
+
for (const file of readdirSync(dir).sort()) {
|
|
11518
|
+
if (!file.endsWith(".yaml")) continue;
|
|
11519
|
+
const slug = file.slice(0, -".yaml".length);
|
|
11520
|
+
let manifest;
|
|
11521
|
+
try {
|
|
11522
|
+
manifest = decodeSkaileManifest(readFileSync(path22.join(dir, file), "utf-8")).manifest;
|
|
11523
|
+
} catch {
|
|
11524
|
+
continue;
|
|
11525
|
+
}
|
|
11526
|
+
const repoPublisher2 = manifest.publisher?.replace(/^@/, "");
|
|
11527
|
+
for (const a of manifest.assets ?? []) {
|
|
11528
|
+
const publisher = (a.publisher ?? repoPublisher2 ?? "").replace(/^@/, "");
|
|
11529
|
+
const haystack = [a.name, a.description ?? "", publisher, a.kind].join(" ").toLowerCase();
|
|
11530
|
+
if (!haystack.includes(q)) continue;
|
|
11531
|
+
hits.push({ slug, kind: a.kind, publisher, name: a.name, description: a.description });
|
|
11532
|
+
}
|
|
11533
|
+
}
|
|
11534
|
+
return hits;
|
|
11535
|
+
}
|
|
11536
|
+
|
|
11537
|
+
// cli/src/commands/store.ts
|
|
11038
11538
|
async function fetchIdentity() {
|
|
11039
11539
|
const jwt = await getStoreToken();
|
|
11040
11540
|
return storeFetch({ ...getStoreConfig(), jwt }, "/api/v1/me");
|
|
@@ -11080,43 +11580,70 @@ function makeStoreCommand() {
|
|
|
11080
11580
|
});
|
|
11081
11581
|
store.command("mode <auto|local|remote>").description("Set the catalog resolution mode (not yet wired)").action((_mode) => {
|
|
11082
11582
|
logErr(
|
|
11083
|
-
`\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${
|
|
11583
|
+
`\`skaile store mode\` is scaffolded but not yet wired. Store config lives at ${path22__default.join(globalSkaileDir(), "store", "config.yaml")}.`
|
|
11084
11584
|
);
|
|
11085
11585
|
process.exit(2);
|
|
11086
11586
|
});
|
|
11087
|
-
store.command("search <query>").description("Search the AI Asset Store catalog by name, description, or publisher").option("--kind <kind>", "Filter by asset kind (skill,
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11587
|
+
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(
|
|
11588
|
+
"--all",
|
|
11589
|
+
`List every match (default: ${STORE_ROW_LIMIT} rows, only what \`skaile add\` can install)`
|
|
11590
|
+
).option("-C, --project-dir <dir>", "Project directory (catalog config overlay)", process.cwd()).action(async (query, opts) => {
|
|
11591
|
+
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-N6ESO6IK.js');
|
|
11592
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
11593
|
+
const curated = searchCuratedManifests(query).filter(
|
|
11594
|
+
(h) => !opts.kind || h.kind === opts.kind
|
|
11595
|
+
);
|
|
11596
|
+
const printCurated = () => {
|
|
11597
|
+
if (curated.length === 0) return;
|
|
11598
|
+
console.log(`
|
|
11599
|
+
${S.heading("Local curated manifests")}`);
|
|
11600
|
+
for (const h of curated) {
|
|
11601
|
+
console.log(
|
|
11602
|
+
` ${kindColorPad(h.kind)} ${h.kind}:@${h.publisher}/${h.name} ${S.dim(`(manifest ${h.slug})`)}`
|
|
11603
|
+
);
|
|
11096
11604
|
}
|
|
11097
|
-
console.log();
|
|
11098
|
-
for (const row of formatStoreRows(results, " ")) console.log(row);
|
|
11099
11605
|
console.log(
|
|
11100
11606
|
`
|
|
11101
|
-
${S.dim(
|
|
11607
|
+
${S.dim("Not published: `skaile source add <repo URL>` indexes them for `skaile add`.")}
|
|
11102
11608
|
`
|
|
11103
11609
|
);
|
|
11610
|
+
};
|
|
11611
|
+
try {
|
|
11612
|
+
const remote = await openCatalogSource2({ projectDir });
|
|
11613
|
+
const assets = await remote.listAssets(opts.kind ? { kind: opts.kind } : {});
|
|
11614
|
+
const sel = selectStoreRows(filterCatalogAssets(assets, query), query, Boolean(opts.all));
|
|
11615
|
+
if (sel.shown.length === 0) {
|
|
11616
|
+
logInfo(`No store results for "${query}".`);
|
|
11617
|
+
for (const note of storeSelectionNotes(sel, "")) console.log(note);
|
|
11618
|
+
} else {
|
|
11619
|
+
console.log();
|
|
11620
|
+
for (const row of formatStoreRows(sel.shown, " ")) console.log(row);
|
|
11621
|
+
console.log(
|
|
11622
|
+
`
|
|
11623
|
+
${S.dim(`${sel.shown.length} result(s) \xB7 \`skaile store show <ref>\` for details`)}`
|
|
11624
|
+
);
|
|
11625
|
+
for (const note of storeSelectionNotes(sel, " ")) console.log(note);
|
|
11626
|
+
if (curated.length === 0) console.log();
|
|
11627
|
+
}
|
|
11628
|
+
printCurated();
|
|
11104
11629
|
} catch (e) {
|
|
11630
|
+
printCurated();
|
|
11631
|
+
if (e instanceof LocalCatalogDisabledError2 && curated.length > 0) return;
|
|
11105
11632
|
if (e instanceof LocalCatalogDisabledError2) {
|
|
11106
11633
|
logErr(
|
|
11107
11634
|
`Remote catalog disabled (catalog.url: local). Set \`catalog.url: https://skaile.store\` in ${userConfigPath()}.`
|
|
11108
11635
|
);
|
|
11109
11636
|
} else {
|
|
11110
|
-
logErr(`Store search failed: ${e
|
|
11637
|
+
logErr(`Store search failed: ${await describeStoreFailure(e, projectDir)}`);
|
|
11111
11638
|
}
|
|
11112
11639
|
process.exit(1);
|
|
11113
11640
|
}
|
|
11114
11641
|
});
|
|
11115
11642
|
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) => {
|
|
11116
|
-
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-
|
|
11117
|
-
const { supportsInstallManifest } = await import('../project-
|
|
11643
|
+
const { openCatalogSource: openCatalogSource2, LocalCatalogDisabledError: LocalCatalogDisabledError2 } = await import('../open-library-N6ESO6IK.js');
|
|
11644
|
+
const { supportsInstallManifest } = await import('../project-UP52HEHC.js');
|
|
11118
11645
|
try {
|
|
11119
|
-
const remote = await openCatalogSource2({ projectDir:
|
|
11646
|
+
const remote = await openCatalogSource2({ projectDir: path22__default.resolve(opts.projectDir) });
|
|
11120
11647
|
const asset = await remote.resolve(ref);
|
|
11121
11648
|
if (!asset) {
|
|
11122
11649
|
logErr(`Not found in store: ${ref} (try a full ref, e.g. skill:@publisher/name#version)`);
|
|
@@ -11124,8 +11651,12 @@ function makeStoreCommand() {
|
|
|
11124
11651
|
}
|
|
11125
11652
|
const canonical = catalogAssetRef(asset);
|
|
11126
11653
|
let manifest = null;
|
|
11654
|
+
const manifestFailure = {};
|
|
11127
11655
|
if (supportsInstallManifest(remote)) {
|
|
11128
|
-
manifest = await remote.getInstallManifest(canonical).catch(() =>
|
|
11656
|
+
manifest = await remote.getInstallManifest(canonical).catch(async (err2) => {
|
|
11657
|
+
manifestFailure.text = await describeStoreFailure(err2, path22__default.resolve(opts.projectDir));
|
|
11658
|
+
return null;
|
|
11659
|
+
});
|
|
11129
11660
|
}
|
|
11130
11661
|
const field = (label, value) => ` ${S.label(label.padEnd(11))}${value}`;
|
|
11131
11662
|
console.log();
|
|
@@ -11155,13 +11686,25 @@ function makeStoreCommand() {
|
|
|
11155
11686
|
console.log(field("Repo", asset.repo));
|
|
11156
11687
|
if (asset.sha256) console.log(field("Integrity", asset.sha256));
|
|
11157
11688
|
}
|
|
11689
|
+
if (!manifest && manifestFailure.text) {
|
|
11690
|
+
console.log();
|
|
11691
|
+
console.log(field("Files", S.dim(`unavailable (${manifestFailure.text})`)));
|
|
11692
|
+
}
|
|
11693
|
+
if (asset.requires?.length) {
|
|
11694
|
+
console.log();
|
|
11695
|
+
console.log(` ${S.heading("Requires")}`);
|
|
11696
|
+
for (const dep of asset.requires) console.log(` ${S.dim("\u2192")} ${dep}`);
|
|
11697
|
+
}
|
|
11158
11698
|
if (asset.softDeps?.length) {
|
|
11159
11699
|
console.log();
|
|
11160
11700
|
console.log(` ${S.heading("Soft dependencies")}`);
|
|
11161
11701
|
for (const dep of asset.softDeps) console.log(` ${S.dim("\u2192")} ${dep}`);
|
|
11162
11702
|
}
|
|
11163
11703
|
console.log();
|
|
11164
|
-
|
|
11704
|
+
const notInstallable = storeNotInstallableReason(asset);
|
|
11705
|
+
console.log(
|
|
11706
|
+
notInstallable ? ` ${S.dim(`Not installable: ${notInstallable}`)}` : ` ${S.dim(`Install: skaile add ${canonical}`)}`
|
|
11707
|
+
);
|
|
11165
11708
|
console.log();
|
|
11166
11709
|
} catch (e) {
|
|
11167
11710
|
if (e instanceof LocalCatalogDisabledError2) {
|
|
@@ -11169,7 +11712,9 @@ function makeStoreCommand() {
|
|
|
11169
11712
|
`Remote catalog disabled (catalog.url: local). Set \`catalog.url: https://skaile.store\` in ${userConfigPath()}.`
|
|
11170
11713
|
);
|
|
11171
11714
|
} else {
|
|
11172
|
-
logErr(
|
|
11715
|
+
logErr(
|
|
11716
|
+
`Store show failed: ${await describeStoreFailure(e, path22__default.resolve(opts.projectDir))}`
|
|
11717
|
+
);
|
|
11173
11718
|
}
|
|
11174
11719
|
process.exit(1);
|
|
11175
11720
|
}
|
|
@@ -11239,9 +11784,10 @@ function treeRefs(nodes) {
|
|
|
11239
11784
|
}
|
|
11240
11785
|
function makeTreeCommand() {
|
|
11241
11786
|
return new Command("tree").description("Show full dependency tree").option("--project-dir <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
11787
|
+
requireProjectConfig(opts.projectDir);
|
|
11242
11788
|
const am2 = new AssetManager({
|
|
11243
11789
|
registry: getKindRegistry(),
|
|
11244
|
-
projectDir:
|
|
11790
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
11245
11791
|
});
|
|
11246
11792
|
const root = await am2.tree();
|
|
11247
11793
|
if (root.children.length === 0) {
|
|
@@ -11268,14 +11814,15 @@ function makeUpdateCommand() {
|
|
|
11268
11814
|
"Update only this declared asset (kind:@publisher/name, kind:name or name); exits 1 when none matches"
|
|
11269
11815
|
).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(
|
|
11270
11816
|
async (name, opts) => {
|
|
11271
|
-
const projectDir =
|
|
11817
|
+
const projectDir = path22__default.resolve(opts.projectDir);
|
|
11818
|
+
if (!opts.catalogOnly) requireProjectConfig(projectDir);
|
|
11272
11819
|
const am2 = new AssetManager({ registry: getKindRegistry(), projectDir });
|
|
11273
11820
|
const target = name !== void 0 && !opts.catalogOnly ? await resolveUpdateTarget(am2, name) : void 0;
|
|
11274
11821
|
if (opts.catalog !== false) {
|
|
11275
11822
|
const catalogSpinner = createSpinner();
|
|
11276
11823
|
catalogSpinner.start("Refreshing catalog cache");
|
|
11277
11824
|
try {
|
|
11278
|
-
const remote = await openCatalogSource({ projectDir:
|
|
11825
|
+
const remote = await openCatalogSource({ projectDir: path22__default.resolve(opts.projectDir) });
|
|
11279
11826
|
const result2 = await remote.refresh();
|
|
11280
11827
|
catalogSpinner.stop(
|
|
11281
11828
|
`Catalog refreshed: ${S.heading(String(result2.assetsCached))} assets cached`
|
|
@@ -11287,6 +11834,10 @@ function makeUpdateCommand() {
|
|
|
11287
11834
|
} else {
|
|
11288
11835
|
catalogSpinner.stop("Catalog refresh failed");
|
|
11289
11836
|
logErr(`Catalog refresh failed: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
11837
|
+
if (opts.catalogOnly) {
|
|
11838
|
+
logInfo("Run `skaile catalog test` to debug.");
|
|
11839
|
+
process.exit(1);
|
|
11840
|
+
}
|
|
11290
11841
|
logInfo("Continuing with asset re-deploy. Run `skaile catalog test` to debug.");
|
|
11291
11842
|
}
|
|
11292
11843
|
}
|
|
@@ -11295,11 +11846,11 @@ function makeUpdateCommand() {
|
|
|
11295
11846
|
if (await shouldSyncSources(opts)) {
|
|
11296
11847
|
const syncSpinner = createSpinner();
|
|
11297
11848
|
syncSpinner.start("Syncing sources");
|
|
11298
|
-
const { total, synced, failed } = await syncProjectSources(projectDir);
|
|
11849
|
+
const { total, synced, failed: failed2 } = await syncProjectSources(projectDir);
|
|
11299
11850
|
syncSpinner.stop(
|
|
11300
|
-
total === 0 ? "No sources to sync." : `Synced ${S.heading(`${synced}/${total}`)} source(s)` + (
|
|
11851
|
+
total === 0 ? "No sources to sync." : `Synced ${S.heading(`${synced}/${total}`)} source(s)` + (failed2 ? ` (${failed2} failed)` : "")
|
|
11301
11852
|
);
|
|
11302
|
-
if (
|
|
11853
|
+
if (failed2 > 0) process.exitCode = 1;
|
|
11303
11854
|
} else {
|
|
11304
11855
|
for (const slug of divergedSourceClones(projectDir)) {
|
|
11305
11856
|
logErr(`${slug}: git pull failed: Not possible to fast-forward, aborting.`);
|
|
@@ -11314,27 +11865,39 @@ function makeUpdateCommand() {
|
|
|
11314
11865
|
spinner.start("Re-deploying assets");
|
|
11315
11866
|
let result;
|
|
11316
11867
|
try {
|
|
11317
|
-
result = await am2.install();
|
|
11868
|
+
result = await am2.install({ moveLibraries: true });
|
|
11318
11869
|
} catch (err2) {
|
|
11319
11870
|
spinner.stop("Failed");
|
|
11320
11871
|
logErr(String(err2));
|
|
11321
11872
|
process.exit(1);
|
|
11322
11873
|
}
|
|
11323
|
-
|
|
11874
|
+
const failed = result.missing.length > 0 || !!result.agentInstanceErrors?.length || process.exitCode === 1;
|
|
11875
|
+
spinner.stop(failed ? "Failed" : "Done");
|
|
11324
11876
|
if (result.deployed.length > 0) {
|
|
11325
11877
|
for (const d of result.deployed) logOk(`Updated ${d}`);
|
|
11326
11878
|
}
|
|
11879
|
+
for (const r of result.restored ?? []) {
|
|
11880
|
+
for (const f of r.restored) logInfo(`Restored ${f}`);
|
|
11881
|
+
for (const f of r.removed) logInfo(`Removed ${f} (not part of ${r.ref})`);
|
|
11882
|
+
}
|
|
11327
11883
|
for (const r of result.removed) logWarn(`Removed: ${r}`);
|
|
11328
11884
|
reportReplaced(result.replaced);
|
|
11329
11885
|
reportRelocked(result.relocked);
|
|
11330
|
-
|
|
11886
|
+
reportMoved(result.moved);
|
|
11887
|
+
const changed = result.deployed.length > 0 || result.removed.length > 0 || !!result.replaced?.length || !!result.moved?.length || !!result.relocked?.length;
|
|
11331
11888
|
if (result.lockWritten && changed) {
|
|
11332
11889
|
logInfo(`Lock file written: ${S.dim("skaile.lock.yaml")}`);
|
|
11333
11890
|
}
|
|
11891
|
+
if (result.agentInstanceErrors?.length) {
|
|
11892
|
+
logErr(
|
|
11893
|
+
`${result.agentInstanceErrors.length} agent instance(s) could not be rendered (see above)`
|
|
11894
|
+
);
|
|
11895
|
+
process.exitCode = 1;
|
|
11896
|
+
}
|
|
11334
11897
|
if (result.missing.length > 0) {
|
|
11335
11898
|
for (const m of result.missing) logErr(`Missing: ${m}${result.missingHints?.[m] ?? ""}`);
|
|
11336
11899
|
process.exitCode = 1;
|
|
11337
|
-
} else if (!changed) {
|
|
11900
|
+
} else if (!changed && !failed) {
|
|
11338
11901
|
logInfo("Nothing to update.");
|
|
11339
11902
|
}
|
|
11340
11903
|
}
|
|
@@ -11388,20 +11951,23 @@ function readText2(file) {
|
|
|
11388
11951
|
}
|
|
11389
11952
|
}
|
|
11390
11953
|
async function updateOne(am2, projectDir, target) {
|
|
11391
|
-
const lockPath =
|
|
11954
|
+
const lockPath = path22__default.join(projectDir, "skaile.lock.yaml");
|
|
11392
11955
|
const before = readText2(lockPath);
|
|
11393
11956
|
const spinner = createSpinner();
|
|
11394
11957
|
spinner.start(`Updating ${target.ref}`);
|
|
11395
11958
|
let deployed;
|
|
11396
11959
|
try {
|
|
11397
|
-
deployed = await am2.add(target.ref
|
|
11960
|
+
deployed = await am2.add(target.ref, {
|
|
11961
|
+
preferLockedLibrary: true,
|
|
11962
|
+
onLibraryMoved: (m) => reportMoved([m])
|
|
11963
|
+
});
|
|
11398
11964
|
} catch (err2) {
|
|
11399
11965
|
spinner.stop("Failed");
|
|
11400
11966
|
logErr(err2 instanceof Error ? err2.message : String(err2));
|
|
11401
11967
|
process.exitCode = 1;
|
|
11402
11968
|
return;
|
|
11403
11969
|
}
|
|
11404
|
-
spinner.stop("Done");
|
|
11970
|
+
spinner.stop(process.exitCode === 1 ? "Failed" : "Done");
|
|
11405
11971
|
for (const d of deployed) logOk(`Updated ${d}`);
|
|
11406
11972
|
if (deployed.length > 0) return;
|
|
11407
11973
|
if (readText2(lockPath) !== before) logInfo(`Re-locked ${target.ref}`);
|
|
@@ -11495,17 +12061,23 @@ function refKindName(ref) {
|
|
|
11495
12061
|
let rest = colon === -1 ? trimmed : trimmed.slice(colon + 1);
|
|
11496
12062
|
const hash = rest.indexOf("#");
|
|
11497
12063
|
if (hash !== -1) rest = rest.slice(0, hash);
|
|
12064
|
+
let publisher;
|
|
11498
12065
|
if (rest.startsWith("@")) {
|
|
11499
12066
|
const slash = rest.indexOf("/");
|
|
11500
|
-
if (slash !== -1)
|
|
12067
|
+
if (slash !== -1) {
|
|
12068
|
+
publisher = rest.slice(1, slash);
|
|
12069
|
+
rest = rest.slice(slash + 1);
|
|
12070
|
+
}
|
|
11501
12071
|
}
|
|
11502
|
-
return { kind, name: rest };
|
|
12072
|
+
return { kind, name: rest, publisher };
|
|
11503
12073
|
}
|
|
11504
12074
|
function whyEmptyMessage(ref, declared) {
|
|
11505
|
-
const { kind, name } = refKindName(ref);
|
|
11506
|
-
const isDeclared = declared.some(
|
|
11507
|
-
(d
|
|
11508
|
-
|
|
12075
|
+
const { kind, name, publisher } = refKindName(ref);
|
|
12076
|
+
const isDeclared = declared.some((d) => {
|
|
12077
|
+
if (d.name !== name || kind !== void 0 && d.kind !== kind) return false;
|
|
12078
|
+
const declaredPublisher = d.ref ? refKindName(d.ref).publisher : void 0;
|
|
12079
|
+
return !publisher || !declaredPublisher || publisher === declaredPublisher;
|
|
12080
|
+
});
|
|
11509
12081
|
if (isDeclared) {
|
|
11510
12082
|
return `${ref} not found in lock file. Run \`skaile install\` first.`;
|
|
11511
12083
|
}
|
|
@@ -11513,17 +12085,26 @@ function whyEmptyMessage(ref, declared) {
|
|
|
11513
12085
|
}
|
|
11514
12086
|
function makeWhyCommand() {
|
|
11515
12087
|
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) => {
|
|
12088
|
+
requireProjectConfig(opts.projectDir);
|
|
11516
12089
|
const am2 = new AssetManager({
|
|
11517
12090
|
registry: getKindRegistry(),
|
|
11518
|
-
projectDir:
|
|
12091
|
+
projectDir: path22__default.resolve(opts.projectDir)
|
|
11519
12092
|
});
|
|
11520
12093
|
const chain = await am2.why(ref);
|
|
11521
12094
|
if (chain.length === 0) {
|
|
12095
|
+
const declaredGap = (await am2.gapsOf(ref)).find((g) => g.type === "declared");
|
|
12096
|
+
if (declaredGap) {
|
|
12097
|
+
logErr(declaredGap.message);
|
|
12098
|
+
process.exitCode = 1;
|
|
12099
|
+
return;
|
|
12100
|
+
}
|
|
11522
12101
|
let declared;
|
|
11523
12102
|
try {
|
|
11524
12103
|
declared = await am2.listDeclared();
|
|
11525
|
-
} catch {
|
|
11526
|
-
logErr(
|
|
12104
|
+
} catch (err2) {
|
|
12105
|
+
logErr(
|
|
12106
|
+
`${ref} is not in the lock file, and skaile.yaml cannot be read: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
12107
|
+
);
|
|
11527
12108
|
process.exitCode = 1;
|
|
11528
12109
|
return;
|
|
11529
12110
|
}
|
|
@@ -11548,11 +12129,38 @@ function makeWhyCommand() {
|
|
|
11548
12129
|
});
|
|
11549
12130
|
}
|
|
11550
12131
|
|
|
12132
|
+
// cli/src/index-busy.ts
|
|
12133
|
+
var INDEX_BUSY_MESSAGE = "The skaile index is busy (another skaile process holds it); retry in a moment.";
|
|
12134
|
+
function isIndexBusyError(err2) {
|
|
12135
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12136
|
+
let cur = err2;
|
|
12137
|
+
while (cur && typeof cur === "object" && !seen.has(cur)) {
|
|
12138
|
+
seen.add(cur);
|
|
12139
|
+
const { code, message, cause } = cur;
|
|
12140
|
+
if (typeof code === "string" && code.startsWith("SQLITE_BUSY")) return true;
|
|
12141
|
+
if (typeof message === "string" && /SQLITE_BUSY|database is locked/i.test(message)) return true;
|
|
12142
|
+
cur = cause;
|
|
12143
|
+
}
|
|
12144
|
+
return false;
|
|
12145
|
+
}
|
|
12146
|
+
|
|
11551
12147
|
// cli/src/index.ts
|
|
12148
|
+
{
|
|
12149
|
+
const envLevel = process.env.SKAILE_LOG_LEVEL;
|
|
12150
|
+
const level = envLevel === "debug" || envLevel === "info" || envLevel === "warn" || envLevel === "error" ? envLevel : "warn";
|
|
12151
|
+
registerLogStore(
|
|
12152
|
+
new LogStore({
|
|
12153
|
+
sessionId: "cli",
|
|
12154
|
+
level,
|
|
12155
|
+
flushIntervalMs: 0,
|
|
12156
|
+
sinks: [new StdoutSink({ stream: "stderr", format: "pretty" })]
|
|
12157
|
+
})
|
|
12158
|
+
);
|
|
12159
|
+
}
|
|
11552
12160
|
var _defaultFormatHelp = Help.prototype.formatHelp;
|
|
11553
12161
|
var pkg = JSON.parse(
|
|
11554
12162
|
readFileSync(
|
|
11555
|
-
|
|
12163
|
+
path22__default.resolve(path22__default.dirname(fileURLToPath(import.meta.url)), "../../package.json"),
|
|
11556
12164
|
"utf-8"
|
|
11557
12165
|
)
|
|
11558
12166
|
);
|
|
@@ -11563,7 +12171,7 @@ for (const key of [
|
|
|
11563
12171
|
"SKAILE_CACHE_DIR"
|
|
11564
12172
|
]) {
|
|
11565
12173
|
const value = process.env[key];
|
|
11566
|
-
if (value) process.env[key] =
|
|
12174
|
+
if (value) process.env[key] = path22__default.resolve(value);
|
|
11567
12175
|
}
|
|
11568
12176
|
var program = new Command("skaile").description("AI asset manager").version(pkg.version, "-v, --version", "Show the skaile CLI version").enablePositionalOptions().configureHelp({
|
|
11569
12177
|
formatHelp(cmd, helper) {
|
|
@@ -11608,7 +12216,7 @@ Execution:
|
|
|
11608
12216
|
repl Interactive agent REPL
|
|
11609
12217
|
resume Resume last session
|
|
11610
12218
|
serve [--compile-test] Start WebSocket agent server
|
|
11611
|
-
mcp-server Start workspace MCP server (for .
|
|
12219
|
+
mcp-server Start workspace MCP server (for .mcp.json)
|
|
11612
12220
|
integration install [--driver all] Install agent integration (claude-code | omp | codex)
|
|
11613
12221
|
integration uninstall [--driver all] Uninstall agent integration
|
|
11614
12222
|
integration enable Enable integration (claude-code only)
|
|
@@ -11683,7 +12291,7 @@ program.command("init [project-dir]").description("Initialize a project director
|
|
|
11683
12291
|
(projectDir, opts) => runInit(projectDir, opts)
|
|
11684
12292
|
);
|
|
11685
12293
|
async function runInit(projectDir, opts) {
|
|
11686
|
-
const { mkdirSync: mkdirSync5, writeFileSync:
|
|
12294
|
+
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync7 } = await import('fs');
|
|
11687
12295
|
const { stringify: stringify2 } = await import('yaml');
|
|
11688
12296
|
const { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS: SUPPORTED_DRIVER_TARGETS2 } = await import('../core/index.js');
|
|
11689
12297
|
const harness = opts.harness;
|
|
@@ -11692,32 +12300,32 @@ async function runInit(projectDir, opts) {
|
|
|
11692
12300
|
process.exitCode = 1;
|
|
11693
12301
|
return;
|
|
11694
12302
|
}
|
|
11695
|
-
const resolved =
|
|
11696
|
-
const projectName =
|
|
12303
|
+
const resolved = path22__default.resolve(projectDir ?? ".");
|
|
12304
|
+
const projectName = path22__default.basename(resolved);
|
|
11697
12305
|
const created = [];
|
|
11698
|
-
const { existsSync:
|
|
11699
|
-
if (!
|
|
12306
|
+
const { existsSync: existsSync20 } = await import('fs');
|
|
12307
|
+
if (!existsSync20(resolved)) {
|
|
11700
12308
|
mkdirSync5(resolved, { recursive: true });
|
|
11701
12309
|
created.push(".");
|
|
11702
12310
|
}
|
|
11703
|
-
const skaileDir =
|
|
11704
|
-
if (!
|
|
11705
|
-
mkdirSync5(
|
|
12311
|
+
const skaileDir = path22__default.join(resolved, ".skaile");
|
|
12312
|
+
if (!existsSync20(skaileDir)) {
|
|
12313
|
+
mkdirSync5(path22__default.join(skaileDir, "sessions"), { recursive: true });
|
|
11706
12314
|
created.push(".skaile/");
|
|
11707
12315
|
}
|
|
11708
|
-
const settingsPath =
|
|
11709
|
-
if (!
|
|
11710
|
-
|
|
12316
|
+
const settingsPath = path22__default.join(skaileDir, "settings.json");
|
|
12317
|
+
if (!existsSync20(settingsPath)) {
|
|
12318
|
+
writeFileSync7(settingsPath, "{}\n");
|
|
11711
12319
|
created.push(".skaile/settings.json");
|
|
11712
12320
|
}
|
|
11713
|
-
const wsConfigPath =
|
|
11714
|
-
if (!
|
|
11715
|
-
|
|
12321
|
+
const wsConfigPath = path22__default.join(resolved, "skaile.yaml");
|
|
12322
|
+
if (!existsSync20(wsConfigPath)) {
|
|
12323
|
+
writeFileSync7(wsConfigPath, stringify2(buildInitWorkspaceConfig(projectName, harness)));
|
|
11716
12324
|
created.push("skaile.yaml");
|
|
11717
12325
|
}
|
|
11718
12326
|
for (const dir of new Set(Object.values(DRIVER_TARGETS[harness].local))) {
|
|
11719
|
-
const full =
|
|
11720
|
-
if (!
|
|
12327
|
+
const full = path22__default.join(resolved, dir);
|
|
12328
|
+
if (!existsSync20(full)) {
|
|
11721
12329
|
mkdirSync5(full, { recursive: true });
|
|
11722
12330
|
created.push(`${dir}/`);
|
|
11723
12331
|
}
|
|
@@ -11747,10 +12355,13 @@ function buildInitWorkspaceConfig(projectName, harness) {
|
|
|
11747
12355
|
}
|
|
11748
12356
|
async function initGitScaffold(resolved, created) {
|
|
11749
12357
|
const { execSync: execSync2 } = await import('child_process');
|
|
11750
|
-
const { existsSync:
|
|
11751
|
-
const gitignorePath =
|
|
12358
|
+
const { existsSync: existsSync20, readFileSync: readFileSync12, writeFileSync: writeFileSync7 } = await import('fs');
|
|
12359
|
+
const gitignorePath = path22__default.join(resolved, ".gitignore");
|
|
11752
12360
|
const entries = [
|
|
11753
12361
|
"node_modules/",
|
|
12362
|
+
// Python bytecode a deployed skill script leaves inside `.claude/skills` and friends.
|
|
12363
|
+
"__pycache__/",
|
|
12364
|
+
"*.pyc",
|
|
11754
12365
|
".skaile/sessions/",
|
|
11755
12366
|
".skaile/cache/",
|
|
11756
12367
|
// skaile-created artifacts that must never be committed: the per-session log
|
|
@@ -11761,20 +12372,25 @@ async function initGitScaffold(resolved, created) {
|
|
|
11761
12372
|
".skaile/settings.json",
|
|
11762
12373
|
".skaile/providers.yml",
|
|
11763
12374
|
".skaile/history.yaml",
|
|
12375
|
+
// Per-machine files a run writes into the project: the system prompt handed to the harness
|
|
12376
|
+
// (it carries the host path) and omp's session logs.
|
|
12377
|
+
".codex/skaile-session-instructions.md",
|
|
12378
|
+
".omp/system.md",
|
|
12379
|
+
".omp/sessions/",
|
|
11764
12380
|
"*.log",
|
|
11765
12381
|
".env",
|
|
11766
12382
|
".env.local"
|
|
11767
12383
|
];
|
|
11768
|
-
const existing =
|
|
12384
|
+
const existing = existsSync20(gitignorePath) ? readFileSync12(gitignorePath, "utf-8") : "";
|
|
11769
12385
|
const have = new Set(existing.split("\n").map((l) => l.trim()));
|
|
11770
12386
|
const append = entries.filter((e) => !have.has(e));
|
|
11771
12387
|
if (append.length > 0) {
|
|
11772
12388
|
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
11773
|
-
|
|
12389
|
+
writeFileSync7(gitignorePath, `${existing + prefix}${append.join("\n")}
|
|
11774
12390
|
`);
|
|
11775
12391
|
if (!existing) created.push(".gitignore");
|
|
11776
12392
|
}
|
|
11777
|
-
if (!
|
|
12393
|
+
if (!existsSync20(path22__default.join(resolved, ".git"))) {
|
|
11778
12394
|
try {
|
|
11779
12395
|
execSync2("git init", { cwd: resolved, stdio: "pipe" });
|
|
11780
12396
|
created.push(".git/");
|
|
@@ -11804,7 +12420,7 @@ async function bootstrapUserConfig() {
|
|
|
11804
12420
|
}
|
|
11805
12421
|
async function hydrateInitSources(resolved, created) {
|
|
11806
12422
|
try {
|
|
11807
|
-
const { ensureSourcesCloned } = await import('../ensure-sources-
|
|
12423
|
+
const { ensureSourcesCloned } = await import('../ensure-sources-POMEQSTM.js');
|
|
11808
12424
|
const hydrate = ensureSourcesCloned(resolved, { quiet: true });
|
|
11809
12425
|
for (const n of hydrate.cloned) created.push(`~/.skaile/cache/sources/${n}/`);
|
|
11810
12426
|
if (hydrate.failed.length > 0) {
|
|
@@ -11820,7 +12436,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
11820
12436
|
logOk(`Initialized project at ${S.heading(resolved)}`);
|
|
11821
12437
|
console.log();
|
|
11822
12438
|
console.log(S.heading(" Next steps:"));
|
|
11823
|
-
const isCurrentDir = resolved ===
|
|
12439
|
+
const isCurrentDir = resolved === path22__default.resolve(".");
|
|
11824
12440
|
let step = 1;
|
|
11825
12441
|
if (!isCurrentDir) {
|
|
11826
12442
|
console.log(` ${S.dim(`${step}.`)} ${S.cmd(`cd ${projectDir}`)}`);
|
|
@@ -11844,7 +12460,7 @@ function printInitSummary(resolved, projectDir, created) {
|
|
|
11844
12460
|
console.log();
|
|
11845
12461
|
}
|
|
11846
12462
|
program.command("setup").description("Interactive provider setup wizard").action(async () => {
|
|
11847
|
-
const { cmdSetup } = await import('../setup-
|
|
12463
|
+
const { cmdSetup } = await import('../setup-5IRUH5OS.js');
|
|
11848
12464
|
await cmdSetup([], { projectDir: process.cwd() });
|
|
11849
12465
|
});
|
|
11850
12466
|
program.addCommand(makeInstallCommand());
|
|
@@ -11922,9 +12538,20 @@ process.stdout.on("error", (err2) => {
|
|
|
11922
12538
|
if (err2.code === "EPIPE") process.exit(0);
|
|
11923
12539
|
throw err2;
|
|
11924
12540
|
});
|
|
12541
|
+
var commandSettled = false;
|
|
12542
|
+
process.once("beforeExit", () => {
|
|
12543
|
+
if (commandSettled) return;
|
|
12544
|
+
logErr("The command ended before it finished (nothing left to wait for).");
|
|
12545
|
+
process.exit(1);
|
|
12546
|
+
});
|
|
11925
12547
|
try {
|
|
11926
12548
|
await program.parseAsync();
|
|
12549
|
+
commandSettled = true;
|
|
11927
12550
|
} catch (err2) {
|
|
12551
|
+
if (isIndexBusyError(err2)) {
|
|
12552
|
+
logErr(INDEX_BUSY_MESSAGE);
|
|
12553
|
+
process.exit(1);
|
|
12554
|
+
}
|
|
11928
12555
|
const { LibrarySyncError } = await import('../library/index.js');
|
|
11929
12556
|
if (!(err2 instanceof LibrarySyncError || err2 instanceof SourceEntryError)) throw err2;
|
|
11930
12557
|
logErr(err2.message);
|