sootsim 0.1.140 → 0.1.142
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 +3 -3
- package/dist-cli/chunks/{agent-N767ME6M.js → agent-NAAIMWH7.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-ELHIUFZZ.js → agent-wrapper-XTURYUNI.js} +2 -2
- package/dist-cli/chunks/{app-fonts-OZ3OSNAJ.js → app-fonts-RSEABY54.js} +2 -2
- package/dist-cli/chunks/{assert-GGFUQBNB.js → assert-FLKFAP5S.js} +2 -2
- package/dist-cli/chunks/auto-bootstrap-UTDQXKT2.js +2 -0
- package/dist-cli/chunks/beta-WOG3OLTT.js +2 -0
- package/dist-cli/chunks/{camera-5PYEDLLB.js → camera-YW7TIZMC.js} +2 -2
- package/dist-cli/chunks/{chunk-QRRBQE6M.js → chunk-2SUXNIRB.js} +2 -2
- package/dist-cli/chunks/{chunk-GI43DDEI.js → chunk-3EETVUZK.js} +1 -1
- package/dist-cli/chunks/{chunk-WGDXZMKT.js → chunk-3ITFZJ7S.js} +2 -2
- package/dist-cli/chunks/{chunk-FYUDIUFX.js → chunk-3OPQ44BF.js} +2 -2
- package/dist-cli/chunks/chunk-5PZ7JGND.js +2 -0
- package/dist-cli/chunks/{chunk-N2XPC4Z7.js → chunk-6J5EKBUF.js} +2 -2
- package/dist-cli/chunks/{chunk-R5F7XGAO.js → chunk-AIS5XNOM.js} +3 -3
- package/dist-cli/chunks/chunk-BGIDIZGS.js +1 -0
- package/dist-cli/chunks/{chunk-5VTYMBUK.js → chunk-BZO4BFHL.js} +2 -2
- package/dist-cli/chunks/{chunk-HPTMLB7V.js → chunk-C3GZZTY2.js} +1 -1
- package/dist-cli/chunks/{chunk-BLQBPN76.js → chunk-CHTLYKGS.js} +2 -2
- package/dist-cli/chunks/{chunk-7SMEXHWJ.js → chunk-D6V27NP5.js} +1 -1
- package/dist-cli/chunks/{chunk-GYZNLDBX.js → chunk-FSKCHXES.js} +5 -5
- package/dist-cli/chunks/{chunk-AOICEZCA.js → chunk-GCCVK7DE.js} +2 -2
- package/dist-cli/chunks/{chunk-PBS47TD5.js → chunk-HAUBNMGA.js} +2 -2
- package/dist-cli/chunks/{chunk-ZGDJ5TFU.js → chunk-HJ6M2MSA.js} +2 -2
- package/dist-cli/chunks/{chunk-BM7QWZRI.js → chunk-HL3XSORU.js} +2 -2
- package/dist-cli/chunks/chunk-ITJU4NUU.js +1 -0
- package/dist-cli/chunks/{chunk-CQ3LV5VL.js → chunk-JVDKRU4Y.js} +2 -2
- package/dist-cli/chunks/{chunk-EMNVJOEL.js → chunk-KOZ5XDC7.js} +3 -3
- package/dist-cli/chunks/{chunk-4FBFOWV3.js → chunk-LTYJMDYI.js} +2 -2
- package/dist-cli/chunks/{chunk-X6AWKKL4.js → chunk-MO6Q4PLZ.js} +2 -2
- package/dist-cli/chunks/{chunk-ZN4Z2W7F.js → chunk-O4YHBU62.js} +2 -2
- package/dist-cli/chunks/{chunk-RAY2DLSK.js → chunk-OI5YSYX2.js} +1 -1
- package/dist-cli/chunks/{chunk-QOZ2Q4FH.js → chunk-P7FJ6IE4.js} +1 -1
- package/dist-cli/chunks/{chunk-4FGNOWB6.js → chunk-PQFNHOPP.js} +1 -1
- package/dist-cli/chunks/{chunk-AI65UVSN.js → chunk-QJ2H2D5V.js} +2 -2
- package/dist-cli/chunks/chunk-QJKMMHUB.js +406 -0
- package/dist-cli/chunks/{chunk-GL74P6NR.js → chunk-R42X5C7W.js} +1 -1
- package/dist-cli/chunks/{chunk-REIC7HRW.js → chunk-RNNX77AX.js} +1 -1
- package/dist-cli/chunks/{chunk-SSZBFWV7.js → chunk-RQPGGNZW.js} +1 -1
- package/dist-cli/chunks/chunk-SM3OY52S.js +119 -0
- package/dist-cli/chunks/chunk-SN3MJYP7.js +1 -0
- package/dist-cli/chunks/{chunk-O2SQNUDP.js → chunk-TKNYTKLF.js} +1 -1
- package/dist-cli/chunks/{chunk-BGXNYXBC.js → chunk-UCPLYSBA.js} +1 -1
- package/dist-cli/chunks/{chunk-C3FURRBF.js → chunk-UUKLS7ZA.js} +1 -1
- package/dist-cli/chunks/{chunk-ZVQOEMXS.js → chunk-VGCBZCSG.js} +54 -58
- package/dist-cli/chunks/{chunk-AP2MOP44.js → chunk-W5FZTYVP.js} +1 -1
- package/dist-cli/chunks/{chunk-UHTE6FLK.js → chunk-WEDVFO7O.js} +2 -2
- package/dist-cli/chunks/{chunk-XGYD25DJ.js → chunk-WHTKAFVO.js} +1 -1
- package/dist-cli/chunks/{chunk-77TL74AM.js → chunk-XNHS44BQ.js} +1 -1
- package/dist-cli/chunks/chunk-XZHTKBH7.js +5 -0
- package/dist-cli/chunks/{chunk-MRQRJINW.js → chunk-YG4V3MOQ.js} +1 -1
- package/dist-cli/chunks/{chunk-QXOZB7WD.js → chunk-YIWBIAVG.js} +2 -2
- package/dist-cli/chunks/{chunk-6KUVOSFF.js → chunk-ZWIFZAXU.js} +2 -2
- package/dist-cli/chunks/cli-version-IRAJSCVW.js +2 -0
- package/dist-cli/chunks/{compat-U3772TUK.js → compat-HLFCOAFE.js} +3 -3
- package/dist-cli/chunks/{config-6CZCIYKJ.js → config-YFXVAWO3.js} +2 -2
- package/dist-cli/chunks/{control-NVA25O65.js → control-I4OAASMO.js} +2 -2
- package/dist-cli/chunks/{cpu-profile-WRLTZYO6.js → cpu-profile-OKH4Y467.js} +2 -2
- package/dist-cli/chunks/{daemon-QQPGLGS6.js → daemon-SI2HN567.js} +2 -2
- package/dist-cli/chunks/{debug-RKYLSDZV.js → debug-AEHF4WWI.js} +3 -3
- package/dist-cli/chunks/{detox-ZRUQQU22.js → detox-HLZCQK7Z.js} +2 -2
- package/dist-cli/chunks/{device-HXTOLEWY.js → device-WDLN7VOT.js} +2 -2
- package/dist-cli/chunks/{diagnose-QN4E4WA6.js → diagnose-3KKIW2KV.js} +2 -2
- package/dist-cli/chunks/drivers-G6Y3D5KN.js +2 -0
- package/dist-cli/chunks/{electron-ZHRC4WQ5.js → electron-XRQZK2WQ.js} +3 -3
- package/dist-cli/chunks/flow-U2Y6PHQY.js +2 -0
- package/dist-cli/chunks/help-7TWUPXUX.js +2 -0
- package/dist-cli/chunks/{hints-HCHKMDUE.js → hints-B63I5SSR.js} +2 -2
- package/dist-cli/chunks/{home-paths-3OHKRAE4.js → home-paths-BDQIBV2V.js} +2 -2
- package/dist-cli/chunks/{inspect-QXUBDKJJ.js → inspect-7XVNDGN4.js} +3 -3
- package/dist-cli/chunks/install-UJ4KBTQ4.js +2 -0
- package/dist-cli/chunks/{install-desktop-QCX44BGL.js → install-desktop-JBQQTH3I.js} +3 -3
- package/dist-cli/chunks/{keys-VEP2KPUF.js → keys-IMBTM4HL.js} +2 -2
- package/dist-cli/chunks/{launch-K4BPQLTP.js → launch-XU64UAEQ.js} +3 -3
- package/dist-cli/chunks/{login-UVC5XRKR.js → login-63BFWUJD.js} +4 -4
- package/dist-cli/chunks/{logout-3VW34IBA.js → logout-RHE2W3WL.js} +2 -2
- package/dist-cli/chunks/maestro-4CAIVMXK.js +94 -0
- package/dist-cli/chunks/optional-demo-registry-BTUMTEBH.js +2 -0
- package/dist-cli/chunks/{preview-TZYJMLEJ.js → preview-XZYX3SSZ.js} +2 -2
- package/dist-cli/chunks/{profile-HDJRF7YB.js → profile-NNNFLZ6K.js} +2 -2
- package/dist-cli/chunks/{react-RLJR26M7.js → react-45J3NYF6.js} +2 -2
- package/dist-cli/chunks/{record-2LDDHHUY.js → record-QEON42UG.js} +2 -2
- package/dist-cli/chunks/runtime-2LEYVXKV.js +2 -0
- package/dist-cli/chunks/{runtime-delivery-3F6O57E5.js → runtime-delivery-LGV6QPZS.js} +2 -2
- package/dist-cli/chunks/{screenshot-QAUSSEPK.js → screenshot-SW2ZM723.js} +2 -2
- package/dist-cli/chunks/{screenshot-mode-K6HEVK4K.js → screenshot-mode-DSEJREME.js} +2 -2
- package/dist-cli/chunks/{screenshots-TWMCGUBT.js → screenshots-QWUZGYAS.js} +2 -2
- package/dist-cli/chunks/{server-ZPIZCBW5.js → server-6PTAPUIC.js} +3 -3
- package/dist-cli/chunks/setup-repo-3EBO7HQE.js +2 -0
- package/dist-cli/chunks/{skills-NI3RH7CW.js → skills-OAKG5VHJ.js} +2 -2
- package/dist-cli/chunks/{start-G6CQL6HJ.js → start-3QVTLFG7.js} +4 -4
- package/dist-cli/chunks/store-HKA3ET4T.js +2 -0
- package/dist-cli/chunks/telemetry-6ORWTXX5.js +2 -0
- package/dist-cli/chunks/{test-V47D6EPK.js → test-PYY6TAZF.js} +3 -3
- package/dist-cli/chunks/{three-mode-G7N3LRHM.js → three-mode-4CJYCCE6.js} +2 -2
- package/dist-cli/chunks/{timeline-EBUOILTJ.js → timeline-C4WE3FQZ.js} +2 -2
- package/dist-cli/chunks/{upgrade-OQJLTCQP.js → upgrade-PY3F4JQ6.js} +2 -2
- package/dist-cli/chunks/upload-NFFWJLCQ.js +2 -0
- package/dist-cli/chunks/{version-3YJPPUE5.js → version-CVDLRIWC.js} +2 -2
- package/dist-cli/chunks/{web-ZKUX5ICX.js → web-DWUYDFQ3.js} +2 -2
- package/dist-cli/chunks/{what-happened-HOY3TA42.js → what-happened-6NQLDVJC.js} +2 -2
- package/dist-cli/chunks/{whoami-GOCSBVTG.js → whoami-WK3UUIOA.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.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 +5 -2
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +2 -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/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 +2 -2
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +360 -92
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/src/config.ts +13 -0
- package/dist-cli/chunks/auto-bootstrap-L5E6XMCK.js +0 -2
- package/dist-cli/chunks/beta-D74SDA2L.js +0 -2
- package/dist-cli/chunks/chunk-5EP5RRNS.js +0 -381
- package/dist-cli/chunks/chunk-BEA3AO36.js +0 -5
- package/dist-cli/chunks/chunk-EH6YDCSN.js +0 -119
- package/dist-cli/chunks/chunk-NQG4R5K2.js +0 -1
- package/dist-cli/chunks/chunk-Q5Z7P54I.js +0 -2
- package/dist-cli/chunks/chunk-S7I6ZCT2.js +0 -1
- package/dist-cli/chunks/chunk-WN3WZEE5.js +0 -1
- package/dist-cli/chunks/cli-version-EZRTEUXF.js +0 -2
- package/dist-cli/chunks/drivers-EVK22AX5.js +0 -2
- package/dist-cli/chunks/flow-ICCRVJVX.js +0 -2
- package/dist-cli/chunks/help-QMZ35MIQ.js +0 -2
- package/dist-cli/chunks/install-JSDZIE2T.js +0 -2
- package/dist-cli/chunks/maestro-HTFXXMLR.js +0 -80
- package/dist-cli/chunks/optional-demo-registry-5YYEAL46.js +0 -2
- package/dist-cli/chunks/runtime-QPYF2WQX.js +0 -2
- package/dist-cli/chunks/setup-repo-VHOZJEIV.js +0 -2
- package/dist-cli/chunks/store-F6MJUJYW.js +0 -2
- package/dist-cli/chunks/telemetry-DM2Y7OQJ.js +0 -2
- package/dist-cli/chunks/upload-W3YCA65H.js +0 -2
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.142 | (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;
|
|
@@ -9982,7 +9982,7 @@ function hasOwnKeys(value) {
|
|
|
9982
9982
|
}
|
|
9983
9983
|
function hasSootSimConfig(config) {
|
|
9984
9984
|
if (!config) return false;
|
|
9985
|
-
return hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
|
|
9985
|
+
return hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
|
|
9986
9986
|
}
|
|
9987
9987
|
function applySootSimConfigToUrl(url, config) {
|
|
9988
9988
|
const parsed = new URL(url);
|
|
@@ -15325,10 +15325,6 @@ var init_app_state_reset = __esm({
|
|
|
15325
15325
|
),
|
|
15326
15326
|
)
|
|
15327
15327
|
} catch {}
|
|
15328
|
-
try {
|
|
15329
|
-
const names = await caches.keys()
|
|
15330
|
-
await Promise.all(names.map((name) => caches.delete(name)))
|
|
15331
|
-
} catch {}
|
|
15332
15328
|
try {
|
|
15333
15329
|
document.cookie.split(';').forEach((cookie) => {
|
|
15334
15330
|
const name = cookie.split('=')[0]?.trim()
|
|
@@ -15465,36 +15461,241 @@ var init_settling = __esm({
|
|
|
15465
15461
|
}
|
|
15466
15462
|
});
|
|
15467
15463
|
|
|
15468
|
-
// cli/
|
|
15469
|
-
function
|
|
15470
|
-
if (
|
|
15471
|
-
|
|
15472
|
-
if (scopedVars?.has(name)) return scopedVars.get(name);
|
|
15473
|
-
const resolved = process.env[name];
|
|
15474
|
-
if (resolved === void 0) {
|
|
15475
|
-
throw new Error(`missing environment variable for flow placeholder: ${name}`);
|
|
15476
|
-
}
|
|
15477
|
-
return resolved;
|
|
15478
|
-
});
|
|
15464
|
+
// cli/maestro-js.ts
|
|
15465
|
+
function executeSyncHttp(url, method, params) {
|
|
15466
|
+
if (params?.multipartForm) {
|
|
15467
|
+
throw new Error("http: multipartForm is not supported by sootsim yet");
|
|
15479
15468
|
}
|
|
15480
|
-
|
|
15481
|
-
|
|
15469
|
+
const childEnv = { ...process.env };
|
|
15470
|
+
for (const key of Object.keys(childEnv)) {
|
|
15471
|
+
if (key.startsWith("BUN_INSPECT") || key === "NODE_OPTIONS") {
|
|
15472
|
+
delete childEnv[key];
|
|
15473
|
+
}
|
|
15474
|
+
}
|
|
15475
|
+
const child = (0, import_child_process6.spawnSync)(process.execPath, ["-e", HTTP_CHILD_SRC], {
|
|
15476
|
+
input: JSON.stringify({ url, method, headers: params?.headers, body: params?.body }),
|
|
15477
|
+
encoding: "utf8",
|
|
15478
|
+
timeout: HTTP_TIMEOUT_MS,
|
|
15479
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
15480
|
+
env: childEnv
|
|
15481
|
+
});
|
|
15482
|
+
if (child.error) {
|
|
15483
|
+
throw new Error(`http ${method} ${url} failed: ${child.error.message}`);
|
|
15482
15484
|
}
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
|
|
15486
|
-
|
|
15487
|
-
|
|
15488
|
-
|
|
15485
|
+
let parsed;
|
|
15486
|
+
try {
|
|
15487
|
+
parsed = JSON.parse(child.stdout || "");
|
|
15488
|
+
} catch {
|
|
15489
|
+
throw new Error(
|
|
15490
|
+
`http ${method} ${url} failed: no response (${(child.stderr || "").trim().slice(0, 200)})`
|
|
15489
15491
|
);
|
|
15490
15492
|
}
|
|
15491
|
-
|
|
15493
|
+
const result = parsed;
|
|
15494
|
+
if (result.__error) {
|
|
15495
|
+
throw new Error(`http ${method} ${url} failed: ${result.__error}`);
|
|
15496
|
+
}
|
|
15497
|
+
return result;
|
|
15492
15498
|
}
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15499
|
+
function stringifyJs(value) {
|
|
15500
|
+
if (value === void 0) return "undefined";
|
|
15501
|
+
if (value === null) return "null";
|
|
15502
|
+
if (typeof value === "object") {
|
|
15503
|
+
try {
|
|
15504
|
+
return JSON.stringify(value);
|
|
15505
|
+
} catch {
|
|
15506
|
+
return String(value);
|
|
15507
|
+
}
|
|
15508
|
+
}
|
|
15509
|
+
return String(value);
|
|
15510
|
+
}
|
|
15511
|
+
function scriptConditionIsTruthy(value) {
|
|
15512
|
+
if (value === void 0 || value === null) return false;
|
|
15513
|
+
if (typeof value === "boolean") return value;
|
|
15514
|
+
const text = String(value);
|
|
15515
|
+
if (text.trim().length === 0) return false;
|
|
15516
|
+
if (text.toLowerCase() === "false") return false;
|
|
15517
|
+
if (text === "undefined" || text === "null") return false;
|
|
15518
|
+
const num = Number(text);
|
|
15519
|
+
if (!Number.isNaN(num) && num === 0) return false;
|
|
15520
|
+
return true;
|
|
15521
|
+
}
|
|
15522
|
+
var import_child_process6, vm, HTTP_TIMEOUT_MS, HTTP_CHILD_SRC, TEMPLATE_RE, ESCAPED_TEMPLATE_RE, BARE_IDENTIFIER_RE, MaestroJsContext;
|
|
15523
|
+
var init_maestro_js = __esm({
|
|
15524
|
+
"cli/maestro-js.ts"() {
|
|
15496
15525
|
"use strict";
|
|
15497
|
-
|
|
15526
|
+
import_child_process6 = require("child_process");
|
|
15527
|
+
vm = __toESM(require("vm"), 1);
|
|
15528
|
+
HTTP_TIMEOUT_MS = 3e5;
|
|
15529
|
+
HTTP_CHILD_SRC = `
|
|
15530
|
+
let input = '';
|
|
15531
|
+
process.stdin.on('data', (c) => { input += c });
|
|
15532
|
+
process.stdin.on('end', async () => {
|
|
15533
|
+
try {
|
|
15534
|
+
const req = JSON.parse(input);
|
|
15535
|
+
const res = await fetch(req.url, {
|
|
15536
|
+
method: req.method,
|
|
15537
|
+
headers: req.headers,
|
|
15538
|
+
body: req.body === undefined || req.body === null ? undefined : req.body,
|
|
15539
|
+
});
|
|
15540
|
+
const body = await res.text();
|
|
15541
|
+
const headers = {};
|
|
15542
|
+
for (const [k, v] of res.headers.entries()) {
|
|
15543
|
+
headers[k] = headers[k] ? headers[k] + ',' + v : v;
|
|
15544
|
+
}
|
|
15545
|
+
process.stdout.write(JSON.stringify({ ok: res.ok, status: res.status, body, headers }));
|
|
15546
|
+
} catch (err) {
|
|
15547
|
+
process.stdout.write(JSON.stringify({ __error: (err && err.message) || String(err) }));
|
|
15548
|
+
process.exitCode = 1;
|
|
15549
|
+
}
|
|
15550
|
+
});
|
|
15551
|
+
`;
|
|
15552
|
+
TEMPLATE_RE = /(?<!\\)\$\{([^$]*)\}/g;
|
|
15553
|
+
ESCAPED_TEMPLATE_RE = /\\(\$\{[^$]*\})/g;
|
|
15554
|
+
BARE_IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
15555
|
+
MaestroJsContext = class {
|
|
15556
|
+
context;
|
|
15557
|
+
envBinding = /* @__PURE__ */ new Map();
|
|
15558
|
+
envScopeStack = [];
|
|
15559
|
+
// env keys currently materialized as context globals — cleared and re-set
|
|
15560
|
+
// before each evaluation, mirroring upstream syncBindingsToContext.
|
|
15561
|
+
syncedEnvKeys = /* @__PURE__ */ new Set();
|
|
15562
|
+
output = {};
|
|
15563
|
+
maestro;
|
|
15564
|
+
constructor(opts = {}) {
|
|
15565
|
+
this.maestro = { copiedText: null, platform: opts.platform ?? "ios" };
|
|
15566
|
+
const onLog = opts.onLog ?? ((msg) => console.log(`[flow] js: ${msg}`));
|
|
15567
|
+
const sandbox = {
|
|
15568
|
+
output: this.output,
|
|
15569
|
+
maestro: this.maestro,
|
|
15570
|
+
http: {
|
|
15571
|
+
get: (url, params) => executeSyncHttp(url, "GET", params),
|
|
15572
|
+
post: (url, params) => executeSyncHttp(url, "POST", params),
|
|
15573
|
+
put: (url, params) => executeSyncHttp(url, "PUT", params),
|
|
15574
|
+
delete: (url, params) => executeSyncHttp(url, "DELETE", params),
|
|
15575
|
+
request: (url, params) => executeSyncHttp(url, (params?.method ?? "GET").toUpperCase(), params)
|
|
15576
|
+
},
|
|
15577
|
+
console: {
|
|
15578
|
+
log: (...args) => onLog(args.map((a) => typeof a === "string" ? a : stringifyJs(a)).join(" "))
|
|
15579
|
+
}
|
|
15580
|
+
};
|
|
15581
|
+
this.context = vm.createContext(sandbox);
|
|
15582
|
+
vm.runInContext(
|
|
15583
|
+
`
|
|
15584
|
+
globalThis.__maestroScope = new Proxy(globalThis, {
|
|
15585
|
+
has() { return true },
|
|
15586
|
+
get(target, key) { return target[key] },
|
|
15587
|
+
})
|
|
15588
|
+
function json(text) { return JSON.parse(text) }
|
|
15589
|
+
function relativePoint(x, y) {
|
|
15590
|
+
var xPercent = Math.ceil(x * 100) + '%'
|
|
15591
|
+
var yPercent = Math.ceil(y * 100) + '%'
|
|
15592
|
+
return xPercent + ',' + yPercent
|
|
15593
|
+
}
|
|
15594
|
+
`,
|
|
15595
|
+
this.context
|
|
15596
|
+
);
|
|
15597
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
15598
|
+
if (value !== void 0) this.envBinding.set(key, value);
|
|
15599
|
+
}
|
|
15600
|
+
}
|
|
15601
|
+
putEnv(key, value) {
|
|
15602
|
+
this.envBinding.set(key, value);
|
|
15603
|
+
}
|
|
15604
|
+
setCopiedText(text) {
|
|
15605
|
+
this.maestro.copiedText = text;
|
|
15606
|
+
}
|
|
15607
|
+
enterEnvScope() {
|
|
15608
|
+
this.envScopeStack.push(new Map(this.envBinding));
|
|
15609
|
+
}
|
|
15610
|
+
leaveEnvScope() {
|
|
15611
|
+
const previous = this.envScopeStack.pop();
|
|
15612
|
+
if (previous) {
|
|
15613
|
+
this.envBinding.clear();
|
|
15614
|
+
for (const [k, v] of previous) this.envBinding.set(k, v);
|
|
15615
|
+
}
|
|
15616
|
+
}
|
|
15617
|
+
// evaluate a JS snippet in the shared context. mirrors upstream
|
|
15618
|
+
// evalWithIIFE: the script is embedded in a template literal and run
|
|
15619
|
+
// through eval inside an IIFE so var/let/const stay scoped to this
|
|
15620
|
+
// evaluation while the last expression's value is returned.
|
|
15621
|
+
evaluate(script, opts = {}) {
|
|
15622
|
+
const env = opts.env;
|
|
15623
|
+
if (env && Object.keys(env).length > 0) {
|
|
15624
|
+
this.enterEnvScope();
|
|
15625
|
+
try {
|
|
15626
|
+
for (const [k, v] of Object.entries(env)) this.envBinding.set(k, v);
|
|
15627
|
+
return this.evalRaw(script);
|
|
15628
|
+
} finally {
|
|
15629
|
+
this.leaveEnvScope();
|
|
15630
|
+
}
|
|
15631
|
+
}
|
|
15632
|
+
return this.evalRaw(script);
|
|
15633
|
+
}
|
|
15634
|
+
evalRaw(script) {
|
|
15635
|
+
this.syncEnvToContext();
|
|
15636
|
+
const escaped = script.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
15637
|
+
return vm.runInContext(
|
|
15638
|
+
`(function(){ with(__maestroScope){ return eval(\`${escaped}\`) } })()`,
|
|
15639
|
+
this.context
|
|
15640
|
+
);
|
|
15641
|
+
}
|
|
15642
|
+
syncEnvToContext() {
|
|
15643
|
+
const globals = vm.runInContext("globalThis", this.context);
|
|
15644
|
+
for (const key of this.syncedEnvKeys) {
|
|
15645
|
+
if (!this.envBinding.has(key)) delete globals[key];
|
|
15646
|
+
}
|
|
15647
|
+
this.syncedEnvKeys = /* @__PURE__ */ new Set();
|
|
15648
|
+
for (const [key, value] of this.envBinding) {
|
|
15649
|
+
try {
|
|
15650
|
+
globals[key] = value;
|
|
15651
|
+
this.syncedEnvKeys.add(key);
|
|
15652
|
+
} catch {
|
|
15653
|
+
}
|
|
15654
|
+
}
|
|
15655
|
+
}
|
|
15656
|
+
// upstream Env.kt String.evaluateScripts: replace every unescaped `${expr}`
|
|
15657
|
+
// with the stringified evaluation result, then unescape `\${...}`.
|
|
15658
|
+
evaluateStringTemplate(value) {
|
|
15659
|
+
const replaced = value.replace(TEMPLATE_RE, (_match, expr) => {
|
|
15660
|
+
if (expr.trim().length === 0) return "";
|
|
15661
|
+
const result = this.evaluate(expr);
|
|
15662
|
+
if (result === void 0 && BARE_IDENTIFIER_RE.test(expr.trim())) {
|
|
15663
|
+
throw new Error(`missing variable for flow placeholder: ${expr.trim()}`);
|
|
15664
|
+
}
|
|
15665
|
+
return stringifyJs(result);
|
|
15666
|
+
});
|
|
15667
|
+
return replaced.replace(ESCAPED_TEMPLATE_RE, (_match, inner) => inner);
|
|
15668
|
+
}
|
|
15669
|
+
// walk a parsed step and evaluate every string template. nested command
|
|
15670
|
+
// lists are skipped — each nested command evaluates its own strings when
|
|
15671
|
+
// it executes (matching upstream per-command evaluateScripts timing, and
|
|
15672
|
+
// required for values that change between iterations, e.g. copyTextFrom
|
|
15673
|
+
// inside repeat).
|
|
15674
|
+
interpolateStep(step) {
|
|
15675
|
+
return this.interpolateValue(step, null);
|
|
15676
|
+
}
|
|
15677
|
+
interpolateValue(value, parentKey) {
|
|
15678
|
+
if (typeof value === "string") {
|
|
15679
|
+
if (parentKey === "evalScript") return value;
|
|
15680
|
+
return this.evaluateStringTemplate(value);
|
|
15681
|
+
}
|
|
15682
|
+
if (Array.isArray(value)) {
|
|
15683
|
+
if (parentKey === "commands" || parentKey === "onFlowStart" || parentKey === "onFlowComplete") {
|
|
15684
|
+
return value;
|
|
15685
|
+
}
|
|
15686
|
+
return value.map((entry) => this.interpolateValue(entry, parentKey));
|
|
15687
|
+
}
|
|
15688
|
+
if (value && typeof value === "object") {
|
|
15689
|
+
return Object.fromEntries(
|
|
15690
|
+
Object.entries(value).map(([key, entry]) => [
|
|
15691
|
+
key,
|
|
15692
|
+
this.interpolateValue(entry, key)
|
|
15693
|
+
])
|
|
15694
|
+
);
|
|
15695
|
+
}
|
|
15696
|
+
return value;
|
|
15697
|
+
}
|
|
15698
|
+
};
|
|
15498
15699
|
}
|
|
15499
15700
|
});
|
|
15500
15701
|
|
|
@@ -15814,19 +16015,11 @@ var init_recording_access = __esm({
|
|
|
15814
16015
|
var bridge_flow_runner_exports = {};
|
|
15815
16016
|
__export(bridge_flow_runner_exports, {
|
|
15816
16017
|
SootSimBridgeFlowRunner: () => SootSimBridgeFlowRunner,
|
|
15817
|
-
clearFlowScopedVars: () => clearFlowScopedVars,
|
|
15818
16018
|
normalizeFlowScreenshotSpec: () => normalizeFlowScreenshotSpec,
|
|
15819
16019
|
parseFlowSteps: () => parseFlowSteps,
|
|
15820
16020
|
resolveFlowScreenshotPath: () => resolveFlowScreenshotPath,
|
|
15821
|
-
resolveFlowScreenshotPathWithMode: () => resolveFlowScreenshotPathWithMode
|
|
15822
|
-
setFlowScopedVar: () => setFlowScopedVar
|
|
16021
|
+
resolveFlowScreenshotPathWithMode: () => resolveFlowScreenshotPathWithMode
|
|
15823
16022
|
});
|
|
15824
|
-
function setFlowScopedVar(name, value) {
|
|
15825
|
-
flowScopedVars.set(name, value);
|
|
15826
|
-
}
|
|
15827
|
-
function clearFlowScopedVars() {
|
|
15828
|
-
flowScopedVars.clear();
|
|
15829
|
-
}
|
|
15830
16023
|
function sleep(ms) {
|
|
15831
16024
|
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
15832
16025
|
}
|
|
@@ -15873,34 +16066,39 @@ function parsePoint(value) {
|
|
|
15873
16066
|
function parseFlowSteps(content) {
|
|
15874
16067
|
const parts = content.split(/^---$/m);
|
|
15875
16068
|
const candidate = parts.length > 1 ? parts[parts.length - 1] : content;
|
|
15876
|
-
const parsed =
|
|
16069
|
+
const parsed = import_yaml.default.parse(candidate);
|
|
15877
16070
|
return Array.isArray(parsed) ? parsed : [];
|
|
15878
16071
|
}
|
|
15879
|
-
var fs7, path7, import_settings2,
|
|
16072
|
+
var fs7, path7, import_settings2, import_yaml, DEFAULT_TIMEOUT, SCREEN_W, SCREEN_H, CLI_PERF_SESSION_GLOBAL, SootSimBridgeFlowRunner;
|
|
15880
16073
|
var init_bridge_flow_runner = __esm({
|
|
15881
16074
|
"cli/bridge-flow-runner.ts"() {
|
|
15882
16075
|
"use strict";
|
|
15883
16076
|
fs7 = __toESM(require("fs"), 1);
|
|
15884
16077
|
path7 = __toESM(require("path"), 1);
|
|
15885
16078
|
import_settings2 = require("sootsim-engine/settings");
|
|
15886
|
-
|
|
16079
|
+
import_yaml = __toESM(require("yaml"), 1);
|
|
15887
16080
|
init_frame_compose();
|
|
15888
16081
|
init_app_state_reset();
|
|
15889
16082
|
init_settling();
|
|
15890
|
-
|
|
16083
|
+
init_maestro_js();
|
|
15891
16084
|
init_recording_access();
|
|
15892
16085
|
DEFAULT_TIMEOUT = 1e4;
|
|
15893
16086
|
SCREEN_W = 393;
|
|
15894
16087
|
SCREEN_H = 852;
|
|
15895
16088
|
CLI_PERF_SESSION_GLOBAL = "__sootsimCliPerf";
|
|
15896
|
-
MAESTRO_COPIED_TEXT_KEY = "maestroCopiedText";
|
|
15897
|
-
flowScopedVars = /* @__PURE__ */ new Map();
|
|
15898
16089
|
SootSimBridgeFlowRunner = class {
|
|
15899
16090
|
constructor(bridge, opts) {
|
|
15900
16091
|
this.bridge = bridge;
|
|
15901
16092
|
this.opts = opts;
|
|
15902
16093
|
}
|
|
15903
16094
|
stepDelay = 0;
|
|
16095
|
+
// maestro-compatible JS context for the whole flow run (shared with
|
|
16096
|
+
// runFlow sub-flows): `${...}` templates, runScript, evalScript, output,
|
|
16097
|
+
// maestro.copiedText. one per runner = one per flow file, like upstream.
|
|
16098
|
+
js = new MaestroJsContext({
|
|
16099
|
+
platform: "ios",
|
|
16100
|
+
onLog: (msg) => console.log(`[flow] js: ${msg}`)
|
|
16101
|
+
});
|
|
15904
16102
|
firstLaunchDone = false;
|
|
15905
16103
|
profilingEnabled = false;
|
|
15906
16104
|
recordingEnabled = false;
|
|
@@ -16717,15 +16915,12 @@ var init_bridge_flow_runner = __esm({
|
|
|
16717
16915
|
}
|
|
16718
16916
|
async launchApp(opts) {
|
|
16719
16917
|
await this.refreshSimId();
|
|
16918
|
+
if (opts && typeof opts === "object" && opts.arguments) {
|
|
16919
|
+
console.log("[flow] launchApp.arguments ignored (sootsim has no native process)");
|
|
16920
|
+
}
|
|
16720
16921
|
const wantsClear = !!(opts && typeof opts === "object" && opts.clearState);
|
|
16721
16922
|
if (wantsClear) {
|
|
16722
|
-
await this.evaluate(
|
|
16723
|
-
await (${CLEAR_APP_STATE_EVAL})
|
|
16724
|
-
try {
|
|
16725
|
-
const regs = await navigator.serviceWorker?.getRegistrations?.()
|
|
16726
|
-
await Promise.all((regs || []).map((reg) => reg.unregister()))
|
|
16727
|
-
} catch {}
|
|
16728
|
-
})()`);
|
|
16923
|
+
await this.evaluate(CLEAR_APP_STATE_EVAL, 6e4);
|
|
16729
16924
|
}
|
|
16730
16925
|
if (!this.firstLaunchDone && !wantsClear) {
|
|
16731
16926
|
this.firstLaunchDone = true;
|
|
@@ -16900,7 +17095,8 @@ var init_bridge_flow_runner = __esm({
|
|
|
16900
17095
|
);
|
|
16901
17096
|
}
|
|
16902
17097
|
// maestro copyTextFrom: find an element and capture its text for use in
|
|
16903
|
-
// later steps via ${
|
|
17098
|
+
// later steps via ${maestro.copiedText} (upstream form) or the legacy
|
|
17099
|
+
// ${maestroCopiedText}. the matcher shape matches tapOn.
|
|
16904
17100
|
async copyTextFrom(target) {
|
|
16905
17101
|
const opts = typeof target === "string" ? { id: target } : target;
|
|
16906
17102
|
const node = await this.findElement(opts);
|
|
@@ -16908,36 +17104,52 @@ var init_bridge_flow_runner = __esm({
|
|
|
16908
17104
|
throw new Error(`copyTextFrom: element not found: ${JSON.stringify(opts)}`);
|
|
16909
17105
|
}
|
|
16910
17106
|
const captured = node.text ?? node.testID ?? "";
|
|
16911
|
-
|
|
17107
|
+
this.js.setCopiedText(captured);
|
|
17108
|
+
this.js.putEnv("maestroCopiedText", captured);
|
|
16912
17109
|
console.log(`[flow] copied text: ${JSON.stringify(captured)}`);
|
|
16913
17110
|
}
|
|
16914
|
-
// maestro evalScript: run
|
|
16915
|
-
//
|
|
16916
|
-
//
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
|
|
16920
|
-
|
|
16921
|
-
|
|
16922
|
-
|
|
16923
|
-
|
|
16924
|
-
|
|
16925
|
-
const r = result;
|
|
16926
|
-
if (!r.ok) throw new Error(`evalScript failed: ${r.error}`);
|
|
16927
|
-
if (r.value !== void 0) {
|
|
16928
|
-
console.log(`[flow] evalScript ->`, r.value);
|
|
17111
|
+
// maestro evalScript: run JS in the flow's shared HOST-side context (the
|
|
17112
|
+
// same engine that owns `output` and env vars) — never in the app page.
|
|
17113
|
+
// the canonical maestro form is `evalScript: ${output.x = 1}`, which is
|
|
17114
|
+
// pure template evaluation. a script with no `${}` at all would be a
|
|
17115
|
+
// silent no-op upstream; we charitably evaluate it as raw JS in the same
|
|
17116
|
+
// context so plain-JS evalScript blocks fail or work loudly.
|
|
17117
|
+
evalScript(code) {
|
|
17118
|
+
const hasTemplate = /(?<!\\)\$\{[^$]*\}/.test(code);
|
|
17119
|
+
const result = hasTemplate ? this.js.evaluateStringTemplate(code) : this.js.evaluate(code);
|
|
17120
|
+
if (result !== void 0 && result !== "") {
|
|
17121
|
+
console.log(`[flow] evalScript ->`, result);
|
|
16929
17122
|
}
|
|
16930
17123
|
}
|
|
16931
|
-
// maestro
|
|
16932
|
-
//
|
|
16933
|
-
//
|
|
17124
|
+
// maestro runScript: execute a JS file in the shared flow context. env
|
|
17125
|
+
// vars are scoped to the script (upstream runInSubScope=true). paths
|
|
17126
|
+
// resolve relative to the flow file, like runFlow.
|
|
17127
|
+
runScript(target) {
|
|
17128
|
+
const spec = typeof target === "string" ? { file: target } : target;
|
|
17129
|
+
if (!spec.file) throw new Error("runScript requires a file");
|
|
17130
|
+
const scriptPath = path7.resolve(this.opts.flowDir, spec.file);
|
|
17131
|
+
const source = fs7.readFileSync(scriptPath, "utf8");
|
|
17132
|
+
this.js.evaluate(source, { env: spec.env });
|
|
17133
|
+
console.log(`[flow] runScript: ${spec.file} done`);
|
|
17134
|
+
}
|
|
17135
|
+
// maestro openLink: on-device maestro asks the OS to open the link, and
|
|
17136
|
+
// iOS routes an app-claimed URL into the running app as a Linking 'url'
|
|
17137
|
+
// event. sootsim mirrors that: dispatch through the engine's Linking
|
|
17138
|
+
// emulation so react-navigation useLinking / addEventListener('url')
|
|
17139
|
+
// handlers fire exactly like on a real device. an app that doesn't
|
|
17140
|
+
// handle the link simply ignores it (same as iOS routing to Safari —
|
|
17141
|
+
// the app under test sees nothing).
|
|
16934
17142
|
async openLink(target) {
|
|
16935
17143
|
const link = typeof target === "string" ? target : target.link;
|
|
16936
17144
|
if (!link) throw new Error("openLink: missing link");
|
|
16937
|
-
|
|
17145
|
+
const result = await this.callTest(
|
|
17146
|
+
"openDeepLink",
|
|
17147
|
+
link
|
|
17148
|
+
);
|
|
17149
|
+
if (!result?.ok) {
|
|
17150
|
+
throw new Error(`openLink failed: ${result?.error || "no test bridge"}`);
|
|
17151
|
+
}
|
|
16938
17152
|
await sleep(300);
|
|
16939
|
-
await this.refreshSimId();
|
|
16940
|
-
await this.waitForTree(3e4);
|
|
16941
17153
|
}
|
|
16942
17154
|
// evaluate a `when:` predicate. returns true if the step should run.
|
|
16943
17155
|
async evaluateWhen(when) {
|
|
@@ -16952,10 +17164,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
16952
17164
|
return !el;
|
|
16953
17165
|
}
|
|
16954
17166
|
if (when.platform !== void 0) {
|
|
16955
|
-
return when.platform.toLowerCase() ===
|
|
17167
|
+
return when.platform.toLowerCase() === this.js.maestro.platform.toLowerCase();
|
|
16956
17168
|
}
|
|
16957
17169
|
if (when.true !== void 0) {
|
|
16958
|
-
return when.true
|
|
17170
|
+
return scriptConditionIsTruthy(when.true);
|
|
16959
17171
|
}
|
|
16960
17172
|
return true;
|
|
16961
17173
|
}
|
|
@@ -16966,9 +17178,26 @@ var init_bridge_flow_runner = __esm({
|
|
|
16966
17178
|
const value = entry ? entry[1] : void 0;
|
|
16967
17179
|
return !!(value && typeof value === "object" && "optional" in value && value.optional);
|
|
16968
17180
|
}
|
|
16969
|
-
async runStep(
|
|
16970
|
-
const stepName = Object.keys(
|
|
17181
|
+
async runStep(rawStep, stepIndex) {
|
|
17182
|
+
const stepName = Object.keys(rawStep).find((k) => k !== "when") || Object.keys(rawStep)[0];
|
|
16971
17183
|
console.log(`[flow] step ${stepIndex + 1}: ${stepName}`);
|
|
17184
|
+
let step;
|
|
17185
|
+
try {
|
|
17186
|
+
step = this.js.interpolateStep(rawStep);
|
|
17187
|
+
} catch (error) {
|
|
17188
|
+
if (this.isOptional(rawStep)) {
|
|
17189
|
+
console.log(
|
|
17190
|
+
`[flow] (optional, skipped: ${error.message.slice(0, 80)})`
|
|
17191
|
+
);
|
|
17192
|
+
return;
|
|
17193
|
+
}
|
|
17194
|
+
this.lastFailedStep = {
|
|
17195
|
+
index: stepIndex,
|
|
17196
|
+
kind: stepName,
|
|
17197
|
+
target: rawStep[stepName]
|
|
17198
|
+
};
|
|
17199
|
+
throw error;
|
|
17200
|
+
}
|
|
16972
17201
|
if (step.when) {
|
|
16973
17202
|
const shouldRun = await this.evaluateWhen(step.when);
|
|
16974
17203
|
if (!shouldRun) {
|
|
@@ -16977,7 +17206,9 @@ var init_bridge_flow_runner = __esm({
|
|
|
16977
17206
|
}
|
|
16978
17207
|
}
|
|
16979
17208
|
try {
|
|
16980
|
-
const hasExplicitWait = !!(step.extendedWaitUntil || step.waitFor || step.scrollUntilVisible || step.launchApp || step.runFlow
|
|
17209
|
+
const hasExplicitWait = !!(step.extendedWaitUntil || step.waitFor || step.scrollUntilVisible || step.launchApp || step.runFlow || // runScript http calls are synchronous with a 5-minute upstream
|
|
17210
|
+
// timeout — the 10s watchdog would kill legitimate setup scripts.
|
|
17211
|
+
step.runScript);
|
|
16981
17212
|
const STEP_WATCHDOG_MS = 1e4;
|
|
16982
17213
|
const body = this.runStepInner(step);
|
|
16983
17214
|
if (hasExplicitWait) {
|
|
@@ -17073,7 +17304,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
17073
17304
|
} else if (typeof step.eraseText === "number") {
|
|
17074
17305
|
await this.eraseText(step.eraseText);
|
|
17075
17306
|
} else if (step.repeat) {
|
|
17076
|
-
|
|
17307
|
+
const times = Number(step.repeat.times);
|
|
17308
|
+
if (!Number.isFinite(times)) {
|
|
17309
|
+
throw new Error(`repeat.times is not a number: ${step.repeat.times}`);
|
|
17310
|
+
}
|
|
17311
|
+
for (let i = 0; i < times; i++) {
|
|
17077
17312
|
for (let j = 0; j < step.repeat.commands.length; j++) {
|
|
17078
17313
|
await this.runStep(step.repeat.commands[j], j);
|
|
17079
17314
|
}
|
|
@@ -17087,26 +17322,59 @@ var init_bridge_flow_runner = __esm({
|
|
|
17087
17322
|
} else if (step.copyTextFrom !== void 0) {
|
|
17088
17323
|
await this.copyTextFrom(step.copyTextFrom);
|
|
17089
17324
|
} else if (typeof step.evalScript === "string") {
|
|
17090
|
-
|
|
17325
|
+
this.evalScript(step.evalScript);
|
|
17326
|
+
} else if (step.runScript) {
|
|
17327
|
+
const rs = step.runScript;
|
|
17328
|
+
const innerWhen = typeof rs === "string" ? void 0 : rs.when;
|
|
17329
|
+
if (innerWhen && !await this.evaluateWhen(innerWhen)) {
|
|
17330
|
+
console.log(`[flow] runScript skipped (when predicate false)`);
|
|
17331
|
+
return;
|
|
17332
|
+
}
|
|
17333
|
+
this.runScript(rs);
|
|
17091
17334
|
} else if (step.openLink !== void 0) {
|
|
17092
17335
|
await this.openLink(step.openLink);
|
|
17093
17336
|
} else if (step.runFlow) {
|
|
17094
17337
|
const rf = step.runFlow;
|
|
17095
17338
|
const file = typeof rf === "string" ? rf : rf.file;
|
|
17339
|
+
const commands = typeof rf === "string" ? void 0 : rf.commands;
|
|
17340
|
+
const env = typeof rf === "string" ? void 0 : rf.env;
|
|
17096
17341
|
const innerWhen = typeof rf === "string" ? void 0 : rf.when;
|
|
17097
17342
|
if (innerWhen) {
|
|
17098
17343
|
const shouldRun = await this.evaluateWhen(innerWhen);
|
|
17099
17344
|
if (!shouldRun) {
|
|
17100
|
-
console.log(
|
|
17345
|
+
console.log(
|
|
17346
|
+
`[flow] runFlow skipped (when predicate false): ${file ?? "inline commands"}`
|
|
17347
|
+
);
|
|
17101
17348
|
return;
|
|
17102
17349
|
}
|
|
17103
17350
|
}
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
this.
|
|
17108
|
-
|
|
17109
|
-
|
|
17351
|
+
if (!file && !commands) {
|
|
17352
|
+
throw new Error("runFlow requires either file or commands");
|
|
17353
|
+
}
|
|
17354
|
+
this.js.enterEnvScope();
|
|
17355
|
+
try {
|
|
17356
|
+
if (env) {
|
|
17357
|
+
for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
|
|
17358
|
+
}
|
|
17359
|
+
if (file) {
|
|
17360
|
+
const flowPath = path7.resolve(this.opts.flowDir, file);
|
|
17361
|
+
const flowContent = fs7.readFileSync(flowPath, "utf8");
|
|
17362
|
+
const previousDir = this.opts.flowDir;
|
|
17363
|
+
this.opts.flowDir = path7.dirname(flowPath);
|
|
17364
|
+
try {
|
|
17365
|
+
await this.runFlow(parseFlowSteps(flowContent));
|
|
17366
|
+
} finally {
|
|
17367
|
+
;
|
|
17368
|
+
this.opts.flowDir = previousDir;
|
|
17369
|
+
}
|
|
17370
|
+
} else if (commands) {
|
|
17371
|
+
for (let i = 0; i < commands.length; i++) {
|
|
17372
|
+
await this.runStep(commands[i], i);
|
|
17373
|
+
}
|
|
17374
|
+
}
|
|
17375
|
+
} finally {
|
|
17376
|
+
this.js.leaveEnvScope();
|
|
17377
|
+
}
|
|
17110
17378
|
} else {
|
|
17111
17379
|
throw new Error(`unsupported flow step: ${JSON.stringify(step)}`);
|
|
17112
17380
|
}
|
|
@@ -17159,7 +17427,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
17159
17427
|
const explicitWait = typeof step.wait === "number" ? step.wait : 0;
|
|
17160
17428
|
const waitForTimeout = typeof step.waitFor?.timeout === "number" ? step.waitFor.timeout : 0;
|
|
17161
17429
|
const stepCeiling = Math.max(6e4, explicitWait + 15e3, waitForTimeout + 15e3);
|
|
17162
|
-
if (step.runFlow) {
|
|
17430
|
+
if (step.runFlow || step.launchApp) {
|
|
17163
17431
|
await this.runStep(step, i);
|
|
17164
17432
|
continue;
|
|
17165
17433
|
}
|
|
@@ -17489,7 +17757,7 @@ var skill5 = {
|
|
|
17489
17757
|
async execute(params, context) {
|
|
17490
17758
|
const fs9 = await import("fs");
|
|
17491
17759
|
const path9 = await import("path");
|
|
17492
|
-
const
|
|
17760
|
+
const yaml2 = await import("yaml");
|
|
17493
17761
|
const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT2 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
|
|
17494
17762
|
const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
|
|
17495
17763
|
const { createBridge: createBridge2 } = await Promise.resolve().then(() => (init_ws_bridge(), ws_bridge_exports));
|
|
@@ -17500,7 +17768,7 @@ var skill5 = {
|
|
|
17500
17768
|
const flowContent = fs9.readFileSync(params.flowPath, "utf8");
|
|
17501
17769
|
const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
17502
17770
|
const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
|
|
17503
|
-
const steps =
|
|
17771
|
+
const steps = yaml2.parse(stepsBody);
|
|
17504
17772
|
const beforeIds = new Set(host.listSims().map((sim) => sim.id));
|
|
17505
17773
|
await host.openUrl(context.url);
|
|
17506
17774
|
let simId = null;
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.142 | (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/config.ts
CHANGED
|
@@ -20,6 +20,15 @@ export interface SootSimConfig<
|
|
|
20
20
|
turboModules?: Record<string, NativeModuleResolution>
|
|
21
21
|
nativeModules?: Record<string, NativeModuleResolution>
|
|
22
22
|
env?: Record<string, string>
|
|
23
|
+
// generic per-sim network rewrites for the guest app's runtime fetches.
|
|
24
|
+
// `remap` keys/values are `host:port` (or bare `host`) — a tenant fetch whose
|
|
25
|
+
// url matches a key has its host:port swapped for the value before the
|
|
26
|
+
// request is issued. exists for third-party e2e suites that hardcode a port
|
|
27
|
+
// (e.g. bluesky's flows type `http://localhost:3000`) which collides with a
|
|
28
|
+
// host service; map it to the real bound port without editing the app.
|
|
29
|
+
network?: {
|
|
30
|
+
remap?: Record<string, string>
|
|
31
|
+
}
|
|
23
32
|
settings?: Partial<Settings>
|
|
24
33
|
initialState?: {
|
|
25
34
|
authenticated?: boolean
|
|
@@ -51,6 +60,7 @@ export function hasSootSimConfig<
|
|
|
51
60
|
hasOwnKeys(config.turboModules as Record<string, unknown> | undefined) ||
|
|
52
61
|
hasOwnKeys(config.nativeModules as Record<string, unknown> | undefined) ||
|
|
53
62
|
hasOwnKeys(config.env as Record<string, unknown> | undefined) ||
|
|
63
|
+
hasOwnKeys(config.network?.remap as Record<string, unknown> | undefined) ||
|
|
54
64
|
hasOwnKeys(config.settings as Record<string, unknown> | undefined) ||
|
|
55
65
|
hasOwnKeys(config.initialState as Record<string, unknown> | undefined)
|
|
56
66
|
)
|
|
@@ -74,6 +84,9 @@ export function mergeSootSimConfig<
|
|
|
74
84
|
...(override.nativeModules || {}),
|
|
75
85
|
},
|
|
76
86
|
env: { ...(base.env || {}), ...(override.env || {}) },
|
|
87
|
+
network: {
|
|
88
|
+
remap: { ...(base.network?.remap || {}), ...(override.network?.remap || {}) },
|
|
89
|
+
},
|
|
77
90
|
settings: {
|
|
78
91
|
...(base.settings || {}),
|
|
79
92
|
...(override.settings || {}),
|