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