@skaile/workspaces 5.6.0 → 5.7.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.
Files changed (261) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +4 -2
  3. package/dist/{asset-feeds-4O2JK5S4.js → asset-feeds-K36CR52Q.js} +17 -17
  4. package/dist/{asset-feeds-4O2JK5S4.js.map → asset-feeds-K36CR52Q.js.map} +1 -1
  5. package/dist/asset-manager/catalog-deployer.js +9 -9
  6. package/dist/asset-manager/index.js +14 -14
  7. package/dist/asset-manager/installer.js +10 -10
  8. package/dist/asset-manager/renderers.js +9 -9
  9. package/dist/asset-manager/src/index.d.ts +106 -16
  10. package/dist/asset-manager/src/index.d.ts.map +1 -1
  11. package/dist/asset-manager/src/installer.d.ts +4 -1
  12. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  13. package/dist/bridge/drivers/claude-sdk.js +11 -11
  14. package/dist/bridge/drivers/codex.js +10 -10
  15. package/dist/bridge/drivers/continue.js +12 -12
  16. package/dist/bridge/drivers/echo.js +1 -1
  17. package/dist/bridge/drivers/gemini.js +5 -5
  18. package/dist/bridge/drivers/goose.js +12 -12
  19. package/dist/bridge/drivers/omp.js +2 -2
  20. package/dist/bridge/drivers/opencode.js +12 -12
  21. package/dist/bridge/drivers/qwen.js +5 -5
  22. package/dist/bridge/index.js +12 -12
  23. package/dist/{chunk-VX3INFBA.js → chunk-34C42MJX.js} +3 -3
  24. package/dist/{chunk-VX3INFBA.js.map → chunk-34C42MJX.js.map} +1 -1
  25. package/dist/{chunk-NLXIALVO.js → chunk-53MSCGR2.js} +5 -5
  26. package/dist/{chunk-NLXIALVO.js.map → chunk-53MSCGR2.js.map} +1 -1
  27. package/dist/chunk-6C654TFI.js +84 -0
  28. package/dist/chunk-6C654TFI.js.map +1 -0
  29. package/dist/{chunk-6NPINANG.js → chunk-6UFFKMVC.js} +5 -5
  30. package/dist/{chunk-6NPINANG.js.map → chunk-6UFFKMVC.js.map} +1 -1
  31. package/dist/{chunk-XOGG7VDZ.js → chunk-6VRJH4MR.js} +16 -24
  32. package/dist/chunk-6VRJH4MR.js.map +1 -0
  33. package/dist/{chunk-IPWR33AW.js → chunk-74EEFB52.js} +31 -15
  34. package/dist/chunk-74EEFB52.js.map +1 -0
  35. package/dist/{chunk-OGLDAJFL.js → chunk-7FJQT3GT.js} +4 -4
  36. package/dist/{chunk-OGLDAJFL.js.map → chunk-7FJQT3GT.js.map} +1 -1
  37. package/dist/{chunk-VKSXST23.js → chunk-AVCUPPG6.js} +3 -3
  38. package/dist/{chunk-VKSXST23.js.map → chunk-AVCUPPG6.js.map} +1 -1
  39. package/dist/{chunk-5B5IZVEP.js → chunk-BTK7ECLH.js} +2 -2
  40. package/dist/{chunk-5B5IZVEP.js.map → chunk-BTK7ECLH.js.map} +1 -1
  41. package/dist/{chunk-O5GDKC5I.js → chunk-BWZF2ZIF.js} +3 -3
  42. package/dist/{chunk-O5GDKC5I.js.map → chunk-BWZF2ZIF.js.map} +1 -1
  43. package/dist/{chunk-PJS2YWGG.js → chunk-CWM3MYGX.js} +6 -6
  44. package/dist/{chunk-PJS2YWGG.js.map → chunk-CWM3MYGX.js.map} +1 -1
  45. package/dist/{chunk-4CTGEEN6.js → chunk-D5HOETOB.js} +424 -98
  46. package/dist/chunk-D5HOETOB.js.map +1 -0
  47. package/dist/{chunk-MX3UQXLU.js → chunk-DFFD4BFG.js} +96 -20
  48. package/dist/chunk-DFFD4BFG.js.map +1 -0
  49. package/dist/{chunk-KXTO7HON.js → chunk-EAZECHPM.js} +3 -3
  50. package/dist/{chunk-KXTO7HON.js.map → chunk-EAZECHPM.js.map} +1 -1
  51. package/dist/{chunk-ZBBM6O6P.js → chunk-EB4XN3KE.js} +3 -3
  52. package/dist/{chunk-ZBBM6O6P.js.map → chunk-EB4XN3KE.js.map} +1 -1
  53. package/dist/{chunk-MX6LZE2C.js → chunk-EU3Q5AQ4.js} +26 -18
  54. package/dist/chunk-EU3Q5AQ4.js.map +1 -0
  55. package/dist/{chunk-BTISGSK4.js → chunk-FAP63KV7.js} +4 -4
  56. package/dist/{chunk-BTISGSK4.js.map → chunk-FAP63KV7.js.map} +1 -1
  57. package/dist/{chunk-46OVMT76.js → chunk-G67BOI2J.js} +3 -3
  58. package/dist/{chunk-46OVMT76.js.map → chunk-G67BOI2J.js.map} +1 -1
  59. package/dist/{chunk-V7NN3HXR.js → chunk-GIC3G5YG.js} +6 -6
  60. package/dist/{chunk-V7NN3HXR.js.map → chunk-GIC3G5YG.js.map} +1 -1
  61. package/dist/{chunk-27HS2DHB.js → chunk-GWXFSLBK.js} +3 -3
  62. package/dist/{chunk-27HS2DHB.js.map → chunk-GWXFSLBK.js.map} +1 -1
  63. package/dist/{chunk-VSQFGU5D.js → chunk-ILFGVSTJ.js} +3 -3
  64. package/dist/{chunk-VSQFGU5D.js.map → chunk-ILFGVSTJ.js.map} +1 -1
  65. package/dist/{chunk-KYXOGHY6.js → chunk-IUUYRXT6.js} +4 -4
  66. package/dist/{chunk-KYXOGHY6.js.map → chunk-IUUYRXT6.js.map} +1 -1
  67. package/dist/{chunk-436GRQC2.js → chunk-IZLQ4GDO.js} +63 -44
  68. package/dist/chunk-IZLQ4GDO.js.map +1 -0
  69. package/dist/{chunk-LLKKLKZJ.js → chunk-JLSCA5T5.js} +3 -3
  70. package/dist/{chunk-LLKKLKZJ.js.map → chunk-JLSCA5T5.js.map} +1 -1
  71. package/dist/{chunk-SX4UIDKT.js → chunk-KM7XWC4Y.js} +3 -3
  72. package/dist/{chunk-SX4UIDKT.js.map → chunk-KM7XWC4Y.js.map} +1 -1
  73. package/dist/{chunk-KUFNKVBM.js → chunk-KNWCFEWU.js} +3 -3
  74. package/dist/{chunk-KUFNKVBM.js.map → chunk-KNWCFEWU.js.map} +1 -1
  75. package/dist/{chunk-MFHKHXDE.js → chunk-L5VSIPQD.js} +5 -5
  76. package/dist/chunk-L5VSIPQD.js.map +1 -0
  77. package/dist/{chunk-AOAZCSDI.js → chunk-LBQ4BBX4.js} +3 -3
  78. package/dist/{chunk-AOAZCSDI.js.map → chunk-LBQ4BBX4.js.map} +1 -1
  79. package/dist/{chunk-2W4LBLIN.js → chunk-LCU5U5IW.js} +6 -6
  80. package/dist/{chunk-2W4LBLIN.js.map → chunk-LCU5U5IW.js.map} +1 -1
  81. package/dist/{chunk-DZM73WDN.js → chunk-LXY4BUA3.js} +5 -5
  82. package/dist/{chunk-DZM73WDN.js.map → chunk-LXY4BUA3.js.map} +1 -1
  83. package/dist/{chunk-7KLC4LZO.js → chunk-MKLBK7HI.js} +8 -8
  84. package/dist/{chunk-7KLC4LZO.js.map → chunk-MKLBK7HI.js.map} +1 -1
  85. package/dist/{chunk-4GNJELPH.js → chunk-N6FBTXQ5.js} +2 -2
  86. package/dist/{chunk-4GNJELPH.js.map → chunk-N6FBTXQ5.js.map} +1 -1
  87. package/dist/{chunk-2XFUXGV6.js → chunk-NWQB7UTY.js} +3 -3
  88. package/dist/{chunk-2XFUXGV6.js.map → chunk-NWQB7UTY.js.map} +1 -1
  89. package/dist/{chunk-SDFROXSA.js → chunk-O4Z7MAW7.js} +3 -3
  90. package/dist/{chunk-SDFROXSA.js.map → chunk-O4Z7MAW7.js.map} +1 -1
  91. package/dist/{chunk-AO7VJ6G6.js → chunk-O7VPNKYN.js} +8 -3
  92. package/dist/chunk-O7VPNKYN.js.map +1 -0
  93. package/dist/{chunk-TZCQ7ZWQ.js → chunk-OOLT6HGP.js} +10 -11
  94. package/dist/chunk-OOLT6HGP.js.map +1 -0
  95. package/dist/{chunk-2GRB5ITE.js → chunk-PSA6ONFB.js} +4 -4
  96. package/dist/{chunk-2GRB5ITE.js.map → chunk-PSA6ONFB.js.map} +1 -1
  97. package/dist/{chunk-45VFGT7A.js → chunk-RNPHRRLG.js} +3 -3
  98. package/dist/{chunk-45VFGT7A.js.map → chunk-RNPHRRLG.js.map} +1 -1
  99. package/dist/{chunk-7ZHLYXTI.js → chunk-RVIZQ5XD.js} +3 -3
  100. package/dist/{chunk-7ZHLYXTI.js.map → chunk-RVIZQ5XD.js.map} +1 -1
  101. package/dist/{chunk-BF33SCLY.js → chunk-SWO25LTO.js} +4 -4
  102. package/dist/{chunk-BF33SCLY.js.map → chunk-SWO25LTO.js.map} +1 -1
  103. package/dist/{chunk-UAP2XHRF.js → chunk-SZWRPEF7.js} +8 -8
  104. package/dist/{chunk-UAP2XHRF.js.map → chunk-SZWRPEF7.js.map} +1 -1
  105. package/dist/{chunk-S7QXEXKY.js → chunk-THEJJBOU.js} +3 -3
  106. package/dist/{chunk-S7QXEXKY.js.map → chunk-THEJJBOU.js.map} +1 -1
  107. package/dist/{chunk-PA7WLID3.js → chunk-TTPSDC2G.js} +33 -3
  108. package/dist/chunk-TTPSDC2G.js.map +1 -0
  109. package/dist/{chunk-VBBBZDI7.js → chunk-UX3K4RKE.js} +3 -3
  110. package/dist/{chunk-VBBBZDI7.js.map → chunk-UX3K4RKE.js.map} +1 -1
  111. package/dist/{chunk-RGXVQZOV.js → chunk-VOOI7B2L.js} +23 -21
  112. package/dist/chunk-VOOI7B2L.js.map +1 -0
  113. package/dist/{chunk-OLLAQLFJ.js → chunk-WIEC3ZE4.js} +5 -5
  114. package/dist/{chunk-OLLAQLFJ.js.map → chunk-WIEC3ZE4.js.map} +1 -1
  115. package/dist/cli/index.js +944 -600
  116. package/dist/cli/index.js.map +1 -1
  117. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  118. package/dist/cli/src/commands/catalog.d.ts +12 -3
  119. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  120. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  121. package/dist/cli/src/commands/library-index.d.ts +41 -4
  122. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  123. package/dist/cli/src/commands/library-publish.d.ts +9 -0
  124. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  125. package/dist/cli/src/commands/manage.d.ts +8 -2
  126. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  127. package/dist/cli/src/commands/migrate-agents.d.ts.map +1 -1
  128. package/dist/cli/src/commands/outdated.d.ts +3 -2
  129. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  130. package/dist/cli/src/commands/project.d.ts +13 -4
  131. package/dist/cli/src/commands/project.d.ts.map +1 -1
  132. package/dist/cli/src/commands/source.d.ts +4 -3
  133. package/dist/cli/src/commands/source.d.ts.map +1 -1
  134. package/dist/cli/src/commands/update.d.ts +1 -1
  135. package/dist/cli/src/commands/update.d.ts.map +1 -1
  136. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  137. package/dist/cli/src/skill-checks.d.ts +21 -10
  138. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  139. package/dist/connectors/config.js +6 -6
  140. package/dist/connectors/index.js +15 -15
  141. package/dist/{connectors-HWENZFKW.js → connectors-SSOTIDHT.js} +18 -18
  142. package/dist/{connectors-HWENZFKW.js.map → connectors-SSOTIDHT.js.map} +1 -1
  143. package/dist/core/index.js +8 -8
  144. package/dist/core/manifest.js +2 -2
  145. package/dist/core/models.js +1 -1
  146. package/dist/core/publish-manifest.js +2 -2
  147. package/dist/core/ref.js +1 -1
  148. package/dist/core/runtime-assets.js +6 -6
  149. package/dist/core/src/cache-paths.d.ts.map +1 -1
  150. package/dist/core/src/index.d.ts +1 -1
  151. package/dist/core/src/index.d.ts.map +1 -1
  152. package/dist/core/src/lock.d.ts +3 -3
  153. package/dist/core/src/lock.d.ts.map +1 -1
  154. package/dist/core/src/manifest.d.ts +6 -1
  155. package/dist/core/src/manifest.d.ts.map +1 -1
  156. package/dist/core/src/models.d.ts +8 -0
  157. package/dist/core/src/models.d.ts.map +1 -1
  158. package/dist/core/store.js +2 -2
  159. package/dist/core/workspace-config.js +5 -5
  160. package/dist/deploy/index.js +8 -8
  161. package/dist/discovery/index.js +4 -4
  162. package/dist/discovery/src/index.d.ts +1 -1
  163. package/dist/discovery/src/index.d.ts.map +1 -1
  164. package/dist/discovery/src/source-config.d.ts +12 -0
  165. package/dist/discovery/src/source-config.d.ts.map +1 -1
  166. package/dist/discovery/src/tree-entries.d.ts.map +1 -1
  167. package/dist/{ensure-sources-VCPKNPK2.js → ensure-sources-277VI7R3.js} +17 -17
  168. package/dist/{ensure-sources-VCPKNPK2.js.map → ensure-sources-277VI7R3.js.map} +1 -1
  169. package/dist/factory-assets/connectors/box.js +15 -15
  170. package/dist/factory-assets/connectors/deploy.js +15 -15
  171. package/dist/factory-assets/connectors/devserver.js +15 -15
  172. package/dist/factory-assets/connectors/flow/adapter.js +15 -15
  173. package/dist/factory-assets/connectors/flow/engine.js +9 -9
  174. package/dist/factory-assets/connectors/flow/run-flow.js +17 -17
  175. package/dist/factory-assets/connectors/flow.js +15 -15
  176. package/dist/factory-assets/connectors/git.js +15 -15
  177. package/dist/factory-assets/connectors/gmail.js +15 -15
  178. package/dist/factory-assets/connectors/googledrive.js +15 -15
  179. package/dist/factory-assets/connectors/local.js +15 -15
  180. package/dist/factory-assets/connectors/mattermost.js +15 -15
  181. package/dist/factory-assets/connectors/memory.js +15 -15
  182. package/dist/factory-assets/connectors/minio.js +15 -15
  183. package/dist/factory-assets/connectors/postgres.js +15 -15
  184. package/dist/factory-assets/connectors/s3.js +15 -15
  185. package/dist/factory-assets/connectors/sharepoint.js +15 -15
  186. package/dist/factory-assets/connectors/sqlite.js +15 -15
  187. package/dist/factory-assets/connectors/static-server.js +15 -15
  188. package/dist/factory-assets/connectors/tunnel.js +15 -15
  189. package/dist/factory-assets/connectors/webdav.js +15 -15
  190. package/dist/factory-assets/connectors/xstate-store.js +15 -15
  191. package/dist/factory-assets/connectors/xstate.js +15 -15
  192. package/dist/{flows-ENQY2DV7.js → flows-J2UEU2QM.js} +13 -13
  193. package/dist/{flows-ENQY2DV7.js.map → flows-J2UEU2QM.js.map} +1 -1
  194. package/dist/{helpers-IW36CEJX.js → helpers-KC5O7CML.js} +17 -17
  195. package/dist/{helpers-IW36CEJX.js.map → helpers-KC5O7CML.js.map} +1 -1
  196. package/dist/library/index.js +11 -11
  197. package/dist/library/install.js +3 -3
  198. package/dist/library/src/index.d.ts +3 -3
  199. package/dist/library/src/index.d.ts.map +1 -1
  200. package/dist/library/src/local/library-manager.d.ts +6 -0
  201. package/dist/library/src/local/library-manager.d.ts.map +1 -1
  202. package/dist/library/src/local/local-catalog-source.d.ts +5 -2
  203. package/dist/library/src/local/local-catalog-source.d.ts.map +1 -1
  204. package/dist/library/src/manifest-writer.d.ts +23 -1
  205. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  206. package/dist/library/src/sync/git-driver.d.ts +12 -0
  207. package/dist/library/src/sync/git-driver.d.ts.map +1 -1
  208. package/dist/{library-publish-R3DQLMTD.js → library-publish-FGXF5TJO.js} +85 -41
  209. package/dist/library-publish-FGXF5TJO.js.map +1 -0
  210. package/dist/{open-library-FAJZRDKE.js → open-library-P3D337NH.js} +20 -20
  211. package/dist/{open-library-FAJZRDKE.js.map → open-library-P3D337NH.js.map} +1 -1
  212. package/dist/open-registry-Z3P2X2AB.js +32 -0
  213. package/dist/{open-registry-NVPCQPND.js.map → open-registry-Z3P2X2AB.js.map} +1 -1
  214. package/dist/paths-JKEKXM52.js +22 -0
  215. package/dist/{paths-YUCP7K6U.js.map → paths-JKEKXM52.js.map} +1 -1
  216. package/dist/{plugin-store-66QFBNEO.js → plugin-store-WI4MZJLP.js} +10 -10
  217. package/dist/{plugin-store-66QFBNEO.js.map → plugin-store-WI4MZJLP.js.map} +1 -1
  218. package/dist/project-WFUDVYNN.js +41 -0
  219. package/dist/{project-ALJIVFHI.js.map → project-WFUDVYNN.js.map} +1 -1
  220. package/dist/resolver/index.js +9 -9
  221. package/dist/runner/index.js +28 -28
  222. package/dist/runner/src/serve.d.ts.map +1 -1
  223. package/dist/sdk/asset-manager.js +14 -14
  224. package/dist/sdk/bridge.js +12 -12
  225. package/dist/sdk/core.js +8 -8
  226. package/dist/sdk/flow.js +9 -9
  227. package/dist/sdk/index.js +28 -28
  228. package/dist/sdk/resolver.js +9 -9
  229. package/dist/sdk/runner.js +28 -28
  230. package/dist/secrets/index.js +2 -2
  231. package/dist/{setup-35JXIA3N.js → setup-RAMLTORM.js} +22 -22
  232. package/dist/{setup-35JXIA3N.js.map → setup-RAMLTORM.js.map} +1 -1
  233. package/dist/skills-EOHZ2DZ4.js +26 -0
  234. package/dist/{skills-CS7NE5TT.js.map → skills-EOHZ2DZ4.js.map} +1 -1
  235. package/dist/{source-ISR4KRZV.js → source-FYVSFYEI.js} +21 -21
  236. package/dist/{source-ISR4KRZV.js.map → source-FYVSFYEI.js.map} +1 -1
  237. package/dist/{source-manifest-publish-P22IPK5F.js → source-manifest-publish-4FPIPPLV.js} +23 -23
  238. package/dist/{source-manifest-publish-P22IPK5F.js.map → source-manifest-publish-4FPIPPLV.js.map} +1 -1
  239. package/dist/tui/index.js +28 -28
  240. package/dist/workspace-plugin/adapters/mcp.js +22 -22
  241. package/dist/workspace-plugin/adapters/omp.js +14 -14
  242. package/dist/workspace-plugin/index.js +1 -1
  243. package/package.json +3 -1
  244. package/dist/chunk-2NYXQYHN.js +0 -22
  245. package/dist/chunk-2NYXQYHN.js.map +0 -1
  246. package/dist/chunk-436GRQC2.js.map +0 -1
  247. package/dist/chunk-4CTGEEN6.js.map +0 -1
  248. package/dist/chunk-AO7VJ6G6.js.map +0 -1
  249. package/dist/chunk-IPWR33AW.js.map +0 -1
  250. package/dist/chunk-MFHKHXDE.js.map +0 -1
  251. package/dist/chunk-MX3UQXLU.js.map +0 -1
  252. package/dist/chunk-MX6LZE2C.js.map +0 -1
  253. package/dist/chunk-PA7WLID3.js.map +0 -1
  254. package/dist/chunk-RGXVQZOV.js.map +0 -1
  255. package/dist/chunk-TZCQ7ZWQ.js.map +0 -1
  256. package/dist/chunk-XOGG7VDZ.js.map +0 -1
  257. package/dist/library-publish-R3DQLMTD.js.map +0 -1
  258. package/dist/open-registry-NVPCQPND.js +0 -32
  259. package/dist/paths-YUCP7K6U.js +0 -22
  260. package/dist/project-ALJIVFHI.js +0 -41
  261. package/dist/skills-CS7NE5TT.js +0 -26
