@skaile/workspaces 5.15.1 → 5.17.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 (398) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/dist/app-sdk/index.js +1 -1
  3. package/dist/{asset-feeds-FVDNQ2FM.js → asset-feeds-MALYFZUM.js} +18 -18
  4. package/dist/{asset-feeds-FVDNQ2FM.js.map → asset-feeds-MALYFZUM.js.map} +1 -1
  5. package/dist/asset-manager/catalog-deployer.js +7 -7
  6. package/dist/asset-manager/index.js +13 -13
  7. package/dist/asset-manager/installer.js +9 -9
  8. package/dist/asset-manager/renderers.js +8 -8
  9. package/dist/asset-manager/src/index.d.ts +105 -6
  10. package/dist/asset-manager/src/index.d.ts.map +1 -1
  11. package/dist/asset-manager/src/installer.d.ts +11 -2
  12. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  13. package/dist/asset-manager/src/mcp-config.d.ts.map +1 -1
  14. package/dist/bridge/drivers/claude-sdk.js +425 -111
  15. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  16. package/dist/bridge/drivers/codex.js +15 -128
  17. package/dist/bridge/drivers/codex.js.map +1 -1
  18. package/dist/bridge/drivers/continue.js +10 -10
  19. package/dist/bridge/drivers/echo.js +4 -4
  20. package/dist/bridge/drivers/gemini.js +7 -7
  21. package/dist/bridge/drivers/goose.js +10 -10
  22. package/dist/bridge/drivers/omp.js +64 -8
  23. package/dist/bridge/drivers/omp.js.map +1 -1
  24. package/dist/bridge/drivers/opencode.js +10 -10
  25. package/dist/bridge/drivers/qwen.js +7 -7
  26. package/dist/bridge/index.js +15 -14
  27. package/dist/bridge/src/approval-card.d.ts +24 -0
  28. package/dist/bridge/src/approval-card.d.ts.map +1 -0
  29. package/dist/bridge/src/driver-model-check.d.ts +21 -0
  30. package/dist/bridge/src/driver-model-check.d.ts.map +1 -0
  31. package/dist/bridge/src/drivers/claude-sdk.d.ts +95 -19
  32. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  33. package/dist/bridge/src/drivers/claude-self-turns.d.ts +25 -6
  34. package/dist/bridge/src/drivers/claude-self-turns.d.ts.map +1 -1
  35. package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +1 -1
  36. package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
  37. package/dist/bridge/src/drivers/sanitize-assistant-text.d.ts +10 -0
  38. package/dist/bridge/src/drivers/sanitize-assistant-text.d.ts.map +1 -1
  39. package/dist/bridge/src/drivers/scrub-transcript.d.ts +20 -0
  40. package/dist/bridge/src/drivers/scrub-transcript.d.ts.map +1 -1
  41. package/dist/bridge/src/index.d.ts +2 -0
  42. package/dist/bridge/src/index.d.ts.map +1 -1
  43. package/dist/bridge/src/types.d.ts +23 -0
  44. package/dist/bridge/src/types.d.ts.map +1 -1
  45. package/dist/{chunk-YUURCZWY.js → chunk-2SKPPIV7.js} +5 -5
  46. package/dist/{chunk-YUURCZWY.js.map → chunk-2SKPPIV7.js.map} +1 -1
  47. package/dist/{chunk-TCWECSEB.js → chunk-3OYOBTY4.js} +70 -6
  48. package/dist/chunk-3OYOBTY4.js.map +1 -0
  49. package/dist/{chunk-PK5XQBOC.js → chunk-46IRZJV4.js} +4 -4
  50. package/dist/{chunk-PK5XQBOC.js.map → chunk-46IRZJV4.js.map} +1 -1
  51. package/dist/{chunk-54TVXZP3.js → chunk-5DCOG5B5.js} +3 -3
  52. package/dist/{chunk-54TVXZP3.js.map → chunk-5DCOG5B5.js.map} +1 -1
  53. package/dist/{chunk-X7DIT65W.js → chunk-5RDZ5JHH.js} +4 -4
  54. package/dist/{chunk-X7DIT65W.js.map → chunk-5RDZ5JHH.js.map} +1 -1
  55. package/dist/chunk-5SWED2LW.js +125 -0
  56. package/dist/chunk-5SWED2LW.js.map +1 -0
  57. package/dist/{chunk-BV7NLPI6.js → chunk-6GSE63K2.js} +4 -4
  58. package/dist/{chunk-BV7NLPI6.js.map → chunk-6GSE63K2.js.map} +1 -1
  59. package/dist/{chunk-PW3TYWOI.js → chunk-AJ7EGIFR.js} +3 -3
  60. package/dist/{chunk-PW3TYWOI.js.map → chunk-AJ7EGIFR.js.map} +1 -1
  61. package/dist/{chunk-LEOXPIC6.js → chunk-AP24HESN.js} +3 -3
  62. package/dist/{chunk-LEOXPIC6.js.map → chunk-AP24HESN.js.map} +1 -1
  63. package/dist/{chunk-7Y7UYNGL.js → chunk-BBRMS4IC.js} +12 -9
  64. package/dist/chunk-BBRMS4IC.js.map +1 -0
  65. package/dist/{chunk-55VKZUQY.js → chunk-BVXXBZWA.js} +70 -34
  66. package/dist/chunk-BVXXBZWA.js.map +1 -0
  67. package/dist/{chunk-JUHDED6J.js → chunk-CWAWYXD5.js} +3 -3
  68. package/dist/{chunk-JUHDED6J.js.map → chunk-CWAWYXD5.js.map} +1 -1
  69. package/dist/{chunk-OOQ5Q75W.js → chunk-D3PU3C6F.js} +41 -16
  70. package/dist/chunk-D3PU3C6F.js.map +1 -0
  71. package/dist/{chunk-WXKNM2JJ.js → chunk-D5REDKVU.js} +3 -3
  72. package/dist/{chunk-WXKNM2JJ.js.map → chunk-D5REDKVU.js.map} +1 -1
  73. package/dist/{chunk-B6I7SF2X.js → chunk-DR5ZOEYI.js} +114 -81
  74. package/dist/chunk-DR5ZOEYI.js.map +1 -0
  75. package/dist/{chunk-YIDZJHY6.js → chunk-EFLKSMCO.js} +3 -3
  76. package/dist/{chunk-YIDZJHY6.js.map → chunk-EFLKSMCO.js.map} +1 -1
  77. package/dist/{chunk-JJLH4TX4.js → chunk-EOKWTN4N.js} +421 -112
  78. package/dist/chunk-EOKWTN4N.js.map +1 -0
  79. package/dist/{chunk-NKDSU4Q7.js → chunk-ES6ARJPQ.js} +21 -7
  80. package/dist/chunk-ES6ARJPQ.js.map +1 -0
  81. package/dist/{chunk-VQQCA7BD.js → chunk-EYDRONKO.js} +4 -4
  82. package/dist/{chunk-VQQCA7BD.js.map → chunk-EYDRONKO.js.map} +1 -1
  83. package/dist/{chunk-U7YMGW7M.js → chunk-FACRITOL.js} +2 -2
  84. package/dist/{chunk-U7YMGW7M.js.map → chunk-FACRITOL.js.map} +1 -1
  85. package/dist/{chunk-WWUWMOX2.js → chunk-FSLVMZXR.js} +37 -17
  86. package/dist/chunk-FSLVMZXR.js.map +1 -0
  87. package/dist/{chunk-MKTJZLQM.js → chunk-FSSRBWYL.js} +4 -4
  88. package/dist/{chunk-MKTJZLQM.js.map → chunk-FSSRBWYL.js.map} +1 -1
  89. package/dist/{chunk-VY6NTFE7.js → chunk-FT4ZHLYR.js} +3 -2
  90. package/dist/chunk-FT4ZHLYR.js.map +1 -0
  91. package/dist/{chunk-O673TBWJ.js → chunk-GYZJKZPJ.js} +3 -3
  92. package/dist/{chunk-O673TBWJ.js.map → chunk-GYZJKZPJ.js.map} +1 -1
  93. package/dist/{chunk-ANSZULXH.js → chunk-H7R7R5BN.js} +21 -6
  94. package/dist/chunk-H7R7R5BN.js.map +1 -0
  95. package/dist/{chunk-RNFHJUK7.js → chunk-HLETG3CX.js} +3 -3
  96. package/dist/{chunk-RNFHJUK7.js.map → chunk-HLETG3CX.js.map} +1 -1
  97. package/dist/{plugin-store-BIITCNOZ.js → chunk-HUKUYWBJ.js} +32 -23
  98. package/dist/chunk-HUKUYWBJ.js.map +1 -0
  99. package/dist/chunk-KZWZRNIY.js +1016 -0
  100. package/dist/chunk-KZWZRNIY.js.map +1 -0
  101. package/dist/{chunk-X5O56UO4.js → chunk-L2AMXONH.js} +3 -3
  102. package/dist/chunk-L2AMXONH.js.map +1 -0
  103. package/dist/{chunk-NOF73BUH.js → chunk-L6UMSKDF.js} +10 -2
  104. package/dist/chunk-L6UMSKDF.js.map +1 -0
  105. package/dist/{chunk-GQ5OYFVD.js → chunk-LQT2IKYY.js} +47 -47
  106. package/dist/chunk-LQT2IKYY.js.map +1 -0
  107. package/dist/{chunk-NHH3MRSC.js → chunk-MMARPEV7.js} +7 -7
  108. package/dist/{chunk-NHH3MRSC.js.map → chunk-MMARPEV7.js.map} +1 -1
  109. package/dist/{chunk-GR7TV4XC.js → chunk-OQN7PCI4.js} +4 -4
  110. package/dist/{chunk-GR7TV4XC.js.map → chunk-OQN7PCI4.js.map} +1 -1
  111. package/dist/{chunk-NVBN3YOH.js → chunk-OXUCYHL5.js} +46 -67
  112. package/dist/chunk-OXUCYHL5.js.map +1 -0
  113. package/dist/{chunk-SZPE55SB.js → chunk-PGZDSDOB.js} +3 -3
  114. package/dist/{chunk-SZPE55SB.js.map → chunk-PGZDSDOB.js.map} +1 -1
  115. package/dist/{chunk-4QINFQ27.js → chunk-PIC23DDE.js} +59 -17
  116. package/dist/chunk-PIC23DDE.js.map +1 -0
  117. package/dist/{chunk-SAKVAG23.js → chunk-QBY74UBH.js} +7 -7
  118. package/dist/{chunk-SAKVAG23.js.map → chunk-QBY74UBH.js.map} +1 -1
  119. package/dist/{chunk-GV3MFKDV.js → chunk-QEX75L77.js} +62 -6
  120. package/dist/chunk-QEX75L77.js.map +1 -0
  121. package/dist/{chunk-4AKR4XPQ.js → chunk-QSLXB44M.js} +3 -3
  122. package/dist/chunk-QSLXB44M.js.map +1 -0
  123. package/dist/{chunk-PQF5QHVS.js → chunk-QW534EZB.js} +20 -6
  124. package/dist/chunk-QW534EZB.js.map +1 -0
  125. package/dist/{chunk-DPCEQOIZ.js → chunk-QXA2W6UB.js} +3 -3
  126. package/dist/{chunk-DPCEQOIZ.js.map → chunk-QXA2W6UB.js.map} +1 -1
  127. package/dist/{chunk-N36S36OZ.js → chunk-SPV2CXJ3.js} +3 -3
  128. package/dist/{chunk-N36S36OZ.js.map → chunk-SPV2CXJ3.js.map} +1 -1
  129. package/dist/{chunk-KRRHADE7.js → chunk-SXWGLW23.js} +4 -4
  130. package/dist/{chunk-KRRHADE7.js.map → chunk-SXWGLW23.js.map} +1 -1
  131. package/dist/{chunk-MUOSKYI2.js → chunk-V5CDPKDA.js} +12 -12
  132. package/dist/{chunk-MUOSKYI2.js.map → chunk-V5CDPKDA.js.map} +1 -1
  133. package/dist/{chunk-R37L4BNR.js → chunk-W44KA24A.js} +648 -76
  134. package/dist/chunk-W44KA24A.js.map +1 -0
  135. package/dist/{chunk-PV47EEHD.js → chunk-WKEBNB5S.js} +4 -4
  136. package/dist/{chunk-PV47EEHD.js.map → chunk-WKEBNB5S.js.map} +1 -1
  137. package/dist/{chunk-ESXZJP4M.js → chunk-WXWQNJCT.js} +3 -3
  138. package/dist/{chunk-ESXZJP4M.js.map → chunk-WXWQNJCT.js.map} +1 -1
  139. package/dist/{chunk-354JIEIE.js → chunk-WY22FMZF.js} +5 -5
  140. package/dist/{chunk-354JIEIE.js.map → chunk-WY22FMZF.js.map} +1 -1
  141. package/dist/{chunk-D5WTOVLG.js → chunk-Y56YIT6J.js} +2 -2
  142. package/dist/chunk-Y56YIT6J.js.map +1 -0
  143. package/dist/{chunk-ZIW34FGO.js → chunk-YIF2IJUA.js} +3 -3
  144. package/dist/{chunk-ZIW34FGO.js.map → chunk-YIF2IJUA.js.map} +1 -1
  145. package/dist/{chunk-MGM5EJQQ.js → chunk-YK3XLEQJ.js} +40 -26
  146. package/dist/chunk-YK3XLEQJ.js.map +1 -0
  147. package/dist/{chunk-SP5NGNBV.js → chunk-YW2BNDSE.js} +11 -4
  148. package/dist/chunk-YW2BNDSE.js.map +1 -0
  149. package/dist/{chunk-GLMKS6V6.js → chunk-ZPCABSSW.js} +4 -4
  150. package/dist/{chunk-GLMKS6V6.js.map → chunk-ZPCABSSW.js.map} +1 -1
  151. package/dist/{chunk-J76LDUDS.js → chunk-ZVZTCDUN.js} +26 -10
  152. package/dist/chunk-ZVZTCDUN.js.map +1 -0
  153. package/dist/{chunk-RTYDYSUV.js → chunk-ZWUJ22RF.js} +82 -22
  154. package/dist/chunk-ZWUJ22RF.js.map +1 -0
  155. package/dist/cli/index.js +902 -1620
  156. package/dist/cli/index.js.map +1 -1
  157. package/dist/cli/src/agent-checks.d.ts +22 -10
  158. package/dist/cli/src/agent-checks.d.ts.map +1 -1
  159. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  160. package/dist/cli/src/commands/config.d.ts.map +1 -1
  161. package/dist/cli/src/commands/integration.d.ts.map +1 -1
  162. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  163. package/dist/cli/src/commands/library-index.d.ts +6 -0
  164. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  165. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  166. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  167. package/dist/cli/src/commands/plugin/codex.d.ts +10 -0
  168. package/dist/cli/src/commands/plugin/codex.d.ts.map +1 -1
  169. package/dist/cli/src/commands/plugin/types.d.ts +5 -2
  170. package/dist/cli/src/commands/plugin/types.d.ts.map +1 -1
  171. package/dist/cli/src/commands/preset-export.d.ts.map +1 -1
  172. package/dist/cli/src/commands/project.d.ts +6 -0
  173. package/dist/cli/src/commands/project.d.ts.map +1 -1
  174. package/dist/cli/src/commands/rebuild.d.ts.map +1 -1
  175. package/dist/cli/src/commands/run.d.ts.map +1 -1
  176. package/dist/cli/src/commands/serve-preflight.d.ts +13 -0
  177. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
  178. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  179. package/dist/cli/src/commands/show.d.ts.map +1 -1
  180. package/dist/cli/src/commands/source.d.ts +2 -1
  181. package/dist/cli/src/commands/source.d.ts.map +1 -1
  182. package/dist/cli/src/commands/store.d.ts.map +1 -1
  183. package/dist/cli/src/commands/update.d.ts.map +1 -1
  184. package/dist/cli/src/commands/validate.d.ts +6 -1
  185. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  186. package/dist/cli/src/commands/verify.d.ts.map +1 -1
  187. package/dist/cli/src/helpers.d.ts +23 -0
  188. package/dist/cli/src/helpers.d.ts.map +1 -1
  189. package/dist/cli/src/plugin-store/index.d.ts +8 -0
  190. package/dist/cli/src/plugin-store/index.d.ts.map +1 -1
  191. package/dist/cli/src/plugin-store/load.d.ts +1 -0
  192. package/dist/cli/src/plugin-store/load.d.ts.map +1 -1
  193. package/dist/cli/src/skill-checks.d.ts +9 -21
  194. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  195. package/dist/connectors/config.js +5 -5
  196. package/dist/connectors/index.js +19 -18
  197. package/dist/{connectors-TVFFE5H4.js → connectors-CIEIMJY2.js} +22 -21
  198. package/dist/{connectors-TVFFE5H4.js.map → connectors-CIEIMJY2.js.map} +1 -1
  199. package/dist/connectors-shared/index.js +2 -2
  200. package/dist/core/index.js +6 -6
  201. package/dist/core/manifest.js +2 -2
  202. package/dist/core/models.js +1 -1
  203. package/dist/core/publish-manifest.js +3 -3
  204. package/dist/core/ref.js +1 -1
  205. package/dist/core/runtime-assets.js +5 -5
  206. package/dist/core/src/conformance.d.ts.map +1 -1
  207. package/dist/core/src/driver-sdk.d.ts +12 -2
  208. package/dist/core/src/driver-sdk.d.ts.map +1 -1
  209. package/dist/core/src/index.d.ts +4 -4
  210. package/dist/core/src/index.d.ts.map +1 -1
  211. package/dist/core/src/lock.d.ts +7 -0
  212. package/dist/core/src/lock.d.ts.map +1 -1
  213. package/dist/core/src/manifest.d.ts +9 -0
  214. package/dist/core/src/manifest.d.ts.map +1 -1
  215. package/dist/core/src/models.d.ts.map +1 -1
  216. package/dist/core/src/publish-manifest.d.ts +5 -2
  217. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  218. package/dist/core/src/repo-manager.d.ts +14 -0
  219. package/dist/core/src/repo-manager.d.ts.map +1 -1
  220. package/dist/core/workspace-config.js +4 -4
  221. package/dist/deploy/index.js +6 -6
  222. package/dist/discovery/index.js +5 -5
  223. package/dist/discovery/src/index.d.ts +2 -2
  224. package/dist/discovery/src/index.d.ts.map +1 -1
  225. package/dist/discovery/src/parse-manifest.d.ts +7 -0
  226. package/dist/discovery/src/parse-manifest.d.ts.map +1 -1
  227. package/dist/discovery/src/source-config.d.ts +6 -0
  228. package/dist/discovery/src/source-config.d.ts.map +1 -1
  229. package/dist/{ensure-sources-N4E5EDGC.js → ensure-sources-I62QMZZP.js} +16 -16
  230. package/dist/{ensure-sources-N4E5EDGC.js.map → ensure-sources-I62QMZZP.js.map} +1 -1
  231. package/dist/factory-assets/README.md +1 -1
  232. package/dist/factory-assets/connectors/box.js +19 -18
  233. package/dist/factory-assets/connectors/deploy.js +19 -18
  234. package/dist/factory-assets/connectors/devserver.js +19 -18
  235. package/dist/factory-assets/connectors/flow/adapter.js +19 -18
  236. package/dist/factory-assets/connectors/flow/engine.js +7 -7
  237. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  238. package/dist/factory-assets/connectors/flow/run-flow.js +21 -20
  239. package/dist/factory-assets/connectors/flow.js +19 -18
  240. package/dist/factory-assets/connectors/git.js +19 -18
  241. package/dist/factory-assets/connectors/gmail.js +19 -18
  242. package/dist/factory-assets/connectors/googledrive.js +19 -18
  243. package/dist/factory-assets/connectors/local.js +19 -18
  244. package/dist/factory-assets/connectors/mattermost.js +19 -18
  245. package/dist/factory-assets/connectors/memory.js +19 -18
  246. package/dist/factory-assets/connectors/minio.js +19 -18
  247. package/dist/factory-assets/connectors/postgres.js +19 -18
  248. package/dist/factory-assets/connectors/s3.js +19 -18
  249. package/dist/factory-assets/connectors/sharepoint.js +19 -18
  250. package/dist/factory-assets/connectors/sqlite.js +19 -18
  251. package/dist/factory-assets/connectors/static-server.js +19 -18
  252. package/dist/factory-assets/connectors/tunnel.js +19 -18
  253. package/dist/factory-assets/connectors/webdav.js +19 -18
  254. package/dist/factory-assets/connectors/xstate-store.js +19 -18
  255. package/dist/factory-assets/connectors/xstate.js +19 -18
  256. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +12 -11
  257. package/dist/factory-assets/skills/authoring-skaile-manifests/SKILL.md +11 -7
  258. package/dist/factory-assets/skills/skailify/SKILL.md +3 -3
  259. package/dist/{flows-CYJI3URW.js → flows-YKC53LDP.js} +11 -11
  260. package/dist/{flows-CYJI3URW.js.map → flows-YKC53LDP.js.map} +1 -1
  261. package/dist/{helpers-PPVGVYIZ.js → helpers-3FOM37BO.js} +16 -16
  262. package/dist/{helpers-PPVGVYIZ.js.map → helpers-3FOM37BO.js.map} +1 -1
  263. package/dist/library/index.js +10 -10
  264. package/dist/library/install.js +4 -4
  265. package/dist/library/src/index.d.ts +1 -1
  266. package/dist/library/src/index.d.ts.map +1 -1
  267. package/dist/library/src/local/store-paths.d.ts +8 -0
  268. package/dist/library/src/local/store-paths.d.ts.map +1 -1
  269. package/dist/library/src/manifest-writer.d.ts +5 -1
  270. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  271. package/dist/library/src/remote/remote-catalog-source.d.ts +3 -2
  272. package/dist/library/src/remote/remote-catalog-source.d.ts.map +1 -1
  273. package/dist/{library-publish-EQFYHJ6G.js → library-publish-EFKITCGE.js} +59 -51
  274. package/dist/library-publish-EFKITCGE.js.map +1 -0
  275. package/dist/model-endpoint/index.js +19 -3
  276. package/dist/model-endpoint/src/index.d.ts +1 -1
  277. package/dist/model-endpoint/src/index.d.ts.map +1 -1
  278. package/dist/model-endpoint/src/resolve.d.ts +5 -0
  279. package/dist/model-endpoint/src/resolve.d.ts.map +1 -1
  280. package/dist/model-endpoint/src/server.d.ts +7 -0
  281. package/dist/model-endpoint/src/server.d.ts.map +1 -1
  282. package/dist/model-endpoint/src/types.d.ts +41 -7
  283. package/dist/model-endpoint/src/types.d.ts.map +1 -1
  284. package/dist/{open-library-JJGDEYYT.js → open-library-NZUI4XGF.js} +19 -19
  285. package/dist/{open-library-JJGDEYYT.js.map → open-library-NZUI4XGF.js.map} +1 -1
  286. package/dist/{open-registry-X6YQVP7V.js → open-registry-YPRQDUMK.js} +14 -14
  287. package/dist/{open-registry-X6YQVP7V.js.map → open-registry-YPRQDUMK.js.map} +1 -1
  288. package/dist/{paths-NXWIBZCX.js → paths-P55DTBEK.js} +9 -9
  289. package/dist/{paths-NXWIBZCX.js.map → paths-P55DTBEK.js.map} +1 -1
  290. package/dist/plugin-store-IPIBZRBX.js +23 -0
  291. package/dist/plugin-store-IPIBZRBX.js.map +1 -0
  292. package/dist/project-2BNFZ2CR.js +83 -0
  293. package/dist/{project-5HW3XSOE.js.map → project-2BNFZ2CR.js.map} +1 -1
  294. package/dist/resolver/index.js +7 -7
  295. package/dist/resolver/src/types.d.ts +1 -0
  296. package/dist/resolver/src/types.d.ts.map +1 -1
  297. package/dist/resolver/src/validator.d.ts +1 -1
  298. package/dist/runner/index.js +35 -34
  299. package/dist/runner/src/agent.d.ts +9 -1
  300. package/dist/runner/src/agent.d.ts.map +1 -1
  301. package/dist/runner/src/agents/in-process-host.d.ts.map +1 -1
  302. package/dist/runner/src/coalesced-restart.d.ts +41 -0
  303. package/dist/runner/src/coalesced-restart.d.ts.map +1 -0
  304. package/dist/runner/src/compaction/prompt.d.ts.map +1 -1
  305. package/dist/runner/src/composition/content-source.d.ts.map +1 -1
  306. package/dist/runner/src/composition/index.d.ts +1 -1
  307. package/dist/runner/src/composition/index.d.ts.map +1 -1
  308. package/dist/runner/src/composition/resolve-instance.d.ts +20 -0
  309. package/dist/runner/src/composition/resolve-instance.d.ts.map +1 -1
  310. package/dist/runner/src/mcp-runtime-handlers.d.ts +27 -0
  311. package/dist/runner/src/mcp-runtime-handlers.d.ts.map +1 -1
  312. package/dist/runner/src/model-endpoint-discovery.d.ts.map +1 -1
  313. package/dist/runner/src/resource-handler.d.ts.map +1 -1
  314. package/dist/runner/src/runner-capabilities.d.ts +16 -3
  315. package/dist/runner/src/runner-capabilities.d.ts.map +1 -1
  316. package/dist/runner/src/serve.d.ts +10 -0
  317. package/dist/runner/src/serve.d.ts.map +1 -1
  318. package/dist/runner/src/session-builder.d.ts +20 -1
  319. package/dist/runner/src/session-builder.d.ts.map +1 -1
  320. package/dist/runner/src/session-capability-wiring.d.ts +7 -0
  321. package/dist/runner/src/session-capability-wiring.d.ts.map +1 -1
  322. package/dist/sdk/asset-manager.js +13 -13
  323. package/dist/sdk/bridge.js +15 -14
  324. package/dist/sdk/core.js +6 -6
  325. package/dist/sdk/flow.js +7 -7
  326. package/dist/sdk/index.js +35 -34
  327. package/dist/sdk/index.js.map +1 -1
  328. package/dist/sdk/resolver.js +7 -7
  329. package/dist/sdk/runner.js +35 -34
  330. package/dist/sdk/session.js +2 -2
  331. package/dist/sdk/transport/ws/server.js +1 -1
  332. package/dist/sdk/transport/ws.js +1 -1
  333. package/dist/sdk/transport.js +1 -1
  334. package/dist/sdk/types.js +1 -1
  335. package/dist/{serve-preflight-GD7IQFA3.js → serve-preflight-V5GM33T3.js} +15 -9
  336. package/dist/serve-preflight-V5GM33T3.js.map +1 -0
  337. package/dist/session/index.js +2 -2
  338. package/dist/{setup-52NDDR7C.js → setup-ZMAPTKJW.js} +25 -24
  339. package/dist/setup-ZMAPTKJW.js.map +1 -0
  340. package/dist/{skills-XVHOXOOH.js → skills-7G6QCDEM.js} +12 -12
  341. package/dist/{skills-XVHOXOOH.js.map → skills-7G6QCDEM.js.map} +1 -1
  342. package/dist/{source-WKV4QFGS.js → source-6BZA34F5.js} +45 -44
  343. package/dist/{source-WKV4QFGS.js.map → source-6BZA34F5.js.map} +1 -1
  344. package/dist/{source-manifest-publish-3HAX6DPN.js → source-manifest-publish-MJXCSUKT.js} +47 -46
  345. package/dist/source-manifest-publish-MJXCSUKT.js.map +1 -0
  346. package/dist/transport/index.js +1 -1
  347. package/dist/transport/src/ws/server.d.ts +9 -0
  348. package/dist/transport/src/ws/server.d.ts.map +1 -1
  349. package/dist/transport/ws/server.js +1 -1
  350. package/dist/transport/ws.js +1 -1
  351. package/dist/tui/index.js +110 -44
  352. package/dist/tui/index.js.map +1 -1
  353. package/dist/tui/src/repl-session.d.ts +7 -0
  354. package/dist/tui/src/repl-session.d.ts.map +1 -1
  355. package/dist/tui/src/repl.d.ts +16 -0
  356. package/dist/tui/src/repl.d.ts.map +1 -1
  357. package/dist/types/index.js +1 -1
  358. package/dist/types/manifests.js +1 -1
  359. package/dist/types/src/events.d.ts +7 -4
  360. package/dist/types/src/events.d.ts.map +1 -1
  361. package/dist/types/src/manifests/index.d.ts +1 -0
  362. package/dist/types/src/manifests/index.d.ts.map +1 -1
  363. package/dist/types/src/manifests/scaffold-body.d.ts +8 -0
  364. package/dist/types/src/manifests/scaffold-body.d.ts.map +1 -0
  365. package/dist/workspace-plugin/adapters/mcp.js +26 -25
  366. package/dist/workspace-plugin/adapters/omp.js +14 -14
  367. package/dist/workspace-plugin/index.js +1 -1
  368. package/package.json +1 -1
  369. package/dist/chunk-4AKR4XPQ.js.map +0 -1
  370. package/dist/chunk-4QINFQ27.js.map +0 -1
  371. package/dist/chunk-55VKZUQY.js.map +0 -1
  372. package/dist/chunk-7Y7UYNGL.js.map +0 -1
  373. package/dist/chunk-ANSZULXH.js.map +0 -1
  374. package/dist/chunk-B6I7SF2X.js.map +0 -1
  375. package/dist/chunk-D5WTOVLG.js.map +0 -1
  376. package/dist/chunk-GQ5OYFVD.js.map +0 -1
  377. package/dist/chunk-GV3MFKDV.js.map +0 -1
  378. package/dist/chunk-J76LDUDS.js.map +0 -1
  379. package/dist/chunk-JJLH4TX4.js.map +0 -1
  380. package/dist/chunk-MGM5EJQQ.js.map +0 -1
  381. package/dist/chunk-NKDSU4Q7.js.map +0 -1
  382. package/dist/chunk-NOF73BUH.js.map +0 -1
  383. package/dist/chunk-NVBN3YOH.js.map +0 -1
  384. package/dist/chunk-OOQ5Q75W.js.map +0 -1
  385. package/dist/chunk-PQF5QHVS.js.map +0 -1
  386. package/dist/chunk-R37L4BNR.js.map +0 -1
  387. package/dist/chunk-RTYDYSUV.js.map +0 -1
  388. package/dist/chunk-SP5NGNBV.js.map +0 -1
  389. package/dist/chunk-TCWECSEB.js.map +0 -1
  390. package/dist/chunk-VY6NTFE7.js.map +0 -1
  391. package/dist/chunk-WWUWMOX2.js.map +0 -1
  392. package/dist/chunk-X5O56UO4.js.map +0 -1
  393. package/dist/library-publish-EQFYHJ6G.js.map +0 -1
  394. package/dist/plugin-store-BIITCNOZ.js.map +0 -1
  395. package/dist/project-5HW3XSOE.js +0 -82
  396. package/dist/serve-preflight-GD7IQFA3.js.map +0 -1
  397. package/dist/setup-52NDDR7C.js.map +0 -1
  398. package/dist/source-manifest-publish-3HAX6DPN.js.map +0 -1
