rnxsim 0.1.452 → 0.1.454
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/cli/bridge-flow-runner.ts +41 -13
- package/cli/cloud-client.ts +10 -0
- package/cli/commands/control.ts +52 -7
- package/cli/commands/flow.ts +1 -5
- package/cli/commands/inspect/settling.ts +35 -3
- package/cli/drivers/playwright.ts +2 -4
- package/cli/ws-bridge.ts +72 -5
- package/detox/proof-frame.cjs +2 -5
- 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/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +2 -4
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +1 -1
- 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/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +89 -8
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +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 +35 -5
- package/dist-lib/sdk.mjs +35 -5
- package/dist-lib/skills.cjs +190 -44
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/flow-timeout-scale.ts +15 -0
- package/src/playwright-host-log.ts +16 -0
- package/src/sim-client.ts +4 -0
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.454 | (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;
|
|
@@ -1274,8 +1274,8 @@ var init_capability_inventory_coverage = __esm({
|
|
|
1274
1274
|
ios: {
|
|
1275
1275
|
combined: {
|
|
1276
1276
|
raw: {
|
|
1277
|
-
covered:
|
|
1278
|
-
ratio: 0.
|
|
1277
|
+
covered: 233,
|
|
1278
|
+
ratio: 0.167264895908,
|
|
1279
1279
|
total: 1393
|
|
1280
1280
|
},
|
|
1281
1281
|
weighted: {
|
|
@@ -1286,8 +1286,8 @@ var init_capability_inventory_coverage = __esm({
|
|
|
1286
1286
|
},
|
|
1287
1287
|
semantic: {
|
|
1288
1288
|
raw: {
|
|
1289
|
-
covered:
|
|
1290
|
-
ratio: 0.
|
|
1289
|
+
covered: 233,
|
|
1290
|
+
ratio: 0.23370110331,
|
|
1291
1291
|
total: 997
|
|
1292
1292
|
},
|
|
1293
1293
|
weighted: {
|
|
@@ -2715,13 +2715,13 @@ var init_capability_outcomes2 = __esm({
|
|
|
2715
2715
|
assessed: 0
|
|
2716
2716
|
},
|
|
2717
2717
|
ios: {
|
|
2718
|
-
passedWeight:
|
|
2718
|
+
passedWeight: 8422,
|
|
2719
2719
|
failedWeight: 0,
|
|
2720
|
-
unassessedWeight:
|
|
2720
|
+
unassessedWeight: 24028,
|
|
2721
2721
|
totalWeight: 32450,
|
|
2722
|
-
assessedWeight:
|
|
2722
|
+
assessedWeight: 8422,
|
|
2723
2723
|
compatibility: 1,
|
|
2724
|
-
assessed: 0.
|
|
2724
|
+
assessed: 0.259537750385208
|
|
2725
2725
|
}
|
|
2726
2726
|
},
|
|
2727
2727
|
byWeighting: {
|
|
@@ -2736,13 +2736,13 @@ var init_capability_outcomes2 = __esm({
|
|
|
2736
2736
|
assessed: 0
|
|
2737
2737
|
},
|
|
2738
2738
|
ios: {
|
|
2739
|
-
passedWeight:
|
|
2739
|
+
passedWeight: 181,
|
|
2740
2740
|
failedWeight: 0,
|
|
2741
|
-
unassessedWeight:
|
|
2741
|
+
unassessedWeight: 1024,
|
|
2742
2742
|
totalWeight: 1205,
|
|
2743
|
-
assessedWeight:
|
|
2743
|
+
assessedWeight: 181,
|
|
2744
2744
|
compatibility: 1,
|
|
2745
|
-
assessed: 0.
|
|
2745
|
+
assessed: 0.15020746887966804
|
|
2746
2746
|
}
|
|
2747
2747
|
},
|
|
2748
2748
|
usage: {
|
|
@@ -2756,13 +2756,13 @@ var init_capability_outcomes2 = __esm({
|
|
|
2756
2756
|
assessed: 0
|
|
2757
2757
|
},
|
|
2758
2758
|
ios: {
|
|
2759
|
-
passedWeight:
|
|
2759
|
+
passedWeight: 8422,
|
|
2760
2760
|
failedWeight: 0,
|
|
2761
|
-
unassessedWeight:
|
|
2761
|
+
unassessedWeight: 24028,
|
|
2762
2762
|
totalWeight: 32450,
|
|
2763
|
-
assessedWeight:
|
|
2763
|
+
assessedWeight: 8422,
|
|
2764
2764
|
compatibility: 1,
|
|
2765
|
-
assessed: 0.
|
|
2765
|
+
assessed: 0.259537750385208
|
|
2766
2766
|
}
|
|
2767
2767
|
}
|
|
2768
2768
|
}
|
|
@@ -25730,6 +25730,9 @@ var init_cloud_client = __esm({
|
|
|
25730
25730
|
focusSim() {
|
|
25731
25731
|
return Promise.reject(new Error("remote simulators have no browser window to focus"));
|
|
25732
25732
|
}
|
|
25733
|
+
resolveReloadedSim() {
|
|
25734
|
+
return Promise.resolve(null);
|
|
25735
|
+
}
|
|
25733
25736
|
closeSim() {
|
|
25734
25737
|
return Promise.reject(
|
|
25735
25738
|
new Error("remote simulator close uses the simulator DELETE route")
|
|
@@ -25796,6 +25799,9 @@ var init_cloud_client = __esm({
|
|
|
25796
25799
|
focusSim() {
|
|
25797
25800
|
return Promise.reject(new Error("a box simulator has no browser window to focus"));
|
|
25798
25801
|
}
|
|
25802
|
+
resolveReloadedSim() {
|
|
25803
|
+
return Promise.resolve(null);
|
|
25804
|
+
}
|
|
25799
25805
|
closeSim() {
|
|
25800
25806
|
return Promise.reject(new Error("close a box simulator with rnx box stop"));
|
|
25801
25807
|
}
|
|
@@ -28611,6 +28617,15 @@ function createBridge(wsPort, opts = {}) {
|
|
|
28611
28617
|
});
|
|
28612
28618
|
let warnedAboutContention = false;
|
|
28613
28619
|
let noticedTarget = false;
|
|
28620
|
+
let pinnedHostPid = null;
|
|
28621
|
+
let lineageLookupInFlight = false;
|
|
28622
|
+
function pickReloadedSuccessor(sims, retiredSimId) {
|
|
28623
|
+
if (pinnedHostPid === null) return null;
|
|
28624
|
+
const successors = (Array.isArray(sims) ? sims : []).filter(
|
|
28625
|
+
(sim) => sim.id !== retiredSimId && sim.readyState === "open" && sim.meta?.sootsimHostPid === pinnedHostPid
|
|
28626
|
+
);
|
|
28627
|
+
return successors.length === 1 ? successors[0].id : null;
|
|
28628
|
+
}
|
|
28614
28629
|
function maybeNoticeTarget(cmdType, simId) {
|
|
28615
28630
|
if (noticedTarget) return;
|
|
28616
28631
|
if (process.env.SOOTSIM_QUIET_TARGET_NOTICE === "1") return;
|
|
@@ -28666,7 +28681,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
28666
28681
|
plane: "local",
|
|
28667
28682
|
async send(cmd, callOpts) {
|
|
28668
28683
|
const effectiveTimeoutMs = callOpts?.timeoutMs ?? commandTimeoutMs;
|
|
28669
|
-
const sendOnce = async (defaultSimId) => {
|
|
28684
|
+
const sendOnce = async (defaultSimId, cmdOverride) => {
|
|
28670
28685
|
await ready;
|
|
28671
28686
|
const id = nextId++;
|
|
28672
28687
|
return new Promise((resolve9, reject) => {
|
|
@@ -28688,7 +28703,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
28688
28703
|
reject(e);
|
|
28689
28704
|
}
|
|
28690
28705
|
});
|
|
28691
|
-
const payload = { ...cmd, id };
|
|
28706
|
+
const payload = { ...cmdOverride ?? cmd, id };
|
|
28692
28707
|
if (payload.simId === void 0 && defaultSimId) {
|
|
28693
28708
|
payload.simId = defaultSimId;
|
|
28694
28709
|
}
|
|
@@ -28698,11 +28713,36 @@ function createBridge(wsPort, opts = {}) {
|
|
|
28698
28713
|
};
|
|
28699
28714
|
const sentSimId = opts.simIdSource === "flag" ? opts.simId : readCurrentSimId() ?? opts.simId;
|
|
28700
28715
|
try {
|
|
28701
|
-
|
|
28716
|
+
const result = await sendOnce(sentSimId);
|
|
28717
|
+
if (sentSimId && pinnedHostPid === null && !lineageLookupInFlight) {
|
|
28718
|
+
lineageLookupInFlight = true;
|
|
28719
|
+
void sendOnce(void 0, { type: "bridge:list-sims" }).then((sims) => {
|
|
28720
|
+
if (!Array.isArray(sims)) return;
|
|
28721
|
+
const pinned = sims.find((sim) => sim.id === sentSimId);
|
|
28722
|
+
const hostPid = pinned?.meta?.sootsimHostPid;
|
|
28723
|
+
if (typeof hostPid === "number") pinnedHostPid = hostPid;
|
|
28724
|
+
}).catch(() => {
|
|
28725
|
+
}).finally(() => {
|
|
28726
|
+
lineageLookupInFlight = false;
|
|
28727
|
+
});
|
|
28728
|
+
}
|
|
28729
|
+
return result;
|
|
28702
28730
|
} catch (error) {
|
|
28703
28731
|
const message = error instanceof Error ? error.message : String(error);
|
|
28704
28732
|
const missingSimMessage = `no sim connected with id ${sentSimId}`;
|
|
28705
28733
|
if (opts.simIdSource !== "flag" && sentSimId && cmd.simId === void 0 && (message === missingSimMessage || message.startsWith(`${missingSimMessage};`))) {
|
|
28734
|
+
const successor = pickReloadedSuccessor(
|
|
28735
|
+
await sendOnce(void 0, { type: "bridge:list-sims" }),
|
|
28736
|
+
sentSimId
|
|
28737
|
+
);
|
|
28738
|
+
if (successor) {
|
|
28739
|
+
saveCurrentSimId(successor);
|
|
28740
|
+
process.stderr.write(
|
|
28741
|
+
` note: sim ${sentSimId} reloaded and reconnected as ${successor}; following it
|
|
28742
|
+
`
|
|
28743
|
+
);
|
|
28744
|
+
return sendOnce(successor);
|
|
28745
|
+
}
|
|
28706
28746
|
clearCurrentSimId();
|
|
28707
28747
|
throw new Error(
|
|
28708
28748
|
`saved sim ${sentSimId} is gone${message.slice(missingSimMessage.length)}; run \`rnx list\` and \`rnx use <sim>\`, or open a fresh sim`
|
|
@@ -28715,6 +28755,13 @@ function createBridge(wsPort, opts = {}) {
|
|
|
28715
28755
|
const sims = await this.send({ type: "bridge:list-sims" });
|
|
28716
28756
|
return Array.isArray(sims) ? sims : [];
|
|
28717
28757
|
},
|
|
28758
|
+
// a caller holding its own pinned sim id (a flow runner sets simId on every
|
|
28759
|
+
// command, so it never reaches the pin-following path in send) asks here
|
|
28760
|
+
// after a reload retires that id. null means nothing proves what replaced
|
|
28761
|
+
// it, and the caller must fail rather than guess.
|
|
28762
|
+
async resolveReloadedSim(retiredSimId) {
|
|
28763
|
+
return pickReloadedSuccessor(await this.listSims(), retiredSimId);
|
|
28764
|
+
},
|
|
28718
28765
|
async focusSim(simId) {
|
|
28719
28766
|
return this.send({ type: "focus", simId });
|
|
28720
28767
|
},
|
|
@@ -29107,6 +29154,18 @@ var init_dev_bundle_resolution = __esm({
|
|
|
29107
29154
|
}
|
|
29108
29155
|
});
|
|
29109
29156
|
|
|
29157
|
+
// src/flow-timeout-scale.ts
|
|
29158
|
+
function flowTimeoutScale() {
|
|
29159
|
+
return Math.min(10, Math.max(1, Number(process.env[FLOW_TIMEOUT_SCALE_ENV]) || 1));
|
|
29160
|
+
}
|
|
29161
|
+
var FLOW_TIMEOUT_SCALE_ENV;
|
|
29162
|
+
var init_flow_timeout_scale = __esm({
|
|
29163
|
+
"src/flow-timeout-scale.ts"() {
|
|
29164
|
+
"use strict";
|
|
29165
|
+
FLOW_TIMEOUT_SCALE_ENV = "SOOTSIM_FLOW_TIMEOUT_SCALE";
|
|
29166
|
+
}
|
|
29167
|
+
});
|
|
29168
|
+
|
|
29110
29169
|
// src/profiles.ts
|
|
29111
29170
|
function normalizeProfileId(input) {
|
|
29112
29171
|
const id = input.trim();
|
|
@@ -30613,6 +30672,18 @@ var init_electron = __esm({
|
|
|
30613
30672
|
}
|
|
30614
30673
|
});
|
|
30615
30674
|
|
|
30675
|
+
// src/playwright-host-log.ts
|
|
30676
|
+
function playwrightHostLogName(nowMs, pid) {
|
|
30677
|
+
return `${PLAYWRIGHT_HOST_LOG_PREFIX}${nowMs.toString(36)}-${pid}.log`;
|
|
30678
|
+
}
|
|
30679
|
+
var PLAYWRIGHT_HOST_LOG_PREFIX;
|
|
30680
|
+
var init_playwright_host_log = __esm({
|
|
30681
|
+
"src/playwright-host-log.ts"() {
|
|
30682
|
+
"use strict";
|
|
30683
|
+
PLAYWRIGHT_HOST_LOG_PREFIX = "rnx-playwright-host-";
|
|
30684
|
+
}
|
|
30685
|
+
});
|
|
30686
|
+
|
|
30616
30687
|
// cli/internal-child.ts
|
|
30617
30688
|
var RNX_INTERNAL_COMMAND, RNX_INTERNAL_CHILDREN;
|
|
30618
30689
|
var init_internal_child = __esm({
|
|
@@ -30822,10 +30893,7 @@ async function launch2(opts) {
|
|
|
30822
30893
|
message: `playwright browser provisioning failed: ${provisioning.message}`
|
|
30823
30894
|
};
|
|
30824
30895
|
}
|
|
30825
|
-
const errLog = (0, import_path7.join)(
|
|
30826
|
-
(0, import_os2.tmpdir)(),
|
|
30827
|
-
`rnx-playwright-host-${Date.now().toString(36)}-${process.pid}.log`
|
|
30828
|
-
);
|
|
30896
|
+
const errLog = (0, import_path7.join)((0, import_os2.tmpdir)(), playwrightHostLogName(Date.now(), process.pid));
|
|
30829
30897
|
const connectAckFile = `${errLog}.connected`;
|
|
30830
30898
|
const errFd = (0, import_fs8.openSync)(errLog, "a");
|
|
30831
30899
|
try {
|
|
@@ -30900,6 +30968,7 @@ var init_playwright = __esm({
|
|
|
30900
30968
|
import_fs8 = require("fs");
|
|
30901
30969
|
import_os2 = require("os");
|
|
30902
30970
|
import_path7 = require("path");
|
|
30971
|
+
init_playwright_host_log();
|
|
30903
30972
|
init_profiles();
|
|
30904
30973
|
init_internal_child();
|
|
30905
30974
|
init_parent_pid();
|
|
@@ -31792,9 +31861,11 @@ async function buildOpenUrl(target, baseUrl, openToken, opts = {}) {
|
|
|
31792
31861
|
return url.toString();
|
|
31793
31862
|
}
|
|
31794
31863
|
async function waitForSimReady(wsPort, commandTimeoutMs, simId, opts = {}) {
|
|
31795
|
-
const attempts = opts.attempts ?? 30;
|
|
31796
31864
|
const intervalMs = opts.intervalMs ?? 500;
|
|
31865
|
+
const attempts = opts.attempts ?? Math.round(30 * flowTimeoutScale());
|
|
31797
31866
|
const minNodeCount = opts.minNodeCount ?? 10;
|
|
31867
|
+
let lastCount;
|
|
31868
|
+
let lastError = "";
|
|
31798
31869
|
for (let i = 0; i < attempts; i++) {
|
|
31799
31870
|
const bridge = createBridge(wsPort, {
|
|
31800
31871
|
commandTimeoutMs,
|
|
@@ -31804,17 +31875,20 @@ async function waitForSimReady(wsPort, commandTimeoutMs, simId, opts = {}) {
|
|
|
31804
31875
|
try {
|
|
31805
31876
|
const count = await bridge.send({
|
|
31806
31877
|
type: "evaluate",
|
|
31807
|
-
code: "(async () => (await window.__sootsimTest?.getNodeCount())
|
|
31878
|
+
code: "(async () => (await window.__sootsimTest?.getNodeCount()) ?? null)()"
|
|
31808
31879
|
});
|
|
31880
|
+
lastCount = count;
|
|
31881
|
+
lastError = "";
|
|
31809
31882
|
if (typeof count === "number" && count > minNodeCount) {
|
|
31810
31883
|
return { bridge, count };
|
|
31811
31884
|
}
|
|
31812
|
-
} catch {
|
|
31885
|
+
} catch (err) {
|
|
31886
|
+
lastError = err instanceof Error ? err.message : String(err);
|
|
31813
31887
|
}
|
|
31814
31888
|
bridge.close();
|
|
31815
31889
|
await sleep2(intervalMs);
|
|
31816
31890
|
}
|
|
31817
|
-
return null;
|
|
31891
|
+
return { bridge: null, attempts, intervalMs, minNodeCount, lastCount, lastError };
|
|
31818
31892
|
}
|
|
31819
31893
|
async function waitForSimMatch(wsPort, commandTimeoutMs, predicate, opts = {}) {
|
|
31820
31894
|
const attempts = opts.attempts ?? 30;
|
|
@@ -32306,6 +32380,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
32306
32380
|
const bridge = createBridgeFromParsed(parsed);
|
|
32307
32381
|
const simHint = parsed.simId ? ` --sim ${parsed.simId}` : "";
|
|
32308
32382
|
let fallBackToNewSim = false;
|
|
32383
|
+
let preNavSimIds = /* @__PURE__ */ new Set();
|
|
32309
32384
|
try {
|
|
32310
32385
|
let targetSim = null;
|
|
32311
32386
|
let targetShellUrl = null;
|
|
@@ -32355,6 +32430,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
32355
32430
|
}
|
|
32356
32431
|
}
|
|
32357
32432
|
if (!fallBackToNewSim && targetSim) {
|
|
32433
|
+
preNavSimIds = new Set(sims.map((sim) => sim.id));
|
|
32358
32434
|
const resolvedBaseUrl = hasExplicitBaseUrl || looksLikeSootsimUrl(target) ? baseUrl : deriveCurrentSimBaseUrl(targetSim, baseUrl);
|
|
32359
32435
|
const shellUrl = targetShellUrl ?? await buildShellUrl(
|
|
32360
32436
|
target,
|
|
@@ -32381,13 +32457,31 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
32381
32457
|
}
|
|
32382
32458
|
if (!fallBackToNewSim && targetSim) {
|
|
32383
32459
|
await sleep2(1500);
|
|
32460
|
+
const navSim = targetSim;
|
|
32461
|
+
const reloadedSim = await waitForSimMatch(
|
|
32462
|
+
parsed.wsPort,
|
|
32463
|
+
parsed.commandTimeoutMs,
|
|
32464
|
+
(sim) => sim.readyState === "open" && simUsesDriver(sim, driverId) && (sim.id === navSim.id || !preNavSimIds.has(sim.id) && sim.isPrimary),
|
|
32465
|
+
{ attempts: Math.round(30 * flowTimeoutScale()) }
|
|
32466
|
+
);
|
|
32467
|
+
if (reloadedSim && reloadedSim.id !== navSim.id) {
|
|
32468
|
+
targetSim = reloadedSim;
|
|
32469
|
+
}
|
|
32384
32470
|
const ready = await waitForSimReady(
|
|
32385
32471
|
parsed.wsPort,
|
|
32386
32472
|
parsed.commandTimeoutMs,
|
|
32387
32473
|
targetSim.id
|
|
32388
32474
|
);
|
|
32389
|
-
if (!ready) {
|
|
32390
|
-
|
|
32475
|
+
if (!ready.bridge) {
|
|
32476
|
+
const observed = ready.lastError ? `last bridge error: ${ready.lastError}` : ready.lastCount === null ? "guest never installed window.__sootsimTest" : `last node count: ${String(ready.lastCount)} (needs > ${ready.minNodeCount})`;
|
|
32477
|
+
console.error(
|
|
32478
|
+
` timed out waiting for current sim to load target after ${ready.attempts} polls over ${Math.round(ready.attempts * ready.intervalMs / 1e3)}s; ${observed}`
|
|
32479
|
+
);
|
|
32480
|
+
await printBridgeFailureDiagnostics(bridge, {
|
|
32481
|
+
errorsCommand: `rnx get errors 5${simHint}`,
|
|
32482
|
+
warningsCommand: `rnx get warnings 5${simHint}`,
|
|
32483
|
+
requestsCommand: `rnx get requests 5${simHint}`
|
|
32484
|
+
});
|
|
32391
32485
|
rnxExit(1);
|
|
32392
32486
|
}
|
|
32393
32487
|
ready.bridge.close();
|
|
@@ -32787,6 +32881,7 @@ var init_control = __esm({
|
|
|
32787
32881
|
init_bridge_constants();
|
|
32788
32882
|
init_config();
|
|
32789
32883
|
init_dev_bundle_resolution();
|
|
32884
|
+
init_flow_timeout_scale();
|
|
32790
32885
|
init_home_paths();
|
|
32791
32886
|
init_native_dev_bundle_url();
|
|
32792
32887
|
init_profiles();
|
|
@@ -32847,9 +32942,7 @@ var require_proof_frame = __commonJS({
|
|
|
32847
32942
|
throw new Error("proof content measurement needs RGBA pixels and dimensions");
|
|
32848
32943
|
}
|
|
32849
32944
|
const yStart = Math.floor(height * PROOF_CONTENT_DEFINITION.contentBandInsetFraction);
|
|
32850
|
-
const yEnd = Math.ceil(
|
|
32851
|
-
height * (1 - PROOF_CONTENT_DEFINITION.contentBandInsetFraction)
|
|
32852
|
-
);
|
|
32945
|
+
const yEnd = Math.ceil(height * (1 - PROOF_CONTENT_DEFINITION.contentBandInsetFraction));
|
|
32853
32946
|
const bucketCounts = new Uint32Array(32 * 32 * 32);
|
|
32854
32947
|
let totalPixels = 0;
|
|
32855
32948
|
for (let y = yStart; y < yEnd; y++) {
|
|
@@ -33350,8 +33443,19 @@ async function waitForSootsimIdle({
|
|
|
33350
33443
|
let lastRequestTotal = -1
|
|
33351
33444
|
let stable = 0
|
|
33352
33445
|
let visuallyStillSince = 0
|
|
33446
|
+
// counts across the whole budget: a flag that is true on every poll is a
|
|
33447
|
+
// different bug from one that is true intermittently, and the two need
|
|
33448
|
+
// opposite fixes (engine vs budget).
|
|
33449
|
+
let polls = 0
|
|
33450
|
+
let dirtyPolls = 0
|
|
33451
|
+
let animatingPolls = 0
|
|
33452
|
+
let layoutChangedPolls = 0
|
|
33353
33453
|
while (Date.now() < deadline) {
|
|
33354
33454
|
const snapshot = await readSnapshot()
|
|
33455
|
+
polls++
|
|
33456
|
+
if (snapshot.layoutDirty) dirtyPolls++
|
|
33457
|
+
if (snapshot.animating) animatingPolls++
|
|
33458
|
+
if (polls > 1 && snapshot.layout !== lastLayout) layoutChangedPolls++
|
|
33355
33459
|
const strictOk =
|
|
33356
33460
|
!strict ||
|
|
33357
33461
|
(snapshot.renderStatsAvailable && !snapshot.animating && !snapshot.layoutDirty)
|
|
@@ -33372,7 +33476,7 @@ async function waitForSootsimIdle({
|
|
|
33372
33476
|
stable >= requiredStablePolls &&
|
|
33373
33477
|
(networkQuiet || Date.now() - visuallyStillSince >= networkQuietGraceMs)
|
|
33374
33478
|
) {
|
|
33375
|
-
return { settled: true, elapsed: Date.now() - start }
|
|
33479
|
+
return { settled: true, elapsed: Date.now() - start, blockedBy: '' }
|
|
33376
33480
|
}
|
|
33377
33481
|
} else {
|
|
33378
33482
|
stable = 0
|
|
@@ -33382,17 +33486,33 @@ async function waitForSootsimIdle({
|
|
|
33382
33486
|
lastRequestTotal = snapshot.requestTotal
|
|
33383
33487
|
await sleep(pollMs)
|
|
33384
33488
|
}
|
|
33385
|
-
|
|
33489
|
+
const last = await readSnapshot()
|
|
33490
|
+
const blockers = []
|
|
33491
|
+
if (strict && !last.renderStatsAvailable) blockers.push('render stats unavailable')
|
|
33492
|
+
if (last.animating) blockers.push('animations still running')
|
|
33493
|
+
if (last.layoutDirty) blockers.push('layout still dirty')
|
|
33494
|
+
if (last.pendingFetches > 0) blockers.push(last.pendingFetches + ' image fetches pending')
|
|
33495
|
+
if (last.layout !== lastLayout) blockers.push('layout still changing')
|
|
33496
|
+
if (last.requestInFlight > 0) blockers.push(last.requestInFlight + ' requests in flight')
|
|
33497
|
+
return {
|
|
33498
|
+
settled: false,
|
|
33499
|
+
elapsed: Date.now() - start,
|
|
33500
|
+
blockedBy:
|
|
33501
|
+
(blockers.length ? blockers.join(', ') : 'unknown') +
|
|
33502
|
+
' over ' + polls + ' polls (layout changed ' + layoutChangedPolls +
|
|
33503
|
+
'x, layoutDirty ' + dirtyPolls + 'x, animating ' + animatingPolls + 'x)',
|
|
33504
|
+
}
|
|
33386
33505
|
})()`
|
|
33387
33506
|
},
|
|
33388
33507
|
{
|
|
33389
33508
|
timeoutMs: maxMs + 1e3
|
|
33390
33509
|
}
|
|
33391
33510
|
);
|
|
33392
|
-
const { elapsed, settled } = result ?? {};
|
|
33511
|
+
const { elapsed, settled, blockedBy } = result ?? {};
|
|
33393
33512
|
return {
|
|
33394
33513
|
elapsed: typeof elapsed === "number" ? elapsed : maxMs,
|
|
33395
|
-
settled: settled === true
|
|
33514
|
+
settled: settled === true,
|
|
33515
|
+
blockedBy: typeof blockedBy === "string" ? blockedBy : "unknown"
|
|
33396
33516
|
};
|
|
33397
33517
|
}
|
|
33398
33518
|
var init_settling = __esm({
|
|
@@ -33869,17 +33989,16 @@ var init_bridge_flow_runner = __esm({
|
|
|
33869
33989
|
import_settings3 = require("sootsim-engine/settings");
|
|
33870
33990
|
import_yaml = __toESM(require("yaml"), 1);
|
|
33871
33991
|
import_proof_frame = __toESM(require_proof_frame(), 1);
|
|
33992
|
+
init_flow_timeout_scale();
|
|
33872
33993
|
init_frame_compose();
|
|
33873
33994
|
init_core();
|
|
33874
33995
|
init_settling();
|
|
33875
33996
|
init_shared();
|
|
33997
|
+
init_current_sim();
|
|
33876
33998
|
init_maestro_js();
|
|
33877
33999
|
init_recording_access();
|
|
33878
34000
|
DEFAULT_TIMEOUT = 1e4;
|
|
33879
|
-
FLOW_TIMEOUT_SCALE =
|
|
33880
|
-
10,
|
|
33881
|
-
Math.max(1, Number(process.env.SOOTSIM_FLOW_TIMEOUT_SCALE) || 1)
|
|
33882
|
-
);
|
|
34001
|
+
FLOW_TIMEOUT_SCALE = flowTimeoutScale();
|
|
33883
34002
|
scaledTimeout = (ms) => Math.round(ms * FLOW_TIMEOUT_SCALE);
|
|
33884
34003
|
SCREEN_W = 393;
|
|
33885
34004
|
SCREEN_H = 852;
|
|
@@ -33942,11 +34061,32 @@ var init_bridge_flow_runner = __esm({
|
|
|
33942
34061
|
});
|
|
33943
34062
|
}
|
|
33944
34063
|
async waitForTree(timeout = DEFAULT_TIMEOUT) {
|
|
33945
|
-
|
|
34064
|
+
let status = await inspectWaitReady(this.bridge, scaledTimeout(timeout));
|
|
33946
34065
|
if (status.ready) return;
|
|
33947
34066
|
if (status.externalError) {
|
|
33948
34067
|
throw new Error(`app failed to load: ${status.externalError}`);
|
|
33949
34068
|
}
|
|
34069
|
+
if (status.bridgeError) {
|
|
34070
|
+
const pinned = this.opts.simId;
|
|
34071
|
+
let successor = null;
|
|
34072
|
+
if (pinned) {
|
|
34073
|
+
const deadline = Date.now() + scaledTimeout(15e3);
|
|
34074
|
+
do {
|
|
34075
|
+
successor = await this.bridge.resolveReloadedSim(pinned);
|
|
34076
|
+
if (successor) break;
|
|
34077
|
+
await sleep3(500);
|
|
34078
|
+
} while (Date.now() < deadline);
|
|
34079
|
+
}
|
|
34080
|
+
if (successor) {
|
|
34081
|
+
console.error(
|
|
34082
|
+
` note: sim ${pinned} reloaded and reconnected as ${successor}; following it`
|
|
34083
|
+
);
|
|
34084
|
+
this.opts.simId = successor;
|
|
34085
|
+
saveCurrentSimId(successor);
|
|
34086
|
+
status = await inspectWaitReady(this.bridge, scaledTimeout(timeout));
|
|
34087
|
+
if (status.ready) return;
|
|
34088
|
+
}
|
|
34089
|
+
}
|
|
33950
34090
|
if (status.bridgeError) {
|
|
33951
34091
|
throw new Error(
|
|
33952
34092
|
`target sim is not responding to the bridge (${status.bridgeError}). it is likely a stale orphan; run \`rnx list\`, then close it with \`rnx close <id>\` or start a fresh one with \`rnx open --new <port>\`.`
|
|
@@ -35077,7 +35217,9 @@ var init_bridge_flow_runner = __esm({
|
|
|
35077
35217
|
strict: true
|
|
35078
35218
|
});
|
|
35079
35219
|
if (!result.settled) {
|
|
35080
|
-
throw new Error(
|
|
35220
|
+
throw new Error(
|
|
35221
|
+
`visual state did not settle within ${result.elapsed}ms (${result.blockedBy})`
|
|
35222
|
+
);
|
|
35081
35223
|
}
|
|
35082
35224
|
}
|
|
35083
35225
|
resolveShellLaunchAppId(opts, state) {
|
|
@@ -35306,7 +35448,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
35306
35448
|
try {
|
|
35307
35449
|
const hasExplicitWait = !!(step.extendedWaitUntil || step.waitFor || step.scrollUntilVisible || step.launchApp || step.runFlow || // runScript http calls are synchronous with a 5-minute upstream
|
|
35308
35450
|
// timeout — the 10s watchdog would kill legitimate setup scripts.
|
|
35309
|
-
step.runScript
|
|
35451
|
+
step.runScript || // takeScreenshot self-governs: it retries a bounded visual settle that
|
|
35452
|
+
// already fails with its own reason. sharing the watchdog's 10s budget
|
|
35453
|
+
// meant the watchdog always won that race, reporting "bridge probably
|
|
35454
|
+
// hung" for a screen that was merely still animating.
|
|
35455
|
+
step.takeScreenshot);
|
|
35310
35456
|
const STEP_WATCHDOG_MS = 1e4;
|
|
35311
35457
|
const body = this.runStepInner(step);
|
|
35312
35458
|
let screenshotPath;
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.454 | (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
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// hosted-runner previews reach first-render much slower than local dev: the
|
|
2
|
+
// guest bundle (often tens of MB) re-evals and re-hydrates on every launchApp
|
|
3
|
+
// hard reload, and it is served over a cloudflared tunnel. run.sh sets
|
|
4
|
+
// SOOTSIM_FLOW_TIMEOUT_SCALE for the recording lane so a slow-but-working app
|
|
5
|
+
// clears its waits without per-app timeouts. off (1x) locally, clamped to 1..10.
|
|
6
|
+
//
|
|
7
|
+
// every deadline a hosted launchApp has to clear must use this, or the lane is
|
|
8
|
+
// only half-scaled: the flow runner's own waits scaled while the CLI's
|
|
9
|
+
// post-navigation readiness poll kept a flat ceiling, so a launchApp that was
|
|
10
|
+
// working but slow failed the flow.
|
|
11
|
+
export const FLOW_TIMEOUT_SCALE_ENV = 'SOOTSIM_FLOW_TIMEOUT_SCALE'
|
|
12
|
+
|
|
13
|
+
export function flowTimeoutScale(): number {
|
|
14
|
+
return Math.min(10, Math.max(1, Number(process.env[FLOW_TIMEOUT_SCALE_ENV]) || 1))
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// the playwright driver writes its browser-host stderr to a tmpdir log, and
|
|
2
|
+
// that log carries the only hardware-WebGL proof the hosted recorder accepts.
|
|
3
|
+
// the driver names the file and the recorder scans for it, so the prefix lives
|
|
4
|
+
// here rather than as a literal in both. it was already renamed once
|
|
5
|
+
// (sootsim- -> rnx-) without the recorder following, which silently failed
|
|
6
|
+
// every hosted job with "run completed without hardware WebGL proof" even when
|
|
7
|
+
// the preview itself uploaded fine.
|
|
8
|
+
export const PLAYWRIGHT_HOST_LOG_PREFIX = 'rnx-playwright-host-'
|
|
9
|
+
|
|
10
|
+
export function playwrightHostLogName(nowMs: number, pid: number): string {
|
|
11
|
+
return `${PLAYWRIGHT_HOST_LOG_PREFIX}${nowMs.toString(36)}-${pid}.log`
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isPlaywrightHostLog(name: string): boolean {
|
|
15
|
+
return name.startsWith(PLAYWRIGHT_HOST_LOG_PREFIX) && name.endsWith('.log')
|
|
16
|
+
}
|
package/src/sim-client.ts
CHANGED
|
@@ -261,6 +261,10 @@ export class SimClient implements WsBridge, InspectBridge {
|
|
|
261
261
|
return this.bridge.listSims()
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
resolveReloadedSim(retiredSimId: string): Promise<string | null> {
|
|
265
|
+
return this.bridge.resolveReloadedSim(retiredSimId)
|
|
266
|
+
}
|
|
267
|
+
|
|
264
268
|
focusSim(simId: string = this.simId): Promise<any> {
|
|
265
269
|
return this.bridge.focusSim(simId)
|
|
266
270
|
}
|