@skaile/workspaces 1.15.1 → 2.0.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 (299) hide show
  1. package/CHANGELOG.md +271 -0
  2. package/dist/{asset-feeds-MWEMXMZA.js → asset-feeds-7VQVISDI.js} +25 -24
  3. package/dist/asset-feeds-7VQVISDI.js.map +1 -0
  4. package/dist/asset-manager/catalog-deployer.js +13 -1
  5. package/dist/asset-manager/index.js +10 -9
  6. package/dist/asset-manager/installer.js +7 -6
  7. package/dist/asset-manager/src/catalog-deployer.d.ts +70 -5
  8. package/dist/asset-manager/src/catalog-deployer.d.ts.map +1 -1
  9. package/dist/asset-manager/src/index.d.ts +22 -17
  10. package/dist/asset-manager/src/index.d.ts.map +1 -1
  11. package/dist/bridge/drivers/claude-sdk.js +108 -56
  12. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  13. package/dist/bridge/drivers/codex.js +3 -2
  14. package/dist/bridge/drivers/codex.js.map +1 -1
  15. package/dist/bridge/drivers/continue.js +4 -3
  16. package/dist/bridge/drivers/continue.js.map +1 -1
  17. package/dist/bridge/drivers/echo.js +3 -2
  18. package/dist/bridge/drivers/echo.js.map +1 -1
  19. package/dist/bridge/drivers/gemini.js +5 -4
  20. package/dist/bridge/drivers/goose.js +4 -3
  21. package/dist/bridge/drivers/goose.js.map +1 -1
  22. package/dist/bridge/drivers/omp.js +3 -2
  23. package/dist/bridge/drivers/omp.js.map +1 -1
  24. package/dist/bridge/drivers/opencode.js +4 -3
  25. package/dist/bridge/drivers/opencode.js.map +1 -1
  26. package/dist/bridge/drivers/qwen.js +5 -4
  27. package/dist/bridge/drivers/qwen.js.map +1 -1
  28. package/dist/bridge/index.js +4 -3
  29. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  30. package/dist/bridge/src/drivers/scrub-transcript.d.ts +21 -1
  31. package/dist/bridge/src/drivers/scrub-transcript.d.ts.map +1 -1
  32. package/dist/{chunk-344DEXZS.js → chunk-35ELAMQ5.js} +4 -4
  33. package/dist/{chunk-344DEXZS.js.map → chunk-35ELAMQ5.js.map} +1 -1
  34. package/dist/{chunk-73HV7RV3.js → chunk-6FJH63NN.js} +4 -4
  35. package/dist/{chunk-73HV7RV3.js.map → chunk-6FJH63NN.js.map} +1 -1
  36. package/dist/{chunk-ISA7R7PK.js → chunk-72EOJJOM.js} +82 -38
  37. package/dist/chunk-72EOJJOM.js.map +1 -0
  38. package/dist/chunk-7GOCNYUV.js +300 -0
  39. package/dist/chunk-7GOCNYUV.js.map +1 -0
  40. package/dist/{chunk-TFIFNDT2.js → chunk-A5OYCQGT.js} +4 -4
  41. package/dist/{chunk-TFIFNDT2.js.map → chunk-A5OYCQGT.js.map} +1 -1
  42. package/dist/{chunk-KY5NY7LB.js → chunk-BCTU4TN7.js} +11 -11
  43. package/dist/chunk-BCTU4TN7.js.map +1 -0
  44. package/dist/chunk-BEAIJRVF.js +159 -0
  45. package/dist/chunk-BEAIJRVF.js.map +1 -0
  46. package/dist/chunk-BK3WL3QK.js +10 -0
  47. package/dist/chunk-BK3WL3QK.js.map +1 -0
  48. package/dist/{chunk-BI2NKPA4.js → chunk-CA5CWLGN.js} +3 -2
  49. package/dist/chunk-CA5CWLGN.js.map +1 -0
  50. package/dist/{chunk-2TSSCHCQ.js → chunk-CKVIN4H3.js} +5 -5
  51. package/dist/{chunk-2TSSCHCQ.js.map → chunk-CKVIN4H3.js.map} +1 -1
  52. package/dist/{chunk-GXC3TYMQ.js → chunk-CZZRDYT4.js} +70 -32
  53. package/dist/chunk-CZZRDYT4.js.map +1 -0
  54. package/dist/{chunk-MNKUZUN2.js → chunk-DRXDEL3A.js} +3 -3
  55. package/dist/{chunk-MNKUZUN2.js.map → chunk-DRXDEL3A.js.map} +1 -1
  56. package/dist/{chunk-Z6NGK5YC.js → chunk-DY2AK577.js} +3 -3
  57. package/dist/{chunk-Z6NGK5YC.js.map → chunk-DY2AK577.js.map} +1 -1
  58. package/dist/chunk-DYMWJAL4.js +552 -0
  59. package/dist/chunk-DYMWJAL4.js.map +1 -0
  60. package/dist/{chunk-ACXLKNIM.js → chunk-E7HKNQTH.js} +10 -4
  61. package/dist/chunk-E7HKNQTH.js.map +1 -0
  62. package/dist/{chunk-O5VCUU6D.js → chunk-KUZEIKZH.js} +4 -4
  63. package/dist/{chunk-O5VCUU6D.js.map → chunk-KUZEIKZH.js.map} +1 -1
  64. package/dist/{chunk-RADBQ5XJ.js → chunk-KYLWY3A7.js} +10 -10
  65. package/dist/{chunk-RADBQ5XJ.js.map → chunk-KYLWY3A7.js.map} +1 -1
  66. package/dist/{chunk-2BQBWWFX.js → chunk-LBZP2IYG.js} +6 -6
  67. package/dist/chunk-LBZP2IYG.js.map +1 -0
  68. package/dist/{chunk-MZV6WCF3.js → chunk-MAN7AGQJ.js} +3 -3
  69. package/dist/{chunk-MZV6WCF3.js.map → chunk-MAN7AGQJ.js.map} +1 -1
  70. package/dist/{chunk-7J7LQP6T.js → chunk-MMD2KQ3A.js} +31 -19
  71. package/dist/chunk-MMD2KQ3A.js.map +1 -0
  72. package/dist/{chunk-NRXVS7E4.js → chunk-NYCJ7B27.js} +19 -11
  73. package/dist/chunk-NYCJ7B27.js.map +1 -0
  74. package/dist/{chunk-ACWCVB5Q.js → chunk-ORZW7MMO.js} +3 -3
  75. package/dist/{chunk-ACWCVB5Q.js.map → chunk-ORZW7MMO.js.map} +1 -1
  76. package/dist/{chunk-M5GJT3D7.js → chunk-OYX22NJL.js} +3 -3
  77. package/dist/{chunk-M5GJT3D7.js.map → chunk-OYX22NJL.js.map} +1 -1
  78. package/dist/{chunk-MJEUK6VJ.js → chunk-QIQTYN7F.js} +3 -3
  79. package/dist/{chunk-MJEUK6VJ.js.map → chunk-QIQTYN7F.js.map} +1 -1
  80. package/dist/{chunk-2IJFUAZB.js → chunk-RK3HU3H3.js} +123 -18
  81. package/dist/chunk-RK3HU3H3.js.map +1 -0
  82. package/dist/{chunk-5NZ56R63.js → chunk-ST3DLLNZ.js} +18 -6
  83. package/dist/chunk-ST3DLLNZ.js.map +1 -0
  84. package/dist/{chunk-MTM6C7IS.js → chunk-SVL4EZJT.js} +463 -251
  85. package/dist/chunk-SVL4EZJT.js.map +1 -0
  86. package/dist/{chunk-JB35MVBN.js → chunk-U5POE4BA.js} +4 -298
  87. package/dist/chunk-U5POE4BA.js.map +1 -0
  88. package/dist/{chunk-DB264AVQ.js → chunk-UAQVFATZ.js} +8 -8
  89. package/dist/{chunk-DB264AVQ.js.map → chunk-UAQVFATZ.js.map} +1 -1
  90. package/dist/{chunk-DPUZJI45.js → chunk-UVW3R6S7.js} +72 -37
  91. package/dist/chunk-UVW3R6S7.js.map +1 -0
  92. package/dist/{chunk-STQOPWPS.js → chunk-VCU4NPUS.js} +4 -4
  93. package/dist/{chunk-STQOPWPS.js.map → chunk-VCU4NPUS.js.map} +1 -1
  94. package/dist/{chunk-MB6563TL.js → chunk-WCWXDW22.js} +3 -3
  95. package/dist/{chunk-MB6563TL.js.map → chunk-WCWXDW22.js.map} +1 -1
  96. package/dist/{chunk-EKGB4ZWR.js → chunk-WZPADAE7.js} +255 -136
  97. package/dist/chunk-WZPADAE7.js.map +1 -0
  98. package/dist/{chunk-SRWIVMJI.js → chunk-Y3JVBJ3Y.js} +5 -5
  99. package/dist/{chunk-SRWIVMJI.js.map → chunk-Y3JVBJ3Y.js.map} +1 -1
  100. package/dist/{chunk-3EBFDMZC.js → chunk-Y662DNQQ.js} +14 -3
  101. package/dist/chunk-Y662DNQQ.js.map +1 -0
  102. package/dist/cli/index.js +348 -128
  103. package/dist/cli/index.js.map +1 -1
  104. package/dist/cli/src/asset-feeds.d.ts +2 -2
  105. package/dist/cli/src/asset-feeds.d.ts.map +1 -1
  106. package/dist/cli/src/commands/catalog.d.ts +51 -2
  107. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  108. package/dist/cli/src/commands/connector.d.ts +1 -1
  109. package/dist/cli/src/commands/connector.d.ts.map +1 -1
  110. package/dist/cli/src/commands/logs.d.ts.map +1 -1
  111. package/dist/cli/src/commands/manage.d.ts +30 -3
  112. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  113. package/dist/cli/src/commands/project.d.ts +5 -2
  114. package/dist/cli/src/commands/project.d.ts.map +1 -1
  115. package/dist/connectors/config.js +7 -6
  116. package/dist/connectors/index.js +9 -8
  117. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  118. package/dist/connectors/src/connector-prompt.d.ts.map +1 -1
  119. package/dist/connectors/src/watcher.d.ts.map +1 -1
  120. package/dist/connectors/src/worktree.d.ts +20 -2
  121. package/dist/connectors/src/worktree.d.ts.map +1 -1
  122. package/dist/core/index.js +6 -5
  123. package/dist/core/logging.js +2 -1
  124. package/dist/core/manifest.js +2 -1
  125. package/dist/core/runtime-assets.js +4 -3
  126. package/dist/core/src/fs-deadline.d.ts +84 -0
  127. package/dist/core/src/fs-deadline.d.ts.map +1 -0
  128. package/dist/core/src/index.d.ts +4 -3
  129. package/dist/core/src/index.d.ts.map +1 -1
  130. package/dist/core/src/manifest.d.ts +142 -18
  131. package/dist/core/src/manifest.d.ts.map +1 -1
  132. package/dist/core/src/repo-manager.d.ts +2 -2
  133. package/dist/core/src/repo-manager.d.ts.map +1 -1
  134. package/dist/core/src/runtime-assets.d.ts.map +1 -1
  135. package/dist/core/src/subprocess.d.ts +33 -1
  136. package/dist/core/src/subprocess.d.ts.map +1 -1
  137. package/dist/core/src/walker.d.ts +1 -1
  138. package/dist/core/src/walker.d.ts.map +1 -1
  139. package/dist/core/src/workspace-config.d.ts +9 -2
  140. package/dist/core/src/workspace-config.d.ts.map +1 -1
  141. package/dist/core/workspace-config.js +3 -2
  142. package/dist/deploy/index.js +12 -7
  143. package/dist/deploy/index.js.map +1 -1
  144. package/dist/deploy/src/targets/container-runtime.d.ts.map +1 -1
  145. package/dist/discovery/index.js +3 -2
  146. package/dist/{ensure-sources-QGL44IRI.js → ensure-sources-JLVHHZI2.js} +13 -12
  147. package/dist/ensure-sources-JLVHHZI2.js.map +1 -0
  148. package/dist/factory-assets/connectors/box.js +9 -8
  149. package/dist/factory-assets/connectors/deploy/CONNECTOR.md +19 -0
  150. package/dist/factory-assets/connectors/deploy/adapter.d.ts.map +1 -1
  151. package/dist/factory-assets/connectors/deploy.js +9 -8
  152. package/dist/factory-assets/connectors/devserver/adapter.d.ts.map +1 -1
  153. package/dist/factory-assets/connectors/devserver.js +9 -8
  154. package/dist/factory-assets/connectors/flow/CONNECTOR.md +3 -1
  155. package/dist/factory-assets/connectors/flow/adapter.d.ts +2 -1
  156. package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
  157. package/dist/factory-assets/connectors/flow/adapter.js +9 -8
  158. package/dist/factory-assets/connectors/flow/engine.js +6 -5
  159. package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts +9 -2
  160. package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts.map +1 -1
  161. package/dist/factory-assets/connectors/flow/prompt-fragments.js +1 -1
  162. package/dist/factory-assets/connectors/flow/run-flow.js +11 -10
  163. package/dist/factory-assets/connectors/flow.js +9 -8
  164. package/dist/factory-assets/connectors/git/driver.d.ts +12 -1
  165. package/dist/factory-assets/connectors/git/driver.d.ts.map +1 -1
  166. package/dist/factory-assets/connectors/git.js +9 -8
  167. package/dist/factory-assets/connectors/gmail.js +9 -8
  168. package/dist/factory-assets/connectors/googledrive.js +9 -8
  169. package/dist/factory-assets/connectors/local/driver.d.ts +25 -1
  170. package/dist/factory-assets/connectors/local/driver.d.ts.map +1 -1
  171. package/dist/factory-assets/connectors/local.js +9 -8
  172. package/dist/factory-assets/connectors/mattermost.js +9 -8
  173. package/dist/factory-assets/connectors/memory.js +9 -8
  174. package/dist/factory-assets/connectors/minio.js +9 -8
  175. package/dist/factory-assets/connectors/postgres.js +9 -8
  176. package/dist/factory-assets/connectors/s3/driver.d.ts +15 -0
  177. package/dist/factory-assets/connectors/s3/driver.d.ts.map +1 -1
  178. package/dist/factory-assets/connectors/s3.js +9 -8
  179. package/dist/factory-assets/connectors/sharepoint.js +9 -8
  180. package/dist/factory-assets/connectors/sqlite/adapter.d.ts +8 -1
  181. package/dist/factory-assets/connectors/sqlite/adapter.d.ts.map +1 -1
  182. package/dist/factory-assets/connectors/sqlite.js +9 -8
  183. package/dist/factory-assets/connectors/static-server/adapter.d.ts.map +1 -1
  184. package/dist/factory-assets/connectors/static-server.js +9 -8
  185. package/dist/factory-assets/connectors/tunnel.js +9 -8
  186. package/dist/factory-assets/connectors/webdav.js +9 -8
  187. package/dist/factory-assets/connectors/xstate/adapter.d.ts +6 -0
  188. package/dist/factory-assets/connectors/xstate/adapter.d.ts.map +1 -1
  189. package/dist/factory-assets/connectors/xstate-store.js +9 -8
  190. package/dist/factory-assets/connectors/xstate.js +9 -8
  191. package/dist/flows-LV5WYJ2I.js +20 -0
  192. package/dist/{flows-FHWBCLXF.js.map → flows-LV5WYJ2I.js.map} +1 -1
  193. package/dist/{helpers-FMWODXTW.js → helpers-PJ3CPUUL.js} +13 -12
  194. package/dist/{helpers-FMWODXTW.js.map → helpers-PJ3CPUUL.js.map} +1 -1
  195. package/dist/library/index.js +8 -7
  196. package/dist/library/install.js +6 -5
  197. package/dist/{library-publish-7YDHQGBN.js → library-publish-HVZRCE3C.js} +16 -15
  198. package/dist/library-publish-HVZRCE3C.js.map +1 -0
  199. package/dist/{open-library-O6T3ELPK.js → open-library-RMI2FTQ4.js} +14 -13
  200. package/dist/{open-library-O6T3ELPK.js.map → open-library-RMI2FTQ4.js.map} +1 -1
  201. package/dist/{paths-5QJJBAND.js → paths-JSVTQAVW.js} +11 -10
  202. package/dist/{paths-5QJJBAND.js.map → paths-JSVTQAVW.js.map} +1 -1
  203. package/dist/plugin-registry/src/deploy-helpers.d.ts +1 -1
  204. package/dist/{plugin-store-ZBJZ7F6D.js → plugin-store-7TVJB2TS.js} +8 -7
  205. package/dist/plugin-store-7TVJB2TS.js.map +1 -0
  206. package/dist/{project-HAMLHLD5.js → project-P636MSYT.js} +14 -13
  207. package/dist/{project-HAMLHLD5.js.map → project-P636MSYT.js.map} +1 -1
  208. package/dist/resolver/index.js +13 -1
  209. package/dist/resolver/src/types.d.ts +7 -0
  210. package/dist/resolver/src/types.d.ts.map +1 -1
  211. package/dist/resolver/src/validator.d.ts +8 -1
  212. package/dist/resolver/src/validator.d.ts.map +1 -1
  213. package/dist/runner/index.js +14 -13
  214. package/dist/runner/src/external-mcp.d.ts +1 -1
  215. package/dist/runner/src/external-mcp.d.ts.map +1 -1
  216. package/dist/runner/src/mcp-prompt.d.ts +7 -3
  217. package/dist/runner/src/mcp-prompt.d.ts.map +1 -1
  218. package/dist/runner/src/mcp-runtime-handlers.d.ts +12 -0
  219. package/dist/runner/src/mcp-runtime-handlers.d.ts.map +1 -1
  220. package/dist/runner/src/mixin-resolver.d.ts.map +1 -1
  221. package/dist/runner/src/recipe-resolver.d.ts +20 -6
  222. package/dist/runner/src/recipe-resolver.d.ts.map +1 -1
  223. package/dist/runner/src/resource-handler.d.ts +43 -0
  224. package/dist/runner/src/resource-handler.d.ts.map +1 -1
  225. package/dist/runner/src/resources.d.ts +12 -5
  226. package/dist/runner/src/resources.d.ts.map +1 -1
  227. package/dist/runner/src/serve.d.ts +5 -5
  228. package/dist/runner/src/serve.d.ts.map +1 -1
  229. package/dist/runner/src/session-builder.d.ts +9 -0
  230. package/dist/runner/src/session-builder.d.ts.map +1 -1
  231. package/dist/runner/src/session-capability-wiring.d.ts +5 -0
  232. package/dist/runner/src/session-capability-wiring.d.ts.map +1 -1
  233. package/dist/runner/src/workspace-migration.d.ts +37 -3
  234. package/dist/runner/src/workspace-migration.d.ts.map +1 -1
  235. package/dist/sdk/asset-manager.js +10 -9
  236. package/dist/sdk/bridge.js +4 -3
  237. package/dist/sdk/core.js +6 -5
  238. package/dist/sdk/flow.js +6 -5
  239. package/dist/sdk/index.js +14 -13
  240. package/dist/sdk/index.js.map +1 -1
  241. package/dist/sdk/resolver.js +13 -1
  242. package/dist/sdk/runner.js +14 -13
  243. package/dist/sdk/session.js +1 -1
  244. package/dist/sdk/store.js +1 -1
  245. package/dist/session/index.js +1 -1
  246. package/dist/session/src/dispatcher.d.ts.map +1 -1
  247. package/dist/{setup-WJPNUE32.js → setup-OYW3W3XK.js} +10 -9
  248. package/dist/setup-OYW3W3XK.js.map +1 -0
  249. package/dist/skills-QY5PHBD3.js +20 -0
  250. package/dist/{skills-BMI6H7HI.js.map → skills-QY5PHBD3.js.map} +1 -1
  251. package/dist/{source-ITDH4367.js → source-63CHWDC2.js} +15 -14
  252. package/dist/{source-ITDH4367.js.map → source-63CHWDC2.js.map} +1 -1
  253. package/dist/{source-manifest-publish-RMHC7R6M.js → source-manifest-publish-DLASGDK5.js} +17 -16
  254. package/dist/source-manifest-publish-DLASGDK5.js.map +1 -0
  255. package/dist/store/index.js +1 -1
  256. package/dist/store/src/store.d.ts +9 -0
  257. package/dist/store/src/store.d.ts.map +1 -1
  258. package/dist/tui/index.js +14 -13
  259. package/dist/tui/index.js.map +1 -1
  260. package/dist/validator-RN64BKFW.js +5 -0
  261. package/dist/{validator-VF5M764T.js.map → validator-RN64BKFW.js.map} +1 -1
  262. package/dist/workspace-plugin/adapters/mcp.js +18 -5
  263. package/dist/workspace-plugin/adapters/mcp.js.map +1 -1
  264. package/dist/workspace-plugin/adapters/omp.js +10 -10
  265. package/dist/workspace-plugin/index.js +3 -2
  266. package/dist/workspace-plugin/src/tools/validator.d.ts.map +1 -1
  267. package/dist/workspace-plugin/src/utils/ai-assets.d.ts +11 -6
  268. package/dist/workspace-plugin/src/utils/ai-assets.d.ts.map +1 -1
  269. package/package.json +1 -1
  270. package/dist/asset-feeds-MWEMXMZA.js.map +0 -1
  271. package/dist/chunk-2BQBWWFX.js.map +0 -1
  272. package/dist/chunk-2IJFUAZB.js.map +0 -1
  273. package/dist/chunk-3EBFDMZC.js.map +0 -1
  274. package/dist/chunk-5NZ56R63.js.map +0 -1
  275. package/dist/chunk-7J7LQP6T.js.map +0 -1
  276. package/dist/chunk-ACXLKNIM.js.map +0 -1
  277. package/dist/chunk-BI2NKPA4.js.map +0 -1
  278. package/dist/chunk-BQCGFPHW.js +0 -345
  279. package/dist/chunk-BQCGFPHW.js.map +0 -1
  280. package/dist/chunk-DPUZJI45.js.map +0 -1
  281. package/dist/chunk-EKGB4ZWR.js.map +0 -1
  282. package/dist/chunk-GXC3TYMQ.js.map +0 -1
  283. package/dist/chunk-ISA7R7PK.js.map +0 -1
  284. package/dist/chunk-JB35MVBN.js.map +0 -1
  285. package/dist/chunk-KY5NY7LB.js.map +0 -1
  286. package/dist/chunk-LV2HPH3C.js +0 -73
  287. package/dist/chunk-LV2HPH3C.js.map +0 -1
  288. package/dist/chunk-MTM6C7IS.js.map +0 -1
  289. package/dist/chunk-NRXVS7E4.js.map +0 -1
  290. package/dist/chunk-XCBG2KDC.js +0 -23
  291. package/dist/chunk-XCBG2KDC.js.map +0 -1
  292. package/dist/ensure-sources-QGL44IRI.js.map +0 -1
  293. package/dist/flows-FHWBCLXF.js +0 -7
  294. package/dist/library-publish-7YDHQGBN.js.map +0 -1
  295. package/dist/plugin-store-ZBJZ7F6D.js.map +0 -1
  296. package/dist/setup-WJPNUE32.js.map +0 -1
  297. package/dist/skills-BMI6H7HI.js +0 -7
  298. package/dist/source-manifest-publish-RMHC7R6M.js.map +0 -1
  299. package/dist/validator-VF5M764T.js +0 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,276 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#470](https://github.com/skaile-ai/workspaces/pull/470) [`208af20`](https://github.com/skaile-ai/workspaces/commit/208af209fb59c18e483e7c3662d1a672d55aa465) Thanks [@peteralbert](https://github.com/peteralbert)! - Never touch the workspace mount synchronously ([#454](https://github.com/skaile-ai/workspaces/issues/454))
