@skaile/workspaces 3.27.1 → 4.1.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 (356) hide show
  1. package/CHANGELOG.md +482 -0
  2. package/dist/app-sdk/index.js +1 -1
  3. package/dist/{asset-feeds-QF7LGRUX.js → asset-feeds-VEPD5ZU7.js} +11 -9
  4. package/dist/asset-feeds-VEPD5ZU7.js.map +1 -0
  5. package/dist/asset-manager/catalog-deployer.js +5 -3
  6. package/dist/asset-manager/index.js +11 -9
  7. package/dist/asset-manager/installer.js +8 -6
  8. package/dist/asset-manager/renderers.js +2 -2
  9. package/dist/asset-manager/src/renderers.d.ts.map +1 -1
  10. package/dist/bridge/codex-app-server.js +15 -1
  11. package/dist/bridge/drivers/claude-sdk.js +102 -55
  12. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  13. package/dist/bridge/drivers/codex.js +179 -23
  14. package/dist/bridge/drivers/codex.js.map +1 -1
  15. package/dist/bridge/drivers/continue.js +199 -7
  16. package/dist/bridge/drivers/continue.js.map +1 -1
  17. package/dist/bridge/drivers/echo.js +10 -4
  18. package/dist/bridge/drivers/echo.js.map +1 -1
  19. package/dist/bridge/drivers/gemini.js +7 -4
  20. package/dist/bridge/drivers/goose.js +160 -7
  21. package/dist/bridge/drivers/goose.js.map +1 -1
  22. package/dist/bridge/drivers/omp.js +321 -96
  23. package/dist/bridge/drivers/omp.js.map +1 -1
  24. package/dist/bridge/drivers/opencode.js +148 -13
  25. package/dist/bridge/drivers/opencode.js.map +1 -1
  26. package/dist/bridge/drivers/qwen.js +41 -11
  27. package/dist/bridge/drivers/qwen.js.map +1 -1
  28. package/dist/bridge/index.js +12 -9
  29. package/dist/bridge/src/cloud.d.ts +62 -71
  30. package/dist/bridge/src/cloud.d.ts.map +1 -1
  31. package/dist/bridge/src/codex/config-toml.d.ts +128 -0
  32. package/dist/bridge/src/codex/config-toml.d.ts.map +1 -0
  33. package/dist/bridge/src/codex/credentials.d.ts +26 -0
  34. package/dist/bridge/src/codex/credentials.d.ts.map +1 -1
  35. package/dist/bridge/src/codex/managed-driver.d.ts.map +1 -1
  36. package/dist/bridge/src/codex-app-server.d.ts.map +1 -1
  37. package/dist/bridge/src/drivers/_subprocess-cli.d.ts +9 -4
  38. package/dist/bridge/src/drivers/_subprocess-cli.d.ts.map +1 -1
  39. package/dist/bridge/src/drivers/claude-sdk.d.ts +19 -11
  40. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  41. package/dist/bridge/src/drivers/codex.d.ts +26 -1
  42. package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
  43. package/dist/bridge/src/drivers/continue.d.ts +31 -5
  44. package/dist/bridge/src/drivers/continue.d.ts.map +1 -1
  45. package/dist/bridge/src/drivers/echo.d.ts.map +1 -1
  46. package/dist/bridge/src/drivers/gemini.d.ts +34 -3
  47. package/dist/bridge/src/drivers/gemini.d.ts.map +1 -1
  48. package/dist/bridge/src/drivers/goose.d.ts +26 -2
  49. package/dist/bridge/src/drivers/goose.d.ts.map +1 -1
  50. package/dist/bridge/src/drivers/omp-models-yml.d.ts +216 -0
  51. package/dist/bridge/src/drivers/omp-models-yml.d.ts.map +1 -0
  52. package/dist/bridge/src/drivers/omp.d.ts +26 -23
  53. package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
  54. package/dist/bridge/src/drivers/opencode.d.ts +28 -3
  55. package/dist/bridge/src/drivers/opencode.d.ts.map +1 -1
  56. package/dist/bridge/src/drivers/qwen.d.ts +10 -4
  57. package/dist/bridge/src/drivers/qwen.d.ts.map +1 -1
  58. package/dist/bridge/src/index.d.ts +3 -1
  59. package/dist/bridge/src/index.d.ts.map +1 -1
  60. package/dist/bridge/src/models.d.ts +118 -19
  61. package/dist/bridge/src/models.d.ts.map +1 -1
  62. package/dist/bridge/src/provider-catalog.d.ts +188 -0
  63. package/dist/bridge/src/provider-catalog.d.ts.map +1 -0
  64. package/dist/bridge/src/provider-materialize/continue-config-yaml.d.ts +117 -0
  65. package/dist/bridge/src/provider-materialize/continue-config-yaml.d.ts.map +1 -0
  66. package/dist/bridge/src/provider-materialize/credential-env.d.ts +103 -0
  67. package/dist/bridge/src/provider-materialize/credential-env.d.ts.map +1 -0
  68. package/dist/bridge/src/provider-materialize/env-drivers.d.ts +209 -0
  69. package/dist/bridge/src/provider-materialize/env-drivers.d.ts.map +1 -0
  70. package/dist/bridge/src/provider-materialize/goose-custom-providers.d.ts +127 -0
  71. package/dist/bridge/src/provider-materialize/goose-custom-providers.d.ts.map +1 -0
  72. package/dist/bridge/src/provider-materialize/opencode-config.d.ts +127 -0
  73. package/dist/bridge/src/provider-materialize/opencode-config.d.ts.map +1 -0
  74. package/dist/bridge/src/provider-materialize/session-config-home.d.ts +63 -0
  75. package/dist/bridge/src/provider-materialize/session-config-home.d.ts.map +1 -0
  76. package/dist/bridge/src/provider-registry-derive.d.ts +59 -0
  77. package/dist/bridge/src/provider-registry-derive.d.ts.map +1 -0
  78. package/dist/bridge/src/registry.d.ts +19 -7
  79. package/dist/bridge/src/registry.d.ts.map +1 -1
  80. package/dist/bridge/src/runtime.d.ts.map +1 -1
  81. package/dist/bridge/src/types.d.ts +79 -60
  82. package/dist/bridge/src/types.d.ts.map +1 -1
  83. package/dist/bridge/src/validation.d.ts +2 -3
  84. package/dist/bridge/src/validation.d.ts.map +1 -1
  85. package/dist/{chunk-ZEXYTJ6Y.js → chunk-2GF42G2J.js} +6 -6
  86. package/dist/{chunk-ZEXYTJ6Y.js.map → chunk-2GF42G2J.js.map} +1 -1
  87. package/dist/{chunk-WWGU3REE.js → chunk-2K7NURDN.js} +7 -7
  88. package/dist/{chunk-WWGU3REE.js.map → chunk-2K7NURDN.js.map} +1 -1
  89. package/dist/{chunk-TCHEW3T2.js → chunk-2RO6N7DN.js} +6 -6
  90. package/dist/{chunk-TCHEW3T2.js.map → chunk-2RO6N7DN.js.map} +1 -1
  91. package/dist/{chunk-HSRHO7SK.js → chunk-3VSRJE3M.js} +155 -143
  92. package/dist/chunk-3VSRJE3M.js.map +1 -0
  93. package/dist/{chunk-T3YLZQS4.js → chunk-45LLHKQ2.js} +24 -3
  94. package/dist/chunk-45LLHKQ2.js.map +1 -0
  95. package/dist/chunk-5DQWB5TW.js +843 -0
  96. package/dist/chunk-5DQWB5TW.js.map +1 -0
  97. package/dist/{chunk-JMYOJ3PA.js → chunk-5HT5M5HX.js} +3 -3
  98. package/dist/{chunk-JMYOJ3PA.js.map → chunk-5HT5M5HX.js.map} +1 -1
  99. package/dist/{chunk-VN7DELUT.js → chunk-6AMTSRRO.js} +4 -4
  100. package/dist/{chunk-VN7DELUT.js.map → chunk-6AMTSRRO.js.map} +1 -1
  101. package/dist/{chunk-MX6TGDZ7.js → chunk-6DI4NTZN.js} +5 -5
  102. package/dist/{chunk-MX6TGDZ7.js.map → chunk-6DI4NTZN.js.map} +1 -1
  103. package/dist/{chunk-FFE7YLYO.js → chunk-AN7E2IL5.js} +7 -7
  104. package/dist/chunk-AN7E2IL5.js.map +1 -0
  105. package/dist/{chunk-A3HTL7XV.js → chunk-APDN5LW4.js} +3 -3
  106. package/dist/{chunk-A3HTL7XV.js.map → chunk-APDN5LW4.js.map} +1 -1
  107. package/dist/{chunk-FACPWN6P.js → chunk-ASU5IJZS.js} +9 -12
  108. package/dist/chunk-ASU5IJZS.js.map +1 -0
  109. package/dist/{chunk-J3IXRPZB.js → chunk-BTMDSMXF.js} +10 -10
  110. package/dist/{chunk-J3IXRPZB.js.map → chunk-BTMDSMXF.js.map} +1 -1
  111. package/dist/chunk-CTBUPYOQ.js +500 -0
  112. package/dist/chunk-CTBUPYOQ.js.map +1 -0
  113. package/dist/{chunk-K6VZQNTR.js → chunk-DKCFWSVW.js} +3 -3
  114. package/dist/{chunk-K6VZQNTR.js.map → chunk-DKCFWSVW.js.map} +1 -1
  115. package/dist/{chunk-MQASB52N.js → chunk-FEFTOV2Y.js} +3 -3
  116. package/dist/{chunk-MQASB52N.js.map → chunk-FEFTOV2Y.js.map} +1 -1
  117. package/dist/{chunk-XMULHVKX.js → chunk-FGTYTU6Q.js} +17 -15
  118. package/dist/chunk-FGTYTU6Q.js.map +1 -0
  119. package/dist/{chunk-WJVBJAM5.js → chunk-HHC2T7BM.js} +7 -7
  120. package/dist/{chunk-WJVBJAM5.js.map → chunk-HHC2T7BM.js.map} +1 -1
  121. package/dist/chunk-ILG4BXYE.js +936 -0
  122. package/dist/chunk-ILG4BXYE.js.map +1 -0
  123. package/dist/{chunk-E7HKNQTH.js → chunk-JXCUUZA3.js} +3 -4
  124. package/dist/chunk-JXCUUZA3.js.map +1 -0
  125. package/dist/{chunk-MBARHWMZ.js → chunk-K27T47OO.js} +79 -53
  126. package/dist/chunk-K27T47OO.js.map +1 -0
  127. package/dist/chunk-KSIRR5PL.js +142 -0
  128. package/dist/chunk-KSIRR5PL.js.map +1 -0
  129. package/dist/{chunk-SIREWRZE.js → chunk-KW7YIRYL.js} +3 -3
  130. package/dist/{chunk-SIREWRZE.js.map → chunk-KW7YIRYL.js.map} +1 -1
  131. package/dist/{chunk-3U3ZKYR7.js → chunk-LPF24MZA.js} +139 -29
  132. package/dist/chunk-LPF24MZA.js.map +1 -0
  133. package/dist/chunk-M2F5UXCX.js +187 -0
  134. package/dist/chunk-M2F5UXCX.js.map +1 -0
  135. package/dist/{chunk-DZ4UZOFB.js → chunk-M5H4DWIA.js} +3 -3
  136. package/dist/{chunk-DZ4UZOFB.js.map → chunk-M5H4DWIA.js.map} +1 -1
  137. package/dist/{chunk-PHBYB4XT.js → chunk-MLDJHV2U.js} +4 -8
  138. package/dist/chunk-MLDJHV2U.js.map +1 -0
  139. package/dist/{chunk-773WLEXL.js → chunk-MVBK4JUK.js} +3 -3
  140. package/dist/{chunk-773WLEXL.js.map → chunk-MVBK4JUK.js.map} +1 -1
  141. package/dist/{chunk-AN6NAFRT.js → chunk-N7B3LZ7V.js} +31 -6
  142. package/dist/chunk-N7B3LZ7V.js.map +1 -0
  143. package/dist/{chunk-EB72L5ZL.js → chunk-ORZBDXNS.js} +18 -30
  144. package/dist/chunk-ORZBDXNS.js.map +1 -0
  145. package/dist/{chunk-6H6HLMWG.js → chunk-OXTPH6HT.js} +3 -3
  146. package/dist/{chunk-6H6HLMWG.js.map → chunk-OXTPH6HT.js.map} +1 -1
  147. package/dist/{chunk-QSPCI4W2.js → chunk-PI244HAH.js} +175 -178
  148. package/dist/chunk-PI244HAH.js.map +1 -0
  149. package/dist/{chunk-NW65H5EV.js → chunk-PTETBRRC.js} +3 -3
  150. package/dist/{chunk-NW65H5EV.js.map → chunk-PTETBRRC.js.map} +1 -1
  151. package/dist/{chunk-UL4LD7KD.js → chunk-QQL3ET3J.js} +3 -3
  152. package/dist/{chunk-UL4LD7KD.js.map → chunk-QQL3ET3J.js.map} +1 -1
  153. package/dist/{chunk-GURXUF2J.js → chunk-R2GE2NXM.js} +95 -80
  154. package/dist/chunk-R2GE2NXM.js.map +1 -0
  155. package/dist/{chunk-IB4XKQMQ.js → chunk-REILIKVM.js} +3 -3
  156. package/dist/{chunk-IB4XKQMQ.js.map → chunk-REILIKVM.js.map} +1 -1
  157. package/dist/{chunk-3NCGSSCU.js → chunk-WLFRA5RM.js} +47 -45
  158. package/dist/chunk-WLFRA5RM.js.map +1 -0
  159. package/dist/{chunk-2BK4N3FS.js → chunk-WO65FA7W.js} +2 -7
  160. package/dist/chunk-WO65FA7W.js.map +1 -0
  161. package/dist/{chunk-72DG6GSB.js → chunk-YS4XBN7O.js} +4 -4
  162. package/dist/{chunk-72DG6GSB.js.map → chunk-YS4XBN7O.js.map} +1 -1
  163. package/dist/chunk-YSJKLJD4.js +32 -0
  164. package/dist/chunk-YSJKLJD4.js.map +1 -0
  165. package/dist/cli/index.js +765 -334
  166. package/dist/cli/index.js.map +1 -1
  167. package/dist/cli/src/commands/config.d.ts +17 -6
  168. package/dist/cli/src/commands/config.d.ts.map +1 -1
  169. package/dist/cli/src/commands/migrate-legacy-entry.d.ts +46 -0
  170. package/dist/cli/src/commands/migrate-legacy-entry.d.ts.map +1 -0
  171. package/dist/cli/src/commands/migrate-providers.d.ts +93 -0
  172. package/dist/cli/src/commands/migrate-providers.d.ts.map +1 -0
  173. package/dist/cli/src/commands/providers.d.ts +89 -0
  174. package/dist/cli/src/commands/providers.d.ts.map +1 -0
  175. package/dist/cli/src/commands/run.d.ts +1 -1
  176. package/dist/cli/src/commands/run.d.ts.map +1 -1
  177. package/dist/cli/src/setup.d.ts +46 -6
  178. package/dist/cli/src/setup.d.ts.map +1 -1
  179. package/dist/connectors/config.js +6 -4
  180. package/dist/connectors/index.js +15 -12
  181. package/dist/core/index.js +5 -3
  182. package/dist/core/provider-registry-credentials.d.ts +2 -0
  183. package/dist/core/provider-registry-credentials.js +5 -0
  184. package/dist/core/provider-registry-credentials.js.map +1 -0
  185. package/dist/core/provider-registry.d.ts +2 -0
  186. package/dist/core/provider-registry.js +4 -0
  187. package/dist/core/provider-registry.js.map +1 -0
  188. package/dist/core/runtime-assets.js +2 -2
  189. package/dist/core/src/index.d.ts +11 -4
  190. package/dist/core/src/index.d.ts.map +1 -1
  191. package/dist/core/src/process-alive.d.ts +28 -0
  192. package/dist/core/src/process-alive.d.ts.map +1 -0
  193. package/dist/core/src/provider-registry-credentials.d.ts +50 -0
  194. package/dist/core/src/provider-registry-credentials.d.ts.map +1 -0
  195. package/dist/core/src/provider-registry-files.d.ts +97 -0
  196. package/dist/core/src/provider-registry-files.d.ts.map +1 -0
  197. package/dist/core/src/provider-registry.d.ts +450 -0
  198. package/dist/core/src/provider-registry.d.ts.map +1 -0
  199. package/dist/core/src/settings.d.ts +18 -78
  200. package/dist/core/src/settings.d.ts.map +1 -1
  201. package/dist/core/src/workspace-config.d.ts +31 -47
  202. package/dist/core/src/workspace-config.d.ts.map +1 -1
  203. package/dist/core/src/workspace-yaml-editor.d.ts.map +1 -1
  204. package/dist/core/workspace-config.js +1 -1
  205. package/dist/deploy/index.js +9 -16
  206. package/dist/deploy/index.js.map +1 -1
  207. package/dist/deploy/src/targets/local.d.ts.map +1 -1
  208. package/dist/deploy/src/targets/nix.d.ts.map +1 -1
  209. package/dist/deploy/src/targets/process-handle.d.ts +0 -2
  210. package/dist/deploy/src/targets/process-handle.d.ts.map +1 -1
  211. package/dist/discovery/index.js +2 -2
  212. package/dist/{ensure-sources-GEJGBQIP.js → ensure-sources-B3VWHD5M.js} +14 -12
  213. package/dist/ensure-sources-B3VWHD5M.js.map +1 -0
  214. package/dist/factory-assets/connectors/box.js +15 -12
  215. package/dist/factory-assets/connectors/deploy.js +15 -12
  216. package/dist/factory-assets/connectors/devserver/adapter.d.ts.map +1 -1
  217. package/dist/factory-assets/connectors/devserver.js +15 -12
  218. package/dist/factory-assets/connectors/flow/adapter.js +15 -12
  219. package/dist/factory-assets/connectors/flow/engine.js +6 -4
  220. package/dist/factory-assets/connectors/flow/index.d.ts +1 -1
  221. package/dist/factory-assets/connectors/flow/index.d.ts.map +1 -1
  222. package/dist/factory-assets/connectors/flow/run-flow.d.ts +0 -3
  223. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  224. package/dist/factory-assets/connectors/flow/run-flow.js +16 -13
  225. package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts +31 -28
  226. package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts.map +1 -1
  227. package/dist/factory-assets/connectors/flow.js +15 -12
  228. package/dist/factory-assets/connectors/git.js +15 -12
  229. package/dist/factory-assets/connectors/gmail.js +15 -12
  230. package/dist/factory-assets/connectors/googledrive.js +15 -12
  231. package/dist/factory-assets/connectors/local.js +15 -12
  232. package/dist/factory-assets/connectors/mattermost.js +15 -12
  233. package/dist/factory-assets/connectors/memory.js +15 -12
  234. package/dist/factory-assets/connectors/minio.js +15 -12
  235. package/dist/factory-assets/connectors/postgres.js +15 -12
  236. package/dist/factory-assets/connectors/s3.js +15 -12
  237. package/dist/factory-assets/connectors/sharepoint.js +15 -12
  238. package/dist/factory-assets/connectors/sqlite.js +15 -12
  239. package/dist/factory-assets/connectors/static-server.js +15 -12
  240. package/dist/factory-assets/connectors/tunnel.js +15 -12
  241. package/dist/factory-assets/connectors/webdav.js +15 -12
  242. package/dist/factory-assets/connectors/xstate-store.js +15 -12
  243. package/dist/factory-assets/connectors/xstate.js +15 -12
  244. package/dist/{flows-MI2VM5JZ.js → flows-KIQH2VGA.js} +9 -7
  245. package/dist/{flows-MI2VM5JZ.js.map → flows-KIQH2VGA.js.map} +1 -1
  246. package/dist/{helpers-DXZOHX25.js → helpers-72W3NZ2L.js} +14 -12
  247. package/dist/{helpers-DXZOHX25.js.map → helpers-72W3NZ2L.js.map} +1 -1
  248. package/dist/library/index.js +8 -6
  249. package/dist/library/install.js +5 -3
  250. package/dist/{library-publish-CUPDG5NI.js → library-publish-YPHKEA6L.js} +18 -16
  251. package/dist/library-publish-YPHKEA6L.js.map +1 -0
  252. package/dist/{open-library-32XAI2LH.js → open-library-7OIUAGAH.js} +16 -14
  253. package/dist/{open-library-32XAI2LH.js.map → open-library-7OIUAGAH.js.map} +1 -1
  254. package/dist/paths-XLSP5K6C.js +18 -0
  255. package/dist/{paths-CZEH643M.js.map → paths-XLSP5K6C.js.map} +1 -1
  256. package/dist/plugin-registry/src/targets.d.ts +16 -2
  257. package/dist/plugin-registry/src/targets.d.ts.map +1 -1
  258. package/dist/{plugin-store-QJNBPIQK.js → plugin-store-V5BMOYGS.js} +7 -5
  259. package/dist/plugin-store-V5BMOYGS.js.map +1 -0
  260. package/dist/{project-RRHUCVXW.js → project-KNAZV4B3.js} +15 -13
  261. package/dist/{project-RRHUCVXW.js.map → project-KNAZV4B3.js.map} +1 -1
  262. package/dist/resolver/index.js +5 -3
  263. package/dist/runner/index.js +25 -22
  264. package/dist/runner/src/agent.d.ts +0 -2
  265. package/dist/runner/src/agent.d.ts.map +1 -1
  266. package/dist/runner/src/codex-init.d.ts.map +1 -1
  267. package/dist/runner/src/codex-resource-tools.d.ts.map +1 -1
  268. package/dist/runner/src/managed-codex-bootstrap.d.ts.map +1 -1
  269. package/dist/runner/src/resources.d.ts +1 -2
  270. package/dist/runner/src/resources.d.ts.map +1 -1
  271. package/dist/runner/src/serve.d.ts.map +1 -1
  272. package/dist/runner/src/session-builder.d.ts +31 -35
  273. package/dist/runner/src/session-builder.d.ts.map +1 -1
  274. package/dist/runner/src/session.d.ts +0 -2
  275. package/dist/runner/src/session.d.ts.map +1 -1
  276. package/dist/sdk/asset-manager.js +11 -9
  277. package/dist/sdk/bridge.js +12 -9
  278. package/dist/sdk/core.js +5 -3
  279. package/dist/sdk/flow.js +6 -4
  280. package/dist/sdk/index.js +25 -22
  281. package/dist/sdk/index.js.map +1 -1
  282. package/dist/sdk/resolver.js +5 -3
  283. package/dist/sdk/runner.js +25 -22
  284. package/dist/sdk/session.js +2 -2
  285. package/dist/sdk/types.js +1 -1
  286. package/dist/session/index.js +2 -2
  287. package/dist/setup-TG4KECRQ.js +435 -0
  288. package/dist/setup-TG4KECRQ.js.map +1 -0
  289. package/dist/{skills-IE3IWWB7.js → skills-KHBYF6AU.js} +7 -5
  290. package/dist/{skills-IE3IWWB7.js.map → skills-KHBYF6AU.js.map} +1 -1
  291. package/dist/{source-RHQLCTWA.js → source-7AFRUD3U.js} +17 -15
  292. package/dist/{source-RHQLCTWA.js.map → source-7AFRUD3U.js.map} +1 -1
  293. package/dist/{source-manifest-publish-DXMCSKU7.js → source-manifest-publish-JWOT7O3A.js} +19 -17
  294. package/dist/source-manifest-publish-JWOT7O3A.js.map +1 -0
  295. package/dist/tui/index.js +25 -23
  296. package/dist/tui/index.js.map +1 -1
  297. package/dist/tui/src/repl.d.ts +0 -2
  298. package/dist/tui/src/repl.d.ts.map +1 -1
  299. package/dist/types/index.js +1 -1
  300. package/dist/types/manifests.js +1 -1
  301. package/dist/types/src/index.d.ts +1 -1
  302. package/dist/types/src/index.d.ts.map +1 -1
  303. package/dist/types/src/lifecycle.d.ts +35 -10
  304. package/dist/types/src/lifecycle.d.ts.map +1 -1
  305. package/dist/types/src/manifests/agent.d.ts +116 -22
  306. package/dist/types/src/manifests/agent.d.ts.map +1 -1
  307. package/dist/types/src/manifests/index.d.ts +2 -2
  308. package/dist/types/src/manifests/index.d.ts.map +1 -1
  309. package/dist/types/src/manifests/preset.d.ts +5 -5
  310. package/dist/types/src/runtime.d.ts +51 -5
  311. package/dist/types/src/runtime.d.ts.map +1 -1
  312. package/dist/types/src/version.d.ts +18 -2
  313. package/dist/types/src/version.d.ts.map +1 -1
  314. package/dist/validator-P5ESKTW5.js +5 -0
  315. package/dist/{validator-RN64BKFW.js.map → validator-P5ESKTW5.js.map} +1 -1
  316. package/dist/workspace-plugin/adapters/mcp.js +11 -9
  317. package/dist/workspace-plugin/adapters/omp.js +11 -11
  318. package/dist/workspace-plugin/adapters/omp.js.map +1 -1
  319. package/dist/workspace-plugin/index.js +1 -1
  320. package/dist/workspace-plugin/src/plugin.d.ts +1 -4
  321. package/dist/workspace-plugin/src/plugin.d.ts.map +1 -1
  322. package/dist/workspace-plugin/src/tools/validator.d.ts +4 -4
  323. package/dist/workspace-plugin/src/tools/validator.d.ts.map +1 -1
  324. package/package.json +13 -1
  325. package/dist/asset-feeds-QF7LGRUX.js.map +0 -1
  326. package/dist/bridge/src/provider-endpoints.d.ts +0 -55
  327. package/dist/bridge/src/provider-endpoints.d.ts.map +0 -1
  328. package/dist/chunk-2BK4N3FS.js.map +0 -1
  329. package/dist/chunk-3NCGSSCU.js.map +0 -1
  330. package/dist/chunk-3U3ZKYR7.js.map +0 -1
  331. package/dist/chunk-AN6NAFRT.js.map +0 -1
  332. package/dist/chunk-AQW4BWNR.js +0 -324
  333. package/dist/chunk-AQW4BWNR.js.map +0 -1
  334. package/dist/chunk-E7HKNQTH.js.map +0 -1
  335. package/dist/chunk-EB72L5ZL.js.map +0 -1
  336. package/dist/chunk-FACPWN6P.js.map +0 -1
  337. package/dist/chunk-FFE7YLYO.js.map +0 -1
  338. package/dist/chunk-FYIHH56K.js +0 -110
  339. package/dist/chunk-FYIHH56K.js.map +0 -1
  340. package/dist/chunk-GURXUF2J.js.map +0 -1
  341. package/dist/chunk-HSRHO7SK.js.map +0 -1
  342. package/dist/chunk-MBARHWMZ.js.map +0 -1
  343. package/dist/chunk-PHBYB4XT.js.map +0 -1
  344. package/dist/chunk-QSPCI4W2.js.map +0 -1
  345. package/dist/chunk-T3YLZQS4.js.map +0 -1
  346. package/dist/chunk-XMULHVKX.js.map +0 -1
  347. package/dist/ensure-sources-GEJGBQIP.js.map +0 -1
  348. package/dist/library-publish-CUPDG5NI.js.map +0 -1
  349. package/dist/paths-CZEH643M.js +0 -16
  350. package/dist/plugin-store-QJNBPIQK.js.map +0 -1
  351. package/dist/runner/src/cloud-bundle.d.ts +0 -36
  352. package/dist/runner/src/cloud-bundle.d.ts.map +0 -1
  353. package/dist/setup-CIRH5BYB.js +0 -517
  354. package/dist/setup-CIRH5BYB.js.map +0 -1
  355. package/dist/source-manifest-publish-DXMCSKU7.js.map +0 -1
  356. package/dist/validator-RN64BKFW.js +0 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,487 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#739](https://github.com/skaile-ai/workspaces/pull/739) [`390450b`](https://github.com/skaile-ai/workspaces/commit/390450b5432637dee051007faf1d20e7c3bc1b99) Thanks [@peteralbert](https://github.com/peteralbert)! - Pid liveness no longer counts a zombie as alive. The `local` and `nix` deploy targets (`health()`, `restore()`, `stop()`) and the devserver connector (`register`, status refresh) now use a shared `processAlive` from `@skaile/workspaces/core`, which on Linux also reads `/proc/<pid>/stat` and treats an exited-but-unreaped process as gone. A dead deploy or devserver process in a container without an init now reports unhealthy / crashed instead of healthy, and `restore()` refuses it. The devserver connector also rejects a pid <= 0 on `register`, which previously probed a process group.
