sliccy 3.5.4 → 3.6.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 (240) hide show
  1. package/README.md +1 -2
  2. package/dist/node-server/_cloud_core/src/errors.d.ts +14 -0
  3. package/dist/node-server/_cloud_core/src/errors.d.ts.map +1 -0
  4. package/dist/node-server/_cloud_core/src/errors.js +13 -0
  5. package/dist/node-server/_cloud_core/src/index.d.ts +19 -0
  6. package/dist/node-server/_cloud_core/src/index.d.ts.map +1 -0
  7. package/dist/node-server/_cloud_core/src/index.js +14 -0
  8. package/dist/node-server/_cloud_core/src/operations/kill.d.ts +18 -0
  9. package/dist/node-server/_cloud_core/src/operations/kill.d.ts.map +1 -0
  10. package/dist/node-server/_cloud_core/src/operations/kill.js +32 -0
  11. package/dist/node-server/_cloud_core/src/operations/list.d.ts +25 -0
  12. package/dist/node-server/_cloud_core/src/operations/list.d.ts.map +1 -0
  13. package/dist/node-server/_cloud_core/src/operations/list.js +145 -0
  14. package/dist/node-server/_cloud_core/src/operations/pause.d.ts +15 -0
  15. package/dist/node-server/_cloud_core/src/operations/pause.d.ts.map +1 -0
  16. package/dist/node-server/_cloud_core/src/operations/pause.js +27 -0
  17. package/dist/node-server/_cloud_core/src/operations/resume.d.ts +22 -0
  18. package/dist/node-server/_cloud_core/src/operations/resume.d.ts.map +1 -0
  19. package/dist/node-server/_cloud_core/src/operations/resume.js +86 -0
  20. package/dist/node-server/_cloud_core/src/operations/start.d.ts +67 -0
  21. package/dist/node-server/_cloud_core/src/operations/start.d.ts.map +1 -0
  22. package/dist/node-server/_cloud_core/src/operations/start.js +228 -0
  23. package/dist/node-server/_cloud_core/src/polling.d.ts +18 -0
  24. package/dist/node-server/_cloud_core/src/polling.d.ts.map +1 -0
  25. package/dist/node-server/_cloud_core/src/polling.js +79 -0
  26. package/dist/node-server/_cloud_core/src/registry.d.ts +27 -0
  27. package/dist/node-server/_cloud_core/src/registry.d.ts.map +1 -0
  28. package/dist/node-server/_cloud_core/src/registry.js +1 -0
  29. package/dist/node-server/_cloud_core/src/secrets-filter.d.ts +2 -0
  30. package/dist/node-server/_cloud_core/src/secrets-filter.d.ts.map +1 -0
  31. package/dist/node-server/_cloud_core/src/secrets-filter.js +17 -0
  32. package/dist/node-server/_cloud_core/src/substrate-factory.d.ts +3 -0
  33. package/dist/node-server/_cloud_core/src/substrate-factory.d.ts.map +1 -0
  34. package/dist/node-server/_cloud_core/src/substrate-factory.js +6 -0
  35. package/dist/node-server/_cloud_core/src/substrate.d.ts +53 -0
  36. package/dist/node-server/_cloud_core/src/substrate.d.ts.map +1 -0
  37. package/dist/node-server/_cloud_core/src/substrate.js +1 -0
  38. package/dist/node-server/_cloud_core/src/substrates/e2b.d.ts +3 -0
  39. package/dist/node-server/_cloud_core/src/substrates/e2b.d.ts.map +1 -0
  40. package/dist/node-server/_cloud_core/src/substrates/e2b.js +98 -0
  41. package/dist/node-server/_cloud_core/src/types.d.ts +94 -0
  42. package/dist/node-server/_cloud_core/src/types.d.ts.map +1 -0
  43. package/dist/node-server/_cloud_core/src/types.js +3 -0
  44. package/dist/node-server/_cloud_core/tests/fixtures/fake-substrate.d.ts +39 -0
  45. package/dist/node-server/_cloud_core/tests/fixtures/fake-substrate.d.ts.map +1 -0
  46. package/dist/node-server/_cloud_core/tests/fixtures/fake-substrate.js +75 -0
  47. package/dist/node-server/_cloud_core/tests/fixtures/index.d.ts +4 -0
  48. package/dist/node-server/_cloud_core/tests/fixtures/index.d.ts.map +1 -0
  49. package/dist/node-server/_cloud_core/tests/fixtures/index.js +2 -0
  50. package/dist/node-server/_cloud_core/tests/fixtures/mem-registry.d.ts +10 -0
  51. package/dist/node-server/_cloud_core/tests/fixtures/mem-registry.d.ts.map +1 -0
  52. package/dist/node-server/_cloud_core/tests/fixtures/mem-registry.js +25 -0
  53. package/dist/node-server/_cloud_core/tests/kill.test.d.ts +2 -0
  54. package/dist/node-server/_cloud_core/tests/kill.test.d.ts.map +1 -0
  55. package/dist/node-server/_cloud_core/tests/kill.test.js +164 -0
  56. package/dist/node-server/_cloud_core/tests/list.test.d.ts +2 -0
  57. package/dist/node-server/_cloud_core/tests/list.test.d.ts.map +1 -0
  58. package/dist/node-server/_cloud_core/tests/list.test.js +300 -0
  59. package/dist/node-server/_cloud_core/tests/pause.test.d.ts +2 -0
  60. package/dist/node-server/_cloud_core/tests/pause.test.d.ts.map +1 -0
  61. package/dist/node-server/_cloud_core/tests/pause.test.js +167 -0
  62. package/dist/node-server/_cloud_core/tests/resume.test.d.ts +2 -0
  63. package/dist/node-server/_cloud_core/tests/resume.test.d.ts.map +1 -0
  64. package/dist/node-server/_cloud_core/tests/resume.test.js +203 -0
  65. package/dist/node-server/_cloud_core/tests/secrets-filter.test.d.ts +2 -0
  66. package/dist/node-server/_cloud_core/tests/secrets-filter.test.d.ts.map +1 -0
  67. package/dist/node-server/_cloud_core/tests/secrets-filter.test.js +30 -0
  68. package/dist/node-server/_cloud_core/tests/start.test.d.ts +2 -0
  69. package/dist/node-server/_cloud_core/tests/start.test.d.ts.map +1 -0
  70. package/dist/node-server/_cloud_core/tests/start.test.js +513 -0
  71. package/dist/node-server/chrome-launch.d.ts +1 -0
  72. package/dist/node-server/chrome-launch.js +3 -0
  73. package/dist/node-server/cloud/dispatch.d.ts +34 -0
  74. package/dist/node-server/cloud/dispatch.js +79 -0
  75. package/dist/node-server/cloud/kill.d.ts +12 -0
  76. package/dist/node-server/cloud/kill.js +11 -0
  77. package/dist/node-server/cloud/list.d.ts +6 -0
  78. package/dist/node-server/cloud/list.js +6 -0
  79. package/dist/node-server/cloud/pause.d.ts +7 -0
  80. package/dist/node-server/cloud/pause.js +6 -0
  81. package/dist/node-server/cloud/registry-file.d.ts +13 -0
  82. package/dist/node-server/cloud/registry-file.js +85 -0
  83. package/dist/node-server/cloud/resume.d.ts +11 -0
  84. package/dist/node-server/cloud/resume.js +17 -0
  85. package/dist/node-server/cloud/start.d.ts +16 -0
  86. package/dist/node-server/cloud/start.js +49 -0
  87. package/dist/node-server/cloud-status.d.ts +11 -0
  88. package/dist/node-server/cloud-status.js +49 -0
  89. package/dist/node-server/hosted-bootstrap.d.ts +21 -0
  90. package/dist/node-server/hosted-bootstrap.js +14 -0
  91. package/dist/node-server/index.js +146 -3
  92. package/dist/node-server/leader-restart.d.ts +29 -0
  93. package/dist/node-server/leader-restart.js +146 -0
  94. package/dist/node-server/runtime-flags.d.ts +1 -0
  95. package/dist/node-server/runtime-flags.js +6 -0
  96. package/dist/ui/assets/adobe-BLY_1hN7.js +1 -0
  97. package/dist/ui/assets/adobe-BZS2Kmci.js +2 -0
  98. package/dist/ui/assets/agent-bridge-BFRFxJAl.js +1 -0
  99. package/dist/ui/assets/{agent-message-to-chat-H07zq-Kv.js → agent-message-to-chat-Cd-DQATg.js} +1 -1
  100. package/dist/ui/assets/anthropic-BbwUhO9H.js +39 -0
  101. package/dist/ui/assets/{anthropic-BK3Od7MT.js → anthropic-Dg9_3G1u.js} +3 -3
  102. package/dist/ui/assets/{apps-mZJxOz_q.js → apps-BQuoIsxV.js} +1 -1
  103. package/dist/ui/assets/azure-openai-CilK3M_Q.js +1 -0
  104. package/dist/ui/assets/{azure-openai-Dch5aR9j.js → azure-openai-CleJGzBE.js} +1 -1
  105. package/dist/ui/assets/azure-openai-responses-DMLD0Ano.js +1 -0
  106. package/dist/ui/assets/azure-openai-responses-_joBD1ru.js +1 -0
  107. package/dist/ui/assets/{bsh-watchdog-i5GXbvla.js → bsh-watchdog-CpJwB685.js} +1 -1
  108. package/dist/ui/assets/{cdp-Cv6W51Ld.js → cdp-BXSNdZRM.js} +3 -3
  109. package/dist/ui/assets/cloud-CCHD45tb.js +1 -0
  110. package/dist/ui/assets/cloud-DyAca2cv.css +1 -0
  111. package/dist/ui/assets/cost-command-Bv5UQVUC.js +1 -0
  112. package/dist/ui/assets/{dist-cK1g1pHF.js → dist-ChvbMSOY.js} +1 -1
  113. package/dist/ui/assets/{dist-BTGs16AV.js → dist-CltZJzbd.js} +1 -1
  114. package/dist/ui/assets/{dist-BcBxL8nL.js → dist-cZSF0917.js} +1 -1
  115. package/dist/ui/assets/{dist-Bgcuvc8h.js → dist-ljtB3O-J.js} +1 -1
  116. package/dist/ui/assets/{dist-EkY3RL7q.js → dist-tLLu0PBg.js} +1 -1
  117. package/dist/ui/assets/{es-Crcyr8Z7.js → es-C2wm9v2H.js} +1 -1
  118. package/dist/ui/assets/follower-sprinkle-bridge-Bg1mCcnG.js +1 -0
  119. package/dist/ui/assets/{github-DKcpc18I.js → github-BDzC2pCD.js} +1 -1
  120. package/dist/ui/assets/github-BzwlgA3s.js +2 -0
  121. package/dist/ui/assets/{google-IZXg3PJn.js → google-BVxsfaV3.js} +1 -1
  122. package/dist/ui/assets/google-C0Zd1qsl.js +1 -0
  123. package/dist/ui/assets/google-shared-DcZhZ_Z7.js +11 -0
  124. package/dist/ui/assets/{google-shared-BaIigNCs.js → google-shared-KyLYJrXa.js} +1 -1
  125. package/dist/ui/assets/google-vertex-BGpbWEWq.js +1 -0
  126. package/dist/ui/assets/{google-vertex-DDwmtWoJ.js → google-vertex-BSOalca9.js} +1 -1
  127. package/dist/ui/assets/{intercepted-oauth-CEgKdcyY.js → intercepted-oauth-D6eAxYca.js} +1 -1
  128. package/dist/ui/assets/{kernel-worker-dg2bRx7X.js → kernel-worker-D1_EtuZW.js} +1016 -980
  129. package/dist/ui/assets/{lick-ws-bridge-DgWfdUlv.js → lick-ws-bridge-DXFDOui-.js} +1 -1
  130. package/dist/ui/assets/{local-llm-DuUGv7wX.js → local-llm-B3qsU55x.js} +1 -1
  131. package/dist/ui/assets/magick-wasm-CasStH-w.js +1 -0
  132. package/dist/ui/assets/main-BSfjQXCf.js +1612 -0
  133. package/dist/ui/assets/{mistral-czd8-m0c.js → mistral-BkhZQqeV.js} +1 -1
  134. package/dist/ui/assets/{mistral-BS_Gm2MH.js → mistral-D130SR-b.js} +1 -1
  135. package/dist/ui/assets/modulepreload-polyfill-wMinxHhO.js +1 -0
  136. package/dist/ui/assets/nuke-command-D_sxu_AA.js +1 -0
  137. package/dist/ui/assets/{oauth-CJxNn7hC.js → oauth-BocTO4G9.js} +1 -1
  138. package/dist/ui/assets/oauth-bootstrap-DZdd7KZS.js +2 -0
  139. package/dist/ui/assets/{oauth-service-BAnfipgD.js → oauth-service-DAWR1CpY.js} +1 -1
  140. package/dist/ui/assets/oauth-service-y04jhWb_.js +1 -0
  141. package/dist/ui/assets/offscreen-client-HCLuFFlN.js +1 -0
  142. package/dist/ui/assets/onboarding-orchestrator-qbEVluIu.js +1 -0
  143. package/dist/ui/assets/openai-codex-responses-Bmd17Jq9.js +7 -0
  144. package/dist/ui/assets/openai-codex-responses-CMOclqki.js +7 -0
  145. package/dist/ui/assets/openai-completions-DmwgEsb4.js +5 -0
  146. package/dist/ui/assets/openai-responses-BYdEOxUq.js +1 -0
  147. package/dist/ui/assets/openai-responses-C3bs8sd1.js +1 -0
  148. package/dist/ui/assets/{openai-responses-shared-DDootAUL.js → openai-responses-shared-AM04ghTC.js} +1 -1
  149. package/dist/ui/assets/{openai-responses-shared-07lPyxEg.js → openai-responses-shared-Be22tDzQ.js} +1 -1
  150. package/dist/ui/assets/openrouter-BIFqVYxG.js +1 -0
  151. package/dist/ui/assets/openrouter-Dc1D0QOS.js +1 -0
  152. package/dist/ui/assets/panel-rpc-handlers-DDaHHzWR.js +1 -0
  153. package/dist/ui/assets/{provider-rBD-3FHW.js → provider-CU5ao6kF.js} +2 -2
  154. package/dist/ui/assets/{provider-BhabAJGA.js → provider-ChUiWhH0.js} +1 -1
  155. package/dist/ui/assets/provider-store-access-Bliwcbgg.js +1 -0
  156. package/dist/ui/assets/provider-store-access-iTh_6mMO.js +1 -0
  157. package/dist/ui/assets/proxied-fetch-8v3TaZYg.js +1 -0
  158. package/dist/ui/assets/{pyodide-BC4PaR54.js → pyodide-B7x60zRI.js} +2 -2
  159. package/dist/ui/assets/{remote-terminal-view-CXbFLcuS.js → remote-terminal-view-BREvd00U.js} +1 -1
  160. package/dist/ui/assets/secret-env-Js2g2sNO.js +1 -0
  161. package/dist/ui/assets/slicc-editor-Bu07BjW4.js +12 -0
  162. package/dist/ui/assets/{spawn-qtlw6x6p.js → spawn-CQ5XACZ1.js} +1 -1
  163. package/dist/ui/assets/{sql-wasm-DeVtn0z8.js → sql-wasm-C-pXJvOw.js} +1 -1
  164. package/dist/ui/assets/{store-DLeVoNF3.js → store-DQUahHdW.js} +1 -1
  165. package/dist/ui/assets/tray-leave-runtime-BEBMIYY_.js +1 -0
  166. package/dist/ui/assets/{upgrade-detection-CKrzeeRx.js → upgrade-detection-T74KTnyb.js} +1 -1
  167. package/dist/ui/assets/{xai-grok-CNyu04Tg.js → xai-grok-CkPPMxfZ.js} +1 -1
  168. package/dist/ui/assets/{xai-grok-sanitize-BeI8rdV5.js → xai-grok-sanitize-C7TgWvwD.js} +1 -1
  169. package/dist/ui/assets/{xai-grok-sanitize-h_8XMTD9.js → xai-grok-sanitize-L5nUbDcW.js} +1 -1
  170. package/dist/ui/assets/xai-grok-u9MyUN8m.js +1 -0
  171. package/dist/ui/electron-overlay-entry.js +9 -9
  172. package/dist/ui/index.html +3 -2
  173. package/dist/ui/packages/webapp/cloud/index.html +38 -0
  174. package/dist/ui/packages/webapp/index.html +3 -2
  175. package/package.json +10 -8
  176. package/dist/ui/assets/adobe-DpCIcyEb.js +0 -2
  177. package/dist/ui/assets/adobe-NMBK1vG2.js +0 -1
  178. package/dist/ui/assets/agent-bridge-D2k69QZ-.js +0 -1
  179. package/dist/ui/assets/anthropic-ZtfIcLyL.js +0 -39
  180. package/dist/ui/assets/azure-openai-CN9QA_pv.js +0 -1
  181. package/dist/ui/assets/azure-openai-responses-Bhr0mNdj.js +0 -1
  182. package/dist/ui/assets/azure-openai-responses-D400BxTc.js +0 -1
  183. package/dist/ui/assets/cost-command-BGqK_hbH.js +0 -1
  184. package/dist/ui/assets/follower-sprinkle-bridge-BayCf20v.js +0 -1
  185. package/dist/ui/assets/github-DpDjTcq9.js +0 -2
  186. package/dist/ui/assets/google-B97zVBac.js +0 -1
  187. package/dist/ui/assets/google-shared-DwzANLbz.js +0 -11
  188. package/dist/ui/assets/google-vertex-ICKJGS1M.js +0 -1
  189. package/dist/ui/assets/index-CCGqFzR9.js +0 -1575
  190. package/dist/ui/assets/magick-wasm-Bu7zx3Ux.js +0 -1
  191. package/dist/ui/assets/nuke-command-BSkSFZ4H.js +0 -1
  192. package/dist/ui/assets/oauth-bootstrap-BeZQrd7y.js +0 -2
  193. package/dist/ui/assets/oauth-service-BX55wTV9.js +0 -1
  194. package/dist/ui/assets/offscreen-client-DSEhUCxj.js +0 -1
  195. package/dist/ui/assets/onboarding-orchestrator-DjNti83y.js +0 -1
  196. package/dist/ui/assets/openai-codex-responses-DJKJH9AX.js +0 -7
  197. package/dist/ui/assets/openai-codex-responses-jB5RkWeq.js +0 -7
  198. package/dist/ui/assets/openai-completions-BWWM3S2J.js +0 -5
  199. package/dist/ui/assets/openai-responses-C_3YpAmj.js +0 -1
  200. package/dist/ui/assets/openai-responses-tJegTQYT.js +0 -1
  201. package/dist/ui/assets/panel-rpc-handlers-B4jZTNHO.js +0 -1
  202. package/dist/ui/assets/provider-store-access-H9Lu5HRL.js +0 -1
  203. package/dist/ui/assets/provider-store-access-biaB--zG.js +0 -1
  204. package/dist/ui/assets/proxied-fetch-C6dm2Ugc.js +0 -1
  205. package/dist/ui/assets/secret-env-s_8cP7Wf.js +0 -1
  206. package/dist/ui/assets/slicc-editor-pZcWEwTm.js +0 -12
  207. package/dist/ui/assets/tray-leave-runtime-DqA9PbxV.js +0 -1
  208. package/dist/ui/assets/xai-grok-CN1nP4TF.js +0 -1
  209. /package/dist/ui/assets/{active-transport-CfU1UxY6.js → active-transport-Clj9slj7.js} +0 -0
  210. /package/dist/ui/assets/{active-transport-Dm6CWYVE.js → active-transport-DHcaBd4j.js} +0 -0
  211. /package/dist/ui/assets/{addon-fit-BDUxDgg1.js → addon-fit-CBG3Hsec.js} +0 -0
  212. /package/dist/ui/assets/{addon-fit-Dkm5m5XK.js → addon-fit-CUt9lrQO.js} +0 -0
  213. /package/dist/ui/assets/{azure-ai-foundry-BHLfY_0t.js → azure-ai-foundry-B4QrVklT.js} +0 -0
  214. /package/dist/ui/assets/{azure-ai-foundry-1pnZpxAJ.js → azure-ai-foundry-CGkSI_4f.js} +0 -0
  215. /package/dist/ui/assets/{chat-fixture-DOzffHLr.js → chat-fixture-ChGRNFda.js} +0 -0
  216. /package/dist/ui/assets/{dist-BYoCEWmq.js → dist-9RlRmGag.js} +0 -0
  217. /package/dist/ui/assets/{dist-BNe7ZIzA.js → dist-CZcDRTma.js} +0 -0
  218. /package/dist/ui/assets/{dist-BrjVVq8c.js → dist-D0kTaNET.js} +0 -0
  219. /package/dist/ui/assets/{git-config-CGMfR0WK.js → git-config-DcQbkikl.js} +0 -0
  220. /package/dist/ui/assets/{github-copilot-headers-CTUP_cqn.js → github-copilot-headers-C5CocKfn.js} +0 -0
  221. /package/dist/ui/assets/{global-db-B97_fwjD.js → global-db-DL3jdM9H.js} +0 -0
  222. /package/dist/ui/assets/{hash-B9Dtr1VK.js → hash-iitWbNjK.js} +0 -0
  223. /package/dist/ui/assets/{headers-AeYLn7L4.js → headers-qDMOQQGF.js} +0 -0
  224. /package/dist/ui/assets/{lick-manager-proxy-BnnMFbgv.js → lick-manager-proxy-1L0EGIWD.js} +0 -0
  225. /package/dist/ui/assets/{index-CvlDeETm.css → main-CvlDeETm.css} +0 -0
  226. /package/dist/ui/assets/{openai-Bf1npfRy.js → openai-BR_xAflc.js} +0 -0
  227. /package/dist/ui/assets/{page-storage-sync-CqMAh8jG.js → page-storage-sync-sv2ogNKh.js} +0 -0
  228. /package/dist/ui/assets/{pdfjs-DDDkZHZ4.js → pdfjs-CW51NNE6.js} +0 -0
  229. /package/dist/ui/assets/{rum-DCU8sePD.js → rum-z5wz4Dnj.js} +0 -0
  230. /package/dist/ui/assets/{sanitize-unicode-h0KEBmEw.js → sanitize-unicode-B1z_Y4Dq.js} +0 -0
  231. /package/dist/ui/assets/{sprinkle-bridge-channel-DojIojh7.js → sprinkle-bridge-channel-Bw5UaanD.js} +0 -0
  232. /package/dist/ui/assets/{sprinkle-bridge-channel-DJC5SGWr.js → sprinkle-bridge-channel-ChD0T07C.js} +0 -0
  233. /package/dist/ui/assets/{sprinkle-proxy-rF3NSOGq.js → sprinkle-proxy-D6wqmewK.js} +0 -0
  234. /package/dist/ui/assets/{src-BQRb5emh.js → src-DRmQ1wr-.js} +0 -0
  235. /package/dist/ui/assets/{xai-grok-errors-Bzn3oNvW.js → xai-grok-errors-BdY43UIn.js} +0 -0
  236. /package/dist/ui/assets/{xai-grok-errors-WbFsMZum.js → xai-grok-errors-C6VnD_MH.js} +0 -0
  237. /package/dist/ui/assets/{xai-grok-models-cvcIXmNM.js → xai-grok-models-BndZgIFZ.js} +0 -0
  238. /package/dist/ui/assets/{xai-grok-models-DMYWtapT.js → xai-grok-models-C9MIa-Aj.js} +0 -0
  239. /package/dist/ui/assets/{xterm-D8ldLLKi.js → xterm-DLCsxsB1.js} +0 -0
  240. /package/dist/ui/assets/{xterm-DhusGoAm.js → xterm-VndicwFp.js} +0 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=secrets-filter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets-filter.test.d.ts","sourceRoot":"","sources":["../../tests/secrets-filter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { filterSecretsEnv } from '../src/secrets-filter.js';
