sliccy 6.87.2 → 6.88.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 (349) hide show
  1. package/README.md +1 -1
  2. package/dist/node-server/_shared/index.d.ts +1 -0
  3. package/dist/node-server/_shared/index.d.ts.map +1 -1
  4. package/dist/node-server/_shared/index.js +1 -0
  5. package/dist/node-server/_shared/index.js.map +1 -1
  6. package/dist/node-server/_shared/loopback.d.ts +18 -0
  7. package/dist/node-server/_shared/loopback.d.ts.map +1 -0
  8. package/dist/node-server/_shared/loopback.js +41 -0
  9. package/dist/node-server/_shared/loopback.js.map +1 -0
  10. package/dist/node-server/bridge-security.d.ts +4 -1
  11. package/dist/node-server/bridge-security.js +6 -16
  12. package/dist/node-server/cloud-status.d.ts +3 -0
  13. package/dist/node-server/cloud-status.js +6 -2
  14. package/dist/node-server/hostfs.d.ts +58 -0
  15. package/dist/node-server/hostfs.js +257 -0
  16. package/dist/node-server/index.js +10 -0
  17. package/dist/node-server/routes/fetch-proxy.js +3 -18
  18. package/dist/node-server/runtime-flags.d.ts +22 -0
  19. package/dist/node-server/runtime-flags.js +78 -2
  20. package/dist/ui/.vite/manifest.json +508 -437
  21. package/dist/ui/assets/CLAUDE-4LHXSyPA.js +1 -0
  22. package/dist/ui/assets/CLAUDE-Bio4HPGK.js +1 -0
  23. package/dist/ui/assets/MEMORY-6FXnIBfJ.js +135 -0
  24. package/dist/ui/assets/SKILL-BKUxKc7f.js +296 -0
  25. package/dist/ui/assets/SKILL-BKyxMoME.js +1 -0
  26. package/dist/ui/assets/SKILL-BcELX5TL.js +1 -0
  27. package/dist/ui/assets/SKILL-Bd5ykLEh.js +1 -0
  28. package/dist/ui/assets/SKILL-Bt-RhG0L.js +1 -0
  29. package/dist/ui/assets/SKILL-CED8RXQP.js +69 -0
  30. package/dist/ui/assets/SKILL-CNdAIhbb.js +1 -0
  31. package/dist/ui/assets/SKILL-CcMg6eqt.js +1 -0
  32. package/dist/ui/assets/SKILL-Ch-cOl61.js +1 -0
  33. package/dist/ui/assets/SKILL-CkfptFag.js +132 -0
  34. package/dist/ui/assets/SKILL-Ckg2XbSL.js +114 -0
  35. package/dist/ui/assets/SKILL-D40-t9w0.js +57 -0
  36. package/dist/ui/assets/SKILL-DFKKFkzD.js +96 -0
  37. package/dist/ui/assets/SKILL-DJ815vTN.js +62 -0
  38. package/dist/ui/assets/SKILL-DLXzwsY4.js +1 -0
  39. package/dist/ui/assets/SKILL-DXIigmDy.js +35 -0
  40. package/dist/ui/assets/SKILL-DfSluXpV.js +385 -0
  41. package/dist/ui/assets/SKILL-DhKtVqb-.js +1 -0
  42. package/dist/ui/assets/SKILL-FnBxPcDX.js +1 -0
  43. package/dist/ui/assets/SKILL-HEHb9hIB.js +1 -0
  44. package/dist/ui/assets/SKILL-i1NMDKwT.js +1 -0
  45. package/dist/ui/assets/SKILL-oOIS8LAm.js +1 -0
  46. package/dist/ui/assets/{account-store-u5knhoCx.js → account-store-BLu0_ipL.js} +2 -2
  47. package/dist/ui/assets/{account-store-D1f8dn0G.js → account-store-l8BmmoRx.js} +4 -4
  48. package/dist/ui/assets/adobe-Caluo3Vg.js +2 -0
  49. package/dist/ui/assets/adobe-Cj2iYsHq.js +1 -0
  50. package/dist/ui/assets/{angular-html-Cm4-xod0.js → angular-html-aPuBvESs.js} +1 -1
  51. package/dist/ui/assets/{angular-ts-Dopuir71.js → angular-ts-ocjSXnvf.js} +1 -1
  52. package/dist/ui/assets/anthropic-messages-CpSojOI8.js +39 -0
  53. package/dist/ui/assets/anthropic-messages-DbPJ2ji9.js +39 -0
  54. package/dist/ui/assets/api-endpoint-C00IT5T9.js +1 -0
  55. package/dist/ui/assets/api-endpoint-GRCyib6X.js +1 -0
  56. package/dist/ui/assets/{apply-layout-g9ha9fDb.js → apply-layout-lJ2Uyc3p.js} +1 -1
  57. package/dist/ui/assets/{apps-D2giAoeX.js → apps-BRi5S2KV.js} +1 -1
  58. package/dist/ui/assets/{astro-E_b8esPp.js → astro-go1PgQEf.js} +1 -1
  59. package/dist/ui/assets/auto-mount-table-CdyPAwVL.js +1 -0
  60. package/dist/ui/assets/{azure-openai-DYlB7tTf.js → azure-openai-DtPDwGAY.js} +2 -2
  61. package/dist/ui/assets/azure-openai-responses-BcoOaRCx.js +1 -0
  62. package/dist/ui/assets/azure-openai-responses-DUMDrZ29.js +1 -0
  63. package/dist/ui/assets/{azure-openai-CB7Ox9_p.js → azure-openai-xFuHu_hU.js} +2 -2
  64. package/dist/ui/assets/backend-hostfs-Com-zF5W.js +1 -0
  65. package/dist/ui/assets/backend-hostfs-bQQx-S0W.js +1 -0
  66. package/dist/ui/assets/bedrock-camp-BcJEC3Pg.js +1 -0
  67. package/dist/ui/assets/bedrock-camp-LeceEQbU.js +1 -0
  68. package/dist/ui/assets/bedrock-camp-compat-CYnC9BQI.js +1 -0
  69. package/dist/ui/assets/bedrock-camp-compat-CgBMwna8.js +1 -0
  70. package/dist/ui/assets/{blade-mj2TcBTp.js → blade-DPPr6MF0.js} +1 -1
  71. package/dist/ui/assets/catppuccin-frappe-C9Q5zVZY.js +1 -0
  72. package/dist/ui/assets/catppuccin-latte-CtsyrtPq.js +1 -0
  73. package/dist/ui/assets/catppuccin-macchiato-R8nAf1vR.js +1 -0
  74. package/dist/ui/assets/catppuccin-mocha-DjuaAJKi.js +1 -0
  75. package/dist/ui/assets/cerebras-BKhMaWSl.js +1 -0
  76. package/dist/ui/assets/cerebras-CCLa0xVH.js +1 -0
  77. package/dist/ui/assets/chime-CPc6qSh5.js +1 -0
  78. package/dist/ui/assets/claude-model-version-Csn7RPVg.js +1 -0
  79. package/dist/ui/assets/claude-model-version-DoVrYsKi.js +2 -0
  80. package/dist/ui/assets/{client-BTUV7dbh.js → client-DVC0x03n.js} +1 -1
  81. package/dist/ui/assets/{composer-speech-SNeD5SER.js → composer-speech-Cy4g3lh3.js} +1 -1
  82. package/dist/ui/assets/connect-llm-FevTa-aV.js +561 -0
  83. package/dist/ui/assets/{connect-surface-NkMUeXbQ.js → connect-surface-T7iCJFeB.js} +1 -1
  84. package/dist/ui/assets/cpp-Ct9pQPqT.js +1 -0
  85. package/dist/ui/assets/{css-vJJohHMc.js → css-DlBQoFxe.js} +1 -1
  86. package/dist/ui/assets/discovery-preference-__0HPYJC.js +1 -0
  87. package/dist/ui/assets/dist-B4LJzMVB.js +1547 -0
  88. package/dist/ui/assets/{ensure-speech-assets-DvFwJX-M.js → ensure-speech-assets-CKwQ54O1.js} +1 -1
  89. package/dist/ui/assets/float-topology-DiK91BlA.js +1 -0
  90. package/dist/ui/assets/{follower-navigate-watcher-CNC7ybEv.js → follower-navigate-watcher-Dz-52eZY.js} +1 -1
  91. package/dist/ui/assets/fs-1btyYJVn.js +1 -0
  92. package/dist/ui/assets/fs-BYtJQhvh.js +2 -0
  93. package/dist/ui/assets/github-BHL_hKU_.js +2 -0
  94. package/dist/ui/assets/github-copilot-CZorsYUj.js +1 -0
  95. package/dist/ui/assets/github-copilot-DVmzgGYz.js +2 -0
  96. package/dist/ui/assets/github-fX2kuECo.js +1 -0
  97. package/dist/ui/assets/{github-install-C7YXkDBT.js → github-install-DVzD1asQ.js} +1 -1
  98. package/dist/ui/assets/{github-zip-DVWjYLIh.js → github-zip-5ekKl7Z0.js} +1 -1
  99. package/dist/ui/assets/{go-BJwz_mda.js → go-rLFTqkRN.js} +1 -1
  100. package/dist/ui/assets/google-generative-ai-Dxo91M3n.js +1 -0
  101. package/dist/ui/assets/google-generative-ai-Rjh7hNBV.js +1 -0
  102. package/dist/ui/assets/{google-shared-BMJ_JErv.js → google-shared-CzJgTu-P.js} +3 -3
  103. package/dist/ui/assets/{google-shared-YqcyR4cm.js → google-shared-DQJPCU3d.js} +3 -3
  104. package/dist/ui/assets/google-vertex-61Jj0dk6.js +1 -0
  105. package/dist/ui/assets/google-vertex-DEwkNZJm.js +1 -0
  106. package/dist/ui/assets/{haml-DboNpPfQ.js → haml-Bqgi1Cau.js} +1 -1
  107. package/dist/ui/assets/{handlebars-Bv_jLwHk.js → handlebars-JgcNzdBj.js} +1 -1
  108. package/dist/ui/assets/{hear-D33CHppO.js → hear-BqNAK8-P.js} +1 -1
  109. package/dist/ui/assets/{horizon-bright-Br1oVSNq.js → horizon-bright-DSNQnXHK.js} +1 -1
  110. package/dist/ui/assets/{host-command-G_JIdBPR.js → host-command-C3cIKdbE.js} +1 -1
  111. package/dist/ui/assets/{html-BLkwJ0Yd.js → html-BsvMqTlf.js} +1 -1
  112. package/dist/ui/assets/{html-derivative-B3p5VrMH.js → html-derivative-D9FvRNj4.js} +1 -1
  113. package/dist/ui/assets/icon-example-LUkiEXyS.js +111 -0
  114. package/dist/ui/assets/{jinja-BeFOxtqS.js → jinja-CixBDh_U.js} +1 -1
  115. package/dist/ui/assets/{js-realm-worker-Ymi_bwDP.js → js-realm-worker-iDrigwwJ.js} +1 -1
  116. package/dist/ui/assets/jsh-runtime-extensions-DpVq60Gw.js +1 -0
  117. package/dist/ui/assets/julia-B5NbrcUp.js +1 -0
  118. package/dist/ui/assets/kanagawa-dragon-Bozd7klA.js +1 -0
  119. package/dist/ui/assets/kanagawa-lotus-BmuOG9ZW.js +1 -0
  120. package/dist/ui/assets/kanagawa-wave-BML5mF2J.js +1 -0
  121. package/dist/ui/assets/{kernel-worker-CJu5HqlT.js → kernel-worker-BdKtpNzV.js} +614 -4395
  122. package/dist/ui/assets/legacy-api-aliases-BnRqMAef.js +1 -0
  123. package/dist/ui/assets/legacy-api-aliases-oJPAvhVV.js +1 -0
  124. package/dist/ui/assets/{lick-urls-AW0BSaf4.js → lick-urls-DcXOqXGm.js} +1 -1
  125. package/dist/ui/assets/{lick-ws-bridge-DiPcVRfN.js → lick-ws-bridge-CnkYvHKI.js} +1 -1
  126. package/dist/ui/assets/{lick-ws-bridge-CWRES2H2.js → lick-ws-bridge-DOJW_mZp.js} +1 -1
  127. package/dist/ui/assets/loader-B23_5sFw.js +4 -0
  128. package/dist/ui/assets/{local-llm-CwFpBJ4H.js → local-llm-BoLsVU6D.js} +1 -1
  129. package/dist/ui/assets/{local-llm-C0c86vuh.js → local-llm-aZ3BO7wK.js} +1 -1
  130. package/dist/ui/assets/loopback-2H1kMO8T.js +1 -0
  131. package/dist/ui/assets/main-CSh1z5qo.js +22 -0
  132. package/dist/ui/assets/{marko-C3klgjEa.js → marko-DYWPPmCl.js} +1 -1
  133. package/dist/ui/assets/mdc-Cno1UUUH.js +1 -0
  134. package/dist/ui/assets/mistral-conversations-BtaPxrK1.js +4 -0
  135. package/dist/ui/assets/mistral-conversations-CDLVw-9i.js +4 -0
  136. package/dist/ui/assets/{transform-messages-DEFauvrq.js → models-4WTk3EBD.js} +1 -1
  137. package/dist/ui/assets/{transform-messages-N_eMsP2M.js → models-BSkXF4T6.js} +1 -1
  138. package/dist/ui/assets/monokai-B_bV9PQ9.js +1 -0
  139. package/dist/ui/assets/mount-BCaA8NF3.js +1 -0
  140. package/dist/ui/assets/mount-ICXjya6b.js +2 -0
  141. package/dist/ui/assets/{mount-bridge-client-4blXuJO1.js → mount-bridge-client-DZE6sHdr.js} +1 -1
  142. package/dist/ui/assets/mount-recovery-CtadSXiq.js +2 -0
  143. package/dist/ui/assets/new-session-CCcPVim0.js +2 -0
  144. package/dist/ui/assets/oauth-bootstrap-CJ7pyk8I.js +2 -0
  145. package/dist/ui/assets/oauth-service-CTntqv0R.js +1 -0
  146. package/dist/ui/assets/oauth-service-Uk8UIb05.js +1 -0
  147. package/dist/ui/assets/openai-codex-C7WXAsyq.js +1 -0
  148. package/dist/ui/assets/openai-codex-DJHh6O0O.js +1 -0
  149. package/dist/ui/assets/openai-codex-responses-CPOJeFUY.js +7 -0
  150. package/dist/ui/assets/openai-codex-responses-jQR19NyX.js +7 -0
  151. package/dist/ui/assets/openai-completions-DGOcowq8.js +5 -0
  152. package/dist/ui/assets/openai-completions-DGZFJo5D.js +5 -0
  153. package/dist/ui/assets/openai-responses-CDTdSIhv.js +1 -0
  154. package/dist/ui/assets/openai-responses-bnETPgx9.js +1 -0
  155. package/dist/ui/assets/{openai-responses-shared-DxcsuzHF.js → openai-responses-shared-ChgvRZ74.js} +5 -5
  156. package/dist/ui/assets/{openai-responses-shared-DhnqxYC9.js → openai-responses-shared-DqJbHrek.js} +5 -5
  157. package/dist/ui/assets/openrouter-CIXJV3ar.js +1 -0
  158. package/dist/ui/assets/openrouter-CbIgawBs.js +1 -0
  159. package/dist/ui/assets/{openrouter-oauth-578SWfOt.js → openrouter-oauth-CfwEmxEv.js} +1 -1
  160. package/dist/ui/assets/{openrouter-oauth-BeOk-ba4.js → openrouter-oauth-ZehYXklO.js} +1 -1
  161. package/dist/ui/assets/{page-approval-service-Bbc3_KdK.js → page-approval-service-BsXoPdFJ.js} +1 -1
  162. package/dist/ui/assets/panel-rpc-handlers-Bg0_q2j9.js +2 -0
  163. package/dist/ui/assets/{panelize-shell-BRldzPxv.js → panelize-shell-DG3fFAS4.js} +1 -1
  164. package/dist/ui/assets/patterns-ChiGbijt.js +171 -0
  165. package/dist/ui/assets/php-m5Ug_San.js +1 -0
  166. package/dist/ui/assets/port-bridge-client-BhmNRlRv.js +2 -0
  167. package/dist/ui/assets/port-bridge-client-Bz2N1tvn.js +1 -0
  168. package/dist/ui/assets/{provider-qCqf7_uc.js → provider-1dH_J0Ky.js} +2 -2
  169. package/dist/ui/assets/{provider-B5MTJuhf.js → provider-CCer_iKN.js} +1 -1
  170. package/dist/ui/assets/{provider-settings-NcM2Npzg.js → provider-settings-DKXi1uSi.js} +1 -1
  171. package/dist/ui/assets/provider-settings-DZxqnVAO.js +2 -0
  172. package/dist/ui/assets/{provider-store-access-BlHUi5MH.js → provider-store-access-BthQZUzO.js} +2 -2
  173. package/dist/ui/assets/provider-store-access-NzVfMvPw.js +1 -0
  174. package/dist/ui/assets/providers-D8GPTe3s.js +2 -0
  175. package/dist/ui/assets/providers-DdfpdKUf.js +1 -0
  176. package/dist/ui/assets/proxied-fetch-BGeNrvQ4.js +2 -0
  177. package/dist/ui/assets/proxied-fetch-Co-pb0x0.js +1 -0
  178. package/dist/ui/assets/{pug-BPcX_o8k.js → pug-B4bk2kWf.js} +1 -1
  179. package/dist/ui/assets/quick-llm-DscHMm6M.js +1 -0
  180. package/dist/ui/assets/r-C5FwQflr.js +1 -0
  181. package/dist/ui/assets/{recovery-screen-CC3JYs-j.js → recovery-screen-CmxX9RlA.js} +1 -1
  182. package/dist/ui/assets/red-DX1BQOs8.js +1 -0
  183. package/dist/ui/assets/{redirect-uri-Cz0-DXMU.js → redirect-uri-CSXbRzUU.js} +1 -1
  184. package/dist/ui/assets/rose-pine-aMsaMD1D.js +1 -0
  185. package/dist/ui/assets/rose-pine-dawn-8PwUyIlP.js +1 -0
  186. package/dist/ui/assets/rose-pine-moon-DO-qXg-I.js +1 -0
  187. package/dist/ui/assets/{scss-0nEf0IT-.js → scss-BaZL6t2Y.js} +1 -1
  188. package/dist/ui/assets/secret-env-CjwX7z7b.js +1 -0
  189. package/dist/ui/assets/secret-topology-0AWfFTh5.js +1 -0
  190. package/dist/ui/assets/{secrets-bridge-client-cWDAnFqs.js → secrets-bridge-client-DCQ44RyR.js} +1 -1
  191. package/dist/ui/assets/{session-freezer-DYVYVWZ3.js → session-freezer-cQJKe1j_.js} +3 -3
  192. package/dist/ui/assets/{setup-feature-flags-remote-DtLgZPds.js → setup-feature-flags-remote-BxfewGbb.js} +1 -1
  193. package/dist/ui/assets/setup-standalone-prelude-Bv9X4-V2.js +2 -0
  194. package/dist/ui/assets/setup-sudo-B3tWN6O2.js +2 -0
  195. package/dist/ui/assets/silent-renew-backoff-C_Iv54ZG.js +1 -0
  196. package/dist/ui/assets/silent-renew-backoff-t_Cd4Zw7.js +1 -0
  197. package/dist/ui/assets/{skills-CfaCWaY6.js → skills-C8Ojzeu6.js} +1 -1
  198. package/dist/ui/assets/{slicc-diff-DsGtkf0J.js → slicc-diff-DhGIKKqP.js} +1 -1
  199. package/dist/ui/assets/slicc-version-CaunkoU5.js +1 -0
  200. package/dist/ui/assets/smithy-Dgaz7aur.js +1 -0
  201. package/dist/ui/assets/solarized-dark-UdsmMDCL.js +1 -0
  202. package/dist/ui/assets/solarized-light-C1IUL_tW.js +1 -0
  203. package/dist/ui/assets/{speak-BDT9rGzg.js → speak-BSK3Souh.js} +1 -1
  204. package/dist/ui/assets/{sql-69VAgb2g.js → sql-DvarVTMJ.js} +1 -1
  205. package/dist/ui/assets/{src-DsDPrXOS.js → src-DXdqCrdV.js} +2 -2
  206. package/dist/ui/assets/{store-sdSLaoJp.js → store-BPyCiwPs.js} +1 -1
  207. package/dist/ui/assets/{store-BQWc00Lo.js → store-CGgqI527.js} +1 -1
  208. package/dist/ui/assets/style-guide-Bgzsk7bf.js +821 -0
  209. package/dist/ui/assets/{sudo-BTuTezs4.js → sudo-1gsx4XWx.js} +2 -2
  210. package/dist/ui/assets/{svelte-B4PVQJ-7.js → svelte-D4FIy7cP.js} +1 -1
  211. package/dist/ui/assets/swift-CyEgAFGc.js +1 -0
  212. package/dist/ui/assets/temperature-support-B4x2xaWY.js +1 -0
  213. package/dist/ui/assets/temperature-support-Cpml9LfI.js +1 -0
  214. package/dist/ui/assets/transform-messages-DZg9zDcV.js +1 -0
  215. package/dist/ui/assets/transform-messages-XkZ1QnTb.js +1 -0
  216. package/dist/ui/assets/transformers-env-DPjdc2EQ.js +1 -0
  217. package/dist/ui/assets/tray-leader-CP11I609.js +1 -0
  218. package/dist/ui/assets/{tray-leave-runtime-BGfdX5KF.js → tray-leave-runtime-CN7V9V7O.js} +1 -1
  219. package/dist/ui/assets/{tray-runtime-config-B1LF8Kd4.js → tray-runtime-config-CVoPQrT2.js} +1 -1
  220. package/dist/ui/assets/tray-runtime-config-D7cmCcHJ.js +1 -0
  221. package/dist/ui/assets/ts-tags-C4Ifwy6r.js +1 -0
  222. package/dist/ui/assets/{upgrade-detection-CmsEVCLH.js → upgrade-detection-DHKcwE9c.js} +1 -1
  223. package/dist/ui/assets/vesper-DdrHHSXu.js +1 -0
  224. package/dist/ui/assets/{voice-reply-CnP5wEO_.js → voice-reply-BNX-jA0G.js} +1 -1
  225. package/dist/ui/assets/{vue-Dg0Kv3qp.js → vue-Djeyp8pE.js} +1 -1
  226. package/dist/ui/assets/{vue-vine-DdvC-EE2.js → vue-vine-By_xyXdL.js} +1 -1
  227. package/dist/ui/assets/{wc-attach-DsMfUpx8.js → wc-attach-CPoS-Z-g.js} +2 -2
  228. package/dist/ui/assets/{wc-extension-wBWx11Lq.js → wc-extension-vZctlNTg.js} +2 -2
  229. package/dist/ui/assets/wc-float-label-D7p-4xyd.js +1 -0
  230. package/dist/ui/assets/wc-follower-BgCWId1J.js +17 -0
  231. package/dist/ui/assets/wc-live-leqS7MUz.js +8 -0
  232. package/dist/ui/assets/wc-nav-CO_N4L3V.js +2 -0
  233. package/dist/ui/assets/wc-onboarding-B4o-Pdiq.js +2 -0
  234. package/dist/ui/assets/wc-placeholder-BTbGc9bq.js +4 -0
  235. package/dist/ui/assets/wc-settings-B4hsC2Um.js +51 -0
  236. package/dist/ui/assets/{wc-shell-DrXzWzBs.js → wc-shell-B9UbR2P2.js} +3 -3
  237. package/dist/ui/assets/{wc-sprinkles-Hdy-5FTU.js → wc-sprinkles-Ds-rd0k7.js} +2 -2
  238. package/dist/ui/assets/wc-tray-BQls_HTm.js +2 -0
  239. package/dist/ui/assets/{wc-tray-scoops-B2RP8cgD.js → wc-tray-scoops-D8qwcovR.js} +1 -1
  240. package/dist/ui/assets/welcome-CyCMJDqG.js +621 -0
  241. package/dist/ui/assets/whisper-session-DpDs0sDL.js +2 -0
  242. package/dist/ui/assets/x_search-C-5p00-C.js +131 -0
  243. package/dist/ui/assets/xai-grok-DzMkuuG4.js +1 -0
  244. package/dist/ui/assets/xai-grok-kLSQtmUi.js +1 -0
  245. package/dist/ui/index.html +17 -16
  246. package/dist/ui/llm-proxy-sw.js +1 -1
  247. package/dist/ui/packages/webapp/index.html +17 -16
  248. package/dist/ui/slicc-diff.js +1 -1
  249. package/package.json +1 -1
  250. package/dist/ui/assets/adobe-B034kk8u.js +0 -2
  251. package/dist/ui/assets/adobe-FLVM_96g.js +0 -1
  252. package/dist/ui/assets/anthropic-messages-BX4DpK10.js +0 -39
  253. package/dist/ui/assets/anthropic-messages-C-orWG7m.js +0 -39
  254. package/dist/ui/assets/azure-openai-responses-C2LleG-4.js +0 -1
  255. package/dist/ui/assets/azure-openai-responses-Df9YPxyp.js +0 -1
  256. package/dist/ui/assets/bedrock-camp-B0KF_4RS.js +0 -1
  257. package/dist/ui/assets/bedrock-camp-qpZqnqLa.js +0 -2
  258. package/dist/ui/assets/bridge-launch-params-zrpWWxT3.js +0 -1
  259. package/dist/ui/assets/catppuccin-frappe-3VR1Za6u.js +0 -1
  260. package/dist/ui/assets/catppuccin-latte-DwIHMF0Q.js +0 -1
  261. package/dist/ui/assets/catppuccin-macchiato-DYnBP6_5.js +0 -1
  262. package/dist/ui/assets/catppuccin-mocha-DYhrFGRu.js +0 -1
  263. package/dist/ui/assets/cerebras-DweKDbE1.js +0 -1
  264. package/dist/ui/assets/cerebras-O8AuH6NY.js +0 -1
  265. package/dist/ui/assets/cpp-CdhRINFH.js +0 -1
  266. package/dist/ui/assets/discovery-preference-fqUhjzeE.js +0 -1
  267. package/dist/ui/assets/dist-Dwa3Gdd4.js +0 -1547
  268. package/dist/ui/assets/float-topology-BgioAcOd.js +0 -1
  269. package/dist/ui/assets/fs-Bov3sJ0L.js +0 -1
  270. package/dist/ui/assets/fs-Drpegy_X.js +0 -2
  271. package/dist/ui/assets/github-CE8SlGEA.js +0 -2
  272. package/dist/ui/assets/github-copilot-DsCq9ehC.js +0 -2
  273. package/dist/ui/assets/github-copilot-ywjopCMn.js +0 -1
  274. package/dist/ui/assets/github-t3RMhkRE.js +0 -1
  275. package/dist/ui/assets/google-generative-ai-C9uw7Zks.js +0 -1
  276. package/dist/ui/assets/google-generative-ai-DHBc1oKV.js +0 -1
  277. package/dist/ui/assets/google-vertex-BaT3InWy.js +0 -1
  278. package/dist/ui/assets/google-vertex-DX8CfGr6.js +0 -1
  279. package/dist/ui/assets/julia-DibC-h6i.js +0 -1
  280. package/dist/ui/assets/kanagawa-dragon-CXtmUGW6.js +0 -1
  281. package/dist/ui/assets/kanagawa-lotus-BN08jTvb.js +0 -1
  282. package/dist/ui/assets/kanagawa-wave-CTweb8Dz.js +0 -1
  283. package/dist/ui/assets/legacy-api-aliases-CsTVszvY.js +0 -1
  284. package/dist/ui/assets/legacy-api-aliases-nSD9C16V.js +0 -1
  285. package/dist/ui/assets/loader-sgPDMLWT.js +0 -4
  286. package/dist/ui/assets/main-BWIUe9mc.js +0 -22
  287. package/dist/ui/assets/mdc-Otire2H_.js +0 -1
  288. package/dist/ui/assets/mistral-conversations-BXo-tb0V.js +0 -4
  289. package/dist/ui/assets/mistral-conversations-Ck257tvp.js +0 -4
  290. package/dist/ui/assets/monokai-CdkpiU2Y.js +0 -1
  291. package/dist/ui/assets/mount-CDH4T-Mp.js +0 -2
  292. package/dist/ui/assets/mount-CE7C-kQS.js +0 -1
  293. package/dist/ui/assets/mount-recovery-h9v3cRpd.js +0 -2
  294. package/dist/ui/assets/new-session-CU8TGRAW.js +0 -2
  295. package/dist/ui/assets/oauth-bootstrap-CRJLIz8V.js +0 -2
  296. package/dist/ui/assets/oauth-service-Bbrrl8Mr.js +0 -1
  297. package/dist/ui/assets/oauth-service-Cy5ngmcU.js +0 -1
  298. package/dist/ui/assets/openai-codex-C2u_j09G.js +0 -1
  299. package/dist/ui/assets/openai-codex-DhoN0DsA.js +0 -1
  300. package/dist/ui/assets/openai-codex-responses-BQzefg3i.js +0 -7
  301. package/dist/ui/assets/openai-codex-responses-JtcU5b3J.js +0 -7
  302. package/dist/ui/assets/openai-completions-D-HjYi8x.js +0 -5
  303. package/dist/ui/assets/openai-completions-QMfwfjiE.js +0 -5
  304. package/dist/ui/assets/openai-responses-BVHnEPuG.js +0 -1
  305. package/dist/ui/assets/openai-responses-Ca0oWhbv.js +0 -1
  306. package/dist/ui/assets/openrouter-DnjFjBY3.js +0 -1
  307. package/dist/ui/assets/openrouter-DvfkEaFA.js +0 -1
  308. package/dist/ui/assets/panel-rpc-handlers-CqcvBRTi.js +0 -2
  309. package/dist/ui/assets/php-BidqsJNR.js +0 -1
  310. package/dist/ui/assets/port-bridge-client-BbVs1yhx.js +0 -2
  311. package/dist/ui/assets/port-bridge-client-DxYLF2-N.js +0 -1
  312. package/dist/ui/assets/provider-settings-DcYK3m1J.js +0 -2
  313. package/dist/ui/assets/provider-store-access-BN6c8KtH.js +0 -1
  314. package/dist/ui/assets/providers-BAjAn8LJ.js +0 -2
  315. package/dist/ui/assets/providers-BYRmRIj_.js +0 -1
  316. package/dist/ui/assets/proxied-fetch-B4g-4VbQ.js +0 -2
  317. package/dist/ui/assets/proxied-fetch-n2pCvcgW.js +0 -1
  318. package/dist/ui/assets/quick-llm-CXBgg2d_.js +0 -1
  319. package/dist/ui/assets/r-Dzep-lPg.js +0 -1
  320. package/dist/ui/assets/red-CJ3rzSJv.js +0 -1
  321. package/dist/ui/assets/rose-pine-BthvhNj6.js +0 -1
  322. package/dist/ui/assets/rose-pine-dawn-Dg85fqjY.js +0 -1
  323. package/dist/ui/assets/rose-pine-moon-hon4tzzS.js +0 -1
  324. package/dist/ui/assets/secret-env-q4hxkt7Z.js +0 -1
  325. package/dist/ui/assets/secret-topology-xLmXoozo.js +0 -1
  326. package/dist/ui/assets/setup-standalone-prelude-B5yx5j_i.js +0 -2
  327. package/dist/ui/assets/setup-sudo-CGpFS_H9.js +0 -2
  328. package/dist/ui/assets/silent-renew-backoff-BhyOB6Rq.js +0 -1
  329. package/dist/ui/assets/silent-renew-backoff-BrAZcbzt.js +0 -1
  330. package/dist/ui/assets/slicc-version-ClAVruxy.js +0 -1
  331. package/dist/ui/assets/solarized-dark-DV17i1UV.js +0 -1
  332. package/dist/ui/assets/solarized-light-DSh2HLQt.js +0 -1
  333. package/dist/ui/assets/swift-DonLKvLd.js +0 -1
  334. package/dist/ui/assets/transformers-env-SL0zTs7S.js +0 -1
  335. package/dist/ui/assets/tray-leader-DcRtwWl-.js +0 -1
  336. package/dist/ui/assets/tray-runtime-config-CRGwg9SK.js +0 -1
  337. package/dist/ui/assets/ts-tags-BUIgHz80.js +0 -1
  338. package/dist/ui/assets/vesper-D5bVUKB1.js +0 -1
  339. package/dist/ui/assets/wc-float-label-qqb_uM9y.js +0 -1
  340. package/dist/ui/assets/wc-follower-Di7VVZ0z.js +0 -17
  341. package/dist/ui/assets/wc-live-1OpoOfN1.js +0 -8
  342. package/dist/ui/assets/wc-nav-B8ymo0Vu.js +0 -2
  343. package/dist/ui/assets/wc-onboarding-CMJYjLlt.js +0 -2
  344. package/dist/ui/assets/wc-placeholder-DIOhu2Ac.js +0 -4
  345. package/dist/ui/assets/wc-settings-D2oVzKVs.js +0 -51
  346. package/dist/ui/assets/wc-tray-CfSIy5M0.js +0 -2
  347. package/dist/ui/assets/whisper-session-Cf2gGkoR.js +0 -2
  348. package/dist/ui/assets/xai-grok-B_POoF8K.js +0 -1
  349. package/dist/ui/assets/xai-grok-D__MgEgm.js +0 -1
