sliccy 6.185.1 → 6.187.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 (169) hide show
  1. package/dist/node-server/chrome-launch.d.ts +2 -0
  2. package/dist/node-server/chrome-launch.js +11 -0
  3. package/dist/node-server/index.js +1 -0
  4. package/dist/ui/.vite/manifest.json +182 -182
  5. package/dist/ui/assets/__vite-browser-external-DH1K0mQP.js +1 -0
  6. package/dist/ui/assets/{account-store-Br2mSpab.js → account-store-Ck_NeUVO.js} +1 -1
  7. package/dist/ui/assets/{account-store-BYWm5ahZ.js → account-store-CrPZWXpS.js} +1 -1
  8. package/dist/ui/assets/{adobe-Cf5-hIji.js → adobe-BI6JR44Y.js} +1 -1
  9. package/dist/ui/assets/{adobe-CObWZuyD.js → adobe-dNVaXloQ.js} +1 -1
  10. package/dist/ui/assets/{agent-panels-BvZGSCD0.js → agent-panels-BmN7YTnN.js} +1 -1
  11. package/dist/ui/assets/{almost-bash-shell-headless-CZLDhK1f.js → almost-bash-shell-headless-C-B2HDJv.js} +111 -111
  12. package/dist/ui/assets/{apply-layout-D2JbVCM_.js → apply-layout-BcVt9n4G.js} +1 -1
  13. package/dist/ui/assets/{apps-B5iEJzUt.js → apps-BXsnzvUU.js} +1 -1
  14. package/dist/ui/assets/{azure-openai-Cep1RYAS.js → azure-openai-CauTZIht.js} +1 -1
  15. package/dist/ui/assets/{azure-openai-DFccznQV.js → azure-openai-DD0SunAH.js} +1 -1
  16. package/dist/ui/assets/{backend-hostfs-D57AvEFu.js → backend-hostfs-MPHBq8u6.js} +1 -1
  17. package/dist/ui/assets/{browser-Cja95Zor.js → browser-lOfOvFLr.js} +642 -632
  18. package/dist/ui/assets/{cdp-h_BPeDae.js → cdp-BZr5FOvD.js} +1 -1
  19. package/dist/ui/assets/{cerebras-BVj2bFId.js → cerebras-Def_qTnM.js} +1 -1
  20. package/dist/ui/assets/{cerebras-BINd88DM.js → cerebras-hwNhqQrb.js} +1 -1
  21. package/dist/ui/assets/{composer-speech-C4P1wrBq.js → composer-speech-C7z2hUyU.js} +1 -1
  22. package/dist/ui/assets/{connect-surface-BOZaT8zF.js → connect-surface-DzBdDu0F.js} +1 -1
  23. package/dist/ui/assets/{cost-command-BZZ15zbR.js → cost-command-za5tV-xi.js} +1 -1
  24. package/dist/ui/assets/{directed-approval-C0AwARyp.js → directed-approval-BACdueb2.js} +1 -1
  25. package/dist/ui/assets/{emscripten-vfs-hook-I9U0qMWS.js → emscripten-vfs-hook-DJOrVwqh.js} +1 -1
  26. package/dist/ui/assets/{emscripten-vfs-hook-Dydz8mUS.js → emscripten-vfs-hook-DNWfHxzZ.js} +1 -1
  27. package/dist/ui/assets/{ensure-speech-assets-C7BqIxvE.js → ensure-speech-assets-DExppM1u.js} +1 -1
  28. package/dist/ui/assets/{frozen-archive-writer-BdhAPJA-.js → frozen-archive-writer-DV9dxndk.js} +1 -1
  29. package/dist/ui/assets/{fs-B2fd3m5O.js → fs-CpdJyYHq.js} +2 -2
  30. package/dist/ui/assets/{fs-CGwyt0NN.js → fs-DF0kyjO6.js} +1 -1
  31. package/dist/ui/assets/{gelatiere-store-BMIL9lQv.js → gelatiere-store-Blbokfar.js} +1 -1
  32. package/dist/ui/assets/{gelatiere-unit-CMya23QY.js → gelatiere-unit-DIWpdUpg.js} +1 -1
  33. package/dist/ui/assets/{github-DdvtTOtn.js → github-DtEnsnbl.js} +2 -2
  34. package/dist/ui/assets/{github-D-otjGSE.js → github-GnVIg6pC.js} +1 -1
  35. package/dist/ui/assets/{github-auth-DtKPkP6O.js → github-auth-CxbtOLix.js} +1 -1
  36. package/dist/ui/assets/{github-copilot-DJ4atTnp.js → github-copilot-Doz50sPf.js} +1 -1
  37. package/dist/ui/assets/{github-copilot-DhZpRpZ7.js → github-copilot-InpGcSFW.js} +1 -1
  38. package/dist/ui/assets/{github-install-CTgTDuO_.js → github-install-D6LtCUEz.js} +1 -1
  39. package/dist/ui/assets/{github-zip-B7ij9nSt.js → github-zip-Bc5S-lSD.js} +1 -1
  40. package/dist/ui/assets/{hear-BAzZhRH5.js → hear-DE-kdVg6.js} +1 -1
  41. package/dist/ui/assets/{help-Cda2RKb5.js → help-pAatI3yJ.js} +1 -1
  42. package/dist/ui/assets/{host-command-BUDUMrMx.js → host-command-BQ9cD7ut.js} +1 -1
  43. package/dist/ui/assets/installer-L1fqDJks.js +4 -0
  44. package/dist/ui/assets/{js-realm-worker-BOxTbSGf.js → js-realm-worker-DyJ9cjpk.js} +7 -7
  45. package/dist/ui/assets/{jsh-executor-CS83LMmZ.js → jsh-executor-CEDhJPuw.js} +3 -3
  46. package/dist/ui/assets/{jsh-runtime-extensions-DOE4hLxi.js → jsh-runtime-extensions-DiQ9SvKe.js} +1 -1
  47. package/dist/ui/assets/{kernel-worker-BJ0c96Mi.js → kernel-worker-DRjzxL4z.js} +10 -10
  48. package/dist/ui/assets/{lick-ws-bridge-DD_ESCbV.js → lick-ws-bridge-Dj_Pkx4k.js} +1 -1
  49. package/dist/ui/assets/{lick-ws-bridge-CcI6teSG.js → lick-ws-bridge-Ws2bWT5P.js} +1 -1
  50. package/dist/ui/assets/{live-session-curation-BZAOH9nA.js → live-session-curation-DwPSPSAA.js} +1 -1
  51. package/dist/ui/assets/{live-session-snapshot-CZ-B04Oo.js → live-session-snapshot-DEf-QY6I.js} +1 -1
  52. package/dist/ui/assets/{local-llm-tUt9259j.js → local-llm-BSr8n2n7.js} +1 -1
  53. package/dist/ui/assets/{local-llm-sjHLMR0H.js → local-llm-D9U8dpC5.js} +1 -1
  54. package/dist/ui/assets/{main-BxJYvn2p.js → main-CbOwhc79.js} +3 -3
  55. package/dist/ui/assets/{main-cherry-B6afTuP6.js → main-cherry-D79x1nLm.js} +1 -1
  56. package/dist/ui/assets/{memory-curation-seam-Cfdj18W8.js → memory-curation-seam-IxcUlymv.js} +1 -1
  57. package/dist/ui/assets/{memory-health-59w2sixO.js → memory-health-D5xoV18g.js} +1 -1
  58. package/dist/ui/assets/{memory-write-execute-c1nS7nAF.js → memory-write-execute-CJ0MlAt2.js} +1 -1
  59. package/dist/ui/assets/{mount-CwV2ETLu.js → mount-CMW93rGs.js} +1 -1
  60. package/dist/ui/assets/{mount-DU11qcVU.js → mount-LqqOAtXG.js} +3 -3
  61. package/dist/ui/assets/{new-session-C0-6JwTm.js → new-session-KXqiLL-g.js} +2 -2
  62. package/dist/ui/assets/{oauth-bootstrap-IhFv8x_G.js → oauth-bootstrap-BRjVNOtR.js} +2 -2
  63. package/dist/ui/assets/{onboarding-orchestrator-BPTv9Yh5.js → onboarding-orchestrator-_2vyomhi.js} +1 -1
  64. package/dist/ui/assets/{openai-codex-CSvp2o5O.js → openai-codex-BpfHK7OP.js} +1 -1
  65. package/dist/ui/assets/{openai-codex-B-_op7Op.js → openai-codex-CfFbLGxu.js} +1 -1
  66. package/dist/ui/assets/{openrouter-nhXX67Yd.js → openrouter-DLe9IBeZ.js} +1 -1
  67. package/dist/ui/assets/{openrouter-BtEOgbx4.js → openrouter-Dhzy392D.js} +1 -1
  68. package/dist/ui/assets/{openrouter-free-BWYrQTrf.js → openrouter-free-B0geQNLa.js} +1 -1
  69. package/dist/ui/assets/{openrouter-free-BCsuDfQ_.js → openrouter-free-y8pb25fa.js} +1 -1
  70. package/dist/ui/assets/{openrouter-oauth-Iu13nSWU.js → openrouter-oauth-CCBRIB3H.js} +1 -1
  71. package/dist/ui/assets/{openrouter-oauth-CHHX03dR.js → openrouter-oauth-Dr7xH6gM.js} +1 -1
  72. package/dist/ui/assets/{opfs-mount-DQ8hqRqi.js → opfs-mount-DNAC6uCc.js} +1 -1
  73. package/dist/ui/assets/{panel-rpc-handlers-gIjFzE4p.js → panel-rpc-handlers-BgCwxhaT.js} +2 -2
  74. package/dist/ui/assets/{panelize-shell-4Ckl1Rlr.js → panelize-shell-CC2aKjLE.js} +1 -1
  75. package/dist/ui/assets/{pi-edit-execution-DwX-a8w-.js → pi-edit-execution-_OFqm1q4.js} +1 -1
  76. package/dist/ui/assets/{provider-BvruW9_d.js → provider-BBchPEFm.js} +1 -1
  77. package/dist/ui/assets/{provider-Vc-3ZUEr.js → provider-rNKgeRry.js} +2 -2
  78. package/dist/ui/assets/{provider-settings-C0a7xTzz.js → provider-settings-CcL-7Ce-.js} +1 -1
  79. package/dist/ui/assets/provider-store-access-CG2e8EzW.js +1 -0
  80. package/dist/ui/assets/provider-store-access-afiHCPVB.js +1 -0
  81. package/dist/ui/assets/{providers-BUt9cTjL.js → providers-CAPQdKcc.js} +2 -2
  82. package/dist/ui/assets/{providers-DSnqrxU3.js → providers-CBpGiXaA.js} +1 -1
  83. package/dist/ui/assets/{py-live-vfs-DMc0LhCg.js → py-live-vfs-DeChUQwG.js} +2 -2
  84. package/dist/ui/assets/{py-live-vfs-Dm8bBjqR.js → py-live-vfs-Uud7Qmjl.js} +1 -1
  85. package/dist/ui/assets/{py-realm-worker-BaO89JAR.js → py-realm-worker-CpOMOUd5.js} +1 -1
  86. package/dist/ui/assets/{pyodide-DY17DXNV.js → pyodide-DFCa52VK.js} +2 -2
  87. package/dist/ui/assets/{quick-llm-CwMENyH2.js → quick-llm-CgT6r0ZO.js} +1 -1
  88. package/dist/ui/assets/realm-body-handles-BeoKKjy1.js +1 -0
  89. package/dist/ui/assets/{realm-inprocess-BPdEAS55.js → realm-inprocess-CiFoJQtp.js} +4 -4
  90. package/dist/ui/assets/realm-sync-transport-CuihwLFz.js +1 -0
  91. package/dist/ui/assets/{recovery-screen-nUj2S4Kl.js → recovery-screen--Af-FQUy.js} +1 -1
  92. package/dist/ui/assets/{remote-terminal-view-yc1ctoH3.js → remote-terminal-view-OpkjfE0P.js} +1 -1
  93. package/dist/ui/assets/{require-guards-DPf5QETL.js → require-guards-DyoCy2Tn.js} +1 -1
  94. package/dist/ui/assets/{restore-5Pd0vEqt.js → restore-CxpX56qq.js} +1 -1
  95. package/dist/ui/assets/{run-Bm5wfw7W.js → run-B9n8WrBZ.js} +2 -2
  96. package/dist/ui/assets/{run-B7JwvoYv.js → run-BreyHZHn.js} +1 -1
  97. package/dist/ui/assets/{run-BXtEkg8U.js → run-CFXUPx7_.js} +2 -2
  98. package/dist/ui/assets/{run-Jp_ZOByn.js → run-CUfbL4TT.js} +2 -2
  99. package/dist/ui/assets/{run-DCB_d0xn.js → run-CcJdU-Hm.js} +1 -1
  100. package/dist/ui/assets/{run-BPIWk2Dz.js → run-Ch01vfKx.js} +1 -1
  101. package/dist/ui/assets/{run-BCW6JYCx.js → run-DR7aMRhL.js} +1 -1
  102. package/dist/ui/assets/{run-oxE2jfCs.js → run-DnymiHD7.js} +1 -1
  103. package/dist/ui/assets/{run-CgPXJKZ-.js → run-F1o8qnmE.js} +2 -2
  104. package/dist/ui/assets/{session-command-memory-BWg7sIYO.js → session-command-memory-BhlrMZGp.js} +2 -2
  105. package/dist/ui/assets/{session-jsonl-Bhp6wipk.js → session-jsonl-ClT-JWp_.js} +1 -1
  106. package/dist/ui/assets/{session-jsonl-BiCcpvNV.js → session-jsonl-DC7cWpaZ.js} +1 -1
  107. package/dist/ui/assets/{session-search-index-BqxvtCBQ.js → session-search-index-CvchXWPz.js} +1 -1
  108. package/dist/ui/assets/{setup-feature-flags-remote-CYBfAxiL.js → setup-feature-flags-remote-CkUiZ2Ze.js} +1 -1
  109. package/dist/ui/assets/{setup-model-catalog-Dmni1WC1.js → setup-model-catalog-yB6VyINC.js} +1 -1
  110. package/dist/ui/assets/{signed-fetch-CPM5oMES.js → signed-fetch-K4qaZ6Ue.js} +1 -1
  111. package/dist/ui/assets/{silent-renew-backoff-ThMSvZZl.js → silent-renew-backoff-t6XaSrQD.js} +1 -1
  112. package/dist/ui/assets/slicc-version-Chtfcn49.js +1 -0
  113. package/dist/ui/assets/{snapshot-DUtYnaet.js → snapshot-CH6SwWeT.js} +1 -1
  114. package/dist/ui/assets/{snapshot-features-DeyPsTfS.js → snapshot-features-I3eA0V-k.js} +1 -1
  115. package/dist/ui/assets/{soundscape-9E8QV2kT.js → soundscape-aQxOh10J.js} +1 -1
  116. package/dist/ui/assets/{speak-B3zyT2Ll.js → speak-C-HEIK4L.js} +1 -1
  117. package/dist/ui/assets/{sprinkle-manager-C_xPQk_d.js → sprinkle-manager-CIFGQlrz.js} +1 -1
  118. package/dist/ui/assets/{sprinkle-renderer-PJtkMKp5.js → sprinkle-renderer-MPnIDdVY.js} +1 -1
  119. package/dist/ui/assets/{ssh-Ca0IyfQK.js → ssh-D03rg-3P.js} +1 -1
  120. package/dist/ui/assets/{state-fLtv6usH.js → state-Daa8jIBa.js} +1 -1
  121. package/dist/ui/assets/{store-CeiTFba0.js → store-BvJSXww9.js} +1 -1
  122. package/dist/ui/assets/{store-CS22MHEy.js → store-DsSEiLWM.js} +1 -1
  123. package/dist/ui/assets/{sudo-B-FlSan1.js → sudo-bCcOXm14.js} +1 -1
  124. package/dist/ui/assets/{supervisor-qNiNIhSg.js → supervisor-DxFMqnF7.js} +1 -1
  125. package/dist/ui/assets/{sync-dialog-nKWUK7fT.js → sync-dialog-CFiETB2A.js} +1 -1
  126. package/dist/ui/assets/{sync-exec-dispatch-CEbwf9Az.js → sync-exec-dispatch-BwrIjhDd.js} +1 -1
  127. package/dist/ui/assets/{transformers-env-B3GpaxuZ.js → transformers-env-lAvFqMAL.js} +1 -1
  128. package/dist/ui/assets/{tray-leader-CYp-DQMu.js → tray-leader-DyM_b_so.js} +1 -1
  129. package/dist/ui/assets/{tray-leave-runtime-tEMCrIY2.js → tray-leave-runtime-0UMRiTF_.js} +1 -1
  130. package/dist/ui/assets/{tray-sidecar-4C7VUy9Q.js → tray-sidecar-DOiJE8Jc.js} +1 -1
  131. package/dist/ui/assets/{upgrade-detection-BZipCNim.js → upgrade-detection-BBrpZ3fl.js} +1 -1
  132. package/dist/ui/assets/{upskill-lick-skip-CAvgv_ri.js → upskill-lick-skip-CTf8LMtq.js} +1 -1
  133. package/dist/ui/assets/{voice-reply-1yeNMEnU.js → voice-reply-BEe3HnVg.js} +1 -1
  134. package/dist/ui/assets/{wc-attach-Bmr96lo2.js → wc-attach-DtDxRmHe.js} +2 -2
  135. package/dist/ui/assets/{wc-browser-CFWI2FeJ.js → wc-browser-CA-k7nY-.js} +1 -1
  136. package/dist/ui/assets/{wc-computers-B9NC1Ue0.js → wc-computers-BsR3yA3j.js} +1 -1
  137. package/dist/ui/assets/{wc-detached-CjTNI4rY.js → wc-detached-VOfp49rt.js} +1 -1
  138. package/dist/ui/assets/{wc-extension-BcE7UaX7.js → wc-extension-CzPYl7z_.js} +2 -2
  139. package/dist/ui/assets/{wc-follower-DE4kJ5Rn.js → wc-follower-DE3ADV47.js} +3 -3
  140. package/dist/ui/assets/{wc-follower-oauth-DHlE6ql1.js → wc-follower-oauth-BZJVyyms.js} +1 -1
  141. package/dist/ui/assets/{wc-gelatiere-0HIlLrum.js → wc-gelatiere-9WKKPVV5.js} +1 -1
  142. package/dist/ui/assets/{wc-live-DKnjSwhd.js → wc-live-g86dmTNK.js} +5 -5
  143. package/dist/ui/assets/{wc-nav-GtDOyEGR.js → wc-nav-Bgwx5ECQ.js} +2 -2
  144. package/dist/ui/assets/{wc-onboarding-B6t6zCns.js → wc-onboarding-WrKzKn9i.js} +2 -2
  145. package/dist/ui/assets/{wc-permissions-hTpsWKNG.js → wc-permissions-Fo69X8BW.js} +2 -2
  146. package/dist/ui/assets/{wc-placeholder-CgtGXSv5.js → wc-placeholder-CMqqSTR1.js} +3 -3
  147. package/dist/ui/assets/{wc-secret-request-ButBnUJH.js → wc-secret-request-CGNiHFSX.js} +1 -1
  148. package/dist/ui/assets/{wc-settings-DIjjwws4.js → wc-settings-vlsLwwRX.js} +3 -3
  149. package/dist/ui/assets/{wc-shell-Dz1_0PFH.js → wc-shell-BCLvj6_o.js} +3 -3
  150. package/dist/ui/assets/{wc-shortcut-config-D6CuLO30.js → wc-shortcut-config-g8iW-xo-.js} +1 -1
  151. package/dist/ui/assets/{wc-sprinkles-Bc29I0Xy.js → wc-sprinkles-DiJtWeIx.js} +2 -2
  152. package/dist/ui/assets/{wc-transcript-export-yLjd8vVn.js → wc-transcript-export-Cubr1DB_.js} +2 -2
  153. package/dist/ui/assets/{wc-tray-AjdLCp0o.js → wc-tray-CWLisX78.js} +4 -4
  154. package/dist/ui/assets/welcome-detection-B6FunPhS.js +1 -0
  155. package/dist/ui/assets/{whisper-session-Q3OwxGiv.js → whisper-session-rpeX9FhX.js} +2 -2
  156. package/dist/ui/assets/{xai-grok-C7_Vjmtd.js → xai-grok-83T7U6MO.js} +1 -1
  157. package/dist/ui/assets/{xai-grok-C_rWJJ_o.js → xai-grok-DzQmYRGn.js} +1 -1
  158. package/dist/ui/index.html +3 -3
  159. package/dist/ui/llm-proxy-sw.js +1 -1
  160. package/dist/ui/packages/webapp/index.html +3 -3
  161. package/package.json +2 -1
  162. package/dist/ui/assets/__vite-browser-external-CJkRLpJ-.js +0 -1
  163. package/dist/ui/assets/installer-DsU9Bt88.js +0 -4
  164. package/dist/ui/assets/provider-store-access-CIdsyXCw.js +0 -1
  165. package/dist/ui/assets/provider-store-access-T6xp0Y3c.js +0 -1
  166. package/dist/ui/assets/realm-body-handles-DtLxL_rB.js +0 -1
  167. package/dist/ui/assets/realm-sync-transport-Bii99lU6.js +0 -1
  168. package/dist/ui/assets/slicc-version-Bq7GVQX1.js +0 -1
  169. package/dist/ui/assets/welcome-detection-Bcatt_wO.js +0 -1
