@skaile/workspaces 6.5.0 → 6.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 (392) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/ai-sdk.js +12 -19
  3. package/dist/ai-sdk.js.map +1 -1
  4. package/dist/app-sdk/index.js +1 -1
  5. package/dist/{asset-feeds-4I6Z4OI3.js → asset-feeds-4A7PJ4OB.js} +20 -20
  6. package/dist/{asset-feeds-4I6Z4OI3.js.map → asset-feeds-4A7PJ4OB.js.map} +1 -1
  7. package/dist/asset-manager/catalog-deployer.js +7 -7
  8. package/dist/asset-manager/index.js +12 -12
  9. package/dist/asset-manager/installer.js +8 -8
  10. package/dist/asset-manager/renderers.js +7 -7
  11. package/dist/asset-manager/src/index.d.ts +89 -15
  12. package/dist/asset-manager/src/index.d.ts.map +1 -1
  13. package/dist/asset-manager/src/install-agent.d.ts +22 -1
  14. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  15. package/dist/asset-manager/src/install-instances.d.ts +30 -1
  16. package/dist/asset-manager/src/install-instances.d.ts.map +1 -1
  17. package/dist/asset-manager/src/installer.d.ts +12 -0
  18. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  19. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  20. package/dist/bridge/harnesses/claude-sdk.js +23 -17
  21. package/dist/bridge/harnesses/claude-sdk.js.map +1 -1
  22. package/dist/bridge/harnesses/codex.js +12 -11
  23. package/dist/bridge/harnesses/codex.js.map +1 -1
  24. package/dist/bridge/harnesses/continue.js +13 -11
  25. package/dist/bridge/harnesses/continue.js.map +1 -1
  26. package/dist/bridge/harnesses/echo.js +6 -5
  27. package/dist/bridge/harnesses/echo.js.map +1 -1
  28. package/dist/bridge/harnesses/gemini.js +9 -7
  29. package/dist/bridge/harnesses/goose.js +13 -11
  30. package/dist/bridge/harnesses/goose.js.map +1 -1
  31. package/dist/bridge/harnesses/omp.js +10 -8
  32. package/dist/bridge/harnesses/omp.js.map +1 -1
  33. package/dist/bridge/harnesses/opencode.js +13 -11
  34. package/dist/bridge/harnesses/opencode.js.map +1 -1
  35. package/dist/bridge/harnesses/qwen.js +10 -8
  36. package/dist/bridge/harnesses/qwen.js.map +1 -1
  37. package/dist/bridge/index.js +19 -17
  38. package/dist/bridge/src/ai-sdk.d.ts.map +1 -1
  39. package/dist/bridge/src/claude-sdk-surface.d.ts +2 -1
  40. package/dist/bridge/src/claude-sdk-surface.d.ts.map +1 -1
  41. package/dist/bridge/src/harness-binaries.d.ts +21 -0
  42. package/dist/bridge/src/harness-binaries.d.ts.map +1 -0
  43. package/dist/bridge/src/harness-model-check.d.ts +22 -6
  44. package/dist/bridge/src/harness-model-check.d.ts.map +1 -1
  45. package/dist/bridge/src/harnesses/claude-sdk.d.ts.map +1 -1
  46. package/dist/bridge/src/harnesses/continue.d.ts.map +1 -1
  47. package/dist/bridge/src/harnesses/gemini.d.ts.map +1 -1
  48. package/dist/bridge/src/harnesses/goose.d.ts.map +1 -1
  49. package/dist/bridge/src/harnesses/omp-models-yml.d.ts.map +1 -1
  50. package/dist/bridge/src/harnesses/omp.d.ts.map +1 -1
  51. package/dist/bridge/src/harnesses/opencode.d.ts.map +1 -1
  52. package/dist/bridge/src/harnesses/qwen.d.ts.map +1 -1
  53. package/dist/bridge/src/index.d.ts +2 -1
  54. package/dist/bridge/src/index.d.ts.map +1 -1
  55. package/dist/{chunk-UZET67SO.js → chunk-237BMOZW.js} +4 -4
  56. package/dist/{chunk-UZET67SO.js.map → chunk-237BMOZW.js.map} +1 -1
  57. package/dist/{chunk-J5JWLKLB.js → chunk-37AYPPOO.js} +41 -19
  58. package/dist/chunk-37AYPPOO.js.map +1 -0
  59. package/dist/{chunk-3KSLUVKB.js → chunk-37X4A6VZ.js} +7 -7
  60. package/dist/{chunk-3KSLUVKB.js.map → chunk-37X4A6VZ.js.map} +1 -1
  61. package/dist/{chunk-EO7KGX6P.js → chunk-3HSLJAMJ.js} +4 -4
  62. package/dist/{chunk-EO7KGX6P.js.map → chunk-3HSLJAMJ.js.map} +1 -1
  63. package/dist/{chunk-AFTZNR2W.js → chunk-3W6XZQ2Y.js} +3 -3
  64. package/dist/{chunk-AFTZNR2W.js.map → chunk-3W6XZQ2Y.js.map} +1 -1
  65. package/dist/{chunk-SZTHSPRC.js → chunk-4C2E5QUP.js} +4 -3
  66. package/dist/chunk-4C2E5QUP.js.map +1 -0
  67. package/dist/{chunk-T7HGEMNB.js → chunk-4CD2R4MJ.js} +5 -4
  68. package/dist/chunk-4CD2R4MJ.js.map +1 -0
  69. package/dist/{chunk-TNQLDEM6.js → chunk-6RPS7JEH.js} +302 -54
  70. package/dist/chunk-6RPS7JEH.js.map +1 -0
  71. package/dist/{chunk-NSIOBKDX.js → chunk-6UP2EDFN.js} +4 -313
  72. package/dist/chunk-6UP2EDFN.js.map +1 -0
  73. package/dist/{chunk-KUADKMNX.js → chunk-72TLO2AG.js} +4 -4
  74. package/dist/{chunk-KUADKMNX.js.map → chunk-72TLO2AG.js.map} +1 -1
  75. package/dist/{chunk-HPA3RP5E.js → chunk-AO57IFME.js} +3 -3
  76. package/dist/{chunk-HPA3RP5E.js.map → chunk-AO57IFME.js.map} +1 -1
  77. package/dist/{chunk-G5SYFFMD.js → chunk-ASBZOTEO.js} +2 -2
  78. package/dist/{chunk-G5SYFFMD.js.map → chunk-ASBZOTEO.js.map} +1 -1
  79. package/dist/{chunk-YBEJCQE5.js → chunk-BB5EJLKZ.js} +3 -3
  80. package/dist/{chunk-YBEJCQE5.js.map → chunk-BB5EJLKZ.js.map} +1 -1
  81. package/dist/{chunk-LE6QS4PG.js → chunk-BKLDBUQA.js} +3 -3
  82. package/dist/{chunk-LE6QS4PG.js.map → chunk-BKLDBUQA.js.map} +1 -1
  83. package/dist/{chunk-HTGTNN2B.js → chunk-CMXDFTA2.js} +3 -3
  84. package/dist/{chunk-HTGTNN2B.js.map → chunk-CMXDFTA2.js.map} +1 -1
  85. package/dist/{chunk-J6YPKMMY.js → chunk-CTRTFMCX.js} +6 -6
  86. package/dist/{chunk-J6YPKMMY.js.map → chunk-CTRTFMCX.js.map} +1 -1
  87. package/dist/{chunk-ETF6Q3R3.js → chunk-DFP476EU.js} +8 -4
  88. package/dist/chunk-DFP476EU.js.map +1 -0
  89. package/dist/{chunk-TGUMN5G7.js → chunk-G44FFUMA.js} +13 -11
  90. package/dist/chunk-G44FFUMA.js.map +1 -0
  91. package/dist/{chunk-G4NCSYWR.js → chunk-G7NMF5WQ.js} +4 -4
  92. package/dist/{chunk-G4NCSYWR.js.map → chunk-G7NMF5WQ.js.map} +1 -1
  93. package/dist/{chunk-KA2GLAPS.js → chunk-GAIMSCZ7.js} +10 -8
  94. package/dist/chunk-GAIMSCZ7.js.map +1 -0
  95. package/dist/{chunk-AVFRFGM2.js → chunk-GNUA7XT2.js} +3 -2
  96. package/dist/chunk-GNUA7XT2.js.map +1 -0
  97. package/dist/{chunk-6Y3SC7O4.js → chunk-GTAHU4N4.js} +4 -4
  98. package/dist/{chunk-6Y3SC7O4.js.map → chunk-GTAHU4N4.js.map} +1 -1
  99. package/dist/{chunk-7H4GTP7V.js → chunk-HLAEYFUN.js} +3 -3
  100. package/dist/{chunk-7H4GTP7V.js.map → chunk-HLAEYFUN.js.map} +1 -1
  101. package/dist/{chunk-B436SG5P.js → chunk-HMVAGPYR.js} +48 -12
  102. package/dist/chunk-HMVAGPYR.js.map +1 -0
  103. package/dist/{chunk-EN5REMWV.js → chunk-HPXONAI2.js} +7 -5
  104. package/dist/chunk-HPXONAI2.js.map +1 -0
  105. package/dist/{chunk-KYNCY3F3.js → chunk-HQAPUPBE.js} +3 -3
  106. package/dist/{chunk-KYNCY3F3.js.map → chunk-HQAPUPBE.js.map} +1 -1
  107. package/dist/{chunk-USVUS4DJ.js → chunk-IRK3LNG3.js} +7 -7
  108. package/dist/{chunk-USVUS4DJ.js.map → chunk-IRK3LNG3.js.map} +1 -1
  109. package/dist/{chunk-7EMS2GZO.js → chunk-J7VEQORJ.js} +70 -17
  110. package/dist/chunk-J7VEQORJ.js.map +1 -0
  111. package/dist/{chunk-2HS357RA.js → chunk-KO3VSZQP.js} +48 -19
  112. package/dist/chunk-KO3VSZQP.js.map +1 -0
  113. package/dist/{chunk-KSH5CFQS.js → chunk-KORDNXKA.js} +3 -3
  114. package/dist/{chunk-KSH5CFQS.js.map → chunk-KORDNXKA.js.map} +1 -1
  115. package/dist/{chunk-Z2X7UZEZ.js → chunk-L3JQJ6D5.js} +6 -6
  116. package/dist/{chunk-Z2X7UZEZ.js.map → chunk-L3JQJ6D5.js.map} +1 -1
  117. package/dist/{chunk-OBZ5WQ32.js → chunk-L7QOZG5V.js} +3 -3
  118. package/dist/{chunk-OBZ5WQ32.js.map → chunk-L7QOZG5V.js.map} +1 -1
  119. package/dist/{chunk-B4BLJUYN.js → chunk-LX4TTTRR.js} +79 -36
  120. package/dist/chunk-LX4TTTRR.js.map +1 -0
  121. package/dist/{chunk-KSUT5KAE.js → chunk-LZPJOF7Y.js} +3 -3
  122. package/dist/{chunk-KSUT5KAE.js.map → chunk-LZPJOF7Y.js.map} +1 -1
  123. package/dist/{chunk-OLHHN3NO.js → chunk-N6ZGB5ES.js} +4 -3
  124. package/dist/chunk-N6ZGB5ES.js.map +1 -0
  125. package/dist/{chunk-2M3VLKT2.js → chunk-NURTGAWM.js} +3 -3
  126. package/dist/{chunk-2M3VLKT2.js.map → chunk-NURTGAWM.js.map} +1 -1
  127. package/dist/{chunk-22ZX33H6.js → chunk-O5Y7VMVQ.js} +16 -15
  128. package/dist/chunk-O5Y7VMVQ.js.map +1 -0
  129. package/dist/{chunk-IWKKTCXY.js → chunk-O7ADRMCR.js} +67 -16
  130. package/dist/chunk-O7ADRMCR.js.map +1 -0
  131. package/dist/{chunk-SRTWKZP2.js → chunk-OGTQUEAO.js} +21 -14
  132. package/dist/chunk-OGTQUEAO.js.map +1 -0
  133. package/dist/{chunk-U6KRTCNA.js → chunk-OSABUEWA.js} +3 -3
  134. package/dist/{chunk-U6KRTCNA.js.map → chunk-OSABUEWA.js.map} +1 -1
  135. package/dist/{chunk-E6UWI3TP.js → chunk-PLLZSKOO.js} +3 -3
  136. package/dist/{chunk-E6UWI3TP.js.map → chunk-PLLZSKOO.js.map} +1 -1
  137. package/dist/{chunk-W5KCAWGN.js → chunk-PTJTOPE5.js} +3 -3
  138. package/dist/{chunk-W5KCAWGN.js.map → chunk-PTJTOPE5.js.map} +1 -1
  139. package/dist/{chunk-TROEC2Z2.js → chunk-Q2NYTMT6.js} +18 -17
  140. package/dist/chunk-Q2NYTMT6.js.map +1 -0
  141. package/dist/{chunk-23SG4JRV.js → chunk-QC5BYUED.js} +52 -16
  142. package/dist/chunk-QC5BYUED.js.map +1 -0
  143. package/dist/{chunk-WFLQMAR5.js → chunk-QCR5AE5E.js} +5 -5
  144. package/dist/{chunk-WFLQMAR5.js.map → chunk-QCR5AE5E.js.map} +1 -1
  145. package/dist/{chunk-THX5EE3K.js → chunk-QW5B3TEO.js} +10 -4
  146. package/dist/chunk-QW5B3TEO.js.map +1 -0
  147. package/dist/{chunk-TDPQOR3C.js → chunk-RAHAZ7LP.js} +2 -2
  148. package/dist/{chunk-TDPQOR3C.js.map → chunk-RAHAZ7LP.js.map} +1 -1
  149. package/dist/{chunk-ZUU2PLA3.js → chunk-SBNUXJ6E.js} +3 -3
  150. package/dist/{chunk-ZUU2PLA3.js.map → chunk-SBNUXJ6E.js.map} +1 -1
  151. package/dist/{chunk-DKXNKFKP.js → chunk-SGI5MRKP.js} +75 -3
  152. package/dist/chunk-SGI5MRKP.js.map +1 -0
  153. package/dist/{chunk-UMLCKKIA.js → chunk-TMJBEGS4.js} +36 -7
  154. package/dist/chunk-TMJBEGS4.js.map +1 -0
  155. package/dist/{chunk-K4DHYTUM.js → chunk-TXX3OUYI.js} +3 -3
  156. package/dist/{chunk-K4DHYTUM.js.map → chunk-TXX3OUYI.js.map} +1 -1
  157. package/dist/{chunk-SN663FCA.js → chunk-U52FYGK5.js} +5 -5
  158. package/dist/{chunk-SN663FCA.js.map → chunk-U52FYGK5.js.map} +1 -1
  159. package/dist/{chunk-S7DVT2BV.js → chunk-UCB7FK25.js} +10 -8
  160. package/dist/chunk-UCB7FK25.js.map +1 -0
  161. package/dist/{chunk-3DA74PLW.js → chunk-USSP43U3.js} +3 -3
  162. package/dist/{chunk-3DA74PLW.js.map → chunk-USSP43U3.js.map} +1 -1
  163. package/dist/{chunk-X44XKBZX.js → chunk-WFK4MUBL.js} +21 -7
  164. package/dist/chunk-WFK4MUBL.js.map +1 -0
  165. package/dist/{chunk-YRC2EFOU.js → chunk-WIYVR24B.js} +4 -4
  166. package/dist/{chunk-YRC2EFOU.js.map → chunk-WIYVR24B.js.map} +1 -1
  167. package/dist/{chunk-6EKQENAP.js → chunk-WKENHNDM.js} +6 -6
  168. package/dist/{chunk-6EKQENAP.js.map → chunk-WKENHNDM.js.map} +1 -1
  169. package/dist/chunk-WWSRIT3J.js +59 -0
  170. package/dist/chunk-WWSRIT3J.js.map +1 -0
  171. package/dist/chunk-XON6ODIC.js +315 -0
  172. package/dist/chunk-XON6ODIC.js.map +1 -0
  173. package/dist/{chunk-2IAWVUW3.js → chunk-ZBA4P5TD.js} +4 -4
  174. package/dist/{chunk-2IAWVUW3.js.map → chunk-ZBA4P5TD.js.map} +1 -1
  175. package/dist/{chunk-IS3NIZBX.js → chunk-ZDTDS62B.js} +596 -127
  176. package/dist/chunk-ZDTDS62B.js.map +1 -0
  177. package/dist/{chunk-DNXPXJ3X.js → chunk-ZM4SDVUV.js} +79 -20
  178. package/dist/chunk-ZM4SDVUV.js.map +1 -0
  179. package/dist/{claude-code-JY6CYEG7.js → claude-code-BLFRZU2X.js} +5 -5
  180. package/dist/{claude-code-JY6CYEG7.js.map → claude-code-BLFRZU2X.js.map} +1 -1
  181. package/dist/cli/index.js +481 -205
  182. package/dist/cli/index.js.map +1 -1
  183. package/dist/cli/src/agent-pins.d.ts +9 -3
  184. package/dist/cli/src/agent-pins.d.ts.map +1 -1
  185. package/dist/cli/src/commands/asset-cmd.d.ts +1 -1
  186. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  187. package/dist/cli/src/commands/cache.d.ts.map +1 -1
  188. package/dist/cli/src/commands/catalog.d.ts +2 -0
  189. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  190. package/dist/cli/src/commands/config.d.ts.map +1 -1
  191. package/dist/cli/src/commands/harness-preflight.d.ts +38 -0
  192. package/dist/cli/src/commands/harness-preflight.d.ts.map +1 -0
  193. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  194. package/dist/cli/src/commands/library-index.d.ts +16 -0
  195. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  196. package/dist/cli/src/commands/migrate-assets.d.ts +5 -0
  197. package/dist/cli/src/commands/migrate-assets.d.ts.map +1 -1
  198. package/dist/cli/src/commands/migrate-harness.d.ts +15 -7
  199. package/dist/cli/src/commands/migrate-harness.d.ts.map +1 -1
  200. package/dist/cli/src/commands/migrate.d.ts.map +1 -1
  201. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  202. package/dist/cli/src/commands/plugin-registry-cmd.d.ts.map +1 -1
  203. package/dist/cli/src/commands/project.d.ts +14 -0
  204. package/dist/cli/src/commands/project.d.ts.map +1 -1
  205. package/dist/cli/src/commands/run.d.ts.map +1 -1
  206. package/dist/cli/src/commands/serve-preflight.d.ts +6 -5
  207. package/dist/cli/src/commands/serve-preflight.d.ts.map +1 -1
  208. package/dist/cli/src/commands/serve.d.ts.map +1 -1
  209. package/dist/cli/src/commands/session.d.ts.map +1 -1
  210. package/dist/cli/src/commands/source.d.ts +11 -0
  211. package/dist/cli/src/commands/source.d.ts.map +1 -1
  212. package/dist/cli/src/commands/update.d.ts.map +1 -1
  213. package/dist/cli/src/commands/validate-instances.d.ts +6 -0
  214. package/dist/cli/src/commands/validate-instances.d.ts.map +1 -1
  215. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  216. package/dist/cli/src/commands/why.d.ts.map +1 -1
  217. package/dist/cli/src/plugin-store/reconcile.d.ts.map +1 -1
  218. package/dist/cli/src/session-hint.d.ts +7 -0
  219. package/dist/cli/src/session-hint.d.ts.map +1 -0
  220. package/dist/connectors/config.js +4 -4
  221. package/dist/connectors/index.js +23 -21
  222. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  223. package/dist/connectors/src/managed-gitconfig.d.ts +6 -4
  224. package/dist/connectors/src/managed-gitconfig.d.ts.map +1 -1
  225. package/dist/connectors/src/mount-ledger.d.ts.map +1 -1
  226. package/dist/{connectors-VLFOQNS6.js → connectors-OJJU4LSN.js} +26 -24
  227. package/dist/{connectors-VLFOQNS6.js.map → connectors-OJJU4LSN.js.map} +1 -1
  228. package/dist/connectors-shared/index.js +2 -2
  229. package/dist/core/index.js +6 -6
  230. package/dist/core/logging.js +1 -1
  231. package/dist/core/manifest.js +1 -1
  232. package/dist/core/publish-manifest.js +2 -2
  233. package/dist/core/runtime-assets.js +4 -4
  234. package/dist/core/src/agent-instances.d.ts +11 -0
  235. package/dist/core/src/agent-instances.d.ts.map +1 -1
  236. package/dist/core/src/index.d.ts +3 -2
  237. package/dist/core/src/index.d.ts.map +1 -1
  238. package/dist/core/src/logging/index.d.ts +1 -0
  239. package/dist/core/src/logging/index.d.ts.map +1 -1
  240. package/dist/core/src/logging/log-safe-text.d.ts +20 -0
  241. package/dist/core/src/logging/log-safe-text.d.ts.map +1 -0
  242. package/dist/core/src/manifest.d.ts.map +1 -1
  243. package/dist/core/src/publish-manifest.d.ts +20 -6
  244. package/dist/core/src/publish-manifest.d.ts.map +1 -1
  245. package/dist/core/src/repo-manager.d.ts +9 -0
  246. package/dist/core/src/repo-manager.d.ts.map +1 -1
  247. package/dist/core/src/run-state-ignore.d.ts +17 -0
  248. package/dist/core/src/run-state-ignore.d.ts.map +1 -0
  249. package/dist/core/src/workspace-config.d.ts +6 -0
  250. package/dist/core/src/workspace-config.d.ts.map +1 -1
  251. package/dist/core/workspace-config.js +3 -3
  252. package/dist/deploy/index.js +6 -6
  253. package/dist/discovery/index.js +3 -3
  254. package/dist/discovery/src/builtin-providers.d.ts.map +1 -1
  255. package/dist/discovery/src/discover-manifest.d.ts.map +1 -1
  256. package/dist/discovery/src/tree-entries.d.ts.map +1 -1
  257. package/dist/{ensure-sources-6O54DUQB.js → ensure-sources-F6VQDCWY.js} +28 -26
  258. package/dist/ensure-sources-F6VQDCWY.js.map +1 -0
  259. package/dist/factory-assets/connectors/box.js +23 -21
  260. package/dist/factory-assets/connectors/deploy.js +23 -21
  261. package/dist/factory-assets/connectors/devserver.js +23 -21
  262. package/dist/factory-assets/connectors/flow/adapter.js +23 -21
  263. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts +2 -0
  264. package/dist/factory-assets/connectors/flow/engine/router-settlement.d.ts.map +1 -1
  265. package/dist/factory-assets/connectors/flow/engine.js +7 -7
  266. package/dist/factory-assets/connectors/flow/run-flow.js +25 -23
  267. package/dist/factory-assets/connectors/flow.js +23 -21
  268. package/dist/factory-assets/connectors/git/CONNECTOR.md +4 -1
  269. package/dist/factory-assets/connectors/git/exec.d.ts.map +1 -1
  270. package/dist/factory-assets/connectors/git.js +23 -21
  271. package/dist/factory-assets/connectors/gmail.js +23 -21
  272. package/dist/factory-assets/connectors/googledrive.js +23 -21
  273. package/dist/factory-assets/connectors/local.js +23 -21
  274. package/dist/factory-assets/connectors/mattermost.js +23 -21
  275. package/dist/factory-assets/connectors/memory.js +23 -21
  276. package/dist/factory-assets/connectors/minio.js +23 -21
  277. package/dist/factory-assets/connectors/postgres.js +23 -21
  278. package/dist/factory-assets/connectors/s3.js +23 -21
  279. package/dist/factory-assets/connectors/sharepoint.js +23 -21
  280. package/dist/factory-assets/connectors/sqlite.js +23 -21
  281. package/dist/factory-assets/connectors/static-server.js +23 -21
  282. package/dist/factory-assets/connectors/tunnel.js +23 -21
  283. package/dist/factory-assets/connectors/webdav.js +23 -21
  284. package/dist/factory-assets/connectors/xstate-store.js +23 -21
  285. package/dist/factory-assets/connectors/xstate.js +23 -21
  286. package/dist/factory-assets/skills/authoring-skaile-assets/SKILL.md +14 -1
  287. package/dist/{flows-CIUPK7SB.js → flows-I6ODIPZZ.js} +11 -11
  288. package/dist/{flows-CIUPK7SB.js.map → flows-I6ODIPZZ.js.map} +1 -1
  289. package/dist/{helpers-YHDQHQEQ.js → helpers-PJNUTZXZ.js} +28 -26
  290. package/dist/{helpers-YHDQHQEQ.js.map → helpers-PJNUTZXZ.js.map} +1 -1
  291. package/dist/library/index.js +9 -9
  292. package/dist/library/install.js +3 -3
  293. package/dist/library/src/manifest-writer.d.ts +5 -0
  294. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  295. package/dist/{library-publish-MUGUST43.js → library-publish-FNNDWVBO.js} +54 -52
  296. package/dist/library-publish-FNNDWVBO.js.map +1 -0
  297. package/dist/model-endpoint/index.js +10 -9
  298. package/dist/open-library-R5EZROFN.js +59 -0
  299. package/dist/{open-library-BVQCB37E.js.map → open-library-R5EZROFN.js.map} +1 -1
  300. package/dist/{open-registry-JCSIAKEC.js → open-registry-RZW2AFD6.js} +13 -13
  301. package/dist/{open-registry-JCSIAKEC.js.map → open-registry-RZW2AFD6.js.map} +1 -1
  302. package/dist/{paths-XLKCAFRZ.js → paths-RPK5PNZQ.js} +9 -9
  303. package/dist/{paths-XLKCAFRZ.js.map → paths-RPK5PNZQ.js.map} +1 -1
  304. package/dist/{plugin-store-NGRUTCJI.js → plugin-store-OJTERUEZ.js} +9 -9
  305. package/dist/{plugin-store-NGRUTCJI.js.map → plugin-store-OJTERUEZ.js.map} +1 -1
  306. package/dist/project-S2FT3LLR.js +90 -0
  307. package/dist/{project-BGYMLAS6.js.map → project-S2FT3LLR.js.map} +1 -1
  308. package/dist/resolver/index.js +7 -7
  309. package/dist/runner/index.js +39 -37
  310. package/dist/runner/src/capability-roundtrip.d.ts +6 -6
  311. package/dist/runner/src/capability-roundtrip.d.ts.map +1 -1
  312. package/dist/runner/src/composition/run-snapshot.d.ts +7 -1
  313. package/dist/runner/src/composition/run-snapshot.d.ts.map +1 -1
  314. package/dist/runner/src/external-mcp.d.ts +22 -0
  315. package/dist/runner/src/external-mcp.d.ts.map +1 -1
  316. package/dist/runner/src/mcp-tools-snapshot.d.ts +13 -0
  317. package/dist/runner/src/mcp-tools-snapshot.d.ts.map +1 -0
  318. package/dist/runner/src/resources.d.ts +14 -0
  319. package/dist/runner/src/resources.d.ts.map +1 -1
  320. package/dist/runner/src/serve.d.ts.map +1 -1
  321. package/dist/sdk/asset-manager.js +12 -12
  322. package/dist/sdk/bridge.js +19 -17
  323. package/dist/sdk/core.js +6 -6
  324. package/dist/sdk/flow.js +7 -7
  325. package/dist/sdk/index.js +39 -37
  326. package/dist/sdk/index.js.map +1 -1
  327. package/dist/sdk/resolver.js +7 -7
  328. package/dist/sdk/runner.js +39 -37
  329. package/dist/sdk/session.js +2 -2
  330. package/dist/sdk/transport/ws/server.js +7 -7
  331. package/dist/sdk/transport/ws.js +7 -7
  332. package/dist/sdk/transport.js +7 -7
  333. package/dist/sdk/types.js +1 -1
  334. package/dist/serve-preflight-AADSOUO2.js +58 -0
  335. package/dist/{serve-preflight-GQY5DZX6.js.map → serve-preflight-AADSOUO2.js.map} +1 -1
  336. package/dist/session/index.js +2 -2
  337. package/dist/{setup-2NWSKSCO.js → setup-HOAJHUFQ.js} +29 -27
  338. package/dist/setup-HOAJHUFQ.js.map +1 -0
  339. package/dist/{skills-PXZOL2FZ.js → skills-KHHW3RZ3.js} +12 -12
  340. package/dist/{skills-PXZOL2FZ.js.map → skills-KHHW3RZ3.js.map} +1 -1
  341. package/dist/source-FOELFCY6.js +88 -0
  342. package/dist/{source-XA3L4H6I.js.map → source-FOELFCY6.js.map} +1 -1
  343. package/dist/{source-manifest-publish-QEGMTS33.js → source-manifest-publish-Q7P5AEVU.js} +51 -49
  344. package/dist/source-manifest-publish-Q7P5AEVU.js.map +1 -0
  345. package/dist/transport/index.js +7 -7
  346. package/dist/transport/ws/server.js +7 -7
  347. package/dist/transport/ws.js +7 -7
  348. package/dist/tui/index.js +63 -44
  349. package/dist/tui/index.js.map +1 -1
  350. package/dist/tui/src/repl.d.ts +10 -0
  351. package/dist/tui/src/repl.d.ts.map +1 -1
  352. package/dist/types/index.js +1 -1
  353. package/dist/types/src/version.d.ts +4 -4
  354. package/dist/workspace-plugin/adapters/mcp.js +30 -28
  355. package/dist/workspace-plugin/adapters/omp.js +14 -14
  356. package/dist/workspace-plugin/index.js +2 -2
  357. package/package.json +1 -1
  358. package/dist/chunk-22ZX33H6.js.map +0 -1
  359. package/dist/chunk-23SG4JRV.js.map +0 -1
  360. package/dist/chunk-2HS357RA.js.map +0 -1
  361. package/dist/chunk-7EMS2GZO.js.map +0 -1
  362. package/dist/chunk-AVFRFGM2.js.map +0 -1
  363. package/dist/chunk-B436SG5P.js.map +0 -1
  364. package/dist/chunk-B4BLJUYN.js.map +0 -1
  365. package/dist/chunk-DKXNKFKP.js.map +0 -1
  366. package/dist/chunk-DNXPXJ3X.js.map +0 -1
  367. package/dist/chunk-EN5REMWV.js.map +0 -1
  368. package/dist/chunk-ETF6Q3R3.js.map +0 -1
  369. package/dist/chunk-IS3NIZBX.js.map +0 -1
  370. package/dist/chunk-IWKKTCXY.js.map +0 -1
  371. package/dist/chunk-J5JWLKLB.js.map +0 -1
  372. package/dist/chunk-KA2GLAPS.js.map +0 -1
  373. package/dist/chunk-NSIOBKDX.js.map +0 -1
  374. package/dist/chunk-OLHHN3NO.js.map +0 -1
  375. package/dist/chunk-S7DVT2BV.js.map +0 -1
  376. package/dist/chunk-SRTWKZP2.js.map +0 -1
  377. package/dist/chunk-SZTHSPRC.js.map +0 -1
  378. package/dist/chunk-T7HGEMNB.js.map +0 -1
  379. package/dist/chunk-TGUMN5G7.js.map +0 -1
  380. package/dist/chunk-THX5EE3K.js.map +0 -1
  381. package/dist/chunk-TNQLDEM6.js.map +0 -1
  382. package/dist/chunk-TROEC2Z2.js.map +0 -1
  383. package/dist/chunk-UMLCKKIA.js.map +0 -1
  384. package/dist/chunk-X44XKBZX.js.map +0 -1
  385. package/dist/ensure-sources-6O54DUQB.js.map +0 -1
  386. package/dist/library-publish-MUGUST43.js.map +0 -1
  387. package/dist/open-library-BVQCB37E.js +0 -57
  388. package/dist/project-BGYMLAS6.js +0 -88
  389. package/dist/serve-preflight-GQY5DZX6.js +0 -56
  390. package/dist/setup-2NWSKSCO.js.map +0 -1
  391. package/dist/source-XA3L4H6I.js +0 -86
  392. package/dist/source-manifest-publish-QEGMTS33.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { entrySurface } from './chunk-SZTHSPRC.js';