package/README.md CHANGED
@@ -78,7 +78,7 @@ SLICC is for you if:
78
78
  - **Boot full x86 virtual machines in the browser.** `v86 start` runs real operating systems (Alpine, FreeDOS, KolibriOS, ...) on the wasm-based [v86](https://github.com/copy/v86) emulator, entirely client-side. The agent drives the guest from the shell — type, click, screenshot, stream the screen live, save/restore state — and `-net <model>,relay=fetch` gives the guest HTTP access through SLICC's fetch proxy. Install with `ipk add v86`.
79
79
  - **Delegate parallel work to scoops.** Split tasks into isolated sub-agents with their own sandboxes and context, then let the main agent coordinate the results.
80
80
  - **Turn one-off wins into reusable workflows.** Package behavior as skills, build interactive sprinkles, and react to external events with webhooks and cron-driven licks.
81
- - **Mount your local file system.** By default, SLICC is confined to your browser. But you can ask it to mount folders from your local file system, so it can read and write from there. Mount into an empty path such as `/mnt/myproject` so you do not hide existing skills or scripts.
81
+ - **Mount your local file system.** By default, SLICC is confined to your browser. But you can ask it to mount folders from your local file system, so it can read and write from there. Mount into an empty path such as `/mnt/myproject` so you do not hide existing skills or scripts. Picker mounts ask again after a page reload; for folders you always want available, map them in the launcher's mount table (`npx slicc --mount=~/Projects/foo:/mnt/foo`, or Settings → Mounts in Sliccstart.app) and they are mounted automatically on every launch, with no picker or permission prompt — see [Auto-mounted host folders](docs/mounts.md#auto-mounted-host-folders-the-mount-table).
82
82
  - **Mount remote storage as if it were local.** Beyond local folders, `mount --source` bridges S3 buckets, S3-compatible services like Cloudflare R2 and MinIO, and Adobe authoring content — both da.live repositories and Helix 6 sites on the AEM Source Bus — into the same VFS surface. Reads use TTL+ETag caching with conditional revalidation; writes use ETag-conditional PUTs that surface concurrent-edit conflicts as `EBUSY`. Credentials live server-side (`~/.slicc/secrets.env` in CLI, `chrome.storage.local` in the extension via the **Extension options** page) and never reach the agent. After setup: `mount --source s3://my-bucket --profile r2 /mnt/r2`, `mount --source da://my-org/my-repo /mnt/da`, or `mount --source aem://my-org/my-site /mnt/aem`. A `da://` source checks the site config first and re-routes to the Source Bus when the site has been upgraded to Helix 6, rather than quietly mounting a store that no longer holds its content. See [docs/mounts.md](docs/mounts.md) for the full guide.
83
83
 
84
84
  ## Getting started
@@ -5,6 +5,7 @@ export * from './cdp-frame-unmask.js';
5
5
  export * from './content-type.js';
6
6
  export * from './electron-overlay-route.js';
7
7
  export * from './fetch-proxy-protocol.js';
8
+ export * from './loopback.js';
8
9
  export * from './oauth-extra-domains-storage.js';
9
10
  export * from './preview-url.js';
10
11
  export * from './runtime-env.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,kCAAkC,CAAC;AACjD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC"}
@@ -6,6 +6,7 @@ export * from './cdp-frame-unmask.js';
6
6
  export * from './content-type.js';
7
7
  export * from './electron-overlay-route.js';
8
8
  export * from './fetch-proxy-protocol.js';
9
+ export * from './loopback.js';
9
10
  export * from './oauth-extra-domains-storage.js';
10
11
  export * from './preview-url.js';
11
12
  export * from './runtime-env.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AAEjF,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AAEjF,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,kCAAkC,CAAC;AACjD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Canonical loopback-host detection shared across security gates
3
+ * (bridge-token exemption, localhost-only endpoints, http: allowlists,
4
+ * OAuth redirect branching). One accepted set — do not reimplement.
5
+ *
6
+ * Accepts:
7
+ * - `localhost`
8
+ * - the entire `127.0.0.0/8` block (e.g. `127.0.0.1`, `127.0.0.2`)
9
+ * - IPv6 loopback, bracketed or bare (`[::1]`, `::1`)
10
+ */
11
+ /** True when `hostname` is a loopback name (no URL parse — host only). */
12
+ export declare function isLoopbackHostname(hostname: string): boolean;
13
+ /**
14
+ * True when `origin` parses as a URL whose hostname is loopback.
15
+ * Returns false for missing / empty / unparseable values.
16
+ */
17
+ export declare function isLoopbackOrigin(origin: string | undefined | null): boolean;
18
+ //# sourceMappingURL=loopback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopback.d.ts","sourceRoot":"","sources":["../src/loopback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAW5D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAO3E"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Canonical loopback-host detection shared across security gates
3
+ * (bridge-token exemption, localhost-only endpoints, http: allowlists,
4
+ * OAuth redirect branching). One accepted set — do not reimplement.
5
+ *
6
+ * Accepts:
7
+ * - `localhost`
8
+ * - the entire `127.0.0.0/8` block (e.g. `127.0.0.1`, `127.0.0.2`)
9
+ * - IPv6 loopback, bracketed or bare (`[::1]`, `::1`)
10
+ */
11
+ /** True when `hostname` is a loopback name (no URL parse — host only). */
12
+ export function isLoopbackHostname(hostname) {
13
+ if (!hostname)
14
+ return false;
15
+ // WHATWG URL keeps brackets on IPv6 hostnames (`http://[::1]` → `[::1]`);
16
+ // socket addresses and some callers pass bare `::1`. Accept both.
17
+ const host = hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;
18
+ if (host === 'localhost')
19
+ return true;
20
+ if (host === '::1')
21
+ return true;
22
+ // 127.0.0.0/8 — octet shape only (same as the former webapp plugin gate).
23
+ if (/^127(\.\d{1,3}){3}$/.test(host))
24
+ return true;
25
+ return false;
26
+ }
27
+ /**
28
+ * True when `origin` parses as a URL whose hostname is loopback.
29
+ * Returns false for missing / empty / unparseable values.
30
+ */
31
+ export function isLoopbackOrigin(origin) {
32
+ if (!origin)
33
+ return false;
34
+ try {
35
+ return isLoopbackHostname(new URL(origin).hostname);
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ //# sourceMappingURL=loopback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopback.js","sourceRoot":"","sources":["../src/loopback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,0EAA0E;AAC1E,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,0EAA0E;IAC1E,kEAAkE;IAClE,MAAM,IAAI,GACR,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxF,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAChC,0EAA0E;IAC1E,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAiC;IAChE,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -42,12 +42,15 @@ export declare const BRIDGE_ALLOWED_ORIGINS: readonly string[];
42
42
  */
43
43
  export declare function isAllowedBridgeOrigin(origin: string | undefined | null): boolean;
44
44
  /**
45
- * True iff `origin` is a loopback host (localhost / 127.0.0.1 / ::1).
45
+ * True iff `origin` is a loopback host.
46
46
  * Loopback allowlisted origins (e.g. the locally-served OAuth callback
47
47
  * page at `http://localhost:5710/auth/callback` posting to
48
48
  * `/api/oauth-result`) are exempt from the bridge-token requirement —
49
49
  * the token's threat model is "remote allowlisted origin (sliccy.ai)
50
50
  * with a hostile script", not "local server talking to itself".
51
+ *
52
+ * Canonical set: `@slicc/shared-ts` `isLoopbackOrigin` (localhost,
53
+ * 127.0.0.0/8, bracketed/bare ::1).
51
54
  */
52
55
  export declare function isLoopbackBridgeOrigin(origin: string | undefined | null): boolean;
53
56
  /**
@@ -19,7 +19,7 @@
19
19
  * testable from `tests/bridge-security.test.ts`.
20
20
  */
21
21
  import { randomUUID, timingSafeEqual } from 'node:crypto';
22
- import { BRIDGE_SUBPROTOCOL_PREFIX, BRIDGE_TOKEN_HEADER, BRIDGE_TOKEN_QUERY_PARAM, BRIDGE_WS_QUERY_PARAM, SLICC_HOSTED_ORIGIN, SLICC_STAGING_HUB_ORIGIN, } from './_shared/index.js';
22
+ import { BRIDGE_SUBPROTOCOL_PREFIX, BRIDGE_TOKEN_HEADER, BRIDGE_TOKEN_QUERY_PARAM, BRIDGE_WS_QUERY_PARAM, isLoopbackOrigin, SLICC_HOSTED_ORIGIN, SLICC_STAGING_HUB_ORIGIN, } from './_shared/index.js';
23
23
  // Re-exported so the many existing bridge-security importers (index.ts,
24
24
  // launch-url.ts, electron-controller.ts, tests) keep their import surface.
25
25
  // Canonical definitions: packages/shared-ts/src/bridge-protocol.ts.
@@ -144,28 +144,18 @@ export function isAllowedBridgeOrigin(origin) {
144
144
  return BRIDGE_DEV_ALLOWED_ORIGINS.has(normalized);
145
145
  }
146
146
  /**
147
- * True iff `origin` is a loopback host (localhost / 127.0.0.1 / ::1).
147
+ * True iff `origin` is a loopback host.
148
148
  * Loopback allowlisted origins (e.g. the locally-served OAuth callback
149
149
  * page at `http://localhost:5710/auth/callback` posting to
150
150
  * `/api/oauth-result`) are exempt from the bridge-token requirement —
151
151
  * the token's threat model is "remote allowlisted origin (sliccy.ai)
152
152
  * with a hostile script", not "local server talking to itself".
153
+ *
154
+ * Canonical set: `@slicc/shared-ts` `isLoopbackOrigin` (localhost,
155
+ * 127.0.0.0/8, bracketed/bare ::1).
153
156
  */
154
157
  export function isLoopbackBridgeOrigin(origin) {
155
- if (!origin)
156
- return false;
157
- try {
158
- const url = new URL(origin);
159
- // Node's WHATWG URL parser keeps the brackets on IPv6 hostnames
160
- // (`http://[::1]:5710` → `[::1]`); accept both bracketed and bare.
161
- return (url.hostname === 'localhost' ||
162
- url.hostname === '127.0.0.1' ||
163
- url.hostname === '::1' ||
164
- url.hostname === '[::1]');
165
- }
166
- catch {
167
- return false;
168
- }
158
+ return isLoopbackOrigin(origin);
169
159
  }
170
160
  /**
171
161
  * Constant-time compare for the bridge token. `presented` may be missing
@@ -15,6 +15,9 @@ export interface CloudStatusPayload {
15
15
  * Reject non-loopback requests. The sandbox is a private execution boundary,
16
16
  * but defense in depth: someone might wire a port-forward and we want this
17
17
  * endpoint to be unreachable from the outside.
18
+ *
19
+ * Socket addresses may be IPv4-mapped IPv6 (`::ffff:127.0.0.1`); strip that
20
+ * prefix then use the shared loopback hostname check.
18
21
  */
19
22
  export declare function requireLoopback(req: Request, res: Response, next: NextFunction): void;
20
23
  export declare function registerCloudStatusEndpoint(app: Express, options: CloudStatusEndpointOptions): void;
@@ -1,4 +1,5 @@
1
1
  import { promises as fs } from 'node:fs';
2
+ import { isLoopbackHostname } from './_shared/index.js';
2
3
  import express from 'express';
3
4
  /** The optional string fields validated when present but never required. */
4
5
  const OPTIONAL_STRING_FIELDS = [
@@ -25,11 +26,14 @@ function isCloudStatusPayload(x) {
25
26
  * Reject non-loopback requests. The sandbox is a private execution boundary,
26
27
  * but defense in depth: someone might wire a port-forward and we want this
27
28
  * endpoint to be unreachable from the outside.
29
+ *
30
+ * Socket addresses may be IPv4-mapped IPv6 (`::ffff:127.0.0.1`); strip that
31
+ * prefix then use the shared loopback hostname check.
28
32
  */
29
33
  export function requireLoopback(req, res, next) {
30
34
  const addr = req.socket.remoteAddress ?? '';
31
- const isLoopback = addr === '127.0.0.1' || addr === '::1' || addr === '::ffff:127.0.0.1' || addr === 'localhost';
32
- if (!isLoopback) {
35
+ const normalized = addr.toLowerCase().startsWith('::ffff:') ? addr.slice('::ffff:'.length) : addr;
36
+ if (!isLoopbackHostname(normalized)) {
33
37
  res.status(403).json({ error: 'localhost only' });
34
38
  return;
35
39
  }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Host filesystem bridge — serves the folders named in the mount table
3
+ * (`--mount=<os-path>:<slicc-path>`) to the webapp over the local /api
4
+ * surface, so configured mounts appear in the VFS fully automatically,
5
+ * with no File System Access picker and no Chrome permission prompt.
6
+ *
7
+ * Only paths under a configured mount root are reachable. Every request
8
+ * names a mount by its SLICC target (`?mount=/mnt/project`) plus a
9
+ * mount-relative path (`?path=sub/file.txt`); the mapping to the OS root
10
+ * happens here and `resolveWithinRoot` rejects traversal (`..`) and
11
+ * symlink escapes, so the browser never addresses the host filesystem
12
+ * directly.
13
+ *
14
+ * Protected like every other /api route: same-origin / loopback callers
15
+ * pass, cross-origin callers need the bridge token (see
16
+ * `createThinBridgeCorsMiddleware` in index.ts).
17
+ */
18
+ import type { Express } from 'express';
19
+ import type { HostMountMapping } from './runtime-flags.js';
20
+ /** Matches the webapp's hostfs body cap (backend-hostfs.ts). */
21
+ export declare const HOSTFS_MAX_BODY_BYTES: number;
22
+ /**
23
+ * Resolve `relPath` against `root`, rejecting anything that leaves the root
24
+ * either lexically (`..`) or via symlinks. Symlinks *inside* the root that
25
+ * also point inside the root are followed; a link pointing outside is
26
+ * rejected. The check walks to the nearest existing ancestor so that writes
27
+ * to not-yet-existing paths are still validated.
28
+ */
29
+ export declare function resolveWithinRoot(root: string, relPath: string): Promise<string>;
30
+ interface HostMountRoot {
31
+ /** SLICC target path, e.g. /mnt/project. */
32
+ path: string;
33
+ /** realpath()'d OS root. */
34
+ root: string;
35
+ }
36
+ /**
37
+ * Resolve the configured mappings to realpath'd roots. Mappings whose OS
38
+ * path does not exist (or is not a directory) are dropped with a warning —
39
+ * a missing folder must not take the whole /api surface down, and the
40
+ * webapp will surface the absent mount as "not mounted".
41
+ */
42
+ export declare function resolveHostMountRoots(mounts: readonly HostMountMapping[], warn?: (msg: string) => void): Promise<HostMountRoot[]>;
43
+ /**
44
+ * Register the /api/hostfs routes for the resolved mount roots. The route
45
+ * surface mirrors `MountBackend` 1:1 (webapp `backend-hostfs.ts`):
46
+ *
47
+ * GET /api/hostfs/list?mount=&path= → { entries: [...] }
48
+ * GET /api/hostfs/stat?mount=&path= → { kind, size, mtime }
49
+ * GET /api/hostfs/read?mount=&path= → octet-stream body
50
+ * PUT /api/hostfs/write?mount=&path= ← octet-stream body
51
+ * POST /api/hostfs/mkdir?mount=&path=
52
+ * DELETE /api/hostfs/remove?mount=&path=[&recursive=1]
53
+ *
54
+ * Errors are `{ code, message }` JSON with an errno-derived status so the
55
+ * webapp backend can rethrow faithful `FsError`s.
56
+ */
57
+ export declare function registerHostFsRoutes(app: Express, roots: readonly HostMountRoot[]): void;
58
+ export {};
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Host filesystem bridge — serves the folders named in the mount table
3
+ * (`--mount=<os-path>:<slicc-path>`) to the webapp over the local /api
4
+ * surface, so configured mounts appear in the VFS fully automatically,
5
+ * with no File System Access picker and no Chrome permission prompt.
6
+ *
7
+ * Only paths under a configured mount root are reachable. Every request
8
+ * names a mount by its SLICC target (`?mount=/mnt/project`) plus a
9
+ * mount-relative path (`?path=sub/file.txt`); the mapping to the OS root
10
+ * happens here and `resolveWithinRoot` rejects traversal (`..`) and
11
+ * symlink escapes, so the browser never addresses the host filesystem
12
+ * directly.
13
+ *
14
+ * Protected like every other /api route: same-origin / loopback callers
15
+ * pass, cross-origin callers need the bridge token (see
16
+ * `createThinBridgeCorsMiddleware` in index.ts).
17
+ */
18
+ import express from 'express';
19
+ import { lstat, mkdir, readdir, readFile, realpath, rename, rm, stat, writeFile, } from 'fs/promises';
20
+ import { dirname, resolve, sep } from 'path';
21
+ /** Matches the webapp's hostfs body cap (backend-hostfs.ts). */
22
+ export const HOSTFS_MAX_BODY_BYTES = 100 * 1024 * 1024;
23
+ function errnoCode(err) {
24
+ const code = err?.code;
25
+ return typeof code === 'string' ? code : null;
26
+ }
27
+ /** Map an fs errno (or traversal rejection) to an HTTP status + FsError code. */
28
+ function toFsCodeError(err) {
29
+ const code = errnoCode(err) ?? 'EIO';
30
+ const message = err instanceof Error ? err.message : String(err);
31
+ switch (code) {
32
+ case 'ENOENT':
33
+ return { status: 404, code, message };
34
+ case 'EACCES':
35
+ case 'EPERM':
36
+ return { status: 403, code: 'EACCES', message };
37
+ case 'EISDIR':
38
+ case 'ENOTDIR':
39
+ case 'ENOTEMPTY':
40
+ case 'EEXIST':
41
+ return { status: 409, code, message };
42
+ default:
43
+ return { status: 500, code, message };
44
+ }
45
+ }
46
+ function sendFsError(res, err) {
47
+ const mapped = toFsCodeError(err);
48
+ res.status(mapped.status).json({ code: mapped.code, message: mapped.message });
49
+ }
50
+ /** Traversal/symlink escape → EACCES, so it renders as a permission error. */
51
+ function escapeError(target) {
52
+ const err = new Error(`path escapes the mount root: ${target}`);
53
+ err.code = 'EACCES';
54
+ return err;
55
+ }
56
+ function isWithin(root, target) {
57
+ return target === root || target.startsWith(root + sep);
58
+ }
59
+ /**
60
+ * Resolve `relPath` against `root`, rejecting anything that leaves the root
61
+ * either lexically (`..`) or via symlinks. Symlinks *inside* the root that
62
+ * also point inside the root are followed; a link pointing outside is
63
+ * rejected. The check walks to the nearest existing ancestor so that writes
64
+ * to not-yet-existing paths are still validated.
65
+ */
66
+ export async function resolveWithinRoot(root, relPath) {
67
+ const cleaned = relPath.replace(/^\/+/, '');
68
+ const target = resolve(root, cleaned);
69
+ if (!isWithin(root, target))
70
+ throw escapeError(target);
71
+ // Walk up to the nearest existing ancestor and realpath it; a symlinked
72
+ // ancestor must still land inside the (already realpath'd) root.
73
+ let probe = target;
74
+ for (;;) {
75
+ try {
76
+ const real = await realpath(probe);
77
+ if (!isWithin(root, real) && probe !== root)
78
+ throw escapeError(target);
79
+ break;
80
+ }
81
+ catch (err) {
82
+ if (errnoCode(err) !== 'ENOENT')
83
+ throw err;
84
+ const parent = dirname(probe);
85
+ if (parent === probe)
86
+ break;
87
+ probe = parent;
88
+ }
89
+ }
90
+ return target;
91
+ }
92
+ function statPayload(s) {
93
+ return {
94
+ kind: s.isDirectory() ? 'directory' : 'file',
95
+ size: s.isDirectory() ? 0 : s.size,
96
+ mtime: Math.round(s.mtimeMs),
97
+ };
98
+ }
99
+ /**
100
+ * Resolve the configured mappings to realpath'd roots. Mappings whose OS
101
+ * path does not exist (or is not a directory) are dropped with a warning —
102
+ * a missing folder must not take the whole /api surface down, and the
103
+ * webapp will surface the absent mount as "not mounted".
104
+ */
105
+ export async function resolveHostMountRoots(mounts, warn = (msg) => console.warn(msg)) {
106
+ const roots = [];
107
+ for (const mapping of mounts) {
108
+ try {
109
+ const root = await realpath(mapping.hostPath);
110
+ const s = await stat(root);
111
+ if (!s.isDirectory()) {
112
+ warn(`--mount ${mapping.hostPath}: not a directory, skipping`);
113
+ continue;
114
+ }
115
+ roots.push({ path: mapping.path, root });
116
+ }
117
+ catch {
118
+ warn(`--mount ${mapping.hostPath}: does not exist, skipping`);
119
+ }
120
+ }
121
+ return roots;
122
+ }
123
+ function queryString(req, name) {
124
+ const value = req.query[name];
125
+ return typeof value === 'string' && value.length > 0 ? value : null;
126
+ }
127
+ /**
128
+ * Register the /api/hostfs routes for the resolved mount roots. The route
129
+ * surface mirrors `MountBackend` 1:1 (webapp `backend-hostfs.ts`):
130
+ *
131
+ * GET /api/hostfs/list?mount=&path= → { entries: [...] }
132
+ * GET /api/hostfs/stat?mount=&path= → { kind, size, mtime }
133
+ * GET /api/hostfs/read?mount=&path= → octet-stream body
134
+ * PUT /api/hostfs/write?mount=&path= ← octet-stream body
135
+ * POST /api/hostfs/mkdir?mount=&path=
136
+ * DELETE /api/hostfs/remove?mount=&path=[&recursive=1]
137
+ *
138
+ * Errors are `{ code, message }` JSON with an errno-derived status so the
139
+ * webapp backend can rethrow faithful `FsError`s.
140
+ */
141
+ export function registerHostFsRoutes(app, roots) {
142
+ const byPath = new Map(roots.map((r) => [r.path, r]));
143
+ const withTarget = (handler) => {
144
+ return (req, res) => {
145
+ void (async () => {
146
+ const mount = queryString(req, 'mount');
147
+ const rel = queryString(req, 'path') ?? '';
148
+ const entry = mount ? byPath.get(mount) : undefined;
149
+ if (!entry) {
150
+ res.status(404).json({ code: 'ENOENT', message: `no such mount: ${mount ?? ''}` });
151
+ return;
152
+ }
153
+ try {
154
+ const target = await resolveWithinRoot(entry.root, rel);
155
+ await handler(target, req, res);
156
+ }
157
+ catch (err) {
158
+ sendFsError(res, err);
159
+ }
160
+ })();
161
+ };
162
+ };
163
+ app.get('/api/hostfs/list', withTarget(async (target, _req, res) => {
164
+ const dirents = await readdir(target, { withFileTypes: true });
165
+ const entries = await Promise.all(dirents.map(async (d) => {
166
+ if (d.isDirectory())
167
+ return { name: d.name, kind: 'directory' };
168
+ try {
169
+ // stat() follows symlinks, so a link to a directory classifies as
170
+ // a directory — matching what every subsequent access sees (and
171
+ // the swift server, whose fileExists follows links). Escaping
172
+ // links are still refused at access time by resolveWithinRoot.
173
+ const s = await stat(resolve(target, d.name));
174
+ if (s.isDirectory())
175
+ return { name: d.name, kind: 'directory' };
176
+ return {
177
+ name: d.name,
178
+ kind: 'file',
179
+ size: s.size,
180
+ lastModified: Math.round(s.mtimeMs),
181
+ };
182
+ }
183
+ catch {
184
+ // Raced deletion / dangling link / unreadable: name only.
185
+ return { name: d.name, kind: 'file' };
186
+ }
187
+ }));
188
+ res.json({ entries });
189
+ }));
190
+ app.get('/api/hostfs/stat', withTarget(async (target, _req, res) => {
191
+ res.json(statPayload(await stat(target)));
192
+ }));
193
+ app.get('/api/hostfs/read', withTarget(async (target, _req, res) => {
194
+ // lstat first so a dangling symlink is ENOENT, a directory is EISDIR.
195
+ const s = await stat(target);
196
+ if (s.isDirectory()) {
197
+ sendFsError(res, Object.assign(new Error(`is a directory: ${target}`), { code: 'EISDIR' }));
198
+ return;
199
+ }
200
+ if (s.size > HOSTFS_MAX_BODY_BYTES) {
201
+ res.status(413).json({
202
+ code: 'EFBIG',
203
+ message: `file exceeds the ${HOSTFS_MAX_BODY_BYTES} byte hostfs cap`,
204
+ });
205
+ return;
206
+ }
207
+ const body = await readFile(target);
208
+ res.setHeader('Content-Type', 'application/octet-stream');
209
+ res.send(body);
210
+ }));
211
+ app.put('/api/hostfs/write', express.raw({ type: () => true, limit: HOSTFS_MAX_BODY_BYTES }), withTarget(async (target, req, res) => {
212
+ // Refuse to clobber a directory with a file (fs would throw EISDIR on
213
+ // open, but check explicitly so the error is deterministic).
214
+ try {
215
+ const existing = await lstat(target);
216
+ if (existing.isDirectory()) {
217
+ sendFsError(res, Object.assign(new Error(`is a directory: ${target}`), { code: 'EISDIR' }));
218
+ return;
219
+ }
220
+ }
221
+ catch {
222
+ /* ENOENT — fresh file */
223
+ }
224
+ await mkdir(dirname(target), { recursive: true });
225
+ const body = Buffer.isBuffer(req.body) ? req.body : Buffer.alloc(0);
226
+ // Write-then-rename would break hardlinks and xattrs on user files;
227
+ // plain writeFile matches what local tools do.
228
+ await writeFile(target, body);
229
+ res.json({ ok: true });
230
+ }));
231
+ app.post('/api/hostfs/mkdir', withTarget(async (target, _req, res) => {
232
+ await mkdir(target, { recursive: true });
233
+ res.json({ ok: true });
234
+ }));
235
+ app.post('/api/hostfs/rename', withTarget(async (target, req, res) => {
236
+ const mount = queryString(req, 'mount');
237
+ const toRel = queryString(req, 'to');
238
+ const entry = mount ? byPath.get(mount) : undefined;
239
+ if (!entry || !toRel) {
240
+ res.status(400).json({ code: 'EINVAL', message: 'rename requires mount and to' });
241
+ return;
242
+ }
243
+ const to = await resolveWithinRoot(entry.root, toRel);
244
+ await rename(target, to);
245
+ res.json({ ok: true });
246
+ }));
247
+ app.delete('/api/hostfs/remove', withTarget(async (target, req, res) => {
248
+ const isRoot = roots.some((r) => r.root === target);
249
+ if (isRoot) {
250
+ res.status(403).json({ code: 'EACCES', message: 'refusing to remove a mount root' });
251
+ return;
252
+ }
253
+ const recursive = queryString(req, 'recursive') === '1';
254
+ await rm(target, { recursive, force: false });
255
+ res.json({ ok: true });
256
+ }));
257
+ }
@@ -30,6 +30,7 @@ import { getElectronAppPorts } from './electron-runtime.js';
30
30
  import { ElectronTrayFollower } from './electron-tray-follower.js';
31
31
  import { FileLogger } from './file-logger.js';
32
32
  import { registerHostedBootstrapEndpoint } from './hosted-bootstrap.js';
33
+ import { registerHostFsRoutes, resolveHostMountRoots } from './hostfs.js';
33
34
  import { runInstallCli } from './install-cli.js';
34
35
  import { resolveCliBrowserLaunchUrl } from './launch-url.js';
35
36
  import { createHttpCdp, registerLeaderRestartEndpoint } from './leader-restart.js';
@@ -197,6 +198,7 @@ function createServerState() {
197
198
  electronFollower: null,
198
199
  shuttingDown: false,
199
200
  discoveredTrayJoinUrl: RUNTIME_FLAGS.joinUrl ?? null,
201
+ hostMountRoots: [],
200
202
  bridgeToken: resolveServerBridgeToken(process.env, { thinBridgeMode: THIN_BRIDGE_MODE }),
201
203
  cdpUrl: null,
202
204
  chromeWs: null,
@@ -1106,6 +1108,10 @@ async function main() {
1106
1108
  // after `server.listen()`, so this endpoint must NOT close over a
1107
1109
  // pre-launch snapshot or it would always return null.
1108
1110
  trayJoinUrl: state.discoveredTrayJoinUrl ?? null,
1111
+ // Mount table (--mount=<os-path>:<slicc-path>): served over
1112
+ // /api/hostfs and auto-mounted by the webapp at boot. Only mappings
1113
+ // whose OS folder existed at startup are advertised.
1114
+ autoMounts: state.hostMountRoots.map(({ path, root }) => ({ path, hostPath: root })),
1109
1115
  });
1110
1116
  });
1111
1117
  // Localhost API descriptor — the discoverable surface advertised by the
@@ -1144,6 +1150,10 @@ async function main() {
1144
1150
  registerHostedBootstrapEndpoint(app, { secretStore });
1145
1151
  registerSecretsReloadEndpoint(app, { secretProxy, secretStore, oauthStore });
1146
1152
  }
1153
+ // Host-FS bridge for the mount table (--mount=<os>:<vfs>), every mode.
1154
+ // Roots are resolved once at startup; a folder created later needs a restart.
1155
+ state.hostMountRoots = await resolveHostMountRoots(RUNTIME_FLAGS.mounts);
1156
+ registerHostFsRoutes(app, state.hostMountRoots);
1147
1157
  // Sudo approval endpoint — raises a native OS dialog / TTY prompt from this
1148
1158
  // trusted process so the in-browser agent can request, but never fabricate,
1149
1159
  // an approval. Loopback-only; selects a backend by environment at call time.
@@ -1,6 +1,6 @@
1
1
  import { Readable, Transform } from 'node:stream';
2
2
  import { StringDecoder } from 'node:string_decoder';
3
- import { HMAC_SIGN_HEADER, isTextContentType } from '../_shared/index.js';
3
+ import { HMAC_SIGN_HEADER, isLoopbackOrigin, isTextContentType } from '../_shared/index.js';
4
4
  import { FETCH_PROXY_CONTENT_LENGTH_HEADER, FETCH_PROXY_SKIP_HEADERS, FETCH_PROXY_SKIP_RESPONSE_HEADERS, FETCH_PROXY_SKIP_RESPONSE_PREFIXES, } from '../fetch-proxy-headers.js';
5
5
  import { AgentActivityTracker, registerAgentActivityRoute } from './agent-activity.js';
6
6
  /** Pick the first value of a possibly-multi-valued request header. */
@@ -9,21 +9,6 @@ function firstHeaderValue(value) {
9
9
  return undefined;
10
10
  return Array.isArray(value) ? value[0] : value;
11
11
  }
12
- /** True when an origin/referer value points at localhost (any family). */
13
- function isLocalhostOrigin(origin) {
14
- if (!origin)
15
- return false;
16
- try {
17
- const url = new URL(origin);
18
- return (url.hostname === 'localhost' ||
19
- url.hostname === '127.0.0.1' ||
20
- url.hostname === '::1' ||
21
- url.hostname === '[::1]');
22
- }
23
- catch {
24
- return false;
25
- }
26
- }
27
12
  /** Get the body — either from express.json()'s parsed body or raw chunks. */
28
13
  async function collectRawBody(req) {
29
14
  if (req.body && typeof req.body === 'object' && Object.keys(req.body).length > 0) {
@@ -58,7 +43,7 @@ function buildForwardHeaders(req, targetUrl) {
58
43
  if (proxyOrigin) {
59
44
  headers.origin = proxyOrigin;
60
45
  }
61
- else if (isLocalhostOrigin(headers.origin)) {
46
+ else if (isLoopbackOrigin(headers.origin)) {
62
47
  // Only strip the browser's auto-added localhost origin; preserve legitimate origins.
63
48
  delete headers.origin;
64
49
  }
@@ -77,7 +62,7 @@ function buildForwardHeaders(req, targetUrl) {
77
62
  if (proxyReferer) {
78
63
  headers.referer = proxyReferer;
79
64
  }
80
- else if (isLocalhostOrigin(headers.referer)) {
65
+ else if (isLoopbackOrigin(headers.referer)) {
81
66
  delete headers.referer;
82
67
  }
83
68
  // Restore any X-Proxy-Proxy-* transport headers as Proxy-* headers
@@ -24,7 +24,29 @@ export interface CliRuntimeFlags {
24
24
  installCli: boolean;
25
25
  /** Target directory for --install-cli (default: OS-idiomatic, see install-cli.ts) */
26
26
  installDir: string | null;
27
+ /**
28
+ * Mount table: OS-folder → SLICC-target mappings served over the local
29
+ * host-FS bridge (`/api/hostfs`) and auto-mounted by the webapp at boot,
30
+ * with no picker and no Chrome permission prompt. Filled by repeatable
31
+ * `--mount=<os-path>:<slicc-path>` / `--mount <os-path>:<slicc-path>`
32
+ * flags. Picker-initiated (`mount <path>`) FS-Access mounts are
33
+ * unaffected and keep asking for permission.
34
+ */
35
+ mounts: HostMountMapping[];
36
+ }
37
+ /** One `--mount` entry: an absolute OS folder mapped to a VFS target. */
38
+ export interface HostMountMapping {
39
+ hostPath: string;
40
+ path: string;
27
41
  }
28
42
  export declare const DEFAULT_CLI_CDP_PORT = 9222;
29
43
  export declare const DEFAULT_ELECTRON_ATTACH_CDP_PORT = 9223;
44
+ /**
45
+ * Parse a `--mount` value of the form `<os-path>:<slicc-path>`. The split is
46
+ * on the LAST `:` whose remainder is an absolute path, so OS paths containing
47
+ * `:` still parse. A leading `~/` on the OS side expands against `homeDir`.
48
+ * Returns null (never a partial mapping) for anything else, so a stray
49
+ * `--mount=` or a one-sided value never lands in the table.
50
+ */
51
+ export declare function parseMountTableMapping(value: string, homeDir?: string): HostMountMapping | null;
30
52
  export declare function parseCliRuntimeFlags(argv: string[]): CliRuntimeFlags;