@@ -1,5 +1,5 @@
1
- import{t as e}from"./logger-LESFN7Hj.js";import{t}from"./content-type-_QKWY0B2.js";import"./proxied-fetch-DXaTHROw.js";import{i as n,r}from"./panel-rpc-DW7W4w6_.js";import{t as i}from"./fetch-body-CuwTaJC_.js";import{a}from"./path-utils-DNJG-zQf.js";import{r as o,t as s}from"./multipart-form-data-DopbgwRR.js";import"./tray-storage-keys-DbThbnIh.js";import"./tray-runtime-config-CTm013-K.js";import{n as c,t as l}from"./picker-popup-B6AyYTBw.js";import{t as u}from"./process-manager-BkhAohXT.js";import{C as d,N as f,b as p,d as m,g as h,p as g,t as ee,x as te,y as _}from"./shared-DfMXB1pm.js";import{t as ne}from"./require-guards-DPf5QETL.js";import{n as v}from"./esbuild-wasm-CeZYVyQ9.js";import{t as re}from"./wasm-compiler-Ct7QZURL.js";import{a as y,i as ie,n as ae,o as oe,s as se,t as ce}from"./usb-device-registry-DFzxaOky.js";import{C as le,a as ue,b as de,c as fe,i as pe,m as me,o as he,r as ge,x as _e}from"./sync-exec-dispatch-CEbwf9Az.js";import{a as ve,o as ye,s as be}from"./sync-sab-wire-D_d0fd3b.js";import{i as xe}from"./just-bash-compat-B-SPHuh_.js";let b,x;function S(){return async({kind:e,ctx:t})=>{if(e===`py`){if(typeof Worker<`u`)return Ce();if(!x){let{createInProcessPyRealmFactory:e}=await import(`./realm-inprocess-BPdEAS55.js`);x=e()}return x({kind:e,ctx:t})}if(typeof Worker<`u`)return Se();if(!b){let{createInProcessJsRealmFactory:e}=await import(`./realm-inprocess-BPdEAS55.js`);b=e()}return b({kind:e,ctx:t})}}function Se(){if(typeof Worker>`u`)throw Error(`realm-factory: Worker is not available in this runtime`);return we(new Worker(new URL(`/assets/js-realm-worker-BOxTbSGf.js`,``+import.meta.url),{type:`module`}))}function Ce(){if(typeof Worker>`u`)throw Error(`realm-factory: Worker is not available in this runtime`);return we(new Worker(new URL(`/assets/py-realm-worker-BaO89JAR.js`,``+import.meta.url),{type:`module`}))}function we(e){let t={postMessage:(t,n)=>n?e.postMessage(t,n):e.postMessage(t),addEventListener:(t,n)=>e.addEventListener(t,n),removeEventListener:(t,n)=>e.removeEventListener(t,n)},n=!1;return{controlPort:t,isolatedThread:!0,addEventListener:(t,n,r)=>e.addEventListener(t,n,r),removeEventListener:(t,n)=>e.removeEventListener(t,n),terminate(){if(!n){n=!0;try{e.terminate()}catch{}}}}}function Te(){if(g())return decodeURIComponent(h(`pyodide/pyodide.mjs`,`../../../../../node_modules/pyodide/`).pathname)}function Ee(e){let t=e.startsWith(`/`)?e:`/${e}`;return new URL(`file://${t}`).href}function C(e){return e instanceof Error?e.message:String(e)}function De(e){return`${(e&&e.length>0?e:`[eval]`).replace(/\.[^./]+$/,``)}.js`}async function Oe(e,t,n,r){return(await(await e()).transform(t,{loader:`js`,format:`cjs`,sourcefile:De(n),supported:{"dynamic-import":!1},define:{"import.meta.url":JSON.stringify(r)}})).code}async function ke(e,t,n,r){return(await(await e()).transform(t,{loader:`js`,format:`cjs`,sourcefile:De(n),supported:{"dynamic-import":!1},...r?{define:{"import.meta.url":JSON.stringify(r)}}:{}})).code}const Ae=/\bimport\s*\.\s*meta\s*\.\s*url\b/g,je=/\bimport\s*\.\s*meta\b/g;function Me(e,t){let n=JSON.stringify(t);return e.replace(Ae,n).replace(je,`({ url: ${n} })`)}async function w(e,t,n,r){let i=await e();return i.transpileModule(Me(t,r),{compilerOptions:{module:i.ModuleKind.CommonJS,target:i.ScriptTarget.ES2020,esModuleInterop:!0},fileName:`${n.replace(/\.[^./]+$/,``)}.ts`}).outputText}function Ne(e={}){let{ipk:t}=e,n=e.loadEsbuild??(()=>v(t?{ipk:t}:{})),r=e.loadTypeScript??(()=>m(t));return async({source:e,path:t,kind:i})=>{if(i!==`esm`||!p(e))return e;let a=Ee(t),o;try{return await Oe(n,e,t,a)}catch(e){o=e}try{return await w(r,e,t,a)}catch(e){throw Error(`Failed to transpile ESM module '${t}': ${C(o)}; typescript fallback: ${C(e)}`)}}}function T(e={}){let{ipk:t}=e,n=e.loadEsbuild??(()=>v(t?{ipk:t}:{})),r=e.loadTypeScript??(()=>m(t));return async({source:e,filename:t})=>{if(!p(e)&&!_(e))return e;let i=typeof t==`string`&&t.startsWith(`/`),a=i?Ee(t):void 0,o=i?t:`[eval].js`,s;try{return await ke(n,e,t,a)}catch(e){s=e}try{return await w(r,e,o,a??``)}catch(e){throw Error(`Failed to transpile entry source: ${C(s)}; typescript fallback: ${C(e)}`)}}}function E(e,t){if(!e.startsWith(`#!`))return e;let n=e.indexOf(`
2
- `);if(n===-1)return``;let r=e.slice(n+1);return t?.keepLine?`\n${r}`:r}function Pe(e){return a(e).dir}const D=[`node`,`require`,`default`],O=[`node`,`import`,`default`],Fe=/\brequire\s*\(\s*(['"`])([^'"`\s]+)\1\s*\)/g,Ie=/\bimport\s*\(\s*(['"`])([^'"`\s]+)\1\s*\)/g,Le=/(?:^|[;\n}])\s*import\b[\s\S]*?\bfrom\s*(['"])([^'"]+)\1/g,Re=/(?:^|[;\n}])\s*export\b[\s\S]*?\bfrom\s*(['"])([^'"]+)\1/g,ze=/(?:^|[;\n}])\s*import\s*(['"])([^'"]+)\1/g;function Be(e,t,n){let r=t[0].indexOf(n);return r<0?!1:e.startsWith(n,t.index+r)}function Ve(e){let t=te(e),n=new Map,r=(r,i,a)=>{r.lastIndex=0;let o;for(;(o=r.exec(e))!==null;){if(!Be(t,o,a))continue;let e=o[2];n.get(e)!==`import`&&n.set(e,i)}};return r(Fe,`require`,`require`),r(Ie,`import`,`import`),r(Le,`import`,`import`),r(Re,`import`,`export`),r(ze,`import`,`import`),[...n].map(([e,t])=>({specifier:e,kind:t}))}async function He(e,t,n,r){if(n===`json`)return`module.exports = JSON.parse(${JSON.stringify(e)});\n`;let i=E(e);if(n===`esm`){if(!r)throw Error(`Cannot load ESM module '${t}': no transpile hook configured (run: ${ee} esbuild-wasm)`);return await r({source:i,path:t,kind:n})}return i}async function Ue(e){let{entrySpecifiers:t,fromDir:n,reader:r,conditions:i,transpile:a}=e,o=e.requireConditions??D,s=e.importConditions??O,c=i??o,l=new Map,u=[],f={},p={};async function m(e,t){if(l.has(e))return;let n=await r.readFile(e),i=await He(n,e,t,a);l.set(e,{path:e,source:n,cjsSource:i,kind:t});let c=Pe(e),h={},g={};for(let{specifier:e,kind:t}of Ve(n)){let n;try{n=await d(e,c,r,{conditions:t===`import`?s:o})}catch(t){g[e]=t instanceof Error?t.message:String(t);continue}n.type===`file`&&(h[e]=n.path,await m(n.path,n.moduleKind))}f[e]=h,Object.keys(g).length>0&&(p[e]=g),u.push(e)}let h={};for(let e of t){let t=await d(e,n,r,{conditions:c});t.type===`file`&&(h[e]=t.path,await m(t.path,t.moduleKind))}return{files:u.map(e=>{let t=l.get(e);if(!t)throw Error(`module-loader: missing built module for '${e}'`);return t}),entryMap:h,edges:f,edgeErrors:p}}function We(e){return!(e.startsWith(`sliccy:`)||e.startsWith(`node:`)||f.has(e)||ne.has(e))}function Ge(e,t){for(let[n,r]of Object.entries(t))e[n]={...e[n]??{},...r}}async function Ke(e){let{entryCode:t,fromDir:n,entryFilename:r,reader:i,transpile:a,transpileEntry:o}=e,s=new Map,c=[],l={},u={},d={},f={};for(let{specifier:e,kind:r}of Ve(t))if(We(e))try{let t=await Ue({entrySpecifiers:[e],fromDir:n,reader:i,transpile:a,conditions:r===`import`?O:D,requireConditions:D,importConditions:O});for(let e of t.files)s.has(e.path)||(s.set(e.path,e),c.push(e.path));Object.assign(l,t.entryMap),Ge(u,t.edges),Ge(d,t.edgeErrors)}catch(t){f[e]=t instanceof Error?t.message:String(t)}let m;o&&(p(t)||_(t))&&(m=await o({source:t,filename:r??`[eval]`,fromDir:n}));let h={files:c.map(e=>{let t=s.get(e);if(!t)throw Error(`module-loader: missing built module for '${e}'`);return{path:t.path,cjsSource:t.cjsSource,kind:t.kind}}),entryMap:l,edges:u,edgeErrors:d,errors:f};return m!==void 0&&(h.entrySource=m),m!==void 0&&p(t)&&(h.entryIsModule=!0),h}function k(){return globalThis.navigator?.hid??null}function qe(e){let t=e.collections?.[0];return t?`${t.usagePage??``}:${t.usage??``}`:``}function Je(e,t){return e===t||e.vendorId===t.vendorId&&e.productId===t.productId&&(e.productName??``)===(t.productName??``)&&qe(e)===qe(t)&&!!e.productName}var Ye=class{byHandle=new Map;counter=0;register(e){for(let[t,n]of this.byHandle)if(Je(n,e))return this.byHandle.set(t,e),t;let t=`hid${++this.counter}`;return this.byHandle.set(t,e),t}get(e){return this.byHandle.get(e)}remove(e){return this.byHandle.delete(e)}list(){return[...this.byHandle].map(([e,t])=>({handle:e,device:t}))}};let Xe=null;function Ze(){return Xe||=new Ye,Xe}const Qe=4194304;function A(e,t){let n=t.collections?.[0];return{handle:e,vendorId:t.vendorId,productId:t.productId,...t.productName?{productName:t.productName}:{},...n?.usagePage===void 0?{}:{usagePage:n.usagePage},...n?.usage===void 0?{}:{usage:n.usage},opened:t.opened}}function j(e,t){let n=e.get(t);if(!n)throw Error(`unknown hid handle '${t}'`);return n}async function M(e){e.opened||await e.open()}function N(e,t){if(e>4194304)throw Error(`${t} exceeds the ${Qe}-byte (4 MiB) v1 limit`)}function P(e){let t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),t}async function $e(e,t){return(await t.getDevices()).map(t=>A(e.register(t),t))}async function et(e,t,n){let r=await t.requestDevice({filters:n});if(r.length===0)throw Error(`No device selected.`);return r.map(t=>A(e.register(t),t))}function tt(e,t){return A(t,j(e,t))}async function nt(e,t){await j(e,t).open()}async function rt(e,t){await j(e,t).close()}async function it(e,t,n,r){N(r.byteLength,`send report payload`);let i=j(e,t);await M(i),await i.sendReport(n,r)}async function at(e,t,n,r){N(r.byteLength,`send feature report payload`);let i=j(e,t);await M(i),await i.sendFeatureReport(n,r)}async function ot(e,t,n){let r=j(e,t);return await M(r),{reportId:n,bytes:P(await r.receiveFeatureReport(n))}}async function st(e,t,n){let r=j(e,t);await M(r);let i=e=>{n({reportId:e.reportId,bytes:P(e.data)})};return r.addEventListener(`inputreport`,i),()=>r.removeEventListener(`inputreport`,i)}const F=6e4;function ct(){return l()}function lt(e){return new Promise(t=>{let n=!1,r=e=>{n||(n=!0,clearTimeout(i),t(e))},i=setTimeout(()=>r({cancelled:!0}),F);c(`hid-device`,e??[],void 0,{timeoutMs:F}).then(e=>{let t=e;t.cancelled?r({cancelled:!0}):typeof t.error==`string`?r({error:t.error}):t.granted&&t.info?r({granted:!0,info:t.info}):r({error:`hid picker returned an unexpected response`})}).catch(e=>{r({error:e instanceof Error?e.message:`Failed to open HID picker`})})})}function I(e){let t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(e),t}var ut=class{registry;constructor(e){this.registry=e}hid(){let e=k();if(!e)throw Error(`WebHID is unavailable in this browser`);return e}list(){return $e(this.registry,this.hid())}async request(e){if(ct()){let t=await lt(e);if(`cancelled`in t)throw Error(`user cancelled the HID picker`);if(`error`in t)throw Error(t.error);let n=await this.reacquireAll(t.info);if(n.length===0)throw Error(`granted device could not be re-acquired`);return n.map(e=>A(this.registry.register(e),e))}return et(this.registry,this.hid(),e)}async reacquireAll(e){return(await this.hid().getDevices()).filter(t=>t.vendorId===e.vendorId&&t.productId===e.productId)}info(e){return Promise.resolve(tt(this.registry,e))}open(e){return nt(this.registry,e)}close(e){return rt(this.registry,e)}sendReport(e,t,n){return it(this.registry,e,t,I(n))}sendFeatureReport(e,t,n){return at(this.registry,e,t,I(n))}async receiveFeatureReport(e,t){let n=await ot(this.registry,e,t);return{reportId:n.reportId,bytes:new Uint8Array(n.bytes)}}async subscribeInputReports(e,t){return st(this.registry,e,e=>t({reportId:e.reportId,bytes:new Uint8Array(e.bytes)}))}},dt=class e{rpc;constructor(e){this.rpc=e}static REQUEST_TIMEOUT_MS=3e5;async list(){return(await this.rpc.call(`hid-list`,void 0)).devices}async request(t){return(await this.rpc.call(`hid-request`,{filters:t},{timeoutMs:e.REQUEST_TIMEOUT_MS})).devices}async info(e){return(await this.rpc.call(`hid-device-info`,{handle:e})).device}async open(e){await this.rpc.call(`hid-open`,{handle:e})}async close(e){await this.rpc.call(`hid-close`,{handle:e})}async sendReport(e,t,n){await this.rpc.call(`hid-send-report`,{handle:e,reportId:t,bytes:I(n)})}async sendFeatureReport(e,t,n){await this.rpc.call(`hid-send-feature-report`,{handle:e,reportId:t,bytes:I(n)})}async receiveFeatureReport(e,t){let n=await this.rpc.call(`hid-receive-feature-report`,{handle:e,reportId:t});return{reportId:n.reportId,bytes:new Uint8Array(n.bytes)}}async subscribeInputReports(e,t){let n=this.rpc.onEvent(`hid-input-report`,n=>{let r=n;!r||r.handle!==e||t({reportId:r.reportId,bytes:new Uint8Array(r.bytes)})});try{await this.rpc.call(`hid-subscribe-input-reports`,{handle:e})}catch(e){throw n(),e}return async()=>{n();try{await this.rpc.call(`hid-unsubscribe-input-reports`,{handle:e})}catch{}}}};function L(e,t){return e&&k()?new ut(Ze()):t?new dt(t):null}function ft(e){return async function(t,n){let r=t instanceof Request?t:null,i=pt(t),a=(n?.method??r?.method??`GET`).toUpperCase(),o=ht(r?.headers,n?.headers),s=await _t(n,r,a,o);s.defaultContentType&&!gt(o,`content-type`)&&(o[`Content-Type`]=s.defaultContentType);let c=await e(i,{method:a,headers:o,body:s.body}),l=new Headers;for(let[e,t]of Object.entries(c.headers))try{l.set(e,t)}catch{}let u=c.status===204||c.status===205||c.status===304||!c.body||c.body.byteLength===0?null:c.body,d=new Response(u,{status:c.status,statusText:c.statusText,headers:l});try{Object.defineProperty(d,"url",{value:c.url||i,writable:!1,configurable:!0,enumerable:!1})}catch{}return d}}function pt(e){return typeof e==`string`?e:e instanceof URL?e.toString():e.url}function mt(e){if(e){if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}if(Array.isArray(e)){let t={};for(let[n,r]of e)t[n]=r;return t}return{...e}}}function ht(e,t){let n={};e&&e.forEach((e,t)=>{n[t]=e});let r=mt(t);if(r)for(let[e,t]of Object.entries(r))n[e]=t;return n}function gt(e,t){return R(e,t)!==void 0}function R(e,t){let n=t.toLowerCase(),r;for(let[t,i]of Object.entries(e))t.toLowerCase()===n&&(r=i);return r}async function _t(e,n,r,a){if(e&&`body`in e&&e.body!==void 0)return vt(e.body,r);if(n&&r!==`GET`&&r!==`HEAD`){let e=n.body!==null,r=new Uint8Array(await n.arrayBuffer()),o=R(a,`content-type`)??``,s=e&&(!o||!t(o));return{body:r.byteLength===0?void 0:s?i(r):new TextDecoder(`utf-8`).decode(r),defaultContentType:s?`application/octet-stream`:void 0}}return{}}async function vt(e,t){if(o(e)){if(t===`GET`||t===`HEAD`)return{};let n=await s(e);return{body:n.bytes,defaultContentType:n.contentType}}return{body:await yt(e,t),defaultContentType:xt(e,t)}}async function yt(e,t){if(e!=null&&t!==`GET`&&t!==`HEAD`){if(typeof e==`string`)return e;if(e instanceof URLSearchParams)return e.toString();if(e instanceof Uint8Array)return i(e);if(e instanceof ArrayBuffer)return new Uint8Array(e).slice();if(ArrayBuffer.isView(e)){let t=e;return new Uint8Array(t.buffer,t.byteOffset,t.byteLength).slice()}if(typeof Blob<`u`&&e instanceof Blob)return new Uint8Array(await e.arrayBuffer());throw typeof ReadableStream<`u`&&e instanceof ReadableStream?Error(`node fetch shim: ReadableStream request bodies are not supported (collect into a Uint8Array or string before calling fetch)`):Error(`node fetch shim: unsupported request body type (${Object.prototype.toString.call(e)}); use a string, Uint8Array, ArrayBuffer, Blob, FormData, or URLSearchParams`)}}function bt(e){return e instanceof Uint8Array||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||typeof Blob<`u`&&e instanceof Blob}function xt(e,t){if(e instanceof URLSearchParams)return`application/x-www-form-urlencoded;charset=UTF-8`;if(!(t===`GET`||t===`HEAD`||!bt(e)))return typeof Blob<`u`&&e instanceof Blob&&e.type?e.type:`application/octet-stream`}function z(){return globalThis.navigator?.serial??null}var St=class{byHandle=new Map;counter=0;register(e){for(let[t,n]of this.byHandle)if(n.port===e)return t;let t=`serial${++this.counter}`;return this.byHandle.set(t,{port:e,opened:!1}),t}get(e){return this.byHandle.get(e)}remove(e){return this.byHandle.delete(e)}list(){return[...this.byHandle].map(([e,t])=>({handle:e,entry:t}))}retainOnly(e){let t=[];for(let[n,r]of[...this.byHandle])e.includes(r.port)||(this.byHandle.delete(n),t.push({handle:n,entry:r}));return t}};let B=null;function V(){return B||=new St,B}const H=4194304;function U(e,t){let n=t.port.getInfo();return{handle:e,...n.usbVendorId===void 0?{}:{usbVendorId:n.usbVendorId},...n.usbProductId===void 0?{}:{usbProductId:n.usbProductId},opened:t.opened}}function W(e,t){let n=e.get(t);if(!n)throw Error(`unknown serial handle '${t}'`);return n}function Ct(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e),n.set(t,e.length),n}function wt(e,t,n){if(t.length===0)return-1;outer:for(let r=Math.max(0,n);r+t.length<=e.length;r++){for(let n=0;n<t.length;n++)if(e[r+n]!==t[n])continue outer;return r}return-1}async function G(e){if(e.reader){try{await e.reader.cancel()}catch{}try{e.reader.releaseLock()}catch{}e.reader=void 0}if(e.pendingRead=void 0,e.leftover=void 0,e.writer){try{e.writer.releaseLock()}catch{}e.writer=void 0}}async function Tt(e){if(await G(e),e.opened){try{await e.port.close()}catch{}e.opened=!1}}async function Et(e,t){let n=await t.getPorts();for(let{entry:t}of e.retainOnly(n))await Tt(t);return n.map(t=>{let n=e.register(t);return U(n,e.get(n))})}async function Dt(e,t,n){let r=await t.requestPort(n.length?{filters:n}:{}),i=e.register(r);return U(i,e.get(i))}function Ot(e,t){return U(t,W(e,t))}async function kt(e,t,n){let r=W(e,t);try{await r.port.open(n)}catch(e){throw Error(`${e instanceof Error?e.message:String(e)} (handle '${t}' may be stale after a device reset — re-run 'serial list' to pick up the current handle)`)}r.opened=!0}async function At(e,t){let n=W(e,t);await G(n);try{await n.port.close()}catch(e){if(!jt(e))throw e}n.opened=!1}function jt(e){let t=e instanceof Error?e.message:String(e);return/already closed|not open/i.test(t)}function Mt(e){if(!e.reader){if(!e.port.readable)throw Error(`serial port is not readable (is it open?)`);e.reader=e.port.readable.getReader()}return e.reader}function Nt(e){if(!e.writer){if(!e.port.writable)throw Error(`serial port is not writable (is it open?)`);e.writer=e.port.writable.getWriter()}return e.writer}async function Pt(e,t,n){let r=W(e,t),i=Math.min(n.maxBytes??4194304,H),a=n.until?.length?n.until:void 0,o=n.timeoutMs??1e3,s=Date.now()+Math.max(0,o),c=r.leftover??new Uint8Array;r.leftover=void 0;let l=0,u=()=>{if(a){let e=wt(c,a,Math.max(0,l-(a.length-1)));if(e>=0){let t=e+a.length;return r.leftover=c.slice(t),c.slice(0,t)}}return c.length>=i?(r.leftover=c.slice(i),c.slice(0,i)):null},d=u();if(d)return d;let f=Mt(r);for(;Date.now()<s;){let e=s-Date.now(),t=r.pendingRead??f.read();r.pendingRead=t;let n,i=new Promise(t=>{n=setTimeout(()=>t(`__timeout`),e)}),a;try{a=await Promise.race([t,i])}finally{n&&clearTimeout(n)}if(a===`__timeout`)break;if(r.pendingRead=void 0,a.done){r.reader=void 0;break}if(a.value?.length){l=c.length,c=Ct(c,a.value);let e=u();if(e)return e}}return c}async function Ft(e,t,n){if(n.length>4194304)throw Error(`serial write payload exceeds the ${H}-byte (4 MiB) v1 limit`);return await Nt(W(e,t)).write(n),n.length}async function It(e,t){return W(e,t).port.getSignals()}async function Lt(e,t,n){await W(e,t).port.setSignals(n)}const Rt=6e4;function zt(){return l()}function Bt(e){return new Promise(t=>{let n=!1,r=e=>{n||(n=!0,clearTimeout(i),t(e))},i=setTimeout(()=>r({cancelled:!0}),Rt);c(`serial-port`,e??[],void 0,{timeoutMs:Rt}).then(e=>{let t=e;t.cancelled?r({cancelled:!0}):typeof t.error==`string`?r({error:t.error}):t.granted&&t.info?r({granted:!0,info:t.info}):r({error:`serial picker returned an unexpected response`})}).catch(e=>{r({error:e instanceof Error?e.message:`Failed to open serial picker`})})})}function Vt(e){let t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(e),t}var Ht=class{registry;constructor(e){this.registry=e}serial(){let e=z();if(!e)throw Error(`Web Serial is unavailable in this browser`);return e}list(){return Et(this.registry,this.serial())}async request(e){if(zt()){let t=await Bt(e);if(`cancelled`in t)throw Error(`user cancelled the serial picker`);if(`error`in t)throw Error(t.error);let n=await this.reacquire(t.info);if(!n)throw Error(`granted port could not be re-acquired`);let r=this.registry.register(n);return U(r,this.registry.get(r))}return Dt(this.registry,this.serial(),e)}async reacquire(e){let t=await this.serial().getPorts(),n=t.filter(t=>{let n=t.getInfo();return!(e.usbVendorId!==void 0&&n.usbVendorId!==e.usbVendorId||e.usbProductId!==void 0&&n.usbProductId!==e.usbProductId)}),r=n.length?n:t,i=this.registry.list().map(e=>e.entry.port);return r.find(e=>!i.includes(e))??r[0]??null}info(e){return Promise.resolve(Ot(this.registry,e))}open(e,t){return kt(this.registry,e,t)}close(e){return At(this.registry,e)}read(e,t){return Pt(this.registry,e,t)}write(e,t){return Ft(this.registry,e,t)}getSignals(e){return It(this.registry,e)}setSignals(e,t){return Lt(this.registry,e,t)}},Ut=class e{rpc;constructor(e){this.rpc=e}static REQUEST_TIMEOUT_MS=3e5;static READ_MARGIN_MS=3e4;async list(){return(await this.rpc.call(`serial-list`,void 0)).devices}async request(t){return(await this.rpc.call(`serial-request`,{filters:t},{timeoutMs:e.REQUEST_TIMEOUT_MS})).device}async info(e){return(await this.rpc.call(`serial-device-info`,{handle:e})).device}async open(e,t){await this.rpc.call(`serial-open`,{handle:e,options:t})}async close(e){await this.rpc.call(`serial-close`,{handle:e})}async read(t,n){let r=(n.timeoutMs??1e3)+e.READ_MARGIN_MS,i=await this.rpc.call(`serial-read`,{handle:t,maxBytes:n.maxBytes,until:n.until?Vt(n.until):void 0,timeoutMs:n.timeoutMs},{timeoutMs:r});return new Uint8Array(i.bytes)}async write(e,t){return(await this.rpc.call(`serial-write`,{handle:e,bytes:Vt(t)})).bytesWritten}async getSignals(e){return(await this.rpc.call(`serial-get-signals`,{handle:e})).signals}async setSignals(e,t){await this.rpc.call(`serial-set-signals`,{handle:e,signals:t})}};function Wt(e,t){return e&&z()?new Ht(V()):t?new Ut(t):null}const Gt=e(`usb`);async function K(){return import(`./usb-claim-broker-C5dFP5bv.js`)}function q(e,t){let n=e.get(t);if(!n)throw Error(`unknown usb handle '${t}'`);return n}function J(e,t){if(e>4194304)throw Error(`${t} exceeds the ${ce}-byte (4 MiB) v1 limit`)}function Kt(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}async function qt(e,t){return(await t.getDevices()).map(t=>y(e.register(t),t))}async function Jt(e,t,n){let r=await t.requestDevice({filters:n});return y(e.register(r),r)}function Yt(e,t){return y(t,q(e,t))}async function Xt(e,t){await q(e,t).open()}async function Zt(e,t,n){await cn(e,t,`close`,n)}async function Qt(e,t,n){await q(e,t).selectConfiguration(n)}async function $t(e,t,n,r){let i=r?.owner??`usb`,a=q(e,t),o=await K(),s=await o.acquireInterfaceClaim(e,t,n,i,r?.wait??!1,r?.signal),c=()=>o.claimOwner(e,t,n),l=()=>c()===i,u=()=>o.wasGrantCancelled(e,t,n,i),d=async r=>{if(!(l()&&!u())){if(u()||!c()){if(r)try{await a.releaseInterface(n)}catch{}o.settleCancelledGrant(e,t,n,i),o.wakeInterfaceWaiter(e,t,n)}throw o.claimWaitCancelledError(t,n,i)}};try{await d(!1),await a.claimInterface(n),await d(!0)}catch(r){throw s===`acquired`&&(u()?(o.settleCancelledGrant(e,t,n,i),o.wakeInterfaceWaiter(e,t,n)):l()?o.releaseInterfaceClaim(e,t,n,i):c()||o.wakeInterfaceWaiter(e,t,n)),r}finally{o.clearPendingGrant(e,t,n,i)}}async function en(e,t){let n=await K(),r=n.takeOwnerClaims(e,t);for(let t of r){try{await e.get(t.handle)?.releaseInterface(t.interfaceNumber)}catch{}n.wakeInterfaceWaiter(e,t.handle,t.interfaceNumber)}}async function tn(e,t,n,r){let i=r?.owner??`usb`,a=q(e,t),o=await K(),s=o.claimOwner(e,t,n);if(s&&s!==i)throw new ie({handle:t,holder:s,op:`release`,interfaceNumber:n});await a.releaseInterface(n),o.releaseInterfaceClaim(e,t,n,i)}async function nn(e,t,n,r){J(r,`control-in length`);let i=await q(e,t).controlTransferIn(n,r);return{status:i.status??`ok`,bytes:i.data?Kt(i.data):new ArrayBuffer(0)}}async function rn(e,t,n,r){J(r.byteLength,`control-out payload`);let i=await q(e,t).controlTransferOut(n,r);return{status:i.status??`ok`,bytesWritten:i.bytesWritten}}async function an(e,t,n,r){J(r,`transfer-in length`);let i=await q(e,t).transferIn(n,r);return{status:i.status??`ok`,bytes:i.data?Kt(i.data):new ArrayBuffer(0)}}async function on(e,t,n,r){J(r.byteLength,`transfer-out payload`);let i=await q(e,t).transferOut(n,r);return{status:i.status??`ok`,bytesWritten:i.bytesWritten}}async function sn(e,t,n){await cn(e,t,`reset`,n)}async function cn(e,t,n,r){let i=r?.owner??`usb`,a=r?.force??!1,o=q(e,t),s=await K(),c=s.listClaims(e,t);if(c.length>0){let e=c.map(e=>`${e.interfaceNumber}=${e.owner}`).join(`, `);Gt.warn(`usb ${n} ${t} with claimed interfaces (${e})${a?` [force]`:``}`)}let l=s.assertExclusive(e,t,i,a,n);n===`close`?await o.close():await o.reset(),s.displaceHandle(e,t,{reason:n,displacedBy:i,displaced:l})}async function ln(e,t,n,r){await q(e,t).clearHalt(n,r)}const un=6e4;function dn(){return l()}function fn(e){return new Promise(t=>{let n=!1,r=e=>{n||(n=!0,clearTimeout(i),t(e))},i=setTimeout(()=>r({cancelled:!0}),un);c(`usb-device`,e??[],void 0,{timeoutMs:un}).then(e=>{let t=e;t.cancelled?r({cancelled:!0}):typeof t.error==`string`?r({error:t.error}):t.granted&&t.info?r({granted:!0,info:t.info}):r({error:`usb picker returned an unexpected response`})}).catch(e=>{r({error:e instanceof Error?e.message:`Failed to open USB picker`})})})}function Y(e){let t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(e),t}var pn=class{registry;constructor(e){this.registry=e}usb(){let e=oe();if(!e)throw Error(`WebUSB is unavailable in this browser`);return e}list(){return qt(this.registry,this.usb())}async request(e){if(dn()){let t=await fn(e);if(`cancelled`in t)throw Error(`user cancelled the USB picker`);if(`error`in t)throw Error(t.error);let n=await this.reacquire(t.info);if(!n)throw Error(`granted device could not be re-acquired`);return y(this.registry.register(n),n)}return Jt(this.registry,this.usb(),e)}async reacquire(e){return(await this.usb().getDevices()).find(t=>t.vendorId===e.vendorId&&t.productId===e.productId&&(!e.serialNumber||t.serialNumber===e.serialNumber))??null}info(e){return Promise.resolve(Yt(this.registry,e))}open(e){return Xt(this.registry,e)}close(e,t){return Zt(this.registry,e,X(t))}selectConfig(e,t){return Qt(this.registry,e,t)}claim(e,t,n){return $t(this.registry,e,t,X(n))}release(e,t,n){return tn(this.registry,e,t,X(n))}async controlIn(e,t,n){let r=await nn(this.registry,e,t,n);return{status:r.status,bytes:new Uint8Array(r.bytes)}}controlOut(e,t,n){return rn(this.registry,e,t,Y(n))}async transferIn(e,t,n){let r=await an(this.registry,e,t,n);return{status:r.status,bytes:new Uint8Array(r.bytes)}}transferOut(e,t,n){return on(this.registry,e,t,Y(n))}clearHalt(e,t,n){return ln(this.registry,e,t,n)}reset(e,t){return sn(this.registry,e,X(t))}subscribeClaimEvents(e){let t,n=import(`./usb-claim-broker-C5dFP5bv.js`).then(n=>{t=n.addClaimListener(this.registry,e)});return()=>{n.then(()=>t?.())}}dropOwner(e){return en(this.registry,e)}};function X(e){return{...e,owner:e?.owner??`shell`}}var mn=class e{rpc;constructor(e){this.rpc=e}static REQUEST_TIMEOUT_MS=3e5;static CLAIM_WAIT_TIMEOUT_MS=3e5;async list(){return(await this.rpc.call(`usb-list`,void 0)).devices}async request(t){return(await this.rpc.call(`usb-request`,{filters:t},{timeoutMs:e.REQUEST_TIMEOUT_MS})).device}async info(e){return(await this.rpc.call(`usb-device-info`,{handle:e})).device}async open(e){await this.rpc.call(`usb-open`,{handle:e})}async close(e,t){await this.rpc.call(`usb-close`,{handle:e,owner:t?.owner??`shell`,force:t?.force??!1})}async selectConfig(e,t){await this.rpc.call(`usb-select-configuration`,{handle:e,configurationValue:t})}async claim(t,n,r){let i=r?.owner??`shell`,a=r?.wait??!1;try{await this.rpc.call(`usb-claim-interface`,{handle:t,interfaceNumber:n,owner:i,wait:a},a?{timeoutMs:e.CLAIM_WAIT_TIMEOUT_MS}:void 0)}catch(e){throw a&&await this.rpc.call(`usb-cancel-claim-wait`,{handle:t,interfaceNumber:n,owner:i}).catch(()=>void 0),e}}async release(e,t,n){await this.rpc.call(`usb-release-interface`,{handle:e,interfaceNumber:t,owner:n?.owner??`shell`})}async controlIn(e,t,n){let r=await this.rpc.call(`usb-control-transfer-in`,{handle:e,setup:t,length:n});return{status:r.status,bytes:new Uint8Array(r.bytes)}}async controlOut(e,t,n){return this.rpc.call(`usb-control-transfer-out`,{handle:e,setup:t,bytes:Y(n)})}async transferIn(e,t,n){let r=await this.rpc.call(`usb-transfer-in`,{handle:e,endpointNumber:t,length:n});return{status:r.status,bytes:new Uint8Array(r.bytes)}}async transferOut(e,t,n){return this.rpc.call(`usb-transfer-out`,{handle:e,endpointNumber:t,bytes:Y(n)})}async clearHalt(e,t,n){await this.rpc.call(`usb-clear-halt`,{handle:e,direction:t,endpointNumber:n})}async reset(e,t){await this.rpc.call(`usb-reset`,{handle:e,owner:t?.owner??`shell`,force:t?.force??!1})}subscribeClaimEvents(e){return this.rpc.onEvent(`usb-claim-event`,t=>{e(t)})}async dropOwner(e){await this.rpc.call(`usb-drop-owner`,{owner:e})}};function hn(e,t){return e&&oe()?new pn(se()):t?new mn(t):null}const gn=Math.max(me,fe)+5e3;function _n(e,t,n,r={}){let{header:i,window:a}=be(t),o=new Map,s=!1,c=r.dispatch??(e=>pe(e)?ge(e):de(e));function l(e){let t=o.get(e);t&&(clearTimeout(t.timer),o.delete(e))}function u(e,t,n){let r=Math.min(a.byteLength,t.payload.byteLength-n);r>0&&a.set(t.payload.subarray(n,n+r)),Atomics.store(i,2,t.status),Atomics.store(i,3,t.payload.byteLength),Atomics.store(i,4,r),Atomics.store(i,5,n),Atomics.store(i,1,e),Atomics.store(i,0,2),Atomics.notify(i,0),n+r>=t.payload.byteLength&&l(e)}function d(e,t){if(s)return;let{status:n,payload:r}=ve(t);l(e);let i={status:n,payload:r,timer:setTimeout(()=>l(e),gn)};o.set(e,i),u(e,i,0)}let f=e=>{let t=e.data;if(!t||typeof t.id!=`number`)return;if(t.type===`sync-sab-next`){let e=o.get(t.id),n=t.offset;if(!e||typeof n!=`number`||!Number.isInteger(n)||n<0||n>e.payload.byteLength){d(t.id,{ok:!1,errno:`EIO`,message:`sync-sab: bad continuation`});return}u(t.id,e,n);return}if(t.type!==`sync-sab-req`||!t.req||typeof t.req!=`object`)return;let r=t.id,i={...t.req,token:n},a;try{a=c(i)}catch(e){d(r,{ok:!1,errno:`EIO`,message:e instanceof Error?e.message:String(e)});return}a.then(e=>d(r,e),e=>d(r,{ok:!1,errno:`EIO`,message:e instanceof Error?e.message:String(e)}))};return e.addEventListener(`message`,f),{dispose:()=>{if(!s){s=!0,e.removeEventListener(`message`,f);for(let e of[...o.keys()])l(e)}}}}const vn=e(`realm-host`);let yn=0;function bn(e,t,n={}){let r=new Map,i=new Map,a=`${ae}:${++yn}`,o=n.syncFsBridgeEnabled?_e({fs:t.fs,...t.exec?{exec:t.exec}:{},cwd:t.cwd}):void 0,s=!1,c=(t,n=[])=>{if(!s)try{e.postMessage(t,n)}catch{}},l={subscriptions:r,pushEvent:c},u={subscriptions:i,pushEvent:c,owner:a},d=new Map,f={spawns:d,opts:n},p={pushEvent:c,pending:new Map,registered:[],backends:new Map,requestSeq:0,pid:n.ppid??null},m=r=>{if(r.data?.type!==`realm-rpc-req`)return;let i=r.data;xn(e,i,t,n,l,u,f,p)};e.addEventListener(`message`,m);let h=o&&n.syncSab?_n(e,n.syncSab,o):void 0;return e.start?.(),{syncFsToken:o,dispose:()=>{if(!s){s=!0,h?.dispose(),o&&le(o),e.removeEventListener(`message`,m);for(let{controller:e}of d.values())try{e.signal.aborted||e.abort()}catch{}d.clear();for(let e of r.values())try{Promise.resolve(e()).catch(()=>{})}catch{}r.clear(),fr(p);for(let e of i.values())try{Promise.resolve(e()).catch(()=>{})}catch{}i.clear();try{(n.usbBackend??wn(n)).dropOwner?.(a)?.catch(()=>{})}catch{}}}}}async function xn(e,t,n,r,i,a,o,s){try{let c=await Sn(t,n,r,i,a,o,s),l={type:`realm-rpc-res`,id:t.id,result:c},u=hr(c);e.postMessage(l,u)}catch(n){let r=n instanceof Error?n.message:String(n),i={type:`realm-rpc-res`,id:t.id,error:r};e.postMessage(i)}}async function Sn(e,t,n,r,i,a,o){switch(e.channel){case`vfs`:return On(e.op,e.args,t,n.onHostFsMutation);case`exec`:return Vn(e.op,e.args,t,a);case`fetch`:return qn(e.op,e.args,t);case`browser`:return Zn(e.op,e.args,Cn(n),n);case`usb`:return ur(e.op,e.args,wn(n),i);case`serial`:return dr(e.op,e.args,Tn(n));case`hid`:return mr(e.op,e.args,En(n),r);case`computer`:return pr(e.op,e.args,o);case`module`:return Yn(e.op,e.args,t);case`wasm`:return Xn(e.op,e.args,t);default:throw Error(`realm-host: unknown channel '${e.channel}'`)}}function Cn(e){if(e.browser)return e.browser;let t=globalThis;if(t.__slicc_browser)return t.__slicc_browser;throw Error(`browser is not available in this runtime`)}function Z(e){if(e.wsSubscribers)return e.wsSubscribers;let t=globalThis;if(t.__slicc_wsSubscribers)return t.__slicc_wsSubscribers;throw Error(`browser.websocket is not available in this runtime`)}function wn(e){if(e.usbBackend)return e.usbBackend;let t=hn(n(),r());if(!t)throw Error(`usb is not available in this runtime`);return t}function Tn(e){if(e.serialBackend)return e.serialBackend;let t=Wt(n(),r());if(!t)throw Error(`serial is not available in this runtime`);return t}function En(e){if(e.hidBackend)return e.hidBackend;let t=L(n(),r());if(!t)throw Error(`hid is not available in this runtime`);return t}function Dn(e){return[...e.deleted,...e.created.map(e=>e.path),...e.modified.map(e=>e.path)]}async function On(e,t,n,r){let i=typeof t[0]==`string`?t[0]:null,a=i===null?null:n.fs.resolvePath(n.cwd,i);switch(e){case`readFile`:return n.fs.readFile(a);case`readFileBinary`:return n.fs.readFileBuffer(a);case`writeFile`:return await n.fs.writeFile(a,t[1]),a&&r?.([a]),!0;case`writeFileBinary`:return await n.fs.writeFile(a,t[1]),a&&r?.([a]),!0;case`appendFile`:return await n.fs.appendFile(a,t[1]),a&&r?.([a]),!0;case`readDir`:return n.fs.readdir(a);case`exists`:return n.fs.exists(a);case`stat`:{let e=await n.fs.stat(a);return{isDirectory:e.isDirectory,isFile:e.isFile,size:e.size}}case`mkdir`:return await n.fs.mkdir(a,{recursive:!0}),!0;case`rm`:return await n.fs.rm(a,{recursive:!0}),a&&r?.([a]),!0;case`rename`:{let e=n.fs.resolvePath(n.cwd,t[1]),{renameViaFs:i}=await import(`./rename-via-fs-ckVY1Ljv.js`);return await i(n.fs,a,e),r?.(a?[a,e]:[e]),!0}case`resolvePath`:return n.fs.resolvePath(n.cwd,t[0]);case`invalidatePaths`:{let e=t[0],r=n.fs;return r.invalidatePaths&&r.invalidatePaths(e),!0}case`forgetSidecarConsistency`:return await n.fs.forgetSidecarConsistency?.(),!0;case`snapshot`:return Ln(n,typeof t[0]==`string`?t[0]:n.cwd);case`flushWrites`:{let e=t[0];return await Rn(n,e),r?.(Dn(e)),!0}default:throw Error(`realm-host: unknown vfs op '${e}'`)}}const kn=10485760;function An(e){return e.fileCount>=500||e.totalBytes>=kn}function jn(e){return e.entries.length>=2e4}async function Mn(e,t,n,r){r.entries.push({path:t,content:new Uint8Array,isDirectory:!0});let i;try{i=await e.fs.readdir(t)}catch{return}for(let e of i)e!==`node_modules`&&n.push(t===`/`?`/${e}`:`${t}/${e}`)}async function Nn(e,t,n,r){let i=``;try{i=await e.fs.readlink(t)}catch{return}r.entries.push({path:t,content:new Uint8Array,isDirectory:!1,isSymbolicLink:!0,symlinkTarget:i,size:n})}async function Pn(e,t,n,r,i){if(n>1048576||An(r)||r.totalBytes+n>kn){r.entries.push({path:t,content:new Uint8Array,isDirectory:!1,truncated:!0,size:n});return}let a;try{a=await e.fs.readFileBuffer(t)}catch{await Fn(e,t,i,r);return}r.entries.push({path:t,content:a,isDirectory:!1}),r.fileCount+=1,r.totalBytes+=a.byteLength}async function Fn(e,t,n,r){let i;try{i=await e.fs.stat(t)}catch{return}if(i.isDirectory){await Mn(e,t,n,r);return}r.entries.push({path:t,content:new Uint8Array,isDirectory:!1,truncated:!0,size:i.size})}async function In(e,t,n){if(jn(n))return;let r=[t];for(;r.length>0;){if(jn(n))return;let t=r.pop(),i;try{i=await e.fs.lstat(t)}catch{}if(i?.isSymbolicLink){await Nn(e,t,i.size,n);continue}let a;try{a=await e.fs.stat(t)}catch{continue}a.isDirectory?await Mn(e,t,r,n):a.isFile&&await Pn(e,t,a.size,n,r)}}async function Ln(e,t){let n={entries:[],totalBytes:0,fileCount:0};return await In(e,t,n),t!==`/tmp`&&await In(e,`/tmp`,n),{entries:n.entries}}async function Rn(e,t){let n=[],r=async(e,t)=>{try{await t()}catch(t){n.push(`${e}: ${t instanceof Error?t.message:String(t)}`)}};for(let n of t.deleted)await r(n,()=>e.fs.rm(n,{recursive:!0}));for(let n of t.created)n.isSymbolicLink?await r(n.path,()=>e.fs.symlink(n.symlinkTarget??``,n.path)):n.isDirectory?await r(n.path,()=>e.fs.mkdir(n.path,{recursive:!0})):await r(n.path,()=>e.fs.writeFile(n.path,n.content));for(let n of t.modified)await r(n.path,()=>e.fs.writeFile(n.path,n.content));if(n.length>0)throw Error(`sync-fs flush failed for ${n.length} path(s): ${n.join(`; `)}`)}const zn=new Set([`SIGINT`,`SIGTERM`,`SIGKILL`,`SIGSTOP`,`SIGCONT`]),Bn=new Set([`SIGINT`,`SIGTERM`,`SIGKILL`]);async function Vn(e,t,n,r){if(!n.exec)throw Error(`exec is not available in this runtime`);if(e===`run`){let e=t[0],r=await n.exec(e,{cwd:n.cwd});return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}if(e===`spawn`){let e=t[0];if(!Array.isArray(e)||e.length===0||!e.every(e=>typeof e==`string`))throw Error(`exec.spawn: argv must be a non-empty string[]`);let[r,...i]=e,a=await n.exec(r,{cwd:n.cwd,args:i});return{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode}}if(e===`start`)return Gn(t,n,r);if(e===`kill`)return Kn(t,r);throw Error(`realm-host: unknown exec op '${e}'`)}function Hn(e){if(e.stdin!==void 0&&typeof e.stdin!=`string`)throw Error(`exec.start: stdin must be a string`);if(e.stdinKind!==void 0&&e.stdinKind!==`text`&&e.stdinKind!==`bytes`)throw Error(`exec.start: stdinKind must be 'text' or 'bytes'`);if(e.args!==void 0&&(!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`)))throw Error(`exec.start: args must be a string[]`);if(e.cwd!==void 0&&typeof e.cwd!=`string`)throw Error(`exec.start: cwd must be a string`);if(e.env!==void 0){if(e.env===null||typeof e.env!=`object`||Array.isArray(e.env))throw Error(`exec.start: env must be an object`);for(let[t,n]of Object.entries(e.env))if(n!==void 0&&typeof n!=`string`)throw Error(`exec.start: env[${t}] must be a string`)}}function Un(e){throw Object.assign(Error(e.message),{code:e.errno})}async function Wn(e,t){let n=await he(e.fs,e.cwd,t.cwd);`errno`in n&&Un(n);let r=ue(t.env);return r!==void 0&&`errno`in r&&Un(r),{cwd:n.cwd,...r===void 0?{}:{env:r.env}}}async function Gn(e,t,n){let[r,i,a]=e;if(typeof r!=`number`)throw Error(`exec.start: spawnId must be a number`);if(n.spawns.has(r))throw Error(`exec.start: spawnId ${r} is already in use`);let o,s,c;if(Array.isArray(i)){if(i.length===0||!i.every(e=>typeof e==`string`))throw Error(`exec.start: argv must be a non-empty string[]`);[o,...s]=i,c=i.slice()}else if(typeof i==`string`)o=i,c=[i];else throw Error(`exec.start: command must be a string or a non-empty string[]`);let l=a??{};Hn(l);let u=await Wn(t,l),d=new AbortController,{pm:f,owner:p}=n.opts,m=0;f&&p&&(m=f.spawn({kind:`shell`,argv:c,cwd:u.cwd,owner:p,...n.opts.ppid===void 0?{}:{ppid:n.opts.ppid},adoptAbort:d}).pid),n.spawns.set(r,{controller:d,pid:m});let h;try{let e={cwd:u.cwd,signal:d.signal};return l.stdin!==void 0&&(e.stdin=l.stdin),l.stdinKind!==void 0&&(e.stdinKind=l.stdinKind),s===void 0?l.args!==void 0&&(e.args=l.args):e.args=s,u.env!==void 0&&(e.env=u.env,e.replaceEnv=!0),h=await t.exec(o,e),{stdout:h.stdout,stderr:h.stderr,exitCode:h.exitCode}}finally{if(n.spawns.delete(r),f&&m){let e=f.get(m);f.exit(m,e?.terminatedBy?null:h?.exitCode??1)}}}function Kn(e,t){let[n,r]=e,i=t.spawns.get(n);if(!i)return!1;let a=typeof r==`string`&&zn.has(r)?r:`SIGTERM`;Bn.has(a)&&!i.controller.signal.aborted&&i.controller.abort();let{pm:o}=t.opts;return o&&i.pid?o.signal(i.pid,a):!0}async function qn(e,t,n){if(e!==`request`)throw Error(`realm-host: unknown fetch op '${e}'`);let[r,i]=t,a=await(n.fetch?ft(n.fetch):globalThis.fetch.bind(globalThis))(r,i),o={};a.headers.forEach((e,t)=>{o[t]=e});let s=new Uint8Array(await a.arrayBuffer());return{status:a.status,statusText:a.statusText,headers:o,body:s,url:a.url}}function Jn(e){let t=t=>e.fs.resolvePath(e.cwd,t);return{exists:n=>e.fs.exists(t(n)),isDirectory:async n=>{try{return(await e.fs.stat(t(n))).isDirectory}catch{return!1}},readFile:async n=>{let r=await e.fs.readFile(t(n));return typeof r==`string`?r:new TextDecoder().decode(r)}}}async function Yn(e,t,n){if(e!==`buildGraph`)throw Error(`realm-host: unknown module op '${e}'`);let r=typeof t[0]==`string`?t[0]:``,i=typeof t[1]==`string`&&t[1]?t[1]:n.cwd,a=typeof t[2]==`string`?t[2]:``,o=Jn(n),s={reader:o,readBytes:e=>n.fs.readFileBuffer(e),fromDir:i};return Ke({entryCode:r,fromDir:i,entryFilename:a,reader:o,transpile:Ne({ipk:s}),transpileEntry:T({ipk:s})})}async function Xn(e,t,n){if(e!==`compile`)throw Error(`realm-host: unknown wasm op '${e}'`);let r=typeof t[0]==`string`?t[0]:null;if(r===null)throw Error(`realm-host: wasm.compile requires a path argument`);let i=n.fs.resolvePath(n.cwd,r);return re(e=>n.fs.readFileBuffer(e),i)}async function Zn(e,t,n,r){switch(e){case`findTab`:return $n(n,t[0]??{});case`ensureTab`:{let e=t[0];return er(n,e,t[1]??{})}case`openWindow`:{let e=t[0];return tr(n,e,t[1]??{})}case`windowBounds`:{let e=t[0];return n.getWindowBounds(e)}case`setWindowBounds`:{let e=t[0],r=t[1]??{};return n.setWindowBounds(e,r)}case`eval`:{let e=t[0],r=t[1];return nr(n,e,r,!1)}case`evalAsync`:{let e=t[0],r=t[1];return nr(n,e,r,!0)}case`cookie`:{let e=t[0],r=t[1];return or(n,e,r)}case`localStorage`:{let e=t[0],r=t[1];return sr(n,e,r)}case`wsObserve`:{let e={...t[0],scoopJid:r.scoopJid};return await Z(r).observe(e)}case`wsUpdate`:{let e=t[0],n=t[1]??{};return Z(r).update(e,n)}case`wsClose`:{let e=t[0];return Z(r).close(e)}case`wsList`:return Z(r).list();case`createTab`:{let e=t[0];return n.createPage(e)}case`closeTab`:{let e=t[0];return n.closePage(e)}case`setViewport`:{let e=t[0],r=t[1],i=t[2];return n.withTab(e,e=>e.setViewportOverride(r,i))}case`navigateTab`:{let e=t[0],r=t[1];return n.withTab(e,e=>e.navigate(r))}case`screenshotTab`:{let e=t[0],r=t[1];return n.withTab(e,e=>e.screenshot(r))}case`waitForLoadState`:{let e=t[0],r=t[1];return ar(n,e,r)}default:throw Error(`realm-host: unknown browser op '${e}'`)}}function Qn(){try{let e=globalThis.localStorage;return e?!!(e.getItem(`slicc.trayWorkerBaseUrl`)||e.getItem(`slicc.trayJoinUrl`)):!1}catch{return!1}}async function Q(e){if(typeof e.listAllTargets!=`function`)return(await e.listPages()).map(e=>({targetId:e.targetId,url:e.url,title:e.title}));let t=(await e.listAllTargets()).map(e=>({targetId:e.targetId,url:e.url,title:e.title})),n=Qn()?r():null;if(n)try{let{targets:e}=await n.call(`list-remote-targets`,void 0,{timeoutMs:3e3}),r=new Set(t.map(e=>e.targetId));for(let n of e)r.has(n.targetId)||(r.add(n.targetId),t.push({targetId:n.targetId,url:n.url,title:n.title}))}catch(e){vn.debug(`panel-rpc list-remote-targets failed`,{err:String(e)})}return t}async function $n(e,t){let n=await Q(e);if(t.domain){let e=t.domain.toLowerCase();for(let t of n){let n=cr(t.url);if(n&&n.toLowerCase()===e)return t}return null}if(t.urlMatch){let e;try{e=new RegExp(t.urlMatch)}catch(e){throw Error(`browser.findTab: invalid urlMatch regex: ${e instanceof Error?e.message:String(e)}`)}for(let t of n)if(e.test(t.url))return t;return null}throw Error("browser.findTab: query requires `domain` or `urlMatch`")}async function er(e,t,n){let r=await Q(e);if(n.matchUrl){let e;try{e=new RegExp(n.matchUrl)}catch(e){throw Error(`browser.ensureTab: invalid matchUrl regex: ${e instanceof Error?e.message:String(e)}`)}let t=r.find(t=>e.test(t.url));if(t)return t}else{let e=lr(t);if(e){let t=r.find(t=>lr(t.url)===e);if(t)return t}}return{targetId:await e.createPage(t),url:t,title:``}}async function tr(e,t,n){if(typeof e.openWindow!=`function`)throw Error(`browser.openWindow is not available in this runtime`);return{targetId:await e.openWindow(t,n),url:t||`about:blank`,title:``}}async function nr(e,t,n,r){return e.withTab(t,async e=>rr(await e.evaluate(n,{awaitPromise:r,returnByValue:!0})))}function rr(e){if(typeof e!=`string`)return e;let t=ir(e);if(t===void 0)return e;if(typeof t==`object`&&t)return t;if(typeof t==`string`){let e=t.trim();if(e.length>0&&(e[0]===`{`||e[0]===`[`)){let e=ir(t);if(typeof e==`object`&&e)return e}return t}return e}function ir(e){let t=e.trim();if(t.length===0)return;let n=t[0];if(n===`{`||n===`[`||n===`"`||n===`-`||n>=`0`&&n<=`9`||t===`true`||t===`false`||t===`null`)try{return JSON.parse(t)}catch{return}}async function ar(e,t,n){if(n===`networkidle`)return e.withTab(t,async e=>{for(let t=0;t<20;t++)if(await new Promise(e=>setTimeout(e,250)),await e.evaluate(`(function(){
1
+ import{t as e}from"./logger-LESFN7Hj.js";import{t}from"./content-type-_QKWY0B2.js";import"./proxied-fetch-DXaTHROw.js";import{i as n,r}from"./panel-rpc-DW7W4w6_.js";import{t as i}from"./fetch-body-CuwTaJC_.js";import{a}from"./path-utils-DNJG-zQf.js";import{r as o,t as s}from"./multipart-form-data-DopbgwRR.js";import"./tray-storage-keys-DbThbnIh.js";import"./tray-runtime-config-CTm013-K.js";import{n as c,t as l}from"./picker-popup-B6AyYTBw.js";import{t as u}from"./process-manager-BkhAohXT.js";import{C as d,N as f,b as p,d as m,g as h,p as g,t as ee,x as te,y as _}from"./shared-DfMXB1pm.js";import{t as ne}from"./require-guards-DyoCy2Tn.js";import{n as v}from"./esbuild-wasm-CeZYVyQ9.js";import{t as re}from"./wasm-compiler-Ct7QZURL.js";import{a as y,i as ie,n as ae,o as oe,s as se,t as ce}from"./usb-device-registry-DFzxaOky.js";import{S as le,h as ue,i as de,l as fe,n as pe,o as me,r as he,w as ge,x as _e}from"./sync-exec-dispatch-BwrIjhDd.js";import{a as ve,o as ye,s as be}from"./sync-sab-wire-D_d0fd3b.js";import{i as xe}from"./just-bash-compat-B-SPHuh_.js";let b,x;function S(){return async({kind:e,ctx:t})=>{if(e===`py`){if(typeof Worker<`u`)return Ce();if(!x){let{createInProcessPyRealmFactory:e}=await import(`./realm-inprocess-CiFoJQtp.js`);x=e()}return x({kind:e,ctx:t})}if(typeof Worker<`u`)return Se();if(!b){let{createInProcessJsRealmFactory:e}=await import(`./realm-inprocess-CiFoJQtp.js`);b=e()}return b({kind:e,ctx:t})}}function Se(){if(typeof Worker>`u`)throw Error(`realm-factory: Worker is not available in this runtime`);return we(new Worker(new URL(`/assets/js-realm-worker-DyJ9cjpk.js`,``+import.meta.url),{type:`module`}))}function Ce(){if(typeof Worker>`u`)throw Error(`realm-factory: Worker is not available in this runtime`);return we(new Worker(new URL(`/assets/py-realm-worker-CpOMOUd5.js`,``+import.meta.url),{type:`module`}))}function we(e){let t={postMessage:(t,n)=>n?e.postMessage(t,n):e.postMessage(t),addEventListener:(t,n)=>e.addEventListener(t,n),removeEventListener:(t,n)=>e.removeEventListener(t,n)},n=!1;return{controlPort:t,isolatedThread:!0,addEventListener:(t,n,r)=>e.addEventListener(t,n,r),removeEventListener:(t,n)=>e.removeEventListener(t,n),terminate(){if(!n){n=!0;try{e.terminate()}catch{}}}}}function Te(){if(g())return decodeURIComponent(h(`pyodide/pyodide.mjs`,`../../../../../node_modules/pyodide/`).pathname)}function Ee(e){let t=e.startsWith(`/`)?e:`/${e}`;return new URL(`file://${t}`).href}function C(e){return e instanceof Error?e.message:String(e)}function De(e){return`${(e&&e.length>0?e:`[eval]`).replace(/\.[^./]+$/,``)}.js`}async function Oe(e,t,n,r){return(await(await e()).transform(t,{loader:`js`,format:`cjs`,sourcefile:De(n),supported:{"dynamic-import":!1},define:{"import.meta.url":JSON.stringify(r)}})).code}async function ke(e,t,n,r){return(await(await e()).transform(t,{loader:`js`,format:`cjs`,sourcefile:De(n),supported:{"dynamic-import":!1},...r?{define:{"import.meta.url":JSON.stringify(r)}}:{}})).code}const Ae=/\bimport\s*\.\s*meta\s*\.\s*url\b/g,je=/\bimport\s*\.\s*meta\b/g;function Me(e,t){let n=JSON.stringify(t);return e.replace(Ae,n).replace(je,`({ url: ${n} })`)}async function w(e,t,n,r){let i=await e();return i.transpileModule(Me(t,r),{compilerOptions:{module:i.ModuleKind.CommonJS,target:i.ScriptTarget.ES2020,esModuleInterop:!0},fileName:`${n.replace(/\.[^./]+$/,``)}.ts`}).outputText}function Ne(e={}){let{ipk:t}=e,n=e.loadEsbuild??(()=>v(t?{ipk:t}:{})),r=e.loadTypeScript??(()=>m(t));return async({source:e,path:t,kind:i})=>{if(i!==`esm`||!p(e))return e;let a=Ee(t),o;try{return await Oe(n,e,t,a)}catch(e){o=e}try{return await w(r,e,t,a)}catch(e){throw Error(`Failed to transpile ESM module '${t}': ${C(o)}; typescript fallback: ${C(e)}`)}}}function T(e={}){let{ipk:t}=e,n=e.loadEsbuild??(()=>v(t?{ipk:t}:{})),r=e.loadTypeScript??(()=>m(t));return async({source:e,filename:t})=>{if(!p(e)&&!_(e))return e;let i=typeof t==`string`&&t.startsWith(`/`),a=i?Ee(t):void 0,o=i?t:`[eval].js`,s;try{return await ke(n,e,t,a)}catch(e){s=e}try{return await w(r,e,o,a??``)}catch(e){throw Error(`Failed to transpile entry source: ${C(s)}; typescript fallback: ${C(e)}`)}}}function E(e,t){if(!e.startsWith(`#!`))return e;let n=e.indexOf(`
2
+ `);if(n===-1)return``;let r=e.slice(n+1);return t?.keepLine?`\n${r}`:r}function Pe(e){return a(e).dir}const D=[`node`,`require`,`default`],O=[`node`,`import`,`default`],Fe=/\brequire\s*\(\s*(['"`])([^'"`\s]+)\1\s*\)/g,Ie=/\bimport\s*\(\s*(['"`])([^'"`\s]+)\1\s*\)/g,Le=/(?:^|[;\n}])\s*import\b[\s\S]*?\bfrom\s*(['"])([^'"]+)\1/g,Re=/(?:^|[;\n}])\s*export\b[\s\S]*?\bfrom\s*(['"])([^'"]+)\1/g,ze=/(?:^|[;\n}])\s*import\s*(['"])([^'"]+)\1/g;function Be(e,t,n){let r=t[0].indexOf(n);return r<0?!1:e.startsWith(n,t.index+r)}function Ve(e){let t=te(e),n=new Map,r=(r,i,a)=>{r.lastIndex=0;let o;for(;(o=r.exec(e))!==null;){if(!Be(t,o,a))continue;let e=o[2];n.get(e)!==`import`&&n.set(e,i)}};return r(Fe,`require`,`require`),r(Ie,`import`,`import`),r(Le,`import`,`import`),r(Re,`import`,`export`),r(ze,`import`,`import`),[...n].map(([e,t])=>({specifier:e,kind:t}))}async function He(e,t,n,r){if(n===`json`)return`module.exports = JSON.parse(${JSON.stringify(e)});\n`;let i=E(e);if(n===`esm`){if(!r)throw Error(`Cannot load ESM module '${t}': no transpile hook configured (run: ${ee} esbuild-wasm)`);return await r({source:i,path:t,kind:n})}return i}async function Ue(e){let{entrySpecifiers:t,fromDir:n,reader:r,conditions:i,transpile:a}=e,o=e.requireConditions??D,s=e.importConditions??O,c=i??o,l=new Map,u=[],f={},p={};async function m(e,t){if(l.has(e))return;let n=await r.readFile(e),i=await He(n,e,t,a);l.set(e,{path:e,source:n,cjsSource:i,kind:t});let c=Pe(e),h={},g={};for(let{specifier:e,kind:t}of Ve(n)){let n;try{n=await d(e,c,r,{conditions:t===`import`?s:o})}catch(t){g[e]=t instanceof Error?t.message:String(t);continue}n.type===`file`&&(h[e]=n.path,await m(n.path,n.moduleKind))}f[e]=h,Object.keys(g).length>0&&(p[e]=g),u.push(e)}let h={};for(let e of t){let t=await d(e,n,r,{conditions:c});t.type===`file`&&(h[e]=t.path,await m(t.path,t.moduleKind))}return{files:u.map(e=>{let t=l.get(e);if(!t)throw Error(`module-loader: missing built module for '${e}'`);return t}),entryMap:h,edges:f,edgeErrors:p}}function We(e){return!(e.startsWith(`sliccy:`)||e.startsWith(`node:`)||f.has(e)||ne.has(e))}function Ge(e,t){for(let[n,r]of Object.entries(t))e[n]={...e[n]??{},...r}}async function Ke(e){let{entryCode:t,fromDir:n,entryFilename:r,reader:i,transpile:a,transpileEntry:o}=e,s=new Map,c=[],l={},u={},d={},f={};for(let{specifier:e,kind:r}of Ve(t))if(We(e))try{let t=await Ue({entrySpecifiers:[e],fromDir:n,reader:i,transpile:a,conditions:r===`import`?O:D,requireConditions:D,importConditions:O});for(let e of t.files)s.has(e.path)||(s.set(e.path,e),c.push(e.path));Object.assign(l,t.entryMap),Ge(u,t.edges),Ge(d,t.edgeErrors)}catch(t){f[e]=t instanceof Error?t.message:String(t)}let m;o&&(p(t)||_(t))&&(m=await o({source:t,filename:r??`[eval]`,fromDir:n}));let h={files:c.map(e=>{let t=s.get(e);if(!t)throw Error(`module-loader: missing built module for '${e}'`);return{path:t.path,cjsSource:t.cjsSource,kind:t.kind}}),entryMap:l,edges:u,edgeErrors:d,errors:f};return m!==void 0&&(h.entrySource=m),m!==void 0&&p(t)&&(h.entryIsModule=!0),h}function k(){return globalThis.navigator?.hid??null}function qe(e){let t=e.collections?.[0];return t?`${t.usagePage??``}:${t.usage??``}`:``}function Je(e,t){return e===t||e.vendorId===t.vendorId&&e.productId===t.productId&&(e.productName??``)===(t.productName??``)&&qe(e)===qe(t)&&!!e.productName}var Ye=class{byHandle=new Map;counter=0;register(e){for(let[t,n]of this.byHandle)if(Je(n,e))return this.byHandle.set(t,e),t;let t=`hid${++this.counter}`;return this.byHandle.set(t,e),t}get(e){return this.byHandle.get(e)}remove(e){return this.byHandle.delete(e)}list(){return[...this.byHandle].map(([e,t])=>({handle:e,device:t}))}};let Xe=null;function Ze(){return Xe||=new Ye,Xe}const Qe=4194304;function A(e,t){let n=t.collections?.[0];return{handle:e,vendorId:t.vendorId,productId:t.productId,...t.productName?{productName:t.productName}:{},...n?.usagePage===void 0?{}:{usagePage:n.usagePage},...n?.usage===void 0?{}:{usage:n.usage},opened:t.opened}}function j(e,t){let n=e.get(t);if(!n)throw Error(`unknown hid handle '${t}'`);return n}async function M(e){e.opened||await e.open()}function N(e,t){if(e>4194304)throw Error(`${t} exceeds the ${Qe}-byte (4 MiB) v1 limit`)}function P(e){let t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),t}async function $e(e,t){return(await t.getDevices()).map(t=>A(e.register(t),t))}async function et(e,t,n){let r=await t.requestDevice({filters:n});if(r.length===0)throw Error(`No device selected.`);return r.map(t=>A(e.register(t),t))}function tt(e,t){return A(t,j(e,t))}async function nt(e,t){await j(e,t).open()}async function rt(e,t){await j(e,t).close()}async function it(e,t,n,r){N(r.byteLength,`send report payload`);let i=j(e,t);await M(i),await i.sendReport(n,r)}async function at(e,t,n,r){N(r.byteLength,`send feature report payload`);let i=j(e,t);await M(i),await i.sendFeatureReport(n,r)}async function ot(e,t,n){let r=j(e,t);return await M(r),{reportId:n,bytes:P(await r.receiveFeatureReport(n))}}async function st(e,t,n){let r=j(e,t);await M(r);let i=e=>{n({reportId:e.reportId,bytes:P(e.data)})};return r.addEventListener(`inputreport`,i),()=>r.removeEventListener(`inputreport`,i)}const F=6e4;function ct(){return l()}function lt(e){return new Promise(t=>{let n=!1,r=e=>{n||(n=!0,clearTimeout(i),t(e))},i=setTimeout(()=>r({cancelled:!0}),F);c(`hid-device`,e??[],void 0,{timeoutMs:F}).then(e=>{let t=e;t.cancelled?r({cancelled:!0}):typeof t.error==`string`?r({error:t.error}):t.granted&&t.info?r({granted:!0,info:t.info}):r({error:`hid picker returned an unexpected response`})}).catch(e=>{r({error:e instanceof Error?e.message:`Failed to open HID picker`})})})}function I(e){let t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(e),t}var ut=class{registry;constructor(e){this.registry=e}hid(){let e=k();if(!e)throw Error(`WebHID is unavailable in this browser`);return e}list(){return $e(this.registry,this.hid())}async request(e){if(ct()){let t=await lt(e);if(`cancelled`in t)throw Error(`user cancelled the HID picker`);if(`error`in t)throw Error(t.error);let n=await this.reacquireAll(t.info);if(n.length===0)throw Error(`granted device could not be re-acquired`);return n.map(e=>A(this.registry.register(e),e))}return et(this.registry,this.hid(),e)}async reacquireAll(e){return(await this.hid().getDevices()).filter(t=>t.vendorId===e.vendorId&&t.productId===e.productId)}info(e){return Promise.resolve(tt(this.registry,e))}open(e){return nt(this.registry,e)}close(e){return rt(this.registry,e)}sendReport(e,t,n){return it(this.registry,e,t,I(n))}sendFeatureReport(e,t,n){return at(this.registry,e,t,I(n))}async receiveFeatureReport(e,t){let n=await ot(this.registry,e,t);return{reportId:n.reportId,bytes:new Uint8Array(n.bytes)}}async subscribeInputReports(e,t){return st(this.registry,e,e=>t({reportId:e.reportId,bytes:new Uint8Array(e.bytes)}))}},dt=class e{rpc;constructor(e){this.rpc=e}static REQUEST_TIMEOUT_MS=3e5;async list(){return(await this.rpc.call(`hid-list`,void 0)).devices}async request(t){return(await this.rpc.call(`hid-request`,{filters:t},{timeoutMs:e.REQUEST_TIMEOUT_MS})).devices}async info(e){return(await this.rpc.call(`hid-device-info`,{handle:e})).device}async open(e){await this.rpc.call(`hid-open`,{handle:e})}async close(e){await this.rpc.call(`hid-close`,{handle:e})}async sendReport(e,t,n){await this.rpc.call(`hid-send-report`,{handle:e,reportId:t,bytes:I(n)})}async sendFeatureReport(e,t,n){await this.rpc.call(`hid-send-feature-report`,{handle:e,reportId:t,bytes:I(n)})}async receiveFeatureReport(e,t){let n=await this.rpc.call(`hid-receive-feature-report`,{handle:e,reportId:t});return{reportId:n.reportId,bytes:new Uint8Array(n.bytes)}}async subscribeInputReports(e,t){let n=this.rpc.onEvent(`hid-input-report`,n=>{let r=n;!r||r.handle!==e||t({reportId:r.reportId,bytes:new Uint8Array(r.bytes)})});try{await this.rpc.call(`hid-subscribe-input-reports`,{handle:e})}catch(e){throw n(),e}return async()=>{n();try{await this.rpc.call(`hid-unsubscribe-input-reports`,{handle:e})}catch{}}}};function L(e,t){return e&&k()?new ut(Ze()):t?new dt(t):null}function ft(e){return async function(t,n){let r=t instanceof Request?t:null,i=pt(t),a=(n?.method??r?.method??`GET`).toUpperCase(),o=ht(r?.headers,n?.headers),s=await _t(n,r,a,o);s.defaultContentType&&!gt(o,`content-type`)&&(o[`Content-Type`]=s.defaultContentType);let c=await e(i,{method:a,headers:o,body:s.body}),l=new Headers;for(let[e,t]of Object.entries(c.headers))try{l.set(e,t)}catch{}let u=c.status===204||c.status===205||c.status===304||!c.body||c.body.byteLength===0?null:c.body,d=new Response(u,{status:c.status,statusText:c.statusText,headers:l});try{Object.defineProperty(d,"url",{value:c.url||i,writable:!1,configurable:!0,enumerable:!1})}catch{}return d}}function pt(e){return typeof e==`string`?e:e instanceof URL?e.toString():e.url}function mt(e){if(e){if(e instanceof Headers){let t={};return e.forEach((e,n)=>{t[n]=e}),t}if(Array.isArray(e)){let t={};for(let[n,r]of e)t[n]=r;return t}return{...e}}}function ht(e,t){let n={};e&&e.forEach((e,t)=>{n[t]=e});let r=mt(t);if(r)for(let[e,t]of Object.entries(r))n[e]=t;return n}function gt(e,t){return R(e,t)!==void 0}function R(e,t){let n=t.toLowerCase(),r;for(let[t,i]of Object.entries(e))t.toLowerCase()===n&&(r=i);return r}async function _t(e,n,r,a){if(e&&`body`in e&&e.body!==void 0)return vt(e.body,r);if(n&&r!==`GET`&&r!==`HEAD`){let e=n.body!==null,r=new Uint8Array(await n.arrayBuffer()),o=R(a,`content-type`)??``,s=e&&(!o||!t(o));return{body:r.byteLength===0?void 0:s?i(r):new TextDecoder(`utf-8`).decode(r),defaultContentType:s?`application/octet-stream`:void 0}}return{}}async function vt(e,t){if(o(e)){if(t===`GET`||t===`HEAD`)return{};let n=await s(e);return{body:n.bytes,defaultContentType:n.contentType}}return{body:await yt(e,t),defaultContentType:xt(e,t)}}async function yt(e,t){if(e!=null&&t!==`GET`&&t!==`HEAD`){if(typeof e==`string`)return e;if(e instanceof URLSearchParams)return e.toString();if(e instanceof Uint8Array)return i(e);if(e instanceof ArrayBuffer)return new Uint8Array(e).slice();if(ArrayBuffer.isView(e)){let t=e;return new Uint8Array(t.buffer,t.byteOffset,t.byteLength).slice()}if(typeof Blob<`u`&&e instanceof Blob)return new Uint8Array(await e.arrayBuffer());throw typeof ReadableStream<`u`&&e instanceof ReadableStream?Error(`node fetch shim: ReadableStream request bodies are not supported (collect into a Uint8Array or string before calling fetch)`):Error(`node fetch shim: unsupported request body type (${Object.prototype.toString.call(e)}); use a string, Uint8Array, ArrayBuffer, Blob, FormData, or URLSearchParams`)}}function bt(e){return e instanceof Uint8Array||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||typeof Blob<`u`&&e instanceof Blob}function xt(e,t){if(e instanceof URLSearchParams)return`application/x-www-form-urlencoded;charset=UTF-8`;if(!(t===`GET`||t===`HEAD`||!bt(e)))return typeof Blob<`u`&&e instanceof Blob&&e.type?e.type:`application/octet-stream`}function z(){return globalThis.navigator?.serial??null}var St=class{byHandle=new Map;counter=0;register(e){for(let[t,n]of this.byHandle)if(n.port===e)return t;let t=`serial${++this.counter}`;return this.byHandle.set(t,{port:e,opened:!1}),t}get(e){return this.byHandle.get(e)}remove(e){return this.byHandle.delete(e)}list(){return[...this.byHandle].map(([e,t])=>({handle:e,entry:t}))}retainOnly(e){let t=[];for(let[n,r]of[...this.byHandle])e.includes(r.port)||(this.byHandle.delete(n),t.push({handle:n,entry:r}));return t}};let B=null;function V(){return B||=new St,B}const H=4194304;function U(e,t){let n=t.port.getInfo();return{handle:e,...n.usbVendorId===void 0?{}:{usbVendorId:n.usbVendorId},...n.usbProductId===void 0?{}:{usbProductId:n.usbProductId},opened:t.opened}}function W(e,t){let n=e.get(t);if(!n)throw Error(`unknown serial handle '${t}'`);return n}function Ct(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e),n.set(t,e.length),n}function wt(e,t,n){if(t.length===0)return-1;outer:for(let r=Math.max(0,n);r+t.length<=e.length;r++){for(let n=0;n<t.length;n++)if(e[r+n]!==t[n])continue outer;return r}return-1}async function G(e){if(e.reader){try{await e.reader.cancel()}catch{}try{e.reader.releaseLock()}catch{}e.reader=void 0}if(e.pendingRead=void 0,e.leftover=void 0,e.writer){try{e.writer.releaseLock()}catch{}e.writer=void 0}}async function Tt(e){if(await G(e),e.opened){try{await e.port.close()}catch{}e.opened=!1}}async function Et(e,t){let n=await t.getPorts();for(let{entry:t}of e.retainOnly(n))await Tt(t);return n.map(t=>{let n=e.register(t);return U(n,e.get(n))})}async function Dt(e,t,n){let r=await t.requestPort(n.length?{filters:n}:{}),i=e.register(r);return U(i,e.get(i))}function Ot(e,t){return U(t,W(e,t))}async function kt(e,t,n){let r=W(e,t);try{await r.port.open(n)}catch(e){throw Error(`${e instanceof Error?e.message:String(e)} (handle '${t}' may be stale after a device reset — re-run 'serial list' to pick up the current handle)`)}r.opened=!0}async function At(e,t){let n=W(e,t);await G(n);try{await n.port.close()}catch(e){if(!jt(e))throw e}n.opened=!1}function jt(e){let t=e instanceof Error?e.message:String(e);return/already closed|not open/i.test(t)}function Mt(e){if(!e.reader){if(!e.port.readable)throw Error(`serial port is not readable (is it open?)`);e.reader=e.port.readable.getReader()}return e.reader}function Nt(e){if(!e.writer){if(!e.port.writable)throw Error(`serial port is not writable (is it open?)`);e.writer=e.port.writable.getWriter()}return e.writer}async function Pt(e,t,n){let r=W(e,t),i=Math.min(n.maxBytes??4194304,H),a=n.until?.length?n.until:void 0,o=n.timeoutMs??1e3,s=Date.now()+Math.max(0,o),c=r.leftover??new Uint8Array;r.leftover=void 0;let l=0,u=()=>{if(a){let e=wt(c,a,Math.max(0,l-(a.length-1)));if(e>=0){let t=e+a.length;return r.leftover=c.slice(t),c.slice(0,t)}}return c.length>=i?(r.leftover=c.slice(i),c.slice(0,i)):null},d=u();if(d)return d;let f=Mt(r);for(;Date.now()<s;){let e=s-Date.now(),t=r.pendingRead??f.read();r.pendingRead=t;let n,i=new Promise(t=>{n=setTimeout(()=>t(`__timeout`),e)}),a;try{a=await Promise.race([t,i])}finally{n&&clearTimeout(n)}if(a===`__timeout`)break;if(r.pendingRead=void 0,a.done){r.reader=void 0;break}if(a.value?.length){l=c.length,c=Ct(c,a.value);let e=u();if(e)return e}}return c}async function Ft(e,t,n){if(n.length>4194304)throw Error(`serial write payload exceeds the ${H}-byte (4 MiB) v1 limit`);return await Nt(W(e,t)).write(n),n.length}async function It(e,t){return W(e,t).port.getSignals()}async function Lt(e,t,n){await W(e,t).port.setSignals(n)}const Rt=6e4;function zt(){return l()}function Bt(e){return new Promise(t=>{let n=!1,r=e=>{n||(n=!0,clearTimeout(i),t(e))},i=setTimeout(()=>r({cancelled:!0}),Rt);c(`serial-port`,e??[],void 0,{timeoutMs:Rt}).then(e=>{let t=e;t.cancelled?r({cancelled:!0}):typeof t.error==`string`?r({error:t.error}):t.granted&&t.info?r({granted:!0,info:t.info}):r({error:`serial picker returned an unexpected response`})}).catch(e=>{r({error:e instanceof Error?e.message:`Failed to open serial picker`})})})}function Vt(e){let t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(e),t}var Ht=class{registry;constructor(e){this.registry=e}serial(){let e=z();if(!e)throw Error(`Web Serial is unavailable in this browser`);return e}list(){return Et(this.registry,this.serial())}async request(e){if(zt()){let t=await Bt(e);if(`cancelled`in t)throw Error(`user cancelled the serial picker`);if(`error`in t)throw Error(t.error);let n=await this.reacquire(t.info);if(!n)throw Error(`granted port could not be re-acquired`);let r=this.registry.register(n);return U(r,this.registry.get(r))}return Dt(this.registry,this.serial(),e)}async reacquire(e){let t=await this.serial().getPorts(),n=t.filter(t=>{let n=t.getInfo();return!(e.usbVendorId!==void 0&&n.usbVendorId!==e.usbVendorId||e.usbProductId!==void 0&&n.usbProductId!==e.usbProductId)}),r=n.length?n:t,i=this.registry.list().map(e=>e.entry.port);return r.find(e=>!i.includes(e))??r[0]??null}info(e){return Promise.resolve(Ot(this.registry,e))}open(e,t){return kt(this.registry,e,t)}close(e){return At(this.registry,e)}read(e,t){return Pt(this.registry,e,t)}write(e,t){return Ft(this.registry,e,t)}getSignals(e){return It(this.registry,e)}setSignals(e,t){return Lt(this.registry,e,t)}},Ut=class e{rpc;constructor(e){this.rpc=e}static REQUEST_TIMEOUT_MS=3e5;static READ_MARGIN_MS=3e4;async list(){return(await this.rpc.call(`serial-list`,void 0)).devices}async request(t){return(await this.rpc.call(`serial-request`,{filters:t},{timeoutMs:e.REQUEST_TIMEOUT_MS})).device}async info(e){return(await this.rpc.call(`serial-device-info`,{handle:e})).device}async open(e,t){await this.rpc.call(`serial-open`,{handle:e,options:t})}async close(e){await this.rpc.call(`serial-close`,{handle:e})}async read(t,n){let r=(n.timeoutMs??1e3)+e.READ_MARGIN_MS,i=await this.rpc.call(`serial-read`,{handle:t,maxBytes:n.maxBytes,until:n.until?Vt(n.until):void 0,timeoutMs:n.timeoutMs},{timeoutMs:r});return new Uint8Array(i.bytes)}async write(e,t){return(await this.rpc.call(`serial-write`,{handle:e,bytes:Vt(t)})).bytesWritten}async getSignals(e){return(await this.rpc.call(`serial-get-signals`,{handle:e})).signals}async setSignals(e,t){await this.rpc.call(`serial-set-signals`,{handle:e,signals:t})}};function Wt(e,t){return e&&z()?new Ht(V()):t?new Ut(t):null}const Gt=e(`usb`);async function K(){return import(`./usb-claim-broker-C5dFP5bv.js`)}function q(e,t){let n=e.get(t);if(!n)throw Error(`unknown usb handle '${t}'`);return n}function J(e,t){if(e>4194304)throw Error(`${t} exceeds the ${ce}-byte (4 MiB) v1 limit`)}function Kt(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}async function qt(e,t){return(await t.getDevices()).map(t=>y(e.register(t),t))}async function Jt(e,t,n){let r=await t.requestDevice({filters:n});return y(e.register(r),r)}function Yt(e,t){return y(t,q(e,t))}async function Xt(e,t){await q(e,t).open()}async function Zt(e,t,n){await cn(e,t,`close`,n)}async function Qt(e,t,n){await q(e,t).selectConfiguration(n)}async function $t(e,t,n,r){let i=r?.owner??`usb`,a=q(e,t),o=await K(),s=await o.acquireInterfaceClaim(e,t,n,i,r?.wait??!1,r?.signal),c=()=>o.claimOwner(e,t,n),l=()=>c()===i,u=()=>o.wasGrantCancelled(e,t,n,i),d=async r=>{if(!(l()&&!u())){if(u()||!c()){if(r)try{await a.releaseInterface(n)}catch{}o.settleCancelledGrant(e,t,n,i),o.wakeInterfaceWaiter(e,t,n)}throw o.claimWaitCancelledError(t,n,i)}};try{await d(!1),await a.claimInterface(n),await d(!0)}catch(r){throw s===`acquired`&&(u()?(o.settleCancelledGrant(e,t,n,i),o.wakeInterfaceWaiter(e,t,n)):l()?o.releaseInterfaceClaim(e,t,n,i):c()||o.wakeInterfaceWaiter(e,t,n)),r}finally{o.clearPendingGrant(e,t,n,i)}}async function en(e,t){let n=await K(),r=n.takeOwnerClaims(e,t);for(let t of r){try{await e.get(t.handle)?.releaseInterface(t.interfaceNumber)}catch{}n.wakeInterfaceWaiter(e,t.handle,t.interfaceNumber)}}async function tn(e,t,n,r){let i=r?.owner??`usb`,a=q(e,t),o=await K(),s=o.claimOwner(e,t,n);if(s&&s!==i)throw new ie({handle:t,holder:s,op:`release`,interfaceNumber:n});await a.releaseInterface(n),o.releaseInterfaceClaim(e,t,n,i)}async function nn(e,t,n,r){J(r,`control-in length`);let i=await q(e,t).controlTransferIn(n,r);return{status:i.status??`ok`,bytes:i.data?Kt(i.data):new ArrayBuffer(0)}}async function rn(e,t,n,r){J(r.byteLength,`control-out payload`);let i=await q(e,t).controlTransferOut(n,r);return{status:i.status??`ok`,bytesWritten:i.bytesWritten}}async function an(e,t,n,r){J(r,`transfer-in length`);let i=await q(e,t).transferIn(n,r);return{status:i.status??`ok`,bytes:i.data?Kt(i.data):new ArrayBuffer(0)}}async function on(e,t,n,r){J(r.byteLength,`transfer-out payload`);let i=await q(e,t).transferOut(n,r);return{status:i.status??`ok`,bytesWritten:i.bytesWritten}}async function sn(e,t,n){await cn(e,t,`reset`,n)}async function cn(e,t,n,r){let i=r?.owner??`usb`,a=r?.force??!1,o=q(e,t),s=await K(),c=s.listClaims(e,t);if(c.length>0){let e=c.map(e=>`${e.interfaceNumber}=${e.owner}`).join(`, `);Gt.warn(`usb ${n} ${t} with claimed interfaces (${e})${a?` [force]`:``}`)}let l=s.assertExclusive(e,t,i,a,n);n===`close`?await o.close():await o.reset(),s.displaceHandle(e,t,{reason:n,displacedBy:i,displaced:l})}async function ln(e,t,n,r){await q(e,t).clearHalt(n,r)}const un=6e4;function dn(){return l()}function fn(e){return new Promise(t=>{let n=!1,r=e=>{n||(n=!0,clearTimeout(i),t(e))},i=setTimeout(()=>r({cancelled:!0}),un);c(`usb-device`,e??[],void 0,{timeoutMs:un}).then(e=>{let t=e;t.cancelled?r({cancelled:!0}):typeof t.error==`string`?r({error:t.error}):t.granted&&t.info?r({granted:!0,info:t.info}):r({error:`usb picker returned an unexpected response`})}).catch(e=>{r({error:e instanceof Error?e.message:`Failed to open USB picker`})})})}function Y(e){let t=new ArrayBuffer(e.byteLength);return new Uint8Array(t).set(e),t}var pn=class{registry;constructor(e){this.registry=e}usb(){let e=oe();if(!e)throw Error(`WebUSB is unavailable in this browser`);return e}list(){return qt(this.registry,this.usb())}async request(e){if(dn()){let t=await fn(e);if(`cancelled`in t)throw Error(`user cancelled the USB picker`);if(`error`in t)throw Error(t.error);let n=await this.reacquire(t.info);if(!n)throw Error(`granted device could not be re-acquired`);return y(this.registry.register(n),n)}return Jt(this.registry,this.usb(),e)}async reacquire(e){return(await this.usb().getDevices()).find(t=>t.vendorId===e.vendorId&&t.productId===e.productId&&(!e.serialNumber||t.serialNumber===e.serialNumber))??null}info(e){return Promise.resolve(Yt(this.registry,e))}open(e){return Xt(this.registry,e)}close(e,t){return Zt(this.registry,e,X(t))}selectConfig(e,t){return Qt(this.registry,e,t)}claim(e,t,n){return $t(this.registry,e,t,X(n))}release(e,t,n){return tn(this.registry,e,t,X(n))}async controlIn(e,t,n){let r=await nn(this.registry,e,t,n);return{status:r.status,bytes:new Uint8Array(r.bytes)}}controlOut(e,t,n){return rn(this.registry,e,t,Y(n))}async transferIn(e,t,n){let r=await an(this.registry,e,t,n);return{status:r.status,bytes:new Uint8Array(r.bytes)}}transferOut(e,t,n){return on(this.registry,e,t,Y(n))}clearHalt(e,t,n){return ln(this.registry,e,t,n)}reset(e,t){return sn(this.registry,e,X(t))}subscribeClaimEvents(e){let t,n=import(`./usb-claim-broker-C5dFP5bv.js`).then(n=>{t=n.addClaimListener(this.registry,e)});return()=>{n.then(()=>t?.())}}dropOwner(e){return en(this.registry,e)}};function X(e){return{...e,owner:e?.owner??`shell`}}var mn=class e{rpc;constructor(e){this.rpc=e}static REQUEST_TIMEOUT_MS=3e5;static CLAIM_WAIT_TIMEOUT_MS=3e5;async list(){return(await this.rpc.call(`usb-list`,void 0)).devices}async request(t){return(await this.rpc.call(`usb-request`,{filters:t},{timeoutMs:e.REQUEST_TIMEOUT_MS})).device}async info(e){return(await this.rpc.call(`usb-device-info`,{handle:e})).device}async open(e){await this.rpc.call(`usb-open`,{handle:e})}async close(e,t){await this.rpc.call(`usb-close`,{handle:e,owner:t?.owner??`shell`,force:t?.force??!1})}async selectConfig(e,t){await this.rpc.call(`usb-select-configuration`,{handle:e,configurationValue:t})}async claim(t,n,r){let i=r?.owner??`shell`,a=r?.wait??!1;try{await this.rpc.call(`usb-claim-interface`,{handle:t,interfaceNumber:n,owner:i,wait:a},a?{timeoutMs:e.CLAIM_WAIT_TIMEOUT_MS}:void 0)}catch(e){throw a&&await this.rpc.call(`usb-cancel-claim-wait`,{handle:t,interfaceNumber:n,owner:i}).catch(()=>void 0),e}}async release(e,t,n){await this.rpc.call(`usb-release-interface`,{handle:e,interfaceNumber:t,owner:n?.owner??`shell`})}async controlIn(e,t,n){let r=await this.rpc.call(`usb-control-transfer-in`,{handle:e,setup:t,length:n});return{status:r.status,bytes:new Uint8Array(r.bytes)}}async controlOut(e,t,n){return this.rpc.call(`usb-control-transfer-out`,{handle:e,setup:t,bytes:Y(n)})}async transferIn(e,t,n){let r=await this.rpc.call(`usb-transfer-in`,{handle:e,endpointNumber:t,length:n});return{status:r.status,bytes:new Uint8Array(r.bytes)}}async transferOut(e,t,n){return this.rpc.call(`usb-transfer-out`,{handle:e,endpointNumber:t,bytes:Y(n)})}async clearHalt(e,t,n){await this.rpc.call(`usb-clear-halt`,{handle:e,direction:t,endpointNumber:n})}async reset(e,t){await this.rpc.call(`usb-reset`,{handle:e,owner:t?.owner??`shell`,force:t?.force??!1})}subscribeClaimEvents(e){return this.rpc.onEvent(`usb-claim-event`,t=>{e(t)})}async dropOwner(e){await this.rpc.call(`usb-drop-owner`,{owner:e})}};function hn(e,t){return e&&oe()?new pn(se()):t?new mn(t):null}const gn=Math.max(ue,fe)+5e3;function _n(e,t,n,r={}){let{header:i,window:a}=be(t),o=new Map,s=!1,c=r.dispatch??(e=>he(e)?pe(e,{allowNoDeadline:!0}):_e(e));function l(e){let t=o.get(e);t&&(clearTimeout(t.timer),o.delete(e))}function u(e,t,n){let r=Math.min(a.byteLength,t.payload.byteLength-n);r>0&&a.set(t.payload.subarray(n,n+r)),Atomics.store(i,2,t.status),Atomics.store(i,3,t.payload.byteLength),Atomics.store(i,4,r),Atomics.store(i,5,n),Atomics.store(i,1,e),Atomics.store(i,0,2),Atomics.notify(i,0),n+r>=t.payload.byteLength&&l(e)}function d(e,t){if(s)return;let{status:n,payload:r}=ve(t);l(e);let i={status:n,payload:r,timer:setTimeout(()=>l(e),gn)};o.set(e,i),u(e,i,0)}let f=e=>{let t=e.data;if(!t||typeof t.id!=`number`)return;if(t.type===`sync-sab-next`){let e=o.get(t.id),n=t.offset;if(!e||typeof n!=`number`||!Number.isInteger(n)||n<0||n>e.payload.byteLength){d(t.id,{ok:!1,errno:`EIO`,message:`sync-sab: bad continuation`});return}u(t.id,e,n);return}if(t.type!==`sync-sab-req`||!t.req||typeof t.req!=`object`)return;let r=t.id,i={...t.req,token:n},a;try{a=c(i)}catch(e){d(r,{ok:!1,errno:`EIO`,message:e instanceof Error?e.message:String(e)});return}a.then(e=>d(r,e),e=>d(r,{ok:!1,errno:`EIO`,message:e instanceof Error?e.message:String(e)}))};return e.addEventListener(`message`,f),{dispose:()=>{if(!s){s=!0,e.removeEventListener(`message`,f);for(let e of[...o.keys()])l(e)}}}}const vn=e(`realm-host`);let yn=0;function bn(e,t,n={}){let r=new Map,i=new Map,a=`${ae}:${++yn}`,o=n.syncFsBridgeEnabled?le({fs:t.fs,...t.exec?{exec:t.exec}:{},cwd:t.cwd}):void 0,s=!1,c=(t,n=[])=>{if(!s)try{e.postMessage(t,n)}catch{}},l={subscriptions:r,pushEvent:c},u={subscriptions:i,pushEvent:c,owner:a},d=new Map,f={spawns:d,opts:n},p={pushEvent:c,pending:new Map,registered:[],backends:new Map,requestSeq:0,pid:n.ppid??null},m=r=>{if(r.data?.type!==`realm-rpc-req`)return;let i=r.data;xn(e,i,t,n,l,u,f,p)};e.addEventListener(`message`,m);let h=o&&n.syncSab?_n(e,n.syncSab,o):void 0;return e.start?.(),{syncFsToken:o,dispose:()=>{if(!s){s=!0,h?.dispose(),o&&ge(o),e.removeEventListener(`message`,m);for(let{controller:e}of d.values())try{e.signal.aborted||e.abort()}catch{}d.clear();for(let e of r.values())try{Promise.resolve(e()).catch(()=>{})}catch{}r.clear(),fr(p);for(let e of i.values())try{Promise.resolve(e()).catch(()=>{})}catch{}i.clear();try{(n.usbBackend??wn(n)).dropOwner?.(a)?.catch(()=>{})}catch{}}}}}async function xn(e,t,n,r,i,a,o,s){try{let c=await Sn(t,n,r,i,a,o,s),l={type:`realm-rpc-res`,id:t.id,result:c},u=hr(c);e.postMessage(l,u)}catch(n){let r=n instanceof Error?n.message:String(n),i={type:`realm-rpc-res`,id:t.id,error:r};e.postMessage(i)}}async function Sn(e,t,n,r,i,a,o){switch(e.channel){case`vfs`:return On(e.op,e.args,t,n.onHostFsMutation);case`exec`:return Vn(e.op,e.args,t,a);case`fetch`:return qn(e.op,e.args,t);case`browser`:return Zn(e.op,e.args,Cn(n),n);case`usb`:return ur(e.op,e.args,wn(n),i);case`serial`:return dr(e.op,e.args,Tn(n));case`hid`:return mr(e.op,e.args,En(n),r);case`computer`:return pr(e.op,e.args,o);case`module`:return Yn(e.op,e.args,t);case`wasm`:return Xn(e.op,e.args,t);default:throw Error(`realm-host: unknown channel '${e.channel}'`)}}function Cn(e){if(e.browser)return e.browser;let t=globalThis;if(t.__slicc_browser)return t.__slicc_browser;throw Error(`browser is not available in this runtime`)}function Z(e){if(e.wsSubscribers)return e.wsSubscribers;let t=globalThis;if(t.__slicc_wsSubscribers)return t.__slicc_wsSubscribers;throw Error(`browser.websocket is not available in this runtime`)}function wn(e){if(e.usbBackend)return e.usbBackend;let t=hn(n(),r());if(!t)throw Error(`usb is not available in this runtime`);return t}function Tn(e){if(e.serialBackend)return e.serialBackend;let t=Wt(n(),r());if(!t)throw Error(`serial is not available in this runtime`);return t}function En(e){if(e.hidBackend)return e.hidBackend;let t=L(n(),r());if(!t)throw Error(`hid is not available in this runtime`);return t}function Dn(e){return[...e.deleted,...e.created.map(e=>e.path),...e.modified.map(e=>e.path)]}async function On(e,t,n,r){let i=typeof t[0]==`string`?t[0]:null,a=i===null?null:n.fs.resolvePath(n.cwd,i);switch(e){case`readFile`:return n.fs.readFile(a);case`readFileBinary`:return n.fs.readFileBuffer(a);case`writeFile`:return await n.fs.writeFile(a,t[1]),a&&r?.([a]),!0;case`writeFileBinary`:return await n.fs.writeFile(a,t[1]),a&&r?.([a]),!0;case`appendFile`:return await n.fs.appendFile(a,t[1]),a&&r?.([a]),!0;case`readDir`:return n.fs.readdir(a);case`exists`:return n.fs.exists(a);case`stat`:{let e=await n.fs.stat(a);return{isDirectory:e.isDirectory,isFile:e.isFile,size:e.size}}case`mkdir`:return await n.fs.mkdir(a,{recursive:!0}),!0;case`rm`:return await n.fs.rm(a,{recursive:!0}),a&&r?.([a]),!0;case`rename`:{let e=n.fs.resolvePath(n.cwd,t[1]),{renameViaFs:i}=await import(`./rename-via-fs-ckVY1Ljv.js`);return await i(n.fs,a,e),r?.(a?[a,e]:[e]),!0}case`resolvePath`:return n.fs.resolvePath(n.cwd,t[0]);case`invalidatePaths`:{let e=t[0],r=n.fs;return r.invalidatePaths&&r.invalidatePaths(e),!0}case`forgetSidecarConsistency`:return await n.fs.forgetSidecarConsistency?.(),!0;case`snapshot`:return Ln(n,typeof t[0]==`string`?t[0]:n.cwd);case`flushWrites`:{let e=t[0];return await Rn(n,e),r?.(Dn(e)),!0}default:throw Error(`realm-host: unknown vfs op '${e}'`)}}const kn=10485760;function An(e){return e.fileCount>=500||e.totalBytes>=kn}function jn(e){return e.entries.length>=2e4}async function Mn(e,t,n,r){r.entries.push({path:t,content:new Uint8Array,isDirectory:!0});let i;try{i=await e.fs.readdir(t)}catch{return}for(let e of i)e!==`node_modules`&&n.push(t===`/`?`/${e}`:`${t}/${e}`)}async function Nn(e,t,n,r){let i=``;try{i=await e.fs.readlink(t)}catch{return}r.entries.push({path:t,content:new Uint8Array,isDirectory:!1,isSymbolicLink:!0,symlinkTarget:i,size:n})}async function Pn(e,t,n,r,i){if(n>1048576||An(r)||r.totalBytes+n>kn){r.entries.push({path:t,content:new Uint8Array,isDirectory:!1,truncated:!0,size:n});return}let a;try{a=await e.fs.readFileBuffer(t)}catch{await Fn(e,t,i,r);return}r.entries.push({path:t,content:a,isDirectory:!1}),r.fileCount+=1,r.totalBytes+=a.byteLength}async function Fn(e,t,n,r){let i;try{i=await e.fs.stat(t)}catch{return}if(i.isDirectory){await Mn(e,t,n,r);return}r.entries.push({path:t,content:new Uint8Array,isDirectory:!1,truncated:!0,size:i.size})}async function In(e,t,n){if(jn(n))return;let r=[t];for(;r.length>0;){if(jn(n))return;let t=r.pop(),i;try{i=await e.fs.lstat(t)}catch{}if(i?.isSymbolicLink){await Nn(e,t,i.size,n);continue}let a;try{a=await e.fs.stat(t)}catch{continue}a.isDirectory?await Mn(e,t,r,n):a.isFile&&await Pn(e,t,a.size,n,r)}}async function Ln(e,t){let n={entries:[],totalBytes:0,fileCount:0};return await In(e,t,n),t!==`/tmp`&&await In(e,`/tmp`,n),{entries:n.entries}}async function Rn(e,t){let n=[],r=async(e,t)=>{try{await t()}catch(t){n.push(`${e}: ${t instanceof Error?t.message:String(t)}`)}};for(let n of t.deleted)await r(n,()=>e.fs.rm(n,{recursive:!0}));for(let n of t.created)n.isSymbolicLink?await r(n.path,()=>e.fs.symlink(n.symlinkTarget??``,n.path)):n.isDirectory?await r(n.path,()=>e.fs.mkdir(n.path,{recursive:!0})):await r(n.path,()=>e.fs.writeFile(n.path,n.content));for(let n of t.modified)await r(n.path,()=>e.fs.writeFile(n.path,n.content));if(n.length>0)throw Error(`sync-fs flush failed for ${n.length} path(s): ${n.join(`; `)}`)}const zn=new Set([`SIGINT`,`SIGTERM`,`SIGKILL`,`SIGSTOP`,`SIGCONT`]),Bn=new Set([`SIGINT`,`SIGTERM`,`SIGKILL`]);async function Vn(e,t,n,r){if(!n.exec)throw Error(`exec is not available in this runtime`);if(e===`run`){let e=t[0],r=await n.exec(e,{cwd:n.cwd});return{stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode}}if(e===`spawn`){let e=t[0];if(!Array.isArray(e)||e.length===0||!e.every(e=>typeof e==`string`))throw Error(`exec.spawn: argv must be a non-empty string[]`);let[r,...i]=e,a=await n.exec(r,{cwd:n.cwd,args:i});return{stdout:a.stdout,stderr:a.stderr,exitCode:a.exitCode}}if(e===`start`)return Gn(t,n,r);if(e===`kill`)return Kn(t,r);throw Error(`realm-host: unknown exec op '${e}'`)}function Hn(e){if(e.stdin!==void 0&&typeof e.stdin!=`string`)throw Error(`exec.start: stdin must be a string`);if(e.stdinKind!==void 0&&e.stdinKind!==`text`&&e.stdinKind!==`bytes`)throw Error(`exec.start: stdinKind must be 'text' or 'bytes'`);if(e.args!==void 0&&(!Array.isArray(e.args)||!e.args.every(e=>typeof e==`string`)))throw Error(`exec.start: args must be a string[]`);if(e.cwd!==void 0&&typeof e.cwd!=`string`)throw Error(`exec.start: cwd must be a string`);if(e.env!==void 0){if(e.env===null||typeof e.env!=`object`||Array.isArray(e.env))throw Error(`exec.start: env must be an object`);for(let[t,n]of Object.entries(e.env))if(n!==void 0&&typeof n!=`string`)throw Error(`exec.start: env[${t}] must be a string`)}}function Un(e){throw Object.assign(Error(e.message),{code:e.errno})}async function Wn(e,t){let n=await me(e.fs,e.cwd,t.cwd);`errno`in n&&Un(n);let r=de(t.env);return r!==void 0&&`errno`in r&&Un(r),{cwd:n.cwd,...r===void 0?{}:{env:r.env}}}async function Gn(e,t,n){let[r,i,a]=e;if(typeof r!=`number`)throw Error(`exec.start: spawnId must be a number`);if(n.spawns.has(r))throw Error(`exec.start: spawnId ${r} is already in use`);let o,s,c;if(Array.isArray(i)){if(i.length===0||!i.every(e=>typeof e==`string`))throw Error(`exec.start: argv must be a non-empty string[]`);[o,...s]=i,c=i.slice()}else if(typeof i==`string`)o=i,c=[i];else throw Error(`exec.start: command must be a string or a non-empty string[]`);let l=a??{};Hn(l);let u=await Wn(t,l),d=new AbortController,{pm:f,owner:p}=n.opts,m=0;f&&p&&(m=f.spawn({kind:`shell`,argv:c,cwd:u.cwd,owner:p,...n.opts.ppid===void 0?{}:{ppid:n.opts.ppid},adoptAbort:d}).pid),n.spawns.set(r,{controller:d,pid:m});let h;try{let e={cwd:u.cwd,signal:d.signal};return l.stdin!==void 0&&(e.stdin=l.stdin),l.stdinKind!==void 0&&(e.stdinKind=l.stdinKind),s===void 0?l.args!==void 0&&(e.args=l.args):e.args=s,u.env!==void 0&&(e.env=u.env,e.replaceEnv=!0),h=await t.exec(o,e),{stdout:h.stdout,stderr:h.stderr,exitCode:h.exitCode}}finally{if(n.spawns.delete(r),f&&m){let e=f.get(m);f.exit(m,e?.terminatedBy?null:h?.exitCode??1)}}}function Kn(e,t){let[n,r]=e,i=t.spawns.get(n);if(!i)return!1;let a=typeof r==`string`&&zn.has(r)?r:`SIGTERM`;Bn.has(a)&&!i.controller.signal.aborted&&i.controller.abort();let{pm:o}=t.opts;return o&&i.pid?o.signal(i.pid,a):!0}async function qn(e,t,n){if(e!==`request`)throw Error(`realm-host: unknown fetch op '${e}'`);let[r,i]=t,a=await(n.fetch?ft(n.fetch):globalThis.fetch.bind(globalThis))(r,i),o={};a.headers.forEach((e,t)=>{o[t]=e});let s=new Uint8Array(await a.arrayBuffer());return{status:a.status,statusText:a.statusText,headers:o,body:s,url:a.url}}function Jn(e){let t=t=>e.fs.resolvePath(e.cwd,t);return{exists:n=>e.fs.exists(t(n)),isDirectory:async n=>{try{return(await e.fs.stat(t(n))).isDirectory}catch{return!1}},readFile:async n=>{let r=await e.fs.readFile(t(n));return typeof r==`string`?r:new TextDecoder().decode(r)}}}async function Yn(e,t,n){if(e!==`buildGraph`)throw Error(`realm-host: unknown module op '${e}'`);let r=typeof t[0]==`string`?t[0]:``,i=typeof t[1]==`string`&&t[1]?t[1]:n.cwd,a=typeof t[2]==`string`?t[2]:``,o=Jn(n),s={reader:o,readBytes:e=>n.fs.readFileBuffer(e),fromDir:i};return Ke({entryCode:r,fromDir:i,entryFilename:a,reader:o,transpile:Ne({ipk:s}),transpileEntry:T({ipk:s})})}async function Xn(e,t,n){if(e!==`compile`)throw Error(`realm-host: unknown wasm op '${e}'`);let r=typeof t[0]==`string`?t[0]:null;if(r===null)throw Error(`realm-host: wasm.compile requires a path argument`);let i=n.fs.resolvePath(n.cwd,r);return re(e=>n.fs.readFileBuffer(e),i)}async function Zn(e,t,n,r){switch(e){case`findTab`:return $n(n,t[0]??{});case`ensureTab`:{let e=t[0];return er(n,e,t[1]??{})}case`openWindow`:{let e=t[0];return tr(n,e,t[1]??{})}case`windowBounds`:{let e=t[0];return n.getWindowBounds(e)}case`setWindowBounds`:{let e=t[0],r=t[1]??{};return n.setWindowBounds(e,r)}case`eval`:{let e=t[0],r=t[1];return nr(n,e,r,!1)}case`evalAsync`:{let e=t[0],r=t[1];return nr(n,e,r,!0)}case`cookie`:{let e=t[0],r=t[1];return or(n,e,r)}case`localStorage`:{let e=t[0],r=t[1];return sr(n,e,r)}case`wsObserve`:{let e={...t[0],scoopJid:r.scoopJid};return await Z(r).observe(e)}case`wsUpdate`:{let e=t[0],n=t[1]??{};return Z(r).update(e,n)}case`wsClose`:{let e=t[0];return Z(r).close(e)}case`wsList`:return Z(r).list();case`createTab`:{let e=t[0];return n.createPage(e)}case`closeTab`:{let e=t[0];return n.closePage(e)}case`setViewport`:{let e=t[0],r=t[1],i=t[2];return n.withTab(e,e=>e.setViewportOverride(r,i))}case`navigateTab`:{let e=t[0],r=t[1];return n.withTab(e,e=>e.navigate(r))}case`screenshotTab`:{let e=t[0],r=t[1];return n.withTab(e,e=>e.screenshot(r))}case`waitForLoadState`:{let e=t[0],r=t[1];return ar(n,e,r)}default:throw Error(`realm-host: unknown browser op '${e}'`)}}function Qn(){try{let e=globalThis.localStorage;return e?!!(e.getItem(`slicc.trayWorkerBaseUrl`)||e.getItem(`slicc.trayJoinUrl`)):!1}catch{return!1}}async function Q(e){if(typeof e.listAllTargets!=`function`)return(await e.listPages()).map(e=>({targetId:e.targetId,url:e.url,title:e.title}));let t=(await e.listAllTargets()).map(e=>({targetId:e.targetId,url:e.url,title:e.title})),n=Qn()?r():null;if(n)try{let{targets:e}=await n.call(`list-remote-targets`,void 0,{timeoutMs:3e3}),r=new Set(t.map(e=>e.targetId));for(let n of e)r.has(n.targetId)||(r.add(n.targetId),t.push({targetId:n.targetId,url:n.url,title:n.title}))}catch(e){vn.debug(`panel-rpc list-remote-targets failed`,{err:String(e)})}return t}async function $n(e,t){let n=await Q(e);if(t.domain){let e=t.domain.toLowerCase();for(let t of n){let n=cr(t.url);if(n&&n.toLowerCase()===e)return t}return null}if(t.urlMatch){let e;try{e=new RegExp(t.urlMatch)}catch(e){throw Error(`browser.findTab: invalid urlMatch regex: ${e instanceof Error?e.message:String(e)}`)}for(let t of n)if(e.test(t.url))return t;return null}throw Error("browser.findTab: query requires `domain` or `urlMatch`")}async function er(e,t,n){let r=await Q(e);if(n.matchUrl){let e;try{e=new RegExp(n.matchUrl)}catch(e){throw Error(`browser.ensureTab: invalid matchUrl regex: ${e instanceof Error?e.message:String(e)}`)}let t=r.find(t=>e.test(t.url));if(t)return t}else{let e=lr(t);if(e){let t=r.find(t=>lr(t.url)===e);if(t)return t}}return{targetId:await e.createPage(t),url:t,title:``}}async function tr(e,t,n){if(typeof e.openWindow!=`function`)throw Error(`browser.openWindow is not available in this runtime`);return{targetId:await e.openWindow(t,n),url:t||`about:blank`,title:``}}async function nr(e,t,n,r){return e.withTab(t,async e=>rr(await e.evaluate(n,{awaitPromise:r,returnByValue:!0})))}function rr(e){if(typeof e!=`string`)return e;let t=ir(e);if(t===void 0)return e;if(typeof t==`object`&&t)return t;if(typeof t==`string`){let e=t.trim();if(e.length>0&&(e[0]===`{`||e[0]===`[`)){let e=ir(t);if(typeof e==`object`&&e)return e}return t}return e}function ir(e){let t=e.trim();if(t.length===0)return;let n=t[0];if(n===`{`||n===`[`||n===`"`||n===`-`||n>=`0`&&n<=`9`||t===`true`||t===`false`||t===`null`)try{return JSON.parse(t)}catch{return}}async function ar(e,t,n){if(n===`networkidle`)return e.withTab(t,async e=>{for(let t=0;t<20;t++)if(await new Promise(e=>setTimeout(e,250)),await e.evaluate(`(function(){
3
3
  try {
4
4
  var entries = performance.getEntriesByType('resource');
5
5
  var now = performance.now();
@@ -15,4 +15,4 @@ import{t as e}from"./logger-LESFN7Hj.js";import{t}from"./content-type-_QKWY0B2.j
15
15
  })()`,{returnByValue:!0}))return})}async function or(e,t,n){return e.withTab(t,async e=>{let t=((await e.send(`Network.getCookies`)).cookies??[]).find(e=>e.name===n);return t&&typeof t.value==`string`?t.value:null})}async function sr(e,t,n){return e.withTab(t,async e=>{let t=await e.evaluate(`(function(){try{var v=window.localStorage.getItem(${JSON.stringify(n)});return v===null?null:String(v);}catch(e){return null;}})()`,{returnByValue:!0});return t==null?null:typeof t==`string`?t:String(t)})}function cr(e){try{return new URL(e).hostname}catch{return null}}function lr(e){try{return new URL(e).origin}catch{return null}}async function ur(e,t,n,r){switch(e){case`list`:return n.list();case`request`:return n.request(t[0]??[]);case`info`:return n.info(t[0]);case`open`:return n.open(t[0]);case`close`:return n.close(t[0],{owner:r.owner,force:!!t[1]?.force});case`reset`:return n.reset(t[0],{owner:r.owner,force:!!t[1]?.force});case`clearHalt`:return n.clearHalt(t[0],t[1],t[2]);case`selectConfig`:return n.selectConfig(t[0],t[1]);case`claim`:return n.claim(t[0],t[1],{owner:r.owner,wait:!!t[2]?.wait});case`release`:return n.release(t[0],t[1],{owner:r.owner});case`controlIn`:return n.controlIn(t[0],t[1],t[2]);case`controlOut`:return n.controlOut(t[0],t[1],t[2]);case`transferIn`:return n.transferIn(t[0],t[1],t[2]);case`transferOut`:return n.transferOut(t[0],t[1],t[2]);case`subscribeClaimEvents`:{let e=t[0];if(r.subscriptions.has(e))return!0;let i=n.subscribeClaimEvents;if(!i)return!0;let a=i(t=>{t.handle===e&&r.pushEvent({type:`realm-event`,channel:`usb-claim-event`,payload:t})});return r.subscriptions.set(e,a),!0}case`unsubscribeClaimEvents`:{let e=t[0],n=r.subscriptions.get(e);return!n||(r.subscriptions.delete(e),await n(),!0)}default:throw Error(`realm-host: unknown usb op '${e}'`)}}async function dr(e,t,n){switch(e){case`list`:return n.list();case`request`:return n.request(t[0]??[]);case`info`:return n.info(t[0]);case`open`:return n.open(t[0],t[1]);case`close`:return n.close(t[0]);case`read`:{let e=t[1]??{};return n.read(t[0],e)}case`write`:return n.write(t[0],t[1]);case`getSignals`:return n.getSignals(t[0]);case`setSignals`:return n.setSignals(t[0],t[1]);default:throw Error(`realm-host: unknown serial op '${e}'`)}}function fr(e){let t=e.registered.splice(0);e.backends.clear(),t.length>0&&import(`./registry-DfuJBCKY.js`).then(({getComputerRegistry:e})=>{let n=e();for(let e of t)n?.unregister(e)});for(let t of e.pending.values())t.reject(Error(`realm disposed`));e.pending.clear()}async function pr(e,t,n){switch(e){case`register`:{let e=t[0],[{JshComputerBackend:r},{getComputerRegistry:i,installComputerRegistry:a}]=await Promise.all([import(`./jsh-BjvyvzNA.js`),import(`./registry-DfuJBCKY.js`)]),o=new r(e,(t,r)=>{let i=`c${++n.requestSeq}`;return new Promise((a,o)=>{n.pending.set(i,{resolve:a,reject:o}),n.pushEvent({type:`realm-event`,channel:`computer-call`,payload:{requestId:i,id:e.id,op:t,args:r}})})});return(i()??a(null)).register(o,{pid:n.pid}),n.registered.push(e.id),n.backends.set(e.id,o),{id:e.id}}case`unregister`:{let e=String(t[0]??``);n.backends.delete(e);let{getComputerRegistry:r}=await import(`./registry-DfuJBCKY.js`);return await r()?.unregister(e),n.registered=n.registered.filter(t=>t!==e),{ok:!0}}case`reply`:{let e=String(t[0]??``),r=t[1],i=n.pending.get(e);if(!i)return{ok:!1};n.pending.delete(e);let a=r?.error;return a?i.reject(Error(a)):i.resolve(r),{ok:!0}}case`frame`:{let e=String(t[0]??``),r=t[1];return n.backends.get(e)?.pushFrame(r),{ok:!0}}default:throw Error(`realm-host: unknown computer op '${e}'`)}}async function mr(e,t,n,r){switch(e){case`list`:return n.list();case`request`:return n.request(t[0]??[]);case`info`:return n.info(t[0]);case`open`:return n.open(t[0]);case`close`:return n.close(t[0]);case`sendReport`:return n.sendReport(t[0],t[1],t[2]);case`sendFeatureReport`:return n.sendFeatureReport(t[0],t[1],t[2]);case`receiveFeatureReport`:return n.receiveFeatureReport(t[0],t[1]);case`subscribeInputReports`:{let e=t[0];if(r.subscriptions.has(e))return!0;let i=await n.subscribeInputReports(e,t=>{let n=t.bytes instanceof Uint8Array?t.bytes:new Uint8Array(t.bytes),i={type:`realm-event`,channel:`hid-input-report`,payload:{handle:e,reportId:t.reportId,bytes:n}};r.pushEvent(i,[n.buffer])});return r.subscriptions.set(e,i),!0}case`unsubscribeInputReports`:{let e=t[0],n=r.subscriptions.get(e);return!n||(r.subscriptions.delete(e),await n(),!0)}default:throw Error(`realm-host: unknown hid op '${e}'`)}}function hr(e){if(e instanceof Uint8Array)return[e.buffer];if(e&&typeof e==`object`){let t=e;if(t.body instanceof Uint8Array)return[t.body.buffer];if(t.bytes instanceof Uint8Array)return[t.bytes.buffer]}return[]}const gr=65536;function _r(e,t){if(!t)return e;let n=e+t;return n.length<=gr?n:n.slice(n.length-gr)}const vr={SIGKILL:137,SIGINT:130,SIGTERM:143};function yr(e,t){let n=Math.max(0,e)/1e3;return`--- killed after ${n<10?n.toFixed(2).replace(/(\.\d*?)0+$/,`$1`).replace(/\.$/,``):String(Math.round(n))}s (exit ${t}) ---\n`}function br(e,t){for(let n of t)e.pendingByPath.delete(n)}function xr(e,t,n){if(e.type===`realm-output`){let r=e;return r.stream===`stdout`?t.stdout=t.captureOutput?t.stdout+r.chunk:_r(t.stdout,r.chunk):t.stderr=t.captureOutput?t.stderr+r.chunk:_r(t.stderr,r.chunk),n?.(r.chunk,r.stream),`live`}if(e.type===`realm-fs-write`){let n=e;return t.pendingByPath.set(n.path,{op:`write`,path:n.path,bytes:n.bytes}),`live`}if(e.type===`realm-fs-delete`){let n=e;return t.pendingByPath.set(n.path,{op:`delete`,path:n.path}),`live`}return e.type===`realm-done`?`done`:e.type===`realm-error`?`error`:`live`}async function Sr(e,t,n){try{if(t.op===`write`){let n=e.fs?.writeFile?.bind(e.fs);n&&await n(t.path,t.bytes)}else{let n=e.fs?.rm?.bind(e.fs);n&&await n(t.path,{recursive:!0})}}catch(e){let r=e instanceof Error?e.message:String(e),i=t.op===`write`?`write`:`delete`;n.stderr+=`[sync-fs] ERROR: ${i} of ${t.path} was NOT persisted: ${r}\n`}}async function Cr(e,t,n){for(let r of e)await Sr(t,r,n)}function wr(e,t,n){return{type:`realm-init`,kind:e.kind,code:e.code,argv:e.realmArgv??e.argv,env:e.env,cwd:e.cwd,filename:e.filename,stdin:e.stdin,pyodideIndexURL:e.pyodideIndexURL,pyodideAssetRoot:e.pyodideAssetRoot,pyodideMountDirs:e.pyodideMountDirs,opfsMountDbName:e.opfsMountDbName,mountPoints:e.mountPoints,...t.syncFsToken===void 0?{}:{syncFsToken:t.syncFsToken},...n?{syncSab:n}:{},...e.captureOutput===!1?{captureOutput:!1}:{}}}async function Tr(e){let t=e.procKind??`jsh`,n=e.pm.spawn({kind:t,argv:e.argv,cwd:e.cwd,env:e.env,owner:e.owner,ppid:e.ppid});e.onSpawn?.(n);let r;try{r=await e.realmFactory({kind:e.kind,ctx:e.ctx})}catch(t){let r=t instanceof Error?t.message:String(t);return e.pm.exit(n.pid,1),{stdout:``,stderr:`realm-runner: ${r}\n`,exitCode:1}}let i=r.isolatedThread?Er(e.syncSabBytes):void 0,a={stdout:``,stderr:``,pendingByPath:new Map,captureOutput:e.captureOutput!==!1},o=bn(r.controlPort,e.ctx,{...e.owner.scoopJid===void 0?{}:{scoopJid:e.owner.scoopJid},pm:e.pm,owner:e.owner,ppid:n.pid,syncFsBridgeEnabled:!!e.syncFsBridgeEnabled||i!==void 0,...i?{syncSab:i}:{},onHostFsMutation:e=>br(a,e)});return new Promise(t=>{let s=!1,c=!1,l=null,u=null,d=null,f=null,p=()=>{if(!c){c=!0,u&&r.controlPort.removeEventListener(`message`,u),r.removeEventListener&&(d&&r.removeEventListener(`error`,d),f&&r.removeEventListener(`messageerror`,f)),l?.();try{r.terminate()}catch{}}},m=(r,i)=>{p(),o.dispose(),e.pm.exit(n.pid,i),t(r)},h=(e,t)=>{s||(s=!0,Promise.resolve().then(()=>m(e,t)))},g=t=>{s||(s=!0,Promise.resolve().then(()=>{let r=[...a.pendingByPath.values()];a.pendingByPath.clear(),p(),Cr(r,e.ctx,a).finally(()=>{let e=yr(Date.now()-n.startedAt,t);m({stdout:a.stdout,stderr:a.stderr+e,exitCode:t},t)})}))};u=t=>{let n=t.data,r=xr(n,a,e.onOutput);if(r===`done`){let e=t.data;h({stdout:e.stdout,stderr:e.stderr,exitCode:e.exitCode},e.exitCode)}else if(r===`error`){let e=t.data;h({stdout:a.stdout,stderr:a.stderr+e.message+`
16
16
  `,exitCode:1},1)}},d=e=>{let t=e.message??`realm error`;h({stdout:a.stdout,stderr:a.stderr+t+`
17
17
  `,exitCode:1},1)},f=()=>{h({stdout:a.stdout,stderr:a.stderr+`realm-runner: worker message could not be deserialized
18
- `,exitCode:1},1)},l=e.pm.onSignal((e,t)=>{if(e.pid!==n.pid)return;let r=vr[t];r!==void 0&&g(r)}),r.controlPort.addEventListener(`message`,u),r.addEventListener&&(r.addEventListener(`error`,d),r.addEventListener(`messageerror`,f)),r.controlPort.postMessage(wr(e,o,i))})}function Er(e){if(ye())try{return new SharedArrayBuffer(64+(e??1048576))}catch{return}}let Dr=!1;function Or(e){Dr=e}function kr(){return Dr}const Ar=Object.freeze({anthropic:`ANTHROPIC_API_KEY`,"ant-ling":`ANT_LING_API_KEY`,"qwen-token-plan":`QWEN_TOKEN_PLAN_API_KEY`,"qwen-token-plan-cn":`QWEN_TOKEN_PLAN_CN_API_KEY`,"qwen-token-plan-individual":`QWEN_TOKEN_PLAN_API_KEY`,openai:`OPENAI_API_KEY`,"azure-openai-responses":`AZURE_OPENAI_API_KEY`,nvidia:`NVIDIA_API_KEY`,deepseek:`DEEPSEEK_API_KEY`,google:`GEMINI_API_KEY`,"google-vertex":`GOOGLE_CLOUD_API_KEY`,groq:`GROQ_API_KEY`,cerebras:`CEREBRAS_API_KEY`,xai:`XAI_API_KEY`,radius:`RADIUS_API_KEY`,openrouter:`OPENROUTER_API_KEY`,"vercel-ai-gateway":`AI_GATEWAY_API_KEY`,zai:`ZAI_API_KEY`,"zai-coding-cn":`ZAI_CODING_CN_API_KEY`,mistral:`MISTRAL_API_KEY`,minimax:`MINIMAX_API_KEY`,"minimax-cn":`MINIMAX_CN_API_KEY`,moonshotai:`MOONSHOT_API_KEY`,"moonshotai-cn":`MOONSHOT_API_KEY`,huggingface:`HF_TOKEN`,fireworks:`FIREWORKS_API_KEY`,together:`TOGETHER_API_KEY`,baseten:`BASETEN_API_KEY`,opencode:`OPENCODE_API_KEY`,"opencode-go":`OPENCODE_API_KEY`,"kimi-coding":`KIMI_API_KEY`,"cloudflare-workers-ai":`CLOUDFLARE_API_KEY`,"cloudflare-ai-gateway":`CLOUDFLARE_API_KEY`,xiaomi:`XIAOMI_API_KEY`,"xiaomi-token-plan-cn":`XIAOMI_TOKEN_PLAN_CN_API_KEY`,"xiaomi-token-plan-ams":`XIAOMI_TOKEN_PLAN_AMS_API_KEY`,"xiaomi-token-plan-sgp":`XIAOMI_TOKEN_PLAN_SGP_API_KEY`});function jr(e){return Ar[e]??null}function Mr(e,t){let n=jr(e);if(!n)return{};let r=t.find(t=>t.providerId===e)?.apiKey?.trim();return r?{[n]:r}:{}}let $=null;function Nr(e){let t=$;return $=e,t}async function Pr(){if(!$)return{};try{return await $()??{}}catch{return{}}}function Fr(){return async()=>{let{getAccounts:e,getSelectedProvider:t}=await import(`./account-store-Br2mSpab.js`).then(e=>e.t);return Mr(t(),e())}}async function Ir(e,t,n,r,i={}){return await n.fs.exists(e)?Lr(await n.fs.readFile(e),[`node`,e,...t],n,r,{...i,filename:e}):{stdout:``,stderr:`jsh: cannot find script '${e}'\n`,exitCode:127}}async function Lr(e,t,n,r,i={}){let a=i.realmFactory??await Rr(),o=r?.processManager??Vr()??Br(),s=r?.owner??{kind:`system`},c=i.filename??t[1]??`<eval>`;return await Tr({pm:o,realmFactory:a,owner:s,kind:`js`,code:E(e,{keepLine:!0}),argv:t,env:{...s.kind===`scoop`||s.kind===`jshd`?{}:await Pr(),...Object.fromEntries(n.env.entries())},cwd:n.cwd,filename:c,stdin:xe(n.stdin),ctx:n,ppid:r?.getParentPid?.(),syncFsBridgeEnabled:kr(),...i.onSpawn?{onSpawn:e=>i.onSpawn?.(e.pid)}:{},...i.onOutput?{onOutput:i.onOutput}:{},...i.captureOutput===!1?{captureOutput:!1}:{}})}async function Rr(){if(typeof Worker<`u`||typeof document<`u`)return S();let{createInProcessJsRealmFactory:e}=await import(`./realm-inprocess-BPdEAS55.js`);return e()}let zr=null;function Br(){return zr||=new u,zr}function Vr(){let e=globalThis.__slicc_pm;return e&&typeof e==`object`&&typeof e.spawn==`function`&&typeof e.onSignal==`function`?e:null}export{Ze as _,kr as a,S as b,hn as c,U as d,z as f,k as g,Qe as h,Nr as i,Wt as l,L as m,Ir as n,Or as o,V as p,Fr as r,Tr as s,Lr as t,H as u,E as v,Te as x,T as y};
18
+ `,exitCode:1},1)},l=e.pm.onSignal((e,t)=>{if(e.pid!==n.pid)return;let r=vr[t];r!==void 0&&g(r)}),r.controlPort.addEventListener(`message`,u),r.addEventListener&&(r.addEventListener(`error`,d),r.addEventListener(`messageerror`,f)),r.controlPort.postMessage(wr(e,o,i))})}function Er(e){if(ye())try{return new SharedArrayBuffer(64+(e??1048576))}catch{return}}let Dr=!1;function Or(e){Dr=e}function kr(){return Dr}const Ar=Object.freeze({anthropic:`ANTHROPIC_API_KEY`,"ant-ling":`ANT_LING_API_KEY`,"qwen-token-plan":`QWEN_TOKEN_PLAN_API_KEY`,"qwen-token-plan-cn":`QWEN_TOKEN_PLAN_CN_API_KEY`,"qwen-token-plan-individual":`QWEN_TOKEN_PLAN_API_KEY`,openai:`OPENAI_API_KEY`,"azure-openai-responses":`AZURE_OPENAI_API_KEY`,nvidia:`NVIDIA_API_KEY`,deepseek:`DEEPSEEK_API_KEY`,google:`GEMINI_API_KEY`,"google-vertex":`GOOGLE_CLOUD_API_KEY`,groq:`GROQ_API_KEY`,cerebras:`CEREBRAS_API_KEY`,xai:`XAI_API_KEY`,radius:`RADIUS_API_KEY`,openrouter:`OPENROUTER_API_KEY`,"vercel-ai-gateway":`AI_GATEWAY_API_KEY`,zai:`ZAI_API_KEY`,"zai-coding-cn":`ZAI_CODING_CN_API_KEY`,mistral:`MISTRAL_API_KEY`,minimax:`MINIMAX_API_KEY`,"minimax-cn":`MINIMAX_CN_API_KEY`,moonshotai:`MOONSHOT_API_KEY`,"moonshotai-cn":`MOONSHOT_API_KEY`,huggingface:`HF_TOKEN`,fireworks:`FIREWORKS_API_KEY`,together:`TOGETHER_API_KEY`,baseten:`BASETEN_API_KEY`,opencode:`OPENCODE_API_KEY`,"opencode-go":`OPENCODE_API_KEY`,"kimi-coding":`KIMI_API_KEY`,"cloudflare-workers-ai":`CLOUDFLARE_API_KEY`,"cloudflare-ai-gateway":`CLOUDFLARE_API_KEY`,xiaomi:`XIAOMI_API_KEY`,"xiaomi-token-plan-cn":`XIAOMI_TOKEN_PLAN_CN_API_KEY`,"xiaomi-token-plan-ams":`XIAOMI_TOKEN_PLAN_AMS_API_KEY`,"xiaomi-token-plan-sgp":`XIAOMI_TOKEN_PLAN_SGP_API_KEY`});function jr(e){return Ar[e]??null}function Mr(e,t){let n=jr(e);if(!n)return{};let r=t.find(t=>t.providerId===e)?.apiKey?.trim();return r?{[n]:r}:{}}let $=null;function Nr(e){let t=$;return $=e,t}async function Pr(){if(!$)return{};try{return await $()??{}}catch{return{}}}function Fr(){return async()=>{let{getAccounts:e,getSelectedProvider:t}=await import(`./account-store-Ck_NeUVO.js`).then(e=>e.t);return Mr(t(),e())}}async function Ir(e,t,n,r,i={}){return await n.fs.exists(e)?Lr(await n.fs.readFile(e),[`node`,e,...t],n,r,{...i,filename:e}):{stdout:``,stderr:`jsh: cannot find script '${e}'\n`,exitCode:127}}async function Lr(e,t,n,r,i={}){let a=i.realmFactory??await Rr(),o=r?.processManager??Vr()??Br(),s=r?.owner??{kind:`system`},c=i.filename??t[1]??`<eval>`;return await Tr({pm:o,realmFactory:a,owner:s,kind:`js`,code:E(e,{keepLine:!0}),argv:t,env:{...s.kind===`scoop`||s.kind===`jshd`?{}:await Pr(),...Object.fromEntries(n.env.entries())},cwd:n.cwd,filename:c,stdin:xe(n.stdin),ctx:n,ppid:r?.getParentPid?.(),syncFsBridgeEnabled:kr(),...i.onSpawn?{onSpawn:e=>i.onSpawn?.(e.pid)}:{},...i.onOutput?{onOutput:i.onOutput}:{},...i.captureOutput===!1?{captureOutput:!1}:{}})}async function Rr(){if(typeof Worker<`u`||typeof document<`u`)return S();let{createInProcessJsRealmFactory:e}=await import(`./realm-inprocess-CiFoJQtp.js`);return e()}let zr=null;function Br(){return zr||=new u,zr}function Vr(){let e=globalThis.__slicc_pm;return e&&typeof e==`object`&&typeof e.spawn==`function`&&typeof e.onSignal==`function`?e:null}export{Ze as _,kr as a,S as b,hn as c,U as d,z as f,k as g,Qe as h,Nr as i,Wt as l,L as m,Ir as n,Or as o,V as p,Fr as r,Tr as s,Lr as t,H as u,E as v,Te as x,T as y};
@@ -1 +1 @@
1
- var e="# jsh runtime extensions\n\nThis file is bundled into the agent VFS at `/workspace/skills/skill-authoring/jsh-runtime-extensions.md`. Developer-facing equivalent: `docs/shell-reference.md` (which lives outside the VFS). Keep both in sync when the runtime surface changes.\n\n## Runtime globals (Globals API)\n\nEvery `.jsh` script runs in an async wrapper with a small Node-standard surface available as bare globals. SLICC's capability bridges (exec, agent, http, browser, USB / Serial / HID, computer, skill, color, cli, time, fmt, pool) are NOT bare globals; they are reached via the `sliccy:` virtual-module scheme below.\n\n### Node-standard bare globals\n\n| Global | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `process` | `argv` (with `.parseFlags()`), `env`, `cwd()`, `exit(code)`, `exitCode` (deferred status: assignment does not unwind; the realm reads it after the event-loop drain, including from an async callback), `stdout.write`, `stderr.write`. `stdin` is a fully-buffered (no streaming) one-shot value with three surfaces sharing one `consumed` flag — `read()` (returns `null` when nothing was piped, Node parity), events (`on('data')`→`'end'`→`'close'`, single chunk, no real streaming — `pause()` suppresses emission until `resume()`, and `exit(N)` from a handler exits with code `N`), and async iterator. Drain via exactly one; the others then see EOF. |\n| `console` | `log`/`info`/`debug`/`dirxml`/`table`/`dir` → stdout; `warn`/`error`/`assert`/`trace` → stderr (`assert` does not throw). `group`/`groupCollapsed`/`groupEnd` indent; `time`/`timeEnd`/`timeLog` and `count`/`countReset` are labeled; `clear` is a no-op. All 19 standard methods are functions. |\n| `fetch` | Standard `fetch` routed through SLICC's proxied transport (cookies + CORS + secret masking handled). Binary bodies (`Uint8Array` / `Blob` / `FormData`) are sent as raw bytes — bytes ≥0x80 are not UTF-8-expanded. `await res.json()` / `res.text()` resolve from the already-buffered body and keep the realm alive for the rest of the continuation. Later WHATWG stream I/O (`Request`/`Response`/`Blob` body reads, `ReadableStream` `read`/`pipeTo`) also keeps the realm alive (succeed or reject — never silent exit 0). |\n| `require(p)` | Synchronous CJS `require`. Use `require('sliccy:<name>')` for capability bridges, `require('fs')` / `require('node:fs')` for the VFS bridge, `require('<pkg>')` for installed packages. |\n| `Buffer` / `globalThis` | Node-standard surface. |\n| `setTimeout` / `clearTimeout` / `setInterval` / `queueMicrotask` | Web timer surface (also reachable through `globalThis`). Outstanding timeouts and intervals keep the realm alive the way Node keeps a process alive for ref'd handles; `queueMicrotask` is not a handle. `process.exit()` cancels pending timers. |\n| `__dirname` / `__filename` | CJS scope vars — the running script's own directory and absolute path. |\n| `module` / `exports` | CJS module record (writeable; useful when a `.jsh` is treated as a library by a sibling `require('./helper.jsh')`). |\n| `process.argv.parseFlags()` | Parse `--flag=val` / `--flag val` / `-x` / positional / `--` passthrough into `{ positional, flags, subcommand, passthrough }`. |\n\n### Capability bridges — `sliccy:` virtual modules\n\nThe bespoke globals are hard-cut. Reach each capability via `require('sliccy:<name>')` (CJS) or `import ... from 'sliccy:<name>'` (ESM). `require('fs')` / `require('node:fs')` keeps returning the VFS bridge.\n\n| `require('sliccy:<name>')` | Purpose |\n| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `sliccy:exec` | Callable `exec(cmd)` plus `.spawn(argv[])`, `.start(cmdOrArgv, opts?)` (killable, buffered-stdin spawn handle) and `.exec` self-reference. Returns `{ stdout, stderr, exitCode }`. Use `const { exec } = require('sliccy:exec')` or `const exec = require('sliccy:exec')`. |\n| `sliccy:agent` | Callable `agent(prompt, opts?)` — spawns a one-shot sub-scoop, feeds it the prompt, blocks until the agent loop completes; resolves to trimmed final text (JSON-parsed when `opts.schema` is set), REJECTS on non-zero exit or schema-parse failure. `.spawn(prompt, opts?)` is the non-throwing variant → `{ finalText, exitCode, stderr }`. `opts`: `model`, `thinking`, `cwd`, `allowedCommands`, `readOnly`, `schema`. |\n| `sliccy:skill` | Frozen `{ dir, root, refs, assets, config(), config(updates), token(providerId) }`. `refs`/`assets` resolve from the skill root (parent of `scripts/` when the script lives there). Replaces ad-hoc `argv[1]` dirname math and `oauth-token` shell-outs. |\n| `sliccy:http` | `http.client({ baseUrl, token, headers, retry, timeoutMs })` builder. |\n| `sliccy:browser` | `findTab`, `ensureTab`, `openWindow`, `windowBounds`, `setWindowBounds`, `eval`, `evalAsync`, `cookie`, `localStorage`, `fetch`, `websocket.on(...).filter(...).forward(...)`. |\n| `sliccy:usb` / `sliccy:serial` / `sliccy:hid` | `list()` / `request()` + device methods (`open`/`close`/`sendReport`/...). Chromium-only. |\n| `sliccy:computer` | `register(handlers)` — jsh-hosted computer backend. Screenshot/input/subscribe round-trip over host `computer-call` events (keep-alive via `onEvent`); frames return via `computer.frame`. |\n| `sliccy:cli` | `die(msg, opts?)`, `out(value)`, `warn(msg, opts?)`, `help(text)`. `opts` is `number` or `{ exitCode?, prefix? }`; `prefix: ''` removes the default `Error:` / `Warning:` label entirely. |\n| `sliccy:color` | ANSI helpers: `green`, `red`, `yellow`, `gray`, `bold`, `cyan`, `dim`, plus `enabled` flag (auto-disabled on non-TTY / `NO_COLOR`). |\n| `sliccy:time` | `parseDuration(spec)`, `ago(spec)`, `range(spec)`, `future(spec)`, `gmailDate(spec)`. Units: `ms s m h d w M y` (note: `m` = minutes, `M` = months). |\n| `sliccy:fmt` | `trunc(s, n)`, `col(s, width)`, `table(rows, widths?)`, `date(value, style?)`. `style`: `'short' \\| 'iso' \\| 'human' \\| 'locale'` (locale = `Intl.DateTimeFormat` medium). |\n| `sliccy:pool` | `pool(n, items, fn)` — bounded concurrency runner, results returned in input order. |\n\n`require('sliccy:<unknown>')` throws a scheme-specific error (`Unknown sliccy: module '<name>'`); empty `require('sliccy:')` throws `empty sliccy: module name`. `sliccy:` lookups never hit the registry / `node_modules` / `ipk install`.\n\n### Filesystem (VFS bridge)\n\n`require('fs')` and `require('node:fs')` return the VFS bridge (`readFile`, `writeFile`, `readFileBinary`, `writeFileBinary`, `appendFile`, `readDir`, `exists`, `stat`, `mkdir`, `rm`, `fetchToFile(url, path)`), plus the sync set (`readFileSync`, `writeFileSync`, `appendFileSync`, `existsSync`, `statSync`, …). All paths are VFS-resolved. There is no bare `fs` global. Async `appendFile` is one locked VFS RPC, so concurrent appends to the same path keep every payload. `writeFileSync` / `appendFileSync` persist at call time, and `console.log` is captured as it prints — a `timeout`/`kill` of the node realm (rc=124/137) still leaves the log file and the stdout written before the hang.\n\nStdio fds and device paths work like Node: `fs.readFileSync(0, 'utf8')` (or `'/dev/stdin'`) reads the full piped stdin without consuming `process.stdin`; `fs.writeFileSync(1, …)` / `fs.writeFileSync(2, …)` (or `/dev/stdout` / `/dev/stderr`) write to stdout/stderr; `existsSync`/`statSync` report the three stream devices as present. Unknown numeric fds and wrong-direction stream ops throw `EBADF`.\n\n### Line reading (`readline`)\n\n`require('readline')` and `require('readline/promises')` work over the buffered stdin:\n\n```javascript\nconst readline = require('readline/promises');\nconst rl = readline.createInterface({ input: process.stdin, output: process.stdout });\nfor await (const line of rl) console.log('>', line);\n// or: rl.on('line', fn) … rl.on('close', fn), or const answer = await rl.question('name? ')\n```\n\nCreating the interface drains `process.stdin` (one-shot, like Node's flowing mode); `question()` answers with the next unconsumed line (`''` at EOF).\n\n### Examples for the non-trivial globals\n\n```javascript\n// process.argv.parseFlags() — replace per-skill arg loops\nconst { positional, flags, subcommand, passthrough } = process.argv.parseFlags();\n// e.g. `mycli send --to alice --json -- --raw` →\n// positional: ['send', 'alice'], flags: { to: 'alice', json: true },\n// subcommand: 'send', passthrough: ['--raw']\n```\n\n**Two-level routing**: `parseFlags` populates `subcommand` only from the first positional. For `<cmd> <sub> [args]` CLIs, route the second level manually from `positional[1]`:\n\n```javascript\nconst { positional, flags } = process.argv.parseFlags();\nconst [cmd, sub] = positional;\nswitch (cmd) {\n case 'pr':\n if (sub === 'list') return prList(flags);\n if (sub === 'view') return prView(positional[2], flags);\n return cli.die(`unknown pr subcommand: ${sub}`);\n // …\n}\n```\n\n```javascript\n// cli + color — early-exit helpers and color (both via sliccy:)\nconst cli = require('sliccy:cli');\nconst c = require('sliccy:color');\nif (!flags.to) cli.die('--to is required'); // writes \"Error: …\" to stderr, exits 1\ncli.out({ ok: true }); // pretty-prints JSON to stdout with trailing newline\nconsole.log(c.green('✓'), c.dim('done'));\n```\n\n```javascript\n// domain-specific prefix instead of the default \"Error:\"\nconst cli = require('sliccy:cli');\nif (!flags.repo) cli.die('--repo is required', { prefix: 'gh' });\n// → \"gh: --repo is required\"\ncli.warn('rate limit at 80%', { prefix: 'gh' });\n```\n\n```javascript\n// time — duration math\nconst time = require('sliccy:time');\nconst since = time.ago('7d'); // Date 7 days ago\nconst q = `after:${time.gmailDate('7d')}`; // \"after:2026/05/22\"\n\n// fmt — ANSI-aware table\nconst fmt = require('sliccy:fmt');\nconst c = require('sliccy:color');\nconsole.log(\n fmt.table([\n ['name', 'status'],\n ['hub', c.green('up')],\n ['relay', c.red('down')],\n ])\n);\n\n// pool — bounded concurrency\nconst pool = require('sliccy:pool');\nconst results = await pool(4, urls, async (url) => (await fetch(url)).status);\n```\n\n```javascript\n// exec.spawn(argv[]) — bypass shell parsing. Use for any arg derived from\n// untrusted input: it can't be shell-interpolated.\nconst { exec } = require('sliccy:exec');\nconst userMessage = flags.message ?? 'wip';\nawait exec.spawn(['git', 'commit', '-m', userMessage]); // safe even with quotes/spaces in userMessage\n```\n\n```javascript\n// exec.start(cmdOrArgv, opts?) — killable, buffered-stdin spawn handle. Buffer\n// stdin with .write(), launch with .end(), await .done for the result, and\n// .kill(signal?) to abort. NOT interactive/streaming — just-bash is one-shot\n// buffered, so stdin is a single upfront buffer and post-launch writes drop.\nconst { exec } = require('sliccy:exec');\nconst h = exec.start(['jq', '.name']);\nh.stdin.write('{\"name\":\"slicc\"}');\nh.stdin.end();\nconst { stdout, exitCode } = await h.done;\n// h.kill('SIGTERM') fans a signal out via the exec:kill op.\n```\n\n```javascript\n// agent — spawn a one-shot sub-scoop and block on its result. The callable\n// resolves to the sub-scoop's final text; with `schema` it resolves to the\n// parsed object (rejects if the reply wasn't valid JSON) and rejects on a\n// non-zero exit. Use agent.spawn(...) when you want the raw outcome instead.\nconst agent = require('sliccy:agent');\nconst summary = await agent('Summarize /workspace/README.md in one line', {\n thinking: 'low',\n readOnly: '/workspace/',\n});\n\nconst parsed = await agent('Extract the title as {\"title\": string}', {\n schema: { type: 'object', properties: { title: { type: 'string' } } },\n});\n\nconst { finalText, exitCode, stderr } = await agent.spawn('do the thing', {\n model: 'claude-opus-4-6',\n cwd: process.env.TMPDIR ?? '/tmp',\n allowedCommands: 'git,node',\n});\n```\n\n### `require('child_process')` — Node process API over the exec bridge\n\n`require('child_process')` / `require('node:child_process')` resolves in the `.jsh` / `node` realm to a shim built on `exec.start`. `exec` / `execFile` / `spawn` map onto the one-shot just-bash exec pipeline: the returned `ChildProcess` is an `EventEmitter` that fires `'exit'` / `'close'`, and its `.stdout` / `.stderr` are Readable stubs that each emit a single `'data'` chunk then `'end'`. `exec` / `execFile` also carry a `util.promisify.custom` implementation resolving `{ stdout, stderr }`.\n\n```javascript\nconst { exec } = require('child_process');\nconst { promisify } = require('util');\nconst { stdout } = await promisify(exec)('ls -la /workspace');\n```\n\nThe **sync forms** (`execSync` / `spawnSync` / `execFileSync`) run on the blocking sync-XHR bridge and follow Node's return/throw contracts (`spawnSync` never throws on a non-zero exit). `{ cwd }` sets the child's working directory; `{ env }` **replaces** the child's environment (spread `process.env` to extend), including `spawnSync('sh', ['-c', …], { env })` / `bash -c`. A missing `cwd` is `ENOENT`, not a silent fallback to the parent. They need a controlling Service Worker; on a float without one they throw an error naming the async escape hatch. `fork` always throws — no long-lived process model. `.bsh` scripts (which run in the target page via CDP, not the realm) have no shell bridge at all, so `require('child_process')` there is unavailable; use `exec()` from a `.jsh` script instead.\n\n## jsh runtime extensions\n\nThe following capabilities collapse the boilerplate that 18 of 23 surveyed skills reinvented. They're available in both standalone and extension floats; each is reached through `require('sliccy:<name>')` (or the equivalent ESM `import`).\n\n### `sliccy:skill` — skill-root paths, config, tokens\n\nComputed once at boot from `argv[1]` and frozen. Replaces ad-hoc `process.argv[1].substring(0, …)` dirname math, bespoke `.config` JSON readers, and `oauth-token` shell-outs.\n\nAgent Skills layout is `<skill-root>/{SKILL.md,scripts/,references/,assets/}`. `skill.dir` is the directory containing the running script. When any path segment of that directory is `scripts` (`<skill-root>/scripts/<name>.jsh`, including helpers under `scripts/<subdir>/`), `skill.root` is the parent of that segment — the skill folder. Otherwise `skill.root` equals `skill.dir`. `skill.refs` and `skill.assets` resolve from `skill.root`. `skill.config()` still reads/writes `<dir>/.config` (typically `scripts/.config`) so `upskill` can preserve that dotfile.\n\n```typescript\nconst skill = require('sliccy:skill');\nskill.dir: string // directory containing the running script\nskill.root: string // skill folder (parent of `scripts/` when applicable)\nskill.refs: string // `<root>/references`\nskill.assets: string // `<root>/assets`\nskill.config(): Promise<Record<string, unknown> | null> // read parsed JSON from `<dir>/.config`\nskill.config(updates): Promise<Record<string, unknown>> // shallow-merge + write, returns merged\nskill.token(providerId: string): Promise<string> // shells out to `oauth-token <id>`\n```\n\n```javascript\nconst skill = require('sliccy:skill');\nconst fs = require('fs');\nconst cfg = (await skill.config()) ?? {};\nconst token = await skill.token('adobe');\nconst tmpl = await fs.readFile(`${skill.refs}/prompt.md`);\n```\n\n### `sliccy:browser` — page-context CDP bridge\n\nReplaces the `exec('playwright-cli tab-list')` shell-out + regex parse used in ~12 skills. Accepts a `TabHandle` (from `findTab` / `ensureTab` / `openWindow`) or a bare `targetId` string. `eval` / `evalAsync` serialize functions to a string call expression so realm code can pass a closure as ergonomically as a string.\n\n```typescript\nconst browser = require('sliccy:browser');\nbrowser.findTab(opts: { domain?: string; urlMatch?: RegExp | string }): Promise<TabHandle | null>\nbrowser.ensureTab(url: string, opts?: { matchUrl?: RegExp | string }): Promise<TabHandle>\nbrowser.openWindow(url: string, opts?: {\n width?: number; height?: number; // FRAME DIP pixels (incl. chrome), not content area\n left?: number; top?: number;\n state?: 'normal' | 'minimized' | 'maximized' | 'fullscreen';\n decorated?: boolean; // default true; false → extension popup chrome\n focus?: boolean; // default true; false opens it unfocused so the user's typing stays in SLICC\n}): Promise<TabHandle>\nbrowser.windowBounds(tab): Promise<{\n left: number; top: number; width: number; height: number;\n state: 'normal' | 'minimized' | 'maximized' | 'fullscreen';\n dpr: number; // devicePixelRatio — capture frame = outer × dpr\n}>\nbrowser.setWindowBounds(tab, bounds: {\n left?: number; top?: number; width?: number; height?: number;\n state?: 'normal' | 'minimized' | 'maximized' | 'fullscreen';\n}): Promise</* achieved bounds (Chrome clamps silently) */>\nbrowser.eval(tab, fn: Function | string): Promise<unknown> // sync expression\nbrowser.evalAsync(tab, fn: AsyncFunction): Promise<unknown> // async, returns parsed JSON\nbrowser.cookie(tab, name: string): Promise<string | null>\nbrowser.localStorage(tab, key: string): Promise<string | null>\n```\n\n**Window sizing units are frame DIP**, matching CDP `Target.createTarget` / `Browser.Bounds` and `chrome.windows.create` (height includes the title bar). That differs from `window.open` features, which size the content area. Do not port a `window.open` size naively — it will be short by the chrome height. `state` other than `normal` cannot be combined with left/top/width/height. `setWindowBounds` always reads back the achieved bounds because Chrome clamps oversized requests without error.\n\nStandalone (Swift / Node CDP) uses `Target.createTarget({ newWindow: true, … })` plus `Browser.get/setWindowBounds`. The Chrome extension maps the same CDP methods onto `chrome.windows.create` / `update` / `get` (chrome.debugger cannot run Browser-domain commands).\n\n```javascript\nconst browser = require('sliccy:browser');\nconst cli = require('sliccy:cli');\nconst tab = await browser.findTab({ domain: 'slack.com' });\nif (!tab) cli.die('open slack.com first');\nconst team = await browser.eval(tab, () => document.title);\nconst xoxc = await browser.localStorage(tab, 'localConfig_v2');\n```\n\n```javascript\n// Sized + decorated capture window (frame 1280×800 at native dpr)\nconst tab = await browser.openWindow('https://example.com/demo', {\n width: 1280,\n height: 800,\n});\nconst { width, height, dpr } = await browser.windowBounds(tab);\n```\n\n### `browser.fetch(tab, url, opts)` — page-context fetch\n\nReplaces the eval-file + base64 + double-JSON-unwrap pattern in ~9 skills. Runs inside the tab's origin, so **session cookies and same-origin headers are automatic** — don't try to forward cookies manually.\n\n```typescript\nbrowser.fetch(tab: TabHandle | string, url: string, opts?: {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | ...;\n headers?: Record<string, string>;\n body?: unknown; // object → JSON-stringified\n credentials?: 'include' | 'omit'; // defaults to 'include'\n responseType?: 'text' | 'json' | 'binary';\n timeoutMs?: number; // page-side AbortSignal.timeout()\n}): Promise<{\n ok: boolean; status: number; statusText: string;\n url: string; redirected: boolean; // final URL after redirects\n headers: Record<string, string>;\n body: unknown; bodyEncoding?: 'base64';\n}>\n```\n\nFrom the shell, `curlwright` is the same capability with curl's flags — reach for it while\nexploring an API, and for `browser.fetch` once the call is settled into a `.jsh`.\n\n```javascript\nconst browser = require('sliccy:browser');\nconst cli = require('sliccy:cli');\nconst resp = await browser.fetch(tab, '/api/conversations.list', {\n method: 'POST',\n body: { limit: 100 },\n});\nif (!resp.ok) cli.die(`slack ${resp.status}`);\nconst channels = resp.body.channels;\n```\n\n### `browser.websocket` — declarative WebSocket observer\n\nSanctioned replacement for `WebSocket.prototype.send` monkey-patches. **REQUIRED for any new WS-watch use case** — skill code MUST NOT author page-context functions that patch a third-party page's prototypes or see the inbound frame firehose.\n\n```typescript\nconst sub = await browser.websocket\n .on(tab, { urlMatch: /wss-primary\\.slack\\.com/ })\n .filter({ parseAs: 'json', where: { type: 'message', channel: 'C0899S7HV0E' } })\n .forward({ sink: 'webhook', webhookId: 'slack-watch-abc123' });\n\nawait sub.update({ filter: { where: { channel: 'C-new' } } });\nawait sub.close();\nawait browser.websocket.list();\n```\n\n**Sink set is a closed enum.** The page-side router (runtime-owned, audited once) only knows how to forward matched frames to:\n\n- `'webhook'` — resolved against the existing `webhook` registry; an unknown `webhookId` rejects at subscriber-creation time.\n- `'scoop'` — delivered via the orchestrator's scoop dispatch.\n- `'vfs'` — appended to an absolute path that must start with `/workspace/`.\n- `'log'` — telemetry only.\n\n**Discovery requires outbound `send()`.** The router patches `WebSocket.prototype.send` as a pure discovery hook — it never observes outbound frames, but a WebSocket instance is only wrapped (and its inbound `message` listener attached) the first time something calls `send()` on it. Receive-only sockets that never call `send()` are not currently captured; trigger a no-op send from the page (or wait for the page to send a heartbeat / subscription frame) before subscribing.\n\nSkills cannot supply an arbitrary URL, cannot supply page-context code (the `filter` selector is a declarative JSON object — `parseAs`, `where`, `project` — and the realm rejects functions or strings of JS at the boundary), and cannot intercept outbound `send` traffic. Subscribers owned by a scoop auto-close when the scoop is dropped.\n\n### `sliccy:http` — standard API-client builder\n\n`require('sliccy:http')` exposes `http.client({ baseUrl, token, headers, retry, timeoutMs })`. Standardizes the `build URL → merge headers → resolve auth → fetch → unwrap JSON → throw on !ok` boilerplate. `token` is **lazy** — resolved freshly per request so token rotation / refresh hooks are picked up without recreating the client. Backoff is exponential, but **`Retry-After` (when present and parseable, in seconds or HTTP date) takes precedence** — the server knows its own rate limit.\n\n```typescript\nconst http = require('sliccy:http');\nhttp.client(config: {\n baseUrl?: string;\n token?: (req?: { method: string; path: string; url: string }) => string | Promise<string | null | undefined>;\n headers?: Record<string, string>;\n retry?: { on: number[]; maxAttempts: number }; // maxAttempts is total (including first)\n timeoutMs?: number; // per-attempt timeout; aborts the fetch\n}): {\n get(path, opts?): Promise<unknown>;\n post(path, opts?): Promise<unknown>;\n put(path, opts?): Promise<unknown>;\n patch(path, opts?): Promise<unknown>;\n delete(path, opts?): Promise<unknown>;\n}\n// opts: { params?, headers?, body?, signal?: AbortSignal, raw?: boolean }\n// - body object → JSON, params → querystring\n// - signal: caller-owned abort signal (timeoutMs creates its own per-attempt signal that combines with this)\n// - raw: when true, returns { body, headers, status } instead of just body — needed for pagination (Link header) and rate-limit (X-RateLimit-*) instrumentation\n```\n\n```javascript\nconst http = require('sliccy:http');\nconst skill = require('sliccy:skill');\nconst api = http.client({\n baseUrl: 'https://graph.microsoft.com/v1.0',\n token: () => skill.token('microsoft'),\n headers: { Accept: 'application/json' },\n retry: { on: [429, 503], maxAttempts: 4 },\n});\n\nconst me = await api.get('/me');\nconst sent = await api.post('/me/sendMail', {\n body: {\n message: {/* … */},\n },\n});\n// Non-2xx throws `HttpError` with { status, statusText, url, body }.\n```\n\n```javascript\n// raw responses for pagination\nconst resp = await api.get('/users', { raw: true });\nconst link = resp.headers['link']; // e.g. '<…/users?page=2>; rel=\"next\"'\n\n// per-request abort\nconst ctl = new AbortController();\nsetTimeout(() => ctl.abort(), 5000);\nawait api.get('/slow', { signal: ctl.signal });\n\n// token with request context (e.g. different token for reads vs writes)\nconst api = http.client({\n baseUrl: 'https://api.example.com',\n token: (req) => (req?.method === 'GET' ? skill.token('read') : skill.token('write')),\n});\n```\n\n### `sliccy:hid` / `sliccy:serial` / `sliccy:usb` — native device scripting\n\n`require('sliccy:hid')` / `require('sliccy:serial')` / `require('sliccy:usb')` expose the WebHID / Web Serial / WebUSB bridges. The top-level entry points are `hid.list()` / `hid.request(filters?)` (and parity `serial.*` / `usb.*`); each device returned carries its opaque handle and methods that round-trip via panel-RPC. The handle namespace is shared with the `hid` / `serial` / `usb` shell commands — a port from `serial request` is reachable as `(await serial.list()).find(p => p.handle === 'serial1')`. Chromium-only; unavailable in the cloud / hosted-leader float. `hid.request()` still needs a user gesture (same as the shell `hid request`).\n\nHID devices expose an `EventTarget`-shaped surface so a VIA-style **request/response in one script** doesn't race: subscribe `'inputreport'` first, then `sendReport`, await the callback. The first listener lazily subscribes the kernel-side relay; the last `removeEventListener` (or realm teardown) unsubscribes — no leaked page-side listeners.\n\n```typescript\nconst hid = require('sliccy:hid');\nhid.list(): Promise<HidDevice[]>\nhid.request(filters?: HidDeviceFilter | HidDeviceFilter[]): Promise<HidDevice>\n\n// On each HidDevice (carries `handle`, `vendorId`, `productId`, `productName`, `collections`):\ndevice.open(): Promise<void>\ndevice.close(): Promise<void>\ndevice.sendReport(reportId: number, data: ArrayBuffer | ArrayBufferView): Promise<void>\ndevice.sendFeatureReport(reportId: number, data: ArrayBuffer | ArrayBufferView): Promise<void>\ndevice.receiveFeatureReport(reportId: number): Promise<DataView>\ndevice.addEventListener('inputreport', cb): void // event: { reportId, data: DataView }\ndevice.removeEventListener('inputreport', cb): void\ndevice.addEventListener('disconnect', cb): void // registers; no backend emit yet\ndevice.onInputReport(cb): void // alias for addEventListener('inputreport', cb)\n```\n\n```javascript\n// VIA-style protocol-version round-trip as a single .jsh script.\n// Subscribe BEFORE sendReport so the reply can't beat the listener.\nconst hid = require('sliccy:hid');\nconst [device] = await hid.list();\nawait device.open();\nconst reply = new Promise((resolve, reject) => {\n const t = setTimeout(() => reject(new Error('timeout')), 1000);\n device.addEventListener('inputreport', function once(e) {\n clearTimeout(t);\n device.removeEventListener('inputreport', once);\n resolve(new Uint8Array(e.data.buffer, e.data.byteOffset, e.data.byteLength));\n });\n});\nawait device.sendReport(0, new Uint8Array([0x01]));\nconst bytes = await reply;\nconsole.log([...bytes].map((b) => b.toString(16).padStart(2, '0')).join(' '));\n```\n\n`serial.*` mirrors the shell surface (`open` / `close` / `read` / `write` / `getSignals` / `setSignals` on serial ports). **`usb.*` does not** — USB device methods carry their **WebUSB** names, not the `usb` shell command's verbs:\n\n```typescript\ndevice.open(): Promise<void>\ndevice.close(opts?: { force?: boolean }): Promise<void>\ndevice.reset(opts?: { force?: boolean }): Promise<void>\ndevice.selectConfiguration(configurationValue: number): Promise<void>\ndevice.claimInterface(interfaceNumber: number, opts?: { wait?: boolean }): Promise<void>\ndevice.releaseInterface(interfaceNumber: number): Promise<void>\ndevice.addEventListener('disconnect' | 'claim-lost', cb): void\ndevice.removeEventListener('disconnect' | 'claim-lost', cb): void\ndevice.controlTransferIn(setup, length): Promise<{ status: string; data: DataView }>\ndevice.controlTransferOut(setup, data): Promise<{ status: string; bytesWritten: number }>\ndevice.transferIn(endpointNumber: number, length: number): Promise<{ status: string; data: DataView }>\ndevice.transferOut(endpointNumber: number, data): Promise<{ status: string; bytesWritten: number }>\ndevice.clearHalt(direction: 'in' | 'out', endpointNumber: number): Promise<void>\n```\n\nSo it is `claimInterface(1)`, not `claim(1)`; `controlTransferIn(...)`, not `controlIn(...)`. Note the read results resolve `{ status, data }` where `data` is a **`DataView`** — wrap it (`new Uint8Array(d.data.buffer, d.data.byteOffset, d.data.byteLength)`) before treating it as bytes.\n\n`clearHalt` recovers a single stalled bulk/interrupt endpoint. Prefer it to\n`reset()`, which re-enumerates the whole device. Handles are shared with the\n`usb` shell command and `slicc.usb`, but interface claims are exclusive: a\nsecond `claimInterface` is refused with the current holder named (or queued\nwith `{ wait: true }`). `close()` / `reset()` refuse while another consumer\nholds a claim unless `{ force: true }`, which emits `claim-lost` then\n`disconnect` so the displaced consumer is told.\n\nEach device also carries its **configuration descriptors** as plain data, so an\ninterface can be located by class/subclass/protocol without opening the device\nand re-reading the descriptor over a control transfer:\n\n```typescript\ndevice.configurations?: Array<{\n configurationValue: number;\n configurationName?: string;\n interfaces: Array<{\n interfaceNumber: number;\n claimed: boolean;\n alternates: Array<{\n alternateSetting: number;\n interfaceClass: number;\n interfaceSubclass: number;\n interfaceProtocol: number;\n interfaceName?: string;\n endpoints: Array<{\n endpointNumber: number;\n direction: 'in' | 'out';\n type: 'bulk' | 'interrupt' | 'isochronous';\n packetSize: number;\n }>;\n }>;\n }>;\n}>\n```\n\nIt is **optional** — absent when the platform does not expose the tree — so\nbranch on it. Endpoints reported with a direction or type outside the vocabulary\nabove are omitted rather than passed through, so matching on those fields is\nsafe.\n\n`serial.*` still has no `EventTarget` shape — that transport is explicit-poll.\n\nFor ESP32 / ESP8266 work, drive `esptool` through `require('sliccy:exec')` (there is no bare `exec` global). Beyond the existing `chip_id` / `read_mac` / `erase_flash` / `write_flash` verbs, the read/inspect set is now `flash_id`, `read_reg <addr>`, `read_flash <addr> <size> <outfile>`, `erase_region <addr> <size>`, and `run`. Pass `--port <handle>` to reuse a port from `serial request` so no second picker fires:\n\n```javascript\nconst serial = require('sliccy:serial');\nconst { exec } = require('sliccy:exec');\nconst port = (await serial.list())[0] ?? (await serial.request());\nconst { stdout } = await exec(`esptool --port ${port.handle} flash_id`);\nconsole.log(stdout);\nawait exec.spawn([\n 'esptool',\n '--port',\n port.handle,\n 'read_flash',\n '0',\n '0x1000',\n `${process.env.TMPDIR ?? '/tmp'}/header.bin`,\n]);\n```\n\n### `sliccy:computer` — jsh-hosted computer backends\n\n`require('sliccy:computer').register(handlers)` registers a computer the `computer` shell command can screenshot and poke. `register()` subscribes to host `computer-call` events, which keeps a `jshd` unit alive the same way `sliccy:hid` inputreport listeners do. The disposer unregisters. Ids are typically `jsh:<name>`.\n\n```javascript\nconst computer = require('sliccy:computer');\ncomputer.register({\n id: 'jsh:fake',\n title: 'fake',\n size: { width: 640, height: 400 },\n capabilities: {\n screenshot: true,\n text: true,\n frames: 'push',\n keyboard: true,\n mouse: 'absolute',\n scroll: false,\n exec: false,\n inputAllowed: true,\n },\n async screenshot() {\n return { seq: 1, mime: 'image/png', width: 640, height: 400, bytes };\n },\n subscribe(fps, onFrame, maxWidth) {\n const timer = setInterval(() => {\n void onFrame({ seq: 1, mime: 'image/png', width: 640, height: 400, bytes });\n }, 1000 / fps);\n return () => clearInterval(timer);\n },\n async text() {\n return '(empty)';\n },\n async input(events) {\n /* mousemove / button / click / scroll / key / text / wait / drag */\n },\n});\n```\n\nHandlers: required `id`, `capabilities`, `screenshot`, `input`; optional `title`, `size`, `softKeys`, `text`, `exec`, `subscribe(fps, onFrame, maxWidth)` (return an unsubscribe). Example: `/workspace/skills/jshd/examples/fake-computer.jsh` (640×400 clock, frame counter, click marker; Home/Back/Menu soft keys move the marker or cycle the background; OffscreenCanvas JPEG or stored-deflate PNG). The real ADB `screenrecord` / `phone-view` consumer lives in the skills repo, not this tree.\n\n## Reaching these from sprinkles & dips\n\nThe high-value capabilities here — `exec` / `exec.spawn`, `fetch`, `http.client`, `browser.*`, and the device APIs (`hid.*` / `serial.*` / `usb.*`) — are also exposed to `.shtml` **sprinkles** and **trusted dips** through the `slicc.*` bridge, which routes each call into the **same worker shell** `.jsh` scripts run in. So a sprinkle button can `await slicc.exec('…')` to reach any supplemental command or `.jsh` script, `await slicc.agent('…')` to spawn a one-shot sub-scoop, or `slicc.hid.on('inputreport', cb)` + `slicc.hid.sendReport(handle, reportId, bytes)` to drive a VIA-style keyboard from a UI panel (handles persist across button clicks). The bridge is trust-gated: VFS-sourced sprinkles and trusted dips get it; untrusted inline-chat dips never receive `exec` / `agent` / `browser` / device globals. See the sprinkles skill (`/workspace/skills/sprinkles/SKILL.md`) \"Shell, agent, and jsh globals\" section, and `docs/shell-reference.md` \"Sprinkle & Dip Bridge\" (developer-facing).\n";export{e as default};
1
+ var e="# jsh runtime extensions\n\nThis file is bundled into the agent VFS at `/workspace/skills/skill-authoring/jsh-runtime-extensions.md`. Developer-facing equivalent: `docs/shell-reference.md` (which lives outside the VFS). Keep both in sync when the runtime surface changes.\n\n## Runtime globals (Globals API)\n\nEvery `.jsh` script runs in an async wrapper with a small Node-standard surface available as bare globals. SLICC's capability bridges (exec, agent, http, browser, USB / Serial / HID, computer, skill, color, cli, time, fmt, pool) are NOT bare globals; they are reached via the `sliccy:` virtual-module scheme below.\n\n### Node-standard bare globals\n\n| Global | Purpose |\n| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `process` | `argv` (with `.parseFlags()`), `env`, `cwd()`, `exit(code)`, `exitCode` (deferred status: assignment does not unwind; the realm reads it after the event-loop drain, including from an async callback), `stdout.write`, `stderr.write`. `stdin` is a fully-buffered (no streaming) one-shot value with three surfaces sharing one `consumed` flag — `read()` (returns `null` when nothing was piped, Node parity), events (`on('data')`→`'end'`→`'close'`, single chunk, no real streaming — `pause()` suppresses emission until `resume()`, and `exit(N)` from a handler exits with code `N`), and async iterator. Drain via exactly one; the others then see EOF. |\n| `console` | `log`/`info`/`debug`/`dirxml`/`table`/`dir` → stdout; `warn`/`error`/`assert`/`trace` → stderr (`assert` does not throw). `group`/`groupCollapsed`/`groupEnd` indent; `time`/`timeEnd`/`timeLog` and `count`/`countReset` are labeled; `clear` is a no-op. All 19 standard methods are functions. |\n| `fetch` | Standard `fetch` routed through SLICC's proxied transport (cookies + CORS + secret masking handled). Binary bodies (`Uint8Array` / `Blob` / `FormData`) are sent as raw bytes — bytes ≥0x80 are not UTF-8-expanded. `await res.json()` / `res.text()` resolve from the already-buffered body and keep the realm alive for the rest of the continuation. Later WHATWG stream I/O (`Request`/`Response`/`Blob` body reads, `ReadableStream` `read`/`pipeTo`) also keeps the realm alive (succeed or reject — never silent exit 0). |\n| `require(p)` | Synchronous CJS `require`. Use `require('sliccy:<name>')` for capability bridges, `require('fs')` / `require('node:fs')` for the VFS bridge, `require('<pkg>')` for installed packages. |\n| `Buffer` / `globalThis` | Node-standard surface. |\n| `setTimeout` / `clearTimeout` / `setInterval` / `queueMicrotask` | Web timer surface (also reachable through `globalThis`). Outstanding timeouts and intervals keep the realm alive the way Node keeps a process alive for ref'd handles; `queueMicrotask` is not a handle. `process.exit()` cancels pending timers. |\n| `__dirname` / `__filename` | CJS scope vars — the running script's own directory and absolute path. |\n| `module` / `exports` | CJS module record (writeable; useful when a `.jsh` is treated as a library by a sibling `require('./helper.jsh')`). |\n| `process.argv.parseFlags()` | Parse `--flag=val` / `--flag val` / `-x` / positional / `--` passthrough into `{ positional, flags, subcommand, passthrough }`. |\n\n### Capability bridges — `sliccy:` virtual modules\n\nThe bespoke globals are hard-cut. Reach each capability via `require('sliccy:<name>')` (CJS) or `import ... from 'sliccy:<name>'` (ESM). `require('fs')` / `require('node:fs')` keeps returning the VFS bridge.\n\n| `require('sliccy:<name>')` | Purpose |\n| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `sliccy:exec` | Callable `exec(cmd)` plus `.spawn(argv[])`, `.start(cmdOrArgv, opts?)` (killable, buffered-stdin spawn handle) and `.exec` self-reference. Returns `{ stdout, stderr, exitCode }`. Use `const { exec } = require('sliccy:exec')` or `const exec = require('sliccy:exec')`. |\n| `sliccy:agent` | Callable `agent(prompt, opts?)` — spawns a one-shot sub-scoop, feeds it the prompt, blocks until the agent loop completes; resolves to trimmed final text (JSON-parsed when `opts.schema` is set), REJECTS on non-zero exit or schema-parse failure. `.spawn(prompt, opts?)` is the non-throwing variant → `{ finalText, exitCode, stderr }`. `opts`: `model`, `thinking`, `cwd`, `allowedCommands`, `readOnly`, `schema`. |\n| `sliccy:skill` | Frozen `{ dir, root, refs, assets, config(), config(updates), token(providerId) }`. `refs`/`assets` resolve from the skill root (parent of `scripts/` when the script lives there). Replaces ad-hoc `argv[1]` dirname math and `oauth-token` shell-outs. |\n| `sliccy:http` | `http.client({ baseUrl, token, headers, retry, timeoutMs })` builder. |\n| `sliccy:browser` | `findTab`, `ensureTab`, `openWindow`, `windowBounds`, `setWindowBounds`, `eval`, `evalAsync`, `cookie`, `localStorage`, `fetch`, `websocket.on(...).filter(...).forward(...)`. |\n| `sliccy:usb` / `sliccy:serial` / `sliccy:hid` | `list()` / `request()` + device methods (`open`/`close`/`sendReport`/...). Chromium-only. |\n| `sliccy:computer` | `register(handlers)` — jsh-hosted computer backend. Screenshot/input/subscribe round-trip over host `computer-call` events (keep-alive via `onEvent`); frames return via `computer.frame`. |\n| `sliccy:cli` | `die(msg, opts?)`, `out(value)`, `warn(msg, opts?)`, `help(text)`. `opts` is `number` or `{ exitCode?, prefix? }`; `prefix: ''` removes the default `Error:` / `Warning:` label entirely. |\n| `sliccy:color` | ANSI helpers: `green`, `red`, `yellow`, `gray`, `bold`, `cyan`, `dim`, plus `enabled` flag (auto-disabled on non-TTY / `NO_COLOR`). |\n| `sliccy:time` | `parseDuration(spec)`, `ago(spec)`, `range(spec)`, `future(spec)`, `gmailDate(spec)`. Units: `ms s m h d w M y` (note: `m` = minutes, `M` = months). |\n| `sliccy:fmt` | `trunc(s, n)`, `col(s, width)`, `table(rows, widths?)`, `date(value, style?)`. `style`: `'short' \\| 'iso' \\| 'human' \\| 'locale'` (locale = `Intl.DateTimeFormat` medium). |\n| `sliccy:pool` | `pool(n, items, fn)` — bounded concurrency runner, results returned in input order. |\n\n`require('sliccy:<unknown>')` throws a scheme-specific error (`Unknown sliccy: module '<name>'`); empty `require('sliccy:')` throws `empty sliccy: module name`. `sliccy:` lookups never hit the registry / `node_modules` / `ipk install`.\n\n### Filesystem (VFS bridge)\n\n`require('fs')` and `require('node:fs')` return the VFS bridge (`readFile`, `writeFile`, `readFileBinary`, `writeFileBinary`, `appendFile`, `readDir`, `exists`, `stat`, `mkdir`, `rm`, `fetchToFile(url, path)`), plus the sync set (`readFileSync`, `writeFileSync`, `appendFileSync`, `existsSync`, `statSync`, …). All paths are VFS-resolved. There is no bare `fs` global. Async `appendFile` is one locked VFS RPC, so concurrent appends to the same path keep every payload. `writeFileSync` / `appendFileSync` persist at call time, and `console.log` is captured as it prints — a `timeout`/`kill` of the node realm (rc=124/137) still leaves the log file and the stdout written before the hang.\n\nStdio fds and device paths work like Node: `fs.readFileSync(0, 'utf8')` (or `'/dev/stdin'`) reads the full piped stdin without consuming `process.stdin`; `fs.writeFileSync(1, …)` / `fs.writeFileSync(2, …)` (or `/dev/stdout` / `/dev/stderr`) write to stdout/stderr; `existsSync`/`statSync` report the three stream devices as present. Unknown numeric fds and wrong-direction stream ops throw `EBADF`.\n\n### Line reading (`readline`)\n\n`require('readline')` and `require('readline/promises')` work over the buffered stdin:\n\n```javascript\nconst readline = require('readline/promises');\nconst rl = readline.createInterface({ input: process.stdin, output: process.stdout });\nfor await (const line of rl) console.log('>', line);\n// or: rl.on('line', fn) … rl.on('close', fn), or const answer = await rl.question('name? ')\n```\n\nCreating the interface drains `process.stdin` (one-shot, like Node's flowing mode); `question()` answers with the next unconsumed line (`''` at EOF).\n\n### Examples for the non-trivial globals\n\n```javascript\n// process.argv.parseFlags() — replace per-skill arg loops\nconst { positional, flags, subcommand, passthrough } = process.argv.parseFlags();\n// e.g. `mycli send --to alice --json -- --raw` →\n// positional: ['send', 'alice'], flags: { to: 'alice', json: true },\n// subcommand: 'send', passthrough: ['--raw']\n```\n\n**Two-level routing**: `parseFlags` populates `subcommand` only from the first positional. For `<cmd> <sub> [args]` CLIs, route the second level manually from `positional[1]`:\n\n```javascript\nconst { positional, flags } = process.argv.parseFlags();\nconst [cmd, sub] = positional;\nswitch (cmd) {\n case 'pr':\n if (sub === 'list') return prList(flags);\n if (sub === 'view') return prView(positional[2], flags);\n return cli.die(`unknown pr subcommand: ${sub}`);\n // …\n}\n```\n\n```javascript\n// cli + color — early-exit helpers and color (both via sliccy:)\nconst cli = require('sliccy:cli');\nconst c = require('sliccy:color');\nif (!flags.to) cli.die('--to is required'); // writes \"Error: …\" to stderr, exits 1\ncli.out({ ok: true }); // pretty-prints JSON to stdout with trailing newline\nconsole.log(c.green('✓'), c.dim('done'));\n```\n\n```javascript\n// domain-specific prefix instead of the default \"Error:\"\nconst cli = require('sliccy:cli');\nif (!flags.repo) cli.die('--repo is required', { prefix: 'gh' });\n// → \"gh: --repo is required\"\ncli.warn('rate limit at 80%', { prefix: 'gh' });\n```\n\n```javascript\n// time — duration math\nconst time = require('sliccy:time');\nconst since = time.ago('7d'); // Date 7 days ago\nconst q = `after:${time.gmailDate('7d')}`; // \"after:2026/05/22\"\n\n// fmt — ANSI-aware table\nconst fmt = require('sliccy:fmt');\nconst c = require('sliccy:color');\nconsole.log(\n fmt.table([\n ['name', 'status'],\n ['hub', c.green('up')],\n ['relay', c.red('down')],\n ])\n);\n\n// pool — bounded concurrency\nconst pool = require('sliccy:pool');\nconst results = await pool(4, urls, async (url) => (await fetch(url)).status);\n```\n\n```javascript\n// exec.spawn(argv[]) — bypass shell parsing. Use for any arg derived from\n// untrusted input: it can't be shell-interpolated.\nconst { exec } = require('sliccy:exec');\nconst userMessage = flags.message ?? 'wip';\nawait exec.spawn(['git', 'commit', '-m', userMessage]); // safe even with quotes/spaces in userMessage\n```\n\n```javascript\n// exec.start(cmdOrArgv, opts?) — killable, buffered-stdin spawn handle. Buffer\n// stdin with .write(), launch with .end(), await .done for the result, and\n// .kill(signal?) to abort. NOT interactive/streaming — just-bash is one-shot\n// buffered, so stdin is a single upfront buffer and post-launch writes drop.\nconst { exec } = require('sliccy:exec');\nconst h = exec.start(['jq', '.name']);\nh.stdin.write('{\"name\":\"slicc\"}');\nh.stdin.end();\nconst { stdout, exitCode } = await h.done;\n// h.kill('SIGTERM') fans a signal out via the exec:kill op.\n```\n\n```javascript\n// agent — spawn a one-shot sub-scoop and block on its result. The callable\n// resolves to the sub-scoop's final text; with `schema` it resolves to the\n// parsed object (rejects if the reply wasn't valid JSON) and rejects on a\n// non-zero exit. Use agent.spawn(...) when you want the raw outcome instead.\nconst agent = require('sliccy:agent');\nconst summary = await agent('Summarize /workspace/README.md in one line', {\n thinking: 'low',\n readOnly: '/workspace/',\n});\n\nconst parsed = await agent('Extract the title as {\"title\": string}', {\n schema: { type: 'object', properties: { title: { type: 'string' } } },\n});\n\nconst { finalText, exitCode, stderr } = await agent.spawn('do the thing', {\n model: 'claude-opus-4-6',\n cwd: process.env.TMPDIR ?? '/tmp',\n allowedCommands: 'git,node',\n});\n```\n\n### `require('child_process')` — Node process API over the exec bridge\n\n`require('child_process')` / `require('node:child_process')` resolves in the `.jsh` / `node` realm to a shim built on `exec.start`. `exec` / `execFile` / `spawn` map onto the one-shot just-bash exec pipeline: the returned `ChildProcess` is an `EventEmitter` that fires `'exit'` / `'close'`, and its `.stdout` / `.stderr` are Readable stubs that each emit a single `'data'` chunk then `'end'`. `exec` / `execFile` also carry a `util.promisify.custom` implementation resolving `{ stdout, stderr }`.\n\n```javascript\nconst { exec } = require('child_process');\nconst { promisify } = require('util');\nconst { stdout } = await promisify(exec)('ls -la /workspace');\n```\n\nThe **sync forms** (`execSync` / `spawnSync` / `execFileSync`) run on the blocking sync-XHR bridge and follow Node's return/throw contracts (`spawnSync` never throws on a non-zero exit). `{ cwd }` sets the child's working directory; `{ env }` **replaces** the child's environment (spread `process.env` to extend), including `spawnSync('sh', ['-c', …], { env })` / `bash -c`. A missing `cwd` is `ENOENT`, not a silent fallback to the parent. They need a controlling Service Worker; on a float without one they throw an error naming the async escape hatch. `fork` always throws — no long-lived process model. `.bsh` scripts (which run in the target page via CDP, not the realm) have no shell bridge at all, so `require('child_process')` there is unavailable; use `exec()` from a `.jsh` script instead.\n\n## jsh runtime extensions\n\nThe following capabilities collapse the boilerplate that 18 of 23 surveyed skills reinvented. They're available in both standalone and extension floats; each is reached through `require('sliccy:<name>')` (or the equivalent ESM `import`).\n\n### `sliccy:skill` — skill-root paths, config, tokens\n\nComputed once at boot from `argv[1]` and frozen. Replaces ad-hoc `process.argv[1].substring(0, …)` dirname math, bespoke `.config` JSON readers, and `oauth-token` shell-outs.\n\nAgent Skills layout is `<skill-root>/{SKILL.md,scripts/,references/,assets/}`. `skill.dir` is the directory containing the running script. When any path segment of that directory is `scripts` (`<skill-root>/scripts/<name>.jsh`, including helpers under `scripts/<subdir>/`), `skill.root` is the parent of that segment — the skill folder. Otherwise `skill.root` equals `skill.dir`. `skill.refs` and `skill.assets` resolve from `skill.root`. `skill.config()` still reads/writes `<dir>/.config` (typically `scripts/.config`) so `upskill` can preserve that dotfile.\n\n```typescript\nconst skill = require('sliccy:skill');\nskill.dir: string // directory containing the running script\nskill.root: string // skill folder (parent of `scripts/` when applicable)\nskill.refs: string // `<root>/references`\nskill.assets: string // `<root>/assets`\nskill.config(): Promise<Record<string, unknown> | null> // read parsed JSON from `<dir>/.config`\nskill.config(updates): Promise<Record<string, unknown>> // shallow-merge + write, returns merged\nskill.token(providerId: string): Promise<string> // shells out to `oauth-token <id>`\n```\n\n```javascript\nconst skill = require('sliccy:skill');\nconst fs = require('fs');\nconst cfg = (await skill.config()) ?? {};\nconst token = await skill.token('adobe');\nconst tmpl = await fs.readFile(`${skill.refs}/prompt.md`);\n```\n\n### `sliccy:browser` — page-context CDP bridge\n\nReplaces the `exec('playwright-cli tab-list')` shell-out + regex parse used in ~12 skills. Accepts a `TabHandle` (from `findTab` / `ensureTab` / `openWindow`) or a bare `targetId` string. `eval` / `evalAsync` serialize functions to a string call expression so realm code can pass a closure as ergonomically as a string.\n\n```typescript\nconst browser = require('sliccy:browser');\nbrowser.findTab(opts: { domain?: string; urlMatch?: RegExp | string }): Promise<TabHandle | null>\nbrowser.ensureTab(url: string, opts?: { matchUrl?: RegExp | string }): Promise<TabHandle>\nbrowser.openWindow(url: string, opts?: {\n width?: number; height?: number; // FRAME DIP pixels (incl. chrome), not content area\n left?: number; top?: number;\n state?: 'normal' | 'minimized' | 'maximized' | 'fullscreen';\n decorated?: boolean; // default true; false → extension popup chrome\n focus?: boolean; // default true; false opens it unfocused so the user's typing stays in SLICC\n}): Promise<TabHandle>\nbrowser.windowBounds(tab): Promise<{\n left: number; top: number; width: number; height: number;\n state: 'normal' | 'minimized' | 'maximized' | 'fullscreen';\n dpr: number; // devicePixelRatio — capture frame = outer × dpr\n}>\nbrowser.setWindowBounds(tab, bounds: {\n left?: number; top?: number; width?: number; height?: number;\n state?: 'normal' | 'minimized' | 'maximized' | 'fullscreen';\n}): Promise</* achieved bounds (Chrome clamps silently) */>\nbrowser.eval(tab, fn: Function | string): Promise<unknown> // sync expression\nbrowser.evalAsync(tab, fn: AsyncFunction): Promise<unknown> // async, returns parsed JSON\nbrowser.cookie(tab, name: string): Promise<string | null>\nbrowser.localStorage(tab, key: string): Promise<string | null>\n```\n\n**Window sizing units are frame DIP**, matching CDP `Target.createTarget` / `Browser.Bounds` and `chrome.windows.create` (height includes the title bar). That differs from `window.open` features, which size the content area. Do not port a `window.open` size naively — it will be short by the chrome height. `state` other than `normal` cannot be combined with left/top/width/height. `setWindowBounds` always reads back the achieved bounds because Chrome clamps oversized requests without error.\n\nStandalone (Swift / Node CDP) uses `Target.createTarget({ newWindow: true, … })` plus `Browser.get/setWindowBounds`. The Chrome extension maps the same CDP methods onto `chrome.windows.create` / `update` / `get` (chrome.debugger cannot run Browser-domain commands).\n\n```javascript\nconst browser = require('sliccy:browser');\nconst cli = require('sliccy:cli');\nconst tab = await browser.findTab({ domain: 'slack.com' });\nif (!tab) cli.die('open slack.com first');\nconst team = await browser.eval(tab, () => document.title);\nconst xoxc = await browser.localStorage(tab, 'localConfig_v2');\n```\n\n```javascript\n// Sized + decorated capture window (frame 1280×800 at native dpr)\nconst tab = await browser.openWindow('https://example.com/demo', {\n width: 1280,\n height: 800,\n});\nconst { width, height, dpr } = await browser.windowBounds(tab);\n```\n\n### `browser.fetch(tab, url, opts)` — page-context fetch\n\nReplaces the eval-file + base64 + double-JSON-unwrap pattern in ~9 skills. Runs inside the tab's origin, so **session cookies and same-origin headers are automatic** — don't try to forward cookies manually.\n\n```typescript\nbrowser.fetch(tab: TabHandle | string, url: string, opts?: {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | ...;\n headers?: Record<string, string>;\n body?: unknown; // object → JSON-stringified\n credentials?: 'include' | 'omit'; // defaults to 'include'\n responseType?: 'text' | 'json' | 'binary';\n timeoutMs?: number; // page-side AbortSignal.timeout()\n}): Promise<{\n ok: boolean; status: number; statusText: string;\n url: string; redirected: boolean; // final URL after redirects\n headers: Record<string, string>;\n body: unknown; bodyEncoding?: 'base64';\n}>\n```\n\nFrom the shell, `curlwright` is the same capability with curl's flags — reach for it while\nexploring an API, and for `browser.fetch` once the call is settled into a `.jsh`.\n\n```javascript\nconst browser = require('sliccy:browser');\nconst cli = require('sliccy:cli');\nconst resp = await browser.fetch(tab, '/api/conversations.list', {\n method: 'POST',\n body: { limit: 100 },\n});\nif (!resp.ok) cli.die(`slack ${resp.status}`);\nconst channels = resp.body.channels;\n```\n\n### `browser.websocket` — declarative WebSocket observer\n\nSanctioned replacement for `WebSocket.prototype.send` monkey-patches. **REQUIRED for any new WS-watch use case** — skill code MUST NOT author page-context functions that patch a third-party page's prototypes or see the inbound frame firehose.\n\n```typescript\nconst sub = await browser.websocket\n .on(tab, { urlMatch: /wss-primary\\.slack\\.com/ })\n .filter({ parseAs: 'json', where: { type: 'message', channel: 'C0899S7HV0E' } })\n .forward({ sink: 'webhook', webhookId: 'slack-watch-abc123' });\n\nawait sub.update({ filter: { where: { channel: 'C-new' } } });\nawait sub.close();\nawait browser.websocket.list();\n```\n\n**Sink set is a closed enum.** The page-side router (runtime-owned, audited once) only knows how to forward matched frames to:\n\n- `'webhook'` — resolved against the existing `webhook` registry; an unknown `webhookId` rejects at subscriber-creation time.\n- `'scoop'` — delivered via the orchestrator's scoop dispatch.\n- `'vfs'` — appended to an absolute path that must start with `/workspace/`.\n- `'log'` — telemetry only.\n\n**Discovery requires outbound `send()`.** The router patches `WebSocket.prototype.send` as a pure discovery hook — it never observes outbound frames, but a WebSocket instance is only wrapped (and its inbound `message` listener attached) the first time something calls `send()` on it. Receive-only sockets that never call `send()` are not currently captured; trigger a no-op send from the page (or wait for the page to send a heartbeat / subscription frame) before subscribing.\n\nSkills cannot supply an arbitrary URL, cannot supply page-context code (the `filter` selector is a declarative JSON object — `parseAs`, `where`, `project` — and the realm rejects functions or strings of JS at the boundary), and cannot intercept outbound `send` traffic. Subscribers owned by a scoop auto-close when the scoop is dropped.\n\n### `sliccy:http` — standard API-client builder\n\n`require('sliccy:http')` exposes `http.client({ baseUrl, token, headers, retry, timeoutMs })`. Standardizes the `build URL → merge headers → resolve auth → fetch → unwrap JSON → throw on !ok` boilerplate. `token` is **lazy** — resolved freshly per request so token rotation / refresh hooks are picked up without recreating the client. Backoff is exponential, but **`Retry-After` (when present and parseable, in seconds or HTTP date) takes precedence** — the server knows its own rate limit.\n\n**Retries are gated by method.** `retry.methods` defaults to the RFC 9110 idempotent set (`GET`/`HEAD`/`OPTIONS`/`TRACE`/`PUT`/`DELETE`), so a `503` (or any status other than `429`) never silently replays a `POST`/`PATCH`: a `503` does not prove the first attempt had no effect — if the write landed and only the response was lost, a retry would duplicate it. `429` is exempt and retries for **every** method (the server rejected the request before acting). To opt a non-idempotent method into retries (e.g. a `POST` carrying an idempotency key), pass `retry: { on: [...], maxAttempts, methods: ['POST', ...] }`.\n\n```typescript\nconst http = require('sliccy:http');\nhttp.client(config: {\n baseUrl?: string;\n token?: (req?: { method: string; path: string; url: string }) => string | Promise<string | null | undefined>;\n headers?: Record<string, string>;\n retry?: { on: number[]; maxAttempts: number; methods?: string[] }; // maxAttempts total (incl. first); methods defaults to the idempotent set (429 retries any method)\n timeoutMs?: number; // per-attempt timeout; aborts the fetch\n}): {\n get(path, opts?): Promise<unknown>;\n post(path, opts?): Promise<unknown>;\n put(path, opts?): Promise<unknown>;\n patch(path, opts?): Promise<unknown>;\n delete(path, opts?): Promise<unknown>;\n}\n// opts: { params?, headers?, body?, signal?: AbortSignal, raw?: boolean }\n// - body object → JSON, params → querystring\n// - signal: caller-owned abort signal (timeoutMs creates its own per-attempt signal that combines with this)\n// - raw: when true, returns { body, headers, status } instead of just body — needed for pagination (Link header) and rate-limit (X-RateLimit-*) instrumentation\n```\n\n```javascript\nconst http = require('sliccy:http');\nconst skill = require('sliccy:skill');\nconst api = http.client({\n baseUrl: 'https://graph.microsoft.com/v1.0',\n token: () => skill.token('microsoft'),\n headers: { Accept: 'application/json' },\n retry: { on: [429, 503], maxAttempts: 4 },\n});\n\nconst me = await api.get('/me');\nconst sent = await api.post('/me/sendMail', {\n body: {\n message: {/* … */},\n },\n});\n// Non-2xx throws `HttpError` with { status, statusText, url, body }.\n```\n\n```javascript\n// raw responses for pagination\nconst resp = await api.get('/users', { raw: true });\nconst link = resp.headers['link']; // e.g. '<…/users?page=2>; rel=\"next\"'\n\n// per-request abort\nconst ctl = new AbortController();\nsetTimeout(() => ctl.abort(), 5000);\nawait api.get('/slow', { signal: ctl.signal });\n\n// token with request context (e.g. different token for reads vs writes)\nconst api = http.client({\n baseUrl: 'https://api.example.com',\n token: (req) => (req?.method === 'GET' ? skill.token('read') : skill.token('write')),\n});\n```\n\n### `sliccy:hid` / `sliccy:serial` / `sliccy:usb` — native device scripting\n\n`require('sliccy:hid')` / `require('sliccy:serial')` / `require('sliccy:usb')` expose the WebHID / Web Serial / WebUSB bridges. The top-level entry points are `hid.list()` / `hid.request(filters?)` (and parity `serial.*` / `usb.*`); each device returned carries its opaque handle and methods that round-trip via panel-RPC. The handle namespace is shared with the `hid` / `serial` / `usb` shell commands — a port from `serial request` is reachable as `(await serial.list()).find(p => p.handle === 'serial1')`. Chromium-only; unavailable in the cloud / hosted-leader float. `hid.request()` still needs a user gesture (same as the shell `hid request`).\n\nHID devices expose an `EventTarget`-shaped surface so a VIA-style **request/response in one script** doesn't race: subscribe `'inputreport'` first, then `sendReport`, await the callback. The first listener lazily subscribes the kernel-side relay; the last `removeEventListener` (or realm teardown) unsubscribes — no leaked page-side listeners.\n\n```typescript\nconst hid = require('sliccy:hid');\nhid.list(): Promise<HidDevice[]>\nhid.request(filters?: HidDeviceFilter | HidDeviceFilter[]): Promise<HidDevice>\n\n// On each HidDevice (carries `handle`, `vendorId`, `productId`, `productName`, `collections`):\ndevice.open(): Promise<void>\ndevice.close(): Promise<void>\ndevice.sendReport(reportId: number, data: ArrayBuffer | ArrayBufferView): Promise<void>\ndevice.sendFeatureReport(reportId: number, data: ArrayBuffer | ArrayBufferView): Promise<void>\ndevice.receiveFeatureReport(reportId: number): Promise<DataView>\ndevice.addEventListener('inputreport', cb): void // event: { reportId, data: DataView }\ndevice.removeEventListener('inputreport', cb): void\ndevice.addEventListener('disconnect', cb): void // registers; no backend emit yet\ndevice.onInputReport(cb): void // alias for addEventListener('inputreport', cb)\n```\n\n```javascript\n// VIA-style protocol-version round-trip as a single .jsh script.\n// Subscribe BEFORE sendReport so the reply can't beat the listener.\nconst hid = require('sliccy:hid');\nconst [device] = await hid.list();\nawait device.open();\nconst reply = new Promise((resolve, reject) => {\n const t = setTimeout(() => reject(new Error('timeout')), 1000);\n device.addEventListener('inputreport', function once(e) {\n clearTimeout(t);\n device.removeEventListener('inputreport', once);\n resolve(new Uint8Array(e.data.buffer, e.data.byteOffset, e.data.byteLength));\n });\n});\nawait device.sendReport(0, new Uint8Array([0x01]));\nconst bytes = await reply;\nconsole.log([...bytes].map((b) => b.toString(16).padStart(2, '0')).join(' '));\n```\n\n`serial.*` mirrors the shell surface (`open` / `close` / `read` / `write` / `getSignals` / `setSignals` on serial ports). **`usb.*` does not** — USB device methods carry their **WebUSB** names, not the `usb` shell command's verbs:\n\n```typescript\ndevice.open(): Promise<void>\ndevice.close(opts?: { force?: boolean }): Promise<void>\ndevice.reset(opts?: { force?: boolean }): Promise<void>\ndevice.selectConfiguration(configurationValue: number): Promise<void>\ndevice.claimInterface(interfaceNumber: number, opts?: { wait?: boolean }): Promise<void>\ndevice.releaseInterface(interfaceNumber: number): Promise<void>\ndevice.addEventListener('disconnect' | 'claim-lost', cb): void\ndevice.removeEventListener('disconnect' | 'claim-lost', cb): void\ndevice.controlTransferIn(setup, length): Promise<{ status: string; data: DataView }>\ndevice.controlTransferOut(setup, data): Promise<{ status: string; bytesWritten: number }>\ndevice.transferIn(endpointNumber: number, length: number): Promise<{ status: string; data: DataView }>\ndevice.transferOut(endpointNumber: number, data): Promise<{ status: string; bytesWritten: number }>\ndevice.clearHalt(direction: 'in' | 'out', endpointNumber: number): Promise<void>\n```\n\nSo it is `claimInterface(1)`, not `claim(1)`; `controlTransferIn(...)`, not `controlIn(...)`. Note the read results resolve `{ status, data }` where `data` is a **`DataView`** — wrap it (`new Uint8Array(d.data.buffer, d.data.byteOffset, d.data.byteLength)`) before treating it as bytes.\n\n`clearHalt` recovers a single stalled bulk/interrupt endpoint. Prefer it to\n`reset()`, which re-enumerates the whole device. Handles are shared with the\n`usb` shell command and `slicc.usb`, but interface claims are exclusive: a\nsecond `claimInterface` is refused with the current holder named (or queued\nwith `{ wait: true }`). `close()` / `reset()` refuse while another consumer\nholds a claim unless `{ force: true }`, which emits `claim-lost` then\n`disconnect` so the displaced consumer is told.\n\nEach device also carries its **configuration descriptors** as plain data, so an\ninterface can be located by class/subclass/protocol without opening the device\nand re-reading the descriptor over a control transfer:\n\n```typescript\ndevice.configurations?: Array<{\n configurationValue: number;\n configurationName?: string;\n interfaces: Array<{\n interfaceNumber: number;\n claimed: boolean;\n alternates: Array<{\n alternateSetting: number;\n interfaceClass: number;\n interfaceSubclass: number;\n interfaceProtocol: number;\n interfaceName?: string;\n endpoints: Array<{\n endpointNumber: number;\n direction: 'in' | 'out';\n type: 'bulk' | 'interrupt' | 'isochronous';\n packetSize: number;\n }>;\n }>;\n }>;\n}>\n```\n\nIt is **optional** — absent when the platform does not expose the tree — so\nbranch on it. Endpoints reported with a direction or type outside the vocabulary\nabove are omitted rather than passed through, so matching on those fields is\nsafe.\n\n`serial.*` still has no `EventTarget` shape — that transport is explicit-poll.\n\nFor ESP32 / ESP8266 work, drive `esptool` through `require('sliccy:exec')` (there is no bare `exec` global). Beyond the existing `chip_id` / `read_mac` / `erase_flash` / `write_flash` verbs, the read/inspect set is now `flash_id`, `read_reg <addr>`, `read_flash <addr> <size> <outfile>`, `erase_region <addr> <size>`, and `run`. Pass `--port <handle>` to reuse a port from `serial request` so no second picker fires:\n\n```javascript\nconst serial = require('sliccy:serial');\nconst { exec } = require('sliccy:exec');\nconst port = (await serial.list())[0] ?? (await serial.request());\nconst { stdout } = await exec(`esptool --port ${port.handle} flash_id`);\nconsole.log(stdout);\nawait exec.spawn([\n 'esptool',\n '--port',\n port.handle,\n 'read_flash',\n '0',\n '0x1000',\n `${process.env.TMPDIR ?? '/tmp'}/header.bin`,\n]);\n```\n\n### `sliccy:computer` — jsh-hosted computer backends\n\n`require('sliccy:computer').register(handlers)` registers a computer the `computer` shell command can screenshot and poke. `register()` subscribes to host `computer-call` events, which keeps a `jshd` unit alive the same way `sliccy:hid` inputreport listeners do. The disposer unregisters. Ids are typically `jsh:<name>`.\n\n```javascript\nconst computer = require('sliccy:computer');\ncomputer.register({\n id: 'jsh:fake',\n title: 'fake',\n size: { width: 640, height: 400 },\n capabilities: {\n screenshot: true,\n text: true,\n frames: 'push',\n keyboard: true,\n mouse: 'absolute',\n scroll: false,\n exec: false,\n inputAllowed: true,\n },\n async screenshot() {\n return { seq: 1, mime: 'image/png', width: 640, height: 400, bytes };\n },\n subscribe(fps, onFrame, maxWidth) {\n const timer = setInterval(() => {\n void onFrame({ seq: 1, mime: 'image/png', width: 640, height: 400, bytes });\n }, 1000 / fps);\n return () => clearInterval(timer);\n },\n async text() {\n return '(empty)';\n },\n async input(events) {\n /* mousemove / button / click / scroll / key / text / wait / drag */\n },\n});\n```\n\nHandlers: required `id`, `capabilities`, `screenshot`, `input`; optional `title`, `size`, `softKeys`, `text`, `exec`, `subscribe(fps, onFrame, maxWidth)` (return an unsubscribe). Example: `/workspace/skills/jshd/examples/fake-computer.jsh` (640×400 clock, frame counter, click marker; Home/Back/Menu soft keys move the marker or cycle the background; OffscreenCanvas JPEG or stored-deflate PNG). The real ADB `screenrecord` / `phone-view` consumer lives in the skills repo, not this tree.\n\n## Reaching these from sprinkles & dips\n\nThe high-value capabilities here — `exec` / `exec.spawn`, `fetch`, `http.client`, `browser.*`, and the device APIs (`hid.*` / `serial.*` / `usb.*`) — are also exposed to `.shtml` **sprinkles** and **trusted dips** through the `slicc.*` bridge, which routes each call into the **same worker shell** `.jsh` scripts run in. So a sprinkle button can `await slicc.exec('…')` to reach any supplemental command or `.jsh` script, `await slicc.agent('…')` to spawn a one-shot sub-scoop, or `slicc.hid.on('inputreport', cb)` + `slicc.hid.sendReport(handle, reportId, bytes)` to drive a VIA-style keyboard from a UI panel (handles persist across button clicks). The bridge is trust-gated: VFS-sourced sprinkles and trusted dips get it; untrusted inline-chat dips never receive `exec` / `agent` / `browser` / device globals. See the sprinkles skill (`/workspace/skills/sprinkles/SKILL.md`) \"Shell, agent, and jsh globals\" section, and `docs/shell-reference.md` \"Sprinkle & Dip Bridge\" (developer-facing).\n";export{e as default};