2
- import { unresolvedProviderCredentials, entryCredentialValue, providerCredentialEnvName } from './chunk-NSIOBKDX.js';
1
+ import { entrySurface } from './chunk-4C2E5QUP.js';
2
+ import { unresolvedProviderCredentials, entryCredentialValue, providerCredentialEnvName } from './chunk-XON6ODIC.js';
3
3
  import { AI_PROVIDER_SURFACES, registryEntries, isEntryEnabled, parseModelRef, normalizeEntryBaseUrl, resolveEntryBaseUrl } from './chunk-RXGPFAMN.js';
4
4
  import { createHash } from 'crypto';
5
5
  import fs from 'fs/promises';
@@ -148,11 +148,13 @@ function renderModelRoles(registry, roles, modelRef, warnings) {
148
148
  );
149
149
  continue;
150
150
  }
151
- out[role] = `${ref.providerId}/${ref.providerModelId}`;
151
+ out[role] = ref.fallback ? trimmed : `${ref.providerId}/${ref.providerModelId}`;
152
152
  }
153
153
  if (out.default === void 0 && modelRef) {
154
154
  const ref = parseModelRef(modelRef, registry, roles);
155
- if (ref?.providerModelId) out.default = `${ref.providerId}/${ref.providerModelId}`;
155
+ if (ref?.providerModelId && !ref.fallback) {
156
+ out.default = `${ref.providerId}/${ref.providerModelId}`;
157
+ }
156
158
  }
