sootsim 0.1.200 → 0.1.202
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.
- package/dist-cli/bin.js +5 -4
- package/dist-cli/chunks/{agent-RJBLYNGF.js → agent-SP6EE5XV.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-E6WLI6L3.js → agent-wrapper-PWZVJ3OK.js} +2 -2
- package/dist-cli/chunks/{app-fonts-O3VYBYQW.js → app-fonts-EMJB6QLM.js} +2 -2
- package/dist-cli/chunks/{assert-VFBTT2JB.js → assert-H2B6TDXT.js} +2 -2
- package/dist-cli/chunks/{auth-DQ6AJU2X.js → auth-SOHXBYLQ.js} +2 -2
- package/dist-cli/chunks/beta-CCNQQ73A.js +2 -0
- package/dist-cli/chunks/{camera-C2OFA3JA.js → camera-ULLCBM5H.js} +2 -2
- package/dist-cli/chunks/{chunk-UGJFYNMX.js → chunk-2CID4LNK.js} +3 -3
- package/dist-cli/chunks/chunk-2V43M57C.js +2 -0
- package/dist-cli/chunks/{chunk-GKXPIE6X.js → chunk-3ZENZOIX.js} +2 -2
- package/dist-cli/chunks/{chunk-6RHOWIGL.js → chunk-4KT2BGQE.js} +1 -1
- package/dist-cli/chunks/{chunk-P4PCUR4Y.js → chunk-4KVSVFRF.js} +1 -1
- package/dist-cli/chunks/{chunk-VACKEJ3E.js → chunk-4NM6JBYH.js} +1 -1
- package/dist-cli/chunks/chunk-5J63S2NM.js +1 -0
- package/dist-cli/chunks/{chunk-7BS4AKZT.js → chunk-5SKKMM7E.js} +1 -1
- package/dist-cli/chunks/chunk-6FZ6SNVP.js +4 -0
- package/dist-cli/chunks/{chunk-3BEGOL5T.js → chunk-6QFVYLX6.js} +2 -2
- package/dist-cli/chunks/{chunk-IJ6DRL7N.js → chunk-AAQVPSIV.js} +2 -2
- package/dist-cli/chunks/{chunk-XF3JBBPU.js → chunk-B6JB4THC.js} +2 -2
- package/dist-cli/chunks/{chunk-JJOS6L5H.js → chunk-BZ7AW7ZB.js} +2 -2
- package/dist-cli/chunks/{chunk-OCA5CK4S.js → chunk-CB7LDZKJ.js} +3 -3
- package/dist-cli/chunks/{chunk-6JKBWHIO.js → chunk-CGJ2U6ST.js} +1 -1
- package/dist-cli/chunks/chunk-DKBKU55D.js +2 -0
- package/dist-cli/chunks/{chunk-QSWT3OVG.js → chunk-DRJ4YWUG.js} +1 -1
- package/dist-cli/chunks/{chunk-XAIDHR55.js → chunk-EMOZJ773.js} +2 -2
- package/dist-cli/chunks/{chunk-KFGBNAV3.js → chunk-ENXHZGSL.js} +1 -1
- package/dist-cli/chunks/{chunk-I6DJFJQ6.js → chunk-F2LLN4U7.js} +2 -2
- package/dist-cli/chunks/{chunk-3PAUJH34.js → chunk-GUYKLSTX.js} +1 -1
- package/dist-cli/chunks/chunk-GZKT53SA.js +7 -0
- package/dist-cli/chunks/{chunk-DWFS6IIT.js → chunk-HZYHSLNH.js} +2 -2
- package/dist-cli/chunks/chunk-I6O7NBPZ.js +1 -0
- package/dist-cli/chunks/{chunk-U5O3F3NB.js → chunk-JP7J325R.js} +2 -2
- package/dist-cli/chunks/{chunk-5SB3N45C.js → chunk-K3UBHPVP.js} +1 -1
- package/dist-cli/chunks/{chunk-VFSOKG53.js → chunk-KRGHRSKY.js} +2 -2
- package/dist-cli/chunks/{chunk-VP4Y767U.js → chunk-KYGUR727.js} +2 -2
- package/dist-cli/chunks/{chunk-2E4DUZEV.js → chunk-LNDRRZP3.js} +2 -2
- package/dist-cli/chunks/{chunk-NEQRFWA3.js → chunk-OG6TFGYF.js} +2 -2
- package/dist-cli/chunks/{chunk-PJAKGC4A.js → chunk-PL4GXELT.js} +1 -1
- package/dist-cli/chunks/{chunk-MZLG4WVE.js → chunk-RJVIUQK4.js} +1 -1
- package/dist-cli/chunks/{chunk-4RUK2YSF.js → chunk-ROYBEBG2.js} +1 -1
- package/dist-cli/chunks/{chunk-42G5ZRQR.js → chunk-RS7QLHEH.js} +2 -2
- package/dist-cli/chunks/{chunk-LSDJTPOY.js → chunk-RWXCSRNE.js} +2 -2
- package/dist-cli/chunks/{chunk-NX4VSQD5.js → chunk-RZQO4Q7E.js} +1 -1
- package/dist-cli/chunks/{chunk-SFUQJU5Q.js → chunk-SQBX2HS7.js} +6 -6
- package/dist-cli/chunks/{chunk-NK4FF37S.js → chunk-TANTCV45.js} +2 -2
- package/dist-cli/chunks/chunk-W4Y3JJX6.js +29 -0
- package/dist-cli/chunks/chunk-WILIVPUU.js +567 -0
- package/dist-cli/chunks/{chunk-GMBG6JLV.js → chunk-WVDWIXPH.js} +2 -2
- package/dist-cli/chunks/{chunk-HGBMGQGP.js → chunk-Z5VMWFCY.js} +1 -1
- package/dist-cli/chunks/cli-version-Z4NGLJLH.js +2 -0
- package/dist-cli/chunks/{compat-L2E3OQW3.js → compat-YW3OJ7RX.js} +3 -3
- package/dist-cli/chunks/{config-K4IMJRHG.js → config-ZGOXFEX4.js} +2 -2
- package/dist-cli/chunks/{control-OXJ7S7UG.js → control-75JRFOYV.js} +2 -2
- package/dist-cli/chunks/daemon-SHFBQRHD.js +2 -0
- package/dist-cli/chunks/{debug-ZPKRTLGX.js → debug-4APEP64L.js} +3 -3
- package/dist-cli/chunks/{desktop-YA2UL7Q4.js → desktop-CS7S4CXK.js} +3 -3
- package/dist-cli/chunks/detox-7R7DOKQM.js +50 -0
- package/dist-cli/chunks/{device-M6YG7TKY.js → device-EIDKLBEK.js} +2 -2
- package/dist-cli/chunks/{diagnose-3OUFTELV.js → diagnose-J2F7MJAJ.js} +2 -2
- package/dist-cli/chunks/drivers-55L7BHDF.js +2 -0
- package/dist-cli/chunks/flow-AHWVTHJP.js +2 -0
- package/dist-cli/chunks/help-C4BTMPEE.js +2 -0
- package/dist-cli/chunks/home-paths-WVCREWI7.js +2 -0
- package/dist-cli/chunks/inspect-M4Z4SSSB.js +2 -0
- package/dist-cli/chunks/install-desktop-PVRUAEMA.js +2 -0
- package/dist-cli/chunks/{login-RNYBOMNF.js → login-EOBJ7CZ4.js} +4 -4
- package/dist-cli/chunks/{logout-XBW3BXL4.js → logout-RL7D66VQ.js} +2 -2
- package/dist-cli/chunks/maestro-F66ZIJKA.js +96 -0
- package/dist-cli/chunks/{mode-E353E6HN.js → mode-R2VIW66U.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-ILX5YV34.js +2 -0
- package/dist-cli/chunks/{perf-CIOBGFHU.js → perf-PGYO5BBR.js} +2 -2
- package/dist-cli/chunks/{record-I626AYJ5.js → record-IGDVHC67.js} +3 -3
- package/dist-cli/chunks/runtime-43RJGUGS.js +2 -0
- package/dist-cli/chunks/{screenshot-command-TTB5OOL2.js → screenshot-command-HX4GVUJM.js} +2 -2
- package/dist-cli/chunks/{serve-AEBEXTTW.js → serve-3TFVHYLY.js} +18 -18
- package/dist-cli/chunks/{setup-7QCI53ZK.js → setup-JSPPRVET.js} +3 -3
- package/dist-cli/chunks/{skills-7LHL5KHW.js → skills-LK3B76W7.js} +2 -2
- package/dist-cli/chunks/{storage-BVWLYY23.js → storage-NC5RNBUA.js} +2 -2
- package/dist-cli/chunks/store-3XMEKA6H.js +2 -0
- package/dist-cli/chunks/telemetry-CVJ5YZNS.js +2 -0
- package/dist-cli/chunks/test-2CXPLH5N.js +69 -0
- package/dist-cli/chunks/{timeline-BVR4E6PY.js → timeline-WDTEVELN.js} +2 -2
- package/dist-cli/chunks/upgrade-TT2IJSNJ.js +4 -0
- package/dist-cli/chunks/upload-4HMNB4HA.js +2 -0
- package/dist-cli/chunks/version-JUNH4FOR.js +4 -0
- package/dist-cli/chunks/{web-HYLNFAXS.js → web-BWCW26ZA.js} +2 -2
- package/dist-cli/chunks/{what-happened-YGRE2NFG.js → what-happened-L6EEB6MB.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +32 -1
- package/dist-lib/host/bridge-host.cjs +51 -2
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +115 -36
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/home-paths.ts +48 -1
- package/src/host/bridge-host.ts +12 -0
- package/src/runtime-delivery.ts +59 -9
- package/src/screenshots/frame-compose.ts +21 -13
- package/dist-cli/chunks/beta-ZXPAAXGE.js +0 -2
- package/dist-cli/chunks/chunk-CB3I3VQT.js +0 -6
- package/dist-cli/chunks/chunk-EY2OMKPT.js +0 -1
- package/dist-cli/chunks/chunk-M3AUV33V.js +0 -4
- package/dist-cli/chunks/chunk-RJ6WD7XJ.js +0 -567
- package/dist-cli/chunks/chunk-TMXLUWD2.js +0 -27
- package/dist-cli/chunks/chunk-USDJA22M.js +0 -1
- package/dist-cli/chunks/chunk-VXBWUAYL.js +0 -2
- package/dist-cli/chunks/cli-version-E3OGD447.js +0 -2
- package/dist-cli/chunks/daemon-G5GBYBJ4.js +0 -2
- package/dist-cli/chunks/detox-LKEZBGH5.js +0 -49
- package/dist-cli/chunks/drivers-CTSUKCFK.js +0 -2
- package/dist-cli/chunks/flow-R5GJJLLW.js +0 -2
- package/dist-cli/chunks/help-CSSCFOBR.js +0 -2
- package/dist-cli/chunks/home-paths-4V6CGISP.js +0 -2
- package/dist-cli/chunks/inspect-NIBEAJND.js +0 -2
- package/dist-cli/chunks/install-desktop-7TYE6TTP.js +0 -2
- package/dist-cli/chunks/maestro-3EBOG357.js +0 -96
- package/dist-cli/chunks/optional-demo-registry-BEUP6OEZ.js +0 -2
- package/dist-cli/chunks/runtime-254BNZHB.js +0 -2
- package/dist-cli/chunks/store-6KAKNNCL.js +0 -2
- package/dist-cli/chunks/telemetry-EZ42CD35.js +0 -2
- package/dist-cli/chunks/test-BK4GZZR2.js +0 -69
- package/dist-cli/chunks/upgrade-AY5XC5QI.js +0 -4
- package/dist-cli/chunks/upload-HOF4XBAG.js +0 -2
- package/dist-cli/chunks/version-WQM34S4E.js +0 -4
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.202 | (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;
|
|
@@ -10635,6 +10635,16 @@ function writeSharedConfig(patch) {
|
|
|
10635
10635
|
import_node_fs2.default.renameSync(tmp, configFilePath());
|
|
10636
10636
|
return next;
|
|
10637
10637
|
}
|
|
10638
|
+
function runtimeUpgradeNoticePath() {
|
|
10639
|
+
return import_node_path.default.join(sootsimHomeDir(), "runtime-upgraded.json");
|
|
10640
|
+
}
|
|
10641
|
+
function writeRuntimeUpgradeNotice(notice) {
|
|
10642
|
+
ensureSootsimHome();
|
|
10643
|
+
const tmp = `${runtimeUpgradeNoticePath()}.tmp`;
|
|
10644
|
+
import_node_fs2.default.writeFileSync(tmp, `${JSON.stringify(notice)}
|
|
10645
|
+
`, "utf8");
|
|
10646
|
+
import_node_fs2.default.renameSync(tmp, runtimeUpgradeNoticePath());
|
|
10647
|
+
}
|
|
10638
10648
|
function ensureSootsimHome() {
|
|
10639
10649
|
import_node_fs2.default.mkdirSync(sootsimHomeDir(), { recursive: true });
|
|
10640
10650
|
import_node_fs2.default.mkdirSync(runtimesDir(), { recursive: true });
|
|
@@ -10856,6 +10866,12 @@ function resolveRuntimeChannel(input) {
|
|
|
10856
10866
|
const config = readConfig();
|
|
10857
10867
|
return input || process.env[RUNTIME_CHANNEL_ENV] || config.runtimeChannel || "stable";
|
|
10858
10868
|
}
|
|
10869
|
+
function resolveRuntimePin() {
|
|
10870
|
+
const env = process.env[RUNTIME_PIN_ENV];
|
|
10871
|
+
if (env && env.trim()) return env.trim();
|
|
10872
|
+
const config = readConfig();
|
|
10873
|
+
return typeof config.runtimeVersion === "string" && config.runtimeVersion.trim() ? config.runtimeVersion.trim() : null;
|
|
10874
|
+
}
|
|
10859
10875
|
function runtimeManifestUrl(cdnOrigin) {
|
|
10860
10876
|
const url = new URL(`${resolveRuntimeCdnOrigin(cdnOrigin)}/runtimes/manifest.json`);
|
|
10861
10877
|
url.searchParams.set("t", String(Date.now()));
|
|
@@ -10874,7 +10890,7 @@ async function fetchRuntimeManifest(cdnOrigin) {
|
|
|
10874
10890
|
}
|
|
10875
10891
|
function resolveRuntimeVersion(manifest, opts = {}) {
|
|
10876
10892
|
const channel = resolveRuntimeChannel(opts.channel);
|
|
10877
|
-
const version = opts.version || manifest.channels[channel]?.latest;
|
|
10893
|
+
const version = opts.version || resolveRuntimePin() || manifest.channels[channel]?.latest;
|
|
10878
10894
|
if (!version) {
|
|
10879
10895
|
throw new Error(
|
|
10880
10896
|
`no version specified and channel '${channel}' has no latest entry in the manifest`
|
|
@@ -10950,6 +10966,29 @@ async function updateRuntimeToLatest(opts = {}) {
|
|
|
10950
10966
|
ensureSootsimHome();
|
|
10951
10967
|
const cdnOrigin = resolveRuntimeCdnOrigin(opts.cdnOrigin);
|
|
10952
10968
|
const channel = resolveRuntimeChannel(opts.channel);
|
|
10969
|
+
const pin = resolveRuntimePin();
|
|
10970
|
+
if (pin) {
|
|
10971
|
+
const activeVersion2 = readActiveRuntime();
|
|
10972
|
+
const pinInstalled = import_fs2.default.existsSync(import_path2.default.join(runtimeDir(pin), "index.html"));
|
|
10973
|
+
if (activeVersion2 === pin && pinInstalled) {
|
|
10974
|
+
return {
|
|
10975
|
+
checked: true,
|
|
10976
|
+
updated: false,
|
|
10977
|
+
reason: `runtime is pinned to ${pin}`,
|
|
10978
|
+
activeVersion: activeVersion2,
|
|
10979
|
+
latestVersion: pin
|
|
10980
|
+
};
|
|
10981
|
+
}
|
|
10982
|
+
const install2 = await installRuntime({ version: pin, channel, cdnOrigin, setActive: false });
|
|
10983
|
+
return {
|
|
10984
|
+
checked: true,
|
|
10985
|
+
updated: true,
|
|
10986
|
+
reason: `runtime is pinned to ${pin}`,
|
|
10987
|
+
activeVersion: pin,
|
|
10988
|
+
latestVersion: pin,
|
|
10989
|
+
install: install2
|
|
10990
|
+
};
|
|
10991
|
+
}
|
|
10953
10992
|
const manifest = await fetchRuntimeManifest(cdnOrigin);
|
|
10954
10993
|
const latestVersion = manifest.channels[channel]?.latest;
|
|
10955
10994
|
if (!latestVersion) {
|
|
@@ -11039,7 +11078,7 @@ function extractTarball(tarPath, destDir) {
|
|
|
11039
11078
|
});
|
|
11040
11079
|
});
|
|
11041
11080
|
}
|
|
11042
|
-
var import_child_process2, import_crypto, import_fs2, import_path2, import_stream, import_promises, DEFAULT_RUNTIME_CDN_ORIGIN, RUNTIME_CDN_ORIGIN_ENV, RUNTIME_CHANNEL_ENV;
|
|
11081
|
+
var import_child_process2, import_crypto, import_fs2, import_path2, import_stream, import_promises, DEFAULT_RUNTIME_CDN_ORIGIN, RUNTIME_CDN_ORIGIN_ENV, RUNTIME_CHANNEL_ENV, RUNTIME_PIN_ENV;
|
|
11043
11082
|
var init_runtime_delivery = __esm({
|
|
11044
11083
|
"src/runtime-delivery.ts"() {
|
|
11045
11084
|
"use strict";
|
|
@@ -11053,6 +11092,7 @@ var init_runtime_delivery = __esm({
|
|
|
11053
11092
|
DEFAULT_RUNTIME_CDN_ORIGIN = "https://sootbean.com";
|
|
11054
11093
|
RUNTIME_CDN_ORIGIN_ENV = "SOOTSIM_CDN_ORIGIN";
|
|
11055
11094
|
RUNTIME_CHANNEL_ENV = "SOOTSIM_RUNTIME_CHANNEL";
|
|
11095
|
+
RUNTIME_PIN_ENV = "SOOTSIM_RUNTIME_VERSION";
|
|
11056
11096
|
}
|
|
11057
11097
|
});
|
|
11058
11098
|
|
|
@@ -13867,9 +13907,18 @@ var init_bridge_host = __esm({
|
|
|
13867
13907
|
}
|
|
13868
13908
|
return;
|
|
13869
13909
|
}
|
|
13910
|
+
const previousVersion = this.activeRuntimeVersion;
|
|
13870
13911
|
const active = this.setActiveRuntime(result.latestVersion);
|
|
13871
13912
|
process.stderr.write(`sootsim runtime updated to ${active.version} (${reason})
|
|
13872
13913
|
`);
|
|
13914
|
+
try {
|
|
13915
|
+
writeRuntimeUpgradeNotice({
|
|
13916
|
+
from: previousVersion,
|
|
13917
|
+
to: active.version,
|
|
13918
|
+
at: Date.now()
|
|
13919
|
+
});
|
|
13920
|
+
} catch {
|
|
13921
|
+
}
|
|
13873
13922
|
} catch (err) {
|
|
13874
13923
|
process.stderr.write(
|
|
13875
13924
|
`sootsim runtime update failed (${reason}): ${err instanceof Error ? err.message : String(err)}
|
|
@@ -15542,18 +15591,18 @@ var init_ws_bridge = __esm({
|
|
|
15542
15591
|
function getFramedScreenshotLayout(model) {
|
|
15543
15592
|
const spec = (0, import_settings.getDevice)(model);
|
|
15544
15593
|
const renderScale = spec.scale;
|
|
15545
|
-
const isLegacyHardware = !spec.dynamicIsland && spec.homeIndicatorHeight === 0 && spec.cornerRadius === 0;
|
|
15594
|
+
const isLegacyHardware = spec.statusBarHeight > 0 && !spec.dynamicIsland && spec.homeIndicatorHeight === 0 && spec.cornerRadius === 0;
|
|
15546
15595
|
const logicalScreenWidth = spec.width;
|
|
15547
15596
|
const logicalScreenHeight = spec.height;
|
|
15548
|
-
const logicalFrameWidth = isLegacyHardware ? spec.width + LEGACY_SIDE_BEZEL * 2 : spec.width +
|
|
15549
|
-
const logicalFrameHeight = isLegacyHardware ? spec.height + LEGACY_TOP_BEZEL + LEGACY_BOTTOM_BEZEL : spec.height +
|
|
15597
|
+
const logicalFrameWidth = isLegacyHardware ? spec.width + import_chrome_metrics.LEGACY_SIDE_BEZEL * 2 : spec.width + spec.bezelWidth * 2;
|
|
15598
|
+
const logicalFrameHeight = isLegacyHardware ? spec.height + import_chrome_metrics.LEGACY_TOP_BEZEL + import_chrome_metrics.LEGACY_BOTTOM_BEZEL : spec.height + spec.bezelWidth * 2;
|
|
15550
15599
|
const logicalFrameLeft = import_chrome_metrics.SIDE_BUTTON_RESERVE;
|
|
15551
15600
|
const logicalFrameTop = FRAME_OUTLINE_BLEED;
|
|
15552
15601
|
const logicalOuterWidth = logicalFrameWidth + logicalFrameLeft * 2;
|
|
15553
15602
|
const logicalOuterHeight = logicalFrameHeight + FRAME_OUTLINE_BLEED * 2;
|
|
15554
|
-
const logicalScreenLeft = logicalFrameLeft + (isLegacyHardware ? LEGACY_SIDE_BEZEL :
|
|
15555
|
-
const logicalScreenTop = isLegacyHardware ? LEGACY_TOP_BEZEL :
|
|
15556
|
-
const logicalFrameRadius = isLegacyHardware ? LEGACY_FRAME_RADIUS : spec.cornerRadius +
|
|
15603
|
+
const logicalScreenLeft = logicalFrameLeft + (isLegacyHardware ? import_chrome_metrics.LEGACY_SIDE_BEZEL : spec.bezelWidth);
|
|
15604
|
+
const logicalScreenTop = isLegacyHardware ? import_chrome_metrics.LEGACY_TOP_BEZEL : spec.bezelWidth;
|
|
15605
|
+
const logicalFrameRadius = isLegacyHardware ? import_chrome_metrics.LEGACY_FRAME_RADIUS : spec.cornerRadius + spec.bezelWidth;
|
|
15557
15606
|
const buttons = [
|
|
15558
15607
|
{
|
|
15559
15608
|
side: "right",
|
|
@@ -15602,10 +15651,10 @@ function getFramedScreenshotLayout(model) {
|
|
|
15602
15651
|
metallicRingShadow: isLegacyHardware ? null : METALLIC_RING_SHADOW,
|
|
15603
15652
|
buttons,
|
|
15604
15653
|
legacyHomeButton: isLegacyHardware ? {
|
|
15605
|
-
top: LEGACY_TOP_BEZEL + spec.height + (LEGACY_BOTTOM_BEZEL - LEGACY_HOME_BUTTON_SIZE) / 2,
|
|
15606
|
-
left: spec.width / 2 - LEGACY_HOME_BUTTON_SIZE / 2 + LEGACY_SIDE_BEZEL,
|
|
15607
|
-
size: LEGACY_HOME_BUTTON_SIZE,
|
|
15608
|
-
ring: LEGACY_HOME_BUTTON_RING
|
|
15654
|
+
top: import_chrome_metrics.LEGACY_TOP_BEZEL + spec.height + (import_chrome_metrics.LEGACY_BOTTOM_BEZEL - import_chrome_metrics.LEGACY_HOME_BUTTON_SIZE) / 2,
|
|
15655
|
+
left: spec.width / 2 - import_chrome_metrics.LEGACY_HOME_BUTTON_SIZE / 2 + import_chrome_metrics.LEGACY_SIDE_BEZEL,
|
|
15656
|
+
size: import_chrome_metrics.LEGACY_HOME_BUTTON_SIZE,
|
|
15657
|
+
ring: import_chrome_metrics.LEGACY_HOME_BUTTON_RING
|
|
15609
15658
|
} : null,
|
|
15610
15659
|
showHomeIndicator: spec.homeIndicatorHeight > 0,
|
|
15611
15660
|
logicalHomeIndicatorStripHeight: spec.homeIndicatorHeight
|
|
@@ -15857,18 +15906,12 @@ async function createFramedScreenshotComposer(browser) {
|
|
|
15857
15906
|
}
|
|
15858
15907
|
};
|
|
15859
15908
|
}
|
|
15860
|
-
var import_chrome_metrics, import_settings,
|
|
15909
|
+
var import_chrome_metrics, import_settings, METALLIC_RING_SHADOW, FRAME_OUTLINE_BLEED;
|
|
15861
15910
|
var init_frame_compose = __esm({
|
|
15862
15911
|
"src/screenshots/frame-compose.ts"() {
|
|
15863
15912
|
"use strict";
|
|
15864
15913
|
import_chrome_metrics = require("sootsim-engine/ios/chrome-metrics");
|
|
15865
15914
|
import_settings = require("sootsim-engine/settings");
|
|
15866
|
-
LEGACY_FRAME_RADIUS = 52;
|
|
15867
|
-
LEGACY_SIDE_BEZEL = 18;
|
|
15868
|
-
LEGACY_TOP_BEZEL = 42;
|
|
15869
|
-
LEGACY_BOTTOM_BEZEL = 96;
|
|
15870
|
-
LEGACY_HOME_BUTTON_SIZE = 54;
|
|
15871
|
-
LEGACY_HOME_BUTTON_RING = 1.5;
|
|
15872
15915
|
METALLIC_RING_SHADOW = "inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121";
|
|
15873
15916
|
FRAME_OUTLINE_BLEED = 1;
|
|
15874
15917
|
}
|
|
@@ -18665,6 +18708,9 @@ var init_bridge_flow_runner = __esm({
|
|
|
18665
18708
|
throw new Error(`unsupported flow step: ${JSON.stringify(step)}`);
|
|
18666
18709
|
}
|
|
18667
18710
|
}
|
|
18711
|
+
// live progress reporter (shell devtools "test" tab). attached by
|
|
18712
|
+
// runFlowPlayback; absent for programmatic callers.
|
|
18713
|
+
liveStatus = null;
|
|
18668
18714
|
async runFlow(steps) {
|
|
18669
18715
|
const onStart = [];
|
|
18670
18716
|
const onComplete = [];
|
|
@@ -18681,6 +18727,15 @@ var init_bridge_flow_runner = __esm({
|
|
|
18681
18727
|
}
|
|
18682
18728
|
body.push(step);
|
|
18683
18729
|
}
|
|
18730
|
+
if (this.liveStatus) {
|
|
18731
|
+
await this.liveStatus.plan(
|
|
18732
|
+
body.map((rawStep, index) => {
|
|
18733
|
+
const step = typeof rawStep === "string" ? normalizeBareStringStep(rawStep) : rawStep;
|
|
18734
|
+
const name = Object.keys(step).find((k) => k !== "when") ?? Object.keys(step)[0];
|
|
18735
|
+
return { index, name, target: this.flowStepTargetLabel(step, name) };
|
|
18736
|
+
})
|
|
18737
|
+
);
|
|
18738
|
+
}
|
|
18684
18739
|
if (onStart.length > 0) {
|
|
18685
18740
|
console.log(`[flow] onFlowStart (${onStart.length} steps)`);
|
|
18686
18741
|
for (let i = 0; i < onStart.length; i++) {
|
|
@@ -18713,23 +18768,47 @@ var init_bridge_flow_runner = __esm({
|
|
|
18713
18768
|
const explicitWait = typeof step.wait === "number" ? step.wait : 0;
|
|
18714
18769
|
const waitForTimeout = typeof step.waitFor?.timeout === "number" ? step.waitFor.timeout : 0;
|
|
18715
18770
|
const stepCeiling = Math.max(6e4, explicitWait + 15e3, waitForTimeout + 15e3);
|
|
18716
|
-
if (
|
|
18717
|
-
await this.
|
|
18718
|
-
|
|
18719
|
-
}
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
|
|
18723
|
-
|
|
18724
|
-
|
|
18725
|
-
|
|
18726
|
-
|
|
18771
|
+
if (this.liveStatus) {
|
|
18772
|
+
await this.liveStatus.waitWhilePaused();
|
|
18773
|
+
await this.liveStatus.step(i, "running");
|
|
18774
|
+
}
|
|
18775
|
+
const liveStartedAtMs = Date.now();
|
|
18776
|
+
const reportOutcome = async (failed, error) => {
|
|
18777
|
+
if (!this.liveStatus) return;
|
|
18778
|
+
const last = this.flowTraceSteps[this.flowTraceSteps.length - 1];
|
|
18779
|
+
const traced = last && last.stepIndex === i && last.startedAtMs >= liveStartedAtMs;
|
|
18780
|
+
await this.liveStatus.step(
|
|
18781
|
+
i,
|
|
18782
|
+
failed ? "failure" : traced && last.status === "skipped" ? "skipped" : "success",
|
|
18783
|
+
{
|
|
18784
|
+
durationMs: Date.now() - liveStartedAtMs,
|
|
18785
|
+
error: failed ? error instanceof Error ? error.message.slice(0, 300) : String(error).slice(0, 300) : traced && last.error || void 0
|
|
18786
|
+
}
|
|
18787
|
+
);
|
|
18788
|
+
};
|
|
18789
|
+
try {
|
|
18790
|
+
if (step.runFlow || step.launchApp) {
|
|
18791
|
+
await this.runStep(step, i);
|
|
18792
|
+
} else {
|
|
18793
|
+
await Promise.race([
|
|
18794
|
+
this.runStep(step, i),
|
|
18795
|
+
new Promise(
|
|
18796
|
+
(_, reject) => setTimeout(
|
|
18797
|
+
() => reject(
|
|
18798
|
+
new Error(
|
|
18799
|
+
`step ${i + 1} (${Object.keys(step)[0]}) exceeded ${stepCeiling}ms deadline`
|
|
18800
|
+
)
|
|
18801
|
+
),
|
|
18802
|
+
stepCeiling
|
|
18727
18803
|
)
|
|
18728
|
-
)
|
|
18729
|
-
|
|
18730
|
-
|
|
18731
|
-
|
|
18732
|
-
|
|
18804
|
+
)
|
|
18805
|
+
]);
|
|
18806
|
+
}
|
|
18807
|
+
} catch (error) {
|
|
18808
|
+
await reportOutcome(true, error);
|
|
18809
|
+
throw error;
|
|
18810
|
+
}
|
|
18811
|
+
await reportOutcome(false);
|
|
18733
18812
|
}
|
|
18734
18813
|
}
|
|
18735
18814
|
};
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.202 | (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
package/src/home-paths.ts
CHANGED
|
@@ -15,7 +15,11 @@
|
|
|
15
15
|
// │ └── sootsim-runtime-<version>.tar.gz
|
|
16
16
|
// ├── daemon.json lockfile: pid, ports, active runtime, heartbeat
|
|
17
17
|
// ├── dev-bridge.json live Vite dev bridge pointer for local CLI commands
|
|
18
|
-
//
|
|
18
|
+
// ├── runtime-upgraded.json one-shot notice written by the daemon's
|
|
19
|
+
// │ background updater, consumed (printed + deleted)
|
|
20
|
+
// │ by the next interactive CLI run
|
|
21
|
+
// └── config.json user prefs: runtime pin, update channel, cdn
|
|
22
|
+
// origin override, telemetry, engine settings
|
|
19
23
|
|
|
20
24
|
import { randomUUID } from 'node:crypto'
|
|
21
25
|
import fs from 'node:fs'
|
|
@@ -232,6 +236,49 @@ export function writeTelemetryEnabled(enabled: boolean): void {
|
|
|
232
236
|
writeSharedConfig({ telemetry: enabled })
|
|
233
237
|
}
|
|
234
238
|
|
|
239
|
+
// --- background-upgrade notice --------------------------------------------
|
|
240
|
+
//
|
|
241
|
+
// the daemon auto-updates the engine runtime in the background (hourly), so
|
|
242
|
+
// the only place its "updated to vX" line lands is the daemon's own stderr,
|
|
243
|
+
// which nobody reads. it also drops a one-shot notice file here; the next
|
|
244
|
+
// interactive CLI invocation prints it once and deletes it, so users learn
|
|
245
|
+
// their engine moved without having to run `sootsim version`.
|
|
246
|
+
|
|
247
|
+
export interface RuntimeUpgradeNotice {
|
|
248
|
+
from: string | null
|
|
249
|
+
to: string
|
|
250
|
+
at: number
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function runtimeUpgradeNoticePath(): string {
|
|
254
|
+
return path.join(sootsimHomeDir(), 'runtime-upgraded.json')
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function writeRuntimeUpgradeNotice(notice: RuntimeUpgradeNotice): void {
|
|
258
|
+
ensureSootsimHome()
|
|
259
|
+
const tmp = `${runtimeUpgradeNoticePath()}.tmp`
|
|
260
|
+
fs.writeFileSync(tmp, `${JSON.stringify(notice)}\n`, 'utf8')
|
|
261
|
+
fs.renameSync(tmp, runtimeUpgradeNoticePath())
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** read + delete the pending upgrade notice, or null when none is pending.
|
|
265
|
+
* deleting first-read keeps the banner one-shot even across racing CLIs. */
|
|
266
|
+
export function consumeRuntimeUpgradeNotice(): RuntimeUpgradeNotice | null {
|
|
267
|
+
try {
|
|
268
|
+
const raw = fs.readFileSync(runtimeUpgradeNoticePath(), 'utf8')
|
|
269
|
+
fs.unlinkSync(runtimeUpgradeNoticePath())
|
|
270
|
+
const parsed = JSON.parse(raw) as Partial<RuntimeUpgradeNotice>
|
|
271
|
+
if (typeof parsed?.to !== 'string' || !parsed.to) return null
|
|
272
|
+
return {
|
|
273
|
+
from: typeof parsed.from === 'string' ? parsed.from : null,
|
|
274
|
+
to: parsed.to,
|
|
275
|
+
at: typeof parsed.at === 'number' ? parsed.at : 0,
|
|
276
|
+
}
|
|
277
|
+
} catch {
|
|
278
|
+
return null
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
235
282
|
export function ensureSootsimHome(): void {
|
|
236
283
|
fs.mkdirSync(sootsimHomeDir(), { recursive: true })
|
|
237
284
|
fs.mkdirSync(runtimesDir(), { recursive: true })
|
package/src/host/bridge-host.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
writeActiveRuntime,
|
|
26
26
|
writeDaemonLockfile,
|
|
27
27
|
writeDevBridgeLockfile,
|
|
28
|
+
writeRuntimeUpgradeNotice,
|
|
28
29
|
writeSharedConfig,
|
|
29
30
|
type DaemonLockfile,
|
|
30
31
|
type DevBridgeLockfile,
|
|
@@ -1283,8 +1284,19 @@ export class SootSimBridgeHost {
|
|
|
1283
1284
|
}
|
|
1284
1285
|
return
|
|
1285
1286
|
}
|
|
1287
|
+
const previousVersion = this.activeRuntimeVersion
|
|
1286
1288
|
const active = this.setActiveRuntime(result.latestVersion)
|
|
1287
1289
|
process.stderr.write(`sootsim runtime updated to ${active.version} (${reason})\n`)
|
|
1290
|
+
// the daemon's stderr goes to a log nobody watches — drop a one-shot
|
|
1291
|
+
// notice so the next interactive CLI run tells the user their engine
|
|
1292
|
+
// moved (consumed + deleted by bin.ts).
|
|
1293
|
+
try {
|
|
1294
|
+
writeRuntimeUpgradeNotice({
|
|
1295
|
+
from: previousVersion,
|
|
1296
|
+
to: active.version,
|
|
1297
|
+
at: Date.now(),
|
|
1298
|
+
})
|
|
1299
|
+
} catch {}
|
|
1288
1300
|
} catch (err) {
|
|
1289
1301
|
process.stderr.write(
|
|
1290
1302
|
`sootsim runtime update failed (${reason}): ${
|
package/src/runtime-delivery.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
export const DEFAULT_RUNTIME_CDN_ORIGIN = 'https://sootbean.com'
|
|
18
18
|
export const RUNTIME_CDN_ORIGIN_ENV = 'SOOTSIM_CDN_ORIGIN'
|
|
19
19
|
export const RUNTIME_CHANNEL_ENV = 'SOOTSIM_RUNTIME_CHANNEL'
|
|
20
|
+
export const RUNTIME_PIN_ENV = 'SOOTSIM_RUNTIME_VERSION'
|
|
20
21
|
|
|
21
22
|
export interface RuntimeManifestChannel {
|
|
22
23
|
latest: string
|
|
@@ -70,6 +71,7 @@ export interface RuntimeUpdateResult {
|
|
|
70
71
|
|
|
71
72
|
interface SootsimConfig {
|
|
72
73
|
runtimeChannel?: string
|
|
74
|
+
runtimeVersion?: string
|
|
73
75
|
cdnOrigin?: string
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -97,6 +99,18 @@ export function resolveRuntimeChannel(input?: string): string {
|
|
|
97
99
|
return input || process.env[RUNTIME_CHANNEL_ENV] || config.runtimeChannel || 'stable'
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
/** pinned runtime version, or null when following the channel's latest.
|
|
103
|
+
* env wins over config so CI can pin per-invocation; the persistent pin
|
|
104
|
+
* lives in ~/.sootsim/config.json (`sootsim runtime pin <version>`). */
|
|
105
|
+
export function resolveRuntimePin(): string | null {
|
|
106
|
+
const env = process.env[RUNTIME_PIN_ENV]
|
|
107
|
+
if (env && env.trim()) return env.trim()
|
|
108
|
+
const config = readConfig()
|
|
109
|
+
return typeof config.runtimeVersion === 'string' && config.runtimeVersion.trim()
|
|
110
|
+
? config.runtimeVersion.trim()
|
|
111
|
+
: null
|
|
112
|
+
}
|
|
113
|
+
|
|
100
114
|
export function runtimeManifestUrl(cdnOrigin?: string): string {
|
|
101
115
|
const url = new URL(`${resolveRuntimeCdnOrigin(cdnOrigin)}/runtimes/manifest.json`)
|
|
102
116
|
// cdn edges can keep the no-query manifest around longer than its
|
|
@@ -123,7 +137,7 @@ export function resolveRuntimeVersion(
|
|
|
123
137
|
opts: Pick<RuntimeInstallOptions, 'version' | 'channel'> = {},
|
|
124
138
|
): { version: string; channel: string; entry: RuntimeManifestVersion } {
|
|
125
139
|
const channel = resolveRuntimeChannel(opts.channel)
|
|
126
|
-
const version = opts.version || manifest.channels[channel]?.latest
|
|
140
|
+
const version = opts.version || resolveRuntimePin() || manifest.channels[channel]?.latest
|
|
127
141
|
if (!version) {
|
|
128
142
|
throw new Error(
|
|
129
143
|
`no version specified and channel '${channel}' has no latest entry in the manifest`,
|
|
@@ -211,6 +225,34 @@ export async function updateRuntimeToLatest(
|
|
|
211
225
|
ensureSootsimHome()
|
|
212
226
|
const cdnOrigin = resolveRuntimeCdnOrigin(opts.cdnOrigin)
|
|
213
227
|
const channel = resolveRuntimeChannel(opts.channel)
|
|
228
|
+
|
|
229
|
+
// a pinned runtime never follows the channel. when the pin is already
|
|
230
|
+
// active + on disk this is a no-network no-op; otherwise install exactly
|
|
231
|
+
// the pinned version (it must still exist in the hosted manifest).
|
|
232
|
+
const pin = resolveRuntimePin()
|
|
233
|
+
if (pin) {
|
|
234
|
+
const activeVersion = readActiveRuntime()
|
|
235
|
+
const pinInstalled = fs.existsSync(path.join(runtimeDir(pin), 'index.html'))
|
|
236
|
+
if (activeVersion === pin && pinInstalled) {
|
|
237
|
+
return {
|
|
238
|
+
checked: true,
|
|
239
|
+
updated: false,
|
|
240
|
+
reason: `runtime is pinned to ${pin}`,
|
|
241
|
+
activeVersion,
|
|
242
|
+
latestVersion: pin,
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const install = await installRuntime({ version: pin, channel, cdnOrigin, setActive: false })
|
|
246
|
+
return {
|
|
247
|
+
checked: true,
|
|
248
|
+
updated: true,
|
|
249
|
+
reason: `runtime is pinned to ${pin}`,
|
|
250
|
+
activeVersion: pin,
|
|
251
|
+
latestVersion: pin,
|
|
252
|
+
install,
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
214
256
|
const manifest = await fetchRuntimeManifest(cdnOrigin)
|
|
215
257
|
const latestVersion = manifest.channels[channel]?.latest
|
|
216
258
|
if (!latestVersion) {
|
|
@@ -272,27 +314,35 @@ export async function updateRuntimeToLatest(
|
|
|
272
314
|
export interface RuntimeUpToDateCheck {
|
|
273
315
|
active: string | null
|
|
274
316
|
latest: string | null
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
|
|
317
|
+
// pinned version when one is set — a pinned runtime is only "outdated"
|
|
318
|
+
// when the pin itself isn't active yet, never against channel latest.
|
|
319
|
+
pinned: string | null
|
|
320
|
+
// true only when a target version is known and it is newer than / not
|
|
321
|
+
// the active one (or nothing is active yet). network failures resolve
|
|
322
|
+
// to false so callers can treat this as a best-effort hint.
|
|
278
323
|
outdated: boolean
|
|
279
324
|
}
|
|
280
325
|
|
|
281
|
-
/** read-only check: is the active runtime the latest on its channel
|
|
282
|
-
* unlike updateRuntimeToLatest this never downloads
|
|
283
|
-
* for surfacing a "newer runtime available" hint at
|
|
326
|
+
/** read-only check: is the active runtime the latest on its channel (or,
|
|
327
|
+
* when pinned, the pin)? unlike updateRuntimeToLatest this never downloads
|
|
328
|
+
* or activates — it's for surfacing a "newer runtime available" hint at
|
|
329
|
+
* startup / in help. */
|
|
284
330
|
export async function checkRuntimeUpToDate(
|
|
285
331
|
opts: Pick<RuntimeInstallOptions, 'channel' | 'cdnOrigin'> = {},
|
|
286
332
|
): Promise<RuntimeUpToDateCheck> {
|
|
287
333
|
const active = readActiveRuntime()
|
|
334
|
+
const pinned = resolveRuntimePin()
|
|
335
|
+
if (pinned) {
|
|
336
|
+
return { active, latest: pinned, pinned, outdated: active !== pinned }
|
|
337
|
+
}
|
|
288
338
|
try {
|
|
289
339
|
const manifest = await fetchRuntimeManifest(resolveRuntimeCdnOrigin(opts.cdnOrigin))
|
|
290
340
|
const channel = resolveRuntimeChannel(opts.channel)
|
|
291
341
|
const latest = manifest.channels[channel]?.latest ?? null
|
|
292
342
|
const outdated = !!(latest && (!active || compareSemver(latest, active) > 0))
|
|
293
|
-
return { active, latest, outdated }
|
|
343
|
+
return { active, latest, pinned: null, outdated }
|
|
294
344
|
} catch {
|
|
295
|
-
return { active, latest: null, outdated: false }
|
|
345
|
+
return { active, latest: null, pinned: null, outdated: false }
|
|
296
346
|
}
|
|
297
347
|
}
|
|
298
348
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
LEGACY_BOTTOM_BEZEL,
|
|
3
|
+
LEGACY_FRAME_RADIUS,
|
|
4
|
+
LEGACY_HOME_BUTTON_RING,
|
|
5
|
+
LEGACY_HOME_BUTTON_SIZE,
|
|
6
|
+
LEGACY_SIDE_BEZEL,
|
|
7
|
+
LEGACY_TOP_BEZEL,
|
|
8
|
+
SIDE_BUTTON_RESERVE,
|
|
9
|
+
} from 'sootsim-engine/ios/chrome-metrics'
|
|
2
10
|
import { getDevice, type DeviceModel } from 'sootsim-engine/settings'
|
|
3
11
|
|
|
4
|
-
const LEGACY_FRAME_RADIUS = 52
|
|
5
|
-
const LEGACY_SIDE_BEZEL = 18
|
|
6
|
-
const LEGACY_TOP_BEZEL = 42
|
|
7
|
-
const LEGACY_BOTTOM_BEZEL = 96
|
|
8
|
-
const LEGACY_HOME_BUTTON_SIZE = 54
|
|
9
|
-
const LEGACY_HOME_BUTTON_RING = 1.5
|
|
10
12
|
const METALLIC_RING_SHADOW =
|
|
11
13
|
'inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121'
|
|
12
14
|
const FRAME_OUTLINE_BLEED = 1
|
|
@@ -59,26 +61,32 @@ export interface FramedScreenshotLayout {
|
|
|
59
61
|
export function getFramedScreenshotLayout(model: DeviceModel): FramedScreenshotLayout {
|
|
60
62
|
const spec = getDevice(model)
|
|
61
63
|
const renderScale = spec.scale
|
|
64
|
+
// legacy = home-button iPhone (SE). the canvas workspace also has no island /
|
|
65
|
+
// home indicator / corner radius, but no status bar, so gate on statusBar > 0
|
|
66
|
+
// to keep it out of the SE shell (mirrors DeviceFrame.isLegacyHardware).
|
|
62
67
|
const isLegacyHardware =
|
|
63
|
-
|
|
68
|
+
spec.statusBarHeight > 0 &&
|
|
69
|
+
!spec.dynamicIsland &&
|
|
70
|
+
spec.homeIndicatorHeight === 0 &&
|
|
71
|
+
spec.cornerRadius === 0
|
|
64
72
|
const logicalScreenWidth = spec.width
|
|
65
73
|
const logicalScreenHeight = spec.height
|
|
66
74
|
const logicalFrameWidth = isLegacyHardware
|
|
67
75
|
? spec.width + LEGACY_SIDE_BEZEL * 2
|
|
68
|
-
: spec.width +
|
|
76
|
+
: spec.width + spec.bezelWidth * 2
|
|
69
77
|
const logicalFrameHeight = isLegacyHardware
|
|
70
78
|
? spec.height + LEGACY_TOP_BEZEL + LEGACY_BOTTOM_BEZEL
|
|
71
|
-
: spec.height +
|
|
79
|
+
: spec.height + spec.bezelWidth * 2
|
|
72
80
|
const logicalFrameLeft = SIDE_BUTTON_RESERVE
|
|
73
81
|
const logicalFrameTop = FRAME_OUTLINE_BLEED
|
|
74
82
|
const logicalOuterWidth = logicalFrameWidth + logicalFrameLeft * 2
|
|
75
83
|
const logicalOuterHeight = logicalFrameHeight + FRAME_OUTLINE_BLEED * 2
|
|
76
84
|
const logicalScreenLeft =
|
|
77
|
-
logicalFrameLeft + (isLegacyHardware ? LEGACY_SIDE_BEZEL :
|
|
78
|
-
const logicalScreenTop = isLegacyHardware ? LEGACY_TOP_BEZEL :
|
|
85
|
+
logicalFrameLeft + (isLegacyHardware ? LEGACY_SIDE_BEZEL : spec.bezelWidth)
|
|
86
|
+
const logicalScreenTop = isLegacyHardware ? LEGACY_TOP_BEZEL : spec.bezelWidth
|
|
79
87
|
const logicalFrameRadius = isLegacyHardware
|
|
80
88
|
? LEGACY_FRAME_RADIUS
|
|
81
|
-
: spec.cornerRadius +
|
|
89
|
+
: spec.cornerRadius + spec.bezelWidth
|
|
82
90
|
const buttons: FrameButtonLayout[] = [
|
|
83
91
|
{
|
|
84
92
|
side: 'right',
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.200 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{randomUUID as I}from"node:crypto";import t from"node:fs";import{homedir as E}from"node:os";import o from"node:path";var _="SOOTSIM_HOME",N="active",P="daemon.json",j="dev-bridge.json",F="config.json",k=3e4;function u(){let e=process.env[_];return e&&e.length>0?o.resolve(e):o.join(E(),".sootsim")}function w(){if(process.env.SOOTSIM_FORCE_DAEMON_INSTALL==="1")return!1;let e=process.env.SOOTSIM_DEV;if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;let r=process.argv[1];if(!r)return!1;try{return t.realpathSync(r).includes(`${o.sep}packages${o.sep}sootsim${o.sep}`)}catch{return!1}}function T(){return process.env.SOOTSIM_FORCE_DAEMON_INSTALL==="1"?!1:process.env.IS_TAMAGUI_DEV==="1"}function q(){return w()||T()}function f(){return o.join(u(),"runtimes")}function B(e){return o.join(f(),e)}function L(){return o.join(f(),N)}function D(){return o.join(u(),"electron")}function z(){return o.join(D(),"userData")}function Q(e){return o.join(D(),e)}function C(){return o.join(u(),"profiles")}function M(){return o.join(u(),"daemon-app")}function R(){return o.join(M(),"SootSim Daemon.app")}function Z(){return o.join(R(),"Contents","MacOS","sootsim-daemon")}function $(){return o.join(u(),"cache")}function p(){return o.join(u(),P)}function m(){return o.join(u(),j)}function b(){return o.join(u(),F)}function h(){try{let e=t.readFileSync(b(),"utf8"),r=JSON.parse(e);return r&&typeof r=="object"?r:{}}catch{return{}}}function O(e){g();let r=h(),i={...r,...e};e.settings&&typeof e.settings=="object"&&(i.settings={...r.settings&&typeof r.settings=="object"?r.settings:{},...e.settings});let c=`${b()}.tmp`;return t.writeFileSync(c,`${JSON.stringify(i,null,2)}
|
|
3
|
-
`,"utf8"),t.renameSync(c,b()),i}function ee(){return h().telemetry!==!1}function re(){let e=h().anonymousId;if(typeof e=="string"&&e.trim())return e;let r=`anon-cli-${I()}`;return O({anonymousId:r}),r}function te(e){O({telemetry:e})}function g(){t.mkdirSync(u(),{recursive:!0}),t.mkdirSync(f(),{recursive:!0}),t.mkdirSync(D(),{recursive:!0}),t.mkdirSync(C(),{recursive:!0}),t.mkdirSync($(),{recursive:!0})}function J(){try{let e=t.readFileSync(L(),"utf8").trim();return e.length>0?e:null}catch{return null}}function ne(e){t.mkdirSync(f(),{recursive:!0}),t.writeFileSync(L(),`${e}
|
|
4
|
-
`,"utf8")}function oe(){try{return t.readdirSync(f(),{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).sort(V)}catch{return[]}}function V(e,r){let i=s=>{let a=s.indexOf("-"),l=a>=0?s.slice(0,a):s,A=a>=0?s.slice(a+1):"",x=l.split(".").map(S=>Number.parseInt(S,10));return x.some(S=>!Number.isFinite(S))?[[Number.POSITIVE_INFINITY],s]:[x,A]},[c,n]=i(e),[v,y]=i(r);for(let s=0;s<Math.max(c.length,v.length);s++){let a=c[s]??0,l=v[s]??0;if(a!==l)return a-l}return n===y?0:n?y?n<y?-1:1:-1:1}function ie(){let e=J();if(!e)return null;let r=B(e);try{if(t.statSync(r).isDirectory())return r}catch{}return null}var d=16*1024;function H(){try{let e=t.openSync(p(),"r");try{let r=Buffer.alloc(d),i=t.readSync(e,r,0,d,0),c=r.subarray(0,i).toString("utf8"),n=JSON.parse(c);return n&&n.schema===1&&typeof n.pid=="number"&&typeof n.bridgePort=="number"&&typeof n.runtimePort=="number"&&typeof n.startedAt=="number"&&typeof n.heartbeatAt=="number"?n:null}finally{t.closeSync(e)}}catch{return null}}function se(){try{let e=t.openSync(m(),"r");try{let r=Buffer.alloc(d),i=t.readSync(e,r,0,d,0),c=r.subarray(0,i).toString("utf8"),n=JSON.parse(c);return n&&n.schema===1&&n.source==="vite-dev"&&typeof n.pid=="number"&&typeof n.bridgePort=="number"&&typeof n.runtimePort=="number"&&typeof n.cwd=="string"&&typeof n.startedAt=="number"&&typeof n.heartbeatAt=="number"&&(n.shellPort===void 0||typeof n.shellPort=="number")?n:null}finally{t.closeSync(e)}}catch{return null}}function U(e,r=Date.now()){if(!e||r-e.heartbeatAt>k)return!1;try{return process.kill(e.pid,0),!0}catch{return!1}}function ce(e,r=Date.now()){if(!e||r-e.heartbeatAt>k)return!1;try{return process.kill(e.pid,0),!0}catch{return!1}}function G(e){g();let r=`${p()}.tmp`;t.writeFileSync(r,`${JSON.stringify(e,null,2)}
|
|
5
|
-
`,"utf8"),t.renameSync(r,p())}function ue(e){g();let r=`${m()}.tmp`;t.writeFileSync(r,`${JSON.stringify(e,null,2)}
|
|
6
|
-
`,"utf8"),t.renameSync(r,m())}function ae(e){g();let r=H();return r&&U(r)&&r.pid!==e.pid?!1:(G(e),!0)}function fe(){try{t.unlinkSync(p())}catch{}}function le(){try{t.unlinkSync(m())}catch{}}export{_ as a,N as b,P as c,j as d,F as e,k as f,u as g,w as h,T as i,q as j,f as k,B as l,L as m,D as n,z as o,Q as p,C as q,M as r,R as s,Z as t,$ as u,p as v,m as w,b as x,h as y,O as z,ee as A,re as B,te as C,g as D,J as E,ne as F,oe as G,V as H,ie as I,H as J,se as K,U as L,ce as M,G as N,ue as O,ae as P,fe as Q,le as R};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.200 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.200 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{D as v,E as f,F as R,H as w,l as p,u as S,x as O}from"./chunk-CB3I3VQT.js";import{spawn as I}from"child_process";import C from"crypto";import s from"fs";import l from"path";import{Readable as M}from"stream";import{pipeline as k}from"stream/promises";var N="https://sootbean.com",E="SOOTSIM_CDN_ORIGIN",T="SOOTSIM_RUNTIME_CHANNEL",q="https://sootsim.com/changelog";function $(){try{let t=JSON.parse(s.readFileSync(O(),"utf8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function d(t){let e=$();return(t||process.env[E]||e.cdnOrigin||N).replace(/\/+$/,"")}function x(t){let e=$();return t||process.env[T]||e.runtimeChannel||"stable"}function D(t){let e=new URL(`${d(t)}/runtimes/manifest.json`);return e.searchParams.set("t",String(Date.now())),e.toString()}function U(t,e){return`${d(e)}/runtimes/sootsim-runtime-${t}.tar.gz`}async function y(t){let e=D(t),r=await fetch(e,{headers:{Accept:"application/json"}});if(!r.ok)throw new Error(`manifest fetch failed: ${r.status} ${r.statusText} (${e})`);return await r.json()}function P(t,e={}){let r=x(e.channel),n=e.version||t.channels[r]?.latest;if(!n)throw new Error(`no version specified and channel '${r}' has no latest entry in the manifest`);let i=t.versions[n];if(!i)throw new Error(`version ${n} not found in manifest; available: ${Object.keys(t.versions).slice(-10).join(", ")||"(none)"}`);return{version:n,channel:r,entry:i}}async function _(t={}){v();let e=d(t.cdnOrigin),r=await y(e),{version:n,channel:i,entry:a}=P(r,t),o=p(n),c=t.setActive!==!1;if(!t.force&&s.existsSync(l.join(o,"index.html")))return c&&R(n),{version:n,channel:i,cdnOrigin:e,runtimeDir:o,installed:!1,activated:c,manifest:r};let g=a.tarball||U(n,e),m=l.join(S(),`sootsim-runtime-${n}.tar.gz`);process.stderr.write(`sootsim: downloading runtime ${n}\u2026
|
|
3
|
-
`),await V(g,m),process.stderr.write(`sootsim: extracting runtime ${n}\u2026
|
|
4
|
-
`);let h=await A(m);if(h!==a.sha256)throw s.rmSync(m,{force:!0}),new Error(`sha256 mismatch for runtime ${n}: expected ${a.sha256}, actual ${h}`);let u=l.join(l.dirname(o),`.installing-${n}-${process.pid}`);s.rmSync(u,{recursive:!0,force:!0}),s.mkdirSync(u,{recursive:!0});try{if(await j(m,u),!s.existsSync(l.join(u,"index.html")))throw new Error(`extracted tarball for runtime ${n} is missing index.html`);s.rmSync(o,{recursive:!0,force:!0}),s.renameSync(u,o)}catch(b){throw s.rmSync(u,{recursive:!0,force:!0}),b}return c&&R(n),{version:n,channel:i,cdnOrigin:e,runtimeDir:o,installed:!0,activated:c,manifest:r}}async function B(t={}){v();let e=d(t.cdnOrigin),r=x(t.channel),n=await y(e),i=n.channels[r]?.latest;if(!i)return{checked:!0,updated:!1,reason:`channel '${r}' has no latest runtime`,activeVersion:f()};if(!n.versions[i])return{checked:!0,updated:!1,reason:`manifest is missing version ${i}`,activeVersion:f(),latestVersion:i};let o=f(),c=o?p(o):null,g=c?s.existsSync(l.join(c,"index.html")):!1;if(!(!o||!g||w(i,o)>0))return{checked:!0,updated:!1,reason:"active runtime is current",activeVersion:o,latestVersion:i};let h=await _({version:i,channel:r,cdnOrigin:e,setActive:!1});return{checked:!0,updated:!0,activeVersion:i,latestVersion:i,install:h}}async function K(t={}){let e=f();try{let r=await y(d(t.cdnOrigin)),n=x(t.channel),i=r.channels[n]?.latest??null,a=!!(i&&(!e||w(i,e)>0));return{active:e,latest:i,outdated:a}}catch{return{active:e,latest:null,outdated:!1}}}async function V(t,e){let r=await fetch(t);if(!r.ok||!r.body)throw new Error(`download failed: ${r.status} ${r.statusText} (${t})`);s.mkdirSync(l.dirname(e),{recursive:!0});let n=`${e}.partial`;try{await k(M.fromWeb(r.body),s.createWriteStream(n)),s.renameSync(n,e)}catch(i){try{s.unlinkSync(n)}catch{}throw i}}function A(t){return new Promise((e,r)=>{let n=C.createHash("sha256"),i=s.createReadStream(t);i.on("data",a=>n.update(a)),i.on("error",r),i.on("end",()=>e(n.digest("hex")))})}function j(t,e){return new Promise((r,n)=>{let i=I("tar",["-xzf",t,"-C",e],{stdio:["ignore","inherit","inherit"]});i.on("error",n),i.on("exit",a=>{a===0?r():n(new Error(`tar exited with code ${a}`))})})}export{N as a,q as b,d as c,x as d,y as e,_ as f,B as g,K as h};
|