@@ -1,20 +1,21 @@
1
- import { unregisteredLibraryNames, renamedLibraryName, resolveConfig, RemoteCatalogSource, OfflineError, describeCatalogError, CatalogHttpError, scanUnlistedAssets, getStoreManifestsDir, missingLibraryDirMessage } from './chunk-OOQ5Q75W.js';
2
- import { SEMVER_RE, readManifestSourceConfig, discoverAssetsInTree, isManifestMode } from './chunk-NKDSU4Q7.js';
3
- import { installTargetOf, canonicalEntryRef, deployedAssetDrift, deployAll, removeAsset, diffDeployedAgent, createScaffold, installAgent } from './chunk-WWUWMOX2.js';
1
+ import { unregisteredLibraryNames, renamedLibraryName, resolveConfig, RemoteCatalogSource, OfflineError, describeCatalogError, CatalogHttpError, scanUnlistedAssets, storeManifestFile, missingLibraryDirMessage } from './chunk-D3PU3C6F.js';
2
+ import { SEMVER_RE, invalidSemverMessage, flowFileNameError, readManifestSourceConfig, discoverAssetsInTree, isManifestMode } from './chunk-ES6ARJPQ.js';
3
+ import { installTargetOf, readKeptLegacyCopies, writeKeptLegacyCopies, canonicalEntryRef, diffDeployedAgent, deployedAssetDrift, deployAll, removeAsset, createScaffold, installAgent } from './chunk-FSLVMZXR.js';
4
4
  import { appendHistory, getRecentHistory, clearHistory } from './chunk-KTBKW2FI.js';
