@skaile/workspaces 6.9.1 → 6.10.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 +24 -0
- package/dist/ai-sdk.js +8 -8
- package/dist/{asset-feeds-PANNQPEE.js → asset-feeds-UG3PG423.js} +22 -22
- package/dist/{asset-feeds-PANNQPEE.js.map → asset-feeds-UG3PG423.js.map} +1 -1
- package/dist/asset-manager/catalog-deployer.js +8 -8
- package/dist/asset-manager/history.js +8 -8
- package/dist/asset-manager/index.js +14 -14
- package/dist/asset-manager/installer.js +9 -9
- package/dist/asset-manager/renderers.js +8 -8
- package/dist/asset-manager/src/harness-switch-state.d.ts +30 -0
- package/dist/asset-manager/src/harness-switch-state.d.ts.map +1 -0
- package/dist/asset-manager/src/index.d.ts +49 -12
- package/dist/asset-manager/src/index.d.ts.map +1 -1
- package/dist/asset-manager/src/mcp-config.d.ts +6 -0
- package/dist/asset-manager/src/mcp-config.d.ts.map +1 -1
- package/dist/bridge/codex-app-server.js +1 -2
- package/dist/bridge/harnesses/claude-sdk.js +11 -11
- package/dist/bridge/harnesses/codex.js +15 -1926
- package/dist/bridge/harnesses/codex.js.map +1 -1
- package/dist/bridge/harnesses/continue.js +11 -11
- package/dist/bridge/harnesses/echo.js +3 -3
- package/dist/bridge/harnesses/gemini.js +6 -6
- package/dist/bridge/harnesses/goose.js +11 -11
- package/dist/bridge/harnesses/omp.js +26 -9
- package/dist/bridge/harnesses/omp.js.map +1 -1
- package/dist/bridge/harnesses/opencode.js +11 -11
- package/dist/bridge/harnesses/qwen.js +6 -6
- package/dist/bridge/index.js +17 -16
- package/dist/bridge/src/harness-model-check.d.ts +5 -4
- package/dist/bridge/src/harness-model-check.d.ts.map +1 -1
- package/dist/bridge/src/harnesses/codex.d.ts +13 -0
- package/dist/bridge/src/harnesses/codex.d.ts.map +1 -1
- package/dist/bridge/src/harnesses/omp.d.ts +11 -0
- package/dist/bridge/src/harnesses/omp.d.ts.map +1 -1
- package/dist/bridge/src/index.d.ts +1 -0
- package/dist/bridge/src/index.d.ts.map +1 -1
- package/dist/{chunk-SME3PK4L.js → chunk-2D6HZAO5.js} +8 -8
- package/dist/{chunk-SME3PK4L.js.map → chunk-2D6HZAO5.js.map} +1 -1
- package/dist/chunk-2MUUPRIG.js +688 -0
- package/dist/chunk-2MUUPRIG.js.map +1 -0
- package/dist/{chunk-TMQFOJ6F.js → chunk-2PVYDAFN.js} +3 -3
- package/dist/{chunk-TMQFOJ6F.js.map → chunk-2PVYDAFN.js.map} +1 -1
- package/dist/{chunk-S47KU4YB.js → chunk-2U67XYZM.js} +3 -3
- package/dist/{chunk-S47KU4YB.js.map → chunk-2U67XYZM.js.map} +1 -1
- package/dist/{chunk-PLVM6OIV.js → chunk-375HN3FD.js} +18 -14
- package/dist/chunk-375HN3FD.js.map +1 -0
- package/dist/{chunk-VEIWFS7Z.js → chunk-4I4SBOCS.js} +345 -88
- package/dist/chunk-4I4SBOCS.js.map +1 -0
- package/dist/{chunk-PBEDRYHP.js → chunk-4Z4RULWQ.js} +48 -28
- package/dist/{chunk-PBEDRYHP.js.map → chunk-4Z4RULWQ.js.map} +1 -1
- package/dist/{chunk-MPO5CQUZ.js → chunk-5JBMYZNA.js} +3 -3
- package/dist/{chunk-MPO5CQUZ.js.map → chunk-5JBMYZNA.js.map} +1 -1
- package/dist/{chunk-EMSU6L7K.js → chunk-5KQFR4D7.js} +6 -6
- package/dist/{chunk-EMSU6L7K.js.map → chunk-5KQFR4D7.js.map} +1 -1
- package/dist/{chunk-KNY356I3.js → chunk-5KSGZP3E.js} +11 -4
- package/dist/chunk-5KSGZP3E.js.map +1 -0
- package/dist/{chunk-IISEBVMA.js → chunk-5P7LTPBR.js} +5 -5
- package/dist/{chunk-IISEBVMA.js.map → chunk-5P7LTPBR.js.map} +1 -1
- package/dist/{chunk-2UKNI2HJ.js → chunk-6O7VDKX3.js} +2 -2
- package/dist/{chunk-2UKNI2HJ.js.map → chunk-6O7VDKX3.js.map} +1 -1
- package/dist/{chunk-FZTHL6SK.js → chunk-7DUOKE73.js} +27 -33
- package/dist/chunk-7DUOKE73.js.map +1 -0
- package/dist/{chunk-V5KG6CCV.js → chunk-7HRZACI4.js} +7 -2
- package/dist/chunk-7HRZACI4.js.map +1 -0
- package/dist/{chunk-U3FI4DVT.js → chunk-7K73MCI6.js} +7 -5
- package/dist/chunk-7K73MCI6.js.map +1 -0
- package/dist/{chunk-BDAXHJC5.js → chunk-BCID52M5.js} +6 -6
- package/dist/{chunk-BDAXHJC5.js.map → chunk-BCID52M5.js.map} +1 -1
- package/dist/{chunk-FZO64PLQ.js → chunk-BNLXZXZN.js} +81 -8
- package/dist/chunk-BNLXZXZN.js.map +1 -0
- package/dist/{chunk-ZUROGXJM.js → chunk-C5UKYTTD.js} +13 -23
- package/dist/chunk-C5UKYTTD.js.map +1 -0
- package/dist/{chunk-LYVLDGML.js → chunk-CG63XGVV.js} +3 -3
- package/dist/{chunk-LYVLDGML.js.map → chunk-CG63XGVV.js.map} +1 -1
- package/dist/{chunk-4ROXSQEG.js → chunk-CJO3XKO7.js} +4 -4
- package/dist/{chunk-4ROXSQEG.js.map → chunk-CJO3XKO7.js.map} +1 -1
- package/dist/{chunk-OSABUEWA.js → chunk-CVUMZTNO.js} +4 -4
- package/dist/{chunk-OSABUEWA.js.map → chunk-CVUMZTNO.js.map} +1 -1
- package/dist/{chunk-E675QKFG.js → chunk-DOMRBOJZ.js} +5 -5
- package/dist/{chunk-E675QKFG.js.map → chunk-DOMRBOJZ.js.map} +1 -1
- package/dist/{chunk-GTAHU4N4.js → chunk-EB2LKPI6.js} +4 -4
- package/dist/{chunk-GTAHU4N4.js.map → chunk-EB2LKPI6.js.map} +1 -1
- package/dist/{chunk-GZL6RN4Z.js → chunk-FXBKBOI5.js} +169 -49
- package/dist/chunk-FXBKBOI5.js.map +1 -0
- package/dist/{chunk-J45JCYS4.js → chunk-GA4GUDTL.js} +4 -4
- package/dist/{chunk-J45JCYS4.js.map → chunk-GA4GUDTL.js.map} +1 -1
- package/dist/{chunk-RZRJTCP2.js → chunk-HE3TZYNG.js} +4 -4
- package/dist/{chunk-RZRJTCP2.js.map → chunk-HE3TZYNG.js.map} +1 -1
- package/dist/chunk-HLFLET7S.js +2443 -0
- package/dist/chunk-HLFLET7S.js.map +1 -0
- package/dist/{chunk-WEPTGUR4.js → chunk-HQUF6O4B.js} +27 -56
- package/dist/chunk-HQUF6O4B.js.map +1 -0
- package/dist/{chunk-QIV7H3GJ.js → chunk-IMO4EHND.js} +5 -5
- package/dist/{chunk-QIV7H3GJ.js.map → chunk-IMO4EHND.js.map} +1 -1
- package/dist/{chunk-TUOHA6BM.js → chunk-IOXFT5D7.js} +3 -3
- package/dist/{chunk-TUOHA6BM.js.map → chunk-IOXFT5D7.js.map} +1 -1
- package/dist/{chunk-CPMLMNI5.js → chunk-JDZUQFN7.js} +4 -4
- package/dist/{chunk-CPMLMNI5.js.map → chunk-JDZUQFN7.js.map} +1 -1
- package/dist/{chunk-7TF5MNFK.js → chunk-KE5HDORU.js} +2 -2
- package/dist/{chunk-7TF5MNFK.js.map → chunk-KE5HDORU.js.map} +1 -1
- package/dist/{chunk-PTJTOPE5.js → chunk-KOI7QFDH.js} +3 -3
- package/dist/{chunk-PTJTOPE5.js.map → chunk-KOI7QFDH.js.map} +1 -1
- package/dist/{chunk-NDBHEOIA.js → chunk-KRL53RZB.js} +8 -8
- package/dist/{chunk-NDBHEOIA.js.map → chunk-KRL53RZB.js.map} +1 -1
- package/dist/{chunk-7QYBKUAS.js → chunk-LKBRBVVS.js} +3 -3
- package/dist/{chunk-7QYBKUAS.js.map → chunk-LKBRBVVS.js.map} +1 -1
- package/dist/{chunk-USSP43U3.js → chunk-LQWOU7S2.js} +3 -3
- package/dist/{chunk-USSP43U3.js.map → chunk-LQWOU7S2.js.map} +1 -1
- package/dist/{chunk-4KPQ6ILH.js → chunk-MEU2HHGV.js} +18 -9
- package/dist/chunk-MEU2HHGV.js.map +1 -0
- package/dist/{chunk-QC5BYUED.js → chunk-MS2IXLTC.js} +4 -4
- package/dist/{chunk-QC5BYUED.js.map → chunk-MS2IXLTC.js.map} +1 -1
- package/dist/{chunk-Q5SSRVD5.js → chunk-NCJSYU6A.js} +16 -14
- package/dist/chunk-NCJSYU6A.js.map +1 -0
- package/dist/{chunk-5J6N6LHL.js → chunk-NFFBYG2W.js} +3 -3
- package/dist/{chunk-5J6N6LHL.js.map → chunk-NFFBYG2W.js.map} +1 -1
- package/dist/{chunk-7UCPGQCW.js → chunk-NTFP2XF4.js} +10 -10
- package/dist/chunk-NTFP2XF4.js.map +1 -0
- package/dist/{chunk-KVTV4LT2.js → chunk-PSPFWTJI.js} +4 -4
- package/dist/{chunk-KVTV4LT2.js.map → chunk-PSPFWTJI.js.map} +1 -1
- package/dist/{chunk-YPTDPN2B.js → chunk-PTXQMTCG.js} +3 -3
- package/dist/{chunk-YPTDPN2B.js.map → chunk-PTXQMTCG.js.map} +1 -1
- package/dist/{chunk-X5SGUBUV.js → chunk-QBJQ426X.js} +3 -3
- package/dist/{chunk-X5SGUBUV.js.map → chunk-QBJQ426X.js.map} +1 -1
- package/dist/{chunk-QBUJTVMY.js → chunk-R3ZNAPBV.js} +3 -3
- package/dist/{chunk-QBUJTVMY.js.map → chunk-R3ZNAPBV.js.map} +1 -1
- package/dist/{chunk-RP3ML3QD.js → chunk-RTFH2QR2.js} +3 -3
- package/dist/{chunk-RP3ML3QD.js.map → chunk-RTFH2QR2.js.map} +1 -1
- package/dist/{chunk-5KWQMCH7.js → chunk-RZ5R6GDJ.js} +5 -5
- package/dist/{chunk-5KWQMCH7.js.map → chunk-RZ5R6GDJ.js.map} +1 -1
- package/dist/{chunk-MDCI4RSG.js → chunk-RZL4TOK3.js} +20 -6
- package/dist/chunk-RZL4TOK3.js.map +1 -0
- package/dist/{chunk-LMADWO4Q.js → chunk-SBAUZ7XH.js} +4 -4
- package/dist/{chunk-LMADWO4Q.js.map → chunk-SBAUZ7XH.js.map} +1 -1
- package/dist/{chunk-AQTAULXT.js → chunk-SKG6G4HO.js} +108 -44
- package/dist/chunk-SKG6G4HO.js.map +1 -0
- package/dist/{chunk-HQAPUPBE.js → chunk-V2VDTQ7A.js} +3 -3
- package/dist/{chunk-HQAPUPBE.js.map → chunk-V2VDTQ7A.js.map} +1 -1
- package/dist/{chunk-GNUA7XT2.js → chunk-VS6XC5JE.js} +3 -3
- package/dist/{chunk-GNUA7XT2.js.map → chunk-VS6XC5JE.js.map} +1 -1
- package/dist/{chunk-5J6JWGY4.js → chunk-WDG5IVEA.js} +3 -3
- package/dist/{chunk-5J6JWGY4.js.map → chunk-WDG5IVEA.js.map} +1 -1
- package/dist/{chunk-XB4XHGIE.js → chunk-XWCV2A2F.js} +4 -4
- package/dist/{chunk-XB4XHGIE.js.map → chunk-XWCV2A2F.js.map} +1 -1
- package/dist/{chunk-UWD7YBDR.js → chunk-ZLDAPZIX.js} +4 -4
- package/dist/{chunk-UWD7YBDR.js.map → chunk-ZLDAPZIX.js.map} +1 -1
- package/dist/{claude-code-ILZ46SLO.js → claude-code-CMFGCDMX.js} +5 -5
- package/dist/{claude-code-ILZ46SLO.js.map → claude-code-CMFGCDMX.js.map} +1 -1
- package/dist/cli/index.js +322 -196
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/catalog.d.ts.map +1 -1
- package/dist/cli/src/commands/config.d.ts.map +1 -1
- package/dist/cli/src/commands/connector.d.ts.map +1 -1
- package/dist/cli/src/commands/harness-preflight.d.ts +3 -1
- package/dist/cli/src/commands/harness-preflight.d.ts.map +1 -1
- package/dist/cli/src/commands/harness.d.ts.map +1 -1
- package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
- package/dist/cli/src/commands/library-index.d.ts +3 -3
- package/dist/cli/src/commands/library-index.d.ts.map +1 -1
- package/dist/cli/src/commands/migrate-files.d.ts +8 -0
- package/dist/cli/src/commands/migrate-files.d.ts.map +1 -1
- package/dist/cli/src/commands/migrate-harness.d.ts.map +1 -1
- package/dist/cli/src/commands/migrate-providers.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/project.d.ts.map +1 -1
- package/dist/cli/src/commands/run.d.ts.map +1 -1
- package/dist/cli/src/commands/serve-preflight.d.ts +7 -5
- package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
- package/dist/cli/src/commands/serve.d.ts.map +1 -1
- package/dist/cli/src/commands/source.d.ts.map +1 -1
- package/dist/cli/src/commands/validate.d.ts.map +1 -1
- package/dist/cli/src/config-checks.d.ts +50 -12
- package/dist/cli/src/config-checks.d.ts.map +1 -1
- package/dist/cli/src/ensure-sources.d.ts.map +1 -1
- package/dist/cli/src/harness-error.d.ts +7 -0
- package/dist/cli/src/harness-error.d.ts.map +1 -1
- package/dist/cli/src/helpers.d.ts.map +1 -1
- package/dist/connectors/config.js +5 -5
- package/dist/connectors/index.js +20 -19
- package/dist/connectors/src/index.d.ts +1 -1
- package/dist/connectors/src/index.d.ts.map +1 -1
- package/dist/connectors/src/managed-gitconfig.d.ts +12 -0
- package/dist/connectors/src/managed-gitconfig.d.ts.map +1 -1
- package/dist/{connectors-KTRUUKWG.js → connectors-P5M2D4MH.js} +23 -22
- package/dist/{connectors-KTRUUKWG.js.map → connectors-P5M2D4MH.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 +3 -3
- package/dist/core/ref.js +1 -1
- package/dist/core/runtime-assets.js +5 -5
- package/dist/core/src/index.d.ts +2 -2
- package/dist/core/src/index.d.ts.map +1 -1
- package/dist/core/src/lock.d.ts +7 -1
- package/dist/core/src/lock.d.ts.map +1 -1
- package/dist/core/src/models.d.ts.map +1 -1
- package/dist/core/src/repo-manager.d.ts +28 -0
- package/dist/core/src/repo-manager.d.ts.map +1 -1
- package/dist/core/src/run-state-ignore.d.ts +5 -3
- package/dist/core/src/run-state-ignore.d.ts.map +1 -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 +4 -4
- package/dist/{ensure-sources-5QWKUIUD.js → ensure-sources-MOGLBEUF.js} +31 -29
- package/dist/ensure-sources-MOGLBEUF.js.map +1 -0
- package/dist/factory-assets/connectors/box.js +20 -19
- package/dist/factory-assets/connectors/deploy.js +20 -19
- package/dist/factory-assets/connectors/devserver.js +20 -19
- package/dist/factory-assets/connectors/flow/adapter.js +20 -19
- package/dist/factory-assets/connectors/flow/engine.js +8 -8
- package/dist/factory-assets/connectors/flow/run-flow.js +22 -21
- package/dist/factory-assets/connectors/flow.js +20 -19
- package/dist/factory-assets/connectors/git/exec.d.ts +7 -0
- package/dist/factory-assets/connectors/git/exec.d.ts.map +1 -1
- package/dist/factory-assets/connectors/git/repo.d.ts.map +1 -1
- package/dist/factory-assets/connectors/git.js +20 -19
- package/dist/factory-assets/connectors/gmail/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/gmail.js +20 -19
- package/dist/factory-assets/connectors/googledrive.js +20 -19
- package/dist/factory-assets/connectors/local.js +20 -19
- package/dist/factory-assets/connectors/mattermost.js +20 -19
- package/dist/factory-assets/connectors/memory.js +20 -19
- package/dist/factory-assets/connectors/minio/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/minio.js +20 -19
- package/dist/factory-assets/connectors/postgres/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/postgres.js +20 -19
- package/dist/factory-assets/connectors/s3/driver.d.ts.map +1 -1
- package/dist/factory-assets/connectors/s3.js +20 -19
- package/dist/factory-assets/connectors/sharepoint.js +20 -19
- package/dist/factory-assets/connectors/sqlite/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/sqlite.js +20 -19
- package/dist/factory-assets/connectors/static-server.js +20 -19
- package/dist/factory-assets/connectors/tunnel.js +20 -19
- package/dist/factory-assets/connectors/webdav.js +20 -19
- package/dist/factory-assets/connectors/xstate-store.js +20 -19
- package/dist/factory-assets/connectors/xstate.js +20 -19
- package/dist/{flows-UCP6ZUYS.js → flows-J64L5MGJ.js} +12 -12
- package/dist/{flows-UCP6ZUYS.js.map → flows-J64L5MGJ.js.map} +1 -1
- package/dist/{helpers-INS4B7OQ.js → helpers-JL5AEGDT.js} +28 -26
- package/dist/{helpers-INS4B7OQ.js.map → helpers-JL5AEGDT.js.map} +1 -1
- package/dist/library/index.js +10 -10
- package/dist/library/install.js +4 -4
- package/dist/library/src/index.d.ts +2 -2
- package/dist/library/src/index.d.ts.map +1 -1
- package/dist/library/src/library.d.ts +6 -2
- package/dist/library/src/library.d.ts.map +1 -1
- package/dist/library/src/local/db.d.ts.map +1 -1
- package/dist/library/src/local/library.d.ts +10 -3
- package/dist/library/src/local/library.d.ts.map +1 -1
- package/dist/library/src/local/local-catalog-source.d.ts +0 -9
- package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
- package/dist/library/src/local/schema.d.ts +27 -20
- package/dist/library/src/local/schema.d.ts.map +1 -1
- package/dist/library/src/manifest-writer.d.ts +13 -0
- 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 +6 -0
- package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
- package/dist/library/src/sync/git-driver.d.ts.map +1 -1
- package/dist/{library-publish-AZTYRASL.js → library-publish-DZNNZNMB.js} +49 -50
- package/dist/library-publish-DZNNZNMB.js.map +1 -0
- package/dist/model-endpoint/index.js +10 -10
- package/dist/open-library-OJREQ22B.js +61 -0
- package/dist/{open-library-3HMXYGUF.js.map → open-library-OJREQ22B.js.map} +1 -1
- package/dist/{open-registry-BHBHQMBA.js → open-registry-OEU6QUK2.js} +14 -14
- package/dist/{open-registry-BHBHQMBA.js.map → open-registry-OEU6QUK2.js.map} +1 -1
- package/dist/paths-PXBWY532.js +22 -0
- package/dist/{paths-77PXOXZY.js.map → paths-PXBWY532.js.map} +1 -1
- package/dist/{plugin-store-XQP2CRYH.js → plugin-store-ZC3EGZ3D.js} +10 -10
- package/dist/{plugin-store-XQP2CRYH.js.map → plugin-store-ZC3EGZ3D.js.map} +1 -1
- package/dist/{project-HVNPK2ZF.js → project-52UABBD5.js} +45 -46
- package/dist/{project-HVNPK2ZF.js.map → project-52UABBD5.js.map} +1 -1
- package/dist/resolver/index.js +8 -8
- package/dist/runner/index.js +35 -35
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +14 -14
- package/dist/sdk/bridge.js +17 -16
- package/dist/sdk/core.js +7 -7
- package/dist/sdk/flow.js +8 -8
- package/dist/sdk/index.js +35 -35
- package/dist/sdk/resolver.js +8 -8
- package/dist/sdk/runner.js +35 -35
- package/dist/sdk/transport/ws/server.js +8 -8
- package/dist/sdk/transport/ws.js +8 -8
- package/dist/sdk/transport.js +8 -8
- package/dist/{serve-preflight-NHZOKHIC.js → serve-preflight-HOQ7CGYR.js} +30 -30
- package/dist/{serve-preflight-NHZOKHIC.js.map → serve-preflight-HOQ7CGYR.js.map} +1 -1
- package/dist/{setup-EX7Z7XRN.js → setup-JIDZ372C.js} +29 -27
- package/dist/setup-JIDZ372C.js.map +1 -0
- package/dist/{skills-DE2BDQ6G.js → skills-5D4KDVPJ.js} +13 -13
- package/dist/{skills-DE2BDQ6G.js.map → skills-5D4KDVPJ.js.map} +1 -1
- package/dist/{source-URRPRGMZ.js → source-P6ZFSSZZ.js} +47 -46
- package/dist/{source-URRPRGMZ.js.map → source-P6ZFSSZZ.js.map} +1 -1
- package/dist/{source-manifest-publish-ZWRYRJ2U.js → source-manifest-publish-Y36FHVDS.js} +49 -48
- package/dist/source-manifest-publish-Y36FHVDS.js.map +1 -0
- package/dist/transport/index.js +8 -8
- package/dist/transport/src/ws/server.d.ts.map +1 -1
- package/dist/transport/ws/server.js +8 -8
- package/dist/transport/ws.js +8 -8
- package/dist/tui/index.js +35 -35
- package/dist/workspace-plugin/adapters/mcp.js +27 -26
- package/dist/workspace-plugin/adapters/omp.js +14 -14
- package/dist/workspace-plugin/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-4KPQ6ILH.js.map +0 -1
- package/dist/chunk-7UCPGQCW.js.map +0 -1
- package/dist/chunk-AQTAULXT.js.map +0 -1
- package/dist/chunk-BLBXOG5Q.js +0 -299
- package/dist/chunk-BLBXOG5Q.js.map +0 -1
- package/dist/chunk-C324IAXI.js +0 -160
- package/dist/chunk-C324IAXI.js.map +0 -1
- package/dist/chunk-DJSGQW2Q.js +0 -334
- package/dist/chunk-DJSGQW2Q.js.map +0 -1
- package/dist/chunk-FZO64PLQ.js.map +0 -1
- package/dist/chunk-FZTHL6SK.js.map +0 -1
- package/dist/chunk-GYPPVANR.js +0 -357
- package/dist/chunk-GYPPVANR.js.map +0 -1
- package/dist/chunk-GZL6RN4Z.js.map +0 -1
- package/dist/chunk-KNY356I3.js.map +0 -1
- package/dist/chunk-LOO5CB5M.js +0 -12
- package/dist/chunk-LOO5CB5M.js.map +0 -1
- package/dist/chunk-MDCI4RSG.js.map +0 -1
- package/dist/chunk-PLVM6OIV.js.map +0 -1
- package/dist/chunk-Q5SSRVD5.js.map +0 -1
- package/dist/chunk-U3FI4DVT.js.map +0 -1
- package/dist/chunk-V5KG6CCV.js.map +0 -1
- package/dist/chunk-VEIWFS7Z.js.map +0 -1
- package/dist/chunk-WEPTGUR4.js.map +0 -1
- package/dist/chunk-ZUROGXJM.js.map +0 -1
- package/dist/ensure-sources-5QWKUIUD.js.map +0 -1
- package/dist/library-publish-AZTYRASL.js.map +0 -1
- package/dist/open-library-3HMXYGUF.js +0 -59
- package/dist/paths-77PXOXZY.js +0 -22
- package/dist/setup-EX7Z7XRN.js.map +0 -1
- package/dist/source-manifest-publish-ZWRYRJ2U.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../core/src/runtime-assets.ts"],"names":["resolvePath","require"],"mappings":";;;;;;;;AAsDA,SAAS,sBACP,OAAA,EACmC;AACnC,EAAA,MAAM,aAAa,iBAAA,EAAkB;AACrC,EAAA,MAAM,MAAyC,EAAC;AAChD,EAAA,KAAA,MAAW,CAAA,IAAK,OAAA,IAAW,EAAC,EAAG;AAC7B,IAAA,MAAM,GAAA,GAAM,cAAA,CAAe,CAAA,CAAE,GAAG,CAAA;AAChC,IAAA,IAAI,GAAA,CAAI,GAAG,CAAA,EAAG;AACd,IAAA,GAAA,CAAI,GAAG,CAAA,GAAI;AAAA,MACT,IAAA,EAAM,IAAA,CAAK,UAAA,EAAY,GAAG,CAAA;AAAA,MAC1B,KAAK,CAAA,CAAE,GAAA;AAAA,MACP,QAAQ,CAAA,CAAE,GAAA;AAAA,MACV,GAAI,EAAE,SAAA,GAAY,EAAE,WAAW,CAAA,CAAE,SAAA,KAAc;AAAC,KAClD;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;AAqDO,IAAM,wBAAA,GAA2B;AAMxC,IAAM,iCAAA,GAAoC,yBAAA;AAkD1C,eAAsB,oBAAA,CACpB,UAAA,EACA,OAAA,GAAgC,EAAC,EACH;AAC9B,EAAA,MAAM,MAAA,GAA8B;AAAA,IAClC,gBAAgB,EAAC;AAAA,IACjB,cAAc,EAAC;AAAA,IACf,iBAAiB,EAAE,QAAA,EAAU,EAAC,EAAG,QAAA,EAAU,EAAC,EAAE;AAAA,IAC9C,UAAU,EAAC;AAAA,IACX,SAAS,YAAY;AACnB,MAAA,MAAM,QAAA,CAAS,UAAA,EAAY,MAAA,EAAQ,OAAO,CAAA;AAAA,IAC5C,CAAA;AAAA,IACA,WAAW,CAAC,KAAA,KAAU,gBAAA,CAAiB,MAAA,CAAO,gBAAgB,KAAK;AAAA,GACrE;AAEA,EAAA,MAAM,QAAA,CAAS,UAAA,EAAY,MAAA,EAAQ,OAAO,CAAA;AAC1C,EAAA,OAAO,MAAA;AACT;AAmBO,SAAS,iBAAA,GAA8B;AAC5C,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,yBAAA,IAA6B,QAAQ,GAAA,CAAI,sBAAA;AAOpE,EAAA,IAAI,MAAA,IAAU,WAAW,MAAM,CAAA,QAAS,IAAA,CAAKA,OAAA,CAAY,MAAM,CAAC,CAAA;AAChE,EAAA,MAAM,OAAA,GAAU,yBAAyB,gBAAgB,CAAA;AACzD,EAAA,IAAI,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA;AAC/B,EAAA,OAAO,CAAC,GAAG,IAAI,GAAA,CAAI,KAAK,CAAC,CAAA;AAC3B;AAYO,SAAS,wBAAA,GAAmC;AACjD,EAAA,MAAM,MAAM,8BAAA,EAA+B;AAC3C,EAAA,IAAI,KAAK,OAAO,GAAA;AAEhB,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,+LAAA;AAAA,GAIF;AACF;AAUO,SAAS,8BAAA,GAAgD;AAC9D,EAAA,OAAO,iBAAA,EAAkB,CAAE,CAAC,CAAA,IAAK,IAAA;AACnC;AAoBA,IAAI,0BAAA;AAEG,SAAS,4BAAA,GAA8C;AAC5D,EAAA,IAAI,0BAAA,KAA+B,QAAW,OAAO,0BAAA;AACrD,EAAA,0BAAA,GAA6B,4BAAA,EAA6B;AAC1D,EAAA,OAAO,0BAAA;AACT;AAEA,SAAS,4BAAA,GAA8C;AACrD,EAAA,IAAI;AACF,IAAA,MAAMC,QAAAA,GAAU,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA;AAC7C,IAAA,OAAO,OAAA,CAAQA,QAAAA,CAAQ,OAAA,CAAQ,iCAAiC,CAAC,CAAA;AAAA,EACnE,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,OAAA,CAAQ,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,CAAA;AAAA,EAC9C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC1B,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAK,cAAc,CAAA;AACxC,IAAA,IAAI,UAAA,CAAW,OAAO,CAAA,EAAG;AACvB,MAAA,IAAI;AACF,QAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,OAAA,EAAS,OAAO,CAAC,CAAA;AACrD,QAAA,IAAI,GAAA,CAAI,IAAA,KAAS,oBAAA,EAAsB,OAAO,GAAA;AAAA,MAChD,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,QAAQ,GAAG,CAAA;AAC1B,IAAA,IAAI,WAAW,GAAA,EAAK;AACpB,IAAA,GAAA,GAAM,MAAA;AAAA,EACR;AACA,EAAA,OAAO,IAAA;AACT;AAiBO,SAAS,yBAAyB,MAAA,EAA+B;AACtE,EAAA,MAAM,OAAO,4BAAA,EAA6B;AAC1C,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,IAAA,CAAK,IAAA,EAAM,MAAM,CAAA,EAAG,IAAA,CAAK,IAAA,EAAM,MAAA,EAAQ,MAAM,CAAC,CAAA,EAAG;AACnE,IAAA,IAAI,UAAA,CAAW,IAAI,CAAA,EAAG,OAAO,IAAA;AAAA,EAC/B;AACA,EAAA,OAAO,IAAA;AACT;AAIA,IAAM,oBAAA,mBAA4C,IAAI,GAAA,CAAI,CAAC,WAAW,CAAC,CAAA;AAEvE,eAAe,QAAA,CACb,UAAA,EACA,MAAA,EACA,OAAA,EACe;AACf,EAAA,MAAA,CAAO,iBAAiB,EAAC;AACzB,EAAA,MAAA,CAAO,eAAe,EAAC;AACvB,EAAA,MAAA,CAAO,kBAAkB,EAAE,QAAA,EAAU,EAAC,EAAG,QAAA,EAAU,EAAC,EAAE;AACtD,EAAA,MAAA,CAAO,WAAW,EAAC;AAEnB,EAAA,MAAM,MAAA,GAAS,yBAAyB,UAAU,CAAA;AAGlD,EAAA,MAAM,YAAA,GAAe,0BAAA,CAA2B,qBAAA,CAAsB,MAAA,CAAO,OAAO,CAAC,CAAA;AACrF,EAAA,MAAM,KAAA,GAAQ,UAAU,UAAU,CAAA;AAGlC,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,IAAI,KAAK,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,EAAG;AACvD,IAAA,MAAM,UAAU,MAAM,cAAA,CAAe,IAAA,EAAM,IAAA,EAAM,YAAY,KAAK,CAAA;AAClE,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAA,CAAO,SAAS,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,kBAAA;AAAA,QACN,IAAA;AAAA,QACA,OAAA,EAAS,sBAAA,CAAuB,IAAA,EAAM,IAAI;AAAA,OAC3C,CAAA;AACD,MAAA;AAAA,IACF;AACA,IAAA,IAAI;AAGF,MAAA,MAAM,QAAA,GAAW,IAAA,KAAS,iCAAA,GAAoC,wBAAA,GAA2B,IAAA;AAGzF,MAAA,MAAM,OAAA,GAAU,MAAM,aAAA,CAAc,OAAA,EAAS,QAAA,EAAU;AAAA,QACrD,UAAA,EAAY,oBAAA;AAAA,QACZ,cAAc,MAAM;AAAA,QAAC;AAAA,OACtB,CAAA;AACD,MAAA,MAAM,UAAU,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,WAAW,CAAA;AAC5D,MAAA,MAAA,CAAO,cAAA,CAAe,IAAA,CAAK,GAAG,OAAO,CAAA;AAAA,IACvC,SAAS,GAAA,EAAK;AACZ,MAAA,MAAA,CAAO,SAAS,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,kBAAA;AAAA,QACN,IAAA;AAAA,QACA,OAAA,EAAS,CAAA,2BAAA,EAA8B,IAAI,CAAA,KAAA,EAAQ,OAAO,CAAA,EAAA,EACxD,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CACjD,CAAA;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAMA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAA,CAAO,cAAA,GAAiB,MAAA,CAAO,cAAA,CAAe,MAAA,CAAO,CAAC,CAAA,KAAM;AAC1D,IAAA,MAAM,MAAM,CAAA,EAAG,CAAA,CAAE,IAAI,CAAA,CAAA,EAAI,EAAE,IAAI,CAAA,CAAA;AAC/B,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,KAAA;AAC1B,IAAA,IAAA,CAAK,IAAI,GAAG,CAAA;AACZ,IAAA,OAAO,IAAA;AAAA,EACT,CAAC,CAAA;AAGD,EAAA,KAAA,MAAW,CAAC,OAAO,CAAC,CAAA,IAAA,CAAM,OAAO,UAAA,IAAc,EAAC,EAAG,OAAA,EAAQ,EAAG;AAG5D,IAAA,IAAI,OAAO,CAAA,CAAE,MAAA,KAAW,QAAA,IAAY,CAAA,CAAE,WAAW,EAAA,EAAI;AACnD,MAAA,MAAM,SAAU,CAAA,CAAyC,OAAA;AACzD,MAAA,MAAM,KAAA,GAAQ,OAAO,CAAA,CAAE,EAAA,KAAO,YAAY,CAAA,CAAE,EAAA,KAAO,EAAA,GAAK,CAAA,CAAA,EAAI,CAAA,CAAE,EAAE,CAAA,CAAA,CAAA,GAAM,CAAA,CAAA,EAAI,QAAQ,CAAC,CAAA,CAAA;AACnF,MAAA,MAAA,CAAO,SAAS,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,gBAAA;AAAA,QACN,GAAI,OAAO,CAAA,CAAE,EAAA,KAAO,QAAA,IAAY,CAAA,CAAE,EAAA,KAAO,EAAA,GAAK,EAAE,aAAA,EAAe,CAAA,CAAE,EAAA,KAAO,EAAC;AAAA,QACzE,OAAA,EACE,MAAA,KAAW,MAAA,GACP,CAAA,UAAA,EAAa,KAAK,CAAA,iBAAA,EAAoB,MAAA,CAAO,MAAM,CAAC,CAAA,4DAAA,CAAA,GACpD,CAAA,UAAA,EAAa,KAAK,CAAA,uEAAA;AAAA,OACzB,CAAA;AACD,MAAA;AAAA,IACF;AACA,IAAA,MAAA,CAAO,YAAA,CAAa,IAAA,CAAK,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,CAAA,CAAE,MAAA,EAAQ,aAAA,EAAe,CAAA,CAAE,EAAA,EAAI,CAAA;AAAA,EACrF;AAGA,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AACpC,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AACpC,EAAA,KAAA,MAAW,GAAA,IAAO,OAAO,YAAA,EAAc;AACrC,IAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,MAAA,CAAO,cAAA,EAAgB,GAAG,CAAA;AAEzD,IAAA,IAAI,CAAC,KAAA,IAAS,OAAA,CAAQ,kBAAA,GAAqB,GAAA,CAAI,IAAI,CAAA,EAAG;AACtD,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAA,CAAO,SAAS,IAAA,CAAK;AAAA,QACnB,IAAA,EAAM,gBAAA;AAAA,QACN,eAAe,GAAA,CAAI,aAAA;AAAA,QACnB,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,OAAA,EACE,CAAA,QAAA,EAAW,GAAA,CAAI,IAAI,YAAY,GAAA,CAAI,IAAI,CAAA,gBAAA,EAAmB,GAAA,CAAI,IAAI,CAAA,EAAA,EAAK,GAAA,CAAI,aAAa,CAAA,gBAAA,EACxE,IAAI,IAAI,CAAA,sGAAA;AAAA,OAE3B,CAAA;AACD,MAAA;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAO,KAAA,CAAM,QAAA,EAAU,QAAA,IAAY,EAAC;AAC1C,IAAA,KAAA,MAAW,KAAK,GAAA,CAAI,QAAA,IAAY,EAAC,EAAG,WAAA,CAAY,IAAI,CAAC,CAAA;AACrD,IAAA,KAAA,MAAW,KAAK,GAAA,CAAI,QAAA,IAAY,EAAC,EAAG,WAAA,CAAY,IAAI,CAAC,CAAA;AAAA,EACvD;AACA,EAAA,MAAA,CAAO,eAAA,CAAgB,QAAA,GAAW,CAAC,GAAG,WAAW,CAAA;AACjD,EAAA,MAAA,CAAO,eAAA,CAAgB,QAAA,GAAW,CAAC,GAAG,WAAW,CAAA;AACnD;AAUA,SAAS,2BACP,QAAA,EACmC;AACnC,EAAA,MAAM,MAAA,GAA4C,EAAE,GAAI,QAAA,IAAY,EAAC,EAAG;AACxE,EAAA,MAAM,QAAQ,iBAAA,EAAkB;AAChC,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAItB,IAAA,IAAI,CAAC,OAAO,wBAAwB,CAAA,SAAU,wBAAwB,CAAA,GAAI,EAAE,IAAA,EAAM,EAAA,EAAG;AACrF,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,MAAM,IAAA,GACJ,MAAM,MAAA,GAAS,CAAA,GACX,CAAC,iCAAA,EAAmC,wBAAwB,CAAA,GAC5D,CAAC,wBAAwB,CAAA;AAC/B,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM;AACxB,IAAA,MAAM,MAAM,IAAA,CAAK,CAAC,KAAK,CAAA,EAAG,wBAAwB,IAAI,CAAC,CAAA,CAAA;AACvD,IAAA,IAAI,CAAC,OAAO,GAAG,CAAA,SAAU,GAAG,CAAA,GAAI,EAAE,IAAA,EAAM,GAAA,EAAI;AAAA,EAC9C,CAAC,CAAA;AACD,EAAA,OAAO,MAAA;AACT;AAoBA,eAAe,cAAA,CACb,IAAA,EACA,IAAA,EACA,UAAA,EACA,KAAA,EACwB;AAExB,EAAA,MAAM,MAAA,GAAS,MAAM,IAAI,CAAA;AACzB,EAAA,IAAI,MAAA,IAAW,MAAM,UAAA,CAAW,MAAM,GAAI,OAAO,MAAA;AAGjD,EAAA,IAAI,KAAK,IAAA,EAAM;AACb,IAAA,MAAM,QAAA,GAAWD,OAAA,CAAY,UAAA,EAAY,IAAA,CAAK,IAAI,CAAA;AAClD,IAAA,OAAQ,MAAM,UAAA,CAAW,QAAQ,CAAA,GAAK,QAAA,GAAW,IAAA;AAAA,EACnD;AAKA,EAAA,IAAI,KAAK,GAAA,EAAK;AACZ,IAAA,MAAM,cAAc,IAAA,CAAK,UAAA,EAAY,SAAA,EAAW,OAAA,EAAS,WAAW,IAAI,CAAA;AAIxE,IAAA,MAAM,QAAQ,MAAM,iBAAA;AAAA,MAClB,SAAS,WAAW,CAAA,CAAA;AAAA,MACpB,YAAY;AACV,QAAA,MAAM,MAAM,WAAW,CAAA;AACvB,QAAA,OAAO,IAAA;AAAA,MACT,CAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAO,QAAQ,WAAA,GAAc,IAAA;AAAA,EAC/B;AAEA,EAAA,OAAO,IAAA;AACT;AAGA,SAAS,WAAW,IAAA,EAAgC;AAClD,EAAA,OAAO,iBAAA;AAAA,IACL,QAAQ,IAAI,CAAA,CAAA;AAAA,IACZ,YAAY;AACV,MAAA,MAAM,KAAK,IAAI,CAAA;AACf,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,SAAS,sBAAA,CAAuB,MAAc,IAAA,EAAiC;AAC7E,EAAA,IAAI,SAAS,wBAAA,IAA4B,CAAC,KAAK,IAAA,IAAQ,CAAC,KAAK,GAAA,EAAK;AAChE,IAAA,OACE,CAAA,oHAAA,CAAA;AAAA,EAGJ;AACA,EAAA,IAAI,KAAK,GAAA,EAAK;AACZ,IAAA,OAAO,CAAA,YAAA,EAAe,IAAI,CAAA,GAAA,EAAM,IAAA,CAAK,GAAG,CAAA,8EAAA,CAAA;AAAA,EAC1C;AACA,EAAA,IAAI,KAAK,IAAA,EAAM;AACb,IAAA,OAAO,CAAA,YAAA,EAAe,IAAI,CAAA,kBAAA,EAAqB,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,EAC1D;AACA,EAAA,OAAO,eAAe,IAAI,CAAA,2BAAA,CAAA;AAC5B;AAEA,SAAS,gBAAA,CACP,SACA,KAAA,EACiC;AACjC,EAAA,IAAI,MAAM,IAAA,EAAM;AACd,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,KAAA,CAAM,IAAA,IAAQ,CAAA,CAAE,IAAA,KAAS,KAAA,CAAM,IAAI,CAAA;AAAA,EAC3E;AACA,EAAA,MAAM,OAAA,GAAU,QAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,MAAM,IAAI,CAAA;AAC3D,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,QAAQ,CAAC,CAAA;AAE1C,EAAA,OAAO,MAAA;AACT","file":"chunk-4ROXSQEG.js","sourcesContent":["/**\n * Runtime asset resolution — read `skaile.yaml`, scan all declared repositories\n * (including the built-in `factory-assets/` directory as an implicit default),\n * and produce a unified view of connector catalog entries plus the implicit refs\n * that the `skaile.yaml` `connectors:` section adds to the dependency graph.\n *\n * This module is the single source of truth for \"which connectors does this\n * project see at runtime, and where do their implementations live on disk\".\n * Both the runner (serve, REPL, flow) and the platform's mid-session\n * `add_resource` flow consume `RuntimeAssetsResult.catalogEntries` and pass\n * it into `ConnectorManager` for catalog-based resolution.\n *\n * `factory-assets/` is the single first-party content tree (built-in connectors\n * + first-party skills + bundles) shipped inside the `@skaile/workspaces`\n * package — not a standalone package.\n *\n * It resolves to an **ordered list of roots** ({@link factoryAssetRoots}), not a\n * single dir. The bundled tree is always the baseline; an optional\n * `SKAILE_FACTORY_ASSETS_DIR` (legacy: `SKAILE_BASE_ASSETS_DIR`) is layered\n * **in front** as an additive override source — the agent container points it at\n * `/app/factory-assets/` (or a bind-mounted host dir) to ship updated skills /\n * flows / bundles / connector manifests without rebuilding the image. The two\n * roots resolve uniformly across every consumer (connector catalog scan, skill /\n * flow / completion discovery, the asset-manager factory source):\n * 1. `SKAILE_FACTORY_ASSETS_DIR` env dir, when set and existing (override layer).\n * 2. the bundled tree via {@link resolvePackagedAssetsDir} — the in-repo source\n * `packages/workspaces/factory-assets/` during dev, else the published\n * `dist/factory-assets/` after install (always-present baseline).\n *\n * Override semantics are **env-first**: on a name conflict the env root wins and\n * the bundled root fills the rest. Connector *code* still loads via the package's\n * static `exports` map, so the env root can override/add skills, flows, bundles,\n * and connector **manifests/metadata**, but cannot ship a new executable\n * connector — its `.js` is not on the package's import graph.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { lstat, stat } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, resolve as resolvePath } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { tryWithFsDeadline } from \"./fs-deadline.js\";\nimport { scanDirectory } from \"./manifest.js\";\nimport type { CatalogEntry } from \"./models.js\";\nimport { getGlobalCacheDir, readLinks, sourceCacheKey } from \"./repo-manager.js\";\nimport type { SourceDeclaration, SourceEntry } from \"./workspace-config.js\";\nimport { resolveSkWorkspaceConfig } from \"./workspace-config.js\";\n\n/**\n * Map declared `sources[]` to internal `SourceDeclaration`s keyed by the\n * collision-free {@link sourceCacheKey} (`<host>/<owner>/<repo>`), pointing at\n * the unified machine-cache clone path (`getGlobalCacheDir()/<key>/`). Keyed by\n * the same function every other cache writer/reader uses so the path resolves.\n */\nfunction sourcesToDeclarations(\n sources: SourceEntry[] | undefined,\n): Record<string, SourceDeclaration> {\n const sourcesDir = getGlobalCacheDir();\n const out: Record<string, SourceDeclaration> = {};\n for (const s of sources ?? []) {\n const key = sourceCacheKey(s.url);\n if (out[key]) continue;\n out[key] = {\n path: join(sourcesDir, key),\n url: s.url,\n branch: s.pin,\n ...(s.publisher ? { publisher: s.publisher } : {}),\n };\n }\n return out;\n}\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/**\n * Catalog entry filtered to mount/connector kinds. Same shape as `CatalogEntry`.\n * @docLink packages/core/concepts#runtime-catalog-entry\n */\nexport type RuntimeCatalogEntry = CatalogEntry;\n\n/**\n * Implicit catalog reference derived from a `connectors:` declaration in `skaile.yaml`.\n * Each connector driver becomes an implicit ref that must be resolved in the catalog.\n * @docLink packages/core/concepts#runtime-asset-ref\n */\nexport interface RuntimeAssetRef {\n kind: \"connector\";\n /** Driver name — matches `RuntimeCatalogEntry.name`. */\n name: string;\n /** Source declaration id from `skaile.yaml`. */\n declarationId: string;\n}\n\n/**\n * Aggregated npm packages required by all resolved mount/connector adapters.\n * Populated from `metadata.npm_deps` in each matched catalog entry.\n * @docLink packages/core/concepts#runtime-npm-deps\n */\nexport interface RuntimeNpmDeps {\n required: string[];\n optional: string[];\n}\n\n/**\n * Non-fatal warning emitted during `resolveRuntimeAssets` when a repo is unavailable\n * or a driver is not found in any catalog.\n * @docLink packages/core/concepts#runtime-asset-warning\n */\nexport interface RuntimeAssetWarning {\n /** Stable code for filtering / structured logging. */\n code: \"missing_driver\" | \"repo_unavailable\" | \"invalid_repo_decl\";\n message: string;\n /** Declaration id when applicable. */\n declarationId?: string;\n /** Driver / repository name when applicable. */\n name?: string;\n}\n\n/**\n * Repository name used for the implicit built-in `factory-assets` catalog entry\n * (the in-package connector tree).\n * @docLink packages/core/concepts#factory-assets-repo-name\n */\nexport const FACTORY_ASSETS_REPO_NAME = \"factory-assets\";\n\n/**\n * Repository name for the optional `SKAILE_FACTORY_ASSETS_DIR` override layer,\n * scanned ahead of (and overriding) the bundled {@link FACTORY_ASSETS_REPO_NAME}.\n */\nconst FACTORY_ASSETS_OVERRIDE_REPO_NAME = \"factory-assets:override\";\n\n/**\n * Result of `resolveRuntimeAssets`.\n * The same object is mutated in place by `refresh()`, allowing callers to hold\n * a stable reference and observe updates after a new repository is cloned or\n * a driver is installed mid-session.\n * @docLink packages/core/concepts#runtime-assets-result\n */\nexport interface RuntimeAssetsResult {\n catalogEntries: RuntimeCatalogEntry[];\n implicitRefs: RuntimeAssetRef[];\n requiredNpmDeps: RuntimeNpmDeps;\n warnings: RuntimeAssetWarning[];\n /** Re-scan repositories and re-derive implicit refs. Mutates in place. */\n refresh(): Promise<void>;\n /**\n * Catalog lookup. When `kind` is omitted and multiple entries share the\n * `name`, returns `undefined` (caller must disambiguate).\n */\n findEntry(query: { kind?: \"connector\"; name: string }): RuntimeCatalogEntry | undefined;\n}\n\n/** Options of {@link resolveRuntimeAssets}. */\nexport interface RuntimeAssetsOptions {\n /**\n * True when a connector driver is registered in the process (built-in or loaded plugin).\n * Core does not know the registry; the caller passes its lookup. Without it only the catalog\n * counts, so a driver a plugin registers is reported as `missing_driver`.\n */\n isDriverRegistered?: (driver: string) => boolean;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Resolve all runtime assets visible to a project by scanning declared repositories.\n *\n * Reads `skaile.yaml`, scans every declared repository (plus the implicit\n * built-in `factory-assets` repo), and derives implicit refs from `mounts:` /\n * `connectors:` declarations. Does not clone or install anything — purely a\n * read-only scan of what is already on disk. URL-only repositories that have\n * not been cloned yet are reported as `repo_unavailable` warnings.\n *\n * @param projectDir - Absolute path to the project workspace root\n * @param options - `isDriverRegistered`: a driver that no catalog entry lists but a plugin\n * registered is not reported as `missing_driver`\n * @returns `RuntimeAssetsResult` with catalog entries, implicit refs, npm deps, and warnings\n * @docLink packages/core/concepts#resolve-runtime-assets\n */\nexport async function resolveRuntimeAssets(\n projectDir: string,\n options: RuntimeAssetsOptions = {},\n): Promise<RuntimeAssetsResult> {\n const result: RuntimeAssetsResult = {\n catalogEntries: [],\n implicitRefs: [],\n requiredNpmDeps: { required: [], optional: [] },\n warnings: [],\n refresh: async () => {\n await populate(projectDir, result, options);\n },\n findEntry: (query) => findCatalogEntry(result.catalogEntries, query),\n };\n\n await populate(projectDir, result, options);\n return result;\n}\n\n/**\n * Resolve the ordered list of on-disk roots for the built-in `factory-assets`\n * tree (built-in connectors + first-party skills + bundles). This is the single\n * shared resolver every consumer goes through, so the env override and the\n * bundled baseline are honoured uniformly.\n *\n * Order (env-first = override-wins):\n * 1. `SKAILE_FACTORY_ASSETS_DIR` env dir (legacy: `SKAILE_BASE_ASSETS_DIR`),\n * when set and existing — an additive override layer.\n * 2. {@link resolvePackagedAssetsDir} — the bundled tree (in-repo source in dev,\n * `dist/factory-assets/` after install). Always-present baseline.\n *\n * Returns `[]` only when the package cannot be located at all. De-duplicated, so\n * pointing the env var at the bundled dir collapses to one root.\n *\n * @docLink packages/core/concepts#resolve-factory-assets-root\n */\nexport function factoryAssetRoots(): string[] {\n const roots: string[] = [];\n const envDir = process.env.SKAILE_FACTORY_ASSETS_DIR ?? process.env.SKAILE_BASE_ASSETS_DIR;\n // Deliberately still synchronous after #454: both candidates are\n // container-local (the image's `/app/factory-assets/`, or the installed\n // package tree resolved by `resolvePackagedAssetsDir`), never the FUSE\n // workspace mount. The mount-reachable probes on this module's scan path —\n // the project-relative `sources[].path` candidates in `resolveRepoDir` — are\n // async and deadline-bounded.\n if (envDir && existsSync(envDir)) roots.push(resolvePath(envDir));\n const bundled = resolvePackagedAssetsDir(\"factory-assets\");\n if (bundled) roots.push(bundled);\n return [...new Set(roots)];\n}\n\n/**\n * Resolve the primary on-disk root of the `factory-assets` tree — the first of\n * {@link factoryAssetRoots} (the env override when set, else the bundled tree).\n * Prefer {@link factoryAssetRoots} when you need to scan every layer; this\n * single-dir form is for callers that want one canonical path.\n *\n * @returns Absolute path to the highest-precedence `factory-assets` directory\n * @throws When no root can be located\n * @docLink packages/core/concepts#resolve-factory-assets-root\n */\nexport function resolveFactoryAssetsRoot(): string {\n const hit = resolveFactoryAssetsRootOrNull();\n if (hit) return hit;\n\n throw new Error(\n `Cannot resolve the factory-assets directory. ` +\n `Set SKAILE_FACTORY_ASSETS_DIR to the on-disk path, ` +\n `ensure @skaile/workspaces is installed, ` +\n `or run from within the @skaile/workspaces package tree.`,\n );\n}\n\n/**\n * Non-throwing variant of {@link resolveFactoryAssetsRoot}: the same\n * env-then-packaged resolution tiers, returning `null` instead of throwing when\n * none locate the directory. Callers that treat a missing factory tree as a\n * soft \"not present\" (e.g. the asset-manager's implicit-source injection) MUST\n * use this so they honour the `SKAILE_FACTORY_ASSETS_DIR` container override\n * identically to the runtime path.\n */\nexport function resolveFactoryAssetsRootOrNull(): string | null {\n return factoryAssetRoots()[0] ?? null;\n}\n\n/**\n * Resolve the `@skaile/workspaces` package root — the directory containing its\n * `package.json`. Tries `require.resolve` first (works when installed as a\n * dependency *and* in-repo via the self-reference), then walks upward from this\n * module looking for a `package.json` whose `name` is `@skaile/workspaces`\n * (bounded to 8 levels). Returns `null` when neither locates it.\n *\n * The single source of truth for finding content shipped inside the package —\n * the unified `factory-assets/` tree (built-in connectors + first-party skills\n * + bundles) resolves through {@link resolvePackagedAssetsDir} on top of this.\n *\n * Memoized: the package location is immutable for the process lifetime, but\n * this sits on the CLI hot path (every `findSkills` / flow / completion call\n * funnels through here), so the `require.resolve` + upward `package.json` walk\n * runs once. `undefined` = not yet computed.\n *\n * @docLink packages/core/concepts#resolve-factory-assets-root\n */\nlet workspacesPackageRootCache: string | null | undefined;\n\nexport function resolveWorkspacesPackageRoot(): string | null {\n if (workspacesPackageRootCache !== undefined) return workspacesPackageRootCache;\n workspacesPackageRootCache = computeWorkspacesPackageRoot();\n return workspacesPackageRootCache;\n}\n\nfunction computeWorkspacesPackageRoot(): string | null {\n try {\n const require = createRequire(import.meta.url);\n return dirname(require.resolve(\"@skaile/workspaces/package.json\"));\n } catch {\n // Fall through to the workspace walk.\n }\n let dir: string;\n try {\n dir = dirname(fileURLToPath(import.meta.url));\n } catch {\n return null;\n }\n for (let i = 0; i < 8; i++) {\n const pkgPath = join(dir, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as { name?: string };\n if (pkg.name === \"@skaile/workspaces\") return dir;\n } catch {\n // Ignore malformed package.json and keep walking.\n }\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/**\n * Locate a content-asset directory inside the package. Prefers the in-repo\n * **source** dir `<pkgRoot>/<subdir>` when present — in a dev checkout it is the\n * full tree (e.g. `factory-assets/` keeps the connector `.ts` entry files that\n * `dist/` does not) — then the published `dist/<subdir>` copy (what\n * `files: [\"dist\"]` ships, the only one present after `npm i`). Returns `null`\n * when neither exists.\n *\n * `factory-assets/` resolves to the source tree in dev (code + skills + bundles)\n * and to `dist/factory-assets` post-install (compiled connectors + copied\n * manifests/skills/bundles).\n *\n * @param subdir - `\"factory-assets\"` | …\n * @docLink packages/core/concepts#resolve-factory-assets-root\n */\nexport function resolvePackagedAssetsDir(subdir: string): string | null {\n const root = resolveWorkspacesPackageRoot();\n if (!root) return null;\n for (const cand of [join(root, subdir), join(root, \"dist\", subdir)]) {\n if (existsSync(cand)) return cand;\n }\n return null;\n}\n\n// ─── Internals ────────────────────────────────────────────────────────────────\n\nconst CONNECTOR_SCAN_KINDS: ReadonlySet<string> = new Set([\"connector\"]);\n\nasync function populate(\n projectDir: string,\n target: RuntimeAssetsResult,\n options: RuntimeAssetsOptions,\n): Promise<void> {\n target.catalogEntries = [];\n target.implicitRefs = [];\n target.requiredNpmDeps = { required: [], optional: [] };\n target.warnings = [];\n\n const config = resolveSkWorkspaceConfig(projectDir);\n // Connector catalog scan runs over the project's declared sources[] (resolved\n // to their machine-cache clone paths) plus the implicit factory-assets repo.\n const repositories = buildEffectiveRepositories(sourcesToDeclarations(config.sources));\n const links = readLinks(projectDir);\n\n // Scan each repository for connector entries.\n for (const [name, decl] of Object.entries(repositories)) {\n const repoDir = await resolveRepoDir(name, decl, projectDir, links);\n if (!repoDir) {\n target.warnings.push({\n code: \"repo_unavailable\",\n name,\n message: repoUnavailableMessage(name, decl),\n });\n continue;\n }\n try {\n // Both factory layers carry the same `factory-assets` provenance — the\n // override repo is an internal scan-order device, not a distinct source.\n const repoName = name === FACTORY_ASSETS_OVERRIDE_REPO_NAME ? FACTORY_ASSETS_REPO_NAME : name;\n // Only connector descriptors are consumed here, so only that kind is\n // \"known\": typed manifests of any other kind are irrelevant to this scan.\n const scanned = await scanDirectory(repoDir, repoName, {\n knownKinds: CONNECTOR_SCAN_KINDS,\n onDiagnostic: () => {},\n });\n const entries = scanned.filter((e) => e.kind === \"connector\");\n target.catalogEntries.push(...entries);\n } catch (err) {\n target.warnings.push({\n code: \"repo_unavailable\",\n name,\n message: `Failed to scan repository \"${name}\" at ${repoDir}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n });\n }\n }\n\n // De-duplicate by (kind, name), keeping the first occurrence. Scan order is\n // declared sources → env override → bundled baseline, so an env-supplied\n // connector manifest overrides the bundled one and the bundled one fills the\n // rest (the override layer can refresh built-in manifests in place).\n const seen = new Set<string>();\n target.catalogEntries = target.catalogEntries.filter((e) => {\n const key = `${e.kind}:${e.name}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n\n // Derive implicit refs from skaile.yaml connectors.\n for (const [index, c] of (config.connectors ?? []).entries()) {\n // No `driver` (a misspelt or old `adapter:` key): say so with the text `validate` prints,\n // not a warning about the driver `\"undefined\"` (p1739).\n if (typeof c.driver !== \"string\" || c.driver === \"\") {\n const legacy = (c as unknown as Record<string, unknown>).adapter;\n const label = typeof c.id === \"string\" && c.id !== \"\" ? `\"${c.id}\"` : `#${index + 1}`;\n target.warnings.push({\n code: \"missing_driver\",\n ...(typeof c.id === \"string\" && c.id !== \"\" ? { declarationId: c.id } : {}),\n message:\n legacy !== undefined\n ? `Connector ${label} sets \\`adapter: ${String(legacy)}\\`; the key is \\`driver\\`. Rename \\`adapter\\` to \\`driver\\`.`\n : `Connector ${label} has no \\`driver\\`; the runner cannot mount it. Add \\`driver: <name>\\`.`,\n });\n continue;\n }\n target.implicitRefs.push({ kind: \"connector\", name: c.driver, declarationId: c.id });\n }\n\n // Validate refs and aggregate npm deps.\n const requiredSet = new Set<string>();\n const optionalSet = new Set<string>();\n for (const ref of target.implicitRefs) {\n const entry = findCatalogEntry(target.catalogEntries, ref);\n // A plugin's connector has no catalog entry: the process registry knows it.\n if (!entry && options.isDriverRegistered?.(ref.name)) continue;\n if (!entry) {\n target.warnings.push({\n code: \"missing_driver\",\n declarationId: ref.declarationId,\n name: ref.name,\n message:\n `Unknown ${ref.kind} driver \"${ref.name}\" referenced by ${ref.kind} \"${ref.declarationId}\". ` +\n `Run \\`skaile ${ref.kind} catalog\\` to see available drivers, ` +\n `or declare a repository in skaile.yaml that provides this driver.`,\n });\n continue;\n }\n const npm = (entry.metadata?.npm_deps ?? {}) as { required?: string[]; optional?: string[] };\n for (const p of npm.required ?? []) requiredSet.add(p);\n for (const p of npm.optional ?? []) optionalSet.add(p);\n }\n target.requiredNpmDeps.required = [...requiredSet];\n target.requiredNpmDeps.optional = [...optionalSet];\n}\n\n/**\n * Build the effective `repositories` map: caller's declarations first, then the\n * implicit built-in `factory-assets` repos. Each {@link factoryAssetRoots} layer\n * becomes its own repo, the env override inserted **before** the bundled\n * baseline so its connector entries win on the first-match dedup downstream.\n * When the package cannot be located at all, a path-less sentinel under\n * {@link FACTORY_ASSETS_REPO_NAME} drives the `repo_unavailable` warning.\n */\nfunction buildEffectiveRepositories(\n declared: Record<string, SourceDeclaration> | undefined,\n): Record<string, SourceDeclaration> {\n const result: Record<string, SourceDeclaration> = { ...(declared ?? {}) };\n const roots = factoryAssetRoots();\n if (roots.length === 0) {\n // Surface as a warning during scan rather than throwing here — let the\n // caller decide whether factory-assets is required. resolveRepoDir() /\n // repoUnavailableMessage re-discover the failure and emit it.\n if (!result[FACTORY_ASSETS_REPO_NAME]) result[FACTORY_ASSETS_REPO_NAME] = { path: \"\" };\n return result;\n }\n // override-first when both layers exist, so the env root's entries are scanned\n // (and matched) ahead of the bundled baseline.\n const keys =\n roots.length > 1\n ? [FACTORY_ASSETS_OVERRIDE_REPO_NAME, FACTORY_ASSETS_REPO_NAME]\n : [FACTORY_ASSETS_REPO_NAME];\n roots.forEach((dir, i) => {\n const key = keys[i] ?? `${FACTORY_ASSETS_REPO_NAME}:${i}`;\n if (!result[key]) result[key] = { path: dir };\n });\n return result;\n}\n\n/**\n * Resolve a repository declaration to an on-disk directory. Order:\n * 1. Linked override (`.skaile/links.yaml`).\n * 2. Local `path` — relative to `projectDir`.\n * 3. Cloned URL repo at `.skaile/cache/sources/<name>/` (must already exist).\n *\n * Returns `null` when none of these resolve. Does not clone.\n *\n * **Async and deadline-bounded since #454.** Every candidate here is a\n * project-relative or operator-supplied path, so a `sources[].path` of\n * `workspace/my-assets` resolves onto the rclone FUSE mount — the same tree the\n * scan that follows walks. Probing it with `existsSync`/`lstatSync` would park\n * the `skaile serve` event loop *before* the (now async) scan ever ran, which\n * would leave the H2 fix meaningless on the very declaration that triggers it.\n * A probe that misses its deadline reads as \"unavailable\", which is what the\n * caller already does with an absent path — it becomes a `repo_unavailable`\n * warning rather than a stall.\n */\nasync function resolveRepoDir(\n name: string,\n decl: SourceDeclaration,\n projectDir: string,\n links: Record<string, string>,\n): Promise<string | null> {\n // 1. Linked override\n const linked = links[name];\n if (linked && (await pathExists(linked))) return linked;\n\n // 2. Local path\n if (decl.path) {\n const resolved = resolvePath(projectDir, decl.path);\n return (await pathExists(resolved)) ? resolved : null;\n }\n\n // 3. URL repo cloned to project's .skaile/cache/sources/<name> — the\n // project-local clone dir (often a symlink into the global cache, which\n // lives at getGlobalCacheDir()); NOT the global clone root itself.\n if (decl.url) {\n const projectDest = join(projectDir, \".skaile\", \"cache\", \"sources\", name);\n // One `lstat` answers both questions the pre-#454 `existsSync` + `lstatSync`\n // pair asked, and `lstat` (not `stat`) keeps the \"a symlink into the global\n // cache counts\" behaviour intact.\n const found = await tryWithFsDeadline(\n `lstat ${projectDest}`,\n async () => {\n await lstat(projectDest);\n return true;\n },\n false,\n );\n return found ? projectDest : null;\n }\n\n return null;\n}\n\n/** Deadline-bounded `existsSync` replacement — a wedged mount reads as absent. */\nfunction pathExists(path: string): Promise<boolean> {\n return tryWithFsDeadline(\n `stat ${path}`,\n async () => {\n await stat(path);\n return true;\n },\n false,\n );\n}\n\nfunction repoUnavailableMessage(name: string, decl: SourceDeclaration): string {\n if (name === FACTORY_ASSETS_REPO_NAME && !decl.path && !decl.url) {\n return (\n `Cannot resolve the built-in factory-assets. ` +\n `Set SKAILE_FACTORY_ASSETS_DIR or ensure @skaile/workspaces is installed.`\n );\n }\n if (decl.url) {\n return `Repository \"${name}\" (${decl.url}) is not available. Register it as a Library Source via \\`skaile source add\\`.`;\n }\n if (decl.path) {\n return `Repository \"${name}\" path not found: ${decl.path}`;\n }\n return `Repository \"${name}\" has neither url nor path.`;\n}\n\nfunction findCatalogEntry(\n entries: RuntimeCatalogEntry[],\n query: { kind?: \"connector\"; name: string },\n): RuntimeCatalogEntry | undefined {\n if (query.kind) {\n return entries.find((e) => e.kind === query.kind && e.name === query.name);\n }\n const matches = entries.filter((e) => e.name === query.name);\n if (matches.length === 1) return matches[0];\n // 0 or >1 with no kind — caller must disambiguate.\n return undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../core/src/runtime-assets.ts"],"names":["resolvePath","require"],"mappings":"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","file":"chunk-CJO3XKO7.js","sourcesContent":["/**\n * Runtime asset resolution — read `skaile.yaml`, scan all declared repositories\n * (including the built-in `factory-assets/` directory as an implicit default),\n * and produce a unified view of connector catalog entries plus the implicit refs\n * that the `skaile.yaml` `connectors:` section adds to the dependency graph.\n *\n * This module is the single source of truth for \"which connectors does this\n * project see at runtime, and where do their implementations live on disk\".\n * Both the runner (serve, REPL, flow) and the platform's mid-session\n * `add_resource` flow consume `RuntimeAssetsResult.catalogEntries` and pass\n * it into `ConnectorManager` for catalog-based resolution.\n *\n * `factory-assets/` is the single first-party content tree (built-in connectors\n * + first-party skills + bundles) shipped inside the `@skaile/workspaces`\n * package — not a standalone package.\n *\n * It resolves to an **ordered list of roots** ({@link factoryAssetRoots}), not a\n * single dir. The bundled tree is always the baseline; an optional\n * `SKAILE_FACTORY_ASSETS_DIR` (legacy: `SKAILE_BASE_ASSETS_DIR`) is layered\n * **in front** as an additive override source — the agent container points it at\n * `/app/factory-assets/` (or a bind-mounted host dir) to ship updated skills /\n * flows / bundles / connector manifests without rebuilding the image. The two\n * roots resolve uniformly across every consumer (connector catalog scan, skill /\n * flow / completion discovery, the asset-manager factory source):\n * 1. `SKAILE_FACTORY_ASSETS_DIR` env dir, when set and existing (override layer).\n * 2. the bundled tree via {@link resolvePackagedAssetsDir} — the in-repo source\n * `packages/workspaces/factory-assets/` during dev, else the published\n * `dist/factory-assets/` after install (always-present baseline).\n *\n * Override semantics are **env-first**: on a name conflict the env root wins and\n * the bundled root fills the rest. Connector *code* still loads via the package's\n * static `exports` map, so the env root can override/add skills, flows, bundles,\n * and connector **manifests/metadata**, but cannot ship a new executable\n * connector — its `.js` is not on the package's import graph.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { lstat, stat } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, resolve as resolvePath } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { tryWithFsDeadline } from \"./fs-deadline.js\";\nimport { scanDirectory } from \"./manifest.js\";\nimport type { CatalogEntry } from \"./models.js\";\nimport { getGlobalCacheDir, readLinks, sourceCacheKey } from \"./repo-manager.js\";\nimport type { SourceDeclaration, SourceEntry } from \"./workspace-config.js\";\nimport { resolveSkWorkspaceConfig } from \"./workspace-config.js\";\n\n/**\n * Map declared `sources[]` to internal `SourceDeclaration`s keyed by the\n * collision-free {@link sourceCacheKey} (`<host>/<owner>/<repo>`), pointing at\n * the unified machine-cache clone path (`getGlobalCacheDir()/<key>/`). Keyed by\n * the same function every other cache writer/reader uses so the path resolves.\n */\nfunction sourcesToDeclarations(\n sources: SourceEntry[] | undefined,\n): Record<string, SourceDeclaration> {\n const sourcesDir = getGlobalCacheDir();\n const out: Record<string, SourceDeclaration> = {};\n for (const s of sources ?? []) {\n const key = sourceCacheKey(s.url);\n if (out[key]) continue;\n out[key] = {\n path: join(sourcesDir, key),\n url: s.url,\n branch: s.pin,\n ...(s.publisher ? { publisher: s.publisher } : {}),\n };\n }\n return out;\n}\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\n/**\n * Catalog entry filtered to mount/connector kinds. Same shape as `CatalogEntry`.\n * @docLink packages/core/concepts#runtime-catalog-entry\n */\nexport type RuntimeCatalogEntry = CatalogEntry;\n\n/**\n * Implicit catalog reference derived from a `connectors:` declaration in `skaile.yaml`.\n * Each connector driver becomes an implicit ref that must be resolved in the catalog.\n * @docLink packages/core/concepts#runtime-asset-ref\n */\nexport interface RuntimeAssetRef {\n kind: \"connector\";\n /** Driver name — matches `RuntimeCatalogEntry.name`. */\n name: string;\n /** Source declaration id from `skaile.yaml`. */\n declarationId: string;\n}\n\n/**\n * Aggregated npm packages required by all resolved mount/connector adapters.\n * Populated from `metadata.npm_deps` in each matched catalog entry.\n * @docLink packages/core/concepts#runtime-npm-deps\n */\nexport interface RuntimeNpmDeps {\n required: string[];\n optional: string[];\n}\n\n/**\n * Non-fatal warning emitted during `resolveRuntimeAssets` when a repo is unavailable\n * or a driver is not found in any catalog.\n * @docLink packages/core/concepts#runtime-asset-warning\n */\nexport interface RuntimeAssetWarning {\n /** Stable code for filtering / structured logging. */\n code: \"missing_driver\" | \"repo_unavailable\" | \"invalid_repo_decl\";\n message: string;\n /** Declaration id when applicable. */\n declarationId?: string;\n /** Driver / repository name when applicable. */\n name?: string;\n}\n\n/**\n * Repository name used for the implicit built-in `factory-assets` catalog entry\n * (the in-package connector tree).\n * @docLink packages/core/concepts#factory-assets-repo-name\n */\nexport const FACTORY_ASSETS_REPO_NAME = \"factory-assets\";\n\n/**\n * Repository name for the optional `SKAILE_FACTORY_ASSETS_DIR` override layer,\n * scanned ahead of (and overriding) the bundled {@link FACTORY_ASSETS_REPO_NAME}.\n */\nconst FACTORY_ASSETS_OVERRIDE_REPO_NAME = \"factory-assets:override\";\n\n/**\n * Result of `resolveRuntimeAssets`.\n * The same object is mutated in place by `refresh()`, allowing callers to hold\n * a stable reference and observe updates after a new repository is cloned or\n * a driver is installed mid-session.\n * @docLink packages/core/concepts#runtime-assets-result\n */\nexport interface RuntimeAssetsResult {\n catalogEntries: RuntimeCatalogEntry[];\n implicitRefs: RuntimeAssetRef[];\n requiredNpmDeps: RuntimeNpmDeps;\n warnings: RuntimeAssetWarning[];\n /** Re-scan repositories and re-derive implicit refs. Mutates in place. */\n refresh(): Promise<void>;\n /**\n * Catalog lookup. When `kind` is omitted and multiple entries share the\n * `name`, returns `undefined` (caller must disambiguate).\n */\n findEntry(query: { kind?: \"connector\"; name: string }): RuntimeCatalogEntry | undefined;\n}\n\n/** Options of {@link resolveRuntimeAssets}. */\nexport interface RuntimeAssetsOptions {\n /**\n * True when a connector driver is registered in the process (built-in or loaded plugin).\n * Core does not know the registry; the caller passes its lookup. Without it only the catalog\n * counts, so a driver a plugin registers is reported as `missing_driver`.\n */\n isDriverRegistered?: (driver: string) => boolean;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Resolve all runtime assets visible to a project by scanning declared repositories.\n *\n * Reads `skaile.yaml`, scans every declared repository (plus the implicit\n * built-in `factory-assets` repo), and derives implicit refs from `mounts:` /\n * `connectors:` declarations. Does not clone or install anything — purely a\n * read-only scan of what is already on disk. URL-only repositories that have\n * not been cloned yet are reported as `repo_unavailable` warnings.\n *\n * @param projectDir - Absolute path to the project workspace root\n * @param options - `isDriverRegistered`: a driver that no catalog entry lists but a plugin\n * registered is not reported as `missing_driver`\n * @returns `RuntimeAssetsResult` with catalog entries, implicit refs, npm deps, and warnings\n * @docLink packages/core/concepts#resolve-runtime-assets\n */\nexport async function resolveRuntimeAssets(\n projectDir: string,\n options: RuntimeAssetsOptions = {},\n): Promise<RuntimeAssetsResult> {\n const result: RuntimeAssetsResult = {\n catalogEntries: [],\n implicitRefs: [],\n requiredNpmDeps: { required: [], optional: [] },\n warnings: [],\n refresh: async () => {\n await populate(projectDir, result, options);\n },\n findEntry: (query) => findCatalogEntry(result.catalogEntries, query),\n };\n\n await populate(projectDir, result, options);\n return result;\n}\n\n/**\n * Resolve the ordered list of on-disk roots for the built-in `factory-assets`\n * tree (built-in connectors + first-party skills + bundles). This is the single\n * shared resolver every consumer goes through, so the env override and the\n * bundled baseline are honoured uniformly.\n *\n * Order (env-first = override-wins):\n * 1. `SKAILE_FACTORY_ASSETS_DIR` env dir (legacy: `SKAILE_BASE_ASSETS_DIR`),\n * when set and existing — an additive override layer.\n * 2. {@link resolvePackagedAssetsDir} — the bundled tree (in-repo source in dev,\n * `dist/factory-assets/` after install). Always-present baseline.\n *\n * Returns `[]` only when the package cannot be located at all. De-duplicated, so\n * pointing the env var at the bundled dir collapses to one root.\n *\n * @docLink packages/core/concepts#resolve-factory-assets-root\n */\nexport function factoryAssetRoots(): string[] {\n const roots: string[] = [];\n const envDir = process.env.SKAILE_FACTORY_ASSETS_DIR ?? process.env.SKAILE_BASE_ASSETS_DIR;\n // Deliberately still synchronous after #454: both candidates are\n // container-local (the image's `/app/factory-assets/`, or the installed\n // package tree resolved by `resolvePackagedAssetsDir`), never the FUSE\n // workspace mount. The mount-reachable probes on this module's scan path —\n // the project-relative `sources[].path` candidates in `resolveRepoDir` — are\n // async and deadline-bounded.\n if (envDir && existsSync(envDir)) roots.push(resolvePath(envDir));\n const bundled = resolvePackagedAssetsDir(\"factory-assets\");\n if (bundled) roots.push(bundled);\n return [...new Set(roots)];\n}\n\n/**\n * Resolve the primary on-disk root of the `factory-assets` tree — the first of\n * {@link factoryAssetRoots} (the env override when set, else the bundled tree).\n * Prefer {@link factoryAssetRoots} when you need to scan every layer; this\n * single-dir form is for callers that want one canonical path.\n *\n * @returns Absolute path to the highest-precedence `factory-assets` directory\n * @throws When no root can be located\n * @docLink packages/core/concepts#resolve-factory-assets-root\n */\nexport function resolveFactoryAssetsRoot(): string {\n const hit = resolveFactoryAssetsRootOrNull();\n if (hit) return hit;\n\n throw new Error(\n `Cannot resolve the factory-assets directory. ` +\n `Set SKAILE_FACTORY_ASSETS_DIR to the on-disk path, ` +\n `ensure @skaile/workspaces is installed, ` +\n `or run from within the @skaile/workspaces package tree.`,\n );\n}\n\n/**\n * Non-throwing variant of {@link resolveFactoryAssetsRoot}: the same\n * env-then-packaged resolution tiers, returning `null` instead of throwing when\n * none locate the directory. Callers that treat a missing factory tree as a\n * soft \"not present\" (e.g. the asset-manager's implicit-source injection) MUST\n * use this so they honour the `SKAILE_FACTORY_ASSETS_DIR` container override\n * identically to the runtime path.\n */\nexport function resolveFactoryAssetsRootOrNull(): string | null {\n return factoryAssetRoots()[0] ?? null;\n}\n\n/**\n * Resolve the `@skaile/workspaces` package root — the directory containing its\n * `package.json`. Tries `require.resolve` first (works when installed as a\n * dependency *and* in-repo via the self-reference), then walks upward from this\n * module looking for a `package.json` whose `name` is `@skaile/workspaces`\n * (bounded to 8 levels). Returns `null` when neither locates it.\n *\n * The single source of truth for finding content shipped inside the package —\n * the unified `factory-assets/` tree (built-in connectors + first-party skills\n * + bundles) resolves through {@link resolvePackagedAssetsDir} on top of this.\n *\n * Memoized: the package location is immutable for the process lifetime, but\n * this sits on the CLI hot path (every `findSkills` / flow / completion call\n * funnels through here), so the `require.resolve` + upward `package.json` walk\n * runs once. `undefined` = not yet computed.\n *\n * @docLink packages/core/concepts#resolve-factory-assets-root\n */\nlet workspacesPackageRootCache: string | null | undefined;\n\nexport function resolveWorkspacesPackageRoot(): string | null {\n if (workspacesPackageRootCache !== undefined) return workspacesPackageRootCache;\n workspacesPackageRootCache = computeWorkspacesPackageRoot();\n return workspacesPackageRootCache;\n}\n\nfunction computeWorkspacesPackageRoot(): string | null {\n try {\n const require = createRequire(import.meta.url);\n return dirname(require.resolve(\"@skaile/workspaces/package.json\"));\n } catch {\n // Fall through to the workspace walk.\n }\n let dir: string;\n try {\n dir = dirname(fileURLToPath(import.meta.url));\n } catch {\n return null;\n }\n for (let i = 0; i < 8; i++) {\n const pkgPath = join(dir, \"package.json\");\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\")) as { name?: string };\n if (pkg.name === \"@skaile/workspaces\") return dir;\n } catch {\n // Ignore malformed package.json and keep walking.\n }\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/**\n * Locate a content-asset directory inside the package. Prefers the in-repo\n * **source** dir `<pkgRoot>/<subdir>` when present — in a dev checkout it is the\n * full tree (e.g. `factory-assets/` keeps the connector `.ts` entry files that\n * `dist/` does not) — then the published `dist/<subdir>` copy (what\n * `files: [\"dist\"]` ships, the only one present after `npm i`). Returns `null`\n * when neither exists.\n *\n * `factory-assets/` resolves to the source tree in dev (code + skills + bundles)\n * and to `dist/factory-assets` post-install (compiled connectors + copied\n * manifests/skills/bundles).\n *\n * @param subdir - `\"factory-assets\"` | …\n * @docLink packages/core/concepts#resolve-factory-assets-root\n */\nexport function resolvePackagedAssetsDir(subdir: string): string | null {\n const root = resolveWorkspacesPackageRoot();\n if (!root) return null;\n for (const cand of [join(root, subdir), join(root, \"dist\", subdir)]) {\n if (existsSync(cand)) return cand;\n }\n return null;\n}\n\n// ─── Internals ────────────────────────────────────────────────────────────────\n\nconst CONNECTOR_SCAN_KINDS: ReadonlySet<string> = new Set([\"connector\"]);\n\nasync function populate(\n projectDir: string,\n target: RuntimeAssetsResult,\n options: RuntimeAssetsOptions,\n): Promise<void> {\n target.catalogEntries = [];\n target.implicitRefs = [];\n target.requiredNpmDeps = { required: [], optional: [] };\n target.warnings = [];\n\n const config = resolveSkWorkspaceConfig(projectDir);\n // Connector catalog scan runs over the project's declared sources[] (resolved\n // to their machine-cache clone paths) plus the implicit factory-assets repo.\n const repositories = buildEffectiveRepositories(sourcesToDeclarations(config.sources));\n const links = readLinks(projectDir);\n\n // Scan each repository for connector entries.\n for (const [name, decl] of Object.entries(repositories)) {\n const repoDir = await resolveRepoDir(name, decl, projectDir, links);\n if (!repoDir) {\n target.warnings.push({\n code: \"repo_unavailable\",\n name,\n message: repoUnavailableMessage(name, decl),\n });\n continue;\n }\n try {\n // Both factory layers carry the same `factory-assets` provenance — the\n // override repo is an internal scan-order device, not a distinct source.\n const repoName = name === FACTORY_ASSETS_OVERRIDE_REPO_NAME ? FACTORY_ASSETS_REPO_NAME : name;\n // Only connector descriptors are consumed here, so only that kind is\n // \"known\": typed manifests of any other kind are irrelevant to this scan.\n const scanned = await scanDirectory(repoDir, repoName, {\n knownKinds: CONNECTOR_SCAN_KINDS,\n onDiagnostic: () => {},\n });\n const entries = scanned.filter((e) => e.kind === \"connector\");\n target.catalogEntries.push(...entries);\n } catch (err) {\n target.warnings.push({\n code: \"repo_unavailable\",\n name,\n message: `Failed to scan repository \"${name}\" at ${repoDir}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n });\n }\n }\n\n // De-duplicate by (kind, name), keeping the first occurrence. Scan order is\n // declared sources → env override → bundled baseline, so an env-supplied\n // connector manifest overrides the bundled one and the bundled one fills the\n // rest (the override layer can refresh built-in manifests in place).\n const seen = new Set<string>();\n target.catalogEntries = target.catalogEntries.filter((e) => {\n const key = `${e.kind}:${e.name}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n\n // Derive implicit refs from skaile.yaml connectors.\n for (const [index, c] of (config.connectors ?? []).entries()) {\n // No `driver` (a misspelt or old `adapter:` key): say so with the text `validate` prints,\n // not a warning about the driver `\"undefined\"` (p1739).\n if (typeof c.driver !== \"string\" || c.driver === \"\") {\n const legacy = (c as unknown as Record<string, unknown>).adapter;\n const label = typeof c.id === \"string\" && c.id !== \"\" ? `\"${c.id}\"` : `#${index + 1}`;\n target.warnings.push({\n code: \"missing_driver\",\n ...(typeof c.id === \"string\" && c.id !== \"\" ? { declarationId: c.id } : {}),\n message:\n legacy !== undefined\n ? `Connector ${label} sets \\`adapter: ${String(legacy)}\\`; the key is \\`driver\\`. Rename \\`adapter\\` to \\`driver\\`.`\n : `Connector ${label} has no \\`driver\\`; the runner cannot mount it. Add \\`driver: <name>\\`.`,\n });\n continue;\n }\n target.implicitRefs.push({ kind: \"connector\", name: c.driver, declarationId: c.id });\n }\n\n // Validate refs and aggregate npm deps.\n const requiredSet = new Set<string>();\n const optionalSet = new Set<string>();\n for (const ref of target.implicitRefs) {\n const entry = findCatalogEntry(target.catalogEntries, ref);\n // A plugin's connector has no catalog entry: the process registry knows it.\n if (!entry && options.isDriverRegistered?.(ref.name)) continue;\n if (!entry) {\n target.warnings.push({\n code: \"missing_driver\",\n declarationId: ref.declarationId,\n name: ref.name,\n message:\n `Unknown ${ref.kind} driver \"${ref.name}\" referenced by ${ref.kind} \"${ref.declarationId}\". ` +\n `Run \\`skaile ${ref.kind} catalog\\` to see available drivers, ` +\n `or declare a repository in skaile.yaml that provides this driver.`,\n });\n continue;\n }\n const npm = (entry.metadata?.npm_deps ?? {}) as { required?: string[]; optional?: string[] };\n for (const p of npm.required ?? []) requiredSet.add(p);\n for (const p of npm.optional ?? []) optionalSet.add(p);\n }\n target.requiredNpmDeps.required = [...requiredSet];\n target.requiredNpmDeps.optional = [...optionalSet];\n}\n\n/**\n * Build the effective `repositories` map: caller's declarations first, then the\n * implicit built-in `factory-assets` repos. Each {@link factoryAssetRoots} layer\n * becomes its own repo, the env override inserted **before** the bundled\n * baseline so its connector entries win on the first-match dedup downstream.\n * When the package cannot be located at all, a path-less sentinel under\n * {@link FACTORY_ASSETS_REPO_NAME} drives the `repo_unavailable` warning.\n */\nfunction buildEffectiveRepositories(\n declared: Record<string, SourceDeclaration> | undefined,\n): Record<string, SourceDeclaration> {\n const result: Record<string, SourceDeclaration> = { ...(declared ?? {}) };\n const roots = factoryAssetRoots();\n if (roots.length === 0) {\n // Surface as a warning during scan rather than throwing here — let the\n // caller decide whether factory-assets is required. resolveRepoDir() /\n // repoUnavailableMessage re-discover the failure and emit it.\n if (!result[FACTORY_ASSETS_REPO_NAME]) result[FACTORY_ASSETS_REPO_NAME] = { path: \"\" };\n return result;\n }\n // override-first when both layers exist, so the env root's entries are scanned\n // (and matched) ahead of the bundled baseline.\n const keys =\n roots.length > 1\n ? [FACTORY_ASSETS_OVERRIDE_REPO_NAME, FACTORY_ASSETS_REPO_NAME]\n : [FACTORY_ASSETS_REPO_NAME];\n roots.forEach((dir, i) => {\n const key = keys[i] ?? `${FACTORY_ASSETS_REPO_NAME}:${i}`;\n if (!result[key]) result[key] = { path: dir };\n });\n return result;\n}\n\n/**\n * Resolve a repository declaration to an on-disk directory. Order:\n * 1. Linked override (`.skaile/links.yaml`).\n * 2. Local `path` — relative to `projectDir`.\n * 3. Cloned URL repo at `.skaile/cache/sources/<name>/` (must already exist).\n *\n * Returns `null` when none of these resolve. Does not clone.\n *\n * **Async and deadline-bounded since #454.** Every candidate here is a\n * project-relative or operator-supplied path, so a `sources[].path` of\n * `workspace/my-assets` resolves onto the rclone FUSE mount — the same tree the\n * scan that follows walks. Probing it with `existsSync`/`lstatSync` would park\n * the `skaile serve` event loop *before* the (now async) scan ever ran, which\n * would leave the H2 fix meaningless on the very declaration that triggers it.\n * A probe that misses its deadline reads as \"unavailable\", which is what the\n * caller already does with an absent path — it becomes a `repo_unavailable`\n * warning rather than a stall.\n */\nasync function resolveRepoDir(\n name: string,\n decl: SourceDeclaration,\n projectDir: string,\n links: Record<string, string>,\n): Promise<string | null> {\n // 1. Linked override\n const linked = links[name];\n if (linked && (await pathExists(linked))) return linked;\n\n // 2. Local path\n if (decl.path) {\n const resolved = resolvePath(projectDir, decl.path);\n return (await pathExists(resolved)) ? resolved : null;\n }\n\n // 3. URL repo cloned to project's .skaile/cache/sources/<name> — the\n // project-local clone dir (often a symlink into the global cache, which\n // lives at getGlobalCacheDir()); NOT the global clone root itself.\n if (decl.url) {\n const projectDest = join(projectDir, \".skaile\", \"cache\", \"sources\", name);\n // One `lstat` answers both questions the pre-#454 `existsSync` + `lstatSync`\n // pair asked, and `lstat` (not `stat`) keeps the \"a symlink into the global\n // cache counts\" behaviour intact.\n const found = await tryWithFsDeadline(\n `lstat ${projectDest}`,\n async () => {\n await lstat(projectDest);\n return true;\n },\n false,\n );\n return found ? projectDest : null;\n }\n\n return null;\n}\n\n/** Deadline-bounded `existsSync` replacement — a wedged mount reads as absent. */\nfunction pathExists(path: string): Promise<boolean> {\n return tryWithFsDeadline(\n `stat ${path}`,\n async () => {\n await stat(path);\n return true;\n },\n false,\n );\n}\n\nfunction repoUnavailableMessage(name: string, decl: SourceDeclaration): string {\n if (name === FACTORY_ASSETS_REPO_NAME && !decl.path && !decl.url) {\n return (\n `Cannot resolve the built-in factory-assets. ` +\n `Set SKAILE_FACTORY_ASSETS_DIR or ensure @skaile/workspaces is installed.`\n );\n }\n if (decl.url) {\n return `Repository \"${name}\" (${decl.url}) is not available. Register it as a Library Source via \\`skaile source add\\`.`;\n }\n if (decl.path) {\n return `Repository \"${name}\" path not found: ${decl.path}`;\n }\n return `Repository \"${name}\" has neither url nor path.`;\n}\n\nfunction findCatalogEntry(\n entries: RuntimeCatalogEntry[],\n query: { kind?: \"connector\"; name: string },\n): RuntimeCatalogEntry | undefined {\n if (query.kind) {\n return entries.find((e) => e.kind === query.kind && e.name === query.name);\n }\n const matches = entries.filter((e) => e.name === query.name);\n if (matches.length === 1) return matches[0];\n // 0 or >1 with no kind — caller must disambiguate.\n return undefined;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { compositeSha256 } from './chunk-
|
|
2
|
-
import { parseAssetRef } from './chunk-
|
|
1
|
+
import { compositeSha256 } from './chunk-MS2IXLTC.js';
|
|
2
|
+
import { parseAssetRef } from './chunk-7HRZACI4.js';
|
|
3
3
|
import { createHash } from 'crypto';
|
|
4
4
|
import { openSync, fstatSync, readSync, chmodSync, closeSync } from 'fs';
|
|
5
5
|
import { rm, mkdir, writeFile, chmod } from 'fs/promises';
|
|
@@ -146,5 +146,5 @@ async function installFlat(manifest, targetDir, fetcher) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
export { assertSafeManifestPath, installFromManifest, isScriptBytes, longestCommonDirPrefix, restoreScriptModes };
|
|
149
|
-
//# sourceMappingURL=chunk-
|
|
150
|
-
//# sourceMappingURL=chunk-
|
|
149
|
+
//# sourceMappingURL=chunk-CVUMZTNO.js.map
|
|
150
|
+
//# sourceMappingURL=chunk-CVUMZTNO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../library/src/install/install-from-manifest.ts"],"names":[],"mappings":"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","file":"chunk-OSABUEWA.js","sourcesContent":["/**\n * Pointer-only install path.\n *\n * Given an {@link InstallManifest} (the Pointer Triple the Catalog hands\n * clients), this:\n *\n * 1. fetches the asset bytes directly from the upstream repo at the pinned\n * commit (via an injectable fetcher, default {@link fetchAssetFilesFromGitHub});\n * 2. verifies EVERY per-file SHA256 against `manifest.files[].sha256`;\n * 3. verifies the composite SHA256 rollup over the sorted\n * `<path>:<sha256>\\n` lines against `manifest.sha256`;\n * 4. writes the verified bytes under `<libraryRoot>/@<publisher>/<name>/<version>`.\n *\n * Any hash mismatch is a hard failure — bytes are not written if per-file\n * verification fails, and the composite check is the second gate.\n *\n * @docLink packages/library/concepts#install\n */\n\nimport { createHash } from \"node:crypto\";\nimport { chmodSync, closeSync, fstatSync, openSync, readSync } from \"node:fs\";\nimport { chmod, mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve, sep } from \"node:path\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\n// Narrow module, not the `core` barrel: the barrel's chunks carry `import.meta`,\n// which breaks consumers that transpile this entry to CommonJS.\nimport { parseAssetRef } from \"../../../core/src/models.js\";\nimport { compositeSha256 } from \"../../../core/src/publish-manifest.js\";\n\n/**\n * Validate a single manifest-supplied file path against path traversal.\n *\n * `manifest.files[].path` comes off the network — the attacker controls the\n * entire manifest (and therefore every hash in it), so hash verification can\n * NEVER mitigate a malicious *destination*. A path like\n * `../../../../home/user/.bashrc` or an absolute path would escape\n * `installPath` and yield an arbitrary file write. Every path is checked\n * BEFORE any fetch or write happens; the first bad path aborts the entire\n * install with a hard throw.\n *\n * A path is rejected if ANY of:\n * - it is empty;\n * - it is absolute (`path.isAbsolute`) or has a leading slash;\n * - it contains a `..` segment;\n * - `path.resolve(installPath, p)` is not `installPath` itself and does not\n * start with `installPath + path.sep` (escapes the install dir).\n *\n * @throws An error matching `/unsafe path in manifest/` on the first bad path.\n */\nexport function assertSafeManifestPath(installPath: string, p: string): void {\n const bad = (): never => {\n throw new Error(`unsafe path in manifest: ${p}`);\n };\n if (!p || p.length === 0) bad();\n if (isAbsolute(p) || p.startsWith(\"/\") || p.startsWith(\"\\\\\")) bad();\n const segments = p.split(/[/\\\\]/);\n if (segments.some((s) => s === \"..\")) bad();\n const resolved = resolve(installPath, p);\n if (resolved !== installPath && !resolved.startsWith(installPath + sep)) bad();\n}\n\n/**\n * Validate one component (publisher / name / version) of the attacker-controlled\n * `manifest.ref`.\n *\n * `installPath` is built by joining these components onto `libraryRoot`. A\n * component containing a path separator or a `..` / leading-dot segment would\n * let `installPath` itself escape `libraryRoot` — yielding an arbitrary file\n * write AND, via the pre-write `rm(installPath, { recursive })`, an arbitrary\n * recursive delete. The per-file `assertSafeManifestPath` guard cannot catch\n * this: it only validates each `f.path` *relative to* `installPath`, never\n * `installPath` itself. Components must be plain identifier-like strings.\n *\n * @throws An error matching `/unsafe ref/` on a bad component.\n */\nfunction assertSafeRefComponent(kind: string, value: string): void {\n // Reject empty, leading-dot (covers `.` and `..`), path separators, and\n // ASCII control characters (NUL et al.) — fails a malformed segment fast\n // with a domain-specific error rather than a raw EINVAL deeper in.\n const hasControlChar = [...value].some((c) => c.charCodeAt(0) < 0x20);\n if (!value || value.startsWith(\".\") || /[/\\\\]/.test(value) || hasControlChar) {\n throw new Error(`unsafe ref ${kind} component in manifest: '${value}'`);\n }\n}\n\n/**\n * Longest common **directory** prefix across manifest paths, compared by whole\n * slash-delimited segments (never raw-string — so `app/` and `app-data/` never\n * collide). Each path's basename is excluded, so the result is always a\n * directory prefix and every path keeps a non-empty remainder after stripping.\n *\n * Used by flat mode to reproduce the platform pointer-installer's asset-rooting:\n * the store persists repo-root-relative paths (e.g. `skaile-platform/mcpo/xls/MCP.md`)\n * but the runner scans `.skaile/assets/<kind>/<name>/` for immediate-child files,\n * so this prefix is stripped from the WRITE path while the fetch keeps the full\n * repo path. Returns `''` when there is no common directory (a no-op strip).\n */\nexport function longestCommonDirPrefix(paths: readonly string[]): string {\n if (paths.length === 0) return \"\";\n const dirSegments = paths.map((p) => p.split(\"/\").slice(0, -1));\n let common = dirSegments[0]!;\n for (let i = 1; i < dirSegments.length && common.length > 0; i++) {\n const segs = dirSegments[i]!;\n let n = 0;\n while (n < common.length && n < segs.length && common[n] === segs[n]) n++;\n common = common.slice(0, n);\n }\n return common.join(\"/\");\n}\n\n/**\n * Whether `bytes` start a script (`#!`). A pointer manifest and GitHub's raw host carry no file\n * modes, while the library or clone the same asset comes from keeps its script executable, so a\n * shebang is what marks a file executable here (p1657).\n */\nexport function isScriptBytes(bytes: Uint8Array): boolean {\n return bytes.length >= 2 && bytes[0] === 0x23 && bytes[1] === 0x21;\n}\n\n/** The mode of an executable file written from store bytes. */\nconst EXECUTABLE_MODE = 0o755;\n\n/**\n * Make every file of `relPaths` under `root` that starts with `#!` executable. For bytes an\n * earlier install already wrote (a project store cache from before exec bits were kept), so a\n * restore from them deploys the same modes as a fresh fetch. A missing or unreadable file is\n * skipped.\n */\nexport function restoreScriptModes(root: string, relPaths: readonly string[]): void {\n for (const rel of relPaths) {\n let fd: number | undefined;\n try {\n fd = openSync(join(root, rel), \"r\");\n if ((fstatSync(fd).mode & 0o111) !== 0) continue;\n const head = Buffer.alloc(2);\n if (readSync(fd, head, 0, 2, 0) === 2 && isScriptBytes(head)) {\n chmodSync(join(root, rel), EXECUTABLE_MODE);\n }\n } catch {\n // Not readable or not a file: nothing to fix.\n } finally {\n if (fd !== undefined) closeSync(fd);\n }\n }\n}\n\n/**\n * Fetcher signature — fetches `{ path → Buffer }` for the requested paths at\n * a pinned upstream commit. {@link fetchAssetFilesFromGitHub} is the default\n * production implementation; tests inject a mock.\n */\nexport type AssetFetcher = (opts: {\n url: string;\n commitSha: string;\n paths: string[];\n}) => Promise<Record<string, Buffer>>;\n\n/**\n * Options for {@link installFromManifest}.\n */\nexport interface InstallOpts {\n /** The pointer-only install manifest from the Catalog. */\n manifest: InstallManifest;\n /** Filesystem root the asset is installed under (ref-derived mode). */\n libraryRoot: string;\n /**\n * Pluggable fetcher so tests can inject mock data. Defaults to\n * {@link fetchAssetFilesFromGitHub} in production.\n */\n fetcher?: AssetFetcher;\n /**\n * Flat-layout mode. When set, install-core reproduces the platform\n * pointer-installer's behavior: it ignores `libraryRoot`/ref-derivation, does\n * NOT parse `manifest.ref` and does NOT verify the composite sha256, strips\n * the longest-common-dir prefix from each path, per-file sha256-verifies, and\n * writes the stripped paths as immediate children of `targetDir` (what the\n * runner's `.skaile/assets/<kind>/<name>/` scan requires). `installPath` is\n * `targetDir`. Absent → unchanged ref-derived `@<pub>/name/version/<path>`\n * layout with composite verify.\n */\n targetDir?: string;\n}\n\n/**\n * Result of a successful {@link installFromManifest} call.\n */\nexport interface InstallResult {\n /** Absolute path the asset files were written to. */\n installPath: string;\n}\n\n/**\n * Fetch, verify, and write an asset's files per its {@link InstallManifest}.\n *\n * @throws An error matching `/hash mismatch/i` if any per-file SHA256 differs.\n * @throws An error matching `/composite hash mismatch/i` if the rollup differs.\n * @throws An error if the ref is malformed or the fetcher omits a file.\n */\nexport async function installFromManifest(opts: InstallOpts): Promise<InstallResult> {\n const { manifest, libraryRoot } = opts;\n const fetcher =\n opts.fetcher ?? (await import(\"./source-fetch-github.js\")).fetchAssetFilesFromGitHub;\n\n // Flat mode: reproduce the platform pointer-installer's asset-rooted layout.\n // No ref parse, no composite verify — the platform store may not satisfy a\n // ref-grammar or composite, and the runner only needs immediate-child files.\n if (opts.targetDir !== undefined) {\n return installFlat(manifest, opts.targetDir, fetcher);\n }\n\n // 1. Parse ref into install path: `skill:@x/git#1.0.0` → `<root>/@x/git/1.0.0`.\n // Done first so the C1 path-traversal guard can resolve against installPath\n // BEFORE any network fetch happens. The ref is attacker-controlled, so each\n // segment is further validated as a safe path component (H1) after parsing.\n // `parseAssetRef` is the single canonical grammar (`kind:@publisher/name#version`);\n // the legacy trailing-`@version` shape was removed in core and is rejected here.\n let parsed: ReturnType<typeof parseAssetRef>;\n try {\n parsed = parseAssetRef(manifest.ref);\n } catch (e) {\n throw new Error(`invalid ref: ${manifest.ref}: ${e instanceof Error ? e.message : String(e)}`);\n }\n const publisher = parsed.publisher;\n const name = parsed.name;\n const version = parsed.pin;\n if (!publisher) throw new Error(`invalid ref: ${manifest.ref} (missing publisher)`);\n if (!version) throw new Error(`invalid ref: ${manifest.ref} (missing version pin)`);\n assertSafeRefComponent(\"publisher\", publisher);\n assertSafeRefComponent(\"name\", name);\n assertSafeRefComponent(\"version\", version);\n const root = resolve(libraryRoot);\n const installPath = resolve(join(root, `@${publisher}`, name, version));\n // Defense in depth: even with the segment guards above, assert the built\n // installPath stays strictly inside libraryRoot before any write or `rm`.\n if (installPath !== root && !installPath.startsWith(root + sep)) {\n throw new Error(`unsafe install path: ref '${manifest.ref}' resolves outside the library root`);\n }\n\n // 2. [C1] Validate EVERY manifest path against traversal BEFORE fetching.\n // The attacker controls the manifest (and thus all hashes) — hashes verify\n // content, never destination. Reject the whole install on the first bad path.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n }\n\n // 3. Fetch all files at the pinned commit.\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // 4. Verify per-file SHA256 — hard fail before writing anything. The path\n // key used to read from the fetcher result is re-guarded as defense in depth.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n }\n\n // 5. Verify composite SHA256 over the sorted `<path>:<sha256>\\n` lines.\n const actualComposite = compositeSha256(manifest.files);\n if (actualComposite !== manifest.sha256) {\n throw new Error(`composite hash mismatch: expected ${manifest.sha256}, got ${actualComposite}`);\n }\n\n // 6. [M1] Write all verified files. A failed install must leave NO partial\n // directory: any prior `installPath` is removed first (clean overwrite), and\n // a mid-loop write failure removes the partially-written tree before\n // rethrowing.\n await rm(installPath, { recursive: true, force: true });\n try {\n for (const f of manifest.files) {\n const target = join(installPath, f.path);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, bytes[f.path]!);\n if (isScriptBytes(bytes[f.path]!)) await chmod(target, EXECUTABLE_MODE);\n }\n } catch (e) {\n await rm(installPath, { recursive: true, force: true }).catch(() => {});\n throw e;\n }\n\n return { installPath };\n}\n\n/**\n * Flat-layout install — the platform pointer-installer's behavior, made canonical\n * in install-core. Validates every path, fetches with the FULL repo paths, per-file\n * sha256-verifies, then strips the longest-common-dir prefix and writes each file\n * as `join(targetDir, path.slice(assetRoot.length + 1))` — immediate children of\n * `targetDir`. No ref parse, no composite check.\n */\nasync function installFlat(\n manifest: InstallManifest,\n targetDir: string,\n fetcher: AssetFetcher,\n): Promise<InstallResult> {\n const target = resolve(targetDir);\n\n // Gate every path before any fetch — the attacker controls the whole manifest.\n for (const f of manifest.files) {\n assertSafeManifestPath(target, f.path);\n }\n\n // Fetch keys off the FULL repo path (matches the upstream tree).\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // Strip the asset-root dir prefix from the WRITE path only — the fetch above\n // still keyed off the full repo path. Stripping removes leading whole segments\n // (never the basename), so a non-empty remainder always survives.\n const assetRoot = longestCommonDirPrefix(paths);\n\n for (const f of manifest.files) {\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n const relPath = assetRoot ? f.path.slice(assetRoot.length + 1) : f.path;\n // Re-guard the post-strip destination — it is what we actually write.\n assertSafeManifestPath(target, relPath);\n const dest = join(target, relPath);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, buf);\n if (isScriptBytes(buf)) await chmod(dest, EXECUTABLE_MODE);\n }\n\n return { installPath: target };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../library/src/install/install-from-manifest.ts"],"names":[],"mappings":"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","file":"chunk-CVUMZTNO.js","sourcesContent":["/**\n * Pointer-only install path.\n *\n * Given an {@link InstallManifest} (the Pointer Triple the Catalog hands\n * clients), this:\n *\n * 1. fetches the asset bytes directly from the upstream repo at the pinned\n * commit (via an injectable fetcher, default {@link fetchAssetFilesFromGitHub});\n * 2. verifies EVERY per-file SHA256 against `manifest.files[].sha256`;\n * 3. verifies the composite SHA256 rollup over the sorted\n * `<path>:<sha256>\\n` lines against `manifest.sha256`;\n * 4. writes the verified bytes under `<libraryRoot>/@<publisher>/<name>/<version>`.\n *\n * Any hash mismatch is a hard failure — bytes are not written if per-file\n * verification fails, and the composite check is the second gate.\n *\n * @docLink packages/library/concepts#install\n */\n\nimport { createHash } from \"node:crypto\";\nimport { chmodSync, closeSync, fstatSync, openSync, readSync } from \"node:fs\";\nimport { chmod, mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve, sep } from \"node:path\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\n// Narrow module, not the `core` barrel: the barrel's chunks carry `import.meta`,\n// which breaks consumers that transpile this entry to CommonJS.\nimport { parseAssetRef } from \"../../../core/src/models.js\";\nimport { compositeSha256 } from \"../../../core/src/publish-manifest.js\";\n\n/**\n * Validate a single manifest-supplied file path against path traversal.\n *\n * `manifest.files[].path` comes off the network — the attacker controls the\n * entire manifest (and therefore every hash in it), so hash verification can\n * NEVER mitigate a malicious *destination*. A path like\n * `../../../../home/user/.bashrc` or an absolute path would escape\n * `installPath` and yield an arbitrary file write. Every path is checked\n * BEFORE any fetch or write happens; the first bad path aborts the entire\n * install with a hard throw.\n *\n * A path is rejected if ANY of:\n * - it is empty;\n * - it is absolute (`path.isAbsolute`) or has a leading slash;\n * - it contains a `..` segment;\n * - `path.resolve(installPath, p)` is not `installPath` itself and does not\n * start with `installPath + path.sep` (escapes the install dir).\n *\n * @throws An error matching `/unsafe path in manifest/` on the first bad path.\n */\nexport function assertSafeManifestPath(installPath: string, p: string): void {\n const bad = (): never => {\n throw new Error(`unsafe path in manifest: ${p}`);\n };\n if (!p || p.length === 0) bad();\n if (isAbsolute(p) || p.startsWith(\"/\") || p.startsWith(\"\\\\\")) bad();\n const segments = p.split(/[/\\\\]/);\n if (segments.some((s) => s === \"..\")) bad();\n const resolved = resolve(installPath, p);\n if (resolved !== installPath && !resolved.startsWith(installPath + sep)) bad();\n}\n\n/**\n * Validate one component (publisher / name / version) of the attacker-controlled\n * `manifest.ref`.\n *\n * `installPath` is built by joining these components onto `libraryRoot`. A\n * component containing a path separator or a `..` / leading-dot segment would\n * let `installPath` itself escape `libraryRoot` — yielding an arbitrary file\n * write AND, via the pre-write `rm(installPath, { recursive })`, an arbitrary\n * recursive delete. The per-file `assertSafeManifestPath` guard cannot catch\n * this: it only validates each `f.path` *relative to* `installPath`, never\n * `installPath` itself. Components must be plain identifier-like strings.\n *\n * @throws An error matching `/unsafe ref/` on a bad component.\n */\nfunction assertSafeRefComponent(kind: string, value: string): void {\n // Reject empty, leading-dot (covers `.` and `..`), path separators, and\n // ASCII control characters (NUL et al.) — fails a malformed segment fast\n // with a domain-specific error rather than a raw EINVAL deeper in.\n const hasControlChar = [...value].some((c) => c.charCodeAt(0) < 0x20);\n if (!value || value.startsWith(\".\") || /[/\\\\]/.test(value) || hasControlChar) {\n throw new Error(`unsafe ref ${kind} component in manifest: '${value}'`);\n }\n}\n\n/**\n * Longest common **directory** prefix across manifest paths, compared by whole\n * slash-delimited segments (never raw-string — so `app/` and `app-data/` never\n * collide). Each path's basename is excluded, so the result is always a\n * directory prefix and every path keeps a non-empty remainder after stripping.\n *\n * Used by flat mode to reproduce the platform pointer-installer's asset-rooting:\n * the store persists repo-root-relative paths (e.g. `skaile-platform/mcpo/xls/MCP.md`)\n * but the runner scans `.skaile/assets/<kind>/<name>/` for immediate-child files,\n * so this prefix is stripped from the WRITE path while the fetch keeps the full\n * repo path. Returns `''` when there is no common directory (a no-op strip).\n */\nexport function longestCommonDirPrefix(paths: readonly string[]): string {\n if (paths.length === 0) return \"\";\n const dirSegments = paths.map((p) => p.split(\"/\").slice(0, -1));\n let common = dirSegments[0]!;\n for (let i = 1; i < dirSegments.length && common.length > 0; i++) {\n const segs = dirSegments[i]!;\n let n = 0;\n while (n < common.length && n < segs.length && common[n] === segs[n]) n++;\n common = common.slice(0, n);\n }\n return common.join(\"/\");\n}\n\n/**\n * Whether `bytes` start a script (`#!`). A pointer manifest and GitHub's raw host carry no file\n * modes, while the library or clone the same asset comes from keeps its script executable, so a\n * shebang is what marks a file executable here (p1657).\n */\nexport function isScriptBytes(bytes: Uint8Array): boolean {\n return bytes.length >= 2 && bytes[0] === 0x23 && bytes[1] === 0x21;\n}\n\n/** The mode of an executable file written from store bytes. */\nconst EXECUTABLE_MODE = 0o755;\n\n/**\n * Make every file of `relPaths` under `root` that starts with `#!` executable. For bytes an\n * earlier install already wrote (a project store cache from before exec bits were kept), so a\n * restore from them deploys the same modes as a fresh fetch. A missing or unreadable file is\n * skipped.\n */\nexport function restoreScriptModes(root: string, relPaths: readonly string[]): void {\n for (const rel of relPaths) {\n let fd: number | undefined;\n try {\n fd = openSync(join(root, rel), \"r\");\n if ((fstatSync(fd).mode & 0o111) !== 0) continue;\n const head = Buffer.alloc(2);\n if (readSync(fd, head, 0, 2, 0) === 2 && isScriptBytes(head)) {\n chmodSync(join(root, rel), EXECUTABLE_MODE);\n }\n } catch {\n // Not readable or not a file: nothing to fix.\n } finally {\n if (fd !== undefined) closeSync(fd);\n }\n }\n}\n\n/**\n * Fetcher signature — fetches `{ path → Buffer }` for the requested paths at\n * a pinned upstream commit. {@link fetchAssetFilesFromGitHub} is the default\n * production implementation; tests inject a mock.\n */\nexport type AssetFetcher = (opts: {\n url: string;\n commitSha: string;\n paths: string[];\n}) => Promise<Record<string, Buffer>>;\n\n/**\n * Options for {@link installFromManifest}.\n */\nexport interface InstallOpts {\n /** The pointer-only install manifest from the Catalog. */\n manifest: InstallManifest;\n /** Filesystem root the asset is installed under (ref-derived mode). */\n libraryRoot: string;\n /**\n * Pluggable fetcher so tests can inject mock data. Defaults to\n * {@link fetchAssetFilesFromGitHub} in production.\n */\n fetcher?: AssetFetcher;\n /**\n * Flat-layout mode. When set, install-core reproduces the platform\n * pointer-installer's behavior: it ignores `libraryRoot`/ref-derivation, does\n * NOT parse `manifest.ref` and does NOT verify the composite sha256, strips\n * the longest-common-dir prefix from each path, per-file sha256-verifies, and\n * writes the stripped paths as immediate children of `targetDir` (what the\n * runner's `.skaile/assets/<kind>/<name>/` scan requires). `installPath` is\n * `targetDir`. Absent → unchanged ref-derived `@<pub>/name/version/<path>`\n * layout with composite verify.\n */\n targetDir?: string;\n}\n\n/**\n * Result of a successful {@link installFromManifest} call.\n */\nexport interface InstallResult {\n /** Absolute path the asset files were written to. */\n installPath: string;\n}\n\n/**\n * Fetch, verify, and write an asset's files per its {@link InstallManifest}.\n *\n * @throws An error matching `/hash mismatch/i` if any per-file SHA256 differs.\n * @throws An error matching `/composite hash mismatch/i` if the rollup differs.\n * @throws An error if the ref is malformed or the fetcher omits a file.\n */\nexport async function installFromManifest(opts: InstallOpts): Promise<InstallResult> {\n const { manifest, libraryRoot } = opts;\n const fetcher =\n opts.fetcher ?? (await import(\"./source-fetch-github.js\")).fetchAssetFilesFromGitHub;\n\n // Flat mode: reproduce the platform pointer-installer's asset-rooted layout.\n // No ref parse, no composite verify — the platform store may not satisfy a\n // ref-grammar or composite, and the runner only needs immediate-child files.\n if (opts.targetDir !== undefined) {\n return installFlat(manifest, opts.targetDir, fetcher);\n }\n\n // 1. Parse ref into install path: `skill:@x/git#1.0.0` → `<root>/@x/git/1.0.0`.\n // Done first so the C1 path-traversal guard can resolve against installPath\n // BEFORE any network fetch happens. The ref is attacker-controlled, so each\n // segment is further validated as a safe path component (H1) after parsing.\n // `parseAssetRef` is the single canonical grammar (`kind:@publisher/name#version`);\n // the legacy trailing-`@version` shape was removed in core and is rejected here.\n let parsed: ReturnType<typeof parseAssetRef>;\n try {\n parsed = parseAssetRef(manifest.ref);\n } catch (e) {\n throw new Error(`invalid ref: ${manifest.ref}: ${e instanceof Error ? e.message : String(e)}`);\n }\n const publisher = parsed.publisher;\n const name = parsed.name;\n const version = parsed.pin;\n if (!publisher) throw new Error(`invalid ref: ${manifest.ref} (missing publisher)`);\n if (!version) throw new Error(`invalid ref: ${manifest.ref} (missing version pin)`);\n assertSafeRefComponent(\"publisher\", publisher);\n assertSafeRefComponent(\"name\", name);\n assertSafeRefComponent(\"version\", version);\n const root = resolve(libraryRoot);\n const installPath = resolve(join(root, `@${publisher}`, name, version));\n // Defense in depth: even with the segment guards above, assert the built\n // installPath stays strictly inside libraryRoot before any write or `rm`.\n if (installPath !== root && !installPath.startsWith(root + sep)) {\n throw new Error(`unsafe install path: ref '${manifest.ref}' resolves outside the library root`);\n }\n\n // 2. [C1] Validate EVERY manifest path against traversal BEFORE fetching.\n // The attacker controls the manifest (and thus all hashes) — hashes verify\n // content, never destination. Reject the whole install on the first bad path.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n }\n\n // 3. Fetch all files at the pinned commit.\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // 4. Verify per-file SHA256 — hard fail before writing anything. The path\n // key used to read from the fetcher result is re-guarded as defense in depth.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n }\n\n // 5. Verify composite SHA256 over the sorted `<path>:<sha256>\\n` lines.\n const actualComposite = compositeSha256(manifest.files);\n if (actualComposite !== manifest.sha256) {\n throw new Error(`composite hash mismatch: expected ${manifest.sha256}, got ${actualComposite}`);\n }\n\n // 6. [M1] Write all verified files. A failed install must leave NO partial\n // directory: any prior `installPath` is removed first (clean overwrite), and\n // a mid-loop write failure removes the partially-written tree before\n // rethrowing.\n await rm(installPath, { recursive: true, force: true });\n try {\n for (const f of manifest.files) {\n const target = join(installPath, f.path);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, bytes[f.path]!);\n if (isScriptBytes(bytes[f.path]!)) await chmod(target, EXECUTABLE_MODE);\n }\n } catch (e) {\n await rm(installPath, { recursive: true, force: true }).catch(() => {});\n throw e;\n }\n\n return { installPath };\n}\n\n/**\n * Flat-layout install — the platform pointer-installer's behavior, made canonical\n * in install-core. Validates every path, fetches with the FULL repo paths, per-file\n * sha256-verifies, then strips the longest-common-dir prefix and writes each file\n * as `join(targetDir, path.slice(assetRoot.length + 1))` — immediate children of\n * `targetDir`. No ref parse, no composite check.\n */\nasync function installFlat(\n manifest: InstallManifest,\n targetDir: string,\n fetcher: AssetFetcher,\n): Promise<InstallResult> {\n const target = resolve(targetDir);\n\n // Gate every path before any fetch — the attacker controls the whole manifest.\n for (const f of manifest.files) {\n assertSafeManifestPath(target, f.path);\n }\n\n // Fetch keys off the FULL repo path (matches the upstream tree).\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // Strip the asset-root dir prefix from the WRITE path only — the fetch above\n // still keyed off the full repo path. Stripping removes leading whole segments\n // (never the basename), so a non-empty remainder always survives.\n const assetRoot = longestCommonDirPrefix(paths);\n\n for (const f of manifest.files) {\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n const relPath = assetRoot ? f.path.slice(assetRoot.length + 1) : f.path;\n // Re-guard the post-strip destination — it is what we actually write.\n assertSafeManifestPath(target, relPath);\n const dest = join(target, relPath);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, buf);\n if (isScriptBytes(buf)) await chmod(dest, EXECUTABLE_MODE);\n }\n\n return { installPath: target };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { flowKindProvider } from './chunk-
|
|
2
|
-
import { knowledgeKindProvider } from './chunk-
|
|
3
|
-
import { createDefaultKindRegistry } from './chunk-
|
|
1
|
+
import { flowKindProvider } from './chunk-WDG5IVEA.js';
|
|
2
|
+
import { knowledgeKindProvider } from './chunk-FXBKBOI5.js';
|
|
3
|
+
import { createDefaultKindRegistry } from './chunk-RZ5R6GDJ.js';
|
|
4
4
|
|
|
5
5
|
// cli/src/open-registry.ts
|
|
6
6
|
var registry;
|
|
@@ -13,5 +13,5 @@ function getKnownKinds() {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export { getKindRegistry, getKnownKinds };
|
|
16
|
-
//# sourceMappingURL=chunk-
|
|
17
|
-
//# sourceMappingURL=chunk-
|
|
16
|
+
//# sourceMappingURL=chunk-DOMRBOJZ.js.map
|
|
17
|
+
//# sourceMappingURL=chunk-DOMRBOJZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../cli/src/open-registry.ts"],"names":[],"mappings":";;;;;AAgBA,IAAI,QAAA;AAQG,SAAS,eAAA,GAAqC;AACnD,EAAA,QAAA,KAAa,yBAAA,CAA0B,CAAC,gBAAA,EAAkB,qBAAqB,CAAC,CAAA;AAChF,EAAA,OAAO,QAAA;AACT;AAGO,SAAS,aAAA,GAAqC;AACnD,EAAA,OAAO,IAAI,GAAA,CAAI,eAAA,EAAgB,CAAE,aAAa,CAAA;AAChD","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../cli/src/open-registry.ts"],"names":[],"mappings":";;;;;AAgBA,IAAI,QAAA;AAQG,SAAS,eAAA,GAAqC;AACnD,EAAA,QAAA,KAAa,yBAAA,CAA0B,CAAC,gBAAA,EAAkB,qBAAqB,CAAC,CAAA;AAChF,EAAA,OAAO,QAAA;AACT;AAGO,SAAS,aAAA,GAAqC;AACnD,EAAA,OAAO,IAAI,GAAA,CAAI,eAAA,EAAgB,CAAE,aAAa,CAAA;AAChD","file":"chunk-DOMRBOJZ.js","sourcesContent":["/**\n * open-registry.ts — the CLI's one AssetKindRegistry.\n *\n * The provider registry is the only authority on asset kinds. The CLI builds it\n * once per process with all built-in providers (from @skaile/workspaces/discovery)\n * plus the extension kinds (flow from\n * @skaile/workspaces/factory-assets/connectors/flow/engine, knowledge from\n * @skaile/workspaces/library) and hands the same instance to every consumer\n * (catalog sources, the installer, validation, composition).\n */\n\nimport type { AssetKindRegistry } from \"@skaile/workspaces/discovery\";\nimport { createDefaultKindRegistry } from \"@skaile/workspaces/discovery\";\nimport { flowKindProvider } from \"@skaile/workspaces/factory-assets/connectors/flow/engine\";\nimport { knowledgeKindProvider } from \"@skaile/workspaces/library\";\n\nlet registry: AssetKindRegistry | undefined;\n\n/**\n * The process-wide, fully-configured AssetKindRegistry.\n *\n * Registers every built-in kind plus flow and knowledge. Built lazily on first\n * call; every later call returns the same instance.\n */\nexport function getKindRegistry(): AssetKindRegistry {\n registry ??= createDefaultKindRegistry([flowKindProvider, knowledgeKindProvider]);\n return registry;\n}\n\n/** Registered kind names as a set — the `knownKinds` argument of the manifest scanners. */\nexport function getKnownKinds(): ReadonlySet<string> {\n return new Set(getKindRegistry().getAllKinds());\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { findAiAssetsRoot } from './chunk-
|
|
1
|
+
import { findAiAssetsRoot } from './chunk-V2VDTQ7A.js';
|
|
2
2
|
import { okJson, err, ok } from './chunk-3MWQKQUB.js';
|
|
3
|
-
import { parseSkillRequirements, validateRequirements, buildRequiresPreamble, parseSkillFrontmatter } from './chunk-
|
|
3
|
+
import { parseSkillRequirements, validateRequirements, buildRequiresPreamble, parseSkillFrontmatter } from './chunk-KOI7QFDH.js';
|
|
4
4
|
import { findKindDirs } from './chunk-MWXYN6NY.js';
|
|
5
5
|
import fs from 'fs/promises';
|
|
6
6
|
import path from 'path';
|
|
@@ -136,5 +136,5 @@ async function skillGetPreamble(projectDir, skillId) {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
export { skillCheckRequirements, skillGetPreamble, skillList, skillSearch, skillShow };
|
|
139
|
-
//# sourceMappingURL=chunk-
|
|
140
|
-
//# sourceMappingURL=chunk-
|
|
139
|
+
//# sourceMappingURL=chunk-EB2LKPI6.js.map
|
|
140
|
+
//# sourceMappingURL=chunk-EB2LKPI6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../workspace-plugin/src/tools/skills.ts"],"names":[],"mappings":";;;;;;;AA0BA,eAAe,cAAA,CAAe,KAAa,GAAA,EAAkC;AAC3E,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,MAAM,EAAA,CAAG,OAAA,CAAQ,KAAK,EAAE,aAAA,EAAe,MAAM,CAAA;AAAA,EACzD,CAAA,CAAA,MAAQ;AACN,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,MAAA,EAAO,IAAK,CAAA,CAAE,IAAA,KAAS,UAAU,CAAA;AAC1E,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,UAAU,CAAA;AAC7C,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,EAAA,CAAG,QAAA,CAAS,aAAa,OAAO,CAAA;AACtD,MAAA,MAAM,EAAA,GAAK,sBAAsB,OAAO,CAAA;AACxC,MAAA,MAAM,IAAA,GAAO,OAAO,EAAA,CAAG,IAAA,KAAS,WAAW,EAAA,CAAG,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA;AACtE,MAAA,MAAM,cAAc,OAAO,EAAA,CAAG,WAAA,KAAgB,QAAA,GAAW,GAAG,WAAA,GAAc,EAAA;AAC1E,MAAA,MAAM,SAAS,OAAO,EAAA,CAAG,MAAA,KAAW,QAAA,GAAW,GAAG,MAAA,GAAS,KAAA,CAAA;AAC3D,MAAA,MAAM,UAAU,OAAO,EAAA,CAAG,OAAA,KAAY,QAAA,GAAW,GAAG,OAAA,GAAU,KAAA,CAAA;AAC9D,MAAA,MAAM,WAAW,KAAA,CAAM,OAAA,CAAQ,GAAG,QAAQ,CAAA,GAAK,GAAG,QAAA,GAAwB,KAAA,CAAA;AAC1E,MAAA,GAAA,CAAI,IAAA,CAAK;AAAA,QACP,EAAA,EAAI,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA;AAAA,QACrB,IAAA;AAAA,QACA,WAAA;AAAA,QACA,MAAA;AAAA,QACA,OAAA;AAAA,QACA,QAAA;AAAA,QACA,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,IAAA,IAAI,KAAA,CAAM,aAAY,EAAG;AACvB,MAAA,MAAM,eAAe,IAAA,CAAK,IAAA,CAAK,KAAK,KAAA,CAAM,IAAI,GAAG,GAAG,CAAA;AAAA,IACtD;AAAA,EACF;AACF;AAEA,eAAe,WAAW,YAAA,EAA6C;AACrE,EAAA,MAAM,MAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,SAAA,IAAa,YAAA,CAAa,YAAA,EAAc,QAAQ,CAAA,EAAG;AAC5D,IAAA,MAAM,cAAA,CAAe,WAAW,GAAG,CAAA;AAAA,EACrC;AAEA,EAAA,OAAO,CAAC,GAAG,IAAI,GAAA,CAAI,GAAA,CAAI,IAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,MAAM,CAAC,CAAC,CAAC,CAAA,CAAE,QAAQ,CAAA;AAC1D;AAeA,eAAsB,UAAU,UAAA,EAAyC;AACvE,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAe,MAAM,gBAAA,CAAiB,UAAU,CAAA;AACtD,IAAA,IAAI,CAAC,YAAA,EAAc,OAAO,MAAA,CAAO,EAAE,CAAA;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,YAAY,CAAA;AAC5C,IAAA,OAAO,MAAA;AAAA,MACL,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QACjB,IAAI,CAAA,CAAE,EAAA;AAAA,QACN,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,aAAa,CAAA,CAAE,WAAA;AAAA,QACf,QAAQ,CAAA,CAAE,MAAA;AAAA,QACV,SAAS,CAAA,CAAE,OAAA;AAAA,QACX,UAAU,CAAA,CAAE;AAAA,OACd,CAAE;AAAA,KACJ;AAAA,EACF,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAUA,eAAsB,SAAA,CAAU,YAAoB,OAAA,EAAsC;AACxF,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAe,MAAM,gBAAA,CAAiB,UAAU,CAAA;AACtD,IAAA,IAAI,CAAC,YAAA,EAAc,OAAO,GAAA,CAAI,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AAC3D,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,YAAY,CAAA;AAC5C,IAAA,MAAM,QAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,OAAO,CAAA;AACjD,IAAA,IAAI,CAAC,KAAA,EAAO,OAAO,GAAA,CAAI,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AACpD,IAAA,MAAM,UAAU,MAAM,EAAA,CAAG,QAAA,CAAS,KAAA,CAAM,MAAM,OAAO,CAAA;AACrD,IAAA,OAAO,GAAG,OAAO,CAAA;AAAA,EACnB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAaA,eAAsB,WAAA,CAAY,YAAoB,KAAA,EAAoC;AACxF,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAe,MAAM,gBAAA,CAAiB,UAAU,CAAA;AACtD,IAAA,IAAI,CAAC,YAAA,EAAc,OAAO,MAAA,CAAO,EAAE,CAAA;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,YAAY,CAAA;AAC5C,IAAA,MAAM,CAAA,GAAI,MAAM,WAAA,EAAY;AAC5B,IAAA,MAAM,UAAU,MAAA,CAAO,MAAA;AAAA,MACrB,CAAC,CAAA,KACC,CAAA,CAAE,IAAA,CAAK,aAAY,CAAE,QAAA,CAAS,CAAC,CAAA,IAC/B,EAAE,WAAA,CAAY,WAAA,EAAY,CAAE,QAAA,CAAS,CAAC,CAAA,IACtC,CAAA,CAAE,EAAA,CAAG,WAAA,GAAc,QAAA,CAAS,CAAC,CAAA,IAAA,CAC5B,CAAA,CAAE,YAAY,EAAC,EAAG,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,WAAA,EAAY,CAAE,QAAA,CAAS,CAAC,CAAC;AAAA,KAC9D;AACA,IAAA,OAAO,MAAA;AAAA,MACL,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QAClB,IAAI,CAAA,CAAE,EAAA;AAAA,QACN,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,aAAa,CAAA,CAAE,WAAA;AAAA,QACf,QAAQ,CAAA,CAAE,MAAA;AAAA,QACV,SAAS,CAAA,CAAE,OAAA;AAAA,QACX,UAAU,CAAA,CAAE;AAAA,OACd,CAAE;AAAA,KACJ;AAAA,EACF,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAgBA,eAAsB,sBAAA,CACpB,UAAA,EACA,OAAA,EACA,SAAA,EACqB;AACrB,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAe,MAAM,gBAAA,CAAiB,UAAU,CAAA;AACtD,IAAA,IAAI,CAAC,YAAA,EAAc,OAAO,GAAA,CAAI,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AAC3D,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,YAAY,CAAA;AAC5C,IAAA,MAAM,QAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,OAAO,CAAA;AACjD,IAAA,IAAI,CAAC,KAAA,EAAO,OAAO,GAAA,CAAI,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AACpD,IAAA,MAAM,UAAU,MAAM,EAAA,CAAG,QAAA,CAAS,KAAA,CAAM,MAAM,OAAO,CAAA;AAErD,IAAA,MAAM,YAAA,GAAe,uBAAuB,OAAO,CAAA;AACnD,IAAA,MAAM,MAAA,GAAS,MAAM,oBAAA,CAAqB,OAAA,EAAS,cAAc,SAAS,CAAA;AAC1E,IAAA,OAAO,OAAO,MAAM,CAAA;AAAA,EACtB,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF;AAcA,eAAsB,gBAAA,CAAiB,YAAoB,OAAA,EAAsC;AAC/F,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAe,MAAM,gBAAA,CAAiB,UAAU,CAAA;AACtD,IAAA,IAAI,CAAC,YAAA,EAAc,OAAO,GAAA,CAAI,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AAC3D,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,YAAY,CAAA;AAC5C,IAAA,MAAM,QAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,OAAO,CAAA;AACjD,IAAA,IAAI,CAAC,KAAA,EAAO,OAAO,GAAA,CAAI,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AACpD,IAAA,MAAM,UAAU,MAAM,EAAA,CAAG,QAAA,CAAS,KAAA,CAAM,MAAM,OAAO,CAAA;AAErD,IAAA,MAAM,YAAA,GAAe,uBAAuB,OAAO,CAAA;AACnD,IAAA,MAAM,QAAA,GAAW,qBAAA,CAAsB,YAAA,EAAc,OAAO,CAAA;AAC5D,IAAA,OAAO,EAAA,CAAG,YAAY,4BAA4B,CAAA;AAAA,EACpD,SAAS,CAAA,EAAY;AACnB,IAAA,OAAO,IAAI,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACvD;AACF","file":"chunk-GTAHU4N4.js","sourcesContent":["// src/tools/skills.ts\n\nimport type { Dirent } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { findKindDirs } from \"@skaile/workspaces/core/discovery\";\nimport {\n buildRequiresPreamble,\n parseSkillFrontmatter,\n parseSkillRequirements,\n validateRequirements,\n} from \"@skaile/workspaces/resolver\";\nimport type { ToolResult } from \"../types.js\";\nimport { err, ok, okJson } from \"../types.js\";\nimport { findAiAssetsRoot } from \"../utils/ai-assets.js\";\n\ninterface SkillEntry {\n id: string;\n name: string;\n description: string;\n source?: string;\n version?: string;\n keywords?: string[];\n path: string;\n}\n\nasync function walkForSkillMd(dir: string, acc: SkillEntry[]): Promise<void> {\n let entries: Dirent<string>[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n // Check if this directory contains a SKILL.md\n const hasSkillMd = entries.some((e) => e.isFile() && e.name === \"SKILL.md\");\n if (hasSkillMd) {\n const skillMdPath = path.join(dir, \"SKILL.md\");\n try {\n const content = await fs.readFile(skillMdPath, \"utf-8\");\n const fm = parseSkillFrontmatter(content);\n const name = typeof fm.name === \"string\" ? fm.name : path.basename(dir);\n const description = typeof fm.description === \"string\" ? fm.description : \"\";\n const source = typeof fm.source === \"string\" ? fm.source : undefined;\n const version = typeof fm.version === \"string\" ? fm.version : undefined;\n const keywords = Array.isArray(fm.keywords) ? (fm.keywords as string[]) : undefined;\n acc.push({\n id: path.basename(dir),\n name,\n description,\n source,\n version,\n keywords,\n path: skillMdPath,\n });\n } catch {\n // skip unreadable files\n }\n return; // don't recurse inside a skill directory\n }\n\n // Recurse into subdirectories\n for (const entry of entries) {\n if (entry.isDirectory()) {\n await walkForSkillMd(path.join(dir, entry.name), acc);\n }\n }\n}\n\nasync function scanSkills(aiAssetsRoot: string): Promise<SkillEntry[]> {\n const acc: SkillEntry[] = [];\n for (const skillsDir of findKindDirs(aiAssetsRoot, \"skills\")) {\n await walkForSkillMd(skillsDir, acc);\n }\n // A `skills/` dir nested inside another is walked twice; keep each SKILL.md once.\n return [...new Map(acc.map((s) => [s.path, s])).values()];\n}\n\n// ── Exported tool functions ────────────────────────────────────────────────────\n\n/**\n * List all skills in the `ai-assets` catalog.\n *\n * Walks every `skills/` directory at any depth under the `ai-assets` root\n * looking for `SKILL.md` files. Returns a JSON array of skill summaries\n * `{ id, name, description, source, version, keywords }`.\n *\n * @param projectDir - Absolute path to the skaile project root.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillList(projectDir: string): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return okJson([]);\n const skills = await scanSkills(aiAssetsRoot);\n return okJson(\n skills.map((s) => ({\n id: s.id,\n name: s.name,\n description: s.description,\n source: s.source,\n version: s.version,\n keywords: s.keywords,\n })),\n );\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Show the full `SKILL.md` content for a skill.\n *\n * @param projectDir - Absolute path to the skaile project root.\n * @param skillId - Skill ID (directory name) as returned by {@link skillList}.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillShow(projectDir: string, skillId: string): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return err(`Skill not found: ${skillId}`);\n const skills = await scanSkills(aiAssetsRoot);\n const skill = skills.find((s) => s.id === skillId);\n if (!skill) return err(`Skill not found: ${skillId}`);\n const content = await fs.readFile(skill.path, \"utf-8\");\n return ok(content);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Search skills by name, description, ID, or keywords.\n *\n * Case-insensitive substring match against all text fields in every skill\n * entry. Returns the same summary shape as {@link skillList}.\n *\n * @param projectDir - Absolute path to the skaile project root.\n * @param query - Search string.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillSearch(projectDir: string, query: string): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return okJson([]);\n const skills = await scanSkills(aiAssetsRoot);\n const q = query.toLowerCase();\n const matched = skills.filter(\n (s) =>\n s.name.toLowerCase().includes(q) ||\n s.description.toLowerCase().includes(q) ||\n s.id.toLowerCase().includes(q) ||\n (s.keywords ?? []).some((k) => k.toLowerCase().includes(q)),\n );\n return okJson(\n matched.map((s) => ({\n id: s.id,\n name: s.name,\n description: s.description,\n source: s.source,\n version: s.version,\n keywords: s.keywords,\n })),\n );\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Validate that all prerequisites declared in a skill's `SKILL.md` are\n * satisfied in `targetDir`.\n *\n * Uses `@skaile/workspaces/resolver` to parse the `REQUIRES` / `READS` / `WRITES`\n * DSL and run the requirement checks against the filesystem. Returns a\n * validation report as JSON.\n *\n * @param projectDir - Absolute path to the skaile project root (for skill lookup).\n * @param skillId - Skill ID as returned by {@link skillList}.\n * @param targetDir - Directory to validate against (typically the user's project).\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillCheckRequirements(\n projectDir: string,\n skillId: string,\n targetDir: string,\n): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return err(`Skill not found: ${skillId}`);\n const skills = await scanSkills(aiAssetsRoot);\n const skill = skills.find((s) => s.id === skillId);\n if (!skill) return err(`Skill not found: ${skillId}`);\n const content = await fs.readFile(skill.path, \"utf-8\");\n\n const requirements = parseSkillRequirements(content);\n const report = await validateRequirements(skillId, requirements, targetDir);\n return okJson(report);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Get the formatted `REQUIRES`/`INPUT`/`READS`/`WRITES` DSL preamble for a skill.\n *\n * Uses `@skaile/workspaces/resolver` to build the requirements preamble that can be\n * prepended to the skill prompt for injection into the agent's context.\n * Returns `\"(no requirements declared)\"` when the skill has no requirements.\n *\n * @param projectDir - Absolute path to the skaile project root.\n * @param skillId - Skill ID as returned by {@link skillList}.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillGetPreamble(projectDir: string, skillId: string): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return err(`Skill not found: ${skillId}`);\n const skills = await scanSkills(aiAssetsRoot);\n const skill = skills.find((s) => s.id === skillId);\n if (!skill) return err(`Skill not found: ${skillId}`);\n const content = await fs.readFile(skill.path, \"utf-8\");\n\n const requirements = parseSkillRequirements(content);\n const preamble = buildRequiresPreamble(requirements, skillId);\n return ok(preamble || \"(no requirements declared)\");\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../workspace-plugin/src/tools/skills.ts"],"names":[],"mappings":"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","file":"chunk-EB2LKPI6.js","sourcesContent":["// src/tools/skills.ts\n\nimport type { Dirent } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { findKindDirs } from \"@skaile/workspaces/core/discovery\";\nimport {\n buildRequiresPreamble,\n parseSkillFrontmatter,\n parseSkillRequirements,\n validateRequirements,\n} from \"@skaile/workspaces/resolver\";\nimport type { ToolResult } from \"../types.js\";\nimport { err, ok, okJson } from \"../types.js\";\nimport { findAiAssetsRoot } from \"../utils/ai-assets.js\";\n\ninterface SkillEntry {\n id: string;\n name: string;\n description: string;\n source?: string;\n version?: string;\n keywords?: string[];\n path: string;\n}\n\nasync function walkForSkillMd(dir: string, acc: SkillEntry[]): Promise<void> {\n let entries: Dirent<string>[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n // Check if this directory contains a SKILL.md\n const hasSkillMd = entries.some((e) => e.isFile() && e.name === \"SKILL.md\");\n if (hasSkillMd) {\n const skillMdPath = path.join(dir, \"SKILL.md\");\n try {\n const content = await fs.readFile(skillMdPath, \"utf-8\");\n const fm = parseSkillFrontmatter(content);\n const name = typeof fm.name === \"string\" ? fm.name : path.basename(dir);\n const description = typeof fm.description === \"string\" ? fm.description : \"\";\n const source = typeof fm.source === \"string\" ? fm.source : undefined;\n const version = typeof fm.version === \"string\" ? fm.version : undefined;\n const keywords = Array.isArray(fm.keywords) ? (fm.keywords as string[]) : undefined;\n acc.push({\n id: path.basename(dir),\n name,\n description,\n source,\n version,\n keywords,\n path: skillMdPath,\n });\n } catch {\n // skip unreadable files\n }\n return; // don't recurse inside a skill directory\n }\n\n // Recurse into subdirectories\n for (const entry of entries) {\n if (entry.isDirectory()) {\n await walkForSkillMd(path.join(dir, entry.name), acc);\n }\n }\n}\n\nasync function scanSkills(aiAssetsRoot: string): Promise<SkillEntry[]> {\n const acc: SkillEntry[] = [];\n for (const skillsDir of findKindDirs(aiAssetsRoot, \"skills\")) {\n await walkForSkillMd(skillsDir, acc);\n }\n // A `skills/` dir nested inside another is walked twice; keep each SKILL.md once.\n return [...new Map(acc.map((s) => [s.path, s])).values()];\n}\n\n// ── Exported tool functions ────────────────────────────────────────────────────\n\n/**\n * List all skills in the `ai-assets` catalog.\n *\n * Walks every `skills/` directory at any depth under the `ai-assets` root\n * looking for `SKILL.md` files. Returns a JSON array of skill summaries\n * `{ id, name, description, source, version, keywords }`.\n *\n * @param projectDir - Absolute path to the skaile project root.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillList(projectDir: string): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return okJson([]);\n const skills = await scanSkills(aiAssetsRoot);\n return okJson(\n skills.map((s) => ({\n id: s.id,\n name: s.name,\n description: s.description,\n source: s.source,\n version: s.version,\n keywords: s.keywords,\n })),\n );\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Show the full `SKILL.md` content for a skill.\n *\n * @param projectDir - Absolute path to the skaile project root.\n * @param skillId - Skill ID (directory name) as returned by {@link skillList}.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillShow(projectDir: string, skillId: string): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return err(`Skill not found: ${skillId}`);\n const skills = await scanSkills(aiAssetsRoot);\n const skill = skills.find((s) => s.id === skillId);\n if (!skill) return err(`Skill not found: ${skillId}`);\n const content = await fs.readFile(skill.path, \"utf-8\");\n return ok(content);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Search skills by name, description, ID, or keywords.\n *\n * Case-insensitive substring match against all text fields in every skill\n * entry. Returns the same summary shape as {@link skillList}.\n *\n * @param projectDir - Absolute path to the skaile project root.\n * @param query - Search string.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillSearch(projectDir: string, query: string): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return okJson([]);\n const skills = await scanSkills(aiAssetsRoot);\n const q = query.toLowerCase();\n const matched = skills.filter(\n (s) =>\n s.name.toLowerCase().includes(q) ||\n s.description.toLowerCase().includes(q) ||\n s.id.toLowerCase().includes(q) ||\n (s.keywords ?? []).some((k) => k.toLowerCase().includes(q)),\n );\n return okJson(\n matched.map((s) => ({\n id: s.id,\n name: s.name,\n description: s.description,\n source: s.source,\n version: s.version,\n keywords: s.keywords,\n })),\n );\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Validate that all prerequisites declared in a skill's `SKILL.md` are\n * satisfied in `targetDir`.\n *\n * Uses `@skaile/workspaces/resolver` to parse the `REQUIRES` / `READS` / `WRITES`\n * DSL and run the requirement checks against the filesystem. Returns a\n * validation report as JSON.\n *\n * @param projectDir - Absolute path to the skaile project root (for skill lookup).\n * @param skillId - Skill ID as returned by {@link skillList}.\n * @param targetDir - Directory to validate against (typically the user's project).\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillCheckRequirements(\n projectDir: string,\n skillId: string,\n targetDir: string,\n): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return err(`Skill not found: ${skillId}`);\n const skills = await scanSkills(aiAssetsRoot);\n const skill = skills.find((s) => s.id === skillId);\n if (!skill) return err(`Skill not found: ${skillId}`);\n const content = await fs.readFile(skill.path, \"utf-8\");\n\n const requirements = parseSkillRequirements(content);\n const report = await validateRequirements(skillId, requirements, targetDir);\n return okJson(report);\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n\n/**\n * Get the formatted `REQUIRES`/`INPUT`/`READS`/`WRITES` DSL preamble for a skill.\n *\n * Uses `@skaile/workspaces/resolver` to build the requirements preamble that can be\n * prepended to the skill prompt for injection into the agent's context.\n * Returns `\"(no requirements declared)\"` when the skill has no requirements.\n *\n * @param projectDir - Absolute path to the skaile project root.\n * @param skillId - Skill ID as returned by {@link skillList}.\n *\n * @docLink packages/workspace-plugin/concepts#tool-delivery\n */\nexport async function skillGetPreamble(projectDir: string, skillId: string): Promise<ToolResult> {\n try {\n const aiAssetsRoot = await findAiAssetsRoot(projectDir);\n if (!aiAssetsRoot) return err(`Skill not found: ${skillId}`);\n const skills = await scanSkills(aiAssetsRoot);\n const skill = skills.find((s) => s.id === skillId);\n if (!skill) return err(`Skill not found: ${skillId}`);\n const content = await fs.readFile(skill.path, \"utf-8\");\n\n const requirements = parseSkillRequirements(content);\n const preamble = buildRequiresPreamble(requirements, skillId);\n return ok(preamble || \"(no requirements declared)\");\n } catch (e: unknown) {\n return err(e instanceof Error ? e.message : String(e));\n }\n}\n"]}
|