peachsim 0.1.668 → 0.1.670
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/commands/control.ts +8 -5
- package/cli/commands/inspect/core.ts +7 -5
- package/cli/commands/inspect/wait-selector.ts +2 -11
- package/cli/commands/inspect.ts +6 -59
- package/cli/commands/kotlin.ts +6 -4
- package/cli/commands/skills.ts +28 -7
- package/cli/commands/upgrade.ts +18 -3
- package/cli/main.ts +21 -0
- package/cli/output-redaction.ts +182 -0
- package/cli/parse-args.ts +1 -0
- 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-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.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 +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 +29 -19
- 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 +260 -17
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +2 -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 +259 -16
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- package/dist-lib/native-firebase-metadata.cjs +115 -0
- package/dist-lib/native-firebase-metadata.mjs +86 -0
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +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 +2 -2
- package/dist-lib/sdk.mjs +2 -2
- package/dist-lib/skills.cjs +479 -204
- package/dist-lib/swift-compile.cjs +1 -1
- package/dist-lib/swift-compile.mjs +1 -1
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +21 -13
- package/dist-lib/vite.cjs +1 -1
- package/kotlin/AppSources/androidx/activity/ActivityFlags.kt +9 -0
- package/kotlin/AppSources/androidx/activity/BackEventCompat.kt +25 -4
- package/kotlin/AppSources/androidx/activity/ComponentActivity.kt +15 -4
- package/kotlin/AppSources/androidx/activity/EdgeToEdge.kt +12 -8
- package/kotlin/AppSources/androidx/activity/ExperimentalActivityApi.kt +6 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedCallback.kt +50 -9
- package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +67 -89
- package/kotlin/AppSources/androidx/activity/compose/BackHandler.kt +55 -24
- package/kotlin/AppSources/androidx/activity/compose/internal/BackHandlerCompat.kt +38 -0
- package/kotlin/AppSources/androidx/activity/compose/internal/BackHandlerDispatcherCompat.kt +27 -0
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +5 -5
- package/kotlin/ComposeSources/PeachComposeHost.kt +31 -7
- package/kotlin/fixtures/kotlin-app/app/build.gradle.kts +1 -1
- package/kotlin/fixtures/kotlin-app-variants/Browse.kt +73 -0
- package/kotlin/fixtures/kotlin-app-variants/Focus.kt +62 -0
- package/kotlin/fixtures/kotlin-app-variants/Lists.kt +57 -0
- package/kotlin/fixtures/kotlin-app-variants/Nav.kt +47 -0
- package/kotlin/fixtures/kotlin-app-variants/Nested.kt +64 -0
- package/kotlin/fixtures/kotlin-app-variants/Pan.kt +38 -0
- package/kotlin/fixtures/kotlin-app-variants/Pickers.kt +44 -0
- package/kotlin/fixtures/kotlin-app-variants/Press.kt +43 -0
- package/kotlin/fixtures/kotlin-app-variants/TextWidth.kt +45 -0
- package/kotlin/fixtures/kotlin-app-variants/Transition.kt +69 -0
- package/kotlin/fixtures/kotlin-app-variants/ViewConfig.kt +22 -0
- package/kotlin/toolchain.json +30 -2
- package/package.json +8 -1
- package/skills/contrast/SKILL.md +2 -1
- package/skills/peach-debug/SKILL.md +2 -2
- package/skills/peach-test/SKILL.md +3 -3
- package/src/expo-swift-host.ts +13 -4
- package/src/kotlin-app.ts +35 -16
- package/src/kotlin-host.ts +1 -0
- package/src/metro-plugin.ts +24 -0
- package/src/native-firebase-config.ts +202 -21
- package/src/native-firebase-metadata.ts +114 -0
- package/src/swift-host.ts +30 -15
- package/src/vite-plugin.ts +46 -2
- package/kotlin/AppSources/androidx/activity/Cancellable.kt +0 -5
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! rnx v0.1.
|
|
1
|
+
/*! rnx v0.1.670 | (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;
|
|
@@ -746,7 +746,6 @@ var init_light_native_package_names = __esm({
|
|
|
746
746
|
"@dariyd/react-native-text-recognition",
|
|
747
747
|
"@dashdoc/react-native-system-sounds",
|
|
748
748
|
"@datadog/mobile-react-native-session-replay",
|
|
749
|
-
"@datadog/mobile-react-native-webview",
|
|
750
749
|
"@datadome/datadome-axios",
|
|
751
750
|
"@datadome/react-native-datadome",
|
|
752
751
|
"@datalyr/react-native",
|
|
@@ -18901,7 +18900,7 @@ var init_web = __esm({
|
|
|
18901
18900
|
|
|
18902
18901
|
// src/sleep.ts
|
|
18903
18902
|
function sleep(ms) {
|
|
18904
|
-
return new Promise((
|
|
18903
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
18905
18904
|
}
|
|
18906
18905
|
var init_sleep = __esm({
|
|
18907
18906
|
"src/sleep.ts"() {
|
|
@@ -19045,7 +19044,7 @@ var init_bridge_constants = __esm({
|
|
|
19045
19044
|
|
|
19046
19045
|
// ../contrast/src/sleep.ts
|
|
19047
19046
|
function sleep2(ms) {
|
|
19048
|
-
return new Promise((
|
|
19047
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
19049
19048
|
}
|
|
19050
19049
|
var init_sleep2 = __esm({
|
|
19051
19050
|
"../contrast/src/sleep.ts"() {
|
|
@@ -19481,9 +19480,9 @@ function safeChildPlistName(value) {
|
|
|
19481
19480
|
name: file.toLowerCase().endsWith(".plist") ? file : `${file}.plist`
|
|
19482
19481
|
};
|
|
19483
19482
|
}
|
|
19484
|
-
async function readableSettingsBundle(
|
|
19483
|
+
async function readableSettingsBundle(path28) {
|
|
19485
19484
|
try {
|
|
19486
|
-
const root = await (0, import_promises.stat)((0, import_node_path.join)(
|
|
19485
|
+
const root = await (0, import_promises.stat)((0, import_node_path.join)(path28, "Root.plist"));
|
|
19487
19486
|
return root.isFile() && root.size <= MAX_PLIST_BYTES;
|
|
19488
19487
|
} catch {
|
|
19489
19488
|
return false;
|
|
@@ -19528,11 +19527,11 @@ async function settingsBundleFingerprint(bundlePath) {
|
|
|
19528
19527
|
return null;
|
|
19529
19528
|
}
|
|
19530
19529
|
}
|
|
19531
|
-
async function parsePlistRecord(
|
|
19530
|
+
async function parsePlistRecord(path28) {
|
|
19532
19531
|
try {
|
|
19533
|
-
const metadata = await (0, import_promises.stat)(
|
|
19532
|
+
const metadata = await (0, import_promises.stat)(path28);
|
|
19534
19533
|
if (!metadata.isFile() || metadata.size > MAX_PLIST_BYTES) return null;
|
|
19535
|
-
const source = await (0, import_promises.readFile)(
|
|
19534
|
+
const source = await (0, import_promises.readFile)(path28, "utf8");
|
|
19536
19535
|
const parsed = parsePlistSource(source);
|
|
19537
19536
|
return isRecord2(parsed) ? parsed : null;
|
|
19538
19537
|
} catch {
|
|
@@ -19786,7 +19785,7 @@ var init_optional_demo_registry = __esm({
|
|
|
19786
19785
|
// scripts/dev-server-scanner.ts
|
|
19787
19786
|
function execGuarded(command, timeout, extra = {}) {
|
|
19788
19787
|
const maxBuffer = extra.maxBuffer ?? 1024 * 1024;
|
|
19789
|
-
return new Promise((
|
|
19788
|
+
return new Promise((resolve10, reject) => {
|
|
19790
19789
|
const child = (0, import_child_process.spawn)("/bin/sh", ["-c", command], {
|
|
19791
19790
|
detached: true,
|
|
19792
19791
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -19799,7 +19798,7 @@ function execGuarded(command, timeout, extra = {}) {
|
|
|
19799
19798
|
settled = true;
|
|
19800
19799
|
clearTimeout(deadline);
|
|
19801
19800
|
if (err) reject(err);
|
|
19802
|
-
else
|
|
19801
|
+
else resolve10({ stdout });
|
|
19803
19802
|
};
|
|
19804
19803
|
const killThenSettle = (err) => {
|
|
19805
19804
|
if (killing) return;
|
|
@@ -19834,14 +19833,14 @@ async function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
|
19834
19833
|
try {
|
|
19835
19834
|
return await Promise.any(
|
|
19836
19835
|
LOOPBACK_PROBE_HOSTNAMES.map(
|
|
19837
|
-
(hostname) => new Promise((
|
|
19836
|
+
(hostname) => new Promise((resolve10, reject) => {
|
|
19838
19837
|
const sock = new import_net.default.Socket();
|
|
19839
19838
|
let settled = false;
|
|
19840
19839
|
const done = (reachable) => {
|
|
19841
19840
|
if (settled) return;
|
|
19842
19841
|
settled = true;
|
|
19843
19842
|
sock.destroy();
|
|
19844
|
-
if (reachable)
|
|
19843
|
+
if (reachable) resolve10(hostname);
|
|
19845
19844
|
else reject(new Error(`unreachable loopback host ${hostname}`));
|
|
19846
19845
|
};
|
|
19847
19846
|
sock.setTimeout(timeout);
|
|
@@ -19856,16 +19855,16 @@ async function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
|
19856
19855
|
return null;
|
|
19857
19856
|
}
|
|
19858
19857
|
}
|
|
19859
|
-
function httpGet(hostname, port,
|
|
19860
|
-
return new Promise((
|
|
19858
|
+
function httpGet(hostname, port, path28, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
|
|
19859
|
+
return new Promise((resolve10) => {
|
|
19861
19860
|
let settled = false;
|
|
19862
19861
|
let killing = false;
|
|
19863
19862
|
const settle = (value) => {
|
|
19864
19863
|
if (settled) return;
|
|
19865
19864
|
settled = true;
|
|
19866
|
-
|
|
19865
|
+
resolve10(value);
|
|
19867
19866
|
};
|
|
19868
|
-
const req = import_http.default.request({ hostname, port, path:
|
|
19867
|
+
const req = import_http.default.request({ hostname, port, path: path28, method, headers }, (res) => {
|
|
19869
19868
|
let body = "";
|
|
19870
19869
|
res.on("data", (c) => body += c.toString());
|
|
19871
19870
|
const contentType = (() => {
|
|
@@ -21119,9 +21118,9 @@ function getCliVersion() {
|
|
|
21119
21118
|
() => (0, import_node_url2.fileURLToPath)(import_meta.resolve(`${rnxPublicBrand.packageName}/package.json`)),
|
|
21120
21119
|
() => (0, import_node_url2.fileURLToPath)(new URL("../package.json", __sootsim_import_meta_url))
|
|
21121
21120
|
];
|
|
21122
|
-
for (const
|
|
21121
|
+
for (const resolve10 of candidates) {
|
|
21123
21122
|
try {
|
|
21124
|
-
const version = JSON.parse((0, import_node_fs5.readFileSync)(
|
|
21123
|
+
const version = JSON.parse((0, import_node_fs5.readFileSync)(resolve10(), "utf8")).version;
|
|
21125
21124
|
if (typeof version === "string" && version) {
|
|
21126
21125
|
cached2 = version;
|
|
21127
21126
|
return cached2;
|
|
@@ -21181,8 +21180,8 @@ function pickImagesetFile(images) {
|
|
|
21181
21180
|
scale: pick.scale === "2x" ? 2 : pick.scale === "3x" ? 3 : 1
|
|
21182
21181
|
};
|
|
21183
21182
|
}
|
|
21184
|
-
function flatScale(
|
|
21185
|
-
const match = /@([23])x\.[^./]+$/.exec(
|
|
21183
|
+
function flatScale(path28) {
|
|
21184
|
+
const match = /@([23])x\.[^./]+$/.exec(path28);
|
|
21186
21185
|
return match ? Number(match[1]) : 1;
|
|
21187
21186
|
}
|
|
21188
21187
|
function providesNamespace(text) {
|
|
@@ -21209,13 +21208,13 @@ function catalogEntryName(contentsPath, kind, readText2) {
|
|
|
21209
21208
|
}
|
|
21210
21209
|
return segments.join("/");
|
|
21211
21210
|
}
|
|
21212
|
-
function isFlatResourceImage(
|
|
21213
|
-
return
|
|
21211
|
+
function isFlatResourceImage(path28) {
|
|
21212
|
+
return path28.split("/").includes("Resources") && RASTER_EXTENSIONS.has(extOf(path28));
|
|
21214
21213
|
}
|
|
21215
21214
|
function enumerateBundleImages(paths, readText2) {
|
|
21216
21215
|
const table = [];
|
|
21217
21216
|
const seen = /* @__PURE__ */ new Set();
|
|
21218
|
-
const catalogs = paths.filter((
|
|
21217
|
+
const catalogs = paths.filter((path28) => baseOf(path28) === "Contents.json");
|
|
21219
21218
|
for (const contentsPath of catalogs) {
|
|
21220
21219
|
const name2 = catalogEntryName(contentsPath, ".imageset", readText2);
|
|
21221
21220
|
if (name2 === null || seen.has(name2)) continue;
|
|
@@ -21236,12 +21235,12 @@ function enumerateBundleImages(paths, readText2) {
|
|
|
21236
21235
|
seen.add(name2);
|
|
21237
21236
|
table.push({ name: name2, file: `${dir}/${pick.filename}`, scale: pick.scale });
|
|
21238
21237
|
}
|
|
21239
|
-
for (const
|
|
21240
|
-
if (!isFlatResourceImage(
|
|
21241
|
-
const name2 = baseOf(
|
|
21238
|
+
for (const path28 of paths) {
|
|
21239
|
+
if (!isFlatResourceImage(path28)) continue;
|
|
21240
|
+
const name2 = baseOf(path28).slice(0, -extOf(path28).length);
|
|
21242
21241
|
if (name2 === "" || seen.has(name2)) continue;
|
|
21243
21242
|
seen.add(name2);
|
|
21244
|
-
table.push({ name: name2, file:
|
|
21243
|
+
table.push({ name: name2, file: path28, scale: flatScale(path28) });
|
|
21245
21244
|
}
|
|
21246
21245
|
return table;
|
|
21247
21246
|
}
|
|
@@ -21270,7 +21269,7 @@ function colorsetValue(color) {
|
|
|
21270
21269
|
}
|
|
21271
21270
|
function enumerateBundleColors(paths, readText2) {
|
|
21272
21271
|
const table = {};
|
|
21273
|
-
for (const contentsPath of paths.filter((
|
|
21272
|
+
for (const contentsPath of paths.filter((path28) => baseOf(path28) === "Contents.json")) {
|
|
21274
21273
|
const name2 = catalogEntryName(contentsPath, ".colorset", readText2);
|
|
21275
21274
|
if (name2 === null || name2 in table) continue;
|
|
21276
21275
|
let colors;
|
|
@@ -21334,8 +21333,8 @@ function axisExtremes(points) {
|
|
|
21334
21333
|
function pathBounds(d) {
|
|
21335
21334
|
const xs = [];
|
|
21336
21335
|
const ys = [];
|
|
21337
|
-
for (const
|
|
21338
|
-
(0, import_svgpath.default)(
|
|
21336
|
+
for (const path28 of d)
|
|
21337
|
+
(0, import_svgpath.default)(path28).abs().unshort().unarc().iterate((segment, _index, x, y) => {
|
|
21339
21338
|
const [command, ...args] = segment;
|
|
21340
21339
|
if (command === "M" || command === "L") {
|
|
21341
21340
|
xs.push(Number(args[0]));
|
|
@@ -21362,7 +21361,7 @@ function guide(svg, id, axis) {
|
|
|
21362
21361
|
}
|
|
21363
21362
|
function enumerateBundleSymbols(paths, readText2) {
|
|
21364
21363
|
const table = {};
|
|
21365
|
-
for (const contentsPath of paths.filter((
|
|
21364
|
+
for (const contentsPath of paths.filter((path28) => baseOf(path28) === "Contents.json")) {
|
|
21366
21365
|
const name2 = catalogEntryName(contentsPath, ".symbolset", readText2);
|
|
21367
21366
|
if (name2 === null || name2 in table) continue;
|
|
21368
21367
|
let symbols;
|
|
@@ -21395,8 +21394,8 @@ function enumerateBundleSymbols(paths, readText2) {
|
|
|
21395
21394
|
viewBox: "0 0 24 24",
|
|
21396
21395
|
advance,
|
|
21397
21396
|
box: [12 - advance / 2, 12 - tall / 2, advance, tall],
|
|
21398
|
-
layers: d.map((
|
|
21399
|
-
d: (0, import_svgpath.default)(
|
|
21397
|
+
layers: d.map((path28) => ({
|
|
21398
|
+
d: (0, import_svgpath.default)(path28).abs().scale(scale).translate(translateX, translateY).round(3).toString()
|
|
21400
21399
|
}))
|
|
21401
21400
|
};
|
|
21402
21401
|
}
|
|
@@ -21406,7 +21405,7 @@ function enumerateBundleJson(paths) {
|
|
|
21406
21405
|
const found = [];
|
|
21407
21406
|
const seen = /* @__PURE__ */ new Set();
|
|
21408
21407
|
const ordered = [...paths].filter(
|
|
21409
|
-
(
|
|
21408
|
+
(path28) => path28.split("/").includes("Resources") && path28.split("/").every((segment) => segment !== "" && segment !== "..") && (extOf(path28) === ".json" || extOf(path28) === ".xcstrings")
|
|
21410
21409
|
).sort((a, b) => {
|
|
21411
21410
|
const aDepth = a.split("/").length;
|
|
21412
21411
|
const bDepth = b.split("/").length;
|
|
@@ -22455,10 +22454,10 @@ async function compileSwiftProject(submit, work, origin, signal) {
|
|
|
22455
22454
|
...outcome.native === void 0 ? {} : { native: outcome.native }
|
|
22456
22455
|
};
|
|
22457
22456
|
case "compiling":
|
|
22458
|
-
await new Promise((
|
|
22457
|
+
await new Promise((resolve10, reject) => {
|
|
22459
22458
|
const finish = () => {
|
|
22460
22459
|
signal?.removeEventListener("abort", abort);
|
|
22461
|
-
|
|
22460
|
+
resolve10();
|
|
22462
22461
|
};
|
|
22463
22462
|
const timer = setTimeout(finish, POLL_INTERVAL_MS);
|
|
22464
22463
|
const abort = () => {
|
|
@@ -22820,13 +22819,11 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
|
|
|
22820
22819
|
stamp,
|
|
22821
22820
|
package: content
|
|
22822
22821
|
};
|
|
22823
|
-
const toolchain =
|
|
22824
|
-
|
|
22825
|
-
|
|
22826
|
-
|
|
22827
|
-
|
|
22828
|
-
throw new Error(`swift toolchain manifest at ${moduleRoot} has no release`);
|
|
22829
|
-
}
|
|
22822
|
+
const toolchain = localSwiftToolchain(moduleRoot);
|
|
22823
|
+
if (!toolchain)
|
|
22824
|
+
throw new Error(
|
|
22825
|
+
`the Swift toolchain ${moduleRoot}/toolchain.json names is not installed under ~/Library/Developer/Toolchains`
|
|
22826
|
+
);
|
|
22830
22827
|
const artifact = await compileSwiftProjectUnit(snapshotCompileInput(snapshot, entry), {
|
|
22831
22828
|
// the compile rewrites Sources/App in its root before swiftpm builds, and
|
|
22832
22829
|
// its lock orders one process only: two vites on one root (a lane's dev
|
|
@@ -22839,14 +22836,24 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
|
|
|
22839
22836
|
(0, import_node_crypto4.createHash)("sha256").update(`${moduleRoot}\0${import_node_path9.default.resolve(packagePath)}`).digest("hex").slice(0, 16)
|
|
22840
22837
|
),
|
|
22841
22838
|
moduleRoot,
|
|
22842
|
-
|
|
22843
|
-
toolchainBin: import_node_path9.default.join(
|
|
22844
|
-
import_node_os3.default.homedir(),
|
|
22845
|
-
`Library/Developer/Toolchains/${release}.xctoolchain/usr/bin`
|
|
22846
|
-
)
|
|
22839
|
+
...toolchain
|
|
22847
22840
|
});
|
|
22848
22841
|
return { ...artifact, stamp, package: content };
|
|
22849
22842
|
}
|
|
22843
|
+
function localSwiftToolchain(moduleRoot) {
|
|
22844
|
+
const manifest = import_node_path9.default.join(moduleRoot, "toolchain.json");
|
|
22845
|
+
if (!import_node_fs9.default.existsSync(manifest)) return null;
|
|
22846
|
+
const toolchain = JSON.parse(import_node_fs9.default.readFileSync(manifest, "utf8"));
|
|
22847
|
+
const release = toolchain && typeof toolchain === "object" ? Reflect.get(toolchain, "release") : void 0;
|
|
22848
|
+
if (typeof release !== "string") {
|
|
22849
|
+
throw new Error(`swift toolchain manifest at ${moduleRoot} has no release`);
|
|
22850
|
+
}
|
|
22851
|
+
const toolchainBin = import_node_path9.default.join(
|
|
22852
|
+
import_node_os3.default.homedir(),
|
|
22853
|
+
`Library/Developer/Toolchains/${release}.xctoolchain/usr/bin`
|
|
22854
|
+
);
|
|
22855
|
+
return import_node_fs9.default.existsSync(import_node_path9.default.join(toolchainBin, "swift")) ? { release, toolchainBin } : null;
|
|
22856
|
+
}
|
|
22850
22857
|
async function compileRemote(packagePath, entry, snapshot, hosted) {
|
|
22851
22858
|
const auth = hosted ? null : resolveCliAuth();
|
|
22852
22859
|
if (!hosted && (!auth || auth.kind === "github")) {
|
|
@@ -23198,6 +23205,8 @@ async function handleExpoSwiftRequest(req, res) {
|
|
|
23198
23205
|
pending = (async () => {
|
|
23199
23206
|
const files = await collectExpoSwiftSources(root);
|
|
23200
23207
|
if (!files) return null;
|
|
23208
|
+
const moduleRoot = import_node_path10.default.resolve(import_meta2.dirname, "../../sootsim-swift");
|
|
23209
|
+
if (!localSwiftToolchain(moduleRoot)) return null;
|
|
23201
23210
|
const key = (0, import_node_crypto5.createHash)("sha256").update(import_node_fs10.default.realpathSync(root)).digest("hex");
|
|
23202
23211
|
const packagePath = import_node_path10.default.join(import_node_os4.default.tmpdir(), "peach-expo-swift", key);
|
|
23203
23212
|
const sources = import_node_path10.default.join(packagePath, "Sources");
|
|
@@ -23208,12 +23217,10 @@ async function handleExpoSwiftRequest(req, res) {
|
|
|
23208
23217
|
import_node_fs10.default.mkdirSync(import_node_path10.default.dirname(target), { recursive: true });
|
|
23209
23218
|
import_node_fs10.default.writeFileSync(target, content);
|
|
23210
23219
|
}
|
|
23211
|
-
const moduleRoot = import_node_path10.default.resolve(import_meta2.dirname, "../../sootsim-swift");
|
|
23212
|
-
const local = import_node_fs10.default.existsSync(import_node_path10.default.join(moduleRoot, "toolchain.json"));
|
|
23213
23220
|
const artifact = await artifactFor(
|
|
23214
23221
|
projectFor(packagePath),
|
|
23215
23222
|
EXPO_SWIFT_ENTRY,
|
|
23216
|
-
|
|
23223
|
+
moduleRoot
|
|
23217
23224
|
);
|
|
23218
23225
|
const host2 = req.headers.host;
|
|
23219
23226
|
if (!host2) throw new Error("Expo Swift request has no host");
|
|
@@ -23669,16 +23676,16 @@ async function downloadToFile(url, destPath) {
|
|
|
23669
23676
|
}
|
|
23670
23677
|
}
|
|
23671
23678
|
function digestFile(filePath, algorithm, encoding) {
|
|
23672
|
-
return new Promise((
|
|
23679
|
+
return new Promise((resolve10, reject) => {
|
|
23673
23680
|
const hash = import_node_crypto6.default.createHash(algorithm);
|
|
23674
23681
|
const stream = import_node_fs12.default.createReadStream(filePath);
|
|
23675
23682
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
23676
23683
|
stream.on("error", reject);
|
|
23677
|
-
stream.on("end", () =>
|
|
23684
|
+
stream.on("end", () => resolve10(hash.digest(encoding)));
|
|
23678
23685
|
});
|
|
23679
23686
|
}
|
|
23680
23687
|
function extractTarball(tarPath, destDir, stripComponents) {
|
|
23681
|
-
return new Promise((
|
|
23688
|
+
return new Promise((resolve10, reject) => {
|
|
23682
23689
|
const args = ["-xzf", tarPath, "-C", destDir];
|
|
23683
23690
|
if (stripComponents > 0) args.push(`--strip-components=${stripComponents}`);
|
|
23684
23691
|
const child = (0, import_node_child_process6.spawn)("tar", args, {
|
|
@@ -23686,7 +23693,7 @@ function extractTarball(tarPath, destDir, stripComponents) {
|
|
|
23686
23693
|
});
|
|
23687
23694
|
child.on("error", reject);
|
|
23688
23695
|
child.on("exit", (code) => {
|
|
23689
|
-
if (code === 0)
|
|
23696
|
+
if (code === 0) resolve10();
|
|
23690
23697
|
else reject(new Error(`tar exited with code ${code}`));
|
|
23691
23698
|
});
|
|
23692
23699
|
});
|
|
@@ -23881,8 +23888,8 @@ function sourceEntryPath() {
|
|
|
23881
23888
|
return null;
|
|
23882
23889
|
}
|
|
23883
23890
|
}
|
|
23884
|
-
function isCliEntry(
|
|
23885
|
-
const name2 = (0, import_node_path13.basename)(
|
|
23891
|
+
function isCliEntry(path28) {
|
|
23892
|
+
const name2 = (0, import_node_path13.basename)(path28);
|
|
23886
23893
|
return name2 === "bin.ts" || name2 === "bin.js";
|
|
23887
23894
|
}
|
|
23888
23895
|
function rnxSelfInvocation() {
|
|
@@ -24891,9 +24898,9 @@ var init_agent_host = __esm({
|
|
|
24891
24898
|
if (queue2.length === 0) this.inspectQueues.delete(simId);
|
|
24892
24899
|
return Promise.resolve(queued);
|
|
24893
24900
|
}
|
|
24894
|
-
return new Promise((
|
|
24901
|
+
return new Promise((resolve10, reject) => {
|
|
24895
24902
|
const listeners = this.inspectListeners.get(simId) ?? [];
|
|
24896
|
-
listeners.push({ socket, resolve:
|
|
24903
|
+
listeners.push({ socket, resolve: resolve10, reject });
|
|
24897
24904
|
this.inspectListeners.set(simId, listeners);
|
|
24898
24905
|
});
|
|
24899
24906
|
}
|
|
@@ -25420,7 +25427,7 @@ async function handleFetchProxyRequest(req, res) {
|
|
|
25420
25427
|
} else if (nextBody) {
|
|
25421
25428
|
targetHeaders["content-length"] = String(nextBody.byteLength);
|
|
25422
25429
|
}
|
|
25423
|
-
const proxyRes = await new Promise((
|
|
25430
|
+
const proxyRes = await new Promise((resolve10, reject) => {
|
|
25424
25431
|
const proxyReq = transport.request(
|
|
25425
25432
|
{
|
|
25426
25433
|
hostname: normalizeHostname(targetUrl2.hostname),
|
|
@@ -25430,7 +25437,7 @@ async function handleFetchProxyRequest(req, res) {
|
|
|
25430
25437
|
headers: targetHeaders,
|
|
25431
25438
|
...loopbackTlsOptions(targetUrl2)
|
|
25432
25439
|
},
|
|
25433
|
-
|
|
25440
|
+
resolve10
|
|
25434
25441
|
);
|
|
25435
25442
|
const abort = () => proxyReq.destroy(new Error("fetch proxy client disconnected"));
|
|
25436
25443
|
req.once("aborted", abort);
|
|
@@ -25658,7 +25665,7 @@ function buildOpenUrlCommand(url, options = {}) {
|
|
|
25658
25665
|
};
|
|
25659
25666
|
}
|
|
25660
25667
|
async function spawnLaunch(command, args, detached) {
|
|
25661
|
-
return new Promise((
|
|
25668
|
+
return new Promise((resolve10, reject) => {
|
|
25662
25669
|
const child = (0, import_child_process2.spawn)(command, args, {
|
|
25663
25670
|
detached,
|
|
25664
25671
|
stdio: "ignore"
|
|
@@ -25666,7 +25673,7 @@ async function spawnLaunch(command, args, detached) {
|
|
|
25666
25673
|
child.once("error", reject);
|
|
25667
25674
|
child.once("spawn", () => {
|
|
25668
25675
|
if (detached) child.unref();
|
|
25669
|
-
|
|
25676
|
+
resolve10(child.pid);
|
|
25670
25677
|
});
|
|
25671
25678
|
});
|
|
25672
25679
|
}
|
|
@@ -25900,7 +25907,7 @@ var init_checkout_plane = __esm({
|
|
|
25900
25907
|
}
|
|
25901
25908
|
if (attempt < LIST_FILES_ATTEMPTS) {
|
|
25902
25909
|
await new Promise(
|
|
25903
|
-
(
|
|
25910
|
+
(resolve10) => setTimeout(resolve10, LIST_FILES_RETRY_MS * attempt)
|
|
25904
25911
|
);
|
|
25905
25912
|
}
|
|
25906
25913
|
}
|
|
@@ -28527,8 +28534,8 @@ function metroIosAssetDestRelatives(httpServerLocation, filename) {
|
|
|
28527
28534
|
}
|
|
28528
28535
|
const out = [];
|
|
28529
28536
|
for (const dir of dirs) {
|
|
28530
|
-
const
|
|
28531
|
-
if (!out.includes(
|
|
28537
|
+
const path28 = `${dir}/${filename}`;
|
|
28538
|
+
if (!out.includes(path28)) out.push(path28);
|
|
28532
28539
|
}
|
|
28533
28540
|
if (!out.includes(filename)) out.push(filename);
|
|
28534
28541
|
return out;
|
|
@@ -28870,7 +28877,8 @@ async function readOrInferModuleIdentity(bundle, mode, inferModuleIdentity) {
|
|
|
28870
28877
|
}
|
|
28871
28878
|
async function buildRnxCloudArtifact(bundle, options = {}) {
|
|
28872
28879
|
const mode = options.mode ?? "production";
|
|
28873
|
-
const
|
|
28880
|
+
const firebase = (0, import_native_firebase_metadata.detachNativeFirebaseFooter)(bundle);
|
|
28881
|
+
const nativeIdentity = (0, import_native_app_identity.detachNativeAppIdentityFooter)(firebase.source);
|
|
28874
28882
|
const identity = await readOrInferModuleIdentity(
|
|
28875
28883
|
nativeIdentity.source,
|
|
28876
28884
|
mode,
|
|
@@ -28898,7 +28906,7 @@ async function buildRnxCloudArtifact(bundle, options = {}) {
|
|
|
28898
28906
|
})
|
|
28899
28907
|
]);
|
|
28900
28908
|
const body = pieces.map((piece) => piece.code).join("\n");
|
|
28901
|
-
const code = body + (nativeIdentity.identity ? (0, import_native_app_identity.createNativeAppIdentityFooter)(nativeIdentity.identity) : "") + (0, import_metro_production_bundle.createRNXMetroModuleIdentityFooter)({
|
|
28909
|
+
const code = body + (nativeIdentity.identity ? (0, import_native_app_identity.createNativeAppIdentityFooter)(nativeIdentity.identity) : "") + (firebase.config ? (0, import_native_firebase_metadata.createNativeFirebaseFooter)(firebase.config) : "") + (0, import_metro_production_bundle.createRNXMetroModuleIdentityFooter)({
|
|
28902
28910
|
version: identity.version,
|
|
28903
28911
|
identitySource: identity.identitySource,
|
|
28904
28912
|
modulePaths: identity.modulePaths,
|
|
@@ -28961,12 +28969,13 @@ async function buildRnxCloudArtifact(bundle, options = {}) {
|
|
|
28961
28969
|
}
|
|
28962
28970
|
};
|
|
28963
28971
|
}
|
|
28964
|
-
var import_metro_production_bundle, import_native_app_identity, import_terser, MODULE_PATHS_REQUIRED, SOURCE_MAP_REQUIRED, MINIFY_OPTIONS;
|
|
28972
|
+
var import_metro_production_bundle, import_native_app_identity, import_native_firebase_metadata, import_terser, MODULE_PATHS_REQUIRED, SOURCE_MAP_REQUIRED, MINIFY_OPTIONS;
|
|
28965
28973
|
var init_metroCloudArtifact = __esm({
|
|
28966
28974
|
"../contrast-bundler/src/metroCloudArtifact.ts"() {
|
|
28967
28975
|
"use strict";
|
|
28968
28976
|
import_metro_production_bundle = require("peachsim/metro-production-bundle");
|
|
28969
28977
|
import_native_app_identity = require("peachsim/native-app-identity");
|
|
28978
|
+
import_native_firebase_metadata = require("peachsim/native-firebase-metadata");
|
|
28970
28979
|
import_terser = require("terser");
|
|
28971
28980
|
init_metroAssetArtifact();
|
|
28972
28981
|
init_metroDebugSourceMap();
|
|
@@ -29478,13 +29487,13 @@ function readFactoryStringLiterals(factory) {
|
|
|
29478
29487
|
return literals;
|
|
29479
29488
|
}
|
|
29480
29489
|
function normalizeFingerprintLiteral(literal) {
|
|
29481
|
-
const
|
|
29490
|
+
const path28 = literal.replaceAll("\\\\", "/").replaceAll("\\/", "/");
|
|
29482
29491
|
const nodeModulesMarker = "/node_modules/";
|
|
29483
|
-
const nodeModulesIndex =
|
|
29492
|
+
const nodeModulesIndex = path28.lastIndexOf(nodeModulesMarker);
|
|
29484
29493
|
if (nodeModulesIndex >= 0) {
|
|
29485
|
-
return `node_modules/${
|
|
29494
|
+
return `node_modules/${path28.slice(nodeModulesIndex + nodeModulesMarker.length)}`;
|
|
29486
29495
|
}
|
|
29487
|
-
if ((
|
|
29496
|
+
if ((path28.startsWith("/") || /^[A-Za-z]:\//.test(path28) || path28.startsWith("file:/")) && /\.[cm]?[jt]sx?(?::\d+(?::\d+)?)?$/.test(path28)) {
|
|
29488
29497
|
return null;
|
|
29489
29498
|
}
|
|
29490
29499
|
return literal;
|
|
@@ -29722,10 +29731,10 @@ function templateAssignment(template, embeddings) {
|
|
|
29722
29731
|
if (existingNode !== void 0 && existingNode !== nodeIndex) return null;
|
|
29723
29732
|
nodesByModuleId.set(moduleId, nodeIndex);
|
|
29724
29733
|
const node = template.nodes[nodeIndex];
|
|
29725
|
-
const
|
|
29734
|
+
const path28 = node.landmarkPath ?? `node_modules/${template.packageName}/__rnx_inferred__/${moduleId}.js`;
|
|
29726
29735
|
const existingPath = pathsByModuleId.get(moduleId);
|
|
29727
|
-
if (existingPath !== void 0 && existingPath !==
|
|
29728
|
-
pathsByModuleId.set(moduleId,
|
|
29736
|
+
if (existingPath !== void 0 && existingPath !== path28) return null;
|
|
29737
|
+
pathsByModuleId.set(moduleId, path28);
|
|
29729
29738
|
}
|
|
29730
29739
|
}
|
|
29731
29740
|
return {
|
|
@@ -29887,14 +29896,14 @@ async function inferMetroModuleIdentity(args) {
|
|
|
29887
29896
|
const packageClaims = claimsByPackage.values().next().value;
|
|
29888
29897
|
if (!packageClaims) continue;
|
|
29889
29898
|
const exactClaims = packageClaims.filter((assignment2) => {
|
|
29890
|
-
const
|
|
29891
|
-
return
|
|
29899
|
+
const path28 = assignment2.pathsByModuleId.get(moduleId);
|
|
29900
|
+
return path28 !== void 0 && !path28.includes("/__rnx_inferred__/");
|
|
29892
29901
|
});
|
|
29893
29902
|
const preferredClaims = exactClaims.length > 0 ? exactClaims : packageClaims;
|
|
29894
29903
|
const routes = new Set(
|
|
29895
29904
|
preferredClaims.flatMap((assignment2) => {
|
|
29896
|
-
const
|
|
29897
|
-
return
|
|
29905
|
+
const path28 = assignment2.pathsByModuleId.get(moduleId);
|
|
29906
|
+
return path28 ? [metroFingerprintModuleClaimRoute(assignment2.packageName, path28)] : [];
|
|
29898
29907
|
})
|
|
29899
29908
|
);
|
|
29900
29909
|
if (routes.size !== 1) continue;
|
|
@@ -30215,11 +30224,11 @@ function detectProject(dir) {
|
|
|
30215
30224
|
devCommand: typeof devCommand === "string" ? devCommand : null
|
|
30216
30225
|
};
|
|
30217
30226
|
}
|
|
30218
|
-
function readProjectMetadata(
|
|
30227
|
+
function readProjectMetadata(path28) {
|
|
30219
30228
|
try {
|
|
30220
|
-
const info = (0, import_node_fs20.lstatSync)(
|
|
30229
|
+
const info = (0, import_node_fs20.lstatSync)(path28);
|
|
30221
30230
|
if (!info.isFile() || info.size > 4 * 1024 * 1024) return null;
|
|
30222
|
-
return (0, import_node_fs20.readFileSync)(
|
|
30231
|
+
return (0, import_node_fs20.readFileSync)(path28, "utf8");
|
|
30223
30232
|
} catch {
|
|
30224
30233
|
return null;
|
|
30225
30234
|
}
|
|
@@ -30228,8 +30237,8 @@ function metadataValue(value, key) {
|
|
|
30228
30237
|
if (!value || typeof value !== "object") return void 0;
|
|
30229
30238
|
return Object.getOwnPropertyDescriptor(value, key)?.value;
|
|
30230
30239
|
}
|
|
30231
|
-
function readProjectJson(
|
|
30232
|
-
const text = readProjectMetadata(
|
|
30240
|
+
function readProjectJson(path28) {
|
|
30241
|
+
const text = readProjectMetadata(path28);
|
|
30233
30242
|
if (text === null) return null;
|
|
30234
30243
|
try {
|
|
30235
30244
|
const value = JSON.parse(text);
|
|
@@ -31326,7 +31335,7 @@ var init_bridge_host = __esm({
|
|
|
31326
31335
|
);
|
|
31327
31336
|
}
|
|
31328
31337
|
bindOnce(port, _silent) {
|
|
31329
|
-
return new Promise((
|
|
31338
|
+
return new Promise((resolve10, reject) => {
|
|
31330
31339
|
const server = (0, import_http4.createServer)((req, res) => this.handleHttpRequest(req, res));
|
|
31331
31340
|
let settled = false;
|
|
31332
31341
|
const onError = (err) => {
|
|
@@ -31363,7 +31372,7 @@ var init_bridge_host = __esm({
|
|
|
31363
31372
|
this.wss?.emit("connection", ws, req);
|
|
31364
31373
|
});
|
|
31365
31374
|
});
|
|
31366
|
-
|
|
31375
|
+
resolve10(address.port);
|
|
31367
31376
|
});
|
|
31368
31377
|
});
|
|
31369
31378
|
}
|
|
@@ -32572,7 +32581,7 @@ var init_bridge_host = __esm({
|
|
|
32572
32581
|
async sendCommand(cmd) {
|
|
32573
32582
|
const sim = await this.waitForSim(cmd.simId);
|
|
32574
32583
|
const id = this.nextCommandId++;
|
|
32575
|
-
return new Promise((
|
|
32584
|
+
return new Promise((resolve10, reject) => {
|
|
32576
32585
|
const timeout = setTimeout(() => {
|
|
32577
32586
|
this.pendingCommands.delete(id);
|
|
32578
32587
|
this.broadcastSimClientStates();
|
|
@@ -32584,7 +32593,7 @@ var init_bridge_host = __esm({
|
|
|
32584
32593
|
clearTimeout(timeout);
|
|
32585
32594
|
this.pendingCommands.delete(id);
|
|
32586
32595
|
this.broadcastSimClientStates();
|
|
32587
|
-
|
|
32596
|
+
resolve10(value);
|
|
32588
32597
|
},
|
|
32589
32598
|
reject: (error) => {
|
|
32590
32599
|
clearTimeout(timeout);
|
|
@@ -32610,23 +32619,23 @@ var init_bridge_host = __esm({
|
|
|
32610
32619
|
async openPathInEditor(filePath, line, column) {
|
|
32611
32620
|
const loc = line != null ? `:${line}${column != null ? `:${column}` : ""}` : "";
|
|
32612
32621
|
const target = `${filePath}${loc}`;
|
|
32613
|
-
const trySpawn = (cmd, args) => new Promise((
|
|
32622
|
+
const trySpawn = (cmd, args) => new Promise((resolve10) => {
|
|
32614
32623
|
try {
|
|
32615
32624
|
const child = (0, import_child_process3.spawn)(cmd, args, { detached: true, stdio: "ignore" });
|
|
32616
32625
|
let settled = false;
|
|
32617
32626
|
child.on("error", () => {
|
|
32618
32627
|
if (settled) return;
|
|
32619
32628
|
settled = true;
|
|
32620
|
-
|
|
32629
|
+
resolve10(false);
|
|
32621
32630
|
});
|
|
32622
32631
|
child.on("spawn", () => {
|
|
32623
32632
|
if (settled) return;
|
|
32624
32633
|
settled = true;
|
|
32625
32634
|
child.unref();
|
|
32626
|
-
|
|
32635
|
+
resolve10(true);
|
|
32627
32636
|
});
|
|
32628
32637
|
} catch {
|
|
32629
|
-
|
|
32638
|
+
resolve10(false);
|
|
32630
32639
|
}
|
|
32631
32640
|
});
|
|
32632
32641
|
const envEditor = process.env.REACT_EDITOR || process.env.EDITOR;
|
|
@@ -32707,7 +32716,7 @@ var init_bridge_host = __esm({
|
|
|
32707
32716
|
}
|
|
32708
32717
|
if (httpServer) {
|
|
32709
32718
|
httpServer.closeAllConnections();
|
|
32710
|
-
await new Promise((
|
|
32719
|
+
await new Promise((resolve10) => httpServer.close(() => resolve10()));
|
|
32711
32720
|
}
|
|
32712
32721
|
}
|
|
32713
32722
|
describeSim(sim, viewerIdentityKey) {
|
|
@@ -32876,7 +32885,7 @@ var init_bridge_host = __esm({
|
|
|
32876
32885
|
const sim = this.getOpenSim(simId);
|
|
32877
32886
|
if (sim) return sim;
|
|
32878
32887
|
}
|
|
32879
|
-
await new Promise((
|
|
32888
|
+
await new Promise((resolve10) => setTimeout(resolve10, intervalMs));
|
|
32880
32889
|
}
|
|
32881
32890
|
if (!simId) throw new Error("no sim connected");
|
|
32882
32891
|
const openSimIds = this.getDefaultSimCandidates().map((sim) => sim.id);
|
|
@@ -33688,7 +33697,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
33688
33697
|
const pending = /* @__PURE__ */ new Map();
|
|
33689
33698
|
const ws = new import_ws2.WebSocket(bridgeWsUrl(wsPort));
|
|
33690
33699
|
const identity = getCliIdentity();
|
|
33691
|
-
const ready = new Promise((
|
|
33700
|
+
const ready = new Promise((resolve10, reject) => {
|
|
33692
33701
|
ws.on("open", () => {
|
|
33693
33702
|
try {
|
|
33694
33703
|
ws.send(
|
|
@@ -33702,7 +33711,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
33702
33711
|
);
|
|
33703
33712
|
} catch {
|
|
33704
33713
|
}
|
|
33705
|
-
|
|
33714
|
+
resolve10();
|
|
33706
33715
|
});
|
|
33707
33716
|
ws.on("error", (err) => {
|
|
33708
33717
|
const cause = err.message ? `: ${err.message}` : "";
|
|
@@ -33792,7 +33801,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
33792
33801
|
const sendOnce = async (defaultSimId, cmdOverride) => {
|
|
33793
33802
|
await ready;
|
|
33794
33803
|
const id = nextId++;
|
|
33795
|
-
return new Promise((
|
|
33804
|
+
return new Promise((resolve10, reject) => {
|
|
33796
33805
|
const timeout = setTimeout(() => {
|
|
33797
33806
|
pending.delete(id);
|
|
33798
33807
|
reject(
|
|
@@ -33804,7 +33813,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
33804
33813
|
pending.set(id, {
|
|
33805
33814
|
resolve: (v) => {
|
|
33806
33815
|
clearTimeout(timeout);
|
|
33807
|
-
|
|
33816
|
+
resolve10(v);
|
|
33808
33817
|
},
|
|
33809
33818
|
reject: (e) => {
|
|
33810
33819
|
clearTimeout(timeout);
|
|
@@ -33974,11 +33983,11 @@ async function evalInBridge(bridge, code, opts = {}) {
|
|
|
33974
33983
|
if (opts.acquireLock) payload.acquireLock = true;
|
|
33975
33984
|
return bridge.send(payload);
|
|
33976
33985
|
}
|
|
33977
|
-
async function callInBridge(bridge,
|
|
33978
|
-
return bridge.send({ type: "call", path:
|
|
33986
|
+
async function callInBridge(bridge, path28, ...args) {
|
|
33987
|
+
return bridge.send({ type: "call", path: path28, args });
|
|
33979
33988
|
}
|
|
33980
|
-
async function callInBridgeWrite(bridge,
|
|
33981
|
-
return bridge.send({ type: "call", path:
|
|
33989
|
+
async function callInBridgeWrite(bridge, path28, ...args) {
|
|
33990
|
+
return bridge.send({ type: "call", path: path28, args, acquireLock: true });
|
|
33982
33991
|
}
|
|
33983
33992
|
var import_node_fs23, import_node_path23, import_ws2, PEACH_PLACEMENT_ENV, resolvedWorld, BridgeSimLockedError, BRIDGE_VALUE_FLAGS_TABLE, BRIDGE_VALUE_FLAGS;
|
|
33984
33993
|
var init_ws_bridge = __esm({
|
|
@@ -34113,8 +34122,8 @@ function getDefaultPortForProtocol(protocol) {
|
|
|
34113
34122
|
return protocol === "https:" ? 443 : 80;
|
|
34114
34123
|
}
|
|
34115
34124
|
function isBaseServerUrl(url) {
|
|
34116
|
-
const
|
|
34117
|
-
return (
|
|
34125
|
+
const path28 = url.pathname || "/";
|
|
34126
|
+
return (path28 === "/" || path28 === "") && !url.search && !url.hash;
|
|
34118
34127
|
}
|
|
34119
34128
|
async function resolvePortViaServerScan(port) {
|
|
34120
34129
|
try {
|
|
@@ -34155,8 +34164,8 @@ async function probeExpoManifest(normalizedBaseUrl, port) {
|
|
|
34155
34164
|
let probeDeadline;
|
|
34156
34165
|
const answered = await Promise.race([
|
|
34157
34166
|
pending,
|
|
34158
|
-
new Promise((
|
|
34159
|
-
probeDeadline = setTimeout(() =>
|
|
34167
|
+
new Promise((resolve10) => {
|
|
34168
|
+
probeDeadline = setTimeout(() => resolve10("timeout"), MANIFEST_PROBE_TIMEOUT_MS);
|
|
34160
34169
|
})
|
|
34161
34170
|
]);
|
|
34162
34171
|
clearTimeout(probeDeadline);
|
|
@@ -34204,7 +34213,7 @@ async function probeBaseUrlBundleDirect(baseUrl, port) {
|
|
|
34204
34213
|
if (!packagerConfirmed) return null;
|
|
34205
34214
|
const deadline = Date.now() + MANIFEST_BOOT_BUDGET_MS;
|
|
34206
34215
|
while (manifest.state === "no-answer" && Date.now() < deadline) {
|
|
34207
|
-
await new Promise((
|
|
34216
|
+
await new Promise((resolve10) => setTimeout(resolve10, MANIFEST_BOOT_RETRY_MS));
|
|
34208
34217
|
manifest = await probeExpoManifest(normalizedBaseUrl, port);
|
|
34209
34218
|
}
|
|
34210
34219
|
}
|
|
@@ -34407,27 +34416,177 @@ var init_flow_timeout_scale = __esm({
|
|
|
34407
34416
|
});
|
|
34408
34417
|
|
|
34409
34418
|
// src/native-firebase-config.ts
|
|
34410
|
-
function readNativeFirebaseConfig(projectRoot) {
|
|
34419
|
+
function readNativeFirebaseConfig(projectRoot, platforms = ["ios", "android"]) {
|
|
34411
34420
|
const result = {};
|
|
34412
|
-
|
|
34413
|
-
|
|
34421
|
+
let config = {};
|
|
34422
|
+
const appJsonPath = import_node_path25.default.join(projectRoot, "app.json");
|
|
34423
|
+
const appJson = import_node_fs25.default.existsSync(appJsonPath) ? JSON.parse(import_node_fs25.default.readFileSync(appJsonPath, "utf8")) : null;
|
|
34424
|
+
const staticExpo = isRecord(appJson) && (isRecord(appJson.expo) || [appJson.ios, appJson.android].some(
|
|
34425
|
+
(value) => isRecord(value) && typeof value.googleServicesFile === "string"
|
|
34426
|
+
));
|
|
34427
|
+
const dynamicExpo = [
|
|
34414
34428
|
"app.config.js",
|
|
34415
34429
|
"app.config.ts",
|
|
34416
34430
|
"app.config.cjs",
|
|
34417
34431
|
"app.config.mjs"
|
|
34418
|
-
].some((name2) => import_node_fs25.default.existsSync(import_node_path25.default.join(projectRoot, name2)))
|
|
34419
|
-
|
|
34420
|
-
|
|
34421
|
-
|
|
34422
|
-
|
|
34423
|
-
|
|
34424
|
-
|
|
34425
|
-
|
|
34426
|
-
|
|
34427
|
-
|
|
34428
|
-
|
|
34429
|
-
|
|
34430
|
-
|
|
34432
|
+
].some((name2) => import_node_fs25.default.existsSync(import_node_path25.default.join(projectRoot, name2)));
|
|
34433
|
+
if (staticExpo || dynamicExpo) {
|
|
34434
|
+
const require5 = (0, import_node_module2.createRequire)(import_node_path25.default.join(projectRoot, "package.json"));
|
|
34435
|
+
const configModule = require5("@expo/config");
|
|
34436
|
+
if (!isRecord(configModule) || typeof configModule.getConfig !== "function")
|
|
34437
|
+
throw new Error("Expo native configuration is unavailable.");
|
|
34438
|
+
const resolved = Reflect.apply(configModule.getConfig, configModule, [
|
|
34439
|
+
projectRoot,
|
|
34440
|
+
{ skipSDKVersionRequirement: true }
|
|
34441
|
+
]);
|
|
34442
|
+
config = isRecord(resolved) && isRecord(resolved.exp) ? resolved.exp : {};
|
|
34443
|
+
}
|
|
34444
|
+
const ios = config.ios;
|
|
34445
|
+
if (platforms.includes("ios") && (!isRecord(ios) || typeof ios.googleServicesFile !== "string")) {
|
|
34446
|
+
const iosRoot = import_node_path25.default.join(projectRoot, "ios");
|
|
34447
|
+
if (import_node_fs25.default.existsSync(iosRoot)) {
|
|
34448
|
+
const projects2 = import_node_fs25.default.readdirSync(iosRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.endsWith(".xcodeproj"));
|
|
34449
|
+
if (projects2.length > 1)
|
|
34450
|
+
throw new Error("native Firebase configuration requires a selected Xcode project");
|
|
34451
|
+
if (projects2.length === 1) {
|
|
34452
|
+
const require5 = (0, import_node_module2.createRequire)(import_node_path25.default.join(projectRoot, "package.json"));
|
|
34453
|
+
const xcode = require5("xcode");
|
|
34454
|
+
if (!isRecord(xcode) || typeof xcode.project !== "function")
|
|
34455
|
+
throw new Error("native Xcode project parser is unavailable");
|
|
34456
|
+
const project = Reflect.apply(xcode.project, xcode, [
|
|
34457
|
+
import_node_path25.default.join(iosRoot, projects2[0].name, "project.pbxproj")
|
|
34458
|
+
]);
|
|
34459
|
+
if (!isRecord(project) || typeof project.parseSync !== "function")
|
|
34460
|
+
throw new Error("native Xcode project is malformed");
|
|
34461
|
+
Reflect.apply(project.parseSync, project, []);
|
|
34462
|
+
const hash = project.hash;
|
|
34463
|
+
const native = isRecord(hash) ? hash.project : null;
|
|
34464
|
+
const objects = isRecord(native) ? native.objects : null;
|
|
34465
|
+
if (!isRecord(objects)) throw new Error("native Xcode objects are malformed");
|
|
34466
|
+
const unquote = (value) => typeof value === "string" ? value.replace(/^"|"$/g, "") : "";
|
|
34467
|
+
const targets = isRecord(objects.PBXNativeTarget) ? Object.values(objects.PBXNativeTarget).filter(
|
|
34468
|
+
(target2) => isRecord(target2) && unquote(target2.productType) === "com.apple.product-type.application"
|
|
34469
|
+
) : [];
|
|
34470
|
+
if (targets.length > 1)
|
|
34471
|
+
throw new Error("native Firebase configuration requires a selected app target");
|
|
34472
|
+
const target = targets[0];
|
|
34473
|
+
if (isRecord(target) && Array.isArray(target.buildPhases)) {
|
|
34474
|
+
const buildPhases = target.buildPhases;
|
|
34475
|
+
const filePaths = /* @__PURE__ */ new Map();
|
|
34476
|
+
const groups = isRecord(objects.PBXGroup) ? objects.PBXGroup : {};
|
|
34477
|
+
const references = isRecord(objects.PBXFileReference) ? objects.PBXFileReference : {};
|
|
34478
|
+
const nativeProjects = isRecord(objects.PBXProject) ? Object.values(objects.PBXProject) : [];
|
|
34479
|
+
const roots = nativeProjects.filter(isRecord).map((value) => value.mainGroup);
|
|
34480
|
+
const pending = roots.filter((id) => typeof id === "string").map((id) => ({ id, base: iosRoot }));
|
|
34481
|
+
const visited = /* @__PURE__ */ new Map();
|
|
34482
|
+
while (pending.length) {
|
|
34483
|
+
const item = pending.pop();
|
|
34484
|
+
if (!item) break;
|
|
34485
|
+
const previous = visited.get(item.id);
|
|
34486
|
+
if (previous !== void 0) {
|
|
34487
|
+
if (previous !== item.base)
|
|
34488
|
+
throw new Error("native Xcode group has ambiguous parents");
|
|
34489
|
+
continue;
|
|
34490
|
+
}
|
|
34491
|
+
visited.set(item.id, item.base);
|
|
34492
|
+
const group = groups[item.id];
|
|
34493
|
+
if (!isRecord(group) || !Array.isArray(group.children)) continue;
|
|
34494
|
+
const sourceTree = unquote(group.sourceTree);
|
|
34495
|
+
if (sourceTree && sourceTree !== "<group>" && sourceTree !== "SOURCE_ROOT")
|
|
34496
|
+
continue;
|
|
34497
|
+
const directory = import_node_path25.default.resolve(
|
|
34498
|
+
sourceTree === "SOURCE_ROOT" ? iosRoot : item.base,
|
|
34499
|
+
unquote(group.path)
|
|
34500
|
+
);
|
|
34501
|
+
for (const child of group.children) {
|
|
34502
|
+
if (!isRecord(child) || typeof child.value !== "string") continue;
|
|
34503
|
+
if (isRecord(groups[child.value])) {
|
|
34504
|
+
pending.push({ id: child.value, base: directory });
|
|
34505
|
+
continue;
|
|
34506
|
+
}
|
|
34507
|
+
const file = references[child.value];
|
|
34508
|
+
if (!isRecord(file)) continue;
|
|
34509
|
+
const tree = unquote(file.sourceTree);
|
|
34510
|
+
if (tree !== "<group>" && tree !== "SOURCE_ROOT") continue;
|
|
34511
|
+
const filePath = import_node_path25.default.resolve(
|
|
34512
|
+
tree === "SOURCE_ROOT" ? iosRoot : directory,
|
|
34513
|
+
unquote(file.path)
|
|
34514
|
+
);
|
|
34515
|
+
const values = filePaths.get(child.value) ?? /* @__PURE__ */ new Set();
|
|
34516
|
+
values.add(filePath);
|
|
34517
|
+
filePaths.set(child.value, values);
|
|
34518
|
+
}
|
|
34519
|
+
}
|
|
34520
|
+
const buildFiles = isRecord(objects.PBXBuildFile) ? objects.PBXBuildFile : {};
|
|
34521
|
+
const filesInPhase = (section, name2) => {
|
|
34522
|
+
if (!isRecord(section)) return [];
|
|
34523
|
+
const paths = [];
|
|
34524
|
+
for (const phase of buildPhases) {
|
|
34525
|
+
if (!isRecord(phase) || typeof phase.value !== "string") continue;
|
|
34526
|
+
const value = section[phase.value];
|
|
34527
|
+
if (!isRecord(value) || !Array.isArray(value.files)) continue;
|
|
34528
|
+
for (const entry of value.files) {
|
|
34529
|
+
if (!isRecord(entry) || typeof entry.value !== "string") continue;
|
|
34530
|
+
const file = buildFiles[entry.value];
|
|
34531
|
+
if (!isRecord(file) || typeof file.fileRef !== "string") continue;
|
|
34532
|
+
const reference = references[file.fileRef];
|
|
34533
|
+
if (!isRecord(reference) || !name2.test(import_node_path25.default.basename(unquote(reference.path))))
|
|
34534
|
+
continue;
|
|
34535
|
+
const candidates = filePaths.get(file.fileRef);
|
|
34536
|
+
if (!candidates || candidates.size !== 1)
|
|
34537
|
+
throw new Error("native Firebase build resource path is unresolved");
|
|
34538
|
+
paths.push(...candidates);
|
|
34539
|
+
}
|
|
34540
|
+
}
|
|
34541
|
+
return paths;
|
|
34542
|
+
};
|
|
34543
|
+
const delegates = filesInPhase(
|
|
34544
|
+
objects.PBXSourcesBuildPhase,
|
|
34545
|
+
/^AppDelegate\.(swift|mm|m)$/
|
|
34546
|
+
);
|
|
34547
|
+
const defaultConfigured = delegates.some((file) => {
|
|
34548
|
+
const source = import_node_fs25.default.readFileSync(file, "utf8").replace(
|
|
34549
|
+
/\/\*[\s\S]*?\*\/|\/\/[^\n]*|"(?:\\.|[^"\\])*"/g,
|
|
34550
|
+
(token) => token.startsWith('"') ? '""' : token.replace(/[^\n]/g, " ")
|
|
34551
|
+
);
|
|
34552
|
+
const launch3 = /(?:\bfunc\s+application\s*\([\s\S]*?didFinishLaunchingWithOptions[\s\S]*?\)\s*->\s*Bool|^-\s*\(BOOL\)\s*application\s*:[\s\S]*?didFinishLaunchingWithOptions[^\{]*)\s*\{/m.exec(
|
|
34553
|
+
source
|
|
34554
|
+
);
|
|
34555
|
+
if (!launch3) return false;
|
|
34556
|
+
const body = source.slice(launch3.index + launch3[0].length);
|
|
34557
|
+
const configure = /^\s*(?:FirebaseApp\s*\.\s*configure\s*\(\s*\)|\[FIRApp\s+configure\])/m.exec(
|
|
34558
|
+
body
|
|
34559
|
+
);
|
|
34560
|
+
if (!configure) return false;
|
|
34561
|
+
const before = body.slice(0, configure.index);
|
|
34562
|
+
let depth = 1;
|
|
34563
|
+
for (const token of before) {
|
|
34564
|
+
if (token === "{") depth += 1;
|
|
34565
|
+
if (token === "}") depth -= 1;
|
|
34566
|
+
if (depth === 0) return false;
|
|
34567
|
+
}
|
|
34568
|
+
if (depth !== 1 || /\b(?:return|throw)\b|^\s*#(?:if|elseif|else)/m.test(before))
|
|
34569
|
+
throw new Error(
|
|
34570
|
+
"native Firebase initialization must be unconditional in the app launch method"
|
|
34571
|
+
);
|
|
34572
|
+
return true;
|
|
34573
|
+
});
|
|
34574
|
+
if (defaultConfigured) {
|
|
34575
|
+
const resources = filesInPhase(
|
|
34576
|
+
objects.PBXResourcesBuildPhase,
|
|
34577
|
+
/^GoogleService-Info\.plist$/
|
|
34578
|
+
);
|
|
34579
|
+
if (resources.length !== 1)
|
|
34580
|
+
throw new Error(
|
|
34581
|
+
"native Firebase default initialization requires one GoogleService-Info.plist build resource"
|
|
34582
|
+
);
|
|
34583
|
+
config.ios = { googleServicesFile: import_node_path25.default.relative(projectRoot, resources[0]) };
|
|
34584
|
+
}
|
|
34585
|
+
}
|
|
34586
|
+
}
|
|
34587
|
+
}
|
|
34588
|
+
}
|
|
34589
|
+
for (const platform of platforms) {
|
|
34431
34590
|
const native = config[platform];
|
|
34432
34591
|
if (!isRecord(native) || typeof native.googleServicesFile !== "string") continue;
|
|
34433
34592
|
try {
|
|
@@ -36110,12 +36269,12 @@ function findDesktopCompanion() {
|
|
|
36110
36269
|
}
|
|
36111
36270
|
async function spawnDetached(command, args, opts = {}) {
|
|
36112
36271
|
const stdio = opts.inheritStdio ? ["ignore", "inherit", "inherit"] : "ignore";
|
|
36113
|
-
await new Promise((
|
|
36272
|
+
await new Promise((resolve10, reject) => {
|
|
36114
36273
|
const child = (0, import_child_process5.spawn)(command, args, { detached: true, stdio });
|
|
36115
36274
|
child.once("error", reject);
|
|
36116
36275
|
child.once("spawn", () => {
|
|
36117
36276
|
child.unref();
|
|
36118
|
-
|
|
36277
|
+
resolve10();
|
|
36119
36278
|
});
|
|
36120
36279
|
});
|
|
36121
36280
|
}
|
|
@@ -37767,11 +37926,11 @@ async function launch2(opts) {
|
|
|
37767
37926
|
}
|
|
37768
37927
|
);
|
|
37769
37928
|
child.unref();
|
|
37770
|
-
const earlyExit = await new Promise((
|
|
37771
|
-
const timer = setTimeout(() =>
|
|
37929
|
+
const earlyExit = await new Promise((resolve10) => {
|
|
37930
|
+
const timer = setTimeout(() => resolve10(null), 4e3);
|
|
37772
37931
|
child.once("exit", (code) => {
|
|
37773
37932
|
clearTimeout(timer);
|
|
37774
|
-
|
|
37933
|
+
resolve10(code ?? 0);
|
|
37775
37934
|
});
|
|
37776
37935
|
});
|
|
37777
37936
|
if (earlyExit !== null) {
|
|
@@ -37990,7 +38149,8 @@ var init_parse_args = __esm({
|
|
|
37990
38149
|
// documented aliases for --sim (CLAUDE.md / skills / engine docs say
|
|
37991
38150
|
// `--session <id>`). normalized to the sim target in bin.ts.
|
|
37992
38151
|
"--session": { type: "string" },
|
|
37993
|
-
"--tab": { type: "string" }
|
|
38152
|
+
"--tab": { type: "string" },
|
|
38153
|
+
"--redact": { type: "boolean" }
|
|
37994
38154
|
};
|
|
37995
38155
|
GLOBAL_FLAG_TAKES_VALUE = new Map(
|
|
37996
38156
|
Object.entries(GLOBAL_FLAGS).flatMap(([name2, def]) => {
|
|
@@ -38102,6 +38262,118 @@ var init_runtime_diagnostics = __esm({
|
|
|
38102
38262
|
}
|
|
38103
38263
|
});
|
|
38104
38264
|
|
|
38265
|
+
// cli/commands/skills.ts
|
|
38266
|
+
function getSkillsDir() {
|
|
38267
|
+
if (typeof __PEACH_BUNDLED_SKILLS__ !== "undefined") {
|
|
38268
|
+
const dir = path24.join(rnxHomeDir(), "skills", getCliVersion());
|
|
38269
|
+
for (const [file, body] of Object.entries(__PEACH_BUNDLED_SKILLS__)) {
|
|
38270
|
+
const target = path24.join(dir, file);
|
|
38271
|
+
if (fs21.existsSync(target)) continue;
|
|
38272
|
+
fs21.mkdirSync(path24.dirname(target), { recursive: true });
|
|
38273
|
+
fs21.writeFileSync(target, body);
|
|
38274
|
+
}
|
|
38275
|
+
return dir;
|
|
38276
|
+
}
|
|
38277
|
+
try {
|
|
38278
|
+
const pkgPath = (0, import_url3.fileURLToPath)(
|
|
38279
|
+
import_meta4.resolve(`${rnxPublicBrand.packageName}/package.json`)
|
|
38280
|
+
);
|
|
38281
|
+
return path24.join(path24.dirname(pkgPath), "skills");
|
|
38282
|
+
} catch {
|
|
38283
|
+
const __dirname = path24.dirname((0, import_url3.fileURLToPath)(__sootsim_import_meta_url));
|
|
38284
|
+
return path24.resolve(__dirname, "../../skills");
|
|
38285
|
+
}
|
|
38286
|
+
}
|
|
38287
|
+
function skillsDir() {
|
|
38288
|
+
skillsDirPath ??= getSkillsDir();
|
|
38289
|
+
return skillsDirPath;
|
|
38290
|
+
}
|
|
38291
|
+
function targetFromHome(envName, fallbackDir) {
|
|
38292
|
+
const home = process.env[envName] || path24.join(os5.homedir(), fallbackDir);
|
|
38293
|
+
return path24.join(home, "skills");
|
|
38294
|
+
}
|
|
38295
|
+
function defaultAgentTargets() {
|
|
38296
|
+
return [
|
|
38297
|
+
{ label: "codex", dir: targetFromHome("CODEX_HOME", ".codex") },
|
|
38298
|
+
{ label: "claude", dir: targetFromHome("CLAUDE_CONFIG_DIR", ".claude") }
|
|
38299
|
+
];
|
|
38300
|
+
}
|
|
38301
|
+
function hasInstalledPeachSkills() {
|
|
38302
|
+
const names = typeof __PEACH_BUNDLED_SKILLS__ !== "undefined" ? Object.keys(__PEACH_BUNDLED_SKILLS__).flatMap(
|
|
38303
|
+
(file) => /^([^/]+)\/SKILL\.md$/.exec(file)?.[1] ?? []
|
|
38304
|
+
) : listSkills().map((skill7) => skill7.name);
|
|
38305
|
+
return defaultAgentTargets().some(
|
|
38306
|
+
({ dir }) => names.some((name2) => fs21.existsSync(path24.join(dir, name2, "SKILL.md")))
|
|
38307
|
+
);
|
|
38308
|
+
}
|
|
38309
|
+
function parseSkillFrontmatter(content) {
|
|
38310
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
38311
|
+
if (!match) return null;
|
|
38312
|
+
const frontmatter = match[1];
|
|
38313
|
+
const name2 = readFrontmatterField(frontmatter, "name");
|
|
38314
|
+
if (!name2) return null;
|
|
38315
|
+
return {
|
|
38316
|
+
name: name2,
|
|
38317
|
+
description: readFrontmatterField(frontmatter, "description") || ""
|
|
38318
|
+
};
|
|
38319
|
+
}
|
|
38320
|
+
function readFrontmatterField(frontmatter, field) {
|
|
38321
|
+
const lines = frontmatter.split("\n");
|
|
38322
|
+
const prefix = `${field}:`;
|
|
38323
|
+
for (let index = 0; index < lines.length; index++) {
|
|
38324
|
+
const line = lines[index];
|
|
38325
|
+
if (!line.startsWith(prefix)) continue;
|
|
38326
|
+
const rawValue = line.slice(prefix.length).trim();
|
|
38327
|
+
if (rawValue === ">-" || rawValue === ">" || rawValue === "|-" || rawValue === "|") {
|
|
38328
|
+
const blockLines = [];
|
|
38329
|
+
for (let blockIndex = index + 1; blockIndex < lines.length; blockIndex++) {
|
|
38330
|
+
const blockLine = lines[blockIndex];
|
|
38331
|
+
if (/^[A-Za-z0-9_-]+:\s*/.test(blockLine)) break;
|
|
38332
|
+
if (blockLine.trim() === "") {
|
|
38333
|
+
blockLines.push("");
|
|
38334
|
+
continue;
|
|
38335
|
+
}
|
|
38336
|
+
if (!/^\s+/.test(blockLine)) break;
|
|
38337
|
+
blockLines.push(blockLine.trim());
|
|
38338
|
+
}
|
|
38339
|
+
return blockLines.join(rawValue.startsWith("|") ? "\n" : " ").trim();
|
|
38340
|
+
}
|
|
38341
|
+
if (rawValue.startsWith('"') && rawValue.endsWith('"') || rawValue.startsWith("'") && rawValue.endsWith("'")) {
|
|
38342
|
+
return rawValue.slice(1, -1);
|
|
38343
|
+
}
|
|
38344
|
+
return rawValue;
|
|
38345
|
+
}
|
|
38346
|
+
return null;
|
|
38347
|
+
}
|
|
38348
|
+
function listSkills() {
|
|
38349
|
+
if (!fs21.existsSync(skillsDir())) return [];
|
|
38350
|
+
const skills = [];
|
|
38351
|
+
for (const entry of fs21.readdirSync(skillsDir())) {
|
|
38352
|
+
const skillMd = path24.join(skillsDir(), entry, "SKILL.md");
|
|
38353
|
+
if (!fs21.existsSync(skillMd)) continue;
|
|
38354
|
+
const meta = parseSkillFrontmatter(fs21.readFileSync(skillMd, "utf8"));
|
|
38355
|
+
if (meta) {
|
|
38356
|
+
skills.push({ name: entry, description: meta.description });
|
|
38357
|
+
}
|
|
38358
|
+
}
|
|
38359
|
+
return skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
38360
|
+
}
|
|
38361
|
+
var fs21, os5, path24, import_url3, import_meta4, skillsDirPath;
|
|
38362
|
+
var init_skills = __esm({
|
|
38363
|
+
"cli/commands/skills.ts"() {
|
|
38364
|
+
"use strict";
|
|
38365
|
+
fs21 = __toESM(require("fs"), 1);
|
|
38366
|
+
os5 = __toESM(require("os"), 1);
|
|
38367
|
+
path24 = __toESM(require("path"), 1);
|
|
38368
|
+
import_url3 = require("url");
|
|
38369
|
+
init_cli_version();
|
|
38370
|
+
init_home_paths();
|
|
38371
|
+
init_public_brand();
|
|
38372
|
+
init_run_rnx();
|
|
38373
|
+
import_meta4 = {};
|
|
38374
|
+
}
|
|
38375
|
+
});
|
|
38376
|
+
|
|
38105
38377
|
// cli/runtime-notes.ts
|
|
38106
38378
|
function isChangelogEntry(value) {
|
|
38107
38379
|
if (!value || typeof value !== "object") return false;
|
|
@@ -38255,13 +38527,13 @@ async function tellDaemonRuntimeChanged(version) {
|
|
|
38255
38527
|
const lock = readDaemonLockfile2();
|
|
38256
38528
|
if (!isDaemonLockfileFresh2(lock)) return false;
|
|
38257
38529
|
const port = resolveDefaultBridgePort();
|
|
38258
|
-
return new Promise((
|
|
38530
|
+
return new Promise((resolve10) => {
|
|
38259
38531
|
let settled = false;
|
|
38260
38532
|
let success = false;
|
|
38261
38533
|
const finish = (ok) => {
|
|
38262
38534
|
if (settled) return;
|
|
38263
38535
|
settled = true;
|
|
38264
|
-
|
|
38536
|
+
resolve10(ok);
|
|
38265
38537
|
};
|
|
38266
38538
|
const ws = new import_ws3.WebSocket(`ws://127.0.0.1:${port}`, {
|
|
38267
38539
|
handshakeTimeout: 800
|
|
@@ -38586,7 +38858,7 @@ function spawnSootsim(args) {
|
|
|
38586
38858
|
});
|
|
38587
38859
|
}
|
|
38588
38860
|
function canConnectToBridge(port, timeoutMs) {
|
|
38589
|
-
return new Promise((
|
|
38861
|
+
return new Promise((resolve10) => {
|
|
38590
38862
|
const ws = new import_ws4.WebSocket(`ws://127.0.0.1:${port}`, { handshakeTimeout: timeoutMs });
|
|
38591
38863
|
let settled = false;
|
|
38592
38864
|
const finish = (ok) => {
|
|
@@ -38594,7 +38866,7 @@ function canConnectToBridge(port, timeoutMs) {
|
|
|
38594
38866
|
settled = true;
|
|
38595
38867
|
if (ws.readyState === import_ws4.WebSocket.OPEN) ws.close();
|
|
38596
38868
|
else if (ws.readyState === import_ws4.WebSocket.CONNECTING) ws.terminate();
|
|
38597
|
-
|
|
38869
|
+
resolve10(ok);
|
|
38598
38870
|
};
|
|
38599
38871
|
ws.once("open", () => finish(true));
|
|
38600
38872
|
ws.on("error", () => finish(false));
|
|
@@ -39253,9 +39525,11 @@ function printOpenedSim(openUrl2, sim, mode, quiet = false) {
|
|
|
39253
39525
|
console.log(` current sim: ${sim.id}`);
|
|
39254
39526
|
console.log(JSON.stringify({ simId: sim.id, url: printableSimUrl }, null, 2));
|
|
39255
39527
|
}
|
|
39256
|
-
function
|
|
39257
|
-
if (
|
|
39258
|
-
|
|
39528
|
+
function printAgentHints(quiet) {
|
|
39529
|
+
if (quiet) return;
|
|
39530
|
+
console.log(" inspect messages: run `peach agent listen` when you finish your turn");
|
|
39531
|
+
if (!hasInstalledPeachSkills()) {
|
|
39532
|
+
console.log(" driving peach from an agent? `peach skill install` adds its workflows");
|
|
39259
39533
|
}
|
|
39260
39534
|
}
|
|
39261
39535
|
async function maybeDescribeAfterOpen(wsPort, simId, args) {
|
|
@@ -39738,7 +40012,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
39738
40012
|
quiet
|
|
39739
40013
|
);
|
|
39740
40014
|
await maybeDescribeAfterOpen(parsed.wsPort, targetSim.id, args);
|
|
39741
|
-
|
|
40015
|
+
printAgentHints(quiet);
|
|
39742
40016
|
return { simId: targetSim.id, launched: false };
|
|
39743
40017
|
}
|
|
39744
40018
|
} finally {
|
|
@@ -39821,7 +40095,7 @@ async function runOpenCommand(args, opts = {}) {
|
|
|
39821
40095
|
signalDriverLaunchConnected(result);
|
|
39822
40096
|
printOpenedSim(openUrl2, match, `${driver.name} driver`, quiet);
|
|
39823
40097
|
await maybeDescribeAfterOpen(parsed.wsPort, match.id, args);
|
|
39824
|
-
|
|
40098
|
+
printAgentHints(quiet);
|
|
39825
40099
|
return { simId: match.id, launched: true };
|
|
39826
40100
|
}
|
|
39827
40101
|
async function runUseLikeCommand(args, opts = {}) {
|
|
@@ -40157,6 +40431,7 @@ var init_control = __esm({
|
|
|
40157
40431
|
init_ws_bridge();
|
|
40158
40432
|
init_core();
|
|
40159
40433
|
init_env();
|
|
40434
|
+
init_skills();
|
|
40160
40435
|
DEFAULT_DRIVER_CONNECT_TIMEOUT_MS = 12e4;
|
|
40161
40436
|
DRIVER_CONNECT_INTERVAL_MS = 100;
|
|
40162
40437
|
DRIVER_CONNECT_HOST_GRACE_MS = 5e3;
|
|
@@ -41468,16 +41743,16 @@ function readRecentShellAppId(state) {
|
|
|
41468
41743
|
}
|
|
41469
41744
|
function resolveProjectRelativeFlowBase(flowDir) {
|
|
41470
41745
|
if (!flowDir) return process.cwd();
|
|
41471
|
-
return
|
|
41746
|
+
return path26.basename(flowDir) === ".maestro" ? path26.dirname(flowDir) : flowDir;
|
|
41472
41747
|
}
|
|
41473
41748
|
function resolveFlowScreenshotPathWithMode(screenshotDir, name2, opts) {
|
|
41474
41749
|
const normalizedName = name2.endsWith(".png") ? name2 : `${name2}.png`;
|
|
41475
|
-
if (
|
|
41750
|
+
if (path26.isAbsolute(normalizedName)) return normalizedName;
|
|
41476
41751
|
if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
|
|
41477
41752
|
const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
|
|
41478
|
-
return
|
|
41753
|
+
return path26.resolve(baseDir, normalizedName);
|
|
41479
41754
|
}
|
|
41480
|
-
return
|
|
41755
|
+
return path26.join(screenshotDir, normalizedName);
|
|
41481
41756
|
}
|
|
41482
41757
|
function normalizeFlowScreenshotSpec(step) {
|
|
41483
41758
|
if (typeof step === "string") {
|
|
@@ -41534,12 +41809,12 @@ function parseFlowSteps(content) {
|
|
|
41534
41809
|
const parsed = import_yaml2.default.parse(candidate);
|
|
41535
41810
|
return Array.isArray(parsed) ? parsed : [];
|
|
41536
41811
|
}
|
|
41537
|
-
var
|
|
41812
|
+
var fs24, path26, import_devices4, import_yaml2, import_proof_frame, DEFAULT_TIMEOUT, ASSERTION_LOOKUP_MS, FLOW_TIMEOUT_SCALE, scaledTimeout, MAESTRO_SELECTOR_KEYS, SELECTOR_FILTER_KEYS, UNSUPPORTED_SELECTOR_KEYS, ACCESSIBILITY_SELECTOR_KEYS, ACCESSIBILITY_TRAIT_FILTERS, MAESTRO_PERMISSION_KINDS, MAESTRO_PERMISSION_STATUS, SootSimBridgeFlowRunner;
|
|
41538
41813
|
var init_bridge_flow_runner = __esm({
|
|
41539
41814
|
"cli/bridge-flow-runner.ts"() {
|
|
41540
41815
|
"use strict";
|
|
41541
|
-
|
|
41542
|
-
|
|
41816
|
+
fs24 = __toESM(require("fs"), 1);
|
|
41817
|
+
path26 = __toESM(require("path"), 1);
|
|
41543
41818
|
import_devices4 = require("peach-engine/settings/devices");
|
|
41544
41819
|
import_yaml2 = __toESM(require("yaml"), 1);
|
|
41545
41820
|
import_proof_frame = __toESM(require_proof_frame(), 1);
|
|
@@ -41864,14 +42139,14 @@ var init_bridge_flow_runner = __esm({
|
|
|
41864
42139
|
if (chunks.length === 0) {
|
|
41865
42140
|
throw new Error("recording requested but no video buffer was produced");
|
|
41866
42141
|
}
|
|
41867
|
-
|
|
42142
|
+
fs24.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
|
|
41868
42143
|
const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
|
|
41869
42144
|
const extension = videoMime.includes("mp4") ? "mp4" : "webm";
|
|
41870
|
-
const outputPath =
|
|
42145
|
+
const outputPath = path26.join(
|
|
41871
42146
|
this.opts.recordingOutputDir,
|
|
41872
42147
|
`peach-${Date.now()}.${extension}`
|
|
41873
42148
|
);
|
|
41874
|
-
|
|
42149
|
+
fs24.writeFileSync(outputPath, Buffer.concat(chunks));
|
|
41875
42150
|
return outputPath;
|
|
41876
42151
|
}
|
|
41877
42152
|
async waitForRecordingTail(opts) {
|
|
@@ -42547,7 +42822,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
42547
42822
|
flowDir: this.opts.flowDir
|
|
42548
42823
|
}
|
|
42549
42824
|
);
|
|
42550
|
-
|
|
42825
|
+
fs24.mkdirSync(path26.dirname(outputPath), { recursive: true });
|
|
42551
42826
|
const layers = spec.layers ?? this.opts.screenshotLayers;
|
|
42552
42827
|
const screenshotRequest = {
|
|
42553
42828
|
type: "screenshot",
|
|
@@ -42582,11 +42857,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
42582
42857
|
throw new Error("could not read current device model for framed screenshot");
|
|
42583
42858
|
}
|
|
42584
42859
|
const framed = await composeFramedScreenshot(rawBuffer, model);
|
|
42585
|
-
|
|
42860
|
+
fs24.writeFileSync(outputPath, framed);
|
|
42586
42861
|
console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
|
|
42587
42862
|
return outputPath;
|
|
42588
42863
|
}
|
|
42589
|
-
|
|
42864
|
+
fs24.writeFileSync(outputPath, rawBuffer);
|
|
42590
42865
|
console.log(`[flow] screenshot: ${outputPath}`);
|
|
42591
42866
|
return outputPath;
|
|
42592
42867
|
}
|
|
@@ -42608,10 +42883,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
42608
42883
|
// + a11y tree + console errors/warnings + failed network requests +
|
|
42609
42884
|
// shell state, all under one directory so post-mortem is one grep away.
|
|
42610
42885
|
async captureFailureBundle(outputDir, context) {
|
|
42611
|
-
|
|
42886
|
+
fs24.mkdirSync(outputDir, { recursive: true });
|
|
42612
42887
|
const write = (name2, content) => {
|
|
42613
42888
|
try {
|
|
42614
|
-
|
|
42889
|
+
fs24.writeFileSync(path26.join(outputDir, name2), content);
|
|
42615
42890
|
} catch {
|
|
42616
42891
|
}
|
|
42617
42892
|
};
|
|
@@ -43203,8 +43478,8 @@ var init_bridge_flow_runner = __esm({
|
|
|
43203
43478
|
runScript(target) {
|
|
43204
43479
|
const spec = typeof target === "string" ? { file: target } : target;
|
|
43205
43480
|
if (!spec.file) throw new Error("runScript requires a file");
|
|
43206
|
-
const scriptPath =
|
|
43207
|
-
const source =
|
|
43481
|
+
const scriptPath = path26.resolve(this.opts.flowDir, spec.file);
|
|
43482
|
+
const source = fs24.readFileSync(scriptPath, "utf8");
|
|
43208
43483
|
this.js.evaluate(source, { env: spec.env });
|
|
43209
43484
|
console.log(`[flow] runScript: ${spec.file} done`);
|
|
43210
43485
|
}
|
|
@@ -43564,10 +43839,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
43564
43839
|
for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
|
|
43565
43840
|
}
|
|
43566
43841
|
if (file) {
|
|
43567
|
-
const flowPath =
|
|
43568
|
-
const flowContent =
|
|
43842
|
+
const flowPath = path26.resolve(this.opts.flowDir, file);
|
|
43843
|
+
const flowContent = fs24.readFileSync(flowPath, "utf8");
|
|
43569
43844
|
const previousDir = this.opts.flowDir;
|
|
43570
|
-
this.opts.flowDir =
|
|
43845
|
+
this.opts.flowDir = path26.dirname(flowPath);
|
|
43571
43846
|
try {
|
|
43572
43847
|
await this.runFlow(parseFlowSteps(flowContent));
|
|
43573
43848
|
} finally {
|
|
@@ -43738,8 +44013,8 @@ __export(registry_exports, {
|
|
|
43738
44013
|
skillRegistry: () => skillRegistry
|
|
43739
44014
|
});
|
|
43740
44015
|
module.exports = __toCommonJS(registry_exports);
|
|
43741
|
-
var
|
|
43742
|
-
var
|
|
44016
|
+
var fs25 = __toESM(require("fs"), 1);
|
|
44017
|
+
var path27 = __toESM(require("path"), 1);
|
|
43743
44018
|
|
|
43744
44019
|
// src/skills/builtin/a11y-review.ts
|
|
43745
44020
|
init_reap_browser();
|
|
@@ -43758,8 +44033,8 @@ var skill = {
|
|
|
43758
44033
|
},
|
|
43759
44034
|
async execute(params, context) {
|
|
43760
44035
|
const { chromium } = await import("playwright");
|
|
43761
|
-
const
|
|
43762
|
-
const
|
|
44036
|
+
const path28 = await import("path");
|
|
44037
|
+
const fs26 = await import("fs");
|
|
43763
44038
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
43764
44039
|
headless: true
|
|
43765
44040
|
});
|
|
@@ -43816,9 +44091,9 @@ var skill = {
|
|
|
43816
44091
|
warnings: issues.filter((i) => i.severity === "warning").length,
|
|
43817
44092
|
tree: typeof tree === "string" ? tree : JSON.stringify(tree)
|
|
43818
44093
|
};
|
|
43819
|
-
const reportPath =
|
|
43820
|
-
|
|
43821
|
-
|
|
44094
|
+
const reportPath = path28.join(context.outputDir, "a11y-report.json");
|
|
44095
|
+
fs26.mkdirSync(path28.dirname(reportPath), { recursive: true });
|
|
44096
|
+
fs26.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
43822
44097
|
return {
|
|
43823
44098
|
success: issues.filter((i) => i.severity === "error").length === 0,
|
|
43824
44099
|
message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
|
|
@@ -43851,14 +44126,14 @@ var skill2 = {
|
|
|
43851
44126
|
}
|
|
43852
44127
|
},
|
|
43853
44128
|
async execute(params, context) {
|
|
43854
|
-
const
|
|
43855
|
-
const
|
|
44129
|
+
const fs26 = await import("node:fs");
|
|
44130
|
+
const path28 = await import("node:path");
|
|
43856
44131
|
const { COMPAT_RESULT_CAVEAT: COMPAT_RESULT_CAVEAT2, formatPackageStatus: formatPackageStatus2, formatScanCounts: formatScanCounts2, scanDeps: scanDeps2 } = await Promise.resolve().then(() => (init_web(), web_exports));
|
|
43857
|
-
const packagePath =
|
|
43858
|
-
if (!
|
|
44132
|
+
const packagePath = path28.join(context.projectDir, "package.json");
|
|
44133
|
+
if (!fs26.existsSync(packagePath)) {
|
|
43859
44134
|
return { success: false, message: "No package.json found" };
|
|
43860
44135
|
}
|
|
43861
|
-
const parsed = JSON.parse(
|
|
44136
|
+
const parsed = JSON.parse(fs26.readFileSync(packagePath, "utf8"));
|
|
43862
44137
|
if (!parsed || typeof parsed !== "object") {
|
|
43863
44138
|
return { success: false, message: "package.json is not an object" };
|
|
43864
44139
|
}
|
|
@@ -43870,9 +44145,9 @@ var skill2 = {
|
|
|
43870
44145
|
}) : scanDeps2(parsed);
|
|
43871
44146
|
const packageResult = params.packageName ? scan.packages[0] : void 0;
|
|
43872
44147
|
const message = packageResult ? `${params.packageName}: ${formatPackageStatus2(packageResult)}. ${COMPAT_RESULT_CAVEAT2}` : `${formatScanCounts2(scan)}. ${COMPAT_RESULT_CAVEAT2}`;
|
|
43873
|
-
const reportPath =
|
|
43874
|
-
|
|
43875
|
-
|
|
44148
|
+
const reportPath = path28.join(context.outputDir, "compat-report.json");
|
|
44149
|
+
fs26.mkdirSync(path28.dirname(reportPath), { recursive: true });
|
|
44150
|
+
fs26.writeFileSync(reportPath, `${JSON.stringify(scan, null, 2)}
|
|
43876
44151
|
`);
|
|
43877
44152
|
return {
|
|
43878
44153
|
success: true,
|
|
@@ -43914,8 +44189,8 @@ var skill3 = {
|
|
|
43914
44189
|
record: { type: "boolean", description: "Record video of the flow" }
|
|
43915
44190
|
},
|
|
43916
44191
|
async execute(params, context) {
|
|
43917
|
-
const
|
|
43918
|
-
const
|
|
44192
|
+
const fs26 = await import("fs");
|
|
44193
|
+
const path28 = await import("path");
|
|
43919
44194
|
const yaml2 = await import("yaml");
|
|
43920
44195
|
const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT3 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
|
|
43921
44196
|
const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
|
|
@@ -43925,7 +44200,7 @@ var skill3 = {
|
|
|
43925
44200
|
const host2 = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT3 });
|
|
43926
44201
|
host2.start({ silent: true });
|
|
43927
44202
|
try {
|
|
43928
|
-
const flowContent =
|
|
44203
|
+
const flowContent = fs26.readFileSync(params.flowPath, "utf8");
|
|
43929
44204
|
const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
43930
44205
|
const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
|
|
43931
44206
|
const steps = yaml2.parse(stepsBody);
|
|
@@ -43952,7 +44227,7 @@ var skill3 = {
|
|
|
43952
44227
|
});
|
|
43953
44228
|
const driver = new SootSimBridgeFlowRunner2(bridge, {
|
|
43954
44229
|
screenshotDir: context.outputDir,
|
|
43955
|
-
flowDir:
|
|
44230
|
+
flowDir: path28.dirname(path28.resolve(params.flowPath)),
|
|
43956
44231
|
simId,
|
|
43957
44232
|
recordingOutputDir: params.record ? context.outputDir : void 0
|
|
43958
44233
|
});
|
|
@@ -43974,7 +44249,7 @@ var skill3 = {
|
|
|
43974
44249
|
simId,
|
|
43975
44250
|
videoPath: videoPath || void 0
|
|
43976
44251
|
},
|
|
43977
|
-
artifacts: videoPath ? [{ type: "video", name:
|
|
44252
|
+
artifacts: videoPath ? [{ type: "video", name: path28.basename(videoPath), path: videoPath }] : void 0
|
|
43978
44253
|
};
|
|
43979
44254
|
} finally {
|
|
43980
44255
|
try {
|
|
@@ -44021,8 +44296,8 @@ var skill4 = {
|
|
|
44021
44296
|
},
|
|
44022
44297
|
async execute(params, context) {
|
|
44023
44298
|
const { chromium } = await import("playwright");
|
|
44024
|
-
const
|
|
44025
|
-
const
|
|
44299
|
+
const path28 = await import("path");
|
|
44300
|
+
const fs26 = await import("fs");
|
|
44026
44301
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
44027
44302
|
headless: true
|
|
44028
44303
|
});
|
|
@@ -44050,9 +44325,9 @@ var skill4 = {
|
|
|
44050
44325
|
...profile,
|
|
44051
44326
|
fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
|
|
44052
44327
|
};
|
|
44053
|
-
const reportPath =
|
|
44054
|
-
|
|
44055
|
-
|
|
44328
|
+
const reportPath = path28.join(context.outputDir, "perf-report.json");
|
|
44329
|
+
fs26.mkdirSync(path28.dirname(reportPath), { recursive: true });
|
|
44330
|
+
fs26.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
44056
44331
|
return {
|
|
44057
44332
|
success: true,
|
|
44058
44333
|
message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
|
|
@@ -44085,8 +44360,8 @@ var skill5 = {
|
|
|
44085
44360
|
},
|
|
44086
44361
|
async execute(params, context) {
|
|
44087
44362
|
const { chromium } = await import("playwright");
|
|
44088
|
-
const
|
|
44089
|
-
const
|
|
44363
|
+
const path28 = await import("path");
|
|
44364
|
+
const fs26 = await import("fs");
|
|
44090
44365
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
44091
44366
|
headless: true
|
|
44092
44367
|
});
|
|
@@ -44094,8 +44369,8 @@ var skill5 = {
|
|
|
44094
44369
|
try {
|
|
44095
44370
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
44096
44371
|
await page.waitForTimeout(2e3);
|
|
44097
|
-
const outputPath =
|
|
44098
|
-
|
|
44372
|
+
const outputPath = path28.join(context.outputDir, `${params.name}.png`);
|
|
44373
|
+
fs26.mkdirSync(path28.dirname(outputPath), { recursive: true });
|
|
44099
44374
|
await page.screenshot({ path: outputPath });
|
|
44100
44375
|
return {
|
|
44101
44376
|
success: true,
|
|
@@ -44136,8 +44411,8 @@ var skill6 = {
|
|
|
44136
44411
|
},
|
|
44137
44412
|
async execute(params, context) {
|
|
44138
44413
|
const { chromium } = await import("playwright");
|
|
44139
|
-
const
|
|
44140
|
-
const
|
|
44414
|
+
const path28 = await import("path");
|
|
44415
|
+
const fs26 = await import("fs");
|
|
44141
44416
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
44142
44417
|
headless: true
|
|
44143
44418
|
});
|
|
@@ -44145,14 +44420,14 @@ var skill6 = {
|
|
|
44145
44420
|
try {
|
|
44146
44421
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
44147
44422
|
await page.waitForTimeout(2e3);
|
|
44148
|
-
const currentPath =
|
|
44149
|
-
|
|
44423
|
+
const currentPath = path28.join(context.outputDir, `${params.name}-current.png`);
|
|
44424
|
+
fs26.mkdirSync(path28.dirname(currentPath), { recursive: true });
|
|
44150
44425
|
await page.screenshot({ path: currentPath });
|
|
44151
44426
|
try {
|
|
44152
44427
|
const { PNG } = await import("pngjs");
|
|
44153
44428
|
const pixelmatch = (await import("pixelmatch")).default;
|
|
44154
|
-
const baseline = PNG.sync.read(
|
|
44155
|
-
const current = PNG.sync.read(
|
|
44429
|
+
const baseline = PNG.sync.read(fs26.readFileSync(params.baseline));
|
|
44430
|
+
const current = PNG.sync.read(fs26.readFileSync(currentPath));
|
|
44156
44431
|
const { width, height } = baseline;
|
|
44157
44432
|
const diff = new PNG({ width, height });
|
|
44158
44433
|
const numDiffPixels = pixelmatch(
|
|
@@ -44163,8 +44438,8 @@ var skill6 = {
|
|
|
44163
44438
|
height,
|
|
44164
44439
|
{ threshold: params.threshold || 0.1 }
|
|
44165
44440
|
);
|
|
44166
|
-
const diffPath =
|
|
44167
|
-
|
|
44441
|
+
const diffPath = path28.join(context.outputDir, `${params.name}-diff.png`);
|
|
44442
|
+
fs26.writeFileSync(diffPath, PNG.sync.write(diff));
|
|
44168
44443
|
const totalPixels = width * height;
|
|
44169
44444
|
const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
|
|
44170
44445
|
return {
|
|
@@ -44228,10 +44503,10 @@ var skillRegistry = {
|
|
|
44228
44503
|
},
|
|
44229
44504
|
// load skills from a project manifest (rnx-skills.json)
|
|
44230
44505
|
async loadFromManifest(projectDir) {
|
|
44231
|
-
const manifestPath =
|
|
44232
|
-
if (!
|
|
44506
|
+
const manifestPath = path27.join(projectDir, "rnx-skills.json");
|
|
44507
|
+
if (!fs25.existsSync(manifestPath)) return;
|
|
44233
44508
|
try {
|
|
44234
|
-
const manifest = JSON.parse(
|
|
44509
|
+
const manifest = JSON.parse(fs25.readFileSync(manifestPath, "utf8"));
|
|
44235
44510
|
if (Array.isArray(manifest.skills)) {
|
|
44236
44511
|
for (const entry of manifest.skills) {
|
|
44237
44512
|
if (typeof entry === "string") {
|
|
@@ -44242,7 +44517,7 @@ var skillRegistry = {
|
|
|
44242
44517
|
}
|
|
44243
44518
|
} else if (entry.file) {
|
|
44244
44519
|
try {
|
|
44245
|
-
const mod = await import(
|
|
44520
|
+
const mod = await import(path27.resolve(projectDir, entry.file));
|
|
44246
44521
|
if (mod.skill) this.register(mod.skill);
|
|
44247
44522
|
} catch {
|
|
44248
44523
|
}
|
|
@@ -44255,10 +44530,10 @@ var skillRegistry = {
|
|
|
44255
44530
|
// auto-discover skills based on project dependencies
|
|
44256
44531
|
suggestSkills(projectDir) {
|
|
44257
44532
|
const suggestions = [];
|
|
44258
|
-
const pkgPath =
|
|
44259
|
-
if (!
|
|
44533
|
+
const pkgPath = path27.join(projectDir, "package.json");
|
|
44534
|
+
if (!fs25.existsSync(pkgPath)) return suggestions;
|
|
44260
44535
|
try {
|
|
44261
|
-
const pkg = JSON.parse(
|
|
44536
|
+
const pkg = JSON.parse(fs25.readFileSync(pkgPath, "utf8"));
|
|
44262
44537
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
44263
44538
|
if (deps["detox"] || deps["maestro"]) {
|
|
44264
44539
|
suggestions.push("maestro-test");
|