sootsim 0.1.227 → 0.1.228

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 (175) hide show
  1. package/README.md +14 -14
  2. package/detox/element-types.ts +3 -3
  3. package/detox/expectations.ts +29 -24
  4. package/detox/gestures.ts +16 -16
  5. package/detox/index.ts +34 -32
  6. package/dist-cli/bin.js +4 -4
  7. package/dist-cli/chunks/{agent-HBVXCRJT.js → agent-6P5T2QHC.js} +2 -2
  8. package/dist-cli/chunks/{agent-wrapper-X376DPV2.js → agent-wrapper-SMEMJZXI.js} +2 -2
  9. package/dist-cli/chunks/{app-fonts-LIQTD5RP.js → app-fonts-6OQTLX3U.js} +2 -2
  10. package/dist-cli/chunks/{assert-X6PPLN72.js → assert-ZAYFOW6R.js} +2 -2
  11. package/dist-cli/chunks/{auth-INRWIM2C.js → auth-Y53UANSH.js} +2 -2
  12. package/dist-cli/chunks/beta-ZQCASJ7C.js +2 -0
  13. package/dist-cli/chunks/{camera-LGFHYCJ5.js → camera-AJQWSOO4.js} +2 -2
  14. package/dist-cli/chunks/{chunk-2BQOZATN.js → chunk-2I62CFYI.js} +3 -3
  15. package/dist-cli/chunks/{chunk-E3DLUOFK.js → chunk-34MFG4IM.js} +7 -7
  16. package/dist-cli/chunks/{chunk-J7IFVTWX.js → chunk-4A6HM2K3.js} +1 -1
  17. package/dist-cli/chunks/chunk-4QOY4T27.js +3 -0
  18. package/dist-cli/chunks/{chunk-HRYKZ5YY.js → chunk-6Q2B7QHC.js} +5 -5
  19. package/dist-cli/chunks/{chunk-F5HOYUD2.js → chunk-6U3GMNTP.js} +1 -1
  20. package/dist-cli/chunks/{chunk-RNWJQ4UR.js → chunk-72AQH53U.js} +1 -1
  21. package/dist-cli/chunks/{chunk-NIN75M5H.js → chunk-7HMRWJHH.js} +1 -1
  22. package/dist-cli/chunks/{chunk-YB2LM6VB.js → chunk-7TJVPCQA.js} +6 -6
  23. package/dist-cli/chunks/{chunk-LM544J6V.js → chunk-A5SO4OGE.js} +1 -1
  24. package/dist-cli/chunks/{chunk-D42IRY2Y.js → chunk-AJ3CDBW6.js} +2 -2
  25. package/dist-cli/chunks/chunk-ALE5MU5Z.js +2 -0
  26. package/dist-cli/chunks/{chunk-NHE3YHDU.js → chunk-AVS7RL73.js} +2 -2
  27. package/dist-cli/chunks/chunk-AWF575Y5.js +1 -0
  28. package/dist-cli/chunks/chunk-BHNOPI7I.js +2 -0
  29. package/dist-cli/chunks/{chunk-LCJSTEIR.js → chunk-D2QUTBZP.js} +2 -2
  30. package/dist-cli/chunks/{chunk-ESK7B2BQ.js → chunk-DEVNCWS4.js} +6 -6
  31. package/dist-cli/chunks/{chunk-GUCFICA4.js → chunk-E5FOMYR6.js} +1 -1
  32. package/dist-cli/chunks/{chunk-2XXPF6LP.js → chunk-EFMPSG7T.js} +2 -2
  33. package/dist-cli/chunks/{chunk-4J7BIXEB.js → chunk-EKWOBYJO.js} +2 -2
  34. package/dist-cli/chunks/{chunk-E75EBS77.js → chunk-EPQ5EZBJ.js} +2 -2
  35. package/dist-cli/chunks/{chunk-Q4FB222M.js → chunk-FDSFA7WL.js} +3 -3
  36. package/dist-cli/chunks/{chunk-UGWURWHN.js → chunk-FSKQZHM2.js} +2 -2
  37. package/dist-cli/chunks/{chunk-QWRYD2QV.js → chunk-G42TLJVQ.js} +18 -18
  38. package/dist-cli/chunks/{chunk-HXHB5A6R.js → chunk-JA52F67H.js} +2 -2
  39. package/dist-cli/chunks/chunk-JKZY5CPQ.js +2 -0
  40. package/dist-cli/chunks/{chunk-MG6JE3AM.js → chunk-JV43GSZB.js} +2 -2
  41. package/dist-cli/chunks/{chunk-7L5IKIHC.js → chunk-JWZMAJC7.js} +1 -1
  42. package/dist-cli/chunks/{chunk-F53C5HAB.js → chunk-KIL5F7KD.js} +1 -1
  43. package/dist-cli/chunks/chunk-KY2KLPYL.js +1 -0
  44. package/dist-cli/chunks/{chunk-DB3GMVOH.js → chunk-LBXHG4AU.js} +2 -2
  45. package/dist-cli/chunks/{chunk-SBIAPF6E.js → chunk-MCMMRIJV.js} +1 -1
  46. package/dist-cli/chunks/{chunk-A4BOYB55.js → chunk-MWZOCZ7J.js} +2 -2
  47. package/dist-cli/chunks/{chunk-HXSV263V.js → chunk-NCXHUU7N.js} +1 -1
  48. package/dist-cli/chunks/{chunk-HTVB3FW2.js → chunk-NME4QWJ3.js} +2 -2
  49. package/dist-cli/chunks/{chunk-J2JAOIMN.js → chunk-OETQYAI2.js} +2 -2
  50. package/dist-cli/chunks/chunk-PJBYZZWR.js +2 -0
  51. package/dist-cli/chunks/{chunk-NU755HCE.js → chunk-PNPH4JLS.js} +1 -1
  52. package/dist-cli/chunks/chunk-RT3OS624.js +118 -0
  53. package/dist-cli/chunks/{chunk-7LDHOQ7B.js → chunk-SACWV3LZ.js} +20 -20
  54. package/dist-cli/chunks/chunk-SPJSTRXX.js +24 -0
  55. package/dist-cli/chunks/{chunk-3L5EXWCP.js → chunk-UYLESZU3.js} +1 -1
  56. package/dist-cli/chunks/{chunk-XESYTWFM.js → chunk-WWZL7HNB.js} +29 -29
  57. package/dist-cli/chunks/{chunk-T6MEERRI.js → chunk-ZBJ5JMXM.js} +2 -2
  58. package/dist-cli/chunks/chunk-ZWJEJR73.js +4 -0
  59. package/dist-cli/chunks/cli-version-V4GJYM74.js +2 -0
  60. package/dist-cli/chunks/{compat-MH673TEJ.js → compat-W7E4744D.js} +3 -3
  61. package/dist-cli/chunks/{config-SSCDV5ZJ.js → config-N7G65EY2.js} +2 -2
  62. package/dist-cli/chunks/{control-54R2XDLV.js → control-7VDFEVWU.js} +2 -2
  63. package/dist-cli/chunks/daemon-UI3PQ47F.js +2 -0
  64. package/dist-cli/chunks/{debug-PFP646II.js → debug-ZKUCSCOU.js} +3 -3
  65. package/dist-cli/chunks/{desktop-BPYYJ3EM.js → desktop-L3OXTT45.js} +3 -3
  66. package/dist-cli/chunks/{detox-BIUVHXYH.js → detox-QG4IBZAG.js} +2 -2
  67. package/dist-cli/chunks/{device-BNSPNIP6.js → device-QC6MDI7W.js} +2 -2
  68. package/dist-cli/chunks/{diagnose-BPTDSGOB.js → diagnose-HTUDENJK.js} +2 -2
  69. package/dist-cli/chunks/drivers-L2BXXDI7.js +2 -0
  70. package/dist-cli/chunks/{film-ILA6VSOG.js → film-CT7FHNLE.js} +3 -3
  71. package/dist-cli/chunks/flow-XUBXWJHL.js +2 -0
  72. package/dist-cli/chunks/help-7CIGANJN.js +2 -0
  73. package/dist-cli/chunks/{hidden-runtime-alias-TD7IVAPF.js → hidden-runtime-alias-YTUEPZ3U.js} +2 -2
  74. package/dist-cli/chunks/{home-paths-H36JDTNO.js → home-paths-7K6HDXOP.js} +2 -2
  75. package/dist-cli/chunks/inspect-ZY3QI7VJ.js +2 -0
  76. package/dist-cli/chunks/install-desktop-CVPRYFFV.js +2 -0
  77. package/dist-cli/chunks/{login-5WGZX2ZD.js → login-XHOOXAOW.js} +4 -4
  78. package/dist-cli/chunks/{logout-V53WTVIZ.js → logout-7BISNC5F.js} +2 -2
  79. package/dist-cli/chunks/{maestro-HGKYRD54.js → maestro-YD3G7LSG.js} +3 -3
  80. package/dist-cli/chunks/{maestro-generate-6DNZSKDP.js → maestro-generate-WNOWZC5K.js} +3 -3
  81. package/dist-cli/chunks/{mode-YFMKORE5.js → mode-Y6JJMXU5.js} +2 -2
  82. package/dist-cli/chunks/optional-demo-registry-YUXURWKX.js +2 -0
  83. package/dist-cli/chunks/{perf-EOIGFDWM.js → perf-AY3ZKTDS.js} +2 -2
  84. package/dist-cli/chunks/{record-2F54QS6Y.js → record-ZC4W6QN6.js} +10 -10
  85. package/dist-cli/chunks/runtime-MVYAP3UX.js +2 -0
  86. package/dist-cli/chunks/screenshot-command-NRKTGTSJ.js +151 -0
  87. package/dist-cli/chunks/{screenshots-capture-DIICN24R.js → screenshots-capture-LZR3AHWN.js} +3 -3
  88. package/dist-cli/chunks/{serve-66NC6PPZ.js → serve-4X2WI5XF.js} +5 -5
  89. package/dist-cli/chunks/{setup-ZYN4BTBR.js → setup-KODPGJBJ.js} +3 -3
  90. package/dist-cli/chunks/{skills-MDBIER7U.js → skills-DEAUDOAN.js} +2 -2
  91. package/dist-cli/chunks/{storage-AQ3SEO4Y.js → storage-P7FQRH5T.js} +2 -2
  92. package/dist-cli/chunks/store-PTRXOHHV.js +2 -0
  93. package/dist-cli/chunks/telemetry-JHKOHSI2.js +2 -0
  94. package/dist-cli/chunks/{timeline-VEGHQZ36.js → timeline-7ISYXLR3.js} +2 -2
  95. package/dist-cli/chunks/{upgrade-RNDCRPLJ.js → upgrade-NZBJS5L2.js} +3 -3
  96. package/dist-cli/chunks/upload-J34H5SXV.js +2 -0
  97. package/dist-cli/chunks/{version-XUMPKQUM.js → version-J6BLGLTO.js} +2 -2
  98. package/dist-cli/chunks/{web-ESQGHVPD.js → web-Y6UVYM3Z.js} +2 -2
  99. package/dist-cli/chunks/{what-happened-6NJENKUF.js → what-happened-YKXXY6W2.js} +2 -2
  100. package/dist-lib/agent-daemon-client.cjs +1 -1
  101. package/dist-lib/agent-events.cjs +1 -1
  102. package/dist-lib/agent-identity.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 +2 -2
  106. package/dist-lib/backend-origin.cjs +18 -18
  107. package/dist-lib/beta.cjs +1 -1
  108. package/dist-lib/beta.mjs +1 -1
  109. package/dist-lib/bridge-constants.cjs +4 -4
  110. package/dist-lib/cli-constants.cjs +1 -1
  111. package/dist-lib/config.cjs +1 -1
  112. package/dist-lib/detox/index.cjs +321 -79
  113. package/dist-lib/dev-bundle-resolution.cjs +2 -2
  114. package/dist-lib/home-paths.cjs +1 -1
  115. package/dist-lib/host/bridge-host.cjs +18 -13
  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 +7 -7
  128. package/dist-lib/sdk.cjs +12 -4
  129. package/dist-lib/sdk.mjs +12 -4
  130. package/dist-lib/skills.cjs +425 -169
  131. package/dist-lib/vite.cjs +1 -1
  132. package/package.json +4 -4
  133. package/scripts/dev-server-scanner.ts +5 -5
  134. package/scripts/postinstall.cjs +1 -1
  135. package/scripts/preuninstall.cjs +1 -1
  136. package/skills/{soot → contrast}/SKILL.md +4 -4
  137. package/skills/sootsim-perf/SKILL.md +3 -1
  138. package/src/auth/shared-session.ts +1 -1
  139. package/src/backend-origin.ts +11 -11
  140. package/src/bridge-constants.ts +3 -3
  141. package/src/home-paths.ts +1 -1
  142. package/src/host/agent-host.ts +2 -2
  143. package/src/host/bridge-host.ts +21 -21
  144. package/src/native-dev-bundle-url.ts +3 -3
  145. package/src/runtime-assets.ts +3 -3
  146. package/src/runtime-delivery.ts +10 -4
  147. package/src/screenshots/compose.ts +4 -1
  148. package/src/screenshots/frame-compose.ts +4 -1
  149. package/src/screenshots/orchestrate.ts +7 -2
  150. package/src/vite-plugin-one.ts +3 -3
  151. package/src/vite-plugin.ts +3 -3
  152. package/dist-cli/chunks/beta-WLLSIVLW.js +0 -2
  153. package/dist-cli/chunks/chunk-35EAEAN4.js +0 -24
  154. package/dist-cli/chunks/chunk-44Z2X5R4.js +0 -2
  155. package/dist-cli/chunks/chunk-4BLOZ3AF.js +0 -2
  156. package/dist-cli/chunks/chunk-7K5K5NKB.js +0 -2
  157. package/dist-cli/chunks/chunk-7RWDQCIT.js +0 -1
  158. package/dist-cli/chunks/chunk-BVD2JFOX.js +0 -1
  159. package/dist-cli/chunks/chunk-HBEEYWK5.js +0 -2
  160. package/dist-cli/chunks/chunk-JNUGPBWC.js +0 -118
  161. package/dist-cli/chunks/chunk-KBSJA7HK.js +0 -3
  162. package/dist-cli/chunks/chunk-Z2E2DDIQ.js +0 -4
  163. package/dist-cli/chunks/cli-version-NNBCIQKL.js +0 -2
  164. package/dist-cli/chunks/daemon-GL5GQTWB.js +0 -2
  165. package/dist-cli/chunks/drivers-KBKJVF2Y.js +0 -2
  166. package/dist-cli/chunks/flow-L247VVBM.js +0 -2
  167. package/dist-cli/chunks/help-QIZEANNK.js +0 -2
  168. package/dist-cli/chunks/inspect-6OAVS27G.js +0 -2
  169. package/dist-cli/chunks/install-desktop-LKYAUUQY.js +0 -2
  170. package/dist-cli/chunks/optional-demo-registry-YGNESGBH.js +0 -2
  171. package/dist-cli/chunks/runtime-FYVV4DCQ.js +0 -2
  172. package/dist-cli/chunks/screenshot-command-R535TYXY.js +0 -151
  173. package/dist-cli/chunks/store-6ZGLOTZI.js +0 -2
  174. package/dist-cli/chunks/telemetry-V76UPVDV.js +0 -2
  175. package/dist-cli/chunks/upload-KRBS3Y7Q.js +0 -2
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.227 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.228 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sootsim",
3
- "version": "0.1.227",
3
+ "version": "0.1.228",
4
4
  "description": "sootsim CLI + vite/metro plugins + skills registry. bridge client for driving the proprietary sootsim-engine over WebSocket.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "MIT",
