sootsim 0.1.177 → 0.1.179

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 (147) hide show
  1. package/dist-cli/bin.js +3 -3
  2. package/dist-cli/chunks/{agent-3BCITLIZ.js → agent-IVX2OKG5.js} +2 -2
  3. package/dist-cli/chunks/{agent-wrapper-26RIZVGD.js → agent-wrapper-ZNK7CWJG.js} +2 -2
  4. package/dist-cli/chunks/{app-fonts-JVDHATQE.js → app-fonts-26YQ2LXF.js} +2 -2
  5. package/dist-cli/chunks/{assert-IT2OXM4Y.js → assert-NJFGETXK.js} +2 -2
  6. package/dist-cli/chunks/beta-ZWCMF2ZB.js +2 -0
  7. package/dist-cli/chunks/{camera-ZYVEUCIO.js → camera-QK33IHK2.js} +2 -2
  8. package/dist-cli/chunks/{chunk-4JESO36F.js → chunk-3EEQRIEH.js} +2 -2
  9. package/dist-cli/chunks/{chunk-Z4IMGLHM.js → chunk-6L3RBC37.js} +2 -2
  10. package/dist-cli/chunks/chunk-6MDXUC6O.js +1 -0
  11. package/dist-cli/chunks/{chunk-NYGESF6F.js → chunk-6NCYDHS5.js} +1 -1
  12. package/dist-cli/chunks/{chunk-IBSEFPPL.js → chunk-6RK5PLS5.js} +1 -1
  13. package/dist-cli/chunks/{chunk-WKG5J4RD.js → chunk-7LNH4A5G.js} +1 -1
  14. package/dist-cli/chunks/{chunk-JS7SSYDG.js → chunk-7N73VST2.js} +2 -2
  15. package/dist-cli/chunks/{chunk-JFLNZGDS.js → chunk-7PDA36Q7.js} +2 -2
  16. package/dist-cli/chunks/{chunk-WRHJEI7Y.js → chunk-B4QYQJYE.js} +1 -1
  17. package/dist-cli/chunks/{chunk-ATVKVVHZ.js → chunk-C2LRNUYZ.js} +2 -2
  18. package/dist-cli/chunks/chunk-CE2THOSL.js +1 -0
  19. package/dist-cli/chunks/{chunk-LTZPVG65.js → chunk-CKSZVH4M.js} +1 -1
  20. package/dist-cli/chunks/{chunk-SNLUVL3H.js → chunk-CWBQ4VR3.js} +2 -2
  21. package/dist-cli/chunks/{chunk-QWZFOMCI.js → chunk-CZJ74QZM.js} +2 -2
  22. package/dist-cli/chunks/{chunk-UJN3FMEX.js → chunk-FVLADGKB.js} +2 -2
  23. package/dist-cli/chunks/{chunk-3L6I2M2Z.js → chunk-GDBCGIDS.js} +3 -3
  24. package/dist-cli/chunks/{chunk-D2BBJUEY.js → chunk-HHBOFGWG.js} +1 -1
  25. package/dist-cli/chunks/{chunk-ZUTVEJVA.js → chunk-HJPQAS3T.js} +3 -3
  26. package/dist-cli/chunks/{chunk-52O56BTW.js → chunk-HOS3HFAX.js} +2 -2
  27. package/dist-cli/chunks/{chunk-YVDSGGOT.js → chunk-IR2KKNHX.js} +1 -1
  28. package/dist-cli/chunks/{chunk-CUO7F2JE.js → chunk-J7K5DKTW.js} +1 -1
  29. package/dist-cli/chunks/{chunk-4INGTBO7.js → chunk-JAKFPOU4.js} +1 -1
  30. package/dist-cli/chunks/{chunk-64QAFSY7.js → chunk-JOTROIZO.js} +1 -1
  31. package/dist-cli/chunks/{chunk-PL3ALTWB.js → chunk-LTM24CWP.js} +2 -2
  32. package/dist-cli/chunks/{chunk-A2WASN2L.js → chunk-ORU4M7HC.js} +1 -1
  33. package/dist-cli/chunks/{chunk-PAU64XFG.js → chunk-PGDHMJ2V.js} +1 -1
  34. package/dist-cli/chunks/{chunk-A3VHHWLU.js → chunk-QSB4XZH5.js} +2 -2
  35. package/dist-cli/chunks/{chunk-CH3MWM5W.js → chunk-R4YLBNCO.js} +1 -1
  36. package/dist-cli/chunks/{chunk-NZWTC6K6.js → chunk-RL3JUMAC.js} +2 -2
  37. package/dist-cli/chunks/{chunk-65ZBQDQM.js → chunk-S3QWJ76W.js} +2 -2
  38. package/dist-cli/chunks/{chunk-CHTYIQLE.js → chunk-SN7SSPO3.js} +2 -2
  39. package/dist-cli/chunks/{chunk-UBJQDMDG.js → chunk-SOYTNR2Q.js} +2 -2
  40. package/dist-cli/chunks/{chunk-WUEKKZ7Z.js → chunk-SRV4YD3I.js} +2 -2
  41. package/dist-cli/chunks/{chunk-NOLQYF76.js → chunk-SZT3HRKL.js} +1 -1
  42. package/dist-cli/chunks/{chunk-SU3JJ7ER.js → chunk-T5CZ7MZK.js} +2 -2
  43. package/dist-cli/chunks/chunk-TPQ4OK4D.js +2 -0
  44. package/dist-cli/chunks/{chunk-C5QOGCVN.js → chunk-UM5XHBTT.js} +2 -2
  45. package/dist-cli/chunks/{chunk-TVFHGWTW.js → chunk-UT76PROO.js} +2 -2
  46. package/dist-cli/chunks/{chunk-4YNKFN2A.js → chunk-VCU44BK4.js} +2 -2
  47. package/dist-cli/chunks/{chunk-Y2637KG7.js → chunk-VLTTKNAU.js} +1 -1
  48. package/dist-cli/chunks/{chunk-JHYLPDCC.js → chunk-VOOUQQET.js} +2 -2
  49. package/dist-cli/chunks/{chunk-JXO6UPGI.js → chunk-WIFE3R5F.js} +1 -1
  50. package/dist-cli/chunks/{chunk-JS3NH2SJ.js → chunk-XL4TROEL.js} +1 -1
  51. package/dist-cli/chunks/{chunk-AN4DM7IB.js → chunk-XMZU4AX3.js} +2 -2
  52. package/dist-cli/chunks/chunk-ZNBHWKKF.js +2 -0
  53. package/dist-cli/chunks/cli-version-SRGEH7HC.js +2 -0
  54. package/dist-cli/chunks/{compat-MNTQH57R.js → compat-CQA2G4YG.js} +3 -3
  55. package/dist-cli/chunks/{control-WQ7XEPCI.js → control-M43MOUBZ.js} +2 -2
  56. package/dist-cli/chunks/{cpu-profile-P27HBXOI.js → cpu-profile-DSDDZ4S4.js} +2 -2
  57. package/dist-cli/chunks/daemon-H3LVJNYI.js +2 -0
  58. package/dist-cli/chunks/{debug-ES4A3SZQ.js → debug-N3EXWDAM.js} +3 -3
  59. package/dist-cli/chunks/{detox-Q36B2553.js → detox-3EB23Z3A.js} +2 -2
  60. package/dist-cli/chunks/{device-NA7TB4E6.js → device-JRVGPK4Q.js} +2 -2
  61. package/dist-cli/chunks/{diagnose-DKW5WI3X.js → diagnose-SVSB7IOM.js} +2 -2
  62. package/dist-cli/chunks/drivers-AUU7FNGZ.js +2 -0
  63. package/dist-cli/chunks/{electron-6C2VDAZW.js → electron-4VQZSCQN.js} +3 -3
  64. package/dist-cli/chunks/flow-NLZNYC5P.js +2 -0
  65. package/dist-cli/chunks/help-F6PU7KE4.js +2 -0
  66. package/dist-cli/chunks/{hints-W7ZZ6KZE.js → hints-6O4UX2OF.js} +2 -2
  67. package/dist-cli/chunks/{home-paths-K4347S7C.js → home-paths-WISVEMCR.js} +2 -2
  68. package/dist-cli/chunks/{inspect-ZPHNFMEX.js → inspect-R4CVXNFC.js} +3 -3
  69. package/dist-cli/chunks/{install-desktop-ZCCPJMOF.js → install-desktop-KP5J5MF5.js} +3 -3
  70. package/dist-cli/chunks/{keys-XM67H4SM.js → keys-WE4GTMF3.js} +2 -2
  71. package/dist-cli/chunks/{login-O4OGJKYL.js → login-TAA3T2YS.js} +4 -4
  72. package/dist-cli/chunks/{logout-DWCBRMLM.js → logout-BV7HYRQJ.js} +2 -2
  73. package/dist-cli/chunks/{maestro-MEWENIGQ.js → maestro-A6YFL7RW.js} +2 -2
  74. package/dist-cli/chunks/optional-demo-registry-I2OXGTLM.js +2 -0
  75. package/dist-cli/chunks/{preview-VPWG4462.js → preview-KHM6EDYR.js} +2 -2
  76. package/dist-cli/chunks/{profile-R4CSGXYJ.js → profile-LBXEFSPL.js} +2 -2
  77. package/dist-cli/chunks/{react-5LFUOYV5.js → react-UXZ4MTPG.js} +2 -2
  78. package/dist-cli/chunks/{record-MHAAYOWF.js → record-O26WY3BX.js} +2 -2
  79. package/dist-cli/chunks/runtime-RRJHC2RA.js +2 -0
  80. package/dist-cli/chunks/{screenshot-XAEO7EBF.js → screenshot-BCCNWCT2.js} +2 -2
  81. package/dist-cli/chunks/{screenshot-mode-QNR5ESKN.js → screenshot-mode-DJI7KC7J.js} +2 -2
  82. package/dist-cli/chunks/{screenshots-Z6OSENKY.js → screenshots-DUZZGRH4.js} +2 -2
  83. package/dist-cli/chunks/{screenshots-capture-3DJPYJUD.js → screenshots-capture-CYVKHWJJ.js} +2 -2
  84. package/dist-cli/chunks/{serve-IVTQFOFI.js → serve-35BEN2TU.js} +2 -2
  85. package/dist-cli/chunks/{setup-AMRSL4IK.js → setup-MEBAPMJT.js} +2 -2
  86. package/dist-cli/chunks/{skills-K4DG2CIH.js → skills-EOMZWEIP.js} +2 -2
  87. package/dist-cli/chunks/{slides-UIH7KXFR.js → slides-RWVSNNUD.js} +2 -2
  88. package/dist-cli/chunks/store-FCLI4TX7.js +2 -0
  89. package/dist-cli/chunks/telemetry-YQWQMXZJ.js +2 -0
  90. package/dist-cli/chunks/{test-XUJ2V5ZX.js → test-KDYWRZJ4.js} +3 -3
  91. package/dist-cli/chunks/{three-mode-P6HSLJMD.js → three-mode-2VUNR3QF.js} +2 -2
  92. package/dist-cli/chunks/{timeline-YSUY4PHV.js → timeline-AZ7DXX6R.js} +2 -2
  93. package/dist-cli/chunks/{upgrade-YZMDFQIH.js → upgrade-F3FAGHHI.js} +2 -2
  94. package/dist-cli/chunks/upload-U5XEPNPJ.js +2 -0
  95. package/dist-cli/chunks/{version-5QAMZ5CK.js → version-74YI73TC.js} +2 -2
  96. package/dist-cli/chunks/{web-LM3JSBQF.js → web-OOEXAXRK.js} +2 -2
  97. package/dist-cli/chunks/{what-happened-NYVQ7KER.js → what-happened-X3RPYIMI.js} +2 -2
  98. package/dist-cli/chunks/{whoami-AAHH72FM.js → whoami-MGM7DDPS.js} +2 -2
  99. package/dist-lib/agent-daemon-client.cjs +1 -1
  100. package/dist-lib/agent-events.cjs +1 -1
  101. package/dist-lib/agent-sessions.cjs +1 -1
  102. package/dist-lib/attached-projects.cjs +1 -1
  103. package/dist-lib/auth/shared-session.cjs +1 -1
  104. package/dist-lib/backend-origin.cjs +1 -1
  105. package/dist-lib/beta.cjs +1 -1
  106. package/dist-lib/beta.mjs +1 -1
  107. package/dist-lib/bridge-constants.cjs +1 -1
  108. package/dist-lib/cli-constants.cjs +1 -1
  109. package/dist-lib/config.cjs +1 -1
  110. package/dist-lib/detox/index.cjs +1 -1
  111. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  112. package/dist-lib/home-paths.cjs +1 -1
  113. package/dist-lib/host/bridge-host.cjs +1 -1
  114. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  115. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  116. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  117. package/dist-lib/host/websocket-proxy.cjs +1 -1
  118. package/dist-lib/index.cjs +64 -57
  119. package/dist-lib/jump-to-source-babel.cjs +1 -1
  120. package/dist-lib/menu.cjs +10 -3
  121. package/dist-lib/menu.mjs +10 -3
  122. package/dist-lib/metro.cjs +1 -1
  123. package/dist-lib/profiles.cjs +1 -1
  124. package/dist-lib/render-mode.cjs +1 -1
  125. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  126. package/dist-lib/sdk.cjs +1 -1
  127. package/dist-lib/sdk.mjs +1 -1
  128. package/dist-lib/skills.cjs +14 -1
  129. package/dist-lib/vite.cjs +64 -54
  130. package/package.json +1 -1
  131. package/src/menu.ts +10 -2
  132. package/src/vite-plugin-one.ts +63 -63
  133. package/dist-cli/chunks/beta-SPH73CAA.js +0 -2
  134. package/dist-cli/chunks/chunk-B6GISAUX.js +0 -1
  135. package/dist-cli/chunks/chunk-BTTZN2SN.js +0 -2
  136. package/dist-cli/chunks/chunk-DGDBEXXQ.js +0 -1
  137. package/dist-cli/chunks/chunk-YU6CNUJD.js +0 -2
  138. package/dist-cli/chunks/cli-version-HENS6BZI.js +0 -2
  139. package/dist-cli/chunks/daemon-WUAZELEI.js +0 -2
  140. package/dist-cli/chunks/drivers-RFOOGIRC.js +0 -2
  141. package/dist-cli/chunks/flow-GSHP52QS.js +0 -2
  142. package/dist-cli/chunks/help-J6PF4PZX.js +0 -2
  143. package/dist-cli/chunks/optional-demo-registry-O3XS3WXJ.js +0 -2
  144. package/dist-cli/chunks/runtime-R2PRKIZM.js +0 -2
  145. package/dist-cli/chunks/store-2JY2VLVA.js +0 -2
  146. package/dist-cli/chunks/telemetry-KNKROOT5.js +0 -2
  147. package/dist-cli/chunks/upload-TIH2LID6.js +0 -2
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.179 | (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;
@@ -39,9 +39,8 @@ module.exports = __toCommonJS(vite_plugin_one_exports);
39
39
  var import_fs2 = __toESM(require("fs"), 1);
40
40
  var import_path2 = __toESM(require("path"), 1);
41
41
 
42
- // src/runtime-assets.ts
43
- var import_fs = __toESM(require("fs"), 1);
44
- var import_path = __toESM(require("path"), 1);
42
+ // src/bridge-constants.ts
43
+ var DEFAULT_SOOTSIM_BRIDGE_PORT = 7668;
45
44
 
46
45
  // src/home-paths.ts
47
46
  var import_node_fs = __toESM(require("node:fs"), 1);
@@ -49,6 +48,8 @@ var import_node_os = require("node:os");
49
48
  var import_node_path = __toESM(require("node:path"), 1);
50
49
  var SOOTSIM_HOME_ENV = "SOOTSIM_HOME";
51
50
  var ACTIVE_RUNTIME_FILE = "active";
51
+ var DAEMON_LOCKFILE = "daemon.json";
52
+ var DAEMON_HEARTBEAT_STALE_MS = 3e4;
52
53
  function sootsimHomeDir() {
53
54
  const override = process.env[SOOTSIM_HOME_ENV];
54
55
  if (override && override.length > 0) return import_node_path.default.resolve(override);
@@ -63,6 +64,9 @@ function runtimeDir(version) {
63
64
  function activeRuntimeFile() {
64
65
  return import_node_path.default.join(runtimesDir(), ACTIVE_RUNTIME_FILE);
65
66
  }
67
+ function daemonLockfilePath() {
68
+ return import_node_path.default.join(sootsimHomeDir(), DAEMON_LOCKFILE);
69
+ }
66
70
  function readActiveRuntime() {
67
71
  try {
68
72
  const value = import_node_fs.default.readFileSync(activeRuntimeFile(), "utf8").trim();
@@ -72,8 +76,39 @@ function readActiveRuntime() {
72
76
  }
73
77
  }
74
78
  var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
79
+ function readDaemonLockfile() {
80
+ try {
81
+ const fd = import_node_fs.default.openSync(daemonLockfilePath(), "r");
82
+ try {
83
+ const buf = Buffer.alloc(DAEMON_LOCKFILE_MAX_BYTES);
84
+ const bytesRead = import_node_fs.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
85
+ const raw = buf.subarray(0, bytesRead).toString("utf8");
86
+ const parsed = JSON.parse(raw);
87
+ if (parsed && parsed.schema === 1 && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number") {
88
+ return parsed;
89
+ }
90
+ return null;
91
+ } finally {
92
+ import_node_fs.default.closeSync(fd);
93
+ }
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
98
+ function isDaemonLockfileFresh(lock, now = Date.now()) {
99
+ if (!lock) return false;
100
+ if (now - lock.heartbeatAt > DAEMON_HEARTBEAT_STALE_MS) return false;
101
+ try {
102
+ process.kill(lock.pid, 0);
103
+ return true;
104
+ } catch {
105
+ return false;
106
+ }
107
+ }
75
108
 
76
109
  // src/runtime-assets.ts
110
+ var import_fs = __toESM(require("fs"), 1);
111
+ var import_path = __toESM(require("path"), 1);
77
112
  var SOOTSIM_RUNTIME_MISSING_MESSAGE = "[sootsim] no engine runtime installed \u2014 run `sootsim setup`, or `sootsim runtime install`";
78
113
  var MIME_TYPES = {
79
114
  ".js": "application/javascript",
@@ -139,7 +174,6 @@ function serveRuntimeFile(res, fullPath) {
139
174
  }
140
175
 
141
176
  // src/vite-plugin-one.ts
142
- var sootsimRoot = import_path2.default.resolve(import_path2.default.dirname(new URL(__sootsim_import_meta_url).pathname), "..");
143
177
  function sootsimPlugin(options = {}) {
144
178
  if (options.enabled === false) return [];
145
179
  const prefix = options.prefix || "/__soot";
@@ -148,6 +182,13 @@ function sootsimPlugin(options = {}) {
148
182
  name: "sootsim-one",
149
183
  configureServer(server) {
150
184
  const bundleUrl = options.bundleUrl || "/node_modules/one/metro-entry.bundle?platform=ios&dev=true&minify=false";
185
+ const buildShellHtml = (runtimeRoot) => {
186
+ const html = import_fs2.default.readFileSync(import_path2.default.join(runtimeRoot, "index.html"), "utf8");
187
+ const lock = readDaemonLockfile();
188
+ const bridgePort = lock && isDaemonLockfileFresh(lock) && lock.bridgePort > 0 ? lock.bridgePort : DEFAULT_SOOTSIM_BRIDGE_PORT;
189
+ const inject = `<script>(function(){var u=new URL(location.href);if(!u.searchParams.has('bundle'))u.searchParams.set('bundle',${JSON.stringify(bundleUrl)});window.__sootsimBridgePort=${bridgePort};history.replaceState(null,'','${prefix}/'+u.search)})()</script>`;
190
+ return html.replace("</head>", inject + "</head>");
191
+ };
151
192
  server.middlewares.use((req, res, next) => {
152
193
  const origWriteHead = res.writeHead.bind(res);
153
194
  res.writeHead = function(statusCode, ...args) {
@@ -164,6 +205,22 @@ function sootsimPlugin(options = {}) {
164
205
  };
165
206
  next();
166
207
  });
208
+ server.middlewares.use((req, res, next) => {
209
+ if ((req.url || "").split("?")[0] !== "/__server-scan") return next();
210
+ const scanPort = server.config.server.port || 8081;
211
+ const absoluteBundleUrl = bundleUrl.startsWith("http") ? bundleUrl : `http://localhost:${scanPort}${bundleUrl}`;
212
+ res.setHeader("content-type", "application/json");
213
+ res.end(
214
+ JSON.stringify([
215
+ {
216
+ port: scanPort,
217
+ framework: "one",
218
+ bundleUrl: absoluteBundleUrl,
219
+ lastSeen: Date.now()
220
+ }
221
+ ])
222
+ );
223
+ });
167
224
  server.middlewares.use((req, res, next) => {
168
225
  const url = req.url || "";
169
226
  const pathname = url.split("?")[0];
@@ -185,14 +242,8 @@ function sootsimPlugin(options = {}) {
185
242
  }
186
243
  }
187
244
  if (pathname === prefix || pathname === prefix + "/") {
188
- const htmlPath = import_path2.default.join(runtimeRoot, "index.html");
189
- let html = import_fs2.default.readFileSync(htmlPath, "utf8");
190
- html = html.replace(
191
- "</head>",
192
- `<script>history.replaceState(null,'','${prefix}/?bundle=${encodeURIComponent(bundleUrl)}')</script></head>`
193
- );
194
245
  res.setHeader("content-type", "text/html");
195
- res.end(html);
246
+ res.end(buildShellHtml(runtimeRoot));
196
247
  return;
197
248
  }
198
249
  if (pathname.startsWith(prefix + "/")) {
@@ -206,14 +257,8 @@ function sootsimPlugin(options = {}) {
206
257
  }
207
258
  const ext = import_path2.default.extname(pathname);
208
259
  if (!ext) {
209
- const htmlPath = import_path2.default.join(runtimeRoot, "index.html");
210
- let html = import_fs2.default.readFileSync(htmlPath, "utf8");
211
- html = html.replace(
212
- "</head>",
213
- `<script>history.replaceState(null,'','${prefix}/?bundle=${encodeURIComponent(bundleUrl)}')</script></head>`
214
- );
215
260
  res.setHeader("content-type", "text/html");
216
- res.end(html);
261
+ res.end(buildShellHtml(runtimeRoot));
217
262
  return;
218
263
  }
219
264
  }
@@ -222,45 +267,10 @@ function sootsimPlugin(options = {}) {
222
267
  const port = server.config.server.port || 8081;
223
268
  const sootsimUrl = `http://localhost:${port}${prefix}/`;
224
269
  console.log(`[sootsim] serving at ${sootsimUrl}`);
225
- if (options.open !== false) {
226
- openElectronApp(sootsimUrl);
227
- }
228
270
  }
229
271
  }
230
272
  ];
231
273
  }
232
- async function openElectronApp(sootsimUrl) {
233
- if (process.platform !== "darwin") return;
234
- const { execSync, exec } = await import("child_process");
235
- const schemeUrl = `sootsim://dev?url=${encodeURIComponent(sootsimUrl)}`;
236
- try {
237
- exec(`open "${schemeUrl}"`);
238
- return;
239
- } catch {
240
- }
241
- const candidates = [
242
- "/Applications/sootsim.app",
243
- import_path2.default.join(process.env.HOME || "", "Applications/sootsim.app"),
244
- import_path2.default.join(sootsimRoot, "release/mac-arm64/sootsim.app")
245
- ];
246
- let appPath = candidates.find((p) => import_fs2.default.existsSync(p));
247
- if (!appPath) {
248
- try {
249
- const found = execSync(
250
- 'mdfind "kMDItemCFBundleIdentifier == dev.sootsim.simulator"',
251
- { encoding: "utf8", timeout: 3e3 }
252
- ).trim();
253
- if (found) appPath = found.split("\n")[0];
254
- } catch {
255
- }
256
- }
257
- if (appPath) {
258
- try {
259
- exec(`open -a "${appPath}" "${sootsimUrl}"`);
260
- } catch {
261
- }
262
- }
263
- }
264
274
  var vite_plugin_one_default = sootsimPlugin;
265
275
  // Annotate the CommonJS export names for ESM import in node:
266
276
  0 && (module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sootsim",
3
- "version": "0.1.177",
3
+ "version": "0.1.179",
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",
package/src/menu.ts CHANGED
@@ -38,6 +38,7 @@ export interface SootSimMenuState {
38
38
  showTopBar: boolean
39
39
  screenshotMode: boolean
40
40
  threeMode: boolean
41
+ alwaysShowLiveWebViews: boolean
41
42
  stayOnTop: boolean
42
43
  scaleMode: SootSimScaleMode
43
44
  }
@@ -83,7 +84,7 @@ export function buildSootSimMenuDefs(
83
84
  fileMenu(state, deviceChoices),
84
85
  editMenu(),
85
86
  deviceMenu(state, deviceChoices),
86
- debugMenu(),
87
+ debugMenu(state),
87
88
  windowMenu(state),
88
89
  helpMenu(),
89
90
  ]
@@ -227,7 +228,7 @@ function deviceMenu(
227
228
  }
228
229
  }
229
230
 
230
- function debugMenu(): SootSimMenuDef {
231
+ function debugMenu(state: SootSimMenuState): SootSimMenuDef {
231
232
  return {
232
233
  label: 'Debug',
233
234
  items: [
@@ -254,6 +255,13 @@ function debugMenu(): SootSimMenuDef {
254
255
  showInShortcutDocs: true,
255
256
  },
256
257
  { type: 'separator' },
258
+ {
259
+ label: 'Always Show Live WebViews',
260
+ type: 'checkbox',
261
+ checked: state.alwaysShowLiveWebViews,
262
+ action: 'toggle-live-webviews',
263
+ },
264
+ { type: 'separator' },
257
265
  {
258
266
  label: 'Clear Cache and Reload',
259
267
  accelerator: 'CmdOrCtrl+Shift+R',
@@ -7,6 +7,8 @@
7
7
 
8
8
  import fs from 'fs'
9
9
  import path from 'path'
10
+ import { DEFAULT_SOOTSIM_BRIDGE_PORT } from './bridge-constants'
11
+ import { isDaemonLockfileFresh, readDaemonLockfile } from './home-paths'
10
12
  import {
11
13
  isRootRuntimeAssetPath,
12
14
  resolveActiveRuntimeRoot,
@@ -16,8 +18,6 @@ import {
16
18
  } from './runtime-assets'
17
19
  import type { Plugin } from 'vite'
18
20
 
19
- const sootsimRoot = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..')
20
-
21
21
  export interface SootPluginOptions {
22
22
  // custom bundle URL (default: auto-detect from One's metro)
23
23
  bundleUrl?: string
@@ -25,8 +25,6 @@ export interface SootPluginOptions {
25
25
  prefix?: string
26
26
  // disable sootsim
27
27
  enabled?: boolean
28
- // open the desktop app after the dev server starts (default true)
29
- open?: boolean
30
28
  }
31
29
 
32
30
  export function sootsimPlugin(options: SootPluginOptions = {}): Plugin[] {
@@ -43,6 +41,36 @@ export function sootsimPlugin(options: SootPluginOptions = {}): Plugin[] {
43
41
  options.bundleUrl ||
44
42
  '/node_modules/one/metro-entry.bundle?platform=ios&dev=true&minify=false'
45
43
 
44
+ // build the shell HTML, injecting the bundle URL (so main.tsx loads this
45
+ // app's bundle) AND window.__sootsimBridgePort. the bridge-port injection
46
+ // mirrors the dev-stack bridge-host: without it the engine's
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
49
+ // can't reach the bridge. resolved per-request from the daemon lockfile
50
+ // (the CLI's `open` writes/uses it before the shell loads) so the engine
51
+ // targets the SAME bridge the CLI does; default port otherwise.
52
+ const buildShellHtml = (runtimeRoot: string): string => {
53
+ const html = fs.readFileSync(path.join(runtimeRoot, 'index.html'), 'utf8')
54
+ const lock = readDaemonLockfile()
55
+ const bridgePort =
56
+ lock && isDaemonLockfileFresh(lock) && lock.bridgePort > 0
57
+ ? lock.bridgePort
58
+ : DEFAULT_SOOTSIM_BRIDGE_PORT
59
+ // inject the bridge port + a default bundle (only when the URL has none,
60
+ // so the CLI's resolved bundle wins), and PRESERVE the existing query.
61
+ // preserving the query is essential: `sootsim open` stamps the open URL
62
+ // with `inspectOpen=<token>` and matches the registered sim by that
63
+ // token (waitForSimMatch). the old code forced `?bundle=` only and
64
+ // stripped inspectOpen, so the sim registered but never matched and
65
+ // `open` timed out after 60s.
66
+ const inject =
67
+ `<script>(function(){var u=new URL(location.href);` +
68
+ `if(!u.searchParams.has('bundle'))u.searchParams.set('bundle',${JSON.stringify(bundleUrl)});` +
69
+ `window.__sootsimBridgePort=${bridgePort};` +
70
+ `history.replaceState(null,'','${prefix}/'+u.search)})()</script>`
71
+ return html.replace('</head>', inject + '</head>')
72
+ }
73
+
46
74
  // mirror Set-Cookie into a readable header for sootsim's fetch wrapper
47
75
  server.middlewares.use((req, res, next) => {
48
76
  const origWriteHead = res.writeHead.bind(res)
@@ -63,6 +91,34 @@ export function sootsimPlugin(options: SootPluginOptions = {}): Plugin[] {
63
91
  next()
64
92
  })
65
93
 
94
+ // serve a minimal /__server-scan describing THIS vite dev server, so a
95
+ // sootsim shell loaded from <port>/__soot can resolve this app's native
96
+ // bundle. dev-bundle-resolution's resolvePortViaServerScan fetches
97
+ // `/__server-scan` RELATIVE to the shell origin; when the shell is loaded
98
+ // from this target origin, that hits here. without it the request SPA-
99
+ // falls-back to 404 and the bundle never resolves (sootsim open hangs).
100
+ // we describe only this server (the shell drives THIS app) — no localhost-
101
+ // wide scan, so the published plugin pulls in no shell-only scanner
102
+ // internals. shape matches DiscoveredServer enough for the resolver.
103
+ server.middlewares.use((req, res, next) => {
104
+ if ((req.url || '').split('?')[0] !== '/__server-scan') return next()
105
+ const scanPort = server.config.server.port || 8081
106
+ const absoluteBundleUrl = bundleUrl.startsWith('http')
107
+ ? bundleUrl
108
+ : `http://localhost:${scanPort}${bundleUrl}`
109
+ res.setHeader('content-type', 'application/json')
110
+ res.end(
111
+ JSON.stringify([
112
+ {
113
+ port: scanPort,
114
+ framework: 'one',
115
+ bundleUrl: absoluteBundleUrl,
116
+ lastSeen: Date.now(),
117
+ },
118
+ ]),
119
+ )
120
+ })
121
+
66
122
  server.middlewares.use((req, res, next) => {
67
123
  const url = req.url || ''
68
124
  const pathname = url.split('?')[0]
@@ -92,17 +148,10 @@ export function sootsimPlugin(options: SootPluginOptions = {}): Plugin[] {
92
148
  }
93
149
  }
94
150
 
95
- // serve the sootsim HTML shell — inject bundle URL
151
+ // serve the sootsim HTML shell — inject bundle URL + bridge port
96
152
  if (pathname === prefix || pathname === prefix + '/') {
97
- const htmlPath = path.join(runtimeRoot, 'index.html')
98
- let html = fs.readFileSync(htmlPath, 'utf8')
99
- // inject bundle URL as a query param so main.tsx picks it up
100
- html = html.replace(
101
- '</head>',
102
- `<script>history.replaceState(null,'','${prefix}/?bundle=${encodeURIComponent(bundleUrl)}')</script></head>`,
103
- )
104
153
  res.setHeader('content-type', 'text/html')
105
- res.end(html)
154
+ res.end(buildShellHtml(runtimeRoot))
106
155
  return
107
156
  }
108
157
 
@@ -120,14 +169,8 @@ export function sootsimPlugin(options: SootPluginOptions = {}): Plugin[] {
120
169
  // extensionless in-shell routes should still load the shell.
121
170
  const ext = path.extname(pathname)
122
171
  if (!ext) {
123
- const htmlPath = path.join(runtimeRoot, 'index.html')
124
- let html = fs.readFileSync(htmlPath, 'utf8')
125
- html = html.replace(
126
- '</head>',
127
- `<script>history.replaceState(null,'','${prefix}/?bundle=${encodeURIComponent(bundleUrl)}')</script></head>`,
128
- )
129
172
  res.setHeader('content-type', 'text/html')
130
- res.end(html)
173
+ res.end(buildShellHtml(runtimeRoot))
131
174
  return
132
175
  }
133
176
  }
@@ -135,55 +178,12 @@ export function sootsimPlugin(options: SootPluginOptions = {}): Plugin[] {
135
178
  next()
136
179
  })
137
180
 
138
- // try to open sootsim electron app
139
181
  const port = server.config.server.port || 8081
140
182
  const sootsimUrl = `http://localhost:${port}${prefix}/`
141
183
  console.log(`[sootsim] serving at ${sootsimUrl}`)
142
-
143
- if (options.open !== false) {
144
- openElectronApp(sootsimUrl)
145
- }
146
184
  },
147
185
  },
148
186
  ]
149
187
  }
150
188
 
151
- // try to open the sootsim electron app via URL scheme or direct launch
152
- async function openElectronApp(sootsimUrl: string) {
153
- if (process.platform !== 'darwin') return
154
-
155
- const { execSync, exec } = await import('child_process')
156
-
157
- // try sootsim:// scheme first (works if app registered the protocol)
158
- const schemeUrl = `sootsim://dev?url=${encodeURIComponent(sootsimUrl)}`
159
- try {
160
- exec(`open "${schemeUrl}"`)
161
- return
162
- } catch {}
163
-
164
- // fallback: find the app directly
165
- const candidates = [
166
- '/Applications/sootsim.app',
167
- path.join(process.env.HOME || '', 'Applications/sootsim.app'),
168
- path.join(sootsimRoot, 'release/mac-arm64/sootsim.app'),
169
- ]
170
-
171
- let appPath = candidates.find((p) => fs.existsSync(p))
172
- if (!appPath) {
173
- try {
174
- const found = execSync(
175
- 'mdfind "kMDItemCFBundleIdentifier == dev.sootsim.simulator"',
176
- { encoding: 'utf8', timeout: 3000 },
177
- ).trim()
178
- if (found) appPath = found.split('\n')[0]
179
- } catch {}
180
- }
181
-
182
- if (appPath) {
183
- try {
184
- exec(`open -a "${appPath}" "${sootsimUrl}"`)
185
- } catch {}
186
- }
187
- }
188
-
189
189
  export default sootsimPlugin
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d}from"./chunk-JS3NH2SJ.js";import"./chunk-64QAFSY7.js";export{d as BETA_ASK_HEADLINE,b as BETA_LABEL,c as BETA_TAGLINE,a as IS_BETA};
@@ -1 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{h as w,j as u,k as m,l}from"./chunk-NZWTC6K6.js";var p="sootsim:settings",v=["errorReporting","colorScheme","a11yMode","a11yDepth","screenshotCanvas","screenshotBackground","screenshotText","screenshotPose","screenshotDynamicSize","agentProvider","onboardingComplete","betaConsentVersion","detailedTelemetry"];function S(){if(typeof window>"u")return null;let e=window.sootsimElectron;return e&&typeof e=="object"?e:null}function g(e){let t={};for(let n of v){if(!(n in e))continue;let r=e[n],o=u[n];o.validate&&!o.validate(r)||o.options&&!o.options.includes(r)||(t[n]=r)}return t}function h(e){let t={};for(let n of v)t[n]=e[n];return t}function _(){if(typeof localStorage>"u")return{};try{let e=localStorage.getItem(p);return e?g(JSON.parse(e)):{}}catch{return{}}}function V(e){if(!(typeof localStorage>"u"))try{localStorage.setItem(p,JSON.stringify(h(e)))}catch{}}function E(){let t=S()?.sharedConfig?.settings;return!t||typeof t!="object"?{}:g(t)}function K(e){let t=S();if(t?.writeSharedConfig)try{t.writeSharedConfig({settings:h(e)})}catch{}}function k(){if(typeof window>"u")return null;let e=window.__sootsimSharedConfig;return e&&typeof e=="object"?e:null}function j(){let e=k()?.settings;return!e||typeof e!="object"?{}:g(e)}function D(e){if(!k())return;let t={settings:h(e)};try{if(globalThis.__sootsimBridgeRequest?.writeSharedConfig?.(t))return}catch{}if(!(typeof fetch>"u"))try{fetch("/__sootsim/shared-config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:!0}).catch(()=>{})}catch{}}function b(){let e=_(),t=j(),n=E();return{...e,...t,...n}}function R(e){V(e),K(e),D(e)}function C(e){if(typeof window>"u")return()=>{};let t=i=>{if(!(i.key!==p||i.newValue==null))try{e(g(JSON.parse(i.newValue)))}catch{}};window.addEventListener("storage",t);let n=S(),r;n?.onSharedConfigChanged&&(r=n.onSharedConfigChanged(i=>{let d=i?.settings;!d||typeof d!="object"||e(g(d))}));let c=globalThis.__sootsimBridgeRequest?.subscribeSharedConfig?.(i=>{let d=i?.settings;!d||typeof d!="object"||e(g(d))});return()=>{window.removeEventListener("storage",t),r?.(),c?.()}}var M=l(),P=b();for(let e of Object.keys(m()))delete P[e];var s={...M,...P},f=[],a=null;function y(){for(let e of f)e();R(s)}C(e=>{let t={...s},n=!1;for(let[r,o]of Object.entries(e)){let c=r;t[c]!==o&&(t[c]=o,n=!0)}if(n){s=t,a=null;for(let r of f)r()}});var L={get(e){return s[e]},set(e,t){let n=u[e];n.validate&&!n.validate(t)||n.options&&!n.options.includes(t)||s[e]!==t&&(s={...s,[e]:t},e==="deviceModel"&&(a=null),y())},getAll(){return s},apply(e){let t=!1,n={...s};for(let[r,o]of Object.entries(e)){if(o===void 0)continue;let c=r,i=u[c];i&&(i.validate&&!i.validate(o)||i.options&&!i.options.includes(o)||n[c]!==o&&(n[c]=o,t=!0))}t&&(s=n,a=null,y())},reset(){s=l(),a=null,y()},subscribe(e){return f.push(e),()=>{f=f.filter(t=>t!==e)}},getDeviceSpec(){return a||(a=w(s.deviceModel)),a},getA11yMode(){return s.a11yMode},setA11yMode(e){this.set("a11yMode",e)},getInspectMode(){return s.inspectMode},setInspectMode(e){this.set("inspectMode",e)}};export{L as a};
@@ -1 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- var t="http://localhost:5173/";export{t as a};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a}from"./chunk-CUO7F2JE.js";import"./chunk-64QAFSY7.js";export{a as getCliVersion};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c,d,e}from"./chunk-TVFHGWTW.js";import"./chunk-SNLUVL3H.js";import"./chunk-UBJQDMDG.js";import"./chunk-ATVKVVHZ.js";import"./chunk-4YNKFN2A.js";import"./chunk-A2WASN2L.js";import"./chunk-AN4DM7IB.js";import"./chunk-CHTYIQLE.js";import"./chunk-YU6CNUJD.js";import"./chunk-WKG5J4RD.js";import"./chunk-4INGTBO7.js";import"./chunk-IBSEFPPL.js";import"./chunk-CUO7F2JE.js";import"./chunk-JS3NH2SJ.js";import"./chunk-NZWTC6K6.js";import"./chunk-64QAFSY7.js";export{c as daemonInstall,b as getDaemonServiceStatus,a as runDaemon,d as teardownDaemonService,e as teardownSootsimHome};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import"./chunk-DGDBEXXQ.js";import{a,b,c,d,e,f,g,h,i}from"./chunk-JHYLPDCC.js";import"./chunk-PAU64XFG.js";import"./chunk-UJN3FMEX.js";import"./chunk-JXO6UPGI.js";import"./chunk-4INGTBO7.js";import"./chunk-IBSEFPPL.js";import"./chunk-64QAFSY7.js";export{e as ALL_DRIVERS,i as buildDriverListRows,a as chromiumDriver,b as electronDriver,f as getAllDrivers,g as getDriver,c as playwrightDriver,h as resolveDriver,d as systemDriver};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a as c,b as d,c as e,d as f}from"./chunk-ZUTVEJVA.js";import"./chunk-JFLNZGDS.js";import"./chunk-B6GISAUX.js";import"./chunk-JS7SSYDG.js";import{c as a,d as b}from"./chunk-WUEKKZ7Z.js";import"./chunk-4JESO36F.js";import"./chunk-SU3JJ7ER.js";import"./chunk-A3VHHWLU.js";import"./chunk-D2BBJUEY.js";import"./chunk-YVDSGGOT.js";import"./chunk-JHYLPDCC.js";import"./chunk-PAU64XFG.js";import"./chunk-UJN3FMEX.js";import"./chunk-C5QOGCVN.js";import"./chunk-52O56BTW.js";import"./chunk-NYGESF6F.js";import"./chunk-CH3MWM5W.js";import"./chunk-65ZBQDQM.js";import"./chunk-JXO6UPGI.js";import"./chunk-SNLUVL3H.js";import"./chunk-UBJQDMDG.js";import"./chunk-CHTYIQLE.js";import"./chunk-YU6CNUJD.js";import"./chunk-WKG5J4RD.js";import"./chunk-4INGTBO7.js";import"./chunk-IBSEFPPL.js";import"./chunk-BTTZN2SN.js";import"./chunk-NZWTC6K6.js";import"./chunk-64QAFSY7.js";export{c as discoverSootsimUrl,e as hoistLeadingSimFlag,a as parseFlowFile,f as runFlow,d as runFlowPlayback,b as validateFlowFile};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c}from"./chunk-ATVKVVHZ.js";import"./chunk-4YNKFN2A.js";import"./chunk-A2WASN2L.js";import"./chunk-AN4DM7IB.js";import"./chunk-CHTYIQLE.js";import"./chunk-YU6CNUJD.js";import"./chunk-WKG5J4RD.js";import"./chunk-4INGTBO7.js";import"./chunk-IBSEFPPL.js";import"./chunk-CUO7F2JE.js";import"./chunk-JS3NH2SJ.js";import"./chunk-NZWTC6K6.js";import"./chunk-64QAFSY7.js";export{c as printCommandHelp,b as printGroupHelp,a as printHelp};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b}from"./chunk-YVDSGGOT.js";import"./chunk-64QAFSY7.js";export{a as loadOptionalDemoApps,b as optionalDemoAppsSync};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a}from"./chunk-3L6I2M2Z.js";import"./chunk-QWZFOMCI.js";import"./chunk-65ZBQDQM.js";import"./chunk-WKG5J4RD.js";import"./chunk-4INGTBO7.js";import"./chunk-IBSEFPPL.js";import"./chunk-64QAFSY7.js";export{a as runRuntime};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a}from"./chunk-BTTZN2SN.js";import"./chunk-NZWTC6K6.js";import"./chunk-64QAFSY7.js";export{a as settingsStore};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b}from"./chunk-SNLUVL3H.js";import"./chunk-UBJQDMDG.js";import"./chunk-IBSEFPPL.js";import"./chunk-64QAFSY7.js";export{b as flushCliTelemetry,a as trackCliEvent};
@@ -1,2 +0,0 @@
1
- /*! sootsim v0.1.177 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
- import{a,b,c}from"./chunk-C5QOGCVN.js";import"./chunk-52O56BTW.js";import"./chunk-NYGESF6F.js";import"./chunk-CH3MWM5W.js";import"./chunk-65ZBQDQM.js";import"./chunk-JXO6UPGI.js";import"./chunk-SNLUVL3H.js";import"./chunk-UBJQDMDG.js";import"./chunk-WKG5J4RD.js";import"./chunk-4INGTBO7.js";import"./chunk-IBSEFPPL.js";import"./chunk-64QAFSY7.js";export{a as resolveDefaultUploadOrigin,b as resolvePublicPreviewOrigin,c as runUpload};