sootsim 0.1.295 → 0.1.296

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 (182) hide show
  1. package/README.md +13 -4
  2. package/dist-cli/bin.js +5 -5
  3. package/dist-cli/chunks/{agent-ASAYE5YY.js → agent-3F4K6MQK.js} +2 -2
  4. package/dist-cli/chunks/{agent-wrapper-K2D4Q5AA.js → agent-wrapper-5LLVCQRZ.js} +2 -2
  5. package/dist-cli/chunks/app-fonts-LPTY7A5G.js +4 -0
  6. package/dist-cli/chunks/{assert-4FKHHDY7.js → assert-R2ZUXEMS.js} +2 -2
  7. package/dist-cli/chunks/{auth-BQPOPEFK.js → auth-CA62Q6IS.js} +2 -2
  8. package/dist-cli/chunks/{beta-3LNYONDF.js → beta-4AXSOQLU.js} +2 -2
  9. package/dist-cli/chunks/{camera-Y5MZ5V4L.js → camera-Y4RBIONE.js} +2 -2
  10. package/dist-cli/chunks/{chunk-L7V46673.js → chunk-222Y7NQA.js} +1 -1
  11. package/dist-cli/chunks/{chunk-6VF477QO.js → chunk-2LQOLMRK.js} +1 -1
  12. package/dist-cli/chunks/{chunk-S6BEA6OC.js → chunk-2XUKWIAL.js} +1 -1
  13. package/dist-cli/chunks/{chunk-XQRUWC3F.js → chunk-3PAZJSIG.js} +2 -2
  14. package/dist-cli/chunks/{chunk-UAZ3NVKO.js → chunk-4MDLYOEI.js} +2 -2
  15. package/dist-cli/chunks/{chunk-MEYVMDZR.js → chunk-4NFGOGB7.js} +2 -2
  16. package/dist-cli/chunks/chunk-54TQ3ZGI.js +30 -0
  17. package/dist-cli/chunks/chunk-5FNPAMP4.js +125 -0
  18. package/dist-cli/chunks/{chunk-FH7DQ2HB.js → chunk-6C24WCDK.js} +2 -2
  19. package/dist-cli/chunks/{chunk-T2DHHOWE.js → chunk-74FOMZP7.js} +2 -2
  20. package/dist-cli/chunks/{chunk-K7LQB4IF.js → chunk-7GQWF7HE.js} +1 -1
  21. package/dist-cli/chunks/{chunk-RNW36VM5.js → chunk-7V3JNANH.js} +4 -4
  22. package/dist-cli/chunks/{chunk-SU5WQ4SQ.js → chunk-7YQXQSG7.js} +1 -1
  23. package/dist-cli/chunks/{chunk-DKS75M2I.js → chunk-AUBP44CY.js} +2 -2
  24. package/dist-cli/chunks/chunk-B2FB6IYX.js +4 -0
  25. package/dist-cli/chunks/{chunk-E6DZD6JD.js → chunk-B2LDO55K.js} +1 -1
  26. package/dist-cli/chunks/{chunk-XCCDO6I2.js → chunk-BVWIR4CD.js} +1 -1
  27. package/dist-cli/chunks/{chunk-UBIGBHUM.js → chunk-C462URRQ.js} +2 -2
  28. package/dist-cli/chunks/{chunk-CVDC2ER2.js → chunk-CAAADPRH.js} +2 -2
  29. package/dist-cli/chunks/{chunk-ETDZQUGI.js → chunk-CDCVWGNU.js} +3 -3
  30. package/dist-cli/chunks/{chunk-JPPGM6RZ.js → chunk-CS23DQB2.js} +2 -2
  31. package/dist-cli/chunks/chunk-DUYKBCM7.js +4 -0
  32. package/dist-cli/chunks/chunk-EISE56VD.js +6 -0
  33. package/dist-cli/chunks/{chunk-TNKZWHD2.js → chunk-EJ6BAJKX.js} +1 -1
  34. package/dist-cli/chunks/chunk-F2MS365Z.js +4 -0
  35. package/dist-cli/chunks/{chunk-I4QJVACX.js → chunk-FROCFR77.js} +1 -1
  36. package/dist-cli/chunks/{chunk-RV67EC7L.js → chunk-FUPQIX4U.js} +2 -2
  37. package/dist-cli/chunks/{chunk-U2QPKFOY.js → chunk-G2SO5FPN.js} +2 -2
  38. package/dist-cli/chunks/chunk-GG5PWLGC.js +4 -0
  39. package/dist-cli/chunks/chunk-GG6XOQ5P.js +15 -0
  40. package/dist-cli/chunks/chunk-HSGS2U7P.js +6 -0
  41. package/dist-cli/chunks/{chunk-7GZ6XF2B.js → chunk-IR3DUBRF.js} +2 -2
  42. package/dist-cli/chunks/chunk-LHUY46GE.js +4 -0
  43. package/dist-cli/chunks/{chunk-WFYQNZTT.js → chunk-MDBR4XTV.js} +3 -3
  44. package/dist-cli/chunks/{chunk-UWFAWMPE.js → chunk-MQ6QX46T.js} +2 -2
  45. package/dist-cli/chunks/chunk-N3FZRJT7.js +4 -0
  46. package/dist-cli/chunks/{chunk-QPA44BZC.js → chunk-NEARYPSC.js} +11 -11
  47. package/dist-cli/chunks/chunk-P7HBJBHH.js +4 -0
  48. package/dist-cli/chunks/{chunk-7FYIMLU4.js → chunk-PEUWZRXA.js} +17 -17
  49. package/dist-cli/chunks/{chunk-X5FTDIHQ.js → chunk-QIDFGREY.js} +1 -1
  50. package/dist-cli/chunks/{chunk-4NJIXTVJ.js → chunk-R65XMN4D.js} +1 -1
  51. package/dist-cli/chunks/{chunk-Y6FJ5FCY.js → chunk-S5Z4HKWX.js} +1 -1
  52. package/dist-cli/chunks/chunk-SUJSGGSS.js +23 -0
  53. package/dist-cli/chunks/{chunk-BX2NUJGR.js → chunk-TIOPG6QZ.js} +1 -1
  54. package/dist-cli/chunks/chunk-WJVBD2UL.js +9 -0
  55. package/dist-cli/chunks/{chunk-3WQISFAK.js → chunk-X7B5KJ6N.js} +1 -1
  56. package/dist-cli/chunks/{chunk-2RI6RC6I.js → chunk-XMVVZCIM.js} +2 -2
  57. package/dist-cli/chunks/chunk-ZIBKGZJD.js +4 -0
  58. package/dist-cli/chunks/chunk-ZPBIHFQW.js +12 -0
  59. package/dist-cli/chunks/cleanup-4RSKYPQ7.js +25 -0
  60. package/dist-cli/chunks/{cli-version-I6BOBK57.js → cli-version-VZFF7GGM.js} +2 -2
  61. package/dist-cli/chunks/compat-FABLN4UI.js +20 -0
  62. package/dist-cli/chunks/config-74J37LKC.js +13 -0
  63. package/dist-cli/chunks/control-VBK32Y7F.js +4 -0
  64. package/dist-cli/chunks/daemon-VFO7LRR4.js +4 -0
  65. package/dist-cli/chunks/{debug-VG2JOF6H.js → debug-AOYA2CLR.js} +3 -3
  66. package/dist-cli/chunks/{desktop-GH2POW6X.js → desktop-G7XWDCTM.js} +3 -3
  67. package/dist-cli/chunks/{detox-X6T265L5.js → detox-QXJ3L2ZI.js} +2 -2
  68. package/dist-cli/chunks/{device-VDOOSAXO.js → device-NZZ5ZT3Q.js} +2 -2
  69. package/dist-cli/chunks/{diagnose-6D6WNAGL.js → diagnose-5CAEJ42M.js} +2 -2
  70. package/dist-cli/chunks/disk-cleanup-GZSUZJ6Y.js +4 -0
  71. package/dist-cli/chunks/drivers-OLJCUSPO.js +4 -0
  72. package/dist-cli/chunks/{film-UZWYISAB.js → film-C25VRUNC.js} +3 -3
  73. package/dist-cli/chunks/flow-IW3WUF5D.js +4 -0
  74. package/dist-cli/chunks/help-GEVJF2DA.js +4 -0
  75. package/dist-cli/chunks/{hidden-runtime-alias-UGMJ4LJX.js → hidden-runtime-alias-NSLIK6XT.js} +2 -2
  76. package/dist-cli/chunks/home-paths-OC6JZXIM.js +4 -0
  77. package/dist-cli/chunks/inspect-KXJNI7CU.js +4 -0
  78. package/dist-cli/chunks/install-desktop-IYWPRFPB.js +4 -0
  79. package/dist-cli/chunks/{login-K43TRKUC.js → login-LB4TMM4T.js} +4 -4
  80. package/dist-cli/chunks/{logout-L43CR6M2.js → logout-33IOBD4X.js} +2 -2
  81. package/dist-cli/chunks/{maestro-7VZFYLNS.js → maestro-EEVXX536.js} +3 -3
  82. package/dist-cli/chunks/{maestro-generate-PMYHUVH4.js → maestro-generate-ICPWVXGA.js} +3 -3
  83. package/dist-cli/chunks/{mode-QQS5XFFX.js → mode-6IXOZDK3.js} +2 -2
  84. package/dist-cli/chunks/{optional-demo-registry-2V327HDG.js → optional-demo-registry-KBMC7SNI.js} +2 -2
  85. package/dist-cli/chunks/{perf-CL5P3JVP.js → perf-CTTJSAIJ.js} +2 -2
  86. package/dist-cli/chunks/{permissions-RGVCEC2B.js → permissions-BFQS4DIY.js} +2 -2
  87. package/dist-cli/chunks/{record-ASW6UFQT.js → record-MJR5ELHE.js} +3 -3
  88. package/dist-cli/chunks/report-issue-FMJRNDKH.js +29 -0
  89. package/dist-cli/chunks/runtime-PV4HH2OB.js +4 -0
  90. package/dist-cli/chunks/{screenshot-command-FEJGQMQF.js → screenshot-command-MGNASAXR.js} +3 -3
  91. package/dist-cli/chunks/{screenshots-capture-3JPZ5WMX.js → screenshots-capture-N6PANAVT.js} +2 -2
  92. package/dist-cli/chunks/serve-RS6TIO7U.js +44 -0
  93. package/dist-cli/chunks/setup-MFYGYR2F.js +32 -0
  94. package/dist-cli/chunks/{skills-T6EEX5P6.js → skills-TD35LDKK.js} +2 -2
  95. package/dist-cli/chunks/{storage-ZFUK4EQA.js → storage-VCFXDJNO.js} +2 -2
  96. package/dist-cli/chunks/store-VNSTKYBQ.js +4 -0
  97. package/dist-cli/chunks/telemetry-GPNHSYFF.js +4 -0
  98. package/dist-cli/chunks/{timeline-EIURYQVC.js → timeline-UJCZAWJV.js} +2 -2
  99. package/dist-cli/chunks/upgrade-S24NH4YG.js +7 -0
  100. package/dist-cli/chunks/upload-CCKAO2M5.js +4 -0
  101. package/dist-cli/chunks/version-IVPWT2ZQ.js +6 -0
  102. package/dist-cli/chunks/web-6BMWAWJL.js +4 -0
  103. package/dist-cli/chunks/{what-happened-L5ZN7S5G.js → what-happened-HRHB6ETL.js} +2 -2
  104. package/dist-lib/agent-daemon-client.cjs +1 -1
  105. package/dist-lib/agent-events.cjs +1 -1
  106. package/dist-lib/agent-identity.cjs +1 -1
  107. package/dist-lib/agent-sessions.cjs +1 -1
  108. package/dist-lib/attached-projects.cjs +1 -1
  109. package/dist-lib/auth/shared-session.cjs +1 -1
  110. package/dist-lib/backend-origin.cjs +1 -1
  111. package/dist-lib/beta.cjs +1 -1
  112. package/dist-lib/beta.mjs +1 -1
  113. package/dist-lib/bridge-constants.cjs +1 -1
  114. package/dist-lib/cli-constants.cjs +1 -1
  115. package/dist-lib/config.cjs +3 -2
  116. package/dist-lib/detox/index.cjs +1 -1
  117. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  118. package/dist-lib/home-paths.cjs +41 -14
  119. package/dist-lib/host/bridge-host.cjs +215 -84
  120. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  121. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  122. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  123. package/dist-lib/host/websocket-proxy.cjs +1 -1
  124. package/dist-lib/index.cjs +2 -2
  125. package/dist-lib/jump-to-source-babel.cjs +1 -1
  126. package/dist-lib/menu.cjs +2 -3
  127. package/dist-lib/menu.mjs +2 -3
  128. package/dist-lib/metro.cjs +1 -1
  129. package/dist-lib/profiles.cjs +1 -1
  130. package/dist-lib/render-mode.cjs +1 -1
  131. package/dist-lib/scripts/dev-server-scanner.cjs +2 -2
  132. package/dist-lib/sdk.cjs +1 -1
  133. package/dist-lib/sdk.mjs +1 -1
  134. package/dist-lib/skills.cjs +366 -154
  135. package/dist-lib/vite.cjs +2 -2
  136. package/package.json +2 -1
  137. package/scripts/postinstall.cjs +2 -78
  138. package/skills/contrast/SKILL.md +1 -0
  139. package/skills/sootsim-setup/SKILL.md +25 -0
  140. package/src/config.ts +4 -0
  141. package/src/disk-cleanup.ts +5 -26
  142. package/src/home-paths.ts +58 -23
  143. package/src/host/bridge-host.ts +152 -57
  144. package/src/menu.ts +0 -1
  145. package/src/runtime-assets.ts +35 -0
  146. package/src/runtime-delivery.ts +5 -8
  147. package/src/skills/builtin/compat-check.ts +32 -65
  148. package/dist-cli/chunks/app-fonts-36N7AVQ3.js +0 -4
  149. package/dist-cli/chunks/chunk-4ODQVUBH.js +0 -6
  150. package/dist-cli/chunks/chunk-4V2KYK5T.js +0 -4
  151. package/dist-cli/chunks/chunk-7GVBNEQ3.js +0 -9
  152. package/dist-cli/chunks/chunk-COEKUTWV.js +0 -4
  153. package/dist-cli/chunks/chunk-D2DU3ROC.js +0 -6
  154. package/dist-cli/chunks/chunk-DXCQP3VE.js +0 -12
  155. package/dist-cli/chunks/chunk-HT6WYHQL.js +0 -6
  156. package/dist-cli/chunks/chunk-I7AWRAXM.js +0 -125
  157. package/dist-cli/chunks/chunk-OQ7SSRYK.js +0 -4
  158. package/dist-cli/chunks/chunk-QKZVANQG.js +0 -31
  159. package/dist-cli/chunks/chunk-TGYZYSDB.js +0 -15
  160. package/dist-cli/chunks/chunk-TXURXDZN.js +0 -4
  161. package/dist-cli/chunks/chunk-ZJZYGLJ2.js +0 -4
  162. package/dist-cli/chunks/cleanup-SMCA44QC.js +0 -25
  163. package/dist-cli/chunks/compat-FCM2ZQLV.js +0 -35
  164. package/dist-cli/chunks/config-PZSANSAI.js +0 -13
  165. package/dist-cli/chunks/control-PM554MHE.js +0 -4
  166. package/dist-cli/chunks/daemon-5KXEZZLJ.js +0 -4
  167. package/dist-cli/chunks/disk-cleanup-HTOIDDKK.js +0 -4
  168. package/dist-cli/chunks/drivers-CKLBQDXG.js +0 -4
  169. package/dist-cli/chunks/flow-VOS3RKB3.js +0 -4
  170. package/dist-cli/chunks/help-LVMDERFQ.js +0 -4
  171. package/dist-cli/chunks/home-paths-3LYT47SY.js +0 -4
  172. package/dist-cli/chunks/inspect-FHCSOWGQ.js +0 -4
  173. package/dist-cli/chunks/install-desktop-KLMCVDGZ.js +0 -4
  174. package/dist-cli/chunks/runtime-GB3ZE27C.js +0 -4
  175. package/dist-cli/chunks/serve-SYXRHRQO.js +0 -44
  176. package/dist-cli/chunks/setup-QLGL6MC6.js +0 -99
  177. package/dist-cli/chunks/store-WCDTSWJC.js +0 -4
  178. package/dist-cli/chunks/telemetry-D7SL4WW7.js +0 -4
  179. package/dist-cli/chunks/upgrade-Q7ZGWMCJ.js +0 -6
  180. package/dist-cli/chunks/upload-7XEICYJX.js +0 -4
  181. package/dist-cli/chunks/version-PDG4V26R.js +0 -6
  182. package/dist-cli/chunks/web-AMW2TRWB.js +0 -4
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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;
@@ -99,7 +99,7 @@ function hasOwnKeys(value) {
99
99
  }