@@ -171,9 +171,9 @@
171
171
  }
172
172
  },
173
173
  "devDependencies": {
174
- "@soot/compat": "workspace:*",
175
- "@soot/sootsim-globals": "workspace:*",
176
- "@soot/sootsim-skills": "workspace:*",
174
+ "@sootsim/compat": "workspace:*",
175
+ "@sootsim/globals": "workspace:*",
176
+ "@sootsim/skills": "workspace:*",
177
177
  "@types/ws": "^8.5.13",
178
178
  "esbuild": "^0.25.0",
179
179
  "sootsim-engine": "workspace:*",
@@ -644,14 +644,14 @@ export interface ScanOptions {
644
644
  buildIconProxyUrl?: (externalUrl: string) => string
645
645
  }
646
646
 
647
- function isSootSelfServer(server: DiscoveredServer): boolean {
647
+ function isSootSimSelfServer(server: DiscoveredServer): boolean {
648
648
  const bundleId = server.bundleId?.trim().toLowerCase()
649
649
  if (bundleId?.startsWith('dev.sootsim.')) return true
650
650
 
651
651
  return false
652
652
  }
653
653
 
654
- export const __isSootSelfServerForTests = isSootSelfServer
654
+ export const __isSootSimSelfServerForTests = isSootSimSelfServer
655
655
 
656
656
  // per-(port, pid) probe cache. as long as the same process still owns the
657
657
  // port, its signature endpoints can't have changed, so we return the cached
@@ -666,10 +666,10 @@ interface PortCacheEntry {
666
666
  }
667
667
  const portCache = new Map<number, PortCacheEntry>()
668
668
 
669
- // negative-cache holds a node/bun port that isn't a bundler (e.g. soot's own
669
+ // negative-cache holds a node/bun port that isn't a bundler (e.g. Contrast's own
670
670
  // api server, zero, postgres, a dev tool). at scan interval 3s and a 1.5s ttl
671
671
  // we used to re-probe every scan, which hits `/` on the port every 3s — that
672
- // waking soot's SSR router ~20x/min was a real memory-leak driver. 30s gives
672
+ // waking Contrast's SSR router ~20x/min was a real memory-leak driver. 30s gives
673
673
  // the scanner a much lighter touch on unrelated node processes while still
674
674
  // catching pid-change invalidation immediately when a process restarts.
675
675
  const NEGATIVE_CACHE_TTL_MS = 30_000
@@ -796,5 +796,5 @@ export async function scanDevServers(
796
796
  if (!livePids.has(pid)) cwdByPid.delete(pid)
797
797
  }
798
798
 
799
- return results.filter((r) => !isSootSelfServer(r))
799
+ return results.filter((r) => !isSootSimSelfServer(r))
800
800
  }
@@ -17,7 +17,7 @@ if (process.env.SOOTSIM_SKIP_POSTINSTALL === '1') {
17
17
  process.exit(0)
18
18
  }
19
19
 
20
- // in dev / workspace installs (i.e. running inside the soot monorepo, not
20
+ // in dev / workspace installs (i.e. running inside the Contrast monorepo, not
21
21
  // installed as a dep), the package dir is `<repo>/packages/sootsim/` rather
22
22
  // than `.../node_modules/sootsim/`. skip the runtime fetch in that case —
23
23
  // the workspace already has the engine source.
@@ -29,7 +29,7 @@ if (process.env.SOOTSIM_SKIP_PREUNINSTALL === '1') {
29
29
  process.exit(0)
30
30
  }
31
31
 
32
- // dev / workspace installs (running inside the soot monorepo, not in a
32
+ // dev / workspace installs (running inside the Contrast monorepo, not in a
33
33
  // node_modules tree) — don't tear anything down. the developer is rebuilding
34
34
  // the workspace, not actually uninstalling.
35
35
  const pkgDir = path.resolve(__dirname, '..')
@@ -1,15 +1,15 @@
1
1
  ---
2
- name: soot
2
+ name: contrast
3
3
  description: >-
4
- index of all Soot and SootSim agent skills and CLI commands.
4
+ index of all Contrast and SootSim agent skills and CLI commands.
5
5
  auto-generated from the CLI info registry — do not edit by hand.
6
6
  ---
7
7
 
8
- # soot
8
+ # contrast
9
9
 
10
10
  overview of all available skills and CLI commands in this repo.
11
11
 
12
- > this file is auto-generated by `bun scripts/generate-soot-skill.ts`.
12
+ > this file is auto-generated by `bun scripts/generate-contrast-skill.ts`.
13
13
  > to update, edit the source registries and re-run the generator.
14
14
 
15
15
  ## sootsim CLI commands
@@ -23,7 +23,9 @@ indict, remeasure — and every wasted week came from skipping a step.
23
23
  browser matters just as much: playwright's bundled headless chromium has
24
24
  NO GPU — CanvasKit falls back to SwiftShader and every number lies high.
25
25
  use `--browser webkit` (real Apple GPU even headless, the iOS proxy) or
26
- GPU-backed Chrome (`channel: 'chrome'`), never `chromium.launch()`.
26
+ GPU-backed Chrome via `launchReapedChrome` from `scripts/lib/reap-browser`,
27
+ never a bare `chromium.launch()`. never `channel: 'chrome'` — that is the
28
+ user's own browser, and automation launching it hijacks their Dock events.
27
29
  2. **machinery silently not engaging is the default failure mode.** the
28
30
  raster tier compiled, gated, and did *nothing* for months — zero
29
31
  promotions on its textbook case — until per-gate rejection counters
@@ -37,7 +37,7 @@ export type SharedDesktopAuthSession = {
37
37
 
38
38
  const SESSION_VERSION = 1 as const
39
39
  const SESSION_FILE_ENV = 'SOOTSIM_SHARED_AUTH_FILE'
40
- const DEFAULT_ORIGIN = 'https://sootbean.com'
40
+ const DEFAULT_ORIGIN = 'https://contrast.dev'
41
41
 
42
42
  function getBaseDir() {
43
43
  const explicit = process.env[SESSION_FILE_ENV]
@@ -1,4 +1,4 @@
1
- const DEFAULT_SOOT_BACKEND_ORIGIN = 'https://sootbean.com'
1
+ const DEFAULT_CONTRAST_BACKEND_ORIGIN = 'https://contrast.dev'
2
2
 
3
3
  function normalizeHostname(hostname: string): string {
4
4
  return hostname.replace(/^\[|\]$/g, '').toLowerCase()
@@ -15,35 +15,35 @@ export function isLoopbackHost(hostname: string): boolean {
15
15
  )
16
16
  }
17
17
 
18
- export function isSootBackendHost(hostname: string): boolean {
18
+ export function isContrastBackendHost(hostname: string): boolean {
19
19
  const normalized = normalizeHostname(hostname)
20
20
  return (
21
21
  isLoopbackHost(normalized) ||
22
- normalized === 'sootbean.com' ||
23
- normalized.endsWith('.sootbean.com')
22
+ normalized === 'contrast.dev' ||
23
+ normalized.endsWith('.contrast.dev')
24
24
  )
25
25
  }
26
26
 
27
- export function isSootBackendOrigin(origin: string): boolean {
27
+ export function isContrastBackendOrigin(origin: string): boolean {
28
28
  try {
29
- return isSootBackendHost(new URL(origin).hostname)
29
+ return isContrastBackendHost(new URL(origin).hostname)
30
30
  } catch {
31
31
  return false
32
32
  }
33
33
  }
34
34
 
35
- export function resolveSootBackendOrigin(currentOrigin?: string | null): string {
35
+ export function resolveContrastBackendOrigin(currentOrigin?: string | null): string {
36
36
  const origin = currentOrigin?.trim()
37
- if (!origin) return DEFAULT_SOOT_BACKEND_ORIGIN
37
+ if (!origin) return DEFAULT_CONTRAST_BACKEND_ORIGIN
38
38
 
39
39
  try {
40
40
  const parsed = new URL(origin)
41
- if (isLoopbackHost(parsed.hostname) || isSootBackendHost(parsed.hostname)) {
41
+ if (isLoopbackHost(parsed.hostname) || isContrastBackendHost(parsed.hostname)) {
42
42
  return parsed.origin
43
43
  }
44
44
  } catch {}
45
45
 
46
- return DEFAULT_SOOT_BACKEND_ORIGIN
46
+ return DEFAULT_CONTRAST_BACKEND_ORIGIN
47
47
  }
48
48
 
49
- export { DEFAULT_SOOT_BACKEND_ORIGIN }
49
+ export { DEFAULT_CONTRAST_BACKEND_ORIGIN }
@@ -42,11 +42,11 @@ export function resolveSootsimBridgePortForHttpPort(input: {
42
42
  return resolveSootsimBridgePort({ portOffset })
43
43
  }
44
44
 
45
- const SOOTBEAN_DEV_HTTP_BASE_PORT = 3000
45
+ const CONTRAST_DEV_HTTP_BASE_PORT = 3000
46
46
  const SOOTSIM_SITE_DEV_HTTP_BASE_PORT = 3001
47
47
  const SOOTSIM_SHELL_DEV_HTTP_BASE_PORT = 5173
48
48
  const LOCAL_DEV_HTTP_BASE_PORTS = [
49
- SOOTBEAN_DEV_HTTP_BASE_PORT,
49
+ CONTRAST_DEV_HTTP_BASE_PORT,
50
50
  SOOTSIM_SHELL_DEV_HTTP_BASE_PORT,
51
51
  ]
52
52
  const MAX_LOCAL_DEV_PORT_OFFSET = 2000
@@ -88,7 +88,7 @@ export function resolveSootsimBridgePortForRuntimeLocation(
88
88
  ) {
89
89
  return resolveSootsimBridgePortForHttpPort({
90
90
  httpPort,
91
- baseHttpPort: SOOTBEAN_DEV_HTTP_BASE_PORT,
91
+ baseHttpPort: CONTRAST_DEV_HTTP_BASE_PORT,
92
92
  })
93
93
  }
94
94
  if (
package/src/home-paths.ts CHANGED
@@ -39,7 +39,7 @@ export function sootsimHomeDir(): string {
39
39
  return path.join(homedir(), '.sootsim')
40
40
  }
41
41
 
42
- // detect when sootsim is running from a source checkout (the soot monorepo)
42
+ // detect when sootsim is running from a source checkout (the Contrast monorepo)
43
43
  // rather than a published npm install. used to skip auto-install of the
44
44
  // persistent launchd / systemd agent: dev shells shouldn't register an agent
45
45
  // whose Program path points at workspace artifacts that change between
@@ -63,7 +63,7 @@ interface PendingPromptEcho {
63
63
  }
64
64
 
65
65
  export interface AgentHostOptions {
66
- /** callback so hosts with a soot-env context (electron, dev middleware)
66
+ /** callback so hosts with a Contrast-env context (electron, dev middleware)
67
67
  * can inject their own exclude list. defaults to the env-derived list
68
68
  * the rest of the repo uses, so `sootsim serve` standalone does the
69
69
  * right thing. */
@@ -79,7 +79,7 @@ export interface AgentCliLeaseSnapshot {
79
79
  expiresAt: number
80
80
  }
81
81
 
82
- /** default excludes keep the dev-server scanner from hitting soot's own
82
+ /** default excludes keep the dev-server scanner from hitting Contrast's own
83
83
  * web / zero / postgres / r2 ports. mirrored from
84
84
  * sootsim-engine/src/dev-scan-excludes.ts — duplicated rather than
85
85
  * imported because sootsim is a dependency of sootsim-engine, not the
@@ -65,12 +65,12 @@ export interface BridgeSimInfo {
65
65
  visibilityState?: string
66
66
  documentFocused?: boolean
67
67
  /** registration "kind" — lets a single daemon host multiple surface
68
- * types. omitted / unknown defaults to 'sootsim'. the sootbean web
69
- * IDE registers with kind='sootbean'; CLI consumers filter by this
68
+ * types. omitted / unknown defaults to 'sootsim'. the contrast web
69
+ * IDE registers with kind='contrast'; CLI consumers filter by this
70
70
  * rather than running a parallel bridge. */
71
71
  kind?: string
72
72
  /** opaque metadata supplied at register time (e.g. projectId, route,
73
- * attached iOS sim id for a sootbean tab). free-form by design — the
73
+ * attached iOS sim id for a contrast tab). free-form by design — the
74
74
  * daemon does not interpret it, only stores + reports it back. */
75
75
  meta?: Record<string, unknown>
76
76
  }
@@ -208,7 +208,7 @@ interface BridgeForwardedCommand {
208
208
  export interface BridgeHostOptions {
209
209
  port?: number
210
210
  openUrl?: (url: string, options?: OpenUrlOptions) => Promise<void> | void
211
- /** soot-specific excludes for the agent host's dev-server scan. passed
211
+ /** Contrast-specific excludes for the agent host's dev-server scan. passed
212
212
  * through to AgentHost; see packages/sootsim-engine/src/dev-scan-excludes.ts
213
213
  * for the canonical list. when omitted, AgentHost reads env vars directly. */
214
214
  agentScanExcludes?: AgentHostOptions['getExcludePorts']
@@ -231,15 +231,15 @@ export interface BridgeHostOptions {
231
231
  * fills in once the vite server is actually listening. only meaningful
232
232
  * with writeDevLockfile. */
233
233
  getShellPort?: () => number | null
234
- /** the sootbean origin this daemon's runtimes should talk to for auth,
234
+ /** the contrast origin this daemon's runtimes should talk to for auth,
235
235
  * billing, and preview uploads — inlined into served runtime html as
236
- * `window.__sootsimSootbeanOrigin`. without it the engine's origin.ts
236
+ * `window.__sootsimContrastOrigin`. without it the engine's origin.ts
237
237
  * resolves the daemon's own loopback host (localhost:<runtimePort>) to
238
238
  * the dev `localhost:3000` stack, so a *prod* CLI user's preview
239
239
  * recording would upload to a localhost stack that doesn't exist. the
240
240
  * `sootsim serve` command resolves this with the same probe the
241
241
  * upload itself uses (`resolveDefaultUploadOrigin`). */
242
- sootbeanOrigin?: string
242
+ contrastOrigin?: string
243
243
  /** override the abandoned-sim GC TTL (ms). defaults to
244
244
  * SIM_IDLE_REAP_TTL_MS (30 min). exists so the reaper integration test
245
245
  * can drive the real timer path deterministically instead of mocking
@@ -302,7 +302,7 @@ const HTTP_MIME_TYPES: Record<string, string> = {
302
302
  * hardcode the 7668 default in `resolveBridgePort` and register on a
303
303
  * *different* daemon (or none), so `sootsim open` times out waiting for
304
304
  * a sim that connected to the wrong bridge.
305
- * - `window.__sootsimSootbeanOrigin` — the sootbean origin for auth /
305
+ * - `window.__sootsimContrastOrigin` — the contrast origin for auth /
306
306
  * billing / preview uploads. the daemon serves runtimes from its own
307
307
  * loopback host, and engine `origin.ts` otherwise resolves any
308
308
  * loopback host to the dev `localhost:3000` stack — so without this a
@@ -311,7 +311,7 @@ const HTTP_MIME_TYPES: Record<string, string> = {
311
311
  export function injectSharedConfigIntoHtml(
312
312
  data: Buffer,
313
313
  bridgePort: number,
314
- sootbeanOrigin: string | null,
314
+ contrastOrigin: string | null,
315
315
  ): string {
316
316
  let payload: string
317
317
  try {
@@ -321,13 +321,13 @@ export function injectSharedConfigIntoHtml(
321
321
  payload = '{}'
322
322
  }
323
323
  const bridgePortTag = bridgePort > 0 ? `window.__sootsimBridgePort=${bridgePort};` : ''
324
- const sootbeanOriginTag = sootbeanOrigin
325
- ? `window.__sootsimSootbeanOrigin=${JSON.stringify(sootbeanOrigin)};`
324
+ const contrastOriginTag = contrastOrigin
325
+ ? `window.__sootsimContrastOrigin=${JSON.stringify(contrastOrigin)};`
326
326
  : ''
327
327
  const tag =
328
328
  `<script>window.__sootsimSharedConfig=${payload};` +
329
329
  bridgePortTag +
330
- sootbeanOriginTag +
330
+ contrastOriginTag +
331
331
  `window.__sootsimCliVersion=${JSON.stringify(getCliVersion())};</script>`
332
332
  const html = data.toString('utf8')
333
333
  if (html.includes('<head>')) return html.replace('<head>', `<head>${tag}`)
@@ -405,7 +405,7 @@ export class SootSimBridgeHost {
405
405
  private shouldWriteLockfile: boolean
406
406
  private shouldWriteDevLockfile: boolean
407
407
  private getShellPort: (() => number | null) | null
408
- private sootbeanOrigin: string | null = null
408
+ private contrastOrigin: string | null = null
409
409
  private effectivePort = 0
410
410
  private startedAt = 0
411
411
  private heartbeatTimer: NodeJS.Timeout | null = null
@@ -462,7 +462,7 @@ export class SootSimBridgeHost {
462
462
  : null
463
463
  },
464
464
  })
465
- this.sootbeanOrigin = opts.sootbeanOrigin?.replace(/\/$/, '') || null
465
+ this.contrastOrigin = opts.contrastOrigin?.replace(/\/$/, '') || null
466
466
  this.simIdleReapTtlMs =
467
467
  opts.simIdleReapTtlMs ?? SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS
468
468
  this.automationSimIdleReapTtlMs =
@@ -708,9 +708,9 @@ export class SootSimBridgeHost {
708
708
 
709
709
  // Browsers always send an Origin header, but the IDE needs a second,
710
710
  // short-lived CLI-role socket to route typed app_* calls to an
711
- // sb-dev-owned external runtime driver. `bridge:hello` is already the
712
- // CLI handshake, so let it correct the provisional Origin-based role
713
- // before this socket has registered a page. This reuses the existing
711
+ // Contrast-dev-owned external runtime driver. `bridge:hello` is
712
+ // already the CLI handshake, so let it correct the provisional
713
+ // Origin-based role before this socket has registered a page. This reuses the existing
714
714
  // daemon transport and call envelope; it does not add a second routing
715
715
  // surface or let a registered sim switch roles mid-connection.
716
716
  if (role === 'sim' && msg.type === 'bridge:hello' && sim && !sim.url) {
@@ -1219,7 +1219,7 @@ export class SootSimBridgeHost {
1219
1219
  private refreshActiveRuntime() {
1220
1220
  this.activeRuntimeVersion = readActiveRuntime()
1221
1221
  // mode boundary (see runtime-assets resolveDevCheckoutRuntimeRoot): inside
1222
- // the soot monorepo dev checkout serve the fresh dev-stack build so local
1222
+ // the Contrast monorepo dev checkout serve the fresh dev-stack build so local
1223
1223
  // engine edits reach previews without a publish; otherwise the installed
1224
1224
  // runtime. the version above stays the installed version for display.
1225
1225
  this.activeRuntimeDirPath = resolveDevCheckoutRuntimeRoot() ?? getActiveRuntimeDir()
@@ -1399,7 +1399,7 @@ export class SootSimBridgeHost {
1399
1399
  // ("render worker crashed during boot" / "app:one surface registration
1400
1400
  // failed"). SAB powers the shell-scene fast channel and the worklet
1401
1401
  // runtime's SharedValues. mirrors sootsim-shell/vite.config.ts (dev) and
1402
- // sootbean.com app/_middleware.ts (prod) so the cli daemon serves the
1402
+ // contrast.dev app/_middleware.ts (prod) so the cli daemon serves the
1403
1403
  // same surface those two already enforce. set via setHeader so subsequent
1404
1404
  // writeHead() calls preserve them (writeHead only overrides keys it
1405
1405
  // explicitly passes). Safari/iOS WebKit does not isolate documents for
@@ -1683,7 +1683,7 @@ export class SootSimBridgeHost {
1683
1683
  return
1684
1684
  }
1685
1685
  res.end(
1686
- injectSharedConfigIntoHtml(data, this.effectivePort, this.sootbeanOrigin),
1686
+ injectSharedConfigIntoHtml(data, this.effectivePort, this.contrastOrigin),
1687
1687
  )
1688
1688
  })
1689
1689
  return
@@ -1714,7 +1714,7 @@ export class SootSimBridgeHost {
1714
1714
  return
1715
1715
  }
1716
1716
  res.end(
1717
- injectSharedConfigIntoHtml(data, this.effectivePort, this.sootbeanOrigin),
1717
+ injectSharedConfigIntoHtml(data, this.effectivePort, this.contrastOrigin),
1718
1718
  )
1719
1719
  })
1720
1720
  return
@@ -13,7 +13,7 @@ function isNativeDevBundlePath(pathname: string): boolean {
13
13
  return pathname.endsWith('.bundle')
14
14
  }
15
15
 
16
- // opt-in (sootbot preview-recording context only): serve a production
16
+ // opt-in (contrastbot preview-recording context only): serve a production
17
17
  // minified bundle instead of the default dev=true unminified one. a
18
18
  // preview run just records the app — it never needs fast-refresh or dev
19
19
  // warnings — and the ~28MB unminified dev bundle cold-(re)boots
@@ -33,7 +33,7 @@ function applyPreviewProdBundle(parsed: URL): void {
33
33
  export function normalizeNativeDevBundleUrl(bundleUrl: string): string {
34
34
  try {
35
35
  const isAbsolute = isAbsoluteHttpUrl(bundleUrl)
36
- const parsed = new URL(bundleUrl, 'http://soot.local')
36
+ const parsed = new URL(bundleUrl, 'http://sootsim.local')
37
37
  parsed.pathname = parsed.pathname.replace(/\.\.bundle$/, '.bundle')
38
38
  if (!isNativeDevBundlePath(parsed.pathname)) return bundleUrl
39
39
  // do NOT force dev=true or minify=false — metro's dev server already
@@ -85,7 +85,7 @@ export function normalizeNativeDevBundleUrl(bundleUrl: string): string {
85
85
  export function applyHotMode(bundleUrl: string, hot: boolean): string {
86
86
  try {
87
87
  const isAbsolute = isAbsoluteHttpUrl(bundleUrl)
88
- const parsed = new URL(bundleUrl, 'http://soot.local')
88
+ const parsed = new URL(bundleUrl, 'http://sootsim.local')
89
89
  if (!isNativeDevBundlePath(parsed.pathname)) return bundleUrl
90
90
  parsed.searchParams.set('hot', hot ? 'true' : 'false')
91
91
  if (isAbsolute) return parsed.toString()
@@ -12,7 +12,7 @@ export const SOOTSIM_RUNTIME_MISSING_MESSAGE =
12
12
 
13
13
  // --- dev-checkout mode boundary --------------------------------------------
14
14
  //
15
- // there is exactly one rule for which engine gets served: INSIDE the soot
15
+ // there is exactly one rule for which engine gets served: INSIDE the Contrast
16
16
  // monorepo dev checkout the fresh dev-stack build (public/sootsim, kept current
17
17
  // by `bun dev`'s watch:sootsim) IS the engine; OUTSIDE it (a published CLI in a
18
18
  // user's project, or an isolated home) the installed runtime IS. this is a mode
@@ -33,7 +33,7 @@ let _monorepoRootCache: string | null | undefined
33
33
  function findMonorepoRoot(): string | null {
34
34
  if (_monorepoRootCache !== undefined) return _monorepoRootCache
35
35
  let dir = path.dirname(fileURLToPath(import.meta.url))
36
- // walk up until we find the soot monorepo: it has packages/sootsim-engine and
36
+ // walk up until we find the Contrast monorepo: it has packages/sootsim-engine and
37
37
  // a public/sootsim dev-build output slot. bounded by the filesystem root.
38
38
  for (let i = 0; i < 12 && dir !== path.dirname(dir); i++) {
39
39
  if (
@@ -49,7 +49,7 @@ function findMonorepoRoot(): string | null {
49
49
  return null
50
50
  }
51
51
 
52
- /** the fresh dev-stack engine build to serve when running inside the soot
52
+ /** the fresh dev-stack engine build to serve when running inside the Contrast
53
53
  * monorepo dev checkout, or null when the installed runtime should serve
54
54
  * (published CLI, packaged electron, or an isolated SOOTSIM_HOME). */
55
55
  export function resolveDevCheckoutRuntimeRoot(): string | null {
@@ -14,7 +14,7 @@ import {
14
14
  writeActiveRuntime,
15
15
  } from './home-paths'
16
16
 
17
- export const DEFAULT_RUNTIME_CDN_ORIGIN = 'https://sootbean.com'
17
+ export const DEFAULT_RUNTIME_CDN_ORIGIN = 'https://contrast.dev'
18
18
  export const RUNTIME_CDN_ORIGIN_ENV = 'SOOTSIM_CDN_ORIGIN'
19
19
  export const RUNTIME_CHANNEL_ENV = 'SOOTSIM_RUNTIME_CHANNEL'
20
20
  export const RUNTIME_PIN_ENV = 'SOOTSIM_RUNTIME_VERSION'
@@ -37,7 +37,7 @@ export interface RuntimeManifest {
37
37
 
38
38
  /** website URL where the sootsim changelog is rendered. the CLI used to drain
39
39
  * a paginated /api/changelog/sootsim endpoint here; the changelog is now a
40
- * static page checked into the soot repo (one MDX file per runtime release
40
+ * static page checked into the Contrast repo (one MDX file per runtime release
41
41
  * under src/features/site/changelog/sootsim-entries/), so `sootsim runtime
42
42
  * notes` points users at the page. */
43
43
  export const SOOTSIM_CHANGELOG_URL = 'https://sootsim.com/changelog'
@@ -137,7 +137,8 @@ export function resolveRuntimeVersion(
137
137
  opts: Pick<RuntimeInstallOptions, 'version' | 'channel'> = {},
138
138
  ): { version: string; channel: string; entry: RuntimeManifestVersion } {
139
139
  const channel = resolveRuntimeChannel(opts.channel)
140
- const version = opts.version || resolveRuntimePin() || manifest.channels[channel]?.latest
140
+ const version =
141
+ opts.version || resolveRuntimePin() || manifest.channels[channel]?.latest
141
142
  if (!version) {
142
143
  throw new Error(
143
144
  `no version specified and channel '${channel}' has no latest entry in the manifest`,
@@ -242,7 +243,12 @@ export async function updateRuntimeToLatest(
242
243
  latestVersion: pin,
243
244
  }
244
245
  }
245
- const install = await installRuntime({ version: pin, channel, cdnOrigin, setActive: false })
246
+ const install = await installRuntime({
247
+ version: pin,
248
+ channel,
249
+ cdnOrigin,
250
+ setActive: false,
251
+ })
246
252
  return {
247
253
  checked: true,
248
254
  updated: true,
@@ -1,5 +1,6 @@
1
1
  import { mkdirSync, readFileSync, writeFileSync } from 'fs'
2
2
  import path from 'path'
3
+ import { launchReapedChrome } from '../../../../scripts/lib/reap-browser'
3
4
  import {
4
5
  DEFAULT_FRAME_SHADOW,
5
6
  toAssetKey,
@@ -346,7 +347,9 @@ export async function composeMarketingScreenshots(
346
347
  browserOverride ??
347
348
  (await (async () => {
348
349
  const { chromium } = await import('playwright')
349
- return chromium.launch({ headless: true })
350
+ return launchReapedChrome((options) => chromium.launch(options), {
351
+ headless: true,
352
+ })
350
353
  })())
351
354
  try {
352
355
  const context = await browser.newContext({ viewport: { width: 1280, height: 720 } })
@@ -8,6 +8,7 @@ import {
8
8
  SIDE_BUTTON_RESERVE,
9
9
  } from 'sootsim-engine/ios/chrome-metrics'
10
10
  import { getDevice, type DeviceModel } from 'sootsim-engine/settings'
11
+ import { launchReapedChrome } from '../../../../scripts/lib/reap-browser'
11
12
 
12
13
  const METALLIC_RING_SHADOW =
13
14
  'inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121'
@@ -363,7 +364,9 @@ export async function composeFramedScreenshot(
363
364
  model: DeviceModel,
364
365
  ): Promise<Buffer> {
365
366
  const { chromium } = await import('playwright')
366
- const browser = await chromium.launch({ headless: true })
367
+ const browser = await launchReapedChrome((options) => chromium.launch(options), {
368
+ headless: true,
369
+ })
367
370
  try {
368
371
  const composer = await createFramedScreenshotComposer(browser)
369
372
  try {
@@ -1,6 +1,7 @@
1
1
  import { mkdirSync, readFileSync, writeFileSync } from 'fs'
2
2
  import { tmpdir } from 'os'
3
3
  import path from 'path'
4
+ import { launchReapedChrome } from '../../../../scripts/lib/reap-browser'
4
5
  import { runFlowPlayback } from '../../cli/commands/flow'
5
6
  import {
6
7
  composeMarketingScreenshots,
@@ -103,7 +104,9 @@ async function buildFramedSources(
103
104
  browserOverride ??
104
105
  (await (async () => {
105
106
  const { chromium } = await import('playwright')
106
- return chromium.launch({ headless: true })
107
+ return launchReapedChrome((options) => chromium.launch(options), {
108
+ headless: true,
109
+ })
107
110
  })())
108
111
  try {
109
112
  const composer = await createFramedScreenshotComposer(browser)
@@ -204,7 +207,9 @@ export async function runScreenshotsPlan(
204
207
  const sharedBrowser = needsSharedBrowser
205
208
  ? await (async () => {
206
209
  const { chromium } = await import('playwright')
207
- return chromium.launch({ headless: true })
210
+ return launchReapedChrome((options) => chromium.launch(options), {
211
+ headless: true,
212
+ })
208
213
  })()
209
214
  : null
210
215
  try {
@@ -18,7 +18,7 @@ import {
18
18
  } from './runtime-assets'
19
19
  import type { Plugin } from 'vite'
20
20
 
21
- export interface SootPluginOptions {
21
+ export interface SootSimPluginOptions {
22
22
  // custom bundle URL (default: auto-detect from One's metro)
23
23
  bundleUrl?: string
24
24
  // path prefix (default: '/__soot')
@@ -27,7 +27,7 @@ export interface SootPluginOptions {
27
27
  enabled?: boolean
28
28
  }
29
29
 
30
- export function sootsimPlugin(options: SootPluginOptions = {}): Plugin[] {
30
+ export function sootsimPlugin(options: SootSimPluginOptions = {}): Plugin[] {
31
31
  if (options.enabled === false) return []
32
32
 
33
33
  const prefix = options.prefix || '/__soot'
@@ -45,7 +45,7 @@ export function sootsimPlugin(options: SootPluginOptions = {}): Plugin[] {
45
45
  // app's bundle) AND window.__sootsimBridgePort. the bridge-port injection
46
46
  // mirrors the dev-stack bridge-host: without it the engine's
47
47
  // resolveBridgePort() falls back to a location-derived guess that mis-maps
48
- // a non-soot app port (the mobile template's :4400 -> 9068) and the sim
48
+ // a non-Contrast app port (the mobile template's :4400 -> 9068) and the sim
49
49
  // can't reach the bridge. resolved per-request from the daemon lockfile
50
50
  // (the CLI's `open` writes/uses it before the shell loads) so the engine
51
51
  // targets the SAME bridge the CLI does; default port otherwise.
@@ -25,7 +25,7 @@ import { shouldApplyWorkletsPlugin, transformWorkletsCode } from './worklets-bab
25
25
 
26
26
  const sootsimPluginRequire = createRequire(import.meta.url)
27
27
 
28
- export interface SootOptions {
28
+ export interface SootSimOptions {
29
29
  // directory of an external RN app to load
30
30
  app?: string
31
31
  // additional source directories to treat as app sources (metro transforms apply)
@@ -39,7 +39,7 @@ const sootsimRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '
39
39
  const workspaceRoot = path.resolve(sootsimRoot, '..', '..')
40
40
  const workspaceNodeModules = path.resolve(workspaceRoot, 'node_modules')
41
41
  const workspaceTamaguiDir = path.resolve(workspaceNodeModules, '@tamagui')
42
- // stubs and the mutable React bridge live in @soot/compat.
42
+ // stubs and the mutable React bridge live in @sootsim/compat.
43
43
  const compatRoot = path.resolve(sootsimRoot, '..', 'compat')
44
44
 
45
45
  // the rendering engine and its shims live in the private sootsim-engine
@@ -235,7 +235,7 @@ function moduleExistsIn(pkgName: string, dir: string): boolean {
235
235
  }
236
236
  }
237
237
 
238
- export function sootsim(options: SootOptions = {}): Plugin[] {
238
+ export function sootsim(options: SootSimOptions = {}): Plugin[] {
239
239
  const appDir = options.app ? path.resolve(options.app) : ''
240
240
  const extraSources = (options.sources || []).map((s) => path.resolve(s))
241
241
  const ownedPackages = new Set([...coreOwnedPackages, ...(options.ownedPackages || [])])
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.227 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d}from"./chunk-SBIAPF6E.js";import"./chunk-F5HOYUD2.js";export{d as BETA_ASK_HEADLINE,b as BETA_LABEL,c as BETA_TAGLINE,a as IS_BETA};
@@ -1,24 +0,0 @@
1
- /*! sootsim v0.1.227 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{c as f}from"./chunk-J7IFVTWX.js";import{a as C,d as x,f as F}from"./chunk-E75EBS77.js";import{M as y,N as w,O as I,P as B}from"./chunk-NU755HCE.js";import{WebSocket as k}from"ws";var S=null;function E(){return S||(S=O(),S)}function O(){let i=w();if(i&&B(i))return{source:"dev-bridge",bridgePort:i.bridgePort,shellBaseUrl:i.shellPort?`http://localhost:${i.shellPort}/`:f};let r=y();return r&&I(r)?{source:"daemon",bridgePort:r.bridgePort,shellBaseUrl:r.runtimePort>0?`http://localhost:${r.runtimePort}/`:f}:{source:"default",bridgePort:7668,shellBaseUrl:f}}function M(i){let r=w();if(r&&B(r)&&r.bridgePort===i)return{source:"dev-bridge",shellBaseUrl:r.shellPort?`http://localhost:${r.shellPort}/`:f};let e=y();return e&&I(e)&&e.bridgePort===i?{source:"daemon",shellBaseUrl:e.runtimePort>0?`http://localhost:${e.runtimePort}/`:f}:null}function J(i){let r;try{let l=new URL(i);r=l.port?Number(l.port):l.protocol==="https:"?443:80}catch{return null}if(!Number.isFinite(r)||r<=0)return null;let e=w();if(e&&B(e)&&(e.shellPort===r||e.runtimePort===r||e.bridgePort===r))return e.bridgePort;let d=y();return d&&I(d)&&(d.runtimePort===r||d.bridgePort===r)?d.bridgePort:null}function U(){return E().bridgePort}function G(i,r){let e=M(i),d=e?.source==="dev-bridge"?"dev bridge":e?.source==="daemon"?"daemon bridge":"bridge",l=e?`${e.source}.json`:"no lockfile",t=r??e?.shellBaseUrl;process.stderr.write(` \u2192 ${d} :${i} (${t?`shell ${t}, `:""}${l})
3
- `)}var T=class extends Error{lock;constructor(r,e){super(r),this.name="BridgeSimLockedError",this.lock=e}};function _(i){return i==="flag"?"via --sim":i==="saved"?"saved via `sootsim use`":"primary fallback \u2014 no sim pinned"}function K(i,r={}){let e=new Set,d=r.port??U(),l=r.commandTimeoutMs??15e3,t,m="none",P=new Set(r.stripBooleanFlags??[]),h=new Set(r.stripValueFlags??[]);for(let n=0;n<i.length;n++){let a=i[n];if(a==="--port"||a==="-p"){e.add(n),n+1<i.length&&(e.add(n+1),d=Number(i[n+1])),n++;continue}if(a.startsWith("--port=")){e.add(n),d=Number(a.slice(7));continue}if(a==="--timeout"){e.add(n),n+1<i.length&&(e.add(n+1),l=Number(i[n+1])),n++;continue}if(a==="--sim"||a==="--session"||a==="--tab"){e.add(n),n+1<i.length&&(e.add(n+1),t=i[n+1]?.trim()||void 0,m="flag"),n++;continue}let s=a.startsWith("--sim=")?a.slice(6):a.startsWith("--session=")?a.slice(10):a.startsWith("--tab=")?a.slice(6):void 0;if(s!==void 0){e.add(n),t=s.trim()||void 0,m="flag";continue}if(P.has(a)){e.add(n);continue}h.has(a)&&(e.add(n),n+1<i.length&&e.add(n+1),n++)}if(!t){let n=x();n&&(t=n.trim()||void 0,m="saved")}return{positional:i.filter((n,a)=>!e.has(a)),wsPort:d,simId:t,simIdSource:m,commandTimeoutMs:l}}function N(i,r={}){let e=1,d=r.commandTimeoutMs??15e3,l=new Map,t=new k(`ws://localhost:${i}`),m=C(),P=new Promise((s,o)=>{t.on("open",()=>{try{t.send(JSON.stringify({type:"bridge:hello",id:0,cliIdentityKey:m.key,cliIdentitySource:m.source,cliLabel:r.cliLabel}))}catch{}s()}),t.on("error",c=>{let g=c.message?`: ${c.message}`:"";o(new Error(`could not connect to ws://localhost:${i}${g}`))})}),h=!1,n=!1;function a(s,o){if(n||process.env.SOOTSIM_QUIET_TARGET_NOTICE==="1"||s.startsWith("bridge:")||s==="focus"||s==="close")return;n=!0;let c=o??"primary",g=_(o?r.simIdSource:"none");process.stderr.write(` \u2192 ${c} (${g})
4
- `)}return t.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&&!h&&(h=!0,process.stderr.write(`
5
- \u26A0 ${o._otherCliCount} other CLI identity/identities are driving this sim
6
- taps, scrolls, and keyboard input from multiple agents will collide on
7
- the same screen state (this is not a bridge throughput limit).
8
- use \`sootsim open --new\` for an isolated sim per agent.
9
-
10
- `)),o.error?o._locked?c.reject(new T(o.error,o._locked)):c.reject(new Error(o.error)):c.resolve(o.result))}),t.on("close",(s,o)=>{let c=o?.toString()||"connection closed";for(let[g,u]of l)l.delete(g),u.reject(new Error(`sim disconnected: ${c} (code ${s})`))}),{async send(s,o){let c=o?.timeoutMs??d,g=async u=>{await P;let b=e++;return new Promise((A,W)=>{let $=setTimeout(()=>{l.delete(b),W(new Error(`command timed out after ${Math.round(c/1e3)}s`))},c);l.set(b,{resolve:v=>{clearTimeout($),A(v)},reject:v=>{clearTimeout($),W(v)}});let p={...s,id:b};p.simId===void 0&&u&&(p.simId=u),a(s.type??"",p.simId),t.send(JSON.stringify(p))})};try{return await g(r.simId)}catch(u){let b=u instanceof Error?u.message:String(u);throw r.simIdSource==="saved"&&r.simId&&s.simId===void 0&&b===`no sim connected with id ${r.simId}`?(F(),new Error(`saved sim ${r.simId} is gone; run \`sootsim list\` and \`sootsim use <sim>\`, or open a fresh sim`)):u}},async listSims(){let s=await this.send({type:"bridge:list-sims"});return Array.isArray(s)?s:[]},async openUrl(s,o={}){return this.send({type:"bridge:open",url:s,newWindow:o.newWindow===!0})},async focusSim(s){return this.send({type:"focus",simId:s})},async closeSim(s){return this.send({type:"close",simId:s})},async claim(s,o={}){return await this.send({type:"bridge:claim",simId:s,force:o.force===!0})},close(){try{t.readyState===k.OPEN&&t.send(JSON.stringify({type:"bridge:bye",id:0}))}catch{}t.close();let s=setTimeout(()=>{t.readyState!==k.CLOSED&&t.terminate()},250)}}}function Q(i){return N(i.wsPort,{commandTimeoutMs:i.commandTimeoutMs,simId:i.simId,simIdSource:i.simIdSource})}function R(i,r){let e=i.filter(t=>t.readyState==="open"&&t.id!==r),d=e.find(t=>t.userFocused)??e.find(t=>t.userVisible===!0&&t.isPrimary)??e.find(t=>t.userVisible===!0)??e.find(t=>t.isPrimary);if(!d)return null;let l=[d.isPrimary?"primary":null,d.userVisible===!1?"hidden":d.userVisible===!0?"visible":null,d.userFocused?"focused":null].filter(Boolean);return`${d.id}${l.length?` [${l.join(", ")}]`:""}`}async function z(i){try{let r=await i.send({type:"evaluate",code:`(() => ({
11
- hidden: document.hidden,
12
- visibilityState: document.visibilityState,
13
- hasFocus: typeof document.hasFocus === 'function' ? document.hasFocus() : null,
14
- simId: window.__sootsimBridge?.id ?? window.SootSim?.state?.simId ?? null,
15
- url: location.href
16
- }))()`}),e=typeof r=="object"&&r!==null?r:{hidden:r===!0};if(e.hidden===!0===!0){let l=null;try{l=R(await i.listSims(),e.simId)}catch{}return process.stderr.write(`
17
- \u26A0 target sim${e.simId?` ${e.simId}`:""} is hidden (document.hidden = true)
18
- `+(e.visibilityState?` visibility: ${e.visibilityState}
19
- `:"")+` animations and rAF callbacks are throttled \u2014 coordinates may be wrong
20
- and launch/transition animations will not complete.
21
- `+(l?` another open sim looks usable: ${l}; target it with --sim.
22
- `:" run `sootsim list` to find the visible sim and target it with --sim.\n")+` page-level window.focus() cannot unhide a browser tab.
23
-
24
- `),{hidden:!0,warned:!0,simId:e.simId}}return{hidden:!1,warned:!1,simId:e.simId}}catch{return{hidden:!1,warned:!1}}}async function X(i,r,e={}){let d={type:"evaluate",code:r};return e.acquireLock&&(d.acquireLock=!0),i.send(d)}async function Y(i,r,...e){return i.send({type:"call",path:r,args:e})}async function Z(i,r,...e){return i.send({type:"call",path:r,args:e,acquireLock:!0})}export{E as a,M as b,J as c,U as d,G as e,T as f,K as g,N as h,Q as i,z as j,X as k,Y as l,Z as m};