@@ -1,4 +1,4 @@
1
- import { globalSkaileDir } from './chunk-MFHKHXDE.js';
1
+ import { globalSkaileDir } from './chunk-L5VSIPQD.js';
2
2
  import { createHash } from 'crypto';
3
3
  import { mkdirSync, rmSync, writeFileSync, renameSync, existsSync, readdirSync } from 'fs';
4
4
  import { join } from 'path';
@@ -28,5 +28,5 @@ function removeSessionConfigFile(dir, filename) {
28
28
  }
29
29
 
30
30
  export { driverSessionConfigHome, pruneSessionConfigDir, removeSessionConfigFile, writeSessionConfigFile };
31
- //# sourceMappingURL=chunk-KXTO7HON.js.map
32
- //# sourceMappingURL=chunk-KXTO7HON.js.map
31
+ //# sourceMappingURL=chunk-EAZECHPM.js.map
32
+ //# sourceMappingURL=chunk-EAZECHPM.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../bridge/src/provider-materialize/session-config-home.ts"],"names":[],"mappings":";;;;;AAmDO,SAAS,uBAAA,CAAwB,UAAkB,MAAA,EAAkC;AAC1F,EAAA,MAAM,GAAA,GACJ,MAAA,CAAO,SAAA,IAAa,yBAAA,CAA0B,IAAA,CAAK,OAAO,SAAS,CAAA,GAC/D,MAAA,CAAO,SAAA,GACP,UAAA,CAAW,QAAQ,EAChB,MAAA,CAAO,MAAA,CAAO,SAAA,IAAa,MAAA,CAAO,GAAG,CAAA,CACrC,OAAO,KAAK,CAAA,CACZ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACpB,EAAA,OAAO,IAAA,CAAK,eAAA,EAAgB,EAAG,QAAA,EAAU,GAAG,CAAA;AAC9C;AAQO,SAAS,sBAAA,CAAuB,GAAA,EAAa,QAAA,EAAkB,QAAA,EAA0B;AAC9F,EAAA,SAAA,CAAU,KAAK,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,KAAO,CAAA;AAC/C,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,EAAK,QAAQ,CAAA;AAC/B,EAAA,MAAM,SAAA,GAAY,GAAG,IAAI,CAAA,IAAA,CAAA;AACzB,EAAA,MAAA,CAAO,SAAA,EAAW,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA;AACjC,EAAA,aAAA,CAAc,WAAW,QAAA,EAAU,EAAE,MAAM,GAAA,EAAO,IAAA,EAAM,MAAM,CAAA;AAC9D,EAAA,UAAA,CAAW,WAAW,IAAI,CAAA;AAC1B,EAAA,OAAO,IAAA;AACT;AASO,SAAS,qBAAA,CAAsB,KAAa,IAAA,EAAiC;AAClF,EAAA,IAAI,CAAC,UAAA,CAAW,GAAG,CAAA,EAAG;AACtB,EAAA,KAAA,MAAW,IAAA,IAAQ,WAAA,CAAY,GAAG,CAAA,EAAG;AACnC,IAAA,IAAI,CAAC,KAAK,QAAA,CAAS,OAAO,KAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AAC/C,IAAA,MAAA,CAAO,KAAK,GAAA,EAAK,IAAI,GAAG,EAAE,KAAA,EAAO,MAAM,CAAA;AAAA,EACzC;AACF;AAGO,SAAS,uBAAA,CAAwB,KAAa,QAAA,EAAwB;AAC3E,EAAA,MAAA,CAAO,KAAK,GAAA,EAAK,QAAQ,GAAG,EAAE,KAAA,EAAO,MAAM,CAAA;AAC7C","file":"chunk-KXTO7HON.js","sourcesContent":["/**\n * Session-private config homes for the **file-shaped CLI drivers** — OpenCode,\n * Goose and Continue (§2.3, file rows).\n *\n * An environment variable can say *which* endpoint a harness should use, but\n * it cannot describe one the harness has never heard of: a self-hosted\n * gateway, a LiteLLM proxy, an Ollama box. Each of these three harnesses learns\n * such an endpoint only from its own config file, and each resolves that file\n * out of a config home it takes from the environment:\n *\n * | driver | variable | file this adapter writes |\n * |------------|----------------------|--------------------------------------|\n * | `opencode` | `XDG_CONFIG_HOME` | `opencode/opencode.json` |\n * | `goose` | `GOOSE_PATH_ROOT` | `config/custom_providers/<id>.json` |\n * | `continue` | `CONTINUE_GLOBAL_DIR`| `config.yaml` |\n *\n * Pointing those variables at a directory this process owns is what keeps the\n * developer's real `~/.config/opencode`, goose config dir and `~/.continue`\n * out of the session: unread, and — the part that matters — unwritten. The\n * harnesses all persist state next to their config (sessions, logs, an index),\n * so a session that rendered into the ambient home would leave its debris in\n * it.\n *\n * The home is keyed by session id so a resumed turn finds the same directory,\n * and it lives under `$SKAILE_HOME` (default `~/.skaile`) rather than inside\n * `cwd`: the working tree is writable by the model, and a config home in there\n * would let a turn rewrite its own `base_url`. `$SKAILE_HOME` is also the test\n * seam.\n *\n * @see PROVIDER-CONFIG-PLAN.md §2.3\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { globalSkaileDir } from \"@skaile/workspaces/core\";\n\n/** The `AgentConfig` fields a session home is derived from. */\nexport interface SessionHomeInput {\n cwd: string;\n sessionId?: string;\n}\n\n/**\n * `$SKAILE_HOME/<driverId>/<key>` — the directory this process owns on the\n * session's behalf.\n *\n * `key` is the session id when it is already a safe path segment, and a\n * digest of it (or of `cwd`, for a session that carries no id) otherwise, so\n * an id containing a separator can never escape the driver's subtree.\n */\nexport function driverSessionConfigHome(driverId: string, config: SessionHomeInput): string {\n const key =\n config.sessionId && /^[A-Za-z0-9._-]{1,128}$/.test(config.sessionId)\n ? config.sessionId\n : createHash(\"sha256\")\n .update(config.sessionId ?? config.cwd)\n .digest(\"hex\")\n .slice(0, 32);\n return join(globalSkaileDir(), driverId, key);\n}\n\n/**\n * Write `contents` to `path`, creating its directory.\n *\n * Atomic by rename: a harness reading a half-written config fails the whole\n * session, and these files are re-rendered before every turn.\n */\nexport function writeSessionConfigFile(dir: string, filename: string, contents: string): string {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n const path = join(dir, filename);\n const temporary = `${path}.new`;\n rmSync(temporary, { force: true });\n writeFileSync(temporary, contents, { mode: 0o600, flag: \"wx\" });\n renameSync(temporary, path);\n return path;\n}\n\n/**\n * Delete every `.json` file in `dir` that is not in `keep`.\n *\n * Goose loads *all* of `custom_providers/`, so a provider file left over from\n * an earlier render of the same session would keep answering for an endpoint\n * the registry no longer declares.\n */\nexport function pruneSessionConfigDir(dir: string, keep: ReadonlySet<string>): void {\n if (!existsSync(dir)) return;\n for (const name of readdirSync(dir)) {\n if (!name.endsWith(\".json\") || keep.has(name)) continue;\n rmSync(join(dir, name), { force: true });\n }\n}\n\n/** Remove a file an earlier render left behind. */\nexport function removeSessionConfigFile(dir: string, filename: string): void {\n rmSync(join(dir, filename), { force: true });\n}\n"]}
1
+ {"version":3,"sources":["../bridge/src/provider-materialize/session-config-home.ts"],"names":[],"mappings":";;;;;AAmDO,SAAS,uBAAA,CAAwB,UAAkB,MAAA,EAAkC;AAC1F,EAAA,MAAM,GAAA,GACJ,MAAA,CAAO,SAAA,IAAa,yBAAA,CAA0B,IAAA,CAAK,OAAO,SAAS,CAAA,GAC/D,MAAA,CAAO,SAAA,GACP,UAAA,CAAW,QAAQ,EAChB,MAAA,CAAO,MAAA,CAAO,SAAA,IAAa,MAAA,CAAO,GAAG,CAAA,CACrC,OAAO,KAAK,CAAA,CACZ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACpB,EAAA,OAAO,IAAA,CAAK,eAAA,EAAgB,EAAG,QAAA,EAAU,GAAG,CAAA;AAC9C;AAQO,SAAS,sBAAA,CAAuB,GAAA,EAAa,QAAA,EAAkB,QAAA,EAA0B;AAC9F,EAAA,SAAA,CAAU,KAAK,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,KAAO,CAAA;AAC/C,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,EAAK,QAAQ,CAAA;AAC/B,EAAA,MAAM,SAAA,GAAY,GAAG,IAAI,CAAA,IAAA,CAAA;AACzB,EAAA,MAAA,CAAO,SAAA,EAAW,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA;AACjC,EAAA,aAAA,CAAc,WAAW,QAAA,EAAU,EAAE,MAAM,GAAA,EAAO,IAAA,EAAM,MAAM,CAAA;AAC9D,EAAA,UAAA,CAAW,WAAW,IAAI,CAAA;AAC1B,EAAA,OAAO,IAAA;AACT;AASO,SAAS,qBAAA,CAAsB,KAAa,IAAA,EAAiC;AAClF,EAAA,IAAI,CAAC,UAAA,CAAW,GAAG,CAAA,EAAG;AACtB,EAAA,KAAA,MAAW,IAAA,IAAQ,WAAA,CAAY,GAAG,CAAA,EAAG;AACnC,IAAA,IAAI,CAAC,KAAK,QAAA,CAAS,OAAO,KAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AAC/C,IAAA,MAAA,CAAO,KAAK,GAAA,EAAK,IAAI,GAAG,EAAE,KAAA,EAAO,MAAM,CAAA;AAAA,EACzC;AACF;AAGO,SAAS,uBAAA,CAAwB,KAAa,QAAA,EAAwB;AAC3E,EAAA,MAAA,CAAO,KAAK,GAAA,EAAK,QAAQ,GAAG,EAAE,KAAA,EAAO,MAAM,CAAA;AAC7C","file":"chunk-EAZECHPM.js","sourcesContent":["/**\n * Session-private config homes for the **file-shaped CLI drivers** — OpenCode,\n * Goose and Continue (§2.3, file rows).\n *\n * An environment variable can say *which* endpoint a harness should use, but\n * it cannot describe one the harness has never heard of: a self-hosted\n * gateway, a LiteLLM proxy, an Ollama box. Each of these three harnesses learns\n * such an endpoint only from its own config file, and each resolves that file\n * out of a config home it takes from the environment:\n *\n * | driver | variable | file this adapter writes |\n * |------------|----------------------|--------------------------------------|\n * | `opencode` | `XDG_CONFIG_HOME` | `opencode/opencode.json` |\n * | `goose` | `GOOSE_PATH_ROOT` | `config/custom_providers/<id>.json` |\n * | `continue` | `CONTINUE_GLOBAL_DIR`| `config.yaml` |\n *\n * Pointing those variables at a directory this process owns is what keeps the\n * developer's real `~/.config/opencode`, goose config dir and `~/.continue`\n * out of the session: unread, and — the part that matters — unwritten. The\n * harnesses all persist state next to their config (sessions, logs, an index),\n * so a session that rendered into the ambient home would leave its debris in\n * it.\n *\n * The home is keyed by session id so a resumed turn finds the same directory,\n * and it lives under `$SKAILE_HOME` (default `~/.skaile`) rather than inside\n * `cwd`: the working tree is writable by the model, and a config home in there\n * would let a turn rewrite its own `base_url`. `$SKAILE_HOME` is also the test\n * seam.\n *\n * @see PROVIDER-CONFIG-PLAN.md §2.3\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { globalSkaileDir } from \"@skaile/workspaces/core\";\n\n/** The `AgentConfig` fields a session home is derived from. */\nexport interface SessionHomeInput {\n cwd: string;\n sessionId?: string;\n}\n\n/**\n * `$SKAILE_HOME/<driverId>/<key>` — the directory this process owns on the\n * session's behalf.\n *\n * `key` is the session id when it is already a safe path segment, and a\n * digest of it (or of `cwd`, for a session that carries no id) otherwise, so\n * an id containing a separator can never escape the driver's subtree.\n */\nexport function driverSessionConfigHome(driverId: string, config: SessionHomeInput): string {\n const key =\n config.sessionId && /^[A-Za-z0-9._-]{1,128}$/.test(config.sessionId)\n ? config.sessionId\n : createHash(\"sha256\")\n .update(config.sessionId ?? config.cwd)\n .digest(\"hex\")\n .slice(0, 32);\n return join(globalSkaileDir(), driverId, key);\n}\n\n/**\n * Write `contents` to `path`, creating its directory.\n *\n * Atomic by rename: a harness reading a half-written config fails the whole\n * session, and these files are re-rendered before every turn.\n */\nexport function writeSessionConfigFile(dir: string, filename: string, contents: string): string {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n const path = join(dir, filename);\n const temporary = `${path}.new`;\n rmSync(temporary, { force: true });\n writeFileSync(temporary, contents, { mode: 0o600, flag: \"wx\" });\n renameSync(temporary, path);\n return path;\n}\n\n/**\n * Delete every `.json` file in `dir` that is not in `keep`.\n *\n * Goose loads *all* of `custom_providers/`, so a provider file left over from\n * an earlier render of the same session would keep answering for an endpoint\n * the registry no longer declares.\n */\nexport function pruneSessionConfigDir(dir: string, keep: ReadonlySet<string>): void {\n if (!existsSync(dir)) return;\n for (const name of readdirSync(dir)) {\n if (!name.endsWith(\".json\") || keep.has(name)) continue;\n rmSync(join(dir, name), { force: true });\n }\n}\n\n/** Remove a file an earlier render left behind. */\nexport function removeSessionConfigFile(dir: string, filename: string): void {\n rmSync(join(dir, filename), { force: true });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { withFsDeadline, tryWithFsDeadline, walkDir } from './chunk-PA7WLID3.js';
1
+ import { withFsDeadline, tryWithFsDeadline, walkDir } from './chunk-TTPSDC2G.js';
2
2
  import { createLogger } from './chunk-BOFL7GIF.js';
3
3
  import { parse } from 'yaml';
4
4
  import { readFile, stat } from 'fs/promises';
@@ -329,5 +329,5 @@ function validateFlowVersions(nodes, skillVersions) {
329
329
  }
330
330
 
331
331
  export { buildRequiresPreamble, parseCompactionDirectives, parseSkillFrontmatter, parseSkillRequirements, validateConnectorRequirements, validateFlowVersions, validateRequirements };
332
- //# sourceMappingURL=chunk-ZBBM6O6P.js.map
333
- //# sourceMappingURL=chunk-ZBBM6O6P.js.map
332
+ //# sourceMappingURL=chunk-EB4XN3KE.js.map
333
+ //# sourceMappingURL=chunk-EB4XN3KE.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../resolver/src/parser.ts","../resolver/src/preamble.ts","../resolver/src/validator.ts","../resolver/src/version.ts"],"names":["parseYaml"],"mappings":"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","file":"chunk-ZBBM6O6P.js","sourcesContent":["import { parse as parseYaml } from \"yaml\";\nimport type { ConnectorRequirement, InputField, SkillRequirements } from \"./types.js\";\n\n/**\n * Extract YAML frontmatter from a SKILL.md string.\n *\n * Frontmatter is delimited by leading `---` fences. Returns the parsed object,\n * or an empty object `{}` if no frontmatter block is found or if the YAML is malformed.\n * Errors are silently swallowed — callers should treat an empty result as \"no requirements\".\n *\n * @param content - Raw SKILL.md file content (full string, including `---` fences)\n * @returns Parsed frontmatter object, or `{}` on absence or parse failure\n *\n * @docLink packages/resolver/api-reference#parseskill-frontmatter\n */\nexport function parseSkillFrontmatter(content: string): Record<string, any> {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return {};\n try {\n return parseYaml(match[1]!) ?? {};\n } catch {\n return {};\n }\n}\n\n/**\n * Parse skill requirements from raw SKILL.md content into a `SkillRequirements` object.\n *\n * Supports two frontmatter formats:\n * 1. **New format** — `metadata.prerequisites` with explicit\n * `files`, `inputs_required`, `inputs_optional`, `reads`, `produces`, and `resources` arrays.\n * 2. **Legacy format** — `metadata.user_inputs.dialog[]` array, automatically promoted to\n * `inputs_required` / `inputs_optional` based on each entry's `required` flag.\n *\n * Returns empty requirements `{ files: [], inputs_required: [], inputs_optional: [], reads: [], produces: [], resources: [] }`\n * when no recognisable prerequisites section is found.\n *\n * @param content - Raw SKILL.md file content (full string, including `---` fences)\n * @returns Structured `SkillRequirements` (never throws)\n *\n * @docLink packages/resolver/api-reference#parseskill-requirements\n */\nexport function parseSkillRequirements(content: string): SkillRequirements {\n const fm = parseSkillFrontmatter(content);\n const meta = fm.metadata ?? {};\n const prerequisites = meta.prerequisites ?? {};\n\n const empty: SkillRequirements = {\n files: [],\n inputs_required: [],\n inputs_optional: [],\n reads: [],\n produces: [],\n resources: [],\n connectors: [],\n };\n\n // New format: metadata.prerequisites\n if (\n prerequisites.files ||\n prerequisites.inputs_required ||\n prerequisites.inputs_optional ||\n prerequisites.reads ||\n prerequisites.produces ||\n prerequisites.resources ||\n prerequisites.connectors\n ) {\n return {\n files: (prerequisites.files ?? []).map((f: any) => ({\n path: f.path,\n gate: f.gate ?? \"hard\",\n description: f.description ?? \"\",\n ...(f.min_entries != null ? { min_entries: f.min_entries } : {}),\n })),\n inputs_required: (prerequisites.inputs_required ?? []).map(normalizeInputField(true)),\n inputs_optional: (prerequisites.inputs_optional ?? []).map(normalizeInputField(false)),\n reads: (prerequisites.reads ?? []).map((r: any) => ({\n path: r.path,\n description: r.description ?? \"\",\n })),\n produces: (prerequisites.produces ?? []).map((p: any) => ({\n path: p.path,\n description: p.description ?? \"\",\n })),\n resources: (prerequisites.resources ?? []).map((r: any) => ({\n id: r.id,\n ...(r.operations ? { operations: r.operations } : {}),\n optional: r.optional ?? false,\n ...(r.description ? { description: r.description } : {}),\n })),\n connectors: parseConnectorRequirements(prerequisites.connectors),\n };\n }\n\n // Legacy format: metadata.user_inputs.dialog[]\n const dialog = meta.user_inputs?.dialog;\n if (Array.isArray(dialog)) {\n const required: InputField[] = [];\n const optional: InputField[] = [];\n for (const d of dialog) {\n const field = normalizeInputField(d.required ?? false)(d);\n if (d.required) required.push(field);\n else optional.push(field);\n }\n return { ...empty, inputs_required: required, inputs_optional: optional, resources: [] };\n }\n\n return empty;\n}\n\n/**\n * Extract compaction directives from a SKILL.md markdown body.\n *\n * Scans the markdown body (not frontmatter) for a `## Compaction Directives` section\n * and returns each bullet point as a trimmed string. Compaction directives are hints\n * the agent uses to summarise context when the conversation history grows long.\n * Returns an empty array when the section is absent.\n *\n * @param content - Raw SKILL.md file content (full string including frontmatter and body)\n * @returns Array of directive strings extracted from the bullet list, or `[]` if none found\n *\n * @docLink packages/resolver/api-reference#parse-compaction-directives\n */\nexport function parseCompactionDirectives(content: string): string[] {\n const headerIdx = content.search(/^## Compaction Directives/m);\n if (headerIdx === -1) return [];\n\n // Header on the last line (no trailing newline) → no body to scan.\n const newlineIdx = content.indexOf(\"\\n\", headerIdx);\n if (newlineIdx === -1) return [];\n const bodyStart = newlineIdx + 1;\n const rest = content.slice(bodyStart);\n const nextSection = rest.search(/^##\\s/m);\n const sectionBody = nextSection === -1 ? rest : rest.slice(0, nextSection);\n\n const bullets: string[] = [];\n for (const line of sectionBody.split(\"\\n\")) {\n const match = line.match(/^\\s*[-*]\\s+(.+)/);\n if (match) bullets.push(match[1].trim());\n }\n return bullets;\n}\n\nfunction normalizeInputField(defaultRequired: boolean) {\n return (d: any): InputField => ({\n // UserInputSchema permits `key` or `id`; `prompt` is the legacy label alias.\n id: d.id ?? d.key,\n label: d.label ?? d.prompt ?? d.id ?? d.key,\n type: d.type ?? \"text\",\n required: d.required ?? defaultRequired,\n ...(d.options ? { options: d.options } : {}),\n ...(d.default != null ? { default: d.default } : {}),\n ...(d.hint ? { hint: d.hint } : {}),\n ...(d.schema ? { schema: d.schema } : {}),\n });\n}\n\nfunction parseConnectorRequirements(raw: unknown): ConnectorRequirement[] {\n if (!Array.isArray(raw)) return [];\n return raw\n .filter((c): c is Record<string, unknown> => typeof c === \"object\" && c !== null)\n .map((c) => ({\n driver: String(c.driver ?? \"\"),\n ...(c.access === \"read-write\"\n ? { access: \"read-write\" as const }\n : { access: \"read-only\" as const }),\n }))\n .filter((c) => c.driver.length > 0);\n}\n","import type { SkillRequirements } from \"./types.js\";\n\n/**\n * Generate a DSL-format preamble from skill requirements.\n *\n * The preamble is prepended to the skill prompt when the skill runs standalone\n * (without an orchestrator), giving the agent an explicit checklist of what to\n * verify before starting work. Each section maps to a requirement category:\n *\n * - `REQUIRES` — file/directory gates (`hard:` or `soft:` prefix)\n * - `INPUT` — user input fields, with a pointer to `input.json` if `skillId` is provided\n * - `READS` — informational read sources (not gated)\n * - `WRITES` — files the skill will produce\n * - `RESOURCE` — runtime resource dependencies\n *\n * Sections with no entries are omitted. Returns an empty string when all\n * requirement arrays are empty.\n *\n * @param requirements - Parsed requirements (output of `parseSkillRequirements`)\n * @param skillId - Optional skill identifier; when provided, the INPUT section includes\n * the canonical `input.json` path so the agent knows where to read collected values\n * @returns Multi-section DSL string, or `\"\"` if there are no requirements to list\n *\n * @example\n * ```ts\n * const preamble = buildRequiresPreamble(requirements, \"cf_overview\");\n * const fullPrompt = preamble ? `${preamble}\\n\\n${skillBody}` : skillBody;\n * ```\n *\n * @docLink packages/resolver/api-reference#build-requires-preamble\n */\nexport function buildRequiresPreamble(requirements: SkillRequirements, skillId?: string): string {\n const sections: string[] = [];\n\n pushSection(sections, buildRequiresSection(requirements));\n pushSection(sections, buildInputSection(requirements, skillId));\n pushSection(sections, buildReadsSection(requirements));\n pushSection(sections, buildWritesSection(requirements));\n pushSection(sections, buildResourceSection(requirements));\n\n return sections.join(\"\\n\\n\");\n}\n\n/** Append a section to the list when it produced output. */\nfunction pushSection(sections: string[], section: string | null): void {\n if (section !== null) sections.push(section);\n}\n\n/** REQUIRES section (file gates). Returns `null` when there are no file gates. */\nfunction buildRequiresSection(requirements: SkillRequirements): string | null {\n if (requirements.files.length === 0) return null;\n const lines = [\"REQUIRES\"];\n for (const f of requirements.files) {\n const prefix = f.gate === \"hard\" ? \"hard\" : \"soft\";\n lines.push(` ${prefix}: ${f.path} — ${f.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** INPUT section (user inputs). Returns `null` when there are no inputs. */\nfunction buildInputSection(requirements: SkillRequirements, skillId?: string): string | null {\n const allInputs = [...requirements.inputs_required, ...requirements.inputs_optional];\n if (allInputs.length === 0) return null;\n const lines = [\"INPUT\"];\n if (skillId) {\n lines.push(` Read from: _concept/_grounding/${skillId}/input.json`);\n lines.push(\n ` If input.json is missing, ask the user for the following values and write the file:`,\n );\n }\n for (const input of allInputs) {\n const req = input.required ? \"(required)\" : \"(optional)\";\n const opts = input.options ? ` [${input.options.join(\" | \")}]` : \"\";\n const def = input.default != null ? ` default: ${input.default}` : \"\";\n lines.push(` - ${input.id}: ${input.label} ${req}${opts}${def}`);\n if (input.hint) lines.push(` hint: ${input.hint}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** READS section. Returns `null` when there are no read sources. */\nfunction buildReadsSection(requirements: SkillRequirements): string | null {\n if (requirements.reads.length === 0) return null;\n const lines = [\"READS\"];\n for (const r of requirements.reads) {\n lines.push(` ? ${r.path} — ${r.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** WRITES section (produces). Returns `null` when there is nothing produced. */\nfunction buildWritesSection(requirements: SkillRequirements): string | null {\n if (requirements.produces.length === 0) return null;\n const lines = [\"WRITES\"];\n for (const p of requirements.produces) {\n lines.push(` ${p.path} — ${p.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** RESOURCE section. Returns `null` when there are no resources. */\nfunction buildResourceSection(requirements: SkillRequirements): string | null {\n if (!requirements.resources || requirements.resources.length === 0) return null;\n const lines = [\"RESOURCE\"];\n for (const r of requirements.resources) {\n const req = r.optional ? \"(optional)\" : \"(required)\";\n const ops = r.operations ? ` ops: [${r.operations.join(\", \")}]` : \"\";\n lines.push(` ${r.id} ${req}${ops}`);\n if (r.description) lines.push(` — ${r.description}`);\n }\n return lines.join(\"\\n\");\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n tryWithFsDeadline,\n walkDir,\n type WalkTruncation,\n withFsDeadline,\n} from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type {\n ConnectorRequirement,\n FileCheck,\n InputCheck,\n NodeOverrides,\n ReadCheck,\n RequirementsReport,\n ResourceCheck,\n SkillInputFile,\n SkillRequirements,\n} from \"./types.js\";\n\nlet validatorLogger: ReturnType<typeof createLogger> | undefined;\n\nfunction log(): ReturnType<typeof createLogger> {\n validatorLogger ??= createLogger({ kind: \"runner\", subkind: \"skill-requirements\" });\n return validatorLogger;\n}\n\n/** Best-effort existence probe. A missing path, an unreadable one, and an\n * unresponsive mount are all \"not usable here\" for a requirement check. */\nasync function pathExists(target: string): Promise<boolean> {\n return tryWithFsDeadline(\n `stat ${target}`,\n async () => {\n await stat(target);\n return true;\n },\n false,\n );\n}\n\n/**\n * Validate skill requirements against the filesystem and collected inputs.\n *\n * File checks resolve paths relative to `projectDir`. Hard-gate files that are absent\n * set `satisfied: false` on the returned report; soft-gate misses are recorded but do not block.\n * Input checks read `_concept/_grounding/{skillId}/input.json`; missing files are treated as\n * no inputs collected. Resource checks are always recorded as `available: true` — actual\n * availability must be confirmed by the runner's `ResourceManager`.\n *\n * **Async and bounded since #454.** `projectDir` reaches this function straight\n * from the agent — `workspace_check_skill_requirements` takes `target_dir` as a\n * tool argument — so it can be `/skaile/workspace`, the rclone FUSE mount. Every\n * probe is now awaited and deadline-bounded, and the `min_entries` count walks\n * through the bounded {@link walkDir}, so a wedged mount or a symlink cycle\n * costs one failed tool call instead of the whole `skaile serve` event loop.\n *\n * @param skillId - Canonical skill identifier, used to locate `input.json`\n * @param requirements - Parsed requirements from SKILL.md (`parseSkillRequirements` output)\n * @param projectDir - Absolute path to the project root directory\n * @param overrides - Optional flow-level overrides; paths in `skip_checks` are treated as present\n * @param producesIndex - Maps file paths to the skill ID that produces them, enabling \"produced by\" hints in the report\n * @returns `RequirementsReport` with per-check results and an overall `satisfied` flag\n *\n * @docLink packages/resolver/api-reference#validate-requirements\n */\nexport async function validateRequirements(\n skillId: string,\n requirements: SkillRequirements,\n projectDir: string,\n overrides?: NodeOverrides,\n producesIndex?: Map<string, string>,\n): Promise<RequirementsReport> {\n const skipSet = new Set(overrides?.skip_checks ?? []);\n\n // Check files. Serial on purpose: `projectDir` may be one network mount, and\n // fanning every probe out concurrently multiplies the queue depth on exactly\n // the resource that is already the bottleneck.\n const files: FileCheck[] = [];\n for (const req of requirements.files) {\n if (skipSet.has(req.path)) {\n files.push({ path: req.path, gate: req.gate, exists: true, description: req.description });\n continue;\n }\n\n const fullPath = path.join(projectDir, req.path);\n const check: FileCheck = {\n path: req.path,\n gate: req.gate,\n exists: false,\n description: req.description,\n producedBy: producesIndex?.get(req.path),\n };\n\n if (req.min_entries != null) {\n const counted = await checkDirectoryMinEntries(fullPath, req.min_entries);\n check.exists = counted.satisfied;\n if (counted.truncated) check.truncated = true;\n } else {\n check.exists = await pathExists(fullPath);\n }\n\n files.push(check);\n }\n\n // Check inputs — look for _concept/_grounding/{skillId}/input.json\n const inputFile = path.join(projectDir, \"_concept\", \"_grounding\", skillId, \"input.json\");\n let collectedValues: Record<string, any> = {};\n try {\n const raw = await withFsDeadline(`readFile ${inputFile}`, () => readFile(inputFile, \"utf-8\"));\n const parsed = JSON.parse(raw) as SkillInputFile;\n collectedValues = parsed.values ?? {};\n } catch {\n // No input file — all inputs are missing\n }\n\n const allInputs = [\n ...requirements.inputs_required.map((f) => ({ field: f, required: true })),\n ...requirements.inputs_optional.map((f) => ({ field: f, required: false })),\n ];\n\n const inputs: InputCheck[] = allInputs.map(({ field, required }) => ({\n id: field.id,\n required,\n present: field.id in collectedValues,\n field,\n }));\n\n // Check reads (informational only)\n const reads: ReadCheck[] = [];\n for (const r of requirements.reads) {\n reads.push({\n path: r.path,\n exists: await pathExists(path.join(projectDir, r.path)),\n description: r.description,\n });\n }\n\n // Check resources (validated at a higher level if a ResourceManager is available;\n // here we just record them in the report with unknown status)\n const resources: ResourceCheck[] = (requirements.resources ?? []).map((r) => ({\n id: r.id,\n available: true, // Actual availability checked by runner with ResourceManager\n missingOps: [],\n optional: r.optional ?? false,\n }));\n\n // Satisfaction: all hard file gates pass AND all required inputs present\n const hardFilesSatisfied = files.filter((f) => f.gate === \"hard\").every((f) => f.exists);\n\n const requiredInputsSatisfied = inputs.filter((i) => i.required).every((i) => i.present);\n\n const requiredResourcesSatisfied = resources.filter((r) => !r.optional).every((r) => r.available);\n\n return {\n skillId,\n satisfied: hardFilesSatisfied && requiredInputsSatisfied && requiredResourcesSatisfied,\n files,\n inputs,\n reads,\n resources,\n };\n}\n\n/**\n * A warning produced by `validateConnectorRequirements` when a skill's declared\n * connector requirement is not satisfied by the connectors in skaile.yaml.\n * Each warning covers either a missing driver or an insufficient access level.\n *\n * @docLink packages/resolver/api-reference#connector-validation-warning\n */\nexport interface ConnectorValidationWarning {\n /** Driver name that triggered the warning. */\n driver: string;\n /** Human-readable explanation of the gap, including a remediation command where applicable. */\n message: string;\n}\n\n/** Minimal structural type accepted by validateConnectorRequirements. Compatible with both\n * ConnectorDeclaration shapes in @skaile/workspaces/core and @skaile/workspaces/connectors. */\ninterface AvailableConnector {\n driver: string;\n access?: \"read-only\" | \"read-write\";\n}\n\n/**\n * Check that all connector requirements declared in a skill's SKILL.md are\n * satisfied by the connectors declared in skaile.yaml.\n *\n * Returns one warning per gap — either a missing driver or an insufficient\n * access level. This is a pre-flight advisory; no runtime enforcement is done.\n *\n * @param requirements - Connector requirements from `parseSkillRequirements().connectors`\n * @param available - Connector declarations from `skaile.yaml` (via `loadConnectorDeclarations`)\n * @returns Array of warnings — one per gap. Empty array when all requirements are satisfied.\n *\n * @docLink packages/resolver/api-reference#validate-connector-requirements\n */\nexport function validateConnectorRequirements(\n requirements: ConnectorRequirement[],\n available: AvailableConnector[],\n): ConnectorValidationWarning[] {\n const warnings: ConnectorValidationWarning[] = [];\n\n for (const req of requirements) {\n const matches = available.filter((a) => a.driver === req.driver);\n\n if (matches.length === 0) {\n warnings.push({\n driver: req.driver,\n message:\n `Skill requires connector driver \"${req.driver}\" but none is declared in skaile.yaml. ` +\n `Run: skaile connector add ${req.driver}`,\n });\n continue;\n }\n\n if (req.access === \"read-write\") {\n const hasReadWrite = matches.some((m) => (m.access ?? \"read-only\") === \"read-write\");\n if (!hasReadWrite) {\n warnings.push({\n driver: req.driver,\n message:\n `Skill requires \"${req.driver}\" with read-write access, but all declared instances ` +\n `are read-only. Update access in skaile.yaml.`,\n });\n }\n }\n }\n\n return warnings;\n}\n\n/**\n * Does `dirPath` hold at least `minEntries` files, counted recursively?\n *\n * `truncated` is set when a walk bound was hit *and* the count still fell\n * short: the number is then a floor, not the truth, so `satisfied: false` is\n * \"we could not prove it\" rather than \"there are not enough files\". Reaching\n * `minEntries` short-circuits the walk, so the common case never pays for the\n * whole tree and a bound hit after that point is irrelevant.\n */\nasync function checkDirectoryMinEntries(\n dirPath: string,\n minEntries: number,\n): Promise<{ satisfied: boolean; truncated: boolean }> {\n const st = await tryWithFsDeadline(`stat ${dirPath}`, () => stat(dirPath), null);\n if (!st?.isDirectory()) return { satisfied: false, truncated: false };\n\n const { count, truncation } = await countFilesRecursive(dirPath, minEntries);\n const satisfied = count >= minEntries;\n if (!satisfied && truncation) {\n log().warn(\"min_entries count truncated — result is a lower bound, not the file count\", {\n dirPath,\n minEntries,\n count,\n ...truncation,\n });\n }\n return { satisfied, truncated: !satisfied && truncation !== undefined };\n}\n\n/**\n * Count files under `dirPath`, stopping at `limit`.\n *\n * Delegates to core's {@link walkDir} rather than recursing here: `dirPath` is\n * agent-supplied and can be a network mount, so the walk needs the deadline per\n * `opendir`, the depth / entry / wall-clock bounds, and the visited-inode cycle\n * guard that walker already owns. The pre-#454 `readdirSync` recursion had none\n * of them and recursed forever on `a/link -> a`.\n *\n * Inheriting `walkDir` also inherits its skip list: `.git` and `node_modules`\n * no longer count toward `min_entries`, which is what a prerequisite like\n * \"at least 3 feature files\" meant in the first place.\n */\nasync function countFilesRecursive(\n dirPath: string,\n limit: number,\n): Promise<{ count: number; truncation?: WalkTruncation }> {\n let count = 0;\n let truncation: WalkTruncation | undefined;\n for await (const _entry of walkDir(dirPath, {\n onTruncate: (info) => {\n truncation ??= info;\n },\n })) {\n count++;\n // Enough is enough — no reason to keep walking a large tree (or a wedged\n // mount) once the requirement is already met.\n if (count >= limit) return { count };\n }\n return { count, truncation };\n}\n","import { satisfies, valid, validRange } from \"semver\";\n\n/**\n * Result of a single flow-node version pin check.\n * Returned in the array produced by `validateFlowVersions()` for every\n * node that declares a `requestedVersion`.\n *\n * @docLink packages/resolver/api-reference#version-check\n */\nexport interface VersionCheck {\n /** Flow node identifier. */\n nodeId: string;\n /** Canonical skill identifier. */\n skillId: string;\n /** Semver range from the flow node (e.g. \"^1.0.0\") */\n requested: string;\n /** Version from the skill's frontmatter */\n actual: string;\n /** Whether `actual` satisfies the `requested` semver range. */\n satisfied: boolean;\n}\n\n/**\n * Minimal descriptor for a flow node that optionally pins a skill version.\n * Passed as input to `validateFlowVersions()`. Nodes without `requestedVersion`\n * are skipped during version checking.\n *\n * @docLink packages/resolver/api-reference#flow-version-node\n */\nexport interface FlowVersionNode {\n /** Flow node identifier. */\n nodeId: string;\n /** Canonical skill identifier referenced by this node. */\n skillId: string;\n /** Optional semver range the node requires (e.g. `\"^1.2.0\"`). Omit to skip version checking. */\n requestedVersion?: string;\n}\n\n/**\n * Validate flow node version pins against discovered skill versions.\n *\n * Only checks nodes that declare a `requestedVersion`. Nodes without a\n * version pin are skipped entirely (no entry is produced for those nodes).\n * A check is marked `satisfied: false` when the range is invalid, the actual\n * version string is not valid semver, or the version does not satisfy the range.\n *\n * @param nodes - Flow nodes to check; only those with `requestedVersion` are evaluated\n * @param skillVersions - Map from skill ID to the semver version string in its frontmatter\n * @returns Array of `VersionCheck` results, one per node that declared a version pin\n *\n * @docLink packages/resolver/api-reference#validate-flow-versions\n */\nexport function validateFlowVersions(\n nodes: FlowVersionNode[],\n skillVersions: Map<string, string>,\n): VersionCheck[] {\n const checks: VersionCheck[] = [];\n\n for (const node of nodes) {\n if (!node.requestedVersion) continue;\n\n const actual = skillVersions.get(node.skillId) ?? \"\";\n const requested = node.requestedVersion;\n\n // Invalid range or missing/invalid actual version → not satisfied\n const rangeValid = validRange(requested) !== null;\n const actualValid = actual !== \"\" && valid(actual) !== null;\n const isSatisfied = rangeValid && actualValid && satisfies(actual, requested);\n\n checks.push({\n nodeId: node.nodeId,\n skillId: node.skillId,\n requested,\n actual,\n satisfied: isSatisfied,\n });\n }\n\n return checks;\n}\n"]}
1
+ {"version":3,"sources":["../resolver/src/parser.ts","../resolver/src/preamble.ts","../resolver/src/validator.ts","../resolver/src/version.ts"],"names":["parseYaml"],"mappings":"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","file":"chunk-EB4XN3KE.js","sourcesContent":["import { parse as parseYaml } from \"yaml\";\nimport type { ConnectorRequirement, InputField, SkillRequirements } from \"./types.js\";\n\n/**\n * Extract YAML frontmatter from a SKILL.md string.\n *\n * Frontmatter is delimited by leading `---` fences. Returns the parsed object,\n * or an empty object `{}` if no frontmatter block is found or if the YAML is malformed.\n * Errors are silently swallowed — callers should treat an empty result as \"no requirements\".\n *\n * @param content - Raw SKILL.md file content (full string, including `---` fences)\n * @returns Parsed frontmatter object, or `{}` on absence or parse failure\n *\n * @docLink packages/resolver/api-reference#parseskill-frontmatter\n */\nexport function parseSkillFrontmatter(content: string): Record<string, any> {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return {};\n try {\n return parseYaml(match[1]!) ?? {};\n } catch {\n return {};\n }\n}\n\n/**\n * Parse skill requirements from raw SKILL.md content into a `SkillRequirements` object.\n *\n * Supports two frontmatter formats:\n * 1. **New format** — `metadata.prerequisites` with explicit\n * `files`, `inputs_required`, `inputs_optional`, `reads`, `produces`, and `resources` arrays.\n * 2. **Legacy format** — `metadata.user_inputs.dialog[]` array, automatically promoted to\n * `inputs_required` / `inputs_optional` based on each entry's `required` flag.\n *\n * Returns empty requirements `{ files: [], inputs_required: [], inputs_optional: [], reads: [], produces: [], resources: [] }`\n * when no recognisable prerequisites section is found.\n *\n * @param content - Raw SKILL.md file content (full string, including `---` fences)\n * @returns Structured `SkillRequirements` (never throws)\n *\n * @docLink packages/resolver/api-reference#parseskill-requirements\n */\nexport function parseSkillRequirements(content: string): SkillRequirements {\n const fm = parseSkillFrontmatter(content);\n const meta = fm.metadata ?? {};\n const prerequisites = meta.prerequisites ?? {};\n\n const empty: SkillRequirements = {\n files: [],\n inputs_required: [],\n inputs_optional: [],\n reads: [],\n produces: [],\n resources: [],\n connectors: [],\n };\n\n // New format: metadata.prerequisites\n if (\n prerequisites.files ||\n prerequisites.inputs_required ||\n prerequisites.inputs_optional ||\n prerequisites.reads ||\n prerequisites.produces ||\n prerequisites.resources ||\n prerequisites.connectors\n ) {\n return {\n files: (prerequisites.files ?? []).map((f: any) => ({\n path: f.path,\n gate: f.gate ?? \"hard\",\n description: f.description ?? \"\",\n ...(f.min_entries != null ? { min_entries: f.min_entries } : {}),\n })),\n inputs_required: (prerequisites.inputs_required ?? []).map(normalizeInputField(true)),\n inputs_optional: (prerequisites.inputs_optional ?? []).map(normalizeInputField(false)),\n reads: (prerequisites.reads ?? []).map((r: any) => ({\n path: r.path,\n description: r.description ?? \"\",\n })),\n produces: (prerequisites.produces ?? []).map((p: any) => ({\n path: p.path,\n description: p.description ?? \"\",\n })),\n resources: (prerequisites.resources ?? []).map((r: any) => ({\n id: r.id,\n ...(r.operations ? { operations: r.operations } : {}),\n optional: r.optional ?? false,\n ...(r.description ? { description: r.description } : {}),\n })),\n connectors: parseConnectorRequirements(prerequisites.connectors),\n };\n }\n\n // Legacy format: metadata.user_inputs.dialog[]\n const dialog = meta.user_inputs?.dialog;\n if (Array.isArray(dialog)) {\n const required: InputField[] = [];\n const optional: InputField[] = [];\n for (const d of dialog) {\n const field = normalizeInputField(d.required ?? false)(d);\n if (d.required) required.push(field);\n else optional.push(field);\n }\n return { ...empty, inputs_required: required, inputs_optional: optional, resources: [] };\n }\n\n return empty;\n}\n\n/**\n * Extract compaction directives from a SKILL.md markdown body.\n *\n * Scans the markdown body (not frontmatter) for a `## Compaction Directives` section\n * and returns each bullet point as a trimmed string. Compaction directives are hints\n * the agent uses to summarise context when the conversation history grows long.\n * Returns an empty array when the section is absent.\n *\n * @param content - Raw SKILL.md file content (full string including frontmatter and body)\n * @returns Array of directive strings extracted from the bullet list, or `[]` if none found\n *\n * @docLink packages/resolver/api-reference#parse-compaction-directives\n */\nexport function parseCompactionDirectives(content: string): string[] {\n const headerIdx = content.search(/^## Compaction Directives/m);\n if (headerIdx === -1) return [];\n\n // Header on the last line (no trailing newline) → no body to scan.\n const newlineIdx = content.indexOf(\"\\n\", headerIdx);\n if (newlineIdx === -1) return [];\n const bodyStart = newlineIdx + 1;\n const rest = content.slice(bodyStart);\n const nextSection = rest.search(/^##\\s/m);\n const sectionBody = nextSection === -1 ? rest : rest.slice(0, nextSection);\n\n const bullets: string[] = [];\n for (const line of sectionBody.split(\"\\n\")) {\n const match = line.match(/^\\s*[-*]\\s+(.+)/);\n if (match) bullets.push(match[1].trim());\n }\n return bullets;\n}\n\nfunction normalizeInputField(defaultRequired: boolean) {\n return (d: any): InputField => ({\n // UserInputSchema permits `key` or `id`; `prompt` is the legacy label alias.\n id: d.id ?? d.key,\n label: d.label ?? d.prompt ?? d.id ?? d.key,\n type: d.type ?? \"text\",\n required: d.required ?? defaultRequired,\n ...(d.options ? { options: d.options } : {}),\n ...(d.default != null ? { default: d.default } : {}),\n ...(d.hint ? { hint: d.hint } : {}),\n ...(d.schema ? { schema: d.schema } : {}),\n });\n}\n\nfunction parseConnectorRequirements(raw: unknown): ConnectorRequirement[] {\n if (!Array.isArray(raw)) return [];\n return raw\n .filter((c): c is Record<string, unknown> => typeof c === \"object\" && c !== null)\n .map((c) => ({\n driver: String(c.driver ?? \"\"),\n ...(c.access === \"read-write\"\n ? { access: \"read-write\" as const }\n : { access: \"read-only\" as const }),\n }))\n .filter((c) => c.driver.length > 0);\n}\n","import type { SkillRequirements } from \"./types.js\";\n\n/**\n * Generate a DSL-format preamble from skill requirements.\n *\n * The preamble is prepended to the skill prompt when the skill runs standalone\n * (without an orchestrator), giving the agent an explicit checklist of what to\n * verify before starting work. Each section maps to a requirement category:\n *\n * - `REQUIRES` — file/directory gates (`hard:` or `soft:` prefix)\n * - `INPUT` — user input fields, with a pointer to `input.json` if `skillId` is provided\n * - `READS` — informational read sources (not gated)\n * - `WRITES` — files the skill will produce\n * - `RESOURCE` — runtime resource dependencies\n *\n * Sections with no entries are omitted. Returns an empty string when all\n * requirement arrays are empty.\n *\n * @param requirements - Parsed requirements (output of `parseSkillRequirements`)\n * @param skillId - Optional skill identifier; when provided, the INPUT section includes\n * the canonical `input.json` path so the agent knows where to read collected values\n * @returns Multi-section DSL string, or `\"\"` if there are no requirements to list\n *\n * @example\n * ```ts\n * const preamble = buildRequiresPreamble(requirements, \"cf_overview\");\n * const fullPrompt = preamble ? `${preamble}\\n\\n${skillBody}` : skillBody;\n * ```\n *\n * @docLink packages/resolver/api-reference#build-requires-preamble\n */\nexport function buildRequiresPreamble(requirements: SkillRequirements, skillId?: string): string {\n const sections: string[] = [];\n\n pushSection(sections, buildRequiresSection(requirements));\n pushSection(sections, buildInputSection(requirements, skillId));\n pushSection(sections, buildReadsSection(requirements));\n pushSection(sections, buildWritesSection(requirements));\n pushSection(sections, buildResourceSection(requirements));\n\n return sections.join(\"\\n\\n\");\n}\n\n/** Append a section to the list when it produced output. */\nfunction pushSection(sections: string[], section: string | null): void {\n if (section !== null) sections.push(section);\n}\n\n/** REQUIRES section (file gates). Returns `null` when there are no file gates. */\nfunction buildRequiresSection(requirements: SkillRequirements): string | null {\n if (requirements.files.length === 0) return null;\n const lines = [\"REQUIRES\"];\n for (const f of requirements.files) {\n const prefix = f.gate === \"hard\" ? \"hard\" : \"soft\";\n lines.push(` ${prefix}: ${f.path} — ${f.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** INPUT section (user inputs). Returns `null` when there are no inputs. */\nfunction buildInputSection(requirements: SkillRequirements, skillId?: string): string | null {\n const allInputs = [...requirements.inputs_required, ...requirements.inputs_optional];\n if (allInputs.length === 0) return null;\n const lines = [\"INPUT\"];\n if (skillId) {\n lines.push(` Read from: _concept/_grounding/${skillId}/input.json`);\n lines.push(\n ` If input.json is missing, ask the user for the following values and write the file:`,\n );\n }\n for (const input of allInputs) {\n const req = input.required ? \"(required)\" : \"(optional)\";\n const opts = input.options ? ` [${input.options.join(\" | \")}]` : \"\";\n const def = input.default != null ? ` default: ${input.default}` : \"\";\n lines.push(` - ${input.id}: ${input.label} ${req}${opts}${def}`);\n if (input.hint) lines.push(` hint: ${input.hint}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** READS section. Returns `null` when there are no read sources. */\nfunction buildReadsSection(requirements: SkillRequirements): string | null {\n if (requirements.reads.length === 0) return null;\n const lines = [\"READS\"];\n for (const r of requirements.reads) {\n lines.push(` ? ${r.path} — ${r.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** WRITES section (produces). Returns `null` when there is nothing produced. */\nfunction buildWritesSection(requirements: SkillRequirements): string | null {\n if (requirements.produces.length === 0) return null;\n const lines = [\"WRITES\"];\n for (const p of requirements.produces) {\n lines.push(` ${p.path} — ${p.description}`);\n }\n return lines.join(\"\\n\");\n}\n\n/** RESOURCE section. Returns `null` when there are no resources. */\nfunction buildResourceSection(requirements: SkillRequirements): string | null {\n if (!requirements.resources || requirements.resources.length === 0) return null;\n const lines = [\"RESOURCE\"];\n for (const r of requirements.resources) {\n const req = r.optional ? \"(optional)\" : \"(required)\";\n const ops = r.operations ? ` ops: [${r.operations.join(\", \")}]` : \"\";\n lines.push(` ${r.id} ${req}${ops}`);\n if (r.description) lines.push(` — ${r.description}`);\n }\n return lines.join(\"\\n\");\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n tryWithFsDeadline,\n walkDir,\n type WalkTruncation,\n withFsDeadline,\n} from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type {\n ConnectorRequirement,\n FileCheck,\n InputCheck,\n NodeOverrides,\n ReadCheck,\n RequirementsReport,\n ResourceCheck,\n SkillInputFile,\n SkillRequirements,\n} from \"./types.js\";\n\nlet validatorLogger: ReturnType<typeof createLogger> | undefined;\n\nfunction log(): ReturnType<typeof createLogger> {\n validatorLogger ??= createLogger({ kind: \"runner\", subkind: \"skill-requirements\" });\n return validatorLogger;\n}\n\n/** Best-effort existence probe. A missing path, an unreadable one, and an\n * unresponsive mount are all \"not usable here\" for a requirement check. */\nasync function pathExists(target: string): Promise<boolean> {\n return tryWithFsDeadline(\n `stat ${target}`,\n async () => {\n await stat(target);\n return true;\n },\n false,\n );\n}\n\n/**\n * Validate skill requirements against the filesystem and collected inputs.\n *\n * File checks resolve paths relative to `projectDir`. Hard-gate files that are absent\n * set `satisfied: false` on the returned report; soft-gate misses are recorded but do not block.\n * Input checks read `_concept/_grounding/{skillId}/input.json`; missing files are treated as\n * no inputs collected. Resource checks are always recorded as `available: true` — actual\n * availability must be confirmed by the runner's `ResourceManager`.\n *\n * **Async and bounded since #454.** `projectDir` reaches this function straight\n * from the agent — `workspace_check_skill_requirements` takes `target_dir` as a\n * tool argument — so it can be `/skaile/workspace`, the rclone FUSE mount. Every\n * probe is now awaited and deadline-bounded, and the `min_entries` count walks\n * through the bounded {@link walkDir}, so a wedged mount or a symlink cycle\n * costs one failed tool call instead of the whole `skaile serve` event loop.\n *\n * @param skillId - Canonical skill identifier, used to locate `input.json`\n * @param requirements - Parsed requirements from SKILL.md (`parseSkillRequirements` output)\n * @param projectDir - Absolute path to the project root directory\n * @param overrides - Optional flow-level overrides; paths in `skip_checks` are treated as present\n * @param producesIndex - Maps file paths to the skill ID that produces them, enabling \"produced by\" hints in the report\n * @returns `RequirementsReport` with per-check results and an overall `satisfied` flag\n *\n * @docLink packages/resolver/api-reference#validate-requirements\n */\nexport async function validateRequirements(\n skillId: string,\n requirements: SkillRequirements,\n projectDir: string,\n overrides?: NodeOverrides,\n producesIndex?: Map<string, string>,\n): Promise<RequirementsReport> {\n const skipSet = new Set(overrides?.skip_checks ?? []);\n\n // Check files. Serial on purpose: `projectDir` may be one network mount, and\n // fanning every probe out concurrently multiplies the queue depth on exactly\n // the resource that is already the bottleneck.\n const files: FileCheck[] = [];\n for (const req of requirements.files) {\n if (skipSet.has(req.path)) {\n files.push({ path: req.path, gate: req.gate, exists: true, description: req.description });\n continue;\n }\n\n const fullPath = path.join(projectDir, req.path);\n const check: FileCheck = {\n path: req.path,\n gate: req.gate,\n exists: false,\n description: req.description,\n producedBy: producesIndex?.get(req.path),\n };\n\n if (req.min_entries != null) {\n const counted = await checkDirectoryMinEntries(fullPath, req.min_entries);\n check.exists = counted.satisfied;\n if (counted.truncated) check.truncated = true;\n } else {\n check.exists = await pathExists(fullPath);\n }\n\n files.push(check);\n }\n\n // Check inputs — look for _concept/_grounding/{skillId}/input.json\n const inputFile = path.join(projectDir, \"_concept\", \"_grounding\", skillId, \"input.json\");\n let collectedValues: Record<string, any> = {};\n try {\n const raw = await withFsDeadline(`readFile ${inputFile}`, () => readFile(inputFile, \"utf-8\"));\n const parsed = JSON.parse(raw) as SkillInputFile;\n collectedValues = parsed.values ?? {};\n } catch {\n // No input file — all inputs are missing\n }\n\n const allInputs = [\n ...requirements.inputs_required.map((f) => ({ field: f, required: true })),\n ...requirements.inputs_optional.map((f) => ({ field: f, required: false })),\n ];\n\n const inputs: InputCheck[] = allInputs.map(({ field, required }) => ({\n id: field.id,\n required,\n present: field.id in collectedValues,\n field,\n }));\n\n // Check reads (informational only)\n const reads: ReadCheck[] = [];\n for (const r of requirements.reads) {\n reads.push({\n path: r.path,\n exists: await pathExists(path.join(projectDir, r.path)),\n description: r.description,\n });\n }\n\n // Check resources (validated at a higher level if a ResourceManager is available;\n // here we just record them in the report with unknown status)\n const resources: ResourceCheck[] = (requirements.resources ?? []).map((r) => ({\n id: r.id,\n available: true, // Actual availability checked by runner with ResourceManager\n missingOps: [],\n optional: r.optional ?? false,\n }));\n\n // Satisfaction: all hard file gates pass AND all required inputs present\n const hardFilesSatisfied = files.filter((f) => f.gate === \"hard\").every((f) => f.exists);\n\n const requiredInputsSatisfied = inputs.filter((i) => i.required).every((i) => i.present);\n\n const requiredResourcesSatisfied = resources.filter((r) => !r.optional).every((r) => r.available);\n\n return {\n skillId,\n satisfied: hardFilesSatisfied && requiredInputsSatisfied && requiredResourcesSatisfied,\n files,\n inputs,\n reads,\n resources,\n };\n}\n\n/**\n * A warning produced by `validateConnectorRequirements` when a skill's declared\n * connector requirement is not satisfied by the connectors in skaile.yaml.\n * Each warning covers either a missing driver or an insufficient access level.\n *\n * @docLink packages/resolver/api-reference#connector-validation-warning\n */\nexport interface ConnectorValidationWarning {\n /** Driver name that triggered the warning. */\n driver: string;\n /** Human-readable explanation of the gap, including a remediation command where applicable. */\n message: string;\n}\n\n/** Minimal structural type accepted by validateConnectorRequirements. Compatible with both\n * ConnectorDeclaration shapes in @skaile/workspaces/core and @skaile/workspaces/connectors. */\ninterface AvailableConnector {\n driver: string;\n access?: \"read-only\" | \"read-write\";\n}\n\n/**\n * Check that all connector requirements declared in a skill's SKILL.md are\n * satisfied by the connectors declared in skaile.yaml.\n *\n * Returns one warning per gap — either a missing driver or an insufficient\n * access level. This is a pre-flight advisory; no runtime enforcement is done.\n *\n * @param requirements - Connector requirements from `parseSkillRequirements().connectors`\n * @param available - Connector declarations from `skaile.yaml` (via `loadConnectorDeclarations`)\n * @returns Array of warnings — one per gap. Empty array when all requirements are satisfied.\n *\n * @docLink packages/resolver/api-reference#validate-connector-requirements\n */\nexport function validateConnectorRequirements(\n requirements: ConnectorRequirement[],\n available: AvailableConnector[],\n): ConnectorValidationWarning[] {\n const warnings: ConnectorValidationWarning[] = [];\n\n for (const req of requirements) {\n const matches = available.filter((a) => a.driver === req.driver);\n\n if (matches.length === 0) {\n warnings.push({\n driver: req.driver,\n message:\n `Skill requires connector driver \"${req.driver}\" but none is declared in skaile.yaml. ` +\n `Run: skaile connector add ${req.driver}`,\n });\n continue;\n }\n\n if (req.access === \"read-write\") {\n const hasReadWrite = matches.some((m) => (m.access ?? \"read-only\") === \"read-write\");\n if (!hasReadWrite) {\n warnings.push({\n driver: req.driver,\n message:\n `Skill requires \"${req.driver}\" with read-write access, but all declared instances ` +\n `are read-only. Update access in skaile.yaml.`,\n });\n }\n }\n }\n\n return warnings;\n}\n\n/**\n * Does `dirPath` hold at least `minEntries` files, counted recursively?\n *\n * `truncated` is set when a walk bound was hit *and* the count still fell\n * short: the number is then a floor, not the truth, so `satisfied: false` is\n * \"we could not prove it\" rather than \"there are not enough files\". Reaching\n * `minEntries` short-circuits the walk, so the common case never pays for the\n * whole tree and a bound hit after that point is irrelevant.\n */\nasync function checkDirectoryMinEntries(\n dirPath: string,\n minEntries: number,\n): Promise<{ satisfied: boolean; truncated: boolean }> {\n const st = await tryWithFsDeadline(`stat ${dirPath}`, () => stat(dirPath), null);\n if (!st?.isDirectory()) return { satisfied: false, truncated: false };\n\n const { count, truncation } = await countFilesRecursive(dirPath, minEntries);\n const satisfied = count >= minEntries;\n if (!satisfied && truncation) {\n log().warn(\"min_entries count truncated — result is a lower bound, not the file count\", {\n dirPath,\n minEntries,\n count,\n ...truncation,\n });\n }\n return { satisfied, truncated: !satisfied && truncation !== undefined };\n}\n\n/**\n * Count files under `dirPath`, stopping at `limit`.\n *\n * Delegates to core's {@link walkDir} rather than recursing here: `dirPath` is\n * agent-supplied and can be a network mount, so the walk needs the deadline per\n * `opendir`, the depth / entry / wall-clock bounds, and the visited-inode cycle\n * guard that walker already owns. The pre-#454 `readdirSync` recursion had none\n * of them and recursed forever on `a/link -> a`.\n *\n * Inheriting `walkDir` also inherits its skip list: `.git` and `node_modules`\n * no longer count toward `min_entries`, which is what a prerequisite like\n * \"at least 3 feature files\" meant in the first place.\n */\nasync function countFilesRecursive(\n dirPath: string,\n limit: number,\n): Promise<{ count: number; truncation?: WalkTruncation }> {\n let count = 0;\n let truncation: WalkTruncation | undefined;\n for await (const _entry of walkDir(dirPath, {\n onTruncate: (info) => {\n truncation ??= info;\n },\n })) {\n count++;\n // Enough is enough — no reason to keep walking a large tree (or a wedged\n // mount) once the requirement is already met.\n if (count >= limit) return { count };\n }\n return { count, truncation };\n}\n","import { satisfies, valid, validRange } from \"semver\";\n\n/**\n * Result of a single flow-node version pin check.\n * Returned in the array produced by `validateFlowVersions()` for every\n * node that declares a `requestedVersion`.\n *\n * @docLink packages/resolver/api-reference#version-check\n */\nexport interface VersionCheck {\n /** Flow node identifier. */\n nodeId: string;\n /** Canonical skill identifier. */\n skillId: string;\n /** Semver range from the flow node (e.g. \"^1.0.0\") */\n requested: string;\n /** Version from the skill's frontmatter */\n actual: string;\n /** Whether `actual` satisfies the `requested` semver range. */\n satisfied: boolean;\n}\n\n/**\n * Minimal descriptor for a flow node that optionally pins a skill version.\n * Passed as input to `validateFlowVersions()`. Nodes without `requestedVersion`\n * are skipped during version checking.\n *\n * @docLink packages/resolver/api-reference#flow-version-node\n */\nexport interface FlowVersionNode {\n /** Flow node identifier. */\n nodeId: string;\n /** Canonical skill identifier referenced by this node. */\n skillId: string;\n /** Optional semver range the node requires (e.g. `\"^1.2.0\"`). Omit to skip version checking. */\n requestedVersion?: string;\n}\n\n/**\n * Validate flow node version pins against discovered skill versions.\n *\n * Only checks nodes that declare a `requestedVersion`. Nodes without a\n * version pin are skipped entirely (no entry is produced for those nodes).\n * A check is marked `satisfied: false` when the range is invalid, the actual\n * version string is not valid semver, or the version does not satisfy the range.\n *\n * @param nodes - Flow nodes to check; only those with `requestedVersion` are evaluated\n * @param skillVersions - Map from skill ID to the semver version string in its frontmatter\n * @returns Array of `VersionCheck` results, one per node that declared a version pin\n *\n * @docLink packages/resolver/api-reference#validate-flow-versions\n */\nexport function validateFlowVersions(\n nodes: FlowVersionNode[],\n skillVersions: Map<string, string>,\n): VersionCheck[] {\n const checks: VersionCheck[] = [];\n\n for (const node of nodes) {\n if (!node.requestedVersion) continue;\n\n const actual = skillVersions.get(node.skillId) ?? \"\";\n const requested = node.requestedVersion;\n\n // Invalid range or missing/invalid actual version → not satisfied\n const rangeValid = validRange(requested) !== null;\n const actualValid = actual !== \"\" && valid(actual) !== null;\n const isSatisfied = rangeValid && actualValid && satisfies(actual, requested);\n\n checks.push({\n nodeId: node.nodeId,\n skillId: node.skillId,\n requested,\n actual,\n satisfied: isSatisfied,\n });\n }\n\n return checks;\n}\n"]}
@@ -1,11 +1,11 @@
1
1
  import { createSpinner } from './chunk-NESV47MF.js';
2
- import { logInfo, logWarn, TARGET_DEFAULT_HINT, logErr, logOk, colorRef, S, deferredWarnings, warnLegacyClaudeCopies, formatSoftDepHint } from './chunk-S7QXEXKY.js';
3
- import { getKindRegistry } from './chunk-OLLAQLFJ.js';
4
- import { AssetManager } from './chunk-4CTGEEN6.js';
5
- import { readLock } from './chunk-TZCQ7ZWQ.js';
6
- import { userConfigPath } from './chunk-MFHKHXDE.js';
2
+ import { logInfo, logWarn, TARGET_DEFAULT_HINT, logErr, logOk, colorRef, S, deferredWarnings, warnLegacyClaudeCopies, formatSoftDepHint } from './chunk-THEJJBOU.js';
3
+ import { getKindRegistry } from './chunk-WIEC3ZE4.js';
4
+ import { AssetManager } from './chunk-D5HOETOB.js';
5
+ import { readLock } from './chunk-OOLT6HGP.js';
6
+ import { userConfigPath } from './chunk-L5VSIPQD.js';
7
7
  import { SUPPORTED_DRIVER_TARGETS } from './chunk-CPSIPIX7.js';
8
- import { parseAssetRef } from './chunk-AO7VJ6G6.js';
8
+ import { parseAssetRef } from './chunk-O7VPNKYN.js';
9
9
  import path from 'path';
10
10
  import * as p from '@clack/prompts';
11
11
  import { Command } from 'commander';
@@ -98,7 +98,7 @@ async function runRefInstall(ref, opts) {
98
98
  const spinner = createSpinner();
99
99
  spinner.start(`Installing ${ref}`);
100
100
  try {
101
- const { openCatalogSource, openLibrary } = await import('./open-library-FAJZRDKE.js');
101
+ const { openCatalogSource, openLibrary } = await import('./open-library-P3D337NH.js');
102
102
  const catalog = await openCatalogSource({ projectDir: path.resolve(opts.projectDir) });
103
103
  if (!supportsInstallManifest(catalog)) {
104
104
  throw new Error(
@@ -140,7 +140,7 @@ async function runYamlInstall(opts) {
140
140
  return;
141
141
  }
142
142
  try {
143
- const { ensureSourcesCloned } = await import('./ensure-sources-VCPKNPK2.js');
143
+ const { ensureSourcesCloned } = await import('./ensure-sources-277VI7R3.js');
144
144
  const hydrate = ensureSourcesCloned(projectDir, { quiet: true });
145
145
  if (hydrate.cloned.length > 0) {
146
146
  logOk(`Cloned source(s): ${hydrate.cloned.join(", ")}`);
@@ -176,7 +176,7 @@ async function runYamlInstall(opts) {
176
176
  logInfo("Nothing to install (already up to date).");
177
177
  }
178
178
  if (result.missing.length > 0) {
179
- for (const m of result.missing) logErr(`Missing: ${m}`);
179
+ for (const m of result.missing) logErr(`Missing: ${m}${result.missingHints?.[m] ?? ""}`);
180
180
  process.exitCode = 1;
181
181
  }
182
182
  if (result.lockWritten) {
@@ -221,7 +221,7 @@ async function runGlobalInstall(opts, harnesses) {
221
221
  if (result.deployed.length === 0 && result.removed.length === 0 && result.missing.length === 0)
222
222
  logInfo("Nothing to install (already up to date).");
223
223
  if (result.missing.length > 0) {
224
- for (const m of result.missing) logErr(`Missing: ${m}`);
224
+ for (const m of result.missing) logErr(`Missing: ${m}${result.missingHints?.[m] ?? ""}`);
225
225
  process.exitCode = 1;
226
226
  }
227
227
  if (result.lockWritten) logInfo(`Global lock written: ${S.dim("~/.skaile/skaile.lock.yaml")}`);
@@ -244,21 +244,29 @@ function makeCheckCommand() {
244
244
  projectDir: path.resolve(opts.projectDir)
245
245
  });
246
246
  const issues = await am.doctor();
247
- let drifted = [];
247
+ let notInstalled = [];
248
248
  try {
249
- drifted = (await am.listDeclared()).filter((d) => d.state === "drift");
249
+ notInstalled = (await am.listDeclared()).filter((d) => d.state !== "installed");
250
250
  } catch {
251
251
  }
252
- if (issues.length === 0 && drifted.length === 0) {
252
+ if (issues.length === 0 && notInstalled.length === 0) {
253
253
  logOk("All dependencies satisfied.");
254
254
  } else {
255
255
  for (const i of issues) {
256
+ if (i.unresolved) {
257
+ logErr(
258
+ `${i.assetKind}:${i.assetName} is locked but no source or library provides it any more \u2014 its requirements cannot be checked`
259
+ );
260
+ continue;
261
+ }
256
262
  logErr(
257
263
  `${i.assetKind}:${i.assetName} requires ${i.depKind}:${i.depName} (${i.inRepos ? "fixable" : "not found"})`
258
264
  );
259
265
  }
260
- for (const d of drifted) {
261
- logErr(`${d.ref} is declared and locked but not materialized \u2014 run \`skaile install\``);
266
+ for (const d of notInstalled) {
267
+ logErr(
268
+ d.state === "invalid" ? `${d.ref} is not a valid asset ref (expected ${REF_HINT})` : d.state === "drift" ? `${d.ref} is declared and locked but not materialized \u2014 run \`skaile install\`` : `${d.ref} is declared but does not resolve \u2014 run \`skaile install\``
269
+ );
262
270
  }
263
271
  process.exit(1);
264
272
  }
@@ -323,6 +331,6 @@ function makeCleanCommand() {
323
331
  });
324
332
  }
325
333
 
326
- export { makeCheckCommand, makeCleanCommand, makeInstallCommand, reportAgentInstances, reportInstalledSoftDeps, reportPresetExpansions, runPointerOnlyInstall, supportsInstallManifest };
327
- //# sourceMappingURL=chunk-MX6LZE2C.js.map
328
- //# sourceMappingURL=chunk-MX6LZE2C.js.map
334
+ export { REF_HINT, makeCheckCommand, makeCleanCommand, makeInstallCommand, reportAgentInstances, reportInstalledSoftDeps, reportPresetExpansions, runPointerOnlyInstall, supportsInstallManifest };
335
+ //# sourceMappingURL=chunk-EU3Q5AQ4.js.map
336
+ //# sourceMappingURL=chunk-EU3Q5AQ4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../cli/src/commands/project.ts"],"names":["confirm"],"mappings":"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","file":"chunk-EU3Q5AQ4.js","sourcesContent":["import path from \"node:path\";\nimport * as p from \"@clack/prompts\";\nimport {\n AssetManager,\n type DeclaredAsset,\n type InstalledAgentInstance,\n} from \"@skaile/workspaces/asset-manager\";\nimport {\n type DriverTarget,\n type PresetExpansion,\n parseAssetRef,\n readLock,\n SUPPORTED_DRIVER_TARGETS,\n userConfigPath,\n} from \"@skaile/workspaces/core\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\nimport { Command } from \"commander\";\nimport {\n colorRef,\n deferredWarnings,\n formatSoftDepHint,\n logErr,\n logInfo,\n logOk,\n logWarn,\n S,\n TARGET_DEFAULT_HINT,\n warnLegacyClaudeCopies,\n} from \"../helpers.ts\";\nimport { createSpinner } from \"../spinner.ts\";\nimport { getKindRegistry } from \"../open-registry.ts\";\n\n/**\n * Canonical asset-ref shape accepted by `skaile install <ref>`:\n * `kind:@<publisher>/<name>#<version>` (the `#` version sigil). Validated via\n * `parseAssetRef` so the CLI shares the single canonical grammar; the legacy\n * trailing-`@version` shape is rejected.\n */\nexport const REF_HINT = \"kind:@<publisher>/<name>#<version> (e.g. skill:@skaile/use-exa#1.0.0)\";\n\n/** True when `ref` parses as a canonical asset ref. */\nfunction isValidAssetRef(ref: string): boolean {\n try {\n parseAssetRef(ref);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Minimal catalog-source surface the pointer-only install path needs.\n * `RemoteCatalogSource` satisfies this — narrowing keeps {@link runPointerOnlyInstall}\n * testable with a hand-rolled stub.\n */\nexport interface InstallManifestSource {\n getInstallManifest(ref: string): Promise<InstallManifest>;\n}\n\n/**\n * Capability check: is this catalog source able to serve install manifests?\n *\n * `openCatalogSource` returns a `RemoteCatalogSource | RestCatalogSource`.\n * Only the tRPC-framed `RemoteCatalogSource` implements `getInstallManifest`;\n * the REST-framed `RestCatalogSource` (the default for any catalog URL other\n * than `https://skaile.store`) does not. Calling it unconditionally would be a\n * runtime `TypeError`, so the pointer-only install path must capability-detect\n * first and fail with a clear, actionable message.\n */\nexport function supportsInstallManifest(source: unknown): source is InstallManifestSource {\n return (\n typeof (source as { getInstallManifest?: unknown } | null | undefined)?.getInstallManifest ===\n \"function\"\n );\n}\n\n/**\n * Minimal library surface the pointer-only install path needs.\n * `LocalIndex` satisfies this.\n */\nexport interface InstallLibrary {\n install(manifest: InstallManifest): Promise<{ installPath: string }>;\n}\n\n/**\n * Result of a pointer-only catalog install.\n */\nexport interface PointerOnlyInstallResult {\n /** Absolute path the verified asset bytes were written to. */\n installPath: string;\n /** The pinned upstream commit SHA the asset was fetched at. */\n commitSha: string;\n /** Number of files in the install manifest. */\n fileCount: number;\n}\n\n/**\n * Pointer-only catalog install — the `skaile install <ref>` code path.\n *\n * 1. Resolves the pointer-only {@link InstallManifest} from the Catalog.\n * 2. Hands it to the library, which fetches each file's bytes directly from\n * the upstream repo at the pinned commit, verifies every per-file SHA256\n * plus the composite SHA256, and only then writes the verified files.\n *\n * Both dependencies are injected so the function is unit-testable without a\n * network round-trip. In production the CLI passes a `RemoteCatalogSource`\n * and a `LocalIndex`.\n *\n * @param ref - Canonical asset ref (`kind:@<publisher>/<name>#<version>`).\n * @param deps - Injected catalog source + library.\n * @returns The install path, pinned commit SHA, and file count.\n * @throws When the ref is malformed, the manifest cannot be resolved, or any\n * hash verification fails. The underlying error message is surfaced as-is.\n */\nexport async function runPointerOnlyInstall(\n ref: string,\n deps: { catalog: InstallManifestSource; library: InstallLibrary },\n): Promise<PointerOnlyInstallResult> {\n let requested: ReturnType<typeof parseAssetRef>;\n try {\n requested = parseAssetRef(ref);\n } catch (e) {\n throw new Error(\n `malformed asset ref '${ref}' — expected ${REF_HINT}: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n const manifest = await deps.catalog.getInstallManifest(ref);\n // [M1] Identity check: the catalog must not install a different asset than\n // requested. Compare the PARSED refs (kind/publisher/name/pin) so equivalent\n // spellings (optional `kind:`, default `skill`) are treated as the same ref.\n const got = parseAssetRef(manifest.ref);\n if (\n got.kind !== requested.kind ||\n got.publisher !== requested.publisher ||\n got.name !== requested.name ||\n got.pin !== requested.pin\n ) {\n throw new Error(\n `catalog identity mismatch: requested '${ref}' but the catalog returned a manifest for '${manifest.ref}'`,\n );\n }\n const { installPath } = await deps.library.install(manifest);\n return {\n installPath,\n commitSha: manifest.source.commitSha,\n fileCount: manifest.files.length,\n };\n}\n\n/**\n * Print one summary line per `preset:` dependency `skaile install` expanded: how many\n * asset items joined the install set and how many instance items (`library://`,\n * placeholders) were skipped, which only `skaile preset apply` materialises.\n */\nexport function reportPresetExpansions(\n presets: readonly PresetExpansion[] | undefined,\n onLine: (line: string) => void = logInfo,\n): void {\n for (const preset of presets ?? []) {\n onLine(\n `preset ${preset.ref}: ${preset.assets} assets, ${preset.skipped} instance items skipped (apply with skaile preset apply)`,\n );\n }\n}\n\n/**\n * Print one line per agent instance `skaile install` rendered (with the files\n * written) and one per native agent file removed because its instance left `skaile.yaml`.\n */\nexport function reportAgentInstances(\n instances: readonly InstalledAgentInstance[] | undefined,\n removedFiles: readonly string[] | undefined,\n onLine: (line: string) => void = logInfo,\n onRemoved: (line: string) => void = logWarn,\n): void {\n for (const instance of instances ?? []) {\n onLine(`agent ${instance.id}: ${instance.files.join(\", \")}`);\n }\n for (const file of removedFiles ?? []) onRemoved(`Removed: ${file}`);\n}\n\n/**\n * Creates the `skaile install` command.\n *\n * Two modes, selected by argument shape:\n *\n * - `skaile install` (no positional arg) — reads `skaile.yaml` and deploys all\n * declared assets (and their transitive dependencies) to the configured\n * driver target directory. Supports `--locked` for CI-mode install from a\n * lock file.\n * - `skaile install kind:@<publisher>/<name>#<version>` — pointer-only catalog\n * install: resolves the pointer-only install manifest from the configured\n * Catalog, fetches each file's bytes directly from the upstream repo at the\n * pinned commit, verifies every per-file + the composite SHA256, then writes\n * the verified files into the local Library.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-install-command\n */\nexport function makeInstallCommand(): Command {\n return new Command(\"install\")\n .description(`Install dependencies from skaile.yaml, or a single asset by ref (${REF_HINT})`)\n .argument(\"[ref]\", `Asset ref to install from the Catalog (${REF_HINT})`)\n .option(\"--locked\", \"Install from lock file (CI mode — fails on drift)\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .option(\"--target <agent>\", `Agent framework (${TARGET_DEFAULT_HINT})`)\n .option(\n \"--global\",\n \"Install the global SSOT (~/.skaile/skaile.yaml), fanning out to every global harness\",\n )\n .option(\n \"--harness <ids>\",\n \"Comma-separated global harnesses to install into (default: all resolved); implies --global\",\n )\n .option(\n \"--link\",\n \"symlink local-path assets instead of copying (dev loop; machine-local, not for committing)\",\n )\n .action(runInstallCommand);\n}\n\n/** Options shape accepted by the `skaile install` command action. */\ninterface InstallCommandOptions {\n locked?: boolean;\n projectDir: string;\n target?: string;\n global?: boolean;\n harness?: string;\n link?: boolean;\n}\n\n/**\n * Parse a `--harness a,b` value into validated {@link DriverTarget}s, exiting on\n * an unknown id. Returns `undefined` when the flag is absent (resolve the full\n * global set instead).\n */\nfunction parseHarnessFilter(raw: string | undefined): DriverTarget[] | undefined {\n if (!raw) return undefined;\n const ids = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n const out: DriverTarget[] = [];\n for (const id of ids) {\n if (!(SUPPORTED_DRIVER_TARGETS as string[]).includes(id)) {\n logErr(`unknown harness '${id}' — expected one of: ${SUPPORTED_DRIVER_TARGETS.join(\", \")}`);\n process.exit(1);\n }\n out.push(id as DriverTarget);\n }\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * `skaile install` action body. Dispatches by argument shape:\n * a positional `ref` selects pointer-only catalog install, otherwise the\n * legacy `skaile.yaml` install path runs.\n */\nasync function runInstallCommand(\n ref: string | undefined,\n opts: InstallCommandOptions,\n): Promise<void> {\n // ── Pointer-only catalog install: `skaile install <ref>` ──────────────\n if (ref !== undefined) {\n await runRefInstall(ref, opts);\n return;\n }\n\n // ── Legacy install: `skaile install` reads skaile.yaml ────────────────\n await runYamlInstall(opts);\n}\n\n/** Pointer-only catalog install path for `skaile install <ref>`. */\nasync function runRefInstall(ref: string, opts: InstallCommandOptions): Promise<void> {\n if (!isValidAssetRef(ref)) {\n logErr(`malformed asset ref '${ref}' — expected ${REF_HINT}`);\n process.exit(1);\n }\n const spinner = createSpinner();\n spinner.start(`Installing ${ref}`);\n try {\n const { openCatalogSource, openLibrary } = await import(\"../open-library.ts\");\n const catalog = await openCatalogSource({ projectDir: path.resolve(opts.projectDir) });\n // [H2] REST-framed catalogs (the default for any catalog URL other\n // than https://skaile.store) cannot serve install manifests. Detect\n // and fail clearly rather than throwing a runtime TypeError.\n if (!supportsInstallManifest(catalog)) {\n throw new Error(\n \"pointer-only install (skaile install <ref>) requires a tRPC-framed Catalog. \" +\n \"The configured catalog uses REST framing, which does not serve install \" +\n \"manifests. Set catalog.url to https://skaile.store, or catalog.framing: trpc, \" +\n `in ${userConfigPath()}.`,\n );\n }\n const library = await openLibrary();\n try {\n const result = await runPointerOnlyInstall(ref, { catalog, library });\n spinner.stop(\"Done\");\n logOk(`Installed ${colorRef(ref)}`);\n logInfo(`Path: ${S.dim(result.installPath)}`);\n logInfo(`Commit: ${S.dim(result.commitSha)}`);\n logInfo(`Files: ${S.dim(String(result.fileCount))}`);\n logInfo(\n S.dim(\n `Installed globally (see Path above) — use \\`skaile add ${ref}\\` to deploy into this project.`,\n ),\n );\n } finally {\n library.close();\n }\n } catch (err) {\n spinner.stop(\"Failed\");\n const msg = err instanceof Error ? err.message : String(err);\n if (/unreachable/i.test(msg)) {\n logErr(`asset uninstallable — source commit no longer available (${msg})`);\n } else {\n logErr(msg);\n }\n process.exit(1);\n }\n}\n\n/** Legacy install path for bare `skaile install` (reads skaile.yaml). */\nasync function runYamlInstall(opts: InstallCommandOptions): Promise<void> {\n const projectDir = path.resolve(opts.projectDir);\n\n const harnesses = parseHarnessFilter(opts.harness);\n // `--harness` implies `--global`.\n if (opts.global || harnesses) {\n await runGlobalInstall(opts, harnesses);\n return;\n }\n\n // Hydrate sources declared in skaile.yaml before resolving assets, so\n // freshly checked-out projects pull their source clones automatically.\n try {\n const { ensureSourcesCloned } = await import(\"../ensure-sources.ts\");\n const hydrate = ensureSourcesCloned(projectDir, { quiet: true });\n if (hydrate.cloned.length > 0) {\n logOk(`Cloned source(s): ${hydrate.cloned.join(\", \")}`);\n }\n if (hydrate.failed.length > 0) {\n logErr(`Failed to clone source(s): ${hydrate.failed.join(\", \")}`);\n }\n } catch (err) {\n logWarn(`source hydration skipped: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n const warnings = deferredWarnings();\n const am = new AssetManager({\n registry: getKindRegistry(),\n projectDir,\n driverTarget: opts.target as DriverTarget,\n onLibraryCollision: warnings.push,\n });\n const spinner = createSpinner();\n spinner.start(opts.locked ? \"Installing from lock file\" : \"Installing dependencies\");\n try {\n const result = await am.install({ locked: opts.locked, link: opts.link });\n spinner.stop(\"Done\");\n warnings.flush();\n if (result.deployed.length > 0) {\n for (const d of result.deployed) logOk(d);\n }\n reportPresetExpansions(result.presets);\n reportAgentInstances(result.agentInstances, result.agentFilesRemoved);\n if (result.removed.length > 0) {\n for (const r of result.removed) logWarn(`Removed: ${r}`);\n }\n if (\n result.deployed.length === 0 &&\n result.removed.length === 0 &&\n result.missing.length === 0\n ) {\n logInfo(\"Nothing to install (already up to date).\");\n }\n if (result.missing.length > 0) {\n for (const m of result.missing) logErr(`Missing: ${m}${result.missingHints?.[m] ?? \"\"}`);\n // Partial-miss must fail the process — CI can't otherwise distinguish a\n // clean install from \"half the assets never resolved\".\n process.exitCode = 1;\n }\n if (result.lockWritten) {\n logInfo(`Lock file written: ${S.dim(\"skaile.lock.yaml\")}`);\n }\n warnLegacyClaudeCopies(am);\n // Report-only: surface soft deps the declared assets reference but aren't\n // present. Never a prompt — install is a batch/CI path. Skipped under\n // --locked: that mode is \"restore exactly\", so an `add` nudge would jar.\n if (!opts.locked) await reportInstalledSoftDeps(am);\n } catch (err) {\n spinner.stop(\"Failed\");\n warnings.flush();\n logErr(String(err));\n process.exit(1);\n }\n}\n\n/**\n * Report (never prompt) the body-link soft deps that the declared assets\n * reference but that aren't in the project — the `install` counterpart to the\n * `add`-time soft-dep surface. `install` is a batch/CI path (often non-TTY), so\n * it only ever prints a hint: pulling stays an explicit `skaile add`. Best-effort\n * — `reportSoftDeps` swallows any index failure and returns `[]`.\n */\nexport async function reportInstalledSoftDeps(\n am: Pick<AssetManager, \"listDeclared\" | \"reportSoftDeps\">,\n onHint: (line: string) => void = (l) => logInfo(S.dim(l)),\n): Promise<void> {\n try {\n const declared = (await am.listDeclared()).map((d) => d.ref);\n if (declared.length === 0) return;\n const edges = await am.reportSoftDeps(declared);\n for (const edge of edges) onHint(formatSoftDepHint(edge));\n } catch {\n // Best-effort: a soft-dep report must never fail an install that succeeded.\n }\n}\n\n/**\n * Global cross-harness install: deploy every dep declared in the global SSOT\n * (`~/.skaile/skaile.yaml`) into each resolved global harness's dir under `~`,\n * write the global lock (`~/.skaile/skaile.lock.yaml`), then print per-harness\n * state. `harnesses` is the `--harness` filter (omit for the full resolved set).\n */\nasync function runGlobalInstall(\n opts: InstallCommandOptions,\n harnesses: DriverTarget[] | undefined,\n): Promise<void> {\n const warnings = deferredWarnings();\n const am = new AssetManager({\n registry: getKindRegistry(),\n projectDir: path.resolve(opts.projectDir),\n global: true,\n harnesses,\n onLibraryCollision: warnings.push,\n });\n const spinner = createSpinner();\n spinner.start(\"Installing global dependencies\");\n try {\n const result = await am.install({ locked: opts.locked, link: opts.link });\n spinner.stop(\"Done\");\n warnings.flush();\n if (result.deployed.length > 0) for (const d of result.deployed) logOk(d);\n reportPresetExpansions(result.presets);\n if (result.removed.length > 0) for (const r of result.removed) logWarn(`Removed: ${r}`);\n if (result.deployed.length === 0 && result.removed.length === 0 && result.missing.length === 0)\n logInfo(\"Nothing to install (already up to date).\");\n if (result.missing.length > 0) {\n for (const m of result.missing) logErr(`Missing: ${m}${result.missingHints?.[m] ?? \"\"}`);\n process.exitCode = 1;\n }\n if (result.lockWritten) logInfo(`Global lock written: ${S.dim(\"~/.skaile/skaile.lock.yaml\")}`);\n\n // Per-harness reconciliation summary so a partial fan-out is visible.\n const state = am.globalState({});\n const byHarness = new Map<string, number>();\n for (const s of state)\n if (s.state === \"installed\") byHarness.set(s.harness, (byHarness.get(s.harness) ?? 0) + 1);\n for (const [harness, n] of byHarness) logInfo(`${harness}: ${n} installed`);\n } catch (err) {\n spinner.stop(\"Failed\");\n warnings.flush();\n logErr(String(err));\n process.exit(1);\n }\n}\n\n/**\n * Creates the `skaile check` command.\n *\n * Scans all deployed assets for unmet dependency requirements **and** the\n * declared set for deps that never materialized, and exits with code 1 if\n * either is found. `doctor()` alone only walks *deployed* assets' `requires`, so\n * a declared dep whose bytes never landed (e.g. a store-sourced `mcp-server`)\n * used to report \"satisfied\" (#462). A declared dep that is not in the lock at\n * all (its library or source is gone) fails the check too, like `skaile list`\n * showing it as `declared`.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-check-command\n */\nexport function makeCheckCommand(): Command {\n return new Command(\"check\")\n .description(\"Check for unmet requirements\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .action(async (opts) => {\n const am = new AssetManager({\n registry: getKindRegistry(),\n projectDir: path.resolve(opts.projectDir),\n });\n const issues = await am.doctor();\n // A project with no (or an unreadable) skaile.yaml has no declared set to\n // reconcile — treat it as drift-free so `check` behaves as it always has.\n let notInstalled: DeclaredAsset[] = [];\n try {\n notInstalled = (await am.listDeclared()).filter((d) => d.state !== \"installed\");\n } catch {\n // ignored — doctor() below is still authoritative for deployed assets.\n }\n if (issues.length === 0 && notInstalled.length === 0) {\n logOk(\"All dependencies satisfied.\");\n } else {\n for (const i of issues) {\n if (i.unresolved) {\n logErr(\n `${i.assetKind}:${i.assetName} is locked but no source or library provides it any more — its requirements cannot be checked`,\n );\n continue;\n }\n logErr(\n `${i.assetKind}:${i.assetName} requires ${i.depKind}:${i.depName} (${i.inRepos ? \"fixable\" : \"not found\"})`,\n );\n }\n for (const d of notInstalled) {\n logErr(\n d.state === \"invalid\"\n ? `${d.ref} is not a valid asset ref (expected ${REF_HINT})`\n : d.state === \"drift\"\n ? `${d.ref} is declared and locked but not materialized — run \\`skaile install\\``\n : `${d.ref} is declared but does not resolve — run \\`skaile install\\``,\n );\n }\n process.exit(1);\n }\n });\n}\n\n/**\n * Creates the `skaile clean` command.\n *\n * Removes all skaile-managed assets tracked in `skaile.lock.yaml` from the\n * workspace. With `--all` also removes history, patches, repos, and the lock\n * file itself. Preserves unmanaged (manually placed) assets.\n *\n * @returns Configured {@link Command} ready for `program.addCommand()`.\n * @docLink cli/commands/project#make-clean-command\n */\nexport function makeCleanCommand(): Command {\n return new Command(\"clean\")\n .description(\"Remove all skaile-managed assets from the workspace\")\n .option(\"--all\", \"Full reset: also remove history, patches, repos, and lock file\")\n .option(\"--dry-run\", \"Show what would be removed without doing it\")\n .option(\"-y, --yes\", \"Skip confirmation prompt\")\n .option(\"--project-dir <path>\", \"Project directory\", process.cwd())\n .option(\"--target <agent>\", `Agent framework (${TARGET_DEFAULT_HINT})`)\n .action(async (opts) => {\n const am = new AssetManager({\n registry: getKindRegistry(),\n projectDir: path.resolve(opts.projectDir),\n driverTarget: opts.target as DriverTarget,\n });\n\n // Preview: load lock file to show what will be cleaned\n const lock = readLock(path.resolve(opts.projectDir, \"skaile.lock.yaml\"));\n\n if (!lock || Object.keys(lock.assets).length === 0) {\n logInfo(\"Nothing to clean (no skaile-managed assets found).\");\n return;\n }\n\n const assetRefs = Object.keys(lock.assets);\n console.log();\n console.log(` ${S.heading(\"Assets to remove:\")} ${S.dim(`(${assetRefs.length})`)}`);\n for (const ref of assetRefs) {\n console.log(` ${colorRef(ref)}`);\n }\n\n if (opts.all) {\n console.log();\n console.log(` ${S.heading(\"Also removing:\")}`);\n console.log(` ${S.dim(\".skaile/history.yaml\")}`);\n console.log(` ${S.dim(\".skaile/patches/\")}`);\n console.log(` ${S.dim(\"skaile.lock.yaml\")}`);\n }\n\n if (opts.dryRun) {\n console.log();\n logInfo(\"Dry run — no changes made.\");\n return;\n }\n\n if (!opts.yes) {\n const confirm = await p.confirm({ message: \"Proceed?\" });\n if (p.isCancel(confirm) || !confirm) {\n logInfo(\"Cancelled.\");\n return;\n }\n }\n\n const result = am.clean({ all: opts.all });\n\n console.log();\n for (const r of result.removed) {\n logOk(`Removed ${r}`);\n }\n for (const s of result.skipped) {\n logWarn(`Skipped ${s.ref}: ${s.reason}`);\n }\n if (result.unmanaged.length > 0) {\n console.log();\n logInfo(`Kept ${result.unmanaged.length} unmanaged asset(s):`);\n for (const u of result.unmanaged) {\n console.log(` ${S.dim(u)}`);\n }\n }\n if (opts.all) {\n console.log();\n logOk(\"Full reset complete.\");\n }\n });\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { compositeSha256 } from './chunk-7ZHLYXTI.js';
2
- import { parseAssetRef } from './chunk-AO7VJ6G6.js';
1
+ import { compositeSha256 } from './chunk-RVIZQ5XD.js';
2
+ import { parseAssetRef } from './chunk-O7VPNKYN.js';
3
3
  import { createHash } from 'crypto';
4
4
  import { rm, mkdir, writeFile } from 'fs/promises';
5
5
  import { isAbsolute, resolve, sep, join, dirname } from 'path';
@@ -123,5 +123,5 @@ async function installFlat(manifest, targetDir, fetcher) {
123
123
  }
124
124
 
125
125
  export { assertSafeManifestPath, installFromManifest, longestCommonDirPrefix };
126
- //# sourceMappingURL=chunk-BTISGSK4.js.map
127
- //# sourceMappingURL=chunk-BTISGSK4.js.map
126
+ //# sourceMappingURL=chunk-FAP63KV7.js.map
127
+ //# sourceMappingURL=chunk-FAP63KV7.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../library/src/install/install-from-manifest.ts"],"names":[],"mappings":"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","file":"chunk-BTISGSK4.js","sourcesContent":["/**\n * Pointer-only install path.\n *\n * Given an {@link InstallManifest} (the Pointer Triple the Catalog hands\n * clients), this:\n *\n * 1. fetches the asset bytes directly from the upstream repo at the pinned\n * commit (via an injectable fetcher, default {@link fetchAssetFilesFromGitHub});\n * 2. verifies EVERY per-file SHA256 against `manifest.files[].sha256`;\n * 3. verifies the composite SHA256 rollup over the sorted\n * `<path>:<sha256>\\n` lines against `manifest.sha256`;\n * 4. writes the verified bytes under `<libraryRoot>/@<publisher>/<name>/<version>`.\n *\n * Any hash mismatch is a hard failure — bytes are not written if per-file\n * verification fails, and the composite check is the second gate.\n *\n * @docLink packages/library/concepts#install\n */\n\nimport { createHash } from \"node:crypto\";\nimport { mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve, sep } from \"node:path\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\n// Narrow module, not the `core` barrel: the barrel's chunks carry `import.meta`,\n// which breaks consumers that transpile this entry to CommonJS.\nimport { parseAssetRef } from \"../../../core/src/models.js\";\nimport { compositeSha256 } from \"../../../core/src/publish-manifest.js\";\n\n/**\n * Validate a single manifest-supplied file path against path traversal.\n *\n * `manifest.files[].path` comes off the network — the attacker controls the\n * entire manifest (and therefore every hash in it), so hash verification can\n * NEVER mitigate a malicious *destination*. A path like\n * `../../../../home/user/.bashrc` or an absolute path would escape\n * `installPath` and yield an arbitrary file write. Every path is checked\n * BEFORE any fetch or write happens; the first bad path aborts the entire\n * install with a hard throw.\n *\n * A path is rejected if ANY of:\n * - it is empty;\n * - it is absolute (`path.isAbsolute`) or has a leading slash;\n * - it contains a `..` segment;\n * - `path.resolve(installPath, p)` is not `installPath` itself and does not\n * start with `installPath + path.sep` (escapes the install dir).\n *\n * @throws An error matching `/unsafe path in manifest/` on the first bad path.\n */\nexport function assertSafeManifestPath(installPath: string, p: string): void {\n const bad = (): never => {\n throw new Error(`unsafe path in manifest: ${p}`);\n };\n if (!p || p.length === 0) bad();\n if (isAbsolute(p) || p.startsWith(\"/\") || p.startsWith(\"\\\\\")) bad();\n const segments = p.split(/[/\\\\]/);\n if (segments.some((s) => s === \"..\")) bad();\n const resolved = resolve(installPath, p);\n if (resolved !== installPath && !resolved.startsWith(installPath + sep)) bad();\n}\n\n/**\n * Validate one component (publisher / name / version) of the attacker-controlled\n * `manifest.ref`.\n *\n * `installPath` is built by joining these components onto `libraryRoot`. A\n * component containing a path separator or a `..` / leading-dot segment would\n * let `installPath` itself escape `libraryRoot` — yielding an arbitrary file\n * write AND, via the pre-write `rm(installPath, { recursive })`, an arbitrary\n * recursive delete. The per-file `assertSafeManifestPath` guard cannot catch\n * this: it only validates each `f.path` *relative to* `installPath`, never\n * `installPath` itself. Components must be plain identifier-like strings.\n *\n * @throws An error matching `/unsafe ref/` on a bad component.\n */\nfunction assertSafeRefComponent(kind: string, value: string): void {\n // Reject empty, leading-dot (covers `.` and `..`), path separators, and\n // ASCII control characters (NUL et al.) — fails a malformed segment fast\n // with a domain-specific error rather than a raw EINVAL deeper in.\n const hasControlChar = [...value].some((c) => c.charCodeAt(0) < 0x20);\n if (!value || value.startsWith(\".\") || /[/\\\\]/.test(value) || hasControlChar) {\n throw new Error(`unsafe ref ${kind} component in manifest: '${value}'`);\n }\n}\n\n/**\n * Longest common **directory** prefix across manifest paths, compared by whole\n * slash-delimited segments (never raw-string — so `app/` and `app-data/` never\n * collide). Each path's basename is excluded, so the result is always a\n * directory prefix and every path keeps a non-empty remainder after stripping.\n *\n * Used by flat mode to reproduce the platform pointer-installer's asset-rooting:\n * the store persists repo-root-relative paths (e.g. `skaile-platform/mcpo/xls/MCP.md`)\n * but the runner scans `.skaile/assets/<kind>/<name>/` for immediate-child files,\n * so this prefix is stripped from the WRITE path while the fetch keeps the full\n * repo path. Returns `''` when there is no common directory (a no-op strip).\n */\nexport function longestCommonDirPrefix(paths: readonly string[]): string {\n if (paths.length === 0) return \"\";\n const dirSegments = paths.map((p) => p.split(\"/\").slice(0, -1));\n let common = dirSegments[0]!;\n for (let i = 1; i < dirSegments.length && common.length > 0; i++) {\n const segs = dirSegments[i]!;\n let n = 0;\n while (n < common.length && n < segs.length && common[n] === segs[n]) n++;\n common = common.slice(0, n);\n }\n return common.join(\"/\");\n}\n\n/**\n * Fetcher signature — fetches `{ path → Buffer }` for the requested paths at\n * a pinned upstream commit. {@link fetchAssetFilesFromGitHub} is the default\n * production implementation; tests inject a mock.\n */\nexport type AssetFetcher = (opts: {\n url: string;\n commitSha: string;\n paths: string[];\n}) => Promise<Record<string, Buffer>>;\n\n/**\n * Options for {@link installFromManifest}.\n */\nexport interface InstallOpts {\n /** The pointer-only install manifest from the Catalog. */\n manifest: InstallManifest;\n /** Filesystem root the asset is installed under (ref-derived mode). */\n libraryRoot: string;\n /**\n * Pluggable fetcher so tests can inject mock data. Defaults to\n * {@link fetchAssetFilesFromGitHub} in production.\n */\n fetcher?: AssetFetcher;\n /**\n * Flat-layout mode. When set, install-core reproduces the platform\n * pointer-installer's behavior: it ignores `libraryRoot`/ref-derivation, does\n * NOT parse `manifest.ref` and does NOT verify the composite sha256, strips\n * the longest-common-dir prefix from each path, per-file sha256-verifies, and\n * writes the stripped paths as immediate children of `targetDir` (what the\n * runner's `.skaile/assets/<kind>/<name>/` scan requires). `installPath` is\n * `targetDir`. Absent → unchanged ref-derived `@<pub>/name/version/<path>`\n * layout with composite verify.\n */\n targetDir?: string;\n}\n\n/**\n * Result of a successful {@link installFromManifest} call.\n */\nexport interface InstallResult {\n /** Absolute path the asset files were written to. */\n installPath: string;\n}\n\n/**\n * Fetch, verify, and write an asset's files per its {@link InstallManifest}.\n *\n * @throws An error matching `/hash mismatch/i` if any per-file SHA256 differs.\n * @throws An error matching `/composite hash mismatch/i` if the rollup differs.\n * @throws An error if the ref is malformed or the fetcher omits a file.\n */\nexport async function installFromManifest(opts: InstallOpts): Promise<InstallResult> {\n const { manifest, libraryRoot } = opts;\n const fetcher =\n opts.fetcher ?? (await import(\"./source-fetch-github.js\")).fetchAssetFilesFromGitHub;\n\n // Flat mode: reproduce the platform pointer-installer's asset-rooted layout.\n // No ref parse, no composite verify — the platform store may not satisfy a\n // ref-grammar or composite, and the runner only needs immediate-child files.\n if (opts.targetDir !== undefined) {\n return installFlat(manifest, opts.targetDir, fetcher);\n }\n\n // 1. Parse ref into install path: `skill:@x/git#1.0.0` → `<root>/@x/git/1.0.0`.\n // Done first so the C1 path-traversal guard can resolve against installPath\n // BEFORE any network fetch happens. The ref is attacker-controlled, so each\n // segment is further validated as a safe path component (H1) after parsing.\n // `parseAssetRef` is the single canonical grammar (`kind:@publisher/name#version`);\n // the legacy trailing-`@version` shape was removed in core and is rejected here.\n let parsed: ReturnType<typeof parseAssetRef>;\n try {\n parsed = parseAssetRef(manifest.ref);\n } catch (e) {\n throw new Error(`invalid ref: ${manifest.ref}: ${e instanceof Error ? e.message : String(e)}`);\n }\n const publisher = parsed.publisher;\n const name = parsed.name;\n const version = parsed.pin;\n if (!publisher) throw new Error(`invalid ref: ${manifest.ref} (missing publisher)`);\n if (!version) throw new Error(`invalid ref: ${manifest.ref} (missing version pin)`);\n assertSafeRefComponent(\"publisher\", publisher);\n assertSafeRefComponent(\"name\", name);\n assertSafeRefComponent(\"version\", version);\n const root = resolve(libraryRoot);\n const installPath = resolve(join(root, `@${publisher}`, name, version));\n // Defense in depth: even with the segment guards above, assert the built\n // installPath stays strictly inside libraryRoot before any write or `rm`.\n if (installPath !== root && !installPath.startsWith(root + sep)) {\n throw new Error(`unsafe install path: ref '${manifest.ref}' resolves outside the library root`);\n }\n\n // 2. [C1] Validate EVERY manifest path against traversal BEFORE fetching.\n // The attacker controls the manifest (and thus all hashes) — hashes verify\n // content, never destination. Reject the whole install on the first bad path.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n }\n\n // 3. Fetch all files at the pinned commit.\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // 4. Verify per-file SHA256 — hard fail before writing anything. The path\n // key used to read from the fetcher result is re-guarded as defense in depth.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n }\n\n // 5. Verify composite SHA256 over the sorted `<path>:<sha256>\\n` lines.\n const actualComposite = compositeSha256(manifest.files);\n if (actualComposite !== manifest.sha256) {\n throw new Error(`composite hash mismatch: expected ${manifest.sha256}, got ${actualComposite}`);\n }\n\n // 6. [M1] Write all verified files. A failed install must leave NO partial\n // directory: any prior `installPath` is removed first (clean overwrite), and\n // a mid-loop write failure removes the partially-written tree before\n // rethrowing.\n await rm(installPath, { recursive: true, force: true });\n try {\n for (const f of manifest.files) {\n const target = join(installPath, f.path);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, bytes[f.path]!);\n }\n } catch (e) {\n await rm(installPath, { recursive: true, force: true }).catch(() => {});\n throw e;\n }\n\n return { installPath };\n}\n\n/**\n * Flat-layout install — the platform pointer-installer's behavior, made canonical\n * in install-core. Validates every path, fetches with the FULL repo paths, per-file\n * sha256-verifies, then strips the longest-common-dir prefix and writes each file\n * as `join(targetDir, path.slice(assetRoot.length + 1))` — immediate children of\n * `targetDir`. No ref parse, no composite check.\n */\nasync function installFlat(\n manifest: InstallManifest,\n targetDir: string,\n fetcher: AssetFetcher,\n): Promise<InstallResult> {\n const target = resolve(targetDir);\n\n // Gate every path before any fetch — the attacker controls the whole manifest.\n for (const f of manifest.files) {\n assertSafeManifestPath(target, f.path);\n }\n\n // Fetch keys off the FULL repo path (matches the upstream tree).\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // Strip the asset-root dir prefix from the WRITE path only — the fetch above\n // still keyed off the full repo path. Stripping removes leading whole segments\n // (never the basename), so a non-empty remainder always survives.\n const assetRoot = longestCommonDirPrefix(paths);\n\n for (const f of manifest.files) {\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n const relPath = assetRoot ? f.path.slice(assetRoot.length + 1) : f.path;\n // Re-guard the post-strip destination — it is what we actually write.\n assertSafeManifestPath(target, relPath);\n const dest = join(target, relPath);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, buf);\n }\n\n return { installPath: target };\n}\n"]}
1
+ {"version":3,"sources":["../library/src/install/install-from-manifest.ts"],"names":[],"mappings":"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","file":"chunk-FAP63KV7.js","sourcesContent":["/**\n * Pointer-only install path.\n *\n * Given an {@link InstallManifest} (the Pointer Triple the Catalog hands\n * clients), this:\n *\n * 1. fetches the asset bytes directly from the upstream repo at the pinned\n * commit (via an injectable fetcher, default {@link fetchAssetFilesFromGitHub});\n * 2. verifies EVERY per-file SHA256 against `manifest.files[].sha256`;\n * 3. verifies the composite SHA256 rollup over the sorted\n * `<path>:<sha256>\\n` lines against `manifest.sha256`;\n * 4. writes the verified bytes under `<libraryRoot>/@<publisher>/<name>/<version>`.\n *\n * Any hash mismatch is a hard failure — bytes are not written if per-file\n * verification fails, and the composite check is the second gate.\n *\n * @docLink packages/library/concepts#install\n */\n\nimport { createHash } from \"node:crypto\";\nimport { mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve, sep } from \"node:path\";\nimport type { InstallManifest } from \"@skaile/workspaces/types\";\n// Narrow module, not the `core` barrel: the barrel's chunks carry `import.meta`,\n// which breaks consumers that transpile this entry to CommonJS.\nimport { parseAssetRef } from \"../../../core/src/models.js\";\nimport { compositeSha256 } from \"../../../core/src/publish-manifest.js\";\n\n/**\n * Validate a single manifest-supplied file path against path traversal.\n *\n * `manifest.files[].path` comes off the network — the attacker controls the\n * entire manifest (and therefore every hash in it), so hash verification can\n * NEVER mitigate a malicious *destination*. A path like\n * `../../../../home/user/.bashrc` or an absolute path would escape\n * `installPath` and yield an arbitrary file write. Every path is checked\n * BEFORE any fetch or write happens; the first bad path aborts the entire\n * install with a hard throw.\n *\n * A path is rejected if ANY of:\n * - it is empty;\n * - it is absolute (`path.isAbsolute`) or has a leading slash;\n * - it contains a `..` segment;\n * - `path.resolve(installPath, p)` is not `installPath` itself and does not\n * start with `installPath + path.sep` (escapes the install dir).\n *\n * @throws An error matching `/unsafe path in manifest/` on the first bad path.\n */\nexport function assertSafeManifestPath(installPath: string, p: string): void {\n const bad = (): never => {\n throw new Error(`unsafe path in manifest: ${p}`);\n };\n if (!p || p.length === 0) bad();\n if (isAbsolute(p) || p.startsWith(\"/\") || p.startsWith(\"\\\\\")) bad();\n const segments = p.split(/[/\\\\]/);\n if (segments.some((s) => s === \"..\")) bad();\n const resolved = resolve(installPath, p);\n if (resolved !== installPath && !resolved.startsWith(installPath + sep)) bad();\n}\n\n/**\n * Validate one component (publisher / name / version) of the attacker-controlled\n * `manifest.ref`.\n *\n * `installPath` is built by joining these components onto `libraryRoot`. A\n * component containing a path separator or a `..` / leading-dot segment would\n * let `installPath` itself escape `libraryRoot` — yielding an arbitrary file\n * write AND, via the pre-write `rm(installPath, { recursive })`, an arbitrary\n * recursive delete. The per-file `assertSafeManifestPath` guard cannot catch\n * this: it only validates each `f.path` *relative to* `installPath`, never\n * `installPath` itself. Components must be plain identifier-like strings.\n *\n * @throws An error matching `/unsafe ref/` on a bad component.\n */\nfunction assertSafeRefComponent(kind: string, value: string): void {\n // Reject empty, leading-dot (covers `.` and `..`), path separators, and\n // ASCII control characters (NUL et al.) — fails a malformed segment fast\n // with a domain-specific error rather than a raw EINVAL deeper in.\n const hasControlChar = [...value].some((c) => c.charCodeAt(0) < 0x20);\n if (!value || value.startsWith(\".\") || /[/\\\\]/.test(value) || hasControlChar) {\n throw new Error(`unsafe ref ${kind} component in manifest: '${value}'`);\n }\n}\n\n/**\n * Longest common **directory** prefix across manifest paths, compared by whole\n * slash-delimited segments (never raw-string — so `app/` and `app-data/` never\n * collide). Each path's basename is excluded, so the result is always a\n * directory prefix and every path keeps a non-empty remainder after stripping.\n *\n * Used by flat mode to reproduce the platform pointer-installer's asset-rooting:\n * the store persists repo-root-relative paths (e.g. `skaile-platform/mcpo/xls/MCP.md`)\n * but the runner scans `.skaile/assets/<kind>/<name>/` for immediate-child files,\n * so this prefix is stripped from the WRITE path while the fetch keeps the full\n * repo path. Returns `''` when there is no common directory (a no-op strip).\n */\nexport function longestCommonDirPrefix(paths: readonly string[]): string {\n if (paths.length === 0) return \"\";\n const dirSegments = paths.map((p) => p.split(\"/\").slice(0, -1));\n let common = dirSegments[0]!;\n for (let i = 1; i < dirSegments.length && common.length > 0; i++) {\n const segs = dirSegments[i]!;\n let n = 0;\n while (n < common.length && n < segs.length && common[n] === segs[n]) n++;\n common = common.slice(0, n);\n }\n return common.join(\"/\");\n}\n\n/**\n * Fetcher signature — fetches `{ path → Buffer }` for the requested paths at\n * a pinned upstream commit. {@link fetchAssetFilesFromGitHub} is the default\n * production implementation; tests inject a mock.\n */\nexport type AssetFetcher = (opts: {\n url: string;\n commitSha: string;\n paths: string[];\n}) => Promise<Record<string, Buffer>>;\n\n/**\n * Options for {@link installFromManifest}.\n */\nexport interface InstallOpts {\n /** The pointer-only install manifest from the Catalog. */\n manifest: InstallManifest;\n /** Filesystem root the asset is installed under (ref-derived mode). */\n libraryRoot: string;\n /**\n * Pluggable fetcher so tests can inject mock data. Defaults to\n * {@link fetchAssetFilesFromGitHub} in production.\n */\n fetcher?: AssetFetcher;\n /**\n * Flat-layout mode. When set, install-core reproduces the platform\n * pointer-installer's behavior: it ignores `libraryRoot`/ref-derivation, does\n * NOT parse `manifest.ref` and does NOT verify the composite sha256, strips\n * the longest-common-dir prefix from each path, per-file sha256-verifies, and\n * writes the stripped paths as immediate children of `targetDir` (what the\n * runner's `.skaile/assets/<kind>/<name>/` scan requires). `installPath` is\n * `targetDir`. Absent → unchanged ref-derived `@<pub>/name/version/<path>`\n * layout with composite verify.\n */\n targetDir?: string;\n}\n\n/**\n * Result of a successful {@link installFromManifest} call.\n */\nexport interface InstallResult {\n /** Absolute path the asset files were written to. */\n installPath: string;\n}\n\n/**\n * Fetch, verify, and write an asset's files per its {@link InstallManifest}.\n *\n * @throws An error matching `/hash mismatch/i` if any per-file SHA256 differs.\n * @throws An error matching `/composite hash mismatch/i` if the rollup differs.\n * @throws An error if the ref is malformed or the fetcher omits a file.\n */\nexport async function installFromManifest(opts: InstallOpts): Promise<InstallResult> {\n const { manifest, libraryRoot } = opts;\n const fetcher =\n opts.fetcher ?? (await import(\"./source-fetch-github.js\")).fetchAssetFilesFromGitHub;\n\n // Flat mode: reproduce the platform pointer-installer's asset-rooted layout.\n // No ref parse, no composite verify — the platform store may not satisfy a\n // ref-grammar or composite, and the runner only needs immediate-child files.\n if (opts.targetDir !== undefined) {\n return installFlat(manifest, opts.targetDir, fetcher);\n }\n\n // 1. Parse ref into install path: `skill:@x/git#1.0.0` → `<root>/@x/git/1.0.0`.\n // Done first so the C1 path-traversal guard can resolve against installPath\n // BEFORE any network fetch happens. The ref is attacker-controlled, so each\n // segment is further validated as a safe path component (H1) after parsing.\n // `parseAssetRef` is the single canonical grammar (`kind:@publisher/name#version`);\n // the legacy trailing-`@version` shape was removed in core and is rejected here.\n let parsed: ReturnType<typeof parseAssetRef>;\n try {\n parsed = parseAssetRef(manifest.ref);\n } catch (e) {\n throw new Error(`invalid ref: ${manifest.ref}: ${e instanceof Error ? e.message : String(e)}`);\n }\n const publisher = parsed.publisher;\n const name = parsed.name;\n const version = parsed.pin;\n if (!publisher) throw new Error(`invalid ref: ${manifest.ref} (missing publisher)`);\n if (!version) throw new Error(`invalid ref: ${manifest.ref} (missing version pin)`);\n assertSafeRefComponent(\"publisher\", publisher);\n assertSafeRefComponent(\"name\", name);\n assertSafeRefComponent(\"version\", version);\n const root = resolve(libraryRoot);\n const installPath = resolve(join(root, `@${publisher}`, name, version));\n // Defense in depth: even with the segment guards above, assert the built\n // installPath stays strictly inside libraryRoot before any write or `rm`.\n if (installPath !== root && !installPath.startsWith(root + sep)) {\n throw new Error(`unsafe install path: ref '${manifest.ref}' resolves outside the library root`);\n }\n\n // 2. [C1] Validate EVERY manifest path against traversal BEFORE fetching.\n // The attacker controls the manifest (and thus all hashes) — hashes verify\n // content, never destination. Reject the whole install on the first bad path.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n }\n\n // 3. Fetch all files at the pinned commit.\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // 4. Verify per-file SHA256 — hard fail before writing anything. The path\n // key used to read from the fetcher result is re-guarded as defense in depth.\n for (const f of manifest.files) {\n assertSafeManifestPath(installPath, f.path);\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n }\n\n // 5. Verify composite SHA256 over the sorted `<path>:<sha256>\\n` lines.\n const actualComposite = compositeSha256(manifest.files);\n if (actualComposite !== manifest.sha256) {\n throw new Error(`composite hash mismatch: expected ${manifest.sha256}, got ${actualComposite}`);\n }\n\n // 6. [M1] Write all verified files. A failed install must leave NO partial\n // directory: any prior `installPath` is removed first (clean overwrite), and\n // a mid-loop write failure removes the partially-written tree before\n // rethrowing.\n await rm(installPath, { recursive: true, force: true });\n try {\n for (const f of manifest.files) {\n const target = join(installPath, f.path);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, bytes[f.path]!);\n }\n } catch (e) {\n await rm(installPath, { recursive: true, force: true }).catch(() => {});\n throw e;\n }\n\n return { installPath };\n}\n\n/**\n * Flat-layout install — the platform pointer-installer's behavior, made canonical\n * in install-core. Validates every path, fetches with the FULL repo paths, per-file\n * sha256-verifies, then strips the longest-common-dir prefix and writes each file\n * as `join(targetDir, path.slice(assetRoot.length + 1))` — immediate children of\n * `targetDir`. No ref parse, no composite check.\n */\nasync function installFlat(\n manifest: InstallManifest,\n targetDir: string,\n fetcher: AssetFetcher,\n): Promise<InstallResult> {\n const target = resolve(targetDir);\n\n // Gate every path before any fetch — the attacker controls the whole manifest.\n for (const f of manifest.files) {\n assertSafeManifestPath(target, f.path);\n }\n\n // Fetch keys off the FULL repo path (matches the upstream tree).\n const paths = manifest.files.map((f) => f.path);\n const bytes = await fetcher({\n url: manifest.source.url,\n commitSha: manifest.source.commitSha,\n paths,\n });\n\n // Strip the asset-root dir prefix from the WRITE path only — the fetch above\n // still keyed off the full repo path. Stripping removes leading whole segments\n // (never the basename), so a non-empty remainder always survives.\n const assetRoot = longestCommonDirPrefix(paths);\n\n for (const f of manifest.files) {\n const buf = bytes[f.path];\n if (!buf) throw new Error(`fetcher returned no bytes for ${f.path}`);\n const actual = createHash(\"sha256\").update(buf).digest(\"hex\");\n if (actual !== f.sha256) {\n throw new Error(`hash mismatch for ${f.path}: expected ${f.sha256}, got ${actual}`);\n }\n const relPath = assetRoot ? f.path.slice(assetRoot.length + 1) : f.path;\n // Re-guard the post-strip destination — it is what we actually write.\n assertSafeManifestPath(target, relPath);\n const dest = join(target, relPath);\n await mkdir(dirname(dest), { recursive: true });\n await writeFile(dest, buf);\n }\n\n return { installPath: target };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { globalSkaileDir } from './chunk-MFHKHXDE.js';
1
+ import { globalSkaileDir } from './chunk-L5VSIPQD.js';
2
2
  import { DRIVER_TARGETS } from './chunk-CPSIPIX7.js';
3
3
  import { lstatSync } from 'fs';
4
4
  import { homedir } from 'os';
@@ -31,5 +31,5 @@ function isDeployed(kind, name, target, globalInstall, cwd) {
31
31
  }
32
32
 
33
33
  export { deployedBase, deployedDir, isDeployed };
34
- //# sourceMappingURL=chunk-46OVMT76.js.map
35
- //# sourceMappingURL=chunk-46OVMT76.js.map
34
+ //# sourceMappingURL=chunk-G67BOI2J.js.map
35
+ //# sourceMappingURL=chunk-G67BOI2J.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../core/src/store.ts"],"names":[],"mappings":";;;;;;AA6BO,SAAS,YAAA,CACd,IAAA,EACA,MAAA,EACA,aAAA,EACA,GAAA,EACQ;AACR,EAAA,MAAM,SAAA,GAAY,eAAe,MAAM,CAAA;AACvC,EAAA,IAAI,CAAC,SAAA,EAAW,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,MAAM,CAAA,CAAA,CAAG,CAAA;AACpE,EAAA,MAAM,KAAA,GAAQ,gBAAgB,QAAA,GAAW,OAAA;AACzC,EAAA,MAAM,KAAA,GAAQ,UAAU,KAAK,CAAA;AAC7B,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAI,CAAA,IAAK,MAAM,KAAA,IAAS,EAAA;AAC9C,EAAA,IAAI,aAAA,EAAe;AAGjB,IAAA,IAAI,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,UAAA,CAAW,YAAY,CAAA,EAAG;AAC/D,MAAA,OAAO,KAAK,eAAA,EAAgB,EAAG,QAAQ,KAAA,CAAM,WAAA,CAAY,MAAM,CAAC,CAAA;AAAA,IAClE;AACA,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,EAAM,OAAA,EAAS,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,GAAA,IAAO,OAAO,CAAA;AAC9C;AAaO,SAAS,WAAA,CACd,IAAA,EACA,IAAA,EACA,MAAA,EACA,eACA,GAAA,EACQ;AACR,EAAA,OAAO,KAAK,YAAA,CAAa,IAAA,EAAM,QAAQ,aAAA,EAAe,GAAG,GAAG,IAAI,CAAA;AAClE;AAcO,SAAS,UAAA,CACd,IAAA,EACA,IAAA,EACA,MAAA,EACA,eACA,GAAA,EACS;AACT,EAAA,IAAI;AACF,IAAA,SAAA,CAAU,YAAY,IAAA,EAAM,IAAA,EAAM,MAAA,EAAQ,aAAA,EAAe,GAAG,CAAC,CAAA;AAC7D,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF","file":"chunk-46OVMT76.js","sourcesContent":["/**\n * Deploy-target helpers — resolve framework-specific install paths.\n *\n * This module contains only deploy path resolution. All catalog, repository,\n * and history I/O has moved to @skaile/asset-manager (project-local).\n */\n\nimport { lstatSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { globalSkaileDir } from \"./cache-paths.js\";\nimport type { DriverTarget } from \"./driver-targets.js\";\nimport { type AiComponent, DRIVER_TARGETS } from \"./driver-targets.js\";\n\n// ── Deploy-target helpers ─────────────────────────────────────────────────────\n\n/**\n * Resolve the base deploy directory for an asset kind in a given driver target + scope.\n * For local scope, the path is relative to `cwd` (defaults to `process.cwd()`).\n * For global scope, `~` is expanded to the home directory.\n *\n * @param kind - Asset component type (e.g. `\"skill\"`, `\"agent\"`)\n * @param target - Driver target identifier (e.g. `\"claude-code\"`, `\"omp\"`)\n * @param globalInstall - `true` for user-global install, `false` for project-local\n * @param cwd - Working directory for project-local installs (default: `process.cwd()`)\n * @returns Absolute path to the base deploy directory\n * @throws When `target` is not found in `DRIVER_TARGETS`\n * @docLink packages/core/concepts#deployed-base\n */\nexport function deployedBase(\n kind: AiComponent,\n target: DriverTarget,\n globalInstall: boolean,\n cwd?: string,\n): string {\n const targetMap = DRIVER_TARGETS[target];\n if (!targetMap) throw new Error(`Unknown deploy target: '${target}'`);\n const scope = globalInstall ? \"global\" : \"local\";\n const paths = targetMap[scope];\n const destStr = paths[kind] ?? paths.skill ?? \"\";\n if (globalInstall) {\n // `~/.skaile/...` is skaile's own per-user root, so it follows `$SKAILE_HOME`;\n // every other `~/...` is a driver's home dir (`~/.claude`, `~/.omp`, ...).\n if (destStr === \"~/.skaile\" || destStr.startsWith(\"~/.skaile/\")) {\n return join(globalSkaileDir(), destStr.slice(\"~/.skaile\".length));\n }\n return destStr.replace(/^~/, homedir());\n }\n return resolve(cwd ?? process.cwd(), destStr);\n}\n\n/**\n * Return the full deploy path for a named asset: `<deployedBase>/<name>`.\n *\n * @param kind - Asset component type\n * @param name - Asset name (becomes the directory/file name under the base)\n * @param target - Driver target identifier\n * @param globalInstall - `true` for user-global, `false` for project-local\n * @param cwd - Working directory for local installs\n * @returns Absolute path to the asset's deploy directory\n * @docLink packages/core/concepts#deployed-dir\n */\nexport function deployedDir(\n kind: AiComponent,\n name: string,\n target: DriverTarget,\n globalInstall: boolean,\n cwd?: string,\n): string {\n return join(deployedBase(kind, target, globalInstall, cwd), name);\n}\n\n/**\n * Check whether an asset is already deployed at its expected location.\n * Uses `lstatSync` so symlinks are treated as deployed.\n *\n * @param kind - Asset component type\n * @param name - Asset name\n * @param target - Driver target identifier\n * @param globalInstall - `true` for user-global, `false` for project-local\n * @param cwd - Working directory for local installs\n * @returns `true` if the deploy path exists, `false` otherwise\n * @docLink packages/core/concepts#is-deployed\n */\nexport function isDeployed(\n kind: AiComponent,\n name: string,\n target: DriverTarget,\n globalInstall: boolean,\n cwd?: string,\n): boolean {\n try {\n lstatSync(deployedDir(kind, name, target, globalInstall, cwd));\n return true;\n } catch {\n return false;\n }\n}\n"]}
1
+ {"version":3,"sources":["../core/src/store.ts"],"names":[],"mappings":";;;;;;AA6BO,SAAS,YAAA,CACd,IAAA,EACA,MAAA,EACA,aAAA,EACA,GAAA,EACQ;AACR,EAAA,MAAM,SAAA,GAAY,eAAe,MAAM,CAAA;AACvC,EAAA,IAAI,CAAC,SAAA,EAAW,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,MAAM,CAAA,CAAA,CAAG,CAAA;AACpE,EAAA,MAAM,KAAA,GAAQ,gBAAgB,QAAA,GAAW,OAAA;AACzC,EAAA,MAAM,KAAA,GAAQ,UAAU,KAAK,CAAA;AAC7B,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAI,CAAA,IAAK,MAAM,KAAA,IAAS,EAAA;AAC9C,EAAA,IAAI,aAAA,EAAe;AAGjB,IAAA,IAAI,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,UAAA,CAAW,YAAY,CAAA,EAAG;AAC/D,MAAA,OAAO,KAAK,eAAA,EAAgB,EAAG,QAAQ,KAAA,CAAM,WAAA,CAAY,MAAM,CAAC,CAAA;AAAA,IAClE;AACA,IAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,EAAM,OAAA,EAAS,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,GAAA,IAAO,OAAO,CAAA;AAC9C;AAaO,SAAS,WAAA,CACd,IAAA,EACA,IAAA,EACA,MAAA,EACA,eACA,GAAA,EACQ;AACR,EAAA,OAAO,KAAK,YAAA,CAAa,IAAA,EAAM,QAAQ,aAAA,EAAe,GAAG,GAAG,IAAI,CAAA;AAClE;AAcO,SAAS,UAAA,CACd,IAAA,EACA,IAAA,EACA,MAAA,EACA,eACA,GAAA,EACS;AACT,EAAA,IAAI;AACF,IAAA,SAAA,CAAU,YAAY,IAAA,EAAM,IAAA,EAAM,MAAA,EAAQ,aAAA,EAAe,GAAG,CAAC,CAAA;AAC7D,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF","file":"chunk-G67BOI2J.js","sourcesContent":["/**\n * Deploy-target helpers — resolve framework-specific install paths.\n *\n * This module contains only deploy path resolution. All catalog, repository,\n * and history I/O has moved to @skaile/asset-manager (project-local).\n */\n\nimport { lstatSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { globalSkaileDir } from \"./cache-paths.js\";\nimport type { DriverTarget } from \"./driver-targets.js\";\nimport { type AiComponent, DRIVER_TARGETS } from \"./driver-targets.js\";\n\n// ── Deploy-target helpers ─────────────────────────────────────────────────────\n\n/**\n * Resolve the base deploy directory for an asset kind in a given driver target + scope.\n * For local scope, the path is relative to `cwd` (defaults to `process.cwd()`).\n * For global scope, `~` is expanded to the home directory.\n *\n * @param kind - Asset component type (e.g. `\"skill\"`, `\"agent\"`)\n * @param target - Driver target identifier (e.g. `\"claude-code\"`, `\"omp\"`)\n * @param globalInstall - `true` for user-global install, `false` for project-local\n * @param cwd - Working directory for project-local installs (default: `process.cwd()`)\n * @returns Absolute path to the base deploy directory\n * @throws When `target` is not found in `DRIVER_TARGETS`\n * @docLink packages/core/concepts#deployed-base\n */\nexport function deployedBase(\n kind: AiComponent,\n target: DriverTarget,\n globalInstall: boolean,\n cwd?: string,\n): string {\n const targetMap = DRIVER_TARGETS[target];\n if (!targetMap) throw new Error(`Unknown deploy target: '${target}'`);\n const scope = globalInstall ? \"global\" : \"local\";\n const paths = targetMap[scope];\n const destStr = paths[kind] ?? paths.skill ?? \"\";\n if (globalInstall) {\n // `~/.skaile/...` is skaile's own per-user root, so it follows `$SKAILE_HOME`;\n // every other `~/...` is a driver's home dir (`~/.claude`, `~/.omp`, ...).\n if (destStr === \"~/.skaile\" || destStr.startsWith(\"~/.skaile/\")) {\n return join(globalSkaileDir(), destStr.slice(\"~/.skaile\".length));\n }\n return destStr.replace(/^~/, homedir());\n }\n return resolve(cwd ?? process.cwd(), destStr);\n}\n\n/**\n * Return the full deploy path for a named asset: `<deployedBase>/<name>`.\n *\n * @param kind - Asset component type\n * @param name - Asset name (becomes the directory/file name under the base)\n * @param target - Driver target identifier\n * @param globalInstall - `true` for user-global, `false` for project-local\n * @param cwd - Working directory for local installs\n * @returns Absolute path to the asset's deploy directory\n * @docLink packages/core/concepts#deployed-dir\n */\nexport function deployedDir(\n kind: AiComponent,\n name: string,\n target: DriverTarget,\n globalInstall: boolean,\n cwd?: string,\n): string {\n return join(deployedBase(kind, target, globalInstall, cwd), name);\n}\n\n/**\n * Check whether an asset is already deployed at its expected location.\n * Uses `lstatSync` so symlinks are treated as deployed.\n *\n * @param kind - Asset component type\n * @param name - Asset name\n * @param target - Driver target identifier\n * @param globalInstall - `true` for user-global, `false` for project-local\n * @param cwd - Working directory for local installs\n * @returns `true` if the deploy path exists, `false` otherwise\n * @docLink packages/core/concepts#is-deployed\n */\nexport function isDeployed(\n kind: AiComponent,\n name: string,\n target: DriverTarget,\n globalInstall: boolean,\n cwd?: string,\n): boolean {\n try {\n lstatSync(deployedDir(kind, name, target, globalInstall, cwd));\n return true;\n } catch {\n return false;\n }\n}\n"]}