sootsim 0.1.183 → 0.1.185

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 (156) hide show
  1. package/README.md +22 -19
  2. package/dist-cli/bin.js +6 -6
  3. package/dist-cli/chunks/{agent-AFAFZKMT.js → agent-VF756RZU.js} +2 -2
  4. package/dist-cli/chunks/{agent-wrapper-MV5WGYCS.js → agent-wrapper-IAFL7ROV.js} +2 -2
  5. package/dist-cli/chunks/{app-fonts-ERD5J644.js → app-fonts-VWLEC7ZA.js} +2 -2
  6. package/dist-cli/chunks/{assert-IBMYHSKD.js → assert-I55QVGG7.js} +2 -2
  7. package/dist-cli/chunks/beta-X6YPQVZH.js +2 -0
  8. package/dist-cli/chunks/{camera-Y6XUIEAP.js → camera-CYYBJH7W.js} +2 -2
  9. package/dist-cli/chunks/{chunk-XGVVYY6P.js → chunk-2T73IGB2.js} +2 -2
  10. package/dist-cli/chunks/{chunk-BTIARV2B.js → chunk-4NUQVW5P.js} +17 -4
  11. package/dist-cli/chunks/{chunk-FODJBAWY.js → chunk-4OUQAR34.js} +1 -1
  12. package/dist-cli/chunks/{chunk-RQDJPT6N.js → chunk-7OAUPGLN.js} +2 -2
  13. package/dist-cli/chunks/{chunk-BYKEWDZO.js → chunk-ARNLQPMQ.js} +4 -4
  14. package/dist-cli/chunks/{chunk-AP22KA3Q.js → chunk-BI56RR3G.js} +1 -1
  15. package/dist-cli/chunks/{chunk-WN6XO6JV.js → chunk-BMCBPMTC.js} +1 -1
  16. package/dist-cli/chunks/{chunk-64EKAMA3.js → chunk-C3UEINOZ.js} +2 -2
  17. package/dist-cli/chunks/{chunk-VSDVOOWG.js → chunk-C63EVPDN.js} +2 -2
  18. package/dist-cli/chunks/{chunk-CD3KUHS3.js → chunk-CYBRFHPU.js} +2 -2
  19. package/dist-cli/chunks/chunk-DZLBZGHN.js +62 -0
  20. package/dist-cli/chunks/{chunk-QP4W3SGO.js → chunk-E5DE33BU.js} +1 -1
  21. package/dist-cli/chunks/{chunk-WV7QBUFY.js → chunk-EXFB33AZ.js} +2 -2
  22. package/dist-cli/chunks/{chunk-QF6RJQ2U.js → chunk-FHJTTB3W.js} +2 -2
  23. package/dist-cli/chunks/{chunk-UXHEGFHQ.js → chunk-FUHXL6BW.js} +1 -1
  24. package/dist-cli/chunks/{chunk-WOOWTKM7.js → chunk-FY6DJGOS.js} +1 -1
  25. package/dist-cli/chunks/{chunk-YSTCZI6L.js → chunk-GX6MKIFC.js} +1 -1
  26. package/dist-cli/chunks/{chunk-JR7LKXPB.js → chunk-HQG4DRQ3.js} +1 -1
  27. package/dist-cli/chunks/chunk-IGJHME3T.js +1 -0
  28. package/dist-cli/chunks/{chunk-C7BIPAXT.js → chunk-IJP257WP.js} +1 -1
  29. package/dist-cli/chunks/chunk-JRL7PFNZ.js +463 -0
  30. package/dist-cli/chunks/{chunk-7SP7PFUR.js → chunk-K2THZIVC.js} +1 -1
  31. package/dist-cli/chunks/chunk-KOKIECMB.js +118 -0
  32. package/dist-cli/chunks/{chunk-IJMDXS7N.js → chunk-LI4RLX6B.js} +1 -1
  33. package/dist-cli/chunks/{chunk-3JW7SSYR.js → chunk-LJ3SOZBF.js} +2 -2
  34. package/dist-cli/chunks/{chunk-6TNJLDAQ.js → chunk-M3P67TBN.js} +1 -1
  35. package/dist-cli/chunks/{chunk-OIFGVAV2.js → chunk-MADEJDFD.js} +1 -1
  36. package/dist-cli/chunks/{chunk-RC3FKTYP.js → chunk-NL5IFN4T.js} +2 -2
  37. package/dist-cli/chunks/chunk-OAHGYDJR.js +13 -0
  38. package/dist-cli/chunks/{chunk-RQXZANGL.js → chunk-PDLQWZN4.js} +1 -1
  39. package/dist-cli/chunks/{chunk-KSV6H2IC.js → chunk-PIUKLO3W.js} +1 -1
  40. package/dist-cli/chunks/{chunk-FO3RPGBR.js → chunk-PKZNXDUJ.js} +2 -2
  41. package/dist-cli/chunks/{chunk-N2EXJ7HK.js → chunk-QQ4NSPAD.js} +2 -2
  42. package/dist-cli/chunks/{chunk-W3G5M4UB.js → chunk-QTFCJYBF.js} +3 -3
  43. package/dist-cli/chunks/{chunk-CPZNH3B3.js → chunk-R4KLD4P4.js} +3 -3
  44. package/dist-cli/chunks/chunk-SL6565MR.js +1 -0
  45. package/dist-cli/chunks/{chunk-QQDPEM7F.js → chunk-TFZO277G.js} +1 -1
  46. package/dist-cli/chunks/{chunk-4FVYQIRB.js → chunk-TNHF6BON.js} +1 -1
  47. package/dist-cli/chunks/{chunk-L3FPLPA4.js → chunk-TUF6EPCQ.js} +2 -2
  48. package/dist-cli/chunks/chunk-V4M2R6FZ.js +2 -0
  49. package/dist-cli/chunks/{chunk-6GCEDCO5.js → chunk-V5JEPE3P.js} +2 -2
  50. package/dist-cli/chunks/{chunk-PY4P54SD.js → chunk-WBY4JJ2K.js} +2 -2
  51. package/dist-cli/chunks/{chunk-RAEIXWER.js → chunk-WEJKLJ4B.js} +2 -2
  52. package/dist-cli/chunks/{chunk-SGWTX6CO.js → chunk-X4KS33ZC.js} +2 -2
  53. package/dist-cli/chunks/{chunk-HW65ZTXM.js → chunk-XU5EMZ4B.js} +2 -2
  54. package/dist-cli/chunks/cli-version-ICHQMND6.js +2 -0
  55. package/dist-cli/chunks/{compat-ZTFIQOVI.js → compat-ZJA3N4ZT.js} +3 -3
  56. package/dist-cli/chunks/{control-XWU7LZWC.js → control-CZFSYSYG.js} +2 -2
  57. package/dist-cli/chunks/{cpu-profile-3F2OQNCM.js → cpu-profile-ACSQMVXY.js} +2 -2
  58. package/dist-cli/chunks/daemon-337B4P3B.js +2 -0
  59. package/dist-cli/chunks/{debug-7MIHREPG.js → debug-W2ZOVTQO.js} +3 -3
  60. package/dist-cli/chunks/{detox-CDYD54PS.js → detox-ANJO6T27.js} +2 -2
  61. package/dist-cli/chunks/{device-H53IDQ67.js → device-KPPN4KYD.js} +2 -2
  62. package/dist-cli/chunks/{diagnose-YWSZCFPG.js → diagnose-5PEJYGES.js} +2 -2
  63. package/dist-cli/chunks/drivers-MSDIFHBD.js +2 -0
  64. package/dist-cli/chunks/electron-U456QLSQ.js +19 -0
  65. package/dist-cli/chunks/flow-JL3SC6HC.js +2 -0
  66. package/dist-cli/chunks/help-PA4RTR5X.js +2 -0
  67. package/dist-cli/chunks/{hints-BYH6BMHP.js → hints-MBBQLMQU.js} +2 -2
  68. package/dist-cli/chunks/{home-paths-AXKOJS62.js → home-paths-KQKYP2SE.js} +2 -2
  69. package/dist-cli/chunks/{inspect-TGQU6MZQ.js → inspect-ZP5SM4EW.js} +62 -62
  70. package/dist-cli/chunks/{install-desktop-AOJACCWA.js → install-desktop-OR6ZJ43X.js} +4 -4
  71. package/dist-cli/chunks/{keys-RC6SP7XY.js → keys-JSQMBUE7.js} +2 -2
  72. package/dist-cli/chunks/{login-EQDNEJFU.js → login-DVMWAI3G.js} +4 -4
  73. package/dist-cli/chunks/{logout-QEDUWSSY.js → logout-RIVPFE5N.js} +2 -2
  74. package/dist-cli/chunks/{maestro-6SVETVRL.js → maestro-TX6FPTVH.js} +8 -6
  75. package/dist-cli/chunks/optional-demo-registry-ONYG6DUI.js +2 -0
  76. package/dist-cli/chunks/{preview-UNXWRROE.js → preview-3AD7WNA6.js} +2 -2
  77. package/dist-cli/chunks/{profile-UBHQS25I.js → profile-HY55VFNR.js} +2 -2
  78. package/dist-cli/chunks/{react-THVP5NZX.js → react-HDRCKCKV.js} +2 -2
  79. package/dist-cli/chunks/{record-SOACBRM3.js → record-HW4C7QYN.js} +2 -2
  80. package/dist-cli/chunks/runtime-RHHPW5WO.js +2 -0
  81. package/dist-cli/chunks/{screenshot-MJKWIVV6.js → screenshot-XFR3QN5T.js} +2 -2
  82. package/dist-cli/chunks/{screenshot-mode-RP67FQSA.js → screenshot-mode-Y5CVO267.js} +2 -2
  83. package/dist-cli/chunks/{screenshots-LWDOE4RD.js → screenshots-RKUL2ZZT.js} +2 -2
  84. package/dist-cli/chunks/{screenshots-capture-RUXUL5GO.js → screenshots-capture-RVNF75ZD.js} +8 -8
  85. package/dist-cli/chunks/{serve-TMMMRVTI.js → serve-QMRYLWL5.js} +2 -2
  86. package/dist-cli/chunks/setup-ELNJS7AI.js +97 -0
  87. package/dist-cli/chunks/{skills-P3HEQGPB.js → skills-GPSJYS4W.js} +2 -2
  88. package/dist-cli/chunks/{slides-MICILFXO.js → slides-OCFNPIFG.js} +2 -2
  89. package/dist-cli/chunks/store-MBKDUQEQ.js +2 -0
  90. package/dist-cli/chunks/telemetry-46XXIUEE.js +2 -0
  91. package/dist-cli/chunks/{telemetry-7ZVCPD7R.js → telemetry-KFZQUFG5.js} +2 -2
  92. package/dist-cli/chunks/{test-NT7SGPG5.js → test-Z2HZXCZM.js} +3 -3
  93. package/dist-cli/chunks/{three-mode-6ADYURNM.js → three-mode-NKJFCDYS.js} +2 -2
  94. package/dist-cli/chunks/{timeline-JZNPRKEH.js → timeline-PRGQMQRR.js} +2 -2
  95. package/dist-cli/chunks/upgrade-3NW7JRRX.js +4 -0
  96. package/dist-cli/chunks/upload-QVDVJ6ZK.js +2 -0
  97. package/dist-cli/chunks/{version-GS2J6SFA.js → version-FDTZRIYT.js} +2 -2
  98. package/dist-cli/chunks/{web-J2XC4OK4.js → web-4N5QQEQJ.js} +2 -2
  99. package/dist-cli/chunks/{what-happened-O5MCMYJL.js → what-happened-IX2RRCOS.js} +2 -2
  100. package/dist-cli/chunks/{whoami-Z2Y2X2DN.js → whoami-QZ42FYYF.js} +2 -2
  101. package/dist-lib/agent-daemon-client.cjs +1 -1
  102. package/dist-lib/agent-events.cjs +1 -1
  103. package/dist-lib/agent-sessions.cjs +1 -1
  104. package/dist-lib/attached-projects.cjs +1 -1
  105. package/dist-lib/auth/shared-session.cjs +1 -1
  106. package/dist-lib/backend-origin.cjs +1 -1
  107. package/dist-lib/beta.cjs +1 -1
  108. package/dist-lib/beta.mjs +1 -1
  109. package/dist-lib/bridge-constants.cjs +1 -1
  110. package/dist-lib/cli-constants.cjs +1 -1
  111. package/dist-lib/config.cjs +1 -1
  112. package/dist-lib/detox/index.cjs +1 -1
  113. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  114. package/dist-lib/home-paths.cjs +1 -1
  115. package/dist-lib/host/bridge-host.cjs +1 -1
  116. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  117. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  118. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  119. package/dist-lib/host/websocket-proxy.cjs +1 -1
  120. package/dist-lib/index.cjs +1 -1
  121. package/dist-lib/jump-to-source-babel.cjs +1 -1
  122. package/dist-lib/menu.cjs +1 -1
  123. package/dist-lib/menu.mjs +1 -1
  124. package/dist-lib/metro.cjs +1 -1
  125. package/dist-lib/profiles.cjs +1 -1
  126. package/dist-lib/render-mode.cjs +1 -1
  127. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  128. package/dist-lib/sdk.cjs +1 -1
  129. package/dist-lib/sdk.mjs +1 -1
  130. package/dist-lib/skills.cjs +218 -47
  131. package/dist-lib/vite.cjs +1 -1
  132. package/package.json +1 -1
  133. package/scripts/postinstall.cjs +1 -1
  134. package/skills/soot.md +2 -2
  135. package/skills/sootsim-setup.md +7 -6
  136. package/dist-cli/chunks/beta-T7Z7WSTK.js +0 -2
  137. package/dist-cli/chunks/chunk-4HJKPRWO.js +0 -463
  138. package/dist-cli/chunks/chunk-77GTIGLV.js +0 -1
  139. package/dist-cli/chunks/chunk-B3W63SZA.js +0 -13
  140. package/dist-cli/chunks/chunk-D7ZB6A5T.js +0 -2
  141. package/dist-cli/chunks/chunk-F6DIP2WH.js +0 -62
  142. package/dist-cli/chunks/chunk-MBR6TG2P.js +0 -118
  143. package/dist-cli/chunks/chunk-NLI4YQOY.js +0 -1
  144. package/dist-cli/chunks/cli-version-P4SZNBPQ.js +0 -2
  145. package/dist-cli/chunks/daemon-CUQB4QAP.js +0 -2
  146. package/dist-cli/chunks/drivers-RRCIIDGS.js +0 -2
  147. package/dist-cli/chunks/electron-UPH35PTF.js +0 -18
  148. package/dist-cli/chunks/flow-ZDJI7ICC.js +0 -2
  149. package/dist-cli/chunks/help-U5QGSMDR.js +0 -2
  150. package/dist-cli/chunks/optional-demo-registry-KXYBVP4S.js +0 -2
  151. package/dist-cli/chunks/runtime-BAS2IZFB.js +0 -2
  152. package/dist-cli/chunks/setup-WYKWQPJW.js +0 -77
  153. package/dist-cli/chunks/store-7CIU7X6W.js +0 -2
  154. package/dist-cli/chunks/telemetry-LVBDBPPV.js +0 -2
  155. package/dist-cli/chunks/upgrade-K6V3HYCU.js +0 -4
  156. package/dist-cli/chunks/upload-Q2ZFKOSR.js +0 -2
package/README.md CHANGED
@@ -54,7 +54,7 @@ internally splits into a **shell worker** and a **tenant worker**.
54
54
  graph TD
55
55
  subgraph cli["sootsim CLI process (short-lived, cli/)"]
56
56
  BIN["bin.ts (dispatcher + telemetry)"]
57
- SETUP["commands/setup.ts (daemon + optional repo setup)"]
57
+ SETUP["commands/setup.ts (guided daemon setup)"]
58
58
  RUNTIMECMD["commands/runtime.ts (runtime install/use)"]
59
59
  INSPECT["commands/inspect/* (describe/find/do/get/wait)"]
60
60
  FLOW["bridge-flow-runner.ts (maestro + flow)"]
@@ -131,9 +131,11 @@ graph TD
131
131
  ```
132
132
 
133
133
  **The CLI process** (`cli/bin.ts`) parses argv, emits invocation telemetry, and
134
- lazy-imports exactly one command module per run. `sootsim setup` owns guided
135
- one-time work: install the background daemon, optionally add the Metro/One
136
- repo plugin, and optionally create the advanced config file. `sootsim open`
134
+ lazy-imports exactly one command module per run. Bare `sootsim` and
135
+ `sootsim setup` own guided one-time machine work: ask which package manager you
136
+ use for app commands, explain repo-pinned Node versions, recommend a global
137
+ `sootsim` install, and install the faster background daemon when it is
138
+ missing. `sootsim open`
137
139
  ensures the engine runtime exists and starts a local foreground bridge when no
138
140
  daemon is reachable, then opens a `WsBridge` (`cli/ws-bridge.ts`) on **port
139
141
  7668** and sends JSON commands. Inspection/interaction verbs live in
@@ -178,7 +180,7 @@ distinguish the host page thread, the shell worker, and the tenant worker.)
178
180
 
179
181
  | component | role | key files |
180
182
  | --- | --- | --- |
181
- | sootsim CLI (bin + dispatcher) | Short-lived terminal entry point. Parses argv, emits telemetry, lazy-imports one command per run, and routes setup/open/runtime/inspection flows without a hidden bootstrap path. | `cli/bin.ts`, `cli/parse-args.ts`, `cli/help.ts`, `cli/commands/setup.ts`, `cli/commands/control.ts` |
183
+ | sootsim CLI (bin + dispatcher) | Short-lived terminal entry point. Parses argv, emits telemetry, lazy-imports one command per run, and routes guided setup/open/runtime/inspection flows without a hidden bootstrap path. | `cli/bin.ts`, `cli/parse-args.ts`, `cli/help.ts`, `cli/commands/setup.ts`, `cli/commands/control.ts` |
182
184
  | WsBridge client | Client side of the CLI→daemon link. Resolves the daemon port from the lockfile, opens a WS to `:7668`, sends JSON commands and awaits `{id,result}`/`{id,error}`. Used by every interactive command. | `cli/ws-bridge.ts`, `src/bridge-constants.ts`, `cli/current-sim.ts` |
183
185
  | inspect / SDK command surface | Runtime inspection + interaction verbs (describe, find, do tap, get errors, wait, layout, settle). Re-exported as `sootsim/sdk` so programmatic callers drive a sim the same way the CLI does. | `cli/commands/inspect/core.ts`, `cli/commands/inspect/actions.ts`, `cli/commands/inspect.ts`, `src/sdk.ts` |
184
186
  | flow / maestro / detox runners | Drop-in test compatibility. `bridge-flow-runner.ts` runs maestro-format YAML and recorded flows over the bridge; `detox/` provides a `by`/`element`/`expect`/`device` driver + jest preset so existing Detox suites run unchanged. | `cli/bridge-flow-runner.ts`, `cli/commands/maestro.ts`, `cli/commands/detox.ts`, `detox/index.ts`, `detox/jest-preset.cjs` |
@@ -194,25 +196,26 @@ distinguish the host page thread, the shell worker, and the tenant worker.)
194
196
  ## Getting started
195
197
 
196
198
  ```sh