3
+ describe('filterSecretsEnv', () => {
4
+ it('strips E2B_API_KEY with various whitespace shapes', () => {
5
+ const input = [
6
+ 'ANTHROPIC_API_KEY=sk-test',
7
+ 'E2B_API_KEY=plain',
8
+ ' E2B_API_KEY=leading-space',
9
+ 'E2B_API_KEY =extra-space-before-eq',
10
+ 'E2B_API_KEY_DOMAINS=e2b.dev',
11
+ '\tE2B_API_KEY=tab-prefixed',
12
+ ].join('\n');
13
+ const out = filterSecretsEnv(input);
14
+ expect(out).toContain('ANTHROPIC_API_KEY=sk-test');
15
+ // All four E2B_API_KEY variants must be stripped:
16
+ expect(out).not.toContain('E2B_API_KEY=plain');
17
+ expect(out).not.toContain('E2B_API_KEY=leading-space');
18
+ expect(out).not.toContain('E2B_API_KEY=extra-space-before-eq');
19
+ expect(out).not.toContain('E2B_API_KEY_DOMAINS=e2b.dev');
20
+ expect(out).not.toContain('E2B_API_KEY=tab-prefixed');
21
+ });
22
+ it('preserves comments and empty lines', () => {
23
+ const input = '# important comment\n\nANTHROPIC_API_KEY=x\nE2B_API_KEY=strip\n';
24
+ const out = filterSecretsEnv(input);
25
+ expect(out).toContain('# important comment');
26
+ expect(out.split('\n').some((l) => l === '')).toBe(true);
27
+ expect(out).toContain('ANTHROPIC_API_KEY=x');
28
+ expect(out).not.toContain('E2B_API_KEY=strip');
29
+ });
30
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=start.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.test.d.ts","sourceRoot":"","sources":["../../tests/start.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,513 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { startCone, reserveSlot } from '../src/operations/start.js';
3
+ import { MemRegistry, makeFakeHandle, makeFakeSubstrate } from './fixtures/index.js';
4
+ // Specialized for startCone: handle stores files per-create, tracks kill state for list result.
5
+ function makeStartTestSubstrate(opts) {
6
+ const files = new Map();
7
+ let killed = false;
8
+ return {
9
+ id: 'e2b',
10
+ async create(_opts) {
11
+ const sandboxId = 'sbx-fake';
12
+ files.set('/tmp/slicc-join.json', opts.joinJson);
13
+ const handle = makeFakeHandle({ sandboxId });
14
+ return {
15
+ sandboxId: handle.sandboxId,
16
+ substrate: handle.substrate,
17
+ pause: handle.pause,
18
+ kill: async () => {
19
+ killed = true;
20
+ },
21
+ getInfo: handle.getInfo,
22
+ writeFile: handle.writeFile,
23
+ readFile: async (path) => {
24
+ const content = files.get(path);
25
+ if (!content)
26
+ throw new Error(`ENOENT ${path}`);
27
+ return content;
28
+ },
29
+ run: handle.run,
30
+ };
31
+ },
32
+ async connect() {
33
+ throw new Error('not used in startCone tests');
34
+ },
35
+ async list(_opts) {
36
+ if (killed)
37
+ return [];
38
+ return [
39
+ {
40
+ sandboxId: 'sbx-fake',
41
+ state: 'running',
42
+ metadata: {},
43
+ },
44
+ ];
45
+ },
46
+ async extendTimeout(_sandboxId, _ttlMs) {
47
+ // No-op for tests.
48
+ },
49
+ };
50
+ }
51
+ describe('reserveSlot', () => {
52
+ it('throws CAP_EXCEEDED when paused cap is at limit', async () => {
53
+ const registry = new MemRegistry();
54
+ // Seed CONE_CAP_PAUSED=2 paused cones in both registry and substrate.
55
+ // listCones reconciles them. No userId filter so all cones count.
56
+ for (let i = 0; i < 2; i++) {
57
+ await registry.append({
58
+ sandboxId: `s${i}`,
59
+ substrate: 'e2b',
60
+ createdAt: '',
61
+ lastSeen: '',
62
+ state: 'paused',
63
+ joinUrl: 'https://w',
64
+ });
65
+ }
66
+ const substrate = makeFakeSubstrate({
67
+ listResult: [
68
+ { sandboxId: 's0', state: 'paused', metadata: {} },
69
+ { sandboxId: 's1', state: 'paused', metadata: {} },
70
+ ],
71
+ });
72
+ await expect(reserveSlot({ substrate, registry }, {
73
+ // No userId — all cones count
74
+ metadata: {},
75
+ sliccVersion: 'test',
76
+ env: { CONE_CAP_RUNNING: '5', CONE_CAP_PAUSED: '2' },
77
+ })).rejects.toMatchObject({ code: 'CAP_EXCEEDED' });
78
+ });
79
+ });
80
+ describe('startCone', () => {
81
+ it('creates a sandbox, polls join.json, appends placeholder then updates registry, returns StartResult', async () => {
82
+ // Use a recent timestamp that will pass the minUpdatedAt check (5s skew margin)
83
+ const updatedAt = new Date().toISOString();
84
+ const substrate = makeStartTestSubstrate({
85
+ joinJson: JSON.stringify({
86
+ joinUrl: 'https://w/join/x',
87
+ trayId: 't-1',
88
+ updatedAt,
89
+ }),
90
+ });
91
+ const registry = new MemRegistry();
92
+ const result = await startCone({ substrate, registry }, {
93
+ envContents: 'ANTHROPIC_API_KEY=sk-x\nE2B_API_KEY=should-be-stripped',
94
+ workerBaseUrl: 'https://w',
95
+ sliccVersion: 'test',
96
+ name: 'smoke',
97
+ });
98
+ expect(result.joinUrl).toBe('https://w/join/x');
99
+ expect(result.name).toBe('smoke');
100
+ expect(result.sandboxId).toBe('sbx-fake');
101
+ // After completion, should have exactly one entry with the full data (placeholder updated)
102
+ const entries = await registry.list();
103
+ expect(entries).toHaveLength(1);
104
+ expect(entries[0]?.name).toBe('smoke');
105
+ expect(entries[0]?.state).toBe('running');
106
+ expect(entries[0]?.lastJoinUpdatedAt).toBe(updatedAt);
107
+ expect(entries[0]?.trayId).toBe('t-1');
108
+ expect(entries[0]?.substrate).toBe('e2b');
109
+ expect(entries[0]?.joinUrl).toBe('https://w/join/x');
110
+ });
111
+ it('throws SANDBOX_NOT_READY when pollCloudStatus times out and cleans up placeholder', async () => {
112
+ const substrate = makeStartTestSubstrate({ joinJson: '{}' }); // no joinUrl → poll never returns
113
+ const registry = new MemRegistry();
114
+ await expect(startCone({ substrate, registry }, {
115
+ envContents: '',
116
+ workerBaseUrl: 'https://w',
117
+ sliccVersion: 'test',
118
+ pollTimeoutMs: 200,
119
+ pollIntervalMs: 50,
120
+ })).rejects.toMatchObject({ name: 'CloudError', code: 'SANDBOX_NOT_READY' });
121
+ // Registry should have no entries (placeholder was removed during cleanup).
122
+ expect(await registry.list()).toHaveLength(0);
123
+ // Substrate should have no sandboxes (killed during cleanup).
124
+ expect(await substrate.list()).toHaveLength(0);
125
+ });
126
+ it('includes stderr tail in error message when poll fails', async () => {
127
+ // Create a substrate that seeds stderr but no join.json
128
+ const files = new Map();
129
+ files.set('/tmp/slicc-stderr.log', 'Error: Failed to launch\n cause: missing deps\nStack trace...');
130
+ const substrate = {
131
+ id: 'e2b',
132
+ async create(_opts) {
133
+ const handle = makeFakeHandle({ sandboxId: 'sbx-err' });
134
+ return {
135
+ sandboxId: handle.sandboxId,
136
+ substrate: handle.substrate,
137
+ pause: handle.pause,
138
+ kill: handle.kill,
139
+ getInfo: handle.getInfo,
140
+ writeFile: handle.writeFile,
141
+ readFile: async (path) => {
142
+ const content = files.get(path);
143
+ if (!content)
144
+ throw new Error(`ENOENT ${path}`);
145
+ return content;
146
+ },
147
+ run: handle.run,
148
+ };
149
+ },
150
+ async connect() {
151
+ throw new Error('not used');
152
+ },
153
+ async list(_opts) {
154
+ return [];
155
+ },
156
+ async extendTimeout(_sandboxId, _ttlMs) {
157
+ // No-op for tests.
158
+ },
159
+ };
160
+ const registry = new MemRegistry();
161
+ await expect(startCone({ substrate, registry }, {
162
+ envContents: '',
163
+ workerBaseUrl: 'https://w',
164
+ sliccVersion: 'test',
165
+ pollTimeoutMs: 200,
166
+ pollIntervalMs: 50,
167
+ })).rejects.toThrow(/missing deps/);
168
+ });
169
+ it('appends placeholder entry to registry BEFORE pollCloudStatus runs', async () => {
170
+ // This test protects against the orphan-recovery race: concurrent /list-cones
171
+ // calls should see the new sandbox in the registry (pass 1) during the slow
172
+ // poll window, NOT go through orphan recovery (pass 2).
173
+ const updatedAt = new Date().toISOString();
174
+ let pollStarted = false;
175
+ let entryPresentAtPollStart = false;
176
+ const registry = new MemRegistry();
177
+ // Create a custom substrate that captures the registry state when readFile
178
+ // is first called (which happens inside pollCloudStatus).
179
+ const substrate = {
180
+ id: 'e2b',
181
+ async create(_opts) {
182
+ const handle = makeFakeHandle({ sandboxId: 'sbx-race' });
183
+ return {
184
+ sandboxId: handle.sandboxId,
185
+ substrate: handle.substrate,
186
+ pause: handle.pause,
187
+ kill: handle.kill,
188
+ getInfo: handle.getInfo,
189
+ writeFile: handle.writeFile,
190
+ readFile: async (path) => {
191
+ if (path === '/tmp/slicc-join.json' && !pollStarted) {
192
+ pollStarted = true;
193
+ // Check if the registry already has an entry for this sandbox
194
+ const entries = await registry.list();
195
+ entryPresentAtPollStart = entries.some((e) => e.sandboxId === 'sbx-race');
196
+ }
197
+ if (path === '/tmp/slicc-join.json') {
198
+ return JSON.stringify({
199
+ joinUrl: 'https://w/join/race',
200
+ trayId: 't-race',
201
+ updatedAt,
202
+ });
203
+ }
204
+ throw new Error(`ENOENT ${path}`);
205
+ },
206
+ run: handle.run,
207
+ };
208
+ },
209
+ async connect() {
210
+ throw new Error('not used');
211
+ },
212
+ async list(_opts) {
213
+ return [];
214
+ },
215
+ async extendTimeout(_sandboxId, _ttlMs) {
216
+ // No-op for tests.
217
+ },
218
+ };
219
+ await startCone({ substrate, registry }, {
220
+ envContents: '',
221
+ workerBaseUrl: 'https://w',
222
+ sliccVersion: 'test',
223
+ });
224
+ // The placeholder should have been present in the registry BEFORE pollCloudStatus
225
+ // started reading the file.
226
+ expect(entryPresentAtPollStart).toBe(true);
227
+ // After completion, verify the entry was updated with the real joinUrl
228
+ const entries = await registry.list();
229
+ expect(entries).toHaveLength(1);
230
+ expect(entries[0]?.sandboxId).toBe('sbx-race');
231
+ expect(entries[0]?.joinUrl).toBe('https://w/join/race');
232
+ });
233
+ it('rejects stale /tmp/slicc-join.json from template snapshot and waits for fresh one', async () => {
234
+ // Simulate the template-baked stale file → fresh file transition.
235
+ // First read returns stale (updatedAt 1 hour ago), second returns fresh (updatedAt now).
236
+ const staleUpdatedAt = new Date(Date.now() - 3600_000).toISOString();
237
+ const freshUpdatedAt = new Date().toISOString();
238
+ const files = new Map();
239
+ let readCount = 0;
240
+ files.set('/tmp/slicc-join.json', JSON.stringify({
241
+ joinUrl: 'https://w/join/stale',
242
+ trayId: 't-stale',
243
+ updatedAt: staleUpdatedAt,
244
+ }));
245
+ const substrate = {
246
+ id: 'e2b',
247
+ async create(_opts) {
248
+ const handle = makeFakeHandle({ sandboxId: 'sbx-stale' });
249
+ return {
250
+ sandboxId: handle.sandboxId,
251
+ substrate: handle.substrate,
252
+ pause: handle.pause,
253
+ kill: handle.kill,
254
+ getInfo: handle.getInfo,
255
+ writeFile: handle.writeFile,
256
+ readFile: async (path) => {
257
+ if (path === '/tmp/slicc-join.json') {
258
+ readCount++;
259
+ if (readCount === 1) {
260
+ // First read: stale template-baked file
261
+ return JSON.stringify({
262
+ joinUrl: 'https://w/join/stale',
263
+ trayId: 't-stale',
264
+ updatedAt: staleUpdatedAt,
265
+ });
266
+ }
267
+ else {
268
+ // Second+ read: fresh file written by node-server
269
+ return JSON.stringify({
270
+ joinUrl: 'https://w/join/fresh',
271
+ trayId: 't-fresh',
272
+ updatedAt: freshUpdatedAt,
273
+ });
274
+ }
275
+ }
276
+ const content = files.get(path);
277
+ if (!content)
278
+ throw new Error(`ENOENT ${path}`);
279
+ return content;
280
+ },
281
+ run: handle.run,
282
+ };
283
+ },
284
+ async connect() {
285
+ throw new Error('not used');
286
+ },
287
+ async list(_opts) {
288
+ return [];
289
+ },
290
+ async extendTimeout(_sandboxId, _ttlMs) {
291
+ // No-op for tests.
292
+ },
293
+ };
294
+ const registry = new MemRegistry();
295
+ const result = await startCone({ substrate, registry }, {
296
+ envContents: '',
297
+ workerBaseUrl: 'https://w',
298
+ sliccVersion: 'test',
299
+ pollTimeoutMs: 2000,
300
+ pollIntervalMs: 50,
301
+ });
302
+ // Should have waited past the stale read and returned the fresh one
303
+ expect(result.joinUrl).toBe('https://w/join/fresh');
304
+ expect(readCount).toBeGreaterThan(1); // Proves the stale read was rejected
305
+ // After update, should have exactly one entry with the fresh data
306
+ const entries = await registry.list();
307
+ expect(entries).toHaveLength(1);
308
+ expect(entries[0]?.trayId).toBe('t-fresh');
309
+ expect(entries[0]?.lastJoinUpdatedAt).toBe(freshUpdatedAt);
310
+ expect(entries[0]?.joinUrl).toBe('https://w/join/fresh');
311
+ });
312
+ it('reserveSlot appends a placeholder entry that counts toward cap', async () => {
313
+ // Use makeFakeSubstrate with empty listResult so reserveSlot doesn't see
314
+ // phantom sandboxes from the substrate
315
+ const substrate = makeFakeSubstrate({ listResult: [] });
316
+ const registry = new MemRegistry();
317
+ const { reservationId } = await reserveSlot({ substrate, registry }, {
318
+ userId: 'u1',
319
+ name: 'reserved',
320
+ metadata: { userId: 'u1' },
321
+ sliccVersion: 'test',
322
+ env: { CONE_CAP_RUNNING: '1', CONE_CAP_PAUSED: '5' },
323
+ });
324
+ expect(reservationId).toMatch(/^pending-/);
325
+ // Verify the placeholder was appended
326
+ const entries = await registry.list();
327
+ expect(entries).toHaveLength(1);
328
+ expect(entries[0]?.sandboxId).toBe(reservationId);
329
+ expect(entries[0]?.name).toBe('reserved');
330
+ expect(entries[0]?.state).toBe('reserved');
331
+ expect(entries[0]?.joinUrl).toBe('');
332
+ // Verify a second reservation hits CAP_EXCEEDED
333
+ await expect(reserveSlot({ substrate, registry }, {
334
+ userId: 'u1',
335
+ name: 'second',
336
+ metadata: { userId: 'u1' },
337
+ sliccVersion: 'test',
338
+ env: { CONE_CAP_RUNNING: '1', CONE_CAP_PAUSED: '5' },
339
+ })).rejects.toMatchObject({ name: 'CloudError', code: 'CAP_EXCEEDED' });
340
+ });
341
+ it('reserveSlot throws NAME_TAKEN when name conflicts with existing entry', async () => {
342
+ // Pre-populate substrate with the existing sandbox so listCones sees it as live
343
+ const substrate = makeFakeSubstrate({
344
+ listResult: [
345
+ {
346
+ sandboxId: 'sbx-existing',
347
+ name: 'existing',
348
+ state: 'running',
349
+ metadata: { userId: 'u1' },
350
+ },
351
+ ],
352
+ });
353
+ const registry = new MemRegistry();
354
+ // Pre-populate with an existing entry
355
+ await registry.append({
356
+ substrate: 'e2b',
357
+ sandboxId: 'sbx-existing',
358
+ name: 'existing',
359
+ createdAt: new Date().toISOString(),
360
+ lastSeen: new Date().toISOString(),
361
+ state: 'running',
362
+ joinUrl: 'https://w/join/existing',
363
+ metadata: { userId: 'u1' },
364
+ });
365
+ await expect(reserveSlot({ substrate, registry }, {
366
+ userId: 'u1',
367
+ name: 'existing',
368
+ metadata: { userId: 'u1' },
369
+ sliccVersion: 'test',
370
+ env: { CONE_CAP_RUNNING: '5', CONE_CAP_PAUSED: '5' },
371
+ })).rejects.toMatchObject({ name: 'CloudError', code: 'NAME_TAKEN' });
372
+ });
373
+ it('startCone with reservationId updates the placeholder entry', async () => {
374
+ const updatedAt = new Date().toISOString();
375
+ // For startCone we can use makeStartTestSubstrate since we're actually creating
376
+ const substrate = makeStartTestSubstrate({
377
+ joinJson: JSON.stringify({
378
+ joinUrl: 'https://w/join/real',
379
+ trayId: 't-real',
380
+ updatedAt,
381
+ }),
382
+ });
383
+ const registry = new MemRegistry();
384
+ // First reserve a slot — use a clean substrate for this phase
385
+ const reserveSubstrate = makeFakeSubstrate({ listResult: [] });
386
+ const { reservationId } = await reserveSlot({ substrate: reserveSubstrate, registry }, {
387
+ userId: 'u1',
388
+ name: 'reserved',
389
+ metadata: { userId: 'u1' },
390
+ sliccVersion: 'test',
391
+ env: { CONE_CAP_RUNNING: '5', CONE_CAP_PAUSED: '5' },
392
+ });
393
+ // Verify placeholder exists
394
+ let entries = await registry.list();
395
+ expect(entries).toHaveLength(1);
396
+ expect(entries[0]?.sandboxId).toBe(reservationId);
397
+ // Now call startCone with the reservation (use the real substrate for create)
398
+ const result = await startCone({ substrate, registry }, {
399
+ reservationId,
400
+ envContents: '',
401
+ workerBaseUrl: 'https://w',
402
+ sliccVersion: 'test',
403
+ name: 'reserved',
404
+ metadata: { userId: 'u1' },
405
+ });
406
+ expect(result.sandboxId).toBe('sbx-fake');
407
+ expect(result.joinUrl).toBe('https://w/join/real');
408
+ // Verify the placeholder was replaced with the real entry
409
+ entries = await registry.list();
410
+ expect(entries).toHaveLength(1);
411
+ expect(entries[0]?.sandboxId).toBe('sbx-fake');
412
+ expect(entries[0]?.name).toBe('reserved');
413
+ expect(entries[0]?.joinUrl).toBe('https://w/join/real');
414
+ });
415
+ it('removes reservation when substrate.create fails', async () => {
416
+ const registry = new MemRegistry();
417
+ // Seed a reservation in the registry (as if reserveSlot was called):
418
+ const reservationId = 'pending-test-uuid';
419
+ await registry.append({
420
+ sandboxId: reservationId,
421
+ substrate: 'e2b',
422
+ createdAt: '',
423
+ lastSeen: '',
424
+ state: 'reserved',
425
+ joinUrl: '',
426
+ });
427
+ // Substrate that fails on create
428
+ const substrate = {
429
+ id: 'e2b',
430
+ async create() {
431
+ throw new Error('e2b boom');
432
+ },
433
+ async connect() {
434
+ throw new Error('not used');
435
+ },
436
+ async list() {
437
+ return [];
438
+ },
439
+ async extendTimeout() { },
440
+ };
441
+ await expect(startCone({ substrate, registry }, {
442
+ reservationId,
443
+ envContents: '',
444
+ workerBaseUrl: 'https://w',
445
+ sliccVersion: 'test',
446
+ })).rejects.toThrow('e2b boom');
447
+ expect(registry.entries.find((e) => e.sandboxId === reservationId)).toBeUndefined();
448
+ });
449
+ it('removes real entry when pollCloudStatus fails after sandbox swap', async () => {
450
+ const registry = new MemRegistry();
451
+ const reservationId = 'pending-test-uuid-2';
452
+ await registry.append({
453
+ sandboxId: reservationId,
454
+ substrate: 'e2b',
455
+ createdAt: '',
456
+ lastSeen: '',
457
+ state: 'reserved',
458
+ joinUrl: '',
459
+ });
460
+ let killCalled = false;
461
+ const realSandboxId = 'sbx-created';
462
+ // Substrate creates successfully but readFile never returns joinUrl (poll fails)
463
+ const substrate = {
464
+ id: 'e2b',
465
+ async create() {
466
+ const handle = makeFakeHandle({ sandboxId: realSandboxId });
467
+ return {
468
+ sandboxId: realSandboxId,
469
+ substrate: handle.substrate,
470
+ pause: handle.pause,
471
+ kill: async () => {
472
+ killCalled = true;
473
+ },
474
+ getInfo: handle.getInfo,
475
+ writeFile: handle.writeFile,
476
+ readFile: async (path) => {
477
+ if (path === '/tmp/slicc-join.json') {
478
+ // Return stale data that fails minUpdatedAt check
479
+ return JSON.stringify({
480
+ joinUrl: 'https://w/join/stale',
481
+ trayId: 't-stale',
482
+ updatedAt: '2020-01-01T00:00:00.000Z',
483
+ });
484
+ }
485
+ if (path === '/tmp/slicc-stderr.log')
486
+ return 'no logs';
487
+ throw new Error(`ENOENT ${path}`);
488
+ },
489
+ run: handle.run,
490
+ };
491
+ },
492
+ async connect() {
493
+ throw new Error('not used');
494
+ },
495
+ async list() {
496
+ return [];
497
+ },
498
+ async extendTimeout() { },
499
+ };
500
+ await expect(startCone({ substrate, registry }, {
501
+ reservationId,
502
+ envContents: '',
503
+ workerBaseUrl: 'https://w',
504
+ sliccVersion: 'test',
505
+ pollTimeoutMs: 200,
506
+ pollIntervalMs: 50,
507
+ })).rejects.toMatchObject({ code: 'SANDBOX_NOT_READY' });
508
+ // Assert: reservation was removed, real entry was removed, sandbox was killed
509
+ expect(registry.entries.find((e) => e.sandboxId === reservationId)).toBeUndefined();
510
+ expect(registry.entries.find((e) => e.sandboxId === realSandboxId)).toBeUndefined();
511
+ expect(killCalled).toBe(true);
512
+ });
513
+ });
@@ -36,6 +36,7 @@ export declare function buildChromeLaunchArgs(options: {
36
36
  cdpPort: number;
37
37
  launchUrl: string;
38
38
  profile: ChromeLaunchProfile;
39
+ hosted?: boolean;
39
40
  }): string[];
40
41
  /**
41
42
  * Walk up from a Chrome executable path
@@ -120,6 +120,9 @@ export function buildChromeLaunchArgs(options) {
120
120
  args.push(`--disable-extensions-except=${options.profile.extensionPath}`);
121
121
  args.push(`--load-extension=${options.profile.extensionPath}`);
122
122
  }
123
+ if (options.hosted) {
124
+ args.push('--headless=new', '--no-sandbox', '--disable-dev-shm-usage', '--disable-gpu', '--font-render-hinting=none');
125
+ }
123
126
  args.push(options.launchUrl);
124
127
  return args;
125
128
  }
@@ -0,0 +1,34 @@
1
+ import type { SubstrateId } from '../_cloud_core/src/index.js';
2
+ export type ParsedCloudArgs = {
3
+ subcommand: 'start';
4
+ args: {
5
+ substrate: SubstrateId;
6
+ name?: string;
7
+ envFile?: string;
8
+ };
9
+ } | {
10
+ subcommand: 'list';
11
+ args: {
12
+ substrate: SubstrateId;
13
+ };
14
+ } | {
15
+ subcommand: 'pause';
16
+ args: {
17
+ substrate: SubstrateId;
18
+ query: string;
19
+ };
20
+ } | {
21
+ subcommand: 'resume';
22
+ args: {
23
+ substrate: SubstrateId;
24
+ query: string;
25
+ envFile?: string;
26
+ };
27
+ } | {
28
+ subcommand: 'kill';
29
+ args: {
30
+ substrate: SubstrateId;
31
+ query: string;
32
+ };
33
+ };
34
+ export declare function parseCloudArgs(argv: string[]): ParsedCloudArgs | null;