157
159
  return out;
158
160
  }
@@ -435,7 +437,7 @@ async function materializeOmpProviders(config) {
435
437
  ...config.modelRef ? { modelRef: config.modelRef } : {}
436
438
  }).providerIds;
437
439
  if (usable.length === 0) return void 0;
438
- if (selected && !usable.includes(selected.providerId)) return void 0;
440
+ if (selected && !selected.fallback && !usable.includes(selected.providerId)) return void 0;
439
441
  const plan = await planOmpAgentDir({
440
442
  cwd: config.cwd,
441
443
  ...config.sessionId ? { sessionId: config.sessionId } : {},
@@ -464,7 +466,7 @@ async function materializeOmpProviders(config) {
464
466
  return {
465
467
  ...rendered,
466
468
  ephemeral: plan.ephemeral,
467
- ...selected?.providerModelId ? { modelArg: `${selected.providerId}/${selected.providerModelId}` } : {}
469
+ ...selected?.providerModelId && !selected.fallback ? { modelArg: `${selected.providerId}/${selected.providerModelId}` } : {}
468
470
  };
469
471
  }
470
472
  async function materializeOmpIdentityDir(config) {
@@ -501,5 +503,5 @@ async function materializeOmpIdentityDir(config) {
501
503
  }
502
504
 
503
505
  export { isCredentialOmissionWarning, materializeOmpIdentityDir, materializeOmpProviders, ompRegistryModelRefusal, registryModelEntries };
504
- //# sourceMappingURL=chunk-S7DVT2BV.js.map
505
- //# sourceMappingURL=chunk-S7DVT2BV.js.map
506
+ //# sourceMappingURL=chunk-UCB7FK25.js.map
507
+ //# sourceMappingURL=chunk-UCB7FK25.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../bridge/src/harnesses/omp-models-yml.ts"],"names":[],"mappings":"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","file":"chunk-UCB7FK25.js","sourcesContent":["/**\n * The omp adapter: an AI provider registry serialized into omp's own\n * configuration files, inside a session-private agent directory.\n *\n * omp already implements the target schema — `~/.omp/agent/models.yml` is a\n * `providers:` map with `baseUrl`, `api`, `apiKey`, `headers`, `authHeader`,\n * `auth`, `discovery` and `models[]` (`omp://models.md`) — so this module is a\n * *serializer*, not a translator. Our `surface` enum is omp's `api` enum\n * verbatim (§1.2); {@link OMP_API_VALUES} encodes that assertion so a future\n * surface that omp does not know is reported instead of silently written into\n * a file omp will then reject wholesale.\n *\n * Two files are produced:\n *\n * - `models.yml` — one entry per enabled `llm`/`embed` registry entry. `apiKey`\n * holds the **name** of the per-entry environment variable\n * (`SKAILE_AIP_<ID>_KEY`, {@link providerCredentialEnvName}), never a value:\n * omp resolves a `models.yml` `apiKey` as an env-var name first and only\n * falls back to treating it as a literal token. The values travel in the\n * child environment.\n * - `config.yml` — omp's settings file, carrying `modelRoles` rendered from the\n * `skaile.yaml` `roles` table. `models.yml`'s root accepts only `providers:`;\n * unknown root keys fail its schema, so roles cannot live there.\n *\n * `PI_CODING_AGENT_DIR` relocates omp's whole agent base — `config.yml`,\n * `models.yml` **and** the auth store `agent.db` (`omp://settings.md`). Pointing\n * it at a session-private directory is what makes N providers per session\n * possible without ever writing the user's `~/.omp/agent`. The cost is that a\n * standalone developer session would also lose the OAuth logins stored in that\n * auth store, so {@link materializeOmpAgentDir} seeds the session directory\n * with symlinks to everything in the user's agent directory *except* the two\n * files this module owns. Verified against omp 18.2.6: a ChatGPT/Codex OAuth\n * account stored in `~/.omp/agent/agent.db` still resolves (`omp token\n * openai-codex`) from a relocated directory that only symlinks `agent.db*`.\n * Under the platform the user directory does not exist, the seed is a no-op,\n * and the session starts empty — which is the correct behaviour there.\n *\n * @see PROVIDER-CONFIG-PLAN.md §2.3 (omp row), §5, §9\n * @see omp://models.md, omp://settings.md\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { Stats } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport net from \"node:net\";\nimport path from \"node:path\";\nimport {\n type AIProviderLlmEntry,\n type AIProviderRegistry,\n AI_PROVIDER_SURFACES,\n isEntryEnabled,\n type MergedAIProviderRegistry,\n normalizeEntryBaseUrl,\n parseModelRef,\n registryEntries,\n resolveEntryBaseUrl,\n} from \"@skaile/workspaces/core/provider-registry\";\nimport { parse, stringify } from \"yaml\";\nimport type { ModelEntry } from \"../models.js\";\nimport {\n entryCredentialValue,\n providerCredentialEnvName,\n type RegistryCredentialEnvOptions,\n unresolvedProviderCredentials,\n} from \"../provider-materialize/credential-env.js\";\nimport { entrySurface } from \"../provider-materialize/env-harnesses.js\";\nimport type { AgentConfig, OmpHarnessOptions } from \"../types.js\";\n\n/**\n * omp's allowed provider/model `api` values (`omp://models.md`, \"Allowed\n * provider/model `api` values\").\n *\n * Every {@link AI_PROVIDER_SURFACES} member is in this list — that equality is\n * the premise the whole adapter rests on (§1.2). `google-gemini-cli` is omp's\n * one extra value, which the registry has no surface for.\n */\nexport const OMP_API_VALUES: readonly string[] = [...AI_PROVIDER_SURFACES, \"google-gemini-cli\"];\n\n/**\n * `discovery.type` values omp accepts. The registry's own enum is wider on one\n * side (`anthropic-models-list`, `google-models-list`, `none`) and narrower on\n * the other, so a discovery block is emitted only when omp can act on it.\n */\nconst OMP_DISCOVERY_TYPES: readonly string[] = [\n \"ollama\",\n \"llama.cpp\",\n \"lm-studio\",\n \"openai-models-list\",\n \"proxy\",\n \"litellm\",\n];\n\n/** One `providers.<id>` block of `models.yml`. */\ninterface OmpProviderBlock {\n baseUrl?: string;\n api?: string;\n /** The *name* of the env var holding the credential — never a value. */\n apiKey?: string;\n auth?: \"apiKey\" | \"none\" | \"oauth\";\n authHeader?: boolean;\n headers?: Record<string, string>;\n discovery?: { type: string };\n models?: OmpModelBlock[];\n}\n\n/** One entry of a provider's `models[]`. */\ninterface OmpModelBlock {\n id: string;\n name?: string;\n input?: string[];\n contextWindow?: number;\n supportsTools?: boolean;\n}\n\n/** The two files this module owns inside the agent directory. */\nexport const OMP_MODELS_FILENAME = \"models.yml\";\n\n/** omp's settings file; `modelRoles` lives here, not in `models.yml`. */\nexport const OMP_CONFIG_FILENAME = \"config.yml\";\n\n/**\n * Names {@link materializeOmpAgentDir} never links in from the user's agent\n * directory: the two files it writes itself, their alternate spellings, and\n * the legacy `settings.json` omp would migrate into `config.yml`.\n */\nconst OWNED_AGENT_DIR_FILES: Record<string, true> = {\n \"models.yml\": true,\n \"models.yaml\": true,\n \"models.json\": true,\n \"config.yml\": true,\n \"config.yaml\": true,\n \"config.yml.lock\": true,\n \"config.yaml.lock\": true,\n \"settings.json\": true,\n};\n\n/**\n * omp's own runtime state inside its home. An agent directory that an older release used as\n * omp's home still holds these; they are never agent files, so the identity link skips them\n * and the user's own login (`agent.db`) linked in from their agent directory stays in place.\n */\nconst OMP_RUNTIME_ENTRIES: Record<string, true> = {\n \"agent.db\": true,\n \"agent.db-shm\": true,\n \"agent.db-wal\": true,\n \"models.db\": true,\n \"models.db-shm\": true,\n \"models.db-wal\": true,\n \"skill-descriptions.db\": true,\n \"skill-descriptions.db-shm\": true,\n \"skill-descriptions.db-wal\": true,\n \"custom-session-files\": true,\n intercom: true,\n sessions: true,\n};\n\n/**\n * The only entries of the user's own omp agent directory a session's private home links in:\n * omp's credential store, so the login the developer already has keeps working. Sessions,\n * history, `mcp.json`, extensions and blobs stay out: a run must not write into the user's\n * session store or load their MCP servers and extensions. `config.yml` is copied, not linked.\n */\nconst OMP_LOGIN_FILES = [\"agent.db\", \"agent.db-shm\", \"agent.db-wal\"] as const;\n\n/** Options for {@link renderOmpRegistry}. */\nexport interface RenderOmpRegistryOptions extends RegistryCredentialEnvOptions {\n /** `skaile.yaml` `roles`: role name → model selector. Rendered as `modelRoles`. */\n roles?: Record<string, string>;\n /**\n * The session's own selector. When `roles` names no `default`, the resolved\n * model becomes `modelRoles.default` so `@default` (and omp's `*` alias)\n * resolve to the entry the session actually runs on.\n */\n modelRef?: string;\n /**\n * Settings to render underneath `modelRoles` — the user's own `config.yml`\n * when a standalone session seeds one. `modelRoles` is replaced wholesale,\n * not deep-merged: a seeded role pointing at a provider this session does\n * not define would otherwise survive as a dangling selector.\n */\n baseSettings?: Record<string, unknown>;\n}\n\n/** What {@link renderOmpRegistry} produced. */\nexport interface OmpRegistryRender {\n /** `models.yml` contents. */\n modelsYml: string;\n /** `config.yml` contents. */\n configYml: string;\n /**\n * `SKAILE_AIP_<ID>_KEY` → secret, for the child environment. The only place\n * a credential value appears; both rendered files hold names alone.\n */\n credentialEnv: Record<string, string>;\n /** Entry ids written to `models.yml`, in registry order. */\n providerIds: string[];\n /** `modelRoles` as written, role name → `<providerId>/<providerModelId>`. */\n modelRoles: Record<string, string>;\n /** Entries and roles that could not be rendered, and why. */\n warnings: string[];\n}\n\n/** The provider-side model ids an entry declares, keyed by logical id. */\nfunction entryModelIds(entry: AIProviderLlmEntry): Array<[string, string]> {\n const logical = new Set<string>([\n ...Object.keys(entry.model_map ?? {}),\n ...Object.keys(entry.capabilities ?? {}),\n ]);\n const seen = new Set<string>();\n const out: Array<[string, string]> = [];\n for (const id of logical) {\n const providerSide = entry.model_map?.[id] ?? id;\n if (seen.has(providerSide)) continue;\n seen.add(providerSide);\n out.push([id, providerSide]);\n }\n return out;\n}\n\n/**\n * Serialize one entry into an omp provider block, or report why it cannot be.\n *\n * omp requires `baseUrl` on any provider that declares `models[]`, and\n * provider-level `api` whenever `discovery` is set (except `discovery.type:\n * proxy`, where the wire is auto-detected per model). A file that violates its\n * schema is rejected *wholesale* — the registry keeps operating on built-in\n * models and the error only surfaces through `ModelRegistry.getError()` — so an\n * entry that cannot satisfy those rules is dropped here, loudly, rather than\n * taking every other provider down with it.\n */\nfunction renderProvider(\n id: string,\n entry: AIProviderLlmEntry,\n warnings: string[],\n): OmpProviderBlock | undefined {\n // The Anthropic SDK inside omp appends `/v1/messages`: a stored `…/v1` must\n // not reach the file as written. Not `entryBaseUrl`: omp gets no preset\n // literal, so an entry without an endpoint of its own is reported below.\n const baseUrl = normalizeEntryBaseUrl(resolveEntryBaseUrl(entry), entrySurface(entry));\n if (!baseUrl) {\n warnings.push(\n `provider '${id}' has no resolvable base_url (missing transport params?) — omitted from models.yml`,\n );\n return undefined;\n }\n\n // Only the entry's own surface becomes `api`; an inherited one stays omp's\n // to infer, as before. The preset's surface above only picks the URL rule.\n const surface = entry.surface;\n if (surface && !OMP_API_VALUES.includes(surface)) {\n warnings.push(\n `provider '${id}' has surface '${surface}', which omp's api enum does not accept`,\n );\n return undefined;\n }\n\n const block: OmpProviderBlock = { baseUrl };\n if (surface) block.api = surface;\n\n const kind = entry.credential?.kind ?? \"none\";\n if (kind === \"none\") {\n block.auth = \"none\";\n } else if (kind === \"sigv4\" || kind === \"google_adc\" || kind === \"azure_entra\") {\n // Ambient signing chains: the AWS/Google/Azure SDK inside omp signs the\n // request from its own environment. There is no token to hand over, and\n // omp must not treat the provider as unavailable for the lack of one.\n block.auth = \"none\";\n } else {\n block.apiKey = providerCredentialEnvName(id);\n // `bearer` is the only kind that needs the header injected; the Anthropic\n // and Azure surfaces place an `api_key_header` credential themselves.\n if (kind === \"bearer\" || kind === \"oauth\") block.authHeader = true;\n }\n\n const headers = { ...entry.headers };\n if (entry.query_params && Object.keys(entry.query_params).length > 0) {\n if (surface === \"bedrock-converse-stream\") {\n // omp keeps a query string on a Bedrock `baseUrl` and appends it to the\n // final URL (and to SigV4's canonical request) — the documented carrier\n // for gateways that authenticate by query parameter.\n const search = new URLSearchParams(entry.query_params).toString();\n block.baseUrl = `${baseUrl}${baseUrl.includes(\"?\") ? \"&\" : \"?\"}${search}`;\n } else {\n warnings.push(\n `provider '${id}' declares query_params, which omp's models.yml has no slot for on surface ` +\n `'${surface ?? \"unset\"}' — they were dropped`,\n );\n }\n }\n if (Object.keys(headers).length > 0) block.headers = headers;\n\n const discoveryType = entry.discovery?.type;\n if (discoveryType) {\n if (!OMP_DISCOVERY_TYPES.includes(discoveryType)) {\n warnings.push(\n `provider '${id}' declares discovery '${discoveryType}', which omp does not implement — ` +\n `models come from model_map only`,\n );\n } else if (!surface && discoveryType !== \"proxy\") {\n warnings.push(\n `provider '${id}' declares discovery '${discoveryType}' but no surface — omp requires ` +\n `provider-level api for every discovery type but 'proxy'`,\n );\n } else {\n block.discovery = { type: discoveryType };\n }\n }\n\n const models: OmpModelBlock[] = [];\n for (const [logical, providerSide] of entryModelIds(entry)) {\n const model: OmpModelBlock = { id: providerSide };\n if (logical !== providerSide) model.name = logical;\n const caps = entry.capabilities?.[logical];\n if (caps?.context_window !== undefined) model.contextWindow = caps.context_window;\n if (caps?.images !== undefined) model.input = caps.images ? [\"text\", \"image\"] : [\"text\"];\n if (caps?.tools !== undefined) model.supportsTools = caps.tools;\n models.push(model);\n }\n if (models.length > 0) {\n if (!surface) {\n warnings.push(\n `provider '${id}' declares models but no surface — omp requires api at provider or model level`,\n );\n return undefined;\n }\n block.models = models;\n } else if (!block.discovery) {\n warnings.push(\n `provider '${id}' declares neither model_map/capabilities nor a discovery omp implements — ` +\n `it will only override an omp built-in provider of the same id`,\n );\n }\n\n return block;\n}\n\n/**\n * Resolve the `roles` table into omp `modelRoles` selectors.\n *\n * Roles do not chain, so each value is resolved as a plain selector rather than\n * through `@role` expansion. A trailing omp thinking suffix (`:high`) survives\n * untouched: it is not part of any `model_map` key, so it falls through\n * `parseModelRef`'s literal path and is re-emitted on the provider-side id.\n */\nfunction renderModelRoles(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n roles: Record<string, string> | undefined,\n modelRef: string | undefined,\n warnings: string[],\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [role, selector] of Object.entries(roles ?? {})) {\n const trimmed = selector.trim();\n if (!trimmed) continue;\n const ref = parseModelRef(trimmed, registry);\n if (!ref?.providerModelId) {\n warnings.push(\n `role '${role}' ('${selector}') resolves to no model in this registry — dropped`,\n );\n continue;\n }\n // An id no entry lists is passed on as typed, never under the first entry's name.\n out[role] = ref.fallback ? trimmed : `${ref.providerId}/${ref.providerModelId}`;\n }\n if (out.default === undefined && modelRef) {\n const ref = parseModelRef(modelRef, registry, roles);\n if (ref?.providerModelId && !ref.fallback) {\n out.default = `${ref.providerId}/${ref.providerModelId}`;\n }\n }\n return out;\n}\n\n/**\n * The warning for an entry left out of `models.yml` because its credential does not resolve.\n * `skaile run` and `skaile repl` print the same fact as one `! provider ... is not used` line\n * (runner `credential-notice.ts`), so the harness keeps this warning off the console.\n */\nfunction credentialOmissionWarning(id: string, reason: string): string {\n return `provider '${id}' omitted from models.yml: ${reason}`;\n}\n\n/** True for a warning built by {@link credentialOmissionWarning}. */\nexport function isCredentialOmissionWarning(warning: string): boolean {\n return /^provider '[^']+' omitted from models\\.yml: /.test(warning);\n}\n\n/**\n * Serialize a registry into the two omp files plus the credential environment\n * that carries their secrets.\n *\n * Only enabled `llm`/`embed` entries are rendered: `stt`/`tts` entries have no\n * wire surface and omp has no slot for them. The credential environment is\n * scoped to the same set — the omp child has no use for a Deepgram key, and a\n * secret that reaches a process which cannot spend it is pure exposure.\n *\n * An entry whose credential does not resolve here still gets its\n * `SKAILE_AIP_<ID>_KEY` name written into `models.yml`: a `platform:` ref is\n * resolved by the session boundary, which materializes the value into\n * `AgentConfig.env` under that same programme-standard name.\n */\nexport function renderOmpRegistry(\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n options: RenderOmpRegistryOptions = {},\n): OmpRegistryRender {\n const warnings: string[] = [];\n const providers: Record<string, OmpProviderBlock> = {};\n const providerIds: string[] = [];\n const credentialEnv: Record<string, string> = {};\n\n // An entry whose credential cannot be resolved here is not handed to omp: it\n // would send an empty key (`invalid x-api-key`) and shadow omp's own login for\n // the same provider.\n const unresolved = new Map(\n unresolvedProviderCredentials(registry, options).map((u) => [u.providerId, u.reason]),\n );\n for (const [id, entry] of registryEntries(registry)) {\n if (entry.kind !== \"llm\" && entry.kind !== \"embed\") continue;\n if (!isEntryEnabled(entry)) continue;\n const reason = unresolved.get(id);\n if (reason) {\n warnings.push(credentialOmissionWarning(id, reason));\n continue;\n }\n const block = renderProvider(id, entry as AIProviderLlmEntry, warnings);\n if (!block) continue;\n providers[id] = block;\n providerIds.push(id);\n // Only the canonical name, never a vendor-conventional alias: every\n // endpoint omp may address is named in models.yml with its own variable,\n // and a stray `ANTHROPIC_API_KEY` would silently make omp's *built-in*\n // Anthropic provider look authenticated with some gateway entry's key.\n const secret = entryCredentialValue(id, entry, options);\n if (secret) credentialEnv[providerCredentialEnvName(id)] = secret;\n }\n\n const modelRoles = renderModelRoles(registry, options.roles, options.modelRef, warnings);\n\n const settings: Record<string, unknown> = { ...options.baseSettings };\n if (Object.keys(modelRoles).length > 0) settings.modelRoles = modelRoles;\n\n return {\n modelsYml: stringify({ providers }),\n configYml: stringify(settings),\n credentialEnv,\n providerIds,\n modelRoles,\n warnings,\n };\n}\n\n/**\n * The models a registry makes selectable, as the harness-neutral catalog entry.\n *\n * ids are `<providerId>/<providerModelId>` — the exact selector omp's `--model`\n * and `modelRoles` take, and unambiguous when two entries serve the same model\n * id, which is the normal case once a session carries N providers.\n */\nexport function registryModelEntries(\n registry: AIProviderRegistry | MergedAIProviderRegistry | undefined,\n): ModelEntry[] {\n if (!registry) return [];\n const out: ModelEntry[] = [];\n for (const [id, entry] of registryEntries(registry)) {\n if (entry.kind !== \"llm\" && entry.kind !== \"embed\") continue;\n if (!isEntryEnabled(entry)) continue;\n const label = entry.label ?? id;\n for (const [logical, providerSide] of entryModelIds(entry as AIProviderLlmEntry)) {\n out.push({ id: `${id}/${providerSide}`, name: `${label} ${logical}` });\n }\n }\n return out;\n}\n\n/**\n * Why omp cannot serve `<providerId>/<model>` from this registry, or `undefined` when it can (or\n * when this check cannot tell). omp knows only the models a registry entry declares\n * (`model_map`, `capabilities`) or its `discovery` lists: for a provider id omp has no login for\n * and an entry that declares neither, `omp --model fake/fake-1` exits with `Model \"fake/fake-1\"\n * not found` on the first prompt (p1334). `nativeProviders` are the ids omp ships a login for;\n * their entry only overrides the built-in provider, so the model may still be omp's own.\n */\nexport function ompRegistryModelRefusal(\n registry: AIProviderRegistry | MergedAIProviderRegistry | undefined,\n selector: string,\n nativeProviders: ReadonlySet<string>,\n): string | undefined {\n if (!registry) return undefined;\n const slash = selector.indexOf(\"/\");\n if (slash <= 0) return undefined;\n const head = selector.slice(0, slash);\n // A trailing omp thinking suffix (`:high`) is not part of the model id.\n const model = selector.slice(slash + 1).replace(/:(off|minimal|low|medium|high|xhigh)$/i, \"\");\n if (!model || nativeProviders.has(head)) return undefined;\n const found = registryEntries(registry).find(([id]) => id === head);\n if (!found) return undefined;\n const [, entry] = found;\n if ((entry.kind !== \"llm\" && entry.kind !== \"embed\") || !isEntryEnabled(entry)) return undefined;\n const llm = entry as AIProviderLlmEntry;\n if (llm.discovery?.type && OMP_DISCOVERY_TYPES.includes(llm.discovery.type)) return undefined;\n const known = entryModelIds(llm).flatMap(([logical, providerSide]) => [logical, providerSide]);\n if (known.includes(model)) return undefined;\n return known.length === 0\n ? `omp cannot serve model '${selector}': registry entry '${head}' declares no models (add model_map or capabilities to it in providers.yml), and omp has no login for '${head}'. Pick a model omp lists.`\n : `omp cannot serve model '${selector}': registry entry '${head}' declares ${known.join(\", \")}, not '${model}'. Pick one of those, or add '${model}' to the entry's model_map.`;\n}\n\n/** Options for {@link materializeOmpAgentDir}. */\nexport interface MaterializeOmpAgentDirOptions extends RenderOmpRegistryOptions {\n /**\n * The user's own omp agent directory to seed from — its auth store\n * (`agent.db`) is linked in so a standalone session keeps the login the\n * developer already has, and its `config.yml` is read as base settings.\n * Sessions, history, `mcp.json` and extensions are not linked. Absent (the\n * platform case) seeds nothing. A missing directory is not an error: it is the platform case.\n */\n seedFrom?: string;\n /**\n * GitAgent identity directory (`AgentConfig.agentDir`) whose contents omp\n * reads out of the same base: `agent.yaml`, `SOUL.md`, `RULES.md`,\n * `knowledge/`. Linked in after the seed, so identity wins a name clash.\n */\n identityDir?: string;\n}\n\n/** What {@link materializeOmpAgentDir} wrote. */\nexport interface OmpAgentDirMaterialization extends OmpRegistryRender {\n /** The directory `PI_CODING_AGENT_DIR` must point at. */\n agentDir: string;\n /** The directory is the harness's temporary home: remove it when the run ends. */\n ephemeral?: boolean;\n /** Names linked in from {@link MaterializeOmpAgentDirOptions.seedFrom}. */\n seeded: string[];\n /** Names linked in from {@link MaterializeOmpAgentDirOptions.identityDir}. */\n identity: string[];\n}\n\n/** Inputs {@link planOmpAgentDir} derives the session directory layout from. */\nexport interface OmpAgentDirPlanInput {\n /** Session working directory. Distinguishes two default-named sessions. */\n cwd: string;\n /** Session id — the directory key, so concurrent sessions never collide. */\n sessionId?: string;\n /** `AgentConfig.harnessOptions.omp`. */\n options?: OmpHarnessOptions;\n /** Home the default seed source resolves against. Defaults to `os.homedir()`. */\n homeDir?: string;\n /** Root the private directory is created under. Defaults to `os.tmpdir()`. */\n tmpDir?: string;\n}\n\n/** Where a session's omp agent directory lives, and what it inherits. */\nexport interface OmpAgentDirPlan {\n /** Session-private directory `PI_CODING_AGENT_DIR` points at. */\n agentDir: string;\n /** User agent directory whose login is linked in, when there is one to inherit. */\n seedFrom?: string;\n /**\n * The directory is the harness's own temporary home, to be removed when the run ends. False\n * when the session named its own `harnessOptions.omp.agentHome`, which belongs to the user.\n */\n ephemeral: boolean;\n}\n\n/**\n * Decide the session-private agent directory and whether it inherits the\n * developer's omp state.\n *\n * The directory is deliberately **outside `cwd`**. It holds omp's credential\n * store — a symlink to the developer's `agent.db` on a standalone machine —\n * and `cwd` is the one tree the agent has write access to by design; managed\n * codex draws the same line and rejects a private directory nested in the\n * workspace (`codex/instance-state.ts`). Sessions are keyed by id, falling\n * back to a digest of the workspace path. The temporary directory is `<key>-<random>`, created per\n * call, so no two runs share one (and one run's cleanup never removes another's).\n *\n * Seeding keys on the user directory *existing*, which is exactly the\n * platform/standalone distinction the plan draws: a platform container has no\n * `~/.omp/agent`, so the session correctly starts empty; a developer machine\n * has one, so the session keeps the logins already stored there.\n * `harnessOptions.omp.seedUserAgentDir: false` forces the empty case anyway.\n */\nexport async function planOmpAgentDir(input: OmpAgentDirPlanInput): Promise<OmpAgentDirPlan> {\n const options = input.options;\n const key =\n input.sessionId?.trim() ||\n createHash(\"sha256\").update(path.resolve(input.cwd)).digest(\"hex\").slice(0, 16);\n const ephemeral = options?.agentHome === undefined;\n // The temporary home is unique per spawn: callers key sessions loosely (`skaile chat` passes\n // none, `serve` without --session-id uses one shared id, sub-prompt harnesses share a hash), and\n // the harness deletes its home when its run ends, which must never reach a sibling's home.\n let agentDir = options?.agentHome ?? \"\";\n if (ephemeral) {\n const root = path.join(input.tmpDir ?? os.tmpdir(), \"skaile-omp-agent\");\n await fs.mkdir(root, { recursive: true });\n await sweepStaleOmpHomes(root);\n agentDir = await fs.mkdtemp(path.join(root, `${key.replace(/[^A-Za-z0-9._-]/g, \"_\")}-`));\n await fs.writeFile(path.join(agentDir, OWNER_FILE), String(process.pid));\n }\n if (options?.seedUserAgentDir === false) return { agentDir, ephemeral };\n\n const seedFrom =\n options?.userAgentDir ?? path.join(input.homeDir ?? os.homedir(), \".omp\", \"agent\");\n if (path.resolve(seedFrom) === path.resolve(agentDir)) return { agentDir, ephemeral };\n try {\n if (!(await fs.stat(seedFrom)).isDirectory()) return { agentDir, ephemeral };\n } catch {\n return { agentDir, ephemeral };\n }\n return { agentDir, seedFrom, ephemeral };\n}\n\n/** Names the process that created a temporary home; the sweep keeps a home whose owner lives. */\nconst OWNER_FILE = \".skaile-owner-pid\";\n/** A temporary home older than this whose owner is gone is removed at the next start. */\nconst STALE_HOME_MS = 24 * 60 * 60 * 1000;\n\n/**\n * The names skaile gave a temporary home: `<key>-<six random characters>` (`mkdtemp`), and\n * `<key>-<12 hex>` from releases before 5.16 (p1151).\n */\nconst SKAILE_HOME_NAME = /^[A-Za-z0-9._-]+-(?:[A-Za-z0-9]{6}|[0-9a-f]{12})$/;\n\nfunction processAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === \"EPERM\";\n }\n}\n\n/**\n * Whether nothing listens on the unix socket `file`: a connect is refused (the process that\n * bound it is gone) or finds no socket. A socket somebody still serves, or one that does not\n * answer within a second, counts as in use.\n */\nfunction socketIsDead(file: string): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const conn = net.connect(file);\n const done = (dead: boolean) => {\n conn.destroy();\n resolve(dead);\n };\n conn.setTimeout(1000, () => done(false));\n conn.once(\"connect\", () => done(false));\n conn.once(\"error\", (err: NodeJS.ErrnoException) =>\n done(err.code === \"ECONNREFUSED\" || err.code === \"ENOENT\"),\n );\n });\n}\n\n/**\n * Remove temporary homes older than a day whose creating process is gone: a run that was killed\n * never reached the harness's own cleanup, and every one leaves symlinks and databases behind\n * (p811). A home of a live process is kept whatever its age. A unix socket of that age that\n * nobody listens on is removed too (omp binds one beside the homes and a killed run leaves it,\n * p1316). Best effort: a failure is ignored.\n */\nasync function sweepStaleOmpHomes(root: string, now = Date.now()): Promise<void> {\n let names: string[];\n try {\n names = await fs.readdir(root);\n } catch {\n return;\n }\n await Promise.all(\n names.map(async (name) => {\n const home = path.join(root, name);\n try {\n const stat = await fs.lstat(home);\n if (now - stat.mtimeMs < STALE_HOME_MS) return;\n if (stat.isSocket()) {\n if (await socketIsDead(home)) await fs.rm(home, { force: true });\n return;\n }\n if (!stat.isDirectory()) return;\n const owner = Number.parseInt(\n await fs.readFile(path.join(home, OWNER_FILE), \"utf8\").catch(() => \"\"),\n 10,\n );\n if (Number.isInteger(owner) && processAlive(owner)) return;\n // A home with no owner file is one an older version made: remove it only when its\n // name has the `<key>-<six random characters>` shape `mkdtemp` gives (never a folder\n // somebody else put in this directory).\n if (!Number.isInteger(owner) && !SKAILE_HOME_NAME.test(name)) return;\n await fs.rm(home, { recursive: true, force: true });\n } catch {\n /* another process may be sweeping the same home */\n }\n }),\n );\n}\n\n/**\n * Run the steps that fill a planned home; when one throws, remove a temporary home before\n * rethrowing. The harness only learns the home (and deletes it at cleanup) once these steps\n * return, so a failure here would otherwise leave a new directory per spawn behind.\n */\nasync function removeHomeOnThrow<T>(plan: OmpAgentDirPlan, fill: () => Promise<T>): Promise<T> {\n try {\n return await fill();\n } catch (err) {\n if (plan.ephemeral) await fs.rm(plan.agentDir, { recursive: true, force: true });\n throw err;\n }\n}\n\n/** Remove a path whatever it is, without following a symlink into its target. */\nasync function removeEntry(target: string): Promise<void> {\n let stat: Stats;\n try {\n stat = await fs.lstat(target);\n } catch {\n return;\n }\n if (stat.isSymbolicLink() || stat.isFile()) {\n await fs.unlink(target);\n return;\n }\n await fs.rm(target, { recursive: true, force: true });\n}\n\n/** Symlink every entry of `sourceDir` into `dir`, skipping the owned names. */\nasync function linkInto(\n dir: string,\n sourceDir: string,\n skip: Record<string, true>,\n): Promise<string[]> {\n let names: string[];\n try {\n names = await fs.readdir(sourceDir);\n } catch {\n return [];\n }\n const linked: string[] = [];\n for (const name of names) {\n if (skip[name]) continue;\n const target = path.join(dir, name);\n await removeEntry(target);\n await fs.symlink(path.join(sourceDir, name), target);\n linked.push(name);\n }\n return linked;\n}\n\n/**\n * Remove the symlinks into the user's agent directory that an older release (or a home the\n * session named itself) left in `dir`: only the login files may point there (p811).\n */\nasync function dropStaleSeedLinks(dir: string, sourceDir: string): Promise<void> {\n let names: string[];\n try {\n names = await fs.readdir(dir);\n } catch {\n return;\n }\n const root = path.resolve(sourceDir);\n for (const name of names) {\n if ((OMP_LOGIN_FILES as readonly string[]).includes(name)) continue;\n const entry = path.join(dir, name);\n try {\n if (!(await fs.lstat(entry)).isSymbolicLink()) continue;\n const to = path.resolve(dir, await fs.readlink(entry));\n if (to === root || to.startsWith(root + path.sep)) await fs.unlink(entry);\n } catch {\n // Gone or unreadable: nothing to drop.\n }\n }\n}\n\n/** Symlink the login files (see {@link OMP_LOGIN_FILES}) of the user's agent directory into `dir`. */\nasync function linkLoginFiles(dir: string, sourceDir: string): Promise<string[]> {\n await dropStaleSeedLinks(dir, sourceDir);\n const linked: string[] = [];\n for (const name of OMP_LOGIN_FILES) {\n const from = path.join(sourceDir, name);\n try {\n if (!(await fs.stat(from)).isFile()) continue;\n } catch {\n continue;\n }\n const target = path.join(dir, name);\n await removeEntry(target);\n await fs.symlink(from, target);\n linked.push(name);\n }\n return linked;\n}\n\n/** Read a seeded `config.yml` as the base settings, or `{}` when unusable. */\nasync function readSeededSettings(seedFrom: string): Promise<Record<string, unknown>> {\n for (const name of [\"config.yml\", \"config.yaml\"]) {\n let raw: string;\n try {\n raw = await fs.readFile(path.join(seedFrom, name), \"utf-8\");\n } catch {\n continue;\n }\n const parsed = parse(raw) as unknown;\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n }\n return {};\n}\n\n/**\n * The model selector of the user's own omp default (`modelRoles.default` in their `config.yml`)\n * when it can only be served by their own `models.yml`, else `undefined` (p1172).\n *\n * The session-private home never copies the user's `models.yml`: it holds their credentials.\n * A default such as `anthropic/claude-opus-5-5` that their `models.yml` defines (a gateway, a\n * local server) then names a provider the private home does not have, and omp quietly picks\n * another model. A default on a built-in omp provider keeps working there (its login is linked\n * in), and a provider the registry renders is there too, so neither is reported.\n */\nasync function ownDefaultNeedingOwnModels(\n seedFrom: string,\n rendered: readonly string[],\n): Promise<string | undefined> {\n const selector = (await readSeededSettings(seedFrom)).modelRoles;\n const own =\n selector && typeof selector === \"object\" && !Array.isArray(selector)\n ? (selector as Record<string, unknown>).default\n : undefined;\n if (typeof own !== \"string\" || !own.includes(\"/\")) return undefined;\n const providerId = own.slice(0, own.indexOf(\"/\"));\n if (rendered.includes(providerId)) return undefined;\n let raw: string;\n try {\n raw = await fs.readFile(path.join(seedFrom, OMP_MODELS_FILENAME), \"utf-8\");\n } catch {\n return undefined;\n }\n const providers = (parse(raw) as { providers?: unknown } | null)?.providers;\n if (!providers || typeof providers !== \"object\" || Array.isArray(providers)) return undefined;\n return providerId in providers ? own : undefined;\n}\n\n/**\n * Build the session-private agent directory and write omp's two files into it.\n *\n * The user's `~/.omp/agent/models.yml` and `config.yml` are never opened for\n * writing: `config.yml` is *copied* into the session (so a token refresh or a\n * settings write inside the session cannot reach back through a symlink),\n * `models.yml` is not seeded at all, and everything else — `agent.db*` above\n * all — is symlinked so the session shares the developer's logins and caches.\n */\nexport async function materializeOmpAgentDir(\n agentDir: string,\n registry: AIProviderRegistry | MergedAIProviderRegistry,\n options: MaterializeOmpAgentDirOptions = {},\n): Promise<OmpAgentDirMaterialization> {\n await fs.mkdir(agentDir, { recursive: true });\n\n const seeded = options.seedFrom ? await linkLoginFiles(agentDir, options.seedFrom) : [];\n const identity = options.identityDir\n ? await linkInto(agentDir, options.identityDir, OWNED_AGENT_DIR_FILES)\n : [];\n\n const baseSettings =\n options.baseSettings ??\n (options.seedFrom ? await readSeededSettings(options.seedFrom) : undefined);\n\n const render = renderOmpRegistry(registry, { ...options, baseSettings });\n\n await fs.writeFile(path.join(agentDir, OMP_MODELS_FILENAME), render.modelsYml, \"utf-8\");\n await fs.writeFile(path.join(agentDir, OMP_CONFIG_FILENAME), render.configYml, \"utf-8\");\n\n return { ...render, agentDir, seeded, identity };\n}\n\n/** What the omp harness gets back from {@link materializeOmpProviders}. */\nexport interface OmpProviderMaterialization extends OmpAgentDirMaterialization {\n /**\n * The `--model` argument for this session: `<providerId>/<providerModelId>`,\n * the one selector form omp treats as unambiguous when several providers\n * carry the same model id. Absent when the session named no model.\n */\n modelArg?: string;\n}\n\n/**\n * The whole omp adapter for one session: decide the private agent directory,\n * inherit the developer's omp state where there is any, write `models.yml` and\n * `config.yml`, and report the credential environment and `--model` selector\n * the child needs.\n *\n * Returns `undefined` when the session carries no registry with a selectable\n * entry — the harness then behaves exactly as it did before the registry\n * existed, which is what keeps this an expand-and-contract change.\n *\n * Also returns `undefined` when the session names no model (no `--model`, no\n * `default` role) and the user's own omp default is served by the user's own\n * `models.yml`, which a private home does not carry (p1172): the registry would\n * only swap that default for whatever model omp finds first.\n *\n * Also returns `undefined` when no entry can be handed to omp (every\n * credential unresolved) or when the entry the session's model selects was\n * left out: a session-private agent directory would then start omp without the\n * user's own settings, and a model that only the user's own omp login can\n * serve would fail with `No API key found` although native omp answers. The\n * harness then starts omp on the user's agent directory, so \"omp falls back to\n * its own login\" is true.\n *\n * `env:` references resolve against the runner's environment *overlaid with*\n * `config.env`, so a credential the session boundary already resolved (a\n * `platform:` secret it turned into an env var, for instance) is found here\n * under the name the registry entry points at.\n */\nexport async function materializeOmpProviders(\n config: AgentConfig,\n): Promise<OmpProviderMaterialization | undefined> {\n const registry = config.registry;\n if (!registry) return undefined;\n const selectable = registryEntries(registry).some(\n ([, entry]) => (entry.kind === \"llm\" || entry.kind === \"embed\") && isEntryEnabled(entry),\n );\n if (!selectable) return undefined;\n\n const env = { ...process.env, ...config.env };\n const selected = config.modelRef\n ? parseModelRef(config.modelRef, registry, config.roles)\n : undefined;\n const usable = renderOmpRegistry(registry, {\n env,\n ...(config.roles ? { roles: config.roles } : {}),\n ...(config.modelRef ? { modelRef: config.modelRef } : {}),\n }).providerIds;\n if (usable.length === 0) return undefined;\n // An id no entry lists is no entry's model: omp gets it as typed, whichever entry is first.\n if (selected && !selected.fallback && !usable.includes(selected.providerId)) return undefined;\n\n const plan = await planOmpAgentDir({\n cwd: config.cwd,\n ...(config.sessionId ? { sessionId: config.sessionId } : {}),\n ...(config.harnessOptions?.omp ? { options: config.harnessOptions.omp } : {}),\n });\n\n if (!selected && !config.model && plan.seedFrom) {\n const named = renderOmpRegistry(registry, {\n env,\n ...(config.roles ? { roles: config.roles } : {}),\n }).modelRoles;\n if (named.default === undefined && (await ownDefaultNeedingOwnModels(plan.seedFrom, usable))) {\n if (plan.ephemeral) await fs.rm(plan.agentDir, { recursive: true, force: true });\n return undefined;\n }\n }\n\n const rendered = await removeHomeOnThrow(plan, () =>\n materializeOmpAgentDir(plan.agentDir, registry, {\n env,\n ...(plan.seedFrom ? { seedFrom: plan.seedFrom } : {}),\n ...(config.agentDir ? { identityDir: config.agentDir } : {}),\n ...(config.roles ? { roles: config.roles } : {}),\n ...(config.modelRef ? { modelRef: config.modelRef } : {}),\n }),\n );\n\n return {\n ...rendered,\n ephemeral: plan.ephemeral,\n ...(selected?.providerModelId && !selected.fallback\n ? { modelArg: `${selected.providerId}/${selected.providerModelId}` }\n : {}),\n };\n}\n\n/** What {@link materializeOmpIdentityDir} wrote. */\nexport interface OmpIdentityDirMaterialization {\n /** The directory `PI_CODING_AGENT_DIR` must point at. */\n agentDir: string;\n /** The directory is the harness's temporary home: remove it when the run ends. */\n ephemeral: boolean;\n /** Names linked in from the user's own omp agent directory. */\n seeded: string[];\n /** Names linked in from `AgentConfig.agentDir`. */\n identity: string[];\n}\n\n/**\n * The omp home of a session that has an agent directory but no provider registry.\n *\n * omp keeps its runtime state (`agent.db`, `models.db`, `skill-descriptions.db`, session\n * scratch, `intercom/`) in `PI_CODING_AGENT_DIR`. Pointing that at the agent directory itself\n * put those files beside `SOUL.md` in a pinned, shared source (`.skaile/cache/agents/<name>/`)\n * and made omp name a path inside the cache when it lacks a credential. So the home is a\n * private directory outside `cwd` (see {@link planOmpAgentDir}): the developer's own omp state\n * is linked in (their login keeps working), their `config.yml` / `models.yml` are copied (a\n * settings write cannot reach back), and the agent directory's entries are linked in last,\n * so the agent files stay where they are and omp can still read them.\n *\n * Returns `undefined` when the session has no `agentDir`.\n */\nexport async function materializeOmpIdentityDir(\n config: AgentConfig,\n): Promise<OmpIdentityDirMaterialization | undefined> {\n const identityDir = config.agentDir;\n if (!identityDir) return undefined;\n // Keyed by the agent and the workspace too: two role children of one session, each with\n // its own agent directory, must not link their entries into one home.\n const agentKey = createHash(\"sha256\")\n .update(`${path.resolve(identityDir)}\\0${path.resolve(config.cwd)}`)\n .digest(\"hex\")\n .slice(0, 12);\n const plan = await planOmpAgentDir({\n cwd: config.cwd,\n sessionId: `${config.sessionId?.trim() || \"agent\"}-${agentKey}`,\n ...(config.harnessOptions?.omp ? { options: config.harnessOptions.omp } : {}),\n });\n return removeHomeOnThrow(plan, async () => {\n await fs.mkdir(plan.agentDir, { recursive: true });\n const seeded = plan.seedFrom ? await linkLoginFiles(plan.agentDir, plan.seedFrom) : [];\n if (plan.seedFrom) {\n for (const name of Object.keys(OWNED_AGENT_DIR_FILES)) {\n const from = path.join(plan.seedFrom, name);\n try {\n if (!(await fs.stat(from)).isFile()) continue;\n } catch {\n continue;\n }\n const to = path.join(plan.agentDir, name);\n await removeEntry(to);\n await fs.copyFile(from, to);\n }\n }\n const identity = await linkInto(plan.agentDir, identityDir, {\n ...OWNED_AGENT_DIR_FILES,\n ...OMP_RUNTIME_ENTRIES,\n });\n return { agentDir: plan.agentDir, ephemeral: plan.ephemeral, seeded, identity };\n });\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { tryWithFsDeadline, withFsDeadline, fsDeadlineMs } from './chunk-AVFRFGM2.js';
1
+ import { tryWithFsDeadline, withFsDeadline, fsDeadlineMs } from './chunk-GNUA7XT2.js';
2
2
  import { createLogger } from './chunk-BOFL7GIF.js';
3
3
  import { stat, mkdir, cp, writeFile, rm } from 'fs/promises';
4
4
  import { resolve, sep, join } from 'path';
@@ -155,5 +155,5 @@ function resolveFlowSkills(flow, allEntries) {
155
155
  }
156
156
 
157
157
  export { WORKSPACE_MOUNT_ENV_VAR, deployAll, deployCatalogEntry, findAiAssetsRoot, isUnderWorkspaceMount, resolveFlowSkills, undeployCatalogEntry, workspaceMountDirs };
158
- //# sourceMappingURL=chunk-3DA74PLW.js.map
159
- //# sourceMappingURL=chunk-3DA74PLW.js.map
158
+ //# sourceMappingURL=chunk-USSP43U3.js.map
159
+ //# sourceMappingURL=chunk-USSP43U3.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../asset-manager/src/catalog-deployer.ts"],"names":[],"mappings":"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","file":"chunk-3DA74PLW.js","sourcesContent":["/**\n * Platform-triggered asset deployment.\n *\n * Takes catalog entries (with source_path relative to ai-assets/) and deploys\n * them to a session's .claude/skills/ directory. Handles skill context injection\n * and catalog priority-based name resolution.\n */\n\nimport { cp, mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve, sep } from \"node:path\";\nimport { fsDeadlineMs, tryWithFsDeadline, withFsDeadline } from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\n\n// ---------------------------------------------------------------------------\n// Types (formerly in catalog-compiler.ts, inlined after tear-out in Task 1.5)\n// ---------------------------------------------------------------------------\n\n/**\n * A single user-facing input parameter declared in a SKILL.md.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface InputSpec {\n /** Input parameter key used in skill invocation. */\n key: string;\n /** Whether the input must be provided before running the skill. */\n required?: boolean;\n /** Question string shown to the user when collecting this input. */\n prompt?: string;\n /** Short display label for UI forms. */\n label?: string;\n /** Input data type hint (e.g. `\"string\"`, `\"number\"`, `\"file\"`). */\n type?: string;\n /** Additional guidance text shown alongside the input field. */\n hint?: string;\n}\n\n/**\n * A compiled catalog entry (skill or flow).\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface CatalogEntryCompiled {\n /** Unique ID in `publisher/name` form (e.g. `skaileup/cf_overview`). */\n id: string;\n /** Asset kind. */\n kind: \"skill\" | \"flow\";\n /** Human-readable asset name. */\n name: string;\n /** One-line description. */\n description: string;\n /** Semantic version string. */\n version: string;\n /** Maturity stage. */\n stage: \"alpha\" | \"beta\" | \"stable\";\n /** Searchable keywords. */\n keywords: string[];\n /** User-facing input specifications. */\n inputs: InputSpec[];\n /** Asset path relative to assetsRoot. */\n source_path: string;\n /** Optional icon identifier. */\n icon?: string;\n /** Flow-only: required skill names. */\n required_skills?: string[];\n /** Flow-only: optional skill names. */\n optional_skills?: string[];\n}\n\n/**\n * Options controlling how platform-triggered skill deployment is performed.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface DeployFromCatalogOptions {\n /** Root directory of ai-assets (where `source_path` in catalog entries is relative to). */\n assetsRoot: string;\n /** Target directory for deployed skills (e.g. `/workspace/.claude/skills/`). */\n skillsDir: string;\n /** Optional context markdown appended to the deployed skill directory as `CONTEXT.md`. */\n context?: string;\n}\n\n/**\n * Result of a platform-triggered batch skill deployment.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface DeployResult {\n /** IDs of catalog entries successfully deployed. */\n deployed: string[];\n /** IDs of catalog entries skipped (non-skill kinds). */\n skipped: string[];\n /** Error messages for entries that could not be deployed. */\n errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Workspace-mount awareness\n// ---------------------------------------------------------------------------\n\n/**\n * Multiplier applied to the base filesystem deadline for whole-tree operations\n * (recursive copy / remove), which legitimately outlast a single `stat`.\n */\nconst TREE_OP_DEADLINE_FACTOR = 4;\n\n/** Default number of parent levels {@link findAiAssetsRoot} inspects. */\nconst AI_ASSETS_WALK_LEVELS = 6;\n\nlet deployerLogger: ReturnType<typeof createLogger> | undefined;\n\nfunction log(): ReturnType<typeof createLogger> {\n deployerLogger ??= createLogger({ kind: \"runner\", subkind: \"catalog-deployer\" });\n return deployerLogger;\n}\n\n/**\n * Where the agent container binds its rclone FUSE mount. Nothing under this\n * path is a safe place to read an asset tree from: the mount is remote\n * (SharePoint / OneDrive / WebDAV) and can wedge indefinitely.\n */\nconst DEFAULT_WORKSPACE_MOUNT_DIR = \"/skaile/workspace\";\n\n/**\n * Env override for the workspace-mount path(s), comma-separated.\n *\n * Set it when the runner binds the mount somewhere other than\n * {@link DEFAULT_WORKSPACE_MOUNT_DIR}; set it to the empty string to disable\n * the guard entirely (single-machine dev, where nothing is a network mount).\n */\nexport const WORKSPACE_MOUNT_ENV_VAR = \"SKAILE_WORKSPACE_MOUNT_DIR\";\n\n/**\n * Resolve the directories treated as network mounts.\n *\n * Read per call rather than cached: the runner mutates `process.env` while\n * wiring a session, so a module-load snapshot would pin a pre-configuration\n * value.\n *\n * @returns Absolute mount paths; empty when the guard is disabled.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function workspaceMountDirs(): string[] {\n const raw = process.env[WORKSPACE_MOUNT_ENV_VAR];\n if (raw === undefined) return [DEFAULT_WORKSPACE_MOUNT_DIR];\n return raw\n .split(\",\")\n .map((segment) => segment.trim())\n .filter((segment) => segment.length > 0)\n .map((segment) => resolve(segment));\n}\n\n/**\n * Is `candidate` at, or inside, one of the known workspace mount paths?\n *\n * Pure path arithmetic — deliberately no filesystem access, because the whole\n * point is to decide *before* touching a path that might be unresponsive.\n *\n * @param candidate - Path to test.\n * @param mountDirs - Mount roots; defaults to {@link workspaceMountDirs}.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function isUnderWorkspaceMount(\n candidate: string,\n mountDirs: string[] = workspaceMountDirs(),\n): boolean {\n const target = resolve(candidate);\n return mountDirs.some((dir) => {\n const root = resolve(dir);\n return target === root || target.startsWith(root + sep);\n });\n}\n\n/**\n * Walk upward from `startDir` looking for an `ai-assets/` directory.\n *\n * Two properties matter beyond \"find the folder\":\n *\n * 1. **Never synchronous.** The walk probes up to six directories; any one of\n * them can be on a FUSE mount, and the former `existsSync` chain blocked the\n * event loop on the first unresponsive probe. Each probe is now awaited and\n * deadline-bounded, so a wedged mount costs one skipped candidate.\n * 2. **Never resolves onto a mount.** A hit under the workspace mount is\n * skipped with a warning rather than returned: accepting it would wire every\n * later skill deploy — a recursive copy — to a remote filesystem. The walk\n * continues upward, so a legitimate `ai-assets/` in a parent still wins.\n *\n * Only a **directory** counts. An `ai-assets` file would otherwise be returned\n * as a root and every later `join(root, source_path)` would fail with ENOTDIR.\n *\n * @param startDir - Directory to start from (typically the project dir).\n * @param opts - `levels` caps the upward walk; `mountDirs` overrides the mount\n * roots (defaults to {@link workspaceMountDirs}).\n * @returns Absolute path to the `ai-assets/` directory, or `null` if none is\n * reachable within `levels`.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function findAiAssetsRoot(\n startDir: string,\n opts?: { levels?: number; mountDirs?: string[] },\n): Promise<string | null> {\n const mountDirs = opts?.mountDirs ?? workspaceMountDirs();\n const levels = opts?.levels ?? AI_ASSETS_WALK_LEVELS;\n let dir = resolve(startDir);\n // Every level of a `/skaile/workspace/...` start dir is under the mount, so\n // an unconditional warn would fire once per level for one lookup. Collect and\n // report once — the operator needs the fact, not six copies of it.\n const refused: string[] = [];\n\n for (let i = 0; i < levels; i++) {\n const candidate = join(dir, \"ai-assets\");\n if (isUnderWorkspaceMount(candidate, mountDirs)) {\n refused.push(candidate);\n } else {\n const isDir = await tryWithFsDeadline(\n `stat ${candidate}`,\n async () => (await stat(candidate)).isDirectory(),\n false,\n );\n if (isDir) {\n if (refused.length > 0) warnRefused(refused, mountDirs);\n return candidate;\n }\n }\n const parent = resolve(dir, \"..\");\n if (parent === dir) break; // filesystem root — nothing further up\n dir = parent;\n }\n if (refused.length > 0) warnRefused(refused, mountDirs);\n return null;\n}\n\n/** Single warning for every `ai-assets` candidate skipped for sitting on a mount. */\nfunction warnRefused(refused: string[], mountDirs: string[]): void {\n log().warn(\n \"findAiAssetsRoot refused candidates under a workspace mount — deploying skills from a network mount can stall the session\",\n { refused, mountDirs },\n );\n}\n\n/**\n * Deploy a single catalog entry to the session skills directory.\n *\n * Copies the entire skill source directory into `skillsDir/<entry.name>/`.\n * If `context` is provided, a separate `CONTEXT.md` is written alongside\n * `SKILL.md` so the source file is never modified.\n *\n * Only `skill` entries are deployable; other kinds return an error.\n *\n * **Async by necessity.** This runs from the `session_init` command handler\n * with the WebSocket live, and both `assetsRoot` and `skillsDir` can sit on a\n * network mount. The former `cpSync`/`rmSync` pair parked the event loop for\n * the whole copy; every call is now awaited and deadline-bounded, so an\n * unresponsive mount fails one deployment instead of the session.\n *\n * @param entry - Compiled catalog entry to deploy.\n * @param options - Deployment target and optional context.\n * @returns `{ success: true }` on success, `{ success: false, error }` on failure.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function deployCatalogEntry(\n entry: CatalogEntryCompiled,\n options: DeployFromCatalogOptions,\n): Promise<{ success: boolean; error?: string }> {\n const { assetsRoot, skillsDir, context } = options;\n\n if (entry.kind !== \"skill\") {\n return { success: false, error: `Cannot deploy ${entry.kind} directly — only skills` };\n }\n\n const sourcePath = join(assetsRoot, entry.source_path);\n const skillMdPath = join(sourcePath, \"SKILL.md\");\n\n const hasSkillMd = await tryWithFsDeadline(\n `stat ${skillMdPath}`,\n async () => {\n await stat(skillMdPath);\n return true;\n },\n false,\n );\n if (!hasSkillMd) {\n return { success: false, error: `SKILL.md not found at ${skillMdPath}` };\n }\n\n const destDir = join(skillsDir, entry.name);\n\n try {\n await withFsDeadline(`mkdir ${destDir}`, () => mkdir(destDir, { recursive: true }));\n\n // Copy the entire skill directory\n await withFsDeadline(\n `cp ${sourcePath} -> ${destDir}`,\n () => cp(sourcePath, destDir, { recursive: true }),\n fsDeadlineMs() * TREE_OP_DEADLINE_FACTOR,\n );\n\n // Write context to a separate CONTEXT.md — never modify the original SKILL.md.\n // The agent discovers both files in the skill directory.\n const contextPath = join(destDir, \"CONTEXT.md\");\n if (context) {\n await withFsDeadline(`write ${contextPath}`, () =>\n writeFile(contextPath, `# Additional Context\\n\\n${context}\\n`, \"utf8\"),\n );\n } else {\n // `force: true` makes this a single call: a stale CONTEXT.md is removed,\n // an absent one is a no-op. The former existsSync probe only added a\n // second trip to the same possibly-wedged mount.\n await withFsDeadline(`rm ${contextPath}`, () => rm(contextPath, { force: true }));\n }\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) };\n }\n\n return { success: true };\n}\n\n/**\n * Remove a deployed skill directory from the session skills directory.\n *\n * @param name - Skill name (directory basename under `skillsDir`).\n * @param skillsDir - Absolute path to the session skills directory.\n * @returns `true` if the skill was found and removed; `false` if it was not\n * deployed, or if the directory could not be reached within the deadline.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function undeployCatalogEntry(name: string, skillsDir: string): Promise<boolean> {\n const destDir = join(skillsDir, name);\n const exists = await tryWithFsDeadline(\n `stat ${destDir}`,\n async () => {\n await stat(destDir);\n return true;\n },\n false,\n );\n if (!exists) return false;\n await withFsDeadline(\n `rm -r ${destDir}`,\n () => rm(destDir, { recursive: true, force: true }),\n fsDeadlineMs() * TREE_OP_DEADLINE_FACTOR,\n );\n return true;\n}\n\n/**\n * Deploy multiple catalog entries in a single batch operation.\n *\n * Non-skill entries (flows, agents, etc.) are automatically skipped and\n * recorded in `result.skipped`. Deployment failures are collected in\n * `result.errors` without aborting the rest of the batch.\n *\n * @param entries - Compiled catalog entries to deploy.\n * @param options - Deployment target and optional context.\n * @returns Aggregated {@link DeployResult} with deployed, skipped, and error lists.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function deployAll(\n entries: CatalogEntryCompiled[],\n options: DeployFromCatalogOptions,\n): Promise<DeployResult> {\n const result: DeployResult = { deployed: [], skipped: [], errors: [] };\n\n for (const entry of entries) {\n if (entry.kind !== \"skill\") {\n result.skipped.push(entry.id);\n continue;\n }\n\n // Serial on purpose: concurrent recursive copies onto one mount multiply\n // the queue depth on the exact resource that is already the bottleneck.\n const r = await deployCatalogEntry(entry, options);\n if (r.success) {\n result.deployed.push(entry.id);\n } else {\n result.errors.push(`${entry.id}: ${r.error}`);\n }\n }\n\n return result;\n}\n\n/**\n * Resolve a flow's skill dependencies from the full catalog entry list.\n *\n * Partitions `flow.required_skills` and `flow.optional_skills` into resolved\n * entries and a list of names that could not be found. Missing optional skills\n * are silently ignored (they do not appear in `missing`).\n *\n * @param flow - Compiled flow entry whose skill dependencies should be resolved.\n * @param allEntries - Full set of compiled catalog entries to search.\n * @returns Object containing resolved `required` entries, resolved `optional` entries,\n * and `missing` skill names that were listed as required but not found.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function resolveFlowSkills(\n flow: CatalogEntryCompiled,\n allEntries: CatalogEntryCompiled[],\n): { required: CatalogEntryCompiled[]; optional: CatalogEntryCompiled[]; missing: string[] } {\n const skillsByName = new Map<string, CatalogEntryCompiled>();\n for (const e of allEntries) {\n if (e.kind === \"skill\") skillsByName.set(e.name, e);\n }\n\n const required: CatalogEntryCompiled[] = [];\n const optional: CatalogEntryCompiled[] = [];\n const missing: string[] = [];\n\n for (const name of flow.required_skills ?? []) {\n const entry = skillsByName.get(name);\n if (entry) required.push(entry);\n else missing.push(name);\n }\n\n for (const name of flow.optional_skills ?? []) {\n const entry = skillsByName.get(name);\n if (entry) optional.push(entry);\n // Optional skills don't count as missing\n }\n\n return { required, optional, missing };\n}\n"]}
1
+ {"version":3,"sources":["../asset-manager/src/catalog-deployer.ts"],"names":[],"mappings":"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","file":"chunk-USSP43U3.js","sourcesContent":["/**\n * Platform-triggered asset deployment.\n *\n * Takes catalog entries (with source_path relative to ai-assets/) and deploys\n * them to a session's .claude/skills/ directory. Handles skill context injection\n * and catalog priority-based name resolution.\n */\n\nimport { cp, mkdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join, resolve, sep } from \"node:path\";\nimport { fsDeadlineMs, tryWithFsDeadline, withFsDeadline } from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\n\n// ---------------------------------------------------------------------------\n// Types (formerly in catalog-compiler.ts, inlined after tear-out in Task 1.5)\n// ---------------------------------------------------------------------------\n\n/**\n * A single user-facing input parameter declared in a SKILL.md.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface InputSpec {\n /** Input parameter key used in skill invocation. */\n key: string;\n /** Whether the input must be provided before running the skill. */\n required?: boolean;\n /** Question string shown to the user when collecting this input. */\n prompt?: string;\n /** Short display label for UI forms. */\n label?: string;\n /** Input data type hint (e.g. `\"string\"`, `\"number\"`, `\"file\"`). */\n type?: string;\n /** Additional guidance text shown alongside the input field. */\n hint?: string;\n}\n\n/**\n * A compiled catalog entry (skill or flow).\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface CatalogEntryCompiled {\n /** Unique ID in `publisher/name` form (e.g. `skaileup/cf_overview`). */\n id: string;\n /** Asset kind. */\n kind: \"skill\" | \"flow\";\n /** Human-readable asset name. */\n name: string;\n /** One-line description. */\n description: string;\n /** Semantic version string. */\n version: string;\n /** Maturity stage. */\n stage: \"alpha\" | \"beta\" | \"stable\";\n /** Searchable keywords. */\n keywords: string[];\n /** User-facing input specifications. */\n inputs: InputSpec[];\n /** Asset path relative to assetsRoot. */\n source_path: string;\n /** Optional icon identifier. */\n icon?: string;\n /** Flow-only: required skill names. */\n required_skills?: string[];\n /** Flow-only: optional skill names. */\n optional_skills?: string[];\n}\n\n/**\n * Options controlling how platform-triggered skill deployment is performed.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface DeployFromCatalogOptions {\n /** Root directory of ai-assets (where `source_path` in catalog entries is relative to). */\n assetsRoot: string;\n /** Target directory for deployed skills (e.g. `/workspace/.claude/skills/`). */\n skillsDir: string;\n /** Optional context markdown appended to the deployed skill directory as `CONTEXT.md`. */\n context?: string;\n}\n\n/**\n * Result of a platform-triggered batch skill deployment.\n *\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport interface DeployResult {\n /** IDs of catalog entries successfully deployed. */\n deployed: string[];\n /** IDs of catalog entries skipped (non-skill kinds). */\n skipped: string[];\n /** Error messages for entries that could not be deployed. */\n errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Workspace-mount awareness\n// ---------------------------------------------------------------------------\n\n/**\n * Multiplier applied to the base filesystem deadline for whole-tree operations\n * (recursive copy / remove), which legitimately outlast a single `stat`.\n */\nconst TREE_OP_DEADLINE_FACTOR = 4;\n\n/** Default number of parent levels {@link findAiAssetsRoot} inspects. */\nconst AI_ASSETS_WALK_LEVELS = 6;\n\nlet deployerLogger: ReturnType<typeof createLogger> | undefined;\n\nfunction log(): ReturnType<typeof createLogger> {\n deployerLogger ??= createLogger({ kind: \"runner\", subkind: \"catalog-deployer\" });\n return deployerLogger;\n}\n\n/**\n * Where the agent container binds its rclone FUSE mount. Nothing under this\n * path is a safe place to read an asset tree from: the mount is remote\n * (SharePoint / OneDrive / WebDAV) and can wedge indefinitely.\n */\nconst DEFAULT_WORKSPACE_MOUNT_DIR = \"/skaile/workspace\";\n\n/**\n * Env override for the workspace-mount path(s), comma-separated.\n *\n * Set it when the runner binds the mount somewhere other than\n * {@link DEFAULT_WORKSPACE_MOUNT_DIR}; set it to the empty string to disable\n * the guard entirely (single-machine dev, where nothing is a network mount).\n */\nexport const WORKSPACE_MOUNT_ENV_VAR = \"SKAILE_WORKSPACE_MOUNT_DIR\";\n\n/**\n * Resolve the directories treated as network mounts.\n *\n * Read per call rather than cached: the runner mutates `process.env` while\n * wiring a session, so a module-load snapshot would pin a pre-configuration\n * value.\n *\n * @returns Absolute mount paths; empty when the guard is disabled.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function workspaceMountDirs(): string[] {\n const raw = process.env[WORKSPACE_MOUNT_ENV_VAR];\n if (raw === undefined) return [DEFAULT_WORKSPACE_MOUNT_DIR];\n return raw\n .split(\",\")\n .map((segment) => segment.trim())\n .filter((segment) => segment.length > 0)\n .map((segment) => resolve(segment));\n}\n\n/**\n * Is `candidate` at, or inside, one of the known workspace mount paths?\n *\n * Pure path arithmetic — deliberately no filesystem access, because the whole\n * point is to decide *before* touching a path that might be unresponsive.\n *\n * @param candidate - Path to test.\n * @param mountDirs - Mount roots; defaults to {@link workspaceMountDirs}.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function isUnderWorkspaceMount(\n candidate: string,\n mountDirs: string[] = workspaceMountDirs(),\n): boolean {\n const target = resolve(candidate);\n return mountDirs.some((dir) => {\n const root = resolve(dir);\n return target === root || target.startsWith(root + sep);\n });\n}\n\n/**\n * Walk upward from `startDir` looking for an `ai-assets/` directory.\n *\n * Two properties matter beyond \"find the folder\":\n *\n * 1. **Never synchronous.** The walk probes up to six directories; any one of\n * them can be on a FUSE mount, and the former `existsSync` chain blocked the\n * event loop on the first unresponsive probe. Each probe is now awaited and\n * deadline-bounded, so a wedged mount costs one skipped candidate.\n * 2. **Never resolves onto a mount.** A hit under the workspace mount is\n * skipped with a warning rather than returned: accepting it would wire every\n * later skill deploy — a recursive copy — to a remote filesystem. The walk\n * continues upward, so a legitimate `ai-assets/` in a parent still wins.\n *\n * Only a **directory** counts. An `ai-assets` file would otherwise be returned\n * as a root and every later `join(root, source_path)` would fail with ENOTDIR.\n *\n * @param startDir - Directory to start from (typically the project dir).\n * @param opts - `levels` caps the upward walk; `mountDirs` overrides the mount\n * roots (defaults to {@link workspaceMountDirs}).\n * @returns Absolute path to the `ai-assets/` directory, or `null` if none is\n * reachable within `levels`.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function findAiAssetsRoot(\n startDir: string,\n opts?: { levels?: number; mountDirs?: string[] },\n): Promise<string | null> {\n const mountDirs = opts?.mountDirs ?? workspaceMountDirs();\n const levels = opts?.levels ?? AI_ASSETS_WALK_LEVELS;\n let dir = resolve(startDir);\n // Every level of a `/skaile/workspace/...` start dir is under the mount, so\n // an unconditional warn would fire once per level for one lookup. Collect and\n // report once — the operator needs the fact, not six copies of it.\n const refused: string[] = [];\n\n for (let i = 0; i < levels; i++) {\n const candidate = join(dir, \"ai-assets\");\n if (isUnderWorkspaceMount(candidate, mountDirs)) {\n refused.push(candidate);\n } else {\n const isDir = await tryWithFsDeadline(\n `stat ${candidate}`,\n async () => (await stat(candidate)).isDirectory(),\n false,\n );\n if (isDir) {\n if (refused.length > 0) warnRefused(refused, mountDirs);\n return candidate;\n }\n }\n const parent = resolve(dir, \"..\");\n if (parent === dir) break; // filesystem root — nothing further up\n dir = parent;\n }\n if (refused.length > 0) warnRefused(refused, mountDirs);\n return null;\n}\n\n/** Single warning for every `ai-assets` candidate skipped for sitting on a mount. */\nfunction warnRefused(refused: string[], mountDirs: string[]): void {\n log().warn(\n \"findAiAssetsRoot refused candidates under a workspace mount — deploying skills from a network mount can stall the session\",\n { refused, mountDirs },\n );\n}\n\n/**\n * Deploy a single catalog entry to the session skills directory.\n *\n * Copies the entire skill source directory into `skillsDir/<entry.name>/`.\n * If `context` is provided, a separate `CONTEXT.md` is written alongside\n * `SKILL.md` so the source file is never modified.\n *\n * Only `skill` entries are deployable; other kinds return an error.\n *\n * **Async by necessity.** This runs from the `session_init` command handler\n * with the WebSocket live, and both `assetsRoot` and `skillsDir` can sit on a\n * network mount. The former `cpSync`/`rmSync` pair parked the event loop for\n * the whole copy; every call is now awaited and deadline-bounded, so an\n * unresponsive mount fails one deployment instead of the session.\n *\n * @param entry - Compiled catalog entry to deploy.\n * @param options - Deployment target and optional context.\n * @returns `{ success: true }` on success, `{ success: false, error }` on failure.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function deployCatalogEntry(\n entry: CatalogEntryCompiled,\n options: DeployFromCatalogOptions,\n): Promise<{ success: boolean; error?: string }> {\n const { assetsRoot, skillsDir, context } = options;\n\n if (entry.kind !== \"skill\") {\n return { success: false, error: `Cannot deploy ${entry.kind} directly — only skills` };\n }\n\n const sourcePath = join(assetsRoot, entry.source_path);\n const skillMdPath = join(sourcePath, \"SKILL.md\");\n\n const hasSkillMd = await tryWithFsDeadline(\n `stat ${skillMdPath}`,\n async () => {\n await stat(skillMdPath);\n return true;\n },\n false,\n );\n if (!hasSkillMd) {\n return { success: false, error: `SKILL.md not found at ${skillMdPath}` };\n }\n\n const destDir = join(skillsDir, entry.name);\n\n try {\n await withFsDeadline(`mkdir ${destDir}`, () => mkdir(destDir, { recursive: true }));\n\n // Copy the entire skill directory\n await withFsDeadline(\n `cp ${sourcePath} -> ${destDir}`,\n () => cp(sourcePath, destDir, { recursive: true }),\n fsDeadlineMs() * TREE_OP_DEADLINE_FACTOR,\n );\n\n // Write context to a separate CONTEXT.md — never modify the original SKILL.md.\n // The agent discovers both files in the skill directory.\n const contextPath = join(destDir, \"CONTEXT.md\");\n if (context) {\n await withFsDeadline(`write ${contextPath}`, () =>\n writeFile(contextPath, `# Additional Context\\n\\n${context}\\n`, \"utf8\"),\n );\n } else {\n // `force: true` makes this a single call: a stale CONTEXT.md is removed,\n // an absent one is a no-op. The former existsSync probe only added a\n // second trip to the same possibly-wedged mount.\n await withFsDeadline(`rm ${contextPath}`, () => rm(contextPath, { force: true }));\n }\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : String(err) };\n }\n\n return { success: true };\n}\n\n/**\n * Remove a deployed skill directory from the session skills directory.\n *\n * @param name - Skill name (directory basename under `skillsDir`).\n * @param skillsDir - Absolute path to the session skills directory.\n * @returns `true` if the skill was found and removed; `false` if it was not\n * deployed, or if the directory could not be reached within the deadline.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function undeployCatalogEntry(name: string, skillsDir: string): Promise<boolean> {\n const destDir = join(skillsDir, name);\n const exists = await tryWithFsDeadline(\n `stat ${destDir}`,\n async () => {\n await stat(destDir);\n return true;\n },\n false,\n );\n if (!exists) return false;\n await withFsDeadline(\n `rm -r ${destDir}`,\n () => rm(destDir, { recursive: true, force: true }),\n fsDeadlineMs() * TREE_OP_DEADLINE_FACTOR,\n );\n return true;\n}\n\n/**\n * Deploy multiple catalog entries in a single batch operation.\n *\n * Non-skill entries (flows, agents, etc.) are automatically skipped and\n * recorded in `result.skipped`. Deployment failures are collected in\n * `result.errors` without aborting the rest of the batch.\n *\n * @param entries - Compiled catalog entries to deploy.\n * @param options - Deployment target and optional context.\n * @returns Aggregated {@link DeployResult} with deployed, skipped, and error lists.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport async function deployAll(\n entries: CatalogEntryCompiled[],\n options: DeployFromCatalogOptions,\n): Promise<DeployResult> {\n const result: DeployResult = { deployed: [], skipped: [], errors: [] };\n\n for (const entry of entries) {\n if (entry.kind !== \"skill\") {\n result.skipped.push(entry.id);\n continue;\n }\n\n // Serial on purpose: concurrent recursive copies onto one mount multiply\n // the queue depth on the exact resource that is already the bottleneck.\n const r = await deployCatalogEntry(entry, options);\n if (r.success) {\n result.deployed.push(entry.id);\n } else {\n result.errors.push(`${entry.id}: ${r.error}`);\n }\n }\n\n return result;\n}\n\n/**\n * Resolve a flow's skill dependencies from the full catalog entry list.\n *\n * Partitions `flow.required_skills` and `flow.optional_skills` into resolved\n * entries and a list of names that could not be found. Missing optional skills\n * are silently ignored (they do not appear in `missing`).\n *\n * @param flow - Compiled flow entry whose skill dependencies should be resolved.\n * @param allEntries - Full set of compiled catalog entries to search.\n * @returns Object containing resolved `required` entries, resolved `optional` entries,\n * and `missing` skill names that were listed as required but not found.\n * @docLink packages/asset-manager/concepts#catalog-deployer\n */\nexport function resolveFlowSkills(\n flow: CatalogEntryCompiled,\n allEntries: CatalogEntryCompiled[],\n): { required: CatalogEntryCompiled[]; optional: CatalogEntryCompiled[]; missing: string[] } {\n const skillsByName = new Map<string, CatalogEntryCompiled>();\n for (const e of allEntries) {\n if (e.kind === \"skill\") skillsByName.set(e.name, e);\n }\n\n const required: CatalogEntryCompiled[] = [];\n const optional: CatalogEntryCompiled[] = [];\n const missing: string[] = [];\n\n for (const name of flow.required_skills ?? []) {\n const entry = skillsByName.get(name);\n if (entry) required.push(entry);\n else missing.push(name);\n }\n\n for (const name of flow.optional_skills ?? []) {\n const entry = skillsByName.get(name);\n if (entry) optional.push(entry);\n // Optional skills don't count as missing\n }\n\n return { required, optional, missing };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { isAgentNode, isSubpromptNode, isSubFlowNode, nodeBindings, isRouterNode, nodeIsOptional, nodeSkillId, nodeLabel, isActiveRuntimeNode } from './chunk-7RGTAEG6.js';
2
2
  import { parseFlowDefinition } from './chunk-JRN5QF4C.js';
3
3
  import { resolveFlowBindings, stableFlowJson, evaluateFlowExpression, FlowExpressionError, getConsumedOutputSchema, compileOutputFieldsSchema } from './chunk-NUELZWCF.js';
4
- import { projectAssetRoots } from './chunk-UMLCKKIA.js';
4
+ import { projectAssetRoots } from './chunk-TMJBEGS4.js';
5
5
  import { findKindDirs } from './chunk-MWXYN6NY.js';
6
6
  import * as path2 from 'path';
7
7
  import path2__default from 'path';
@@ -269,7 +269,7 @@ function planRouterSkips(flow, snapshots, settlements) {
269
269
  losingRouteEdges.add(edgeKey(router.id, target));
270
270
  }
271
271
  }
272
- const candidateOrigins = /* @__PURE__ */ new Map();
272
+ const regions = /* @__PURE__ */ new Map();
273
273
  for (const root of losingRoots) {
274
274
  const visited = /* @__PURE__ */ new Set();
275
275
  const queue = [root];
@@ -277,10 +277,22 @@ function planRouterSkips(flow, snapshots, settlements) {
277
277
  const nodeId = queue[index];
278
278
  if (visited.has(nodeId)) continue;
279
279
  visited.add(nodeId);
280
+ for (const target of outgoing.get(nodeId) ?? []) queue.push(target);
281
+ }
282
+ regions.set(root, visited);
283
+ }
284
+ const regionEntries = [...regions];
285
+ const nestedRoots = new Set(
286
+ [...losingRoots].filter(
287
+ (root) => regionEntries.some(([other, region]) => other !== root && region.has(root))
288
+ )
289
+ );
290
+ const candidateOrigins = /* @__PURE__ */ new Map();
291
+ for (const [root, region] of regions) {
292
+ for (const nodeId of region) {
280
293
  const origins = candidateOrigins.get(nodeId) ?? /* @__PURE__ */ new Set();
281
- origins.add(root);
294
+ if (!nestedRoots.has(root)) origins.add(root);
282
295
  candidateOrigins.set(nodeId, origins);
283
- for (const target of outgoing.get(nodeId) ?? []) queue.push(target);
284
296
  }
285
297
  }
286
298
  const candidates = new Set(candidateOrigins.keys());
@@ -309,7 +321,9 @@ function planRouterSkips(flow, snapshots, settlements) {
309
321
  const nodeId = protectionQueue[index];
310
322
  if (protectedNodes.has(nodeId)) continue;
311
323
  protectedNodes.add(nodeId);
312
- protectionQueue.push(...outgoing.get(nodeId) ?? []);
324
+ for (const target of outgoing.get(nodeId) ?? []) {
325
+ if (!losingRouteEdges.has(edgeKey(nodeId, target))) protectionQueue.push(target);
326
+ }
313
327
  protectionQueue.push(...unknownSelections.get(nodeId) ?? []);
314
328
  }
315
329
  return flow.nodes.flatMap(
@@ -979,5 +993,5 @@ function findFlowFileInRoots(flowId, roots, opts = {}) {
979
993
  }
980
994
 
981
995
  export { FLOW_FILE_EXTENSIONS, FlowManifestSchema, appendAttempt, availableRouterFrontier, buildFlowExpressionContext, computeFlowState, computeFlowStateFromSnapshots, computeSkippable, countFailedAttempts, deriveCheckEvidence, evaluateRouterSelection, findFlowFileInRoots, flowFileCandidates, flowKindProvider, flowLookupRoots, hasAutomaticRetryBudget, interpolateNodeInstruction, isActiveExecutionExpired, isBlocking, loadAllFlowEntries, loadAllFlows, loadFlow, loadFlowEntriesFromDir, loadFlowsFromDir, nextAttemptNumber, persistedRouterSelection, planRouterSkips, producerOutputObtainedBy, projectAiAssetsRoots, remainingActiveExecutionMs, resolveAvailableRouter, resolveFlowOutputFields, resolveNextNodes, resolveNodeBindings, resolveTerminalFailureStatus, routerSelectionOutput, unsettledRouterBranchIds, validateConsumedNodeOutput, validateFlow };
982
- //# sourceMappingURL=chunk-X44XKBZX.js.map
983
- //# sourceMappingURL=chunk-X44XKBZX.js.map
996
+ //# sourceMappingURL=chunk-WFK4MUBL.js.map
997
+ //# sourceMappingURL=chunk-WFK4MUBL.js.map