5
5
  import { commitChanges } from './chunk-UQ6LFBPZ.js';
6
- import { driverTargetSupportsAgents, CODEX_IDENTITY_DIR } from './chunk-BV7NLPI6.js';
7
- import { resolveConfiguredDriverTarget, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, computeHash, buildLockFile, writeLock, readLock, verifyLock, mergeLockFile, extractForPatch, generatePatch, savePatch, applyPatch, LOCK_SCHEMA_VERSION } from './chunk-4QINFQ27.js';
8
- import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-X7DIT65W.js';
9
- import { deployedBase, deployedDir, isDeployed, deployedPaths } from './chunk-D54T2F54.js';
10
- import { resolveSkWorkspaceConfig, effectiveAgentInstances, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, readLinks, isCommitOnRemote, resolveAll, agentSourceCacheDir, ensureRepo, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAsset, MAX_PRESET_DEPTH, PresetDepthError, DEFAULT_AGENT_INSTANCE_ID, resolveAgentDefinitionDir, storeManifestSlug } from './chunk-J76LDUDS.js';
6
+ import { driverTargetSupportsAgents, CODEX_IDENTITY_DIR } from './chunk-6GSE63K2.js';
7
+ import { isScaffoldBody } from './chunk-YK3XLEQJ.js';
8
+ import { resolveConfiguredDriverTarget, GLOBAL_INSTALL_DIR_NAME, resolveLibraryDir, buildLibraryLockEntries, computeHash, buildLockFile, writeLock, readLock, verifyLock, mergeLockFile, resyncLockSources, extractForPatch, generatePatch, savePatch, applyPatch, LOCK_SCHEMA_VERSION } from './chunk-PIC23DDE.js';
9
+ import { resolveRuntimeAssets, factoryAssetRoots } from './chunk-5RDZ5JHH.js';
10
+ import { deployedBase, isDeployed, deployedPaths, deployedDir } from './chunk-D54T2F54.js';
11
+ import { resolveSkWorkspaceConfig, effectiveAgentInstances, loadMcpServerDeclarations, resolveGlobalHarnesses, resolveGlobalSkWorkspaceConfig, getGlobalCacheDir, sourceCacheKey, getRepoCommit, matchPin, buildProvenanceIndex, coerceVersion, sourceShortName, readLinks, isCommitOnRemote, resolveAll, agentSourceCacheDir, ensureRepo, scanRepo, SKAILE_YAML_DEFAULT, checkRepoStatus, resolveAgentDefinitionDir, resolveAsset, MAX_PRESET_DEPTH, PresetDepthError, DEFAULT_AGENT_INSTANCE_ID } from './chunk-ZVZTCDUN.js';
11
12
  import { globalSkaileDir, globalCacheRoot, migrateLegacyDir } from './chunk-L5VSIPQD.js';
12
- import { DRIVER_TARGETS } from './chunk-IG5LZ3WU.js';
13
- import { loadSkPublishManifest } from './chunk-ANSZULXH.js';
14
- import { scanDirectory, parseFrontmatter, parseRequires, dedupeRequirements } from './chunk-SP5NGNBV.js';
15
- import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr, parseDep } from './chunk-VY6NTFE7.js';
13
+ import { DRIVER_TARGETS, SUPPORTED_DRIVER_TARGETS } from './chunk-IG5LZ3WU.js';
14
+ import { listAssetFiles, loadSkPublishManifest } from './chunk-H7R7R5BN.js';
15
+ import { scanDirectory, parseFrontmatter, parseRequires, dedupeRequirements, readAssetBody } from './chunk-YW2BNDSE.js';
16
+ import { parseAssetRef, parseAssetRefLoose, assetRefToStr, slugifyAssetName, depToStr, parseDep } from './chunk-FT4ZHLYR.js';
16
17
  import { spawnSync } from 'child_process';
17
- import { existsSync, rmSync, readdirSync, readFileSync, lstatSync, unlinkSync, mkdirSync, writeFileSync } from 'fs';
18
+ import { existsSync, rmSync, readFileSync, readdirSync, lstatSync, writeFileSync, unlinkSync, mkdirSync } from 'fs';
18
19
  import path, { resolve, dirname, sep, join, relative, posix } from 'path';
19
20
  import { gt } from 'semver';
20
21
  import { parse, stringify } from 'yaml';
@@ -266,6 +267,18 @@ async function defaultFetchPayload(url) {
266
267
  if (!res.ok) throw new Error(`${url} answered ${res.status}`);
267
268
  return new Uint8Array(await res.arrayBuffer());
268
269
  }