8
+
9
+ Inside the agent container `/skaile/workspace` **is** the rclone FUSE mount
10
+ (SharePoint / OneDrive / WebDAV), and the long-lived `skaile serve` process was
11
+ reaching it with **synchronous** `fs` and `child_process` calls on per-user-click
12
+ request paths. When the host rclone process wedges, such a call parks the single
13
+ threaded event loop in an uninterruptible kernel wait: the whole runtime stops
14
+ serving and the platform reads the session as dead or idle. **A hang is not an
15
+ error, so the `try/catch` around those calls never fired** — which is why this
16
+ class survived normal review. The same defect caused two total platform outages
17
+ on 2026-08-07 (65 min and 5.5 min); the platform side was fixed in
18
+ skaile-ai/platform#2018, [#2023](https://github.com/skaile-ai/workspaces/issues/2023) and [#2046](https://github.com/skaile-ai/workspaces/issues/2046), and this package carried the remaining
19
+ live CRITICALs.
20
+
21
+ Every such call site is now async (`node:fs/promises`, promisified `execFile`)
22
+ and bounded by a deadline, so a wedged mount degrades to **one failed request**
23
+ instead of a dead session. Async-ness is the actual fix — the deadline only
24
+ converts an unbounded wait into a bounded, reportable failure. Node cannot abort
25
+ a syscall already in the kernel, so a losing operation stays pending; that costs
26
+ one handle rather than the event loop.
27
+
28
+ New shared primitive `withFsDeadline` / `tryWithFsDeadline` / `FsDeadlineError`
29
+ in `@skaile/workspaces/core`, modelled on the existing `ensureFleetMounted`.
30
+
31
+ Also fixed along the way:
32
+
33
+ - **Unbounded recursive walks** — the mount resource listing and `walkDir`
34
+ followed symlinks with no depth, entry, time or cycle bound. Both are now
35
+ bounded on every axis, and truncation is always surfaced rather than passed
36
+ off as a complete result. The two differ in _how_, deliberately:
37
+ - The **mount listing throws**. It feeds the platform's folder rename, which
38
+ is list-recursive + copy + delete, so a silently short listing would have
39
+ deleted the un-copied remainder.
40
+ - **`walkDir` / `scanDirectory` report** a structured `WalkTruncation` (default
41
+ sink: a `warn` naming the bound that was hit) and return what they found. A
42
+ catalog scan is advisory — failing the whole scan because one repo is
43
+ pathologically deep would be worse than listing what is there. Callers that
44
+ need certainty should inspect the reported truncations; today `scanRepo`,
45
+ `resolveLibraryEntries` and the catalog/connector listings do not.
46
+ - **`SIGTERM` never lands on a `D`-state process.** Every git/nix/docker
47
+ subprocess timeout now uses `killSignal: "SIGKILL"`, and the call sites that
48
+ had _no_ timeout at all (`connectors/src/worktree.ts`, the deploy connector's
49
+ `rev-parse`) have explicit ones. The pre-existing timeouts bounded the
50
+ healthy-but-slow case only.
51
+ - **Overlapping timer ticks.** The git connector's 60 s fetch, 120 s submodule
52
+ sync and idle auto-commit could stack once each tick began awaiting; ticks now
53
+ skip while the previous is in flight, catch their own rejections (a `void`-called
54
+ async tick would otherwise take the process down), and cannot outlive `disconnect()`.
55
+ - **A live substitution bug**: `resolveRecipePath` became async and its result
56
+ was placed into the MCP recipe map un-awaited, substituting into config as the
57
+ string `[object Promise]`.
58
+ - **`deployAll` now honours its documented contract** — a filesystem failure
59
+ returns `{ success: false, error }` per entry instead of throwing and aborting
60
+ the batch.
61
+ - The git connector's shell-interpolated command strings are replaced by argv
62
+ arrays, removing an argument-injection/quoting class (paths and commit
63
+ messages containing spaces or quotes were previously mis-split).
64
+
65
+ This is a **major** release: several exported symbols became async. See
66
+ `MIGRATION.md` for the full `from → to` list and migration steps.
67
+
68
+ ### Minor Changes
69
+
70
+ - [#467](https://github.com/skaile-ai/workspaces/pull/467) [`be5a346`](https://github.com/skaile-ai/workspaces/commit/be5a346fd03ea621947ddbf3515e66d7494384c6) Thanks [@peteralbert](https://github.com/peteralbert)! - `skaile manage`: lossless, non-blocking arrow-key navigation (coalesced key chunks are split, the soft-dep preview is debounced instead of awaited, and each frame is a single batched write), plus PgUp/PgDn/Home/End paging and an incremental `/` search on the Assets tab that combines with the origin filter.
71
+
72
+ - [#469](https://github.com/skaile-ai/workspaces/pull/469) [`e4d96bc`](https://github.com/skaile-ai/workspaces/commit/e4d96bced7fde9ac473ec4494f5d13087f6d4d09) Thanks [@peteralbert](https://github.com/peteralbert)! - fix(store): fetch, stage, and wire store-sourced `mcp-server` assets
73
+
74
+ `skaile add mcp-server:<store-ref>` was a silent no-op: the dep landed in
75
+ `skaile.yaml`, `skaile list` / `skaile check` reported it installed/satisfied, but
76
+ the bytes were never fetched and the server was never wired into a session.
77
+
78
+ `NON_DEPLOYABLE_KINDS` was doing double duty — gating both the `deployAll` copy
79
+ (correct: an MCP is wired at session start, not copied to a driver target dir) and
80
+ the `stageStoreAssets` fetch (wrong: the wiring reads a real `MCP.md` off disk).
81
+ Three changes:
82
+
83
+ - `stageStoreAssets` now fetches + SHA-verifies `mcp-server` bytes into
84
+ `.skaile/cache/store/<publisher>/mcp-server/<name>/<version>/`. `persona` /
85
+ `ruleset` / `knowledge` stay unfetched — their resolver only reads clone-derived
86
+ repo maps. Nothing is copied into `.claude/`, so `add()` / `install()` still
87
+ return `[]` for the kind.
88
+ - `loadMcpServerDeclarations()` gained the store cache as a discovery source,
89
+ between catalog-dep refs and platform-materialized assets. Precedence is now
90
+ catalog-dep < store-staged < materialized < explicit `mcp_servers:`; undeclared
91
+ staged dirs are still dropped (canonical-contract invariant).
92
+ - `skaile list` reports a locked `mcp-server` with no resolvable declaration as
93
+ `drift` instead of `installed`, and `skaile check` now fails on any declared-but-
94
+ unmaterialized dep instead of printing "All dependencies satisfied."
95
+
96
+ Note: an `MCP.md` whose `command` uses `${recipe:...}` markers still only starts
97
+ inside a platform-deployed session (the Nix out-paths are built there). Staging
98
+ makes the server visible and declared; resolving recipes locally is a separate gap.
99
+
100
+ ### Patch Changes
101
+
102
+ - [#477](https://github.com/skaile-ai/workspaces/pull/477) [`e253db1`](https://github.com/skaile-ai/workspaces/commit/e253db1ac165767a84aa854db7e28cef456e29e7) Thanks [@peteralbert](https://github.com/peteralbert)! - Enable Biome's `noFloatingPromises` and handle the floating promises it found ([#476](https://github.com/skaile-ai/workspaces/issues/476))
103
+
104
+ The repo had **no** lint rule for unhandled promises, so a missing `await` was
105
+ caught only by `tsc` — and only in the cases where the `Promise` was then used
106
+ as something it isn't (`.map`/`.flatMap`). A promise left floating in statement
107
+ position was invisible.
108
+
109
+ Nine call sites were floating. Two were latent process-killers and seven were
110
+ harmless-but-unmarked:
111
+
112
+ - `bridge/drivers/claude-sdk.ts` — the long-lived message loop now carries a
113
+ terminal handler. Its body is wrapped in `try/catch`, but that catch itself
114
+ emits, which can throw; an unhandled rejection there would take the process
115
+ down. The sibling background fetch is marked `void` instead, since its own
116
+ catch only logs and cannot reject.
117
+ - `factory-assets/connectors/devserver/adapter.ts` — the two stdout/stderr log
118
+ pumps are marked `void`; they run for the process's lifetime and swallow their
119
+ own stream errors.
120
+ - Four test helpers awaited nothing while reading the emitted event
121
+ synchronously. That only worked because `handleMountResourceRequest` happened
122
+ to run synchronously up to its first `await` — a real latent break, not a
123
+ style nit.
124
+ - One e2e test dropped the promise from `unwatchAll()`.
125
+
126
+ Scope note: Biome's rule only sees **statement-position** floats. It does not
127
+ catch a promise that is assigned and then misused in a conditional, a
128
+ comparison, or a template — and Biome has no equivalent of ESLint's
129
+ `no-misused-promises` / `no-unnecessary-condition`. This raises the floor; it
130
+ does not close the class. See [#476](https://github.com/skaile-ai/workspaces/issues/476) for the measurements.
131
+
132
+ - [#468](https://github.com/skaile-ai/workspaces/pull/468) [`74d4e60`](https://github.com/skaile-ai/workspaces/commit/74d4e6060e496137ccf8585f00371eb44b537100) Thanks [@peteralbert](https://github.com/peteralbert)! - `skaile info` now resolves store-sourced assets: the lookup falls back from source clones
133
+ and factory assets to this project's deployed assets (offline) and then to the configured
134
+ catalog source, and the not-found hint no longer tells you to run `skaile source sync` for
135
+ an asset that only exists in the store.
136
+
137
+ - [#465](https://github.com/skaile-ai/workspaces/pull/465) [`a05f2f2`](https://github.com/skaile-ai/workspaces/commit/a05f2f20702a15167a7c8012d6ea8b8e3fc2d656) Thanks [@peteralbert](https://github.com/peteralbert)! - Fix unpinned store-only assets failing to install with `Asset not found`. The store
138
+ fetcher built by `AssetManager` now implements the optional `listVersions` member of
139
+ the resolver's `StoreFetcher` contract, delegating to `RemoteCatalogSource#listVersions`
140
+ (degrading to `[]` on a store/transport failure, with a warning so an outage is not
141
+ silently reported as a missing asset). Without it a store-published asset
142
+ with no source clone and a bare/ranged ref (`skaile add skill:@admin/xls`) produced no
143
+ candidate versions and landed in `missing`; only an exact pin resolved.
144
+
145
+ - [#474](https://github.com/skaile-ai/workspaces/pull/474) [`88ee95e`](https://github.com/skaile-ai/workspaces/commit/88ee95e07610e0270a18b18761997b28a7a0dec8) Thanks [@peteralbert](https://github.com/peteralbert)! - Stop `AgentStore._handleEvent` from notifying subscribers on the four remaining structural
146
+ no-ops. `_notify()` invalidates the cached snapshot, so each of these handed every
147
+ `useSyncExternalStore` / Vue `shallowRef` consumer a brand-new snapshot identity for state that
148
+ had not changed.
149
+
150
+ The largest was a missing `default:` arm. The switch names 22 of `AgentEvent`'s 54 members; the
151
+ other 32 — `log_entry` above all, one per line of container output — fell through to the trailing
152
+ `_notify()` having mutated nothing. Unlike the cases fixed in the two preceding patches this was
153
+ not a replay artifact: it fired on every single occurrence. Those 32 types are now ignored
154
+ outright. The arm is deliberately not an `assertNever` exhaustiveness check — that is a compile
155
+ error while 32 members are unnamed, and naming all 54 would enumerate events the store holds no
156
+ state for just to satisfy it.
157
+
158
+ `state_changed` rebuilt the `sharedState` Map unconditionally, and unchanged re-emits are routine:
159
+ the runner replays every namespace on connect, on a seeded execution, on re-registering an
160
+ already-registered store, and immediately after registration — and the `xstate-store` adapter is
161
+ equality-free, so writing a key its current value emits too. It now compares against the value the
162
+ namespace already holds, reusing the capability comparison generalized into one shared
163
+ `isSameJsonValue` helper: `JSON.stringify` equality with a fail-open `try/catch`, deliberately
164
+ conservative so a genuine state update can never be mistaken for a no-op.
165
+
166
+ `protocol_info` reassigned unconditionally, and the runner announces on every attach — tab mount,
167
+ StrictMode remount, SSE reconnect — almost always with the version already held. `ProtocolInfoEvent`
168
+ carries nothing but `version` and `ProtocolVersion` is exactly three numbers, so the field
169
+ comparison is complete, not conservative. When the version is unchanged the held event object is
170
+ kept, so `snapshot.protocolInfo` does not change identity either.
171
+
172
+ `user_message` is flush-only, and the flush is internally conditional — a peer message arriving
173
+ while nothing is streaming finalized nothing. `_flushStreaming()` now reports whether it flushed
174
+ and the case notifies only when it did.
175
+
176
+ Three behaviour changes consumers can notice, beyond the reduced re-renders. **`protocol_info` now
177
+ clears `incompatibleProtocol`.** Nothing ever cleared it, so the platform's "session restarting on
178
+ incompatible protocol" banner was sticky for the life of the store even though the debug pane
179
+ documents the replacement container's `protocol_info` as the thing that dismisses it; the guard had
180
+ to land together with the clear, or a repeat announcement would never have reached the clearing
181
+ code and the bug would have been cemented permanently. **32 event types no longer notify at
182
+ all**, so a consumer that treated "any event arrived" as a liveness signal must now emit its own —
183
+ hosts that need those events already read them off the transport upstream of the store. And an
184
+ **optimistic `updateState()` write is no longer corrected by the runner's echo** when the two are
185
+ `JSON.stringify`-equal: `updateState()` stores the caller's object verbatim, so a caller passing a
186
+ `Date`, `NaN`, or an `undefined`-valued key now keeps that local form where the echo previously
187
+ overwrote it with the serialized one. Such a caller was already desynchronised from the agent,
188
+ which only ever sees the serialized form; both platform call sites pass plain JSON and are
189
+ unaffected. Normalizing the optimistic write is tracked separately.
190
+
191
+ - [#457](https://github.com/skaile-ai/workspaces/pull/457) [`d7cfdac`](https://github.com/skaile-ai/workspaces/commit/d7cfdac0550fcb9f5919280617b729a7e8ba8317) Thanks [@peteralbert](https://github.com/peteralbert)! - Stop `AgentStore` from notifying subscribers on structural no-ops. `setStatus` wrote and
192
+ notified unconditionally, and `capability_register` rebuilt the capabilities Map on every
193
+ replay — so a byte-identical re-registration produced a fresh Map identity and a fresh
194
+ snapshot. Because `_notify()` invalidates the cached snapshot, each no-op handed every
195
+ `useSyncExternalStore` / Vue `shallowRef` consumer a brand-new snapshot identity for no
196
+ reason. Under a stale-token SSE reconnect storm the gateway replays the whole capability set
197
+ on every reattach, and combined with a per-frame status write that churn compounded into
198
+ React error [#185](https://github.com/skaile-ai/workspaces/issues/185) ("Maximum update depth exceeded") in the platform frontend, crashing
199
+ sessions.
200
+
201
+ Three paths now short-circuit: a `setStatus` call carrying the status the store already
202
+ holds (which also covers the `onStatusChange` transport callback, now routed through the
203
+ guarded setter), a `capability_register` whose every capability is already registered with a
204
+ structurally equal value, and a `capability_deregister` naming only capabilities that are
205
+ absent. Capability comparison is serialized (`JSON.stringify`) equality with a fail-open
206
+ `try/catch` — deliberately conservative, so a reordered-but-equal pair still notifies
207
+ (harmless) but a genuine capability update can never be mistaken for a no-op.
208
+
209
+ Consumers see fewer redundant re-renders and no behavioural change for real state
210
+ transitions. The one semantics change: duplicate `setStatus` writes no longer notify, so a
211
+ consumer that relied on a redundant status write as a de-facto "a reconnect happened" signal
212
+ must now emit its own explicit signal.
213
+
214
+ - [#466](https://github.com/skaile-ai/workspaces/pull/466) [`63bf337`](https://github.com/skaile-ai/workspaces/commit/63bf33720d1effc9d98dd43cd83efe62ff5c648f) Thanks [@peteralbert](https://github.com/peteralbert)! - Stop `AgentStore` from notifying subscribers on a redundant `status` event. `case "status"`
215
+ wrote `phase` and fell through to `_notify()` with no equality check, and because `_notify()`
216
+ invalidates the cached snapshot, a status event carrying the phase the store already held
217
+ handed every `useSyncExternalStore` / Vue `shallowRef` consumer a brand-new snapshot identity
218
+ for nothing. This was the highest-volume instance of the churn fixed for `setStatus` and the
219
+ capability registry: the bridge normalizer re-emits `phase: "working"` from three sites, two of
220
+ which fire on every tool call, so in a turn with N tool calls N-1 of those events were full
221
+ consumer fanouts for an unchanged phase.
222
+
223
+ A `status` event whose `phase` equals the phase the store already holds now short-circuits
224
+ before `_notify()`. `StatusEvent` carries nothing but `phase`, so the comparison is a primitive
225
+ `===` — complete, not conservative: when the phase is unchanged, every field of the snapshot is
226
+ unchanged. Flush semantics are untouched — `status` did not flush streaming text before and
227
+ still does not; `finished` remains the canonical end-of-turn flush.
228
+
229
+ Consumers see fewer redundant re-renders and no behavioural change for real phase transitions.
230
+ The one semantics change: a repeated identical phase no longer notifies, so a consumer that
231
+ treated a redundant status emit as a de-facto "the agent is still alive" heartbeat must now
232
+ emit its own explicit signal. Status events remain individually observable upstream —
233
+ `sdk/agent-session.ts` turns them into its own output lines, on its own dedupe rules — which is
234
+ why the guard is store-local rather than applied at the emit site.
235
+
236
+ - [#481](https://github.com/skaile-ai/workspaces/pull/481) [`1657e15`](https://github.com/skaile-ai/workspaces/commit/1657e15b591b1078af73d699e07a4a1680bcb79d) Thanks [@peteralbert](https://github.com/peteralbert)! - Prevent structurally unchanged `AgentStore.updateState()` writes from replacing the shared-state
237
+ Map, rotating framework snapshots, or notifying subscribers. The `state_update` transport command
238
+ is still sent for every call, and unsupported, aliased, proxied, or caller-shared values retain the
239
+ prior optimistic update-and-notify behavior.
240
+
241
+ - [#464](https://github.com/skaile-ai/workspaces/pull/464) [`00e22e6`](https://github.com/skaile-ai/workspaces/commit/00e22e6cca16210a75046e0dba8cfc9065078f4c) Thanks [@peteralbert](https://github.com/peteralbert)! - fix(runner): hot-plugged MCP servers reach the running claude-sdk driver, and survive
242
+
243
+ `runner.attach_instance` / `runner.add_mcp_server` connected the server and registered its
244
+ tools, but the `claude-sdk` driver composes its SDK `mcpServers` option once inside
245
+ `startQuery` and keeps that query alive across turns — so the agent had no `mcp__<id>__*`
246
+ tools until a full session restart. The runner now queues a driver rebuild (resuming the
247
+ conversation) when the driver bakes its tool set, so the tools are callable on the **next
248
+ turn**, not immediately mid-turn. The rebuild runs in the background: a synchronous one
249
+ would wait out the in-flight turn and blow the platform's 30s runner-capability timeout.
250
+ Concurrent attaches are serialized so two rebuilds can never overlap.
251
+
252
+ Serve now also keeps a per-session registry of live-attached MCP declarations and replays it
253
+ into every session build. The platform never folds a live attach into `skaile.yaml`, and a
254
+ rebuild reads `skaile.yaml` only — so before this, any later recreate (a skill attach, a
255
+ reconnect, a skill restage) silently dropped the hot-plugged server and its tools for the
256
+ rest of the session.
257
+
258
+ Because the declarations now take part in the session build, the system prompt's new
259
+ `## MCP servers` section lists hot-plugged servers alongside declared ones, with their tool
260
+ counts, next to the existing per-server MCP.md guidance.
261
+
262
+ `live: true` from `runner.attach_instance` / `runner.add_mcp_server` therefore now means
263
+ "live from the next turn", and `claude-sdk` sessions return it where they previously
264
+ returned `false`. See MIGRATION.md.
265
+
266
+ - [#480](https://github.com/skaile-ai/workspaces/pull/480) [`9a55d68`](https://github.com/skaile-ai/workspaces/commit/9a55d68e4889a7ebdf775499413fe11de8f50ed5) Thanks [@peteralbert](https://github.com/peteralbert)! - Treat session `status` events as live-only state: active subscribers still receive them, but the dispatcher no longer persists them or assigns them sequence numbers.
267
+
268
+ ## 1.16.0
269
+
270
+ ### Minor Changes
271
+
272
+ - [#452](https://github.com/skaile-ai/workspaces/pull/452) [`24a95f7`](https://github.com/skaile-ai/workspaces/commit/24a95f7f235782e644be3754085bf63f916d52c6) Thanks [@peteralbert](https://github.com/peteralbert)! - Expose flow globals at runtime: render a "Flow globals" section in the orchestrator prompt and add a read-only get_globals flow-connector operation, so agents can read run_input on params-bound runs (fixes [#451](https://github.com/skaile-ai/workspaces/issues/451), upstream of skaile-ai/platform#2039).
273
+
3
274
  ## 1.15.1
4
275
 
5
276
  ### Patch Changes
@@ -1,16 +1,17 @@
1
- import { assignDomain, buildDomainIndex, DOMAIN_MD_FILENAME, parseDomainMd } from './chunk-MZV6WCF3.js';
1
+ import { assignDomain, buildDomainIndex, DOMAIN_MD_FILENAME, parseDomainMd } from './chunk-MAN7AGQJ.js';
2
2
  import './chunk-JXT46QFC.js';
3
- import './chunk-5NZ56R63.js';
3
+ import './chunk-ST3DLLNZ.js';
4
4
  import './chunk-K5GBV4SA.js';
5
5
  import './chunk-ZAP2BDHG.js';
6
- import { factoryAssetRoots } from './chunk-7J7LQP6T.js';
7
- import { scanRepo } from './chunk-ISA7R7PK.js';
6
+ import { factoryAssetRoots } from './chunk-MMD2KQ3A.js';
7
+ import { scanRepo } from './chunk-72EOJJOM.js';
8
8
  import './chunk-P4VHQA4N.js';
9
- import { walkDir, parseFrontmatter } from './chunk-BQCGFPHW.js';
9
+ import { walkDir, parseFrontmatter } from './chunk-DYMWJAL4.js';
10
10
  import './chunk-GEEW6SY2.js';
11
11
  import './chunk-F3HNW354.js';
12
12
  import './chunk-MENCWIHW.js';
13
- import './chunk-JB35MVBN.js';
13
+ import './chunk-U5POE4BA.js';
14
+ import './chunk-7GOCNYUV.js';
14
15
  import './chunk-IRORTHGA.js';
15
16
  import './chunk-NSBPE2FW.js';
16
17
  import { existsSync, readFileSync } from 'fs';
@@ -19,9 +20,9 @@ import * as path from 'path';
19
20
  function toPosix(p) {
20
21
  return p.split(path.sep).join("/");
21
22
  }
22
- function loadDomainMds(root) {
23
+ async function loadDomainMds(root) {
23
24
  const out = [];
24
- for (const { path: filePath, name } of walkDir(root)) {
25
+ for await (const { path: filePath, name } of walkDir(root)) {
25
26
  if (name !== DOMAIN_MD_FILENAME) continue;
26
27
  try {
27
28
  const { data } = parseFrontmatter(readFileSync(filePath, "utf8"));
@@ -31,8 +32,8 @@ function loadDomainMds(root) {
31
32
  }
32
33
  return out;
33
34
  }
34
- function stampDomains(root, fallbackSlug, entries, synthesizeFallback = true) {
35
- const domainMds = loadDomainMds(root);
35
+ async function stampDomains(root, fallbackSlug, entries, synthesizeFallback = true) {
36
+ const domainMds = await loadDomainMds(root);
36
37
  const assignables = entries.map((entry) => ({
37
38
  entry,
38
39
  ref: `${entry.kind}:${entry.name}`,
@@ -64,7 +65,7 @@ async function libraryAssets() {
64
65
  const domains = [];
65
66
  try {
66
67
  const [{ openLibraryManager }, { skaileHomeDir }, { getGlobalCacheDir }] = await Promise.all([
67
- import('./open-library-O6T3ELPK.js'),
68
+ import('./open-library-RMI2FTQ4.js'),
68
69
  import('./library/index.js'),
69
70
  import('./core/index.js')
70
71
  ]);
@@ -78,8 +79,8 @@ async function libraryAssets() {
78
79
  const entries = [];
79
80
  for (const lib of libs) {
80
81
  if (!existsSync(lib.path)) continue;
81
- const libEntries = [...scanRepo(lib.path, lib.name)];
82
- domains.push(...stampDomains(lib.path, lib.name, libEntries, false));
82
+ const libEntries = [...await scanRepo(lib.path, lib.name)];
83
+ domains.push(...await stampDomains(lib.path, lib.name, libEntries, false));
83
84
  for (const entry of libEntries) entries.push({ origin: "library", entry, group: lib.name });
84
85
  }
85
86
  return { entries, domains, notes };
@@ -97,7 +98,7 @@ async function libraryAssets() {
97
98
  async function storeAssets(projectDir) {
98
99
  const notes = [];
99
100
  try {
100
- const { resolveCatalogSource } = await import('./open-library-O6T3ELPK.js');
101
+ const { resolveCatalogSource } = await import('./open-library-RMI2FTQ4.js');
101
102
  const { source, close } = await resolveCatalogSource({ projectDir });
102
103
  try {
103
104
  const assets = await source.listAssets();
@@ -133,10 +134,10 @@ async function loadDomains(source) {
133
134
  const domains = await fn.call(source);
134
135
  return Array.isArray(domains) ? domains : [];
135
136
  }
136
- function sourceAssets(am) {
137
+ async function sourceAssets(am) {
137
138
  const factoryPrefixes = factoryAssetRoots().map((r) => r.endsWith(path.sep) ? r : r + path.sep);
138
139
  const isFactoryPath = (p) => factoryPrefixes.some((fp) => p === fp.slice(0, -1) || p.startsWith(fp));
139
- const all = am.search().filter((e) => !isFactoryPath(e.source));
140
+ const all = (await am.search()).filter((e) => !isFactoryPath(e.source));
140
141
  const entries = [];
141
142
  const domains = [];
142
143
  for (const { repoName, root } of am.searchRepoRoots()) {
@@ -145,19 +146,19 @@ function sourceAssets(am) {
145
146
  const owned = all.filter((e) => e.source === root || e.source.startsWith(prefix));
146
147
  if (owned.length === 0) continue;
147
148
  const sourceName = repoName.split("/").pop() || repoName;
148
- domains.push(...stampDomains(root, sourceName, owned, false));
149
+ domains.push(...await stampDomains(root, sourceName, owned, false));
149
150
  for (const entry of owned) entries.push({ origin: "source", entry, group: sourceName });
150
151
  }
151
152
  return { entries, domains };
152
153
  }
153
- function factoryAssets() {
154
+ async function factoryAssets() {
154
155
  const notes = [];
155
156
  const domains = [];
156
157
  try {
157
158
  const entries = [];
158
159
  for (const root of factoryAssetRoots()) {
159
- const rootEntries = [...scanRepo(root, "skaile-factory")];
160
- domains.push(...stampDomains(root, "skaile-factory", rootEntries));
160
+ const rootEntries = [...await scanRepo(root, "skaile-factory")];
161
+ domains.push(...await stampDomains(root, "skaile-factory", rootEntries));
161
162
  entries.push(...rootEntries);
162
163
  }
163
164
  return { entries, domains, notes };
@@ -174,8 +175,8 @@ function tag(origin, entries) {
174
175
  }
175
176
  async function gatherAssetFeeds(am, projectDir) {
176
177
  const [libs, store] = await Promise.all([libraryAssets(), storeAssets(projectDir)]);
177
- const factory = factoryAssets();
178
- const src = sourceAssets(am);
178
+ const factory = await factoryAssets();
179
+ const src = await sourceAssets(am);
179
180
  return {
180
181
  entries: [
181
182
  ...src.entries,
@@ -201,5 +202,5 @@ function dedupeBySlug(domains) {
201
202
  }
202
203
 
203
204
  export { gatherAssetFeeds };
204
- //# sourceMappingURL=asset-feeds-MWEMXMZA.js.map
205
- //# sourceMappingURL=asset-feeds-MWEMXMZA.js.map
205
+ //# sourceMappingURL=asset-feeds-7VQVISDI.js.map
206
+ //# sourceMappingURL=asset-feeds-7VQVISDI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../cli/src/asset-feeds.ts"],"names":[],"mappings":"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","file":"asset-feeds-7VQVISDI.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,4 +1,16 @@
1
- export { deployAll, deployCatalogEntry, resolveFlowSkills, undeployCatalogEntry } from '../chunk-LV2HPH3C.js';
1
+ export { WORKSPACE_MOUNT_ENV_VAR, deployAll, deployCatalogEntry, findAiAssetsRoot, isUnderWorkspaceMount, resolveFlowSkills, undeployCatalogEntry, workspaceMountDirs } from '../chunk-BEAIJRVF.js';
2
+ import '../chunk-ST3DLLNZ.js';
3
+ import '../chunk-K5GBV4SA.js';
4
+ import '../chunk-ZAP2BDHG.js';
5
+ import '../chunk-MMD2KQ3A.js';
6
+ import '../chunk-72EOJJOM.js';
7
+ import '../chunk-P4VHQA4N.js';
8
+ import '../chunk-DYMWJAL4.js';
9
+ import '../chunk-GEEW6SY2.js';
10
+ import '../chunk-F3HNW354.js';
11
+ import '../chunk-MENCWIHW.js';
12
+ import '../chunk-U5POE4BA.js';
13
+ import '../chunk-7GOCNYUV.js';
2
14
  import '../chunk-NSBPE2FW.js';
3
15
  //# sourceMappingURL=catalog-deployer.js.map
4
16
  //# sourceMappingURL=catalog-deployer.js.map
@@ -1,22 +1,23 @@
1
- export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, NON_DEPLOYABLE_KINDS, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, softDepName } from '../chunk-DPUZJI45.js';
2
- import '../chunk-344DEXZS.js';
1
+ export { AssetManager, FACTORY_SOURCE_URL, MissingManifestError, NON_DEPLOYABLE_KINDS, normalizeRepoUrl, parseCanonicalLockKey, parseRefTolerant, softDepName } from '../chunk-UVW3R6S7.js';
2
+ import '../chunk-35ELAMQ5.js';
3
3
  import '../chunk-UKJMQZV6.js';
4
4
  import '../chunk-R7FOF242.js';
5
- import '../chunk-MZV6WCF3.js';
5
+ import '../chunk-MAN7AGQJ.js';
6
6
  import '../chunk-JXT46QFC.js';
7
- export { createScaffold, deployAll, installAgent, removeAsset } from '../chunk-STQOPWPS.js';
7
+ export { createScaffold, deployAll, installAgent, removeAsset } from '../chunk-VCU4NPUS.js';
8
8
  export { BUILT_IN_FRAGMENTS, loadPromptExtensions, resolveFragments } from '../chunk-CGYEHQOX.js';
9
- import '../chunk-5NZ56R63.js';
9
+ import '../chunk-ST3DLLNZ.js';
10
10
  import '../chunk-K5GBV4SA.js';
11
11
  import '../chunk-ZAP2BDHG.js';
12
- import '../chunk-7J7LQP6T.js';
13
- import '../chunk-ISA7R7PK.js';
12
+ import '../chunk-MMD2KQ3A.js';
13
+ import '../chunk-72EOJJOM.js';
14
14
  import '../chunk-P4VHQA4N.js';
15
- import '../chunk-BQCGFPHW.js';
15
+ import '../chunk-DYMWJAL4.js';
16
16
  import '../chunk-GEEW6SY2.js';
17
17
  import '../chunk-F3HNW354.js';
18
18
  import '../chunk-MENCWIHW.js';
19
- import '../chunk-JB35MVBN.js';
19
+ import '../chunk-U5POE4BA.js';
20
+ import '../chunk-7GOCNYUV.js';
20
21
  export { appendHistory, clearHistory, getRecentHistory, loadHistory } from '../chunk-KTBKW2FI.js';
21
22
  import '../chunk-UQ6LFBPZ.js';
22
23
  export { AGENT_RENDERERS, claudeCodeRenderer, codexRenderer, driverTargetSupportsAgents, ompRenderer, renderAgentToFramework } from '../chunk-IEX5YV4R.js';
@@ -1,16 +1,17 @@
1
- export { createScaffold, deployAll, deployAsset, removeAsset } from '../chunk-STQOPWPS.js';
1
+ export { createScaffold, deployAll, deployAsset, removeAsset } from '../chunk-VCU4NPUS.js';
2
2
  import '../chunk-CGYEHQOX.js';
3
- import '../chunk-5NZ56R63.js';
3
+ import '../chunk-ST3DLLNZ.js';
4
4
  import '../chunk-K5GBV4SA.js';
5
5
  import '../chunk-ZAP2BDHG.js';
6
- import '../chunk-7J7LQP6T.js';
7
- import '../chunk-ISA7R7PK.js';
6
+ import '../chunk-MMD2KQ3A.js';
7
+ import '../chunk-72EOJJOM.js';
8
8
  import '../chunk-P4VHQA4N.js';
9
- import '../chunk-BQCGFPHW.js';
9
+ import '../chunk-DYMWJAL4.js';
10
10
  import '../chunk-GEEW6SY2.js';
11
11
  import '../chunk-F3HNW354.js';
12
12
  import '../chunk-MENCWIHW.js';
13
- import '../chunk-JB35MVBN.js';
13
+ import '../chunk-U5POE4BA.js';
14
+ import '../chunk-7GOCNYUV.js';
14
15
  import '../chunk-IEX5YV4R.js';
15
16
  import '../chunk-IRORTHGA.js';
16
17
  import '../chunk-NSBPE2FW.js';