197
- npm i -g sootsim
198
- sootsim setup # optional but recommended: installs the background daemon
199
- sootsim open 8081 # load a running metro/expo dev server
200
- sootsim link /settings # dispatch a React Native deep link into that app
199
+ npx sootsim # bootstrap into guided setup
200
+ sootsim setup # guided one-time machine setup
201
+ sootsim open 8081 # load a running metro/expo dev server
202
+ sootsim link /settings # dispatch a React Native deep link into that app
201
203
  ```
202
204
 
203
- CLI-first is the canonical path. `sootsim open` starts a local bridge when no
204
- daemon is reachable; `sootsim setup` installs the faster background daemon and
205
- offers optional repo integration. A desktop GUI (Electron) is optional on top,
206
- via `sootsim install-desktop`. In Electron, `File > New Window`
205
+ `npx sootsim` is the bootstrap path; `sootsim` is the normal path after the
206
+ guided setup has you install the CLI globally. There is no per-app install:
207
+ start your Metro, Expo, or One dev server the way you already do, then open it
208
+ from the CLI. There is no iOS native build in the inner loop; Metro alone is
209
+ enough. `sootsim open` starts a local bridge when no daemon is reachable; the
210
+ guided setup installs the faster background daemon so later CLI commands reuse
211
+ one server. A desktop GUI (Electron) is optional on top, via `sootsim
212
+ install-desktop`. In Electron, `File > New Window`
207
213
  duplicates the focused simulator, while `File > New Simulator >` opens a new
208
214
  window for a selected device (same device list as the `Window >` menu).
209
215
 
210
- To uninstall, `npm rm -g sootsim` runs an `preuninstall` hook that tears down
211
- the launchd / systemd daemon and removes `~/.sootsim/` (cache + runtimes +
212
- profiles + lockfile, ~80 MB) before the bin disappears. If you install with
213
- `yarn` / `pnpm` / `bun` (their preuninstall handling varies) or with
214
- `npm rm --ignore-scripts`, run `sootsim daemon uninstall` first — it does the
215
- same teardown manually. Both paths are idempotent and safe to re-run.
216
+ To uninstall the machine daemon and cached runtimes, run
217
+ `sootsim daemon uninstall`. It stops the launchd / systemd daemon and
218
+ removes `~/.sootsim/` (cache + runtimes + profiles + lockfile, ~80 MB).
216
219
 
217
220
  ## Jump to source in inspect mode
218
221
 
package/dist-cli/bin.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
3
- import{a as u,b as d,c as g}from"./chunks/chunk-QQDPEM7F.js";import"./chunks/chunk-YSTCZI6L.js";function f(a){let e=a instanceof Error?a.message:String(a);(/^command timed out after \d+s$/.test(e)||e.startsWith("sim disconnected:")||e.startsWith("bridge never reconnected")||e.startsWith("no sim connected with id ")||e.startsWith("could not connect to ws://")||e.startsWith("sootsim bridge daemon is not running")||e.startsWith("sootsim bridge lockfile is fresh")||e.startsWith("sootsim bridge exited before becoming ready")||e.startsWith("background daemon setup is unavailable")||e.startsWith("sootsim bridge did not start within"))&&!process.env.SOOTSIM_VERBOSE&&(process.stderr.write(` ${e}
2
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
3
+ import{a as u,b as d,c as g}from"./chunks/chunk-TFZO277G.js";import"./chunks/chunk-GX6MKIFC.js";function f(a){let t=a instanceof Error?a.message:String(a);(/^command timed out after \d+s$/.test(t)||t.startsWith("sim disconnected:")||t.startsWith("bridge never reconnected")||t.startsWith("no sim connected with id ")||t.startsWith("could not connect to ws://")||t.startsWith("sootsim bridge daemon is not running")||t.startsWith("sootsim bridge lockfile is fresh")||t.startsWith("sootsim bridge exited before becoming ready")||t.startsWith("background daemon setup is unavailable")||t.startsWith("sootsim bridge did not start within"))&&!process.env.SOOTSIM_VERBOSE&&(process.stderr.write(` ${t}
4
4
  `),process.exit(1)),a instanceof Error&&a.stack?process.stderr.write(`${a.stack}
5
- `):process.stderr.write(`${e}
5
+ `):process.stderr.write(`${t}
6
6
  `),process.exit(1)}process.on("unhandledRejection",f);process.on("uncaughtException",f);var A=typeof __SOOTSIM_STANDALONE__<"u"&&__SOOTSIM_STANDALONE__,k=new Set(["preview","electron","install-desktop"]);function v(a){!A||!k.has(a)||(process.stderr.write(` sootsim ${a} isn't available in the standalone binary \u2014
7
7
  it needs vite / electron / playwright from a project's node_modules.
8
- install the npm package and run via bun or node instead:
9
- npm i -g sootsim && sootsim ${a}
10
- `),process.exit(1))}var t=g(process.argv);{let{trackCliEvent:a}=await import("./chunks/telemetry-LVBDBPPV.js");a({event:"cli_command_invoked",properties:{command:t.command||(t.version?"version":t.help?"help":"none"),arg_count:t.commandArgs.length,platform:process.platform,arch:process.arch,node_version:process.versions.node}})}async function c(a){let{flushCliTelemetry:e}=await import("./chunks/telemetry-LVBDBPPV.js");await e(),process.exit(a)}if(t.version){let{getCliVersion:a}=await import("./chunks/cli-version-P4SZNBPQ.js"),{IS_BETA:e,BETA_LABEL:i}=await import("./chunks/beta-T7Z7WSTK.js"),m=e?` \xB7 ${i}`:"";console.log(`sootsim v${a()}${m}`);let{readActiveRuntime:h}=await import("./chunks/home-paths-AXKOJS62.js"),w=h();console.log(w?`runtime v${w}`:"runtime not installed"),await c(0)}if(t.help&&!t.command){let{printHelp:a}=await import("./chunks/help-U5QGSMDR.js");a(),await c(0)}var o=t.globalFlags.port,n=t.verbose,p=t.globalFlags.device,l=t.globalFlags.theme,S=t.globalFlags.driver,E=t.globalFlags.headless===!0,b=t.globalFlags.sim??t.globalFlags.session??t.globalFlags.tab,s=b?["--sim",b,...t.commandArgs]:t.commandArgs;if(p||l){let{settingsStore:a}=await import("./chunks/store-7CIU7X6W.js"),e={};p&&(e.deviceModel=p),l&&(e.colorScheme=l),a.apply(e)}if(!t.command&&t.commandArgs.length===0){let{printHelp:a}=await import("./chunks/help-U5QGSMDR.js");a(),await c(0)}var r=t.command??"";if(!r){if(t.commandArgs.length>0){let e=t.commandArgs.find(i=>!i.startsWith("-"))??t.commandArgs[0];console.error(` unknown command: ${e}`),console.error(" run `sootsim --help` to see the full surface."),await c(1)}let{printHelp:a}=await import("./chunks/help-U5QGSMDR.js");a(),await c(0)}if(r in d){let a=d[r],e=t.commandArgs.length>0?` ${t.commandArgs.join(" ")}`:"";console.error(` \`sootsim ${r}\` was removed. use \`${a}\` instead.`),e&&console.error(` \u2192 ${a}${e}`),console.error(" run `sootsim --help` to see the new verb groups."),await c(1)}if(t.help||t.commandArgs.includes("--help")||t.commandArgs.includes("-h")){if(r==="skill"){let{runSkill:i}=await import("./chunks/skills-P3HEQGPB.js");await i(t.commandArgs),await c(0)}let a=r==="do"||r==="get"||r==="debug"||r==="shell"||r==="wait",e=t.commandArgs.find(i=>!i.startsWith("-"));if(r!=="shell")if(a&&!e){let{printGroupHelp:i}=await import("./chunks/help-U5QGSMDR.js");i(r)&&await c(0)}else{let{printCommandHelp:i}=await import("./chunks/help-U5QGSMDR.js");i(a&&e?e:r,{prefer:a&&e?"verb":"command",group:a&&e?r:void 0}),await c(0)}}v(r);if(u.has(r)){let{runInspect:a}=await import("./chunks/inspect-TGQU6MZQ.js");await a([r,...s],{port:o,verbose:n})}else switch(r){case"assert":{let{runAssert:a}=await import("./chunks/assert-IBMYHSKD.js");await a(t.commandArgs);break}case"flow":{let{runFlow:a}=await import("./chunks/flow-ZDJI7ICC.js"),e=await a(s);process.exit(typeof e=="number"?e:0)}case"test":{let{runTest:a}=await import("./chunks/test-NT7SGPG5.js");await a(t.commandArgs,{port:o,verbose:n});break}case"detox":{let{runDetox:a}=await import("./chunks/detox-CDYD54PS.js");await a(t.commandArgs,{port:o,verbose:n});break}case"maestro":{let{runMaestro:a}=await import("./chunks/maestro-6SVETVRL.js"),e=await a(s,{port:o,verbose:n});process.exit(typeof e=="number"?e:0)}case"preview":{let{runPreview:a}=await import("./chunks/preview-UNXWRROE.js");await a(t.commandArgs,{port:o,verbose:n});break}case"record":{let{runRecord:a}=await import("./chunks/record-SOACBRM3.js");await a(s,{port:o,verbose:n});break}case"profile":{let{runProfile:a}=await import("./chunks/profile-UBHQS25I.js"),e=await a(t.commandArgs,{port:o,verbose:n});process.exit(typeof e=="number"?e:0)}case"cpu-profile":{let{runCpuProfile:a}=await import("./chunks/cpu-profile-3F2OQNCM.js"),e=await a(s,{port:o,verbose:n});process.exit(typeof e=="number"?e:0)}case"react":{let{runReact:a}=await import("./chunks/react-THVP5NZX.js"),e=await a(s,{port:o,verbose:n});process.exit(typeof e=="number"?e:0)}case"screenshot":{let{runScreenshot:a}=await import("./chunks/screenshot-MJKWIVV6.js");await a(s,{port:o,verbose:n});break}case"screenshots":{if(t.commandArgs[0]==="capture"){let{runScreenshotsCapture:i}=await import("./chunks/screenshots-capture-RUXUL5GO.js"),m=await i(t.commandArgs.slice(1));process.exit(typeof m=="number"?m:0)}let{runScreenshots:a}=await import("./chunks/screenshots-LWDOE4RD.js"),e=await a(s,{port:o,verbose:n});process.exit(typeof e=="number"?e:0)}case"screenshot-mode":{let{runScreenshotMode:a}=await import("./chunks/screenshot-mode-RP67FQSA.js");await a(t.commandArgs,{port:o,verbose:n});break}case"slides":{let{runSlides:a}=await import("./chunks/slides-MICILFXO.js");await a(s,{port:o,verbose:n});break}case"three-mode":case"3d-mode":{let{runThreeMode:a}=await import("./chunks/three-mode-6ADYURNM.js");await a(t.commandArgs,{port:o,verbose:n});break}case"inspect":{let{runInspect:a}=await import("./chunks/inspect-TGQU6MZQ.js");await a(s,{port:o,verbose:n});break}case"debug":{let{runDebug:a}=await import("./chunks/debug-7MIHREPG.js");await a(s,{port:o,verbose:n});break}case"camera":{let{runCamera:a}=await import("./chunks/camera-Y6XUIEAP.js");await a(s,{port:o});break}case"timeline":{let{runTimeline:a}=await import("./chunks/timeline-JZNPRKEH.js");await a(s,{port:o,verbose:n});break}case"what-happened":{let{runWhatHappened:a}=await import("./chunks/what-happened-O5MCMYJL.js");await a(s,{port:o,verbose:n});break}case"diagnose":{let{runDiagnose:a}=await import("./chunks/diagnose-YWSZCFPG.js"),e=await a(s,{port:o,verbose:n});process.exit(typeof e=="number"?e:0)}case"open":{let{runOpenCommand:a}=await import("./chunks/control-XWU7LZWC.js");await a(s,{port:o});break}case"link":{let{runLinkCommand:a}=await import("./chunks/control-XWU7LZWC.js");await a(s,{port:o});break}case"use":case"focus":{let{runUseCommand:a}=await import("./chunks/control-XWU7LZWC.js");await a(s,{port:o});break}case"claim":{let{runClaimCommand:a}=await import("./chunks/control-XWU7LZWC.js");await a(s,{port:o});break}case"close":{let{runCloseCommand:a}=await import("./chunks/control-XWU7LZWC.js");await a(s,{port:o});break}case"device":{let{runDeviceCommand:a}=await import("./chunks/device-H53IDQ67.js");await a(s,{port:o});break}case"scan":case"compat":{let{runCompat:a}=await import("./chunks/compat-ZTFIQOVI.js");await a(t.commandArgs);break}case"electron":{let{runElectron:a}=await import("./chunks/electron-UPH35PTF.js");await a(t.commandArgs,{port:o,device:p,driver:S});break}case"login":{let{runLogin:a}=await import("./chunks/login-EQDNEJFU.js");await a(t.commandArgs);break}case"logout":{let{runLogout:a}=await import("./chunks/logout-QEDUWSSY.js");await a();break}case"whoami":{let{runWhoami:a}=await import("./chunks/whoami-Z2Y2X2DN.js");await a();break}case"keys":{let{runKeys:a}=await import("./chunks/keys-RC6SP7XY.js");await a(t.commandArgs);break}case"setup":{let{runSetup:a}=await import("./chunks/setup-WYKWQPJW.js");await a(t.commandArgs);break}case"install-desktop":{let{runInstallDesktop:a}=await import("./chunks/install-desktop-AOJACCWA.js");await a(t.commandArgs);break}case"serve":{let{runServe:a}=await import("./chunks/serve-TMMMRVTI.js");await a(t.commandArgs,{port:o});break}case"daemon":{let{runDaemon:a}=await import("./chunks/daemon-CUQB4QAP.js");await a(t.commandArgs,{port:o});break}case"runtime":{let{runRuntime:a}=await import("./chunks/runtime-BAS2IZFB.js");await a(t.commandArgs);break}case"upgrade":{let{runUpgrade:a}=await import("./chunks/upgrade-K6V3HYCU.js");await a(t.commandArgs);break}case"version":{let{runVersion:a}=await import("./chunks/version-GS2J6SFA.js");await a(t.commandArgs);break}case"agent":{let{runAgentCommand:a}=await import("./chunks/agent-AFAFZKMT.js"),e=await a(t.commandArgs);process.exit(e)}case"agent-wrapper":{let{runAgentWrapper:a}=await import("./chunks/agent-wrapper-MV5WGYCS.js"),e=await a(t.commandArgs);process.exit(e)}case"skill":{let{runSkill:a}=await import("./chunks/skills-P3HEQGPB.js");await a(t.commandArgs);break}case"upload":{let{runUpload:a}=await import("./chunks/upload-Q2ZFKOSR.js");await a(t.commandArgs,{port:o,verbose:n});break}case"app-fonts":{let{runAppFonts:a}=await import("./chunks/app-fonts-ERD5J644.js");await a(t.commandArgs);break}case"hints":{let{runHints:a}=await import("./chunks/hints-BYH6BMHP.js");a(t.commandArgs);break}case"telemetry":{let{runTelemetry:a}=await import("./chunks/telemetry-7ZVCPD7R.js");await a(t.commandArgs);break}default:console.error(` unknown command: ${r}`),console.error(" run `sootsim --help` to see the full surface."),process.exit(1)}
8
+ run the npm package instead:
9
+ sootsim ${a}
10
+ `),process.exit(1))}var e=g(process.argv);{let{trackCliEvent:a}=await import("./chunks/telemetry-46XXIUEE.js");a({event:"cli_command_invoked",properties:{command:e.command||(e.version?"version":e.help?"help":"none"),arg_count:e.commandArgs.length,platform:process.platform,arch:process.arch,node_version:process.versions.node}})}async function c(a){let{flushCliTelemetry:t}=await import("./chunks/telemetry-46XXIUEE.js");await t(),process.exit(a)}if(e.version){let{getCliVersion:a}=await import("./chunks/cli-version-ICHQMND6.js"),{IS_BETA:t,BETA_LABEL:i}=await import("./chunks/beta-X6YPQVZH.js"),m=t?` \xB7 ${i}`:"";console.log(`sootsim v${a()}${m}`);let{readActiveRuntime:h}=await import("./chunks/home-paths-KQKYP2SE.js"),w=h();console.log(w?`runtime v${w}`:"runtime not installed"),await c(0)}if(e.help&&!e.command){let{printHelp:a}=await import("./chunks/help-PA4RTR5X.js");a(),await c(0)}var o=e.globalFlags.port,n=e.verbose,p=e.globalFlags.device,l=e.globalFlags.theme,S=e.globalFlags.driver,E=e.globalFlags.headless===!0,b=e.globalFlags.sim??e.globalFlags.session??e.globalFlags.tab,s=b?["--sim",b,...e.commandArgs]:e.commandArgs;if(p||l){let{settingsStore:a}=await import("./chunks/store-MBKDUQEQ.js"),t={};p&&(t.deviceModel=p),l&&(t.colorScheme=l),a.apply(t)}if(!e.command&&e.commandArgs.length===0){let{runSetup:a,shouldRunSetupForBareCommand:t}=await import("./chunks/setup-ELNJS7AI.js");t()&&(await a(["--from-welcome"]),await c(0));let{printHelp:i}=await import("./chunks/help-PA4RTR5X.js");i(),await c(0)}var r=e.command??"";if(!r){if(e.commandArgs.length>0){let t=e.commandArgs.find(i=>!i.startsWith("-"))??e.commandArgs[0];console.error(` unknown command: ${t}`),console.error(" run `sootsim --help` to see the full surface."),await c(1)}let{printHelp:a}=await import("./chunks/help-PA4RTR5X.js");a(),await c(0)}if(r in d){let a=d[r],t=e.commandArgs.length>0?` ${e.commandArgs.join(" ")}`:"";console.error(` \`sootsim ${r}\` was removed. use \`${a}\` instead.`),t&&console.error(` \u2192 ${a}${t}`),console.error(" run `sootsim --help` to see the new verb groups."),await c(1)}if(e.help||e.commandArgs.includes("--help")||e.commandArgs.includes("-h")){if(r==="skill"){let{runSkill:i}=await import("./chunks/skills-GPSJYS4W.js");await i(e.commandArgs),await c(0)}let a=r==="do"||r==="get"||r==="debug"||r==="shell"||r==="wait",t=e.commandArgs.find(i=>!i.startsWith("-"));if(r!=="shell")if(a&&!t){let{printGroupHelp:i}=await import("./chunks/help-PA4RTR5X.js");i(r)&&await c(0)}else{let{printCommandHelp:i}=await import("./chunks/help-PA4RTR5X.js");i(a&&t?t:r,{prefer:a&&t?"verb":"command",group:a&&t?r:void 0}),await c(0)}}v(r);if(u.has(r)){let{runInspect:a}=await import("./chunks/inspect-ZP5SM4EW.js");await a([r,...s],{port:o,verbose:n})}else switch(r){case"assert":{let{runAssert:a}=await import("./chunks/assert-I55QVGG7.js");await a(e.commandArgs);break}case"flow":{let{runFlow:a}=await import("./chunks/flow-JL3SC6HC.js"),t=await a(s);process.exit(typeof t=="number"?t:0)}case"test":{let{runTest:a}=await import("./chunks/test-Z2HZXCZM.js");await a(e.commandArgs,{port:o,verbose:n});break}case"detox":{let{runDetox:a}=await import("./chunks/detox-ANJO6T27.js");await a(e.commandArgs,{port:o,verbose:n});break}case"maestro":{let{runMaestro:a}=await import("./chunks/maestro-TX6FPTVH.js"),t=await a(s,{port:o,verbose:n});process.exit(typeof t=="number"?t:0)}case"preview":{let{runPreview:a}=await import("./chunks/preview-3AD7WNA6.js");await a(e.commandArgs,{port:o,verbose:n});break}case"record":{let{runRecord:a}=await import("./chunks/record-HW4C7QYN.js");await a(s,{port:o,verbose:n});break}case"profile":{let{runProfile:a}=await import("./chunks/profile-HY55VFNR.js"),t=await a(e.commandArgs,{port:o,verbose:n});process.exit(typeof t=="number"?t:0)}case"cpu-profile":{let{runCpuProfile:a}=await import("./chunks/cpu-profile-ACSQMVXY.js"),t=await a(s,{port:o,verbose:n});process.exit(typeof t=="number"?t:0)}case"react":{let{runReact:a}=await import("./chunks/react-HDRCKCKV.js"),t=await a(s,{port:o,verbose:n});process.exit(typeof t=="number"?t:0)}case"screenshot":{let{runScreenshot:a}=await import("./chunks/screenshot-XFR3QN5T.js");await a(s,{port:o,verbose:n});break}case"screenshots":{if(e.commandArgs[0]==="capture"){let{runScreenshotsCapture:i}=await import("./chunks/screenshots-capture-RVNF75ZD.js"),m=await i(e.commandArgs.slice(1));process.exit(typeof m=="number"?m:0)}let{runScreenshots:a}=await import("./chunks/screenshots-RKUL2ZZT.js"),t=await a(s,{port:o,verbose:n});process.exit(typeof t=="number"?t:0)}case"screenshot-mode":{let{runScreenshotMode:a}=await import("./chunks/screenshot-mode-Y5CVO267.js");await a(e.commandArgs,{port:o,verbose:n});break}case"slides":{let{runSlides:a}=await import("./chunks/slides-OCFNPIFG.js");await a(s,{port:o,verbose:n});break}case"three-mode":case"3d-mode":{let{runThreeMode:a}=await import("./chunks/three-mode-NKJFCDYS.js");await a(e.commandArgs,{port:o,verbose:n});break}case"inspect":{let{runInspect:a}=await import("./chunks/inspect-ZP5SM4EW.js");await a(s,{port:o,verbose:n});break}case"debug":{let{runDebug:a}=await import("./chunks/debug-W2ZOVTQO.js");await a(s,{port:o,verbose:n});break}case"camera":{let{runCamera:a}=await import("./chunks/camera-CYYBJH7W.js");await a(s,{port:o});break}case"timeline":{let{runTimeline:a}=await import("./chunks/timeline-PRGQMQRR.js");await a(s,{port:o,verbose:n});break}case"what-happened":{let{runWhatHappened:a}=await import("./chunks/what-happened-IX2RRCOS.js");await a(s,{port:o,verbose:n});break}case"diagnose":{let{runDiagnose:a}=await import("./chunks/diagnose-5PEJYGES.js"),t=await a(s,{port:o,verbose:n});process.exit(typeof t=="number"?t:0)}case"open":{let{runOpenCommand:a}=await import("./chunks/control-CZFSYSYG.js");await a(s,{port:o});break}case"link":{let{runLinkCommand:a}=await import("./chunks/control-CZFSYSYG.js");await a(s,{port:o});break}case"use":case"focus":{let{runUseCommand:a}=await import("./chunks/control-CZFSYSYG.js");await a(s,{port:o});break}case"claim":{let{runClaimCommand:a}=await import("./chunks/control-CZFSYSYG.js");await a(s,{port:o});break}case"close":{let{runCloseCommand:a}=await import("./chunks/control-CZFSYSYG.js");await a(s,{port:o});break}case"device":{let{runDeviceCommand:a}=await import("./chunks/device-KPPN4KYD.js");await a(s,{port:o});break}case"scan":case"compat":{let{runCompat:a}=await import("./chunks/compat-ZJA3N4ZT.js");await a(e.commandArgs);break}case"electron":{let{runElectron:a}=await import("./chunks/electron-U456QLSQ.js");await a(e.commandArgs,{port:o,device:p,driver:S});break}case"login":{let{runLogin:a}=await import("./chunks/login-DVMWAI3G.js");await a(e.commandArgs);break}case"logout":{let{runLogout:a}=await import("./chunks/logout-RIVPFE5N.js");await a();break}case"whoami":{let{runWhoami:a}=await import("./chunks/whoami-QZ42FYYF.js");await a();break}case"keys":{let{runKeys:a}=await import("./chunks/keys-JSQMBUE7.js");await a(e.commandArgs);break}case"setup":{let{runSetup:a}=await import("./chunks/setup-ELNJS7AI.js");await a(e.commandArgs);break}case"install-desktop":{let{runInstallDesktop:a}=await import("./chunks/install-desktop-OR6ZJ43X.js");await a(e.commandArgs);break}case"serve":{let{runServe:a}=await import("./chunks/serve-QMRYLWL5.js");await a(e.commandArgs,{port:o});break}case"daemon":{let{runDaemon:a}=await import("./chunks/daemon-337B4P3B.js");await a(e.commandArgs,{port:o});break}case"runtime":{let{runRuntime:a}=await import("./chunks/runtime-RHHPW5WO.js");await a(e.commandArgs);break}case"upgrade":{let{runUpgrade:a}=await import("./chunks/upgrade-3NW7JRRX.js");await a(e.commandArgs);break}case"version":{let{runVersion:a}=await import("./chunks/version-FDTZRIYT.js");await a(e.commandArgs);break}case"agent":{let{runAgentCommand:a}=await import("./chunks/agent-VF756RZU.js"),t=await a(e.commandArgs);process.exit(t)}case"agent-wrapper":{let{runAgentWrapper:a}=await import("./chunks/agent-wrapper-IAFL7ROV.js"),t=await a(e.commandArgs);process.exit(t)}case"skill":{let{runSkill:a}=await import("./chunks/skills-GPSJYS4W.js");await a(e.commandArgs);break}case"upload":{let{runUpload:a}=await import("./chunks/upload-QVDVJ6ZK.js");await a(e.commandArgs,{port:o,verbose:n});break}case"app-fonts":{let{runAppFonts:a}=await import("./chunks/app-fonts-VWLEC7ZA.js");await a(e.commandArgs);break}case"hints":{let{runHints:a}=await import("./chunks/hints-MBBQLMQU.js");a(e.commandArgs);break}case"telemetry":{let{runTelemetry:a}=await import("./chunks/telemetry-KFZQUFG5.js");await a(e.commandArgs);break}default:console.error(` unknown command: ${r}`),console.error(" run `sootsim --help` to see the full surface."),process.exit(1)}
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as b,b as E,c as A,d as l,e as S,g as j,h as T,j as I,m as k,n as D,o as x,p as g,q as O,r as C}from"./chunk-RAEIXWER.js";import"./chunk-IJMDXS7N.js";import{c as $}from"./chunk-SGWTX6CO.js";import"./chunk-WV7QBUFY.js";import"./chunk-MBR6TG2P.js";import"./chunk-CPZNH3B3.js";import"./chunk-L3FPLPA4.js";import"./chunk-D7ZB6A5T.js";import"./chunk-RQXZANGL.js";import"./chunk-QP4W3SGO.js";import{j as y}from"./chunk-AP22KA3Q.js";import"./chunk-KSV6H2IC.js";import"./chunk-6TNJLDAQ.js";import"./chunk-UXHEGFHQ.js";import"./chunk-YSTCZI6L.js";import w from"node:fs";import d from"node:path";import{spawn as _}from"node:child_process";import F from"node:net";import{WebSocket as R}from"ws";var c=class extends Error{code;constructor(e,t){super(e),this.name="AgentDaemonError",this.code=t}},f=class{ws;port;commandTimeoutMs;ready;closed=!1;nextId=1;pending=new Map;eventListeners=new Set;statusListeners=new Set;disconnectListeners=new Set;constructor(e={}){this.port=e.port??7668,this.commandTimeoutMs=e.commandTimeoutMs??15e3,this.ws=new R(`ws://localhost:${this.port}`),this.ready=new Promise((t,r)=>{let s=()=>{this.ws.off("error",o),t()},o=i=>{this.ws.off("open",s),r(new c(`could not connect to sootsim daemon on port ${this.port}: ${i.message}`,"NO_DAEMON"))};this.ws.once("open",s),this.ws.once("error",o)}),this.ws.on("message",t=>this.handleMessage(t)),this.ws.on("close",()=>this.handleClose()),this.ws.on("error",()=>{})}async waitReady(){return this.ready}async listProjects(){return this.send("agent:list-projects")}async upsertProject(e){return this.send("agent:upsert-project",{input:e})}async deleteProject(e){return this.send("agent:delete-project",{projectId:e})}async autoAttachForUrl(e){return this.send("agent:auto-attach-for-url",{input:e})}async listSessions(e){return this.send("agent:list-sessions",{projectId:e})}async startSession(e){return this.send("agent:start-session",{input:e})}async sendPrompt(e,t){return this.send("agent:send-prompt",{sessionId:e,prompt:t})}async sendClaimedPrompt(e,t){return this.send("agent:send-claimed-prompt",{simId:e,prompt:t})}async endSession(e){return this.send("agent:end-session",{sessionId:e})}async getTranscript(e){return this.send("agent:get-transcript",{sessionId:e})}async getPaths(){return this.send("agent:get-paths")}async subscribeEvents(e){return this.send("agent:subscribe-events",{sessionId:e})}async unsubscribeEvents(e){return this.send("agent:unsubscribe-events",{sessionId:e})}onAgentEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}onSessionStatusChange(e){return this.statusListeners.add(e),()=>this.statusListeners.delete(e)}onDisconnect(e){return this.disconnectListeners.add(e),()=>this.disconnectListeners.delete(e)}close(){if(!this.closed){this.closed=!0;try{this.ws.close()}catch{}}}async send(e,t={}){if(await this.ready,this.closed||this.ws.readyState!==R.OPEN)throw new c("daemon connection is closed","NO_DAEMON");let r=this.nextId++;return new Promise((s,o)=>{let i=setTimeout(()=>{this.pending.delete(r),o(new c(`${e} timed out after ${Math.round(this.commandTimeoutMs/1e3)}s`,"TIMEOUT"))},this.commandTimeoutMs);this.pending.set(r,{resolve:s,reject:o,timer:i});try{this.ws.send(JSON.stringify({id:r,type:e,...t}))}catch(a){clearTimeout(i),this.pending.delete(r),o(a instanceof Error?a:new Error(String(a)))}})}handleMessage(e){let t;try{t=JSON.parse(String(e))}catch{return}if(!t||typeof t!="object")return;if(t.type==="agent:event"){for(let s of this.eventListeners)try{s({sessionId:t.sessionId,event:t.event})}catch{}return}if(t.type==="agent:session-status"){for(let s of this.statusListeners)try{s(t.session)}catch{}return}if(typeof t.id!="number")return;let r=this.pending.get(t.id);r&&(this.pending.delete(t.id),clearTimeout(r.timer),t.error?r.reject(new c(t.error,t.code)):r.resolve(t.result))}handleClose(){if(!this.closed){this.closed=!0;for(let[,e]of this.pending)clearTimeout(e.timer),e.reject(new c("daemon disconnected","DISCONNECT"));this.pending.clear();for(let e of this.disconnectListeners)try{e()}catch{}}}};function M(n=7668,e=400){return new Promise(t=>{let r=new F.Socket,s=!1,o=i=>{s||(s=!0,r.destroy(),t(i))};r.setTimeout(e),r.once("connect",()=>o(!0)),r.once("timeout",()=>o(!1)),r.once("error",()=>o(!1)),r.connect(n,"127.0.0.1")})}async function B(n={}){let e=n.port??7668;if(await M(e))return{alreadyRunning:!0};if(y())throw new c(`no sootsim bridge on port ${e}. run \`sootsim setup\` to install the background daemon, or \`sootsim serve\` in another shell.`,"DEV_HOST_REFUSED");let{cmd:t,prefixArgs:r}=C(),s=[...r,"serve","--quiet"];e!==7668&&s.push("--port",String(e));let o=_(t,s,{detached:!0,stdio:"ignore",env:process.env,cwd:process.cwd()});o.unref();let i=Date.now()+(n.startupTimeoutMs??5e3);for(;Date.now()<i;){if(await M(e))return{alreadyRunning:!1,pid:o.pid};await new Promise(a=>setTimeout(a,100))}throw new c(`spawned sootsim daemon on port ${e} but it did not come up in time. run \`sootsim serve\` manually to diagnose.`,"SPAWN_TIMEOUT")}async function h(n={}){await B({port:n.port,startupTimeoutMs:n.startupTimeoutMs});let e=new f(n);try{await e.waitReady()}catch(t){throw e.close(),t}return e}async function ge(n){let[e,...t]=n;try{switch(e){case void 0:case"--help":case"-h":case"help":return L(),0;case"attach":return await W(t);case"projects":return await J();case"project":return await V(t);case"sessions":return await H(t);case"start":return await G(t);case"prompt":return await q(t);case"watch":return await K(t);case"transcript":return await z(t);case"end":return await Q(t);case"paths":return await Y();default:return process.stderr.write(`unknown agent subcommand: ${e}
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as b,b as E,c as A,d as l,e as S,g as j,h as T,j as I,m as k,n as D,o as x,p as g,q as O,r as C}from"./chunk-WEJKLJ4B.js";import"./chunk-LI4RLX6B.js";import{c as $}from"./chunk-X4KS33ZC.js";import"./chunk-EXFB33AZ.js";import"./chunk-TUF6EPCQ.js";import"./chunk-KOKIECMB.js";import"./chunk-R4KLD4P4.js";import"./chunk-V4M2R6FZ.js";import"./chunk-PDLQWZN4.js";import"./chunk-E5DE33BU.js";import{j as y}from"./chunk-BI56RR3G.js";import"./chunk-PIUKLO3W.js";import"./chunk-M3P67TBN.js";import"./chunk-FUHXL6BW.js";import"./chunk-GX6MKIFC.js";import w from"node:fs";import d from"node:path";import{spawn as _}from"node:child_process";import F from"node:net";import{WebSocket as R}from"ws";var c=class extends Error{code;constructor(e,t){super(e),this.name="AgentDaemonError",this.code=t}},f=class{ws;port;commandTimeoutMs;ready;closed=!1;nextId=1;pending=new Map;eventListeners=new Set;statusListeners=new Set;disconnectListeners=new Set;constructor(e={}){this.port=e.port??7668,this.commandTimeoutMs=e.commandTimeoutMs??15e3,this.ws=new R(`ws://localhost:${this.port}`),this.ready=new Promise((t,r)=>{let s=()=>{this.ws.off("error",o),t()},o=i=>{this.ws.off("open",s),r(new c(`could not connect to sootsim daemon on port ${this.port}: ${i.message}`,"NO_DAEMON"))};this.ws.once("open",s),this.ws.once("error",o)}),this.ws.on("message",t=>this.handleMessage(t)),this.ws.on("close",()=>this.handleClose()),this.ws.on("error",()=>{})}async waitReady(){return this.ready}async listProjects(){return this.send("agent:list-projects")}async upsertProject(e){return this.send("agent:upsert-project",{input:e})}async deleteProject(e){return this.send("agent:delete-project",{projectId:e})}async autoAttachForUrl(e){return this.send("agent:auto-attach-for-url",{input:e})}async listSessions(e){return this.send("agent:list-sessions",{projectId:e})}async startSession(e){return this.send("agent:start-session",{input:e})}async sendPrompt(e,t){return this.send("agent:send-prompt",{sessionId:e,prompt:t})}async sendClaimedPrompt(e,t){return this.send("agent:send-claimed-prompt",{simId:e,prompt:t})}async endSession(e){return this.send("agent:end-session",{sessionId:e})}async getTranscript(e){return this.send("agent:get-transcript",{sessionId:e})}async getPaths(){return this.send("agent:get-paths")}async subscribeEvents(e){return this.send("agent:subscribe-events",{sessionId:e})}async unsubscribeEvents(e){return this.send("agent:unsubscribe-events",{sessionId:e})}onAgentEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}onSessionStatusChange(e){return this.statusListeners.add(e),()=>this.statusListeners.delete(e)}onDisconnect(e){return this.disconnectListeners.add(e),()=>this.disconnectListeners.delete(e)}close(){if(!this.closed){this.closed=!0;try{this.ws.close()}catch{}}}async send(e,t={}){if(await this.ready,this.closed||this.ws.readyState!==R.OPEN)throw new c("daemon connection is closed","NO_DAEMON");let r=this.nextId++;return new Promise((s,o)=>{let i=setTimeout(()=>{this.pending.delete(r),o(new c(`${e} timed out after ${Math.round(this.commandTimeoutMs/1e3)}s`,"TIMEOUT"))},this.commandTimeoutMs);this.pending.set(r,{resolve:s,reject:o,timer:i});try{this.ws.send(JSON.stringify({id:r,type:e,...t}))}catch(a){clearTimeout(i),this.pending.delete(r),o(a instanceof Error?a:new Error(String(a)))}})}handleMessage(e){let t;try{t=JSON.parse(String(e))}catch{return}if(!t||typeof t!="object")return;if(t.type==="agent:event"){for(let s of this.eventListeners)try{s({sessionId:t.sessionId,event:t.event})}catch{}return}if(t.type==="agent:session-status"){for(let s of this.statusListeners)try{s(t.session)}catch{}return}if(typeof t.id!="number")return;let r=this.pending.get(t.id);r&&(this.pending.delete(t.id),clearTimeout(r.timer),t.error?r.reject(new c(t.error,t.code)):r.resolve(t.result))}handleClose(){if(!this.closed){this.closed=!0;for(let[,e]of this.pending)clearTimeout(e.timer),e.reject(new c("daemon disconnected","DISCONNECT"));this.pending.clear();for(let e of this.disconnectListeners)try{e()}catch{}}}};function M(n=7668,e=400){return new Promise(t=>{let r=new F.Socket,s=!1,o=i=>{s||(s=!0,r.destroy(),t(i))};r.setTimeout(e),r.once("connect",()=>o(!0)),r.once("timeout",()=>o(!1)),r.once("error",()=>o(!1)),r.connect(n,"127.0.0.1")})}async function B(n={}){let e=n.port??7668;if(await M(e))return{alreadyRunning:!0};if(y())throw new c(`no sootsim bridge on port ${e}. run \`sootsim setup\` to install the background daemon, or \`sootsim serve\` in another shell.`,"DEV_HOST_REFUSED");let{cmd:t,prefixArgs:r}=C(),s=[...r,"serve","--quiet"];e!==7668&&s.push("--port",String(e));let o=_(t,s,{detached:!0,stdio:"ignore",env:process.env,cwd:process.cwd()});o.unref();let i=Date.now()+(n.startupTimeoutMs??5e3);for(;Date.now()<i;){if(await M(e))return{alreadyRunning:!1,pid:o.pid};await new Promise(a=>setTimeout(a,100))}throw new c(`spawned sootsim daemon on port ${e} but it did not come up in time. run \`sootsim serve\` manually to diagnose.`,"SPAWN_TIMEOUT")}async function h(n={}){await B({port:n.port,startupTimeoutMs:n.startupTimeoutMs});let e=new f(n);try{await e.waitReady()}catch(t){throw e.close(),t}return e}async function ge(n){let[e,...t]=n;try{switch(e){case void 0:case"--help":case"-h":case"help":return L(),0;case"attach":return await W(t);case"projects":return await J();case"project":return await V(t);case"sessions":return await H(t);case"start":return await G(t);case"prompt":return await q(t);case"watch":return await K(t);case"transcript":return await z(t);case"end":return await Q(t);case"paths":return await Y();default:return process.stderr.write(`unknown agent subcommand: ${e}
3
3
  `),L(),2}}catch(r){if(r instanceof c)return process.stderr.write(`${r.message}
4
4
  `),1;throw r}}async function v(n){let e=await h({clientLabel:"sootsim-agent-cli"});try{return await n(e)}finally{e.close()}}function L(){$("agent")}function P(n,e){let t={},r=[];for(let s=0;s<n.length;s++){let o=n[s],i=e[o];i==="value"?(t[o]=n[s+1]??"",s++):i==="bool"?t[o]=!0:r.push(o)}return{flags:t,positional:r}}function U(n,e="codex"){return n==="codex"||n==="claude"?n:e}async function W(n){let{flags:e,positional:t}=P(n,{"--name":"value","--provider":"value"}),r=t[0];if(!r)return process.stderr.write(`usage: sootsim agent attach <dir> [--name X] [--provider codex|claude]
5
5
  `),2;let s=d.resolve(r);if(!w.existsSync(s))return process.stderr.write(`directory does not exist: ${s}
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{b as M}from"./chunk-IJMDXS7N.js";import"./chunk-YSTCZI6L.js";import{execFile as G,spawn as q}from"node:child_process";import{randomUUID as X}from"node:crypto";import{constants as R,createReadStream as Y,createWriteStream as j,existsSync as I,openSync as J}from"node:fs";import V from"node:fs/promises";import z from"node:path";import K from"node:readline";import{promisify as Q}from"node:util";import{spawn as H}from"node:child_process";import L from"node:readline";var b=class extends Error{code;data;constructor(t,r,m){super(t),this.name="CodexRpcError",this.code=r,this.data=m}};function W(d){let t=H(d.bin,["app-server"],{cwd:d.cwd,env:{...process.env,...d.env},stdio:["pipe","pipe","pipe"]}),r=new Map,m=new Map,u=1,g=!1,a=new Promise(s=>{t.on("exit",(i,e)=>{g=!0;let p=new Error(`codex app-server exited (code=${i}, signal=${e??""})`);for(let{reject:f}of r.values())f(p);r.clear(),s({code:i,signal:e})})});L.createInterface({input:t.stdout,crlfDelay:1/0}).on("line",s=>{let i=s.trim();if(!i)return;let e;try{e=JSON.parse(i)}catch{return}if(e.id!=null&&(e.result!==void 0||e.error!==void 0)){let p=typeof e.id=="string"?Number(e.id):e.id,f=p!=null?r.get(p):void 0;if(!f)return;r.delete(p),e.error?f.reject(new b(e.error.message,e.error.code,e.error.data)):f.resolve(e.result);return}if(e.method){let p=m.get(e.method);if(!p)return;for(let f of p)try{f(e.params)}catch(l){console.error(`[codex-client] handler for "${e.method}" threw:`,l instanceof Error?l.stack??l.message:l)}}}),t.stderr.setEncoding("utf8"),t.stderr.on("data",s=>{let i=m.get("__stderr__");if(i)for(let e of i)try{e({text:s})}catch{}});function n(s){if(!g)try{t.stdin.write(JSON.stringify(s)+`
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{b as M}from"./chunk-LI4RLX6B.js";import"./chunk-GX6MKIFC.js";import{execFile as G,spawn as q}from"node:child_process";import{randomUUID as X}from"node:crypto";import{constants as R,createReadStream as Y,createWriteStream as j,existsSync as I,openSync as J}from"node:fs";import V from"node:fs/promises";import z from"node:path";import K from"node:readline";import{promisify as Q}from"node:util";import{spawn as H}from"node:child_process";import L from"node:readline";var b=class extends Error{code;data;constructor(t,r,m){super(t),this.name="CodexRpcError",this.code=r,this.data=m}};function W(d){let t=H(d.bin,["app-server"],{cwd:d.cwd,env:{...process.env,...d.env},stdio:["pipe","pipe","pipe"]}),r=new Map,m=new Map,u=1,g=!1,a=new Promise(s=>{t.on("exit",(i,e)=>{g=!0;let p=new Error(`codex app-server exited (code=${i}, signal=${e??""})`);for(let{reject:f}of r.values())f(p);r.clear(),s({code:i,signal:e})})});L.createInterface({input:t.stdout,crlfDelay:1/0}).on("line",s=>{let i=s.trim();if(!i)return;let e;try{e=JSON.parse(i)}catch{return}if(e.id!=null&&(e.result!==void 0||e.error!==void 0)){let p=typeof e.id=="string"?Number(e.id):e.id,f=p!=null?r.get(p):void 0;if(!f)return;r.delete(p),e.error?f.reject(new b(e.error.message,e.error.code,e.error.data)):f.resolve(e.result);return}if(e.method){let p=m.get(e.method);if(!p)return;for(let f of p)try{f(e.params)}catch(l){console.error(`[codex-client] handler for "${e.method}" threw:`,l instanceof Error?l.stack??l.message:l)}}}),t.stderr.setEncoding("utf8"),t.stderr.on("data",s=>{let i=m.get("__stderr__");if(i)for(let e of i)try{e({text:s})}catch{}});function n(s){if(!g)try{t.stdin.write(JSON.stringify(s)+`
3
3
  `)}catch{}}return{exited:a,on(s,i){let e=m.get(s);return e||(e=new Set,m.set(s,e)),e.add(i),()=>{e?.delete(i)}},request(s,i){if(g)return Promise.reject(new Error(`codex app-server closed; cannot call ${s}`));let e=u++;return new Promise((p,f)=>{r.set(e,{resolve:l=>p(l),reject:f,method:s}),n({jsonrpc:"2.0",id:e,method:s,params:i})})},notify(s,i){n({jsonrpc:"2.0",method:s,params:i})},async shutdown(s=1500){if(g)return;try{t.stdin.end()}catch{}let i=setTimeout(()=>{if(!g)try{t.kill("SIGTERM")}catch{}},s);try{await a}finally{clearTimeout(i)}},kill(s="SIGTERM"){if(!g)try{t.kill(s)}catch{}}}}var O="never",F="danger-full-access",Z={type:"dangerFullAccess"},D="fast",ee="medium",te=Q(G);async function ne(d,t){let r=t||d;if(r.includes("/")||r.includes("\\"))return I(r)?{ok:!0,path:r}:{ok:!1,message:`agent binary not found at path: ${r}`};try{let{stdout:m}=await te("which",[r],{timeout:1500}),u=m.trim();return u?{ok:!0,path:u}:{ok:!1,message:`${r} not found on PATH`}}catch{return{ok:!1,message:`${r} not found on PATH. install the ${d} CLI and retry, or pass --${d}-bin /path/to/${d} to agent start.`}}}function re(d){let t={"--session-id":"sessionId","--project-id":"projectId","--provider":"provider","--cwd":"cwd","--prompt-in":"promptIn","--events-out":"eventsOut","--transcript":"transcript","--codex-bin":"codexBin","--claude-bin":"claudeBin","--claude-session-uuid":"claudeSessionUuid"},r={};for(let m=0;m<d.length;m++){let u=d[m];if(u==="--fresh-thread"){r.freshThread=!0;continue}let g=t[u];g&&(r[g]=d[m+1],m++)}return r}async function Ie(d){let t=re(d);if(!t.sessionId||!t.projectId||!t.provider||!t.cwd||!t.promptIn||!t.eventsOut)return process.stderr.write(`usage: sootsim agent-wrapper --session-id <id> --project-id <id>
4
4
  --provider codex|claude --cwd <path>
5
5
  --prompt-in <fifo> --events-out <fifo>
@@ -1,2 +1,2 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{d as p}from"./chunk-C7BIPAXT.js";import"./chunk-YSTCZI6L.js";import{existsSync as h,mkdirSync as d,readFileSync as y,writeFileSync as g}from"node:fs";import{join as m}from"node:path";import{gzipSync as w}from"node:zlib";function f(t,e){let o=t.indexOf(`--${e}`);if(o!==-1&&o+1<t.length)return t[o+1];let i=t.find(r=>r.startsWith(`--${e}=`));return i?i.slice(e.length+3):void 0}async function S(t){let e=f(t,"wire")||"",o=f(t,"out-dir"),i=f(t,"manifest");if((!o||!i)&&(console.error(" usage: sootsim app-fonts stage --wire <wire> --out-dir <dir> --manifest <path>"),process.exit(1)),!e.trim()){console.log("no app fonts declared \u2014 nothing to stage");return}d(o,{recursive:!0});let r=await p(e,{onStaged:({url:n,byteLength:s})=>console.log(` staged app font: ${n} (${(s/1024).toFixed(1)} KiB)`),onError:(n,s)=>console.error(` warning: failed to fetch app font ${n}: ${s instanceof Error?s.message:s}`)}),a=[];for(let n of r){let s=w(n.bytes);g(m(o,n.urlhash),s),a.push({url:n.url,urlhash:n.urlhash,contentType:n.contentType,encoding:"gzip",sizeBytes:s.length,rawBytes:n.bytes.byteLength})}let c=[];if(h(i))try{let n=JSON.parse(y(i,"utf8"));Array.isArray(n)&&(c=n)}catch{}let u=new Set(c.map(n=>n.urlhash)),l=[...c,...a.filter(n=>!u.has(n.urlhash))];g(i,JSON.stringify(l)),console.log(`staged ${a.length} app font(s); manifest now has ${l.length} file(s)`)}async function E(t){let e=t[0];if(e==="stage"){await S(t.slice(1));return}console.error(` unknown app-fonts subcommand: ${e??"(none)"}`),console.error(" available: stage"),process.exit(1)}export{E as runAppFonts};
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{d as p}from"./chunk-IJP257WP.js";import"./chunk-GX6MKIFC.js";import{existsSync as h,mkdirSync as d,readFileSync as y,writeFileSync as g}from"node:fs";import{join as m}from"node:path";import{gzipSync as w}from"node:zlib";function f(t,e){let o=t.indexOf(`--${e}`);if(o!==-1&&o+1<t.length)return t[o+1];let i=t.find(r=>r.startsWith(`--${e}=`));return i?i.slice(e.length+3):void 0}async function S(t){let e=f(t,"wire")||"",o=f(t,"out-dir"),i=f(t,"manifest");if((!o||!i)&&(console.error(" usage: sootsim app-fonts stage --wire <wire> --out-dir <dir> --manifest <path>"),process.exit(1)),!e.trim()){console.log("no app fonts declared \u2014 nothing to stage");return}d(o,{recursive:!0});let r=await p(e,{onStaged:({url:n,byteLength:s})=>console.log(` staged app font: ${n} (${(s/1024).toFixed(1)} KiB)`),onError:(n,s)=>console.error(` warning: failed to fetch app font ${n}: ${s instanceof Error?s.message:s}`)}),a=[];for(let n of r){let s=w(n.bytes);g(m(o,n.urlhash),s),a.push({url:n.url,urlhash:n.urlhash,contentType:n.contentType,encoding:"gzip",sizeBytes:s.length,rawBytes:n.bytes.byteLength})}let c=[];if(h(i))try{let n=JSON.parse(y(i,"utf8"));Array.isArray(n)&&(c=n)}catch{}let u=new Set(c.map(n=>n.urlhash)),l=[...c,...a.filter(n=>!u.has(n.urlhash))];g(i,JSON.stringify(l)),console.log(`staged ${a.length} app font(s); manifest now has ${l.length} file(s)`)}async function E(t){let e=t[0];if(e==="stage"){await S(t.slice(1));return}console.error(` unknown app-fonts subcommand: ${e??"(none)"}`),console.error(" available: stage"),process.exit(1)}export{E as runAppFonts};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-YSTCZI6L.js";import{spawn as x}from"child_process";var w=new Set(["describe","find","list","network","logs","count","tree","url","a11y","node","layout","keyboard","errors","warnings","requests","animations","animation","state","sample-color"]),S=new Set(["--exists","--empty","--negate","--quiet","--allow-timeout","!"]),q=new Set(["--count","--count-at-least","--count-at-most","--contains","--not-contains","--matches","--not-matches","--equals","--jq","--has-path","--within"]),P=new Set(["--path-equals"]);function j(s){let r=[],u=[],n=0,e=!1,t=!1,i=!1;for(let o=0;o<s.length;o++){let a=s[o];if(a==="--within"){let c=Number(s[o+1]);if(!Number.isFinite(c)||c<0)return{error:`--within requires a non-negative number, got: ${s[o+1]}`};n=c,o++;continue}if(a==="--negate"||a==="!"){e=!0;continue}if(a==="--quiet"){t=!0;continue}if(a==="--allow-timeout"){i=!0;continue}if(S.has(a)){u.push({kind:a,args:[]});continue}if(q.has(a)){let c=s[o+1];if(c==null)return{error:`${a} requires a value`};u.push({kind:a,args:[c]}),o++;continue}if(P.has(a)){let c=s[o+1],f=s[o+2];if(c==null||f==null)return{error:`${a} requires <path> <value>`};u.push({kind:a,args:[c,f]}),o+=2;continue}r.push(a)}return r.length===0?{error:"assert requires a verb (e.g. find, describe, get errors)"}:{verbArgs:r,predicates:u,withinMs:n,negate:e,quiet:t,allowTimeout:i}}function N(s){return s[0]==="get"||s[0]==="debug"?w.has(s[1])?s[1]:null:s[0]==="do"||s[0]==="wait"?null:w.has(s[0])?s[0]:null}async function R(s){let u=[process.argv[1],...s,"--json"];return new Promise(n=>{let e=x(process.execPath,u,{stdio:["ignore","pipe","pipe"],env:process.env}),t="",i="";e.stdout.on("data",o=>t+=o.toString()),e.stderr.on("data",o=>i+=o.toString()),e.on("error",o=>{n({ok:!1,payload:null,reason:`spawn failed: ${o.message}`})}),e.on("close",o=>{if(o!==0){let a=i.trim().split(`
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import"./chunk-GX6MKIFC.js";import{spawn as x}from"child_process";var w=new Set(["describe","find","list","network","logs","count","tree","url","a11y","node","layout","keyboard","errors","warnings","requests","animations","animation","state","sample-color"]),S=new Set(["--exists","--empty","--negate","--quiet","--allow-timeout","!"]),q=new Set(["--count","--count-at-least","--count-at-most","--contains","--not-contains","--matches","--not-matches","--equals","--jq","--has-path","--within"]),P=new Set(["--path-equals"]);function j(s){let r=[],u=[],n=0,e=!1,t=!1,i=!1;for(let o=0;o<s.length;o++){let a=s[o];if(a==="--within"){let c=Number(s[o+1]);if(!Number.isFinite(c)||c<0)return{error:`--within requires a non-negative number, got: ${s[o+1]}`};n=c,o++;continue}if(a==="--negate"||a==="!"){e=!0;continue}if(a==="--quiet"){t=!0;continue}if(a==="--allow-timeout"){i=!0;continue}if(S.has(a)){u.push({kind:a,args:[]});continue}if(q.has(a)){let c=s[o+1];if(c==null)return{error:`${a} requires a value`};u.push({kind:a,args:[c]}),o++;continue}if(P.has(a)){let c=s[o+1],f=s[o+2];if(c==null||f==null)return{error:`${a} requires <path> <value>`};u.push({kind:a,args:[c,f]}),o+=2;continue}r.push(a)}return r.length===0?{error:"assert requires a verb (e.g. find, describe, get errors)"}:{verbArgs:r,predicates:u,withinMs:n,negate:e,quiet:t,allowTimeout:i}}function N(s){return s[0]==="get"||s[0]==="debug"?w.has(s[1])?s[1]:null:s[0]==="do"||s[0]==="wait"?null:w.has(s[0])?s[0]:null}async function R(s){let u=[process.argv[1],...s,"--json"];return new Promise(n=>{let e=x(process.execPath,u,{stdio:["ignore","pipe","pipe"],env:process.env}),t="",i="";e.stdout.on("data",o=>t+=o.toString()),e.stderr.on("data",o=>i+=o.toString()),e.on("error",o=>{n({ok:!1,payload:null,reason:`spawn failed: ${o.message}`})}),e.on("close",o=>{if(o!==0){let a=i.trim().split(`
3
3
  `).slice(-2).join(" | ").slice(0,200);n({ok:!1,payload:null,reason:`verb exited ${o}${a?`: ${a}`:""}`});return}if(!t.trim()){n({ok:!1,payload:null,reason:"verb produced no output"});return}try{let a=JSON.parse(t);n({ok:!0,payload:a})}catch{n({ok:!1,payload:null,reason:`verb output was not valid json: ${t.slice(0,120)}`})}})})}function y(s,r){let u=r.split(".").filter(e=>e.length>0),n=s;for(let e of u){if(n==null)return{found:!1};if(Array.isArray(n)){let t=Number(e);if(!Number.isInteger(t)||t<0||t>=n.length)return{found:!1};n=n[t];continue}if(typeof n=="object"){let t=n;if(!(e in t))return{found:!1};n=t[e];continue}return{found:!1}}return{found:!0,value:n}}function d(s){return Array.isArray(s)?s.length:s&&typeof s=="object"?Object.keys(s).length:null}async function A(s,r){let{kind:u,args:n}=s;switch(u){case"--exists":return r==null?{ok:!1,reason:"payload is null"}:d(r)===0?{ok:!1,reason:"payload is empty"}:{ok:!0,reason:"exists"};case"--empty":{if(r==null)return{ok:!0,reason:"payload is null"};let e=d(r);return e===0?{ok:!0,reason:"payload is empty"}:{ok:!1,reason:`payload has ${e} item(s)`}}case"--count":{let e=Number(n[0]),t=d(r);return t==null?{ok:!1,reason:`payload not countable (${typeof r})`}:{ok:t===e,reason:`count=${t}, want=${e}`}}case"--count-at-least":{let e=Number(n[0]),t=d(r);return t==null?{ok:!1,reason:"payload not countable"}:{ok:t>=e,reason:`count=${t}, want>=${e}`}}case"--count-at-most":{let e=Number(n[0]),t=d(r);return t==null?{ok:!1,reason:"payload not countable"}:{ok:t<=e,reason:`count=${t}, want<=${e}`}}case"--contains":{let e=n[0],t=JSON.stringify(r);return{ok:t.includes(e),reason:t.includes(e)?`contains "${e}"`:`missing "${e}"`}}case"--not-contains":{let e=n[0],t=JSON.stringify(r);return{ok:!t.includes(e),reason:t.includes(e)?`unexpected "${e}"`:`not contains "${e}"`}}case"--matches":{let e=new RegExp(n[0]),t=JSON.stringify(r),i=e.test(t);return{ok:i,reason:i?`matches /${n[0]}/`:`no match for /${n[0]}/`}}case"--not-matches":{let e=new RegExp(n[0]),t=JSON.stringify(r),i=!e.test(t);return{ok:i,reason:i?`not matches /${n[0]}/`:`unexpected /${n[0]}/`}}case"--equals":{let e=n[0],t=typeof r=="string"?r:typeof r=="number"||typeof r=="boolean"?String(r):JSON.stringify(r);return{ok:t===e,reason:`got=${JSON.stringify(t)}, want=${JSON.stringify(e)}`}}case"--has-path":{let e=y(r,n[0]);return{ok:e.found,reason:e.found?`path ${n[0]} present`:`path ${n[0]} missing`}}case"--path-equals":{let[e,t]=n,i=y(r,e);if(!i.found)return{ok:!1,reason:`path ${e} missing`};let o=typeof i.value=="string"||typeof i.value=="number"||typeof i.value=="boolean"?String(i.value):JSON.stringify(i.value);return{ok:o===t,reason:`${e}=${o}, want=${t}`}}case"--jq":{let e=n[0];try{let i=(await O(e,r)).trim();return{ok:i.length>0&&i!=="null"&&i!=="false"&&i!=='""',reason:`jq: ${i.slice(0,120)}`}}catch(t){throw new Error(`jq evaluation failed: ${t.message}`)}}default:return{ok:!1,reason:`unknown predicate ${u}`}}}function O(s,r){return new Promise((u,n)=>{let e=x("jq",[s],{stdio:["pipe","pipe","pipe"]}),t="",i="";e.stdout.on("data",o=>t+=o.toString()),e.stderr.on("data",o=>i+=o.toString()),e.on("error",n),e.on("close",o=>{if(o!==0){n(new Error(i.trim()||`jq exited ${o}`));return}u(t)}),e.stdin.end(JSON.stringify(r))})}async function T(s){(s[0]==="--help"||s[0]==="-h"||s.length===0)&&(J(),process.exit(s.length===0?2:0));let r=j(s);"error"in r&&(process.stderr.write(` assert: ${r.error}
4
4
  `),process.exit(2));let{verbArgs:u,predicates:n,withinMs:e,negate:t,quiet:i,allowTimeout:o}=r;N(u)||(process.stderr.write(` assert: unknown or non-read verb: ${u.join(" ")}
5
5
  supported: ${Array.from(w).sort().join(", ")}
@@ -0,0 +1,2 @@
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a,b,c,d}from"./chunk-M3P67TBN.js";import"./chunk-GX6MKIFC.js";export{d as BETA_ASK_HEADLINE,b as BETA_LABEL,c as BETA_TAGLINE,a as IS_BETA};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{m as f}from"./chunk-QF6RJQ2U.js";import"./chunk-WOOWTKM7.js";import{c as m,e as l,g as p}from"./chunk-RQDJPT6N.js";import"./chunk-RQXZANGL.js";import"./chunk-QP4W3SGO.js";import"./chunk-AP22KA3Q.js";import"./chunk-YSTCZI6L.js";function d(){console.log(`
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{m as f}from"./chunk-FHJTTB3W.js";import"./chunk-FY6DJGOS.js";import{c as m,e as l,g as p}from"./chunk-7OAUPGLN.js";import"./chunk-PDLQWZN4.js";import"./chunk-E5DE33BU.js";import"./chunk-BI56RR3G.js";import"./chunk-GX6MKIFC.js";function d(){console.log(`
3
3
  sootsim camera \u2014 drive the sim camera
4
4
 
5
5
  usage:
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{h as u}from"./chunk-UXHEGFHQ.js";var S=52,l=18,h=42,x=96,g=54,E=1.5,$="inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121",w=1;function y(e){let t=u(e),r=t.scale,o=!t.dynamicIsland&&t.homeIndicatorHeight===0&&t.cornerRadius===0,n=t.width,i=t.height,a=o?t.width+l*2:t.width+32,d=o?t.height+h+x:t.height+32,c=9.5,b=w,p=a+c*2,m=d+w*2,f=c+(o?l:16),B=o?h:16,H=o?S:t.cornerRadius+16,v=[{side:"right",top:t.hardwareButtons.lock.top,height:t.hardwareButtons.lock.height,width:t.hardwareButtons.width},{side:"left",top:t.hardwareButtons.ringToggle.top,height:t.hardwareButtons.ringToggle.height,width:t.hardwareButtons.width},{side:"left",top:t.hardwareButtons.volumeUp.top,height:t.hardwareButtons.volumeUp.height,width:t.hardwareButtons.width},{side:"left",top:t.hardwareButtons.volumeDown.top,height:t.hardwareButtons.volumeDown.height,width:t.hardwareButtons.width}];return{model:e,renderScale:r,outerWidth:Math.round(p*r),outerHeight:Math.round(m*r),logicalOuterWidth:p,logicalOuterHeight:m,logicalFrameWidth:a,logicalFrameHeight:d,logicalFrameLeft:c,logicalFrameTop:b,logicalScreenWidth:n,logicalScreenHeight:i,logicalScreenLeft:f,logicalScreenTop:B,logicalScreenRadius:o?0:t.cornerRadius,logicalFrameRadius:H,frameBackground:o?"linear-gradient(180deg, #1b1c20 0%, #0f1012 42%, #050608 100%)":"#000000",frameOutline:o?"0 0 0 1px #1f2125":"0 0 0 1px #333",metallicRingShadow:o?null:$,buttons:v,legacyHomeButton:o?{top:h+t.height+(x-g)/2,left:t.width/2-g/2+l,size:g,ring:E}:null,showHomeIndicator:t.homeIndicatorHeight>0,logicalHomeIndicatorStripHeight:t.homeIndicatorHeight}}function L(e){let t=e.side==="right",r=t?"inset(-3px -3px -3px 0)":"inset(-3px 0 -3px -3px)";return`
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{h as u}from"./chunk-FUHXL6BW.js";var S=52,l=18,h=42,x=96,g=54,E=1.5,$="inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121",w=1;function y(e){let t=u(e),r=t.scale,o=!t.dynamicIsland&&t.homeIndicatorHeight===0&&t.cornerRadius===0,n=t.width,i=t.height,a=o?t.width+l*2:t.width+32,d=o?t.height+h+x:t.height+32,c=9.5,b=w,p=a+c*2,m=d+w*2,f=c+(o?l:16),B=o?h:16,H=o?S:t.cornerRadius+16,v=[{side:"right",top:t.hardwareButtons.lock.top,height:t.hardwareButtons.lock.height,width:t.hardwareButtons.width},{side:"left",top:t.hardwareButtons.ringToggle.top,height:t.hardwareButtons.ringToggle.height,width:t.hardwareButtons.width},{side:"left",top:t.hardwareButtons.volumeUp.top,height:t.hardwareButtons.volumeUp.height,width:t.hardwareButtons.width},{side:"left",top:t.hardwareButtons.volumeDown.top,height:t.hardwareButtons.volumeDown.height,width:t.hardwareButtons.width}];return{model:e,renderScale:r,outerWidth:Math.round(p*r),outerHeight:Math.round(m*r),logicalOuterWidth:p,logicalOuterHeight:m,logicalFrameWidth:a,logicalFrameHeight:d,logicalFrameLeft:c,logicalFrameTop:b,logicalScreenWidth:n,logicalScreenHeight:i,logicalScreenLeft:f,logicalScreenTop:B,logicalScreenRadius:o?0:t.cornerRadius,logicalFrameRadius:H,frameBackground:o?"linear-gradient(180deg, #1b1c20 0%, #0f1012 42%, #050608 100%)":"#000000",frameOutline:o?"0 0 0 1px #1f2125":"0 0 0 1px #333",metallicRingShadow:o?null:$,buttons:v,legacyHomeButton:o?{top:h+t.height+(x-g)/2,left:t.width/2-g/2+l,size:g,ring:E}:null,showHomeIndicator:t.homeIndicatorHeight>0,logicalHomeIndicatorStripHeight:t.homeIndicatorHeight}}function L(e){let t=e.side==="right",r=t?"inset(-3px -3px -3px 0)":"inset(-3px 0 -3px -3px)";return`
3
3
  <div
4
4
  aria-hidden="true"
5
5
  style="
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as u,b as w}from"./chunk-WN6XO6JV.js";import{a as m,c as f}from"./chunk-PY4P54SD.js";import{a as d,b as g,c as v}from"./chunk-JR7LKXPB.js";import{c as p}from"./chunk-QP4W3SGO.js";function x(){let e=d();return e?{available:!0,reason:null,detail:e}:{available:!1,reason:"no chromium-family browser found (chrome, chromium, edge, brave, arc)"}}async function I(e){if(e.headless)return{launched:!1,message:"the chromium driver launches a visible browser window and cannot run headless \u2014 a headless `chrome --headless=new` process exits immediately and the sim never connects. for headless automation use `--driver playwright`."};let r=d();if(!r)return{launched:!1,message:"chromium not found \u2014 install chrome or run `sootsim list --drivers`"};if(!e.url)return{launched:!1,message:"chromium driver requires a target url"};if(e.profileId||e.ephemeralProfile)return{launched:!1,message:"profiles require electron or playwright; browser tabs use your current Chrome profile"};try{let t=await v(e.url,{detached:e.detached??!0});return{launched:!0,message:`chromium launched \u2192 ${e.url}`,pid:t.pid,target:t.target??r,attachUrl:e.url}}catch(t){return{launched:!1,message:`chromium spawn failed: ${t instanceof Error?t.message:String(t)}`}}}var y={id:"chromium",name:"chromium",description:"system chrome / chromium / edge \u2014 visible window (headless: use playwright)",kind:"browser",availability:x,launch:I};function _(){let e=u();return e?{available:!0,reason:null,detail:`${e.kind} @ ${e.path}`}:{available:!1,reason:"sootsim desktop app not installed (run `sootsim install-desktop`)"}}async function M(e){let r=u();if(!r)return{launched:!1,message:"sootsim desktop app not installed"};try{let t=await w(e.url,r,{device:e.device,profileId:e.profileId,ephemeralProfile:e.ephemeralProfile});return t.launched?{launched:!0,message:e.url?`electron launched via ${t.via} \u2192 ${e.url}`:`electron launched via ${t.via}`,target:t.target,attachUrl:e.url}:{launched:!1,message:"desktop companion failed to start"}}catch(t){return{launched:!1,message:`electron launch failed: ${t instanceof Error?t.message:String(t)}`}}}var b={id:"electron",name:"electron",description:"sootsim desktop companion app (native window, menu bar)",kind:"native",availability:_,launch:M};import{spawn as A}from"child_process";import{closeSync as C,mkdtempSync as L,openSync as E,readFileSync as W}from"fs";import{createRequire as R}from"module";import{tmpdir as P}from"os";import{join as S}from"path";var N=`
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as u,b as w}from"./chunk-BMCBPMTC.js";import{a as h,b as g,c as v}from"./chunk-HQG4DRQ3.js";import{a as m,c as f}from"./chunk-WBY4JJ2K.js";import{c as p}from"./chunk-E5DE33BU.js";function x(){let e=h();return e?{available:!0,reason:null,detail:e}:{available:!1,reason:"no chromium-family browser found (chrome, chromium, edge, brave, arc)"}}async function I(e){if(e.headless)return{launched:!1,message:"the chromium driver launches a visible browser window and cannot run headless \u2014 a headless `chrome --headless=new` process exits immediately and the sim never connects. for headless automation use `--driver playwright`."};let r=h();if(!r)return{launched:!1,message:"chromium not found \u2014 install chrome or run `sootsim list --drivers`"};if(!e.url)return{launched:!1,message:"chromium driver requires a target url"};if(e.profileId||e.ephemeralProfile)return{launched:!1,message:"profiles require electron or playwright; browser tabs use your current Chrome profile"};try{let t=await v(e.url,{detached:e.detached??!0});return{launched:!0,message:`chromium launched \u2192 ${e.url}`,pid:t.pid,target:t.target??r,attachUrl:e.url}}catch(t){return{launched:!1,message:`chromium spawn failed: ${t instanceof Error?t.message:String(t)}`}}}var y={id:"chromium",name:"chromium",description:"system chrome / chromium / edge \u2014 visible window (headless: use playwright)",kind:"browser",availability:x,launch:I};function _(){let e=u();return e?{available:!0,reason:null,detail:`${e.kind} @ ${e.path}`}:{available:!1,reason:"sootsim desktop app not installed (run `sootsim install-desktop`)"}}async function M(e){let r=u();if(!r)return{launched:!1,message:"sootsim desktop app not installed"};try{let t=await w(e.url,r,{device:e.device,profileId:e.profileId,ephemeralProfile:e.ephemeralProfile});return t.launched?{launched:!0,message:e.url?`electron launched via ${t.via} \u2192 ${e.url}`:`electron launched via ${t.via}`,target:t.target,attachUrl:e.url}:{launched:!1,message:"desktop companion failed to start"}}catch(t){return{launched:!1,message:`electron launch failed: ${t instanceof Error?t.message:String(t)}`}}}var b={id:"electron",name:"electron",description:"sootsim desktop companion app (native window, menu bar)",kind:"native",availability:_,launch:M};import{spawn as C}from"child_process";import{closeSync as A,mkdtempSync as E,openSync as L,readFileSync as W}from"fs";import{createRequire as R}from"module";import{tmpdir as P}from"os";import{join as S}from"path";var N=`
3
3
  const modulePath = process.env.SOOTSIM_PW_MODULE;
4
4
  const url = process.env.SOOTSIM_PW_URL;
5
5
  const headless = process.env.SOOTSIM_PW_HEADLESS === '1';
@@ -14,6 +14,10 @@ const ownerPollMs = Number(process.env.SOOTSIM_PW_OWNER_POLL_MS || 5000);
14
14
  // bridge-driven sim can also be cpu-profiled (sootsim cpu-profile --cdp-port).
15
15
  // playwright keeps its own pipe connection; the port is an additional endpoint.
16
16
  const cdpPort = process.env.SOOTSIM_PW_CDP_PORT || '';
17
+ // browser engine: 'chromium' (default) | 'webkit' | 'firefox'. webkit is the
18
+ // iOS Safari proxy \u2014 headless webkit keeps the real Apple GPU while headless
19
+ // chromium falls back to SwiftShader software rendering for canvas/WebGL.
20
+ const browserEngine = process.env.SOOTSIM_PW_BROWSER || 'chromium';
17
21
  const closeTimeoutMs = Number(process.env.SOOTSIM_PW_CLOSE_TIMEOUT_MS || 2500);
18
22
  const connectAckFile = process.env.SOOTSIM_PW_CONNECTED_ACK_FILE || '';
19
23
  const { existsSync, mkdtempSync, rmSync, unlinkSync } = require('fs');
@@ -210,6 +214,14 @@ const cleanupProfile = () => {
210
214
  // cannot be constructed in a dedicated worker (see
211
215
  // worker-handlers/cpu-profile.ts). cpu-profile needs a CDP-based profiler
212
216
  // instead.
217
+ if (browserEngine === 'webkit' || browserEngine === 'firefox') {
218
+ // non-chromium engines: no channels, no chromium flags, no CDP. the
219
+ // persistent-context profile dir still appears on the root process
220
+ // cmdline (--user-data-dir / -profile), which is what reapChrome()'s
221
+ // pgrep sweep keys on; helpers die via the recursive killTree.
222
+ context = await pw[browserEngine].launchPersistentContext(profileDir, { headless });
223
+ process.stderr.write('[playwright-driver] launched ' + browserEngine + '\\n');
224
+ } else {
213
225
  const pinnedChannel = process.env.SOOTSIM_PW_CHANNEL || '';
214
226
  const channelsToTry = pinnedChannel
215
227
  ? [pinnedChannel]
@@ -259,6 +271,7 @@ const cleanupProfile = () => {
259
271
  if (launchedChannel) {
260
272
  process.stderr.write('[playwright-driver] launched ' + launchedChannel + '\\n');
261
273
  }
274
+ }
262
275
  const hostMeta = {
263
276
  sootsimHostDriver: 'playwright',
264
277
  sootsimHostPid: process.pid,
@@ -319,6 +332,6 @@ const cleanupProfile = () => {
319
332
  process.stderr.write(String((err && err.stack) || err) + '\\n');
320
333
  process.exit(1);
321
334
  });
322
- `;function D(){let e=[process.cwd()+"/"];try{process.argv[1]&&e.push(process.argv[1])}catch{}for(let r of e)try{let t=R(r);for(let n of["playwright","playwright-chromium","playwright-core"])try{return{spec:n,modulePath:t.resolve(n)}}catch{}}catch{}return null}function U(){let e=D();return e?{available:!0,reason:null,detail:`resolved via ${e.spec}`}:{available:!1,reason:"playwright not installed in the current workspace"}}function $(e,r){return process.platform!=="linux"||e.headless||process.env.DISPLAY||process.env.WAYLAND_DISPLAY||!/missing x server|cannot open display|x server|x11/i.test(r)?null:" hint: linux without DISPLAY/WAYLAND_DISPLAY \u2014 rerun without --headed (or add --headless) to run playwright headless."}function F(e){return e.profileId?m(f(e.profileId).id):e.ephemeralProfile?L(S(P(),"sootsim-playwright-profile-")):""}async function q(e){let r=D();if(!r)return{launched:!1,message:"playwright not installed \u2014 run `bun add -D playwright` first"};if(!e.url)return{launched:!1,message:"playwright driver requires a target url"};let t=S(P(),`sootsim-playwright-host-${Date.now().toString(36)}-${process.pid}.log`),n=`${t}.connected`,a=E(t,"a");try{let o=p(),c=A(process.execPath,["-e",N],{detached:!0,stdio:["ignore","ignore",a],env:{...process.env,SOOTSIM_PW_MODULE:r.modulePath,SOOTSIM_PW_URL:e.url,SOOTSIM_PW_HEADLESS:e.headless??!0?"1":"0",SOOTSIM_PW_USERDATADIR:F(e),SOOTSIM_PW_CDP_PORT:e.cdpPort?String(e.cdpPort):"",SOOTSIM_PW_CONNECTED_ACK_FILE:n,SOOTSIM_PW_CONNECT_TIMEOUT_MS:String(e.connectTimeoutMs??12e4),SOOTSIM_PW_OWNER_PID:o&&o>1?String(o):""}});c.unref();let h=await new Promise(i=>{let l=setTimeout(()=>i(null),4e3);c.once("exit",T=>{clearTimeout(l),i(T??0)})});if(h!==null){let i=W(t,"utf8").trim(),l=$(e,i);return{launched:!1,message:`playwright host exited early (code ${h}) \u2014 host log ${t}${i?`:
335
+ `;function D(){let e=[process.cwd()+"/"];try{process.argv[1]&&e.push(process.argv[1])}catch{}for(let r of e)try{let t=R(r);for(let n of["playwright","playwright-chromium","playwright-core"])try{return{spec:n,modulePath:t.resolve(n)}}catch{}}catch{}return null}function U(){let e=D();return e?{available:!0,reason:null,detail:`resolved via ${e.spec}`}:{available:!1,reason:"playwright not installed in the current workspace"}}function $(e,r){return process.platform!=="linux"||e.headless||process.env.DISPLAY||process.env.WAYLAND_DISPLAY||!/missing x server|cannot open display|x server|x11/i.test(r)?null:" hint: linux without DISPLAY/WAYLAND_DISPLAY \u2014 rerun without --headed (or add --headless) to run playwright headless."}function F(e){return e.profileId?m(f(e.profileId).id):e.ephemeralProfile?E(S(P(),"sootsim-playwright-profile-")):""}async function q(e){let r=D();if(!r)return{launched:!1,message:"playwright not installed \u2014 run `bun add -D playwright` first"};if(!e.url)return{launched:!1,message:"playwright driver requires a target url"};let t=S(P(),`sootsim-playwright-host-${Date.now().toString(36)}-${process.pid}.log`),n=`${t}.connected`,a=L(t,"a");try{let o=p(),c=C(process.execPath,["-e",N],{detached:!0,stdio:["ignore","ignore",a],env:{...process.env,SOOTSIM_PW_MODULE:r.modulePath,SOOTSIM_PW_URL:e.url,SOOTSIM_PW_HEADLESS:e.headless??!0?"1":"0",SOOTSIM_PW_USERDATADIR:F(e),SOOTSIM_PW_CDP_PORT:e.cdpPort?String(e.cdpPort):"",SOOTSIM_PW_BROWSER:e.browser??"",SOOTSIM_PW_CONNECTED_ACK_FILE:n,SOOTSIM_PW_CONNECT_TIMEOUT_MS:String(e.connectTimeoutMs??12e4),SOOTSIM_PW_OWNER_PID:o&&o>1?String(o):""}});c.unref();let d=await new Promise(i=>{let l=setTimeout(()=>i(null),4e3);c.once("exit",T=>{clearTimeout(l),i(T??0)})});if(d!==null){let i=W(t,"utf8").trim(),l=$(e,i);return{launched:!1,message:`playwright host exited early (code ${d}) \u2014 host log ${t}${i?`:
323
336
  ${i}`:""}${l?`
324
- ${l}`:""}`}}return{launched:!0,message:`playwright chrome launched \u2192 ${e.url}`,pid:c.pid,target:r.spec,attachUrl:e.url,connectAckFile:n,diagnosticLogPath:t}}catch(o){return{launched:!1,message:`playwright launch failed: ${o instanceof Error?o.message:String(o)}`}}finally{C(a)}}var k={id:"playwright",name:"playwright",description:"programmatic chromium via the playwright package \u2014 headless default",kind:"automation",availability:U,launch:q};function H(){return process.platform!=="darwin"&&process.platform!=="linux"&&process.platform!=="win32"?{available:!1,reason:`unsupported platform: ${process.platform}`}:{available:!0,reason:null,detail:process.platform==="darwin"?"open(1)":process.platform==="win32"?"cmd /c start":"xdg-open(1)"}}async function G(e){if(e.headless)return{launched:!1,message:"system driver does not support --headless; use chromium or playwright"};if(!e.url)return{launched:!1,message:"system driver requires a target url"};if(e.profileId||e.ephemeralProfile)return{launched:!1,message:"profiles require electron or playwright; browser tabs use your current browser profile"};try{let r=await g(e.url,{detached:e.detached??!0,newWindow:e.newWindow});return{launched:!0,message:`${r.via} launch \u2192 ${e.url}`,pid:r.pid,target:r.target,attachUrl:e.url}}catch(r){return{launched:!1,message:`system launch failed: ${r instanceof Error?r.message:String(r)}`}}}var O={id:"system",name:"system",description:"shared browser launcher \u2014 system default or chromium window",kind:"delegate",availability:H,launch:G};var s=[y,b,k,O];function le(){return s}function ce(e){return s.find(r=>r.id===e)??null}function ue(e,r){if(e)return s.find(n=>n.id===e)??null;for(let t of r){let n=s.find(a=>a.id===t);if(n&&n.availability().available)return n}return null}function de(){return s.map(e=>{let r=e.availability();return{id:e.id,name:e.name,kind:e.kind,description:e.description,available:r.available,reason:r.reason,detail:r.detail??null}})}export{y as a,b,k as c,O as d,s as e,le as f,ce as g,ue as h,de as i};
337
+ ${l}`:""}`}}return{launched:!0,message:`playwright chrome launched \u2192 ${e.url}`,pid:c.pid,target:r.spec,attachUrl:e.url,connectAckFile:n,diagnosticLogPath:t}}catch(o){return{launched:!1,message:`playwright launch failed: ${o instanceof Error?o.message:String(o)}`}}finally{A(a)}}var k={id:"playwright",name:"playwright",description:"programmatic chromium via the playwright package \u2014 headless default",kind:"automation",availability:U,launch:q};function H(){return process.platform!=="darwin"&&process.platform!=="linux"&&process.platform!=="win32"?{available:!1,reason:`unsupported platform: ${process.platform}`}:{available:!0,reason:null,detail:process.platform==="darwin"?"open(1)":process.platform==="win32"?"cmd /c start":"xdg-open(1)"}}async function G(e){if(e.headless)return{launched:!1,message:"system driver does not support --headless; use chromium or playwright"};if(!e.url)return{launched:!1,message:"system driver requires a target url"};if(e.profileId||e.ephemeralProfile)return{launched:!1,message:"profiles require electron or playwright; browser tabs use your current browser profile"};try{let r=await g(e.url,{detached:e.detached??!0,newWindow:e.newWindow});return{launched:!0,message:`${r.via} launch \u2192 ${e.url}`,pid:r.pid,target:r.target,attachUrl:e.url}}catch(r){return{launched:!1,message:`system launch failed: ${r instanceof Error?r.message:String(r)}`}}}var O={id:"system",name:"system",description:"shared browser launcher \u2014 system default or chromium window",kind:"delegate",availability:H,launch:G};var s=[y,b,k,O];function le(){return s}function ce(e){return s.find(r=>r.id===e)??null}function ue(e,r){if(e)return s.find(n=>n.id===e)??null;for(let t of r){let n=s.find(a=>a.id===t);if(n&&n.availability().available)return n}return null}function he(){return s.map(e=>{let r=e.availability();return{id:e.id,name:e.name,kind:e.kind,description:e.description,available:r.available,reason:r.reason,detail:r.detail??null}})}export{y as a,b,k as c,O as d,s as e,le as f,ce as g,ue as h,he as i};
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  import{createInterface as i}from"readline";var c=()=>i({input:process.stdin,output:process.stdout});function s(o){return new Promise(n=>{let r=c();r.question(o,t=>{r.close(),n(t.trim())})})}async function u(o,n=!0){let r=n?"[Y/n]":"[y/N]";if(!process.stdin.isTTY)return console.log(` ${o} ${r} ${n?"y":"n"} (non-interactive)`),n;let t=await s(` ${o} ${r} `);return t===""?n:t.toLowerCase().startsWith("y")}async function a(o,n){console.log(`
3
3
  ${o}
4
4
  `);for(let e=0;e<n.length;e++)console.log(` ${e+1}. ${n[e]}`);if(console.log(),!process.stdin.isTTY)return console.log(` choose [1-${n.length}]: 1 (non-interactive)`),0;let r=await s(` choose [1-${n.length}]: `),t=parseInt(r,10);return t>=1&&t<=n.length?t-1:0}export{u as a,a as b};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as A,d as W,f as x}from"./chunk-QP4W3SGO.js";import{I as v,J as P,K as T,L as C,j as k}from"./chunk-AP22KA3Q.js";import{WebSocket as I}from"ws";function E(){if(k()){let n=P();if(n&&C(n))return n.bridgePort}let e=v();return e&&T(e)?e.bridgePort:7668}var w=class extends Error{lock;constructor(n,i){super(n),this.name="BridgeSimLockedError",this.lock=i}};function L(e){return e==="flag"?"via --sim":e==="saved"?"saved via `sootsim use`":"primary fallback \u2014 no sim pinned"}function V(e,n={}){let i=new Set,a=n.port??E(),l=n.commandTimeoutMs??15e3,r,m="none",h=new Set(n.stripBooleanFlags??[]),b=new Set(n.stripValueFlags??[]);for(let t=0;t<e.length;t++){let d=e[t];if(d==="--port"||d==="-p"){i.add(t),t+1<e.length&&(i.add(t+1),a=Number(e[t+1])),t++;continue}if(d.startsWith("--port=")){i.add(t),a=Number(d.slice(7));continue}if(d==="--timeout"){i.add(t),t+1<e.length&&(i.add(t+1),l=Number(e[t+1])),t++;continue}if(d==="--sim"||d==="--session"||d==="--tab"){i.add(t),t+1<e.length&&(i.add(t+1),r=e[t+1]?.trim()||void 0,m="flag"),t++;continue}let s=d.startsWith("--sim=")?d.slice(6):d.startsWith("--session=")?d.slice(10):d.startsWith("--tab=")?d.slice(6):void 0;if(s!==void 0){i.add(t),r=s.trim()||void 0,m="flag";continue}if(h.has(d)){i.add(t);continue}b.has(d)&&(i.add(t),t+1<e.length&&i.add(t+1),t++)}if(!r){let t=W();t&&(r=t.trim()||void 0,m="saved")}return{positional:e.filter((t,d)=>!i.has(d)),wsPort:a,simId:r,simIdSource:m,commandTimeoutMs:l}}function M(e,n={}){let i=1,a=n.commandTimeoutMs??15e3,l=new Map,r=new I(`ws://localhost:${e}`),m=A(),h=new Promise((s,o)=>{r.on("open",()=>{try{r.send(JSON.stringify({type:"bridge:hello",id:0,cliIdentityKey:m.key,cliIdentitySource:m.source,cliLabel:n.cliLabel}))}catch{}s()}),r.on("error",c=>{let g=c.message?`: ${c.message}`:"";o(new Error(`could not connect to ws://localhost:${e}${g}`))})}),b=!1,t=!1;function d(s,o){if(t||process.env.SOOTSIM_QUIET_TARGET_NOTICE==="1"||s.startsWith("bridge:")||s==="focus"||s==="close")return;t=!0;let c=o??"primary",g=L(o?n.simIdSource:"none");process.stderr.write(` \u2192 ${c} (${g})
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as A,d as W,f as x}from"./chunk-E5DE33BU.js";import{I as v,J as P,K as T,L as C,j as k}from"./chunk-BI56RR3G.js";import{WebSocket as I}from"ws";function E(){if(k()){let n=P();if(n&&C(n))return n.bridgePort}let e=v();return e&&T(e)?e.bridgePort:7668}var w=class extends Error{lock;constructor(n,i){super(n),this.name="BridgeSimLockedError",this.lock=i}};function L(e){return e==="flag"?"via --sim":e==="saved"?"saved via `sootsim use`":"primary fallback \u2014 no sim pinned"}function V(e,n={}){let i=new Set,a=n.port??E(),l=n.commandTimeoutMs??15e3,r,m="none",h=new Set(n.stripBooleanFlags??[]),b=new Set(n.stripValueFlags??[]);for(let t=0;t<e.length;t++){let d=e[t];if(d==="--port"||d==="-p"){i.add(t),t+1<e.length&&(i.add(t+1),a=Number(e[t+1])),t++;continue}if(d.startsWith("--port=")){i.add(t),a=Number(d.slice(7));continue}if(d==="--timeout"){i.add(t),t+1<e.length&&(i.add(t+1),l=Number(e[t+1])),t++;continue}if(d==="--sim"||d==="--session"||d==="--tab"){i.add(t),t+1<e.length&&(i.add(t+1),r=e[t+1]?.trim()||void 0,m="flag"),t++;continue}let s=d.startsWith("--sim=")?d.slice(6):d.startsWith("--session=")?d.slice(10):d.startsWith("--tab=")?d.slice(6):void 0;if(s!==void 0){i.add(t),r=s.trim()||void 0,m="flag";continue}if(h.has(d)){i.add(t);continue}b.has(d)&&(i.add(t),t+1<e.length&&i.add(t+1),t++)}if(!r){let t=W();t&&(r=t.trim()||void 0,m="saved")}return{positional:e.filter((t,d)=>!i.has(d)),wsPort:a,simId:r,simIdSource:m,commandTimeoutMs:l}}function M(e,n={}){let i=1,a=n.commandTimeoutMs??15e3,l=new Map,r=new I(`ws://localhost:${e}`),m=A(),h=new Promise((s,o)=>{r.on("open",()=>{try{r.send(JSON.stringify({type:"bridge:hello",id:0,cliIdentityKey:m.key,cliIdentitySource:m.source,cliLabel:n.cliLabel}))}catch{}s()}),r.on("error",c=>{let g=c.message?`: ${c.message}`:"";o(new Error(`could not connect to ws://localhost:${e}${g}`))})}),b=!1,t=!1;function d(s,o){if(t||process.env.SOOTSIM_QUIET_TARGET_NOTICE==="1"||s.startsWith("bridge:")||s==="focus"||s==="close")return;t=!0;let c=o??"primary",g=L(o?n.simIdSource:"none");process.stderr.write(` \u2192 ${c} (${g})
3
3
  `)}return r.on("message",s=>{let o;try{o=JSON.parse(s.toString())}catch{return}if(o.id===0)return;let c=l.get(o.id);c&&(l.delete(o.id),o._otherCliCount>0&&!b&&(b=!0,process.stderr.write(`
4
4
  \u26A0 ${o._otherCliCount} other CLI identity/identities are driving this sim
5
5
  taps, scrolls, and keyboard input from multiple agents will collide on
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{d as fe,e as ge,f as he}from"./chunk-FO3RPGBR.js";import{c as de}from"./chunk-4FVYQIRB.js";import{d as ue}from"./chunk-C7BIPAXT.js";import{c as le,e as ce,g as P}from"./chunk-RQDJPT6N.js";import{d as pe}from"./chunk-JR7LKXPB.js";import{a as ae,b}from"./chunk-VSDVOOWG.js";import{a as ie}from"./chunk-3JW7SSYR.js";import{createHash as We}from"crypto";import{readFileSync as j}from"fs";import{gzipSync as Ve}from"zlib";function ye(e){let n=(e||"").toLowerCase().split(";")[0].trim();return n?!(n.startsWith("image/")||n.startsWith("video/")||n.startsWith("audio/")||n==="font/woff2"||n==="application/font-woff2"||n==="application/zip"||n==="application/gzip"):!0}import{brotliCompressSync as ke,constants as Ae}from"node:zlib";var ze=9;function me(e){return ke(e,{params:{[Ae.BROTLI_PARAM_QUALITY]:ze}})}function K(e,n){let r=new AbortController,s=setTimeout(()=>r.abort(new Error(`${n} timed out after ${e/1e3}s`)),e);return{signal:r.signal,cancel:()=>clearTimeout(s)}}async function He(e){let n=K(12e4,`PUT ${e.url}`),r;try{r=await fetch(e.url,{method:"PUT",headers:{"content-type":e.contentType},body:e.bytes,signal:n.signal})}finally{n.cancel()}if(!r.ok){let s=await r.text().catch(()=>"");throw new Error(`PUT ${e.url} failed ${r.status}: ${s.slice(0,200)}`)}}async function Me(e,n=8,r){let s=0,i=0,a=e.length;await Promise.all(Array.from({length:Math.min(n,a)},async()=>{for(;s<a;){let c=e[s++];await He(c),i++,r?.(i,a)}}))}function Ce(e,n,r,s){let i=[];i.push({url:e.bundle.putUrl,contentType:e.bundle.contentType,bytes:n});for(let a of e.files){let c=r.get(a.urlhash);c&&i.push({url:a.putUrl,contentType:a.contentType,bytes:c})}e.events&&s?.eventsBytes&&i.push({url:e.events.putUrl,contentType:e.events.contentType,bytes:s.eventsBytes}),e.flowVideo&&s?.videoBytes&&i.push({url:e.flowVideo.putUrl,contentType:e.flowVideo.contentType,bytes:s.videoBytes}),e.storage&&s?.storageBytes&&i.push({url:e.storage.putUrl,contentType:e.storage.contentType,bytes:s.storageBytes});for(let a of e.snapshots??[]){let c=s?.snapshotBytes?.get(a.id);c&&i.push({url:a.putUrl,contentType:a.contentType,bytes:c})}return i}function Ne(e){return e.replace(/\/+$/,"")}var z=class extends Error{constructor(r,s,i,a=""){super(r);this.status=s;this.phase=i;this.responseText=a;this.name="PresignedUploadError"}};async function we(e){let n=Ne(e.originBase),r={"content-type":"application/json"};e.authHeader&&(r.authorization=e.authHeader),e.adminBypassToken&&(r["x-soot-admin-upload-bypass"]=e.adminBypassToken);let s=K(3e4,"init"),i;try{i=await fetch(`${n}/api/preview/upload/init`,{method:"POST",headers:r,body:JSON.stringify(e.initBody),signal:s.signal})}finally{s.cancel()}if(!i.ok){let f=await i.text().catch(()=>"");throw new z(`init failed: ${i.status} ${f.slice(0,200)}`,i.status,"init",f)}let a=await i.json(),c=Ce(a,e.bundleBytes,e.filesByHash,e.extras);await Me(c,e.concurrency??8,e.onPutProgress);let y=K(3e4,"finalize"),d;try{d=await fetch(`${n}/api/preview/upload/finalize`,{method:"POST",headers:r,body:JSON.stringify({token:a.token}),signal:y.signal})}finally{y.cancel()}if(!d.ok){let f=await d.text().catch(()=>"");throw new z(`finalize failed: ${d.status} ${f.slice(0,200)}`,d.status,"finalize",f)}let $=await d.json();return{init:a,finalize:$}}function qe(e){if(!e)return null;try{let n=JSON.parse(e);return typeof n.message=="string"&&n.message?n.message:null}catch{return null}}var Be=process.env.SOOTSIM_UPLOAD_ORIGIN||"https://sootbean.com",Te=process.env.SOOTSIM_PREVIEW_ORIGIN||"https://sootsim.com",Y="http://localhost:3000",De=2e3;async function Ge(e){if(e)return e;if(process.env.SOOTSIM_UPLOAD_ORIGIN)return process.env.SOOTSIM_UPLOAD_ORIGIN;try{let n=await fetch(`${Y}/api/preview/upload/init`,{method:"OPTIONS",signal:AbortSignal.timeout(De)});if(n.ok||n.status===204||n.status===405)return Y}catch{}return Be}function x(e){return e.replace(/\/$/,"")}function Ke(e){try{let r=new URL(e).hostname.replace(/^\[|\]$/g,"").toLowerCase();return r==="localhost"||r.endsWith(".localhost")||r==="0.0.0.0"||r==="::1"||/^127(?:\.\d{1,3}){3}$/.test(r)}catch{return!1}}function je(e){try{let n=new URL(e).hostname.toLowerCase();return n==="sootbean.com"||n.endsWith(".sootbean.com")}catch{return!1}}function Je(e,n){return n?x(n):process.env.SOOTSIM_PREVIEW_ORIGIN?x(process.env.SOOTSIM_PREVIEW_ORIGIN):Ke(e)?x(e):je(e)?x(Te):x(e)}function Ye(){console.log(`
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{d as fe,e as ge,f as he}from"./chunk-PKZNXDUJ.js";import{c as ce}from"./chunk-TNHF6BON.js";import{d as le}from"./chunk-IJP257WP.js";import{c as ue,e as de,g as P}from"./chunk-7OAUPGLN.js";import{d as pe}from"./chunk-HQG4DRQ3.js";import{a as ae,b}from"./chunk-C63EVPDN.js";import{a as ie}from"./chunk-LJ3SOZBF.js";import{createHash as We}from"crypto";import{readFileSync as j}from"fs";import{gzipSync as Ve}from"zlib";function ye(e){let n=(e||"").toLowerCase().split(";")[0].trim();return n?!(n.startsWith("image/")||n.startsWith("video/")||n.startsWith("audio/")||n==="font/woff2"||n==="application/font-woff2"||n==="application/zip"||n==="application/gzip"):!0}import{brotliCompressSync as ke,constants as Ae}from"node:zlib";var ze=9;function me(e){return ke(e,{params:{[Ae.BROTLI_PARAM_QUALITY]:ze}})}function K(e,n){let r=new AbortController,s=setTimeout(()=>r.abort(new Error(`${n} timed out after ${e/1e3}s`)),e);return{signal:r.signal,cancel:()=>clearTimeout(s)}}async function He(e){let n=K(12e4,`PUT ${e.url}`),r;try{r=await fetch(e.url,{method:"PUT",headers:{"content-type":e.contentType},body:e.bytes,signal:n.signal})}finally{n.cancel()}if(!r.ok){let s=await r.text().catch(()=>"");throw new Error(`PUT ${e.url} failed ${r.status}: ${s.slice(0,200)}`)}}async function Me(e,n=8,r){let s=0,i=0,a=e.length;await Promise.all(Array.from({length:Math.min(n,a)},async()=>{for(;s<a;){let c=e[s++];await He(c),i++,r?.(i,a)}}))}function Ce(e,n,r,s){let i=[];i.push({url:e.bundle.putUrl,contentType:e.bundle.contentType,bytes:n});for(let a of e.files){let c=r.get(a.urlhash);c&&i.push({url:a.putUrl,contentType:a.contentType,bytes:c})}e.events&&s?.eventsBytes&&i.push({url:e.events.putUrl,contentType:e.events.contentType,bytes:s.eventsBytes}),e.flowVideo&&s?.videoBytes&&i.push({url:e.flowVideo.putUrl,contentType:e.flowVideo.contentType,bytes:s.videoBytes}),e.storage&&s?.storageBytes&&i.push({url:e.storage.putUrl,contentType:e.storage.contentType,bytes:s.storageBytes});for(let a of e.snapshots??[]){let c=s?.snapshotBytes?.get(a.id);c&&i.push({url:a.putUrl,contentType:a.contentType,bytes:c})}return i}function Ne(e){return e.replace(/\/+$/,"")}var z=class extends Error{constructor(r,s,i,a=""){super(r);this.status=s;this.phase=i;this.responseText=a;this.name="PresignedUploadError"}};async function we(e){let n=Ne(e.originBase),r={"content-type":"application/json"};e.authHeader&&(r.authorization=e.authHeader),e.adminBypassToken&&(r["x-soot-admin-upload-bypass"]=e.adminBypassToken);let s=K(3e4,"init"),i;try{i=await fetch(`${n}/api/preview/upload/init`,{method:"POST",headers:r,body:JSON.stringify(e.initBody),signal:s.signal})}finally{s.cancel()}if(!i.ok){let f=await i.text().catch(()=>"");throw new z(`init failed: ${i.status} ${f.slice(0,200)}`,i.status,"init",f)}let a=await i.json(),c=Ce(a,e.bundleBytes,e.filesByHash,e.extras);await Me(c,e.concurrency??8,e.onPutProgress);let y=K(3e4,"finalize"),d;try{d=await fetch(`${n}/api/preview/upload/finalize`,{method:"POST",headers:r,body:JSON.stringify({token:a.token}),signal:y.signal})}finally{y.cancel()}if(!d.ok){let f=await d.text().catch(()=>"");throw new z(`finalize failed: ${d.status} ${f.slice(0,200)}`,d.status,"finalize",f)}let $=await d.json();return{init:a,finalize:$}}function qe(e){if(!e)return null;try{let n=JSON.parse(e);return typeof n.message=="string"&&n.message?n.message:null}catch{return null}}var Be=process.env.SOOTSIM_UPLOAD_ORIGIN||"https://sootbean.com",Te=process.env.SOOTSIM_PREVIEW_ORIGIN||"https://sootsim.com",Y="http://localhost:3000",De=2e3;async function Ge(e){if(e)return e;if(process.env.SOOTSIM_UPLOAD_ORIGIN)return process.env.SOOTSIM_UPLOAD_ORIGIN;try{let n=await fetch(`${Y}/api/preview/upload/init`,{method:"OPTIONS",signal:AbortSignal.timeout(De)});if(n.ok||n.status===204||n.status===405)return Y}catch{}return Be}function x(e){return e.replace(/\/$/,"")}function Ke(e){try{let r=new URL(e).hostname.replace(/^\[|\]$/g,"").toLowerCase();return r==="localhost"||r.endsWith(".localhost")||r==="0.0.0.0"||r==="::1"||/^127(?:\.\d{1,3}){3}$/.test(r)}catch{return!1}}function je(e){try{let n=new URL(e).hostname.toLowerCase();return n==="sootbean.com"||n.endsWith(".sootbean.com")}catch{return!1}}function Je(e,n){return n?x(n):process.env.SOOTSIM_PREVIEW_ORIGIN?x(process.env.SOOTSIM_PREVIEW_ORIGIN):Ke(e)?x(e):je(e)?x(Te):x(e)}function Ye(){console.log(`
3
3
  sootsim upload \u2014 publish the current recorded bundle as a /preview/<id> link
4
4
 
5
5
  usage:
@@ -39,7 +39,7 @@ examples:
39
39
  sootsim upload --events ./my-session.jsonl.gz
40
40
  sootsim upload --origin http://localhost:3000 --events ./my-session.jsonl.gz --open
41
41
  sootsim upload --video /tmp/soot-flow.mp4 --video-duration-ms 12000
42
- `)}function v(e,n){let r=e.findIndex(i=>i===n);if(r<0)return;let s=e[r+1];return e.splice(r,2),s}function be(e,n){let r=e.findIndex(s=>s===n);return r<0?!1:(e.splice(r,1),!0)}function ve(e){let n=(e||"").toLowerCase().split(";")[0].trim();return n?!!(n.startsWith("image/")||n.startsWith("font/")||n.startsWith("video/")||n.startsWith("audio/")||n.startsWith("model/")||n==="text/css"||n==="application/javascript"||n==="text/javascript"||n==="application/wasm"||n==="application/font-woff"||n==="application/font-woff2"||n==="application/octet-stream"):!1}async function Ue(e){let n=await fetch(e);if(!n.ok)throw new Error(`fetch ${e} -> ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}function Qe(e){return/\.bundle($|\?)/.test(e)||/\.js($|\?)/.test(e)?"application/javascript":/\.zip($|\?)/.test(e)?"application/zip":"application/javascript"}function Xe(e){try{return new URL(e).searchParams.get("appFonts")||""}catch{return""}}function Ze(e){try{return new URL(e).searchParams.get("appSplash")||""}catch{return""}}function et(e){try{let n=new URL(e);return n.searchParams.get("lazy")==="true"?(n.searchParams.set("lazy","false"),n.toString()):e}catch{return e}}async function tt(e,n){let s=[];for(let i=0;i<n;i+=15e5){let a=Math.min(i+15e5,n),c=await P(e,`(window.__sootsimLastTransformedBundle?.text || "").slice(${i}, ${a})`);if(typeof c!="string")return null;s.push(c)}return s.join("")}function J(e){let n=new Map;for(let r of e)n.set(r.urlhash||r.url,r);return Array.from(n.values())}async function vt(e,n){(e.includes("--help")||e.includes("-h"))&&(Ye(),process.exit(0));let r=[...e],s=await Ge(v(r,"--origin")),i=Je(s,v(r,"--public-origin")),a=v(r,"--events"),c=v(r,"--screenshot"),y=v(r,"--video"),d=v(r,"--video-duration-ms"),$=v(r,"--owner"),f=v(r,"--repo"),Pe=be(r,"--open");($&&!f||!$&&f)&&(console.error(" --owner and --repo must be provided together"),process.exit(1)),!a&&!y&&(console.error(" preview uploads require playback data: pass --events or --video.\n for a normal local preview, use `sootsim record --mode combined --open`\n or `sootsim flow --preview` instead of uploading a bundle-only snapshot."),process.exit(1));let Q=be(r,"--assets-only"),Ie=le(r,{stripBooleanFlags:[],stripValueFlags:[]}),U=ce(Ie),l,X=[],m=[],H=null;try{if(l=await P(U,'(typeof window.__sootsimCaptureBundle === "function") ? window.__sootsimCaptureBundle() : null'),l?.bundleUrl){let t=new URL(l.bundleUrl).origin,[o,u]=await Promise.all([P(U,`(window.__sootsimPreviewRecorder?.list?.(${JSON.stringify(t)}) || [])`),P(U,`(async () => {
42
+ `)}function v(e,n){let r=e.findIndex(i=>i===n);if(r<0)return;let s=e[r+1];return e.splice(r,2),s}function be(e,n){let r=e.findIndex(s=>s===n);return r<0?!1:(e.splice(r,1),!0)}function ve(e){let n=(e||"").toLowerCase().split(";")[0].trim();return n?!!(n.startsWith("image/")||n.startsWith("font/")||n.startsWith("video/")||n.startsWith("audio/")||n.startsWith("model/")||n==="text/css"||n==="application/javascript"||n==="text/javascript"||n==="application/wasm"||n==="application/font-woff"||n==="application/font-woff2"||n==="application/octet-stream"):!1}async function Ue(e){let n=await fetch(e);if(!n.ok)throw new Error(`fetch ${e} -> ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}function Qe(e){return/\.bundle($|\?)/.test(e)||/\.js($|\?)/.test(e)?"application/javascript":/\.zip($|\?)/.test(e)?"application/zip":"application/javascript"}function Xe(e){try{return new URL(e).searchParams.get("appFonts")||""}catch{return""}}function Ze(e){try{return new URL(e).searchParams.get("appSplash")||""}catch{return""}}function et(e){try{let n=new URL(e);return n.searchParams.get("lazy")==="true"?(n.searchParams.set("lazy","false"),n.toString()):e}catch{return e}}async function tt(e,n){let s=[];for(let i=0;i<n;i+=15e5){let a=Math.min(i+15e5,n),c=await P(e,`(window.__sootsimLastTransformedBundle?.text || "").slice(${i}, ${a})`);if(typeof c!="string")return null;s.push(c)}return s.join("")}function J(e){let n=new Map;for(let r of e)n.set(r.urlhash||r.url,r);return Array.from(n.values())}async function vt(e,n){(e.includes("--help")||e.includes("-h"))&&(Ye(),process.exit(0));let r=[...e],s=await Ge(v(r,"--origin")),i=Je(s,v(r,"--public-origin")),a=v(r,"--events"),c=v(r,"--screenshot"),y=v(r,"--video"),d=v(r,"--video-duration-ms"),$=v(r,"--owner"),f=v(r,"--repo"),Pe=be(r,"--open");($&&!f||!$&&f)&&(console.error(" --owner and --repo must be provided together"),process.exit(1)),!a&&!y&&(console.error(" preview uploads require playback data: pass --events or --video.\n for a normal local preview, use `sootsim record --mode combined --open`\n or `sootsim flow --preview` instead of uploading a bundle-only snapshot."),process.exit(1));let Q=be(r,"--assets-only"),Ie=ue(r,{stripBooleanFlags:[],stripValueFlags:[]}),U=de(Ie),l,X=[],m=[],H=null;try{if(l=await P(U,'(typeof window.__sootsimCaptureBundle === "function") ? window.__sootsimCaptureBundle() : null'),l?.bundleUrl){let t=new URL(l.bundleUrl).origin,[o,u]=await Promise.all([P(U,`(window.__sootsimPreviewRecorder?.list?.(${JSON.stringify(t)}) || [])`),P(U,`(async () => {
43
43
  const list = window.__sootsimListWorkerFetchRecorder
44
44
  return typeof list === 'function'
45
45
  ? await list(${JSON.stringify(t)})
@@ -75,5 +75,5 @@ examples:
75
75
  : [],
76
76
  }
77
77
  })()`);if(m=J([...p.main,...p.worker]),Q){let _=m.length;m=m.filter(G=>ve(G.contentType));let D=T.totalBytes-m.reduce((G,Fe)=>G+(Fe.size||0),0);console.log(` --assets-only: kept ${m.length}/${_} records (dropped ${(D/1024).toFixed(1)} KiB of API responses)`)}}}l?.transformedBundle&&(H=await tt(U,l.transformedBundle.byteLength))}finally{U.close()}l||(console.error(" could not read bundle snapshot \u2014 is sootsim running and is the bundle loaded?"),process.exit(2)),l.bundleUrl||(console.error(` no ?bundle= URL on the current sootsim tab.
78
- open the app you want to share first (e.g. sootsim open 8082), then run upload.`),process.exit(2));let g,M=!1;if(H!==null)g=new TextEncoder().encode(H),M=!0,console.log(` using post-transform bundle: ${(g.byteLength/1024).toFixed(1)} KiB`);else{let t=et(l.bundleUrl);t!==l.bundleUrl&&console.log(" forcing lazy=false for self-contained bundle"),console.log(` capturing: ${t}`),g=await Ue(t),console.log(` main bundle: ${(g.byteLength/1024).toFixed(1)} KiB`)}let F=X.filter(t=>t.url!==l.bundleUrl);Q&&(F=F.filter(t=>ve(t.contentType))),console.log(` fetching ${F.length} extra files\u2026`);let k=(await Promise.all(F.map(async t=>{try{let o=await Ue(t.url);return{...t,bytes:o}}catch(o){return console.error(` warning: failed to re-fetch ${t.url}: ${o instanceof Error?o.message:o}`),null}}))).filter(t=>!!t),Re=k.reduce((t,o)=>t+o.bytes.byteLength,0);console.log(` ${k.length} extra files: ${(Re/1024).toFixed(1)} KiB`);let B;a&&(B=j(a));let h;c&&(h=j(c),console.log(` attaching screenshot: ${(h.byteLength/1024).toFixed(1)} KiB`));let w,O,Z;if(y){if(w=j(y),O=y.endsWith(".mp4")?"video/mp4":y.endsWith(".gif")?"image/gif":void 0,O||(console.error(" preview flow videos must be mp4 or gif"),await b(),process.exit(1)),d){let t=Number(d);(!Number.isFinite(t)||t<=0)&&(console.error(` invalid --video-duration-ms: ${d}`),await b(),process.exit(1)),Z=Math.round(t)}console.log(` attaching flow video: ${(w.byteLength/1024).toFixed(1)} KiB (${O})`)}let I=fe(),R=he(I),Se=ie();ae({event:"preview_upload_started",identity:{userId:I?.kind==="session"?Se?.user?.id??null:null,repoId:R?.repoId??null,installationId:R?.installationId??null},properties:{origin:s,hasAuth:!!I,authMode:I?.kind??"none",bundleBytes:g.byteLength,isTransformed:M,extraFiles:k.length,recordedFetches:m.length,hasEvents:!!B,hasScreenshot:!!h,hasVideo:!!w}}),I||(console.error(" preview uploads need auth."),console.error(" set SOOTSIM_API_KEY=sk_sootsim_..., run `sootsim login`, or use the soot github runner."),await b(),process.exit(1));let _e=ge(I),xe=(()=>{try{return new URL(l.bundleUrl).origin}catch{return null}})(),A=(t,o,u,L,se,S,T,p)=>{let _=ye(S),D=_?Ve(t):t;return{url:o,urlhash:u,method:L,bodyHash:se,requestVaryHash:p,contentType:S,responseHeaders:T,bytes:D,encoding:_?"gzip":void 0}},ee=[],C=Xe(l.pageHref)||"";if(C){let t=await ue(C,{onStaged:({url:o,byteLength:u})=>console.log(` staged app font: ${o} (${(u/1024).toFixed(1)} KiB)`),onError:(o,u)=>console.error(` warning: failed to fetch app font ${o}: ${u instanceof Error?u.message:u}`)});for(let o of t)ee.push(A(Buffer.from(o.bytes),o.url,o.urlhash,"GET","-",o.contentType))}let te=[],N=Ze(l.pageHref)||"";if(N){let t=await de(N,{onStaged:({url:o,byteLength:u})=>console.log(` staged splash image: ${o} (${(u/1024).toFixed(1)} KiB)`),onError:(o,u)=>console.error(` warning: failed to fetch splash image ${o}: ${u instanceof Error?u.message:u}`)});for(let o of t)te.push(A(Buffer.from(o.bytes),o.url,o.urlhash,"GET","-",o.contentType))}let W=[...k.map(t=>A(t.bytes,t.url,t.urlhash,"GET","-",t.contentType,t.responseHeaders,t.requestVaryHash)),...m.map(t=>A(Buffer.from(t.bodyBase64,"base64"),t.url,t.urlhash,t.method||"GET",t.bodyHash||"-",t.contentType,t.responseHeaders,t.requestVaryHash)),...ee,...te],V=me(g),$e=We("sha256").update(g).digest("hex");console.log(` bundle raw=${(g.byteLength/1024).toFixed(1)} KiB br=${(V.byteLength/1024).toFixed(1)} KiB`);let Oe={contentHash:$e,bundleSizeBytes:g.byteLength,bundleContentType:Qe(l.bundleUrl),bundleEncoding:"br",bundleOrigin:xe,runtimeVersion:l.runtimeVersion??void 0,appFonts:C||void 0,appSplash:N||void 0,entry:l.entry,isTransformed:M,deviceSpec:l.deviceSpec,installationId:R?.installationId??void 0,repoId:R?.repoId,owner:$??R?.owner,repo:f??R?.repo,files:W.map(t=>({url:t.url,urlhash:t.urlhash,method:t.method,bodyHash:t.bodyHash,contentType:t.contentType,responseHeaders:t.responseHeaders,requestVaryHash:t.requestVaryHash,encoding:t.encoding,sizeBytes:t.bytes.byteLength})),events:B?{sizeBytes:B.byteLength}:void 0,snapshots:h?[{id:"landing",label:"Landing",kind:"landing",t:0,contentType:"image/png",sizeBytes:h.byteLength}]:void 0,flowVideo:w&&O?{sizeBytes:w.byteLength,contentType:O,durationMs:Z}:void 0},ne=new Map;for(let t of W)ne.set(t.urlhash,t.bytes);let re=new Map;h&&re.set("landing",h);let Ee=Date.now(),E=V.byteLength;for(let t of W)E+=t.bytes.byteLength;B&&(E+=B.byteLength),h&&(E+=h.byteLength),w&&(E+=w.byteLength);let Le=`${x(s)}/api/preview/upload/init`;console.log(` init: ${Le}`);let q;try{let t=await we({originBase:s,initBody:Oe,bundleBytes:V,filesByHash:ne,extras:{eventsBytes:B,videoBytes:w,snapshotBytes:re},authHeader:_e,concurrency:16});q=t.finalize;let o=1+t.init.files.length+(t.init.events?1:0)+t.init.snapshots.length+(t.init.flowVideo?1:0);console.log(` PUT ${o} objects in ${Date.now()-Ee}ms (${(E/1024).toFixed(1)} KiB)`)}catch(t){let o=t;o.phase==="init"&&o.status===401&&(console.error(" preview upload requires a valid login."),console.error(" run `sootsim login` and retry."),await b(),process.exit(1)),o.status===402&&(console.error(` ${qe(o.responseText)??"preview uploads require Personal, Team, or an active trial \u2014 upgrade from the billing dialog."}`),await b(),process.exit(1)),console.error(` ${o.message??`${o.phase??"upload"} failed: ${String(t)}`}`),await b(),process.exit(1)}let oe=`${i}${q.url}`;console.log(`
78
+ open the app you want to share first (e.g. sootsim open 8082), then run upload.`),process.exit(2));let g,M=!1;if(H!==null)g=new TextEncoder().encode(H),M=!0,console.log(` using post-transform bundle: ${(g.byteLength/1024).toFixed(1)} KiB`);else{let t=et(l.bundleUrl);t!==l.bundleUrl&&console.log(" forcing lazy=false for self-contained bundle"),console.log(` capturing: ${t}`),g=await Ue(t),console.log(` main bundle: ${(g.byteLength/1024).toFixed(1)} KiB`)}let F=X.filter(t=>t.url!==l.bundleUrl);Q&&(F=F.filter(t=>ve(t.contentType))),console.log(` fetching ${F.length} extra files\u2026`);let k=(await Promise.all(F.map(async t=>{try{let o=await Ue(t.url);return{...t,bytes:o}}catch(o){return console.error(` warning: failed to re-fetch ${t.url}: ${o instanceof Error?o.message:o}`),null}}))).filter(t=>!!t),Re=k.reduce((t,o)=>t+o.bytes.byteLength,0);console.log(` ${k.length} extra files: ${(Re/1024).toFixed(1)} KiB`);let B;a&&(B=j(a));let h;c&&(h=j(c),console.log(` attaching screenshot: ${(h.byteLength/1024).toFixed(1)} KiB`));let w,O,Z;if(y){if(w=j(y),O=y.endsWith(".mp4")?"video/mp4":y.endsWith(".gif")?"image/gif":void 0,O||(console.error(" preview flow videos must be mp4 or gif"),await b(),process.exit(1)),d){let t=Number(d);(!Number.isFinite(t)||t<=0)&&(console.error(` invalid --video-duration-ms: ${d}`),await b(),process.exit(1)),Z=Math.round(t)}console.log(` attaching flow video: ${(w.byteLength/1024).toFixed(1)} KiB (${O})`)}let I=fe(),R=he(I),Se=ie();ae({event:"preview_upload_started",identity:{userId:I?.kind==="session"?Se?.user?.id??null:null,repoId:R?.repoId??null,installationId:R?.installationId??null},properties:{origin:s,hasAuth:!!I,authMode:I?.kind??"none",bundleBytes:g.byteLength,isTransformed:M,extraFiles:k.length,recordedFetches:m.length,hasEvents:!!B,hasScreenshot:!!h,hasVideo:!!w}}),I||(console.error(" preview uploads need auth."),console.error(" set SOOTSIM_API_KEY=sk_sootsim_..., run `sootsim login`, or use the soot github runner."),await b(),process.exit(1));let _e=ge(I),xe=(()=>{try{return new URL(l.bundleUrl).origin}catch{return null}})(),A=(t,o,u,L,se,S,T,p)=>{let _=ye(S),D=_?Ve(t):t;return{url:o,urlhash:u,method:L,bodyHash:se,requestVaryHash:p,contentType:S,responseHeaders:T,bytes:D,encoding:_?"gzip":void 0}},ee=[],C=Xe(l.pageHref)||"";if(C){let t=await le(C,{onStaged:({url:o,byteLength:u})=>console.log(` staged app font: ${o} (${(u/1024).toFixed(1)} KiB)`),onError:(o,u)=>console.error(` warning: failed to fetch app font ${o}: ${u instanceof Error?u.message:u}`)});for(let o of t)ee.push(A(Buffer.from(o.bytes),o.url,o.urlhash,"GET","-",o.contentType))}let te=[],N=Ze(l.pageHref)||"";if(N){let t=await ce(N,{onStaged:({url:o,byteLength:u})=>console.log(` staged splash image: ${o} (${(u/1024).toFixed(1)} KiB)`),onError:(o,u)=>console.error(` warning: failed to fetch splash image ${o}: ${u instanceof Error?u.message:u}`)});for(let o of t)te.push(A(Buffer.from(o.bytes),o.url,o.urlhash,"GET","-",o.contentType))}let W=[...k.map(t=>A(t.bytes,t.url,t.urlhash,"GET","-",t.contentType,t.responseHeaders,t.requestVaryHash)),...m.map(t=>A(Buffer.from(t.bodyBase64,"base64"),t.url,t.urlhash,t.method||"GET",t.bodyHash||"-",t.contentType,t.responseHeaders,t.requestVaryHash)),...ee,...te],V=me(g),$e=We("sha256").update(g).digest("hex");console.log(` bundle raw=${(g.byteLength/1024).toFixed(1)} KiB br=${(V.byteLength/1024).toFixed(1)} KiB`);let Oe={contentHash:$e,bundleSizeBytes:g.byteLength,bundleContentType:Qe(l.bundleUrl),bundleEncoding:"br",bundleOrigin:xe,runtimeVersion:l.runtimeVersion??void 0,appFonts:C||void 0,appSplash:N||void 0,entry:l.entry,isTransformed:M,deviceSpec:l.deviceSpec,installationId:R?.installationId??void 0,repoId:R?.repoId,owner:$??R?.owner,repo:f??R?.repo,files:W.map(t=>({url:t.url,urlhash:t.urlhash,method:t.method,bodyHash:t.bodyHash,contentType:t.contentType,responseHeaders:t.responseHeaders,requestVaryHash:t.requestVaryHash,encoding:t.encoding,sizeBytes:t.bytes.byteLength})),events:B?{sizeBytes:B.byteLength}:void 0,snapshots:h?[{id:"landing",label:"Landing",kind:"landing",t:0,contentType:"image/png",sizeBytes:h.byteLength}]:void 0,flowVideo:w&&O?{sizeBytes:w.byteLength,contentType:O,durationMs:Z}:void 0},ne=new Map;for(let t of W)ne.set(t.urlhash,t.bytes);let re=new Map;h&&re.set("landing",h);let Ee=Date.now(),E=V.byteLength;for(let t of W)E+=t.bytes.byteLength;B&&(E+=B.byteLength),h&&(E+=h.byteLength),w&&(E+=w.byteLength);let Le=`${x(s)}/api/preview/upload/init`;console.log(` init: ${Le}`);let q;try{let t=await we({originBase:s,initBody:Oe,bundleBytes:V,filesByHash:ne,extras:{eventsBytes:B,videoBytes:w,snapshotBytes:re},authHeader:_e,concurrency:16});q=t.finalize;let o=1+t.init.files.length+(t.init.events?1:0)+t.init.snapshots.length+(t.init.flowVideo?1:0);console.log(` PUT ${o} objects in ${Date.now()-Ee}ms (${(E/1024).toFixed(1)} KiB)`)}catch(t){let o=t;o.phase==="init"&&o.status===401&&(console.error(" preview upload requires a valid login."),console.error(" run `sootsim login` and retry."),await b(),process.exit(1)),o.status===402&&(console.error(` ${qe(o.responseText)??"preview uploads require Personal, Team, or an active trial \u2014 upgrade from the billing dialog."}`),await b(),process.exit(1)),console.error(` ${o.message??`${o.phase??"upload"} failed: ${String(t)}`}`),await b(),process.exit(1)}let oe=`${i}${q.url}`;console.log(`
79
79
  stored ${q.filesStored??0} extra files`),console.log(` preview: ${oe}`),Pe&&await pe(oe),await b()}export{Ge as a,Je as b,vt as c};
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  import t from"node:fs";import{homedir as A}from"node:os";import o from"node:path";var E="SOOTSIM_HOME",_="active",I="daemon.json",N="dev-bridge.json",j="config.json",h=3e4;function u(){let e=process.env[E];return e&&e.length>0?o.resolve(e):o.join(A(),".sootsim")}function F(){if(process.env.SOOTSIM_FORCE_DAEMON_INSTALL==="1")return!1;let e=process.env.SOOTSIM_DEV;if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;let r=process.argv[1];if(!r)return!1;try{return t.realpathSync(r).includes(`${o.sep}packages${o.sep}sootsim${o.sep}`)}catch{return!1}}function P(){return process.env.SOOTSIM_FORCE_DAEMON_INSTALL==="1"?!1:process.env.IS_TAMAGUI_DEV==="1"}function W(){return F()||P()}function f(){return o.join(u(),"runtimes")}function w(e){return o.join(f(),e)}function k(){return o.join(f(),_)}function D(){return o.join(u(),"electron")}function X(){return o.join(D(),"userData")}function q(e){return o.join(D(),e)}function T(){return o.join(u(),"profiles")}function B(){return o.join(u(),"daemon-app")}function M(){return o.join(B(),"SootSim Daemon.app")}function z(){return o.join(M(),"Contents","MacOS","sootsim-daemon")}function C(){return o.join(u(),"cache")}function p(){return o.join(u(),I)}function m(){return o.join(u(),N)}function b(){return o.join(u(),j)}function L(){try{let e=t.readFileSync(b(),"utf8"),r=JSON.parse(e);return r&&typeof r=="object"?r:{}}catch{return{}}}function R(e){g();let r=L(),i={...r,...e};e.settings&&typeof e.settings=="object"&&(i.settings={...r.settings&&typeof r.settings=="object"?r.settings:{},...e.settings});let c=`${b()}.tmp`;return t.writeFileSync(c,`${JSON.stringify(i,null,2)}
3
3
  `,"utf8"),t.renameSync(c,b()),i}function Q(){return L().telemetry!==!1}function Z(e){R({telemetry:e})}function g(){t.mkdirSync(u(),{recursive:!0}),t.mkdirSync(f(),{recursive:!0}),t.mkdirSync(D(),{recursive:!0}),t.mkdirSync(T(),{recursive:!0}),t.mkdirSync(C(),{recursive:!0})}function $(){try{let e=t.readFileSync(k(),"utf8").trim();return e.length>0?e:null}catch{return null}}function ee(e){t.mkdirSync(f(),{recursive:!0}),t.writeFileSync(k(),`${e}
4
4
  `,"utf8")}function re(){try{return t.readdirSync(f(),{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).sort(J)}catch{return[]}}function J(e,r){let i=s=>{let a=s.indexOf("-"),l=a>=0?s.slice(0,a):s,O=a>=0?s.slice(a+1):"",x=l.split(".").map(S=>Number.parseInt(S,10));return x.some(S=>!Number.isFinite(S))?[[Number.POSITIVE_INFINITY],s]:[x,O]},[c,n]=i(e),[v,y]=i(r);for(let s=0;s<Math.max(c.length,v.length);s++){let a=c[s]??0,l=v[s]??0;if(a!==l)return a-l}return n===y?0:n?y?n<y?-1:1:-1:1}function te(){let e=$();if(!e)return null;let r=w(e);try{if(t.statSync(r).isDirectory())return r}catch{}return null}var d=16*1024;function V(){try{let e=t.openSync(p(),"r");try{let r=Buffer.alloc(d),i=t.readSync(e,r,0,d,0),c=r.subarray(0,i).toString("utf8"),n=JSON.parse(c);return n&&n.schema===1&&typeof n.pid=="number"&&typeof n.bridgePort=="number"&&typeof n.runtimePort=="number"&&typeof n.startedAt=="number"&&typeof n.heartbeatAt=="number"?n:null}finally{t.closeSync(e)}}catch{return null}}function ne(){try{let e=t.openSync(m(),"r");try{let r=Buffer.alloc(d),i=t.readSync(e,r,0,d,0),c=r.subarray(0,i).toString("utf8"),n=JSON.parse(c);return n&&n.schema===1&&n.source==="vite-dev"&&typeof n.pid=="number"&&typeof n.bridgePort=="number"&&typeof n.runtimePort=="number"&&typeof n.cwd=="string"&&typeof n.startedAt=="number"&&typeof n.heartbeatAt=="number"?n:null}finally{t.closeSync(e)}}catch{return null}}function H(e,r=Date.now()){if(!e||r-e.heartbeatAt>h)return!1;try{return process.kill(e.pid,0),!0}catch{return!1}}function oe(e,r=Date.now()){if(!e||r-e.heartbeatAt>h)return!1;try{return process.kill(e.pid,0),!0}catch{return!1}}function G(e){g();let r=`${p()}.tmp`;t.writeFileSync(r,`${JSON.stringify(e,null,2)}
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  import{execFileSync as h,spawn as g}from"child_process";import{existsSync as s,readdirSync as k}from"fs";import{dirname as m,join as l,resolve as a}from"path";import{fileURLToPath as v}from"url";var c;function p(){if(c!==void 0)return c;try{c=m(v(import.meta.resolve("sootsim-engine/package.json")))}catch{c=null}return c}var I="dev.sootsim.simulator";function x(){let n=p();if(!n)return null;let e=l(n,"dist-electron/main.cjs");if(!s(e))return null;let i=D(n);return i?{path:i,platform:process.platform,kind:"dev-electron",engineDir:n}:null}function b(){let n=p();return n?s(l(n,"src-electron/main.ts")):!1}function D(n){let e=n;for(let i=0;i<6;i++){let t=l(e,"node_modules/.bin/electron");if(s(t))return t;let r=m(e);if(r===e)break;e=r}return null}function C(){let n=p(),i=["/Applications/sootsim.app",a(process.env.HOME||"","Applications/sootsim.app"),...n?[a(n,"app/sootsim.app")]:[]].find(t=>s(t));if(i)return{path:i,platform:"darwin",kind:"mac-app"};try{let t=h("mdfind",[`kMDItemCFBundleIdentifier == "${I}"`],{encoding:"utf8",timeout:3e3}).trim();if(t)return{path:t.split(`
3
3
  `)[0],platform:"darwin",kind:"mac-app"}}catch{}return null}function f(n){if(!s(n))return null;let e=k(n).filter(i=>i.startsWith("sootsim")&&i.endsWith(".AppImage")).sort().reverse()[0];return e?l(n,e):null}function w(){let n=p(),i=[a(process.env.HOME||"","Applications/sootsim.AppImage"),a(process.env.HOME||"",".local/bin/sootsim.AppImage"),"/opt/sootsim/sootsim.AppImage","/opt/sootsim/sootsim",...n?[a(n,"app/sootsim.AppImage"),a(n,"release/linux-unpacked/sootsim")]:[]].find(r=>s(r));if(i)return{path:i,platform:"linux",kind:i.endsWith(".AppImage")?"linux-appimage":"linux-binary"};let t=n?f(a(n,"app"))||f(a(n,"release")):null;return t?{path:t,platform:"linux",kind:"linux-appimage"}:null}function A(){let n=x();if(n)return n;if(b()){let e=p(),i=l(e,"dist-electron/main.cjs");return s(i)?console.error(` no node_modules/.bin/electron found near ${e}. run \`bun install\`.`):console.error(` dist-electron/main.cjs missing in ${e}.
4
4
  run: bun run --cwd packages/sootsim-engine build:electron-main
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{C as v,D as f,E as R,G as w,l as p,u as S,x as O}from"./chunk-AP22KA3Q.js";import{spawn as I}from"child_process";import C from"crypto";import s from"fs";import l from"path";import{Readable as M}from"stream";import{pipeline as k}from"stream/promises";var N="https://sootbean.com",E="SOOTSIM_CDN_ORIGIN",T="SOOTSIM_RUNTIME_CHANNEL",q="https://sootsim.com/changelog";function $(){try{let t=JSON.parse(s.readFileSync(O(),"utf8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function d(t){let e=$();return(t||process.env[E]||e.cdnOrigin||N).replace(/\/+$/,"")}function x(t){let e=$();return t||process.env[T]||e.runtimeChannel||"stable"}function D(t){let e=new URL(`${d(t)}/runtimes/manifest.json`);return e.searchParams.set("t",String(Date.now())),e.toString()}function U(t,e){return`${d(e)}/runtimes/sootsim-runtime-${t}.tar.gz`}async function y(t){let e=D(t),r=await fetch(e,{headers:{Accept:"application/json"}});if(!r.ok)throw new Error(`manifest fetch failed: ${r.status} ${r.statusText} (${e})`);return await r.json()}function P(t,e={}){let r=x(e.channel),n=e.version||t.channels[r]?.latest;if(!n)throw new Error(`no version specified and channel '${r}' has no latest entry in the manifest`);let i=t.versions[n];if(!i)throw new Error(`version ${n} not found in manifest; available: ${Object.keys(t.versions).slice(-10).join(", ")||"(none)"}`);return{version:n,channel:r,entry:i}}async function _(t={}){v();let e=d(t.cdnOrigin),r=await y(e),{version:n,channel:i,entry:a}=P(r,t),o=p(n),c=t.setActive!==!1;if(!t.force&&s.existsSync(l.join(o,"index.html")))return c&&R(n),{version:n,channel:i,cdnOrigin:e,runtimeDir:o,installed:!1,activated:c,manifest:r};let g=a.tarball||U(n,e),m=l.join(S(),`sootsim-runtime-${n}.tar.gz`);process.stderr.write(`sootsim: downloading runtime ${n}\u2026
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{C as v,D as f,E as R,G as w,l as p,u as S,x as O}from"./chunk-BI56RR3G.js";import{spawn as I}from"child_process";import C from"crypto";import s from"fs";import l from"path";import{Readable as M}from"stream";import{pipeline as k}from"stream/promises";var N="https://sootbean.com",E="SOOTSIM_CDN_ORIGIN",T="SOOTSIM_RUNTIME_CHANNEL",q="https://sootsim.com/changelog";function $(){try{let t=JSON.parse(s.readFileSync(O(),"utf8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function d(t){let e=$();return(t||process.env[E]||e.cdnOrigin||N).replace(/\/+$/,"")}function x(t){let e=$();return t||process.env[T]||e.runtimeChannel||"stable"}function D(t){let e=new URL(`${d(t)}/runtimes/manifest.json`);return e.searchParams.set("t",String(Date.now())),e.toString()}function U(t,e){return`${d(e)}/runtimes/sootsim-runtime-${t}.tar.gz`}async function y(t){let e=D(t),r=await fetch(e,{headers:{Accept:"application/json"}});if(!r.ok)throw new Error(`manifest fetch failed: ${r.status} ${r.statusText} (${e})`);return await r.json()}function P(t,e={}){let r=x(e.channel),n=e.version||t.channels[r]?.latest;if(!n)throw new Error(`no version specified and channel '${r}' has no latest entry in the manifest`);let i=t.versions[n];if(!i)throw new Error(`version ${n} not found in manifest; available: ${Object.keys(t.versions).slice(-10).join(", ")||"(none)"}`);return{version:n,channel:r,entry:i}}async function _(t={}){v();let e=d(t.cdnOrigin),r=await y(e),{version:n,channel:i,entry:a}=P(r,t),o=p(n),c=t.setActive!==!1;if(!t.force&&s.existsSync(l.join(o,"index.html")))return c&&R(n),{version:n,channel:i,cdnOrigin:e,runtimeDir:o,installed:!1,activated:c,manifest:r};let g=a.tarball||U(n,e),m=l.join(S(),`sootsim-runtime-${n}.tar.gz`);process.stderr.write(`sootsim: downloading runtime ${n}\u2026
3
3
  `),await V(g,m),process.stderr.write(`sootsim: extracting runtime ${n}\u2026
4
4
  `);let h=await A(m);if(h!==a.sha256)throw s.rmSync(m,{force:!0}),new Error(`sha256 mismatch for runtime ${n}: expected ${a.sha256}, actual ${h}`);let u=l.join(l.dirname(o),`.installing-${n}-${process.pid}`);s.rmSync(u,{recursive:!0,force:!0}),s.mkdirSync(u,{recursive:!0});try{if(await j(m,u),!s.existsSync(l.join(u,"index.html")))throw new Error(`extracted tarball for runtime ${n} is missing index.html`);s.rmSync(o,{recursive:!0,force:!0}),s.renameSync(u,o)}catch(b){throw s.rmSync(u,{recursive:!0,force:!0}),b}return c&&R(n),{version:n,channel:i,cdnOrigin:e,runtimeDir:o,installed:!0,activated:c,manifest:r}}async function B(t={}){v();let e=d(t.cdnOrigin),r=x(t.channel),n=await y(e),i=n.channels[r]?.latest;if(!i)return{checked:!0,updated:!1,reason:`channel '${r}' has no latest runtime`,activeVersion:f()};if(!n.versions[i])return{checked:!0,updated:!1,reason:`manifest is missing version ${i}`,activeVersion:f(),latestVersion:i};let o=f(),c=o?p(o):null,g=c?s.existsSync(l.join(c,"index.html")):!1;if(!(!o||!g||w(i,o)>0))return{checked:!0,updated:!1,reason:"active runtime is current",activeVersion:o,latestVersion:i};let h=await _({version:i,channel:r,cdnOrigin:e,setActive:!1});return{checked:!0,updated:!0,activeVersion:i,latestVersion:i,install:h}}async function K(t={}){let e=f();try{let r=await y(d(t.cdnOrigin)),n=x(t.channel),i=r.channels[n]?.latest??null,a=!!(i&&(!e||w(i,e)>0));return{active:e,latest:i,outdated:a}}catch{return{active:e,latest:null,outdated:!1}}}async function V(t,e){let r=await fetch(t);if(!r.ok||!r.body)throw new Error(`download failed: ${r.status} ${r.statusText} (${t})`);s.mkdirSync(l.dirname(e),{recursive:!0});let n=`${e}.partial`;try{await k(M.fromWeb(r.body),s.createWriteStream(n)),s.renameSync(n,e)}catch(i){try{s.unlinkSync(n)}catch{}throw i}}function A(t){return new Promise((e,r)=>{let n=C.createHash("sha256"),i=s.createReadStream(t);i.on("data",a=>n.update(a)),i.on("error",r),i.on("end",()=>e(n.digest("hex")))})}function j(t,e){return new Promise((r,n)=>{let i=I("tar",["-xzf",t,"-C",e],{stdio:["ignore","inherit","inherit"]});i.on("error",n),i.on("exit",a=>{a===0?r():n(new Error(`tar exited with code ${a}`))})})}export{N as a,q as b,d as c,x as d,y as e,_ as f,B as g,K as h};
@@ -1,2 +1,2 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as s}from"./chunk-3JW7SSYR.js";import{A as o}from"./chunk-AP22KA3Q.js";function u(){let e=process.env.DO_NOT_TRACK;return e==="1"||e==="true"||!o()}function a(){if(u())return null;let e=process.env.VITE_POSTHOG_API_KEY||"";if(!e)return null;let t=process.env.SOOT_POSTHOG_HOST||process.env.VITE_POSTHOG_HOST||"https://us.i.posthog.com";return{apiKey:e,host:t.replace(/\/+$/,"")}}function c(e){return e?e.userId?e.userId:e.installationId!=null?`install:${e.installationId}`:e.repoId?`repo:${e.repoId}`:e.shareId?`share:${e.shareId}`:"anonymous-cli":"anonymous-cli"}function p(e){let t=e.identity??{},n={$lib:"soot-cli",source:t.source??"cli",...e.properties};return t.userId&&(n.userId=t.userId),t.repoId&&(n.repoId=t.repoId),t.installationId!=null&&(n.installationId=String(t.installationId)),t.shareId&&(n.shareId=t.shareId),t.plan&&(n.plan=t.plan),{event:e.event,distinct_id:c(t),properties:n,timestamp:new Date().toISOString()}}var r=[],l=!1;async function i(){if(r.length===0)return;let e=a();if(!e){r.length=0;return}let t=r.splice(0,r.length).map(p);try{await fetch(`${e.host}/batch/`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({api_key:e.apiKey,batch:t}),signal:AbortSignal.timeout(2e3)})}catch{}}function d(){l||(l=!0,process.on("beforeExit",()=>void i()),process.on("exit",()=>void i()))}function h(e){if(u())return;d();let t=null;try{t=s()?.user?.id??null}catch{t=null}r.push({...e,identity:{source:"cli",userId:t,...e.identity}})}async function g(){await i()}export{h as a,g as b};
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{a as s}from"./chunk-LJ3SOZBF.js";import{A as o}from"./chunk-BI56RR3G.js";function u(){let e=process.env.DO_NOT_TRACK;return e==="1"||e==="true"||!o()}function a(){if(u())return null;let e=process.env.VITE_POSTHOG_API_KEY||"";if(!e)return null;let t=process.env.SOOT_POSTHOG_HOST||process.env.VITE_POSTHOG_HOST||"https://us.i.posthog.com";return{apiKey:e,host:t.replace(/\/+$/,"")}}function c(e){return e?e.userId?e.userId:e.installationId!=null?`install:${e.installationId}`:e.repoId?`repo:${e.repoId}`:e.shareId?`share:${e.shareId}`:"anonymous-cli":"anonymous-cli"}function p(e){let t=e.identity??{},n={$lib:"soot-cli",source:t.source??"cli",...e.properties};return t.userId&&(n.userId=t.userId),t.repoId&&(n.repoId=t.repoId),t.installationId!=null&&(n.installationId=String(t.installationId)),t.shareId&&(n.shareId=t.shareId),t.plan&&(n.plan=t.plan),{event:e.event,distinct_id:c(t),properties:n,timestamp:new Date().toISOString()}}var r=[],l=!1;async function i(){if(r.length===0)return;let e=a();if(!e){r.length=0;return}let t=r.splice(0,r.length).map(p);try{await fetch(`${e.host}/batch/`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({api_key:e.apiKey,batch:t}),signal:AbortSignal.timeout(2e3)})}catch{}}function d(){l||(l=!0,process.on("beforeExit",()=>void i()),process.on("exit",()=>void i()))}function h(e){if(u())return;d();let t=null;try{t=s()?.user?.id??null}catch{t=null}r.push({...e,identity:{source:"cli",userId:t,...e.identity}})}async function g(){await i()}export{h as a,g as b};
@@ -1,5 +1,5 @@
1
- /*! sootsim v0.1.183 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{c as i,e as d,h as c}from"./chunk-RQDJPT6N.js";function g(r){let e=r[0]?.toLowerCase()??"toggle";return e!=="on"&&e!=="off"&&e!=="toggle"&&(console.error(` unknown argument: "${e}" (expected on | off | toggle)`),process.exit(1)),e}async function u(r,e,t){let l=i(r,{port:e.port}),s=g(l.positional),a=d({...l,commandTimeoutMs:5e3});try{let n=!!(await c(a,"SootSim.bridges.settings.get"))?.[t.modeKey],o=s==="on"?!0:s==="off"?!1:!n;if(n===o)return console.log(` ${t.displayName}: already ${o?"on":"off"}`),{current:n,target:o,changed:!1};if(!await a.send({type:"evaluate",acquireLock:!0,code:`(async () => {
1
+ /*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ import{c as i,e as d,h as c}from"./chunk-7OAUPGLN.js";function g(r){let e=r[0]?.toLowerCase()??"toggle";return e!=="on"&&e!=="off"&&e!=="toggle"&&(console.error(` unknown argument: "${e}" (expected on | off | toggle)`),process.exit(1)),e}async function u(r,e,t){let l=i(r,{port:e.port}),s=g(l.positional),a=d({...l,commandTimeoutMs:5e3});try{let n=!!(await c(a,"SootSim.bridges.settings.get"))?.[t.modeKey],o=s==="on"?!0:s==="off"?!1:!n;if(n===o)return console.log(` ${t.displayName}: already ${o?"on":"off"}`),{current:n,target:o,changed:!1};if(!await a.send({type:"evaluate",acquireLock:!0,code:`(async () => {
3
3
  const modeKey = ${JSON.stringify(t.modeKey)}
4
4
  const target = ${JSON.stringify(o)}
5
5
  window.dispatchEvent(new CustomEvent('sootsim:shell-command', {