270
+ async function markEsmPayload(dir, dest, bytes) {
271
+ if (!dest.endsWith(".js")) return;
272
+ const text = Buffer.from(bytes).toString("utf-8");
273
+ if (!/^\s*(import\s*[\w{*"']|export\s|export\s*\{)|\bimport\.meta\b/m.test(text)) return;
274
+ try {
275
+ await fs.writeFile(path.join(dir, "package.json"), `${JSON.stringify({ type: "module" })}
276
+ `, {
277
+ flag: "wx"
278
+ });
279
+ } catch {
280
+ }
281
+ }
269
282
  async function ensurePayload(projectDir, decl, fetchPayload) {
270
283
  const payload = decl.payload;
271
284
  if (!payload) return void 0;
@@ -284,10 +297,15 @@ async function ensurePayload(projectDir, decl, fetchPayload) {
284
297
  if (!dir) return `payload of '${decl.id}' has no usable directory name`;
285
298
  const file = path.join(dir, dest);
286
299
  const sha = (bytes2) => createHash("sha256").update(bytes2).digest("hex");
300
+ let existing;
287
301
  try {
288
- if (sha(await fs.readFile(file)) === payload.sha256) return void 0;
302
+ existing = await fs.readFile(file);
289
303
  } catch {
290
304
  }
305
+ if (existing && sha(existing) === payload.sha256) {
306
+ await markEsmPayload(dir, dest, existing);
307
+ return void 0;
308
+ }
291
309
  let bytes;
292
310
  try {
293
311
  bytes = await fetchPayload(payload.url);
@@ -307,6 +325,7 @@ async function ensurePayload(projectDir, decl, fetchPayload) {
307
325
  } catch (err) {
308
326
  return `payload ${dest} could not be written: ${err instanceof Error ? err.message : String(err)}`;
309
327
  }
328
+ await markEsmPayload(dir, dest, bytes);
310
329
  return void 0;
311
330
  }
312
331
  async function removePayloadDir(projectDir, id) {
@@ -359,6 +378,28 @@ async function writeJson(p, value) {
359
378
  await fs.writeFile(p, `${JSON.stringify(value, null, 2)}
360
379
  `);
361
380
  }
381
+ function notedSkipsPath(projectDir) {
382
+ return path.join(projectDir, ".skaile", "mcp-skipped.json");
383
+ }
384
+ async function readNotedSkipsState(projectDir) {
385
+ try {
386
+ return JSON.parse(await fs.readFile(notedSkipsPath(projectDir), "utf-8"));
387
+ } catch {
388
+ return { version: 1 };
389
+ }
390
+ }
391
+ async function readNotedSkips(projectDir, target) {
392
+ const noted = (await readNotedSkipsState(projectDir)).targets?.[target];
393
+ return noted && typeof noted === "object" ? noted : {};
394
+ }
395
+ async function writeNotedSkips(projectDir, target, before, skipped) {
396
+ const now = Object.fromEntries(skipped.map((s) => [s.id, s.reason]));
397
+ if (JSON.stringify(now) === JSON.stringify(before)) return;
398
+ const targets = { ...(await readNotedSkipsState(projectDir)).targets ?? {} };
399
+ if (skipped.length > 0) targets[target] = now;
400
+ else delete targets[target];
401
+ await writeJson(notedSkipsPath(projectDir), { version: 1, targets });
402
+ }
362
403
  async function readManagedIds(projectDir, target) {
363
404
  const state = await readJsonStrict(managedStatePath(projectDir));
364
405
  const ids = state?.targets?.[target];
@@ -372,6 +413,16 @@ async function writeManagedIds(projectDir, target, ids) {
372
413
  else delete targets[target];
373
414
  await writeJson(p, { version: 1, targets });
374
415
  }
416
+ async function removeEmptyLedger(projectDir) {
417
+ const p = managedStatePath(projectDir);
418
+ const state = await readJsonStrict(p);
419
+ if (!state || Object.keys(state.targets ?? {}).length > 0) return;
420
+ await fs.rm(p, { force: true });
421
+ try {
422
+ await fs.rmdir(path.dirname(p));
423
+ } catch {
424
+ }
425
+ }
375
426
  function mergeServers(existing, renderable, managedIds, warn, configLabel) {
376
427
  const next = { ...existing };
377
428
  const managed = new Set(managedIds);
@@ -401,15 +452,19 @@ async function renderMcpServerConfig(projectDir, driverTarget, opts) {
401
452
  const declarations = await loadMcpServerDeclarations(projectDir);
402
453
  const skipped = [];
403
454
  const renderable = /* @__PURE__ */ new Map();
455
+ const noted = await readNotedSkips(projectDir, driverTarget);
404
456
  for (const decl of declarations) {
405
457
  const reason = skipReason(decl) ?? await ensurePayload(projectDir, decl, opts?.fetchPayload ?? defaultFetchPayload);
406
458
  if (reason) {
407
459
  skipped.push({ id: decl.id, reason });
408
- warn(`MCP server "${decl.id}" not written to ${relConfig}: ${reason}`);
460
+ if (noted[decl.id] !== reason) {
461
+ warn(`MCP server "${decl.id}" not written to ${relConfig}: ${reason}`);
462
+ }
409
463
  continue;
410
464
  }
411
465
  renderable.set(decl.id, buildEntry(decl, projectDir));
412
466
  }
467
+ await writeNotedSkips(projectDir, driverTarget, noted, skipped);
413
468
  const managedIds = await readManagedIds(projectDir, driverTarget);
414
469
  const existingFile = await readJsonStrict(configPath);
415
470
  if (renderable.size === 0 && managedIds.length === 0 && !existingFile) {
@@ -433,6 +488,11 @@ async function renderMcpServerConfig(projectDir, driverTarget, opts) {
433
488
  if (!ledgerStale && JSON.stringify(next) === JSON.stringify(existingServers) && existingFile) {
434
489
  return { path: configPath, written: false, servers: owned, removed, skipped };
435
490
  }
491
+ if (removed.length > 0 && Object.keys(next).length === 0 && Object.keys(file).every((k) => k === "mcpServers")) {
492
+ await fs.rm(configPath, { force: true });
493
+ if (owned.length === 0) await removeEmptyLedger(projectDir);
494
+ return { path: configPath, written: true, servers: owned, removed, skipped };
495
+ }
436
496
  await writeJson(configPath, { ...file, mcpServers: next });
437
497
  return { path: configPath, written: true, servers: owned, removed, skipped };
438
498
  }
@@ -465,7 +525,7 @@ function libraryRemoteUrl(library) {
465
525
  return url ? withoutUrlSecrets(url) : void 0;
466
526
  }
467
527
  function storeOverlayPathForUrl(url) {
468
- return join(getStoreManifestsDir(), `${storeManifestSlug(url)}.yaml`);
528
+ return storeManifestFile(url);
469
529
  }
470
530
  function pinsBySlug(sources) {
471
531
  return new Map(sources.map((s) => [sourceCacheKey(s.url), s.pin]));
@@ -650,6 +710,19 @@ function newestLibraryDef(snap, libraryName, id) {
650
710
  }
651
711
  return best;
652
712
  }
713
+ var PSEUDO_VERSION_PREFIX = "0.0.0-sha.";
714
+ function isPseudoVersion(version) {
715
+ return version.startsWith(PSEUDO_VERSION_PREFIX);
716
+ }
717
+ function libraryAssetVersion(snap, libraryName, id, declared) {
718
+ if (declared) return declared;
719
+ const lib = snap?.libraries.find((l) => l.name === libraryName);
720
+ if (lib?.ownership === "reader" && "url" in lib.backendConfig) {
721
+ const commit = getRepoCommit(lib.path);
722
+ if (commit) return `${PSEUDO_VERSION_PREFIX}${commit.slice(0, 7)}`;
723
+ }
724
+ return newestLibraryDef(snap ?? null, libraryName, id)?.version;
725
+ }
653
726
  function libraryPreference(isDefaultLib, rank) {
654
727
  return (a, b) => {
655
728
  const va = coerceVersion(a.entry.version ?? "");
@@ -676,6 +749,20 @@ function qualifyDepRef(ref, fallback) {
676
749
  pin
677
750
  });
678
751
  }
752
+ function scaffoldBodyRefs(entries, deployed) {
753
+ const out = [];
754
+ for (const e of entries) {
755
+ const ref = canonicalEntryRef(e);
756
+ if (!deployed.includes(ref) || !e.source) continue;
757
+ try {
758
+ if (isScaffoldBody(e.kind, readAssetBody(e.source, readFileSync(e.source, "utf8")))) {
759
+ out.push(ref);
760
+ }
761
+ } catch {
762
+ }
763
+ }
764
+ return out;
765
+ }
679
766
  function libraryEntryDepRefs(e) {
680
767
  const publisher = e.publisher ?? "";
681
768
  const refs = /* @__PURE__ */ new Set();
@@ -834,6 +921,7 @@ function libraryMoves(prev, next) {
834
921
  if (o.kind !== id.kind || o.name !== id.name || o.publisher !== id.publisher) continue;
835
922
  const from = before.library;
836
923
  if (!from || from.installed || from.name === to.name) continue;
924
+ if (renamedLibraryName(from.name) === to.name) continue;
837
925
  out.push({ ref: `${id.kind}:@${id.publisher}/${id.name}`, from: from.name, to: to.name });
838
926
  break;
839
927
  }
@@ -897,6 +985,27 @@ var MissingManifestError = class extends Error {
897
985
  }
898
986
  projectDir;
899
987
  };
988
+ function unlistedAssetMessage(ref, library, libPath, ownership) {
989
+ const head = `${ref} is in library "${library}" but not listed in its skaile.manifest.yaml, so only part of its files would be deployed.`;
990
+ const segments = libPath.split(/[\\/]/);
991
+ const isReader = ownership === "reader" || segments.some((s, i) => s === "cache" && segments[i + 1] === "sources");
992
+ return isReader ? `${head} "${library}" is a read-only source clone: add it to skaile.manifest.yaml in the source repo and push, then run \`skaile source sync\`.` : `${head} Run \`skaile library index ${library}\`, then add it again.`;
993
+ }
994
+ function pathEntryExists(p) {
995
+ try {
996
+ lstatSync(p);
997
+ return true;
998
+ } catch {
999
+ return false;
1000
+ }
1001
+ }
1002
+ function isSymlink(p) {
1003
+ try {
1004
+ return lstatSync(p).isSymbolicLink();
1005
+ } catch {
1006
+ return false;
1007
+ }
1008
+ }
900
1009
  var FACTORY_SOURCE_URL = "https://github.com/skaile-ai/ai-assets";
901
1010
  function resolveFactoryAssetsDir() {
902
1011
  for (const dir of factoryAssetRoots()) {
@@ -920,6 +1029,40 @@ function resolveFactorySource() {
920
1029
  factorySourceCache = dir && publisher ? { dir, publisher } : null;
921
1030
  return factorySourceCache;
922
1031
  }
1032
+ function legacyOmpPaths(component, name) {
1033
+ const modern = `${sep}.omp${sep}agent${sep}`;
1034
+ return deployedPaths(component, name, "omp", true).filter((path2) => path2.includes(modern)).map((path2) => path2.replace(modern, `${sep}.omp${sep}`)).filter(pathEntryExists);
1035
+ }
1036
+ function sameBytes(a, b) {
1037
+ try {
1038
+ const sa = lstatSync(a);
1039
+ const sb = lstatSync(b);
1040
+ if (sa.isSymbolicLink() || sb.isSymbolicLink()) return false;
1041
+ if (sa.isDirectory() !== sb.isDirectory()) return false;
1042
+ if (!sa.isDirectory()) return readFileSync(a).equals(readFileSync(b));
1043
+ const na = readdirSync(a).sort();
1044
+ const nb = readdirSync(b).sort();
1045
+ return na.length === nb.length && na.every((n, i) => n === nb[i] && sameBytes(join(a, n), join(b, n)));
1046
+ } catch {
1047
+ return false;
1048
+ }
1049
+ }
1050
+ var ENTRY_HARNESSES_KEY = "global_asset_harnesses";
1051
+ function sameList(a, b) {
1052
+ return a.length === b.length && a.every((v, i) => v === b[i]);
1053
+ }
1054
+ function decodeEntryHarnesses(value) {
1055
+ const out = {};
1056
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return out;
1057
+ for (const [key, list] of Object.entries(value)) {
1058
+ if (!Array.isArray(list)) continue;
1059
+ const valid = list.filter(
1060
+ (h) => SUPPORTED_DRIVER_TARGETS.includes(h)
1061
+ );
1062
+ if (valid.length > 0) out[key] = [...new Set(valid)];
1063
+ }
1064
+ return out;
1065
+ }
923
1066
  var AssetManager = class {
924
1067
  /** Resolved absolute path to the workspace root. */
925
1068
  projectDir;
@@ -932,6 +1075,8 @@ var AssetManager = class {
932
1075
  _knownKinds;
933
1076
  /** Explicit global-harness override (global mode only); else auto-resolved. */
934
1077
  harnessesOverride;
1078
+ legacyCopiesRemoved = [];
1079
+ legacyCopiesKept = [];
935
1080
  /** Injected catalog fetcher (tests / custom); falls back to a built one. */
936
1081
  injectedStoreFetcher;
937
1082
  /** Injected byte fetcher for store staging; falls back to GitHub. */
@@ -1001,11 +1146,140 @@ var AssetManager = class {
1001
1146
  targetHarnesses() {
1002
1147
  if (!this.global) return [this.driverTarget];
1003
1148
  if (this.harnessesOverride && this.harnessesOverride.length > 0) return this.harnessesOverride;
1149
+ return this.defaultGlobalHarnesses();
1150
+ }
1151
+ /** The global harness set without a `--harness` filter (see {@link AssetManager.targetHarnesses}). */
1152
+ defaultGlobalHarnesses() {
1004
1153
  const resolved = resolveGlobalHarnesses();
1005
1154
  if (resolveGlobalSkWorkspaceConfig().global_harnesses?.length) return resolved;
1006
1155
  const configured = resolveConfiguredDriverTarget(this.projectDir);
1007
1156
  return configured && !resolved.includes(configured) ? [...resolved, configured] : resolved;
1008
1157
  }
1158
+ /**
1159
+ * `global_asset_harnesses:` of `~/.skaile/skaile.yaml`: the harnesses `add --global --harness`
1160
+ * limited an entry to, keyed by the declared ref without its pin. An entry with no row goes to
1161
+ * every global harness. Global mode only.
1162
+ */
1163
+ readEntryHarnesses() {
1164
+ if (!this.global) return {};
1165
+ const configPath = join(this.stateRoot, "skaile.yaml");
1166
+ if (!existsSync(configPath)) return {};
1167
+ try {
1168
+ const raw = parse(readFileSync(configPath, "utf8"));
1169
+ return decodeEntryHarnesses(raw?.[ENTRY_HARNESSES_KEY]);
1170
+ } catch {
1171
+ return {};
1172
+ }
1173
+ }
1174
+ /** The harnesses recorded for `kind:name` (`publisher` must agree when both sides have one). */
1175
+ entryHarnessRecord(kind, name, publisher) {
1176
+ const wantPub = publisher?.replace(/^@/, "");
1177
+ for (const [key, harnesses] of Object.entries(this.readEntryHarnesses())) {
1178
+ const id = parseAssetRefLoose(key);
1179
+ if (!id || id.kind !== kind || id.name !== name) continue;
1180
+ const havePub = id.publisher?.replace(/^@/, "");
1181
+ if (wantPub === void 0 || havePub === void 0 || havePub === wantPub) return harnesses;
1182
+ }
1183
+ return void 0;
1184
+ }
1185
+ /** Keep the entries a recorded `--harness` limit sends to `target` (all of them in project mode). */
1186
+ entriesForHarness(entries, target) {
1187
+ if (!this.global || Object.keys(this.readEntryHarnesses()).length === 0) return entries;
1188
+ return entries.filter((e) => {
1189
+ const recorded = this.entryHarnessRecord(e.kind, e.name, e.publisher);
1190
+ return !recorded || recorded.includes(target);
1191
+ });
1192
+ }
1193
+ /**
1194
+ * Set (or, with `harnesses` undefined, clear) the harness row of `ref` in the parsed
1195
+ * `~/.skaile/skaile.yaml` `raw`. Returns whether `raw` changed.
1196
+ */
1197
+ setEntryHarnessRow(raw, ref, harnesses) {
1198
+ const id = parseAssetRefLoose(ref);
1199
+ if (!id) return false;
1200
+ const key = `${id.kind}:${id.publisher ? `@${id.publisher.replace(/^@/, "")}/` : ""}${id.name}`;
1201
+ const rows = decodeEntryHarnesses(raw[ENTRY_HARNESSES_KEY]);
1202
+ let changed = false;
1203
+ for (const k of Object.keys(rows)) {
1204
+ const other = parseAssetRefLoose(k);
1205
+ if (other && other.kind === id.kind && other.name === id.name && (!other.publisher || !id.publisher || other.publisher === id.publisher)) {
1206
+ if (k === key && harnesses && sameList(rows[k], harnesses)) continue;
1207
+ delete rows[k];
1208
+ changed = true;
1209
+ }
1210
+ }
1211
+ if (harnesses && harnesses.length > 0 && !(key in rows)) {
1212
+ rows[key] = [...harnesses];
1213
+ changed = true;
1214
+ }
1215
+ if (!changed) return false;
1216
+ if (Object.keys(rows).length === 0) delete raw[ENTRY_HARNESSES_KEY];
1217
+ else raw[ENTRY_HARNESSES_KEY] = rows;
1218
+ return true;
1219
+ }
1220
+ /**
1221
+ * Delete the copies a 5.12.0 global install left in `~/.omp/skills`, `~/.omp/agents`,
1222
+ * `~/.omp/prompts` and `~/.omp/contracts` (omp reads `~/.omp/agent/<dir>`) for the assets just
1223
+ * deployed into omp's new folder, and remember them for {@link takeLegacyCopiesRemoved} (p744).
1224
+ */
1225
+ sweepLegacyOmpCopies(entries) {
1226
+ if (!this.global || !this.targetHarnesses().includes("omp")) return;
1227
+ const locked = new Set(Object.keys(this.tryReadLock()?.assets ?? {}));
1228
+ const kept = readKeptLegacyCopies();
1229
+ for (const entry of entries) {
1230
+ const component = this.installTarget(entry.kind);
1231
+ if (!component || !entry.name) continue;
1232
+ if (!isDeployed(component, entry.name, "omp", true)) continue;
1233
+ const modern = deployedPaths(component, entry.name, "omp", true).filter(
1234
+ (p) => p.includes(`${sep}.omp${sep}agent${sep}`)
1235
+ );
1236
+ const recorded = [...locked].some((key) => {
1237
+ const id = parseCanonicalLockKey(key);
1238
+ return id.kind === entry.kind && id.name === entry.name;
1239
+ });
1240
+ for (const legacy of legacyOmpPaths(component, entry.name)) {
1241
+ const twin = modern.find(
1242
+ (p) => p === legacy.replace(`${sep}.omp${sep}`, `${sep}.omp${sep}agent${sep}`)
1243
+ );
1244
+ if (kept.has(legacy)) continue;
1245
+ if (recorded || twin !== void 0 && sameBytes(legacy, twin)) {
1246
+ rmSync(legacy, { recursive: true, force: true });
1247
+ this.legacyCopiesRemoved.push(legacy);
1248
+ } else {
1249
+ this.legacyCopiesKept.push(legacy);
1250
+ kept.add(legacy);
1251
+ writeKeptLegacyCopies(kept);
1252
+ }
1253
+ }
1254
+ }
1255
+ }
1256
+ /** The old omp copies the deploys since the last call kept, as skaile did not write them. */
1257
+ takeLegacyCopiesKept() {
1258
+ return this.legacyCopiesKept.splice(0);
1259
+ }
1260
+ /**
1261
+ * The old `~/.omp/<dir>/<name>` copies of the globally locked assets that are still on disk
1262
+ * (a 5.12.0 install wrote them; omp reads `~/.omp/agent/<dir>`). Global mode only. `check`,
1263
+ * `doctor` and `clean` with `--global` report or remove them (p911).
1264
+ */
1265
+ staleLegacyOmpCopies() {
1266
+ if (!this.global) return [];
1267
+ const out = [];
1268
+ const kept = readKeptLegacyCopies();
1269
+ for (const key of Object.keys(this.tryReadLock()?.assets ?? {})) {
1270
+ const id = parseCanonicalLockKey(key);
1271
+ const component = id.kind && id.name ? this.installTarget(id.kind) : void 0;
1272
+ if (!component || !id.name) continue;
1273
+ for (const path2 of legacyOmpPaths(component, id.name)) {
1274
+ if (!kept.has(path2)) out.push({ ref: key, path: path2 });
1275
+ }
1276
+ }
1277
+ return out;
1278
+ }
1279
+ /** The old omp copies the deploys since the last call removed (see {@link sweepLegacyOmpCopies}). */
1280
+ takeLegacyCopiesRemoved() {
1281
+ return this.legacyCopiesRemoved.splice(0);
1282
+ }
1009
1283
  /**
1010
1284
  * The harnesses `add` / `install` deploy into: `[driverTarget]` for a project, the global
1011
1285
  * harness set (see {@link AssetManager.targetHarnesses}) for a global manager.
@@ -1296,12 +1570,13 @@ var AssetManager = class {
1296
1570
  continue;
1297
1571
  }
1298
1572
  if (snap === void 0) snap = await this.loadLibraryIndex();
1299
- const def = newestLibraryDef(snap, c.library, {
1300
- kind: c.entry.kind,
1301
- publisher: c.entry.publisher ?? "",
1302
- name: c.entry.name
1303
- });
1304
- pool.push(def?.version ? { ...c, entry: { ...c.entry, version: def.version } } : c);
1573
+ const version = libraryAssetVersion(
1574
+ snap,
1575
+ c.library,
1576
+ { kind: c.entry.kind, publisher: c.entry.publisher ?? "", name: c.entry.name },
1577
+ void 0
1578
+ );
1579
+ pool.push(version ? { ...c, entry: { ...c.entry, version } } : c);
1305
1580
  }
1306
1581
  let candidates = pool.filter((c) => !pin || matchPin(pin, c.entry.version ?? ""));
1307
1582
  let lockedLibrary;
@@ -1336,14 +1611,32 @@ var AssetManager = class {
1336
1611
  const hit = candidates[0];
1337
1612
  if (hit.entry.version && !SEMVER_RE.test(hit.entry.version)) {
1338
1613
  throw new Error(
1339
- `${canonicalEntryRef(hit.entry)} (library ${hit.library}): version "${hit.entry.version}" is not valid semver. Set a valid version in the asset file and run \`skaile library index ${hit.library}\`.`
1614
+ `${canonicalEntryRef(hit.entry)} (library ${hit.library}): ${invalidSemverMessage(hit.entry.version)}. Set a valid version in the asset file and run \`skaile library index ${hit.library}\`.`
1615
+ );
1616
+ }
1617
+ const flowFileError = hit.entry.kind === "flow" && hit.entry.source ? flowFileNameError({ id: hit.entry.name }, hit.entry.source.split(/[\\/]/).pop()) : void 0;
1618
+ if (flowFileError) {
1619
+ throw new Error(
1620
+ `${canonicalEntryRef(hit.entry)} (library ${hit.library}): ${flowFileError}. Fix it, then run \`skaile library index ${hit.library}\`.`
1340
1621
  );
1341
1622
  }
1342
1623
  if (!opts.quiet && !opts.library) {
1624
+ const hashOf = (c) => {
1625
+ const libPath = libraryDir.get(c.library);
1626
+ return libPath ? libraryDiskHashes(libPath, diskHashes, this.registry).get(
1627
+ `${c.entry.kind}:${c.entry.name}`
1628
+ ) : void 0;
1629
+ };
1630
+ const hitHash = hashOf(hit);
1631
+ const sameVersionDiffers = candidates.filter((c) => c.library !== hit.library && c.entry.version === hit.entry.version).filter((c) => {
1632
+ const other = hashOf(c);
1633
+ return hitHash !== void 0 && other !== void 0 && other !== hitHash;
1634
+ }).map((c) => c.library);
1343
1635
  this.warnLibraryCollision(
1344
1636
  `${hit.entry.kind}:@${hit.entry.publisher}/${hit.entry.name}`,
1345
1637
  candidates,
1346
- hit
1638
+ hit,
1639
+ sameVersionDiffers
1347
1640
  );
1348
1641
  }
1349
1642
  const entry = hit.entry;
@@ -1366,7 +1659,16 @@ var AssetManager = class {
1366
1659
  const roots = [];
1367
1660
  for (const l of (await this.loadLibraryIndex())?.libraries ?? []) {
1368
1661
  if (l.name === GLOBAL_INSTALL_DIR_NAME) continue;
1369
- if (existsSync(l.path)) roots.push({ name: l.name, dir: l.path, isDefault: l.isDefault });
1662
+ const cfg = l.backendConfig;
1663
+ const publisher = "url" in cfg ? cfg.publisher : void 0;
1664
+ if (existsSync(l.path)) {
1665
+ roots.push({
1666
+ name: l.name,
1667
+ dir: l.path,
1668
+ isDefault: l.isDefault,
1669
+ ...publisher ? { publisher } : {}
1670
+ });
1671
+ }
1370
1672
  }
1371
1673
  const registered = new Set(roots.map((r) => r.name));
1372
1674
  const unregistered = unregisteredLibraryNames();
@@ -1389,8 +1691,8 @@ var AssetManager = class {
1389
1691
  const byKey = /* @__PURE__ */ new Map();
1390
1692
  const libraryDir = new Map(roots.map((r) => [r.name, r.dir]));
1391
1693
  const isDefaultLib = new Map(roots.map((r) => [r.name, r.isDefault]));
1392
- for (const { name, dir } of roots) {
1393
- const publisher = readDeclaredPublisher(dir) ?? slugifyAssetName(name);
1694
+ for (const { name, dir, publisher: declared } of roots) {
1695
+ const publisher = readDeclaredPublisher(dir) ?? declared ?? slugifyAssetName(name);
1394
1696
  for (const entry of await scanDirectory(dir, publisher, { knownKinds: this.knownKinds })) {
1395
1697
  const key = `${entry.kind}:@${entry.publisher}/${entry.name}`;
1396
1698
  const list = byKey.get(key);
@@ -1462,11 +1764,19 @@ var AssetManager = class {
1462
1764
  */
1463
1765
  async competingOrigins() {
1464
1766
  const out = /* @__PURE__ */ new Map();
1465
- for (const [key, origins] of await this.collectOrigins()) {
1767
+ for (const [key, origins] of await this.allOrigins()) {
1466
1768
  if (new Set(origins.map((o) => o.version)).size > 1) out.set(key, origins);
1467
1769
  }
1468
1770
  return out;
1469
1771
  }
1772
+ /**
1773
+ * The origins of {@link refOrigins} for every ref, keyed by `kind:@publisher/name`: the
1774
+ * version in each row is the one `add` locks (a source asset whose file declares none is
1775
+ * `0.0.0-sha.<commit>`), which `search` lists too (p855).
1776
+ */
1777
+ async allOrigins() {
1778
+ return this.collectOrigins();
1779
+ }
1470
1780
  /**
1471
1781
  * The origins of {@link refOrigins} for every ref, or for the one `only` names
1472
1782
  * (`kind:@publisher/name`), keyed by `kind:@publisher/name`.
@@ -1690,11 +2000,11 @@ var AssetManager = class {
1690
2000
  * Warn once when `key` is held by more than one library: names every library
1691
2001
  * with its version and the one chosen, so a silent pick can't surprise.
1692
2002
  */
1693
- warnLibraryCollision(key, candidates, chosen) {
2003
+ warnLibraryCollision(key, candidates, chosen, differing = []) {
1694
2004
  const libraries = new Set(candidates.map((c) => c.library));
1695
2005
  if (libraries.size < 2) return;
1696
2006
  const held = candidates.map((c) => `${c.library} (${c.entry.version || "unversioned"})`);
1697
- const msg = `${key} exists in ${libraries.size} libraries: ${held.join(", ")} \u2014 using ${chosen.library} (${chosen.entry.version || "unversioned"}). Highest version wins; an equal version goes to the default library, then by name. Pin a version (${key}#<version>) to choose another.`;
2007
+ const msg = `${key} exists in ${libraries.size} libraries: ${held.join(", ")} \u2014 using ${chosen.library} (${chosen.entry.version || "unversioned"}). Highest version wins; an equal version goes to the default library, then by name. ` + (differing.length > 0 ? `Same version, different content: ${chosen.library} and ${differing.join(", ")} hold ${chosen.entry.version || "unversioned"} with different bytes. ` : "") + `Pin a version (${key}#<version>) to choose another.`;
1698
2008
  if (this.warnedLibraryCollisions.has(msg)) return;
1699
2009
  this.warnedLibraryCollisions.add(msg);
1700
2010
  if (this.onLibraryCollision) this.onLibraryCollision(msg);
@@ -1804,10 +2114,10 @@ var AssetManager = class {
1804
2114
  if (isOwned) continue;
1805
2115
  for (const target of this.targetHarnesses()) {
1806
2116
  const held = deployedPaths(component, a.name, target, this.global, this.projectDir).find(
1807
- (p) => existsSync(p)
2117
+ pathEntryExists
1808
2118
  );
1809
2119
  if (!held) continue;
1810
- if (entry && this.deployWouldOnlyRewriteSame(entry, target)) continue;
2120
+ if (entry && !isSymlink(held) && this.deployWouldOnlyRewriteSame(entry, target)) continue;
1811
2121
  const shown = this.global ? held : relative(this.projectDir, held);
1812
2122
  throw new Error(
1813
2123
  `${assetRefToStr({ kind: a.kind, name: a.name, publisher: a.publisher })} would overwrite ${shown}, which no lock entry owns (your own files?) \u2014 move it away, or pass --force to replace it`
@@ -1821,6 +2131,13 @@ var AssetManager = class {
1821
2131
  * markdown file with the same body whose frontmatter the asset's only extends.
1822
2132
  */
1823
2133
  deployWouldOnlyRewriteSame(entry, target) {
2134
+ if (this.installTarget(entry.kind) === "agent") {
2135
+ try {
2136
+ return diffDeployedAgent(entry, { ...this.deployOptsFor(target) }) === "";
2137
+ } catch {
2138
+ return false;
2139
+ }
2140
+ }
1824
2141
  const drift = deployedAssetDrift(entry, {
1825
2142
  registry: this.registry,
1826
2143
  driverTarget: target,
@@ -1887,7 +2204,8 @@ var AssetManager = class {
1887
2204
  * A git-backed library also records its remote URL. When the previous lock names the
1888
2205
  * library under another name that {@link lockedLibrary} matched to this one by URL (a
1889
2206
  * teammate registered the same remote under a different name), the entry keeps the locked
1890
- * name and URL: the lock does not change because it was installed on another machine.
2207
+ * name and URL: the lock does not change because it was installed on another machine. A
2208
+ * library renamed on this machine with `library rename` is locked under its new name.
1891
2209
  */
1892
2210
  async libraryLockEntries(lib) {
1893
2211
  if (lib.entries.length === 0) return {};
@@ -1912,7 +2230,8 @@ var AssetManager = class {
1912
2230
  })?.[1].library;
1913
2231
  if (locked) {
1914
2232
  const lookup = this.lockedLibrary(locked, snap);
1915
- if (lookup.state === "ok" && lookup.name === name) {
2233
+ const renamedHere = !locked.url && !url && renamedLibraryName(locked.name) === name;
2234
+ if (lookup.state === "ok" && lookup.name === name && !renamedHere) {
1916
2235
  lockName = locked.name;
1917
2236
  if (locked.url && url && normalizeRepoUrl(locked.url) === normalizeRepoUrl(url)) {
1918
2237
  url = locked.url;
@@ -2038,9 +2357,9 @@ var AssetManager = class {
2038
2357
  );
2039
2358
  continue;
2040
2359
  }
2041
- const def = newestLibraryDef(snap, lookup.name, { kind, publisher, name });
2042
- const current = found.version || def?.version || "0.0.0";
2043
- if (current !== origin.version) {
2360
+ const current = libraryAssetVersion(snap, lookup.name, { kind, publisher, name }, found.version) || "0.0.0";
2361
+ const sameVersion = current === origin.version || isPseudoVersion(current) && isPseudoVersion(origin.version);
2362
+ if (!sameVersion) {
2044
2363
  missing.push(
2045
2364
  `${ref} (library "${lookup.name}" is at ${current}, locked ${origin.version})`
2046
2365
  );
@@ -2055,7 +2374,7 @@ var AssetManager = class {
2055
2374
  continue;
2056
2375
  }
2057
2376
  }
2058
- found.version = current;
2377
+ found.version = sameVersion ? origin.version : current;
2059
2378
  entries.push(withLibraryFiles(found, libPath, fileSets, this.registry));
2060
2379
  }
2061
2380
  return { entries, missing };
@@ -2562,7 +2881,8 @@ var AssetManager = class {
2562
2881
  *
2563
2882
  * @param opts - Optional installation options.
2564
2883
  * @param opts.locked - When `true`, restore the exact versions recorded in the existing
2565
- * lock file instead of resolving from source. Throws if no lock file is found.
2884
+ * lock file instead of resolving from source. Throws if no lock file is found, unless the
2885
+ * project declares no dependencies (nothing to restore).
2566
2886
  * @param opts.link - When `true`, symlink local-path assets instead of copying them
2567
2887
  * (the author dev-loop). Machine-local / not for committing; a no-op for
2568
2888
  * store/factory sources. Defaults to copy.
@@ -2682,10 +3002,16 @@ var AssetManager = class {
2682
3002
  const deployed = [
2683
3003
  ...new Set(
2684
3004
  this.targetHarnesses().flatMap(
2685
- (t) => deployAll(entries, repositories, patches, this.deployOptsFor(t, opts?.link))
3005
+ (t) => deployAll(
3006
+ this.entriesForHarness(entries, t),
3007
+ repositories,
3008
+ patches,
3009
+ this.deployOptsFor(t, opts?.link)
3010
+ )
2686
3011
  )
2687
3012
  )
2688
3013
  ];
3014
+ this.sweepLegacyOmpCopies(entries);
2689
3015
  await this.renderDriverMcpConfig();
2690
3016
  const agentRender = await this.renderAgentInstances();
2691
3017
  const restored = this.restoredCopies(copyDrift, deployed, missingCopies);
@@ -2705,10 +3031,12 @@ var AssetManager = class {
2705
3031
  const reportedMissing = stillMissing.filter((m) => !storeNotChecked.some((n) => n.ref === m));
2706
3032
  for (const n of storeNotChecked) delete missingHints[n.ref];
2707
3033
  await this.adviseMissing(reportedMissing, missingHints);
3034
+ const placeholderBodies = scaffoldBodyRefs(lib.entries, deployed);
2708
3035
  return {
2709
3036
  deployed,
2710
3037
  removed,
2711
3038
  missing: reportedMissing,
3039
+ ...placeholderBodies.length > 0 ? { placeholderBodies } : {},
2712
3040
  ...storeNotChecked.length > 0 ? { storeNotChecked } : {},
2713
3041
  ...Object.keys(missingHints).length > 0 ? { missingHints } : {},
2714
3042
  ...relocked.length > 0 ? { relocked } : {},
@@ -3093,6 +3421,16 @@ var AssetManager = class {
3093
3421
  npmFailed: []
3094
3422
  };
3095
3423
  }
3424
+ if (dependencies.length === 0) {
3425
+ return {
3426
+ deployed: [],
3427
+ removed: [],
3428
+ missing: [],
3429
+ lockWritten: false,
3430
+ npmInstalled: [],
3431
+ npmFailed: []
3432
+ };
3433
+ }
3096
3434
  throw new Error("No lock file found. Run `skaile install` first.");
3097
3435
  }
3098
3436
  this.assertNoFolderCollision(Object.keys(lock.assets).map(parseCanonicalLockKey));
@@ -3172,7 +3510,7 @@ var AssetManager = class {
3172
3510
  ...new Set(
3173
3511
  this.targetHarnesses().flatMap(
3174
3512
  (t) => deployAll(
3175
- [...resolved, ...library.entries],
3513
+ this.entriesForHarness([...resolved, ...library.entries], t),
3176
3514
  repositories,
3177
3515
  patches,
3178
3516
  this.deployOptsFor(t)
@@ -3180,6 +3518,7 @@ var AssetManager = class {
3180
3518
  )
3181
3519
  )
3182
3520
  ];
3521
+ this.sweepLegacyOmpCopies([...resolved, ...library.entries]);
3183
3522
  await this.renderDriverMcpConfig();
3184
3523
  const agentRender = await this.renderAgentInstances();
3185
3524
  const restored = this.restoredCopies(copyDrift, deployed, missingCopies);
@@ -3195,10 +3534,12 @@ var AssetManager = class {
3195
3534
  const p = parseRefTolerant(g.ref);
3196
3535
  return !(p && alreadyMissing.has(`${p.kind}:${p.name}`));
3197
3536
  }).map((g) => g.message);
3537
+ const placeholderBodies = scaffoldBodyRefs(library.entries, deployed);
3198
3538
  return {
3199
3539
  deployed,
3200
3540
  removed: [],
3201
3541
  missing: [...library.missing, ...gaps],
3542
+ ...placeholderBodies.length > 0 ? { placeholderBodies } : {},
3202
3543
  lockWritten: false,
3203
3544
  ...restored.length > 0 ? { restored } : {},
3204
3545
  ...rewritten.length > 0 ? { rewritten } : {},
@@ -3339,7 +3680,7 @@ var AssetManager = class {
3339
3680
  );
3340
3681
  if (hit) {
3341
3682
  throw new Error(
3342
- `${canonicalEntryRef(hit.entry)} is in library "${l.name}" but not listed in its skaile.manifest.yaml, so only part of its files would be deployed. Run \`skaile library index ${l.name}\`, then add it again.`
3683
+ unlistedAssetMessage(canonicalEntryRef(hit.entry), l.name, libPath, l.ownership)
3343
3684
  );
3344
3685
  }
3345
3686
  }
@@ -3366,7 +3707,12 @@ var AssetManager = class {
3366
3707
  const libPath = origin ? this.libraryPath({ name: origin }, snap) : null;
3367
3708
  if (origin && libPath && isUnlistedLibraryAsset(e, libPath)) {
3368
3709
  throw new Error(
3369
- `${canonicalEntryRef(e)} is in library "${origin}" but not listed in its skaile.manifest.yaml, so only part of its files would be deployed. Run \`skaile library index ${origin}\`, then add it again.`
3710
+ unlistedAssetMessage(
3711
+ canonicalEntryRef(e),
3712
+ origin,
3713
+ libPath,
3714
+ snap?.libraries.find((l) => l.name === origin)?.ownership
3715
+ )
3370
3716
  );
3371
3717
  }
3372
3718
  }
@@ -3410,7 +3756,7 @@ var AssetManager = class {
3410
3756
  ...new Set(
3411
3757
  this.targetHarnesses().flatMap(
3412
3758
  (t) => deployAll(
3413
- entries,
3759
+ this.entriesForHarness(entries, t),
3414
3760
  repositories,
3415
3761
  patches,
3416
3762
  this.deployOptsFor(t, opts?.link, opts?.onSkippedSymlink, opts?.onEnvFile)
@@ -3418,6 +3764,7 @@ var AssetManager = class {
3418
3764
  )
3419
3765
  )
3420
3766
  ];
3767
+ this.sweepLegacyOmpCopies(entries);
3421
3768
  if (opts?.onLibraryOrigin) {
3422
3769
  for (const e of lib.entries) {
3423
3770
  const origin = lib.libraryOf.get(e);
@@ -3426,6 +3773,9 @@ var AssetManager = class {
3426
3773
  }
3427
3774
  }
3428
3775
  if (presets.length > 0) opts?.onPresets?.(presets);
3776
+ for (const placeholder of scaffoldBodyRefs(lib.entries, deployed)) {
3777
+ opts?.onPlaceholderBody?.(placeholder);
3778
+ }
3429
3779
  this.addDependencyToConfig(ref);
3430
3780
  await this.renderDriverMcpConfig();
3431
3781
  await this.renderAgentInstances();
@@ -3696,8 +4046,9 @@ var AssetManager = class {
3696
4046
  *
3697
4047
  * Deliberately does NOT re-render the driver target's MCP config: the render
3698
4048
  * step is async (the declaration resolver is), and making this synchronous
3699
- * method async would break every external caller. A removed MCP server's
3700
- * generated entry is dropped by the next {@link AssetManager.install} — see
4049
+ * method async would break every external caller. {@link removeWithDependencies}
4050
+ * (what `skaile remove` runs) does re-render it; a caller of this method gets the
4051
+ * dropped entry at the next {@link AssetManager.install} — see
3701
4052
  * {@link renderMcpServerConfig}.
3702
4053
  *
3703
4054
  * @param ref - Asset ref: `kind:@publisher/name`, or the short `kind:name` /
@@ -3761,10 +4112,17 @@ var AssetManager = class {
3761
4112
  });
3762
4113
  }
3763
4114
  const kept = [];
3764
- const changed = this.removeResolved(target, { force: opts?.force, kept });
3765
- const keptNote = kept.length > 0 ? { kept } : {};
3766
- if (!changed || requiredRefs.length === 0) return { changed, pruned: [], ...keptNote };
3767
- return { changed, pruned: await this.pruneOrphans(requiredRefs), ...keptNote };
4115
+ const ownedBy = [];
4116
+ const changed = this.removeResolved(target, { force: opts?.force, kept, ownedBy });
4117
+ const keptNote = {
4118
+ ...kept.length > 0 ? { kept } : {},
4119
+ ...ownedBy.length > 0 ? { ownedBy } : {}
4120
+ };
4121
+ const pruned = changed && requiredRefs.length > 0 ? await this.pruneOrphans(requiredRefs) : [];
4122
+ if (changed && (target.kind === "mcp-server" || pruned.some((r) => r.startsWith("mcp-server:")))) {
4123
+ await this.renderDriverMcpConfig();
4124
+ }
4125
+ return { changed, pruned, ...keptNote };
3768
4126
  }
3769
4127
  /**
3770
4128
  * Resolve the identity {@link remove} acts on. A publisher-qualified ref is taken
@@ -3859,15 +4217,24 @@ var AssetManager = class {
3859
4217
  }
3860
4218
  return found;
3861
4219
  }
3862
- /** Whether a lock entry holds `kind:name` (any publisher): the deployed folder is then the project's copy of it. */
3863
- lockHolds(kind, name) {
3864
- return Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey).some((id) => id.kind === kind && id.name === name);
4220
+ /**
4221
+ * The lock entries that hold `kind:name`, each with its publisher (no leading `@`) and its
4222
+ * canonical ref. A deployed folder carries no publisher; these are who it belongs to.
4223
+ */
4224
+ lockHolders(kind, name) {
4225
+ return Object.keys(this.tryReadLock()?.assets ?? {}).map(parseCanonicalLockKey).filter((id) => id.kind === kind && id.name === name).map((id) => {
4226
+ const publisher = id.publisher?.replace(/^@/, "");
4227
+ return {
4228
+ publisher,
4229
+ ref: publisher ? assetRefToStr({ kind, name, publisher }) : `${kind}:${name}`
4230
+ };
4231
+ });
3865
4232
  }
3866
4233
  /** The folders or files of `kind:name` on disk in `target`, shown relative to the project. */
3867
4234
  heldDeployPaths(kind, name, target) {
3868
4235
  const component = this.installTarget(kind);
3869
4236
  if (!component) return [];
3870
- return deployedPaths(component, name, target, this.global, this.projectDir).filter((p) => existsSync(p)).map((p) => this.global ? p : relative(this.projectDir, p));
4237
+ return deployedPaths(component, name, target, this.global, this.projectDir).filter(pathEntryExists).map((p) => this.global ? p : relative(this.projectDir, p));
3871
4238
  }
3872
4239
  /**
3873
4240
  * Undeploy `parsed` from every target harness and drop its declaration and lock entry.
@@ -3878,21 +4245,34 @@ var AssetManager = class {
3878
4245
  removeResolved(parsed, opts = {}) {
3879
4246
  const wantPub = parsed.publisher?.replace(/^@/, "");
3880
4247
  const tracked = this.trackedPublishers(parsed.kind, parsed.name);
4248
+ const holders = this.lockHolders(parsed.kind, parsed.name);
4249
+ const ownHolder = holders.some(
4250
+ (h) => wantPub === void 0 || !h.publisher || h.publisher === wantPub
4251
+ );
4252
+ const otherHolders = ownHolder ? [] : holders;
3881
4253
  const someoneElses = wantPub !== void 0 && tracked.size > 0 && !tracked.has(wantPub) && !tracked.has(void 0);
3882
- const owned = opts.force === true || this.lockHolds(parsed.kind, parsed.name);
4254
+ const owned = opts.force === true || ownHolder;
3883
4255
  let undeployed = false;
3884
- if (!someoneElses) {
4256
+ if (!someoneElses || otherHolders.length > 0) {
3885
4257
  for (const t of this.targetHarnesses()) {
3886
4258
  if (!owned) {
3887
- opts.kept?.push(...this.heldDeployPaths(parsed.kind, parsed.name, t));
4259
+ const held = this.heldDeployPaths(parsed.kind, parsed.name, t);
4260
+ if (otherHolders.length > 0) {
4261
+ if (held.length > 0)
4262
+ opts.ownedBy?.push({ refs: otherHolders.map((h) => h.ref), paths: held });
4263
+ } else {
4264
+ opts.kept?.push(...held);
4265
+ }
3888
4266
  continue;
3889
4267
  }
3890
4268
  if (removeAsset(parsed.kind, parsed.name, this.deployOptsFor(t))) undeployed = true;
3891
4269
  }
3892
4270
  }
3893
- const undeclared = this.removeDependencyFromConfig(parsed);
4271
+ const stillHeldBy = this.harnessesStillHolding(parsed);
4272
+ const undeclared = stillHeldBy ? false : this.removeDependencyFromConfig(parsed);
4273
+ if (stillHeldBy) this.limitDeclaredEntry(parsed, stillHeldBy);
3894
4274
  const unbound = this.removeAgentBindings(parsed);
3895
- const unlocked = undeployed || undeclared || unbound ? this.pruneLockEntry(parsed) : false;
4275
+ const unlocked = !stillHeldBy && (undeployed || undeclared || unbound) ? this.pruneLockEntry(parsed) : false;
3896
4276
  const changed = undeployed || undeclared || unbound || unlocked;
3897
4277
  if (changed) {
3898
4278
  appendHistory(this.projectDir, {
@@ -3904,6 +4284,29 @@ var AssetManager = class {
3904
4284
  }
3905
4285
  return changed;
3906
4286
  }
4287
+ /**
4288
+ * After `remove --global --harness X`: the harnesses outside `X` that still hold a copy of the
4289
+ * asset, or `undefined` when none does (or this is not a harness-limited global remove).
4290
+ */
4291
+ harnessesStillHolding(target) {
4292
+ if (!this.global || !this.harnessesOverride?.length) return void 0;
4293
+ const component = this.installTarget(target.kind);
4294
+ if (!component) return void 0;
4295
+ const current = this.entryHarnessRecord(target.kind, target.name, target.publisher) ?? this.defaultGlobalHarnesses();
4296
+ const left = current.filter((h) => !this.harnessesOverride?.includes(h));
4297
+ const holding = left.filter((h) => isDeployed(component, target.name, h, true));
4298
+ return holding.length > 0 ? holding : void 0;
4299
+ }
4300
+ /** Limit the declared global entry of `target` to `harnesses` (`~/.skaile/skaile.yaml`). */
4301
+ limitDeclaredEntry(target, harnesses) {
4302
+ const configPath = join(this.stateRoot, "skaile.yaml");
4303
+ if (!existsSync(configPath)) return;
4304
+ const raw = parse(readFileSync(configPath, "utf8")) ?? {};
4305
+ const ref = assetRefToStr(target);
4306
+ if (this.setEntryHarnessRow(raw, ref, harnesses)) {
4307
+ writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
4308
+ }
4309
+ }
3907
4310
  /**
3908
4311
  * Drop the locked assets among `requiredRefs` (and what they require in turn) that
3909
4312
  * nothing needs any more: not declared in `skaile.yaml`, not required by a locked
@@ -3965,7 +4368,7 @@ var AssetManager = class {
3965
4368
  changed = true;
3966
4369
  }
3967
4370
  }
3968
- if (changed) writeLock(this.lockPath, lock);
4371
+ if (changed) writeLock(this.lockPath, resyncLockSources(lock));
3969
4372
  return changed;
3970
4373
  }
3971
4374
  // ── Query ──────────────────────────────────────────────────────────────
@@ -4039,9 +4442,11 @@ var AssetManager = class {
4039
4442
  knownKinds: this.knownKinds,
4040
4443
  declaredPublisher: decl.publisher
4041
4444
  });
4042
- const match = entries.find(
4445
+ let match = entries.find(
4043
4446
  (e) => e.kind === parsed.kind && e.name === parsed.name && (!parsed.publisher || e.publisher === parsed.publisher)
4044
4447
  );
4448
+ const commit = match && !match.version ? getRepoCommit(repoDir) : null;
4449
+ if (match && commit) match = { ...match, version: `0.0.0-sha.${commit.slice(0, 7)}` };
4045
4450
  if (match && (!best || gt(coerceVersion(match.version ?? ""), coerceVersion(best.version ?? "")))) {
4046
4451
  best = match;
4047
4452
  }
@@ -4320,7 +4725,8 @@ var AssetManager = class {
4320
4725
  const locked = parsed.kind === "preset" ? lock !== null : lockKeys.some(
4321
4726
  (k) => k.kind === parsed.kind && k.name === parsed.name && (!parsed.publisher || k.publisher === parsed.publisher)
4322
4727
  );
4323
- for (const harness of harnesses) {
4728
+ const recorded = this.entryHarnessRecord(parsed.kind, parsed.name, parsed.publisher);
4729
+ for (const harness of recorded ? harnesses.filter((h) => recorded.includes(h)) : harnesses) {
4324
4730
  let state;
4325
4731
  if (!locked) {
4326
4732
  state = "declared";
@@ -4427,6 +4833,7 @@ var AssetManager = class {
4427
4833
  declared = this.loadConfig().dependencies;
4428
4834
  } catch {
4429
4835
  }
4836
+ declared = [...declared, ...this.declaredAgentInstanceRefs()];
4430
4837
  for (const dep of declared) {
4431
4838
  const key = findKey(dep);
4432
4839
  if (key) {
@@ -4652,8 +5059,13 @@ var AssetManager = class {
4652
5059
  }
4653
5060
  const found = scanned.find((x) => x.kind === kind && x.name === name);
4654
5061
  if (!found) continue;
4655
- const diskVersion = found.version || newestLibraryDef(snap, lookup.name, { kind, publisher, name })?.version;
4656
- if (diskVersion && gt(coerceVersion(diskVersion), coerceVersion(origin.version))) {
5062
+ const diskVersion = libraryAssetVersion(
5063
+ snap,
5064
+ lookup.name,
5065
+ { kind, publisher, name },
5066
+ found.version
5067
+ );
5068
+ if (diskVersion && !isPseudoVersion(diskVersion) && gt(coerceVersion(diskVersion), coerceVersion(origin.version))) {
4657
5069
  result.push({
4658
5070
  kind,
4659
5071
  name,
@@ -4684,8 +5096,56 @@ var AssetManager = class {
4684
5096
  }
4685
5097
  await this.addLibraryMoves(libraryAssets, result);
4686
5098
  }
5099
+ await this.addRekeyRows(lock, result);
4687
5100
  return this.addLockGapRows(result);
4688
5101
  }
5102
+ /**
5103
+ * List a source asset locked under a `0.0.0-sha.<commit>` key whose file now declares a
5104
+ * version: the next `install` or `update` re-keys it (`replaced 0.0.0-sha.7de3555 → 0.2.0`),
5105
+ * so `outdated` lists it as `re-key (…)` instead of saying everything is up to date (p914).
5106
+ * An asset already listed (behind its remote) gets the target on that row.
5107
+ */
5108
+ async addRekeyRows(lock, rows) {
5109
+ const sha = Object.entries(lock.assets).filter(
5110
+ ([key, e]) => e.source && parseCanonicalLockKey(key).version?.startsWith("0.0.0-sha.")
5111
+ );
5112
+ if (sha.length === 0) return;
5113
+ const { repositories } = this.loadConfig();
5114
+ let index;
5115
+ try {
5116
+ index = await buildProvenanceIndex(this.buildClones(repositories), {
5117
+ projectDir: this.projectDir,
5118
+ knownKinds: this.knownKinds,
5119
+ onSourceError: () => void 0
5120
+ });
5121
+ } catch {
5122
+ return;
5123
+ }
5124
+ for (const [key, entry] of sha) {
5125
+ const { publisher, kind, name, version } = parseCanonicalLockKey(key);
5126
+ if (!publisher || !kind || !name || !version || !entry.source) continue;
5127
+ const url = normalizeRepoUrl(entry.source.url);
5128
+ const now = (index.get(`${publisher}/${kind}:${name}`) ?? []).find(
5129
+ (c) => normalizeRepoUrl(c.sourceUrl) === url
5130
+ );
5131
+ if (!now || now.version === version || now.version.startsWith("0.0.0-sha.")) continue;
5132
+ const row = rows.find(
5133
+ (r) => r.kind === kind && r.name === name && r.publisher.replace(/^@/, "") === publisher
5134
+ );
5135
+ if (row) {
5136
+ row.rekeyTo = now.version;
5137
+ continue;
5138
+ }
5139
+ rows.push({
5140
+ kind,
5141
+ name,
5142
+ publisher,
5143
+ currentVersion: version,
5144
+ behind: 0,
5145
+ rekeyTo: now.version
5146
+ });
5147
+ }
5148
+ }
4689
5149
  /**
4690
5150
  * List a locked library asset that `update` would move to another library (a default-library
4691
5151
  * switch, a library that now holds a newer version) as `library → movesTo`, so `outdated`
@@ -4723,6 +5183,7 @@ var AssetManager = class {
4723
5183
  (r) => r.kind === e.kind && r.name === e.name && r.publisher.replace(/^@/, "") === publisher
4724
5184
  );
4725
5185
  if (row) {
5186
+ row.library = from.name;
4726
5187
  row.movesTo = to;
4727
5188
  continue;
4728
5189
  }
@@ -4850,8 +5311,13 @@ var AssetManager = class {
4850
5311
  if (parsed.kind === "preset" && this.presetRecorded(parsed)) return { status: "no-files" };
4851
5312
  if (!component) return { status: "not-deployed" };
4852
5313
  if (component === "agent") {
4853
- const diff = diffDeployedAgent(entry, this.deployOptsFor(this.driverTarget));
4854
- if (diff === null) return { status: "not-deployed" };
5314
+ const opts = this.deployOptsFor(this.driverTarget);
5315
+ const parts = [diffDeployedAgent(entry, opts)];
5316
+ for (const inst of this.instancesBoundTo(parsed)) {
5317
+ parts.push(diffDeployedAgent(entry, opts, inst));
5318
+ }
5319
+ if (parts.every((d) => d === null)) return { status: "not-deployed" };
5320
+ const diff = parts.filter((d) => d !== null).join("");
4855
5321
  return diff === "" ? { status: "identical" } : { status: "differs", diff };
4856
5322
  }
4857
5323
  const deployedPath = join(
@@ -4874,6 +5340,33 @@ var AssetManager = class {
4874
5340
  }
4875
5341
  return diffs.length > 0 ? { status: "differs", diff: diffs.join("") } : { status: "identical" };
4876
5342
  }
5343
+ /**
5344
+ * The agent instances of `skaile.yaml` whose `ref` names `want` (an `agent:` ref, matched on
5345
+ * name and, when both name one, publisher) and bind to an agent definition directory.
5346
+ */
5347
+ instancesBoundTo(want) {
5348
+ if (this.global) return [];
5349
+ let instances;
5350
+ try {
5351
+ instances = effectiveAgentInstances(resolveSkWorkspaceConfig(this.projectDir));
5352
+ } catch {
5353
+ return [];
5354
+ }
5355
+ const out = [];
5356
+ for (const [id, config] of Object.entries(instances)) {
5357
+ const ref = parseRefTolerant(config.ref);
5358
+ if (!ref || ref.kind !== "agent" || ref.name !== want.name) continue;
5359
+ const refPublisher = ref.publisher?.replace(/^@/, "");
5360
+ const wantPublisher = want.publisher?.replace(/^@/, "");
5361
+ if (refPublisher && wantPublisher && refPublisher !== wantPublisher) continue;
5362
+ try {
5363
+ const srcDir = resolveAgentDefinitionDir(this.projectDir, config.ref);
5364
+ if (srcDir !== void 0) out.push({ id, srcDir, config });
5365
+ } catch {
5366
+ }
5367
+ }
5368
+ return out;
5369
+ }
4877
5370
  // ── Lock ───────────────────────────────────────────────────────────────
4878
5371
  /**
4879
5372
  * Resolve all declared dependencies and write (or overwrite) `skaile.lock.yaml`.
@@ -5199,7 +5692,10 @@ var AssetManager = class {
5199
5692
  for (const d of await this.lockedCopyDrift()) {
5200
5693
  if (named.has(gapIdentity(d.ref))) continue;
5201
5694
  const parts = [
5202
- ...d.modified.map((f) => `${f} was edited`),
5695
+ ...d.modified.map((f) => {
5696
+ const instance = d.instanceOf?.get(f);
5697
+ return instance ? `${f}, the file of agent instance "${instance}", was edited` : `${f} was edited`;
5698
+ }),
5203
5699
  ...d.extra.map((f) => `${f} is not part of the asset`)
5204
5700
  ];
5205
5701
  const reason = `is locked, but its deployed copy differs from the lock (${parts.join("; ")}) \u2014 run \`skaile install --locked\` to restore it`;
@@ -5413,8 +5909,13 @@ var AssetManager = class {
5413
5909
  if (found) {
5414
5910
  const onDisk = origin.sha256 ? libraryDiskHashes(libPath, diskHashes, this.registry).get(`${kind}:${name}`) : void 0;
5415
5911
  if (onDisk !== void 0 && onDisk !== origin.sha256) {
5416
- const diskVersion = found.version || newestLibraryDef(snap, lookup.name, { kind, publisher, name })?.version;
5417
- if (!diskVersion || !gt(coerceVersion(diskVersion), coerceVersion(origin.version))) {
5912
+ const diskVersion = libraryAssetVersion(
5913
+ snap,
5914
+ lookup.name,
5915
+ { kind, publisher, name },
5916
+ found.version
5917
+ );
5918
+ if (!diskVersion || isPseudoVersion(diskVersion) || !gt(coerceVersion(diskVersion), coerceVersion(origin.version))) {
5418
5919
  const reason2 = `is locked, but library "${lookup.name}" content changed since lock \u2014 or the lock predates the one shared asset hash; run \`skaile install\` to re-lock it`;
5419
5920
  gaps.push({ type: "content", ref, reason: reason2, message: `${ref} ${reason2}` });
5420
5921
  }
@@ -5694,7 +6195,8 @@ var AssetManager = class {
5694
6195
  continue;
5695
6196
  }
5696
6197
  const modified = [];
5697
- for (const f of lockedAssetFiles(kind, entry.files)) {
6198
+ const locked = lockedAssetFiles(kind, entry.files);
6199
+ for (const f of locked) {
5698
6200
  const deployedFile = join(dest, f.rel);
5699
6201
  if (!existsSync(deployedFile)) continue;
5700
6202
  try {
@@ -5703,8 +6205,14 @@ var AssetManager = class {
5703
6205
  modified.push(f.rel);
5704
6206
  }
5705
6207
  }
5706
- if (modified.length > 0)
5707
- out.push({ ref: refOf(key), key, modified, extra: [], library: false });
6208
+ const covered = new Set(locked.map((f) => f.rel));
6209
+ let extra = [];
6210
+ try {
6211
+ extra = listAssetFiles(dest).filter((rel) => !covered.has(rel));
6212
+ } catch {
6213
+ }
6214
+ if (modified.length > 0 || extra.length > 0)
6215
+ out.push({ ref: refOf(key), key, modified, extra, library: false });
5708
6216
  }
5709
6217
  for (const [key, entry] of Object.entries(lock.assets)) {
5710
6218
  if (!entry.rendered || entry.rendered.length === 0 || entry.library?.installed) continue;
@@ -5722,6 +6230,10 @@ var AssetManager = class {
5722
6230
  }
5723
6231
  }
5724
6232
  if (modified.length > 0) {
6233
+ const instanceOf = /* @__PURE__ */ new Map();
6234
+ for (const inst of renderedInstanceFiles(this.projectDir, this.driverTarget)) {
6235
+ for (const f of inst.files) if (modified.includes(f)) instanceOf.set(f, inst.id);
6236
+ }
5725
6237
  out.push({
5726
6238
  ref: refOf(key),
5727
6239
  key,
@@ -5729,7 +6241,8 @@ var AssetManager = class {
5729
6241
  extra: [],
5730
6242
  library: false,
5731
6243
  rendered: true,
5732
- lockedSha: new Map(entry.rendered.map((f) => [f.path, f.sha256]))
6244
+ lockedSha: new Map(entry.rendered.map((f) => [f.path, f.sha256])),
6245
+ instanceOf
5733
6246
  });
5734
6247
  }
5735
6248
  }
@@ -6009,6 +6522,7 @@ var AssetManager = class {
6009
6522
  * and `unmanaged` (deployed assets not in the lock file).
6010
6523
  */
6011
6524
  clean(opts) {
6525
+ if (this.global) return this.cleanGlobal(opts);
6012
6526
  const lock = this.tryReadLock();
6013
6527
  const skipped = [];
6014
6528
  const removed = this.cleanLockedDeployedAssets(lock);
@@ -6016,6 +6530,42 @@ var AssetManager = class {
6016
6530
  if (opts?.all) this.removeAllManagedState();
6017
6531
  return { removed, skipped, unmanaged };
6018
6532
  }
6533
+ /**
6534
+ * `clean --global`: remove the copy of every asset the global lock tracks from each global
6535
+ * harness (and the old `~/.omp/<dir>` copy), keeping `~/.skaile/skaile.yaml`. With `all`, the
6536
+ * global lock goes too.
6537
+ */
6538
+ cleanGlobal(opts) {
6539
+ const lock = this.tryReadLock();
6540
+ const removed = [];
6541
+ const stale = this.staleLegacyOmpCopies();
6542
+ for (const key of Object.keys(lock?.assets ?? {})) {
6543
+ const { kind, name } = parseCanonicalLockKey(key);
6544
+ const component = kind ? this.installTarget(kind) : void 0;
6545
+ if (!kind || !name || !component) continue;
6546
+ const paths = [
6547
+ ...this.targetHarnesses().flatMap(
6548
+ (t) => deployedPaths(component, name, t, true, this.projectDir)
6549
+ ),
6550
+ ...stale.filter((s) => s.ref === key).map((s) => s.path)
6551
+ ];
6552
+ for (const dest of paths) {
6553
+ try {
6554
+ if (lstatSync(dest).isSymbolicLink()) unlinkSync(dest);
6555
+ else rmSync(dest, { recursive: true, force: true });
6556
+ } catch {
6557
+ }
6558
+ }
6559
+ removed.push(key);
6560
+ }
6561
+ if (opts?.all) {
6562
+ try {
6563
+ unlinkSync(this.lockPath);
6564
+ } catch {
6565
+ }
6566
+ }
6567
+ return { removed, skipped: [], unmanaged: [] };
6568
+ }
6019
6569
  /**
6020
6570
  * Remove the deployed dir of every asset tracked by the lock; missing dirs
6021
6571
  * still count as removed. Returns the list of cleaned refs.
@@ -6095,16 +6645,21 @@ var AssetManager = class {
6095
6645
  */
6096
6646
  addDependencyToConfig(ref) {
6097
6647
  const configPath = join(this.stateRoot, "skaile.yaml");
6648
+ const limit = this.global && this.harnessesOverride?.length ? this.harnessesOverride : void 0;
6098
6649
  if (!existsSync(configPath)) {
6099
6650
  if (!this.global) return;
6100
6651
  mkdirSync(this.stateRoot, { recursive: true });
6101
- writeFileSync(configPath, stringify({ dependencies: [ref] }, { lineWidth: 120 }));
6652
+ const fresh = { dependencies: [ref] };
6653
+ if (limit) this.setEntryHarnessRow(fresh, ref, limit);
6654
+ writeFileSync(configPath, stringify(fresh, { lineWidth: 120 }));
6102
6655
  return;
6103
6656
  }
6104
6657
  const raw = parse(readFileSync(configPath, "utf8")) ?? {};
6105
6658
  if (!Array.isArray(raw.dependencies)) raw.dependencies = [];
6106
6659
  const deps = raw.dependencies;
6660
+ const limitChanged = this.global ? this.setEntryHarnessRow(raw, ref, limit) : false;
6107
6661
  if (deps.includes(ref) && deps.filter((d) => this.sameDeclaredAsset(d, ref)).length === 1) {
6662
+ if (limitChanged) writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
6108
6663
  return;
6109
6664
  }
6110
6665
  const next = [];
@@ -6156,9 +6711,26 @@ var AssetManager = class {
6156
6711
  return !(wantPub === void 0 || havePub === void 0 || havePub === wantPub);
6157
6712
  });
6158
6713
  if (raw.dependencies.length === before) return false;
6714
+ if (this.global) this.setEntryHarnessRow(raw, assetRefToStr(target), void 0);
6159
6715
  writeFileSync(configPath, stringify(raw, { lineWidth: 120 }));
6160
6716
  return true;
6161
6717
  }
6718
+ /** The refs `skaile.yaml` binds agent instances to: every `agents.<id>.ref` and `agent.definition`. Project mode only. */
6719
+ declaredAgentInstanceRefs() {
6720
+ if (this.global) return [];
6721
+ const configPath = join(this.stateRoot, "skaile.yaml");
6722
+ if (!existsSync(configPath)) return [];
6723
+ try {
6724
+ const raw = parse(readFileSync(configPath, "utf8"));
6725
+ const refs = [
6726
+ ...Object.values(raw?.agents ?? {}).map((i) => i?.ref),
6727
+ raw?.agent?.definition
6728
+ ];
6729
+ return refs.filter((r) => typeof r === "string");
6730
+ } catch {
6731
+ return [];
6732
+ }
6733
+ }
6162
6734
  /**
6163
6735
  * Drop the agent instances of `skaile.yaml` (`agents.<id>`, or the `agent.definition`
6164
6736
  * default) whose `ref` binds to `target`, and the native agent files an install rendered for
@@ -6225,5 +6797,5 @@ var AssetManager = class {
6225
6797
  };
6226
6798
 
6227
6799
  export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, installAgentInstances, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, renderMcpServerConfig, softDepName };
6228
- //# sourceMappingURL=chunk-R37L4BNR.js.map
6229
- //# sourceMappingURL=chunk-R37L4BNR.js.map
6800
+ //# sourceMappingURL=chunk-W44KA24A.js.map
6801
+ //# sourceMappingURL=chunk-W44KA24A.js.map