8
+
9
+ `@skaile/workspaces/core` gains `processAlive`, `processGroupAlive` and `processExited`. `CodexAppServerClient.terminationConfirmed` now uses `processGroupAlive`, so a native process group left holding only unreaped zombies confirms termination instead of latching the managed driver's `cleanupUncertain`. An unreadable `/proc` entry (other than a vanished pid) never counts as gone.
10
+
11
+ ## 4.0.0
12
+
13
+ ### Major Changes
14
+
15
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - The AI provider registry is the only provider surface in the runtime.
16
+
17
+ `provider`, `cloud`, `cloudConfig`, `cloudSecrets` and the flat `apiKeys`
18
+ fan-out are deleted from `AgentConfig` (bridge), `AgentRuntimeConfig` and
19
+ `ResolvedAgentConfig` (types), and `AgentSessionConfig` / `AgentSession`
20
+ (runner). A session carries `registry` + `modelRef`; each entry references its
21
+ credential and the value reaches the child under `SKAILE_AIP_<ID>_KEY`.
22
+
23
+ Gone with them: `bridge/src/cloud.ts`'s legacy half (`buildClaudeCloudEnv`,
24
+ `CloudConfig`, `CloudId`, `SUPPORTED_CLOUDS`, `CLOUD_SECRET_ENV_KEYS`), the
25
+ vendor endpoint table (`bridge/src/provider-endpoints.ts` — model discovery and
26
+ key validation resolve through the catalog presets now), the per-driver env
27
+ allowlists and key fan-out (`OMP_PROVIDER_ENV_KEYS`, `mapApiKeysToEnv`, the
28
+ codex/gemini/qwen/continue key cascades), the mixed LLM/voice id list
29
+ (`core` `ALL_PROVIDERS`, with `providerEnvKey`, `resolveApiKey`,
30
+ `detectEnvApiKeys`, `resolveAllKeys`), the runner's per-session cloud resolver
31
+ and provider-key secrets lookup (`runner/src/cloud-bundle.ts` deleted), and the
32
+ session-boundary legacy derivation (`resolveSessionProviderBinding`,
33
+ `deriveLegacyProviderRegistry`). The one survivor is the user-local
34
+ `settings.json` `apiKeys` normalizer (`deriveRegistryFromLegacyApiKeys`), which
35
+ goes one minor later; `skaile migrate providers` keeps its own copy of the
36
+ `provider` × `cloud` translation because that is what it exists to migrate.
37
+
38
+ The runner now resolves each entry's `platform:<configId>` reference against
39
+ the `session_init` secrets map itself and materializes the values into the
40
+ child environment. A `session_init` whose `resolvedConfig.agentConfig` still
41
+ carries `provider`, `cloud` or `cloudConfig` is **rejected** with a fatal error
42
+ naming the replacement. Wire protocol 3.13.0 → **4.0.0**.
43
+
44
+ See `MIGRATION.md` for the full `from → to` table.
45
+
46
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - `skaile.yaml` selects a model, it no longer defines a provider.
47
+
48
+ `agent_config.<profile>.model` is a selector resolved through `parseModelRef`:
49
+ `"<providerId>/<modelId>"` picks a registry entry, a bare `"<modelId>"`
50
+ resolves against registry order, and `"@role"` resolves through the new
51
+ top-level `roles:` table (`SkWorkspaceConfig.roles`, merged per role name
52
+ across the scope chain, surfaced as `SkaileSettings.roles`). Role resolution is
53
+ lenient: an undefined role, a role chain, or a role naming a provider this
54
+ machine lacks falls back to registry order with a warning instead of failing
55
+ the session.
56
+
57
+ **Breaking — hard cutover, no warning period** (repo convention for
58
+ `skaile.yaml` schema changes). These are parse errors, and every message names
59
+ `skaile migrate providers`:
60
+
61
+ - `agent-config.<profile>.provider`, `.cloud`, `.cloud_config` (and
62
+ `.cloudConfig`) — including inside a flat, un-profiled `agent-config` block
63
+ - `providers`, `base_url`, `credential`, `headers`, `query_params`,
64
+ `transport` — at the top level and inside any profile
65
+
66
+ The reserved names are scoped to those two places: `mcp_servers[].transport`
67
+ and `mcp_servers[].headers` are a different noun and keep working.
68
+ `encodeSkaileYaml` strips the three legacy profile keys so the writer cannot
69
+ emit a file its own decoder rejects, and the now-unreachable
70
+ `unknown_provider` / `unknown_cloud` / `gateway_missing_base_url` diagnostics
71
+ are gone.
72
+
73
+ New `skaile migrate providers [--project-dir] [--workspace] [--dry-run]
74
+ [--force]` performs the one-time rewrite: for every `skaile.yaml` in the
75
+ project it derives the endpoint the legacy fields addressed (through the same
76
+ `deriveLegacyProviderRegistry` the runtime uses, so the base URL, surface and
77
+ credential carrier are identical), writes it to `~/.skaile/providers.yml`
78
+ through the `skaile providers add` write path, lifts a reserved top-level
79
+ `providers:` block into the same file, and leaves
80
+ `model: <providerId>/<modelId>` behind. Comments and formatting survive, an id
81
+ that already exists with different settings is reported instead of clobbered,
82
+ and a second run is a no-op.
83
+
84
+ `skaile setup` is now a front-end over `skaile providers add`: it picks
85
+ endpoints from the catalog presets (not `ALL_PROVIDERS`), writes entries whose
86
+ credential is an `env:` reference, sends typed secrets to a `.env` file or the
87
+ operator's shell, and saves `driver` plus one selector. It never writes
88
+ `settings.apiKeys`.
89
+
90
+ `skaile config` follows: `set provider|cloud|cloudConfig` is rejected with the
91
+ commands that replace it, `set apiKey.<provider>` creates the registry entry
92
+ with an `env:` reference instead of storing the secret, and `config show` gains
93
+ a "Model selection" section showing which entry, endpoint and credential the
94
+ selector resolves to.
95
+
96
+ A user-local `settings.json` that still carries `apiKeys` keeps working for one
97
+ more minor: `deriveRegistryFromLegacyApiKeys()` (new, in
98
+ `@skaile/workspaces/bridge`) normalizes it into registry entries with `env:`
99
+ references plus one deprecation line, and returns the literal values in a
100
+ `credentialEnv` map for the child environment.
101
+
102
+ Also fixed: `WorkspaceYamlEditor.setAgentConfig` threw when the file had no
103
+ `agent-config` section (it stored a plain object where a YAML node was
104
+ required), and `getAgentConfig` returned the AST node instead of the profile.
105
+
106
+ ### Minor Changes
107
+
108
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - Every session now carries an AI provider `registry` and a `modelRef` beside the
109
+ fields it carried before. Nothing that works today changes: this is the expand
110
+ half of the provider-registry cutover, and the legacy `provider` / `cloud` /
111
+ `cloudConfig` / `cloudSecrets` / `apiKeys` inputs keep driving the drivers.
112
+
113
+ `AgentConfig` (bridge), `AgentRuntimeConfig` (types), `AgentSessionConfig` +
114
+ `AgentSession` (runner) and `SessionSubpromptRunnerOptions` (flow) all gain the
115
+ optional pair. Every session-assembly boundary fills it — CLI flags, the
116
+ platform's `session_init` resolved config, `skaile.yaml`, user settings, the
117
+ in-process `BridgeRuntime`, and isolated sub-prompt sessions. When a boundary
118
+ has only the legacy axis, `resolveSessionProviderBinding()`
119
+ (`@skaile/workspaces/bridge`) derives a **one-entry** registry describing
120
+ exactly the endpoint those fields already addressed — the catalog preset's base
121
+ URL (or the provider's `*_BASE_URL` override), the same wire surface, and the
122
+ same credential kind and carrier that `buildClaudeCloudEnv` uses for
123
+ `bedrock` / `vertex` / `azure` / `gateway` — and returns one deprecation line
124
+ for that boundary to log. The derivation lives in exactly one place; no
125
+ boundary re-implements it. Secrets never enter an entry: the derived
126
+ `credential.ref` names an env var and the value comes back separately as
127
+ `credentialEnv`.
128
+
129
+ **Protocol 3.12.0 → 3.13.0 (additive minor).**
130
+ `ResolvedAgentConfig` (`session_init.resolvedConfig.agentConfig`) gains optional
131
+ `registry?` — the bare `id → entry` map or the merged view — and `modelRef?`
132
+ (`"<providerId>/<modelId>"`, a bare id, or `"@role"`). Control-plane
133
+ credentials are referenced as `platform:<configId>` against the same sibling
134
+ `secrets` map that carries `<PROVIDER>_API_KEY` today. A platform that sends
135
+ only the legacy fields is byte-identical; a 3.12 runner ignores both keys.
136
+
137
+ **Breaking for callers of the model-listing API.** `listModelsForDriver()` and
138
+ `DriverTarget.listModels()` take a registry instead of a flat key map:
139
+
140
+ ```ts
141
+ // before
142
+ await listModelsForDriver("omp", settings.apiKeys ?? {});
143
+ // after
144
+ const { registry, credentialEnv } = deriveLegacyProviderRegistry({
145
+ provider: settings.provider,
146
+ apiKeys: settings.apiKeys,
147
+ });
148
+ await listModelsForDriver("omp", registry, {
149
+ env: { ...process.env, ...credentialEnv },
150
+ });
151
+ ```
152
+
153
+ A legacy-derived registry yields the same results as the flat map did —
154
+ `registryApiKeys()` is the exact inverse. See `MIGRATION.md`.
155
+
156
+ `BUILTIN_DRIVER_CATALOG` now declares, per driver, the `surfaces` it can speak
157
+ and its `providerPlurality` (`registry` for omp; `credentials-n` for opencode,
158
+ goose and continue; `single` for claude-sdk, codex, gemini and qwen), so a
159
+ consumer can filter registry entries by what a backend can actually address
160
+ instead of matching vendor names. `DriverInfo` is now declared once, in
161
+ `@skaile/workspaces/types`, and re-exported from `@skaile/workspaces/bridge`
162
+ (it was duplicated field-for-field in both).
163
+
164
+ No driver dispatches through the registry yet — that lands per driver in the
165
+ following releases.
166
+
167
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - The `claude-sdk` driver now addresses the endpoint its AI provider registry
168
+ entry describes — on **every** transport, including the plain `direct` one.
169
+
170
+ Until now the Claude Agent SDK child env was assembled only when `cloud` was
171
+ something other than `default`, so a session whose provider config named a
172
+ custom `base_url` on the default transport silently talked to
173
+ `api.anthropic.com` with that endpoint's credential. The gate is gone: the
174
+ driver resolves its entry through `resolveSessionProviderBinding()` and builds
175
+ the child env from it with `buildClaudeEndpointEnv()`
176
+ (`@skaile/workspaces/bridge`, `src/cloud.ts`).
177
+
178
+ What the entry now decides:
179
+
180
+ - **Endpoint** — `base_url` (or the transport-derived one) becomes
181
+ `ANTHROPIC_BASE_URL`, except for Anthropic's own host, which needs no
182
+ redirect.
183
+ - **Credential** — `credential.kind: api_key_header` rides as
184
+ `ANTHROPIC_API_KEY` (the SDK sends `x-api-key`), `bearer` as
185
+ `ANTHROPIC_AUTH_TOKEN` (`Authorization: Bearer`). `sigv4`, `google_adc` and
186
+ `azure_entra` emit nothing and let the AWS/Google/Azure chain sign, as
187
+ before. `oauth` keeps the shipped `CLAUDE_CODE_CREDENTIALS_JSON` mechanism
188
+ (the runner writes the blob to the Claude credentials file; the driver adds
189
+ no env). `env:` and `cmd:` refs resolve against `process.env` + `config.env`;
190
+ a `platform:<configId>` ref is resolved by the runner (which holds the
191
+ `session_init` secrets map) and picked up from the `SKAILE_AIP_<ID>_KEY`
192
+ carrier it delivers.
193
+ - **Transport flag** — `bedrock-converse-stream` → `CLAUDE_CODE_USE_BEDROCK`,
194
+ `google-vertex` → `CLAUDE_CODE_USE_VERTEX`, `transport: foundry` →
195
+ `CLAUDE_CODE_USE_FOUNDRY`, with the same routing vars the `cloud` axis
196
+ emitted. A golden test pins Bedrock, Vertex, Foundry (by resource and by
197
+ base URL) and gateway output against the legacy builder, entry for entry.
198
+ - **Headers** — an entry's static `headers` reach the wire as
199
+ `ANTHROPIC_CUSTOM_HEADERS`, minus the ones the SDK owns.
200
+ - **Model** — the selector's `model_map` result is the model the session runs.
201
+
202
+ The child env is the driver's base environment **plus** the endpoint vars, so
203
+ `PATH`, `HOME` and `SKAILE_SESSION_ID` survive on every path (the OAuth path
204
+ previously dropped `config.env` entirely).
205
+
206
+ Model discovery follows the same entry: `listModels()` asks the entry's own
207
+ base URL with the entry's credential, reports nothing for Bedrock / Vertex /
208
+ Foundry (their model catalogs live behind their own control planes) and
209
+ nothing at all for an entry with no resolvable endpoint, rather than falling
210
+ back to Anthropic with someone else's key.
211
+
212
+ Sessions that still carry only the legacy `cloud` / `cloudConfig` /
213
+ `cloudSecrets` / `apiKeys` fields are unchanged: they get the one-entry
214
+ derivation, which now also keeps the Foundry transport when the endpoint is
215
+ given as a base URL rather than a resource name, and lets an explicitly
216
+ configured key override an ambient variable of the same name — the precedence
217
+ the drivers applied before the registry existed.
218
+
219
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - Codex takes its endpoints from a session-private `config.toml` instead of the
220
+ ambient `~/.codex`.
221
+
222
+ Codex is a file-shaped backend: it reads providers from `$CODEX_HOME/config.toml`
223
+ and from nowhere else. The standalone driver now renders the session's AI
224
+ provider registry into one — `[model_providers.<id>]` per entry, with
225
+ `base_url`, `env_key`, `wire_api`, `query_params` and `http_headers` mapping
226
+ 1:1 onto the entry's `base_url`, `credential`, `surface`, `query_params` and
227
+ `headers`, plus top-level `model_provider`/`model` naming the selection — and
228
+ sets `CODEX_HOME` to the directory holding it. A session pointed at a gateway
229
+ now actually reaches that gateway, and `listModels()` discovers against the
230
+ same endpoint rather than always asking `api.openai.com`.
231
+
232
+ The rendered file never contains a credential. `env_key` names the per-entry
233
+ variable `SKAILE_AIP_<ID>_KEY` (the programme-wide naming rule, shared with the
234
+ omp and env-shaped adapters) and the value is delivered in the child
235
+ environment. An `oauth` entry gets `requires_openai_auth` instead, which routes
236
+ codex to its own auth manager.
237
+
238
+ Two deliberate limits, both from codex-cli itself. `wire_api` accepts only
239
+ `responses` as of codex-cli 0.154 (`chat` was removed, openai/codex#7782) and
240
+ an unknown value fails the whole document at load, so entries on a surface
241
+ codex cannot speak — `openai-completions`, `anthropic-messages`,
242
+ `bedrock-converse-stream`, `google-*` — are left out of the file and logged
243
+ rather than rendered into a config codex would reject. A session with no
244
+ registry entry codex can address writes no file at all and keeps codex's
245
+ built-in providers, exactly as before.
246
+
247
+ Managed codex restates its credential-isolation invariant on the registry: a
248
+ managed session may carry exactly one enabled `llm` entry, on
249
+ `openai-codex-responses`, whose credential is a platform-injected `oauth`
250
+ reference. A second entry, another surface, or an `env:` / `cmd:` / `keyring:`
251
+ reference fails the session with the existing `AI_PROFILE_INVALID` before the
252
+ native process starts. The one-entry projection the session boundary derives
253
+ from the legacy `provider`/`apiKeys`/`cloud` fields (layer `runtime`) is not a
254
+ configured endpoint and is exempt — those inputs are already covered by the
255
+ sibling checks on `provider`, `apiKeys.openai` and `env.OPENAI_API_KEY`.
256
+ Managed mode continues to bind its provider through the app-server login flow
257
+ and renders no provider table: a config-defined provider authenticates from
258
+ `env_key`, so redirecting `model_provider` at one would strip a managed session
259
+ of the very credential the isolation exists to protect.
260
+
261
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - The env-shaped CLI drivers — `gemini`, `qwen`, `opencode`, `goose` and
262
+ `continue` — now take their endpoints and credentials from the AI provider
263
+ registry instead of a hardcoded per-driver key allowlist.
264
+
265
+ **Single-provider backends (`gemini`, `qwen`).** The entry the session's model
266
+ selector names supplies everything: `qwen` sends that entry's `base_url`,
267
+ credential and mapped model id as `OPENAI_BASE_URL` / `OPENAI_API_KEY` /
268
+ `OPENAI_MODEL` (plus `-m`), and `gemini` sends `GEMINI_API_KEY` with `-m` from
269
+ the model ref and `GOOGLE_GEMINI_BASE_URL` for a non-default host. Once an
270
+ entry is bound it is the only authority: an inherited `OPENAI_*` /
271
+ `GEMINI_API_KEY` from the host shell no longer leaks into a session pointed
272
+ somewhere else. Pointing one of them at an entry whose `surface` it cannot
273
+ speak now fails at `start()` — before the first spawn — with the offending
274
+ surface and the backend's own surfaces named, rather than surfacing as an
275
+ opaque HTTP error mid-turn.
276
+
277
+ **`credentials-n` backends (`opencode`, `goose`, `continue`).** Every _enabled_
278
+ entry contributes one credential variable, `SKAILE_AIP_<ID>_KEY`, plus the
279
+ vendor carrier a stock catalog endpoint is already known by
280
+ (`ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, …). The active model is the registry
281
+ selection: `opencode -m <provider>/<model>`, `GOOSE_PROVIDER` +
282
+ `GOOSE_MODEL`, and — because `cn` has no model flag — a Continue **role
283
+ binding** for the `chat` role, which is also the shape the generated
284
+ `config.yaml` will be rendered from. A model selector that the registry
285
+ resolves is no longer passed to `cn --config`, which only ever named a Hub
286
+ assistant.
287
+
288
+ Model discovery takes the registry throughout: `gemini` and `qwen` query the
289
+ bound entry's own endpoint with its credential, and the three `credentials-n`
290
+ backends — which have no discovery endpoint of their own — list what the
291
+ registry declares, namespaced the way each takes it.
292
+
293
+ Two shared pieces come with this:
294
+ `bridge/src/provider-materialize/credential-env.ts` is the single naming rule
295
+ for per-entry credential variables (`providerCredentialEnvName`,
296
+ `registryCredentialEnv`), used by the omp, codex and CLI adapters alike, and
297
+ `bridge/src/provider-materialize/env-drivers.ts` resolves a session's
298
+ registry, binds its selector to an entry and enforces the surface.
299
+
300
+ `SubprocessCliDriver.baseEnv()` now merges `config.env` **over** the allowlist
301
+ instead of replacing it: setting one variable used to drop `PATH` and `HOME`
302
+ and make the spawn fail, which the registry delivery path depends on.
303
+
304
+ Sessions carrying only the legacy `provider` / `model` / `apiKeys` fields are
305
+ unchanged. The one-entry derivation those produce describes a credential, not
306
+ a chosen endpoint — `provider` defaults to `anthropic` for every session — so
307
+ the drivers take its credentials but keep their pre-registry model selection,
308
+ and a single-provider driver handed such an entry with an unusable surface
309
+ warns and falls back instead of failing.
310
+
311
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - Model identity is per wire surface, and model tiers resolve through the provider
312
+ registry.
313
+
314
+ An Anthropic-shaped model id is now required for exactly one target: `surface:
315
+ anthropic-messages` on `transport: direct` pointed at `api.anthropic.com`. Every
316
+ other endpoint names models we cannot enumerate — a Bedrock inference-profile
317
+ ARN, an Azure deployment name, `accounts/fireworks/models/…`,
318
+ `meta-llama/Llama-3.3-70B`, an Ollama tag — and those ids are now accepted.
319
+ New in `@skaile/workspaces/types/manifests`: `ModelIdTarget`,
320
+ `requiresAnthropicModelId()`, `modelIdSchemaForTarget()`,
321
+ `isFirstPartyAnthropicEndpoint()`, `ANTHROPIC_FIRST_PARTY_HOSTS`,
322
+ `FreeFormModelIdSchema` and `ModelSelectorSchema`. `ModelIdSchema` is unchanged
323
+ but is no longer a universal rule: it is the first-party Anthropic vocabulary,
324
+ selected by `modelIdSchemaForTarget()`. `modelIdSchemaForCloud()` keeps its
325
+ signature and is now free-form for every `cloud` other than `default` —
326
+ `bedrock`, `vertex` and `azure` rename the ids, so validating them against
327
+ Anthropic's namespace rejected working deployments.
328
+
329
+ `AgentManifest.model.preferred` / `.fallback` accept a model **selector**:
330
+ `@role`, `<providerId>/<modelId>`, a bare id, or an Anthropic alias. A manifest
331
+ is portable across providers and cannot know which entry will serve it, so the
332
+ id-vocabulary check moved to where the endpoint is known. Only a value no
333
+ endpoint could be handed (empty, or containing whitespace) still fails
334
+ `validateAgent`.
335
+
336
+ New in `@skaile/workspaces/bridge` (`bridge/src/models.ts`):
337
+ `resolveManifestModel()` resolves a manifest preference against the registry —
338
+ `@role` through `roles`, then `provider/id`, then a bare id, all via
339
+ `parseModelRef()` — and reports an `error` when the id the entry would receive
340
+ is not legal for its surface. `modelIdTargetForEntry()` derives that target from
341
+ an entry (falling back to its catalog preset for `surface` / `base_url`).
342
+ `resolveModelCapabilities()` reads `capabilities.context_window` /
343
+ `thinking_max` / `tools` / `images` from the entry serving a model, field by
344
+ field over a caller-supplied per-model fallback table.
345
+
346
+ `resolveModelTier()` takes `{registry, roles, providerId}` and resolves
347
+ `small`/`default`/`deep` through `roles[tier]` and then the selected entry's
348
+ `model_map[tier]` — which works for every provider, not just the ten in
349
+ `PROVIDER_MODEL_TIERS`. That table is now the **no-registry fallback only**:
350
+ where a registry is configured it is not consulted, and a tier the registry does
351
+ not define raises `ModelTierResolutionError` instead of substituting a guess.
352
+ Precedence is unchanged otherwise: a configured override first, and `default`
353
+ still inherits the session model before any table.
354
+
355
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - omp sees every configured AI provider, out of a session-private agent directory.
356
+
357
+ omp is the one backend whose native config already _is_ the registry shape:
358
+ `models.yml` is a `providers:` map with `baseUrl`, `api`, `apiKey`, `headers`,
359
+ `authHeader`, `auth`, `discovery` and `models[]`. So the new adapter
360
+ (`bridge/src/drivers/omp-models-yml.ts`) is a serializer, not a translator —
361
+ each enabled `llm` entry becomes one omp provider, `surface` is written
362
+ verbatim as `api` (the two enums are the same list), `model_map` becomes
363
+ `models[]` keyed by the provider-side id, and `AgentConfig.roles` becomes
364
+ `modelRoles` in a sibling `config.yml`. The result: three configured endpoints
365
+ are three selectable providers in one session, `@smol` and `@default` resolve
366
+ to different vendors, and a subagent pinned to `@smol` reaches that endpoint —
367
+ verified against omp 18.2.6 with fake servers logging the requests.
368
+
369
+ `apiKey` holds the **name** of `SKAILE_AIP_<ID>_KEY`, never a value: omp
370
+ resolves a `models.yml` `apiKey` as an environment variable name before it
371
+ falls back to treating it as a literal token, so the credential can stay in the
372
+ child environment where a config file cannot leak it. The ~50-name
373
+ `OMP_PROVIDER_ENV_KEYS` allowlist stops being the mechanism by which
374
+ credentials reach omp and survives only as an ambient fallback (and as the
375
+ carrier for the `sigv4` / `google_adc` signing chains an entry delegates to)
376
+ until the legacy-contract change deletes it.
377
+
378
+ `PI_CODING_AGENT_DIR` relocates omp's whole agent base — `config.yml`,
379
+ `models.yml` _and_ the auth store `agent.db` — so pointing it at a
380
+ session-private directory is what makes N providers per session possible
381
+ without ever writing the user's `~/.omp/agent`. The directory sits outside
382
+ `cwd`, the one tree the agent has write access to, matching the line managed
383
+ codex already draws for its private directory; `AgentConfig.agentDir`'s
384
+ identity files are symlinked in so `agent.yaml` / `SOUL.md` / `RULES.md` /
385
+ `knowledge/` still resolve.
386
+
387
+ Relocating that base would also have cost a developer their stored OAuth
388
+ logins, which was the one risk that could have descoped this to
389
+ "one active provider". It does not: a machine that has `~/.omp/agent` gets its
390
+ contents symlinked into the session directory, and an OAuth account stored
391
+ there still authenticates inside the relocated session (checked with `omp
392
+ token`, omp 18.2.6). `models.yml` is never seeded and `config.yml` is copied
393
+ rather than linked, so neither of the user's files can be written through the
394
+ session. A platform container has no such directory, so its session starts
395
+ empty — which is the correct behaviour there.
396
+
397
+ `AgentConfig` gains `roles` (the `skaile.yaml` role table) and
398
+ `DriverOptions.omp` (`agentHome`, `seedUserAgentDir`, `userAgentDir`); both are
399
+ additive. A session with no registry keeps the previous behaviour exactly.
400
+
401
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - A custom endpoint now reaches OpenCode, Goose and Continue, not only the
402
+ vendors their own tables know.
403
+
404
+ The env half of these three backends (`SKAILE_AIP_<ID>_KEY` per entry, plus
405
+ `-m <provider>/<model>` / `GOOSE_PROVIDER` / a Continue `chat` binding) can
406
+ name an endpoint the backend already knows. It cannot describe one it has
407
+ never heard of — a self-hosted gateway, a LiteLLM proxy, an Ollama box — and
408
+ each of these backends learns such an endpoint only from its own config file.
409
+ Each driver now renders one:
410
+
411
+ - `opencode` — `opencode/opencode.json` with a `provider.<id>` block
412
+ (`npm` from the entry's `surface`, `options.baseURL`, `options.apiKey`,
413
+ `models`), reached by pointing `XDG_CONFIG_HOME` at the session's own
414
+ directory.
415
+ - `goose` — a declarative provider per entry,
416
+ `config/custom_providers/<id>.json` (`engine`, `base_url`, `api_key_env`,
417
+ `models[]`, `headers`), reached through `GOOSE_PATH_ROOT`.
418
+ - `continue` — `config.yaml` with one `models[]` row per bound model, reached
419
+ through `CONTINUE_GLOBAL_DIR`. `cn` has no model flag, so the session's
420
+ `roles:` table is what binds them: each key that is a Continue role
421
+ (`chat`, `edit`, `apply`, `autocomplete`, `embed`, `rerank`, `summarize`;
422
+ `default` is read as `chat`) becomes that role's model, and the session's
423
+ own selector wins `chat`.
424
+
425
+ Three invariants hold across all three. The rendered file never contains a
426
+ credential — it names the per-entry variable (`{env:SKAILE_AIP_<ID>_KEY}`,
427
+ `api_key_env`, `${{ secrets.… }}`) and the value is delivered in the child
428
+ environment, the same rule the codex and omp adapters follow. The provider
429
+ name in the file is `backendProviderName`, the same name the env half puts on
430
+ the command line, so the two halves cannot drift apart. And the config home is
431
+ session-private, under `$SKAILE_HOME/<driver>/<sessionId>`: the developer's
432
+ `~/.config/opencode`, Goose config directory and `~/.continue` are neither
433
+ read nor written, which also keeps a session's state out of them.
434
+
435
+ Nothing is rendered unless something has to be. A session whose endpoints are
436
+ all stock catalog endpoints, and a session that carries only the legacy
437
+ `provider`/`model`/`apiKeys` fields, write no file and leave the config-home
438
+ variable unset — those backends behave exactly as before, including reading
439
+ the developer's own config.
440
+
441
+ Entries a backend genuinely cannot express are left out of the file and
442
+ logged, never guessed at: Goose's declarative providers are `openai` /
443
+ `anthropic` / `ollama` engines only, so `google-*` and
444
+ `bedrock-converse-stream` entries are reported instead; the same applies to
445
+ any surface with no OpenCode AI SDK package or Continue provider class.
446
+
447
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`194a9c3`](https://github.com/skaile-ai/workspaces/commit/194a9c36cfc6ed6ac028db4aeadaf6d37e32f3cf) Thanks [@mortegro](https://github.com/mortegro)! - Add the AI provider registry: `providers.yml` defines every LLM and voice
448
+ endpoint once, and `skaile providers list|add|set|rm|test` manages it.
449
+
450
+ New in `@skaile/workspaces/core` (`core/src/provider-registry.ts`, also exported
451
+ as `@skaile/workspaces/core/provider-registry`): the record types
452
+ (`kind, label, preset, surface, transport, base_url, params, headers,
453
+ query_params, credential{kind, ref}, model_map, capabilities, discovery,
454
+ enabled, locked`), `validateRegistry()`, `mergeRegistries()`,
455
+ `resolveCredential()`, `resolveEntryBaseUrl()` and `parseModelRef()`.
456
+ `surface` is omp's `api` vocabulary verbatim; `params` is a discriminated union
457
+ keyed on `transport`; `stt`/`tts` entries use a reduced record and reject the
458
+ llm-only fields. A literal secret in `credential.ref`, `headers`,
459
+ `query_params` or `base_url` is a validation error naming the offending key —
460
+ credentials are referenced as `env:NAME`, `cmd:<shell>`, `platform:<configId>`
461
+ or `keyring:<service>/<account>`.
462
+
463
+ `core/src/provider-registry-files.ts` loads `~/.skaile/providers.yml` under
464
+ `<workspace>/.skaile/providers.yml`; the layers are merged **before** they are
465
+ gated, so a file may hold a _partial_ entry — one that names only the fields it
466
+ overrides, `kind` included — and the nearer layer wins per key. An entry no
467
+ layer completes is the error (`missing_kind`, `missing_surface`, naming the
468
+ files that fed it), reported by `loadProviderRegistry()`;
469
+ `validateMergedRegistry()` is that gate for anyone merging layers themselves,
470
+ and `validateRegistry(raw, { layer })` reads one layer. An entry marked
471
+ `locked: true` in a higher layer cannot be overridden from a lower one.
472
+ `bridge/src/provider-catalog.ts` ships presets for the surveyed endpoints
473
+ (Anthropic, OpenAI, Google, Groq, DeepSeek, OpenRouter, Mistral, xAI, Together,
474
+ Fireworks, Bedrock, Vertex, Azure OpenAI, Foundry, Ollama, LM Studio, vLLM,
475
+ LiteLLM, Deepgram, ElevenLabs) so `skaile providers add --preset groq` needs
476
+ nothing but a credential reference.
477
+
478
+ `skaile init` now gitignores `.skaile/providers.yml`. No driver reads the
479
+ registry yet — this release is the schema, the catalog and the CLI.
480
+
481
+ ### Patch Changes
482
+
483
+ - [#736](https://github.com/skaile-ai/workspaces/pull/736) [`2de14a6`](https://github.com/skaile-ai/workspaces/commit/2de14a64fdcd77ec8273679bb13f2a0bf149d845) Thanks [@mortegro](https://github.com/mortegro)! - Fix the provider registry dropping entries whose `kind` or transport `params` come from a preset: the catalog layer is now built from the pre-gate merge (`LoadedProviderRegistry.patches`), so `groq: { preset: groq }` plus a workspace `base_url` override resolves to a complete entry instead of a false "no layer supplies it" error, and a session whose entries all fail the gate logs the diagnostics instead of silently running with no endpoint. The completeness gate also re-scans `credential.ref`, `headers`, `query_params` and `base_url` on programmatically injected layers for literal secrets, and every merge-time diagnostic now names the files that contributed the entry.
484
+
3
485
  ## 3.27.1
4
486
 
5
487
  ### Patch Changes
@@ -1,4 +1,4 @@
1
- import { PROTOCOL_VERSION_STRING } from '../chunk-72DG6GSB.js';
1
+ import { PROTOCOL_VERSION_STRING } from '../chunk-YS4XBN7O.js';
2
2
  import '../chunk-NSBPE2FW.js';
3
3
  import * as z from 'zod';
4
4
 
@@ -1,18 +1,20 @@
1
- import { assignDomain, buildDomainIndex, DOMAIN_MD_FILENAME, parseDomainMd } from './chunk-DZ4UZOFB.js';
1
+ import { assignDomain, buildDomainIndex, DOMAIN_MD_FILENAME, parseDomainMd } from './chunk-M5H4DWIA.js';
2
2
  import './chunk-JXT46QFC.js';
3
- import './chunk-HSRHO7SK.js';
3
+ import './chunk-3VSRJE3M.js';
4
+ import { factoryAssetRoots } from './chunk-REILIKVM.js';
4
5
  import './chunk-F3HNW354.js';
5
6
  import './chunk-K5GBV4SA.js';
6
7
  import './chunk-QVZA2MDT.js';
7
- import { factoryAssetRoots } from './chunk-IB4XKQMQ.js';
8
- import { scanRepo } from './chunk-MBARHWMZ.js';
8
+ import { scanRepo } from './chunk-K27T47OO.js';
9
9
  import './chunk-MENCWIHW.js';
10
10
  import './chunk-P4VHQA4N.js';
11
11
  import { walkDir, parseFrontmatter } from './chunk-MKZOK4JU.js';
12
12
  import './chunk-GEEW6SY2.js';
13
13
  import './chunk-FTG7CRFD.js';
14
+ import './chunk-KSIRR5PL.js';
15
+ import './chunk-ILG4BXYE.js';
14
16
  import './chunk-W4IPN3DD.js';
15
- import './chunk-AN6NAFRT.js';
17
+ import './chunk-N7B3LZ7V.js';
16
18
  import './chunk-NSBPE2FW.js';
17
19
  import { existsSync, readFileSync } from 'fs';
18
20
  import * as path from 'path';
@@ -65,7 +67,7 @@ async function libraryAssets() {
65
67
  const domains = [];
66
68
  try {
67
69
  const [{ openLibraryManager }, { skaileHomeDir }, { getGlobalCacheDir }] = await Promise.all([
68
- import('./open-library-32XAI2LH.js'),
70
+ import('./open-library-7OIUAGAH.js'),
69
71
  import('./library/index.js'),
70
72
  import('./core/index.js')
71
73
  ]);
@@ -98,7 +100,7 @@ async function libraryAssets() {
98
100
  async function storeAssets(projectDir) {
99
101
  const notes = [];
100
102
  try {
101
- const { resolveCatalogSource } = await import('./open-library-32XAI2LH.js');
103
+ const { resolveCatalogSource } = await import('./open-library-7OIUAGAH.js');
102
104
  const { source, close } = await resolveCatalogSource({ projectDir });
103
105
  try {
104
106
  const assets = await source.listAssets();
@@ -202,5 +204,5 @@ function dedupeBySlug(domains) {
202
204
  }
203
205
 
204
206
  export { gatherAssetFeeds };
205
- //# sourceMappingURL=asset-feeds-QF7LGRUX.js.map
206
- //# sourceMappingURL=asset-feeds-QF7LGRUX.js.map
207
+ //# sourceMappingURL=asset-feeds-VEPD5ZU7.js.map
208
+ //# sourceMappingURL=asset-feeds-VEPD5ZU7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../cli/src/asset-feeds.ts"],"names":[],"mappings":"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","file":"asset-feeds-VEPD5ZU7.js","sourcesContent":["/**\n * asset-feeds.ts — gather installable assets from every feed the manage TUI\n * surfaces.\n *\n * Four feeds, normalized into `CatalogEntry`:\n * - **Project sources** — `skaile.yaml` `sources:` entries (scanned via\n * `AssetManager.search()`; the new `sources:` field is merged into the\n * legacy repositories map in `AssetManager.loadConfig`).\n * - **Local libraries** — user authoring places from `LocalIndex` (filesystem\n * scan of each library's `path`).\n * - **Factory assets** — the bundled first-party `factory-assets` tree\n * (`factoryAssetRoots()`), scanned from disk. Always present; no network.\n * - **Remote store** — the configured catalog source when `catalog.url` is\n * not `local`. Failures are non-fatal — they surface as notes.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n type AssetKind,\n type CatalogDomain,\n type CatalogEntry,\n factoryAssetRoots,\n parseFrontmatter,\n scanRepo,\n walkDir,\n} from \"@skaile/workspaces/core\";\nimport {\n assignDomain,\n buildDomainIndex,\n DOMAIN_MD_FILENAME,\n type DomainMd,\n parseDomainMd,\n} from \"@skaile/workspaces/discovery\";\n\n/** One non-fatal note returned to the caller for surfacing in the UI. */\nexport interface FeedNote {\n feed: \"sources\" | \"libraries\" | \"store\" | \"factory\";\n message: string;\n}\n\n/**\n * Which feed an asset came from. This is the top-level grouping axis in the\n * manage TUI (\"where is this skill coming from?\") and is intentionally distinct\n * from `publisher` (asset-intrinsic identity): the same publisher can legitimately\n * appear under more than one origin (e.g. a github repo you added as a `source`\n * that is also listed in the remote `store`).\n */\nexport type AssetOrigin = \"source\" | \"library\" | \"factory\" | \"store\";\n\n/** A catalog entry tagged with the feed it was gathered from. */\nexport interface OriginEntry {\n origin: AssetOrigin;\n entry: CatalogEntry;\n /**\n * Second-level grouping label for the manage tree. Defaults (when unset) to the\n * entry's `publisher`; the source feed sets it to the source's short repo name\n * so the Sources band groups by source — \"which repo did this come from\" — not\n * by the asset-intrinsic publisher.\n */\n group?: string;\n}\n\nexport interface AssetFeedResult {\n entries: OriginEntry[];\n /**\n * Display-only domain metadata, keyed (by the consumer) on `slug`. Populated\n * from the store's `catalog.listDomains` when the connected catalog source\n * exposes it; empty otherwise. The manage TUI joins `entry.domainSlug` → a\n * domain for grouping headers, descriptions, and relation badges.\n */\n domains: CatalogDomain[];\n notes: FeedNote[];\n}\n\n// ── Domain stamping (on-disk feeds) ──────────────────────────────────────────\n//\n// `scanRepo` (the source / library / factory scan path) does not read the\n// `DOMAIN.md` sidecars, so its entries arrive with no `domainSlug` and render\n// flat under their publisher band. We re-derive the grouping here from the\n// root's `DOMAIN.md` files (the same sidecars the remote store computes\n// server-side), and fall back to the repo/source name for any entry no domain\n// claims so it still groups instead of landing in the synthetic \"no domain\" pile.\n\n/** Repo-relative POSIX path (DOMAIN.md slugs are matched whole-segment, `/`-joined). */\nfunction toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\n/** Parse every `DOMAIN.md` sidecar under `root` into a {@link DomainMd}. */\nasync function loadDomainMds(root: string): Promise<DomainMd[]> {\n const out: DomainMd[] = [];\n for await (const { path: filePath, name } of walkDir(root)) {\n if (name !== DOMAIN_MD_FILENAME) continue;\n try {\n const { data } = parseFrontmatter(readFileSync(filePath, \"utf8\"));\n out.push(parseDomainMd(toPosix(path.relative(root, filePath)), data));\n } catch {}\n }\n return out;\n}\n\n/**\n * Stamp `domainSlug` onto every entry scanned from `root` using the root's\n * `DOMAIN.md` sidecars. Returns the `CatalogDomain` registry for the real\n * domains, plus a synthetic fallback domain when any entry used the fallback.\n * Mutates `entries` in place (sets `entry.domainSlug`).\n *\n * `synthesizeFallback` (default true): entries no domain claims fall back to\n * `fallbackSlug` (the repo/source name). Pass `false` when the caller already\n * groups these entries one level up (e.g. the source feed groups by source\n * node) — unmatched entries then get no domain (`\"\"`) and hang directly under\n * that parent, instead of nesting under a same-named fallback domain.\n */\nasync function stampDomains(\n root: string,\n fallbackSlug: string,\n entries: CatalogEntry[],\n synthesizeFallback = true,\n): Promise<CatalogDomain[]> {\n const domainMds = await loadDomainMds(root);\n const assignables = entries.map((entry) => ({\n entry,\n ref: `${entry.kind}:${entry.name}`,\n relativePath: toPosix(path.relative(root, entry.source)),\n }));\n\n let usedFallback = false;\n for (const a of assignables) {\n const slug = assignDomain(a.relativePath, domainMds);\n if (slug) a.entry.domainSlug = slug;\n else if (synthesizeFallback) {\n a.entry.domainSlug = fallbackSlug;\n usedFallback = true;\n } else a.entry.domainSlug = \"\";\n }\n\n const { index } = buildDomainIndex(assignables, domainMds);\n const catalog: CatalogDomain[] = Object.values(index).map((d) => ({\n slug: d.slug,\n title: d.title,\n ...(d.description ? { description: d.description } : {}),\n ...(d.relation ? { relation: d.relation } : {}),\n ...(d.order !== undefined ? { order: d.order } : {}),\n ...(d.recommended[0] ? { recommendedRef: d.recommended[0] } : {}),\n }));\n if (usedFallback) catalog.push({ slug: fallbackSlug, title: fallbackSlug });\n return catalog;\n}\n\n/**\n * Pull assets from local libraries (the authoring places under\n * `~/.skaile/libraries/<name>/`, not the `~/.skaile/cache/sources/` cache). Each\n * library's `path` is scanned with `scanRepo` and grouped under the bare library\n * name (`group: <name>`) so the manage TUI shows a clean `<name>` band — no\n * `library:` prefix and no redundant same-named fallback domain (mirrors the\n * source feed).\n */\nasync function libraryAssets(): Promise<{\n entries: OriginEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n const domains: CatalogDomain[] = [];\n try {\n const [{ openLibraryManager }, { skaileHomeDir }, { getGlobalCacheDir }] = await Promise.all([\n import(\"./open-library.ts\"),\n import(\"@skaile/workspaces/library\"),\n import(\"@skaile/workspaces/core\"),\n ]);\n const { manager, close } = await openLibraryManager();\n try {\n // Authoring libraries are the rows that are NOT source clones. index.db\n // rows predating the cache migration still carry the legacy\n // ~/.skaile/sources path, so exclude both roots.\n const newRoot = getGlobalCacheDir();\n const legacyRoot = path.join(skaileHomeDir(), \"sources\");\n const libs = (await manager.listLibraries()).filter(\n (l) => !l.path.startsWith(newRoot) && !l.path.startsWith(legacyRoot),\n );\n const entries: OriginEntry[] = [];\n for (const lib of libs) {\n if (!existsSync(lib.path)) continue;\n // Scan + group under the bare library name. `synthesizeFallback: false`\n // (as the source feed does) keeps domainless assets directly under the\n // library band instead of a redundant same-named fallback domain.\n const libEntries = [...(await scanRepo(lib.path, lib.name))];\n domains.push(...(await stampDomains(lib.path, lib.name, libEntries, false)));\n for (const entry of libEntries) entries.push({ origin: \"library\", entry, group: lib.name });\n }\n return { entries, domains, notes };\n } finally {\n close();\n }\n } catch (err) {\n notes.push({\n feed: \"libraries\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], domains, notes };\n }\n}\n\n/**\n * Pull a (best-effort) snapshot of the connected remote store catalog.\n *\n * - Returns no entries when the resolved catalog is local-only or the host\n * is unreachable (the failure becomes a note, not an exception).\n * - Maps `CatalogAsset` → `CatalogEntry`, carrying `publisher`, `repo`, and\n * `category` straight through and using `source = \"store://<id>\"`; per-file\n * `source` paths are not available for remote assets so the canonical ref is\n * a stable placeholder.\n */\nasync function storeAssets(projectDir: string): Promise<{\n entries: CatalogEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n try {\n const { resolveCatalogSource } = await import(\"./open-library.ts\");\n const { source, close } = await resolveCatalogSource({ projectDir });\n try {\n const assets = await source.listAssets();\n const entries: CatalogEntry[] = assets.map((a) => ({\n name: a.name,\n kind: (a.kind as AssetKind) ?? \"skill\",\n description: a.description ?? \"\",\n source: `store://${a.id}`,\n publisher: a.publisher,\n repo: a.repo,\n domainSlug: a.domainSlug,\n category: a.category,\n version: a.version,\n requires: [],\n dependencies: [],\n }));\n // Domains are optional on the catalog source — only the store backend\n // (post Part 4 `catalog.listDomains`) exposes them. Duck-type the call so\n // older sources and the local catalog degrade to no domains, not an error.\n const domains = await loadDomains(source);\n return { entries, domains, notes };\n } finally {\n close();\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // Local-only catalog throws a recognizable message — silence it; absence\n // is the user's choice, not an error.\n if (!/local/i.test(msg)) {\n notes.push({ feed: \"store\", message: msg });\n }\n return { entries: [], domains: [], notes };\n }\n}\n\n/** Optional `listDomains` capability — returns `[]` when the source lacks it. */\nasync function loadDomains(source: unknown): Promise<CatalogDomain[]> {\n const fn = (source as { listDomains?: () => Promise<CatalogDomain[]> }).listDomains;\n if (typeof fn !== \"function\") return [];\n const domains = await fn.call(source);\n return Array.isArray(domains) ? domains : [];\n}\n\n/** The slice of `AssetManager` the source feed needs (kept narrow for tests). */\ninterface AssetManagerLike {\n search: () => Promise<CatalogEntry[]>;\n searchRepoRoots: () => { repoName: string; root: string }[];\n}\n\n/**\n * Project-source feed: leans on `AssetManager.search()`, which now merges\n * `skaile.yaml`'s `sources:` field into the repositories map, then stamps\n * `DOMAIN.md`-derived domain grouping onto the scanned entries via\n * `searchRepoRoots()`.\n */\nasync function sourceAssets(\n am: AssetManagerLike,\n): Promise<{ entries: OriginEntry[]; domains: CatalogDomain[] }> {\n // The bundled factory tree is injected into the repositories map as an implicit\n // source, so `am.search()` returns it too. It has its own `factory` origin band,\n // so drop it here — otherwise the same first-party skills list twice under Sources.\n const factoryPrefixes = factoryAssetRoots().map((r) => (r.endsWith(path.sep) ? r : r + path.sep));\n const isFactoryPath = (p: string) =>\n factoryPrefixes.some((fp) => p === fp.slice(0, -1) || p.startsWith(fp));\n\n const all = (await am.search()).filter((e) => !isFactoryPath(e.source));\n const entries: OriginEntry[] = [];\n const domains: CatalogDomain[] = [];\n // Group each source's entries under the source node (its short repo name), not\n // the publisher: under Sources the navigational question is \"which repo did\n // this come from\". Each entry's `source` (absolute manifest path) lives under\n // exactly one declared root, so group + stamp by prefix. The cache slug is\n // URL-keyed `github.com/<org>/<repo>` — take the trailing segment.\n for (const { repoName, root } of am.searchRepoRoots()) {\n if (isFactoryPath(root)) continue;\n const prefix = root.endsWith(path.sep) ? root : root + path.sep;\n const owned = all.filter((e) => e.source === root || e.source.startsWith(prefix));\n if (owned.length === 0) continue;\n const sourceName = repoName.split(\"/\").pop() || repoName;\n // No synthetic fallback domain — the source node already groups these, so a\n // same-named fallback would just nest the source under itself.\n domains.push(...(await stampDomains(root, sourceName, owned, false)));\n for (const entry of owned) entries.push({ origin: \"source\", entry, group: sourceName });\n }\n return { entries, domains };\n}\n\n/**\n * Factory-asset feed: scan the bundled first-party `factory-assets` tree(s)\n * resolved by `factoryAssetRoots()` (the `SKAILE_FACTORY_ASSETS_DIR` override\n * layer ahead of the bundled tree). Local disk only, no network — the entries are\n * the built-in skills / connectors / bundles that ship with `@skaile/workspaces`.\n * `factoryAssetRoots()` already dedupes, so the env override pointing at the\n * bundled dir collapses to one root.\n */\nasync function factoryAssets(): Promise<{\n entries: CatalogEntry[];\n domains: CatalogDomain[];\n notes: FeedNote[];\n}> {\n const notes: FeedNote[] = [];\n const domains: CatalogDomain[] = [];\n try {\n const entries: CatalogEntry[] = [];\n for (const root of factoryAssetRoots()) {\n const rootEntries = [...(await scanRepo(root, \"skaile-factory\"))];\n domains.push(...(await stampDomains(root, \"skaile-factory\", rootEntries)));\n entries.push(...rootEntries);\n }\n return { entries, domains, notes };\n } catch (err) {\n notes.push({\n feed: \"factory\",\n message: err instanceof Error ? err.message : String(err),\n });\n return { entries: [], domains, notes };\n }\n}\n\n/** Tag a flat entry list with a single origin. */\nfunction tag(origin: AssetOrigin, entries: CatalogEntry[]): OriginEntry[] {\n return entries.map((entry) => ({ origin, entry }));\n}\n\n/**\n * Run all feeds and return a single normalized result.\n *\n * Feeds run in parallel where possible — the store fetch is the slow one\n * (one HTTP call) and is fired alongside the local library walk. The factory\n * scan is local disk only, so it runs inline.\n */\nexport async function gatherAssetFeeds(\n am: AssetManagerLike,\n projectDir: string,\n): Promise<AssetFeedResult> {\n const [libs, store] = await Promise.all([libraryAssets(), storeAssets(projectDir)]);\n const factory = await factoryAssets();\n const src = await sourceAssets(am);\n return {\n entries: [\n ...src.entries,\n ...libs.entries,\n ...tag(\"factory\", factory.entries),\n ...tag(\"store\", store.entries),\n ],\n // Store domains first (server-curated), then the on-disk feeds; dedupe by\n // slug, first-wins, so a store-served domain shadows a same-slug local one.\n domains: dedupeBySlug([...store.domains, ...src.domains, ...libs.domains, ...factory.domains]),\n notes: [...libs.notes, ...store.notes, ...factory.notes],\n };\n}\n\n/** First-wins dedupe of a domain list by `slug`. */\nfunction dedupeBySlug(domains: CatalogDomain[]): CatalogDomain[] {\n const seen = new Set<string>();\n const out: CatalogDomain[] = [];\n for (const d of domains) {\n if (seen.has(d.slug)) continue;\n seen.add(d.slug);\n out.push(d);\n }\n return out;\n}\n"]}
@@ -1,15 +1,17 @@
1
1
  export { WORKSPACE_MOUNT_ENV_VAR, deployAll, deployCatalogEntry, findAiAssetsRoot, isUnderWorkspaceMount, resolveFlowSkills, undeployCatalogEntry, workspaceMountDirs } from '../chunk-7BUZQVRR.js';
2
- import '../chunk-HSRHO7SK.js';
2
+ import '../chunk-3VSRJE3M.js';
3
+ import '../chunk-REILIKVM.js';
3
4
  import '../chunk-F3HNW354.js';
4
5
  import '../chunk-K5GBV4SA.js';
5
6
  import '../chunk-QVZA2MDT.js';
6
- import '../chunk-IB4XKQMQ.js';
7
- import '../chunk-MBARHWMZ.js';
7
+ import '../chunk-K27T47OO.js';
8
8
  import '../chunk-MENCWIHW.js';
9
9
  import '../chunk-P4VHQA4N.js';
10
10
  import '../chunk-MKZOK4JU.js';
11
11
  import '../chunk-GEEW6SY2.js';
12
12
  import '../chunk-FTG7CRFD.js';
13
+ import '../chunk-KSIRR5PL.js';
14
+ import '../chunk-ILG4BXYE.js';
13
15
  import '../chunk-W4IPN3DD.js';
14
16
  import '../chunk-NSBPE2FW.js';
15
17
  //# sourceMappingURL=catalog-deployer.js.map