100
100
  function hasSootSimConfig(config) {
101
101
  if (!config) return false;
102
- return hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
102
+ return typeof config.runtimeVersion === "string" && config.runtimeVersion.length > 0 || hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
103
103
  }
104
104
  function applySootSimConfigToUrl(url, config) {
105
105
  const parsed = new URL(url);
@@ -1082,7 +1082,7 @@ function readDaemonLockfile() {
1082
1082
  const bytesRead = import_node_fs2.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
1083
1083
  const raw = buf.subarray(0, bytesRead).toString("utf8");
1084
1084
  const parsed = JSON.parse(raw);
1085
- 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") {
1085
+ 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" && (parsed.servedRuntimes === void 0 || Array.isArray(parsed.servedRuntimes) && parsed.servedRuntimes.every((version) => typeof version === "string"))) {
1086
1086
  return parsed;
1087
1087
  }
1088
1088
  return null;
@@ -1143,35 +1143,12 @@ function removeDevBridgeLockfile() {
1143
1143
  var import_fs = __toESM(require("fs"), 1);
1144
1144
  var import_path = __toESM(require("path"), 1);
1145
1145
  var import_url = require("url");
1146
- var _monorepoRootCache;
1147
- function findMonorepoRoot() {
1148
- if (_monorepoRootCache !== void 0) return _monorepoRootCache;
1149
- let dir = import_path.default.dirname((0, import_url.fileURLToPath)(__sootsim_import_meta_url));
1150
- for (let i = 0; i < 12 && dir !== import_path.default.dirname(dir); i++) {
1151
- if (import_fs.default.existsSync(import_path.default.join(dir, "packages/sootsim-engine/package.json")) && import_fs.default.existsSync(import_path.default.join(dir, "public/sootsim"))) {
1152
- _monorepoRootCache = dir;
1153
- return dir;
1154
- }
1155
- dir = import_path.default.dirname(dir);
1156
- }
1157
- _monorepoRootCache = null;
1158
- return null;
1159
- }
1160
- function resolveDevCheckoutRuntimeRoot() {
1161
- if (process.env.SOOTSIM_HOME && readActiveRuntime()) return null;
1162
- const root = findMonorepoRoot();
1163
- if (!root) return null;
1164
- const devBuild = import_path.default.join(root, "public/sootsim");
1165
- if (import_fs.default.existsSync(import_path.default.join(devBuild, "index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine/index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine-tenant/worker.js"))) {
1166
- return devBuild;
1167
- }
1168
- return null;
1169
- }
1170
1146
 
1171
1147
  // ../contrast-runtime-delivery/src/index.ts
1172
1148
  var import_node_child_process = require("node:child_process");
1173
1149
  var import_node_crypto = __toESM(require("node:crypto"), 1);
1174
1150
  var import_node_fs4 = __toESM(require("node:fs"), 1);
1151
+ var import_node_os2 = __toESM(require("node:os"), 1);
1175
1152
  var import_node_path4 = __toESM(require("node:path"), 1);
1176
1153
  var import_node_stream = require("node:stream");
1177
1154
  var import_promises2 = require("node:stream/promises");
@@ -1179,6 +1156,9 @@ var import_promises2 = require("node:stream/promises");
1179
1156
  // ../contrast-runtime-delivery/src/product.ts
1180
1157
  var import_node_fs3 = __toESM(require("node:fs"), 1);
1181
1158
  var import_node_path3 = __toESM(require("node:path"), 1);
1159
+ function isValidRuntimeVersion(value) {
1160
+ return value.length <= 100 && /^[0-9A-Za-z][0-9A-Za-z._+-]*$/.test(value);
1161
+ }
1182
1162
  function listInstalledRuntimes(product) {
1183
1163
  try {
1184
1164
  return import_node_fs3.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
@@ -1234,6 +1214,7 @@ function createRuntimeDelivery(product) {
1234
1214
  return input || process.env[product.env.channel] || config.runtimeChannel || "stable";
1235
1215
  }
1236
1216
  function resolvePin() {
1217
+ if (!product.env.pin) return null;
1237
1218
  const env = process.env[product.env.pin];
1238
1219
  if (env && env.trim()) return env.trim();
1239
1220
  const config = readConfig();
@@ -1263,6 +1244,9 @@ function createRuntimeDelivery(product) {
1263
1244
  `no version specified and channel '${channel}' has no latest entry in the manifest`
1264
1245
  );
1265
1246
  }
1247
+ if (!isValidRuntimeVersion(version)) {
1248
+ throw new Error(`invalid runtime version: ${version}`);
1249
+ }
1266
1250
  const entry = manifest.versions[version];
1267
1251
  if (!entry) {
1268
1252
  throw new Error(
@@ -1278,10 +1262,11 @@ function createRuntimeDelivery(product) {
1278
1262
  const { version, channel, entry } = resolveVersion(manifest, opts);
1279
1263
  const destDir = product.runtimeDir(version);
1280
1264
  const setActive = opts.setActive !== false;
1281
- pruneLocalRetention({ protectVersions: [version] });
1265
+ const protectVersions = [version, ...opts.protectVersions ?? []];
1266
+ pruneLocalRetention({ protectVersions });
1282
1267
  if (!opts.force && import_node_fs4.default.existsSync(import_node_path4.default.join(destDir, product.installedMarker))) {
1283
1268
  if (setActive) product.writeActiveRuntime(version);
1284
- pruneLocalRetention({ protectVersions: [version] });
1269
+ pruneLocalRetention({ protectVersions });
1285
1270
  return {
1286
1271
  version,
1287
1272
  channel,
@@ -1293,29 +1278,32 @@ function createRuntimeDelivery(product) {
1293
1278
  };
1294
1279
  }
1295
1280
  const tarUrl = entry.tarball || tarballUrl(version, cdnOrigin);
1296
- const tarCachePath = import_node_path4.default.join(
1297
- product.cacheDir(),
1281
+ const downloadDir = import_node_fs4.default.mkdtempSync(
1282
+ import_node_path4.default.join(import_node_os2.default.tmpdir(), `${product.id}-runtime-download-`)
1283
+ );
1284
+ const runtimeArchivePath = import_node_path4.default.join(
1285
+ downloadDir,
1298
1286
  runtimeTarballCacheName(product, version)
1299
1287
  );
1300
- process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
1301
- `);
1302
- await downloadToFile(tarUrl, tarCachePath);
1303
- process.stderr.write(`${product.id}: extracting runtime ${version}\u2026
1304
- `);
1305
1288
  const tmpDir = import_node_path4.default.join(
1306
1289
  import_node_path4.default.dirname(destDir),
1307
1290
  `.installing-${version}-${process.pid}`
1308
1291
  );
1309
1292
  import_node_fs4.default.rmSync(tmpDir, { recursive: true, force: true });
1310
1293
  try {
1311
- const actualSha = await sha256File(tarCachePath);
1294
+ process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
1295
+ `);
1296
+ await downloadToFile(tarUrl, runtimeArchivePath);
1297
+ process.stderr.write(`${product.id}: extracting runtime ${version}\u2026
1298
+ `);
1299
+ const actualSha = await sha256File(runtimeArchivePath);
1312
1300
  if (actualSha !== entry.sha256) {
1313
1301
  throw new Error(
1314
1302
  `sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`
1315
1303
  );
1316
1304
  }
1317
1305
  import_node_fs4.default.mkdirSync(tmpDir, { recursive: true });
1318
- await extractTarball(tarCachePath, tmpDir);
1306
+ await extractTarball(runtimeArchivePath, tmpDir);
1319
1307
  if (!import_node_fs4.default.existsSync(import_node_path4.default.join(tmpDir, product.installedMarker))) {
1320
1308
  throw new Error(
1321
1309
  `extracted tarball for runtime ${version} is missing ${product.installedMarker}`
@@ -1327,10 +1315,10 @@ function createRuntimeDelivery(product) {
1327
1315
  import_node_fs4.default.rmSync(tmpDir, { recursive: true, force: true });
1328
1316
  throw err;
1329
1317
  } finally {
1330
- import_node_fs4.default.rmSync(tarCachePath, { force: true });
1318
+ import_node_fs4.default.rmSync(downloadDir, { recursive: true, force: true });
1331
1319
  }
1332
1320
  if (setActive) product.writeActiveRuntime(version);
1333
- pruneLocalRetention({ protectVersions: [version] });
1321
+ pruneLocalRetention({ protectVersions });
1334
1322
  return {
1335
1323
  version,
1336
1324
  channel,
@@ -1343,7 +1331,7 @@ function createRuntimeDelivery(product) {
1343
1331
  }
1344
1332
  async function updateToLatest(opts = {}) {
1345
1333
  product.ensureHome();
1346
- pruneLocalRetention();
1334
+ pruneLocalRetention({ protectVersions: opts.protectVersions });
1347
1335
  const cdnOrigin = resolveCdnOrigin(opts.cdnOrigin);
1348
1336
  const channel = resolveChannel(opts.channel);
1349
1337
  const pin = resolvePin();
@@ -1365,7 +1353,8 @@ function createRuntimeDelivery(product) {
1365
1353
  version: pin,
1366
1354
  channel,
1367
1355
  cdnOrigin,
1368
- setActive: false
1356
+ setActive: false,
1357
+ protectVersions: opts.protectVersions
1369
1358
  });
1370
1359
  return {
1371
1360
  checked: true,
@@ -1413,7 +1402,8 @@ function createRuntimeDelivery(product) {
1413
1402
  version: latestVersion,
1414
1403
  channel,
1415
1404
  cdnOrigin,
1416
- setActive: false
1405
+ setActive: false,
1406
+ protectVersions: opts.protectVersions
1417
1407
  });
1418
1408
  return {
1419
1409
  checked: true,
@@ -1556,6 +1546,53 @@ function extractTarball(tarPath, destDir) {
1556
1546
  });
1557
1547
  }
1558
1548
 
1549
+ // src/runtime-assets.ts
1550
+ var _monorepoRootCache;
1551
+ function findMonorepoRoot() {
1552
+ if (_monorepoRootCache !== void 0) return _monorepoRootCache;
1553
+ let dir = import_path.default.dirname((0, import_url.fileURLToPath)(__sootsim_import_meta_url));
1554
+ for (let i = 0; i < 12 && dir !== import_path.default.dirname(dir); i++) {
1555
+ if (import_fs.default.existsSync(import_path.default.join(dir, "packages/sootsim-engine/package.json")) && import_fs.default.existsSync(import_path.default.join(dir, "public/sootsim"))) {
1556
+ _monorepoRootCache = dir;
1557
+ return dir;
1558
+ }
1559
+ dir = import_path.default.dirname(dir);
1560
+ }
1561
+ _monorepoRootCache = null;
1562
+ return null;
1563
+ }
1564
+ function resolveDevCheckoutRuntimeRoot() {
1565
+ if (process.env.SOOTSIM_HOME && readActiveRuntime()) return null;
1566
+ const root = findMonorepoRoot();
1567
+ if (!root) return null;
1568
+ const devBuild = import_path.default.join(root, "public/sootsim");
1569
+ if (import_fs.default.existsSync(import_path.default.join(devBuild, "index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine/index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine-tenant/worker.js"))) {
1570
+ return devBuild;
1571
+ }
1572
+ return null;
1573
+ }
1574
+ function runtimeVersionFromHostname(hostname) {
1575
+ const suffix = ".runtime.localhost";
1576
+ if (!hostname.toLowerCase().endsWith(suffix)) return null;
1577
+ const labels = hostname.slice(0, -suffix.length).split(".");
1578
+ if (labels.length === 0 || labels.some((label) => !/^[0-9a-f]{1,60}$/i.test(label))) {
1579
+ return null;
1580
+ }
1581
+ const encoded = labels.join("");
1582
+ if (encoded.length % 2 !== 0) return null;
1583
+ try {
1584
+ const version = Buffer.from(encoded, "hex").toString("utf8");
1585
+ return isValidRuntimeVersion(version) ? version : null;
1586
+ } catch {
1587
+ return null;
1588
+ }
1589
+ }
1590
+ function resolveInstalledRuntimeRoot(version) {
1591
+ const dir = runtimeDir(version);
1592
+ if (!import_fs.default.existsSync(import_path.default.join(dir, "index.html"))) return null;
1593
+ return dir;
1594
+ }
1595
+
1559
1596
  // src/runtime-delivery.ts
1560
1597
  var DEFAULT_RUNTIME_CDN_ORIGIN = "https://contrast.dev";
1561
1598
  var SOOTSIM_RUNTIME_PRODUCT = {
@@ -1569,8 +1606,7 @@ var SOOTSIM_RUNTIME_PRODUCT = {
1569
1606
  installedMarker: "index.html",
1570
1607
  env: {
1571
1608
  cdnOrigin: "SOOTSIM_CDN_ORIGIN",
1572
- channel: "SOOTSIM_RUNTIME_CHANNEL",
1573
- pin: "SOOTSIM_RUNTIME_VERSION"
1609
+ channel: "SOOTSIM_RUNTIME_CHANNEL"
1574
1610
  },
1575
1611
  ensureHome: ensureSootsimHome,
1576
1612
  configFile: configFilePath,
@@ -3863,6 +3899,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3863
3899
  recentActions: []
3864
3900
  };
3865
3901
  this.sims.set(sim.id, sim);
3902
+ this.writeConnectedRuntimeSnapshot();
3866
3903
  if (this.shouldPromoteSim(sim)) {
3867
3904
  this.primarySimId = sim.id;
3868
3905
  }
@@ -3954,6 +3991,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3954
3991
  sim = null;
3955
3992
  role = "cli";
3956
3993
  this.cliIdentityKeyBySocket.set(ws, `ws-${this.nextCliFallbackId++}`);
3994
+ this.writeConnectedRuntimeSnapshot();
3957
3995
  this.broadcastSimAssignments();
3958
3996
  this.broadcastSimClientStates();
3959
3997
  }
@@ -3967,6 +4005,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3967
4005
  sim.url = registration.url;
3968
4006
  sim.title = registration.title;
3969
4007
  sim.userAgent = registration.userAgent;
4008
+ this.writeConnectedRuntimeSnapshot();
3970
4009
  if (typeof registration.kind === "string" && registration.kind.trim()) {
3971
4010
  sim.kind = registration.kind.trim();
3972
4011
  }
@@ -3991,11 +4030,14 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
3991
4030
  return;
3992
4031
  }
3993
4032
  if (msg.type === "bridge:write-shared-config") {
3994
- const patch = msg.patch && typeof msg.patch === "object" ? msg.patch : null;
3995
- if (!patch) return;
3996
- let next;
4033
+ if (!msg.patch || typeof msg.patch !== "object" || Array.isArray(msg.patch)) {
4034
+ return;
4035
+ }
4036
+ const patch = Object.fromEntries(
4037
+ Object.entries(msg.patch)
4038
+ );
3997
4039
  try {
3998
- next = writeSharedConfig(patch);
4040
+ this.writeAndBroadcastSharedConfig(patch);
3999
4041
  } catch (err) {
4000
4042
  process.stderr.write(
4001
4043
  `sootsim: bridge:write-shared-config failed: ${err instanceof Error ? err.message : String(err)}
@@ -4003,17 +4045,6 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4003
4045
  );
4004
4046
  return;
4005
4047
  }
4006
- const payload = JSON.stringify({
4007
- type: "bridge:shared-config-changed",
4008
- config: next
4009
- });
4010
- for (const peer of this.sims.values()) {
4011
- if (peer.ws.readyState !== import_ws2.WebSocket.OPEN) continue;
4012
- try {
4013
- peer.ws.send(payload);
4014
- } catch {
4015
- }
4016
- }
4017
4048
  return;
4018
4049
  }
4019
4050
  if (msg.type === "bridge:open-path") {
@@ -4328,6 +4359,18 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4328
4359
  void this.agentHost.seedOnBoot();
4329
4360
  }
4330
4361
  bootstrapping = true;
4362
+ connectedRuntimeVersions() {
4363
+ const versions = /* @__PURE__ */ new Set();
4364
+ for (const sim of this.sims.values()) {
4365
+ try {
4366
+ const url = new URL(sim.url || sim.origin || "http://localhost");
4367
+ const version = runtimeVersionFromHostname(url.hostname);
4368
+ if (version) versions.add(version);
4369
+ } catch {
4370
+ }
4371
+ }
4372
+ return [...versions].sort();
4373
+ }
4331
4374
  buildLockfileSnapshot() {
4332
4375
  return {
4333
4376
  schema: 1,
@@ -4337,6 +4380,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4337
4380
  runtimePort: this.effectivePort,
4338
4381
  activeRuntime: this.activeRuntimeVersion,
4339
4382
  activeRuntimeDir: this.activeRuntimeDirPath,
4383
+ servedRuntimes: this.connectedRuntimeVersions(),
4340
4384
  startedAt: this.startedAt,
4341
4385
  heartbeatAt: Date.now(),
4342
4386
  bootstrapping: this.bootstrapping
@@ -4354,7 +4398,8 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4354
4398
  cwd: process.cwd(),
4355
4399
  startedAt: this.startedAt,
4356
4400
  heartbeatAt: Date.now(),
4357
- source: "vite-dev"
4401
+ source: "vite-dev",
4402
+ servedRuntimes: this.connectedRuntimeVersions()
4358
4403
  };
4359
4404
  }
4360
4405
  writeLockfileSnapshot() {
@@ -4363,6 +4408,20 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4363
4408
  writeDevLockfileSnapshot() {
4364
4409
  writeDevBridgeLockfile(this.buildDevLockfileSnapshot());
4365
4410
  }
4411
+ writeConnectedRuntimeSnapshot() {
4412
+ if (this.shouldWriteLockfile && this.httpServer) {
4413
+ try {
4414
+ this.writeLockfileSnapshot();
4415
+ } catch {
4416
+ }
4417
+ }
4418
+ if (this.shouldWriteDevLockfile && this.httpServer) {
4419
+ try {
4420
+ this.writeDevLockfileSnapshot();
4421
+ } catch {
4422
+ }
4423
+ }
4424
+ }
4366
4425
  refreshActiveRuntime() {
4367
4426
  this.activeRuntimeVersion = readActiveRuntime();
4368
4427
  this.activeRuntimeDirPath = resolveDevCheckoutRuntimeRoot() ?? activeRuntimeDir();
@@ -4414,6 +4473,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4414
4473
  }
4415
4474
  startRuntimeUpdater() {
4416
4475
  if (!this.shouldWriteLockfile || this.runtimeUpdateTimer) return;
4476
+ if (import_fs3.default.existsSync(import_path3.default.join(sootsimHomeDir(), "runtime-update-disabled"))) return;
4417
4477
  if (process.env.SOOTSIM_HOME && isSootsimDevCheckout() && !readActiveRuntime()) {
4418
4478
  return;
4419
4479
  }
@@ -4431,7 +4491,9 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4431
4491
  if (reason === "startup") {
4432
4492
  process.stderr.write("sootsim: checking for runtime updates\u2026\n");
4433
4493
  }
4434
- const result = await sootsimRuntime.updateToLatest();
4494
+ const result = await sootsimRuntime.updateToLatest({
4495
+ protectVersions: this.connectedRuntimeVersions()
4496
+ });
4435
4497
  if (!result.updated || !result.latestVersion) {
4436
4498
  if (reason === "startup") {
4437
4499
  process.stderr.write(
@@ -4492,6 +4554,11 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4492
4554
  runtimeDir: this.activeRuntimeDirPath
4493
4555
  });
4494
4556
  for (const sim of this.sims.values()) {
4557
+ try {
4558
+ const simUrl = new URL(sim.url || sim.origin || "http://localhost");
4559
+ if (runtimeVersionFromHostname(simUrl.hostname)) continue;
4560
+ } catch {
4561
+ }
4495
4562
  if (sim.ws.readyState === import_ws2.WebSocket.OPEN) {
4496
4563
  try {
4497
4564
  sim.ws.send(payload);
@@ -4535,12 +4602,77 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4535
4602
  return;
4536
4603
  }
4537
4604
  const method = (req.method || "GET").toUpperCase();
4605
+ let url;
4606
+ try {
4607
+ url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
4608
+ } catch {
4609
+ res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
4610
+ res.end("invalid request URL or host");
4611
+ return;
4612
+ }
4613
+ if (url.pathname === "/__sootsim/shared-config") {
4614
+ res.setHeader("Access-Control-Allow-Origin", "*");
4615
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
4616
+ res.setHeader("Cache-Control", "no-store");
4617
+ if (method === "OPTIONS") {
4618
+ res.writeHead(204, { Allow: "GET, HEAD, POST, OPTIONS" });
4619
+ res.end();
4620
+ return;
4621
+ }
4622
+ if (method === "GET" || method === "HEAD") {
4623
+ let body = "{}";
4624
+ try {
4625
+ body = JSON.stringify(readSharedConfig());
4626
+ } catch {
4627
+ }
4628
+ res.writeHead(200, { "Content-Type": "application/json" });
4629
+ if (method === "HEAD") res.end();
4630
+ else res.end(body);
4631
+ return;
4632
+ }
4633
+ if (method === "POST") {
4634
+ void (async () => {
4635
+ try {
4636
+ const chunks = [];
4637
+ let size = 0;
4638
+ for await (const chunk of req) {
4639
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
4640
+ size += buffer.byteLength;
4641
+ if (size > 8 * 1024 * 1024) {
4642
+ res.writeHead(413, { "Content-Type": "text/plain; charset=utf-8" });
4643
+ res.end("shared config patch is too large");
4644
+ return;
4645
+ }
4646
+ chunks.push(buffer);
4647
+ }
4648
+ const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
4649
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
4650
+ throw new Error("shared config patch must be an object");
4651
+ }
4652
+ const patch = Object.fromEntries(
4653
+ Object.entries(parsed)
4654
+ );
4655
+ const next = this.writeAndBroadcastSharedConfig(patch);
4656
+ res.writeHead(200, { "Content-Type": "application/json" });
4657
+ res.end(JSON.stringify(next));
4658
+ } catch (error) {
4659
+ res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
4660
+ res.end(
4661
+ `invalid shared config patch: ${error instanceof Error ? error.message : String(error)}`
4662
+ );
4663
+ }
4664
+ })();
4665
+ return;
4666
+ }
4667
+ res.writeHead(405, { Allow: "GET, HEAD, POST, OPTIONS" });
4668
+ res.end("method not allowed");
4669
+ return;
4670
+ }
4538
4671
  if (method !== "GET" && method !== "HEAD") {
4539
4672
  res.writeHead(405, { Allow: "GET, HEAD" });
4540
4673
  res.end("method not allowed");
4541
4674
  return;
4542
4675
  }
4543
- const url = new URL(req.url || "/", "http://localhost");
4544
4676
  if (url.pathname === "/__bundle-proxy") {
4545
4677
  const target = url.searchParams.get("url");
4546
4678
  if (!target) {
@@ -4617,30 +4749,13 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
4617
4749
  );
4618
4750
  return;
4619
4751
  }
4620
- if (url.pathname === "/__sootsim/shared-config") {
4621
- res.setHeader("Access-Control-Allow-Origin", "*");
4622
- res.setHeader("Cache-Control", "no-store");
4623
- if (method === "GET" || method === "HEAD") {
4624
- let body = "{}";
4625
- try {
4626
- body = JSON.stringify(readSharedConfig());
4627
- } catch {
4628
- }
4629
- res.writeHead(200, { "Content-Type": "application/json" });
4630
- if (method === "HEAD") res.end();
4631
- else res.end(body);
4632
- return;
4633
- }
4634
- res.writeHead(405, { Allow: "GET, HEAD" });
4635
- res.end("method not allowed (use the bridge over WS for writes)");
4636
- return;
4637
- }
4638
- this.refreshActiveRuntime();
4639
- const baseDir = this.activeRuntimeDirPath;
4752
+ const requestedRuntime = runtimeVersionFromHostname(url.hostname);
4753
+ if (!requestedRuntime) this.refreshActiveRuntime();
4754
+ const baseDir = requestedRuntime ? resolveInstalledRuntimeRoot(requestedRuntime) : this.activeRuntimeDirPath;
4640
4755
  if (!baseDir) {
4641
4756
  res.writeHead(503, { "Content-Type": "text/plain; charset=utf-8" });
4642
4757
  res.end(
4643
- "sootsim: no active runtime installed. run `sootsim runtime install` to fetch one."
4758
+ requestedRuntime ? `sootsim: runtime ${requestedRuntime} is not installed. run \`sootsim open\` from that app again.` : "sootsim: no active runtime installed. run `sootsim runtime install` to fetch one."
4644
4759
  );
4645
4760
  return;
4646
4761
  }
@@ -5247,6 +5362,21 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
5247
5362
  );
5248
5363
  }
5249
5364
  }
5365
+ writeAndBroadcastSharedConfig(patch) {
5366
+ const next = writeSharedConfig(patch);
5367
+ const payload = JSON.stringify({
5368
+ type: "bridge:shared-config-changed",
5369
+ config: next
5370
+ });
5371
+ for (const peer of this.sims.values()) {
5372
+ if (peer.ws.readyState !== import_ws2.WebSocket.OPEN) continue;
5373
+ try {
5374
+ peer.ws.send(payload);
5375
+ } catch {
5376
+ }
5377
+ }
5378
+ return next;
5379
+ }
5250
5380
  broadcastSimClientStates() {
5251
5381
  for (const sim of this.sims.values()) {
5252
5382
  if (sim.ws.readyState !== import_ws2.WebSocket.OPEN) continue;
@@ -5385,6 +5515,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
5385
5515
  expiresAt: Date.now() + _SootSimBridgeHost.SIM_RECONNECT_TTL_MS
5386
5516
  });
5387
5517
  this.sims.delete(sim.id);
5518
+ this.writeConnectedRuntimeSnapshot();
5388
5519
  }
5389
5520
  getRestorableSimState(simId) {
5390
5521
  const snapshot = this.restorableSims.get(simId);
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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 __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/host/fetch-proxy-overrides.ts
4
4
  var FETCH_PROXY_BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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 __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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;
@@ -91,7 +91,7 @@ function readDaemonLockfile() {
91
91
  const bytesRead = import_node_fs.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
92
92
  const raw = buf.subarray(0, bytesRead).toString("utf8");
93
93
  const parsed = JSON.parse(raw);
94
- 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") {
94
+ 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" && (parsed.servedRuntimes === void 0 || Array.isArray(parsed.servedRuntimes) && parsed.servedRuntimes.every((version) => typeof version === "string"))) {
95
95
  return parsed;
96
96
  }
97
97
  return null;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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 __defProp = Object.defineProperty;
package/dist-lib/menu.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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 __defProp = Object.defineProperty;
@@ -423,8 +423,7 @@ function helpMenu() {
423
423
  accelerator: "CmdOrCtrl+Shift+I",
424
424
  action: "open-devtools-report",
425
425
  showInShortcutDocs: true
426
- },
427
- { label: "Show Onboarding", action: "open-devtools-onboard" }
426
+ }
428
427
  ]
429
428
  };
430
429
  }
package/dist-lib/menu.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/menu.ts
4
4
  var SOOTSIM_ENGINE_EVENT_NAME = "sootsim:engine-event";
@@ -387,8 +387,7 @@ function helpMenu() {
387
387
  accelerator: "CmdOrCtrl+Shift+I",
388
388
  action: "open-devtools-report",
389
389
  showInShortcutDocs: true
390
- },
391
- { label: "Show Onboarding", action: "open-devtools-onboard" }
390
+ }
392
391
  ]
393
392
  };
394
393
  }
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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 __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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;
@@ -56,7 +56,7 @@ function hasOwnKeys(value) {
56
56
  }
57
57
  function hasSootSimConfig(config) {
58
58
  if (!config) return false;
59
- return hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
59
+ return typeof config.runtimeVersion === "string" && config.runtimeVersion.length > 0 || hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
60
60
  }
61
61
  function applySootSimConfigToUrl(url, config) {
62
62
  const parsed = new URL(url);
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.295 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.296 | (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 __defProp = Object.defineProperty;